( definition: SandboxDefinition, )
| 102 | } |
| 103 | |
| 104 | export function withSandbox( |
| 105 | definition: SandboxDefinition, |
| 106 | ): DefinedChatMiddleware< |
| 107 | unknown, |
| 108 | readonly [], |
| 109 | readonly [typeof SandboxCapability, typeof ProjectionCapability] |
| 110 | > { |
| 111 | return defineChatMiddleware({ |
| 112 | name: 'sandbox', |
| 113 | provides: [SandboxCapability, ProjectionCapability], |
| 114 | // SandboxPolicyCapability is provided conditionally (only when the |
| 115 | // definition has a policy), so it is intentionally NOT declared here — |
| 116 | // consumers read it via `getOptional`. |
| 117 | optionalRequires: [SandboxStoreCapability, LocksCapability], |
| 118 | |
| 119 | async setup(ctx) { |
| 120 | const ensureCtx = buildEnsureCtx(ctx) |
| 121 | const handle = await definition.ensure(ensureCtx) |
| 122 | provideSandbox(ctx, handle) |
| 123 | if (definition.policy) provideSandboxPolicy(ctx, definition.policy) |
| 124 | |
| 125 | const workspace = definition.workspace |
| 126 | if (workspace !== undefined) { |
| 127 | const root = workspace.root ?? DEFAULT_WORKSPACE_ROOT |
| 128 | const workspaceHash = computeWorkspaceHash(workspace) |
| 129 | const secrets = workspace.secrets |
| 130 | provideWorkspaceProjection(ctx, { |
| 131 | skills: workspace.skills ?? [], |
| 132 | plugins: workspace.plugins ?? [], |
| 133 | resolveSecret: (ref) => { |
| 134 | if (secrets === undefined) { |
| 135 | throw new Error( |
| 136 | `resolveSecret: no secrets defined on this workspace (ref: "${ref.__secretName}")`, |
| 137 | ) |
| 138 | } |
| 139 | return resolveSecret(secrets, ref) |
| 140 | }, |
| 141 | markerPath: `${root}/.tanstack-projected-${workspaceHash}`, |
| 142 | root, |
| 143 | ...(workspace.scripts !== undefined |
| 144 | ? { scripts: workspace.scripts } |
| 145 | : {}), |
| 146 | }) |
| 147 | } |
| 148 | |
| 149 | const hooks = definition.hooks |
| 150 | await hooks?.onReady?.(handle) |
| 151 | |
| 152 | let watcher: SandboxWatchHandle | undefined |
| 153 | if (definition.fileEvents !== false) { |
| 154 | const runtime = getSandboxRuntime(ctx, { optional: true }) |
| 155 | watcher = await watchWorkspace(handle, { |
| 156 | onEvent: (event: SandboxFileEvent) => { |
| 157 | void dispatchDefinitionHooks(hooks, event) |
| 158 | runtime?.emit(event) |
| 159 | }, |
| 160 | ...(ctx.signal !== undefined ? { signal: ctx.signal } : {}), |
| 161 | }) |
no test coverage detected