nexus-ai-pro 2.2.0 → 2.3.0

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.
Files changed (135) hide show
  1. package/API_STABILITY.md +39 -0
  2. package/CHANGELOG.md +142 -1
  3. package/README.md +10 -5
  4. package/dist/agent/capabilities.d.ts +39 -0
  5. package/dist/agent/capabilities.js +36 -0
  6. package/dist/agent/create-agent.d.ts +61 -11
  7. package/dist/agent/create-agent.js +136 -22
  8. package/dist/agent/index.d.ts +3 -2
  9. package/dist/agent/index.js +1 -1
  10. package/dist/agent/middleware/approval.d.ts +26 -0
  11. package/dist/agent/middleware/approval.js +23 -0
  12. package/dist/agent/{middleware.d.ts → middleware/basic.d.ts} +5 -4
  13. package/dist/agent/{middleware.js → middleware/basic.js} +3 -5
  14. package/dist/agent/middleware/context-editor.d.ts +52 -0
  15. package/dist/agent/middleware/context-editor.js +66 -0
  16. package/dist/agent/middleware/filesystem.d.ts +44 -0
  17. package/dist/agent/middleware/filesystem.js +83 -0
  18. package/dist/agent/middleware/index.d.ts +19 -0
  19. package/dist/agent/middleware/index.js +9 -0
  20. package/dist/agent/middleware/limits.d.ts +42 -0
  21. package/dist/agent/middleware/limits.js +52 -0
  22. package/dist/agent/middleware/models.d.ts +48 -0
  23. package/dist/agent/middleware/models.js +44 -0
  24. package/dist/agent/middleware/pii.d.ts +67 -0
  25. package/dist/agent/middleware/pii.js +173 -0
  26. package/dist/agent/middleware/retry.d.ts +66 -0
  27. package/dist/agent/middleware/retry.js +59 -0
  28. package/dist/agent/middleware/shared.d.ts +41 -0
  29. package/dist/agent/middleware/shared.js +73 -0
  30. package/dist/agent/middleware/tool-selector.d.ts +64 -0
  31. package/dist/agent/middleware/tool-selector.js +106 -0
  32. package/dist/agent/permissions.d.ts +113 -0
  33. package/dist/agent/permissions.js +180 -0
  34. package/dist/agent/sandbox.d.ts +151 -0
  35. package/dist/agent/sandbox.js +257 -0
  36. package/dist/agent/tool.d.ts +8 -3
  37. package/dist/agent/tool.js +14 -3
  38. package/dist/deep-agent/index.d.ts +109 -0
  39. package/dist/deep-agent/index.js +216 -0
  40. package/dist/graph/functional.d.ts +9 -0
  41. package/dist/graph/functional.js +20 -3
  42. package/dist/graph/graph.js +25 -4
  43. package/dist/graph/lint.d.ts +4 -1
  44. package/dist/graph/lint.js +35 -0
  45. package/dist/postgres/fulltext.d.ts +67 -0
  46. package/dist/postgres/fulltext.js +91 -0
  47. package/dist/rag/elasticsearch.d.ts +71 -0
  48. package/dist/rag/elasticsearch.js +130 -0
  49. package/dist/rag/pipeline.d.ts +140 -0
  50. package/dist/rag/pipeline.js +187 -0
  51. package/dist/rag/rerankers.d.ts +92 -0
  52. package/dist/rag/rerankers.js +97 -0
  53. package/dist/rag/retrievers.d.ts +12 -1
  54. package/dist/server/assistant.d.ts +5 -1
  55. package/dist/server/assistant.js +4 -2
  56. package/dist/server/auth.d.ts +250 -0
  57. package/dist/server/auth.js +392 -0
  58. package/dist/store/memory.d.ts +10 -0
  59. package/dist/store/memory.js +10 -0
  60. package/dist/types/graph.d.ts +38 -0
  61. package/dist/types/messages.d.ts +36 -2
  62. package/dist/types/principal.d.ts +21 -0
  63. package/dist/types/principal.js +1 -0
  64. package/dist/types/server.d.ts +2 -9
  65. package/dist/utils/tenant.d.ts +11 -0
  66. package/dist/utils/tenant.js +14 -0
  67. package/dist/version.d.ts +1 -1
  68. package/dist/version.js +1 -1
  69. package/dist-cjs/agent/capabilities.d.ts +39 -0
  70. package/dist-cjs/agent/capabilities.js +41 -0
  71. package/dist-cjs/agent/create-agent.d.ts +61 -11
  72. package/dist-cjs/agent/create-agent.js +136 -22
  73. package/dist-cjs/agent/index.d.ts +3 -2
  74. package/dist-cjs/agent/index.js +4 -4
  75. package/dist-cjs/agent/middleware/approval.d.ts +26 -0
  76. package/dist-cjs/agent/middleware/approval.js +26 -0
  77. package/dist-cjs/agent/{middleware.d.ts → middleware/basic.d.ts} +5 -4
  78. package/dist-cjs/agent/{middleware.js → middleware/basic.js} +3 -5
  79. package/dist-cjs/agent/middleware/context-editor.d.ts +52 -0
  80. package/dist-cjs/agent/middleware/context-editor.js +70 -0
  81. package/dist-cjs/agent/middleware/filesystem.d.ts +44 -0
  82. package/dist-cjs/agent/middleware/filesystem.js +86 -0
  83. package/dist-cjs/agent/middleware/index.d.ts +19 -0
  84. package/dist-cjs/agent/middleware/index.js +28 -0
  85. package/dist-cjs/agent/middleware/limits.d.ts +42 -0
  86. package/dist-cjs/agent/middleware/limits.js +57 -0
  87. package/dist-cjs/agent/middleware/models.d.ts +48 -0
  88. package/dist-cjs/agent/middleware/models.js +48 -0
  89. package/dist-cjs/agent/middleware/pii.d.ts +67 -0
  90. package/dist-cjs/agent/middleware/pii.js +178 -0
  91. package/dist-cjs/agent/middleware/retry.d.ts +66 -0
  92. package/dist-cjs/agent/middleware/retry.js +63 -0
  93. package/dist-cjs/agent/middleware/shared.d.ts +41 -0
  94. package/dist-cjs/agent/middleware/shared.js +83 -0
  95. package/dist-cjs/agent/middleware/tool-selector.d.ts +64 -0
  96. package/dist-cjs/agent/middleware/tool-selector.js +109 -0
  97. package/dist-cjs/agent/permissions.d.ts +113 -0
  98. package/dist-cjs/agent/permissions.js +189 -0
  99. package/dist-cjs/agent/sandbox.d.ts +151 -0
  100. package/dist-cjs/agent/sandbox.js +297 -0
  101. package/dist-cjs/agent/tool.d.ts +8 -3
  102. package/dist-cjs/agent/tool.js +14 -3
  103. package/dist-cjs/deep-agent/index.d.ts +109 -0
  104. package/dist-cjs/deep-agent/index.js +219 -0
  105. package/dist-cjs/graph/functional.d.ts +9 -0
  106. package/dist-cjs/graph/functional.js +20 -3
  107. package/dist-cjs/graph/graph.js +25 -4
  108. package/dist-cjs/graph/lint.d.ts +4 -1
  109. package/dist-cjs/graph/lint.js +35 -0
  110. package/dist-cjs/postgres/fulltext.d.ts +67 -0
  111. package/dist-cjs/postgres/fulltext.js +129 -0
  112. package/dist-cjs/rag/elasticsearch.d.ts +71 -0
  113. package/dist-cjs/rag/elasticsearch.js +135 -0
  114. package/dist-cjs/rag/pipeline.d.ts +140 -0
  115. package/dist-cjs/rag/pipeline.js +191 -0
  116. package/dist-cjs/rag/rerankers.d.ts +92 -0
  117. package/dist-cjs/rag/rerankers.js +107 -0
  118. package/dist-cjs/rag/retrievers.d.ts +12 -1
  119. package/dist-cjs/server/assistant.d.ts +5 -1
  120. package/dist-cjs/server/assistant.js +4 -2
  121. package/dist-cjs/server/auth.d.ts +250 -0
  122. package/dist-cjs/server/auth.js +402 -0
  123. package/dist-cjs/store/memory.d.ts +10 -0
  124. package/dist-cjs/store/memory.js +10 -0
  125. package/dist-cjs/types/graph.d.ts +38 -0
  126. package/dist-cjs/types/messages.d.ts +36 -2
  127. package/dist-cjs/types/principal.d.ts +21 -0
  128. package/dist-cjs/types/principal.js +2 -0
  129. package/dist-cjs/types/server.d.ts +2 -9
  130. package/dist-cjs/utils/tenant.d.ts +11 -0
  131. package/dist-cjs/utils/tenant.js +15 -0
  132. package/dist-cjs/version.d.ts +1 -1
  133. package/dist-cjs/version.js +1 -1
  134. package/llms.txt +4 -3
  135. package/package.json +118 -1
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Permission policies: what an agent's tools may do, decided per call from what each call declares.
3
+ *
4
+ * Danger belongs to what a tool does, not to its name. A tool declares capabilities — a path it
5
+ * writes, a host it calls, a command it runs — and a policy grants filesystem paths, network hosts,
6
+ * and shell commands, and decides every call: allow it, deny it, or ask a person first. A call is
7
+ * denied when any of its capabilities is, asked about when any needs approval, and allowed only when
8
+ * every one is granted.
9
+ */
10
+ import type { Principal } from '../types/principal.js';
11
+ export { capabilitiesOf, isSensitiveCapability, type ParsedCapability, parseCapability } from './capabilities.js';
12
+ /** What a policy decides for one call: run it, refuse it, or interrupt for a person's approval. */
13
+ export type PermissionDecision = 'allow' | 'ask' | 'deny';
14
+ /** One tool call, as a policy sees it. */
15
+ export interface PermissionRequest {
16
+ /** The tool's name. */
17
+ tool: string;
18
+ /** The call's arguments. */
19
+ args: Record<string, unknown>;
20
+ /** What the call declares it does, or `undefined` when the tool declares nothing. */
21
+ capabilities: readonly string[] | undefined;
22
+ /** Who the run is for, when it has a principal, so a policy of your own can decide by role or scope. */
23
+ principal?: Readonly<Principal>;
24
+ }
25
+ /** A policy's decision, with the reason a person or a model reads. */
26
+ export interface PermissionVerdict {
27
+ /** The decision. */
28
+ decision: PermissionDecision;
29
+ /** Why, naming the capability that decided it. */
30
+ reason: string;
31
+ /** The capability that decided it, when one did. */
32
+ capability?: string;
33
+ }
34
+ /** Anything that decides tool calls. `createAgent({ permissions })` takes one. */
35
+ export interface PermissionPolicyLike {
36
+ /** Decides one call. */
37
+ decide(request: PermissionRequest): PermissionVerdict | Promise<PermissionVerdict>;
38
+ }
39
+ /** What a policy grants. Anything not granted is denied unless `ungranted` says otherwise. */
40
+ export interface PermissionRules {
41
+ /**
42
+ * Paths a tool may read and write, as globs: `*` within one path segment, `**` across segments, so
43
+ * `/workspace/**` is the workspace and everything in it. A write grant also allows reading.
44
+ */
45
+ filesystem?: {
46
+ read?: readonly string[];
47
+ write?: readonly string[];
48
+ };
49
+ /** Hosts a tool may reach: `api.github.com`, `*.openai.com` for its subdomains, or `*` for any. */
50
+ network?: {
51
+ allow?: readonly string[];
52
+ };
53
+ /**
54
+ * Commands a tool may run, each the start of a command line: `git` allows every git command, and
55
+ * `npm test` only that. A command line that chains, pipes, redirects, or substitutes is never
56
+ * granted by these, only by `*`.
57
+ */
58
+ shell?: {
59
+ allow?: readonly string[];
60
+ };
61
+ /** Running code a tool was given. Defaults to `deny`; a sandboxed interpreter is the place for `ask` or `allow`. */
62
+ code?: PermissionDecision;
63
+ /** Decisions for the application's own capabilities, by kind or by full capability: `{ payments: 'ask' }`. */
64
+ custom?: Readonly<Record<string, PermissionDecision>>;
65
+ /**
66
+ * Capabilities that need a person's approval even when granted, as patterns: `shell`,
67
+ * `filesystem:write`, `network:*.stripe.com`, `payments`.
68
+ */
69
+ ask?: readonly string[];
70
+ /** A tool that declares no capabilities. Defaults to `deny`: a policy cannot judge what it cannot see. */
71
+ undeclared?: PermissionDecision;
72
+ /** A capability no grant covers. Defaults to `deny`. */
73
+ ungranted?: 'ask' | 'deny';
74
+ /** Decisions per tool name, applied before anything else. */
75
+ tools?: Readonly<Record<string, PermissionDecision>>;
76
+ /** What a relative path is resolved against. Defaults to `/`. */
77
+ root?: string;
78
+ }
79
+ /**
80
+ * Builds a policy from what it grants.
81
+ *
82
+ * ```ts
83
+ * const permissions = permissionPolicy({
84
+ * filesystem: { read: ['/workspace/**'], write: ['/workspace/output/**'] },
85
+ * network: { allow: ['api.github.com', '*.openai.com'] },
86
+ * shell: { allow: ['git', 'npm test'] },
87
+ * ask: ['shell', 'filesystem:write'],
88
+ * });
89
+ * const agent = createAgent({ client, tools, permissions, checkpointer });
90
+ * ```
91
+ */
92
+ export declare function permissionPolicy(rules: PermissionRules): PermissionPolicy;
93
+ /** A policy built from `PermissionRules`. Deterministic: the same call always gets the same decision. */
94
+ export declare class PermissionPolicy implements PermissionPolicyLike {
95
+ /** What the policy grants. */
96
+ readonly rules: PermissionRules;
97
+ constructor(
98
+ /** What the policy grants. */
99
+ rules: PermissionRules);
100
+ /** Decides one call from its declared capabilities. */
101
+ decide(request: PermissionRequest): PermissionVerdict;
102
+ /** Decides one capability: granted or not, then whether it needs approval. */
103
+ decideOne(capability: string): PermissionVerdict;
104
+ private shown;
105
+ private root;
106
+ private granted;
107
+ }
108
+ /**
109
+ * A path made absolute and normalized, with `.` and `..` resolved, so `/workspace/../etc` is
110
+ * `/etc` before any grant sees it. Backslashes count as separators. `null` for a path that could
111
+ * never be safe to judge, such as one holding a NUL.
112
+ */
113
+ export declare function normalizePath(path: string, root?: string): string | null;
@@ -0,0 +1,180 @@
1
+ import { parseCapability } from './capabilities.js';
2
+ export { capabilitiesOf, isSensitiveCapability, parseCapability } from './capabilities.js';
3
+ const ORDER = { allow: 0, ask: 1, deny: 2 };
4
+ const CHAINING = /[;&|`$<>\n\r]/;
5
+ export function permissionPolicy(rules) {
6
+ return new PermissionPolicy(rules);
7
+ }
8
+ export class PermissionPolicy {
9
+ rules;
10
+ constructor(rules) {
11
+ this.rules = rules;
12
+ }
13
+ decide(request) {
14
+ const forced = this.rules.tools?.[request.tool];
15
+ if (forced)
16
+ return { decision: forced, reason: `"${request.tool}" is set to ${forced} by name` };
17
+ if (request.capabilities === undefined) {
18
+ const decision = this.rules.undeclared ?? 'deny';
19
+ return {
20
+ decision,
21
+ reason: `"${request.tool}" declares no capabilities, so the policy cannot see what it does`,
22
+ };
23
+ }
24
+ let verdict = { decision: 'allow', reason: `every capability of "${request.tool}" is granted` };
25
+ for (const capability of request.capabilities) {
26
+ const next = this.decideOne(capability);
27
+ if (ORDER[next.decision] > ORDER[verdict.decision])
28
+ verdict = next;
29
+ if (verdict.decision === 'deny')
30
+ break;
31
+ }
32
+ return verdict;
33
+ }
34
+ decideOne(capability) {
35
+ const parsed = parseCapability(capability);
36
+ const shown = this.shown(capability, parsed);
37
+ const granted = this.granted(parsed);
38
+ if (granted === 'deny') {
39
+ return { decision: this.rules.ungranted ?? 'deny', reason: `${shown} is not granted`, capability };
40
+ }
41
+ if (granted === 'ask' ||
42
+ (this.rules.ask ?? []).some((pattern) => capabilityMatches(pattern, parsed, this.root()))) {
43
+ return { decision: 'ask', reason: `${shown} needs approval`, capability };
44
+ }
45
+ return { decision: 'allow', reason: `${shown} is granted`, capability };
46
+ }
47
+ shown(capability, parsed) {
48
+ if (parsed.kind !== 'filesystem' || parsed.target === undefined)
49
+ return capability;
50
+ const resolved = normalizePath(parsed.target, this.root());
51
+ return resolved === null ? capability : `filesystem:${parsed.access ?? 'write'}:${resolved}`;
52
+ }
53
+ root() {
54
+ return this.rules.root ?? '/';
55
+ }
56
+ granted(parsed) {
57
+ switch (parsed.kind) {
58
+ case 'filesystem': {
59
+ const path = parsed.target === undefined ? undefined : normalizePath(parsed.target, this.root());
60
+ if (path === null)
61
+ return 'deny';
62
+ const writes = this.rules.filesystem?.write ?? [];
63
+ const reads = [...(this.rules.filesystem?.read ?? []), ...writes];
64
+ const globs = parsed.access === 'read' ? reads : writes;
65
+ const matches = (glob) => path === undefined
66
+ ? glob === '**' || glob === '/**'
67
+ : globToRegExp(normalizePath(glob, this.root()) ?? '').test(path);
68
+ return globs.some(matches) ? 'allow' : 'deny';
69
+ }
70
+ case 'network': {
71
+ const host = parsed.target === undefined ? undefined : hostOf(parsed.target);
72
+ const allowed = this.rules.network?.allow ?? [];
73
+ return allowed.some((pattern) => hostMatches(pattern, host)) ? 'allow' : 'deny';
74
+ }
75
+ case 'shell': {
76
+ const allowed = this.rules.shell?.allow ?? [];
77
+ if (allowed.includes('*'))
78
+ return 'allow';
79
+ const command = parsed.target?.trim();
80
+ if (!command || CHAINING.test(command))
81
+ return 'deny';
82
+ const tokens = command.split(/\s+/);
83
+ return allowed.some((entry) => {
84
+ const prefix = entry.trim().split(/\s+/);
85
+ return prefix.every((token, index) => tokens[index] === token);
86
+ })
87
+ ? 'allow'
88
+ : 'deny';
89
+ }
90
+ case 'code':
91
+ return this.rules.code ?? 'deny';
92
+ default: {
93
+ const custom = this.rules.custom ?? {};
94
+ const full = parsed.target === undefined ? parsed.kind : `${parsed.kind}:${parsed.target}`;
95
+ return custom[full] ?? custom[parsed.kind] ?? 'deny';
96
+ }
97
+ }
98
+ }
99
+ }
100
+ function capabilityMatches(pattern, capability, root) {
101
+ const wanted = parseCapability(pattern);
102
+ if (wanted.kind !== capability.kind)
103
+ return false;
104
+ if (wanted.access && wanted.access !== capability.access)
105
+ return false;
106
+ if (wanted.target === undefined)
107
+ return true;
108
+ if (capability.target === undefined)
109
+ return false;
110
+ if (capability.kind === 'network')
111
+ return hostMatches(wanted.target, hostOf(capability.target));
112
+ if (capability.kind === 'filesystem') {
113
+ const path = normalizePath(capability.target, root);
114
+ return path !== null && globToRegExp(normalizePath(wanted.target, root) ?? '').test(path);
115
+ }
116
+ return globToRegExp(wanted.target).test(capability.target);
117
+ }
118
+ export function normalizePath(path, root = '/') {
119
+ if (path.includes('\0'))
120
+ return null;
121
+ const unified = path.replace(/\\/g, '/');
122
+ const absolute = /^([A-Za-z]:)?\//.test(unified)
123
+ ? unified
124
+ : `${root.replace(/\\/g, '/').replace(/\/+$/, '')}/${unified}`;
125
+ const drive = /^[A-Za-z]:/.exec(absolute)?.[0]?.toLowerCase() ?? '';
126
+ const parts = [];
127
+ for (const segment of absolute.slice(drive.length).split('/')) {
128
+ if (segment === '' || segment === '.')
129
+ continue;
130
+ if (segment === '..')
131
+ parts.pop();
132
+ else
133
+ parts.push(segment);
134
+ }
135
+ return `${drive}/${parts.join('/')}`;
136
+ }
137
+ function globToRegExp(glob) {
138
+ let source = '';
139
+ for (let index = 0; index < glob.length; index += 1) {
140
+ const char = glob[index];
141
+ if (char === '*' && glob[index + 1] === '*') {
142
+ const atEnd = index + 2 === glob.length;
143
+ if (atEnd && source.endsWith('/')) {
144
+ source = `${source.slice(0, -1)}(?:/.*)?`;
145
+ }
146
+ else {
147
+ source += '.*';
148
+ }
149
+ index += 1;
150
+ }
151
+ else if (char === '*') {
152
+ source += '[^/]*';
153
+ }
154
+ else if (char === '?') {
155
+ source += '[^/]';
156
+ }
157
+ else {
158
+ source += char.replace(/[.+^${}()|[\]\\]/g, '\\$&');
159
+ }
160
+ }
161
+ return new RegExp(`^${source}$`, 'i');
162
+ }
163
+ function hostOf(target) {
164
+ try {
165
+ return new URL(target.includes('://') ? target : `https://${target}`).hostname.toLowerCase();
166
+ }
167
+ catch {
168
+ return target.toLowerCase();
169
+ }
170
+ }
171
+ function hostMatches(pattern, host) {
172
+ const wanted = pattern.trim().toLowerCase();
173
+ if (wanted === '*')
174
+ return true;
175
+ if (host === undefined)
176
+ return false;
177
+ if (wanted.startsWith('*.'))
178
+ return host.endsWith(wanted.slice(1)) && host.length > wanted.length - 1;
179
+ return host === wanted;
180
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * The sandbox contract: where an agent's commands and code run, and where its files live.
3
+ *
4
+ * The package ships the contract and a conformance suite, not the isolation: a container, a VM, a
5
+ * remote interpreter, or a hosted sandbox fills the `Sandbox` interface. `processSandbox()` is a
6
+ * reference for development, which runs commands as ordinary processes; it says so in its
7
+ * `isolation`, and is never a security boundary.
8
+ */
9
+ import type { ToolDefinition } from '../types/messages.js';
10
+ /** Options for one command. */
11
+ export interface SandboxExecOptions {
12
+ /** The working directory, inside the sandbox. Defaults to its root. */
13
+ cwd?: string;
14
+ /** Environment variables for the command. The host's own are never passed through. */
15
+ env?: Record<string, string>;
16
+ /** Sent to the command's standard input. */
17
+ stdin?: string;
18
+ /** Stops the command after this many milliseconds. */
19
+ timeoutMs?: number;
20
+ /** Stops the command when aborted. */
21
+ signal?: AbortSignal;
22
+ }
23
+ /** What a command did. */
24
+ export interface SandboxExecResult {
25
+ /** Its exit code, or `null` when it was stopped. */
26
+ exitCode: number | null;
27
+ /** What it wrote to standard output. */
28
+ stdout: string;
29
+ /** What it wrote to standard error. */
30
+ stderr: string;
31
+ /** True when it was stopped by its timeout. */
32
+ timedOut: boolean;
33
+ /** How long it ran, in milliseconds. */
34
+ durationMs: number;
35
+ }
36
+ /** What a sandbox claims to isolate. The conformance suite checks the claims it can observe. */
37
+ export interface SandboxIsolation {
38
+ /** Commands cannot read or write the host's files. */
39
+ filesystem: boolean;
40
+ /** Commands cannot reach the network, or only what the sandbox allows. */
41
+ network: boolean;
42
+ /** Commands cannot see or signal the host's processes. */
43
+ processes: boolean;
44
+ }
45
+ /** Where an agent's commands, code, and files go. The application provides one. */
46
+ export interface Sandbox {
47
+ /** Names the sandbox in reports. */
48
+ readonly name: string;
49
+ /** What it isolates. */
50
+ readonly isolation: SandboxIsolation;
51
+ /** Runs a command line in the sandbox. */
52
+ exec(command: string, options?: SandboxExecOptions): Promise<SandboxExecResult>;
53
+ /** Reads a file, by a path inside the sandbox. */
54
+ readFile(file: string): Promise<string>;
55
+ /** Writes a file, creating its directory. */
56
+ writeFile(file: string, content: string): Promise<void>;
57
+ /** Lists a directory's entries. */
58
+ listFiles?(directory?: string): Promise<string[]>;
59
+ /** Removes a file or directory. */
60
+ removeFile?(file: string): Promise<void>;
61
+ /** Releases the sandbox. */
62
+ dispose?(): Promise<void>;
63
+ }
64
+ /** Raised when a path would leave the sandbox. */
65
+ export declare class SandboxPathError extends Error {
66
+ /** The path that was refused. */
67
+ readonly path: string;
68
+ /** Always `SANDBOX_PATH`. */
69
+ readonly code = "SANDBOX_PATH";
70
+ constructor(
71
+ /** The path that was refused. */
72
+ path: string);
73
+ }
74
+ /** Options for `processSandbox()`. */
75
+ export interface ProcessSandboxOptions {
76
+ /** The directory commands run in and files live under. Created when missing. */
77
+ root: string;
78
+ /** Environment variables every command gets, on top of a minimal `PATH`. */
79
+ env?: Record<string, string>;
80
+ /** Timeout for a command that sets none. Defaults to 30 seconds. */
81
+ timeoutMs?: number;
82
+ /** Output kept per stream, in bytes. Defaults to 1 MB. */
83
+ maxOutputBytes?: number;
84
+ }
85
+ /**
86
+ * A sandbox that runs commands as ordinary processes in a directory, for development and tests only.
87
+ *
88
+ * Its file methods refuse any path outside `root`, and commands get only `PATH` and the variables
89
+ * given, never the host's environment. But a command it runs can read and write anything the user
90
+ * can, and reach any host: `isolation` says so. Use a container or a VM in production.
91
+ */
92
+ export declare function processSandbox(options: ProcessSandboxOptions): Sandbox;
93
+ /** Options for `sandboxTools()`. */
94
+ export interface SandboxToolsOptions {
95
+ /** Offer `run_command`. Defaults to true. */
96
+ shell?: boolean;
97
+ /** Offer `read_file`, `write_file`, and `list_files`. Defaults to true. */
98
+ files?: boolean;
99
+ /**
100
+ * The path a permission policy sees the sandbox's files under. Defaults to `/workspace`, so a
101
+ * policy granting `/workspace/**` grants the sandbox.
102
+ */
103
+ mount?: string;
104
+ /** Timeout for each command. */
105
+ timeoutMs?: number;
106
+ }
107
+ /**
108
+ * Tools that act through a sandbox, each declaring exactly what one call does: `run_command`
109
+ * declares `shell:<the command>`, and the file tools declare `filesystem:read` or
110
+ * `filesystem:write` with the path under `mount`. A permission policy can therefore grant a
111
+ * workspace, a few commands, and nothing else.
112
+ */
113
+ export declare function sandboxTools(sandbox: Sandbox, options?: SandboxToolsOptions): ToolDefinition[];
114
+ /** One conformance check's result. */
115
+ export interface SandboxConformanceCheck {
116
+ /** What was checked. */
117
+ name: string;
118
+ /** Whether it held. */
119
+ ok: boolean;
120
+ /** What went wrong, when it did not. */
121
+ detail?: string;
122
+ }
123
+ /** What `runSandboxConformance()` found. */
124
+ export interface SandboxConformanceReport {
125
+ /** The sandbox's name. */
126
+ sandbox: string;
127
+ /** True when every check held. */
128
+ passed: boolean;
129
+ /** Every check, in order. */
130
+ checks: SandboxConformanceCheck[];
131
+ }
132
+ /** Options for `runSandboxConformance()`. */
133
+ export interface SandboxConformanceOptions {
134
+ /** The command that runs JavaScript inside the sandbox. Defaults to `node`. */
135
+ node?: string;
136
+ /** The timeout the timeout check sets, in milliseconds. Defaults to 300. */
137
+ timeoutMs?: number;
138
+ }
139
+ /**
140
+ * Checks a sandbox against the contract, without a test framework, so any sandbox — a container
141
+ * runner, a VM, a hosted service — can prove itself the same way:
142
+ *
143
+ * - commands report their output, errors, and exit code, take standard input and the variables
144
+ * given, and never see the host's environment;
145
+ * - a command past its timeout is stopped and reported as timed out;
146
+ * - commands run where the files are, and files round-trip;
147
+ * - a path outside the sandbox is refused.
148
+ *
149
+ * Every check runs on a fresh sandbox from `create`, which is disposed afterwards.
150
+ */
151
+ export declare function runSandboxConformance(create: () => Sandbox | Promise<Sandbox>, options?: SandboxConformanceOptions): Promise<SandboxConformanceReport>;