@tanstack/ai-sandbox 0.1.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.
- package/README.md +182 -0
- package/dist/esm/agents-file.d.ts +36 -0
- package/dist/esm/agents-file.js +44 -0
- package/dist/esm/agents-file.js.map +1 -0
- package/dist/esm/approvals.d.ts +38 -0
- package/dist/esm/approvals.js +36 -0
- package/dist/esm/approvals.js.map +1 -0
- package/dist/esm/bootstrap.d.ts +17 -0
- package/dist/esm/bootstrap.js +124 -0
- package/dist/esm/bootstrap.js.map +1 -0
- package/dist/esm/bridge-events.d.ts +21 -0
- package/dist/esm/bridge-events.js +76 -0
- package/dist/esm/bridge-events.js.map +1 -0
- package/dist/esm/capabilities.d.ts +26 -0
- package/dist/esm/capabilities.js +29 -0
- package/dist/esm/capabilities.js.map +1 -0
- package/dist/esm/contracts.d.ts +211 -0
- package/dist/esm/errors.d.ts +16 -0
- package/dist/esm/errors.js +25 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/git-exec.d.ts +2 -0
- package/dist/esm/git-exec.js +68 -0
- package/dist/esm/git-exec.js.map +1 -0
- package/dist/esm/harness-cwd.d.ts +2 -0
- package/dist/esm/harness-cwd.js +24 -0
- package/dist/esm/harness-cwd.js.map +1 -0
- package/dist/esm/index.d.ts +39 -0
- package/dist/esm/index.js +103 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/key.d.ts +20 -0
- package/dist/esm/key.js +41 -0
- package/dist/esm/key.js.map +1 -0
- package/dist/esm/middleware.d.ts +5 -0
- package/dist/esm/middleware.js +140 -0
- package/dist/esm/middleware.js.map +1 -0
- package/dist/esm/ngrok.d.ts +16 -0
- package/dist/esm/ngrok.js +54 -0
- package/dist/esm/ngrok.js.map +1 -0
- package/dist/esm/policy.d.ts +47 -0
- package/dist/esm/policy.js +44 -0
- package/dist/esm/policy.js.map +1 -0
- package/dist/esm/projection.d.ts +31 -0
- package/dist/esm/projection.js +9 -0
- package/dist/esm/projection.js.map +1 -0
- package/dist/esm/remote-tools.d.ts +48 -0
- package/dist/esm/remote-tools.js +76 -0
- package/dist/esm/remote-tools.js.map +1 -0
- package/dist/esm/run-log.d.ts +81 -0
- package/dist/esm/run-log.js +107 -0
- package/dist/esm/run-log.js.map +1 -0
- package/dist/esm/run.d.ts +58 -0
- package/dist/esm/run.js +89 -0
- package/dist/esm/run.js.map +1 -0
- package/dist/esm/runner.d.ts +21 -0
- package/dist/esm/runner.js +54 -0
- package/dist/esm/runner.js.map +1 -0
- package/dist/esm/sandbox.d.ts +79 -0
- package/dist/esm/sandbox.js +125 -0
- package/dist/esm/sandbox.js.map +1 -0
- package/dist/esm/secrets.d.ts +37 -0
- package/dist/esm/secrets.js +59 -0
- package/dist/esm/secrets.js.map +1 -0
- package/dist/esm/setup-plan.d.ts +13 -0
- package/dist/esm/setup-plan.js +16 -0
- package/dist/esm/setup-plan.js.map +1 -0
- package/dist/esm/shell.d.ts +45 -0
- package/dist/esm/shell.js +164 -0
- package/dist/esm/shell.js.map +1 -0
- package/dist/esm/store.d.ts +53 -0
- package/dist/esm/store.js +34 -0
- package/dist/esm/store.js.map +1 -0
- package/dist/esm/tool-bridge.d.ts +130 -0
- package/dist/esm/tool-bridge.js +197 -0
- package/dist/esm/tool-bridge.js.map +1 -0
- package/dist/esm/watch.d.ts +36 -0
- package/dist/esm/watch.js +144 -0
- package/dist/esm/watch.js.map +1 -0
- package/dist/esm/workspace.d.ts +128 -0
- package/dist/esm/workspace.js +42 -0
- package/dist/esm/workspace.js.map +1 -0
- package/package.json +72 -0
- package/skills/ai-sandbox/SKILL.md +366 -0
- package/src/agents-file.ts +101 -0
- package/src/approvals.ts +96 -0
- package/src/bootstrap.ts +196 -0
- package/src/bridge-events.ts +112 -0
- package/src/capabilities.ts +47 -0
- package/src/contracts.ts +236 -0
- package/src/errors.ts +31 -0
- package/src/git-exec.ts +114 -0
- package/src/harness-cwd.ts +38 -0
- package/src/index.ts +222 -0
- package/src/key.ts +70 -0
- package/src/middleware.ts +233 -0
- package/src/ngrok.ts +85 -0
- package/src/policy.ts +111 -0
- package/src/projection.ts +46 -0
- package/src/remote-tools.ts +180 -0
- package/src/run-log.ts +224 -0
- package/src/run.ts +167 -0
- package/src/runner.ts +99 -0
- package/src/sandbox.ts +259 -0
- package/src/secrets.ts +101 -0
- package/src/setup-plan.ts +25 -0
- package/src/shell.ts +288 -0
- package/src/store.ts +83 -0
- package/src/tool-bridge.ts +399 -0
- package/src/watch.ts +256 -0
- package/src/workspace.ts +151 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SandboxHandle } from './contracts.js';
|
|
2
|
+
import { LockStore, SandboxStore } from './store.js';
|
|
3
|
+
import { SandboxPolicy } from './policy.js';
|
|
4
|
+
import { ToolBridgeProvisioner } from './tool-bridge.js';
|
|
5
|
+
export declare const SandboxCapability: import('@tanstack/ai').Capability<SandboxHandle, "sandbox">;
|
|
6
|
+
export declare const SandboxStoreCapability: import('@tanstack/ai').Capability<SandboxStore, "sandbox-store">;
|
|
7
|
+
export declare const LocksCapability: import('@tanstack/ai').Capability<LockStore, "locks">;
|
|
8
|
+
/**
|
|
9
|
+
* The active sandbox policy, provided by `withSandbox` from the definition.
|
|
10
|
+
* Harness adapters read it to map allow/ask/deny rules onto their native
|
|
11
|
+
* permission system.
|
|
12
|
+
*/
|
|
13
|
+
export declare const SandboxPolicyCapability: import('@tanstack/ai').Capability<SandboxPolicy, "sandbox-policy">;
|
|
14
|
+
/**
|
|
15
|
+
* Provisions the MCP tool-bridge endpoint for a run. OPTIONALLY provided by a
|
|
16
|
+
* serverless/edge orchestrator (e.g. a Durable Object) to override the default
|
|
17
|
+
* `node:http` host transport. Harness adapters read it via `getOptional` and
|
|
18
|
+
* fall back to `nodeHttpBridgeProvisioner` when absent.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ToolBridgeProvisionerCapability: import('@tanstack/ai').Capability<ToolBridgeProvisioner, "tool-bridge-provisioner">;
|
|
21
|
+
/** Destructured accessors for adapters: `getSandbox(ctx)` reads the handle. */
|
|
22
|
+
export declare const getSandbox: import('@tanstack/ai').CapabilityGetter<SandboxHandle>, provideSandbox: import('@tanstack/ai').CapabilityProvider<SandboxHandle>;
|
|
23
|
+
export declare const getSandboxStore: import('@tanstack/ai').CapabilityGetter<SandboxStore>, provideSandboxStore: import('@tanstack/ai').CapabilityProvider<SandboxStore>;
|
|
24
|
+
export declare const getLocks: import('@tanstack/ai').CapabilityGetter<LockStore>, provideLocks: import('@tanstack/ai').CapabilityProvider<LockStore>;
|
|
25
|
+
export declare const getSandboxPolicy: import('@tanstack/ai').CapabilityGetter<SandboxPolicy>, provideSandboxPolicy: import('@tanstack/ai').CapabilityProvider<SandboxPolicy>;
|
|
26
|
+
export declare const getToolBridgeProvisioner: import('@tanstack/ai').CapabilityGetter<ToolBridgeProvisioner>, provideToolBridgeProvisioner: import('@tanstack/ai').CapabilityProvider<ToolBridgeProvisioner>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createCapability } from "@tanstack/ai";
|
|
2
|
+
const SandboxCapability = createCapability()("sandbox");
|
|
3
|
+
const SandboxStoreCapability = createCapability()("sandbox-store");
|
|
4
|
+
const LocksCapability = createCapability()("locks");
|
|
5
|
+
const SandboxPolicyCapability = createCapability()("sandbox-policy");
|
|
6
|
+
const ToolBridgeProvisionerCapability = createCapability()("tool-bridge-provisioner");
|
|
7
|
+
const [getSandbox, provideSandbox] = SandboxCapability;
|
|
8
|
+
const [getSandboxStore, provideSandboxStore] = SandboxStoreCapability;
|
|
9
|
+
const [getLocks, provideLocks] = LocksCapability;
|
|
10
|
+
const [getSandboxPolicy, provideSandboxPolicy] = SandboxPolicyCapability;
|
|
11
|
+
const [getToolBridgeProvisioner, provideToolBridgeProvisioner] = ToolBridgeProvisionerCapability;
|
|
12
|
+
export {
|
|
13
|
+
LocksCapability,
|
|
14
|
+
SandboxCapability,
|
|
15
|
+
SandboxPolicyCapability,
|
|
16
|
+
SandboxStoreCapability,
|
|
17
|
+
ToolBridgeProvisionerCapability,
|
|
18
|
+
getLocks,
|
|
19
|
+
getSandbox,
|
|
20
|
+
getSandboxPolicy,
|
|
21
|
+
getSandboxStore,
|
|
22
|
+
getToolBridgeProvisioner,
|
|
23
|
+
provideLocks,
|
|
24
|
+
provideSandbox,
|
|
25
|
+
provideSandboxPolicy,
|
|
26
|
+
provideSandboxStore,
|
|
27
|
+
provideToolBridgeProvisioner
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sources":["../../src/capabilities.ts"],"sourcesContent":["/**\n * Capability tokens the sandbox layer provides/consumes through the\n * `@tanstack/ai` middleware capability system.\n *\n * - `SandboxCapability` is PROVIDED by `withSandbox` and REQUIRED by harness\n * adapters (`requires: [SandboxCapability]`).\n * - `SandboxStoreCapability` / `LocksCapability` are OPTIONALLY required by\n * `withSandbox`. v1 falls back to in-memory defaults; the future persistence\n * package PROVIDES durable implementations.\n */\nimport { createCapability } from '@tanstack/ai'\nimport type { SandboxHandle } from './contracts'\nimport type { LockStore, SandboxStore } from './store'\nimport type { SandboxPolicy } from './policy'\nimport type { ToolBridgeProvisioner } from './tool-bridge'\n\nexport const SandboxCapability = createCapability<SandboxHandle>()('sandbox')\n\nexport const SandboxStoreCapability =\n createCapability<SandboxStore>()('sandbox-store')\n\nexport const LocksCapability = createCapability<LockStore>()('locks')\n\n/**\n * The active sandbox policy, provided by `withSandbox` from the definition.\n * Harness adapters read it to map allow/ask/deny rules onto their native\n * permission system.\n */\nexport const SandboxPolicyCapability =\n createCapability<SandboxPolicy>()('sandbox-policy')\n\n/**\n * Provisions the MCP tool-bridge endpoint for a run. OPTIONALLY provided by a\n * serverless/edge orchestrator (e.g. a Durable Object) to override the default\n * `node:http` host transport. Harness adapters read it via `getOptional` and\n * fall back to `nodeHttpBridgeProvisioner` when absent.\n */\nexport const ToolBridgeProvisionerCapability =\n createCapability<ToolBridgeProvisioner>()('tool-bridge-provisioner')\n\n/** Destructured accessors for adapters: `getSandbox(ctx)` reads the handle. */\nexport const [getSandbox, provideSandbox] = SandboxCapability\nexport const [getSandboxStore, provideSandboxStore] = SandboxStoreCapability\nexport const [getLocks, provideLocks] = LocksCapability\nexport const [getSandboxPolicy, provideSandboxPolicy] = SandboxPolicyCapability\nexport const [getToolBridgeProvisioner, provideToolBridgeProvisioner] =\n ToolBridgeProvisionerCapability\n"],"names":[],"mappings":";AAgBO,MAAM,oBAAoB,iBAAA,EAAkC,SAAS;AAErE,MAAM,yBACX,iBAAA,EAAiC,eAAe;AAE3C,MAAM,kBAAkB,iBAAA,EAA8B,OAAO;AAO7D,MAAM,0BACX,iBAAA,EAAkC,gBAAgB;AAQ7C,MAAM,kCACX,iBAAA,EAA0C,yBAAyB;AAG9D,MAAM,CAAC,YAAY,cAAc,IAAI;AACrC,MAAM,CAAC,iBAAiB,mBAAmB,IAAI;AAC/C,MAAM,CAAC,UAAU,YAAY,IAAI;AACjC,MAAM,CAAC,kBAAkB,oBAAoB,IAAI;AACjD,MAAM,CAAC,0BAA0B,4BAA4B,IAClE;"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { WorkspaceDefinition } from './workspace.js';
|
|
2
|
+
import { SandboxPolicy } from './policy.js';
|
|
3
|
+
/** Static description of what a provider supports. */
|
|
4
|
+
export interface SandboxCapabilities {
|
|
5
|
+
/** Read/write/list/… via {@link SandboxFs}. Always true (mandatory). */
|
|
6
|
+
fs: boolean;
|
|
7
|
+
/** Blocking command execution via {@link SandboxProcess.exec}. Always true (mandatory). */
|
|
8
|
+
exec: boolean;
|
|
9
|
+
/** Per-create / per-command environment variables. */
|
|
10
|
+
env: boolean;
|
|
11
|
+
/** Expose a port and resolve a reachable channel via {@link SandboxPorts}. */
|
|
12
|
+
ports: boolean;
|
|
13
|
+
/** Long-running/background processes via {@link SandboxProcess.spawn}. */
|
|
14
|
+
backgroundProcesses: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* A spawned process exposes a writable host→process stdin
|
|
17
|
+
* ({@link SpawnHandle.stdin}). `true` for host/Docker; some edge providers
|
|
18
|
+
* (e.g. Cloudflare) run background processes WITHOUT a writable stdin, so
|
|
19
|
+
* harness adapters that feed a prompt over stdin must instead deliver it via a
|
|
20
|
+
* file + shell redirection.
|
|
21
|
+
*/
|
|
22
|
+
writableStdin: boolean;
|
|
23
|
+
/** Capture/restore filesystem snapshots via {@link SandboxHandle.snapshot}. */
|
|
24
|
+
snapshots: boolean;
|
|
25
|
+
/** Declarative network egress allow/deny policy. */
|
|
26
|
+
networkPolicy: boolean;
|
|
27
|
+
/** Filesystem persists across sandbox stop/restart without a snapshot. */
|
|
28
|
+
durableFilesystem: boolean;
|
|
29
|
+
/** Branch a new sandbox from current state via {@link SandboxHandle.fork}. */
|
|
30
|
+
fork: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** Result of a blocking command. */
|
|
33
|
+
export interface ExecResult {
|
|
34
|
+
stdout: string;
|
|
35
|
+
stderr: string;
|
|
36
|
+
exitCode: number;
|
|
37
|
+
}
|
|
38
|
+
/** Options for {@link SandboxProcess.exec} / {@link SandboxProcess.spawn}. */
|
|
39
|
+
export interface ProcessOptions {
|
|
40
|
+
/** Working directory inside the sandbox. Defaults to the workspace root. */
|
|
41
|
+
cwd?: string;
|
|
42
|
+
/** Per-command environment variables, merged over the sandbox env. */
|
|
43
|
+
env?: Record<string, string>;
|
|
44
|
+
/** Abort the command/process when this signal fires. */
|
|
45
|
+
signal?: AbortSignal;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A live background process. `stdout`/`stderr` are async-iterables of decoded
|
|
49
|
+
* chunks; `stdin.write` feeds the process (duplex — required for ACP harness
|
|
50
|
+
* protocols such as Codex / Gemini CLI). There is intentionally NO
|
|
51
|
+
* reconnect-to-a-running-process in v1 — that belongs to the durable-stream /
|
|
52
|
+
* persistence layer.
|
|
53
|
+
*/
|
|
54
|
+
export interface SpawnHandle {
|
|
55
|
+
readonly pid: number;
|
|
56
|
+
readonly stdout: AsyncIterable<string>;
|
|
57
|
+
readonly stderr: AsyncIterable<string>;
|
|
58
|
+
readonly stdin: {
|
|
59
|
+
write: (data: string) => Promise<void>;
|
|
60
|
+
end: () => Promise<void>;
|
|
61
|
+
};
|
|
62
|
+
/** Resolves with the exit code when the process exits. */
|
|
63
|
+
wait: () => Promise<number>;
|
|
64
|
+
kill: (signal?: NodeJS.Signals | number) => Promise<void>;
|
|
65
|
+
}
|
|
66
|
+
export interface SandboxProcess {
|
|
67
|
+
/** Run a command to completion and capture stdout/stderr/exit code. */
|
|
68
|
+
exec: (command: string, options?: ProcessOptions) => Promise<ExecResult>;
|
|
69
|
+
/** Start a long-running/background process with streamable, duplex IO. */
|
|
70
|
+
spawn: (command: string, options?: ProcessOptions) => Promise<SpawnHandle>;
|
|
71
|
+
}
|
|
72
|
+
/** Common, portable filesystem operations every provider implements. */
|
|
73
|
+
export interface SandboxFs {
|
|
74
|
+
read: (path: string) => Promise<string>;
|
|
75
|
+
readBytes: (path: string) => Promise<Uint8Array>;
|
|
76
|
+
write: (path: string, data: string | Uint8Array) => Promise<void>;
|
|
77
|
+
list: (path: string) => Promise<Array<{
|
|
78
|
+
name: string;
|
|
79
|
+
path: string;
|
|
80
|
+
type: 'file' | 'dir';
|
|
81
|
+
}>>;
|
|
82
|
+
mkdir: (path: string) => Promise<void>;
|
|
83
|
+
remove: (path: string) => Promise<void>;
|
|
84
|
+
rename: (from: string, to: string) => Promise<void>;
|
|
85
|
+
exists: (path: string) => Promise<boolean>;
|
|
86
|
+
/** Optional — present only when `capabilities.fs` providers advertise watch. */
|
|
87
|
+
watch?: (path: string, onEvent: (event: {
|
|
88
|
+
type: string;
|
|
89
|
+
path: string;
|
|
90
|
+
}) => void) => Promise<{
|
|
91
|
+
stop: () => Promise<void>;
|
|
92
|
+
}>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Uniform git surface. Implementations either delegate to the provider's
|
|
96
|
+
* native git (when advertised) or desugar to `process.exec("git …")`, so the
|
|
97
|
+
* contract is identical across providers.
|
|
98
|
+
*/
|
|
99
|
+
export interface SandboxGit {
|
|
100
|
+
clone: (input: {
|
|
101
|
+
url: string;
|
|
102
|
+
dir?: string;
|
|
103
|
+
ref?: string;
|
|
104
|
+
auth?: {
|
|
105
|
+
username?: string;
|
|
106
|
+
token: string;
|
|
107
|
+
};
|
|
108
|
+
depth?: number | 'full';
|
|
109
|
+
}) => Promise<void>;
|
|
110
|
+
status: (dir?: string) => Promise<string>;
|
|
111
|
+
add: (paths: Array<string>, dir?: string) => Promise<void>;
|
|
112
|
+
commit: (message: string, dir?: string) => Promise<void>;
|
|
113
|
+
push: (dir?: string) => Promise<void>;
|
|
114
|
+
pull: (dir?: string) => Promise<void>;
|
|
115
|
+
/** Returns the current branch name. */
|
|
116
|
+
branch: (dir?: string) => Promise<string>;
|
|
117
|
+
}
|
|
118
|
+
/** A reachable channel to a port inside the sandbox. */
|
|
119
|
+
export interface SandboxChannel {
|
|
120
|
+
/** URL the host can reach (localhost / host-bound port / authenticated preview URL). */
|
|
121
|
+
url: string;
|
|
122
|
+
/** Bearer token gating the channel, when the provider issues one. */
|
|
123
|
+
token?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Ready-to-send HTTP headers that authenticate requests to {@link url}, when
|
|
126
|
+
* the provider's auth doesn't fit a plain `Authorization: Bearer <token>`
|
|
127
|
+
* (e.g. Daytona's `x-daytona-preview-token`). Consumers that speak HTTP to the
|
|
128
|
+
* channel should attach these verbatim; the provider owns the header names so
|
|
129
|
+
* consumers stay provider-agnostic.
|
|
130
|
+
*/
|
|
131
|
+
headers?: Record<string, string>;
|
|
132
|
+
}
|
|
133
|
+
export interface SandboxPorts {
|
|
134
|
+
/** Expose `port` and resolve the best reachable channel for the host. */
|
|
135
|
+
connect: (port: number) => Promise<SandboxChannel>;
|
|
136
|
+
}
|
|
137
|
+
export interface SandboxEnv {
|
|
138
|
+
set: (vars: Record<string, string>) => Promise<void>;
|
|
139
|
+
}
|
|
140
|
+
/** Opaque reference to a stored snapshot, used to restore later. */
|
|
141
|
+
export interface SnapshotRef {
|
|
142
|
+
id: string;
|
|
143
|
+
label?: string;
|
|
144
|
+
}
|
|
145
|
+
/** The uniform runtime surface a sandbox exposes. */
|
|
146
|
+
export interface SandboxHandle {
|
|
147
|
+
/** Provider-assigned id used to reconnect to this sandbox. */
|
|
148
|
+
readonly id: string;
|
|
149
|
+
/** Provider name (e.g. "docker", "cloudflare", "local-process"). */
|
|
150
|
+
readonly provider: string;
|
|
151
|
+
/**
|
|
152
|
+
* Real filesystem path backing the virtual workspace root (`/workspace`).
|
|
153
|
+
* Harness CLIs and ACP `newSession` interpret cwd literally — use
|
|
154
|
+
* {@link resolveHarnessCwd} rather than the virtual path when the provider
|
|
155
|
+
* maps `/workspace` elsewhere (Daytona, Vercel, local-process).
|
|
156
|
+
*/
|
|
157
|
+
readonly workspaceRoot?: string;
|
|
158
|
+
/** What this sandbox can do. */
|
|
159
|
+
readonly capabilities: SandboxCapabilities;
|
|
160
|
+
readonly fs: SandboxFs;
|
|
161
|
+
readonly git: SandboxGit;
|
|
162
|
+
readonly process: SandboxProcess;
|
|
163
|
+
readonly ports: SandboxPorts;
|
|
164
|
+
readonly env: SandboxEnv;
|
|
165
|
+
/** Capability-gated: throws UnsupportedCapabilityError if `capabilities.snapshots` is false. */
|
|
166
|
+
snapshot?: (label?: string) => Promise<SnapshotRef>;
|
|
167
|
+
/** Capability-gated: throws UnsupportedCapabilityError if `capabilities.fork` is false. */
|
|
168
|
+
fork?: () => Promise<SandboxHandle>;
|
|
169
|
+
destroy: () => Promise<void>;
|
|
170
|
+
}
|
|
171
|
+
/** Input passed to {@link SandboxProvider.create}. */
|
|
172
|
+
export interface SandboxCreateInput {
|
|
173
|
+
workspace?: WorkspaceDefinition;
|
|
174
|
+
policy?: SandboxPolicy;
|
|
175
|
+
env?: Record<string, string>;
|
|
176
|
+
signal?: AbortSignal;
|
|
177
|
+
}
|
|
178
|
+
/** Input passed to {@link SandboxProvider.resume}. */
|
|
179
|
+
export interface SandboxResumeInput {
|
|
180
|
+
/** Provider-assigned sandbox id recorded by a prior run. */
|
|
181
|
+
id: string;
|
|
182
|
+
signal?: AbortSignal;
|
|
183
|
+
}
|
|
184
|
+
/** Input passed to {@link SandboxProvider.restoreSnapshot}. */
|
|
185
|
+
export interface SandboxRestoreInput {
|
|
186
|
+
snapshotId: string;
|
|
187
|
+
workspace?: WorkspaceDefinition;
|
|
188
|
+
policy?: SandboxPolicy;
|
|
189
|
+
env?: Record<string, string>;
|
|
190
|
+
signal?: AbortSignal;
|
|
191
|
+
}
|
|
192
|
+
/** Input passed to {@link SandboxProvider.destroy}. */
|
|
193
|
+
export interface SandboxDestroyInput {
|
|
194
|
+
id: string;
|
|
195
|
+
signal?: AbortSignal;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Owns an isolation primitive. Implemented by `@tanstack/ai-sandbox-*`
|
|
199
|
+
* provider packages.
|
|
200
|
+
*/
|
|
201
|
+
export interface SandboxProvider {
|
|
202
|
+
readonly name: string;
|
|
203
|
+
/** Static capability descriptor. */
|
|
204
|
+
capabilities: () => SandboxCapabilities;
|
|
205
|
+
create: (input: SandboxCreateInput) => Promise<SandboxHandle>;
|
|
206
|
+
/** Reconnect to an existing sandbox by id; resolves null if it's gone. */
|
|
207
|
+
resume: (input: SandboxResumeInput) => Promise<SandboxHandle | null>;
|
|
208
|
+
/** Capability-gated: present only when `capabilities().snapshots` is true. */
|
|
209
|
+
restoreSnapshot?: (input: SandboxRestoreInput) => Promise<SandboxHandle>;
|
|
210
|
+
destroy: (input: SandboxDestroyInput) => Promise<void>;
|
|
211
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when code invokes an optional sandbox capability that the active
|
|
3
|
+
* provider does not support. Core/middleware should check
|
|
4
|
+
* `handle.capabilities` BEFORE using an optional capability and degrade
|
|
5
|
+
* gracefully; this error exists so that a direct call to an unsupported
|
|
6
|
+
* optional method fails loud instead of silently no-opping.
|
|
7
|
+
*/
|
|
8
|
+
export declare class UnsupportedCapabilityError extends Error {
|
|
9
|
+
readonly provider: string;
|
|
10
|
+
readonly capability: string;
|
|
11
|
+
constructor(provider: string, capability: string, hint?: string);
|
|
12
|
+
}
|
|
13
|
+
/** Thrown when a harness adapter requires a sandbox but none was provided. */
|
|
14
|
+
export declare class MissingSandboxError extends Error {
|
|
15
|
+
constructor(adapterName: string);
|
|
16
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class UnsupportedCapabilityError extends Error {
|
|
2
|
+
provider;
|
|
3
|
+
capability;
|
|
4
|
+
constructor(provider, capability, hint) {
|
|
5
|
+
super(
|
|
6
|
+
`Sandbox provider "${provider}" does not support the "${capability}" capability.` + (hint ? ` ${hint}` : "")
|
|
7
|
+
);
|
|
8
|
+
this.name = "UnsupportedCapabilityError";
|
|
9
|
+
this.provider = provider;
|
|
10
|
+
this.capability = capability;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
class MissingSandboxError extends Error {
|
|
14
|
+
constructor(adapterName) {
|
|
15
|
+
super(
|
|
16
|
+
`Adapter "${adapterName}" requires a sandbox. Add withSandbox(defineSandbox({ ... })) to chat() middleware.`
|
|
17
|
+
);
|
|
18
|
+
this.name = "MissingSandboxError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
MissingSandboxError,
|
|
23
|
+
UnsupportedCapabilityError
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sources":["../../src/errors.ts"],"sourcesContent":["/**\n * Thrown when code invokes an optional sandbox capability that the active\n * provider does not support. Core/middleware should check\n * `handle.capabilities` BEFORE using an optional capability and degrade\n * gracefully; this error exists so that a direct call to an unsupported\n * optional method fails loud instead of silently no-opping.\n */\nexport class UnsupportedCapabilityError extends Error {\n readonly provider: string\n readonly capability: string\n\n constructor(provider: string, capability: string, hint?: string) {\n super(\n `Sandbox provider \"${provider}\" does not support the \"${capability}\" capability.` +\n (hint ? ` ${hint}` : ''),\n )\n this.name = 'UnsupportedCapabilityError'\n this.provider = provider\n this.capability = capability\n }\n}\n\n/** Thrown when a harness adapter requires a sandbox but none was provided. */\nexport class MissingSandboxError extends Error {\n constructor(adapterName: string) {\n super(\n `Adapter \"${adapterName}\" requires a sandbox. Add withSandbox(defineSandbox({ ... })) to chat() middleware.`,\n )\n this.name = 'MissingSandboxError'\n }\n}\n"],"names":[],"mappings":"AAOO,MAAM,mCAAmC,MAAM;AAAA,EAC3C;AAAA,EACA;AAAA,EAET,YAAY,UAAkB,YAAoB,MAAe;AAC/D;AAAA,MACE,qBAAqB,QAAQ,2BAA2B,UAAU,mBAC/D,OAAO,IAAI,IAAI,KAAK;AAAA,IAAA;AAEzB,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,aAAa;AAAA,EACpB;AACF;AAGO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAAY,aAAqB;AAC/B;AAAA,MACE,YAAY,WAAW;AAAA,IAAA;AAEzB,SAAK,OAAO;AAAA,EACd;AACF;"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function q(value) {
|
|
2
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
3
|
+
}
|
|
4
|
+
function assertNoLeadingDash(value, name) {
|
|
5
|
+
if (value.startsWith("-")) {
|
|
6
|
+
throw new Error(
|
|
7
|
+
`git-exec: ${name} "${value}" must not begin with "-" (argument-injection guard).`
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const CREDENTIAL_HELPER = '!f() { echo "username=${GIT_ASKPASS_USER}"; echo "password=${GIT_ASKPASS_TOKEN}"; }; f';
|
|
12
|
+
function createExecBackedGit(process, defaultRoot) {
|
|
13
|
+
const at = (dir) => {
|
|
14
|
+
const d = dir ?? defaultRoot;
|
|
15
|
+
assertNoLeadingDash(d, "dir");
|
|
16
|
+
return q(d);
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
clone: async ({ url, dir, ref, auth, depth }) => {
|
|
20
|
+
assertNoLeadingDash(url, "url");
|
|
21
|
+
const target = dir ?? defaultRoot;
|
|
22
|
+
assertNoLeadingDash(target, "dir");
|
|
23
|
+
if (ref !== void 0) assertNoLeadingDash(ref, "ref");
|
|
24
|
+
const refArg = ref ? `--branch ${q(ref)} ` : "";
|
|
25
|
+
const resolvedDepth = depth ?? 1;
|
|
26
|
+
if (resolvedDepth !== "full" && (!Number.isInteger(resolvedDepth) || resolvedDepth <= 0)) {
|
|
27
|
+
throw new Error('git-exec: depth must be a positive integer or "full".');
|
|
28
|
+
}
|
|
29
|
+
const depthArg = resolvedDepth === "full" ? "" : `--depth ${resolvedDepth} --single-branch `;
|
|
30
|
+
if (auth?.token) {
|
|
31
|
+
await process.exec(
|
|
32
|
+
`git -c credential.helper=${q(CREDENTIAL_HELPER)} clone ${refArg}${depthArg}-- ${q(url)} ${q(target)}`,
|
|
33
|
+
{
|
|
34
|
+
// Token lives only in the child env, never in argv.
|
|
35
|
+
env: {
|
|
36
|
+
GIT_ASKPASS_USER: auth.username ?? "x-access-token",
|
|
37
|
+
GIT_ASKPASS_TOKEN: auth.token,
|
|
38
|
+
GIT_TERMINAL_PROMPT: "0"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
await process.exec(
|
|
45
|
+
`git clone ${refArg}${depthArg}-- ${q(url)} ${q(target)}`
|
|
46
|
+
);
|
|
47
|
+
},
|
|
48
|
+
status: async (dir) => (await process.exec(`git -C ${at(dir)} status --porcelain`)).stdout,
|
|
49
|
+
add: async (paths, dir) => {
|
|
50
|
+
paths.forEach((p, i) => assertNoLeadingDash(p, `path[${i}]`));
|
|
51
|
+
await process.exec(`git -C ${at(dir)} add -- ${paths.map(q).join(" ")}`);
|
|
52
|
+
},
|
|
53
|
+
commit: async (message, dir) => {
|
|
54
|
+
await process.exec(`git -C ${at(dir)} commit -m ${q(message)}`);
|
|
55
|
+
},
|
|
56
|
+
push: async (dir) => {
|
|
57
|
+
await process.exec(`git -C ${at(dir)} push`);
|
|
58
|
+
},
|
|
59
|
+
pull: async (dir) => {
|
|
60
|
+
await process.exec(`git -C ${at(dir)} pull`);
|
|
61
|
+
},
|
|
62
|
+
branch: async (dir) => (await process.exec(`git -C ${at(dir)} rev-parse --abbrev-ref HEAD`)).stdout.trim()
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
createExecBackedGit
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=git-exec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-exec.js","sources":["../../src/git-exec.ts"],"sourcesContent":["/**\n * An exec-backed {@link SandboxGit} implementation. Providers without a native\n * git API (local-process, Docker) get a uniform `sandbox.git` by desugaring to\n * `process.exec(\"git …\")`. Providers WITH native git (Daytona, Cloudflare) may\n * supply their own implementation instead.\n *\n * Security:\n * - Every interpolated value is single-quote escaped (no shell injection).\n * - A `--` end-of-options separator precedes untrusted positionals and values\n * are rejected if they begin with `-`, so a repo URL / ref / path can't\n * smuggle a git flag (e.g. `--upload-pack=…`).\n * - Auth tokens NEVER appear in argv (they'd leak via `ps` / process logs).\n * Instead a one-shot `credential.helper` reads the token from the child\n * process ENV. The helper string is single-quoted so the OUTER shell never\n * expands the env var — only git's own helper subshell does, at use time.\n *\n * NOTE: `SandboxProcess.exec` takes a command STRING by design (the sandbox\n * runs shell commands), so we mitigate flag smuggling with `--` + validation\n * rather than an argv array.\n */\nimport type { SandboxGit, SandboxProcess } from './contracts'\n\n/** POSIX single-quote escape: wrap in '…' and escape embedded quotes. */\nfunction q(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`\n}\n\n/** Reject values that could be parsed as a git flag when used as a positional. */\nfunction assertNoLeadingDash(value: string, name: string): void {\n if (value.startsWith('-')) {\n throw new Error(\n `git-exec: ${name} \"${value}\" must not begin with \"-\" (argument-injection guard).`,\n )\n }\n}\n\n// Credential helper that prints creds read from the child ENV. Single-quoted at\n// the call site so the outer shell passes it literally; git expands the vars in\n// its own helper subshell, keeping the token out of argv.\nconst CREDENTIAL_HELPER =\n '!f() { echo \"username=${GIT_ASKPASS_USER}\"; echo \"password=${GIT_ASKPASS_TOKEN}\"; }; f'\n\nexport function createExecBackedGit(\n process: SandboxProcess,\n defaultRoot: string,\n): SandboxGit {\n const at = (dir?: string): string => {\n const d = dir ?? defaultRoot\n assertNoLeadingDash(d, 'dir')\n return q(d)\n }\n\n return {\n clone: async ({ url, dir, ref, auth, depth }) => {\n assertNoLeadingDash(url, 'url')\n const target = dir ?? defaultRoot\n assertNoLeadingDash(target, 'dir')\n if (ref !== undefined) assertNoLeadingDash(ref, 'ref')\n const refArg = ref ? `--branch ${q(ref)} ` : ''\n const resolvedDepth = depth ?? 1\n // `depth` is interpolated unquoted into the command, so validate it the\n // same way other positionals are guarded — a non-positive-integer (e.g. an\n // untyped caller passing a string) must never reach the shell.\n if (\n resolvedDepth !== 'full' &&\n (!Number.isInteger(resolvedDepth) || resolvedDepth <= 0)\n ) {\n throw new Error('git-exec: depth must be a positive integer or \"full\".')\n }\n const depthArg =\n resolvedDepth === 'full'\n ? ''\n : `--depth ${resolvedDepth} --single-branch `\n\n if (auth?.token) {\n await process.exec(\n `git -c credential.helper=${q(CREDENTIAL_HELPER)} clone ${refArg}${depthArg}-- ${q(url)} ${q(target)}`,\n {\n // Token lives only in the child env, never in argv.\n env: {\n GIT_ASKPASS_USER: auth.username ?? 'x-access-token',\n GIT_ASKPASS_TOKEN: auth.token,\n GIT_TERMINAL_PROMPT: '0',\n },\n },\n )\n return\n }\n\n await process.exec(\n `git clone ${refArg}${depthArg}-- ${q(url)} ${q(target)}`,\n )\n },\n status: async (dir) =>\n (await process.exec(`git -C ${at(dir)} status --porcelain`)).stdout,\n add: async (paths, dir) => {\n paths.forEach((p, i) => assertNoLeadingDash(p, `path[${i}]`))\n await process.exec(`git -C ${at(dir)} add -- ${paths.map(q).join(' ')}`)\n },\n commit: async (message, dir) => {\n await process.exec(`git -C ${at(dir)} commit -m ${q(message)}`)\n },\n push: async (dir) => {\n await process.exec(`git -C ${at(dir)} push`)\n },\n pull: async (dir) => {\n await process.exec(`git -C ${at(dir)} pull`)\n },\n branch: async (dir) =>\n (\n await process.exec(`git -C ${at(dir)} rev-parse --abbrev-ref HEAD`)\n ).stdout.trim(),\n }\n}\n"],"names":[],"mappings":"AAuBA,SAAS,EAAE,OAAuB;AAChC,SAAO,IAAI,MAAM,QAAQ,MAAM,OAAO,CAAC;AACzC;AAGA,SAAS,oBAAoB,OAAe,MAAoB;AAC9D,MAAI,MAAM,WAAW,GAAG,GAAG;AACzB,UAAM,IAAI;AAAA,MACR,aAAa,IAAI,KAAK,KAAK;AAAA,IAAA;AAAA,EAE/B;AACF;AAKA,MAAM,oBACJ;AAEK,SAAS,oBACd,SACA,aACY;AACZ,QAAM,KAAK,CAAC,QAAyB;AACnC,UAAM,IAAI,OAAO;AACjB,wBAAoB,GAAG,KAAK;AAC5B,WAAO,EAAE,CAAC;AAAA,EACZ;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,EAAE,KAAK,KAAK,KAAK,MAAM,YAAY;AAC/C,0BAAoB,KAAK,KAAK;AAC9B,YAAM,SAAS,OAAO;AACtB,0BAAoB,QAAQ,KAAK;AACjC,UAAI,QAAQ,OAAW,qBAAoB,KAAK,KAAK;AACrD,YAAM,SAAS,MAAM,YAAY,EAAE,GAAG,CAAC,MAAM;AAC7C,YAAM,gBAAgB,SAAS;AAI/B,UACE,kBAAkB,WACjB,CAAC,OAAO,UAAU,aAAa,KAAK,iBAAiB,IACtD;AACA,cAAM,IAAI,MAAM,uDAAuD;AAAA,MACzE;AACA,YAAM,WACJ,kBAAkB,SACd,KACA,WAAW,aAAa;AAE9B,UAAI,MAAM,OAAO;AACf,cAAM,QAAQ;AAAA,UACZ,4BAA4B,EAAE,iBAAiB,CAAC,UAAU,MAAM,GAAG,QAAQ,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;AAAA,UACpG;AAAA;AAAA,YAEE,KAAK;AAAA,cACH,kBAAkB,KAAK,YAAY;AAAA,cACnC,mBAAmB,KAAK;AAAA,cACxB,qBAAqB;AAAA,YAAA;AAAA,UACvB;AAAA,QACF;AAEF;AAAA,MACF;AAEA,YAAM,QAAQ;AAAA,QACZ,aAAa,MAAM,GAAG,QAAQ,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;AAAA,MAAA;AAAA,IAE3D;AAAA,IACA,QAAQ,OAAO,SACZ,MAAM,QAAQ,KAAK,UAAU,GAAG,GAAG,CAAC,qBAAqB,GAAG;AAAA,IAC/D,KAAK,OAAO,OAAO,QAAQ;AACzB,YAAM,QAAQ,CAAC,GAAG,MAAM,oBAAoB,GAAG,QAAQ,CAAC,GAAG,CAAC;AAC5D,YAAM,QAAQ,KAAK,UAAU,GAAG,GAAG,CAAC,WAAW,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE;AAAA,IACzE;AAAA,IACA,QAAQ,OAAO,SAAS,QAAQ;AAC9B,YAAM,QAAQ,KAAK,UAAU,GAAG,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,EAAE;AAAA,IAChE;AAAA,IACA,MAAM,OAAO,QAAQ;AACnB,YAAM,QAAQ,KAAK,UAAU,GAAG,GAAG,CAAC,OAAO;AAAA,IAC7C;AAAA,IACA,MAAM,OAAO,QAAQ;AACnB,YAAM,QAAQ,KAAK,UAAU,GAAG,GAAG,CAAC,OAAO;AAAA,IAC7C;AAAA,IACA,QAAQ,OAAO,SAEX,MAAM,QAAQ,KAAK,UAAU,GAAG,GAAG,CAAC,8BAA8B,GAClE,OAAO,KAAA;AAAA,EAAK;AAEpB;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { DEFAULT_WORKSPACE_ROOT } from "./bootstrap.js";
|
|
3
|
+
function mapVirtualWorkspacePath(virtualCwd, realRoot) {
|
|
4
|
+
if (virtualCwd === DEFAULT_WORKSPACE_ROOT) return realRoot;
|
|
5
|
+
if (virtualCwd.startsWith(`${DEFAULT_WORKSPACE_ROOT}/`)) {
|
|
6
|
+
const rel = virtualCwd.slice(DEFAULT_WORKSPACE_ROOT.length + 1);
|
|
7
|
+
return realRoot === DEFAULT_WORKSPACE_ROOT ? `${DEFAULT_WORKSPACE_ROOT}/${rel}` : path.posix.join(realRoot, rel);
|
|
8
|
+
}
|
|
9
|
+
return virtualCwd;
|
|
10
|
+
}
|
|
11
|
+
function resolveHarnessCwd(handle, virtualCwd = DEFAULT_WORKSPACE_ROOT) {
|
|
12
|
+
if (handle.provider === "local-process") {
|
|
13
|
+
return mapVirtualWorkspacePath(virtualCwd, handle.id);
|
|
14
|
+
}
|
|
15
|
+
const root = handle.workspaceRoot;
|
|
16
|
+
if (root !== void 0 && root !== DEFAULT_WORKSPACE_ROOT) {
|
|
17
|
+
return mapVirtualWorkspacePath(virtualCwd, root);
|
|
18
|
+
}
|
|
19
|
+
return virtualCwd;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
resolveHarnessCwd
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=harness-cwd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-cwd.js","sources":["../../src/harness-cwd.ts"],"sourcesContent":["/**\n * Resolve a VIRTUAL sandbox cwd (e.g. `/workspace`) to the path a harness CLI\n * or ACP session must use on the real filesystem.\n *\n * Provider handles map virtual paths for spawn/exec/fs; harness-facing APIs\n * interpret cwd literally (`grok --cwd`, ACP `newSession`, opencode HTTP\n * `directory`, …).\n */\nimport * as path from 'node:path'\nimport { DEFAULT_WORKSPACE_ROOT } from './bootstrap'\nimport type { SandboxHandle } from './contracts'\n\nfunction mapVirtualWorkspacePath(virtualCwd: string, realRoot: string): string {\n if (virtualCwd === DEFAULT_WORKSPACE_ROOT) return realRoot\n if (virtualCwd.startsWith(`${DEFAULT_WORKSPACE_ROOT}/`)) {\n const rel = virtualCwd.slice(DEFAULT_WORKSPACE_ROOT.length + 1)\n return realRoot === DEFAULT_WORKSPACE_ROOT\n ? `${DEFAULT_WORKSPACE_ROOT}/${rel}`\n : path.posix.join(realRoot, rel)\n }\n return virtualCwd\n}\n\nexport function resolveHarnessCwd(\n handle: SandboxHandle,\n virtualCwd: string = DEFAULT_WORKSPACE_ROOT,\n): string {\n if (handle.provider === 'local-process') {\n return mapVirtualWorkspacePath(virtualCwd, handle.id)\n }\n\n const root = handle.workspaceRoot\n if (root !== undefined && root !== DEFAULT_WORKSPACE_ROOT) {\n return mapVirtualWorkspacePath(virtualCwd, root)\n }\n\n return virtualCwd\n}\n"],"names":[],"mappings":";;AAYA,SAAS,wBAAwB,YAAoB,UAA0B;AAC7E,MAAI,eAAe,uBAAwB,QAAO;AAClD,MAAI,WAAW,WAAW,GAAG,sBAAsB,GAAG,GAAG;AACvD,UAAM,MAAM,WAAW,MAAM,uBAAuB,SAAS,CAAC;AAC9D,WAAO,aAAa,yBAChB,GAAG,sBAAsB,IAAI,GAAG,KAChC,KAAK,MAAM,KAAK,UAAU,GAAG;AAAA,EACnC;AACA,SAAO;AACT;AAEO,SAAS,kBACd,QACA,aAAqB,wBACb;AACR,MAAI,OAAO,aAAa,iBAAiB;AACvC,WAAO,wBAAwB,YAAY,OAAO,EAAE;AAAA,EACtD;AAEA,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,UAAa,SAAS,wBAAwB;AACzD,WAAO,wBAAwB,YAAY,IAAI;AAAA,EACjD;AAEA,SAAO;AACT;"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export { SandboxCapability, SandboxStoreCapability, LocksCapability, SandboxPolicyCapability, ToolBridgeProvisionerCapability, getSandbox, provideSandbox, getSandboxStore, provideSandboxStore, getLocks, provideLocks, getSandboxPolicy, provideSandboxPolicy, getToolBridgeProvisioner, provideToolBridgeProvisioner, } from './capabilities.js';
|
|
2
|
+
export { ProjectionCapability, getWorkspaceProjection, provideWorkspaceProjection, } from './projection.js';
|
|
3
|
+
export type { WorkspaceProjection } from './projection.js';
|
|
4
|
+
export { withSandbox } from './middleware.js';
|
|
5
|
+
export { defineSandbox } from './sandbox.js';
|
|
6
|
+
export type { SandboxConfig, SandboxDefinition, SandboxEnsureContext, SandboxLifecycle, SandboxHooks, ReuseStrategy, SnapshotStrategy, } from './sandbox.js';
|
|
7
|
+
export { defineWorkspace, gitSource, githubRepo, localSource, fileSkill, agentSkill, mcpSkill, gitSkill, } from './workspace.js';
|
|
8
|
+
export type { WorkspaceDefinition, WorkspaceSource, WorkspaceSkill, PackageManager, McpConfig, } from './workspace.js';
|
|
9
|
+
export { createSecrets, bearer, isSecretRef, resolveSecret, resolveBearer, resolveAllSecrets, } from './secrets.js';
|
|
10
|
+
export type { SecretRef, Secrets, BearerRef } from './secrets.js';
|
|
11
|
+
export { defineSandboxPolicy, evaluateCommand, commandAliases } from './policy.js';
|
|
12
|
+
export type { SandboxPolicy, PolicyDecision, CommandRules, CapabilityRules, } from './policy.js';
|
|
13
|
+
export type { SandboxProvider, SandboxHandle, SandboxCapabilities, SandboxFs, SandboxGit, SandboxProcess, SandboxPorts, SandboxEnv, SandboxChannel, SpawnHandle, ExecResult, ProcessOptions, SnapshotRef, SandboxCreateInput, SandboxResumeInput, SandboxRestoreInput, SandboxDestroyInput, } from './contracts.js';
|
|
14
|
+
export { InMemorySandboxStore, InMemoryLockStore } from './store.js';
|
|
15
|
+
export type { SandboxStore, LockStore, SandboxRecord } from './store.js';
|
|
16
|
+
export { bootstrapWorkspace, detectPackageManager, DEFAULT_WORKSPACE_ROOT, } from './bootstrap.js';
|
|
17
|
+
export { resolveHarnessCwd } from './harness-cwd.js';
|
|
18
|
+
export type { BootstrapResult } from './bootstrap.js';
|
|
19
|
+
export { writeAgentsFile, resolveGitSkillDir, formatWorkspaceScriptsSection, mergeAgentsContent, } from './agents-file.js';
|
|
20
|
+
export { createExecBackedGit } from './git-exec.js';
|
|
21
|
+
export { spawnNdjson, toLines } from './runner.js';
|
|
22
|
+
export type { SpawnNdjsonOptions } from './runner.js';
|
|
23
|
+
export { startHostToolBridge, hostForSandbox, createToolBridgeCore, handleBridgeJsonRpc, timingSafeBearerEqual, nodeHttpBridgeProvisioner, BRIDGED_MCP_SERVER_NAME, } from './tool-bridge.js';
|
|
24
|
+
export type { HostToolBridge, StartBridgeOptions, ToolBridgeCore, ToolBridgeCoreOptions, ToolDescriptor, ToolCallResult, BridgePermission, PermissionToolResult, ToolBridgeProvisioner, ToolBridgeProvisionOptions, ProvisionedBridge, } from './tool-bridge.js';
|
|
25
|
+
export { createBridgeEventChannel, mergeChunkStreams } from './bridge-events.js';
|
|
26
|
+
export type { BridgeEventChannel } from './bridge-events.js';
|
|
27
|
+
export { remoteToolStubs, toolDescriptors, httpRemoteToolExecutor, executeHostTool, isToolExecRequest, } from './remote-tools.js';
|
|
28
|
+
export type { RemoteToolExecutor, RemoteToolExecuteOptions, ToolExecRequest, } from './remote-tools.js';
|
|
29
|
+
export { InMemoryRunEventLog, isTerminalRunStatus } from './run-log.js';
|
|
30
|
+
export type { RunEventLog, RunRecord, RunEvent, RunStatus, TerminalRunStatus, RunError, RunEventLogReadOptions, } from './run-log.js';
|
|
31
|
+
export { pipeToRunLog, RunController } from './run.js';
|
|
32
|
+
export type { PipeToRunLogOptions, RunControllerStartInput, RunHandle, } from './run.js';
|
|
33
|
+
export { resolveApproval, approvalId, buildApprovalRequestedEvent, APPROVAL_REQUESTED_EVENT, } from './approvals.js';
|
|
34
|
+
export type { ResolveApprovalInput, ApprovalOutcome } from './approvals.js';
|
|
35
|
+
export { watchWorkspace, diffSnapshots } from './watch.js';
|
|
36
|
+
export type { SandboxFileEvent, FileEvent, FileEventType, WatchOptions, SandboxWatchHandle, } from './watch.js';
|
|
37
|
+
export { computeSandboxKey, computeWorkspaceHash } from './key.js';
|
|
38
|
+
export type { SandboxKeyInput } from './key.js';
|
|
39
|
+
export { UnsupportedCapabilityError, MissingSandboxError } from './errors.js';
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { LocksCapability, SandboxCapability, SandboxPolicyCapability, SandboxStoreCapability, ToolBridgeProvisionerCapability, getLocks, getSandbox, getSandboxPolicy, getSandboxStore, getToolBridgeProvisioner, provideLocks, provideSandbox, provideSandboxPolicy, provideSandboxStore, provideToolBridgeProvisioner } from "./capabilities.js";
|
|
2
|
+
import { ProjectionCapability, getWorkspaceProjection, provideWorkspaceProjection } from "./projection.js";
|
|
3
|
+
import { withSandbox } from "./middleware.js";
|
|
4
|
+
import { defineSandbox } from "./sandbox.js";
|
|
5
|
+
import { agentSkill, defineWorkspace, fileSkill, gitSkill, gitSource, githubRepo, localSource, mcpSkill } from "./workspace.js";
|
|
6
|
+
import { bearer, createSecrets, isSecretRef, resolveAllSecrets, resolveBearer, resolveSecret } from "./secrets.js";
|
|
7
|
+
import { commandAliases, defineSandboxPolicy, evaluateCommand } from "./policy.js";
|
|
8
|
+
import { InMemoryLockStore, InMemorySandboxStore } from "./store.js";
|
|
9
|
+
import { DEFAULT_WORKSPACE_ROOT, bootstrapWorkspace, detectPackageManager } from "./bootstrap.js";
|
|
10
|
+
import { resolveHarnessCwd } from "./harness-cwd.js";
|
|
11
|
+
import { formatWorkspaceScriptsSection, mergeAgentsContent, resolveGitSkillDir, writeAgentsFile } from "./agents-file.js";
|
|
12
|
+
import { createExecBackedGit } from "./git-exec.js";
|
|
13
|
+
import { spawnNdjson, toLines } from "./runner.js";
|
|
14
|
+
import { BRIDGED_MCP_SERVER_NAME, createToolBridgeCore, handleBridgeJsonRpc, hostForSandbox, nodeHttpBridgeProvisioner, startHostToolBridge, timingSafeBearerEqual } from "./tool-bridge.js";
|
|
15
|
+
import { createBridgeEventChannel, mergeChunkStreams } from "./bridge-events.js";
|
|
16
|
+
import { executeHostTool, httpRemoteToolExecutor, isToolExecRequest, remoteToolStubs, toolDescriptors } from "./remote-tools.js";
|
|
17
|
+
import { InMemoryRunEventLog, isTerminalRunStatus } from "./run-log.js";
|
|
18
|
+
import { RunController, pipeToRunLog } from "./run.js";
|
|
19
|
+
import { APPROVAL_REQUESTED_EVENT, approvalId, buildApprovalRequestedEvent, resolveApproval } from "./approvals.js";
|
|
20
|
+
import { diffSnapshots, watchWorkspace } from "./watch.js";
|
|
21
|
+
import { computeSandboxKey, computeWorkspaceHash } from "./key.js";
|
|
22
|
+
import { MissingSandboxError, UnsupportedCapabilityError } from "./errors.js";
|
|
23
|
+
export {
|
|
24
|
+
APPROVAL_REQUESTED_EVENT,
|
|
25
|
+
BRIDGED_MCP_SERVER_NAME,
|
|
26
|
+
DEFAULT_WORKSPACE_ROOT,
|
|
27
|
+
InMemoryLockStore,
|
|
28
|
+
InMemoryRunEventLog,
|
|
29
|
+
InMemorySandboxStore,
|
|
30
|
+
LocksCapability,
|
|
31
|
+
MissingSandboxError,
|
|
32
|
+
ProjectionCapability,
|
|
33
|
+
RunController,
|
|
34
|
+
SandboxCapability,
|
|
35
|
+
SandboxPolicyCapability,
|
|
36
|
+
SandboxStoreCapability,
|
|
37
|
+
ToolBridgeProvisionerCapability,
|
|
38
|
+
UnsupportedCapabilityError,
|
|
39
|
+
agentSkill,
|
|
40
|
+
approvalId,
|
|
41
|
+
bearer,
|
|
42
|
+
bootstrapWorkspace,
|
|
43
|
+
buildApprovalRequestedEvent,
|
|
44
|
+
commandAliases,
|
|
45
|
+
computeSandboxKey,
|
|
46
|
+
computeWorkspaceHash,
|
|
47
|
+
createBridgeEventChannel,
|
|
48
|
+
createExecBackedGit,
|
|
49
|
+
createSecrets,
|
|
50
|
+
createToolBridgeCore,
|
|
51
|
+
defineSandbox,
|
|
52
|
+
defineSandboxPolicy,
|
|
53
|
+
defineWorkspace,
|
|
54
|
+
detectPackageManager,
|
|
55
|
+
diffSnapshots,
|
|
56
|
+
evaluateCommand,
|
|
57
|
+
executeHostTool,
|
|
58
|
+
fileSkill,
|
|
59
|
+
formatWorkspaceScriptsSection,
|
|
60
|
+
getLocks,
|
|
61
|
+
getSandbox,
|
|
62
|
+
getSandboxPolicy,
|
|
63
|
+
getSandboxStore,
|
|
64
|
+
getToolBridgeProvisioner,
|
|
65
|
+
getWorkspaceProjection,
|
|
66
|
+
gitSkill,
|
|
67
|
+
gitSource,
|
|
68
|
+
githubRepo,
|
|
69
|
+
handleBridgeJsonRpc,
|
|
70
|
+
hostForSandbox,
|
|
71
|
+
httpRemoteToolExecutor,
|
|
72
|
+
isSecretRef,
|
|
73
|
+
isTerminalRunStatus,
|
|
74
|
+
isToolExecRequest,
|
|
75
|
+
localSource,
|
|
76
|
+
mcpSkill,
|
|
77
|
+
mergeAgentsContent,
|
|
78
|
+
mergeChunkStreams,
|
|
79
|
+
nodeHttpBridgeProvisioner,
|
|
80
|
+
pipeToRunLog,
|
|
81
|
+
provideLocks,
|
|
82
|
+
provideSandbox,
|
|
83
|
+
provideSandboxPolicy,
|
|
84
|
+
provideSandboxStore,
|
|
85
|
+
provideToolBridgeProvisioner,
|
|
86
|
+
provideWorkspaceProjection,
|
|
87
|
+
remoteToolStubs,
|
|
88
|
+
resolveAllSecrets,
|
|
89
|
+
resolveApproval,
|
|
90
|
+
resolveBearer,
|
|
91
|
+
resolveGitSkillDir,
|
|
92
|
+
resolveHarnessCwd,
|
|
93
|
+
resolveSecret,
|
|
94
|
+
spawnNdjson,
|
|
95
|
+
startHostToolBridge,
|
|
96
|
+
timingSafeBearerEqual,
|
|
97
|
+
toLines,
|
|
98
|
+
toolDescriptors,
|
|
99
|
+
watchWorkspace,
|
|
100
|
+
withSandbox,
|
|
101
|
+
writeAgentsFile
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { WorkspaceDefinition } from './workspace.js';
|
|
2
|
+
/** Inputs that, together, identify one resumable sandbox instance. */
|
|
3
|
+
export interface SandboxKeyInput {
|
|
4
|
+
threadId: string;
|
|
5
|
+
sandboxId: string;
|
|
6
|
+
providerName: string;
|
|
7
|
+
workspace?: WorkspaceDefinition;
|
|
8
|
+
/** Optional tenant scoping pulled from runtimeContext. */
|
|
9
|
+
tenant?: {
|
|
10
|
+
userId?: string;
|
|
11
|
+
orgId?: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Hash of the parts of a workspace that change what the agent sees. Secrets are
|
|
16
|
+
* intentionally excluded (rotating a token must not orphan the sandbox).
|
|
17
|
+
*/
|
|
18
|
+
export declare function computeWorkspaceHash(workspace: WorkspaceDefinition | undefined): string;
|
|
19
|
+
/** Compute the compound sandbox instance key. */
|
|
20
|
+
export declare function computeSandboxKey(input: SandboxKeyInput): string;
|