Files
deepseek-harness/packages/ssh/sandbox-ssh/src/index.ts
T

34 lines
1.7 KiB
TypeScript

/** Remote argv wrapper that selects and applies the sandbox on the SSH host. */
import { SandboxProvider, SandboxUnavailableError } from '@deepseek-ai/dsh-sandbox'
import type { ConfinedArgv, SandboxPolicy } from '@deepseek-ai/dsh-sandbox'
import type {} from '@deepseek-ai/dsh-ssh'
import { z } from 'zod'
const factsSchema = z.object({ argv: z.array(z.string()).min(1), enforcement: z.enum(['full', 'partial']), denialSignatures: z.array(z.string()), runnerFailureRules: z.array(z.object({ allowedExitCodes: z.array(z.number().int()).optional(), fatalSignatures: z.array(z.string()), informationalLines: z.array(z.string()).optional() }).strict()) }).strict()
/** Resolve each confinement request on the same host as its filesystem and subprocess providers. */
export class SshSandboxProvider extends SandboxProvider {
static inject = ['ssh']
override async confine(argv: readonly string[], policy: SandboxPolicy, signal?: AbortSignal): Promise<ConfinedArgv> {
signal?.throwIfAborted()
try {
const confined = await this.ctx.ssh.request('sandbox', { argv, policy }, factsSchema, signal)
signal?.throwIfAborted()
return {
...confined,
runnerFailureRules: confined.runnerFailureRules.map(rule => ({
fatalSignatures: rule.fatalSignatures,
...(rule.allowedExitCodes === undefined ? {} : { allowedExitCodes: rule.allowedExitCodes }),
...(rule.informationalLines === undefined ? {} : { informationalLines: rule.informationalLines }),
})),
}
} catch (error) {
signal?.throwIfAborted()
throw new SandboxUnavailableError(policy.mode, error instanceof Error ? error.message : String(error))
}
}
}
export default SshSandboxProvider