@tanstack/ai-sandbox 0.3.1 → 0.3.3
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 +15 -5
- package/dist/esm/agents-file.d.ts +15 -0
- package/dist/esm/agents-file.js +47 -1
- package/dist/esm/agents-file.js.map +1 -1
- package/dist/esm/bootstrap.js +2 -1
- package/dist/esm/bootstrap.js.map +1 -1
- package/dist/esm/contracts.d.ts +12 -8
- package/dist/esm/git-exec.js +2 -0
- package/dist/esm/git-exec.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +3 -3
- package/dist/esm/journal-sweep.js +3 -2
- package/dist/esm/journal-sweep.js.map +1 -1
- package/dist/esm/middleware.js +5 -2
- package/dist/esm/middleware.js.map +1 -1
- package/dist/esm/reap.js +2 -1
- package/dist/esm/reap.js.map +1 -1
- package/dist/esm/sandbox.d.ts +2 -0
- package/dist/esm/sandbox.js +19 -2
- package/dist/esm/sandbox.js.map +1 -1
- package/dist/esm/shell.js +5 -4
- package/dist/esm/shell.js.map +1 -1
- package/dist/esm/testkit/conformance.js +4 -2
- package/dist/esm/testkit/conformance.js.map +1 -1
- package/dist/esm/testkit/journal-conformance.js +6 -3
- package/dist/esm/testkit/journal-conformance.js.map +1 -1
- package/dist/esm/testkit/reaper-conformance.js +13 -8
- package/dist/esm/testkit/reaper-conformance.js.map +1 -1
- package/dist/esm/testkit/takeover-conformance.js +4 -3
- package/dist/esm/testkit/takeover-conformance.js.map +1 -1
- package/dist/esm/tool-bridge.js +1 -1
- package/dist/esm/tool-bridge.js.map +1 -1
- package/package.json +14 -4
- package/skills/ai-sandbox/SKILL.md +13 -8
- package/src/agents-file.ts +65 -0
- package/src/bootstrap.ts +5 -1
- package/src/contracts.ts +12 -8
- package/src/git-exec.ts +7 -0
- package/src/index.ts +2 -0
- package/src/middleware.ts +4 -1
- package/src/sandbox.ts +23 -0
- package/src/tool-bridge.ts +3 -1
package/src/middleware.ts
CHANGED
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
} from './tool-history'
|
|
49
49
|
import { watchWorkspace } from './watch'
|
|
50
50
|
import { DEFAULT_WORKSPACE_ROOT } from './bootstrap'
|
|
51
|
+
import { resolveHarnessCwd } from './harness-cwd'
|
|
51
52
|
import type { InternalLogger } from '@tanstack/ai/adapter-internals'
|
|
52
53
|
import type { LockStore } from '@tanstack/ai/locks'
|
|
53
54
|
import type {
|
|
@@ -293,6 +294,7 @@ function buildEnsureCtx(
|
|
|
293
294
|
locks: options?.locks ?? ctx.getOptional(LocksCapability),
|
|
294
295
|
tenant: tenantFrom(ctx.context),
|
|
295
296
|
signal: ctx.signal,
|
|
297
|
+
adapterName: ctx.provider,
|
|
296
298
|
}
|
|
297
299
|
}
|
|
298
300
|
|
|
@@ -570,7 +572,8 @@ export function withSandbox<TOffset extends string = string>(
|
|
|
570
572
|
|
|
571
573
|
const workspace = definition.workspace
|
|
572
574
|
if (workspace !== undefined) {
|
|
573
|
-
const
|
|
575
|
+
const virtualRoot = workspace.root ?? DEFAULT_WORKSPACE_ROOT
|
|
576
|
+
const root = resolveHarnessCwd(handle, virtualRoot)
|
|
574
577
|
const workspaceHash = computeWorkspaceHash(workspace)
|
|
575
578
|
const secrets = workspace.secrets
|
|
576
579
|
provideWorkspaceProjection(ctx, {
|
package/src/sandbox.ts
CHANGED
|
@@ -76,6 +76,8 @@ export interface SandboxEnsureContext {
|
|
|
76
76
|
locks?: LockStore
|
|
77
77
|
tenant?: { userId?: string; orgId?: string }
|
|
78
78
|
signal?: AbortSignal
|
|
79
|
+
/** Harness adapter name (`grok-build`, `claude-code`, `codex`, `opencode`). Optional. */
|
|
80
|
+
adapterName?: string
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
export interface SandboxDefinition {
|
|
@@ -123,6 +125,24 @@ const DESTROY_TIMEOUT_MS = 60 * 1000
|
|
|
123
125
|
const fallbackStore = new InMemorySandboxInstanceStore()
|
|
124
126
|
const fallbackLocks = new InMemoryLockStore()
|
|
125
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Put workspace secrets onto a live handle. Resume and snapshot restore skip
|
|
130
|
+
* bootstrap, so this is the only path that re-injects them after reconnect.
|
|
131
|
+
* Create injects secrets via `provider.create({ env })`, but resume/restore
|
|
132
|
+
* return a handle whose process env is empty unless we set it here. sbx in
|
|
133
|
+
* particular has no Docker Env on resume, so this is the only way secrets
|
|
134
|
+
* come back for that provider.
|
|
135
|
+
*/
|
|
136
|
+
async function applyWorkspaceSecrets(
|
|
137
|
+
handle: SandboxHandle,
|
|
138
|
+
workspace: WorkspaceDefinition | undefined,
|
|
139
|
+
): Promise<void> {
|
|
140
|
+
if (workspace?.secrets === undefined) return
|
|
141
|
+
const resolved = resolveAllSecrets(workspace.secrets)
|
|
142
|
+
if (Object.keys(resolved).length === 0) return
|
|
143
|
+
await handle.env.set(resolved)
|
|
144
|
+
}
|
|
145
|
+
|
|
126
146
|
export function defineSandbox(config: SandboxConfig): SandboxDefinition {
|
|
127
147
|
const keyInputFor = (ctx: SandboxEnsureContext): SandboxKeyInput => ({
|
|
128
148
|
threadId:
|
|
@@ -160,6 +180,7 @@ export function defineSandbox(config: SandboxConfig): SandboxDefinition {
|
|
|
160
180
|
signal: ctx.signal,
|
|
161
181
|
})
|
|
162
182
|
if (resumed) {
|
|
183
|
+
await applyWorkspaceSecrets(resumed, config.workspace)
|
|
163
184
|
await store.upsert({
|
|
164
185
|
...existing,
|
|
165
186
|
latestRunId: ctx.runId,
|
|
@@ -183,6 +204,7 @@ export function defineSandbox(config: SandboxConfig): SandboxDefinition {
|
|
|
183
204
|
: undefined,
|
|
184
205
|
signal: ctx.signal,
|
|
185
206
|
})
|
|
207
|
+
await applyWorkspaceSecrets(restored, config.workspace)
|
|
186
208
|
await store.upsert({
|
|
187
209
|
...existing,
|
|
188
210
|
providerSandboxId: restored.id,
|
|
@@ -208,6 +230,7 @@ export function defineSandbox(config: SandboxConfig): SandboxDefinition {
|
|
|
208
230
|
? resolveAllSecrets(config.workspace.secrets)
|
|
209
231
|
: undefined,
|
|
210
232
|
signal: ctx.signal,
|
|
233
|
+
adapterName: ctx.adapterName,
|
|
211
234
|
})
|
|
212
235
|
|
|
213
236
|
if (config.workspace) {
|
package/src/tool-bridge.ts
CHANGED
|
@@ -38,7 +38,9 @@ export const BRIDGED_MCP_SERVER_NAME = 'tanstack'
|
|
|
38
38
|
|
|
39
39
|
/** Hostname the sandbox uses to reach the bridge endpoint, per provider. */
|
|
40
40
|
export function hostForSandbox(provider: string): string {
|
|
41
|
-
return provider === 'docker'
|
|
41
|
+
return provider === 'docker' || provider === 'sbx'
|
|
42
|
+
? 'host.docker.internal'
|
|
43
|
+
: '127.0.0.1'
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
/** Result of a permission decision returned to the harness's prompt tool. */
|