@saadnvd1/agent-os 0.3.637 → 0.3.639

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 (154) hide show
  1. package/app/api/sessions/[id]/pr/route.ts +3 -3
  2. package/app/api/sessions/[id]/setup/route.ts +3 -3
  3. package/app/api/tasks/[id]/approve-plan/route.ts +3 -4
  4. package/app/api/tasks/[id]/arm/route.ts +6 -5
  5. package/app/api/tasks/[id]/chat-facts/route.ts +2 -2
  6. package/app/api/tasks/[id]/chat-tail/route.ts +2 -2
  7. package/app/api/tasks/[id]/checks/route.ts +1 -1
  8. package/app/api/tasks/[id]/diff/route.ts +1 -1
  9. package/app/api/tasks/[id]/done/route.ts +2 -2
  10. package/app/api/tasks/[id]/drop/route.ts +6 -2
  11. package/app/api/tasks/[id]/export/route.ts +3 -5
  12. package/app/api/tasks/[id]/merge/route.ts +3 -3
  13. package/app/api/tasks/[id]/message/route.ts +2 -2
  14. package/app/api/tasks/[id]/model/route.ts +5 -1
  15. package/app/api/tasks/[id]/move/route.ts +5 -1
  16. package/app/api/tasks/[id]/moved/route.ts +6 -8
  17. package/app/api/tasks/[id]/plan/route.ts +4 -6
  18. package/app/api/tasks/[id]/plan-edits/route.ts +6 -5
  19. package/app/api/tasks/[id]/priority/route.ts +4 -1
  20. package/app/api/tasks/[id]/resume/route.ts +3 -4
  21. package/app/api/tasks/[id]/stop/route.ts +2 -2
  22. package/app/api/tasks/route.ts +1 -1
  23. package/lib/approvals/enable.ts +1 -1
  24. package/lib/away/report.ts +4 -4
  25. package/lib/away/run.ts +2 -2
  26. package/lib/bookmarks/store.ts +3 -3
  27. package/lib/bus/held-reply.ts +2 -2
  28. package/lib/bus/index.ts +3 -3
  29. package/lib/chat/compact-context.ts +1 -1
  30. package/lib/chat/hold.ts +3 -3
  31. package/lib/chat/refresh.ts +1 -1
  32. package/lib/chat/registry.ts +3 -3
  33. package/lib/chat/runner.ts +1 -1
  34. package/lib/chat/worker/main.ts +1 -1
  35. package/lib/db/index.ts +5 -1
  36. package/lib/db/lumifyhub.ts +8 -9
  37. package/lib/db/machine-scope.ts +12 -0
  38. package/lib/db/migrations/20261015T1800_split_sessions_tables.ts +172 -0
  39. package/lib/db/migrations/README.md +7 -0
  40. package/lib/db/queries.ts +16 -31
  41. package/lib/db/session-parts/columns.ts +186 -0
  42. package/lib/db/session-parts/fill.ts +33 -0
  43. package/lib/db/session-parts/index.ts +9 -0
  44. package/lib/db/session-parts/pauses.ts +11 -0
  45. package/lib/db/session-parts/placement.ts +11 -0
  46. package/lib/db/session-parts/plans.ts +31 -0
  47. package/lib/db/session-parts/prs.ts +31 -0
  48. package/lib/db/session-parts/tasks.ts +27 -0
  49. package/lib/db/session-parts/view.ts +43 -0
  50. package/lib/db/session-parts/write.ts +69 -0
  51. package/lib/done/archive.ts +2 -2
  52. package/lib/done/auto-archive.ts +1 -1
  53. package/lib/done/bulk.ts +1 -1
  54. package/lib/done/index.ts +8 -14
  55. package/lib/health/evidence.ts +1 -1
  56. package/lib/health/facts.ts +1 -1
  57. package/lib/health/pieces.ts +1 -1
  58. package/lib/hosts/peer-actions.ts +2 -2
  59. package/lib/hosts/peer-mirror.ts +2 -2
  60. package/lib/hosts/peer-sync.ts +69 -32
  61. package/lib/learning-cards/input.ts +1 -1
  62. package/lib/learning-cards/store.ts +1 -1
  63. package/lib/models/plan-step.ts +10 -24
  64. package/lib/models/resume.ts +5 -7
  65. package/lib/notify/index.ts +1 -1
  66. package/lib/notify/push/events.ts +1 -1
  67. package/lib/notify/push/index.ts +1 -1
  68. package/lib/orchestrator/act.ts +1 -1
  69. package/lib/orchestrator/armed.ts +17 -15
  70. package/lib/orchestrator/ask-approvals.ts +1 -1
  71. package/lib/orchestrator/ask-heads.ts +1 -1
  72. package/lib/orchestrator/ask-settle.ts +1 -1
  73. package/lib/orchestrator/brakes.ts +1 -1
  74. package/lib/orchestrator/digest.ts +2 -2
  75. package/lib/orchestrator/external-pr.ts +2 -2
  76. package/lib/orchestrator/facts.ts +4 -28
  77. package/lib/orchestrator/held-asks.ts +3 -3
  78. package/lib/orchestrator/home.ts +2 -2
  79. package/lib/orchestrator/overview.ts +1 -1
  80. package/lib/orchestrator/pr-wake.ts +3 -5
  81. package/lib/orchestrator/questions.ts +1 -1
  82. package/lib/orchestrator/quick-store.ts +1 -1
  83. package/lib/orchestrator/quick.ts +10 -7
  84. package/lib/orchestrator/read.ts +1 -1
  85. package/lib/orchestrator/rebase.ts +8 -11
  86. package/lib/orchestrator/reconcile.ts +2 -2
  87. package/lib/orchestrator/signoff.ts +3 -1
  88. package/lib/orchestrator/targets.ts +1 -1
  89. package/lib/orchestrator/task-state.ts +4 -2
  90. package/lib/plans/features.ts +1 -1
  91. package/lib/plans/release.ts +1 -1
  92. package/lib/ports.ts +1 -1
  93. package/lib/resurrect/find.ts +1 -1
  94. package/lib/resurrect/index.ts +24 -18
  95. package/lib/schedules/store.ts +1 -1
  96. package/lib/session-audit/sources.ts +3 -3
  97. package/lib/session-logs/index.ts +1 -1
  98. package/lib/session-titles.ts +1 -1
  99. package/lib/sessions/setup-progress.ts +1 -1
  100. package/lib/sessions/stop.ts +1 -1
  101. package/lib/sessions/worktree-setup.ts +2 -1
  102. package/lib/simulator/index.ts +1 -1
  103. package/lib/simulator/task-devices.ts +1 -1
  104. package/lib/stacks/board.ts +1 -1
  105. package/lib/stacks/land.ts +1 -1
  106. package/lib/stacks/restack.ts +1 -1
  107. package/lib/stacks/start.ts +2 -2
  108. package/lib/stacks/tick.ts +1 -1
  109. package/lib/stacks/view.ts +1 -1
  110. package/lib/status/incremental.ts +1 -1
  111. package/lib/tasks/contract/actions.ts +35 -0
  112. package/lib/tasks/contract/authorize.ts +82 -0
  113. package/lib/tasks/contract/client.ts +296 -0
  114. package/lib/tasks/{held-remote.ts → contract/held-calls.ts} +35 -66
  115. package/lib/tasks/contract/index.ts +28 -0
  116. package/lib/tasks/{remote-plan-path.ts → contract/plan-path.ts} +2 -2
  117. package/lib/tasks/{remote-plan.ts → contract/plan.ts} +76 -110
  118. package/lib/tasks/contract/routes.ts +26 -0
  119. package/lib/tasks/contract/start.ts +122 -0
  120. package/lib/tasks/contract/sync.ts +126 -0
  121. package/lib/tasks/contract/types.ts +41 -0
  122. package/lib/tasks/{remote-views.ts → contract/views.ts} +11 -18
  123. package/lib/tasks/finish.ts +10 -9
  124. package/lib/tasks/held-replies.ts +7 -13
  125. package/lib/tasks/held.ts +14 -18
  126. package/lib/tasks/import.ts +19 -15
  127. package/lib/tasks/index.ts +34 -22
  128. package/lib/tasks/launch-gate.ts +1 -1
  129. package/lib/tasks/move-carry.ts +15 -7
  130. package/lib/tasks/move-flow.ts +29 -36
  131. package/lib/tasks/move-guard.ts +1 -1
  132. package/lib/tasks/move-recover.ts +6 -25
  133. package/lib/tasks/move.ts +23 -23
  134. package/lib/tasks/moved-away.ts +1 -1
  135. package/lib/tasks/pause-hold.ts +13 -5
  136. package/lib/tasks/pause.ts +19 -23
  137. package/lib/tasks/plan-view.ts +1 -1
  138. package/lib/tasks/queue-placement.ts +1 -1
  139. package/lib/tasks/queue-rows.ts +4 -4
  140. package/lib/tasks/queue-start.ts +5 -3
  141. package/lib/tasks/queue-tick.ts +2 -2
  142. package/lib/tasks/queue.ts +14 -6
  143. package/lib/tasks/session.ts +7 -4
  144. package/lib/tasks/start.ts +4 -4
  145. package/lib/tasks/starter.ts +8 -11
  146. package/lib/usage/calls.ts +1 -1
  147. package/lib/usage/compare.ts +1 -1
  148. package/lib/usage/quality.ts +1 -1
  149. package/lib/usage/turns.ts +1 -1
  150. package/lib/voice/vocab.ts +1 -1
  151. package/package.json +1 -1
  152. package/scripts/backfill-session-logs.ts +1 -1
  153. package/lib/tasks/held-routes.ts +0 -33
  154. package/lib/tasks/remote.ts +0 -255
@@ -1,255 +0,0 @@
1
- /**
2
- * Tasks that run on another machine's AgentOS. That machine schedules them;
3
- * this one keeps a mirror row (same id, the host's id) so the sidebar lists
4
- * them and the terminal attaches through that machine's AgentOS, and asks it for their
5
- * state, sign-off and drop.
6
- */
7
-
8
- import { MERGE_METHODS, type MergeMethod } from "./merge-methods";
9
- import { db, type Project, type Session } from "../db";
10
- import {
11
- HostApiError,
12
- hostApi,
13
- requireHostLink,
14
- type HostLink,
15
- } from "../hosts/remote-api";
16
- import { isRemoteHost } from "../hosts";
17
- import { projectRef } from "./project-ref";
18
- import { orchestratedStart } from "./held";
19
- import type { TaskStatus } from "./state";
20
- import type { TaskView } from "./index";
21
- import { orchestratorOf } from "./starter";
22
-
23
- // What this machine's task API does, for another machine deciding whether
24
- // it can trust it with a pinned merge or a move; keyed-start: a session
25
- // start takes a key, so it's safe to retry (lib/sessions/launch.ts).
26
- export const TASK_CAPABILITIES = [
27
- "pinned-merge",
28
- "move",
29
- "chat-turn",
30
- "keyed-start",
31
- "chat-move",
32
- // Holds an orchestrator's task for the machine that sent it, and answers
33
- // its messages, reads, stops and done (lib/tasks/held.ts).
34
- "orchestrated-move",
35
- // A held task's chat facts and its messages for its orchestrator.
36
- "held-chat-facts",
37
- "held-replies",
38
- // A keyed start that carries an orchestrator's description holds the task
39
- // for the device that sent it, as a move does (lib/tasks/held.ts).
40
- "held-start",
41
- // A plan placed here by another machine stops at the plan for that machine
42
- // to decide what follows (lib/tasks/remote-plan.ts).
43
- "remote-plan",
44
- ] as const;
45
-
46
- export interface HostTasks {
47
- tasks: TaskView[];
48
- moved?: { id: string; movedTo: string | null }[];
49
- capabilities?: string[];
50
- }
51
-
52
- export function isMirror(session: Session): boolean {
53
- return isRemoteHost(session.host_id);
54
- }
55
-
56
- export function mirrorTask(
57
- hostId: string,
58
- projectId: string | null,
59
- remote: Session,
60
- startedBy?: string | null
61
- ): void {
62
- db.prepare(
63
- `INSERT INTO sessions (id, name, tmux_name, working_directory, model, group_path,
64
- agent_type, auto_approve, project_id, host_id, worktree_path, branch_name,
65
- base_branch, task_prompt, task_status, name_source, view)
66
- VALUES (?, ?, ?, ?, ?, 'sessions', 'claude', 1, ?, ?, ?, ?, ?, ?, 'running', 'user', ?)
67
- ON CONFLICT(id) DO NOTHING`
68
- ).run(
69
- remote.id,
70
- remote.name,
71
- remote.tmux_name,
72
- remote.working_directory,
73
- remote.model,
74
- projectId,
75
- hostId,
76
- remote.worktree_path,
77
- remote.branch_name,
78
- remote.base_branch,
79
- remote.task_prompt,
80
- // As that machine runs it: one that predates chat tasks says terminal.
81
- remote.view === "chat" ? "chat" : "terminal"
82
- );
83
- // What carryTaskState gives a moved task's mirror: the orchestrator that
84
- // holds it, and when it began (so its PR is judged from then).
85
- if (startedBy)
86
- db.prepare(
87
- `UPDATE sessions SET started_by = COALESCE(started_by, ?),
88
- task_since = COALESCE(task_since, created_at) WHERE id = ?`
89
- ).run(startedBy, remote.id);
90
- }
91
-
92
- /**
93
- * A machine on an older AgentOS would take a chat task as a terminal one,
94
- * or an orchestrator's task as a plain one that anyone there could merge, or
95
- * refuse to hand one over.
96
- */
97
- export async function requireCapability(
98
- link: HostLink,
99
- capability: string,
100
- what: string,
101
- verb = "move"
102
- ): Promise<void> {
103
- const { capabilities = [] } = await hostTasks(link, true).catch((err) => {
104
- throw new Error(
105
- `Can't ask ${link.hostName} whether it takes ${what}: ${(err as Error).message}`
106
- );
107
- });
108
- if (!capabilities.includes(capability))
109
- throw new Error(
110
- `${link.hostName}'s AgentOS can't ${verb} ${what} yet; update it first`
111
- );
112
- }
113
-
114
- export const unknownOutcome = (err: unknown) =>
115
- err instanceof HostApiError && !err.refused;
116
-
117
- /** POST a call that's safe to repeat; once more if we can't tell it landed. */
118
- export async function postIdempotent<T>(
119
- link: HostLink,
120
- path: string,
121
- body: unknown,
122
- timeout: number
123
- ): Promise<T> {
124
- try {
125
- return await hostApi<T>(link, path, { body, timeout });
126
- } catch (err) {
127
- if (!unknownOutcome(err)) throw err;
128
- return hostApi<T>(link, path, { body, timeout });
129
- }
130
- }
131
-
132
- export async function startRemoteTask(
133
- hostId: string,
134
- project: Project,
135
- opts: {
136
- id: string;
137
- prompt: string;
138
- name?: string;
139
- model?: string;
140
- baseBranch?: string;
141
- view?: "chat" | "terminal";
142
- // The orchestrator that started it: that machine holds the task for it.
143
- startedBy?: string | null;
144
- // It plans first: there it plans, stops, and waits for this machine.
145
- plan?: { only: boolean; reason: string | null };
146
- }
147
- ): Promise<Session> {
148
- const link = requireHostLink(hostId);
149
- const { startedBy: by, plan, ...rest } = opts;
150
- const startedBy = orchestratorOf(by);
151
- if (startedBy)
152
- await requireCapability(
153
- link,
154
- "held-start",
155
- "an orchestrator's task",
156
- "hold"
157
- );
158
- if (plan) await requireCapability(link, "remote-plan", "a plan step", "plan");
159
- const { session } = await postIdempotent<{ session: Session }>(
160
- link,
161
- "/api/tasks",
162
- {
163
- project: await projectRef(project),
164
- ...rest,
165
- ...(plan && {
166
- plan: true,
167
- plan_only: true,
168
- plan_waits: true,
169
- plan_reason: plan.reason ?? undefined,
170
- }),
171
- orchestrated: startedBy ? orchestratedStart(startedBy) : undefined,
172
- },
173
- 180000
174
- );
175
- mirrorTask(hostId, project.id, session, startedBy);
176
- if (plan)
177
- db.prepare(
178
- `UPDATE sessions SET plan_phase = 'planning', plan_only = ?, plan_decided = 1,
179
- plan_reason = ?, plan_waits_for_caller = 1 WHERE id = ?`
180
- ).run(plan.only ? 1 : null, plan.reason, session.id);
181
- forgetHostTasks(hostId);
182
- return db
183
- .prepare(`SELECT * FROM sessions WHERE id = ?`)
184
- .get(session.id) as Session;
185
- }
186
-
187
- const cache = new Map<string, { at: number; list: Promise<HostTasks> }>();
188
-
189
- export function hostTasks(link: HostLink, fresh = false): Promise<HostTasks> {
190
- const hit = cache.get(link.hostId);
191
- if (!fresh && hit && Date.now() - hit.at < 3000) return hit.list;
192
- const list = hostApi<HostTasks>(link, "/api/tasks", { timeout: 8000 });
193
- cache.set(link.hostId, { at: Date.now(), list });
194
- list.catch(() => cache.delete(link.hostId));
195
- return list;
196
- }
197
-
198
- export const forgetHostTasks = (hostId: string) => cache.delete(hostId);
199
-
200
- export function setMirrorStatus(id: string, status: TaskStatus): void {
201
- db.prepare(
202
- `UPDATE sessions SET task_status = ? WHERE id = ? AND task_status = 'running'`
203
- ).run(status, id);
204
- }
205
-
206
- /**
207
- * Sign off or drop on the machine that runs it. A merge returns the method
208
- * that machine merged with; null when it doesn't say (an older AgentOS).
209
- */
210
- export async function remoteTaskAction(
211
- session: Session,
212
- action: "merge" | "drop",
213
- head?: string,
214
- base?: string | null
215
- ): Promise<MergeMethod | null> {
216
- const link = requireHostLink(session.host_id);
217
- // An AgentOS that predates pinned merges would ignore the head and merge
218
- // whatever the PR is at: refuse before asking it.
219
- if (head) {
220
- const { capabilities = [] } = await hostTasks(link, true);
221
- if (!capabilities.includes("pinned-merge"))
222
- throw new Error(
223
- `${link.hostName}'s AgentOS can't pin a merge to a commit; update it first`
224
- );
225
- }
226
- // base: what the gates here were judged against; the machine that merges
227
- // compares the PR with it, not with a base only it recorded.
228
- const res = await hostApi<{ head?: string | null; method?: unknown }>(
229
- link,
230
- `/api/tasks/${encodeURIComponent(session.id)}/${action}`,
231
- {
232
- body: { ...(head && { head }), ...(head && base && { base }) },
233
- timeout: 300000,
234
- }
235
- ).catch(async (err) => {
236
- if (action !== "merge" || !unknownOutcome(err)) throw err;
237
- // A proxy or a dropped connection after the merge ran answers 502 with
238
- // nothing from AgentOS: ask what state the task is in before failing.
239
- const merged = await hostTasks(link, true)
240
- .then((l) => l.tasks.find((t) => t.id === session.id)?.state === "merged")
241
- .catch(() => false);
242
- if (!merged)
243
- throw new Error(
244
- `${(err as Error).message}: couldn't confirm whether ${link.hostName} merged ${session.name}; check its PR before signing off again`
245
- );
246
- return { head: head ?? null, method: undefined };
247
- });
248
- forgetHostTasks(link.hostId);
249
- setMirrorStatus(session.id, action === "merge" ? "merged" : "dropped");
250
- if (head && res.head !== head)
251
- throw new Error(
252
- `${link.hostName} merged without confirming it was ${head.slice(0, 7)}`
253
- );
254
- return MERGE_METHODS.find((m) => m === res.method) ?? null;
255
- }