Let task agents use client Macs directly: bash, copy and hands

This commit is contained in:
Ian Gulliver
2026-10-17 23:45:31 -07:00
parent 8d9ba10849
commit 9b79ade073
25 changed files with 1382 additions and 952 deletions
+5 -40
View File
@@ -6,7 +6,6 @@ import (
"encoding/json"
"errors"
"fmt"
"path/filepath"
"strings"
"time"
@@ -15,7 +14,7 @@ import (
func DeliverableResponse(t api.InboxResponseType) bool {
switch t {
case api.Option, api.Other, api.Run:
case api.Option, api.Other:
return true
}
return false
@@ -168,31 +167,6 @@ func (s *Store) Respond(ctx context.Context, actor string, resolutions []Resolut
var ErrNotOpen = errors.New("inbox item is not open")
func (s *Store) AddRunResponse(ctx context.Context, resp api.InboxResponse) (bool, error) {
added := false
err := s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
res, err := tx.ExecContext(ctx, `
INSERT INTO inbox_responses (id, item_id, user_login, type, text, client, exit_code, images, attachments, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, '[]', '[]', ?)
ON CONFLICT (id) DO NOTHING
`, resp.Id, resp.ItemId, resp.User, string(api.Run), resp.Text, *resp.Client, *resp.ExitCode, formatTime(resp.CreatedAt))
if err != nil {
return err
}
n, err := res.RowsAffected()
if err != nil || n == 0 {
return err
}
added = true
return emitItem(ctx, tx, emit, "inbox.updated", resp.ItemId, resp.User)
})
return added, err
}
func (s *Store) BundlePath(itemID string) string {
return filepath.Join(s.dataDir(), "bundles", itemID+".tar.gz")
}
func (s *Store) WithdrawItem(ctx context.Context, id string) error {
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
res, err := tx.ExecContext(ctx, `UPDATE inbox_items SET state = ?, resolved_at = ? WHERE id = ? AND state = ?`,
@@ -261,9 +235,9 @@ type Pending struct {
func (s *Store) Undelivered(ctx context.Context, sessionID string) ([]Pending, error) {
rows, err := s.db.QueryContext(ctx, `
SELECT r.id, r.item_id FROM inbox_responses r JOIN inbox_items i ON i.id = r.item_id
WHERE i.agent_session_id = ? AND r.delivered_at IS NULL AND r.type IN (?, ?, ?)
WHERE i.agent_session_id = ? AND r.delivered_at IS NULL AND r.type IN (?, ?)
ORDER BY r.created_at
`, sessionID, string(api.Option), string(api.Other), string(api.Run))
`, sessionID, string(api.Option), string(api.Other))
if err != nil {
return nil, err
}
@@ -373,7 +347,7 @@ func getItem(ctx context.Context, q querier, id string) (api.InboxItem, error) {
func getResponses(ctx context.Context, q querier, itemID string) ([]api.InboxResponse, error) {
rows, err := q.QueryContext(ctx, `
SELECT id, item_id, user_login, type, options, text, client, exit_code, images, attachments, created_at, delivered_at
SELECT id, item_id, user_login, type, options, text, images, attachments, created_at, delivered_at
FROM inbox_responses WHERE item_id = ? ORDER BY created_at
`, itemID)
if err != nil {
@@ -387,24 +361,15 @@ func getResponses(ctx context.Context, q querier, itemID string) ([]api.InboxRes
typ := ""
options := sql.NullString{}
text := sql.NullString{}
client := ""
exitCode := sql.NullInt64{}
images := ""
attachments := ""
createdAt := ""
delivered := sql.NullString{}
err = rows.Scan(&r.Id, &r.ItemId, &r.User, &typ, &options, &text, &client, &exitCode, &images, &attachments, &createdAt, &delivered)
err = rows.Scan(&r.Id, &r.ItemId, &r.User, &typ, &options, &text, &images, &attachments, &createdAt, &delivered)
if err != nil {
return nil, err
}
if client != "" {
r.Client = &client
}
if exitCode.Valid {
code := int(exitCode.Int64)
r.ExitCode = &code
}
r.Type = api.InboxResponseType(typ)
if options.Valid {
+5
View File
@@ -469,6 +469,11 @@ ALTER TABLE agent_sessions ADD COLUMN subagents INTEGER NOT NULL DEFAULT 0;
`}, {"add-inbox-run-responses", `
ALTER TABLE inbox_responses ADD COLUMN client TEXT NOT NULL DEFAULT '';
ALTER TABLE inbox_responses ADD COLUMN exit_code INTEGER;
`}, {"drop-client-runs", `
DELETE FROM inbox_responses WHERE item_id IN (SELECT id FROM inbox_items WHERE kind = 'client_run');
DELETE FROM inbox_items WHERE kind = 'client_run';
ALTER TABLE inbox_responses DROP COLUMN client;
ALTER TABLE inbox_responses DROP COLUMN exit_code;
`}}
const (