@yiln-dsh/dsh-plugin-sandbox-guidance 0.1.0
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.md +48 -0
- package/cordis.patch.yml +11 -0
- package/index.js +60 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# @yiln-dsh/dsh-plugin-sandbox-guidance
|
|
2
|
+
|
|
3
|
+
A Host-only DSH plugin that explains one confusing sandbox failure to the model:
|
|
4
|
+
when a bash call asks for a mode that is not strictly wider than the current
|
|
5
|
+
sandbox mode.
|
|
6
|
+
|
|
7
|
+
It does not change sandbox policy, bypass approval, rewrite tool arguments, or
|
|
8
|
+
replace the built-in bash executor. The native failure remains an error and the
|
|
9
|
+
command remains unexecuted.
|
|
10
|
+
|
|
11
|
+
## Behavior
|
|
12
|
+
|
|
13
|
+
The plugin adds a `systemPrompt` section that tells the model to omit
|
|
14
|
+
`sandbox_permissions` during ordinary calls and to explain this failure instead
|
|
15
|
+
of repeating it blindly. It also listens to `tools/post-execute` and replaces
|
|
16
|
+
only the matching bash failure text with a diagnostic containing:
|
|
17
|
+
|
|
18
|
+
- the fact that bash did not run;
|
|
19
|
+
- the requested sandbox mode;
|
|
20
|
+
- the current effective mode;
|
|
21
|
+
- whether the retry should omit `sandbox_permissions` or request a genuinely wider mode.
|
|
22
|
+
|
|
23
|
+
Other bash failures pass through unchanged.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
The published package is `@yiln-dsh/dsh-plugin-sandbox-guidance@0.1.0`.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
dsh plugin --profile web add @yiln-dsh/dsh-plugin-sandbox-guidance@latest
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Restart `dsh web` after installing the package so the Host composition loads the
|
|
34
|
+
new row.
|
|
35
|
+
|
|
36
|
+
## Limitations
|
|
37
|
+
|
|
38
|
+
`tools/pre-execute` and `tools/post-execute` receive immutable tool arguments.
|
|
39
|
+
This plugin can explain a failure and guide the next model step, but it cannot
|
|
40
|
+
silently convert an invalid escalation into a valid one. Removing the strict
|
|
41
|
+
sandbox check still requires a DSH core patch or fork.
|
|
42
|
+
|
|
43
|
+
## Layout
|
|
44
|
+
|
|
45
|
+
| File | Content |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `index.js` | Host system prompt section and bash failure diagnostic. |
|
|
48
|
+
| `cordis.patch.yml` | Composition patch that mounts the Host row. |
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# dsh-plugin-sandbox-guidance bundle patch.
|
|
2
|
+
#
|
|
3
|
+
# Adds a Host-only prompt/result diagnostic; it never changes sandbox policy or
|
|
4
|
+
# replaces the native bash executor.
|
|
5
|
+
|
|
6
|
+
- insert:
|
|
7
|
+
- id: sandbox-guidance
|
|
8
|
+
name: '@yiln-dsh/dsh-plugin-sandbox-guidance'
|
|
9
|
+
inject:
|
|
10
|
+
- tools
|
|
11
|
+
- systemPrompt
|
package/index.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explains non-widening sandbox errors to the model without changing execution.
|
|
3
|
+
* The native bash tool remains fail-closed; this package only improves recovery
|
|
4
|
+
* guidance when a caller repeats the current sandbox mode.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const name = "sandbox-guidance";
|
|
8
|
+
export const inject = ["tools", "systemPrompt"];
|
|
9
|
+
|
|
10
|
+
const NON_WIDENING_ERROR = /^sandbox escalation to "([^"]+)" is not strictly wider than this call's current "([^"]+)" mode$/u;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Turn the native sandbox error into a model-facing diagnostic that says what
|
|
14
|
+
* ran, what did not run, and which retry shape is valid.
|
|
15
|
+
*/
|
|
16
|
+
export function explainSandboxFailure(message) {
|
|
17
|
+
if (typeof message !== "string") return undefined;
|
|
18
|
+
const match = NON_WIDENING_ERROR.exec(message);
|
|
19
|
+
if (match === null) return undefined;
|
|
20
|
+
const requested = match[1];
|
|
21
|
+
const effective = match[2];
|
|
22
|
+
const sameMode = requested === effective;
|
|
23
|
+
return [
|
|
24
|
+
"Bash was not executed; this failure happened before the command ran.",
|
|
25
|
+
`Cause: sandbox_permissions requested \"${requested}\", but the current effective sandbox mode is \"${effective}\".`,
|
|
26
|
+
sameMode
|
|
27
|
+
? "The requested mode is already active, so sandbox_permissions must be omitted for the retry."
|
|
28
|
+
: "sandbox_permissions is only valid for a retry that requests a strictly wider mode; do not retry with this mode.",
|
|
29
|
+
"Explain this cause to the user instead of silently repeating the same bash call.",
|
|
30
|
+
].join(" ");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const SYSTEM_PROMPT = [
|
|
34
|
+
"Sandbox escalation recovery:",
|
|
35
|
+
"- Do not include sandbox_permissions in an ordinary bash call.",
|
|
36
|
+
"- Only include it when retrying a call that was actually denied by the sandbox and the requested mode is strictly wider than the effective mode.",
|
|
37
|
+
"- If a bash result says the requested mode is not strictly wider than the current mode, state that the command did not run, explain the requested and effective modes, and retry without sandbox_permissions when the current mode is sufficient.",
|
|
38
|
+
"- If a wider mode is genuinely required, explain why to the user and request approval rather than repeating the failed call.",
|
|
39
|
+
].join("\n");
|
|
40
|
+
|
|
41
|
+
export function apply(ctx) {
|
|
42
|
+
const order = typeof ctx.systemPrompt.getSectionOrder === "function"
|
|
43
|
+
? ctx.systemPrompt.getSectionOrder("TOOL_BASH") + 1
|
|
44
|
+
: 105;
|
|
45
|
+
ctx.systemPrompt.section({
|
|
46
|
+
name: "tool:sandbox-guidance",
|
|
47
|
+
order,
|
|
48
|
+
text: SYSTEM_PROMPT,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
ctx.on("tools/post-execute", (exec, result, next) => {
|
|
52
|
+
if (exec.name !== "bash" || result.isError !== true) return next();
|
|
53
|
+
const explained = explainSandboxFailure(result.error?.message);
|
|
54
|
+
if (explained === undefined) return next();
|
|
55
|
+
return {
|
|
56
|
+
kind: "accept",
|
|
57
|
+
content: [{ type: "text", text: explained }],
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yiln-dsh/dsh-plugin-sandbox-guidance",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "DSH Host plugin that explains non-widening sandbox failures to the model and user without changing execution policy.",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node --test test/*.test.js"
|
|
11
|
+
},
|
|
12
|
+
"main": "index.js",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./index.js",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"dsh": {
|
|
18
|
+
"bundle": {
|
|
19
|
+
"patch": "./cordis.patch.yml"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"index.js",
|
|
24
|
+
"cordis.patch.yml",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@deepseek-ai/cordis": ">=4.0.2",
|
|
29
|
+
"@deepseek-ai/dsh-system-prompt": ">=0.1.2-rc.1",
|
|
30
|
+
"@deepseek-ai/dsh-tools": ">=0.1.2-rc.1"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=22"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT"
|
|
36
|
+
}
|