@saadnvd1/agent-os 0.3.596 → 0.3.600

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/app/api/bus/spawn/route.ts +35 -16
  2. package/app/api/lumifyhub/cards/[cardId]/run/route.ts +3 -0
  3. package/app/api/tasks/route.ts +3 -0
  4. package/app/page.tsx +2 -1
  5. package/components/SessionList/SessionRow.tsx +2 -1
  6. package/lib/agents/spawn.ts +16 -4
  7. package/lib/chat/refresh.ts +2 -1
  8. package/lib/chat/runner.ts +29 -0
  9. package/lib/chat/store.ts +53 -0
  10. package/lib/db/migration-types.ts +15 -0
  11. package/lib/db/migrations/0001_add_group_path_to_sessions.ts +11 -0
  12. package/lib/db/migrations/0002_add_agent_type_to_sessions.ts +11 -0
  13. package/lib/db/migrations/0003_add_worktree_columns_to_sessions.ts +12 -0
  14. package/lib/db/migrations/0004_add_pr_tracking_to_sessions.ts +11 -0
  15. package/lib/db/migrations/0005_add_group_path_index.ts +11 -0
  16. package/lib/db/migrations/0006_add_orchestration_columns_to_sessions.ts +16 -0
  17. package/lib/db/migrations/0007_add_auto_approve_to_sessions.ts +11 -0
  18. package/lib/db/migrations/0008_add_dev_server_columns.ts +19 -0
  19. package/lib/db/migrations/0009_add_project_id_to_sessions.ts +17 -0
  20. package/lib/db/migrations/0010_add_project_id_to_dev_servers.ts +36 -0
  21. package/lib/db/migrations/0011_add_tmux_name_to_sessions.ts +13 -0
  22. package/lib/db/migrations/0012_add_initial_prompt_to_projects.ts +9 -0
  23. package/lib/db/migrations/0013_add_project_repositories_table.ts +22 -0
  24. package/lib/db/migrations/0014_add_hosts.ts +23 -0
  25. package/lib/db/migrations/0015_add_workspaces.ts +18 -0
  26. package/lib/db/migrations/0016_add_task_columns_to_sessions.ts +13 -0
  27. package/lib/db/migrations/0017_add_bus_messages.ts +24 -0
  28. package/lib/db/migrations/0018_add_chat.ts +23 -0
  29. package/lib/db/migrations/0019_add_lumifyhub.ts +36 -0
  30. package/lib/db/migrations/0020_add_lumifyhub_published_docs.ts +18 -0
  31. package/lib/db/migrations/0021_add_chat_access.ts +14 -0
  32. package/lib/db/migrations/0022_add_last_seen.ts +10 -0
  33. package/lib/db/migrations/0023_mark_existing_sessions_seen.ts +12 -0
  34. package/lib/db/migrations/0024_add_stacks.ts +49 -0
  35. package/lib/db/migrations/0025_add_stack_item_attempts.ts +16 -0
  36. package/lib/db/migrations/0026_add_workspace_orchestrator.ts +47 -0
  37. package/lib/db/migrations/0027_add_devices_and_settings.ts +28 -0
  38. package/lib/db/migrations/0028_add_orchestrator_acting.ts +70 -0
  39. package/lib/db/migrations/0029_add_orchestrator_asks_and_pause.ts +81 -0
  40. package/lib/db/migrations/0030_add_sessions_archived_at.ts +14 -0
  41. package/lib/db/migrations/0031_add_stack_item_restacked_heads.ts +22 -0
  42. package/lib/db/migrations/0032_add_sessions_pinned.ts +12 -0
  43. package/lib/db/migrations/0033_add_program_status.ts +18 -0
  44. package/lib/db/migrations/0034_add_session_names.ts +21 -0
  45. package/lib/db/migrations/0035_add_artifacts.ts +23 -0
  46. package/lib/db/migrations/0036_add_chat_queue.ts +26 -0
  47. package/lib/db/migrations/0037_add_chat_plan_and_turns.ts +39 -0
  48. package/lib/db/migrations/0038_add_schedules.ts +56 -0
  49. package/lib/db/migrations/0039_add_session_name_source.ts +21 -0
  50. package/lib/db/migrations/0040_add_schedule_targets_and_phone_notify.ts +41 -0
  51. package/lib/db/migrations/0041_add_task_setup.ts +17 -0
  52. package/lib/db/migrations/0042_add_host_links_and_moved_tasks.ts +29 -0
  53. package/lib/db/migrations/0043_scratch_project.ts +14 -0
  54. package/lib/db/migrations/0044_chat_item_kind.ts +21 -0
  55. package/lib/db/migrations/0045_change_versions.ts +13 -0
  56. package/lib/db/migrations/0046_session_port_slots.ts +21 -0
  57. package/lib/db/migrations/0047_pin_orchestrators.ts +12 -0
  58. package/lib/db/migrations/0048_session_database.ts +15 -0
  59. package/lib/db/migrations/0049_peer_mirror.ts +14 -0
  60. package/lib/db/migrations/0050_task_queue.ts +44 -0
  61. package/lib/db/migrations/0051_chat_queue_sent_by.ts +16 -0
  62. package/lib/db/migrations/0052_sessions_chat_restarted.ts +17 -0
  63. package/lib/db/migrations/0053_brief_amendments_failure_sha_ask_raised_by.ts +37 -0
  64. package/lib/db/migrations/0054_sessions_chat_tools_digest.ts +15 -0
  65. package/lib/db/migrations/0055_sessions_merge_armed_and_rebase.ts +25 -0
  66. package/lib/db/migrations/0056_orchestrator_rules.ts +39 -0
  67. package/lib/db/migrations/0057_task_pr_wakes.ts +34 -0
  68. package/lib/db/migrations/0058_away_mode.ts +71 -0
  69. package/lib/db/migrations/0059_gate_failure_commits.ts +33 -0
  70. package/lib/db/migrations/0060_check_runs_and_compactions.ts +44 -0
  71. package/lib/db/migrations/0061_model_routing.ts +30 -0
  72. package/lib/db/migrations/0062_sessions_quick_of.ts +19 -0
  73. package/lib/db/migrations/0063_one_off_schedules.ts +16 -0
  74. package/lib/db/migrations/0064_chat_compactions_phase.ts +15 -0
  75. package/lib/db/migrations/0065_orchestrator_triage.ts +23 -0
  76. package/lib/db/migrations/0066_workspace_orch_mcp_servers.ts +16 -0
  77. package/lib/db/migrations/0067_orchestrator_event_log_suppressed.ts +14 -0
  78. package/lib/db/migrations/0068_usage_calls_and_rollups.ts +74 -0
  79. package/lib/db/migrations/0069_session_logs.ts +26 -0
  80. package/lib/db/migrations/0070_chat_items_running.ts +15 -0
  81. package/lib/db/migrations/0071_devices_push.ts +29 -0
  82. package/lib/db/migrations/0072_push_outbox.ts +33 -0
  83. package/lib/db/migrations/0073_orchestrated_task_moves.ts +27 -0
  84. package/lib/db/migrations/0074_held_task_replies.ts +27 -0
  85. package/lib/db/migrations/0075_plan_only_tasks.ts +17 -0
  86. package/lib/db/migrations/0076_welcome_backfill.ts +16 -0
  87. package/lib/db/migrations/0077_simulator_leases.ts +21 -0
  88. package/lib/db/migrations/0078_orchestrator_questions.ts +34 -0
  89. package/lib/db/migrations/0079_task_queue_agent.ts +13 -0
  90. package/lib/db/migrations/0080_recipes.ts +129 -0
  91. package/lib/db/migrations/0081_schedules_into_recipes.ts +18 -0
  92. package/lib/db/migrations/0082_session_shelf_times.ts +23 -0
  93. package/lib/db/migrations/0083_native_devices_can_approve.ts +18 -0
  94. package/lib/db/migrations/0084_approval_audit.ts +20 -0
  95. package/lib/db/migrations/0085_experiment_usage.ts +35 -0
  96. package/lib/db/migrations/0086_learning_cards.ts +28 -0
  97. package/lib/db/migrations/0087_plan_pieces_reconcile.ts +29 -0
  98. package/lib/db/migrations/0088_shared_links.ts +25 -0
  99. package/lib/db/migrations/0089_passkeys_device_keys.ts +23 -0
  100. package/lib/db/migrations/20261014T0900_task_scheduling.ts +57 -0
  101. package/lib/db/migrations/20261014T1235_placed_mirror_started_by.ts +19 -0
  102. package/lib/db/migrations/20261014T1600_queued_task_messages.ts +21 -0
  103. package/lib/db/migrations/20261014T1800_task_starter_device.ts +20 -0
  104. package/lib/db/migrations/20261014T1900_pause_note.ts +13 -0
  105. package/lib/db/migrations/20261014T2000_chat_bookmarks.ts +33 -0
  106. package/lib/db/migrations/20261014T2100_gate_failure_ask_held.ts +18 -0
  107. package/lib/db/migrations/20261014T2110_task_start_record.ts +21 -0
  108. package/lib/db/migrations/20261014T2200_end_orphaned_tasks.ts +23 -0
  109. package/lib/db/migrations/README.md +35 -0
  110. package/lib/db/migrations-legacy-checksums.json +9 -8
  111. package/lib/db/migrations-split-snapshot.json +1759 -0
  112. package/lib/db/migrations.ts +76 -2337
  113. package/lib/db/types.ts +2 -0
  114. package/lib/learning-cards/apply.ts +7 -1
  115. package/lib/models/plan-step.ts +25 -8
  116. package/lib/models/resolve.ts +1 -1
  117. package/lib/models/resume.ts +1 -1
  118. package/lib/models/roles.ts +0 -16
  119. package/lib/models/session-role.ts +19 -0
  120. package/lib/orchestrator/act.ts +22 -7
  121. package/lib/orchestrator/amendments.ts +10 -3
  122. package/lib/orchestrator/serve.ts +1 -0
  123. package/lib/orchestrator/testing.ts +8 -0
  124. package/lib/orchestrator/tool-schemas.ts +9 -0
  125. package/lib/orchestrator/tools.ts +1 -1
  126. package/lib/plans/claim.ts +131 -0
  127. package/lib/plans/release.ts +5 -2
  128. package/lib/recipes/run.ts +6 -0
  129. package/lib/schedules/start.ts +1 -0
  130. package/lib/sessions/fork.ts +10 -0
  131. package/lib/sessions/launch.ts +5 -1
  132. package/lib/stacks/start.ts +1 -0
  133. package/lib/tasks/held-remote.ts +4 -2
  134. package/lib/tasks/held-replies.ts +5 -2
  135. package/lib/tasks/held.ts +2 -1
  136. package/lib/tasks/index.ts +85 -46
  137. package/lib/tasks/move-carry.ts +12 -1
  138. package/lib/tasks/move-guard.ts +2 -1
  139. package/lib/tasks/move.ts +7 -5
  140. package/lib/tasks/pause.ts +1 -1
  141. package/lib/tasks/queue.ts +54 -31
  142. package/lib/tasks/remote.ts +3 -1
  143. package/lib/tasks/starter.ts +124 -0
  144. package/lib/usage/calls.ts +2 -1
  145. package/lib/usage/turns.ts +2 -1
  146. package/package.json +6 -3
  147. package/scripts/check +1 -0
  148. package/scripts/gen-migrations-index.mjs +44 -0
  149. package/scripts/screenshots/demo.ts +5 -1
  150. package/scripts/screenshots/run.ts +5 -1
@@ -0,0 +1,23 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 18,
5
+ name: "add_chat",
6
+ up: (db) => {
7
+ db.exec(
8
+ `ALTER TABLE sessions ADD COLUMN view TEXT NOT NULL DEFAULT 'terminal'`
9
+ );
10
+ db.exec(`
11
+ CREATE TABLE IF NOT EXISTS chat_items (
12
+ session_id TEXT NOT NULL,
13
+ item_id TEXT NOT NULL,
14
+ seq INTEGER NOT NULL,
15
+ data TEXT NOT NULL,
16
+ PRIMARY KEY (session_id, item_id)
17
+ )
18
+ `);
19
+ db.exec(
20
+ `CREATE INDEX IF NOT EXISTS idx_chat_items_seq ON chat_items(session_id, seq)`
21
+ );
22
+ },
23
+ } satisfies Migration;
@@ -0,0 +1,36 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 19,
5
+ name: "add_lumifyhub",
6
+ up: (db) => {
7
+ db.exec(`
8
+ CREATE TABLE IF NOT EXISTS lumifyhub_connection (
9
+ id INTEGER PRIMARY KEY CHECK (id = 1),
10
+ base_url TEXT NOT NULL,
11
+ token TEXT NOT NULL,
12
+ user_id TEXT,
13
+ user_email TEXT,
14
+ user_name TEXT,
15
+ connected_at TEXT NOT NULL DEFAULT (datetime('now'))
16
+ )
17
+ `);
18
+ db.exec(`
19
+ CREATE TABLE IF NOT EXISTS lumifyhub_connect_attempts (
20
+ state TEXT PRIMARY KEY,
21
+ verifier TEXT NOT NULL,
22
+ redirect_uri TEXT NOT NULL,
23
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
24
+ )
25
+ `);
26
+ db.exec(`ALTER TABLE workspaces ADD COLUMN lh_workspace_id TEXT`);
27
+ db.exec(`ALTER TABLE workspaces ADD COLUMN lh_workspace_slug TEXT`);
28
+ db.exec(`ALTER TABLE workspaces ADD COLUMN lh_workspace_name TEXT`);
29
+ db.exec(`ALTER TABLE projects ADD COLUMN lh_board_id TEXT`);
30
+ db.exec(`ALTER TABLE projects ADD COLUMN lh_board_name TEXT`);
31
+ db.exec(`ALTER TABLE projects ADD COLUMN lh_board_page_id TEXT`);
32
+ db.exec(`ALTER TABLE sessions ADD COLUMN lh_card_id TEXT`);
33
+ db.exec(`ALTER TABLE sessions ADD COLUMN lh_board_id TEXT`);
34
+ db.exec(`ALTER TABLE sessions ADD COLUMN lh_card_list TEXT`);
35
+ },
36
+ } satisfies Migration;
@@ -0,0 +1,18 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 20,
5
+ name: "add_lumifyhub_published_docs",
6
+ up: (db) => {
7
+ db.exec(`
8
+ CREATE TABLE IF NOT EXISTS lumifyhub_published_docs (
9
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
10
+ repo_path TEXT NOT NULL,
11
+ page_id TEXT NOT NULL,
12
+ content_hash TEXT NOT NULL,
13
+ published_at TEXT NOT NULL DEFAULT (datetime('now')),
14
+ PRIMARY KEY (project_id, repo_path)
15
+ )
16
+ `);
17
+ },
18
+ } satisfies Migration;
@@ -0,0 +1,14 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 21,
5
+ name: "add_chat_access",
6
+ up: (db) => {
7
+ // What a chat agent may do without asking; full is the old behavior.
8
+ db.exec(
9
+ `ALTER TABLE sessions ADD COLUMN chat_access TEXT NOT NULL DEFAULT 'full'`
10
+ );
11
+ // After an undo, where the next start resumes the conversation from.
12
+ db.exec(`ALTER TABLE sessions ADD COLUMN chat_resume_at TEXT`);
13
+ },
14
+ } satisfies Migration;
@@ -0,0 +1,10 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 22,
5
+ name: "add_last_seen",
6
+ up: (db) => {
7
+ // When the reader last looked, so "needs you" means something new.
8
+ db.exec(`ALTER TABLE sessions ADD COLUMN last_seen_at TEXT`);
9
+ },
10
+ } satisfies Migration;
@@ -0,0 +1,12 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 23,
5
+ name: "mark_existing_sessions_seen",
6
+ up: (db) => {
7
+ // Start quiet: what finished before "needs you" meant news is old news.
8
+ db.exec(
9
+ `UPDATE sessions SET last_seen_at = datetime('now') WHERE last_seen_at IS NULL`
10
+ );
11
+ },
12
+ } satisfies Migration;
@@ -0,0 +1,49 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 24,
5
+ name: "add_stacks",
6
+ up: (db) => {
7
+ // A LumifyHub board's cards run as stacked tasks (lib/stacks).
8
+ db.exec(`
9
+ CREATE TABLE IF NOT EXISTS stacks (
10
+ id TEXT PRIMARY KEY,
11
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
12
+ lh_board_id TEXT NOT NULL,
13
+ name TEXT NOT NULL,
14
+ status TEXT NOT NULL DEFAULT 'running',
15
+ max_parallel INTEGER NOT NULL DEFAULT 3,
16
+ progress TEXT,
17
+ error TEXT,
18
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
19
+ landed_at TEXT
20
+ )
21
+ `);
22
+ db.exec(`
23
+ CREATE TABLE IF NOT EXISTS stack_items (
24
+ id TEXT PRIMARY KEY,
25
+ stack_id TEXT NOT NULL REFERENCES stacks(id) ON DELETE CASCADE,
26
+ position INTEGER NOT NULL,
27
+ lh_card_id TEXT NOT NULL,
28
+ ticket TEXT,
29
+ title TEXT NOT NULL,
30
+ parent_item_id TEXT,
31
+ also_item_ids TEXT NOT NULL DEFAULT '[]',
32
+ blocker_item_ids TEXT NOT NULL DEFAULT '[]',
33
+ status TEXT NOT NULL DEFAULT 'planned',
34
+ session_id TEXT,
35
+ base_branch TEXT,
36
+ base_tip TEXT,
37
+ pr_number INTEGER,
38
+ note TEXT,
39
+ error TEXT
40
+ )
41
+ `);
42
+ db.exec(
43
+ `CREATE INDEX IF NOT EXISTS idx_stack_items_stack ON stack_items(stack_id, position)`
44
+ );
45
+ db.exec(
46
+ `CREATE INDEX IF NOT EXISTS idx_stack_items_session ON stack_items(session_id)`
47
+ );
48
+ },
49
+ } satisfies Migration;
@@ -0,0 +1,16 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 25,
5
+ name: "add_stack_item_attempts",
6
+ up: (db) => {
7
+ // Starts retried after a transient failure, and holds the plan made
8
+ // (an open blocker outside the stack) that a retry must not undo.
9
+ db.exec(
10
+ `ALTER TABLE stack_items ADD COLUMN attempts INTEGER NOT NULL DEFAULT 0`
11
+ );
12
+ db.exec(
13
+ `ALTER TABLE stack_items ADD COLUMN held_outside INTEGER NOT NULL DEFAULT 0`
14
+ );
15
+ },
16
+ } satisfies Migration;
@@ -0,0 +1,47 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 26,
5
+ name: "add_workspace_orchestrator",
6
+ up: (db) => {
7
+ // One standing orchestrator chat per workspace. Its events are kept
8
+ // by key: a key present means that event is known, delivered or
9
+ // queued. An event is sent once seen on two diffs in a row (hits);
10
+ // a passing one that cleared is remembered (cleared_at) so it can't
11
+ // fire again too soon. The log counts deliveries per subject.
12
+ db.exec(`ALTER TABLE sessions ADD COLUMN role TEXT`);
13
+ db.exec(`ALTER TABLE sessions ADD COLUMN workspace_id TEXT`);
14
+ db.exec(
15
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_orchestrator
16
+ ON sessions(workspace_id) WHERE role = 'orchestrator'`
17
+ );
18
+ db.exec(`
19
+ CREATE TABLE IF NOT EXISTS orchestrator_events (
20
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
21
+ workspace_id TEXT NOT NULL,
22
+ key TEXT NOT NULL,
23
+ subject TEXT,
24
+ line TEXT NOT NULL,
25
+ sticky INTEGER NOT NULL DEFAULT 1,
26
+ low INTEGER NOT NULL DEFAULT 0,
27
+ hits INTEGER NOT NULL DEFAULT 1,
28
+ created_at TEXT NOT NULL,
29
+ delivered_at TEXT,
30
+ cleared_at TEXT,
31
+ UNIQUE (workspace_id, key)
32
+ )
33
+ `);
34
+ db.exec(`
35
+ CREATE TABLE IF NOT EXISTS orchestrator_event_log (
36
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
37
+ workspace_id TEXT NOT NULL,
38
+ subject TEXT,
39
+ delivered_at TEXT NOT NULL
40
+ )
41
+ `);
42
+ db.exec(
43
+ `CREATE INDEX IF NOT EXISTS idx_orchestrator_event_log
44
+ ON orchestrator_event_log(workspace_id, delivered_at)`
45
+ );
46
+ },
47
+ } satisfies Migration;
@@ -0,0 +1,28 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 27,
5
+ name: "add_devices_and_settings",
6
+ up: (db) => {
7
+ // Paired phones, tablets and laptops. Only a hash of each token is kept.
8
+ db.exec(`
9
+ CREATE TABLE IF NOT EXISTS devices (
10
+ id TEXT PRIMARY KEY,
11
+ name TEXT NOT NULL,
12
+ token_hash TEXT NOT NULL UNIQUE,
13
+ user_agent TEXT,
14
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
15
+ last_seen_at TEXT,
16
+ last_address TEXT,
17
+ revoked_at TEXT
18
+ )
19
+ `);
20
+ // Small app-wide switches (Wi-Fi access, pairing on the tailnet).
21
+ db.exec(`
22
+ CREATE TABLE IF NOT EXISTS settings (
23
+ key TEXT PRIMARY KEY,
24
+ value TEXT NOT NULL
25
+ )
26
+ `);
27
+ },
28
+ } satisfies Migration;
@@ -0,0 +1,70 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 28,
5
+ name: "add_orchestrator_acting",
6
+ up: (db) => {
7
+ // The orchestrator's brakes (settings per workspace, and the brake in
8
+ // force so it's noted once), its starts, its decision log, the reviews
9
+ // and scope checks it ran per commit, and gate failures per task.
10
+ db.exec(
11
+ `ALTER TABLE workspaces ADD COLUMN orch_max_running INTEGER NOT NULL DEFAULT 4`
12
+ );
13
+ db.exec(
14
+ `ALTER TABLE workspaces ADD COLUMN orch_max_starts_per_hour INTEGER NOT NULL DEFAULT 6`
15
+ );
16
+ db.exec(`ALTER TABLE workspaces ADD COLUMN orch_brake TEXT`);
17
+ // The secret an orchestrator's worker sends with each tool call.
18
+ db.exec(`ALTER TABLE sessions ADD COLUMN orch_token TEXT`);
19
+ db.exec(`
20
+ CREATE TABLE IF NOT EXISTS orchestrator_starts (
21
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
22
+ workspace_id TEXT NOT NULL,
23
+ kind TEXT NOT NULL,
24
+ target TEXT,
25
+ created_at TEXT NOT NULL
26
+ )
27
+ `);
28
+ db.exec(
29
+ `CREATE INDEX IF NOT EXISTS idx_orchestrator_starts
30
+ ON orchestrator_starts(workspace_id, created_at)`
31
+ );
32
+ db.exec(`
33
+ CREATE TABLE IF NOT EXISTS orchestrator_notes (
34
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
35
+ workspace_id TEXT NOT NULL,
36
+ kind TEXT NOT NULL DEFAULT 'note',
37
+ text TEXT NOT NULL,
38
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
39
+ )
40
+ `);
41
+ db.exec(
42
+ `CREATE INDEX IF NOT EXISTS idx_orchestrator_notes
43
+ ON orchestrator_notes(workspace_id, id)`
44
+ );
45
+ db.exec(`
46
+ CREATE TABLE IF NOT EXISTS orchestrator_checks (
47
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
48
+ workspace_id TEXT NOT NULL,
49
+ session_id TEXT NOT NULL,
50
+ sha TEXT NOT NULL,
51
+ kind TEXT NOT NULL,
52
+ status TEXT NOT NULL,
53
+ detail TEXT,
54
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
55
+ UNIQUE (session_id, sha, kind)
56
+ )
57
+ `);
58
+ db.exec(`
59
+ CREATE TABLE IF NOT EXISTS orchestrator_gate_failures (
60
+ session_id TEXT NOT NULL,
61
+ gate TEXT NOT NULL,
62
+ workspace_id TEXT NOT NULL,
63
+ count INTEGER NOT NULL DEFAULT 0,
64
+ last_reason TEXT,
65
+ escalated_at TEXT,
66
+ PRIMARY KEY (session_id, gate)
67
+ )
68
+ `);
69
+ },
70
+ } satisfies Migration;
@@ -0,0 +1,81 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 29,
5
+ name: "add_orchestrator_asks_and_pause",
6
+ up: (db) => {
7
+ // Items the orchestrator parks for Saad. One open ask per subject (a
8
+ // task, the brakes, a title it raised), so a repeat escalation updates
9
+ // it instead of adding another. An approval of a gate or brake ask is
10
+ // spent once (used_at), on the commit it was asked about (sha).
11
+ db.exec(`
12
+ CREATE TABLE IF NOT EXISTS orchestrator_asks (
13
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
14
+ workspace_id TEXT NOT NULL,
15
+ subject TEXT NOT NULL,
16
+ kind TEXT NOT NULL,
17
+ title TEXT NOT NULL,
18
+ detail TEXT NOT NULL DEFAULT '',
19
+ link TEXT,
20
+ sha TEXT,
21
+ status TEXT NOT NULL DEFAULT 'open',
22
+ answer TEXT,
23
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
24
+ resolved_at TEXT,
25
+ used_at TEXT,
26
+ brake_key TEXT
27
+ )
28
+ `);
29
+ db.exec(
30
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_orchestrator_asks_open
31
+ ON orchestrator_asks(workspace_id, subject) WHERE status = 'open'`
32
+ );
33
+ db.exec(
34
+ `CREATE INDEX IF NOT EXISTS idx_orchestrator_asks_workspace
35
+ ON orchestrator_asks(workspace_id, status)`
36
+ );
37
+ // While set, the orchestrator acts on nothing: events queue and its
38
+ // acting tools refuse.
39
+ db.exec(`ALTER TABLE workspaces ADD COLUMN orch_paused_at TEXT`);
40
+ // Proof a person approves: a paired device may answer asks only once
41
+ // Saad lets it, and approvals that matter need a passkey assertion
42
+ // (user verification) on a challenge bound to the one item.
43
+ db.exec(
44
+ `ALTER TABLE devices ADD COLUMN can_approve INTEGER NOT NULL DEFAULT 0`
45
+ );
46
+ db.exec(`
47
+ CREATE TABLE IF NOT EXISTS passkeys (
48
+ id TEXT PRIMARY KEY,
49
+ public_key BLOB NOT NULL,
50
+ counter INTEGER NOT NULL DEFAULT 0,
51
+ transports TEXT,
52
+ rp_id TEXT NOT NULL,
53
+ name TEXT NOT NULL,
54
+ registered_via TEXT,
55
+ registered_from TEXT,
56
+ user_agent TEXT,
57
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
58
+ last_used_at TEXT,
59
+ revoked_at TEXT
60
+ )
61
+ `);
62
+ db.exec(`
63
+ CREATE TABLE IF NOT EXISTS presence_challenges (
64
+ challenge TEXT PRIMARY KEY,
65
+ kind TEXT NOT NULL,
66
+ purpose TEXT NOT NULL,
67
+ binding TEXT NOT NULL,
68
+ rp_id TEXT NOT NULL,
69
+ expires_at INTEGER NOT NULL,
70
+ used_at INTEGER
71
+ )
72
+ `);
73
+ db.exec(`
74
+ CREATE TABLE IF NOT EXISTS passkey_enrollments (
75
+ code_hash TEXT PRIMARY KEY,
76
+ expires_at INTEGER NOT NULL,
77
+ used_at INTEGER
78
+ )
79
+ `);
80
+ },
81
+ } satisfies Migration;
@@ -0,0 +1,14 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 30,
5
+ name: "add_sessions_archived_at",
6
+ up: (db) => {
7
+ // Done sessions leave the sidebar but are never deleted, so their
8
+ // history and chat items stay.
9
+ db.exec(`ALTER TABLE sessions ADD COLUMN archived_at TEXT`);
10
+ db.exec(
11
+ `CREATE INDEX IF NOT EXISTS idx_sessions_archived_at ON sessions(archived_at)`
12
+ );
13
+ },
14
+ } satisfies Migration;
@@ -0,0 +1,22 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 31,
5
+ name: "add_stack_item_restacked_heads",
6
+ up: (db) => {
7
+ // A branch AgentOS rebased itself: its head before (the commit the
8
+ // task's code review covered) and after (the head AgentOS pushed).
9
+ // Each column checked, so a run cut off between the two can't be
10
+ // marked applied with one missing.
11
+ const cols = new Set(
12
+ (
13
+ db.prepare(`PRAGMA table_info(stack_items)`).all() as {
14
+ name: string;
15
+ }[]
16
+ ).map((c) => c.name)
17
+ );
18
+ for (const col of ["restacked_from", "restacked_to"])
19
+ if (!cols.has(col))
20
+ db.exec(`ALTER TABLE stack_items ADD COLUMN ${col} TEXT`);
21
+ },
22
+ } satisfies Migration;
@@ -0,0 +1,12 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 32,
5
+ name: "add_sessions_pinned",
6
+ up: (db) => {
7
+ // Pinned sessions sit on their own shelf at the top of the sidebar.
8
+ db.exec(
9
+ `ALTER TABLE sessions ADD COLUMN pinned INTEGER NOT NULL DEFAULT 0`
10
+ );
11
+ },
12
+ } satisfies Migration;
@@ -0,0 +1,18 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 33,
5
+ name: "add_program_status",
6
+ up: (db) => {
7
+ // What programs in a terminal report about themselves (OSC 7501),
8
+ // by tmux session: kept so a restart doesn't forget a finished or
9
+ // blocked session.
10
+ db.exec(`
11
+ CREATE TABLE IF NOT EXISTS program_status (
12
+ session_name TEXT PRIMARY KEY,
13
+ records TEXT NOT NULL,
14
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
15
+ )
16
+ `);
17
+ },
18
+ } satisfies Migration;
@@ -0,0 +1,21 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 34,
5
+ name: "add_session_names",
6
+ up: (db) => {
7
+ // Names a session had before it was renamed, so a message sent to
8
+ // an old name still reaches it.
9
+ db.exec(`
10
+ CREATE TABLE IF NOT EXISTS session_names (
11
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
12
+ session_id TEXT NOT NULL,
13
+ name TEXT NOT NULL,
14
+ renamed_at TEXT NOT NULL DEFAULT (datetime('now'))
15
+ )
16
+ `);
17
+ db.exec(
18
+ `CREATE INDEX IF NOT EXISTS idx_session_names_session ON session_names(session_id)`
19
+ );
20
+ },
21
+ } satisfies Migration;
@@ -0,0 +1,23 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 35,
5
+ name: "add_artifacts",
6
+ up: (db) => {
7
+ // Pages a chat agent showed with html_render. The HTML lives in a file
8
+ // under ~/.agent-os/artifacts; the row says whose it is and what it's
9
+ // called.
10
+ db.exec(`
11
+ CREATE TABLE IF NOT EXISTS artifacts (
12
+ id TEXT PRIMARY KEY,
13
+ session_id TEXT NOT NULL,
14
+ title TEXT NOT NULL,
15
+ path TEXT NOT NULL,
16
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
17
+ )
18
+ `);
19
+ db.exec(
20
+ `CREATE INDEX IF NOT EXISTS idx_artifacts_session ON artifacts(session_id, created_at)`
21
+ );
22
+ },
23
+ } satisfies Migration;
@@ -0,0 +1,26 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 36,
5
+ name: "add_chat_queue",
6
+ up: (db) => {
7
+ // Messages written while a chat turn runs, sent in order once it ends.
8
+ db.exec(`
9
+ CREATE TABLE IF NOT EXISTS chat_queue (
10
+ session_id TEXT NOT NULL,
11
+ id TEXT NOT NULL,
12
+ position REAL NOT NULL,
13
+ text TEXT NOT NULL,
14
+ images TEXT,
15
+ image_count INTEGER NOT NULL DEFAULT 0,
16
+ created_at INTEGER NOT NULL,
17
+ PRIMARY KEY (session_id, id)
18
+ )
19
+ `);
20
+ db.exec(
21
+ `CREATE INDEX IF NOT EXISTS idx_chat_queue_session ON chat_queue(session_id, position)`
22
+ );
23
+ // The agent's guess at the next message, shown in an empty composer.
24
+ db.exec(`ALTER TABLE sessions ADD COLUMN chat_suggestion TEXT`);
25
+ },
26
+ } satisfies Migration;
@@ -0,0 +1,39 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 37,
5
+ name: "add_chat_plan_and_turns",
6
+ // One transaction, so a crash part-way leaves nothing to skip as
7
+ // "duplicate column" on the next start.
8
+ up: (db) =>
9
+ db.transaction(() => {
10
+ // Plan mode is remembered per session; the context meter's last
11
+ // reading survives a reload; and the agent's running totals at its
12
+ // last turn tell what the next turn added.
13
+ db.exec(
14
+ `ALTER TABLE sessions ADD COLUMN chat_plan INTEGER NOT NULL DEFAULT 0`
15
+ );
16
+ db.exec(`ALTER TABLE sessions ADD COLUMN chat_context TEXT`);
17
+ db.exec(`ALTER TABLE sessions ADD COLUMN chat_usage TEXT`);
18
+ // What each chat turn cost, kept with the session's name and
19
+ // workspace so the history outlives the session.
20
+ db.exec(`
21
+ CREATE TABLE IF NOT EXISTS chat_turns (
22
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
23
+ session_id TEXT NOT NULL,
24
+ session_name TEXT NOT NULL,
25
+ workspace_id TEXT,
26
+ at INTEGER NOT NULL,
27
+ cost_usd REAL NOT NULL,
28
+ input_tokens INTEGER NOT NULL,
29
+ output_tokens INTEGER NOT NULL,
30
+ cache_read_tokens INTEGER NOT NULL,
31
+ cache_write_tokens INTEGER NOT NULL
32
+ )
33
+ `);
34
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_chat_turns_at ON chat_turns(at)`);
35
+ db.exec(
36
+ `CREATE INDEX IF NOT EXISTS idx_chat_turns_session ON chat_turns(session_id, id)`
37
+ );
38
+ })(),
39
+ } satisfies Migration;
@@ -0,0 +1,56 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ id: 38,
5
+ name: "add_schedules",
6
+ up: (db) => {
7
+ // Cron schedules that start agent work, and every run they made or
8
+ // skipped. A run's (schedule, slot) is unique: claiming the row is
9
+ // what stops a slot from running twice. Runs are never deleted, and a
10
+ // removed schedule is archived, not deleted, so its history stays.
11
+ db.exec(`
12
+ CREATE TABLE IF NOT EXISTS schedules (
13
+ id TEXT PRIMARY KEY,
14
+ workspace_id TEXT NOT NULL,
15
+ project_id TEXT,
16
+ name TEXT NOT NULL,
17
+ cron TEXT NOT NULL,
18
+ timezone TEXT NOT NULL DEFAULT 'America/Chicago',
19
+ prompt TEXT NOT NULL,
20
+ kind TEXT NOT NULL,
21
+ enabled INTEGER NOT NULL DEFAULT 1,
22
+ armed_at INTEGER NOT NULL,
23
+ archived_at TEXT,
24
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
25
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
26
+ )
27
+ `);
28
+ db.exec(`
29
+ CREATE TABLE IF NOT EXISTS schedule_runs (
30
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
31
+ schedule_id TEXT NOT NULL,
32
+ slot TEXT NOT NULL,
33
+ slot_at INTEGER NOT NULL,
34
+ trigger TEXT NOT NULL,
35
+ outcome TEXT NOT NULL,
36
+ detail TEXT,
37
+ session_id TEXT,
38
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
39
+ UNIQUE (schedule_id, slot)
40
+ )
41
+ `);
42
+ db.exec(
43
+ `CREATE INDEX IF NOT EXISTS idx_schedule_runs_schedule ON schedule_runs(schedule_id, id)`
44
+ );
45
+ // Which server process ticks the schedules: one row, renewed each
46
+ // tick, so a second server on the same database never runs them.
47
+ db.exec(`
48
+ CREATE TABLE IF NOT EXISTS scheduler_lease (
49
+ id INTEGER PRIMARY KEY CHECK (id = 1),
50
+ owner TEXT NOT NULL,
51
+ pid INTEGER NOT NULL,
52
+ heartbeat INTEGER NOT NULL
53
+ )
54
+ `);
55
+ },
56
+ } satisfies Migration;