toolroll 0.9.65 → 0.9.68
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 +93 -0
- package/README.md +20 -2
- package/dist/acp-client.js +1 -3
- package/dist/agent-board.d.ts +0 -1
- package/dist/agent-board.js +0 -1
- package/dist/agent-fence.d.ts +69 -2
- package/dist/agent-fence.js +294 -11
- package/dist/agentconfig.js +4 -1
- package/dist/batch-checks.js +3 -2
- package/dist/browser/THIRD_PARTY_NOTICES.txt +46 -0
- package/dist/browser/terminal.js +134 -23
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +31 -29
- package/dist/builder.d.ts +4 -0
- package/dist/builder.js +56 -37
- package/dist/canonical-json.d.ts +14 -0
- package/dist/canonical-json.js +36 -0
- package/dist/chat-actions.js +1 -2
- package/dist/chat-admission.d.ts +19 -0
- package/dist/chat-admission.js +22 -0
- package/dist/chat-channel.js +1 -1
- package/dist/chat-delivery.js +0 -1
- package/dist/chat-follow.d.ts +17 -0
- package/dist/chat-follow.js +32 -0
- package/dist/chat-messages.js +0 -1
- package/dist/chat-settings-page.d.ts +23 -0
- package/dist/chat-settings-page.js +41 -0
- package/dist/claim.js +3 -6
- package/dist/claude-print.d.ts +12 -0
- package/dist/claude-print.js +34 -0
- package/dist/cli-http.d.ts +0 -7
- package/dist/cli-http.js +0 -21
- package/dist/cli.d.ts +3 -10
- package/dist/cli.js +15 -24
- package/dist/coding-provider.js +2 -1
- package/dist/coding-workspace.js +1 -1
- package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
- package/dist/connect-cli.js +331 -0
- package/dist/containment.d.ts +0 -2
- package/dist/containment.js +2 -6
- package/dist/contracts/chat-actions.d.ts +0 -1
- package/dist/contracts/chat-content.d.ts +0 -4
- package/dist/contracts/chat-content.js +0 -2
- package/dist/contracts/chat-tables.d.ts +0 -1
- package/dist/contracts/cli.d.ts +0 -62
- package/dist/contracts/cli.js +0 -4
- package/dist/contracts/coding-workspace.js +1 -1
- package/dist/contracts/console-api.d.ts +1 -0
- package/dist/contracts/console-api.js +1 -0
- package/dist/contracts/contract.js +1 -1
- package/dist/contracts/flow-card.d.ts +0 -1
- package/dist/contracts/flow-propose.d.ts +0 -1
- package/dist/contracts/flow-send.js +1 -1
- package/dist/contracts/gateway-tools.d.ts +0 -1
- package/dist/contracts/integration-metadata.js +1 -1
- package/dist/contracts/lead-tools.d.ts +0 -1
- package/dist/contracts/memory-pass.d.ts +0 -1
- package/dist/contracts/memory-pass.js +1 -1
- package/dist/contracts/plan.js +1 -1
- package/dist/contracts/project-knowledge.js +1 -1
- package/dist/contracts/project-skills.d.ts +0 -1
- package/dist/contracts/proof.js +1 -1
- package/dist/contracts/recipes.js +1 -1
- package/dist/contracts/scope.js +1 -1
- package/dist/contracts/scout-report.js +1 -1
- package/dist/contracts/teams-callback.d.ts +0 -1
- package/dist/converse.d.ts +0 -6
- package/dist/converse.js +0 -19
- package/dist/daemon.js +3 -2
- package/dist/decision.d.ts +1 -3
- package/dist/deprecations.d.ts +12 -4
- package/dist/deprecations.js +27 -4
- package/dist/desktop-update-recovery.js +1 -1
- package/dist/desktop-update.js +3 -2
- package/dist/discord-chat.js +4 -15
- package/dist/discord-settings.d.ts +2 -6
- package/dist/discord-settings.js +10 -38
- package/dist/discord.js +12 -23
- package/dist/evidence.d.ts +0 -1
- package/dist/evidence.js +0 -3
- package/dist/exec.d.ts +0 -9
- package/dist/exec.js +3 -81
- package/dist/flow-actions.js +0 -3
- package/dist/flow-draft.d.ts +1 -3
- package/dist/flow-draft.js +15 -28
- package/dist/flow-scripts.d.ts +1 -8
- package/dist/flow-scripts.js +0 -13
- package/dist/flow-send.js +1 -1
- package/dist/flow-share.d.ts +0 -2
- package/dist/flow-share.js +1 -6
- package/dist/flow-steps.js +1 -1
- package/dist/flow-triggers.d.ts +0 -1
- package/dist/flow-triggers.js +1 -2
- package/dist/flow-unattended.js +1 -12
- package/dist/flows.js +1 -1
- package/dist/health-cli.d.ts +2 -2
- package/dist/health-cli.js +1 -1
- package/dist/invoke.d.ts +18 -3
- package/dist/invoke.js +142 -17
- package/dist/is-record.d.ts +2 -0
- package/dist/is-record.js +2 -0
- package/dist/lead-doors.d.ts +1 -5
- package/dist/lead-doors.js +0 -4
- package/dist/lead-tools.js +3 -6
- package/dist/live-detail.d.ts +0 -1
- package/dist/live-detail.js +0 -6
- package/dist/live-terminal.d.ts +24 -13
- package/dist/live-terminal.js +81 -43
- package/dist/live.d.ts +0 -1
- package/dist/live.js +1 -2
- package/dist/mcp-core.js +0 -2
- package/dist/memory-pass.js +1 -1
- package/dist/model-catalog.js +1 -1
- package/dist/modes.js +1 -12
- package/dist/operate.d.ts +2 -0
- package/dist/operate.js +436 -745
- package/dist/password-bearer.d.ts +0 -2
- package/dist/password-bearer.js +0 -4
- package/dist/peek-cli.js +2 -1
- package/dist/peek.d.ts +2 -26
- package/dist/peek.js +2 -168
- package/dist/phase-routing.d.ts +0 -4
- package/dist/phase-routing.js +2 -21
- package/dist/planner-source.d.ts +2 -1
- package/dist/planner-source.js +2 -12
- package/dist/planner.js +2 -14
- package/dist/process-tree.d.ts +0 -2
- package/dist/process-tree.js +0 -10
- package/dist/project-delete-ui.d.ts +6 -0
- package/dist/project-delete-ui.js +20 -1
- package/dist/project-delete.d.ts +0 -2
- package/dist/project-delete.js +1 -3
- package/dist/project-learning.d.ts +0 -14
- package/dist/project-skills.d.ts +0 -1
- package/dist/project-skills.js +0 -14
- package/dist/project-tools.js +2 -10
- package/dist/provider.d.ts +0 -17
- package/dist/provider.js +0 -26
- package/dist/pulls.d.ts +0 -2
- package/dist/pulls.js +0 -9
- package/dist/release-adapters.d.ts +9 -0
- package/dist/release-adapters.js +81 -4
- package/dist/release.d.ts +7 -1
- package/dist/release.js +20 -7
- package/dist/remote-exec.d.ts +3 -2
- package/dist/remote-exec.js +3 -2
- package/dist/repos.d.ts +0 -5
- package/dist/repos.js +2 -10
- package/dist/repository-context.d.ts +0 -2
- package/dist/repository-context.js +0 -4
- package/dist/restart-certification.d.ts +0 -2
- package/dist/restart-certification.js +1 -5
- package/dist/result-follow-ups.d.ts +1 -4
- package/dist/result-follow-ups.js +4 -8
- package/dist/result-review.d.ts +0 -2
- package/dist/result-review.js +0 -2
- package/dist/retention.d.ts +0 -1
- package/dist/retention.js +0 -1
- package/dist/review-context.d.ts +0 -1
- package/dist/review-context.js +1 -12
- package/dist/reviewer.d.ts +0 -16
- package/dist/reviewer.js +0 -18
- package/dist/run-closeout.js +2 -1
- package/dist/scope.d.ts +13 -0
- package/dist/scope.js +11 -18
- package/dist/scout-browser.js +2 -1
- package/dist/serve.js +3 -2
- package/dist/server/chrome.d.ts +10 -1
- package/dist/server/chrome.js +45 -4
- package/dist/server/console.css +60 -137
- package/dist/server/flows.js +2 -2
- package/dist/server/http.d.ts +2 -0
- package/dist/server/http.js +5 -0
- package/dist/server/pages.js +2 -2
- package/dist/server/people-tokens.js +3 -4
- package/dist/server/remote.js +1 -6
- package/dist/server/render-chat.d.ts +9 -2
- package/dist/server/render-chat.js +53 -7
- package/dist/server/render-pages.d.ts +28 -3
- package/dist/server/render-pages.js +78 -9
- package/dist/server/render-results.d.ts +0 -6
- package/dist/server/render-results.js +3 -9
- package/dist/server/render-tasks.js +6 -6
- package/dist/server/route-table.d.ts +0 -4
- package/dist/server/route-table.js +1 -6
- package/dist/server/settings.js +43 -22
- package/dist/server/task-views.js +1 -1
- package/dist/server/tasks.js +10 -7
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills.d.ts +0 -6
- package/dist/skills.js +0 -8
- package/dist/slack-chat.d.ts +1 -7
- package/dist/slack-chat.js +5 -18
- package/dist/slack-settings.d.ts +2 -6
- package/dist/slack-settings.js +10 -38
- package/dist/slack.js +12 -23
- package/dist/sleep.d.ts +2 -0
- package/dist/sleep.js +2 -0
- package/dist/store.d.ts +11 -74
- package/dist/store.js +36 -179
- package/dist/structured-output.d.ts +0 -1
- package/dist/structured-output.js +0 -1
- package/dist/subagent-work.d.ts +0 -2
- package/dist/subagent-work.js +0 -2
- package/dist/subagents.d.ts +1 -3
- package/dist/subagents.js +20 -33
- package/dist/subscription-chat.d.ts +1 -3
- package/dist/subscription-chat.js +2 -3
- package/dist/task-sizing.d.ts +1 -4
- package/dist/task-sizing.js +3 -10
- package/dist/teams-chat.js +4 -11
- package/dist/teams.js +12 -19
- package/dist/teardown-git.d.ts +22 -0
- package/dist/teardown-git.js +136 -2
- package/dist/telegram-lead.js +2 -2
- package/dist/telegram.js +1 -1
- package/dist/token-notices.d.ts +0 -11
- package/dist/token-notices.js +1 -5
- package/dist/tool-broker.d.ts +12 -0
- package/dist/tool-broker.js +66 -2
- package/dist/tool-secret-store.d.ts +0 -3
- package/dist/tool-secret-store.js +2 -11
- package/dist/toolroll-update.d.ts +0 -2
- package/dist/toolroll-update.js +2 -2
- package/dist/unfenced-test-support.d.ts +2 -0
- package/dist/unfenced-test-support.js +11 -0
- package/dist/verification-evidence.d.ts +0 -1
- package/dist/verification-evidence.js +0 -1
- package/dist/webhooks.d.ts +0 -1
- package/dist/webhooks.js +0 -1
- package/dist/workspace-ui.d.ts +0 -8
- package/dist/workspace-ui.js +1 -6
- package/dist/writes-mode.d.ts +9 -0
- package/dist/writes-mode.js +8 -0
- package/package.json +5 -1
- package/dist/contracts/native-census.d.ts +0 -42
- package/dist/contracts/native-census.js +0 -36
- package/dist/process-recovery-anchor.d.ts +0 -75
- package/dist/process-recovery-anchor.js +0 -188
- package/dist/process-recovery-coalition.d.ts +0 -25
- package/dist/process-recovery-coalition.js +0 -105
- package/dist/process-recovery-eligibility.d.ts +0 -179
- package/dist/process-recovery-eligibility.js +0 -174
- package/dist/process-recovery-native.d.ts +0 -161
- package/dist/process-recovery-native.js +0 -595
- package/dist/process-recovery-provenance.d.ts +0 -163
- package/dist/process-recovery-provenance.js +0 -292
- package/dist/process-recovery-services.d.ts +0 -56
- package/dist/process-recovery-services.js +0 -191
- package/dist/process-recovery-settlement.d.ts +0 -32
- package/dist/process-recovery-settlement.js +0 -133
- package/dist/process-recovery.d.ts +0 -41
- package/dist/process-recovery.js +0 -91
- package/dist/session-brief.d.ts +0 -8
- package/dist/session-brief.js +0 -24
- package/dist/session-cli.d.ts +0 -42
- package/dist/session-cli.js +0 -271
- package/dist/session-contract.d.ts +0 -183
- package/dist/session-contract.js +0 -122
- package/dist/session-remote.d.ts +0 -19
- package/dist/session-remote.js +0 -86
- package/dist/session-service.d.ts +0 -22
- package/dist/session-service.js +0 -157
- package/dist/team-cli.js +0 -692
package/dist/tool-broker.js
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
import { spawn } from "node:child_process";
|
|
21
21
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
22
22
|
import { createServer } from "node:http";
|
|
23
|
+
import { accessSync, constants, existsSync, realpathSync } from "node:fs";
|
|
24
|
+
import { delimiter, isAbsolute, resolve, sep } from "node:path";
|
|
23
25
|
const BODY_LIMIT = 4 * 1024 * 1024;
|
|
24
26
|
const ANSWER_LIMIT = 32 * 1024 * 1024;
|
|
25
27
|
const STOP_GRACE_MS = 2_000;
|
|
@@ -59,6 +61,54 @@ export function serverEnv(base, omit, pass, values) {
|
|
|
59
61
|
delete env[name];
|
|
60
62
|
return Object.assign(env, pass, values);
|
|
61
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* The first of a server's command and path-like arguments that resolves inside an untrusted folder (a build's checkout
|
|
66
|
+
* or caches), or null. The command is resolved as spawn would: a path against `cwd`, a bare name through PATH; an
|
|
67
|
+
* argument counts when it names an existing path (relative to `cwd`) or is written as one (`./x`, `../x`, `/x`).
|
|
68
|
+
*/
|
|
69
|
+
export function workspaceBytes(command, args, cwd, path, untrusted) {
|
|
70
|
+
if (untrusted.length === 0)
|
|
71
|
+
return null;
|
|
72
|
+
const base = cwd ?? process.cwd();
|
|
73
|
+
// Canonical on-disk names, folded where the filesystem ignores case (macOS, Windows), so `/Users/a/CHECKOUT` is the checkout.
|
|
74
|
+
const fold = process.platform === "darwin" || process.platform === "win32" ? (one) => one.toLowerCase() : (one) => one;
|
|
75
|
+
const real = (one) => { try {
|
|
76
|
+
return fold(realpathSync.native(one));
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return fold(resolve(one));
|
|
80
|
+
} };
|
|
81
|
+
const roots = untrusted.map(real);
|
|
82
|
+
const within = (one) => { const at = real(one); return roots.some(root => at === root || at.startsWith(`${root}${sep}`)); };
|
|
83
|
+
// A root's name anywhere in an argument (inline code, a list of paths) counts, however it's spelled.
|
|
84
|
+
const mentions = (arg) => { const text = fold(arg); return roots.some(root => text.includes(root)) || untrusted.some(root => text.includes(fold(root))); };
|
|
85
|
+
const located = command.includes("/") || command.includes(sep) ? resolve(base, command)
|
|
86
|
+
: (path ?? "").split(delimiter).filter(Boolean).map(dir => resolve(base, dir, command)).find(one => { try {
|
|
87
|
+
accessSync(one, constants.X_OK);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
} }) ?? null;
|
|
93
|
+
if (located !== null && within(located))
|
|
94
|
+
return located;
|
|
95
|
+
// A relative path once meant "in the checkout" (servers started there): it is refused rather than read elsewhere.
|
|
96
|
+
if (!isAbsolute(command) && (command.includes("/") || command.includes(sep)))
|
|
97
|
+
return `${command} (a relative path)`;
|
|
98
|
+
for (const arg of args) {
|
|
99
|
+
if (mentions(arg))
|
|
100
|
+
return `${arg} (names what this build writes)`;
|
|
101
|
+
// A flag's value (`--config=x`, `-c=x`) is checked as its own argument.
|
|
102
|
+
for (const piece of [arg, ...(arg.startsWith("-") && arg.includes("=") ? [arg.slice(arg.indexOf("=") + 1)] : [])]) {
|
|
103
|
+
if (piece.startsWith("./") || piece.startsWith("../"))
|
|
104
|
+
return `${piece} (a relative path)`;
|
|
105
|
+
const candidate = resolve(base, piece);
|
|
106
|
+
if ((isAbsolute(piece) || existsSync(candidate)) && within(candidate))
|
|
107
|
+
return candidate;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
62
112
|
/** A local server, started on first use and spoken to over its stdin and stdout. */
|
|
63
113
|
class LocalServer {
|
|
64
114
|
tool;
|
|
@@ -68,6 +118,7 @@ class LocalServer {
|
|
|
68
118
|
buffer = "";
|
|
69
119
|
next = 1;
|
|
70
120
|
pending = new Map();
|
|
121
|
+
refusal = null;
|
|
71
122
|
constructor(tool, options) {
|
|
72
123
|
this.tool = tool;
|
|
73
124
|
this.options = options;
|
|
@@ -75,7 +126,19 @@ class LocalServer {
|
|
|
75
126
|
pid() { return this.child?.pid ?? null; }
|
|
76
127
|
start() {
|
|
77
128
|
const env = serverEnv(this.options.env ?? process.env, this.options.omitEnv ?? [], this.options.pass ?? {}, this.tool.values);
|
|
129
|
+
const planted = workspaceBytes(this.tool.spec.command, this.tool.spec.args, this.options.cwd, env["PATH"], this.options.untrusted ?? []);
|
|
130
|
+
if (planted !== null) {
|
|
131
|
+
this.refusal = `The tool's server would run ${planted}, inside what this build can write, so it was not started.`;
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
78
134
|
const wrap = this.options.wrap?.() ?? null;
|
|
135
|
+
if (wrap === null) {
|
|
136
|
+
const why = this.options.unwrapped?.() ?? null;
|
|
137
|
+
if (why !== null) {
|
|
138
|
+
this.refusal = why;
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
79
142
|
const { file, args } = wrap === null ? { file: this.tool.spec.command, args: [...this.tool.spec.args] } : wrap(this.tool.spec.command, this.tool.spec.args);
|
|
80
143
|
const child = spawn(file, args, { env, ...(this.options.cwd === undefined ? {} : { cwd: this.options.cwd }), stdio: ["pipe", "pipe", "ignore"], detached: process.platform !== "win32" });
|
|
81
144
|
this.child = child;
|
|
@@ -131,8 +194,9 @@ class LocalServer {
|
|
|
131
194
|
// A new session (a reconnect) starts a fresh server: a server answers initialize once.
|
|
132
195
|
if (message.method === "initialize" && this.initialized)
|
|
133
196
|
this.stop();
|
|
134
|
-
if (this.child === null)
|
|
135
|
-
this.start
|
|
197
|
+
if (this.child === null && this.start() === null) {
|
|
198
|
+
return Promise.resolve(isRequest(message) ? rpcError(message.id, this.refusal ?? "The tool could not start.") : null);
|
|
199
|
+
}
|
|
136
200
|
if (message.method === "initialize")
|
|
137
201
|
this.initialized = true;
|
|
138
202
|
if (!isRequest(message)) {
|
|
@@ -56,7 +56,6 @@ export declare function detectSecretStore(options?: {
|
|
|
56
56
|
export declare function chooseSecretStore(store: SecretBackend | "files" | DetectedStore | null): void;
|
|
57
57
|
/** This computer's store (found once), or null for owner-only files. */
|
|
58
58
|
export declare function secretBackend(env?: NodeJS.ProcessEnv): SecretBackend | null;
|
|
59
|
-
export declare const secretStoreKind: () => SecretStoreKind;
|
|
60
59
|
/** Where secrets rest, in the words Settings and `toolroll integrations` share; `problem` when Toolroll's folder can't be used. */
|
|
61
60
|
export declare function secretStorage(): {
|
|
62
61
|
kind: SecretStoreKind;
|
|
@@ -166,5 +165,3 @@ export declare function writeSealed(backend: SecretBackend, folder: SecretFolder
|
|
|
166
165
|
export declare function readHeldSecret(state: string, name: string, file: readonly string[]): string | null;
|
|
167
166
|
/** Keep (or, with null, remove) a held secret: see readHeldSecret. */
|
|
168
167
|
export declare function writeHeldSecret(state: string, name: string, file: readonly string[], value: string | null): void;
|
|
169
|
-
/** Whether a held secret has a value, without reading it where that can be helped. */
|
|
170
|
-
export declare function heldSecretSet(state: string, name: string, file: readonly string[]): boolean;
|
|
@@ -32,6 +32,7 @@ import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:
|
|
|
32
32
|
import { closeSync, constants, fstatSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
33
33
|
import { dirname, join } from "node:path";
|
|
34
34
|
import { envValue } from "./names.js";
|
|
35
|
+
import { sleep } from "./sleep.js";
|
|
35
36
|
export class SecretStoreError extends Error {
|
|
36
37
|
}
|
|
37
38
|
/** The words Settings and `toolroll integrations` use for where secrets rest. */
|
|
@@ -200,7 +201,6 @@ function currentStore(env) {
|
|
|
200
201
|
export function secretBackend(env = process.env) {
|
|
201
202
|
return currentStore(env).backend;
|
|
202
203
|
}
|
|
203
|
-
export const secretStoreKind = () => secretBackend()?.kind ?? "files";
|
|
204
204
|
/** Where secrets rest, in the words Settings and `toolroll integrations` share; `problem` when Toolroll's folder can't be used. */
|
|
205
205
|
export function secretStorage() {
|
|
206
206
|
const found = currentStore(process.env);
|
|
@@ -701,7 +701,7 @@ export async function withSecretLockAsync(folder, name, work, options = {}) {
|
|
|
701
701
|
while (!takeLock(lock, options.staleMs ?? 120_000)) {
|
|
702
702
|
if (Date.now() - started > (options.waitMs ?? 120_000))
|
|
703
703
|
throw new SecretStoreError("A sign-in is being renewed elsewhere. Try again in a moment.");
|
|
704
|
-
await
|
|
704
|
+
await sleep(25);
|
|
705
705
|
}
|
|
706
706
|
try {
|
|
707
707
|
return await work();
|
|
@@ -823,12 +823,3 @@ export function writeHeldSecret(state, name, file, value) {
|
|
|
823
823
|
writeSealed(backend, folder, item, value);
|
|
824
824
|
});
|
|
825
825
|
}
|
|
826
|
-
/** Whether a held secret has a value, without reading it where that can be helped. */
|
|
827
|
-
export function heldSecretSet(state, name, file) {
|
|
828
|
-
try {
|
|
829
|
-
return readHeldSecret(state, name, file) !== null;
|
|
830
|
-
}
|
|
831
|
-
catch {
|
|
832
|
-
return false;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
@@ -162,7 +162,6 @@ export type StartOptions = {
|
|
|
162
162
|
/** An older version replaces the current one only when asked for by name. */
|
|
163
163
|
allowDowngrade?: boolean;
|
|
164
164
|
};
|
|
165
|
-
declare function nextAt(hhmm: string, now: Date): Date;
|
|
166
165
|
/** Record an update without running it: the console's job resumes exactly this journal id. */
|
|
167
166
|
export declare function prepareRuntimeUpdate(o: StartOptions, now: Date): RuntimeUpdateJournal | {
|
|
168
167
|
refused: string;
|
|
@@ -257,4 +256,3 @@ export declare function launchRuntimeUpdate(args: {
|
|
|
257
256
|
}): Promise<void>;
|
|
258
257
|
/** The job's last act: its definition goes, so nothing can start it again. Only the definition for this id. */
|
|
259
258
|
export declare function retireUpdateJob(id: string, home?: string): void;
|
|
260
|
-
export declare const nextScheduledAt: typeof nextAt;
|
package/dist/toolroll-update.js
CHANGED
|
@@ -40,6 +40,7 @@ import { orphanKey, updateSafeSchema, V117_RENAMED_COLUMNS, V117_RENAMED_TABLES,
|
|
|
40
40
|
import { isNewer, REGISTRY } from "./releases.js";
|
|
41
41
|
import { markNeverIndex } from "./never-index.js";
|
|
42
42
|
import { readRuntimeUpdateJournal, RUNTIME_PHASES, RUNTIME_UPDATE_STEPS, stagedStartedAt, updaterStartingOf } from "./contracts/update-journal.js";
|
|
43
|
+
import { sleep } from "./sleep.js";
|
|
43
44
|
/** Loaded on first use (as backup.ts and store.ts do), so modules that only import this one (the console,
|
|
44
45
|
* and tests that load it in a browser-like environment) never need `node:sqlite` itself. */
|
|
45
46
|
function sqlite() {
|
|
@@ -1583,7 +1584,7 @@ export function machineSystem(home = homedir(), env = process.env, seams = {}) {
|
|
|
1583
1584
|
};
|
|
1584
1585
|
return {
|
|
1585
1586
|
now: () => new Date(),
|
|
1586
|
-
sleep
|
|
1587
|
+
sleep,
|
|
1587
1588
|
release: async (version) => {
|
|
1588
1589
|
const body = await json(`${REGISTRY}/${NAME}/${version}`);
|
|
1589
1590
|
return { version: String(body.version ?? ""), tarball: String(body.dist?.tarball ?? ""), integrity: String(body.dist?.integrity ?? ""), attestations: body.dist?.attestations?.url ?? null };
|
|
@@ -1805,4 +1806,3 @@ export function retireUpdateJob(id, home = homedir()) {
|
|
|
1805
1806
|
}
|
|
1806
1807
|
catch { /* none */ }
|
|
1807
1808
|
}
|
|
1808
|
-
export const nextScheduledAt = nextAt;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests that run real commands on a machine with no OS fence (CI's Ubuntu runners, where unprivileged namespaces are
|
|
3
|
+
* off) allow unconfined agents on their own store, as an instance operator there would; anywhere a fence exists,
|
|
4
|
+
* nothing changes and the fence is what the test runs under.
|
|
5
|
+
*/
|
|
6
|
+
import { linuxFenceAvailable, macosFenceAvailable } from "./agent-fence.js";
|
|
7
|
+
export function allowWhereUnfenced(store) {
|
|
8
|
+
if (!macosFenceAvailable() && !linuxFenceAvailable())
|
|
9
|
+
store.setUnfencedAgentsAllowed(true, "test", new Date(0));
|
|
10
|
+
return store;
|
|
11
|
+
}
|
|
@@ -2,7 +2,6 @@ import type { Artifact, Store, VerifyCommand } from "./store.js";
|
|
|
2
2
|
import type { VerifyCommandFacts } from "./proof.js";
|
|
3
3
|
import { type AdjudicateResult } from "./proof.js";
|
|
4
4
|
export declare const VERIFICATION_RECEIPT_CAPTURE = "machine verification receipt v1";
|
|
5
|
-
export declare const REVIEW_GATE_NAME = "REVIEW-VERIFICATION.json";
|
|
6
5
|
export declare const isVerificationReceipt: (a: Artifact) => boolean;
|
|
7
6
|
export declare function sealVerificationReceipt(store: Store, root: string, runId: number, head: string, command: VerifyCommand, result: VerifyCommandFacts, now: Date, reusedFrom?: {
|
|
8
7
|
run: number;
|
|
@@ -12,7 +12,6 @@ import { LEGACY_GATE_SOURCE, readVerificationView } from "./contracts/verificati
|
|
|
12
12
|
import { readCandidateEndpoints, savedInventoryPaths } from "./contracts/diff-stat.js";
|
|
13
13
|
import { liveQuickCommand, quickVerifyKey, runCheckLevel } from "./check-levels.js";
|
|
14
14
|
export const VERIFICATION_RECEIPT_CAPTURE = "machine verification receipt v1";
|
|
15
|
-
export const REVIEW_GATE_NAME = "REVIEW-VERIFICATION.json";
|
|
16
15
|
const hash = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
17
16
|
const binding = (a) => ({ artifactId: a.id, sha256: a.sha256, bytesStored: a.bytesStored, bytesOriginal: a.bytesOriginal, truncated: a.truncated, redacted: a.redacted, captureStatus: a.captureStatus });
|
|
18
17
|
export const isVerificationReceipt = (a) => a.kind === "structured-output" && (a.capture === VERIFICATION_RECEIPT_CAPTURE || a.capture === "machine verification reuse v1");
|
package/dist/webhooks.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ export type WebhookTarget = {
|
|
|
6
6
|
};
|
|
7
7
|
export declare const LEGACY_WEBHOOK_WARNING = "Legacy webhooks are deprecated. Connect Slack or Discord in Chat settings.";
|
|
8
8
|
export declare const CONSOLE_URL_ENV = "TOOLROLL_CONSOLE_URL";
|
|
9
|
-
export declare const PRIMARY_ENV = "TOOLROLL_MESSAGING_PRIMARY";
|
|
10
9
|
export type MessagingChannel = "telegram" | "slack" | "discord" | "teams";
|
|
11
10
|
export declare const MESSAGING_CHANNELS: readonly MessagingChannel[];
|
|
12
11
|
export declare function isMessagingChannel(value: string): value is MessagingChannel;
|
package/dist/webhooks.js
CHANGED
|
@@ -17,7 +17,6 @@ const FILE_OF = { slack: "slack-webhook", discord: "discord-webhook" };
|
|
|
17
17
|
const POST_TIMEOUT_MS = 10_000;
|
|
18
18
|
export const LEGACY_WEBHOOK_WARNING = "Legacy webhooks are deprecated. Connect Slack or Discord in Chat settings.";
|
|
19
19
|
export const CONSOLE_URL_ENV = "TOOLROLL_CONSOLE_URL";
|
|
20
|
-
export const PRIMARY_ENV = "TOOLROLL_MESSAGING_PRIMARY";
|
|
21
20
|
const CONSOLE_FILE = "console-url";
|
|
22
21
|
const PRIMARY_FILE = "messaging-primary";
|
|
23
22
|
export const MESSAGING_CHANNELS = ["telegram", "slack", "discord", "teams"];
|
package/dist/workspace-ui.d.ts
CHANGED
|
@@ -261,14 +261,6 @@ export declare function workStatusOf(facts: WorkFacts, resultDisplay?: DisplaySt
|
|
|
261
261
|
export declare function workCounts(rows: readonly {
|
|
262
262
|
views: readonly WorkView[];
|
|
263
263
|
}[]): Record<WorkView, number>;
|
|
264
|
-
/** All's order: rank, then most recently updated. */
|
|
265
|
-
export declare function compareWorkRows(a: {
|
|
266
|
-
rank: number;
|
|
267
|
-
updatedAt: string;
|
|
268
|
-
}, b: {
|
|
269
|
-
rank: number;
|
|
270
|
-
updatedAt: string;
|
|
271
|
-
}): number;
|
|
272
264
|
/** The shell's three primary destinations, from the page's own active
|
|
273
265
|
* key: every old page keeps its key and lights the destination it now
|
|
274
266
|
* lives under. */
|
package/dist/workspace-ui.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { ACCEPT_NEEDS_REASON, FAILED_CHECK, cantAcceptYetOf, evidenceProblemOf } from "./result-acts.js";
|
|
20
20
|
export { ACCEPT_NEEDS_REASON, cantAcceptYetOf, evidenceProblemOf };
|
|
21
|
-
import {
|
|
21
|
+
import { manualReviewOnly, plainReasonWords } from "./proof.js";
|
|
22
22
|
import { OPEN_RESULT, plainReasonOf, stageOfCode, taskStatusOf, workToneOf } from "./task-status.js";
|
|
23
23
|
import { whenUtc } from "./when-html.js";
|
|
24
24
|
import { html, postForm } from "./html.js";
|
|
@@ -54,7 +54,6 @@ export function reviewFactsOf(retry, reviewerAlive, automaticPending = false) {
|
|
|
54
54
|
}
|
|
55
55
|
/** The tokens a review in flight wears — the dispatch codes, unchanged. */
|
|
56
56
|
export const REVIEW_TOKENS = new Set(["reviewing", "review-pending", "review-failed", "review-exhausted"]);
|
|
57
|
-
const retriesLeft = (count, explicit = true) => `${count}${explicit ? " explicit" : ""} ${count === 1 ? "retry" : "retries"}`;
|
|
58
57
|
/**
|
|
59
58
|
* A review that is queued, running, failed with a retry left, or
|
|
60
59
|
* exhausted is the result's PRIMARY status — the machine is still
|
|
@@ -504,10 +503,6 @@ export function workCounts(rows) {
|
|
|
504
503
|
counts[view] += 1;
|
|
505
504
|
return counts;
|
|
506
505
|
}
|
|
507
|
-
/** All's order: rank, then most recently updated. */
|
|
508
|
-
export function compareWorkRows(a, b) {
|
|
509
|
-
return a.rank - b.rank || (a.updatedAt < b.updatedAt ? 1 : a.updatedAt > b.updatedAt ? -1 : 0);
|
|
510
|
-
}
|
|
511
506
|
const WORK_KEYS = new Set(["inbox", "board", "queue", "work", "done", "activity", "review", "tasks", "runs", "workbench", "recipes", "ledger"]);
|
|
512
507
|
const SETTINGS_KEYS = new Set(["fleet", "caps", "people", "mode", "system", "settings"]);
|
|
513
508
|
export function primaryDestinationOf(active) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a build may write (docs/plans/agent-baseline-hardening.md arc 2). `workspace`: only its allowlist (agent-fence.ts
|
|
3
|
+
* WriteAllowlist), whatever its permission mode; `anywhere`: anywhere its fence doesn't deny, as builds did before.
|
|
4
|
+
*/
|
|
5
|
+
export type WritesMode = "workspace" | "anywhere";
|
|
6
|
+
export declare const WRITES_DEFAULT: WritesMode;
|
|
7
|
+
export declare const isWritesMode: (value: unknown) => value is WritesMode;
|
|
8
|
+
/** What an approval card and the CLI say of where a build may write (absent: sealed before write allowlists). */
|
|
9
|
+
export declare function writesWords(writes: WritesMode | undefined): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const WRITES_DEFAULT = "workspace";
|
|
2
|
+
export const isWritesMode = (value) => value === "workspace" || value === "anywhere";
|
|
3
|
+
/** What an approval card and the CLI say of where a build may write (absent: sealed before write allowlists). */
|
|
4
|
+
export function writesWords(writes) {
|
|
5
|
+
return writes === "workspace" ? "only its checkout, its caches and its temp folder"
|
|
6
|
+
: writes === "anywhere" ? "anywhere outside Toolroll's fenced folders (an approver's choice)"
|
|
7
|
+
: "anywhere outside Toolroll's fenced folders (approved before write limits)";
|
|
8
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolroll",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.68",
|
|
4
4
|
"description": "A control plane for unattended coding agents — queue tasks, walk away, come back to pull requests. Agents build in leased worktrees, never touch your default branch, and interrupt you only for decisions that need a human.",
|
|
5
5
|
"directories": {
|
|
6
6
|
"doc": "docs"
|
|
@@ -84,6 +84,8 @@
|
|
|
84
84
|
"@types/react-dom": "19.3.0",
|
|
85
85
|
"@types/ws": "8.18.2",
|
|
86
86
|
"@xterm/addon-fit": "0.11.0",
|
|
87
|
+
"@xterm/addon-unicode11": "0.9.0",
|
|
88
|
+
"@xterm/addon-webgl": "0.19.0",
|
|
87
89
|
"@xterm/xterm": "6.0.0",
|
|
88
90
|
"@xyflow/react": "12.12.0",
|
|
89
91
|
"class-variance-authority": "0.7.1",
|
|
@@ -124,6 +126,8 @@
|
|
|
124
126
|
},
|
|
125
127
|
"dependencies": {
|
|
126
128
|
"@slack/socket-mode": "3.1.0",
|
|
129
|
+
"@xterm/addon-serialize": "0.14.0",
|
|
130
|
+
"@xterm/headless": "6.0.0",
|
|
127
131
|
"discord.js": "14.27.0",
|
|
128
132
|
"imapflow": "2.2.5",
|
|
129
133
|
"mailparser": "3.9.36",
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The macOS process census the recovery helper prints (docs/plans/zod-revamp.md, item 19): `schema: 1`, the boot,
|
|
3
|
-
* the collector, and one identity per process. The parser in process-recovery-native.ts reads it with these schemas
|
|
4
|
-
* and keeps its fail-closed reason codes: a top-level problem is `malformed-native-census`, one in a process row
|
|
5
|
-
* `malformed-process-identity`. Duplicate pids and unique ids, the 64-bit bound on ids and completeness run in plain
|
|
6
|
-
* code after parsing. Unknown keys are dropped, and each identity is rebuilt in its sealed key order.
|
|
7
|
-
*/
|
|
8
|
-
import { z } from "zod";
|
|
9
|
-
export declare const NATIVE_CENSUS_ERRORS: readonly ["kernel-process-table-unreadable", "process-membership-unreadable", "process-identity-unreadable", "boot-identity-unreadable", "coalition-counters-unreadable", "coalition-counters-changed", "coalition-count-mismatch", "anchor-identity-unreadable"];
|
|
10
|
-
export declare const darwinProcessIdentitySchema: z.ZodObject<{
|
|
11
|
-
pid: z.ZodInt;
|
|
12
|
-
ppid: z.ZodNullable<z.ZodInt>;
|
|
13
|
-
uid: z.ZodNullable<z.ZodInt>;
|
|
14
|
-
birthMs: z.ZodNullable<z.ZodNumber>;
|
|
15
|
-
uniqueId: z.ZodNullable<z.ZodString>;
|
|
16
|
-
parentUniqueId: z.ZodNullable<z.ZodString>;
|
|
17
|
-
traced: z.ZodNullable<z.ZodBoolean>;
|
|
18
|
-
executable: z.ZodNullable<z.ZodString>;
|
|
19
|
-
originalParentVersion: z.ZodNullable<z.ZodInt>;
|
|
20
|
-
pidVersion: z.ZodExactOptional<z.ZodInt>;
|
|
21
|
-
}, z.core.$strip>;
|
|
22
|
-
export type DarwinProcessIdentity = z.infer<typeof darwinProcessIdentitySchema>;
|
|
23
|
-
/** Top level only: process rows are read one by one, so a bad row gets its own reason. */
|
|
24
|
-
export declare const darwinNativeCensusSchema: z.ZodObject<{
|
|
25
|
-
schema: z.ZodLiteral<1>;
|
|
26
|
-
bootId: z.ZodNullable<z.ZodString>;
|
|
27
|
-
collectorPid: z.ZodInt;
|
|
28
|
-
complete: z.ZodBoolean;
|
|
29
|
-
processes: z.ZodArray<z.ZodUnknown>;
|
|
30
|
-
errors: z.ZodArray<z.ZodEnum<{
|
|
31
|
-
"anchor-identity-unreadable": "anchor-identity-unreadable";
|
|
32
|
-
"boot-identity-unreadable": "boot-identity-unreadable";
|
|
33
|
-
"coalition-count-mismatch": "coalition-count-mismatch";
|
|
34
|
-
"coalition-counters-changed": "coalition-counters-changed";
|
|
35
|
-
"coalition-counters-unreadable": "coalition-counters-unreadable";
|
|
36
|
-
"kernel-process-table-unreadable": "kernel-process-table-unreadable";
|
|
37
|
-
"process-identity-unreadable": "process-identity-unreadable";
|
|
38
|
-
"process-membership-unreadable": "process-membership-unreadable";
|
|
39
|
-
}>>;
|
|
40
|
-
}, z.core.$strip>;
|
|
41
|
-
/** A kernel id within 64 bits (the schema checks the digits). */
|
|
42
|
-
export declare const kernelIdInRange: (id: string) => boolean;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The macOS process census the recovery helper prints (docs/plans/zod-revamp.md, item 19): `schema: 1`, the boot,
|
|
3
|
-
* the collector, and one identity per process. The parser in process-recovery-native.ts reads it with these schemas
|
|
4
|
-
* and keeps its fail-closed reason codes: a top-level problem is `malformed-native-census`, one in a process row
|
|
5
|
-
* `malformed-process-identity`. Duplicate pids and unique ids, the 64-bit bound on ids and completeness run in plain
|
|
6
|
-
* code after parsing. Unknown keys are dropped, and each identity is rebuilt in its sealed key order.
|
|
7
|
-
*/
|
|
8
|
-
import { z } from "zod";
|
|
9
|
-
export const NATIVE_CENSUS_ERRORS = ["kernel-process-table-unreadable", "process-membership-unreadable", "process-identity-unreadable", "boot-identity-unreadable", "coalition-counters-unreadable", "coalition-counters-changed", "coalition-count-mismatch", "anchor-identity-unreadable"];
|
|
10
|
-
/** A kernel unique id: a decimal unsigned 64-bit integer as text (the bound itself is checked after parsing). */
|
|
11
|
-
const kernelId = z.string().regex(/^(0|[1-9][0-9]{0,19})$/);
|
|
12
|
-
const count = z.int().min(0);
|
|
13
|
-
const version32 = z.int().min(0).max(0xffffffff);
|
|
14
|
-
export const darwinProcessIdentitySchema = z.object({
|
|
15
|
-
pid: z.int().min(1),
|
|
16
|
-
ppid: count.nullable(),
|
|
17
|
-
uid: count.nullable(),
|
|
18
|
-
birthMs: z.number().positive().nullable(),
|
|
19
|
-
uniqueId: kernelId.nullable(),
|
|
20
|
-
parentUniqueId: kernelId.nullable(),
|
|
21
|
-
traced: z.boolean().nullable(),
|
|
22
|
-
executable: z.string().max(4096).regex(/^[^\x00-\x1f\x7f]*$/).nullable(),
|
|
23
|
-
originalParentVersion: version32.nullable(),
|
|
24
|
-
pidVersion: version32.exactOptional(),
|
|
25
|
-
});
|
|
26
|
-
/** Top level only: process rows are read one by one, so a bad row gets its own reason. */
|
|
27
|
-
export const darwinNativeCensusSchema = z.object({
|
|
28
|
-
schema: z.literal(1),
|
|
29
|
-
bootId: z.string().regex(/^[a-fA-F0-9-]{36}$/).nullable(),
|
|
30
|
-
collectorPid: z.int().min(2),
|
|
31
|
-
complete: z.boolean(),
|
|
32
|
-
processes: z.array(z.unknown()).max(100_000),
|
|
33
|
-
errors: z.array(z.enum(NATIVE_CENSUS_ERRORS)),
|
|
34
|
-
});
|
|
35
|
-
/** A kernel id within 64 bits (the schema checks the digits). */
|
|
36
|
-
export const kernelIdInRange = (id) => BigInt(id) <= 0xffffffffffffffffn;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { SQLInputValue } from "node:sqlite";
|
|
2
|
-
import type { DarwinCoalitionProcessIdentity, PreparedDarwinProcessCensus } from "./process-recovery-native.js";
|
|
3
|
-
/** This version's causal argument was audited against these installed bytes:
|
|
4
|
-
* up registers a fresh token BEFORE listening; every watch creates a fresh UUID;
|
|
5
|
-
* heartbeat authenticates that closure's token and exact owner transactionally.
|
|
6
|
-
* A new runtime needs its own audit, not a caller assertion of equivalent code. */
|
|
7
|
-
export declare const SERVICE_ANCHOR_RUNTIME_V1_SHA256 = "9641efcb3b46717a7f122aa025e3945a08fa55ca046605276825a9d69eefd01d";
|
|
8
|
-
export type DarwinServiceAnchorInput = {
|
|
9
|
-
databasePath: string;
|
|
10
|
-
targetRun: number;
|
|
11
|
-
anchorReviewerRun: number;
|
|
12
|
-
runtime: string;
|
|
13
|
-
runtimeSha256: string;
|
|
14
|
-
runner: string;
|
|
15
|
-
repo: string;
|
|
16
|
-
host: string;
|
|
17
|
-
bootId: string;
|
|
18
|
-
resourceCoalitionId: string;
|
|
19
|
-
service: string;
|
|
20
|
-
supervisorPid: number;
|
|
21
|
-
workerPid: number;
|
|
22
|
-
port: number;
|
|
23
|
-
/** Full expected arrays; compared privately, never included in a receipt. */
|
|
24
|
-
supervisorArgv: string[];
|
|
25
|
-
workerArgv: string[];
|
|
26
|
-
/** Recovery must prepare this helper itself from the known embedded source;
|
|
27
|
-
* never accept an executable or this result receipt from a client request. */
|
|
28
|
-
native: PreparedDarwinProcessCensus;
|
|
29
|
-
maxWaitMs?: number;
|
|
30
|
-
};
|
|
31
|
-
export type DarwinServiceAnchorReceipt = {
|
|
32
|
-
schema: 1;
|
|
33
|
-
kind: "authenticated-watch-continuity";
|
|
34
|
-
targetRun: number;
|
|
35
|
-
anchorReviewerRun: number;
|
|
36
|
-
host: string;
|
|
37
|
-
bootId: string;
|
|
38
|
-
observedAt: string;
|
|
39
|
-
runtimeSha256: string;
|
|
40
|
-
databasePath: string;
|
|
41
|
-
runner: string;
|
|
42
|
-
repo: string;
|
|
43
|
-
owner: string;
|
|
44
|
-
generation: number;
|
|
45
|
-
episode: number;
|
|
46
|
-
registeredAt: string;
|
|
47
|
-
heartbeatBefore: string;
|
|
48
|
-
heartbeatAfter: string;
|
|
49
|
-
service: string;
|
|
50
|
-
listener: string;
|
|
51
|
-
worker: DarwinCoalitionProcessIdentity;
|
|
52
|
-
supervisor: DarwinCoalitionProcessIdentity;
|
|
53
|
-
nativeSourceSha256: string;
|
|
54
|
-
nativeExecutableSha256: string;
|
|
55
|
-
};
|
|
56
|
-
export type DarwinServiceAnchorResult = {
|
|
57
|
-
ok: true;
|
|
58
|
-
receipt: DarwinServiceAnchorReceipt;
|
|
59
|
-
} | {
|
|
60
|
-
ok: false;
|
|
61
|
-
reason: string;
|
|
62
|
-
};
|
|
63
|
-
export type RecoveryReadDatabase = {
|
|
64
|
-
prepare(sql: string): {
|
|
65
|
-
get(...parameters: SQLInputValue[]): Record<string, unknown> | undefined;
|
|
66
|
-
all(...parameters: SQLInputValue[]): Record<string, unknown>[];
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
/** Trusted read-only collection, not exit evidence. Reads an existing connection
|
|
70
|
-
* (including a schema69 Store.handle), never opens/migrates or writes a database.
|
|
71
|
-
* Under the trusted installed-code/credential model, renewing a saved pre-run
|
|
72
|
-
* UUID while registration stays fixed establishes a pre-run live service bound.
|
|
73
|
-
* It does NOT establish coalition inheritance, survivor exclusion, or authority
|
|
74
|
-
* to clear process custody. Every incomplete observation returns a refusal. */
|
|
75
|
-
export declare function collectDarwinServiceAnchor(db: RecoveryReadDatabase, input: DarwinServiceAnchorInput): Promise<DarwinServiceAnchorResult>;
|