toolroll 0.9.52 → 0.9.54

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 (187) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +55 -80
  3. package/dist/agentconfig.d.ts +11 -36
  4. package/dist/agentconfig.js +3 -62
  5. package/dist/approval-policy.d.ts +1 -1
  6. package/dist/approval-policy.js +1 -1
  7. package/dist/board.d.ts +3 -19
  8. package/dist/board.js +4 -42
  9. package/dist/browser/workspace.js +18 -18
  10. package/dist/browser-workspace.d.ts +2 -1
  11. package/dist/builder.d.ts +9 -40
  12. package/dist/builder.js +50 -257
  13. package/dist/chat-actions.js +3 -14
  14. package/dist/chat-ask.js +8 -8
  15. package/dist/chat-controls.d.ts +0 -4
  16. package/dist/chat-controls.js +0 -1
  17. package/dist/chat-core.d.ts +171 -0
  18. package/dist/chat-core.js +288 -0
  19. package/dist/chat-decide.d.ts +10 -8
  20. package/dist/chat-decide.js +27 -24
  21. package/dist/chat-delivery-state.d.ts +51 -75
  22. package/dist/chat-delivery-state.js +140 -170
  23. package/dist/chat-delivery.d.ts +21 -4
  24. package/dist/chat-delivery.js +313 -195
  25. package/dist/chat-flow.d.ts +29 -1
  26. package/dist/chat-flow.js +24 -50
  27. package/dist/chat-messages.d.ts +319 -0
  28. package/dist/chat-messages.js +841 -0
  29. package/dist/chat-migration.d.ts +30 -0
  30. package/dist/chat-migration.js +802 -0
  31. package/dist/chat-quiet.d.ts +3 -0
  32. package/dist/chat-quiet.js +7 -2
  33. package/dist/chat-task-actions.d.ts +1 -1
  34. package/dist/chat-task-actions.js +0 -2
  35. package/dist/claim.d.ts +79 -244
  36. package/dist/claim.js +688 -1023
  37. package/dist/cli.d.ts +2 -0
  38. package/dist/cli.js +10 -2
  39. package/dist/contracts/chat-content.d.ts +71 -2
  40. package/dist/contracts/chat-content.js +22 -3
  41. package/dist/contracts/chat-tables.d.ts +11 -4
  42. package/dist/contracts/chat-tables.js +165 -87
  43. package/dist/contracts/cli.d.ts +0 -13
  44. package/dist/contracts/cli.js +0 -2
  45. package/dist/contracts/console-api.d.ts +5 -10
  46. package/dist/contracts/console-api.js +4 -10
  47. package/dist/contracts/discord-callback.js +2 -1
  48. package/dist/contracts/flow.d.ts +50 -0
  49. package/dist/contracts/flow.js +26 -1
  50. package/dist/contracts/lead-tools.d.ts +0 -13
  51. package/dist/contracts/lead-tools.js +3 -3
  52. package/dist/contracts/slack-callback.js +3 -2
  53. package/dist/contracts/store-json.d.ts +1 -29
  54. package/dist/contracts/store-json.js +4 -17
  55. package/dist/contracts/teams-callback.js +2 -1
  56. package/dist/converse.d.ts +1 -11
  57. package/dist/converse.js +6 -38
  58. package/dist/coordinator.d.ts +0 -1
  59. package/dist/coordinator.js +3 -5
  60. package/dist/demo.js +16 -26
  61. package/dist/desktop-update-gate.js +0 -1
  62. package/dist/desktop-update.js +1 -3
  63. package/dist/discord-chat.js +19 -38
  64. package/dist/discord-settings.js +4 -13
  65. package/dist/discord.js +4 -14
  66. package/dist/dispatch.d.ts +1 -1
  67. package/dist/dispatch.js +1 -1
  68. package/dist/dispose.d.ts +2 -3
  69. package/dist/dispose.js +17 -92
  70. package/dist/envelope.js +0 -3
  71. package/dist/exec.d.ts +0 -64
  72. package/dist/exec.js +3 -356
  73. package/dist/exhaustion.d.ts +22 -76
  74. package/dist/exhaustion.js +14 -140
  75. package/dist/export.js +8 -8
  76. package/dist/flow-engine.js +1 -1
  77. package/dist/flow-schedule.d.ts +154 -0
  78. package/dist/flow-schedule.js +321 -0
  79. package/dist/flow-share.js +1 -1
  80. package/dist/flow-triggers.d.ts +6 -1
  81. package/dist/flow-triggers.js +65 -10
  82. package/dist/flows-cli.js +8 -4
  83. package/dist/flows-ui.js +2 -0
  84. package/dist/flows.js +1 -1
  85. package/dist/guides.js +9 -29
  86. package/dist/invoke.d.ts +1 -24
  87. package/dist/invoke.js +17 -259
  88. package/dist/lead-status.js +2 -4
  89. package/dist/lead-voice.js +1 -1
  90. package/dist/mate-doors.d.ts +1 -2
  91. package/dist/mate-doors.js +12 -25
  92. package/dist/mate-tools.d.ts +2 -2
  93. package/dist/mate-tools.js +13 -24
  94. package/dist/modes.d.ts +19 -8
  95. package/dist/modes.js +24 -14
  96. package/dist/notification-rows.d.ts +30 -0
  97. package/dist/notification-rows.js +102 -0
  98. package/dist/operate-remote-arguments.js +2 -6
  99. package/dist/operate-remote.js +6 -7
  100. package/dist/operate.d.ts +0 -6
  101. package/dist/operate.js +226 -2248
  102. package/dist/phase-routing.d.ts +13 -23
  103. package/dist/phase-routing.js +13 -35
  104. package/dist/plan-auto.js +2 -2
  105. package/dist/plane-review.js +5 -11
  106. package/dist/planner-source.js +2 -1
  107. package/dist/policy.d.ts +1 -4
  108. package/dist/policy.js +0 -8
  109. package/dist/process-recovery-eligibility.js +2 -3
  110. package/dist/project-delete.js +24 -41
  111. package/dist/proposal.d.ts +4 -24
  112. package/dist/proposal.js +3 -88
  113. package/dist/provider-auth.d.ts +3 -3
  114. package/dist/provider-auth.js +4 -6
  115. package/dist/provider.d.ts +11 -25
  116. package/dist/provider.js +4 -36
  117. package/dist/push.js +1 -1
  118. package/dist/recipe-ui.js +6 -6
  119. package/dist/recipes.d.ts +3 -3
  120. package/dist/recipes.js +27 -23
  121. package/dist/result-shots.js +2 -2
  122. package/dist/retention.js +1 -1
  123. package/dist/run-closeout.d.ts +1 -1
  124. package/dist/run-closeout.js +1 -4
  125. package/dist/scope.d.ts +11 -65
  126. package/dist/scope.js +17 -82
  127. package/dist/serve.js +15 -24
  128. package/dist/server/chat.js +7 -30
  129. package/dist/server/flows.js +11 -10
  130. package/dist/server/guards.js +0 -1
  131. package/dist/server/pages-assets.js +1 -1
  132. package/dist/server/pages.js +0 -2
  133. package/dist/server/people-tokens.js +0 -4
  134. package/dist/server/route-table.d.ts +1 -1
  135. package/dist/server/route-table.js +2 -17
  136. package/dist/server/settings.js +6 -12
  137. package/dist/server/shared.d.ts +28 -212
  138. package/dist/server/shared.js +71 -780
  139. package/dist/server/task-views.js +9 -76
  140. package/dist/server/tasks.d.ts +1 -50
  141. package/dist/server/tasks.js +36 -946
  142. package/dist/setup-guide.d.ts +2 -2
  143. package/dist/slack-api.d.ts +5 -1
  144. package/dist/slack-api.js +2 -2
  145. package/dist/slack-chat.d.ts +9 -6
  146. package/dist/slack-chat.js +29 -53
  147. package/dist/slack-settings.js +6 -15
  148. package/dist/slack.js +6 -16
  149. package/dist/store.d.ts +200 -1702
  150. package/dist/store.js +811 -5439
  151. package/dist/surface.js +10 -24
  152. package/dist/task-composer.d.ts +1 -1
  153. package/dist/task-composer.js +1 -1
  154. package/dist/task-control.d.ts +3 -10
  155. package/dist/task-control.js +2 -7
  156. package/dist/teammate-desk.js +1 -1
  157. package/dist/teammate-question.js +12 -12
  158. package/dist/teammates-ui.js +1 -1
  159. package/dist/teams-chat.js +12 -9
  160. package/dist/teams-settings.js +2 -2
  161. package/dist/teams.js +4 -5
  162. package/dist/telegram-flow.js +5 -5
  163. package/dist/telegram-mate.d.ts +0 -3
  164. package/dist/telegram-mate.js +0 -1
  165. package/dist/telegram.js +4 -4
  166. package/dist/templates.d.ts +11 -7
  167. package/dist/templates.js +12 -9
  168. package/dist/toolroll-update.d.ts +20 -0
  169. package/dist/toolroll-update.js +104 -5
  170. package/dist/work-index.js +2 -6
  171. package/dist/workspace-revision.js +3 -1
  172. package/dist/workspace-ui.js +1 -1
  173. package/package.json +1 -1
  174. package/scripts/recovery-canary.mjs +3 -3
  175. package/dist/contest.d.ts +0 -318
  176. package/dist/contest.js +0 -753
  177. package/dist/held.d.ts +0 -150
  178. package/dist/held.js +0 -799
  179. package/dist/liveness.d.ts +0 -30
  180. package/dist/liveness.js +0 -42
  181. package/dist/pricing.d.ts +0 -45
  182. package/dist/pricing.js +0 -77
  183. package/dist/routine.d.ts +0 -228
  184. package/dist/routine.js +0 -764
  185. package/dist/slack-state.d.ts +0 -13
  186. package/dist/slack-state.js +0 -10
  187. package/dist/supervisor.mjs +0 -297
@@ -1,13 +0,0 @@
1
- /** Slack compatibility names for the shared durable transport state. */
2
- import { ChatState } from "./chat-delivery-state.js";
3
- import type { Store } from "./store.js";
4
- export { chatHash as slackHash } from "./chat-delivery-state.js";
5
- export type { ChatBinding as SlackBinding, ChatEvent as SlackEvent, ChatPart as SlackPart, ChatContent as SlackContent, } from "./chat-delivery-state.js";
6
- import type { ChatIdentity } from "./chat-delivery-state.js";
7
- export type SlackIdentity = ChatIdentity & {
8
- team: string;
9
- };
10
- export declare const SLACK_SCHEMA: string, SLACK_TABLES: string[];
11
- export declare class SlackState extends ChatState {
12
- constructor(store: Store);
13
- }
@@ -1,10 +0,0 @@
1
- /** Slack compatibility names for the shared durable transport state. */
2
- import { ChatState } from "./chat-delivery-state.js";
3
- import { chatSchema, chatTables } from "./contracts/chat-tables.js";
4
- export { chatHash as slackHash } from "./chat-delivery-state.js";
5
- export const SLACK_SCHEMA = chatSchema("slack"), SLACK_TABLES = chatTables("slack");
6
- export class SlackState extends ChatState {
7
- constructor(store) {
8
- super(store, "slack");
9
- }
10
- }
@@ -1,297 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * The held-session supervisor (Parity II Phase 2, spec v5 P4 / v6 W7+W9).
4
- *
5
- * A minimal, zero-dependency parent for one held agent process. Its whole
6
- * value is PARENTHOOD: while this process lives and has not reaped its
7
- * child, POSIX guarantees the child's PID cannot be reused — so a kill
8
- * ordered through this process can never hit an innocent stranger, which
9
- * no PID-plus-timestamp guess can promise. Everything else here is a dumb
10
- * byte pump.
11
- *
12
- * Invocation (by exec.ts only):
13
- * node supervisor.mjs <agent-binary> <agent-args...>
14
- * env: SO_HELD_SOCKET — unix socket path for the control channel
15
- * SO_HELD_COOKIE — 128-bit hex cookie; every socket verb must carry it
16
- * SO_HELD_GRACE_MS — EOF→SIGKILL grace (default 10s)
17
- * SO_HELD_DIAGNOSTIC_FD — private observer diagnostic pipe (optional)
18
- *
19
- * Protocol, in order:
20
- * 1. The control socket is created FIRST (mode 0600), so a fencer can
21
- * always reach a supervisor that got as far as spawning.
22
- * 2. The agent spawns DETACHED into its own fresh process group.
23
- * 3. stdout emits exactly ONE control frame before any relayed agent
24
- * byte: {"so_supervisor":"ready","agentPgid":N,"supervisorPid":N}
25
- * or {"so_supervisor":"spawn-failed","message":...}. Everything after
26
- * the ready frame is the agent's stream, byte for byte.
27
- * 4. stdin bytes relay to the agent verbatim. stdin EOF (the owner ended
28
- * the hold, or died — the pipe broke) starts the AUTONOMOUS FENCE:
29
- * EOF to the agent, grace, then SIGKILL of its whole group. SIGTERM
30
- * and SIGHUP take the same road (the hard-stop sweep's contract).
31
- * 5. Socket verbs, one JSON line per connection, cookie-checked:
32
- * {"cookie":..,"verb":"status"} → {"ok":true,"alive":bool,...}
33
- * {"cookie":..,"verb":"kill"} → group SIGKILL via the held handle,
34
- * answered only after the group is PROVEN gone (ESRCH poll, 5s bound).
35
- * 6. The supervisor exits when the agent has exited and the relay has
36
- * flushed; the socket file is unlinked on the way out.
37
- */
38
-
39
- // The source supervisor is also exercised directly by the TypeScript test
40
- // runner; its shared helper comes from the normal production build there.
41
- const { stopProcessTree, observeProcessTree, sampleProcessTree } = await import(new URL("./process-tree.js", import.meta.url).href).catch(error => {
42
- if (error.code !== "ERR_MODULE_NOT_FOUND") throw error;
43
- return import(new URL("../dist/process-tree.js", import.meta.url).href);
44
- });
45
- import { spawn } from "node:child_process";
46
- import { createServer } from "node:net";
47
- import { chmodSync, unlinkSync, writeSync } from "node:fs";
48
-
49
- const socketPath = process.env["SO_HELD_SOCKET"] ?? "";
50
- const cookie = process.env["SO_HELD_COOKIE"] ?? "";
51
- const graceMs = Math.max(1000, Number(process.env["SO_HELD_GRACE_MS"] ?? 10_000) || 10_000);
52
- const [agentFile, ...agentArgs] = process.argv.slice(2);
53
-
54
- const frame = payload => {
55
- process.stdout.write(`${JSON.stringify(payload)}\n`);
56
- };
57
-
58
- if (socketPath === "" || cookie === "" || agentFile === undefined) {
59
- frame({ so_supervisor: "spawn-failed", message: "missing SO_HELD_SOCKET, SO_HELD_COOKIE, or agent argv" });
60
- process.exit(2);
61
- }
62
-
63
- let exited = false;
64
- let exitCode = null;
65
- let fencing = false;
66
- let server = null;
67
- let killsInFlight = 0;
68
- const descendantPids = new Set();
69
- let treeUnknown = false;
70
- let exitWanted = false;
71
- let drain = null;
72
- let relayClosed = false;
73
- let relayDeadline = null;
74
-
75
- /** The exit road, deferred while a kill verb's reply is still owed: the
76
- * fencer must HEAR that the group is proven gone before the process that
77
- * proved it disappears. */
78
- const maybeExit = () => {
79
- if (!exitWanted || killsInFlight > 0) return;
80
- cleanup();
81
- for (const connection of pending) connection.destroy();
82
- process.exit(exitCode ?? 1);
83
- };
84
-
85
- const cleanup = () => {
86
- try {
87
- server?.close();
88
- } catch {
89
- // Already closed.
90
- }
91
- try {
92
- unlinkSync(socketPath);
93
- } catch {
94
- // Never existed, or already gone.
95
- }
96
- };
97
-
98
- /** True while ANY member of the agent's group survives. */
99
- const groupAlive = pgid => {
100
- try {
101
- process.kill(-pgid, 0);
102
- return true;
103
- } catch (error) {
104
- return error.code !== "ESRCH";
105
- }
106
- };
107
- const descendantsAlive = () => treeUnknown || [...descendantPids].some(pid => {
108
- try { process.kill(pid, 0); return true; } catch (error) { return error.code !== "ESRCH"; }
109
- });
110
- const holdGone = pgid => relayClosed && !groupAlive(pgid) && !descendantsAlive();
111
-
112
- /** All exit roads share one drain. In particular, child.close must not
113
- * outrun an EOF fence that is still waiting for a detached tool to die. */
114
- const killGroupSettled = pgid => drain ??= Promise.resolve().then(async () => {
115
- if (child !== undefined && !exited) stopProcessTree(child);
116
- try {
117
- process.kill(-pgid, "SIGKILL");
118
- } catch {
119
- // Group already gone — proving below still runs.
120
- }
121
- const deadline = Date.now() + 5_000;
122
- while (Date.now() < deadline) {
123
- if (holdGone(pgid)) return true;
124
- await new Promise(pass => setTimeout(pass, 50));
125
- }
126
- return holdGone(pgid);
127
- });
128
-
129
- // The control socket comes up BEFORE the agent spawns.
130
- const pending = new Set();
131
- server = createServer(connection => {
132
- pending.add(connection);
133
- connection.on("close", () => pending.delete(connection));
134
- let buffered = "";
135
- connection.on("data", chunk => {
136
- buffered += String(chunk);
137
- const cut = buffered.indexOf("\n");
138
- if (cut === -1) {
139
- if (buffered.length > 4096) connection.destroy();
140
- return;
141
- }
142
- const line = buffered.slice(0, cut);
143
- buffered = "";
144
- let order = null;
145
- try {
146
- order = JSON.parse(line);
147
- } catch {
148
- connection.destroy();
149
- return;
150
- }
151
- if (order === null || typeof order !== "object" || order.cookie !== cookie) {
152
- // Wrong cookie: one refusal, no detail, connection over.
153
- connection.end(`${JSON.stringify({ ok: false })}\n`);
154
- return;
155
- }
156
- if (order.verb === "status") {
157
- const pgid = child?.pid;
158
- const group = pgid !== undefined && groupAlive(pgid);
159
- connection.end(
160
- `${JSON.stringify({ ok: true, alive: !exited || !relayClosed || group || descendantsAlive(), groupAlive: group, agentPgid: pgid ?? null, exitCode })}\n`,
161
- );
162
- return;
163
- }
164
- if (order.verb === "kill") {
165
- const pgid = child?.pid;
166
- if (pgid === undefined) {
167
- connection.end(`${JSON.stringify({ ok: true, killed: false, settled: false, exitCode })}\n`);
168
- return;
169
- }
170
- const killed = !exited;
171
- killsInFlight += 1;
172
- killGroupSettled(pgid).then(settled => {
173
- // The reply counts as owed until the write side has FLUSHED —
174
- // exiting on the mere call would let process death eat the FIN.
175
- let settledReply = false;
176
- const done = () => {
177
- if (settledReply) return;
178
- settledReply = true;
179
- killsInFlight -= 1;
180
- maybeExit();
181
- };
182
- try {
183
- connection.on("finish", done);
184
- connection.on("close", done);
185
- connection.end(`${JSON.stringify({ ok: true, killed, settled, exitCode })}\n`);
186
- setTimeout(done, 2_000).unref();
187
- } catch {
188
- done();
189
- }
190
- });
191
- return;
192
- }
193
- connection.end(`${JSON.stringify({ ok: false })}\n`);
194
- });
195
- });
196
-
197
- let child;
198
- server.on("error", error => {
199
- frame({ so_supervisor: "spawn-failed", message: `control socket: ${String(error)}` });
200
- process.exit(1);
201
- });
202
- server.listen(socketPath, () => {
203
- try {
204
- chmodSync(socketPath, 0o600);
205
- } catch {
206
- // Best effort; the parent directory is already private.
207
- }
208
-
209
- child = spawn(agentFile, agentArgs, {
210
- detached: true,
211
- stdio: ["pipe", "pipe", "pipe"],
212
- });
213
-
214
- child.on("error", error => {
215
- frame({ so_supervisor: "spawn-failed", message: String(error) });
216
- cleanup();
217
- process.exit(1);
218
- });
219
-
220
- observeProcessTree(child, {
221
- onDescendant: pid => descendantPids.add(pid),
222
- onObservationFailure: failure => {
223
- // A dedicated pipe, never the untrusted agent's stdout/stderr. The
224
- // agent gets exactly three stdio descriptors and cannot inherit it.
225
- if (process.env["SO_HELD_DIAGNOSTIC_FD"] === "3") writeSync(3, `${JSON.stringify(failure)}\n`);
226
- },
227
- onUnknown: () => { treeUnknown = true; },
228
- });
229
- child.on("spawn", () => {
230
- frame({ so_supervisor: "ready", agentPgid: child.pid, supervisorPid: process.pid });
231
- // Relay AFTER the frame: agent bytes buffered meanwhile flow next.
232
- child.stdout.pipe(process.stdout, { end: false });
233
- child.stderr.pipe(process.stderr, { end: false });
234
- process.stdin.pipe(child.stdin, { end: false });
235
- process.stdin.on("end", () => fence());
236
- process.stdin.on("error", () => fence());
237
- });
238
-
239
- child.on("exit", (code, signal) => {
240
- exited = true;
241
- exitCode = code ?? (signal === null ? 1 : 143);
242
- // A tool may inherit stdout/stderr and keep `close` from ever firing.
243
- // Start cleanup at root exit, while retaining the relay until flushed.
244
- if (child.pid !== undefined) void killGroupSettled(child.pid);
245
- relayDeadline = setTimeout(() => {
246
- if (relayClosed) return;
247
- // Open pipes after the drain bound may belong to an unobserved,
248
- // detached writer. Do not call the hold successfully completed.
249
- treeUnknown = true;
250
- exitCode = 126;
251
- child.stdout.destroy();
252
- child.stderr.destroy();
253
- }, 5_000);
254
- });
255
-
256
- child.on("close", code => {
257
- relayClosed = true;
258
- clearTimeout(relayDeadline);
259
- // stdio flushed and the process reaped. The GROUP may still have
260
- // members — a tool the agent launched can outlive its leader (round-6
261
- // finding 4) — so the whole group is drained and PROVEN gone before
262
- // custody releases; the whole-tree invariant is the group, never the
263
- // one pid.
264
- exitCode = exitCode ?? code ?? 1;
265
- const pgid = child.pid;
266
- const drained = pgid !== undefined ? killGroupSettled(pgid) : Promise.resolve(false);
267
- drained.then(settled => {
268
- // Match exec.ts's containment refusal. A clean root exit is not a
269
- // clean hold when descendants remain or observation failed.
270
- if (!settled || treeUnknown) exitCode = 126;
271
- exitWanted = true;
272
- maybeExit();
273
- });
274
- });
275
- });
276
-
277
- /** EOF → grace → group SIGKILL. Idempotent; every exit road converges here. */
278
- const fence = () => {
279
- if (fencing || exited || child === undefined) return;
280
- fencing = true;
281
- // Preserve witnesses before a cooperative root can exit and orphan its
282
- // tools between the observer's periodic snapshots.
283
- sampleProcessTree(child);
284
- try {
285
- child.stdin.end();
286
- } catch {
287
- // Already closed.
288
- }
289
- const timer = setTimeout(() => {
290
- if (!exited && child.pid !== undefined) void killGroupSettled(child.pid);
291
- }, graceMs);
292
- timer.unref();
293
- };
294
-
295
- process.on("SIGTERM", () => fence());
296
- process.on("SIGHUP", () => fence());
297
- process.on("SIGINT", () => fence());