@saadnvd1/agent-os 0.3.700 → 0.3.723

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 (306) hide show
  1. package/README.md +2 -0
  2. package/app/api/agent-roles/route.test.ts +67 -0
  3. package/app/api/agent-roles/route.ts +61 -0
  4. package/app/api/analyst/[id]/recommendations/[recId]/again/route.ts +15 -0
  5. package/app/api/analyst/[id]/recommendations/[recId]/dismiss/route.ts +13 -0
  6. package/app/api/analyst/[id]/recommendations/[recId]/send/route.ts +13 -0
  7. package/app/api/analyst/[id]/review/route.ts +22 -0
  8. package/app/api/analyst/[id]/route.ts +44 -0
  9. package/app/api/analyst/route.ts +10 -0
  10. package/app/api/bus/groups/route.ts +44 -0
  11. package/app/api/bus/spawn/route.ts +34 -2
  12. package/app/api/claims/[id]/route.ts +20 -0
  13. package/app/api/claims/check/route.ts +23 -0
  14. package/app/api/claims/check.test.ts +113 -0
  15. package/app/api/claims/exchange/route.ts +42 -0
  16. package/app/api/claims/outside.test.ts +90 -0
  17. package/app/api/claims/route.test.ts +193 -0
  18. package/app/api/claims/route.ts +73 -0
  19. package/app/api/hosts/[id]/route.ts +9 -1
  20. package/app/api/models/availability/route.ts +9 -0
  21. package/app/api/models/choices/route.ts +9 -0
  22. package/app/api/peer/unlink/route.ts +17 -0
  23. package/app/api/peers/[hostId]/audit/route.ts +14 -0
  24. package/app/api/peers/[hostId]/route.ts +20 -0
  25. package/app/api/peers/gate.test.ts +64 -1
  26. package/app/api/peers/pending/route.test.ts +37 -0
  27. package/app/api/peers/pending/route.ts +11 -4
  28. package/app/api/session-groups/[id]/restore/route.ts +11 -0
  29. package/app/api/session-groups/[id]/route.ts +25 -0
  30. package/app/api/session-groups/order/route.ts +15 -0
  31. package/app/api/session-groups/route.ts +21 -0
  32. package/app/api/sessions/[id]/analyst/route.ts +11 -0
  33. package/app/api/sessions/[id]/crew/route.ts +38 -0
  34. package/app/api/sessions/[id]/export/estimate/route.ts +23 -0
  35. package/app/api/sessions/[id]/export/route.test.ts +125 -0
  36. package/app/api/sessions/[id]/export/route.ts +34 -0
  37. package/app/api/sessions/[id]/fork/route.ts +3 -0
  38. package/app/api/sessions/[id]/group/route.ts +18 -0
  39. package/app/api/sessions/[id]/model/route.ts +49 -0
  40. package/app/api/sessions/[id]/route.ts +14 -4
  41. package/app/api/sessions/[id]/summarize/route.ts +2 -0
  42. package/app/api/sessions/claims.test.ts +122 -0
  43. package/app/api/sessions/group/route.ts +17 -0
  44. package/app/api/sessions/route.ts +31 -14
  45. package/app/page.tsx +10 -0
  46. package/components/Chat/Messages.tsx +104 -10
  47. package/components/Claims/ClaimFiles.tsx +38 -0
  48. package/components/Claims/ClaimRow.tsx +82 -0
  49. package/components/Claims/ClaimsSheet.tsx +176 -0
  50. package/components/Claims/OverlapPill.tsx +31 -0
  51. package/components/Claims/StartClaimsNotice.tsx +70 -0
  52. package/components/Claims/claims-ui.test.ts +161 -0
  53. package/components/Claims/format.ts +57 -0
  54. package/components/Claims/index.ts +3 -0
  55. package/components/Draft/DraftChips.tsx +6 -1
  56. package/components/Draft/DraftPanel.tsx +90 -3
  57. package/components/Draft/ModelUnavailableDialog.tsx +78 -0
  58. package/components/Draft/RoleChips.tsx +110 -0
  59. package/components/Export/ExportActions.tsx +136 -0
  60. package/components/Export/ExportSheet.tsx +217 -0
  61. package/components/Export/RangePicker.tsx +144 -0
  62. package/components/Export/Seg.tsx +38 -0
  63. package/components/Export/TurnSelectBar.tsx +45 -0
  64. package/components/Hosts/AccountMachines.tsx +32 -18
  65. package/components/Hosts/HostRow.tsx +155 -14
  66. package/components/Hosts/IncomingLinkSheet.tsx +28 -10
  67. package/components/Hosts/PeerActivitySheet.tsx +111 -0
  68. package/components/Models/AgentRoleCard.tsx +114 -0
  69. package/components/Models/AgentRolesSection.tsx +132 -0
  70. package/components/Models/ModelBadges.tsx +48 -0
  71. package/components/Models/ModelsSection.tsx +4 -2
  72. package/components/Models/RoleModelSelect.tsx +87 -0
  73. package/components/Pane/DesktopTabBar.tsx +2 -0
  74. package/components/Pane/MobileTabBar.tsx +12 -0
  75. package/components/Pane/PaneMenu.tsx +10 -0
  76. package/components/SessionList/GroupShelves.tsx +195 -0
  77. package/components/SessionList/MoveToGroupMenu.tsx +105 -0
  78. package/components/SessionList/RowSubtitle.tsx +7 -1
  79. package/components/SessionList/SelectionToolbar.tsx +52 -1
  80. package/components/SessionList/SessionRow.tsx +19 -7
  81. package/components/SessionList/SessionRowMenu.tsx +23 -0
  82. package/components/SessionList/SessionShelves.tsx +5 -0
  83. package/components/SessionList/SidebarBody.tsx +6 -0
  84. package/components/SessionList/SidebarContextMenu.test.ts +104 -0
  85. package/components/SessionList/SidebarContextMenu.tsx +59 -0
  86. package/components/SessionList/SidebarHeader.tsx +5 -0
  87. package/components/SessionList/WorkspaceSwitcher.tsx +23 -6
  88. package/components/SessionList/index.tsx +18 -14
  89. package/components/SessionList/useSidebarData.ts +10 -0
  90. package/components/Sessions/RolePill.tsx +196 -0
  91. package/components/Settings/SettingsDialog.tsx +9 -0
  92. package/components/Share/ShareDialog.tsx +13 -0
  93. package/components/ui/notice.tsx +46 -0
  94. package/components/ui/status-pill.tsx +39 -0
  95. package/data/analyst/index.ts +3 -0
  96. package/data/analyst/keys.ts +6 -0
  97. package/data/analyst/mutations.ts +116 -0
  98. package/data/analyst/queries.ts +35 -0
  99. package/data/claims/index.ts +2 -0
  100. package/data/claims/keys.ts +5 -0
  101. package/data/claims/queries.ts +47 -0
  102. package/data/exports/index.ts +2 -0
  103. package/data/exports/keys.ts +3 -0
  104. package/data/exports/queries.ts +51 -0
  105. package/data/models/index.ts +98 -0
  106. package/data/peers/keys.ts +1 -0
  107. package/data/peers/queries.ts +31 -0
  108. package/data/push/topics.ts +9 -0
  109. package/data/session-groups/index.ts +156 -0
  110. package/data/sessions/index.ts +0 -1
  111. package/data/sessions/pin.ts +2 -6
  112. package/data/sessions/queries.ts +36 -29
  113. package/data/sessions/shelf.ts +2 -6
  114. package/data/tasks/index.ts +2 -0
  115. package/hooks/useSessions.ts +0 -12
  116. package/lib/__fixtures__/peer-rpc.ts +65 -33
  117. package/lib/agents/brief.ts +1 -0
  118. package/lib/agents/spawn.ts +4 -0
  119. package/lib/analyst/__fixtures__/items.ts +57 -0
  120. package/lib/analyst/__fixtures__/mocks.ts +49 -0
  121. package/lib/analyst/brief.ts +17 -0
  122. package/lib/analyst/buildDigest.ts +204 -0
  123. package/lib/analyst/createLink.ts +98 -0
  124. package/lib/analyst/endLink.ts +31 -0
  125. package/lib/analyst/forward.ts +109 -0
  126. package/lib/analyst/index.ts +16 -0
  127. package/lib/analyst/linkView.ts +38 -0
  128. package/lib/analyst/onTurnEnd.ts +119 -0
  129. package/lib/analyst/parseReview.ts +41 -0
  130. package/lib/analyst/pushDigest.ts +143 -0
  131. package/lib/analyst/resume.ts +35 -0
  132. package/lib/analyst/route.ts +50 -0
  133. package/lib/analyst/signals.ts +121 -0
  134. package/lib/analyst/store.ts +303 -0
  135. package/lib/analyst/types.ts +140 -0
  136. package/lib/bus/condense.ts +5 -1
  137. package/lib/bus/index.ts +13 -0
  138. package/lib/bus/read-scope.ts +12 -0
  139. package/lib/bus/role-alias.ts +70 -0
  140. package/lib/bus/targets.ts +3 -0
  141. package/lib/chat/drivers/opencode-mapper.ts +55 -1
  142. package/lib/chat/drivers/pi-approvals.ts +7 -4
  143. package/lib/chat/drivers/pi-mapper.ts +38 -0
  144. package/lib/chat/drivers/pi-text-tools.ts +104 -0
  145. package/lib/chat/drivers/pi.ts +8 -3
  146. package/lib/chat/drivers/turn-items.ts +36 -11
  147. package/lib/chat/drivers/turn-outcome.ts +108 -0
  148. package/lib/chat/events.ts +8 -0
  149. package/lib/chat/registry.ts +13 -0
  150. package/lib/chat/store.ts +19 -0
  151. package/lib/chat/turns.ts +1 -0
  152. package/lib/chat/worker/extras.ts +4 -2
  153. package/lib/claims/collectLocal.ts +123 -0
  154. package/lib/claims/describe.ts +41 -0
  155. package/lib/claims/exchange.ts +91 -0
  156. package/lib/claims/goal.ts +45 -0
  157. package/lib/claims/index.ts +10 -0
  158. package/lib/claims/loop.ts +51 -0
  159. package/lib/claims/machine.ts +21 -0
  160. package/lib/claims/mine.ts +43 -0
  161. package/lib/claims/notifyOverlaps.ts +101 -0
  162. package/lib/claims/onMerged.ts +85 -0
  163. package/lib/claims/outside.ts +36 -0
  164. package/lib/claims/overlap.ts +87 -0
  165. package/lib/claims/overlapCache.ts +86 -0
  166. package/lib/claims/overlapText.ts +36 -0
  167. package/lib/claims/peers.ts +56 -0
  168. package/lib/claims/startCheck.ts +100 -0
  169. package/lib/claims/startWarning.ts +29 -0
  170. package/lib/claims/store.ts +366 -0
  171. package/lib/claims/types.ts +102 -0
  172. package/lib/claims/view.ts +80 -0
  173. package/lib/claims/yield.ts +24 -0
  174. package/lib/db/changes.ts +12 -0
  175. package/lib/db/migrations/20261020T1400_work_claims.ts +35 -0
  176. package/lib/db/migrations/20261020T1515_peer_unlinked.ts +22 -0
  177. package/lib/db/migrations/20261020T1700_clean_connect_names.ts +18 -0
  178. package/lib/db/migrations/20261020T1800_session_groups.ts +49 -0
  179. package/lib/db/migrations/20261020T1900_task_queue_after_claim.ts +13 -0
  180. package/lib/db/migrations/20261020T2000_claim_notices.ts +20 -0
  181. package/lib/db/migrations/20261020T2100_claims_via_host.ts +21 -0
  182. package/lib/db/migrations/20261020T2200_work_claims_watch.ts +10 -0
  183. package/lib/db/migrations/20261021T1400_session_agent_roles.ts +20 -0
  184. package/lib/db/migrations/20261021T1430_analyst_links.ts +52 -0
  185. package/lib/db/queries.ts +0 -40
  186. package/lib/db/session-parts/columns.ts +3 -0
  187. package/lib/db/types.ts +19 -8
  188. package/lib/doctor/checks.ts +64 -1
  189. package/lib/done/archive.ts +2 -0
  190. package/lib/drafts.ts +4 -0
  191. package/lib/export/build.ts +470 -0
  192. package/lib/export/compact.ts +156 -0
  193. package/lib/export/estimate.ts +83 -0
  194. package/lib/export/fixtures.ts +45 -0
  195. package/lib/export/html.tsx +195 -0
  196. package/lib/export/json.ts +39 -0
  197. package/lib/export/load.ts +64 -0
  198. package/lib/export/markdown.ts +127 -0
  199. package/lib/export/request.ts +36 -0
  200. package/lib/export/service.ts +142 -0
  201. package/lib/export/summary.ts +86 -0
  202. package/lib/export/turns.ts +63 -0
  203. package/lib/export/view.ts +173 -0
  204. package/lib/git-remote.ts +43 -0
  205. package/lib/hosts/index.ts +10 -1
  206. package/lib/models/agent-binding.ts +102 -0
  207. package/lib/models/agent-roles-view.ts +157 -0
  208. package/lib/models/agent-roles.ts +87 -0
  209. package/lib/models/availability-refs.ts +17 -0
  210. package/lib/models/availability.ts +91 -0
  211. package/lib/models/catalog.ts +156 -0
  212. package/lib/models/config.ts +27 -0
  213. package/lib/models/locality.ts +33 -0
  214. package/lib/models/providers.ts +11 -0
  215. package/lib/models/resolve.ts +50 -12
  216. package/lib/models/roles.ts +12 -0
  217. package/lib/needs-you.ts +1 -1
  218. package/lib/orchestration.ts +2 -0
  219. package/lib/orchestrator/act.ts +54 -4
  220. package/lib/orchestrator/brief.ts +2 -1
  221. package/lib/orchestrator/claim-wait.ts +71 -0
  222. package/lib/orchestrator/conditions.ts +28 -1
  223. package/lib/orchestrator/describe.ts +6 -1
  224. package/lib/orchestrator/facts.ts +12 -2
  225. package/lib/orchestrator/read.ts +5 -1
  226. package/lib/orchestrator/serve.ts +37 -2
  227. package/lib/orchestrator/tool-names.ts +1 -0
  228. package/lib/orchestrator/tool-schemas.ts +31 -1
  229. package/lib/orchestrator/tools.ts +3 -1
  230. package/lib/orchestrator/untrusted.ts +5 -0
  231. package/lib/orchestrator/watcher.ts +19 -1
  232. package/lib/peer/account.ts +74 -2
  233. package/lib/peer/allowlist.ts +1 -1
  234. package/lib/peer/client.ts +26 -1
  235. package/lib/peer/link-cli.ts +19 -4
  236. package/lib/peer/links.ts +117 -5
  237. package/lib/peer/machines.ts +14 -2
  238. package/lib/peer/name.ts +32 -0
  239. package/lib/peer/pairing.ts +34 -5
  240. package/lib/peer/pin.ts +10 -3
  241. package/lib/peer/reasons.ts +7 -0
  242. package/lib/peer/revoke.ts +75 -0
  243. package/lib/peer/rpc-server.ts +53 -5
  244. package/lib/peer/unlink.ts +62 -0
  245. package/lib/peer/unlinked-proof.ts +44 -0
  246. package/lib/projects.ts +6 -2
  247. package/lib/security/demo.ts +7 -0
  248. package/lib/session-artifacts/agentos-files.ts +94 -0
  249. package/lib/session-artifacts/collect.ts +17 -0
  250. package/lib/session-groups/assignSessions.ts +81 -0
  251. package/lib/session-groups/cli.ts +61 -0
  252. package/lib/session-groups/createGroup.ts +28 -0
  253. package/lib/session-groups/index.ts +21 -0
  254. package/lib/session-groups/removeGroup.ts +36 -0
  255. package/lib/session-groups/reorderGroups.ts +31 -0
  256. package/lib/session-groups/resolveGroup.ts +19 -0
  257. package/lib/session-groups/route.ts +32 -0
  258. package/lib/session-groups/store.ts +85 -0
  259. package/lib/session-groups/types.ts +25 -0
  260. package/lib/session-groups/updateGroup.ts +35 -0
  261. package/lib/session-groups/workspace.ts +21 -0
  262. package/lib/sessions/crew.ts +72 -0
  263. package/lib/sessions/launch.ts +54 -11
  264. package/lib/settings-url.ts +1 -0
  265. package/lib/share/markdown.ts +2 -2
  266. package/lib/share/redact.ts +16 -10
  267. package/lib/share/render.tsx +1 -1
  268. package/lib/share/snapshot.ts +2 -2
  269. package/lib/sidebar/rollup.ts +1 -0
  270. package/lib/sidebar/row-menu.ts +8 -1
  271. package/lib/sidebar/shelves.ts +90 -15
  272. package/lib/sidebar/visible-order.ts +5 -0
  273. package/lib/tasks/hold-checks.ts +3 -1
  274. package/lib/tasks/holds.ts +3 -0
  275. package/lib/tasks/index.ts +11 -0
  276. package/lib/tasks/queue-rows.ts +8 -1
  277. package/lib/tasks/queue-start.ts +1 -0
  278. package/lib/tasks/queue-types.ts +9 -1
  279. package/lib/tasks/queue.ts +15 -5
  280. package/lib/tasks/schedule-types.ts +1 -0
  281. package/lib/test-temp.ts +19 -3
  282. package/lib/workspaces.ts +11 -3
  283. package/lib/worktree-deps/caches.ts +3 -2
  284. package/lib/worktree-deps/clone.ts +3 -1
  285. package/lib/worktree-deps/paths.ts +26 -0
  286. package/lib/worktree-sweep/testTemp.ts +23 -106
  287. package/package.json +1 -1
  288. package/scripts/agent-os +1 -1
  289. package/scripts/autodeploy +2 -0
  290. package/scripts/autodeploy.test.ts +31 -1
  291. package/scripts/claim-hook.sh +31 -0
  292. package/scripts/claim-hook.test.ts +230 -0
  293. package/scripts/lib/cli-links.sh +36 -0
  294. package/scripts/lib/commands.sh +3 -0
  295. package/scripts/lib/machine.sh +27 -2
  296. package/scripts/lib/machine.test.ts +25 -3
  297. package/scripts/sync-cli-links +7 -0
  298. package/scripts/sync-cli-links.test.ts +69 -0
  299. package/server.ts +12 -1
  300. package/stores/claimsUi.ts +22 -0
  301. package/stores/exportUi.ts +87 -0
  302. package/app/api/groups/[...path]/route.ts +0 -136
  303. package/app/api/groups/route.ts +0 -93
  304. package/data/groups/index.ts +0 -1
  305. package/data/groups/mutations.ts +0 -95
  306. package/hooks/useGroups.ts +0 -37
@@ -0,0 +1,49 @@
1
+ import type { Migration } from "../migration-types";
2
+ import {
3
+ installChangeTriggers,
4
+ TABLES_WATCHED_SESSION_GROUPS,
5
+ } from "../changes";
6
+ import { createSessionRowsView } from "../session-parts/view";
7
+
8
+ export default {
9
+ key: "20261020T1800_session_groups",
10
+ up: (db) => {
11
+ // Named shelves a user files sessions into (lib/session-groups). Not the
12
+ // old `groups` table, which nothing reads. Additive.
13
+ db.exec(`CREATE TABLE IF NOT EXISTS session_groups (
14
+ id TEXT PRIMARY KEY,
15
+ workspace_id TEXT REFERENCES workspaces(id) ON DELETE SET NULL,
16
+ name TEXT NOT NULL,
17
+ sort_order INTEGER NOT NULL DEFAULT 0,
18
+ collapsed INTEGER NOT NULL DEFAULT 0,
19
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
20
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
21
+ deleted_at TEXT
22
+ )`);
23
+ db.exec(
24
+ `CREATE UNIQUE INDEX IF NOT EXISTS session_groups_name
25
+ ON session_groups(COALESCE(workspace_id, ''), lower(name))
26
+ WHERE deleted_at IS NULL`
27
+ );
28
+ const has = (
29
+ db.prepare(`PRAGMA table_info(sessions)`).all() as { name: string }[]
30
+ ).some((c) => c.name === "session_group_id");
31
+ if (!has)
32
+ db.exec(
33
+ `ALTER TABLE sessions ADD COLUMN session_group_id TEXT
34
+ REFERENCES session_groups(id) ON DELETE SET NULL`
35
+ );
36
+ db.exec(
37
+ `CREATE INDEX IF NOT EXISTS sessions_session_group
38
+ ON sessions(session_group_id)`
39
+ );
40
+ // A queued task remembers the group it starts in.
41
+ const queueHas = (
42
+ db.prepare(`PRAGMA table_info(task_queue)`).all() as { name: string }[]
43
+ ).some((c) => c.name === "session_group_id");
44
+ if (!queueHas)
45
+ db.exec(`ALTER TABLE task_queue ADD COLUMN session_group_id TEXT`);
46
+ createSessionRowsView(db);
47
+ installChangeTriggers(db, TABLES_WATCHED_SESSION_GROUPS);
48
+ },
49
+ } satisfies Migration;
@@ -0,0 +1,13 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ key: "20261020T1900_task_queue_after_claim",
5
+ up: (db) => {
6
+ // The work claim (lib/claims) a queued task waits on, by claim id.
7
+ const cols = db.prepare(`PRAGMA table_info(task_queue)`).all() as {
8
+ name: string;
9
+ }[];
10
+ if (!cols.some((c) => c.name === "after_claim"))
11
+ db.exec(`ALTER TABLE task_queue ADD COLUMN after_claim TEXT`);
12
+ },
13
+ } satisfies Migration;
@@ -0,0 +1,20 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ key: "20261020T2000_claim_notices",
5
+ up: (db) => {
6
+ // What a mid-work overlap between two claims has told the local session:
7
+ // how many syncs it has held, the shared paths last told, and whether the
8
+ // winner's merge has been passed on. Times are this machine's clock in ms.
9
+ db.exec(`
10
+ CREATE TABLE IF NOT EXISTS claim_notices (
11
+ pair_key TEXT PRIMARY KEY,
12
+ hits INTEGER NOT NULL DEFAULT 0,
13
+ shared TEXT NOT NULL DEFAULT '[]',
14
+ told_at INTEGER,
15
+ merged_at INTEGER,
16
+ seen_at INTEGER NOT NULL
17
+ );
18
+ `);
19
+ },
20
+ } satisfies Migration;
@@ -0,0 +1,21 @@
1
+ import type { Migration } from "../migration-types";
2
+
3
+ export default {
4
+ key: "20261020T2100_claims_via_host",
5
+ up: (db) => {
6
+ // The link (hosts.id) a remote claim arrived through, and which claims
7
+ // machine each link talks to, so a machine linked twice is asked once.
8
+ const cols = db.prepare(`PRAGMA table_info(work_claims)`).all() as {
9
+ name: string;
10
+ }[];
11
+ if (!cols.some((c) => c.name === "via_host"))
12
+ db.exec(`ALTER TABLE work_claims ADD COLUMN via_host TEXT`);
13
+ db.exec(`
14
+ CREATE TABLE IF NOT EXISTS claim_peers (
15
+ host_id TEXT PRIMARY KEY,
16
+ machine_id TEXT NOT NULL,
17
+ seen_at INTEGER NOT NULL
18
+ );
19
+ `);
20
+ },
21
+ } satisfies Migration;
@@ -0,0 +1,10 @@
1
+ import type { Migration } from "../migration-types";
2
+ import { installChangeTriggers, TABLES_WATCHED_WORK_CLAIMS } from "../changes";
3
+
4
+ export default {
5
+ key: "20261020T2200_work_claims_watch",
6
+ up: (db) => {
7
+ // The claims sheet and the overlap pills refetch when a claim changes.
8
+ installChangeTriggers(db, TABLES_WATCHED_WORK_CLAIMS);
9
+ },
10
+ } satisfies Migration;
@@ -0,0 +1,20 @@
1
+ import type { Migration } from "../migration-types";
2
+ import { createSessionRowsView } from "../session-parts/view";
3
+
4
+ export default {
5
+ key: "20261021T1400_session_agent_roles",
6
+ up: (db) => {
7
+ // The role a session was started in (developer, analyst, reviewer,
8
+ // supervisor) and the crew it works with: the id of the session that
9
+ // began it. Additive.
10
+ const cols = (
11
+ db.prepare(`PRAGMA table_info(sessions)`).all() as { name: string }[]
12
+ ).map((c) => c.name);
13
+ if (!cols.includes("agent_role"))
14
+ db.exec(`ALTER TABLE sessions ADD COLUMN agent_role TEXT`);
15
+ if (!cols.includes("crew_id"))
16
+ db.exec(`ALTER TABLE sessions ADD COLUMN crew_id TEXT`);
17
+ db.exec(`CREATE INDEX IF NOT EXISTS sessions_crew ON sessions(crew_id)`);
18
+ createSessionRowsView(db);
19
+ },
20
+ } satisfies Migration;
@@ -0,0 +1,52 @@
1
+ import type { Migration } from "../migration-types";
2
+ import { installChangeTriggers, TABLES_WATCHED_ANALYST } from "../changes";
3
+
4
+ export default {
5
+ key: "20261021T1430_analyst_links",
6
+ up: (db) => {
7
+ // A coding chat paired with an analyst chat that reviews each of its
8
+ // turns (lib/analyst). Rows are kept after unlinking.
9
+ db.exec(`
10
+ CREATE TABLE IF NOT EXISTS analyst_links (
11
+ id TEXT PRIMARY KEY,
12
+ coder_session_id TEXT NOT NULL,
13
+ analyst_session_id TEXT NOT NULL,
14
+ paused INTEGER NOT NULL DEFAULT 0,
15
+ reviewed_through TEXT,
16
+ pending_digest_id TEXT,
17
+ pending_through TEXT,
18
+ digest_signals TEXT,
19
+ created_at INTEGER NOT NULL,
20
+ ended_at INTEGER
21
+ );
22
+ CREATE UNIQUE INDEX IF NOT EXISTS analyst_links_coder_live
23
+ ON analyst_links(coder_session_id) WHERE ended_at IS NULL;
24
+ CREATE UNIQUE INDEX IF NOT EXISTS analyst_links_analyst
25
+ ON analyst_links(analyst_session_id);
26
+ CREATE TABLE IF NOT EXISTS analyst_recommendations (
27
+ id TEXT PRIMARY KEY,
28
+ link_id TEXT NOT NULL,
29
+ analyst_item_id TEXT NOT NULL,
30
+ coder_through TEXT,
31
+ verdict TEXT,
32
+ summary TEXT NOT NULL DEFAULT '',
33
+ issues TEXT NOT NULL DEFAULT '[]',
34
+ signals TEXT,
35
+ prompt TEXT,
36
+ state TEXT NOT NULL DEFAULT 'open',
37
+ error TEXT,
38
+ sent_text TEXT,
39
+ sent_item_id TEXT,
40
+ edited INTEGER NOT NULL DEFAULT 0,
41
+ created_at INTEGER NOT NULL,
42
+ decided_at INTEGER
43
+ );
44
+ CREATE UNIQUE INDEX IF NOT EXISTS analyst_recs_item
45
+ ON analyst_recommendations(link_id, analyst_item_id);
46
+ CREATE INDEX IF NOT EXISTS analyst_recs_link
47
+ ON analyst_recommendations(link_id, created_at);
48
+ `);
49
+ // The pane's card and the sidebar refetch when either changes.
50
+ installChangeTriggers(db, TABLES_WATCHED_ANALYST);
51
+ },
52
+ } satisfies Migration;
package/lib/db/queries.ts CHANGED
@@ -94,24 +94,6 @@ export const queries = {
94
94
  `UPDATE sessions SET worktree_path = ?, branch_name = ?, base_branch = ?, dev_server_port = ?, updated_at = datetime('now') WHERE id = ?`
95
95
  ),
96
96
 
97
- updateSessionGroup: (db: Database.Database) =>
98
- getStmt(
99
- db,
100
- `UPDATE sessions SET group_path = ?, updated_at = datetime('now') WHERE id = ?`
101
- ),
102
-
103
- getSessionsByGroup: (db: Database.Database) =>
104
- getStmt(
105
- db,
106
- `SELECT * FROM session_rows WHERE group_path = ? ORDER BY updated_at DESC`
107
- ),
108
-
109
- moveSessionsToGroup: (db: Database.Database) =>
110
- getStmt(
111
- db,
112
- `UPDATE sessions SET group_path = ?, updated_at = datetime('now') WHERE group_path = ?`
113
- ),
114
-
115
97
  updateSessionProject: (db: Database.Database) =>
116
98
  getStmt(
117
99
  db,
@@ -196,28 +178,6 @@ export const queries = {
196
178
  `SELECT * FROM tool_calls WHERE message_id = ? ORDER BY timestamp ASC`
197
179
  ),
198
180
 
199
- // Groups
200
- getAllGroups: (db: Database.Database) =>
201
- getStmt(db, `SELECT * FROM groups ORDER BY sort_order ASC, name ASC`),
202
-
203
- getGroup: (db: Database.Database) =>
204
- getStmt(db, `SELECT * FROM groups WHERE path = ?`),
205
-
206
- createGroup: (db: Database.Database) =>
207
- getStmt(db, `INSERT INTO groups (path, name, sort_order) VALUES (?, ?, ?)`),
208
-
209
- updateGroupName: (db: Database.Database) =>
210
- getStmt(db, `UPDATE groups SET name = ? WHERE path = ?`),
211
-
212
- updateGroupExpanded: (db: Database.Database) =>
213
- getStmt(db, `UPDATE groups SET expanded = ? WHERE path = ?`),
214
-
215
- updateGroupOrder: (db: Database.Database) =>
216
- getStmt(db, `UPDATE groups SET sort_order = ? WHERE path = ?`),
217
-
218
- deleteGroup: (db: Database.Database) =>
219
- getStmt(db, `DELETE FROM groups WHERE path = ?`),
220
-
221
181
  // Projects
222
182
  createProject: (db: Database.Database) =>
223
183
  getStmt(
@@ -183,4 +183,7 @@ export const SESSION_ROW_COLUMNS: readonly string[] = [
183
183
  "started_via",
184
184
  "plan_waits_for_caller",
185
185
  "plan_handoff_message",
186
+ "session_group_id",
187
+ "agent_role",
188
+ "crew_id",
186
189
  ];
package/lib/db/types.ts CHANGED
@@ -94,11 +94,26 @@ export interface Session {
94
94
  // it, as a short line (lib/bus/waits/store).
95
95
  waiting_on?: string | null;
96
96
  waited_by?: string | null;
97
+ // Set only by GET /api/sessions: the strongest overlap of this session's
98
+ // work with a claim here or on a linked machine (lib/claims/overlapCache).
99
+ overlap?: {
100
+ strength: "strong" | "weak";
101
+ machine: string;
102
+ goal: string;
103
+ shared: number;
104
+ claimId: string;
105
+ mineId: string;
106
+ } | null;
97
107
  placed_note?: string | null;
98
108
  // Set by done: hidden from the sidebar and the orchestrator, never deleted.
99
109
  archived_at: string | null;
100
110
  // On the sidebar's Pinned shelf (0/1 from SQLite).
101
111
  pinned: boolean;
112
+ // The user's group it sits in (session_groups), or null.
113
+ session_group_id?: string | null;
114
+ // The agent role it was started in (lib/models/agent-roles) and its crew.
115
+ agent_role?: string | null;
116
+ crew_id?: string | null;
102
117
  // A workspace's standing orchestrator chat (and that workspace), or null.
103
118
  role: "orchestrator" | null;
104
119
  // An orchestrator's tool-call secret.
@@ -165,14 +180,6 @@ export interface Session {
165
180
  worker_status: "pending" | "running" | "completed" | "failed" | null;
166
181
  }
167
182
 
168
- export interface Group {
169
- path: string;
170
- name: string;
171
- expanded: boolean;
172
- sort_order: number;
173
- created_at: string;
174
- }
175
-
176
183
  // production: every merge gate applies. fast: a task's PR merges when it opens.
177
184
  export type ProjectTier = "production" | "fast";
178
185
 
@@ -314,4 +321,8 @@ export interface Host {
314
321
  kind?: "ssh" | "connect";
315
322
  // Paired with that machine's own AgentOS (lib/hosts/link.ts); 0/1 from SQLite.
316
323
  linked?: boolean | number;
324
+ // Connect hosts (lib/peer): the link's state, and why it's suspended or
325
+ // who unlinked it.
326
+ peer_state?: "active" | "suspended" | "unlinked" | null;
327
+ peer_note?: string | null;
317
328
  }
@@ -5,7 +5,11 @@
5
5
  */
6
6
 
7
7
  import { execFile } from "child_process";
8
+ import fs from "fs";
9
+ import os from "os";
10
+ import path from "path";
8
11
  import { promisify } from "util";
12
+ import { agentOsHome, liveCheckout } from "../dev-instance/liveServer";
9
13
  import { probeAgents, type AgentProbe } from "../agents/probe";
10
14
  import { getAllProviderDefinitions } from "../providers/registry";
11
15
 
@@ -37,12 +41,14 @@ export interface DoctorDeps {
37
41
  exec: ExecFn;
38
42
  probe: (fresh: boolean) => Promise<Record<string, AgentProbe>>;
39
43
  nodeVersion: string;
44
+ cliLinks: () => DoctorCheck | null;
40
45
  }
41
46
 
42
47
  const defaultDeps: DoctorDeps = {
43
48
  exec: promisify(execFile) as ExecFn,
44
49
  probe: probeAgents,
45
50
  nodeVersion: process.versions.node,
51
+ cliLinks: () => checkCliLinks(),
46
52
  };
47
53
 
48
54
  const INSTALL = {
@@ -190,6 +196,62 @@ export function checkAgents(probes: Record<string, AgentProbe>): DoctorCheck {
190
196
  };
191
197
  }
192
198
 
199
+ const CLI_LINKS: Array<[string, string]> = [
200
+ ["agent-os", "scripts/agent-os"],
201
+ ["aos", "bin/aos"],
202
+ ];
203
+
204
+ const real = (p: string) => {
205
+ try {
206
+ return fs.realpathSync(p);
207
+ } catch {
208
+ return null;
209
+ }
210
+ };
211
+
212
+ /**
213
+ * Do the CLI links in ~/.local/bin run the checkout the live server runs from?
214
+ * A link into an older clone runs an old `aos`. Null when there is no live
215
+ * server record or no link to judge.
216
+ */
217
+ export function checkCliLinks(
218
+ binDir = process.env.AOS_BIN_DIR || path.join(os.homedir(), ".local/bin"),
219
+ home = agentOsHome()
220
+ ): DoctorCheck | null {
221
+ const live = liveCheckout(home);
222
+ if (!live) return null;
223
+ const stale: string[] = [];
224
+ let seen = 0;
225
+ for (const [name, rel] of CLI_LINKS) {
226
+ const link = path.join(binDir, name);
227
+ let target: string;
228
+ try {
229
+ target = fs.readlinkSync(link);
230
+ } catch {
231
+ continue;
232
+ }
233
+ seen++;
234
+ const want = real(path.join(live, rel));
235
+ if (!want || real(path.resolve(binDir, target)) !== want)
236
+ stale.push(`${name} -> ${target}`);
237
+ }
238
+ if (seen === 0) return null;
239
+ if (stale.length === 0)
240
+ return {
241
+ id: "cli-links",
242
+ label: "CLI links",
243
+ status: "ok",
244
+ detail: `Point at ${live}`,
245
+ };
246
+ return {
247
+ id: "cli-links",
248
+ label: "CLI links",
249
+ status: "warn",
250
+ detail: `${stale.join(", ")}; the live server runs from ${live}`,
251
+ fix: `${live}/scripts/sync-cli-links`,
252
+ };
253
+ }
254
+
193
255
  let cache: { at: number; checks: Promise<DoctorCheck[]> } | null = null;
194
256
 
195
257
  /** Every check, in parallel, cached for a minute. `fresh` runs them again. */
@@ -214,7 +276,8 @@ export function runDoctor(
214
276
  detail: "Couldn't check the agent CLIs",
215
277
  fix: "Check again",
216
278
  })),
217
- ]);
279
+ Promise.resolve(d.cliLinks()),
280
+ ]).then((all) => all.filter((c): c is DoctorCheck => c !== null));
218
281
  if (!custom) cache = { at: Date.now(), checks };
219
282
  return checks;
220
283
  }
@@ -6,6 +6,7 @@ import { db, queries, type Session } from "../db";
6
6
  import { statusOf } from "../orchestrator/facts";
7
7
  import { kickWaits } from "../bus/waits/kick";
8
8
  import { peerSessionLink } from "../hosts/peer-actions";
9
+ import { endLinkOf } from "../analyst/endLink";
9
10
 
10
11
  export interface ArchivedView {
11
12
  id: string;
@@ -27,6 +28,7 @@ export function archiveSession(id: string): void {
27
28
  db.prepare(
28
29
  `UPDATE sessions SET archived_at = datetime('now') WHERE id = ? AND archived_at IS NULL`
29
30
  ).run(id);
31
+ endLinkOf(id);
30
32
  kickWaits();
31
33
  }
32
34
 
package/lib/drafts.ts CHANGED
@@ -29,6 +29,10 @@ export interface Draft {
29
29
  // A task's own model, "provider/model"; unset, its roles' models
30
30
  // (lib/models).
31
31
  taskModel?: string | null;
32
+ // Start in an agent role (Developer, Analyst, Reviewer, Supervisor): its
33
+ // binding picks the model; roleModel overrides it for this session.
34
+ agentRole?: string | null;
35
+ roleModel?: string | null;
32
36
  // A task's priority in the queue; unset: normal.
33
37
  taskPriority?: Priority;
34
38
  createdAt: number;