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
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type AcpProviderId } from "./acp-agents.js";
|
|
2
|
+
export type AcpInspection = {
|
|
3
|
+
found: false;
|
|
4
|
+
binary: string;
|
|
5
|
+
} | {
|
|
6
|
+
found: true;
|
|
7
|
+
binary: string;
|
|
8
|
+
/** The PATH entry that matched, and where it really is. */
|
|
9
|
+
path: string;
|
|
10
|
+
realpath: string;
|
|
11
|
+
/** A native executable (Mach-O/ELF), or a script with a shebang line. */
|
|
12
|
+
kind: "native" | "script" | "unknown";
|
|
13
|
+
/** For a script: the nearest package.json's name and version, read, never run. */
|
|
14
|
+
package: {
|
|
15
|
+
name: string;
|
|
16
|
+
version: string;
|
|
17
|
+
} | null;
|
|
18
|
+
size: number;
|
|
19
|
+
};
|
|
20
|
+
/** Find an agent's binary on PATH, and describe it without running it. */
|
|
21
|
+
export declare function inspectAcpAgent(provider: AcpProviderId, env?: Readonly<Record<string, string | undefined>>): AcpInspection;
|
|
22
|
+
/** The words a screen says for an inspection: "installed at …, version …" or "not installed". */
|
|
23
|
+
export declare function inspectionWords(inspection: AcpInspection): string;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What can be known about an ACP agent's binary without running it
|
|
3
|
+
* (docs/plans/acp-adapter.md § Identity): nothing outside the one spawning
|
|
4
|
+
* gateway executes an ACP agent — not readiness, not the providers screen,
|
|
5
|
+
* not a version probe. So readiness and the screens look, and never run:
|
|
6
|
+
* PATH lookup, realpath, lstat, and for a script launcher a bounded read of
|
|
7
|
+
* the nearest package.json for its name and version.
|
|
8
|
+
*
|
|
9
|
+
* None of this is evidence an agent may run. That is its conformance check
|
|
10
|
+
* (attestation), which this only helps describe.
|
|
11
|
+
*/
|
|
12
|
+
import { closeSync, constants, fstatSync, lstatSync, openSync, readSync, realpathSync, statSync } from "node:fs";
|
|
13
|
+
import { delimiter, dirname, isAbsolute, join } from "node:path";
|
|
14
|
+
import { ACP_AGENTS } from "./acp-agents.js";
|
|
15
|
+
/** The most bytes read from a launcher (its first line) or a package.json. */
|
|
16
|
+
const READ_CAP = 64 * 1024;
|
|
17
|
+
/** How many folders up from the launcher a package.json is looked for. */
|
|
18
|
+
const PACKAGE_DEPTH = 6;
|
|
19
|
+
/** Read at most `cap` bytes from the start of a regular file, without following a final symlink. */
|
|
20
|
+
function readHead(file, cap) {
|
|
21
|
+
let fd = null;
|
|
22
|
+
try {
|
|
23
|
+
fd = openSync(file, constants.O_RDONLY | constants.O_NOFOLLOW | (constants.O_NONBLOCK ?? 0));
|
|
24
|
+
if (!fstatSync(fd).isFile())
|
|
25
|
+
return null;
|
|
26
|
+
const buffer = Buffer.alloc(cap);
|
|
27
|
+
const read = readSync(fd, buffer, 0, cap, 0);
|
|
28
|
+
return buffer.subarray(0, read);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
if (fd !== null)
|
|
35
|
+
closeSync(fd);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function kindOf(head) {
|
|
39
|
+
if (head === null || head.length < 4)
|
|
40
|
+
return "unknown";
|
|
41
|
+
if (head[0] === 0x23 && head[1] === 0x21)
|
|
42
|
+
return "script"; // "#!"
|
|
43
|
+
const magic = head.readUInt32BE(0);
|
|
44
|
+
// ELF, Mach-O (both byte orders, 32/64-bit) and fat binaries.
|
|
45
|
+
if (magic === 0x7f454c46 || [0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe, 0xcafebabe, 0xbebafeca].includes(magic))
|
|
46
|
+
return "native";
|
|
47
|
+
return "unknown";
|
|
48
|
+
}
|
|
49
|
+
/** The nearest package.json above a script, by bounded read; its name and plain version, or null. */
|
|
50
|
+
function packageOf(realpath) {
|
|
51
|
+
let folder = dirname(realpath);
|
|
52
|
+
for (let depth = 0; depth < PACKAGE_DEPTH; depth += 1) {
|
|
53
|
+
const head = readHead(join(folder, "package.json"), READ_CAP);
|
|
54
|
+
if (head !== null) {
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(head.toString("utf8"));
|
|
57
|
+
const name = parsed["name"];
|
|
58
|
+
const version = parsed["version"];
|
|
59
|
+
if (typeof name === "string" && typeof version === "string" && name.length <= 214 && /^\d+\.\d+\.\d+$/.test(version))
|
|
60
|
+
return { name, version };
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// A package.json past the cap or not JSON says nothing.
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const up = dirname(folder);
|
|
68
|
+
if (up === folder)
|
|
69
|
+
break;
|
|
70
|
+
folder = up;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
/** Find an agent's binary on PATH, and describe it without running it. */
|
|
75
|
+
export function inspectAcpAgent(provider, env = process.env) {
|
|
76
|
+
const binary = ACP_AGENTS[provider].binary;
|
|
77
|
+
for (const folder of (env["PATH"] ?? "").split(delimiter)) {
|
|
78
|
+
if (folder === "" || !isAbsolute(folder))
|
|
79
|
+
continue;
|
|
80
|
+
const path = join(folder, binary);
|
|
81
|
+
try {
|
|
82
|
+
lstatSync(path);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
let realpath;
|
|
88
|
+
try {
|
|
89
|
+
realpath = realpathSync(path);
|
|
90
|
+
const stat = statSync(realpath);
|
|
91
|
+
if (!stat.isFile() || (stat.mode & 0o111) === 0)
|
|
92
|
+
continue;
|
|
93
|
+
const head = readHead(realpath, 4096);
|
|
94
|
+
const kind = kindOf(head);
|
|
95
|
+
return { found: true, binary, path, realpath, kind, package: kind === "script" ? packageOf(realpath) : null, size: stat.size };
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return { found: false, binary };
|
|
102
|
+
}
|
|
103
|
+
/** The words a screen says for an inspection: "installed at …, version …" or "not installed". */
|
|
104
|
+
export function inspectionWords(inspection) {
|
|
105
|
+
if (!inspection.found)
|
|
106
|
+
return `\`${inspection.binary}\` is not installed on this computer's PATH`;
|
|
107
|
+
const version = inspection.package === null ? "" : ` (${inspection.package.name} ${inspection.package.version})`;
|
|
108
|
+
return `installed at ${inspection.realpath}${version}`;
|
|
109
|
+
}
|
package/dist/agent-board.d.ts
CHANGED
|
@@ -20,8 +20,6 @@ export declare const QUESTIONS_PER_ATTEMPT = 10;
|
|
|
20
20
|
export declare const QUESTION_PAGE_EVERY_MS: number;
|
|
21
21
|
/** The board's one note on a run whose agent asked past the caps (set once). */
|
|
22
22
|
export declare const QUESTIONS_OVERFLOW_NOTE = "The agent asked more questions than the board takes; see its transcript.";
|
|
23
|
-
/** Notification kinds held while the person watches the run, and re-checked when the watch lapses. */
|
|
24
|
-
export declare const WATCHED_KINDS: ReadonlySet<string>;
|
|
25
23
|
export declare const AGENT_BOARD_SCHEMA = "\nCREATE TABLE IF NOT EXISTS agent_turn (\n id INTEGER PRIMARY KEY,\n run INTEGER NOT NULL REFERENCES run(id) ON DELETE CASCADE,\n attempt_key TEXT NOT NULL,\n state TEXT NOT NULL CHECK (state IN ('busy','idle','crashed')),\n at TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS agent_turn_run ON agent_turn (run, id);\nCREATE TABLE IF NOT EXISTS agent_now (\n task_ref INTEGER PRIMARY KEY REFERENCES task_ref(id) ON DELETE CASCADE,\n run INTEGER NOT NULL REFERENCES run(id) ON DELETE CASCADE,\n attempt_key TEXT NOT NULL,\n state TEXT NOT NULL CHECK (state IN ('busy','idle','crashed')),\n state_at TEXT NOT NULL,\n transcript_bytes INTEGER NOT NULL DEFAULT 0,\n transcript_at TEXT NOT NULL,\n stuck_at TEXT,\n said TEXT CHECK (said IN ('working','blocked','done')),\n said_note TEXT,\n said_at TEXT,\n status_offset INTEGER NOT NULL DEFAULT 0,\n diff_files INTEGER,\n diff_at TEXT\n);\nCREATE TABLE IF NOT EXISTS agent_question (\n id INTEGER PRIMARY KEY,\n run INTEGER NOT NULL REFERENCES run(id) ON DELETE CASCADE,\n task_ref INTEGER NOT NULL REFERENCES task_ref(id) ON DELETE CASCADE,\n attempt_key TEXT NOT NULL,\n key TEXT NOT NULL,\n question TEXT NOT NULL,\n asked_at TEXT NOT NULL,\n closed_at TEXT,\n closed_how TEXT CHECK (closed_how IN ('answered','ended')),\n answer_note INTEGER REFERENCES task_steer(id),\n answered_by TEXT,\n UNIQUE (run, key)\n);\nCREATE INDEX IF NOT EXISTS agent_question_open ON agent_question (task_ref) WHERE closed_at IS NULL;\nCREATE TABLE IF NOT EXISTS agent_seen (\n account TEXT NOT NULL,\n run INTEGER NOT NULL REFERENCES run(id) ON DELETE CASCADE,\n seen_at TEXT NOT NULL,\n PRIMARY KEY (account, run)\n);\nCREATE TABLE IF NOT EXISTS agent_view (\n view TEXT PRIMARY KEY,\n account TEXT NOT NULL,\n run INTEGER NOT NULL,\n expires_at TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS agent_view_run ON agent_view (run, account);\nCREATE INDEX IF NOT EXISTS agent_board_open ON run (task_ref, id) WHERE role = 'builder' AND outcome IS NULL;\nCREATE INDEX IF NOT EXISTS agent_board_recent ON run (finished_at, task_ref, id) WHERE role = 'builder' AND outcome IS NOT NULL;\nCREATE INDEX IF NOT EXISTS agent_board_repair ON run (parent_run, id) WHERE role = 'repair';\n";
|
|
26
24
|
/** Added to agent_now after the table first shipped (store.ts addColumn): the oldest open tool call's kind and start. */
|
|
27
25
|
export declare const AGENT_NOW_COLUMNS: readonly [string, string][];
|
|
@@ -194,15 +192,30 @@ export declare function releaseAgentView(store: Store, view: string, at: Date):
|
|
|
194
192
|
export declare function watchingAgentUntil(store: Store, account: string, run: number, at: Date): string | null;
|
|
195
193
|
/** Someone has this exact run open right now. */
|
|
196
194
|
export declare function watchingAgent(store: Store, account: string, run: number, at: Date): boolean;
|
|
195
|
+
export declare const neverHeld: (kind: string) => boolean;
|
|
197
196
|
/**
|
|
198
|
-
* A
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
197
|
+
* A notification's subject (cockpit §3, R11): the run it is about — its own, or for a ping about a task the task's
|
|
198
|
+
* live build — so any ping, not only the agent's own kinds, can be held while its person watches that agent. Null:
|
|
199
|
+
* about nothing a person watches. Its version is the notification's own identity (its dedupe key), so a newer fact
|
|
200
|
+
* about the same subject is a new ping.
|
|
201
|
+
*/
|
|
202
|
+
export declare function attentionSubjectOf(store: Store, row: {
|
|
203
|
+
kind: string;
|
|
204
|
+
run: number | null;
|
|
205
|
+
taskRef?: number | null;
|
|
206
|
+
}): {
|
|
207
|
+
run: number;
|
|
208
|
+
} | null;
|
|
209
|
+
/**
|
|
210
|
+
* A watched ping (cockpit §3, R11), decided when its delivery is claimed AND again at every channel's final send
|
|
211
|
+
* fence, after the permanent rules in store.pingAllowed: held until the watch lapses while this person has its
|
|
212
|
+
* subject's agent open; then skipped when it was news about a finished run they have since seen; otherwise sent.
|
|
213
|
+
* A ping about nothing anyone watches is sent. (A delivery already handed to the network can't be recalled.)
|
|
202
214
|
*/
|
|
203
215
|
export declare function watchedPing(store: Store, row: {
|
|
204
216
|
kind: string;
|
|
205
217
|
run: number | null;
|
|
218
|
+
taskRef?: number | null;
|
|
206
219
|
}, account: string, now: Date): {
|
|
207
220
|
hold: string;
|
|
208
221
|
} | "skip" | "send";
|
package/dist/agent-board.js
CHANGED
|
@@ -46,8 +46,6 @@ export const QUESTIONS_PER_ATTEMPT = 10;
|
|
|
46
46
|
export const QUESTION_PAGE_EVERY_MS = 5 * 60_000;
|
|
47
47
|
/** The board's one note on a run whose agent asked past the caps (set once). */
|
|
48
48
|
export const QUESTIONS_OVERFLOW_NOTE = "The agent asked more questions than the board takes; see its transcript.";
|
|
49
|
-
/** Notification kinds held while the person watches the run, and re-checked when the watch lapses. */
|
|
50
|
-
export const WATCHED_KINDS = new Set(["agent-question", "run-finished", "build-failed"]);
|
|
51
49
|
export const AGENT_BOARD_SCHEMA = `
|
|
52
50
|
CREATE TABLE IF NOT EXISTS agent_turn (
|
|
53
51
|
id INTEGER PRIMARY KEY,
|
|
@@ -435,19 +433,42 @@ export function watchingAgentUntil(store, account, run, at) {
|
|
|
435
433
|
export function watchingAgent(store, account, run, at) {
|
|
436
434
|
return watchingAgentUntil(store, account, run, at) !== null;
|
|
437
435
|
}
|
|
436
|
+
/** Kinds no watch ever holds: a security alert and the evening digest reach people as they are (store.pingAllowed).
|
|
437
|
+
* Nothing held may delay them either: a channel's ordering never keeps one behind a held ping (neverHeld). */
|
|
438
|
+
const NEVER_HELD = new Set(["secret-detected", "security-release", "evening-digest"]);
|
|
439
|
+
export const neverHeld = (kind) => NEVER_HELD.has(kind);
|
|
440
|
+
/** Kinds that are news only until the finished run is seen: a ping about one already opened is not sent at all. */
|
|
441
|
+
const SEEN_SETTLES = new Set(["run-finished", "build-failed"]);
|
|
438
442
|
/**
|
|
439
|
-
* A
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
+
* A notification's subject (cockpit §3, R11): the run it is about — its own, or for a ping about a task the task's
|
|
444
|
+
* live build — so any ping, not only the agent's own kinds, can be held while its person watches that agent. Null:
|
|
445
|
+
* about nothing a person watches. Its version is the notification's own identity (its dedupe key), so a newer fact
|
|
446
|
+
* about the same subject is a new ping.
|
|
447
|
+
*/
|
|
448
|
+
export function attentionSubjectOf(store, row) {
|
|
449
|
+
if (NEVER_HELD.has(row.kind))
|
|
450
|
+
return null;
|
|
451
|
+
if (row.run !== null)
|
|
452
|
+
return { run: row.run };
|
|
453
|
+
if (row.taskRef === undefined || row.taskRef === null)
|
|
454
|
+
return null;
|
|
455
|
+
const live = store.handle.prepare("SELECT id FROM run WHERE task_ref = ? AND role = 'builder' AND outcome IS NULL ORDER BY id DESC LIMIT 1").get(row.taskRef);
|
|
456
|
+
return live === undefined ? null : { run: Number(live["id"]) };
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* A watched ping (cockpit §3, R11), decided when its delivery is claimed AND again at every channel's final send
|
|
460
|
+
* fence, after the permanent rules in store.pingAllowed: held until the watch lapses while this person has its
|
|
461
|
+
* subject's agent open; then skipped when it was news about a finished run they have since seen; otherwise sent.
|
|
462
|
+
* A ping about nothing anyone watches is sent. (A delivery already handed to the network can't be recalled.)
|
|
443
463
|
*/
|
|
444
464
|
export function watchedPing(store, row, account, now) {
|
|
445
|
-
|
|
465
|
+
const subject = attentionSubjectOf(store, row);
|
|
466
|
+
if (subject === null)
|
|
446
467
|
return "send";
|
|
447
|
-
const until = watchingAgentUntil(store, account,
|
|
468
|
+
const until = watchingAgentUntil(store, account, subject.run, now);
|
|
448
469
|
if (until !== null)
|
|
449
470
|
return { hold: until };
|
|
450
|
-
if (row.kind ===
|
|
471
|
+
if (!SEEN_SETTLES.has(row.kind) || row.run === null)
|
|
451
472
|
return "send";
|
|
452
473
|
const seen = store.handle.prepare("SELECT 1 AS hit FROM agent_seen WHERE account = ? AND run = ?").get(account, boardRunOf(store, row.run));
|
|
453
474
|
return seen === undefined ? "send" : "skip";
|
package/dist/agent-fence.d.ts
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
import type { LoopbackMode } from "./egress.js";
|
|
2
|
+
/** Beside the database: where Linux builds' network bridges are made (its name reads as secret wherever it is). */
|
|
3
|
+
export declare const BRIDGE_DIR = "bridge-secrets";
|
|
1
4
|
/** How a launch was fenced, as recorded on the run and said on the task. */
|
|
2
5
|
export type FenceMethod = "codex-profile" | "macos-sandbox" | "linux-bubblewrap" | "claude-rules" | "none";
|
|
6
|
+
/** Only the plane's recorded repository may supply an own-Git exemption. */
|
|
7
|
+
export type WorktreeBinding = {
|
|
8
|
+
main: string;
|
|
9
|
+
gitdir: string;
|
|
10
|
+
};
|
|
11
|
+
export declare class CheckoutBindingError extends Error {
|
|
12
|
+
}
|
|
13
|
+
export declare const HARDENED_GIT_ARGS: readonly ["--no-optional-locks", "-c", "core.fsmonitor=false", "-c", "core.hooksPath=/dev/null"];
|
|
14
|
+
export declare function checkoutGitEnv(base?: Readonly<NodeJS.ProcessEnv>): Record<string, string>;
|
|
15
|
+
export declare function trustedWorktreeBinding(repository: string, worktree: string, poolRoots?: readonly (string | null)[]): WorktreeBinding;
|
|
3
16
|
/**
|
|
4
17
|
* Every path an agent must not reach: the Toolroll state folder
|
|
5
18
|
* beside the database (all of it, except the folder that holds this run's
|
|
@@ -14,11 +27,17 @@ export declare function agentFence(options: {
|
|
|
14
27
|
home?: string;
|
|
15
28
|
extra?: readonly string[];
|
|
16
29
|
boundary?: TaskBoundary | null;
|
|
30
|
+
binding?: WorktreeBinding | null;
|
|
31
|
+
runFolders?: RunFolders;
|
|
17
32
|
}): string[];
|
|
18
|
-
/** The task's boundary: `shell` joins the OS fence; `fileTools` only Claude's file-tool deny rules
|
|
33
|
+
/** The task's boundary: `shell` joins the OS fence; `fileTools` only Claude's file-tool deny rules; `readOnly` and
|
|
34
|
+
* `lookup` are other tasks' git metadata and checkout roots (see FenceGrants). */
|
|
19
35
|
export type TaskBoundary = {
|
|
36
|
+
protectedShell?: string[];
|
|
20
37
|
shell: string[];
|
|
21
38
|
fileTools: string[];
|
|
39
|
+
readOnly: string[];
|
|
40
|
+
lookup: string[];
|
|
22
41
|
};
|
|
23
42
|
/**
|
|
24
43
|
* Everything outside a task's own folders that a build could otherwise
|
|
@@ -32,19 +51,187 @@ export declare function taskBoundary(options: {
|
|
|
32
51
|
worktree: string;
|
|
33
52
|
provider: string;
|
|
34
53
|
home?: string;
|
|
54
|
+
binding?: WorktreeBinding | null;
|
|
35
55
|
}): TaskBoundary;
|
|
56
|
+
/** Where launches keep their private folders (the system temp folder), and this launch's own tool folder. */
|
|
57
|
+
export type RunFolders = {
|
|
58
|
+
root: string;
|
|
59
|
+
own: string | null;
|
|
60
|
+
};
|
|
61
|
+
/** The prefixes of every launch's private folders: its tools' config, a Codex build's own home, and a Linux build's
|
|
62
|
+
* network bridge (egress-bridge.ts). */
|
|
63
|
+
export declare const RUN_FOLDER_PREFIXES: readonly ["so-tools-", "so-codex-", "so-net-"];
|
|
64
|
+
export declare function runFolders(own: string | null, root?: string): RunFolders;
|
|
65
|
+
/**
|
|
66
|
+
* What a fence gives back beside its denied paths. Each is narrow and none
|
|
67
|
+
* ever writes: `readOnly` is read, never written (other tasks' git
|
|
68
|
+
* metadata); `readable` is read and run inside a denied folder (the shared
|
|
69
|
+
* dependencies this checkout links); `lookup` is only looked up, never
|
|
70
|
+
* listed or read (the deps root and the copy linked, other tasks' checkout
|
|
71
|
+
* roots); `runFolders` denies every launch folder in the temp folder but
|
|
72
|
+
* this launch's own (macOS: by pattern, so a later one is denied too);
|
|
73
|
+
* `pool` denies the plane's checkout pools whole and gives this build's own
|
|
74
|
+
* checkout back (CheckoutPool).
|
|
75
|
+
*/
|
|
76
|
+
export type FenceGrants = {
|
|
77
|
+
readOnly: string[];
|
|
78
|
+
readable: string[];
|
|
79
|
+
lookup: string[];
|
|
80
|
+
runFolders?: RunFolders;
|
|
81
|
+
pool?: CheckoutPool;
|
|
82
|
+
network?: NetworkFence;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* A launch's network confinement (egress.ts, docs/plans/agent-baseline-hardening.md arc 1). `open`: the network as it
|
|
86
|
+
* always was. `allowlist`: nothing leaves the machine but through the run's own proxy (`proxyPort`); the run's tool
|
|
87
|
+
* broker (`brokerPorts`) stays reachable; on macOS this Mac's other local services are reachable only under
|
|
88
|
+
* `loopback: "any"` (all of them: Seatbelt can't refuse one local port once it admits the rest); unix sockets only
|
|
89
|
+
* under `socketRoots` (the run's own temp folder and checkout). On Linux the agent gets a network of its own and
|
|
90
|
+
* reaches the proxy and broker through `bridge` (a folder of unix sockets the plane serves, and the forwarder that
|
|
91
|
+
* carries them onto the namespace's own loopback).
|
|
92
|
+
*/
|
|
93
|
+
export type NetworkFence = {
|
|
94
|
+
mode: "open";
|
|
95
|
+
} | {
|
|
96
|
+
mode: "allowlist";
|
|
97
|
+
proxyPort: number;
|
|
98
|
+
brokerPorts: number[];
|
|
99
|
+
loopback: LoopbackMode;
|
|
100
|
+
socketRoots: string[];
|
|
101
|
+
bridge?: {
|
|
102
|
+
folder: string;
|
|
103
|
+
forwarder: string;
|
|
104
|
+
node: string;
|
|
105
|
+
};
|
|
106
|
+
/** Linux: the run's own folders a private /tmp gives back (its checkout, its launch folder), when they are there. */
|
|
107
|
+
keep?: string[];
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Services a sandboxed process could ask to act outside the sandbox for it (macOS): open a URL in a browser (Launch
|
|
111
|
+
* Services), script another application (Apple Events), fetch in the background (nsurlsessiond), look a name up
|
|
112
|
+
* (the DNS service: a lookup is itself a message out), or read and write the clipboard. Denied when the network is
|
|
113
|
+
* confined; the run's proxy resolves names for it.
|
|
114
|
+
*/
|
|
115
|
+
export declare const DELEGATION_SERVICES: readonly string[];
|
|
116
|
+
export declare const NO_GRANTS: FenceGrants;
|
|
117
|
+
/**
|
|
118
|
+
* The plane's checkout pools, denied whole: every project's worktrees, and any made there after launch. `agentFence`
|
|
119
|
+
* drops a path at or above the checkout, so the deny lives here and each sandbox gives back, right after it, only
|
|
120
|
+
* `own` (this build's checkout, read and written) and `lookup` (the folders between, looked up, never listed).
|
|
121
|
+
*/
|
|
122
|
+
export type CheckoutPool = {
|
|
123
|
+
deny: string[];
|
|
124
|
+
own: string | null;
|
|
125
|
+
lookup: string[];
|
|
126
|
+
gitPaths?: string[];
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* The pool deny for one launch. `roots` come from the plane's own records (the pool beside the database, and the one
|
|
130
|
+
* the recorded checkout was made in), never from the checkout. A root that holds this checkout's own Git data (the
|
|
131
|
+
* binding's gitdir or the repository's .git) is never denied whole: it is split around that data instead, entry by
|
|
132
|
+
* entry, so it is denied as far as it can be (fail closed by denying more, never by refusing). A root inside the
|
|
133
|
+
* checkout, the home folder, a folder above it or / is left alone: the first is the build's own work, the others the
|
|
134
|
+
* whole machine.
|
|
135
|
+
*/
|
|
136
|
+
export declare function checkoutPool(options: {
|
|
137
|
+
roots: readonly (string | null)[];
|
|
138
|
+
worktree: string | null;
|
|
139
|
+
binding?: WorktreeBinding | null;
|
|
140
|
+
home?: string;
|
|
141
|
+
}, list?: (path: string) => string[]): CheckoutPool;
|
|
142
|
+
/** The grants for one build: its task boundary's git rules, the shared dependencies its checkout links, and the
|
|
143
|
+
* checkout pools (`poolRoots`, from the plane's records) denied around its own checkout. */
|
|
144
|
+
export declare function fenceGrants(options: {
|
|
145
|
+
databaseFile: string | null;
|
|
146
|
+
worktree: string | null;
|
|
147
|
+
boundary?: TaskBoundary | null;
|
|
148
|
+
runFolders?: RunFolders;
|
|
149
|
+
linked?: {
|
|
150
|
+
repo: string;
|
|
151
|
+
setupDigest: string | null;
|
|
152
|
+
} | null;
|
|
153
|
+
poolRoots?: readonly (string | null)[];
|
|
154
|
+
binding?: WorktreeBinding | null;
|
|
155
|
+
home?: string;
|
|
156
|
+
}): FenceGrants;
|
|
157
|
+
/**
|
|
158
|
+
* Git settings every fenced build runs with (GIT_CONFIG_COUNT, after any the
|
|
159
|
+
* caller already set): `git gc` never expires a reflog, so it never rewrites
|
|
160
|
+
* another task's reflog, which the fence would refuse mid-collection.
|
|
161
|
+
*/
|
|
162
|
+
export declare function fencedGitEnv(base?: Readonly<Record<string, string | undefined>>): Record<string, string>;
|
|
36
163
|
/**
|
|
37
164
|
* Codex's own sandbox, fenced. Auto: the `:workspace` profile Codex's
|
|
38
165
|
* `--sandbox workspace-write` already gives (workspace and temp writes, no
|
|
39
166
|
* network). Full access: the same profile widened to write anywhere with
|
|
40
167
|
* network on, instead of no sandbox at all. Either way the fenced paths are
|
|
41
|
-
* denied, which in Codex outranks any write or read grant.
|
|
168
|
+
* denied, which in Codex outranks any write or read grant. The checkout pools
|
|
169
|
+
* are never `flattened` (which leaves what is made after launch readable): see
|
|
170
|
+
* `codexPool`, which denies them around the build's own checkout, written back.
|
|
171
|
+
*/
|
|
172
|
+
export declare function codexFenceArgv(fence: readonly string[], fullAccess: boolean, grants?: FenceGrants): string[];
|
|
173
|
+
/**
|
|
174
|
+
* Codex cannot deny an ancestor and still traverse it to the own checkout. Deny existing
|
|
175
|
+
* siblings individually, from the trusted pool roots and a fresh listing, never through
|
|
176
|
+
* flattened or name patterns. A project added after launch is covered on the next launch;
|
|
177
|
+
* Seatbelt and bubblewrap retain the stronger whole-pool rule for later-created projects.
|
|
178
|
+
*/
|
|
179
|
+
export declare function codexPool(pool: CheckoutPool, list?: (path: string) => string[]): {
|
|
180
|
+
read: string[];
|
|
181
|
+
deny: string[];
|
|
182
|
+
write: string[];
|
|
183
|
+
};
|
|
184
|
+
/** Secret-looking names denied by pattern inside a folder `flattened` makes read-only, so one written there after
|
|
185
|
+
* launch is denied too (the database and its journals, tokens, login and other text files). */
|
|
186
|
+
export declare const SPLIT_SECRET_PATTERNS: readonly ["orders.db*", "*token*", "up-login*", "*.txt", "*secret*", "*password*", "*credential*", "*.pem", "*.key"];
|
|
187
|
+
/**
|
|
188
|
+
* A fence as plain denied and read-only paths, for a sandbox that can't
|
|
189
|
+
* grant inside a denied folder (Codex: a deny outranks any grant): a denied
|
|
190
|
+
* folder holding something readable becomes read-only, with each of its
|
|
191
|
+
* entries not on the way to what is readable denied instead. Fails closed: a
|
|
192
|
+
* folder that can't be listed stays denied whole and its grant is dropped.
|
|
193
|
+
* Residual: an entry made after launch in a read-only folder is denied only
|
|
194
|
+
* when its name matches SPLIT_SECRET_PATTERNS; any other new entry there is
|
|
195
|
+
* readable (never writable) until the next launch. The macOS fence has no
|
|
196
|
+
* such gap: it denies the folder and grants back only the readable path.
|
|
197
|
+
*/
|
|
198
|
+
export declare function flattened(fence: readonly string[], grants?: FenceGrants, list?: (path: string) => string[]): {
|
|
199
|
+
deny: string[];
|
|
200
|
+
readOnly: string[];
|
|
201
|
+
};
|
|
202
|
+
/** Claude's own file tools refuse the fenced paths in every mode (its shell is fenced by the macOS sandbox), and
|
|
203
|
+
* never edit a read-only one. */
|
|
204
|
+
export declare function claudeFenceSettings(fence: readonly string[], readOnly?: readonly string[]): string;
|
|
205
|
+
/**
|
|
206
|
+
* The folders the user owns above each path (never `/`, nor the path itself), and each `roots` folder itself when the
|
|
207
|
+
* user owns it. A Seatbelt path rule follows the name, not the folder: renaming one of these would bring a fenced path
|
|
208
|
+
* back under a name no rule mentions. A folder the user doesn't own can't be renamed by a build anyway.
|
|
209
|
+
*/
|
|
210
|
+
export declare function ownedAncestors(paths: readonly string[], roots?: readonly string[], uid?: number | undefined): string[];
|
|
211
|
+
/**
|
|
212
|
+
* A Seatbelt profile that allows everything except reading or writing the
|
|
213
|
+
* fenced paths, less what `grants` gives back (a later Seatbelt rule
|
|
214
|
+
* outranks an earlier one). Whatever the paths, the process can't read
|
|
215
|
+
* another's arguments and environment (`kern.procargs`, which `ps -E` and
|
|
216
|
+
* KERN_PROCARGS2 use) or inspect a process outside its own sandbox:
|
|
217
|
+
* `process-info*` limited by target alone doesn't stop the sysctl. It can't
|
|
218
|
+
* take another process's task port either (`task_for_pid`, what lldb attaches
|
|
219
|
+
* with; a task name port too), so a tool server's or Toolroll's own memory
|
|
220
|
+
* and environment stay out of reach. Last, every folder of the user's above
|
|
221
|
+
* a fenced or read-only path and above the temp folder (and the temp folder
|
|
222
|
+
* itself) can't be renamed or removed, though what is inside them stays
|
|
223
|
+
* writable as before. The checkout pools are denied first, and the build's own
|
|
224
|
+
* checkout given back right after, so every later deny still holds inside it.
|
|
225
|
+
*/
|
|
226
|
+
export declare function macosFenceProfile(fence: readonly string[], grants?: FenceGrants): string;
|
|
227
|
+
/**
|
|
228
|
+
* The network half of the macOS fence. Every outbound connection is denied, then loopback is given back as the launch
|
|
229
|
+
* allows: every local port under `loopback: "any"`, else the run's proxy and broker alone. (Seatbelt admits a port an
|
|
230
|
+
* allow names whatever a deny after it says, so a local port can't be refused once all are admitted: the choice is all
|
|
231
|
+
* or none, plus the run's own.) Filters name the remote end only: a `local ip` filter would admit any outbound
|
|
232
|
+
* connection.
|
|
42
233
|
*/
|
|
43
|
-
export declare function
|
|
44
|
-
/** Claude's own file tools refuse the fenced paths in every mode (its shell is fenced by the macOS sandbox). */
|
|
45
|
-
export declare function claudeFenceSettings(fence: readonly string[]): string;
|
|
46
|
-
/** A Seatbelt profile that allows everything except reading or writing the fenced paths. */
|
|
47
|
-
export declare function macosFenceProfile(fence: readonly string[]): string;
|
|
234
|
+
export declare function macosNetworkRules(network: NetworkFence | undefined): string[];
|
|
48
235
|
export declare const SANDBOX_EXEC = "/usr/bin/sandbox-exec";
|
|
49
236
|
/**
|
|
50
237
|
* Whether this machine can run an agent inside the macOS fence (checked once). Not from inside another
|
|
@@ -58,13 +245,19 @@ export declare function macosFenceAvailable(platform?: NodeJS.Platform, probe?:
|
|
|
58
245
|
stderr: string;
|
|
59
246
|
}): boolean;
|
|
60
247
|
/** The spawn that runs `file args` inside the macOS fence (same process: sandbox-exec replaces itself with the agent). */
|
|
61
|
-
export declare function macosFenced(file: string, args: readonly string[], fence: readonly string[]): {
|
|
248
|
+
export declare function macosFenced(file: string, args: readonly string[], fence: readonly string[], grants?: FenceGrants): {
|
|
62
249
|
file: string;
|
|
63
250
|
args: string[];
|
|
64
251
|
};
|
|
65
252
|
export declare function linuxFenceAvailable(platform?: NodeJS.Platform, probe?: () => boolean): boolean;
|
|
66
|
-
/** The spawn that runs `file args` inside the Linux fence: the whole filesystem as it is,
|
|
67
|
-
|
|
253
|
+
/** The spawn that runs `file args` inside the Linux fence: the whole filesystem as it is, the checkout pools masked
|
|
254
|
+
* and the build's own checkout bound back read-write over them, then every fenced path masked whole (an empty
|
|
255
|
+
* folder, or /dev/null for a file), so what is made there after launch is masked too; then only the explicit grants
|
|
256
|
+
* bound back read-only (bubblewrap binds from the original root, so a grant inside a mask still reaches its files). */
|
|
257
|
+
export declare function linuxFenced(file: string, args: readonly string[], fence: readonly string[], grants?: FenceGrants): {
|
|
68
258
|
file: string;
|
|
69
259
|
args: string[];
|
|
70
260
|
};
|
|
261
|
+
/** The host's own sockets a process in a mounted filesystem could still talk to (D-Bus, the display, container
|
|
262
|
+
* engines), wherever they exist here. */
|
|
263
|
+
export declare function linuxHostSockets(uid?: number | undefined, home?: string, tmp?: string): string[];
|