mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Machine-produced by `pnpm run rescope-vendor --apply` plus the regeneration it prints: `pnpm install` for the lockfile, `pnpm run gen-third-party-notices`, `verify-translation-pairing --write` for the touched bilingual pairs, `gen-doc-graphs`, and one typert snapshot whose ids embed character offsets. `pnpm run rescope-vendor --check` verifies the result. Renames nine vendored packages (cordis, cosmokit, schemastery and the six @cordisjs plugins) and every reference that resolves them: manifest names and dependency keys, module specifiers including declare-module merges, cordis.yml plugin names, tsconfig paths, every Markdown fence, and `docs/` prose. Directory names, upstream versions, and dependency ranges are unchanged, so vendor/README.md still reads as an upstream snapshot; its manifest table gains an upstream-name column so THIRD_PARTY_NOTICES keeps MIT attribution pointed at each fork's origin. The tutorial tier follows the rename end to end: its yaml fences named plugins the Loader can no longer resolve, its `ts ignore-check` fences disagreed with the compiled fences beside them, and its prose quoted both. The contracts that told readers to keep upstream names — the root convention and the vendoring cookbook's tree comment and manifest invariant — now say to rescope instead. Two rules read `@deepseek-ai/` as "another workspace plugin": the client bundle purity gate now names the vendored libraries a browser bundle inlines, and the files where a bare `cordis` is an agent-preset id keep that product data.
190 lines
8.0 KiB
TypeScript
190 lines
8.0 KiB
TypeScript
/**
|
|
* Sandbox-consuming PowerShell executor — the pwsh twin of
|
|
* `@deepseek-ai/dsh-bash-sandbox`. It wraps the exact local pwsh argv through
|
|
* `ctx.sandbox` (which on Windows resolves to the ACL restricted-token runner
|
|
* chain), inherits local process mechanics, and reports the selected mode,
|
|
* enforcement, and denial facts. Positive runner-launch evidence means the
|
|
* command never ran: foreground calls throw `SANDBOX_UNAVAILABLE`, while
|
|
* background processes carry `runnerFailed`; other spawn rejections retain
|
|
* local-executor semantics. The tool layer owns the escalation approval flow
|
|
* through `ctx.approval`; this executor reports the sandbox facts the tool
|
|
* renders.
|
|
* @module @deepseek-ai/dsh-pwsh-sandbox
|
|
*/
|
|
|
|
import { Context } from '@deepseek-ai/cordis'
|
|
import type { BashExecRequest, BashExecSpec, BashProcess, BashRunResult } from '@deepseek-ai/dsh-bash'
|
|
import { SandboxUnavailableError } from '@deepseek-ai/dsh-sandbox'
|
|
import type {
|
|
ConfinedArgv,
|
|
ConfinedSandboxMode,
|
|
RunnerFailureRule,
|
|
SandboxEnforcement,
|
|
SandboxExecutionPolicy,
|
|
SandboxMode,
|
|
SandboxPolicy,
|
|
} from '@deepseek-ai/dsh-sandbox'
|
|
import type {} from '@deepseek-ai/dsh-sandbox-policy'
|
|
import { PwshLocalExecutor } from '@deepseek-ai/dsh-pwsh-local'
|
|
import type { Config as LocalConfig } from '@deepseek-ai/dsh-pwsh-local'
|
|
import { classifyDenial, classifyRunnerFailure, isRunnerSpawnFailure, matchesSignature } from './helpers.ts'
|
|
|
|
/**
|
|
* Plugin config: the local executor's knobs, verbatim. The sandbox policy —
|
|
* the default mode and fallback `workspace-write` root — is NOT here: it lives
|
|
* on `ctx.sandboxPolicy` (`@deepseek-ai/dsh-sandbox-policy`), which resolves
|
|
* each calling session's mode and cwd for every enforcing capability. The
|
|
* runner choice is likewise the `ctx.sandbox` provider's config, not this
|
|
* executor's.
|
|
*/
|
|
export type Config = LocalConfig
|
|
|
|
/**
|
|
* Registers as `ctx.bash` in place of the local pwsh executor and requires a
|
|
* `ctx.sandbox` provider plus `ctx.sandboxPolicy`; the tool layer carries the
|
|
* sandbox denial rendering and escalation surface (see the
|
|
* pwsh-tool-and-executor Agent Note). Tool calls pass the calling session's
|
|
* resolved policy; direct calls fall back to deployment policy.
|
|
* `result.sandbox` reports the mode, enforcement, and denial facts the tool
|
|
* renders.
|
|
*/
|
|
/* jscpd:ignore-start -- deliberate call-for-call mirror of bash-sandbox's executor (pwsh-tool-and-executor Agent Note) */
|
|
export class SandboxPwshExecutor extends PwshLocalExecutor {
|
|
static override inject = ['subprocess', 'sandbox', 'sandboxPolicy']
|
|
|
|
// No own Config: the sandbox default (mode + workspaceRoot) moved to
|
|
// ctx.sandboxPolicy, so this executor inherits PwshLocalExecutor's Config
|
|
// verbatim (the config catalog walks the inherited static).
|
|
|
|
private readonly mode: SandboxMode
|
|
/**
|
|
* Per-process confinement facts retained until settlement. Providers may
|
|
* vary enforcement and diagnostic dialect between overlapping calls, so a
|
|
* shared latest-wrap value would classify a process against the wrong facts.
|
|
* Unconfined processes have no entry.
|
|
*/
|
|
private readonly processFacts = new Map<BashProcess, {
|
|
mode: ConfinedSandboxMode
|
|
enforcement: SandboxEnforcement
|
|
denialSignatures: readonly string[]
|
|
runnerFailureRules: readonly RunnerFailureRule[]
|
|
runnerProgram: string | undefined
|
|
workdir: string
|
|
}>()
|
|
|
|
constructor(ctx: Context, config: Config) {
|
|
super(ctx, config)
|
|
// The default mode is the capability fact used for schema advertisement;
|
|
// actual tool executions carry their resolved per-call policy.
|
|
this.mode = ctx.sandboxPolicy.defaultMode
|
|
}
|
|
|
|
/** The configured default mode — the capability fact the tool layer reads. */
|
|
override get sandboxMode(): SandboxMode {
|
|
return this.mode
|
|
}
|
|
|
|
/**
|
|
* Stamp a complete per-call policy onto the spec. Tool calls supply the
|
|
* calling session's resolved mode and root; lower-level callers fall back to
|
|
* the deployment policy.
|
|
*/
|
|
override resolve(request: BashExecRequest): BashExecSpec {
|
|
return { ...super.resolve(request), sandboxPolicy: request.sandboxPolicy ?? this.ctx.sandboxPolicy.resolve() }
|
|
}
|
|
|
|
override async run(spec: BashExecSpec): Promise<BashRunResult> {
|
|
const policy = spec.sandboxPolicy as SandboxExecutionPolicy
|
|
const { mode } = policy
|
|
if (mode === 'danger-full-access') {
|
|
const result = await super.run(spec)
|
|
return { ...result, sandbox: { mode, denied: false } }
|
|
}
|
|
const confined = this.confine(spec, { ...policy, mode })
|
|
let result: BashRunResult
|
|
try {
|
|
result = await this.runArgv(spec, confined.argv)
|
|
} catch (error) {
|
|
// An upstream abort remains cancellation even when it prevents spawn.
|
|
if (spec.signal?.aborted === true) spec.signal.throwIfAborted()
|
|
if (isRunnerSpawnFailure(error, confined.argv[0], spec.workdir)) {
|
|
throw new SandboxUnavailableError(mode, String(error))
|
|
}
|
|
throw error
|
|
}
|
|
// Runner failure outranks denial because the command did not run. Carry
|
|
// the matched fatal line, not an informational line that preceded it.
|
|
const runnerFailure = classifyRunnerFailure(result.exitCode, result.stderr.text, confined.runnerFailureRules)
|
|
if (runnerFailure !== undefined) {
|
|
throw new SandboxUnavailableError(mode, runnerFailure.detail)
|
|
}
|
|
return { ...result, sandbox: { mode, denied: classifyDenial(result, confined.denialSignatures), enforcement: confined.enforcement } }
|
|
}
|
|
|
|
override start(spec: BashExecSpec): BashProcess {
|
|
const policy = spec.sandboxPolicy as SandboxExecutionPolicy
|
|
const { mode } = policy
|
|
if (mode === 'danger-full-access') return super.start(spec)
|
|
// Once startArgv returns, install facts synchronously; promise settlement
|
|
// cannot run before start() returns.
|
|
const confined = this.confine(spec, { ...policy, mode })
|
|
let proc: BashProcess
|
|
try {
|
|
proc = this.startArgv(spec, confined.argv)
|
|
} catch (error) {
|
|
if (isRunnerSpawnFailure(error, confined.argv[0], spec.workdir)) {
|
|
throw new SandboxUnavailableError(mode, String(error))
|
|
}
|
|
throw error
|
|
}
|
|
const { enforcement, denialSignatures, runnerFailureRules } = confined
|
|
this.processFacts.set(proc, {
|
|
mode,
|
|
enforcement,
|
|
denialSignatures,
|
|
runnerFailureRules,
|
|
runnerProgram: confined.argv[0],
|
|
workdir: spec.workdir,
|
|
})
|
|
return proc
|
|
}
|
|
|
|
/**
|
|
* Stamp per-process sandbox facts before `done` settles. Full-access
|
|
* processes have no facts; signal deaths are not denials.
|
|
*/
|
|
protected override onProcessDone(proc: BashProcess, stderr: string, spawnFailed: boolean, spawnError?: unknown): void {
|
|
const facts = this.processFacts.get(proc)
|
|
if (facts !== undefined) {
|
|
this.processFacts.delete(proc)
|
|
// A rejected spawn never started the confined launch. Otherwise runner
|
|
// failure outranks denial because its diagnostics may contain denial terms.
|
|
const runnerFailed = spawnFailed
|
|
? isRunnerSpawnFailure(spawnError, facts.runnerProgram, facts.workdir)
|
|
: classifyRunnerFailure(proc.exitCode, stderr, facts.runnerFailureRules) !== undefined
|
|
proc.sandbox = {
|
|
mode: facts.mode,
|
|
denied: !runnerFailed && matchesSignature(proc.exitCode, stderr, facts.denialSignatures),
|
|
enforcement: facts.enforcement,
|
|
...(runnerFailed ? { runnerFailed } : {}),
|
|
}
|
|
}
|
|
super.onProcessDone(proc, stderr, spawnFailed, spawnError)
|
|
}
|
|
|
|
/**
|
|
* Wrap one pwsh invocation via the `ctx.sandbox` provider. Provider errors
|
|
* propagate unchanged; the returned argv is handed directly to the local
|
|
* executor's subprocess path.
|
|
* @param spec - resolved execution spec whose pwsh argv is confined.
|
|
* @param policy - resolved confined execution policy.
|
|
* @returns the provider's exact argv and settlement-classification facts.
|
|
*/
|
|
private confine(spec: BashExecSpec, policy: SandboxPolicy): ConfinedArgv {
|
|
return this.ctx.sandbox.confine(this.argv(spec), policy)
|
|
}
|
|
}
|
|
/* jscpd:ignore-end */
|
|
|
|
export default SandboxPwshExecutor
|