@celestea/tools 2.7.1
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/LICENSE +21 -0
- package/dist/args.d.ts +15 -0
- package/dist/args.js +55 -0
- package/dist/attachments/image-header.d.ts +28 -0
- package/dist/attachments/image-header.js +148 -0
- package/dist/attachments/store.d.ts +56 -0
- package/dist/attachments/store.js +148 -0
- package/dist/browser/cdp.d.ts +162 -0
- package/dist/browser/cdp.js +269 -0
- package/dist/browser/launch.d.ts +92 -0
- package/dist/browser/launch.js +232 -0
- package/dist/browser/memory-guard.d.ts +55 -0
- package/dist/browser/memory-guard.js +210 -0
- package/dist/browser/session.d.ts +146 -0
- package/dist/browser/session.js +371 -0
- package/dist/browser/snapshot.d.ts +69 -0
- package/dist/browser/snapshot.js +163 -0
- package/dist/browser/types.d.ts +51 -0
- package/dist/browser/types.js +8 -0
- package/dist/builtin.d.ts +54 -0
- package/dist/builtin.js +77 -0
- package/dist/desc.d.ts +20 -0
- package/dist/desc.js +22 -0
- package/dist/disclosure.d.ts +113 -0
- package/dist/disclosure.js +141 -0
- package/dist/env.d.ts +10 -0
- package/dist/env.js +33 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.js +60 -0
- package/dist/exposure.d.ts +145 -0
- package/dist/exposure.js +244 -0
- package/dist/fn-tool.d.ts +14 -0
- package/dist/fn-tool.js +14 -0
- package/dist/fs/file-io.d.ts +78 -0
- package/dist/fs/file-io.js +239 -0
- package/dist/guard/path-guard.d.ts +144 -0
- package/dist/guard/path-guard.js +289 -0
- package/dist/guard/paths.d.ts +35 -0
- package/dist/guard/paths.js +100 -0
- package/dist/http/errors.d.ts +24 -0
- package/dist/http/errors.js +64 -0
- package/dist/http/headers.d.ts +19 -0
- package/dist/http/headers.js +62 -0
- package/dist/http/redirects.d.ts +31 -0
- package/dist/http/redirects.js +76 -0
- package/dist/http/ssrf.d.ts +105 -0
- package/dist/http/ssrf.js +272 -0
- package/dist/http/transport.d.ts +50 -0
- package/dist/http/transport.js +130 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.js +129 -0
- package/dist/memory/log.d.ts +75 -0
- package/dist/memory/log.js +157 -0
- package/dist/memory/store.d.ts +47 -0
- package/dist/memory/store.js +61 -0
- package/dist/platform/exec.d.ts +79 -0
- package/dist/platform/exec.js +218 -0
- package/dist/platform/index.d.ts +12 -0
- package/dist/platform/index.js +12 -0
- package/dist/platform/paths.d.ts +51 -0
- package/dist/platform/paths.js +60 -0
- package/dist/platform/quote.d.ts +72 -0
- package/dist/platform/quote.js +102 -0
- package/dist/plugin.d.ts +96 -0
- package/dist/plugin.js +101 -0
- package/dist/process/buffers.d.ts +33 -0
- package/dist/process/buffers.js +86 -0
- package/dist/process/registry.d.ts +98 -0
- package/dist/process/registry.js +282 -0
- package/dist/registry.d.ts +52 -0
- package/dist/registry.js +161 -0
- package/dist/run-code/broker.d.ts +68 -0
- package/dist/run-code/broker.js +465 -0
- package/dist/run-code/limits.d.ts +69 -0
- package/dist/run-code/limits.js +88 -0
- package/dist/run-code/lines.d.ts +69 -0
- package/dist/run-code/lines.js +199 -0
- package/dist/run-code/sdk-ts.d.ts +34 -0
- package/dist/run-code/sdk-ts.js +276 -0
- package/dist/run-code/sdk.d.ts +39 -0
- package/dist/run-code/sdk.js +294 -0
- package/dist/sandbox/async.d.ts +10 -0
- package/dist/sandbox/async.js +26 -0
- package/dist/sandbox/bwrap-argv.d.ts +62 -0
- package/dist/sandbox/bwrap-argv.js +113 -0
- package/dist/sandbox/bwrap.d.ts +94 -0
- package/dist/sandbox/bwrap.js +159 -0
- package/dist/sandbox/child.d.ts +38 -0
- package/dist/sandbox/child.js +98 -0
- package/dist/sandbox/config.d.ts +89 -0
- package/dist/sandbox/config.js +149 -0
- package/dist/sandbox/fake-sandbox.d.ts +57 -0
- package/dist/sandbox/fake-sandbox.js +110 -0
- package/dist/sandbox/launch.d.ts +51 -0
- package/dist/sandbox/launch.js +134 -0
- package/dist/sandbox/limits.d.ts +63 -0
- package/dist/sandbox/limits.js +113 -0
- package/dist/sandbox/probe.d.ts +46 -0
- package/dist/sandbox/probe.js +102 -0
- package/dist/sandbox/provider.d.ts +83 -0
- package/dist/sandbox/provider.js +126 -0
- package/dist/sandbox/rlimit.d.ts +60 -0
- package/dist/sandbox/rlimit.js +76 -0
- package/dist/sandbox/seccomp.d.ts +48 -0
- package/dist/sandbox/seccomp.js +115 -0
- package/dist/sandbox/userspace.d.ts +65 -0
- package/dist/sandbox/userspace.js +107 -0
- package/dist/sandbox/workdir.d.ts +13 -0
- package/dist/sandbox/workdir.js +44 -0
- package/dist/schema.d.ts +20 -0
- package/dist/schema.js +135 -0
- package/dist/testing/platform-gates.d.ts +54 -0
- package/dist/testing/platform-gates.js +62 -0
- package/dist/tool-failure.d.ts +13 -0
- package/dist/tool-failure.js +19 -0
- package/dist/tools/ask-user.d.ts +32 -0
- package/dist/tools/ask-user.js +145 -0
- package/dist/tools/browser.d.ts +24 -0
- package/dist/tools/browser.js +132 -0
- package/dist/tools/http-request.d.ts +31 -0
- package/dist/tools/http-request.js +117 -0
- package/dist/tools/list-dir.d.ts +9 -0
- package/dist/tools/list-dir.js +45 -0
- package/dist/tools/load-skill.d.ts +37 -0
- package/dist/tools/load-skill.js +76 -0
- package/dist/tools/memory.d.ts +46 -0
- package/dist/tools/memory.js +131 -0
- package/dist/tools/process-control.d.ts +14 -0
- package/dist/tools/process-control.js +49 -0
- package/dist/tools/read-file.d.ts +11 -0
- package/dist/tools/read-file.js +81 -0
- package/dist/tools/read-image.d.ts +33 -0
- package/dist/tools/read-image.js +144 -0
- package/dist/tools/run-code.d.ts +48 -0
- package/dist/tools/run-code.js +115 -0
- package/dist/tools/run-shell.d.ts +22 -0
- package/dist/tools/run-shell.js +81 -0
- package/dist/tools/write-file.d.ts +8 -0
- package/dist/tools/write-file.js +31 -0
- package/package.json +28 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell resolution (W885) — WHICH shell runs a `run_shell` / `run_code` command.
|
|
3
|
+
*
|
|
4
|
+
* Product decision (W885): on Windows the priority is
|
|
5
|
+
*
|
|
6
|
+
* gitbash > pwsh > cmd
|
|
7
|
+
*
|
|
8
|
+
* and the choice is **probe-based, never guessed**: every candidate is looked up
|
|
9
|
+
* through the injected `which` / `exists` callbacks (defaults: the filesystem +
|
|
10
|
+
* `PATH`), and when nothing is found the resolver **fails closed** with a
|
|
11
|
+
* structured [ShellNotFoundError] instead of silently picking a shell the host
|
|
12
|
+
* may not have.
|
|
13
|
+
*
|
|
14
|
+
* Linux behaviour is byte-identical to the pre-W885 code: the POSIX answer is
|
|
15
|
+
* the literal `/bin/sh` with argv `["-c", command]` (W883 B8 anchored that
|
|
16
|
+
* shape in `config.ts` / `bwrap-argv.ts`). `$SHELL` is deliberately NOT
|
|
17
|
+
* consulted implicitly — that would change what runs on every Linux host that
|
|
18
|
+
* exports it; an operator pins a shell explicitly with `CELESTEA_SHELL`.
|
|
19
|
+
*
|
|
20
|
+
* Pure and injectable: the platform / env / homedir inputs are arguments (the
|
|
21
|
+
* `celestea-home.ts` pattern), so the win32 branches are unit-testable on
|
|
22
|
+
* Linux.
|
|
23
|
+
*/
|
|
24
|
+
import { existsSync } from "node:fs";
|
|
25
|
+
import { envValue, execSuffixes, isWindows, pathApi, pathDelimiter } from "./paths.js";
|
|
26
|
+
/** Env var pinning one explicit shell executable (any platform, fail-closed). */
|
|
27
|
+
export const ENV_SHELL_PIN = "CELESTEA_SHELL";
|
|
28
|
+
/** Structured failure: no usable shell on this host (never a fallback guess). */
|
|
29
|
+
export class ShellNotFoundError extends Error {
|
|
30
|
+
code = "shell_not_found";
|
|
31
|
+
constructor(message) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "ShellNotFoundError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** The argv shape of one shell carrying exactly one command string. */
|
|
37
|
+
export function shellArgv(kind, command) {
|
|
38
|
+
if (kind === "pwsh")
|
|
39
|
+
return ["-NoProfile", "-NonInteractive", "-Command", command];
|
|
40
|
+
if (kind === "cmd")
|
|
41
|
+
return ["/d", "/s", "/c", command];
|
|
42
|
+
// posix + gitbash both speak `sh -c`.
|
|
43
|
+
return ["-c", command];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolve the shell that should carry `command` on `platform`.
|
|
47
|
+
*
|
|
48
|
+
* Precedence: an explicit `CELESTEA_SHELL` pin > the platform ladder
|
|
49
|
+
* (POSIX: `/bin/sh`; Windows: gitbash > pwsh > cmd). Nothing found ⇒ throws.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveShell(command, input = {}) {
|
|
52
|
+
const chosen = resolveShellKind(input);
|
|
53
|
+
return { ...chosen, argv: shellArgv(chosen.kind, command) };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The shell a command WOULD be given to, without a command (W885: `run_code`
|
|
57
|
+
* needs the kind to quote its interpreter line before it has one).
|
|
58
|
+
*/
|
|
59
|
+
export function resolveShellKind(input = {}) {
|
|
60
|
+
const platform = input.platform ?? process.platform;
|
|
61
|
+
const env = input.env ?? process.env;
|
|
62
|
+
const lookup = lookupFor(platform, env, input);
|
|
63
|
+
const pinned = envValue(env, ENV_SHELL_PIN);
|
|
64
|
+
if (pinned !== undefined)
|
|
65
|
+
return pinnedShell(pinned, platform, lookup);
|
|
66
|
+
return isWindows(platform) ? resolveWindows(env, lookup) : resolvePosix();
|
|
67
|
+
}
|
|
68
|
+
/** The default lookups: real filesystem, PATH split per platform delimiter. */
|
|
69
|
+
export function lookupFor(platform, env, input = {}) {
|
|
70
|
+
const exists = input.exists ?? ((path) => existsSync(path));
|
|
71
|
+
return { which: input.which ?? ((bin) => whichInPath(bin, platform, env, exists)), exists };
|
|
72
|
+
}
|
|
73
|
+
function resolvePosix() {
|
|
74
|
+
// Byte-for-byte the pre-W885 answer; `$SHELL` is intentionally ignored (see
|
|
75
|
+
// the module header) so no existing Linux deployment changes behaviour.
|
|
76
|
+
return { kind: "posix", path: "/bin/sh" };
|
|
77
|
+
}
|
|
78
|
+
function resolveWindows(env, lookup) {
|
|
79
|
+
const gitbash = findGitBash(env, lookup);
|
|
80
|
+
if (gitbash !== null)
|
|
81
|
+
return { kind: "gitbash", path: gitbash };
|
|
82
|
+
const pwsh = findPwsh(env, lookup);
|
|
83
|
+
if (pwsh !== null)
|
|
84
|
+
return { kind: "pwsh", path: pwsh };
|
|
85
|
+
const cmd = findCmd(env, lookup);
|
|
86
|
+
if (cmd !== null)
|
|
87
|
+
return { kind: "cmd", path: cmd };
|
|
88
|
+
throw new ShellNotFoundError("no usable shell on this Windows host: looked for bash.exe (Git for Windows: " +
|
|
89
|
+
"%ProgramFiles%\\Git\\bin\\bash.exe, %ProgramFiles(x86)%\\Git\\bin\\bash.exe, " +
|
|
90
|
+
"%LOCALAPPDATA%\\Programs\\Git\\bin\\bash.exe, PATH), pwsh.exe (PATH, " +
|
|
91
|
+
"%ProgramFiles%\\PowerShell\\7\\pwsh.exe) and cmd.exe (%ComSpec%, PATH, %SystemRoot%\\System32). " +
|
|
92
|
+
"Install Git for Windows / PowerShell 7, or pin one with " + ENV_SHELL_PIN + ".");
|
|
93
|
+
}
|
|
94
|
+
/** Git for Windows, in the order the user's priority implies. */
|
|
95
|
+
function findGitBash(env, lookup) {
|
|
96
|
+
const onPath = lookup.which("bash.exe");
|
|
97
|
+
if (onPath !== null)
|
|
98
|
+
return onPath;
|
|
99
|
+
return firstExisting(underRoots(env, GITBASH_ROOTS), lookup.exists);
|
|
100
|
+
}
|
|
101
|
+
function findPwsh(env, lookup) {
|
|
102
|
+
const onPath = lookup.which("pwsh.exe");
|
|
103
|
+
if (onPath !== null)
|
|
104
|
+
return onPath;
|
|
105
|
+
return firstExisting(underRoots(env, PWSH_ROOTS), lookup.exists);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* cmd.exe: `%ComSpec%` first (the OS's own answer), then PATH, then the
|
|
109
|
+
* canonical `%SystemRoot%\\System32` location. Never invented beyond that.
|
|
110
|
+
*/
|
|
111
|
+
function findCmd(env, lookup) {
|
|
112
|
+
const comspec = envValue(env, "ComSpec");
|
|
113
|
+
if (comspec !== undefined && lookup.exists(comspec))
|
|
114
|
+
return comspec;
|
|
115
|
+
const onPath = lookup.which("cmd.exe");
|
|
116
|
+
if (onPath !== null)
|
|
117
|
+
return onPath;
|
|
118
|
+
return firstExisting(underRoots(env, CMD_ROOTS), lookup.exists);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* `[install-root env var, path under it]` pairs, in the order Git for Windows
|
|
122
|
+
* actually uses. Program Files first (the machine-wide installer), then the
|
|
123
|
+
* per-user default — the W883 §2.2 note that a Git installed "for me only"
|
|
124
|
+
* lives under `%LOCALAPPDATA%\Programs`.
|
|
125
|
+
*/
|
|
126
|
+
const GITBASH_ROOTS = [
|
|
127
|
+
["ProgramFiles", ["Git", "bin", "bash.exe"]],
|
|
128
|
+
["ProgramFiles(x86)", ["Git", "bin", "bash.exe"]],
|
|
129
|
+
["LOCALAPPDATA", ["Programs", "Git", "bin", "bash.exe"]],
|
|
130
|
+
];
|
|
131
|
+
/** PowerShell 7's documented install root (pwsh is never under Program Files (x86)). */
|
|
132
|
+
const PWSH_ROOTS = [["ProgramFiles", ["PowerShell", "7", "pwsh.exe"]]];
|
|
133
|
+
/** cmd.exe's canonical location when `%ComSpec%` and PATH are both silent. */
|
|
134
|
+
const CMD_ROOTS = [
|
|
135
|
+
["SystemRoot", ["System32", "cmd.exe"]],
|
|
136
|
+
["windir", ["System32", "cmd.exe"]],
|
|
137
|
+
];
|
|
138
|
+
/** Absolute candidates for `[envVar, segments]` pairs under one install root. */
|
|
139
|
+
function underRoots(env, roots) {
|
|
140
|
+
const api = pathApi("win32");
|
|
141
|
+
const out = [];
|
|
142
|
+
for (const [key, segments] of roots) {
|
|
143
|
+
const root = envValue(env, key);
|
|
144
|
+
if (root !== undefined)
|
|
145
|
+
out.push(api.join(root, ...segments));
|
|
146
|
+
}
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
function firstExisting(candidates, exists) {
|
|
150
|
+
for (const candidate of candidates)
|
|
151
|
+
if (exists(candidate))
|
|
152
|
+
return candidate;
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* An explicitly pinned shell (`CELESTEA_SHELL`). The kind is derived from the
|
|
157
|
+
* file name so the argv shape matches; an unrecognised name is a structured
|
|
158
|
+
* error rather than a silent guess.
|
|
159
|
+
*/
|
|
160
|
+
function pinnedShell(path, platform, lookup) {
|
|
161
|
+
if (!lookup.exists(path))
|
|
162
|
+
throw new ShellNotFoundError(ENV_SHELL_PIN + "='" + path + "' does not exist on this host");
|
|
163
|
+
return { kind: kindOfExecutable(path, platform), path };
|
|
164
|
+
}
|
|
165
|
+
const PINNED_KINDS = new Map([
|
|
166
|
+
["bash", "gitbash"],
|
|
167
|
+
["sh", "posix"],
|
|
168
|
+
["dash", "posix"],
|
|
169
|
+
["pwsh", "pwsh"],
|
|
170
|
+
["powershell", "pwsh"],
|
|
171
|
+
["cmd", "cmd"],
|
|
172
|
+
]);
|
|
173
|
+
/** `pwsh.exe` -> `pwsh`; the kind a pinned executable's argv shape follows. */
|
|
174
|
+
export function kindOfExecutable(path, platform = process.platform) {
|
|
175
|
+
const base = pathApi(platform).basename(path).toLowerCase().replace(/\.(exe|cmd|bat|com)$/, "");
|
|
176
|
+
const kind = PINNED_KINDS.get(base);
|
|
177
|
+
if (kind === undefined) {
|
|
178
|
+
throw new ShellNotFoundError(ENV_SHELL_PIN + "='" + path + "' is not a recognised shell (expected sh, bash, dash, pwsh, powershell or cmd)");
|
|
179
|
+
}
|
|
180
|
+
// `bash` on a POSIX host is the ordinary POSIX shell; on Windows it is Git Bash.
|
|
181
|
+
return kind === "gitbash" && !isWindows(platform) ? "posix" : kind;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* PATH lookup that honours the injected env and the platform's delimiter —
|
|
185
|
+
* `;` plus `PATHEXT` suffixes on Windows, `:` with no suffixes elsewhere. A
|
|
186
|
+
* value that looks like a path is checked directly (the pre-W885 rule).
|
|
187
|
+
*/
|
|
188
|
+
export function whichInPath(bin, platform = process.platform, env = {}, exists = existsSync) {
|
|
189
|
+
if (looksLikePath(bin, platform))
|
|
190
|
+
return exists(bin) ? bin : null;
|
|
191
|
+
const api = pathApi(platform);
|
|
192
|
+
for (const dir of searchPath(platform, env)) {
|
|
193
|
+
if (dir === "")
|
|
194
|
+
continue;
|
|
195
|
+
for (const name of candidateNames(bin, platform, env)) {
|
|
196
|
+
const candidate = api.join(dir, name);
|
|
197
|
+
if (exists(candidate))
|
|
198
|
+
return candidate;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
/** The PATH entries to search (POSIX keeps the historical /usr/bin:/bin floor). */
|
|
204
|
+
function searchPath(platform, env) {
|
|
205
|
+
const raw = env["PATH"] ?? (isWindows(platform) ? "" : "/usr/bin:/bin");
|
|
206
|
+
return raw.split(pathDelimiter(platform));
|
|
207
|
+
}
|
|
208
|
+
/** Exact name first, then the platform suffixes (Windows only). */
|
|
209
|
+
function candidateNames(bin, platform, env) {
|
|
210
|
+
if (pathApi(platform).extname(bin) !== "")
|
|
211
|
+
return [bin];
|
|
212
|
+
return [bin, ...execSuffixes(platform, env).map((suffix) => bin + suffix)];
|
|
213
|
+
}
|
|
214
|
+
function looksLikePath(bin, platform) {
|
|
215
|
+
if (isWindows(platform))
|
|
216
|
+
return pathApi(platform).isAbsolute(bin) || bin.includes("\\");
|
|
217
|
+
return bin.includes("/");
|
|
218
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* W885 — the platform seam barrel (`@celestea/tools/platform` internals).
|
|
3
|
+
*
|
|
4
|
+
* Three concerns, deliberately split so each file stays inside the repo's
|
|
5
|
+
* 400-line / 80-line-per-function shape rules:
|
|
6
|
+
* paths.ts platform ids, path API, PATH delimiter, PATHEXT suffixes
|
|
7
|
+
* exec.ts shell resolution (gitbash > pwsh > cmd) + PATH lookup
|
|
8
|
+
* quote.ts per-shell command quoting + the run_code interpreter line
|
|
9
|
+
*/
|
|
10
|
+
export * from "./paths.js";
|
|
11
|
+
export * from "./exec.js";
|
|
12
|
+
export * from "./quote.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* W885 — the platform seam barrel (`@celestea/tools/platform` internals).
|
|
3
|
+
*
|
|
4
|
+
* Three concerns, deliberately split so each file stays inside the repo's
|
|
5
|
+
* 400-line / 80-line-per-function shape rules:
|
|
6
|
+
* paths.ts platform ids, path API, PATH delimiter, PATHEXT suffixes
|
|
7
|
+
* exec.ts shell resolution (gitbash > pwsh > cmd) + PATH lookup
|
|
8
|
+
* quote.ts per-shell command quoting + the run_code interpreter line
|
|
9
|
+
*/
|
|
10
|
+
export * from "./paths.js";
|
|
11
|
+
export * from "./exec.js";
|
|
12
|
+
export * from "./quote.js";
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* W885 (Windows slice 1) — the injectable platform seam.
|
|
3
|
+
*
|
|
4
|
+
* `celestea-home.ts` (W880) set the pattern: a platform decision takes its
|
|
5
|
+
* inputs as ARGUMENTS (`platform` / `env` / `homedir`) and stays a pure
|
|
6
|
+
* function, so the win32 branch is unit-testable on a Linux host and the global
|
|
7
|
+
* `process` is read only where a default is unavoidable. This module is that
|
|
8
|
+
* seam for everything the sandbox/guard/broker layers need.
|
|
9
|
+
*
|
|
10
|
+
* It lives in `@celestea/tools` (not core): `probe.ts`, `path-guard.ts`,
|
|
11
|
+
* `config.ts`, `child.ts` and `broker.ts` — the consumers — are all in this
|
|
12
|
+
* package, the dependency direction stays L1 → L0, and core keeps its leaf
|
|
13
|
+
* promise (W883 §6.2 P0-2 listed both locations as acceptable).
|
|
14
|
+
*/
|
|
15
|
+
import { posix } from "node:path";
|
|
16
|
+
/** Everything a platform decision may depend on (injectable; never global). */
|
|
17
|
+
export interface PlatformInput {
|
|
18
|
+
/** Defaults to `process.platform` at the call site only. */
|
|
19
|
+
platform?: NodeJS.Platform | string;
|
|
20
|
+
/** Defaults to `process.env` at the call site only. */
|
|
21
|
+
env?: Record<string, string | undefined>;
|
|
22
|
+
/** Defaults to `os.homedir()` at the call site only. */
|
|
23
|
+
homedir?: string;
|
|
24
|
+
}
|
|
25
|
+
/** true for the Windows platform id (the only place the literal lives). */
|
|
26
|
+
export declare function isWindows(platform?: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The path implementation of a platform (same rule as `celestea-home.ts`):
|
|
29
|
+
* deterministic across hosts, so a win32 test never touches the host's path
|
|
30
|
+
* semantics.
|
|
31
|
+
*/
|
|
32
|
+
export declare function pathApi(platform?: string): typeof posix;
|
|
33
|
+
/** `PATH` list separator: `;` on Windows, `:` everywhere else. */
|
|
34
|
+
export declare function pathDelimiter(platform?: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Executable suffixes tried when resolving a bare name on Windows. The real
|
|
37
|
+
* rule is `PATHEXT` (plus an exact-name match first, which command lookup also
|
|
38
|
+
* allows); the two ARE checked independently and must not be collapsed.
|
|
39
|
+
*/
|
|
40
|
+
export declare const WINDOWS_EXEC_SUFFIXES: readonly string[];
|
|
41
|
+
/**
|
|
42
|
+
* The suffixes to try for `bin` on `platform`, from the injected env.
|
|
43
|
+
*
|
|
44
|
+
* `PATHEXT` is honoured when present (the operator's real resolution order) and
|
|
45
|
+
* the defaults are used otherwise. The order inside the list is significant:
|
|
46
|
+
* `.exe` before `.cmd` is what makes `bash.exe` win over a `bash.cmd`
|
|
47
|
+
* shim, which matters for the gitbash > pwsh > cmd priority.
|
|
48
|
+
*/
|
|
49
|
+
export declare function execSuffixes(platform?: string, env?: Record<string, string | undefined>): readonly string[];
|
|
50
|
+
/** A non-blank, trimmed env value; `undefined` when unset or blank. */
|
|
51
|
+
export declare function envValue(env: Record<string, string | undefined>, name: string): string | undefined;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* W885 (Windows slice 1) — the injectable platform seam.
|
|
3
|
+
*
|
|
4
|
+
* `celestea-home.ts` (W880) set the pattern: a platform decision takes its
|
|
5
|
+
* inputs as ARGUMENTS (`platform` / `env` / `homedir`) and stays a pure
|
|
6
|
+
* function, so the win32 branch is unit-testable on a Linux host and the global
|
|
7
|
+
* `process` is read only where a default is unavoidable. This module is that
|
|
8
|
+
* seam for everything the sandbox/guard/broker layers need.
|
|
9
|
+
*
|
|
10
|
+
* It lives in `@celestea/tools` (not core): `probe.ts`, `path-guard.ts`,
|
|
11
|
+
* `config.ts`, `child.ts` and `broker.ts` — the consumers — are all in this
|
|
12
|
+
* package, the dependency direction stays L1 → L0, and core keeps its leaf
|
|
13
|
+
* promise (W883 §6.2 P0-2 listed both locations as acceptable).
|
|
14
|
+
*/
|
|
15
|
+
import { posix, win32 } from "node:path";
|
|
16
|
+
/** true for the Windows platform id (the only place the literal lives). */
|
|
17
|
+
export function isWindows(platform = process.platform) {
|
|
18
|
+
return platform === "win32";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The path implementation of a platform (same rule as `celestea-home.ts`):
|
|
22
|
+
* deterministic across hosts, so a win32 test never touches the host's path
|
|
23
|
+
* semantics.
|
|
24
|
+
*/
|
|
25
|
+
export function pathApi(platform = process.platform) {
|
|
26
|
+
return isWindows(platform) ? win32 : posix;
|
|
27
|
+
}
|
|
28
|
+
/** `PATH` list separator: `;` on Windows, `:` everywhere else. */
|
|
29
|
+
export function pathDelimiter(platform = process.platform) {
|
|
30
|
+
return isWindows(platform) ? ";" : ":";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Executable suffixes tried when resolving a bare name on Windows. The real
|
|
34
|
+
* rule is `PATHEXT` (plus an exact-name match first, which command lookup also
|
|
35
|
+
* allows); the two ARE checked independently and must not be collapsed.
|
|
36
|
+
*/
|
|
37
|
+
export const WINDOWS_EXEC_SUFFIXES = [".exe", ".cmd", ".bat", ".com"];
|
|
38
|
+
/**
|
|
39
|
+
* The suffixes to try for `bin` on `platform`, from the injected env.
|
|
40
|
+
*
|
|
41
|
+
* `PATHEXT` is honoured when present (the operator's real resolution order) and
|
|
42
|
+
* the defaults are used otherwise. The order inside the list is significant:
|
|
43
|
+
* `.exe` before `.cmd` is what makes `bash.exe` win over a `bash.cmd`
|
|
44
|
+
* shim, which matters for the gitbash > pwsh > cmd priority.
|
|
45
|
+
*/
|
|
46
|
+
export function execSuffixes(platform = process.platform, env = {}) {
|
|
47
|
+
if (!isWindows(platform))
|
|
48
|
+
return [];
|
|
49
|
+
const raw = env["PATHEXT"];
|
|
50
|
+
const parsed = (raw ?? "").split(";").map((entry) => entry.trim().toLowerCase()).filter((entry) => entry !== "");
|
|
51
|
+
return parsed.length > 0 ? parsed : WINDOWS_EXEC_SUFFIXES;
|
|
52
|
+
}
|
|
53
|
+
/** A non-blank, trimmed env value; `undefined` when unset or blank. */
|
|
54
|
+
export function envValue(env, name) {
|
|
55
|
+
const raw = env[name];
|
|
56
|
+
if (typeof raw !== "string")
|
|
57
|
+
return undefined;
|
|
58
|
+
const trimmed = raw.trim();
|
|
59
|
+
return trimmed === "" ? undefined : trimmed;
|
|
60
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command assembly + quoting per shell (W885) — the arg the CHILD sees must be
|
|
3
|
+
* one string, whatever the shell.
|
|
4
|
+
*
|
|
5
|
+
* Three dialects, three rules, and they are not interchangeable:
|
|
6
|
+
*
|
|
7
|
+
* | shell | argv shape | quote rule |
|
|
8
|
+
* |---------|---------------------------------------------------------|------------|
|
|
9
|
+
* | posix | `sh -c <command>` | none — the command IS the argument (byte-identical to pre-W885) |
|
|
10
|
+
* | gitbash | `bash -c <command>` | POSIX single quotes (same as posix) |
|
|
11
|
+
* | pwsh | `pwsh -NoProfile -NonInteractive -Command <command>` | single quotes; an embedded `'` doubles |
|
|
12
|
+
* | cmd | `cmd /d /s /c <command>` | double quotes; an embedded `"` is backslash-escaped, and a trailing backslash run doubles |
|
|
13
|
+
*
|
|
14
|
+
* The POSIX branch is deliberately a **pass-through**: W885's hard requirement
|
|
15
|
+
* is that Linux behaviour does not change by a single byte, so no quoting is
|
|
16
|
+
* introduced where there was none.
|
|
17
|
+
*
|
|
18
|
+
* Honest limitation (this host is Linux): cmd.exe's parser is not a regular
|
|
19
|
+
* language and has no fully general escaping rule. [quoteCmd] implements the
|
|
20
|
+
* documented "wrap in double quotes, escape an embedded quote, double a
|
|
21
|
+
* trailing backslash" convention, which is correct for the lines this repo
|
|
22
|
+
* builds (`<interpreter> <script path>`) and is unit-tested for the
|
|
23
|
+
* meta-characters below — it is NOT a proof of cmd-safety for arbitrary user
|
|
24
|
+
* commands. The same caveat applies to PowerShell's single-quote rule, which is
|
|
25
|
+
* well-defined but only exercised here against strings, not against a real pwsh.
|
|
26
|
+
*/
|
|
27
|
+
import type { ShellKind } from "./exec.js";
|
|
28
|
+
/** Quote `value` for the given shell's parser (POSIX + gitbash: verbatim). */
|
|
29
|
+
export declare function quoteForShell(kind: ShellKind, value: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* One shell WORD — an interpreter, a flag, a path — quoted for `kind`, and
|
|
32
|
+
* quoted ONLY when the dialect needs it.
|
|
33
|
+
*
|
|
34
|
+
* The POSIX "only when needed" rule is what keeps the `run_code` line
|
|
35
|
+
* byte-identical to pre-W885: `python3` and `/usr/bin/node` go through
|
|
36
|
+
* verbatim exactly as they used to, while a word that WOULD be mangled (a space,
|
|
37
|
+
* a quote, a glob) now gets the historical single-quote treatment instead of
|
|
38
|
+
* being pasted in raw. pwsh and cmd quote unconditionally — their parsers have
|
|
39
|
+
* no safe set to rely on.
|
|
40
|
+
*/
|
|
41
|
+
export declare function quoteWord(kind: ShellKind, word: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* A path that is ALWAYS quoted for `kind`. The `run_code` script path has been
|
|
44
|
+
* single-quoted on POSIX since before W885 (`broker.ts` `shellQuote`), so this
|
|
45
|
+
* keeps those bytes exactly and gives cmd/pwsh their own dialect.
|
|
46
|
+
*/
|
|
47
|
+
export declare function quotePath(kind: ShellKind, path: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* POSIX single-quote a word so an absolute path with spaces stays one word
|
|
50
|
+
* (pre-W885 `broker.ts` behaviour, preserved verbatim).
|
|
51
|
+
*/
|
|
52
|
+
export declare function shellQuote(value: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* cmd.exe double-quoting: wrap in `"…"`, escape an embedded quote, and double
|
|
55
|
+
* a trailing run of backslashes (command-line quoting consumes them before the
|
|
56
|
+
* closing quote).
|
|
57
|
+
*/
|
|
58
|
+
export declare function quoteCmd(value: string): string;
|
|
59
|
+
/** Interpreters a `run_code` program can be executed with. */
|
|
60
|
+
export type RunCodeLanguageName = "typescript" | "python";
|
|
61
|
+
/** Python interpreters tried on POSIX, in order (`python3` keeps its priority). */
|
|
62
|
+
export declare const PYTHON_CANDIDATES_POSIX: readonly string[];
|
|
63
|
+
/** Python interpreters Windows actually ships (the `py` launcher included). */
|
|
64
|
+
export declare const PYTHON_CANDIDATES_WINDOWS: readonly string[];
|
|
65
|
+
/** The interpreter names to try, most preferred first, for `platform`. */
|
|
66
|
+
export declare function pythonCandidates(platform?: string): readonly string[];
|
|
67
|
+
/**
|
|
68
|
+
* The full command line one `run_code` program is executed with, quoted for
|
|
69
|
+
* `kind`. `interpreter` is an already-resolved absolute path or bare name
|
|
70
|
+
* (see `resolveInterpreter` in `run-code/broker.ts`).
|
|
71
|
+
*/
|
|
72
|
+
export declare function runCodeCommand(kind: ShellKind, language: RunCodeLanguageName, interpreter: string, scriptPath: string): string;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command assembly + quoting per shell (W885) — the arg the CHILD sees must be
|
|
3
|
+
* one string, whatever the shell.
|
|
4
|
+
*
|
|
5
|
+
* Three dialects, three rules, and they are not interchangeable:
|
|
6
|
+
*
|
|
7
|
+
* | shell | argv shape | quote rule |
|
|
8
|
+
* |---------|---------------------------------------------------------|------------|
|
|
9
|
+
* | posix | `sh -c <command>` | none — the command IS the argument (byte-identical to pre-W885) |
|
|
10
|
+
* | gitbash | `bash -c <command>` | POSIX single quotes (same as posix) |
|
|
11
|
+
* | pwsh | `pwsh -NoProfile -NonInteractive -Command <command>` | single quotes; an embedded `'` doubles |
|
|
12
|
+
* | cmd | `cmd /d /s /c <command>` | double quotes; an embedded `"` is backslash-escaped, and a trailing backslash run doubles |
|
|
13
|
+
*
|
|
14
|
+
* The POSIX branch is deliberately a **pass-through**: W885's hard requirement
|
|
15
|
+
* is that Linux behaviour does not change by a single byte, so no quoting is
|
|
16
|
+
* introduced where there was none.
|
|
17
|
+
*
|
|
18
|
+
* Honest limitation (this host is Linux): cmd.exe's parser is not a regular
|
|
19
|
+
* language and has no fully general escaping rule. [quoteCmd] implements the
|
|
20
|
+
* documented "wrap in double quotes, escape an embedded quote, double a
|
|
21
|
+
* trailing backslash" convention, which is correct for the lines this repo
|
|
22
|
+
* builds (`<interpreter> <script path>`) and is unit-tested for the
|
|
23
|
+
* meta-characters below — it is NOT a proof of cmd-safety for arbitrary user
|
|
24
|
+
* commands. The same caveat applies to PowerShell's single-quote rule, which is
|
|
25
|
+
* well-defined but only exercised here against strings, not against a real pwsh.
|
|
26
|
+
*/
|
|
27
|
+
import { isWindows } from "./paths.js";
|
|
28
|
+
/** POSIX: a literal single quote inside single quotes. */
|
|
29
|
+
const POSIX_QUOTE = String.raw `'\''`;
|
|
30
|
+
/** cmd.exe: a literal double quote inside a double-quoted argument. */
|
|
31
|
+
const CMD_QUOTE = String.raw `\"`;
|
|
32
|
+
/** Quote `value` for the given shell's parser (POSIX + gitbash: verbatim). */
|
|
33
|
+
export function quoteForShell(kind, value) {
|
|
34
|
+
if (kind === "cmd")
|
|
35
|
+
return quoteCmd(value);
|
|
36
|
+
if (kind === "pwsh")
|
|
37
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
/** Characters a POSIX shell passes through unchanged (no quoting needed). */
|
|
41
|
+
const SAFE_WORD = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
42
|
+
/**
|
|
43
|
+
* One shell WORD — an interpreter, a flag, a path — quoted for `kind`, and
|
|
44
|
+
* quoted ONLY when the dialect needs it.
|
|
45
|
+
*
|
|
46
|
+
* The POSIX "only when needed" rule is what keeps the `run_code` line
|
|
47
|
+
* byte-identical to pre-W885: `python3` and `/usr/bin/node` go through
|
|
48
|
+
* verbatim exactly as they used to, while a word that WOULD be mangled (a space,
|
|
49
|
+
* a quote, a glob) now gets the historical single-quote treatment instead of
|
|
50
|
+
* being pasted in raw. pwsh and cmd quote unconditionally — their parsers have
|
|
51
|
+
* no safe set to rely on.
|
|
52
|
+
*/
|
|
53
|
+
export function quoteWord(kind, word) {
|
|
54
|
+
if (kind === "cmd" || kind === "pwsh")
|
|
55
|
+
return quoteForShell(kind, word);
|
|
56
|
+
return SAFE_WORD.test(word) ? word : shellQuote(word);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A path that is ALWAYS quoted for `kind`. The `run_code` script path has been
|
|
60
|
+
* single-quoted on POSIX since before W885 (`broker.ts` `shellQuote`), so this
|
|
61
|
+
* keeps those bytes exactly and gives cmd/pwsh their own dialect.
|
|
62
|
+
*/
|
|
63
|
+
export function quotePath(kind, path) {
|
|
64
|
+
if (kind === "cmd" || kind === "pwsh")
|
|
65
|
+
return quoteForShell(kind, path);
|
|
66
|
+
return shellQuote(path);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* POSIX single-quote a word so an absolute path with spaces stays one word
|
|
70
|
+
* (pre-W885 `broker.ts` behaviour, preserved verbatim).
|
|
71
|
+
*/
|
|
72
|
+
export function shellQuote(value) {
|
|
73
|
+
return `'${value.replace(/'/g, POSIX_QUOTE)}'`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* cmd.exe double-quoting: wrap in `"…"`, escape an embedded quote, and double
|
|
77
|
+
* a trailing run of backslashes (command-line quoting consumes them before the
|
|
78
|
+
* closing quote).
|
|
79
|
+
*/
|
|
80
|
+
export function quoteCmd(value) {
|
|
81
|
+
const escaped = value.replace(/"/g, CMD_QUOTE);
|
|
82
|
+
const trailing = /\\+$/.exec(escaped);
|
|
83
|
+
const padded = trailing === null ? escaped : escaped + trailing[0];
|
|
84
|
+
return `"${padded}"`;
|
|
85
|
+
}
|
|
86
|
+
/** Python interpreters tried on POSIX, in order (`python3` keeps its priority). */
|
|
87
|
+
export const PYTHON_CANDIDATES_POSIX = ["python3", "python"];
|
|
88
|
+
/** Python interpreters Windows actually ships (the `py` launcher included). */
|
|
89
|
+
export const PYTHON_CANDIDATES_WINDOWS = ["python.exe", "python3.exe", "py.exe"];
|
|
90
|
+
/** The interpreter names to try, most preferred first, for `platform`. */
|
|
91
|
+
export function pythonCandidates(platform = process.platform) {
|
|
92
|
+
return isWindows(platform) ? PYTHON_CANDIDATES_WINDOWS : PYTHON_CANDIDATES_POSIX;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The full command line one `run_code` program is executed with, quoted for
|
|
96
|
+
* `kind`. `interpreter` is an already-resolved absolute path or bare name
|
|
97
|
+
* (see `resolveInterpreter` in `run-code/broker.ts`).
|
|
98
|
+
*/
|
|
99
|
+
export function runCodeCommand(kind, language, interpreter, scriptPath) {
|
|
100
|
+
const flags = language === "python" ? " -uB" : "";
|
|
101
|
+
return `${quoteWord(kind, interpreter)}${flags} ${quotePath(kind, scriptPath)}`;
|
|
102
|
+
}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tools plugin — `mount(ctx)` is the only installation path (nothing
|
|
3
|
+
* self-registers at runtime), and it publishes exactly three services:
|
|
4
|
+
*
|
|
5
|
+
* - `ToolRegistryService` → the assembled registry (schema → guard → execute);
|
|
6
|
+
* - `SandboxService` → the execution boundary `run_shell` orchestrates;
|
|
7
|
+
* - `ProcessRegistryService` → the session-scoped background process registry.
|
|
8
|
+
*
|
|
9
|
+
* The guard chain is mounted here because **order is security semantics**: the
|
|
10
|
+
* path whitelist must run before any tool execution, and `CELESTEA_TOOL_GUARD=0`
|
|
11
|
+
* is the only (explicit, documented) way to skip it.
|
|
12
|
+
*
|
|
13
|
+
* `run_code` (W255) is mounted here too, not in `builtinTools`: it needs a
|
|
14
|
+
* late-bound handle on the very registry it will dispatch sub-calls through,
|
|
15
|
+
* which only the assembly can bind — exactly like the runtime compose
|
|
16
|
+
* (`crates/runtime/src/tools.rs`). Pass `runCode: false` to leave it out.
|
|
17
|
+
*/
|
|
18
|
+
import { type Plugin, type Sandbox, type Tool, type ToolGuard, type UserQuestionService } from "@celestea/core";
|
|
19
|
+
import type { AttachmentStore } from "./attachments/store.js";
|
|
20
|
+
import { type PathGuardGrants } from "./guard/path-guard.js";
|
|
21
|
+
import { type SsrfGrantView } from "./http/ssrf.js";
|
|
22
|
+
import type { HttpRequestToolOptions } from "./tools/http-request.js";
|
|
23
|
+
import { ProcessRegistry } from "./process/registry.js";
|
|
24
|
+
import { ToolRegistryImpl } from "./registry.js";
|
|
25
|
+
import type { RunCodeEventSink } from "./run-code/broker.js";
|
|
26
|
+
import type { RunCodeConfig } from "./run-code/limits.js";
|
|
27
|
+
import { type SessionFsScope } from "./sandbox/config.js";
|
|
28
|
+
import { type SandboxGrantView } from "./sandbox/provider.js";
|
|
29
|
+
import { RegistryHandle } from "./tools/run-code.js";
|
|
30
|
+
export declare const TOOLS_PLUGIN_NAME = "celestea.tools";
|
|
31
|
+
/** `run_code` wiring (W255): broker limits + the optional sub-call event sink. */
|
|
32
|
+
export interface RunCodeMount {
|
|
33
|
+
/** Broker limits; default = `runCodeConfigFromEnv()` (CELAESTEA_RUN_CODE_TIMEOUT_MS). */
|
|
34
|
+
config?: RunCodeConfig;
|
|
35
|
+
/** Session-log sink for nested sub-call rows (see `RunCodeEventSink`). */
|
|
36
|
+
events?: RunCodeEventSink;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Per-session grants (W516) reaching the assembly point. All three views are
|
|
40
|
+
* widen-only; `undefined` (no `grants.json`) reproduces the env-derived posture
|
|
41
|
+
* byte for byte.
|
|
42
|
+
*/
|
|
43
|
+
export interface ToolAssemblyGrants extends PathGuardGrants, SandboxGrantView, SsrfGrantView {
|
|
44
|
+
}
|
|
45
|
+
export interface ToolsPluginOptions {
|
|
46
|
+
/** Tool set; default: the six builtins sharing [processes] + [sandbox]. */
|
|
47
|
+
tools?: readonly Tool[];
|
|
48
|
+
sandbox?: Sandbox;
|
|
49
|
+
processes?: ProcessRegistry;
|
|
50
|
+
/** Guard chain override: `null` disables guarding, `undefined` = env default. */
|
|
51
|
+
guard?: ToolGuard | null;
|
|
52
|
+
env?: NodeJS.ProcessEnv;
|
|
53
|
+
/** Session grants (W516): read from the session's `grants.json` by the host. */
|
|
54
|
+
grants?: ToolAssemblyGrants;
|
|
55
|
+
/**
|
|
56
|
+
* W768: the composing SESSION's own workspace (cwd + containment root for the
|
|
57
|
+
* default sandbox, writable root for the path guard). Omitted/null = the
|
|
58
|
+
* process-wide env posture, which is what a detached or legacy session keeps.
|
|
59
|
+
*/
|
|
60
|
+
scope?: SessionFsScope | null;
|
|
61
|
+
/**
|
|
62
|
+
* `run_code` mount: default = mounted; `false` = not registered. The tool is
|
|
63
|
+
* registered *before* its registry handle is bound, so sub-calls ride this
|
|
64
|
+
* assembly's exact pipeline (runtime compose parity).
|
|
65
|
+
*/
|
|
66
|
+
runCode?: RunCodeMount | false;
|
|
67
|
+
/**
|
|
68
|
+
* W783: the host's user-question service. Supplied = the default tool set also
|
|
69
|
+
* carries `ask_user_question`; absent = it does not (an embedding with no human
|
|
70
|
+
* answerer must not offer a tool that could only ever hang).
|
|
71
|
+
*/
|
|
72
|
+
questions?: UserQuestionService | null;
|
|
73
|
+
/**
|
|
74
|
+
* W804: the session's attachment store. Supplied = the default tool set also
|
|
75
|
+
* carries `read_image`; absent = it does not (no store, no image tool).
|
|
76
|
+
*/
|
|
77
|
+
attachments?: AttachmentStore | null;
|
|
78
|
+
/** W804: false ONLY when the model explicitly excludes image input (section 6.6). */
|
|
79
|
+
imageInputAllowed?: boolean;
|
|
80
|
+
/** W804: the target model id, for the read_image refusal text. */
|
|
81
|
+
model?: string;
|
|
82
|
+
}
|
|
83
|
+
/** The wired handles a compose root keeps after mounting the plugin. */
|
|
84
|
+
export interface ToolAssembly {
|
|
85
|
+
registry: ToolRegistryImpl;
|
|
86
|
+
sandbox: Sandbox;
|
|
87
|
+
processes: ProcessRegistry;
|
|
88
|
+
guardMounted: boolean;
|
|
89
|
+
/** Late-bound handle of the mounted `run_code` (`null` when disabled). */
|
|
90
|
+
runCode: RegistryHandle | null;
|
|
91
|
+
}
|
|
92
|
+
/** Build the tool assembly without mounting it (compose roots / tests). */
|
|
93
|
+
export declare function assembleTools(options?: ToolsPluginOptions): ToolAssembly;
|
|
94
|
+
/** The `http_request` options of this assembly (grants merged into allow). */
|
|
95
|
+
export declare function httpOptions(env: NodeJS.ProcessEnv, grants: SsrfGrantView): HttpRequestToolOptions;
|
|
96
|
+
export declare function toolsPlugin(options?: ToolsPluginOptions): Plugin;
|