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.d.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* Fail-soft everywhere: a live view that cannot be written must never
|
|
14
14
|
* break, slow, or reclassify a build.
|
|
15
15
|
*/
|
|
16
|
+
import { type KeyState, type LiveActivityKind, type LiveRecord, type LiveRecorderOptions } from "./live-records.js";
|
|
16
17
|
export declare const LIVE_LINE_CAP: number;
|
|
17
18
|
export declare const LIVE_FILE_CAP: number;
|
|
18
19
|
export declare const LIVE_CAP_MARKER = "[the live view stopped at its size cap \u2014 the run record continues]";
|
|
@@ -23,29 +24,18 @@ export declare const LIVE_RETAIN_MS: number;
|
|
|
23
24
|
export declare const LIVE_FILE_BOUND = 500;
|
|
24
25
|
export declare function liveDir(root: string): string;
|
|
25
26
|
/** The exact filename, from the numeric id and nothing else — no user
|
|
26
|
-
* input is ever parsed into this path.
|
|
27
|
+
* input is ever parsed into this path. Records (`.jsonl`) are what every
|
|
28
|
+
* run writes now; the name is the format. */
|
|
27
29
|
export declare function liveLogPath(root: string, runId: number): string;
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* name, arguments, and metadata never reach the file: a tool named after
|
|
32
|
-
* a secret stays unspoken.
|
|
33
|
-
*/
|
|
34
|
-
export type LiveActivityKind = "session" | "message" | "edit" | "command" | "read" | "search" | "lookup" | "plan" | "delegate" | "tool";
|
|
35
|
-
export declare const LIVE_ACTIVITY_KINDS: readonly LiveActivityKind[];
|
|
30
|
+
/** The plain-text file runs wrote before the live conversation; read until it ages out. */
|
|
31
|
+
export declare function legacyLiveLogPath(root: string, runId: number): string;
|
|
32
|
+
export { LIVE_ACTIVITY_KINDS, type LiveActivityKind } from "./live-records.js";
|
|
36
33
|
/**
|
|
37
34
|
* What one stream event says the agent just did, as one fixed kind: the
|
|
38
35
|
* last-activity line's only input. Never text, names or arguments; an
|
|
39
36
|
* event that says nothing (results, deltas, subagent chatter) is null.
|
|
40
37
|
*/
|
|
41
38
|
export declare function liveActivityKind(event: Record<string, unknown>): LiveActivityKind | null;
|
|
42
|
-
/**
|
|
43
|
-
* One stream event → zero or more display lines, in the fixed vocabulary.
|
|
44
|
-
* Assistant TEXT is the agent's own words (sanitized below); tool use is a
|
|
45
|
-
* headline; everything else — tool results, deltas, results, subagent
|
|
46
|
-
* chatter — renders nothing in v1.
|
|
47
|
-
*/
|
|
48
|
-
export declare function renderTranscriptLines(event: Record<string, unknown>): string[];
|
|
49
39
|
/** Sanitize one display line: strip controls and bidi overrides, redact whole on any secret hit, cap. */
|
|
50
40
|
export declare function sanitizeTranscriptLine(line: string): string;
|
|
51
41
|
export type LiveLog = {
|
|
@@ -53,31 +43,52 @@ export type LiveLog = {
|
|
|
53
43
|
close(): void;
|
|
54
44
|
};
|
|
55
45
|
/**
|
|
56
|
-
* Open the run's live file for appending. The directory is 0700,
|
|
57
|
-
* 0600 and CREATED HERE (O_EXCL: a name that already exists —
|
|
58
|
-
* it there — is refused, not appended to), opened O_NOFOLLOW
|
|
59
|
-
* descriptor retained for the run's whole duration.
|
|
60
|
-
*
|
|
46
|
+
* Open the run's live file for appending records. The directory is 0700,
|
|
47
|
+
* the file 0600 and CREATED HERE (O_EXCL: a name that already exists —
|
|
48
|
+
* whatever put it there — is refused, not appended to), opened O_NOFOLLOW
|
|
49
|
+
* with the descriptor retained for the run's whole duration. `options` is
|
|
50
|
+
* the run's trusted context: its checkout, and whether its project shows
|
|
51
|
+
* commands (read once, here). Returns null on any failure: no live view is
|
|
52
|
+
* ever worth a build.
|
|
61
53
|
*/
|
|
62
|
-
export declare function openLiveLog(root: string, runId: number): LiveLog | null;
|
|
54
|
+
export declare function openLiveLog(root: string, runId: number, options?: Partial<LiveRecorderOptions>): LiveLog | null;
|
|
55
|
+
export type LiveFormat = "records" | "text";
|
|
63
56
|
export type LiveWindowRead = {
|
|
64
57
|
ok: true;
|
|
58
|
+
/** Complete lines read from `from`: records (JSON lines) or legacy text. */
|
|
65
59
|
text: string;
|
|
66
60
|
nextOffset: number;
|
|
67
61
|
eof: boolean;
|
|
62
|
+
format: LiveFormat;
|
|
63
|
+
/** Which file this offset belongs to: a client holding another resets. */
|
|
64
|
+
gen: string;
|
|
68
65
|
} | {
|
|
69
66
|
ok: false;
|
|
70
67
|
reason: "missing" | "replaced" | "unreadable";
|
|
71
68
|
};
|
|
72
69
|
/**
|
|
73
70
|
* Read the live file from a byte offset, returning only COMPLETE lines
|
|
74
|
-
* (through the last LF in the window). The
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
71
|
+
* (through the last LF in the window). The records file is read when it
|
|
72
|
+
* exists, else the legacy text file. The descriptor is the authority:
|
|
73
|
+
* opened O_NOFOLLOW | O_NONBLOCK inside a real live directory, proved a
|
|
74
|
+
* regular file, measured and read through itself. A file smaller than the
|
|
75
|
+
* offset was replaced — the caller resets, visibly, and `gen` names the file
|
|
76
|
+
* so an offset is never reused against another one. A line longer than the
|
|
77
|
+
* whole window is skipped through its end, so a reader never stalls.
|
|
78
|
+
* `allowTail` (the final drain) returns the unterminated tail after
|
|
79
|
+
* finalization. Legacy text is cleaned again on the way out.
|
|
79
80
|
*/
|
|
80
81
|
export declare function readLiveWindow(root: string, runId: number, from: number, allowTail?: boolean): LiveWindowRead;
|
|
82
|
+
/** A window's complete lines as the plain words the run page and `toolroll peek` show, whatever its format. */
|
|
83
|
+
export declare function liveWindowLines(read: {
|
|
84
|
+
text: string;
|
|
85
|
+
format: LiveFormat;
|
|
86
|
+
}, keys?: KeyState): string[];
|
|
87
|
+
/** A window as records, whatever its format: an older plain file's lines become the agent's words. */
|
|
88
|
+
export declare function liveWindowRecords(read: {
|
|
89
|
+
text: string;
|
|
90
|
+
format: LiveFormat;
|
|
91
|
+
}, keys?: KeyState): LiveRecord[];
|
|
81
92
|
export type LiveSweepVerdict = {
|
|
82
93
|
/** run id, or null when the name is not a run's file. */
|
|
83
94
|
runId: number | null;
|
package/dist/live.js
CHANGED
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
* Fail-soft everywhere: a live view that cannot be written must never
|
|
14
14
|
* break, slow, or reclassify a build.
|
|
15
15
|
*/
|
|
16
|
-
import { closeSync, constants, fstatSync, mkdirSync, openSync, readSync, readdirSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
16
|
+
import { closeSync, constants, fstatSync, lstatSync, mkdirSync, openSync, readSync, readdirSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
17
17
|
import { join } from "node:path";
|
|
18
18
|
import { scanForSecrets } from "./evidence.js";
|
|
19
|
+
import { createLiveRecorder, LIVE_CAP_WORDS, parseLiveRecords, redactLiveLines, projectLiveText, serializeLiveRecord } from "./live-records.js";
|
|
19
20
|
export const LIVE_LINE_CAP = 2 * 1024;
|
|
20
|
-
export const LIVE_FILE_CAP =
|
|
21
|
-
export const LIVE_CAP_MARKER =
|
|
21
|
+
export const LIVE_FILE_CAP = 4 * 1024 * 1024;
|
|
22
|
+
export const LIVE_CAP_MARKER = LIVE_CAP_WORDS;
|
|
22
23
|
export const LIVE_REDACTED_LINE = "[a credential-shaped line was redacted]";
|
|
23
24
|
/** Finalized runs keep their live file this long for the final drain. */
|
|
24
25
|
export const LIVE_RETAIN_MS = 24 * 60 * 60 * 1000;
|
|
@@ -28,11 +29,17 @@ export function liveDir(root) {
|
|
|
28
29
|
return join(root, "live");
|
|
29
30
|
}
|
|
30
31
|
/** The exact filename, from the numeric id and nothing else — no user
|
|
31
|
-
* input is ever parsed into this path.
|
|
32
|
+
* input is ever parsed into this path. Records (`.jsonl`) are what every
|
|
33
|
+
* run writes now; the name is the format. */
|
|
32
34
|
export function liveLogPath(root, runId) {
|
|
35
|
+
return join(liveDir(root), `${Math.trunc(runId)}.jsonl`);
|
|
36
|
+
}
|
|
37
|
+
/** The plain-text file runs wrote before the live conversation; read until it ages out. */
|
|
38
|
+
export function legacyLiveLogPath(root, runId) {
|
|
33
39
|
return join(liveDir(root), `${Math.trunc(runId)}.log`);
|
|
34
40
|
}
|
|
35
|
-
export
|
|
41
|
+
export { LIVE_ACTIVITY_KINDS } from "./live-records.js";
|
|
42
|
+
/** The activity line's kinds for known Claude tools (task-activity.ts). */
|
|
36
43
|
const TOOL_KINDS = new Map([
|
|
37
44
|
["Edit", "edit"],
|
|
38
45
|
["Write", "edit"],
|
|
@@ -48,18 +55,6 @@ const TOOL_KINDS = new Map([
|
|
|
48
55
|
["TodoWrite", "plan"],
|
|
49
56
|
["Task", "delegate"],
|
|
50
57
|
]);
|
|
51
|
-
const KIND_HEADLINES = {
|
|
52
|
-
session: "the agent session started",
|
|
53
|
-
message: "",
|
|
54
|
-
edit: "→ editing files",
|
|
55
|
-
command: "→ running a command",
|
|
56
|
-
read: "→ reading the code",
|
|
57
|
-
search: "→ searching the code",
|
|
58
|
-
lookup: "→ looking something up",
|
|
59
|
-
plan: "→ organizing its plan",
|
|
60
|
-
delegate: "→ delegating to a helper",
|
|
61
|
-
tool: "→ using a tool",
|
|
62
|
-
};
|
|
63
58
|
const toolKind = (name) => TOOL_KINDS.get(typeof name === "string" ? name : "") ?? "tool";
|
|
64
59
|
/**
|
|
65
60
|
* What one stream event says the agent just did, as one fixed kind: the
|
|
@@ -119,77 +114,6 @@ function capBytes(text, cap) {
|
|
|
119
114
|
// A cut mid-character decodes with a trailing replacement char — drop it.
|
|
120
115
|
return decoded.endsWith("�") ? decoded.slice(0, -1) : decoded;
|
|
121
116
|
}
|
|
122
|
-
/**
|
|
123
|
-
* One stream event → zero or more display lines, in the fixed vocabulary.
|
|
124
|
-
* Assistant TEXT is the agent's own words (sanitized below); tool use is a
|
|
125
|
-
* headline; everything else — tool results, deltas, results, subagent
|
|
126
|
-
* chatter — renders nothing in v1.
|
|
127
|
-
*/
|
|
128
|
-
export function renderTranscriptLines(event) {
|
|
129
|
-
const type = String(event["type"] ?? "");
|
|
130
|
-
if (type === "system" && String(event["subtype"] ?? "") === "init") {
|
|
131
|
-
return ["the agent session started"];
|
|
132
|
-
}
|
|
133
|
-
// Codex-shaped streams (peek): a thread starts, items complete.
|
|
134
|
-
if (type === "thread.started")
|
|
135
|
-
return ["the agent session started"];
|
|
136
|
-
if (type === "item.completed") {
|
|
137
|
-
const item = event["item"];
|
|
138
|
-
const kind = item === undefined ? "" : String(item["type"] ?? "");
|
|
139
|
-
if (kind === "agent_message") {
|
|
140
|
-
const text = item?.["text"];
|
|
141
|
-
return typeof text === "string" ? text.split("\n").filter(one => one.trim() !== "") : [];
|
|
142
|
-
}
|
|
143
|
-
if (kind === "command_execution")
|
|
144
|
-
return ["→ running a command"];
|
|
145
|
-
if (kind === "file_change")
|
|
146
|
-
return ["→ editing files"];
|
|
147
|
-
if (kind === "web_search")
|
|
148
|
-
return ["→ looking something up"];
|
|
149
|
-
return [];
|
|
150
|
-
}
|
|
151
|
-
// Gemini-shaped streams (peek): whole assistant messages, never deltas.
|
|
152
|
-
if (type === "init")
|
|
153
|
-
return ["the agent session started"];
|
|
154
|
-
if (type === "message" && String(event["role"] ?? "") === "assistant" && event["delta"] !== true) {
|
|
155
|
-
const content = event["content"];
|
|
156
|
-
return typeof content === "string" ? content.split("\n").filter(one => one.trim() !== "") : [];
|
|
157
|
-
}
|
|
158
|
-
if (type === "tool_call" || type === "tool_use") {
|
|
159
|
-
const name = event["name"] ?? event["tool"]?.["name"];
|
|
160
|
-
return [KIND_HEADLINES[toolKind(name)]];
|
|
161
|
-
}
|
|
162
|
-
if (type !== "assistant")
|
|
163
|
-
return [];
|
|
164
|
-
// Top-level only: a subagent's words are not this run's transcript.
|
|
165
|
-
const parent = event["parent_tool_use_id"];
|
|
166
|
-
if (parent !== undefined && parent !== null)
|
|
167
|
-
return [];
|
|
168
|
-
const message = event["message"];
|
|
169
|
-
const content = message?.["content"];
|
|
170
|
-
if (!Array.isArray(content))
|
|
171
|
-
return [];
|
|
172
|
-
const lines = [];
|
|
173
|
-
for (const block of content) {
|
|
174
|
-
if (block === null || typeof block !== "object")
|
|
175
|
-
continue;
|
|
176
|
-
const kind = String(block["type"] ?? "");
|
|
177
|
-
if (kind === "text") {
|
|
178
|
-
const text = block["text"];
|
|
179
|
-
if (typeof text === "string" && text.trim() !== "") {
|
|
180
|
-
for (const one of text.split("\n")) {
|
|
181
|
-
if (one.trim() !== "")
|
|
182
|
-
lines.push(one);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
else if (kind === "tool_use") {
|
|
187
|
-
const name = block["name"];
|
|
188
|
-
lines.push(KIND_HEADLINES[toolKind(name)]);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return lines;
|
|
192
|
-
}
|
|
193
117
|
/** Bidirectional overrides and isolates (U+202A–U+202E, U+2066–U+2069): they can make shown text read differently from what was written. */
|
|
194
118
|
const BIDI_CONTROLS = /[\u202a-\u202e\u2066-\u2069]/g;
|
|
195
119
|
/** Sanitize one display line: strip controls and bidi overrides, redact whole on any secret hit, cap. */
|
|
@@ -200,13 +124,15 @@ export function sanitizeTranscriptLine(line) {
|
|
|
200
124
|
return capBytes(stripped, LIVE_LINE_CAP);
|
|
201
125
|
}
|
|
202
126
|
/**
|
|
203
|
-
* Open the run's live file for appending. The directory is 0700,
|
|
204
|
-
* 0600 and CREATED HERE (O_EXCL: a name that already exists —
|
|
205
|
-
* it there — is refused, not appended to), opened O_NOFOLLOW
|
|
206
|
-
* descriptor retained for the run's whole duration.
|
|
207
|
-
*
|
|
127
|
+
* Open the run's live file for appending records. The directory is 0700,
|
|
128
|
+
* the file 0600 and CREATED HERE (O_EXCL: a name that already exists —
|
|
129
|
+
* whatever put it there — is refused, not appended to), opened O_NOFOLLOW
|
|
130
|
+
* with the descriptor retained for the run's whole duration. `options` is
|
|
131
|
+
* the run's trusted context: its checkout, and whether its project shows
|
|
132
|
+
* commands (read once, here). Returns null on any failure: no live view is
|
|
133
|
+
* ever worth a build.
|
|
208
134
|
*/
|
|
209
|
-
export function openLiveLog(root, runId) {
|
|
135
|
+
export function openLiveLog(root, runId, options = {}) {
|
|
210
136
|
let fd;
|
|
211
137
|
try {
|
|
212
138
|
mkdirSync(liveDir(root), { recursive: true, mode: 0o700 });
|
|
@@ -215,19 +141,20 @@ export function openLiveLog(root, runId) {
|
|
|
215
141
|
catch {
|
|
216
142
|
return null;
|
|
217
143
|
}
|
|
144
|
+
const recorder = createLiveRecorder({ base: options.base ?? null, commands: options.commands === true, ...(options.clock === undefined ? {} : { clock: options.clock }) });
|
|
218
145
|
let written = 0;
|
|
219
146
|
let capped = false;
|
|
220
147
|
let closed = false;
|
|
221
|
-
const append = (
|
|
148
|
+
const append = (record) => {
|
|
222
149
|
if (closed || capped)
|
|
223
150
|
return;
|
|
224
|
-
const payload = Buffer.from(`${
|
|
225
|
-
// The
|
|
226
|
-
const
|
|
227
|
-
if (written + payload.length +
|
|
151
|
+
const payload = Buffer.from(`${serializeLiveRecord(record)}\n`, "utf8");
|
|
152
|
+
// The cap record is RESERVED inside the cap: whatever remains must still fit it.
|
|
153
|
+
const capLine = `${serializeLiveRecord({ k: "cap", at: record.at })}\n`;
|
|
154
|
+
if (written + payload.length + Buffer.byteLength(capLine, "utf8") > LIVE_FILE_CAP) {
|
|
228
155
|
capped = true;
|
|
229
156
|
try {
|
|
230
|
-
writeSync(fd,
|
|
157
|
+
writeSync(fd, capLine);
|
|
231
158
|
}
|
|
232
159
|
catch {
|
|
233
160
|
// Nothing to do: the file simply ends early.
|
|
@@ -248,20 +175,27 @@ export function openLiveLog(root, runId) {
|
|
|
248
175
|
}
|
|
249
176
|
}
|
|
250
177
|
};
|
|
178
|
+
append({ k: "open", at: (options.clock ?? (() => new Date()))().toISOString(), detail: options.commands === true ? "commands" : "base" });
|
|
251
179
|
return {
|
|
252
180
|
observe(event) {
|
|
253
181
|
try {
|
|
254
|
-
for (const
|
|
255
|
-
append(
|
|
256
|
-
}
|
|
182
|
+
for (const record of recorder.observe(event))
|
|
183
|
+
append(record);
|
|
257
184
|
}
|
|
258
185
|
catch {
|
|
259
|
-
//
|
|
186
|
+
// Recording is observational; a malformed event records nothing.
|
|
260
187
|
}
|
|
261
188
|
},
|
|
262
189
|
close() {
|
|
263
190
|
if (closed)
|
|
264
191
|
return;
|
|
192
|
+
try {
|
|
193
|
+
for (const record of recorder.end())
|
|
194
|
+
append(record);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// the steps simply stay open in the file
|
|
198
|
+
}
|
|
265
199
|
closed = true;
|
|
266
200
|
try {
|
|
267
201
|
closeSync(fd);
|
|
@@ -274,28 +208,64 @@ export function openLiveLog(root, runId) {
|
|
|
274
208
|
}
|
|
275
209
|
const READ_WINDOW = 64 * 1024;
|
|
276
210
|
const READ_LOOKAHEAD = 2 * 1024;
|
|
211
|
+
/** How far past an over-long line one read looks for its end; past it, the line is skipped up to there. */
|
|
212
|
+
const SKIP_SCAN = 64 * 1024 * 1024;
|
|
213
|
+
/** The live directory itself: a real directory, never a link to one. */
|
|
214
|
+
function liveDirIsReal(root) {
|
|
215
|
+
try {
|
|
216
|
+
const stat = lstatSync(liveDir(root));
|
|
217
|
+
return stat.isDirectory() && !stat.isSymbolicLink();
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function openForRead(path) {
|
|
224
|
+
try {
|
|
225
|
+
return { fd: openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK) };
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
return error.code === "ENOENT" ? { missing: true } : { unreadable: true };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/** The line that stands in for one too long to read, in the file's own format. */
|
|
232
|
+
function cutLine(format) {
|
|
233
|
+
return format === "records" ? `${serializeLiveRecord({ k: "cut", at: "" })}\n` : "[a line was too long to show]\n";
|
|
234
|
+
}
|
|
277
235
|
/**
|
|
278
236
|
* Read the live file from a byte offset, returning only COMPLETE lines
|
|
279
|
-
* (through the last LF in the window). The
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
237
|
+
* (through the last LF in the window). The records file is read when it
|
|
238
|
+
* exists, else the legacy text file. The descriptor is the authority:
|
|
239
|
+
* opened O_NOFOLLOW | O_NONBLOCK inside a real live directory, proved a
|
|
240
|
+
* regular file, measured and read through itself. A file smaller than the
|
|
241
|
+
* offset was replaced — the caller resets, visibly, and `gen` names the file
|
|
242
|
+
* so an offset is never reused against another one. A line longer than the
|
|
243
|
+
* whole window is skipped through its end, so a reader never stalls.
|
|
244
|
+
* `allowTail` (the final drain) returns the unterminated tail after
|
|
245
|
+
* finalization. Legacy text is cleaned again on the way out.
|
|
284
246
|
*/
|
|
285
247
|
export function readLiveWindow(root, runId, from, allowTail = false) {
|
|
286
248
|
if (!Number.isSafeInteger(from) || from < 0)
|
|
287
249
|
return { ok: false, reason: "unreadable" };
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
250
|
+
if (!liveDirIsReal(root))
|
|
251
|
+
return { ok: false, reason: "missing" };
|
|
252
|
+
let format = "records";
|
|
253
|
+
let opened = openForRead(liveLogPath(root, runId));
|
|
254
|
+
if ("missing" in opened) {
|
|
255
|
+
format = "text";
|
|
256
|
+
opened = openForRead(legacyLiveLogPath(root, runId));
|
|
294
257
|
}
|
|
258
|
+
if ("missing" in opened)
|
|
259
|
+
return { ok: false, reason: "missing" };
|
|
260
|
+
if ("unreadable" in opened)
|
|
261
|
+
return { ok: false, reason: "unreadable" };
|
|
262
|
+
const fd = opened.fd;
|
|
295
263
|
try {
|
|
296
|
-
const stat = fstatSync(fd);
|
|
264
|
+
const stat = fstatSync(fd, { bigint: true });
|
|
297
265
|
if (!stat.isFile())
|
|
298
266
|
return { ok: false, reason: "unreadable" };
|
|
267
|
+
// Linux hands a removed file's inode straight to the next one made, so the birth time (ns) tells them apart too.
|
|
268
|
+
const gen = `${format}:${stat.dev}:${stat.ino}:${stat.birthtimeNs}`;
|
|
299
269
|
const size = Number(stat.size);
|
|
300
270
|
if (size < from)
|
|
301
271
|
return { ok: false, reason: "replaced" };
|
|
@@ -311,17 +281,44 @@ export function readLiveWindow(root, runId, from, allowTail = false) {
|
|
|
311
281
|
const chunk = buffer.subarray(0, offset);
|
|
312
282
|
const lastLf = chunk.lastIndexOf(0x0a);
|
|
313
283
|
const eofReached = from + offset >= size;
|
|
284
|
+
const out = (text, next, eof) => ({
|
|
285
|
+
ok: true,
|
|
286
|
+
// Raw: every reader cleans and redacts through liveWindowLines / liveWindowRecords, carrying the key state.
|
|
287
|
+
text,
|
|
288
|
+
nextOffset: next,
|
|
289
|
+
eof,
|
|
290
|
+
format,
|
|
291
|
+
gen,
|
|
292
|
+
});
|
|
314
293
|
if (lastLf === -1) {
|
|
315
|
-
if (allowTail && eofReached && offset > 0)
|
|
316
|
-
return
|
|
294
|
+
if (allowTail && eofReached && offset > 0)
|
|
295
|
+
return out(chunk.toString("utf8"), from + offset, true);
|
|
296
|
+
// A whole window without an end of line: skip through its end (bounded), never stall on it.
|
|
297
|
+
if (offset === READ_WINDOW + READ_LOOKAHEAD) {
|
|
298
|
+
const scan = Buffer.alloc(64 * 1024);
|
|
299
|
+
const limit = Math.min(size, from + SKIP_SCAN);
|
|
300
|
+
let at = from + offset;
|
|
301
|
+
while (at < limit) {
|
|
302
|
+
const read = readSync(fd, scan, 0, Math.min(scan.length, limit - at), at);
|
|
303
|
+
if (read <= 0)
|
|
304
|
+
break;
|
|
305
|
+
const lf = scan.subarray(0, read).indexOf(0x0a);
|
|
306
|
+
if (lf !== -1)
|
|
307
|
+
return { ok: true, text: cutLine(format), nextOffset: at + lf + 1, eof: at + lf + 1 >= size, format, gen };
|
|
308
|
+
at += read;
|
|
309
|
+
}
|
|
310
|
+
// No end within reach. A finished run's drain, or a line longer than any read looks, is cut where the
|
|
311
|
+
// look stopped, so reading always moves on; a live run's line may still be being written, so it waits.
|
|
312
|
+
if (allowTail || at >= from + SKIP_SCAN)
|
|
313
|
+
return { ok: true, text: cutLine(format), nextOffset: at, eof: at >= size, format, gen };
|
|
314
|
+
return { ok: true, text: "", nextOffset: from, eof: false, format, gen };
|
|
317
315
|
}
|
|
318
|
-
return
|
|
319
|
-
}
|
|
320
|
-
if (allowTail && eofReached && lastLf + 1 < offset) {
|
|
321
|
-
return { ok: true, text: chunk.toString("utf8"), nextOffset: from + offset, eof: true };
|
|
316
|
+
return out("", from, eofReached && offset === 0);
|
|
322
317
|
}
|
|
318
|
+
if (allowTail && eofReached && lastLf + 1 < offset)
|
|
319
|
+
return out(chunk.toString("utf8"), from + offset, true);
|
|
323
320
|
const complete = chunk.subarray(0, lastLf + 1);
|
|
324
|
-
return
|
|
321
|
+
return out(complete.toString("utf8"), from + lastLf + 1, from + lastLf + 1 >= size);
|
|
325
322
|
}
|
|
326
323
|
catch {
|
|
327
324
|
return { ok: false, reason: "unreadable" };
|
|
@@ -330,6 +327,27 @@ export function readLiveWindow(root, runId, from, allowTail = false) {
|
|
|
330
327
|
closeSync(fd);
|
|
331
328
|
}
|
|
332
329
|
}
|
|
330
|
+
/** A window's complete lines as the plain words the run page and `toolroll peek` show, whatever its format. */
|
|
331
|
+
export function liveWindowLines(read, keys = { inKey: false }) {
|
|
332
|
+
if (read.format === "records")
|
|
333
|
+
return projectLiveText(parseLiveRecords(read.text, keys));
|
|
334
|
+
return cleanLegacy(read.text, keys).split("\n").filter(one => one !== "");
|
|
335
|
+
}
|
|
336
|
+
/** A window as records, whatever its format: an older plain file's lines become the agent's words. */
|
|
337
|
+
export function liveWindowRecords(read, keys = { inKey: false }) {
|
|
338
|
+
if (read.format === "records")
|
|
339
|
+
return parseLiveRecords(read.text, keys);
|
|
340
|
+
return cleanLegacy(read.text, keys).split("\n").filter(one => one !== "").map(line => ({ k: "say", at: "", t: [line] }));
|
|
341
|
+
}
|
|
342
|
+
/** Legacy text lines, cleaned again on read: the file may have been altered after it was written. */
|
|
343
|
+
function cleanLegacy(text, keys) {
|
|
344
|
+
const lines = text.split("\n");
|
|
345
|
+
const ended = lines.length > 0 && lines[lines.length - 1] === "";
|
|
346
|
+
if (ended)
|
|
347
|
+
lines.pop();
|
|
348
|
+
const shown = redactLiveLines(lines, keys);
|
|
349
|
+
return ended ? `${shown.join("\n")}\n` : shown.join("\n");
|
|
350
|
+
}
|
|
333
351
|
/**
|
|
334
352
|
* Enumerate the live directory for the reconcile sweep. Pure listing — the
|
|
335
353
|
* CALLER decides which runs are finalized and when; this module only
|
|
@@ -353,7 +371,7 @@ export function listLiveFiles(root) {
|
|
|
353
371
|
catch {
|
|
354
372
|
continue;
|
|
355
373
|
}
|
|
356
|
-
const match = /^(\d{1,15})\.log$/.exec(name);
|
|
374
|
+
const match = /^(\d{1,15})\.(?:jsonl|log)$/.exec(name);
|
|
357
375
|
out.push({ runId: match === null ? null : Number(match[1]), fileName: name, mtimeMs });
|
|
358
376
|
}
|
|
359
377
|
return out;
|
package/dist/mcp-connect.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ProjectTool, type ToolSpec } from "./project-tools.js";
|
|
2
2
|
import type { Store } from "./store.js";
|
|
3
|
+
import { readScope, scopeList } from "./oauth-run-token.js";
|
|
4
|
+
export { readScope, scopeList };
|
|
3
5
|
/**
|
|
4
6
|
* A one-click service. `reads` names what a research step may read there:
|
|
5
7
|
* an action is read-only only when it is named by a reading verb (READING)
|
|
@@ -63,10 +65,7 @@ export declare function connectionsOf(store: Store, repo: string, home?: string)
|
|
|
63
65
|
* research read. An allow-list: a word nobody listed withholds the action.
|
|
64
66
|
*/
|
|
65
67
|
export declare function readsOnly(action: string, subjects: readonly string[]): boolean;
|
|
66
|
-
export declare const readScope: (scope: string) => boolean;
|
|
67
68
|
export declare const readOnlyGrant: (grant: readonly string[] | null) => boolean;
|
|
68
|
-
/** An OAuth `scope` value as scope tokens (RFC 6749), sorted and deduplicated; null when absent, empty or malformed. */
|
|
69
|
-
export declare function scopeList(value: unknown): string[] | null;
|
|
70
69
|
/** The scope a connected service's sign-in was granted, as saved beside its token; null when it was never proved. */
|
|
71
70
|
export declare function grantOf(repo: string, tool: string, home?: string): string[] | null;
|
|
72
71
|
/**
|
|
@@ -98,6 +97,7 @@ type Server = {
|
|
|
98
97
|
register: string;
|
|
99
98
|
scopes: string[];
|
|
100
99
|
resource: string | null;
|
|
100
|
+
revoke: string | null;
|
|
101
101
|
};
|
|
102
102
|
/** A sign-in on its way: what the callback needs to finish it (kept in the console's memory, 15 minutes). `kit` or `template` is the page it returns to. */
|
|
103
103
|
export type ConnectVisit = {
|
|
@@ -115,6 +115,8 @@ export type ConnectVisit = {
|
|
|
115
115
|
expires: number;
|
|
116
116
|
/** The scope asked for, when one was: the grant when the token answer leaves `scope` out (RFC 6749 §5.1). */
|
|
117
117
|
scope?: string | null;
|
|
118
|
+
/** Where the service revokes a token, when its metadata said: a run's own token is revoked there when the run ends. */
|
|
119
|
+
revoke?: string | null;
|
|
118
120
|
};
|
|
119
121
|
/** A server's sign-in: the resource metadata its 401 names (or the well-known one), then its authorization server's metadata. */
|
|
120
122
|
export declare function discoverSignIn(mcpUrl: string, fetcher?: Fetch): Promise<Server | null>;
|
|
@@ -145,11 +147,11 @@ export declare function connectedSpec(serviceId: string): ToolSpec | null;
|
|
|
145
147
|
/**
|
|
146
148
|
* Finish connecting: trade the code for tokens, add the tool to the project
|
|
147
149
|
* (or refresh its sign-in, when it's there already), keep the tokens in its
|
|
148
|
-
* secrets
|
|
150
|
+
* secrets, and test it.
|
|
149
151
|
*/
|
|
150
152
|
export declare function finishConnect(store: Store, visit: ConnectVisit, code: string, now: Date, options?: {
|
|
151
153
|
fetcher?: Fetch;
|
|
152
|
-
home?: string;
|
|
154
|
+
home?: string | undefined;
|
|
153
155
|
test?: boolean;
|
|
154
156
|
omitEnv?: readonly string[];
|
|
155
157
|
}): Promise<{
|
|
@@ -162,9 +164,8 @@ export declare function finishConnect(store: Store, visit: ConnectVisit, code: s
|
|
|
162
164
|
/** Keep connected services signed in: any token expiring within ten minutes is refreshed (the worker's pass, and before a subagent's call). */
|
|
163
165
|
export declare function refreshConnections(store: Store, repos: readonly string[], now: Date, options?: {
|
|
164
166
|
fetcher?: Fetch;
|
|
165
|
-
home?: string;
|
|
167
|
+
home?: string | undefined;
|
|
166
168
|
}): Promise<{
|
|
167
169
|
refreshed: number;
|
|
168
170
|
problems: string[];
|
|
169
171
|
}>;
|
|
170
|
-
export {};
|