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.
- package/CHANGELOG.md +80 -0
- package/README.md +66 -8
- package/dist/acp-agents.d.ts +43 -0
- package/dist/acp-agents.js +62 -0
- package/dist/acp-attest.d.ts +44 -0
- package/dist/acp-attest.js +269 -0
- package/dist/acp-check.d.ts +28 -0
- package/dist/acp-check.js +410 -0
- package/dist/acp-client.d.ts +163 -0
- package/dist/acp-client.js +738 -0
- package/dist/acp-inspect.d.ts +23 -0
- package/dist/acp-inspect.js +109 -0
- package/dist/agent-board.d.ts +19 -6
- package/dist/agent-board.js +30 -9
- package/dist/agent-fence.d.ts +203 -10
- package/dist/agent-fence.js +623 -41
- package/dist/agent-pulse.js +9 -2
- package/dist/agent-state-words.d.ts +19 -0
- package/dist/agent-state-words.js +20 -0
- package/dist/agent-state.d.ts +65 -0
- package/dist/agent-state.js +229 -0
- package/dist/agentconfig.js +36 -13
- package/dist/agents-board.d.ts +34 -2
- package/dist/agents-board.js +110 -1
- package/dist/approval-rules-ui.js +2 -2
- package/dist/assignment-delivery.d.ts +14 -0
- package/dist/assignment-delivery.js +13 -0
- package/dist/assignment.js +13 -0
- package/dist/attest.js +7 -0
- package/dist/backup-ui.js +2 -2
- package/dist/browser/THIRD_PARTY_NOTICES.txt +48 -0
- package/dist/browser/terminal.css +37 -0
- package/dist/browser/terminal.js +117 -0
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +42 -38
- package/dist/browser-shell.js +6 -3
- package/dist/browser-workspace.d.ts +263 -1
- package/dist/browser-workspace.js +60 -0
- package/dist/builder.d.ts +6 -1
- package/dist/builder.js +34 -13
- package/dist/chat-actions.d.ts +13 -1
- package/dist/chat-actions.js +199 -17
- package/dist/chat-ask.d.ts +4 -0
- package/dist/chat-ask.js +14 -0
- package/dist/chat-channel.js +20 -0
- package/dist/chat-continuity.js +5 -4
- package/dist/chat-decide.d.ts +0 -14
- package/dist/chat-decide.js +4 -1
- package/dist/chat-delivery.d.ts +9 -0
- package/dist/chat-delivery.js +45 -6
- package/dist/chat-messages.d.ts +8 -0
- package/dist/chat-messages.js +36 -4
- package/dist/check-levels-ui.js +2 -2
- package/dist/check-levels.js +3 -0
- package/dist/checkout-proof.d.ts +28 -0
- package/dist/checkout-proof.js +62 -0
- package/dist/claim.d.ts +12 -0
- package/dist/claim.js +20 -1
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +5 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +24 -2
- package/dist/coding-ui.js +6 -4
- package/dist/console-instance.d.ts +124 -0
- package/dist/console-instance.js +337 -0
- package/dist/contracts/chat-actions.d.ts +16 -0
- package/dist/contracts/chat-actions.js +4 -0
- package/dist/contracts/chat-content.d.ts +19 -0
- package/dist/contracts/chat-content.js +6 -0
- package/dist/contracts/cli.d.ts +8 -0
- package/dist/contracts/cli.js +3 -1
- package/dist/contracts/console-api.d.ts +30 -4
- package/dist/contracts/console-api.js +13 -4
- package/dist/contracts/flow-card.d.ts +4 -0
- package/dist/contracts/flow-card.js +3 -0
- package/dist/contracts/flow.d.ts +46 -0
- package/dist/contracts/flow.js +11 -2
- package/dist/contracts/integration-metadata.d.ts +2 -1
- package/dist/contracts/integration-metadata.js +2 -1
- package/dist/contracts/lead-tools.d.ts +92 -0
- package/dist/contracts/lead-tools.js +13 -0
- package/dist/contracts/provider.d.ts +11 -1
- package/dist/contracts/provider.js +1 -1
- package/dist/contracts/route.d.ts +76 -1
- package/dist/contracts/route.js +1 -1
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/control-setup.d.ts +1 -1
- package/dist/control-ui.js +2 -2
- package/dist/converse.d.ts +16 -0
- package/dist/converse.js +32 -4
- package/dist/demo-chat.js +4 -4
- package/dist/demo.js +2 -2
- package/dist/desktop-update-gate.js +6 -0
- package/dist/discord-chat.js +4 -1
- package/dist/dispatch.js +7 -4
- package/dist/doctor.d.ts +53 -0
- package/dist/doctor.js +427 -0
- package/dist/egress-bridge.d.ts +17 -0
- package/dist/egress-bridge.js +111 -0
- package/dist/egress.d.ts +119 -0
- package/dist/egress.js +423 -0
- package/dist/evidence-pack.d.ts +1 -1
- package/dist/evidence-pack.js +2 -2
- package/dist/exec.d.ts +81 -0
- package/dist/exec.js +368 -9
- package/dist/export-ui.js +2 -2
- package/dist/flow-code.d.ts +2 -2
- package/dist/flow-code.js +4 -15
- package/dist/flow-engine.js +35 -11
- package/dist/flow-gallery-ui.js +2 -2
- package/dist/flow-gallery.js +27 -8
- package/dist/flow-share.js +16 -5
- package/dist/flow-triggers.d.ts +84 -11
- package/dist/flow-triggers.js +554 -87
- package/dist/flow-unattended-words.d.ts +28 -0
- package/dist/flow-unattended-words.js +50 -0
- package/dist/flow-unattended.d.ts +227 -0
- package/dist/flow-unattended.js +776 -0
- package/dist/flows-cli.d.ts +28 -1
- package/dist/flows-cli.js +63 -12
- package/dist/flows-ui.d.ts +2 -3
- package/dist/flows-ui.js +56 -5
- package/dist/flows.d.ts +4 -0
- package/dist/flows.js +9 -1
- package/dist/google-mail.d.ts +1 -0
- package/dist/google-mail.js +61 -18
- package/dist/html.d.ts +9 -0
- package/dist/html.js +11 -0
- package/dist/integrations-ui.d.ts +2 -1
- package/dist/integrations-ui.js +6 -3
- package/dist/integrations.d.ts +17 -3
- package/dist/integrations.js +38 -18
- package/dist/invoke.d.ts +17 -0
- package/dist/invoke.js +510 -182
- package/dist/keys.d.ts +18 -14
- package/dist/keys.js +5 -0
- package/dist/landed-cleanup.d.ts +3 -2
- package/dist/landed-cleanup.js +12 -5
- package/dist/lead-capabilities.js +3 -2
- package/dist/lead-contract.js +2 -0
- package/dist/lead-doors.d.ts +2 -0
- package/dist/lead-doors.js +7 -0
- package/dist/lead-follow.d.ts +2 -0
- package/dist/lead-follow.js +58 -2
- package/dist/lead-progress.js +1 -0
- package/dist/lead-queue-runtime.d.ts +46 -0
- package/dist/lead-queue-runtime.js +191 -0
- package/dist/lead-queue.d.ts +104 -0
- package/dist/lead-queue.js +187 -0
- package/dist/lead-sweep.d.ts +67 -0
- package/dist/lead-sweep.js +99 -0
- package/dist/lead-tools.d.ts +22 -0
- package/dist/lead-tools.js +163 -4
- package/dist/lead.d.ts +13 -5
- package/dist/lead.js +89 -29
- package/dist/limits-ui.d.ts +8 -1
- package/dist/limits-ui.js +26 -0
- package/dist/live-bus.d.ts +8 -0
- package/dist/live-bus.js +40 -4
- package/dist/live-detail.d.ts +27 -0
- package/dist/live-detail.js +57 -0
- package/dist/live-notes.d.ts +20 -0
- package/dist/live-notes.js +47 -0
- package/dist/live-records.d.ts +140 -0
- package/dist/live-records.js +935 -0
- package/dist/live-terminal.d.ts +258 -0
- package/dist/live-terminal.js +649 -0
- package/dist/live.d.ts +38 -27
- package/dist/live.js +142 -124
- package/dist/mcp-connect.d.ts +8 -7
- package/dist/mcp-connect.js +49 -51
- package/dist/mcp-oauth.d.ts +6 -3
- package/dist/mcp-oauth.js +8 -4
- package/dist/memory-pass.js +2 -2
- package/dist/mobile-viewport.d.ts +5 -1
- package/dist/mobile-viewport.js +18 -2
- package/dist/model-catalog.js +4 -0
- package/dist/monitoring-ui.js +2 -2
- package/dist/needs-you.d.ts +1 -1
- package/dist/needs-you.js +11 -4
- package/dist/oauth-run-token.d.ts +51 -0
- package/dist/oauth-run-token.js +127 -0
- package/dist/operate.d.ts +2 -0
- package/dist/operate.js +282 -18
- package/dist/passwordless.d.ts +23 -0
- package/dist/passwordless.js +26 -0
- package/dist/peek-cli.d.ts +12 -4
- package/dist/peek-cli.js +19 -11
- package/dist/phase-routing.js +10 -3
- package/dist/plan-auto.d.ts +11 -0
- package/dist/plan-auto.js +62 -11
- package/dist/planner-source.d.ts +3 -0
- package/dist/planner-source.js +14 -0
- package/dist/planner.d.ts +2 -1
- package/dist/planner.js +7 -1
- package/dist/policy-ui.js +2 -2
- package/dist/policy.d.ts +1 -20
- package/dist/policy.js +29 -2
- package/dist/process-recovery-eligibility.d.ts +1 -1
- package/dist/project-access.d.ts +3 -0
- package/dist/project-access.js +3 -0
- package/dist/project-delete-ui.d.ts +12 -0
- package/dist/project-delete-ui.js +41 -9
- package/dist/project-delete.d.ts +3 -1
- package/dist/project-delete.js +12 -6
- package/dist/project-file.d.ts +3 -0
- package/dist/project-file.js +16 -0
- package/dist/project-memory.d.ts +3 -1
- package/dist/project-memory.js +57 -25
- package/dist/project-tools.d.ts +103 -27
- package/dist/project-tools.js +399 -100
- package/dist/provider-auth.d.ts +4 -3
- package/dist/provider-auth.js +5 -4
- package/dist/provider-connection.d.ts +2 -1
- package/dist/provider-connection.js +5 -0
- package/dist/provider-home.d.ts +22 -0
- package/dist/provider-home.js +99 -0
- package/dist/provider.d.ts +42 -5
- package/dist/provider.js +97 -19
- package/dist/pull-request-ui.js +2 -2
- package/dist/push.js +1 -1
- package/dist/quick-start.d.ts +24 -0
- package/dist/quick-start.js +127 -0
- package/dist/release.d.ts +3 -0
- package/dist/release.js +14 -8
- package/dist/remote-main.d.ts +4 -0
- package/dist/remote-main.js +3 -3
- package/dist/request-budget-ui.js +2 -2
- package/dist/result-review.d.ts +1 -1
- package/dist/result-review.js +9 -3
- package/dist/retention-ui.js +2 -2
- package/dist/retention.js +10 -1
- package/dist/run-efficiency.d.ts +73 -0
- package/dist/run-efficiency.js +228 -0
- package/dist/runner.d.ts +5 -1
- package/dist/runner.js +22 -1
- package/dist/scope.d.ts +171 -6
- package/dist/scope.js +251 -31
- package/dist/scout-net.d.ts +4 -1
- package/dist/scout-net.js +37 -12
- package/dist/scout.d.ts +20 -6
- package/dist/scout.js +27 -3
- package/dist/serve.js +258 -43
- package/dist/server/chat.d.ts +1 -1
- package/dist/server/chat.js +122 -31
- package/dist/server/chrome.d.ts +6 -1
- package/dist/server/chrome.js +18 -7
- package/dist/server/console.css +52 -38
- package/dist/server/flows.js +65 -13
- package/dist/server/guards.d.ts +1 -0
- package/dist/server/guards.js +23 -9
- package/dist/server/http.d.ts +7 -0
- package/dist/server/http.js +3 -2
- package/dist/server/live.d.ts +34 -1
- package/dist/server/live.js +39 -17
- package/dist/server/pages-assets.js +5 -0
- package/dist/server/pages.js +90 -13
- package/dist/server/people-tokens.d.ts +3 -0
- package/dist/server/people-tokens.js +55 -17
- package/dist/server/remote-hooks.js +12 -6
- package/dist/server/remote.d.ts +2 -1
- package/dist/server/remote.js +14 -5
- package/dist/server/render-chat.d.ts +12 -3
- package/dist/server/render-chat.js +47 -16
- package/dist/server/render-pages.d.ts +4 -1
- package/dist/server/render-pages.js +5 -4
- package/dist/server/render-people.d.ts +3 -2
- package/dist/server/render-people.js +3 -2
- package/dist/server/render-results.d.ts +18 -2
- package/dist/server/render-results.js +37 -28
- package/dist/server/render-settings.js +6 -5
- package/dist/server/render-tasks.d.ts +35 -10
- package/dist/server/render-tasks.js +110 -27
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/request-context.js +2 -1
- package/dist/server/route-table.d.ts +3 -0
- package/dist/server/route-table.js +49 -5
- package/dist/server/runtime.d.ts +34 -3
- package/dist/server/session.d.ts +25 -1
- package/dist/server/session.js +18 -4
- package/dist/server/settings.js +132 -13
- package/dist/server/sweeps.d.ts +4 -0
- package/dist/server/sweeps.js +58 -0
- package/dist/server/task-views.d.ts +2 -1
- package/dist/server/task-views.js +96 -6
- package/dist/server/tasks.js +320 -74
- package/dist/server/terminals.d.ts +31 -0
- package/dist/server/terminals.js +365 -0
- package/dist/setup-guide.js +3 -2
- package/dist/slack-chat.js +4 -1
- package/dist/spend-ui.js +3 -3
- package/dist/spend.js +2 -1
- package/dist/steer-capabilities.d.ts +32 -0
- package/dist/steer-capabilities.js +60 -0
- package/dist/steer-controls.d.ts +14 -0
- package/dist/steer-controls.js +36 -0
- package/dist/steer-status.js +2 -2
- package/dist/storage-sweep-child.js +3 -1
- package/dist/storage-sweep-process.d.ts +12 -5
- package/dist/storage-sweep-process.js +23 -6
- package/dist/storage-ui.js +4 -4
- package/dist/store-baseline.d.ts +1 -1
- package/dist/store-baseline.js +1 -1
- package/dist/store.d.ts +466 -19
- package/dist/store.js +1185 -63
- package/dist/subagent-desk.js +1 -1
- package/dist/subagent-tools.d.ts +1 -1
- package/dist/summary.js +3 -0
- package/dist/surface.js +6 -4
- package/dist/task-source.d.ts +58 -0
- package/dist/task-source.js +93 -0
- package/dist/team-leads.js +1 -1
- package/dist/teams-chat.js +4 -1
- package/dist/teardown-git.d.ts +14 -0
- package/dist/teardown-git.js +119 -0
- package/dist/telegram-lead.d.ts +3 -0
- package/dist/telegram-lead.js +44 -7
- package/dist/telegram.d.ts +11 -2
- package/dist/telegram.js +51 -17
- package/dist/terminal-catalog.d.ts +11 -0
- package/dist/terminal-catalog.js +129 -0
- package/dist/text-limits.d.ts +2 -0
- package/dist/text-limits.js +2 -0
- package/dist/tool-broker.d.ts +39 -0
- package/dist/tool-broker.js +370 -0
- package/dist/tool-launcher.js +5 -4
- package/dist/tool-secret-store.d.ts +170 -0
- package/dist/tool-secret-store.js +834 -0
- package/dist/toolroll-update-ui.js +2 -2
- package/dist/toolroll-update.js +14 -3
- package/dist/tools-ui.d.ts +7 -1
- package/dist/tools-ui.js +19 -10
- package/dist/webhook-limits.d.ts +23 -0
- package/dist/webhook-limits.js +30 -0
- package/dist/webhook-readers.d.ts +56 -0
- package/dist/webhook-readers.js +138 -0
- package/dist/webhook-signing.d.ts +27 -0
- package/dist/webhook-signing.js +119 -0
- package/dist/work-index.d.ts +29 -0
- package/dist/work-index.js +21 -5
- package/dist/workspace-revision.js +3 -1
- package/dist/worktree.d.ts +10 -4
- package/dist/worktree.js +70 -29
- package/package.json +13 -2
- package/scripts/provider-canary.mjs +210 -31
package/dist/live-bus.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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[];
|