toolroll 0.9.62 → 0.9.65

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 (345) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +66 -8
  3. package/dist/acp-agents.d.ts +43 -0
  4. package/dist/acp-agents.js +62 -0
  5. package/dist/acp-attest.d.ts +44 -0
  6. package/dist/acp-attest.js +269 -0
  7. package/dist/acp-check.d.ts +28 -0
  8. package/dist/acp-check.js +410 -0
  9. package/dist/acp-client.d.ts +163 -0
  10. package/dist/acp-client.js +738 -0
  11. package/dist/acp-inspect.d.ts +23 -0
  12. package/dist/acp-inspect.js +109 -0
  13. package/dist/agent-board.d.ts +19 -6
  14. package/dist/agent-board.js +30 -9
  15. package/dist/agent-fence.d.ts +203 -10
  16. package/dist/agent-fence.js +623 -41
  17. package/dist/agent-pulse.js +9 -2
  18. package/dist/agent-state-words.d.ts +19 -0
  19. package/dist/agent-state-words.js +20 -0
  20. package/dist/agent-state.d.ts +65 -0
  21. package/dist/agent-state.js +229 -0
  22. package/dist/agentconfig.js +36 -13
  23. package/dist/agents-board.d.ts +34 -2
  24. package/dist/agents-board.js +110 -1
  25. package/dist/approval-rules-ui.js +2 -2
  26. package/dist/assignment-delivery.d.ts +14 -0
  27. package/dist/assignment-delivery.js +13 -0
  28. package/dist/assignment.js +13 -0
  29. package/dist/attest.js +7 -0
  30. package/dist/backup-ui.js +2 -2
  31. package/dist/browser/THIRD_PARTY_NOTICES.txt +48 -0
  32. package/dist/browser/terminal.css +37 -0
  33. package/dist/browser/terminal.js +117 -0
  34. package/dist/browser/workspace.css +2 -2
  35. package/dist/browser/workspace.js +42 -38
  36. package/dist/browser-shell.js +6 -3
  37. package/dist/browser-workspace.d.ts +263 -1
  38. package/dist/browser-workspace.js +60 -0
  39. package/dist/builder.d.ts +6 -1
  40. package/dist/builder.js +34 -13
  41. package/dist/chat-actions.d.ts +13 -1
  42. package/dist/chat-actions.js +199 -17
  43. package/dist/chat-ask.d.ts +4 -0
  44. package/dist/chat-ask.js +14 -0
  45. package/dist/chat-channel.js +20 -0
  46. package/dist/chat-continuity.js +5 -4
  47. package/dist/chat-decide.d.ts +0 -14
  48. package/dist/chat-decide.js +4 -1
  49. package/dist/chat-delivery.d.ts +9 -0
  50. package/dist/chat-delivery.js +45 -6
  51. package/dist/chat-messages.d.ts +8 -0
  52. package/dist/chat-messages.js +36 -4
  53. package/dist/check-levels-ui.js +2 -2
  54. package/dist/check-levels.js +3 -0
  55. package/dist/checkout-proof.d.ts +28 -0
  56. package/dist/checkout-proof.js +62 -0
  57. package/dist/claim.d.ts +12 -0
  58. package/dist/claim.js +20 -1
  59. package/dist/cli-help.d.ts +1 -1
  60. package/dist/cli-help.js +5 -1
  61. package/dist/cli.d.ts +3 -0
  62. package/dist/cli.js +24 -2
  63. package/dist/coding-ui.js +6 -4
  64. package/dist/console-instance.d.ts +124 -0
  65. package/dist/console-instance.js +337 -0
  66. package/dist/contracts/chat-actions.d.ts +16 -0
  67. package/dist/contracts/chat-actions.js +4 -0
  68. package/dist/contracts/chat-content.d.ts +19 -0
  69. package/dist/contracts/chat-content.js +6 -0
  70. package/dist/contracts/cli.d.ts +8 -0
  71. package/dist/contracts/cli.js +3 -1
  72. package/dist/contracts/console-api.d.ts +30 -4
  73. package/dist/contracts/console-api.js +13 -4
  74. package/dist/contracts/flow-card.d.ts +4 -0
  75. package/dist/contracts/flow-card.js +3 -0
  76. package/dist/contracts/flow.d.ts +46 -0
  77. package/dist/contracts/flow.js +11 -2
  78. package/dist/contracts/integration-metadata.d.ts +2 -1
  79. package/dist/contracts/integration-metadata.js +2 -1
  80. package/dist/contracts/lead-tools.d.ts +92 -0
  81. package/dist/contracts/lead-tools.js +13 -0
  82. package/dist/contracts/provider.d.ts +11 -1
  83. package/dist/contracts/provider.js +1 -1
  84. package/dist/contracts/route.d.ts +76 -1
  85. package/dist/contracts/route.js +1 -1
  86. package/dist/contracts/store-json.d.ts +2 -0
  87. package/dist/control-setup.d.ts +1 -1
  88. package/dist/control-ui.js +2 -2
  89. package/dist/converse.d.ts +16 -0
  90. package/dist/converse.js +32 -4
  91. package/dist/demo-chat.js +4 -4
  92. package/dist/demo.js +2 -2
  93. package/dist/desktop-update-gate.js +6 -0
  94. package/dist/discord-chat.js +4 -1
  95. package/dist/dispatch.js +7 -4
  96. package/dist/doctor.d.ts +53 -0
  97. package/dist/doctor.js +427 -0
  98. package/dist/egress-bridge.d.ts +17 -0
  99. package/dist/egress-bridge.js +111 -0
  100. package/dist/egress.d.ts +119 -0
  101. package/dist/egress.js +423 -0
  102. package/dist/evidence-pack.d.ts +1 -1
  103. package/dist/evidence-pack.js +2 -2
  104. package/dist/exec.d.ts +81 -0
  105. package/dist/exec.js +368 -9
  106. package/dist/export-ui.js +2 -2
  107. package/dist/flow-code.d.ts +2 -2
  108. package/dist/flow-code.js +4 -15
  109. package/dist/flow-engine.js +35 -11
  110. package/dist/flow-gallery-ui.js +2 -2
  111. package/dist/flow-gallery.js +27 -8
  112. package/dist/flow-share.js +16 -5
  113. package/dist/flow-triggers.d.ts +84 -11
  114. package/dist/flow-triggers.js +554 -87
  115. package/dist/flow-unattended-words.d.ts +28 -0
  116. package/dist/flow-unattended-words.js +50 -0
  117. package/dist/flow-unattended.d.ts +227 -0
  118. package/dist/flow-unattended.js +776 -0
  119. package/dist/flows-cli.d.ts +28 -1
  120. package/dist/flows-cli.js +63 -12
  121. package/dist/flows-ui.d.ts +2 -3
  122. package/dist/flows-ui.js +56 -5
  123. package/dist/flows.d.ts +4 -0
  124. package/dist/flows.js +9 -1
  125. package/dist/google-mail.d.ts +1 -0
  126. package/dist/google-mail.js +61 -18
  127. package/dist/html.d.ts +9 -0
  128. package/dist/html.js +11 -0
  129. package/dist/integrations-ui.d.ts +2 -1
  130. package/dist/integrations-ui.js +6 -3
  131. package/dist/integrations.d.ts +17 -3
  132. package/dist/integrations.js +38 -18
  133. package/dist/invoke.d.ts +17 -0
  134. package/dist/invoke.js +510 -182
  135. package/dist/keys.d.ts +18 -14
  136. package/dist/keys.js +5 -0
  137. package/dist/landed-cleanup.d.ts +3 -2
  138. package/dist/landed-cleanup.js +12 -5
  139. package/dist/lead-capabilities.js +3 -2
  140. package/dist/lead-contract.js +2 -0
  141. package/dist/lead-doors.d.ts +2 -0
  142. package/dist/lead-doors.js +7 -0
  143. package/dist/lead-follow.d.ts +2 -0
  144. package/dist/lead-follow.js +58 -2
  145. package/dist/lead-progress.js +1 -0
  146. package/dist/lead-queue-runtime.d.ts +46 -0
  147. package/dist/lead-queue-runtime.js +191 -0
  148. package/dist/lead-queue.d.ts +104 -0
  149. package/dist/lead-queue.js +187 -0
  150. package/dist/lead-sweep.d.ts +67 -0
  151. package/dist/lead-sweep.js +99 -0
  152. package/dist/lead-tools.d.ts +22 -0
  153. package/dist/lead-tools.js +163 -4
  154. package/dist/lead.d.ts +13 -5
  155. package/dist/lead.js +89 -29
  156. package/dist/limits-ui.d.ts +8 -1
  157. package/dist/limits-ui.js +26 -0
  158. package/dist/live-bus.d.ts +8 -0
  159. package/dist/live-bus.js +40 -4
  160. package/dist/live-detail.d.ts +27 -0
  161. package/dist/live-detail.js +57 -0
  162. package/dist/live-notes.d.ts +20 -0
  163. package/dist/live-notes.js +47 -0
  164. package/dist/live-records.d.ts +140 -0
  165. package/dist/live-records.js +935 -0
  166. package/dist/live-terminal.d.ts +258 -0
  167. package/dist/live-terminal.js +649 -0
  168. package/dist/live.d.ts +38 -27
  169. package/dist/live.js +142 -124
  170. package/dist/mcp-connect.d.ts +8 -7
  171. package/dist/mcp-connect.js +49 -51
  172. package/dist/mcp-oauth.d.ts +6 -3
  173. package/dist/mcp-oauth.js +8 -4
  174. package/dist/memory-pass.js +2 -2
  175. package/dist/mobile-viewport.d.ts +5 -1
  176. package/dist/mobile-viewport.js +18 -2
  177. package/dist/model-catalog.js +4 -0
  178. package/dist/monitoring-ui.js +2 -2
  179. package/dist/needs-you.d.ts +1 -1
  180. package/dist/needs-you.js +11 -4
  181. package/dist/oauth-run-token.d.ts +51 -0
  182. package/dist/oauth-run-token.js +127 -0
  183. package/dist/operate.d.ts +2 -0
  184. package/dist/operate.js +282 -18
  185. package/dist/passwordless.d.ts +23 -0
  186. package/dist/passwordless.js +26 -0
  187. package/dist/peek-cli.d.ts +12 -4
  188. package/dist/peek-cli.js +19 -11
  189. package/dist/phase-routing.js +10 -3
  190. package/dist/plan-auto.d.ts +11 -0
  191. package/dist/plan-auto.js +62 -11
  192. package/dist/planner-source.d.ts +3 -0
  193. package/dist/planner-source.js +14 -0
  194. package/dist/planner.d.ts +2 -1
  195. package/dist/planner.js +7 -1
  196. package/dist/policy-ui.js +2 -2
  197. package/dist/policy.d.ts +1 -20
  198. package/dist/policy.js +29 -2
  199. package/dist/process-recovery-eligibility.d.ts +1 -1
  200. package/dist/project-access.d.ts +3 -0
  201. package/dist/project-access.js +3 -0
  202. package/dist/project-delete-ui.d.ts +12 -0
  203. package/dist/project-delete-ui.js +41 -9
  204. package/dist/project-delete.d.ts +3 -1
  205. package/dist/project-delete.js +12 -6
  206. package/dist/project-file.d.ts +3 -0
  207. package/dist/project-file.js +16 -0
  208. package/dist/project-memory.d.ts +3 -1
  209. package/dist/project-memory.js +57 -25
  210. package/dist/project-tools.d.ts +103 -27
  211. package/dist/project-tools.js +399 -100
  212. package/dist/provider-auth.d.ts +4 -3
  213. package/dist/provider-auth.js +5 -4
  214. package/dist/provider-connection.d.ts +2 -1
  215. package/dist/provider-connection.js +5 -0
  216. package/dist/provider-home.d.ts +22 -0
  217. package/dist/provider-home.js +99 -0
  218. package/dist/provider.d.ts +42 -5
  219. package/dist/provider.js +97 -19
  220. package/dist/pull-request-ui.js +2 -2
  221. package/dist/push.js +1 -1
  222. package/dist/quick-start.d.ts +24 -0
  223. package/dist/quick-start.js +127 -0
  224. package/dist/release.d.ts +3 -0
  225. package/dist/release.js +14 -8
  226. package/dist/remote-main.d.ts +4 -0
  227. package/dist/remote-main.js +3 -3
  228. package/dist/request-budget-ui.js +2 -2
  229. package/dist/result-review.d.ts +1 -1
  230. package/dist/result-review.js +9 -3
  231. package/dist/retention-ui.js +2 -2
  232. package/dist/retention.js +10 -1
  233. package/dist/run-efficiency.d.ts +73 -0
  234. package/dist/run-efficiency.js +228 -0
  235. package/dist/runner.d.ts +5 -1
  236. package/dist/runner.js +22 -1
  237. package/dist/scope.d.ts +171 -6
  238. package/dist/scope.js +251 -31
  239. package/dist/scout-net.d.ts +4 -1
  240. package/dist/scout-net.js +37 -12
  241. package/dist/scout.d.ts +20 -6
  242. package/dist/scout.js +27 -3
  243. package/dist/serve.js +258 -43
  244. package/dist/server/chat.d.ts +1 -1
  245. package/dist/server/chat.js +122 -31
  246. package/dist/server/chrome.d.ts +6 -1
  247. package/dist/server/chrome.js +18 -7
  248. package/dist/server/console.css +52 -38
  249. package/dist/server/flows.js +65 -13
  250. package/dist/server/guards.d.ts +1 -0
  251. package/dist/server/guards.js +23 -9
  252. package/dist/server/http.d.ts +7 -0
  253. package/dist/server/http.js +3 -2
  254. package/dist/server/live.d.ts +34 -1
  255. package/dist/server/live.js +39 -17
  256. package/dist/server/pages-assets.js +5 -0
  257. package/dist/server/pages.js +90 -13
  258. package/dist/server/people-tokens.d.ts +3 -0
  259. package/dist/server/people-tokens.js +55 -17
  260. package/dist/server/remote-hooks.js +12 -6
  261. package/dist/server/remote.d.ts +2 -1
  262. package/dist/server/remote.js +14 -5
  263. package/dist/server/render-chat.d.ts +12 -3
  264. package/dist/server/render-chat.js +47 -16
  265. package/dist/server/render-pages.d.ts +4 -1
  266. package/dist/server/render-pages.js +5 -4
  267. package/dist/server/render-people.d.ts +3 -2
  268. package/dist/server/render-people.js +3 -2
  269. package/dist/server/render-results.d.ts +18 -2
  270. package/dist/server/render-results.js +37 -28
  271. package/dist/server/render-settings.js +6 -5
  272. package/dist/server/render-tasks.d.ts +35 -10
  273. package/dist/server/render-tasks.js +110 -27
  274. package/dist/server/request-context.d.ts +2 -0
  275. package/dist/server/request-context.js +2 -1
  276. package/dist/server/route-table.d.ts +3 -0
  277. package/dist/server/route-table.js +49 -5
  278. package/dist/server/runtime.d.ts +34 -3
  279. package/dist/server/session.d.ts +25 -1
  280. package/dist/server/session.js +18 -4
  281. package/dist/server/settings.js +132 -13
  282. package/dist/server/sweeps.d.ts +4 -0
  283. package/dist/server/sweeps.js +58 -0
  284. package/dist/server/task-views.d.ts +2 -1
  285. package/dist/server/task-views.js +96 -6
  286. package/dist/server/tasks.js +320 -74
  287. package/dist/server/terminals.d.ts +31 -0
  288. package/dist/server/terminals.js +365 -0
  289. package/dist/setup-guide.js +3 -2
  290. package/dist/slack-chat.js +4 -1
  291. package/dist/spend-ui.js +3 -3
  292. package/dist/spend.js +2 -1
  293. package/dist/steer-capabilities.d.ts +32 -0
  294. package/dist/steer-capabilities.js +60 -0
  295. package/dist/steer-controls.d.ts +14 -0
  296. package/dist/steer-controls.js +36 -0
  297. package/dist/steer-status.js +2 -2
  298. package/dist/storage-sweep-child.js +3 -1
  299. package/dist/storage-sweep-process.d.ts +12 -5
  300. package/dist/storage-sweep-process.js +23 -6
  301. package/dist/storage-ui.js +4 -4
  302. package/dist/store-baseline.d.ts +1 -1
  303. package/dist/store-baseline.js +1 -1
  304. package/dist/store.d.ts +466 -19
  305. package/dist/store.js +1185 -63
  306. package/dist/subagent-desk.js +1 -1
  307. package/dist/subagent-tools.d.ts +1 -1
  308. package/dist/summary.js +3 -0
  309. package/dist/surface.js +6 -4
  310. package/dist/task-source.d.ts +58 -0
  311. package/dist/task-source.js +93 -0
  312. package/dist/team-leads.js +1 -1
  313. package/dist/teams-chat.js +4 -1
  314. package/dist/teardown-git.d.ts +14 -0
  315. package/dist/teardown-git.js +119 -0
  316. package/dist/telegram-lead.d.ts +3 -0
  317. package/dist/telegram-lead.js +44 -7
  318. package/dist/telegram.d.ts +11 -2
  319. package/dist/telegram.js +51 -17
  320. package/dist/terminal-catalog.d.ts +11 -0
  321. package/dist/terminal-catalog.js +129 -0
  322. package/dist/text-limits.d.ts +2 -0
  323. package/dist/text-limits.js +2 -0
  324. package/dist/tool-broker.d.ts +39 -0
  325. package/dist/tool-broker.js +370 -0
  326. package/dist/tool-launcher.js +5 -4
  327. package/dist/tool-secret-store.d.ts +170 -0
  328. package/dist/tool-secret-store.js +834 -0
  329. package/dist/toolroll-update-ui.js +2 -2
  330. package/dist/toolroll-update.js +14 -3
  331. package/dist/tools-ui.d.ts +7 -1
  332. package/dist/tools-ui.js +19 -10
  333. package/dist/webhook-limits.d.ts +23 -0
  334. package/dist/webhook-limits.js +30 -0
  335. package/dist/webhook-readers.d.ts +56 -0
  336. package/dist/webhook-readers.js +138 -0
  337. package/dist/webhook-signing.d.ts +27 -0
  338. package/dist/webhook-signing.js +119 -0
  339. package/dist/work-index.d.ts +29 -0
  340. package/dist/work-index.js +21 -5
  341. package/dist/workspace-revision.js +3 -1
  342. package/dist/worktree.d.ts +10 -4
  343. package/dist/worktree.js +70 -29
  344. package/package.json +13 -2
  345. package/scripts/provider-canary.mjs +210 -31
@@ -85,6 +85,7 @@ export declare class LiveConnection {
85
85
  private readonly proofs;
86
86
  private readonly timer;
87
87
  private closed;
88
+ private refusing;
88
89
  constructor(response: ServerResponse, options?: {
89
90
  limitBytes?: number;
90
91
  keepAliveMs?: number;
@@ -95,6 +96,10 @@ export declare class LiveConnection {
95
96
  get open(): boolean;
96
97
  /** An event for one room: its data says which. */
97
98
  send(room: string, event: string, data?: Record<string, unknown>): void;
99
+ /** A room leaves because its proof failed (a sign-out, a revoked or narrowed account): if that departure ends the
100
+ * connection, the page is told the stream `ended` and stops, rather than reconnecting at once into a request that
101
+ * can't sign in. Any other close — the page going, a later shutdown, an overflow — says nothing of it. */
102
+ refuse(leave: () => void): void;
98
103
  /** Run when the connection ends; returns the undo for a room that leaves first. */
99
104
  onClose(leave: () => void): () => void;
100
105
  close(): void;
@@ -120,6 +125,9 @@ export type LiveRoomOptions = {
120
125
  bus?: LiveBus | null;
121
126
  safetyNetMs?: number;
122
127
  minIntervalMs?: number;
128
+ /** A room whose read is costly reads at most once per this window after a signal; every viewer is still re-proved
129
+ * the moment a signal arrives (and again at the read). */
130
+ readSettleMs?: number;
123
131
  };
124
132
  /**
125
133
  * Rooms of open pages that hear the bus. `presence` says who else is here, as
package/dist/live-bus.js CHANGED
@@ -201,6 +201,7 @@ export class LiveConnection {
201
201
  proofs = new Set();
202
202
  timer;
203
203
  closed = false;
204
+ refusing = false;
204
205
  constructor(response, options = {}) {
205
206
  this.response = response;
206
207
  this.stream = new LiveStream(response, options.limitBytes, () => this.close());
@@ -222,6 +223,19 @@ export class LiveConnection {
222
223
  get open() { return !this.closed && this.stream.open; }
223
224
  /** An event for one room: its data says which. */
224
225
  send(room, event, data = {}) { this.stream.send(event, { room, ...data }); }
226
+ /** A room leaves because its proof failed (a sign-out, a revoked or narrowed account): if that departure ends the
227
+ * connection, the page is told the stream `ended` and stops, rather than reconnecting at once into a request that
228
+ * can't sign in. Any other close — the page going, a later shutdown, an overflow — says nothing of it. */
229
+ refuse(leave) {
230
+ const outer = this.refusing;
231
+ this.refusing = true;
232
+ try {
233
+ leave();
234
+ }
235
+ finally {
236
+ this.refusing = outer;
237
+ }
238
+ }
225
239
  /** Run when the connection ends; returns the undo for a room that leaves first. */
226
240
  onClose(leave) { this.leaves.add(leave); return () => { this.leaves.delete(leave); }; }
227
241
  close() {
@@ -233,6 +247,10 @@ export class LiveConnection {
233
247
  leave();
234
248
  this.leaves.clear();
235
249
  this.proofs.clear();
250
+ if (this.refusing && this.stream.open) {
251
+ this.response.end("event: ended\ndata: {}\n\n");
252
+ return;
253
+ }
236
254
  if (!this.response.writableEnded)
237
255
  this.response.end();
238
256
  }
@@ -251,6 +269,7 @@ export function createLiveRooms(fingerprint, presence, options = {}) {
251
269
  const bus = options.bus ?? null;
252
270
  const safetyNetMs = options.safetyNetMs ?? SAFETY_NET_MS;
253
271
  const minIntervalMs = options.minIntervalMs ?? 0;
272
+ const readSettleMs = options.readSettleMs ?? 0;
254
273
  const rooms = new Map();
255
274
  let unsubscribe = null;
256
275
  const announce = (key, room) => {
@@ -287,6 +306,8 @@ export function createLiveRooms(fingerprint, presence, options = {}) {
287
306
  clearTimeout(room.retry);
288
307
  if (room.holding !== null)
289
308
  clearTimeout(room.holding);
309
+ if (room.reading !== null)
310
+ clearTimeout(room.reading);
290
311
  rooms.delete(key);
291
312
  if (rooms.size === 0 && unsubscribe !== null) {
292
313
  unsubscribe();
@@ -312,7 +333,10 @@ export function createLiveRooms(fingerprint, presence, options = {}) {
312
333
  viewer.connection.send(viewer.room, "gone");
313
334
  }
314
335
  finally {
315
- leave(key, viewer);
336
+ if (valid)
337
+ leave(key, viewer);
338
+ else
339
+ viewer.connection.refuse(() => leave(key, viewer));
316
340
  }
317
341
  return false;
318
342
  }
@@ -366,8 +390,20 @@ export function createLiveRooms(fingerprint, presence, options = {}) {
366
390
  deliver(key, room, viewer, "change", { at: room.last, revision: room.revision });
367
391
  };
368
392
  const heard = (change) => {
369
- for (const [key, room] of [...rooms])
370
- refresh(key, room, change.revision);
393
+ for (const [key, room] of [...rooms]) {
394
+ if (readSettleMs <= 0) {
395
+ refresh(key, room, change.revision);
396
+ continue;
397
+ }
398
+ // Re-prove now; read once the burst settles.
399
+ for (const viewer of [...room.viewers.keys()])
400
+ deliver(key, room, viewer);
401
+ if (rooms.get(key) !== room || room.reading !== null)
402
+ continue;
403
+ room.reading = setTimeout(() => { room.reading = null; if (rooms.get(key) === room)
404
+ refresh(key, room, null); }, readSettleMs);
405
+ room.reading.unref();
406
+ }
371
407
  };
372
408
  return {
373
409
  join(key, viewer) {
@@ -378,7 +414,7 @@ export function createLiveRooms(fingerprint, presence, options = {}) {
378
414
  last = fingerprint(key);
379
415
  }
380
416
  catch { /* the next signal or the safety net reads it */ }
381
- const created = { viewers: new Map(), last, timer: setInterval(() => refresh(key, created, null), safetyNetMs), settling: null, retry: null, saidAt: 0, holding: null, revision: null };
417
+ const created = { viewers: new Map(), last, timer: setInterval(() => refresh(key, created, null), safetyNetMs), settling: null, retry: null, saidAt: 0, holding: null, revision: null, reading: null };
382
418
  created.timer.unref();
383
419
  room = created;
384
420
  rooms.set(key, room);
@@ -0,0 +1,27 @@
1
+ import type { Store } from "./store.js";
2
+ /** The consent a "Show commands" form carries: a single-use nonce minted for this person and these exact terms. */
3
+ export declare const LIVE_VIEW_CONSENT = "live-view";
4
+ export declare function liveViewConsentDigest(repo: string): string;
5
+ export type LiveDetailSetting = {
6
+ repo: string;
7
+ commands: boolean;
8
+ updatedBy: string;
9
+ updatedAt: string;
10
+ };
11
+ /** Whether this project's live conversations show commands. Unknown or absent is off. */
12
+ export declare function liveCommandsShown(store: Store, repo: string | null): boolean;
13
+ export declare function liveDetailSetting(store: Store, repo: string): LiveDetailSetting | null;
14
+ /** Save the setting and its ledger line in one transaction. The caller has proved who is asking (and, to turn it on, their password). */
15
+ export declare function setLiveCommands(store: Store, change: {
16
+ repo: string;
17
+ commands: boolean;
18
+ by: string;
19
+ via: string;
20
+ }, now: Date): {
21
+ said: string;
22
+ };
23
+ /** A run's trusted context for its live file: its own checkout, and its project's setting, read now. */
24
+ export declare function liveLogContext(store: Store, taskRef: number, worktree: string | null): {
25
+ base: string | null;
26
+ commands: boolean;
27
+ };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * A project's "Show commands in the live view" (docs/plans/live-conversation.md):
3
+ * whether a running agent's command text and command output are written to
4
+ * its live conversation. Off unless an approver turned it on for the
5
+ * project with their password; turning it off is one step. Every change is
6
+ * an action-ledger line.
7
+ *
8
+ * The writer reads it once, when it opens a run's live file: what is off
9
+ * never reaches disk, and a change applies from the next run.
10
+ */
11
+ import { createHash } from "node:crypto";
12
+ /** The consent a "Show commands" form carries: a single-use nonce minted for this person and these exact terms. */
13
+ export const LIVE_VIEW_CONSENT = "live-view";
14
+ export function liveViewConsentDigest(repo) {
15
+ return createHash("sha256").update(JSON.stringify(["live-view", repo, "commands-on"])).digest("hex");
16
+ }
17
+ /** Whether this project's live conversations show commands. Unknown or absent is off. */
18
+ export function liveCommandsShown(store, repo) {
19
+ if (repo === null)
20
+ return false;
21
+ try {
22
+ const row = store.handle.prepare("SELECT commands FROM live_detail_setting WHERE repo = ?").get(repo);
23
+ return row !== undefined && Number(row["commands"]) === 1;
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ export function liveDetailSetting(store, repo) {
30
+ const row = store.handle.prepare("SELECT repo, commands, updated_by, updated_at FROM live_detail_setting WHERE repo = ?").get(repo);
31
+ if (row === undefined)
32
+ return null;
33
+ return { repo: String(row["repo"]), commands: Number(row["commands"]) === 1, updatedBy: String(row["updated_by"]), updatedAt: String(row["updated_at"]) };
34
+ }
35
+ /** Save the setting and its ledger line in one transaction. The caller has proved who is asking (and, to turn it on, their password). */
36
+ export function setLiveCommands(store, change, now) {
37
+ store.transact(() => {
38
+ store.handle
39
+ .prepare(`INSERT INTO live_detail_setting (repo, commands, updated_by, updated_at) VALUES (?,?,?,?)
40
+ ON CONFLICT (repo) DO UPDATE SET commands = excluded.commands, updated_by = excluded.updated_by, updated_at = excluded.updated_at`)
41
+ .run(change.repo, change.commands ? 1 : 0, change.by, now.toISOString());
42
+ store.recordAction({ at: now.toISOString(), actor: change.by, repo: change.repo, taskId: null, runId: null,
43
+ action: "live view commands", outcome: change.commands ? "on" : "off", source: "request", detail: `via ${change.via}` });
44
+ });
45
+ return { said: change.commands ? "Commands now show in the live view for this project, from the next run." : "Commands are hidden in the live view for this project, from the next run." };
46
+ }
47
+ /** A run's trusted context for its live file: its own checkout, and its project's setting, read now. */
48
+ export function liveLogContext(store, taskRef, worktree) {
49
+ let repo = null;
50
+ try {
51
+ repo = store.refForId(taskRef)?.repo ?? null;
52
+ }
53
+ catch {
54
+ repo = null;
55
+ }
56
+ return { base: worktree, commands: liveCommandsShown(store, repo) };
57
+ }
@@ -0,0 +1,20 @@
1
+ import type { Store } from "./store.js";
2
+ export declare const RUN_NOTES_SHOWN = 20;
3
+ export type RunNote = {
4
+ id: number;
5
+ author: string;
6
+ /** Whether the person looking wrote it: only then does the view say "You". */
7
+ mine: boolean;
8
+ at: string;
9
+ text: string;
10
+ standing: string;
11
+ readAt: string | null;
12
+ };
13
+ /** This run's notes, oldest first: the newest RUN_NOTES_SHOWN, and how many older ones the task page keeps. */
14
+ export declare function runNotes(store: Store, run: {
15
+ id: number;
16
+ taskRef: number;
17
+ }, viewer: string, now: Date): {
18
+ notes: RunNote[];
19
+ older: number;
20
+ };
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The steering notes that belong in one run's live conversation
3
+ * (docs/plans/live-conversation.md §5): every note this run reached —
4
+ * attached to its brief, mailed into its folder, or read by it, as kept in
5
+ * steer_note_run when it happened — and, only while this run is the task's
6
+ * live build, notes still waiting for it. A note never shows on a run it did
7
+ * not reach, and is credited as read only to the run that read it.
8
+ */
9
+ import { steerStandingParts } from "./steer-status.js";
10
+ export const RUN_NOTES_SHOWN = 20;
11
+ /** Where a note stands as seen from this run. */
12
+ function standingFor(note, run, live) {
13
+ if (note.authorshipState === "verified" && note.supersededAt === null && note.deliveredAt === null && !live) {
14
+ // This run ended (or is not the one reading notes) without reading it: it waits for the next attempt.
15
+ return { standing: "Not read in this attempt — the next one gets it", readAt: null };
16
+ }
17
+ // Once read, a note's attached run is the run that read it (ackSteerNote, settleSteerDelivered).
18
+ if (note.deliveredAt !== null && note.attachedRun !== run)
19
+ return { standing: "Read in another attempt", readAt: null };
20
+ const { words, readAt } = steerStandingParts(note, live);
21
+ return { standing: words, readAt };
22
+ }
23
+ /** This run's notes, oldest first: the newest RUN_NOTES_SHOWN, and how many older ones the task page keeps. */
24
+ export function runNotes(store, run, viewer, now) {
25
+ const live = store.steeringLiveBuild(run.taskRef, now) === run.id;
26
+ const reached = new Map(store.steerNotesReaching(run.id).filter(note => note.taskRef === run.taskRef).map(note => [note.id, note]));
27
+ if (live) {
28
+ for (const note of store.listSteerNotes(run.taskRef)) {
29
+ const waiting = note.authorshipState === "verified" && note.deliveredAt === null && note.supersededAt === null;
30
+ if (waiting && !reached.has(note.id))
31
+ reached.set(note.id, note);
32
+ }
33
+ }
34
+ const all = [...reached.values()].sort((a, b) => a.id - b.id);
35
+ const shown = all.slice(-RUN_NOTES_SHOWN);
36
+ return {
37
+ older: all.length - shown.length,
38
+ notes: shown.map(note => ({
39
+ id: note.id,
40
+ author: note.author,
41
+ mine: note.author === viewer,
42
+ at: note.createdAt,
43
+ text: note.note,
44
+ ...standingFor(note, run.id, live),
45
+ })),
46
+ };
47
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The live conversation's records (docs/plans/live-conversation.md): what a
3
+ * running agent said and did, one JSON object per line of `live/<run>.jsonl`.
4
+ *
5
+ * The recorder turns provider stream events into records. It names a step's
6
+ * target only from a closed list of argument fields, keeps a command's text
7
+ * and output only when the project turned "Show commands in the live view"
8
+ * on (the `commands` tier), and never writes a tool's own name — only our
9
+ * fixed kind. Every string is redacted, then cleaned of controls, then cut.
10
+ * The redaction is best effort; the opt-in is the real control.
11
+ *
12
+ * Readers trust nothing they read back: `parseLiveRecord` re-checks shape,
13
+ * caps and redaction, since the machine running the agent could alter the
14
+ * file. Display state, never evidence.
15
+ */
16
+ /**
17
+ * The fixed tool vocabulary: known harness tools map to OUR kinds; anything
18
+ * unrecognized is "tool". The tool's own name never reaches the file.
19
+ */
20
+ export type LiveActivityKind = "session" | "message" | "edit" | "command" | "read" | "search" | "lookup" | "plan" | "delegate" | "tool";
21
+ export declare const LIVE_ACTIVITY_KINDS: readonly LiveActivityKind[];
22
+ /** What a run's live file may hold: the base tier, or commands too (the project setting, read at open). */
23
+ export type LiveDetail = "base" | "commands";
24
+ /** One record. `at` is when the recorder saw it (ISO). */
25
+ export type LiveRecord =
26
+ /** The file's first record: what this run's project allowed when it started, kept with the run. */
27
+ {
28
+ k: "open";
29
+ at: string;
30
+ detail: LiveDetail;
31
+ } | {
32
+ k: "start";
33
+ at: string;
34
+ } | {
35
+ k: "say";
36
+ at: string;
37
+ t: string[];
38
+ } | {
39
+ k: "step";
40
+ at: string;
41
+ id: string;
42
+ kind: LiveActivityKind;
43
+ target?: string;
44
+ once?: true;
45
+ } | {
46
+ k: "done";
47
+ at: string;
48
+ id: string;
49
+ ok: boolean | null;
50
+ out?: string[];
51
+ } | {
52
+ k: "cut";
53
+ at: string;
54
+ } | {
55
+ k: "cap";
56
+ at: string;
57
+ };
58
+ /** A record's serialized size limit: a longer one is replaced by `cut`. */
59
+ export declare const LIVE_RECORD_CAP: number;
60
+ export declare const HIDDEN_TARGET = "[hidden]";
61
+ export declare const HIDDEN_LINE = "[a line was hidden]";
62
+ export declare const HIDDEN_KEY_BLOCK = "[a key block was hidden]";
63
+ export declare const OUTSIDE_PROJECT = "a file outside the project";
64
+ export declare const SOME_FILE = "a file";
65
+ /** Whether a line looks like it carries a credential (best effort). */
66
+ export declare function liveSecretHit(line: string): boolean;
67
+ /** Controls, ANSI escapes and bidi overrides out; tabs to spaces. */
68
+ export declare function cleanLiveText(text: string): string;
69
+ /** An escape a line ended in the middle of, which the next line finishes: CSI, OSC, or a bare ESC. */
70
+ export type EscapeCarry = "" | "C" | "O" | "E";
71
+ /** Cut to at most `cap` UTF-8 bytes on a character boundary, "…" when cut. */
72
+ export declare function capLive(text: string, cap: number): string;
73
+ /** One line for the view: redacted whole when it hits, then cleaned and cut. */
74
+ export declare function liveLine(raw: string, cap?: number): string;
75
+ /**
76
+ * Lines redacted as a whole: each line on its own, and a key block hidden
77
+ * from its BEGIN line to its END (or to the end) as one line. Used for the
78
+ * agent's words, command output, and everything read back.
79
+ */
80
+ /**
81
+ * Whether reading is inside a key block: carried from line to line, record to
82
+ * record and — through the reader's cursor — from one read to the next, so a
83
+ * block split anywhere stays hidden.
84
+ */
85
+ export type KeyState = {
86
+ inKey: boolean;
87
+ /** Per reading, how much of "-----BEGIN" the stream has ended on so far, then the escape the last line left open:
88
+ * marker characters and one flag only, never content, so it may ride the cursor. Joined with "|" when carried. */
89
+ tail?: string;
90
+ };
91
+ /** Whether a carried tail is one this code could have produced: three BEGIN prefixes and an escape flag, or nothing. */
92
+ export declare function validKeyTail(tail: string): boolean;
93
+ export declare function redactLiveLines(lines: readonly string[], state?: KeyState): string[];
94
+ /**
95
+ * Output for a command step: every line redacted first (a key block hidden
96
+ * from its BEGIN line to its END, or to the end), then the last 20 lines
97
+ * within 4 KiB — truncation never comes before redaction.
98
+ */
99
+ export declare function liveOutput(raw: string, keys?: KeyState): string[];
100
+ /**
101
+ * A path as the view shows it: relative to the run's own checkout when it
102
+ * lies inside it, judged lexically — nothing is opened or resolved on disk.
103
+ */
104
+ export declare function livePath(base: string | null, given: unknown): string | null;
105
+ /** A command's first line, "…" when more followed or it was cut. */
106
+ export declare function liveCommand(given: unknown): string | null;
107
+ export type LiveRecorderOptions = {
108
+ /** The run's own checkout; null when it has none (every path is "a file"). */
109
+ base: string | null;
110
+ /** The project's "Show commands in the live view" setting, read at open. */
111
+ commands: boolean;
112
+ clock?: () => Date;
113
+ };
114
+ export type LiveRecorder = {
115
+ /** The records one stream event adds. Never throws. */
116
+ observe(event: Record<string, unknown>): LiveRecord[];
117
+ /** The process ended: every step still open closes unknown. */
118
+ end(): LiveRecord[];
119
+ };
120
+ export declare function createLiveRecorder(options: LiveRecorderOptions): LiveRecorder;
121
+ /** One record as its file line; an oversized one becomes `cut`. */
122
+ export declare function serializeLiveRecord(record: LiveRecord): string;
123
+ /**
124
+ * One file line back into a record, strictly: a known shape within its caps,
125
+ * every string redacted and cleaned again. Anything else is null — skipped,
126
+ * never shown raw.
127
+ */
128
+ export declare function parseLiveRecord(line: string, keys?: KeyState): LiveRecord | null;
129
+ /** Complete file lines (a window's text) into records; bad lines are skipped. */
130
+ export declare function parseLiveRecords(text: string, keys?: KeyState): LiveRecord[];
131
+ export declare const LIVE_CAP_WORDS = "[the live view stopped at its size cap \u2014 the run record continues]";
132
+ export declare const LIVE_CUT_WORDS = "[a line was too long to show]";
133
+ export declare const LIVE_KIND_HEADLINES: Readonly<Record<LiveActivityKind, string>>;
134
+ /** A step's one line of words, with its target when it has one. */
135
+ export declare function stepWords(step: {
136
+ kind: LiveActivityKind;
137
+ target?: string;
138
+ }): string;
139
+ /** Records as the plain lines the run page and `toolroll peek` show. */
140
+ export declare function projectLiveText(records: readonly LiveRecord[]): string[];