diff --git a/.changeset/daytona-workspace-secrets.md b/.changeset/daytona-workspace-secrets.md new file mode 100644 index 0000000000..ef0dc33e57 --- /dev/null +++ b/.changeset/daytona-workspace-secrets.md @@ -0,0 +1,6 @@ +--- +'@tanstack/ai-sandbox-daytona': patch +'@tanstack/ai-isolate-daytona': patch +--- + +fix: mount workspace secrets as Daytona organization Secrets so values never land in the sandbox record or command strings diff --git a/docs/config.json b/docs/config.json index f2e7b13277..cd5bf6f18a 100644 --- a/docs/config.json +++ b/docs/config.json @@ -698,7 +698,7 @@ "label": "Providers", "to": "sandbox/providers", "addedAt": "2026-06-29", - "updatedAt": "2026-08-24" + "updatedAt": "2026-09-04" }, { "label": "Harnesses", diff --git a/docs/sandbox/providers.md b/docs/sandbox/providers.md index 3af51eb488..5fb5e9c8b6 100644 --- a/docs/sandbox/providers.md +++ b/docs/sandbox/providers.md @@ -191,9 +191,13 @@ const daytona = daytonaSandbox({ - **Isolation:** a managed cloud sandbox on a remote VM you do not run yourself. - **Auth / env:** needs `DAYTONA_API_KEY`. Put harness credentials in - [workspace secrets](./provisioning). They are applied to the live sandbox - at create, resume, and restore. They are not stored on the Daytona create - record, and they are not written into command history. + [workspace secrets](./provisioning). At create and snapshot restore, + Daytona stores each value as an organization Secret and mounts a + placeholder in the sandbox env. The create record, the dashboard env + view, and session command strings do not contain the real value. Daytona + substitutes the value on outbound HTTPS requests. Per-command `opts.env` + uses `executeCommand`'s env argument or a sourced env file. It never + writes `export KEY=` prefixes into the command string. - **Snapshot / resume:** point-in-time snapshots after setup (default when `lifecycle.snapshot` is `'after-setup'`). Pass `snapshot` on `daytonaSandbox()` to pick the Daytona image (for example diff --git a/packages/ai-isolate-daytona/package.json b/packages/ai-isolate-daytona/package.json index 9463108e9e..98b8a1878a 100644 --- a/packages/ai-isolate-daytona/package.json +++ b/packages/ai-isolate-daytona/package.json @@ -52,7 +52,7 @@ "@tanstack/ai-code-mode": "workspace:^" }, "devDependencies": { - "@daytona/sdk": "^0.191.0", + "@daytona/sdk": "^0.192.0", "@tanstack/ai-code-mode": "workspace:*", "@vitest/coverage-v8": "4.1.10" } diff --git a/packages/ai-sandbox-daytona/package.json b/packages/ai-sandbox-daytona/package.json index da599519f1..2c4e105742 100644 --- a/packages/ai-sandbox-daytona/package.json +++ b/packages/ai-sandbox-daytona/package.json @@ -42,7 +42,7 @@ "test:types": "tsc" }, "dependencies": { - "@daytona/sdk": "^0.191.0" + "@daytona/sdk": "^0.192.0" }, "peerDependencies": { "@tanstack/ai-sandbox": "workspace:^" diff --git a/packages/ai-sandbox-daytona/src/handle.ts b/packages/ai-sandbox-daytona/src/handle.ts index fd00c811da..534567e76e 100644 --- a/packages/ai-sandbox-daytona/src/handle.ts +++ b/packages/ai-sandbox-daytona/src/handle.ts @@ -3,8 +3,10 @@ * isolation: fs/exec/git operate inside the remote sandbox; paths are real * sandbox paths (default workdir `/home/daytona/workspace`). * - * fs and git use the native Daytona SDK. Blocking exec sends env through - * `executeCommand`'s env argument so secret values never enter the stored + * fs and git use the native Daytona SDK. Workspace secrets are mounted as + * Daytona organization Secrets at create (opaque `dtn_secret_*` placeholders + * in the sandbox env). Blocking exec sends leftover per-call env through + * `executeCommand`'s env argument so those values never enter the stored * command string. Spawn sources a workdir env file for the same reason. * * NOTE: Daytona's `executeCommand` returns a single combined `result` string @@ -151,6 +153,13 @@ export interface DaytonaHandleDeps { sandbox: Sandbox /** Working directory inside the sandbox (the `/workspace` virtual root maps here). */ workdir: string + /** + * When false, `env.set` does not overlay values onto exec/spawn. Use this + * after workspace secrets are mounted as Daytona organization Secrets so + * later `env.set` (bootstrap, resume) cannot put plaintext into command + * env, the spawn env file, or the process environment. + */ + applyEnvSet?: boolean } export class DaytonaHandle implements SandboxHandle { @@ -166,11 +175,13 @@ export class DaytonaHandle implements SandboxHandle { private readonly sandbox: Sandbox private readonly workdir: string + private readonly applyEnvSet: boolean private readonly envVars: Record = {} constructor(deps: DaytonaHandleDeps) { this.sandbox = deps.sandbox this.workdir = deps.workdir + this.applyEnvSet = deps.applyEnvSet ?? true this.workspaceRoot = deps.workdir this.id = deps.sandbox.id @@ -234,7 +245,7 @@ export class DaytonaHandle implements SandboxHandle { this.env = { set: (vars) => { - Object.assign(this.envVars, vars) + if (this.applyEnvSet) Object.assign(this.envVars, vars) return Promise.resolve() }, } diff --git a/packages/ai-sandbox-daytona/src/provider.ts b/packages/ai-sandbox-daytona/src/provider.ts index 1c26cd575f..1c13ed3893 100644 --- a/packages/ai-sandbox-daytona/src/provider.ts +++ b/packages/ai-sandbox-daytona/src/provider.ts @@ -1,4 +1,5 @@ -import { Daytona } from '@daytona/sdk' +import { createHash } from 'node:crypto' +import { Daytona, DaytonaConflictError } from '@daytona/sdk' import { DAYTONA_CAPS, DaytonaHandle } from './handle' import type { CreateSandboxFromSnapshotParams, @@ -51,6 +52,21 @@ function shQuote(value: string): string { return `'${value.replace(/'/g, `'\\''`)}'` } +/** + * Organization Secret names must match `^[a-zA-Z_][a-zA-Z0-9_-]*$`. + * The value hash keeps two different values for the same env key from sharing one Secret. + */ +function daytonaOrgSecretName(envKey: string, value: string): string { + const hash = createHash('sha256').update(value).digest('hex').slice(0, 12) + const safe = envKey.replace(/[^a-zA-Z0-9_-]/g, '_') + const body = /^[a-zA-Z_]/.test(safe) ? safe : `k_${safe}` + return `tanstack_${body}_${hash}` +} + +function isConflictError(error: unknown): boolean { + return error instanceof DaytonaConflictError +} + class DaytonaProvider implements SandboxProvider { readonly name = 'daytona' private readonly daytona: Daytona @@ -80,15 +96,17 @@ class DaytonaProvider implements SandboxProvider { */ private async wrapCreated( sandbox: Awaited>, + applyEnvSet: boolean, ): Promise { await sandbox.process.executeCommand(`mkdir -p ${shQuote(this.workdir)}`) - return new DaytonaHandle({ sandbox, workdir: this.workdir }) + return new DaytonaHandle({ sandbox, workdir: this.workdir, applyEnvSet }) } private createParams(input: { snapshot?: string id?: string policy?: SandboxCreateInput['policy'] + secrets?: Record }): CreateSandboxFromSnapshotParams { return { language: this.config.language ?? 'typescript', @@ -103,37 +121,62 @@ class DaytonaProvider implements SandboxProvider { ...(input.policy?.capabilities?.network === 'deny' ? { networkBlockAll: true } : {}), + ...(input.secrets !== undefined ? { secrets: input.secrets } : {}), } } - private async wrapReady( - sandbox: Awaited>, + /** + * Create-or-reuse organization Secrets and return env-var → secret-name. + * Empty values are skipped. A 409 means this name (key + value hash) already + * exists, so the mapping can reuse it. + */ + private async ensureOrgSecrets( env?: Record, - ): Promise { - const handle = await this.wrapCreated(sandbox) - if (env !== undefined) await handle.env.set(env) - return handle + ): Promise | undefined> { + if (env === undefined) return undefined + const secrets: Record = {} + for (const [key, value] of Object.entries(env)) { + if (value === '') continue + const name = daytonaOrgSecretName(key, value) + try { + await this.daytona.secret.create({ + name, + value, + description: 'TanStack AI workspace secret', + }) + } catch (error) { + if (!isConflictError(error)) throw error + } + secrets[key] = name + } + return Object.keys(secrets).length > 0 ? secrets : undefined } async create(input: SandboxCreateInput): Promise { + const secrets = await this.ensureOrgSecrets(input.env) const sandbox = await this.daytona.create( this.createParams({ snapshot: this.config.snapshot, id: input.id, policy: input.policy, + ...(secrets !== undefined ? { secrets } : {}), }), ) - return this.wrapReady(sandbox, input.env) + // Workspace secrets live in Daytona OS env as placeholders. Do not overlay + // plaintext via env.set (bootstrap and resume also call env.set). + return this.wrapCreated(sandbox, secrets === undefined) } async restoreSnapshot(input: SandboxRestoreInput): Promise { + const secrets = await this.ensureOrgSecrets(input.env) const sandbox = await this.daytona.create( this.createParams({ snapshot: input.snapshotId, policy: input.policy, + ...(secrets !== undefined ? { secrets } : {}), }), ) - return this.wrapReady(sandbox, input.env) + return this.wrapCreated(sandbox, secrets === undefined) } async resume(input: SandboxResumeInput): Promise { @@ -144,7 +187,13 @@ class DaytonaProvider implements SandboxProvider { if (sandbox.state === 'stopped' || sandbox.state === 'archived') { await sandbox.start() } - return new DaytonaHandle({ sandbox, workdir: this.workdir }) + // Secrets mounted at create stay in the sandbox env as placeholders. + // applyWorkspaceSecrets would otherwise overlay plaintext on spawn/exec. + return new DaytonaHandle({ + sandbox, + workdir: this.workdir, + applyEnvSet: false, + }) } catch { // Gone / not found. return null diff --git a/packages/ai-sandbox-daytona/tests/handle.test.ts b/packages/ai-sandbox-daytona/tests/handle.test.ts index fc370158d6..d44bd69b97 100644 --- a/packages/ai-sandbox-daytona/tests/handle.test.ts +++ b/packages/ai-sandbox-daytona/tests/handle.test.ts @@ -240,6 +240,37 @@ describe('DaytonaHandle env and native fs', () => { expect(command).not.toContain('export ') }) + it('applyEnvSet: false keeps env.set values out of executeCommand', async () => { + const executeCommand = vi.fn( + async ( + _command: string, + _cwd?: string, + _env?: Record, + ) => ({ result: '', exitCode: 0 }), + ) + const sandbox = { + id: 'sbx-1', + process: { executeCommand }, + delete: vi.fn(async () => {}), + } as unknown as Sandbox + const handle = new DaytonaHandle({ + sandbox, + workdir: '/home/daytona/workspace', + applyEnvSet: false, + }) + + await handle.env.set({ ANTHROPIC_API_KEY: 'sk-secret-value' }) + await handle.process.exec('echo hello', { + env: { GIT_ASKPASS_TOKEN: 'ghs_secret' }, + }) + + expect(executeCommand).toHaveBeenCalledWith( + 'echo hello', + '/home/daytona/workspace', + { GIT_ASKPASS_TOKEN: 'ghs_secret' }, + ) + }) + it('writes files through native uploadFile, not a base64 exec command', async () => { const uploadFile = vi.fn(async () => {}) const createFolder = vi.fn(async () => {}) diff --git a/packages/ai-sandbox-daytona/tests/provider.test.ts b/packages/ai-sandbox-daytona/tests/provider.test.ts index a1db107d2b..bea4b897f4 100644 --- a/packages/ai-sandbox-daytona/tests/provider.test.ts +++ b/packages/ai-sandbox-daytona/tests/provider.test.ts @@ -6,16 +6,29 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import type { Sandbox } from '@daytona/sdk' -const create = vi.fn() -const get = vi.fn() -const del = vi.fn() +const { create, get, del, secretCreate, DaytonaConflictError } = vi.hoisted( + () => { + class DaytonaConflictError extends Error { + statusCode = 409 + } + return { + create: vi.fn(), + get: vi.fn(), + del: vi.fn(), + secretCreate: vi.fn(), + DaytonaConflictError, + } + }, +) vi.mock('@daytona/sdk', () => ({ Daytona: class { create = create get = get delete = del + secret = { create: secretCreate } }, + DaytonaConflictError, })) import { daytonaSandbox } from '../src/index' @@ -25,6 +38,7 @@ function fakeRemoteSandbox( extras: { state?: string start?: ReturnType + executeCommand?: ReturnType } = {}, ): Sandbox { // Sandbox from @daytona/sdk is a large class. Tests only need these fields. @@ -33,7 +47,9 @@ function fakeRemoteSandbox( state: extras.state ?? 'started', start: extras.start ?? vi.fn(async () => {}), process: { - executeCommand: vi.fn(async () => ({ result: '', exitCode: 0 })), + executeCommand: + extras.executeCommand ?? + vi.fn(async () => ({ result: '', exitCode: 0 })), }, delete: vi.fn(async () => {}), } as unknown as Sandbox @@ -43,6 +59,8 @@ beforeEach(() => { create.mockReset() get.mockReset() del.mockReset() + secretCreate.mockReset() + secretCreate.mockResolvedValue({ name: 'created' }) }) describe('daytonaSandbox snapshots', () => { @@ -69,6 +87,30 @@ describe('daytonaSandbox snapshots', () => { expect(handle.id).toBe('sbx-restored') expect(handle.provider).toBe('daytona') }) + + it('mounts workspace secrets as organization Secrets on restore', async () => { + const restored = fakeRemoteSandbox('sbx-restored') + create.mockResolvedValue(restored) + const provider = daytonaSandbox({ apiKey: 'test-key' }) + + await provider.restoreSnapshot!({ + snapshotId: 'tanstack-ai-sandbox-snapshot-sbx-1-after-setup', + env: { ANTHROPIC_API_KEY: 'sk-secret-value' }, + }) + + const payload = create.mock.calls[0]?.[0] as { + snapshot?: string + secrets?: Record + envVars?: unknown + } + expect(payload.snapshot).toBe( + 'tanstack-ai-sandbox-snapshot-sbx-1-after-setup', + ) + expect(payload.secrets?.ANTHROPIC_API_KEY).toMatch( + /^tanstack_ANTHROPIC_API_KEY_[0-9a-f]{12}$/, + ) + expect(payload.envVars).toBeUndefined() + }) }) // Issue #1083: Daytona stops an idle sandbox after 15 minutes. resume() @@ -120,11 +162,35 @@ describe('daytonaSandbox resume', () => { await expect(provider.resume({ id: 'missing' })).resolves.toBeNull() }) + + it('does not overlay secret plaintext after resume', async () => { + const executeCommand = vi.fn( + async ( + _command: string, + _cwd?: string, + _env?: Record, + ) => ({ result: '', exitCode: 0 }), + ) + get.mockResolvedValue(fakeRemoteSandbox('sbx-live', { executeCommand })) + const provider = daytonaSandbox({ apiKey: 'test-key' }) + + const handle = await provider.resume({ id: 'sbx-live' }) + expect(handle).not.toBeNull() + await handle!.env.set({ ANTHROPIC_API_KEY: 'sk-secret-value' }) + await handle!.process.exec('echo hello') + + const overlay = executeCommand.mock.calls.filter((call) => { + const env = call[2] as Record | undefined + return env !== undefined && Object.values(env).includes('sk-secret-value') + }) + expect(overlay).toEqual([]) + }) }) // Issue #1084: create-time envVars stay in the Daytona sandbox record -// (GET /sandbox/:id returns them in plain text). Secrets go onto the -// handle after create, not into the create payload. +// (GET /sandbox/:id returns them in plain text). Workspace secrets are +// organization Secrets referenced by name. The sandbox env holds a +// placeholder, not the value. // Issue #1085: create must forward name, auto-stop, ephemeral, and // network block from the portable input / config. describe('daytonaSandbox create', () => { @@ -141,11 +207,155 @@ describe('daytonaSandbox create', () => { envVars: expect.anything(), }), ) - const payload = create.mock.calls[0]?.[0] as { envVars?: unknown } + const payload = create.mock.calls[0]?.[0] as { + envVars?: unknown + secrets?: Record + } expect(payload.envVars).toBeUndefined() expect(handle.id).toBe('sbx-1') }) + it('mounts workspace secrets as Daytona organization Secrets', async () => { + create.mockResolvedValue(fakeRemoteSandbox('sbx-1')) + const provider = daytonaSandbox({ apiKey: 'test-key' }) + + await provider.create({ + env: { ANTHROPIC_API_KEY: 'sk-secret-value' }, + }) + + expect(secretCreate).toHaveBeenCalledWith({ + name: expect.stringMatching(/^tanstack_ANTHROPIC_API_KEY_[0-9a-f]{12}$/), + value: 'sk-secret-value', + description: 'TanStack AI workspace secret', + }) + const secretName = (secretCreate.mock.calls[0]?.[0] as { name: string }) + .name + const payload = create.mock.calls[0]?.[0] as { + secrets?: Record + envVars?: unknown + } + expect(payload.secrets).toEqual({ ANTHROPIC_API_KEY: secretName }) + expect(payload.envVars).toBeUndefined() + expect(secretCreate.mock.invocationCallOrder[0]).toBeLessThan( + create.mock.invocationCallOrder[0] ?? Infinity, + ) + }) + + it('reuses an organization Secret when the name already exists', async () => { + secretCreate.mockRejectedValue(new DaytonaConflictError('exists')) + create.mockResolvedValue(fakeRemoteSandbox('sbx-1')) + const provider = daytonaSandbox({ apiKey: 'test-key' }) + + await provider.create({ + env: { ANTHROPIC_API_KEY: 'sk-secret-value' }, + }) + + const payload = create.mock.calls[0]?.[0] as { + secrets?: Record + } + expect(payload.secrets?.ANTHROPIC_API_KEY).toMatch( + /^tanstack_ANTHROPIC_API_KEY_[0-9a-f]{12}$/, + ) + }) + + it('skips empty secret values', async () => { + create.mockResolvedValue(fakeRemoteSandbox('sbx-1')) + const provider = daytonaSandbox({ apiKey: 'test-key' }) + + await provider.create({ + env: { ANTHROPIC_API_KEY: '' }, + }) + + expect(secretCreate).not.toHaveBeenCalled() + const payload = create.mock.calls[0]?.[0] as { secrets?: unknown } + expect(payload.secrets).toBeUndefined() + }) + + it('does not overlay secret plaintext onto exec after create', async () => { + const executeCommand = vi.fn( + async ( + _command: string, + _cwd?: string, + _env?: Record, + ) => ({ result: '', exitCode: 0 }), + ) + create.mockResolvedValue(fakeRemoteSandbox('sbx-1', { executeCommand })) + const provider = daytonaSandbox({ apiKey: 'test-key' }) + + const handle = await provider.create({ + env: { ANTHROPIC_API_KEY: 'sk-secret-value' }, + }) + // bootstrapWorkspace / applyWorkspaceSecrets call env.set with the + // resolved plaintext. That must not reach executeCommand. + await handle.env.set({ ANTHROPIC_API_KEY: 'sk-secret-value' }) + await handle.process.exec('echo hello') + + const secretCalls = executeCommand.mock.calls.filter((call) => { + const env = call[2] as Record | undefined + return env !== undefined && Object.values(env).includes('sk-secret-value') + }) + expect(secretCalls).toEqual([]) + const commandCalls = executeCommand.mock.calls.filter( + (call) => call[0] === 'echo hello', + ) + expect(commandCalls.length).toBeGreaterThan(0) + for (const call of commandCalls) { + expect(String(call[0])).not.toContain('sk-secret-value') + } + }) + + it('does not write secret plaintext into the spawn env file', async () => { + const executeCommand = vi.fn( + async ( + _command: string, + _cwd?: string, + _env?: Record, + ) => ({ result: '', exitCode: 0 }), + ) + const uploadFile = vi.fn(async (_data: Buffer, _path: string) => {}) + const createFolder = vi.fn(async () => {}) + const executeSessionCommand = vi.fn( + async (_sessionId: string, _request: { command: string }) => ({ + cmdId: 'cmd-1', + }), + ) + const sandbox = fakeRemoteSandbox('sbx-1', { executeCommand }) + Object.assign(sandbox, { + fs: { uploadFile, createFolder }, + process: { + ...sandbox.process, + createSession: vi.fn(async () => {}), + executeSessionCommand, + getSessionCommandLogs: vi.fn(async () => {}), + getSessionCommand: vi.fn(async () => ({ exitCode: 0 })), + deleteSession: vi.fn(async () => {}), + sendSessionCommandInput: vi.fn(async () => {}), + }, + }) + create.mockResolvedValue(sandbox) + const provider = daytonaSandbox({ apiKey: 'test-key' }) + + const handle = await provider.create({ + env: { ANTHROPIC_API_KEY: 'sk-secret-value' }, + }) + await handle.env.set({ ANTHROPIC_API_KEY: 'sk-secret-value' }) + const proc = await handle.process.spawn('echo hi') + await proc.wait() + + for (const call of uploadFile.mock.calls) { + const data = call[0] + const body = + typeof data === 'string' + ? data + : Buffer.isBuffer(data) + ? data.toString('utf8') + : '' + expect(body).not.toContain('sk-secret-value') + } + const command = executeSessionCommand.mock.calls[0]?.[1]?.command + expect(command).not.toContain('sk-secret-value') + }) + it('forwards the deterministic instance id as the Daytona name', async () => { create.mockResolvedValue(fakeRemoteSandbox('sbx-1')) const provider = daytonaSandbox({ apiKey: 'test-key' }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da0e7c0f37..9d3748c623 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2167,8 +2167,8 @@ importers: packages/ai-isolate-daytona: devDependencies: '@daytona/sdk': - specifier: ^0.191.0 - version: 0.191.0(ws@8.21.0) + specifier: ^0.192.0 + version: 0.192.0(ws@8.21.0) '@tanstack/ai-code-mode': specifier: workspace:* version: link:../ai-code-mode @@ -2670,8 +2670,8 @@ importers: packages/ai-sandbox-daytona: dependencies: '@daytona/sdk': - specifier: ^0.191.0 - version: 0.191.0(ws@8.21.0) + specifier: ^0.192.0 + version: 0.192.0(ws@8.21.0) devDependencies: '@tanstack/ai-sandbox': specifier: workspace:* @@ -4528,14 +4528,14 @@ packages: '@date-fns/tz@1.4.1': resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==} - '@daytona/api-client@0.191.0': - resolution: {integrity: sha512-wa5mZugJ4I/o7nRHcZArkzY1+OHw/f3niKCoVZ/pkqwIo5O5ANBWN94CktmoS8THZKmZuSJM+ysjYQ80O+/5bg==} + '@daytona/api-client@0.192.0': + resolution: {integrity: sha512-fBzQ7KT9ZW2c4TgryYVGI8KUiUH02SCuKl1m0hqJQZDVkE6sbMiMlm5DZ0jwMCbQ8afWyOscvXmSSxdGQ/jUKQ==} - '@daytona/sdk@0.191.0': - resolution: {integrity: sha512-4HImbAQRrUXO2iszhH8ZP9IQKcF+6KRnuHr+6c9wJJm+98g0zFm15Dhc5TYldaUiVNaJPLMiPfVmw8M9Pt+ikw==} + '@daytona/sdk@0.192.0': + resolution: {integrity: sha512-pAA1curJCiZ0rqZcE0BUIjsgS90QdDFZ2QYw8nVWwGjjdr+Fndof4MaJfoZRjpcMHjUBoqEZpzO9C5HPv38QeA==} - '@daytona/toolbox-api-client@0.191.0': - resolution: {integrity: sha512-NAW7Ic3O7pKjRw0mLVgqMAs4cokC7ZK8IszRkTvNk44KdGXKzH/bbzGxn0q/vcWQOOpO7mBwZvbMtnGDKGiR8Q==} + '@daytona/toolbox-api-client@0.192.0': + resolution: {integrity: sha512-fEyA3YPK+IJezECBfZoNhf29qtZhy8AqI0lcgR+Bob6hEiInx9+sH26506ZkxmpGM4/5EApeLzUI1g5B9u2XHA==} '@deno/shim-deno-test@0.5.0': resolution: {integrity: sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w==} @@ -19584,19 +19584,19 @@ snapshots: '@date-fns/tz@1.4.1': {} - '@daytona/api-client@0.191.0': + '@daytona/api-client@0.192.0': dependencies: axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) transitivePeerDependencies: - debug - supports-color - '@daytona/sdk@0.191.0(ws@8.21.0)': + '@daytona/sdk@0.192.0(ws@8.21.0)': dependencies: '@aws-sdk/client-s3': 3.1075.0 '@aws-sdk/lib-storage': 3.1075.0(@aws-sdk/client-s3@3.1075.0) - '@daytona/api-client': 0.191.0 - '@daytona/toolbox-api-client': 0.191.0 + '@daytona/api-client': 0.192.0 + '@daytona/toolbox-api-client': 0.192.0 '@iarna/toml': 2.2.5 '@opentelemetry/api': 1.9.1 '@opentelemetry/exporter-trace-otlp-http': 0.217.0(@opentelemetry/api@1.9.1) @@ -19621,7 +19621,7 @@ snapshots: - supports-color - ws - '@daytona/toolbox-api-client@0.191.0': + '@daytona/toolbox-api-client@0.192.0': dependencies: axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) transitivePeerDependencies: