@tanstack/ai-sandbox
Version:
Provider-agnostic sandbox layer for TanStack AI — run harness adapters inside isolated sandboxes (defineSandbox, defineWorkspace, withSandbox) with a uniform SandboxHandle, workspace bootstrap, policy, and resumable lifecycle.
47 lines (43 loc) • 2 kB
text/typescript
/**
* Workspace projection capability — provided by `withSandbox` and consumed by
* harness adapters (claude-code, codex, opencode) to idempotently
* project skills, plugins, and resolved secrets into the native harness format.
*
* The capability carries the raw provisioning inputs (skills, plugins, a
* resolve function for secret refs) together with a marker path that lets
* adapters guard the projection with a one-time idempotency file.
*/
import { createCapability } from '@tanstack/ai'
import type { SecretRef } from './secrets'
import type { WorkspaceSkill } from './workspace'
/**
* The shape provided to harness adapters via the sandbox projection capability.
* Harness adapters read this in their `chatStream` setup to project workspace
* inputs into their native format (MCP config, skills dirs, plugin installs).
*/
export interface WorkspaceProjection {
/** Skills declared on the workspace — MCP servers, file skills, git repos, etc. */
skills: Array<WorkspaceSkill>
/** Harness plugin identifiers to install idempotently. */
plugins: Array<string>
/**
* Resolve a SecretRef to its plaintext value. Bound to the workspace's
* secrets registry; throws when the ref is unknown.
*/
resolveSecret: (ref: SecretRef) => string
/**
* Absolute path to the idempotency marker file. Harness adapters write this
* file after a successful projection so subsequent runs skip re-projection.
* The file is NOT included in snapshots — absent on restore, triggering
* re-projection (which re-writes any secret-bearing config files).
*/
markerPath: string
/** Workspace root inside the sandbox (e.g. `/workspace`). */
root: string
/** Named commands declared on the workspace (e.g. `{ test: 'pnpm test' }`). */
scripts?: Record<string, string>
}
export const ProjectionCapability =
createCapability<WorkspaceProjection>()('sandbox-projection')
export const [getWorkspaceProjection, provideWorkspaceProjection] =
ProjectionCapability