@deepseek-ai/dsh-sandbox 0.1.1-rc.1 → 0.1.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +150 -8
- package/README.zh.md +155 -15
- package/lib/index.js +2 -1
- package/lib/types/escalation.d.ts +1 -1
- package/package.json +12 -9
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/sandbox/sandbox/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 1e39fe31ad607a23a5a59f3e143b6823409126f2
|
|
6
|
+
README.zh.md: 15d200ab6af5c6ff80091163624f5535799c6723
|
package/README.md
CHANGED
|
@@ -1,24 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "The process-sandbox service contract for users and maintainers composing, using, or extending same-world subprocess confinement."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# @deepseek-ai/dsh-sandbox
|
|
2
7
|
|
|
3
8
|
English | [中文](README.zh.md)
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
`dsh-sandbox` confines same-world subprocesses to a file-effect policy: commands run `read-only`, write only under the session workspace (`workspace-write`), or run unrestricted (`danger-full-access`), and every confined execution runs under a per-call policy. The bash and pwsh executors consume it, so a command — and everything it spawns — runs confined without the consumer knowing which platform runner is behind it. When the requested mode cannot be enforced, the call fails closed with a `SANDBOX_UNAVAILABLE` error instead of running unconfined. A denied call can request a strictly wider mode that a human approves once. Confinement is same-world only — backends share the host kernel and filesystem, while containers, microVMs, and remote executors replace whole capabilities instead.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Compose this service with one backend and a confined consumer, and every command the consumer runs executes under the policy you resolve — you see only the confinement result and its enforcement completeness, never the platform runner.
|
|
29
|
+
|
|
30
|
+
### When to choose it
|
|
31
|
+
|
|
32
|
+
Choose this package when a composition confines subprocesses on the host: it is the contract the local backends and the confined executors both implement, so mounting `sandbox-local` behind `ctx.sandbox` and a confined executor behind `ctx.shell` gives every bash or pwsh call a confined default. Choose something else when the process must run in an isolated environment — a container, microVM, or remote executor replaces the whole `ctx.shell`/`ctx.fs` capability rather than adding a backend here.
|
|
33
|
+
|
|
34
|
+
### Confining a command
|
|
35
|
+
|
|
36
|
+
Mount the service with a backend and a confined executor; the [base bundle](../../bundle/base/cordis.patch.yml) owns the shipped composition.
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- id: sandbox
|
|
40
|
+
name: '@deepseek-ai/dsh-sandbox-local' # the per-platform backend provider (ctx.sandbox)
|
|
41
|
+
- id: sandbox-policy
|
|
42
|
+
name: '@deepseek-ai/dsh-sandbox-policy' # the deployment default mode and workspace-write root
|
|
43
|
+
config:
|
|
44
|
+
mode: workspace-write # the deployment default every session starts from
|
|
45
|
+
workspaceRoot: !!js process.cwd() # the boundary workspace-write may write under
|
|
46
|
+
- id: bash
|
|
47
|
+
name: '@deepseek-ai/dsh-bash-sandbox' # the confined executor behind ctx.shell
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
With this composition, a bash call runs confined under `workspace-write`: writes inside the workspace succeed, writes outside it are denied, and the model can recover through the escalation flow below.
|
|
51
|
+
|
|
52
|
+
### Modes and enforcement
|
|
53
|
+
|
|
54
|
+
The mode names the file effects a command may perform; enforcement completeness reports how fully the backend governs them.
|
|
55
|
+
|
|
56
|
+
| Mode | Effect |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `read-only` | Denies writes except required sinks such as `/dev/null` |
|
|
59
|
+
| `workspace-write` | Allows writes under the workspace root plus a backend-defined temp area |
|
|
60
|
+
| `danger-full-access` | Bypasses confinement; the consumer spawns its original argv |
|
|
61
|
+
|
|
62
|
+
Enforcement is reported per call: `full` means the backend governs every promised file effect, while `partial` means an active backend or older kernel ABI governs only a subset — the Windows ACL rung and older Landlock ABIs are the current partial cases, so a consumer that requires the absolute boundary can reject or surface them.
|
|
63
|
+
|
|
64
|
+
### Denied calls and escalation
|
|
65
|
+
|
|
66
|
+
When a confined call is denied, the operation reports a denial marker naming the mode — `[sandbox: file access denied under <mode> mode]` — and, when the composition advertises escalation, an escalation hint. The model may retry the exact call once with `sandbox_permissions` (the narrowest wider mode that suffices) plus a `justification`; the user sees one approval prompt and can allow once, reject, or cancel. The escalation must be strictly wider than the call's effective mode, and it applies to that one call only.
|
|
67
|
+
|
|
68
|
+
### Fail-closed behavior
|
|
69
|
+
|
|
70
|
+
When no backend can enforce the requested mode, the call fails with `SANDBOX_UNAVAILABLE` rather than running unconfined; the error text names the missing platform runner. A backend that fails after starting also reports a structured runner-failure signature, so a broken sandbox is distinguishable from a command failure.
|
|
71
|
+
|
|
72
|
+
-----
|
|
73
|
+
|
|
74
|
+
<a id="understand-the-implementation"></a>
|
|
75
|
+
## Understand the implementation
|
|
76
|
+
|
|
77
|
+
<details>
|
|
78
|
+
<summary>Implementation internals — click to expand</summary>
|
|
79
|
+
|
|
80
|
+
This section explains the design decisions behind the contract and points at the code that realizes them; the observable behavior is fully covered in [Use this package](#use-this-package).
|
|
81
|
+
|
|
82
|
+
### Design philosophy
|
|
83
|
+
|
|
84
|
+
- **Same-world by contract.** `ctx.sandbox` wraps argv under a host-path file policy; containers, microVMs, and remote execution replace the surrounding capability seam instead.
|
|
85
|
+
- **Policy rides the call.** `SandboxPolicy` is carried per call, never fixed on the provider: two consumers may confine under different policies at the same instant, and an escalated retry is a new call with a wider policy. Defaulting and resolution are explicit consumer steps.
|
|
86
|
+
- **Fail closed.** `confine()` returns enforcing argv or throws `SandboxUnavailableError`; silent unconfined passthrough is forbidden, and functional probes arbitrate multi-runner chains.
|
|
87
|
+
- **One vocabulary for denial and escalation.** The marker and hint texts and the strictly-wider ladder live here so the bash and fs families cannot drift apart.
|
|
6
88
|
|
|
7
|
-
|
|
89
|
+
### Source map
|
|
8
90
|
|
|
9
|
-
|
|
91
|
+
| File | Role |
|
|
92
|
+
|---|---|
|
|
93
|
+
| [`src/index.ts`](src/index.ts) | Plugin entry: `SandboxProvider` service, mode/enforcement/policy types, fail-closed error |
|
|
94
|
+
| [`src/escalation.ts`](src/escalation.ts) | Escalation vocabulary: wider-mode ladder, argument validation, denial and hint markers, approval choreography |
|
|
95
|
+
| [`src/roots.ts`](src/roots.ts) | Writable-root derivation shared by the Seatbelt profile and the in-process fs fence |
|
|
96
|
+
| [`src/invariant.ts`](src/invariant.ts) | Invariant companion (no runtime invariant; the abstract seam registers no event or data relation) |
|
|
10
97
|
|
|
11
|
-
|
|
98
|
+
### Escalation choreography
|
|
12
99
|
|
|
13
|
-
|
|
100
|
+
The ladder is a closed table — `read-only` may escalate to `workspace-write` or `danger-full-access`, `workspace-write` only to `danger-full-access` — checked at execution, never baked into a tool schema, whose enum stays the closed target vocabulary. [`approveEscalation`](src/escalation.ts) validates the `sandbox_permissions`/`justification` pairing, rejects non-widening requests without prompting a human, and maps every approval outcome to its own error before anything executes.
|
|
14
101
|
|
|
102
|
+
### Writable roots
|
|
103
|
+
|
|
104
|
+
`workspace-write` means "the workspace root plus the host temp areas": `writableRoots` derives that allow-list canonically, resolving symlinks and deduplicating, so the Seatbelt profile and the in-process fs fence grant exactly the same roots.
|
|
105
|
+
|
|
106
|
+
</details>
|
|
107
|
+
|
|
108
|
+
-----
|
|
109
|
+
|
|
110
|
+
<a id="further-exploration"></a>
|
|
111
|
+
## Further Exploration
|
|
112
|
+
|
|
113
|
+
Start with the subsystem reference for the exhaustive contract, then the backends, consumers, and policy source that realize it.
|
|
114
|
+
|
|
115
|
+
- [Process sandbox subsystem](../../../docs/subsystems/sandbox.md) — the complete vocabulary, per-call policy, and classification dialects.
|
|
116
|
+
- [The subprocess sandbox decision](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.md) — capability boundary, escalation design, and deferred phases.
|
|
117
|
+
- [Local sandbox backends](../sandbox-local/README.md) — the per-platform runners behind `ctx.sandbox`.
|
|
118
|
+
- [Bash sandbox executor](../../shell/bash-sandbox/README.md) — the confined bash consumer.
|
|
119
|
+
- [Sandbox policy package](../sandbox-policy/README.md) — where the per-call mode and workspace root come from.
|
|
120
|
+
|
|
121
|
+
-----
|
|
122
|
+
|
|
123
|
+
<a id="model-experience"></a>
|
|
15
124
|
## Model Experience
|
|
16
125
|
|
|
17
126
|
### Confinement error, indirectly
|
|
18
127
|
|
|
19
128
|
#### What the model sees
|
|
20
129
|
|
|
21
|
-
Through [`dsh-bash-sandbox`](../../shell/bash-sandbox/README.md) and [`dsh-tool-bash`](../../shell/tool-bash/README.md),
|
|
130
|
+
Through [`dsh-bash-sandbox`](../../shell/bash-sandbox/README.md) and [`dsh-tool-bash`](../../shell/tool-bash/README.md), a requested confined mode with no usable backend produces code `SANDBOX_UNAVAILABLE` and the exact error below; an execution-time runner failure appends ` Runner failure: <detail>`.
|
|
22
131
|
|
|
23
132
|
##### Exact error
|
|
24
133
|
|
|
@@ -34,10 +143,43 @@ Conditional error text is visible for that call and retained in history until co
|
|
|
34
143
|
|
|
35
144
|
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
|
|
36
145
|
|
|
146
|
+
### Escalation request and outcome
|
|
147
|
+
|
|
148
|
+
#### What the model sees
|
|
149
|
+
|
|
150
|
+
A denied call surfaces the marker `[sandbox: file access denied under <mode> mode]` and, where the composition advertises escalation, the hint `[sandbox: escalation available — retry this exact <subject> once with sandbox_permissions (the narrowest wider mode that suffices) + justification; the approval prompt asks the user]`. The retry carries `sandbox_permissions` and a `justification`; the user's `allowed-once` / `rejected` / `cancelled` decision becomes the call's result text.
|
|
151
|
+
|
|
152
|
+
#### Token effect
|
|
153
|
+
|
|
154
|
+
Only the denied call's error and any escalation outcome text are visible; both are retained in history until compaction.
|
|
155
|
+
|
|
156
|
+
#### KV Cache effect
|
|
157
|
+
|
|
158
|
+
Append-only; escalation text follows the retained prefix and does not invalidate cached entries.
|
|
159
|
+
|
|
37
160
|
## Known Limitations and Deferred Work
|
|
38
161
|
|
|
162
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
These limits define when the seam is a poor fit or needs special operational care. They are current package constraints, not a general sandbox comparison or a task backlog.
|
|
166
|
+
|
|
39
167
|
- **File effects are the whole policy vocabulary** — the seam expresses no network, process, syscall, device, or credential restrictions.
|
|
40
168
|
- **Same-world confinement only** — containers, microVMs, and remote execution require replacing capability implementations rather than adding a provider here.
|
|
41
|
-
- **Denial reporting is a stderr dialect** — the seam returns backend signatures instead of a typed runtime denial channel, so consumers that need classification
|
|
42
|
-
- **Runner diagnostics are in-band** — exit status plus stderr evidence cannot prove which process wrote a matching line, so a confined child that deliberately mimics its runner can cause
|
|
169
|
+
- **Denial reporting is a stderr dialect** — the seam returns backend signatures instead of a typed runtime denial channel, so consumers that need classification infer it from the child process's output.
|
|
170
|
+
- **Runner diagnostics are in-band** — exit status plus stderr evidence cannot prove which process wrote a matching line, so a confined child that deliberately mimics its runner can cause a false availability or diagnostic attribution; this cannot bypass confinement, and an out-of-band runner-status channel is deferred.
|
|
43
171
|
- **One provider per context** — composing different sandbox mechanisms simultaneously requires a provider-level ladder or separate Cordis contexts; callers choose policy per call, not backend identity.
|
|
172
|
+
|
|
173
|
+
<a id="dev-note"></a>
|
|
174
|
+
### Dev Note
|
|
175
|
+
|
|
176
|
+
<details>
|
|
177
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
178
|
+
|
|
179
|
+
This Dev Note is working context for maintainers: undecided directions and open questions. It is explicitly non-authoritative — shipped behavior, limits, and accepted rationale live in the sections above, the package code, and the linked Agent Notes.
|
|
180
|
+
|
|
181
|
+
#### Future: consumers and environments
|
|
182
|
+
|
|
183
|
+
The [sandbox decision](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.md) lists deferred phases — an optional `subagent-acp` consumer that confines child agents (unconfined default) and environment-coherent capability group examples. Neither is decided; the Windows chain that note listed as deferred has since shipped through the ACL restricted-token rung of `sandbox-local`.
|
|
184
|
+
|
|
185
|
+
</details>
|
package/README.zh.md
CHANGED
|
@@ -1,26 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "进程沙箱服务约定:面向组合、使用或扩展同世界子进程隔离的用户与维护者。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# @deepseek-ai/dsh-sandbox
|
|
2
7
|
|
|
3
8
|
[English](README.md) | 中文
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## 概述
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
`dsh-sandbox` 将同世界子进程限制在文件效果策略之下:命令以 `read-only` 运行、只能写入会话工作区(`workspace-write`)或不受限制地运行(`danger-full-access`),每次受限执行都遵循一份逐调用策略。bash 与 pwsh 执行器直接消费它,因此命令及其派生的所有进程都在限制下运行,消费方无需知道背后是哪个平台 runner。无法强制执行所请求的模式时,调用以 `SANDBOX_UNAVAILABLE` 错误快速失败,绝不会不受限制地运行。被拒绝的调用可以请求一个由人类批准一次、严格更宽的模式。隔离仅限同世界——后端与宿主共享内核和文件系统,容器、microVM 与远程执行器会替换整个能力。
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
## 目录
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
-----
|
|
14
24
|
|
|
15
|
-
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
将此服务与一个后端和一个受限消费方组合,消费方运行的每条命令都会在你解析的策略下执行——你只看到隔离结果及其强制执行完整度,永远看不到 runner。
|
|
29
|
+
|
|
30
|
+
### 何时选择
|
|
31
|
+
|
|
32
|
+
当组合需要在宿主机上隔离子进程时选择本包:本地后端与受限执行器都实现这个约定,因此在 `ctx.sandbox` 后挂载 `sandbox-local`、在 `ctx.shell` 后挂载受限执行器,就能让每次 bash 或 pwsh 调用都有受限默认值。当进程必须在隔离环境中运行时请另选方案——容器、microVM 或远程执行器会替换整个 `ctx.shell`/`ctx.fs` 能力,而不是在这里添加后端。
|
|
33
|
+
|
|
34
|
+
### 隔离命令
|
|
35
|
+
|
|
36
|
+
挂载服务、后端与受限执行器;[base bundle](../../bundle/base/cordis.patch.yml)拥有随附组合。
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- id: sandbox
|
|
40
|
+
name: '@deepseek-ai/dsh-sandbox-local' # the per-platform backend provider (ctx.sandbox)
|
|
41
|
+
- id: sandbox-policy
|
|
42
|
+
name: '@deepseek-ai/dsh-sandbox-policy' # the deployment default mode and workspace-write root
|
|
43
|
+
config:
|
|
44
|
+
mode: workspace-write # the deployment default every session starts from
|
|
45
|
+
workspaceRoot: !!js process.cwd() # the boundary workspace-write may write under
|
|
46
|
+
- id: bash
|
|
47
|
+
name: '@deepseek-ai/dsh-bash-sandbox' # the confined executor behind ctx.shell
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
使用该组合时,bash 调用在 `workspace-write` 下受限运行:工作区内写入成功,工作区外写入被拒绝,模型可以通过下面的升权流程恢复。
|
|
51
|
+
|
|
52
|
+
### 模式与强制执行
|
|
53
|
+
|
|
54
|
+
模式指明命令可以执行的文件操作;强制执行完整度报告后端对这些操作的管辖程度。
|
|
55
|
+
|
|
56
|
+
| 模式 | 效果 |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `read-only` | 拒绝写入,必需 sink(如 `/dev/null`)除外 |
|
|
59
|
+
| `workspace-write` | 允许写入工作区根目录及后端定义的临时区域 |
|
|
60
|
+
| `danger-full-access` | 绕过隔离;消费方直接 spawn 原始 argv |
|
|
61
|
+
|
|
62
|
+
强制执行逐调用报告:`full` 表示后端管辖模式承诺的每个文件操作,`partial` 表示活动后端或较旧的内核 ABI 只管辖子集——Windows ACL 档与较旧的 Landlock ABI 是当前的部分强制执行情形,需要绝对边界的消费方可以拒绝或向上暴露它们。
|
|
63
|
+
|
|
64
|
+
### 被拒绝的调用与升权
|
|
65
|
+
|
|
66
|
+
受限调用被拒绝时,操作会报告指明模式的拒绝标记——`[sandbox: file access denied under <mode> mode]`——组合声明升权能力时还会给出升权提示。模型可以用 `sandbox_permissions`(足以放行的最窄更宽模式)加 `justification` 重试一次完全相同的调用;用户会看到一次审批提示,可以选择允许一次、拒绝或取消。升权必须严格宽于调用的生效模式,且只作用于该次调用。
|
|
67
|
+
|
|
68
|
+
### 故障关闭行为
|
|
69
|
+
|
|
70
|
+
没有后端能强制执行所请求的模式时,调用以 `SANDBOX_UNAVAILABLE` 失败,而不是不受限制地运行;错误文本会指明缺失的平台 runner。启动后失败的后端还会报告结构化的 runner 失败签名,因此损坏的沙箱可以与命令失败区分开。
|
|
71
|
+
|
|
72
|
+
-----
|
|
73
|
+
|
|
74
|
+
<a id="understand-the-implementation"></a>
|
|
75
|
+
## 理解实现
|
|
76
|
+
|
|
77
|
+
<details>
|
|
78
|
+
<summary>实现细节——点击展开</summary>
|
|
79
|
+
|
|
80
|
+
本节解释约定背后的设计决策,并指出实现它们的代码位置;可观察行为已在[使用本包](#use-this-package)中完整说明。
|
|
81
|
+
|
|
82
|
+
### 设计理念
|
|
83
|
+
|
|
84
|
+
- **按约定限同世界。** `ctx.sandbox` 在宿主路径文件策略下包装 argv;容器、microVM 与远程执行会替换周边能力 seam。
|
|
85
|
+
- **策略随调用传递。** `SandboxPolicy` 逐调用携带,绝不在提供方上固定:两个消费方可以同时按不同策略隔离,获批的升权重试只是用更宽策略发起的新调用。默认与解析是消费方显式步骤。
|
|
86
|
+
- **故障关闭。** `confine()` 返回受强制的 argv,或抛出 `SandboxUnavailableError`;绝不允许静默无限制放行,功能探测用于仲裁多 runner 链。
|
|
87
|
+
- **统一的拒绝与升权词汇。** 标记与提示文本以及严格更宽阶梯都放在这里,使 bash 与 fs 家族不会漂移。
|
|
88
|
+
|
|
89
|
+
### 源码地图
|
|
90
|
+
|
|
91
|
+
| 文件 | 职责 |
|
|
92
|
+
|---|---|
|
|
93
|
+
| [`src/index.ts`](src/index.ts) | 插件入口:`SandboxProvider` 服务、模式/强制执行/策略类型、故障关闭错误 |
|
|
94
|
+
| [`src/escalation.ts`](src/escalation.ts) | 升权词汇:更宽模式阶梯、参数校验、拒绝与提示标记、审批编排 |
|
|
95
|
+
| [`src/roots.ts`](src/roots.ts) | 可写根目录推导,Seatbelt profile 与进程内 fs 栅栏共享 |
|
|
96
|
+
| [`src/invariant.ts`](src/invariant.ts) | 不变式伴生插件(无运行时不变式;抽象 seam 不注册事件或数据关系) |
|
|
97
|
+
|
|
98
|
+
### 升权编排
|
|
99
|
+
|
|
100
|
+
阶梯是封闭表——`read-only` 可升权到 `workspace-write` 或 `danger-full-access`,`workspace-write` 只能升权到 `danger-full-access`——在执行时检查,绝不写入工具 schema,schema 的枚举保持封闭的目标词汇。[`approveEscalation`](src/escalation.ts) 校验 `sandbox_permissions`/`justification` 配对、不提示人类就拒绝非加宽请求,并在任何执行前把每个审批结果映射到各自的错误。
|
|
16
101
|
|
|
17
|
-
|
|
102
|
+
### 可写根目录
|
|
103
|
+
|
|
104
|
+
`workspace-write` 意味着「工作区根目录加宿主临时区域」:`writableRoots` 以规范化方式推导该白名单,解析符号链接并去重,使 Seatbelt profile 与进程内 fs 栅栏授予完全相同的根目录。
|
|
105
|
+
|
|
106
|
+
</details>
|
|
107
|
+
|
|
108
|
+
-----
|
|
109
|
+
|
|
110
|
+
<a id="further-exploration"></a>
|
|
111
|
+
## 进一步探索
|
|
112
|
+
|
|
113
|
+
先从子系统参考文档了解穷尽式约定,再看实现它的后端、消费方与策略来源。
|
|
114
|
+
|
|
115
|
+
- [进程沙箱子系统](../../../docs/subsystems/sandbox.zh.md)——完整词汇、逐调用策略与分类方言。
|
|
116
|
+
- [子进程沙箱决策](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md)——能力边界、升权设计与延期阶段。
|
|
117
|
+
- [本地沙箱后端](../sandbox-local/README.zh.md)——`ctx.sandbox` 背后的各平台 runner。
|
|
118
|
+
- [Bash 沙箱执行器](../../shell/bash-sandbox/README.zh.md)——受限的 bash 消费方。
|
|
119
|
+
- [沙箱策略包](../sandbox-policy/README.zh.md)——逐调用模式与工作区根目录的来源。
|
|
120
|
+
|
|
121
|
+
-----
|
|
122
|
+
|
|
123
|
+
<a id="model-experience"></a>
|
|
124
|
+
## 模型体验
|
|
18
125
|
|
|
19
126
|
### 间接的限制错误
|
|
20
127
|
|
|
21
|
-
####
|
|
128
|
+
#### 模型看到什么
|
|
22
129
|
|
|
23
|
-
通过 [`dsh-bash-sandbox`](../../shell/bash-sandbox/README.zh.md) 和 [`dsh-tool-bash`](../../shell/tool-bash/README.zh.md)
|
|
130
|
+
通过 [`dsh-bash-sandbox`](../../shell/bash-sandbox/README.zh.md) 和 [`dsh-tool-bash`](../../shell/tool-bash/README.zh.md),请求的受限模式没有可用后端时会产生错误码 `SANDBOX_UNAVAILABLE` 及下方精确错误;执行期 runner 失败会追加 ` Runner failure: <detail>`。
|
|
24
131
|
|
|
25
132
|
##### 精确错误
|
|
26
133
|
|
|
@@ -36,10 +143,43 @@ sandbox mode "<mode>" is requested but no sandbox backend is usable on this host
|
|
|
36
143
|
|
|
37
144
|
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。
|
|
38
145
|
|
|
39
|
-
|
|
146
|
+
### 升权请求与结果
|
|
147
|
+
|
|
148
|
+
#### 模型看到什么
|
|
149
|
+
|
|
150
|
+
被拒绝的调用会呈现标记 `[sandbox: file access denied under <mode> mode]`,组合声明升权能力时还会呈现提示 `[sandbox: escalation available — retry this exact <subject> once with sandbox_permissions (the narrowest wider mode that suffices) + justification; the approval prompt asks the user]`。重试携带 `sandbox_permissions` 与 `justification`;用户的 `allowed-once`/`rejected`/`cancelled` 决定成为该调用的结果文本。
|
|
151
|
+
|
|
152
|
+
#### Token 影响
|
|
153
|
+
|
|
154
|
+
只有被拒绝调用的错误与任何升权结果文本可见;两者都会保留在历史中直到压缩。
|
|
155
|
+
|
|
156
|
+
#### KV Cache 影响
|
|
157
|
+
|
|
158
|
+
仅追加;升权文本位于保留前缀之后,不会使已缓存条目失效。
|
|
159
|
+
|
|
160
|
+
## 已知限制与延期工作
|
|
161
|
+
|
|
162
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
这些限制说明该 seam 何时不合适,或何时需要特别运维。它们是当前包约束,不是通用沙箱对比或任务积压。
|
|
166
|
+
|
|
167
|
+
- **文件操作是完整的策略词汇**——该 seam 不表达网络、进程、系统调用、设备或凭据限制。
|
|
168
|
+
- **仅限同世界隔离**——容器、microVM 与远程执行需要替换能力实现,而不是在此添加提供方。
|
|
169
|
+
- **拒绝报告是一种 stderr 方言**——该 seam 返回后端签名,而非类型化运行时拒绝通道,需要分类的消费方必须从子进程输出推断。
|
|
170
|
+
- **Runner 诊断使用带内通道**——退出状态与 stderr 证据无法证明匹配行由哪个进程写入,因此故意模仿 runner 的受限子进程可能造成错误的可用性或诊断归因;这无法绕过隔离,带外 runner 状态通道暂缓实现。
|
|
171
|
+
- **每个上下文只有一个提供方**——同时组合不同沙箱机制需要提供方级阶梯或独立 Cordis 上下文;调用方逐调用选择策略,而非后端标识。
|
|
172
|
+
|
|
173
|
+
<a id="dev-note"></a>
|
|
174
|
+
### 开发备注
|
|
175
|
+
|
|
176
|
+
<details>
|
|
177
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
178
|
+
|
|
179
|
+
本开发备注是维护者的工作上下文:未决方向与开放问题。它明确不具权威性——已交付的行为、限制与既定理由以上文、包代码和相关 Agent Note 为准。
|
|
180
|
+
|
|
181
|
+
#### 未来:消费方与环境
|
|
182
|
+
|
|
183
|
+
[沙箱决策](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md)列出延期阶段——可选的 `subagent-acp` 消费方(隔离子 agent(智能体),默认不隔离)与环境一致的能力组示例。两者均未决定;该笔记列为延期的 Windows 链已通过 `sandbox-local` 的 ACL 受限令牌档交付。
|
|
40
184
|
|
|
41
|
-
|
|
42
|
-
- **只支持与宿主共享文件系统和内核的限制**:容器、microVM 与远程执行需要替换能力实现,而不是在此处增加提供方。
|
|
43
|
-
- **拒绝报告是一种 stderr 方言**:该 seam 返回后端签名,而非类型化运行时拒绝通道,因此需要分类的消费方必须从子进程输出推断。
|
|
44
|
-
- **Runner 诊断使用带内通道**:退出状态与 stderr 证据无法证明匹配行由哪个进程写入,因此受限子进程若故意模仿 runner,就可能造成可用性或诊断误归因。这无法绕过约束;带外 runner 状态通道暂缓实现。
|
|
45
|
-
- **每个上下文只有一个提供方**:同时组合不同沙箱机制需要提供方级阶梯或独立 Cordis 上下文;调用方逐调用选择策略,而非后端标识。
|
|
185
|
+
</details>
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Service } from "@deepseek-ai/cordis";
|
|
2
|
-
import { HarnessError
|
|
2
|
+
import { HarnessError } from "@deepseek-ai/dsh-llm";
|
|
3
|
+
import { assertNever } from "@deepseek-ai/dsh-util-values";
|
|
3
4
|
import { realpathSync } from "node:fs";
|
|
4
5
|
import { tmpdir } from "node:os";
|
|
5
6
|
//#region lib/types/escalation.js
|
|
@@ -71,7 +71,7 @@ export type EscalationOutcome = 'allowed-once' | 'rejected' | 'cancelled' | 'una
|
|
|
71
71
|
* structurally the approval seam's `ApprovalService`, generic over the agent
|
|
72
72
|
* type `A` and call-id type `C` so this package resolves escalations through
|
|
73
73
|
* `ctx.approval` without importing the approval or agent packages (the tool
|
|
74
|
-
* layer infers `A`/`C` as its own `Agent`/`
|
|
74
|
+
* layer infers `A`/`C` as its own `Agent`/`ToolCallId`).
|
|
75
75
|
*/
|
|
76
76
|
export interface EscalationApprover<A = object, C = string> {
|
|
77
77
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-sandbox",
|
|
3
3
|
"description": "Abstract process-sandbox seam (ctx.sandbox) for the DeepSeek Harness: same-world confinement vocabulary and the SandboxProvider contract",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -32,15 +32,18 @@
|
|
|
32
32
|
],
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@deepseek-ai/
|
|
36
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
37
|
-
"@deepseek-ai/
|
|
38
|
-
"@deepseek-ai/dsh-llm": "^0.1.
|
|
35
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
36
|
+
"@deepseek-ai/dsh-session": "^0.1.2-alpha.2",
|
|
37
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
38
|
+
"@deepseek-ai/dsh-llm": "^0.1.2-alpha.2"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@deepseek-ai/
|
|
42
|
-
"@deepseek-ai/dsh-
|
|
43
|
-
"@deepseek-ai/dsh-
|
|
44
|
-
"@deepseek-ai/
|
|
41
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
42
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
43
|
+
"@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
|
|
44
|
+
"@deepseek-ai/dsh-session": "^0.1.2-alpha.2"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@deepseek-ai/dsh-util-values": "^0.1.2-alpha.2"
|
|
45
48
|
}
|
|
46
49
|
}
|