@deepseek-ai/dsh-tool-bash-persistent 0.1.0-rc.3 → 0.1.0-rc.7
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 +2 -1
- package/README.zh.md +2 -1
- package/lib/index.js +7 -13
- package/package.json +19 -19
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/shell/tool-bash-persistent/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 606920d087b42344f34b70103e167b0046d3cfd5
|
|
6
|
+
README.zh.md: dd88db87cb617fb2f4d35ada9550d0142e32e979
|
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ Prefix-stable while the configured description and schema remain unchanged.
|
|
|
33
33
|
|
|
34
34
|
#### What the model sees
|
|
35
35
|
|
|
36
|
-
Commands share one shell per Agent, so cwd, exported variables, activated environments, functions, and background jobs persist across calls. Results exclude private completion markers
|
|
36
|
+
Commands share one shell per Agent, so cwd, exported variables, activated environments, functions, and background jobs persist across calls. Results exclude private completion markers. When the shell reads stdin again without having printed the completion marker — after `exec`, an interrupt, or an interactive foreground child whose stdin wait the provider proves — the call returns the captured partial output, which can end with the backend's own prompt text. A nonzero wrapped command appends `[exit code: N]`; a shell that exits before reporting that status instead appends `[shell exited: code N]`, `[shell killed by signal: SIG]`, or `[shell exited]` when the backend supplies neither, then resets and tells the model that the next call starts fresh. Long output keeps the earliest retained prefix plus a clipping notice. If the PTY has already dropped that prefix, the result says so explicitly instead of presenting a tail as complete output. Timeout returns bounded partial output, closes the uncertain shell, and reports the reset.
|
|
37
37
|
|
|
38
38
|
#### Token effect
|
|
39
39
|
|
|
@@ -46,5 +46,6 @@ Append-only tool results follow the reusable request prefix.
|
|
|
46
46
|
## Known Limitations and Deferred Work
|
|
47
47
|
|
|
48
48
|
- The tool requires an owning Agent and a real PTY backend.
|
|
49
|
+
- An interactive foreground child (for example a REPL) returns early with partial output only where the subprocess provider proves its stdin wait; elsewhere the call runs to `timeoutMs`.
|
|
49
50
|
- Explicit `exit` and timeout discard shell state. Cancellation also resets and discards the result, even when a complete status marker is already observable; the next call starts a fresh shell.
|
|
50
51
|
- Environment facts such as network access and package mirrors belong in the configured `description`, not this package's default.
|
package/README.zh.md
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
#### 模型所见
|
|
35
35
|
|
|
36
|
-
每个 Agent 的命令共享一个 shell,因此 cwd
|
|
36
|
+
每个 Agent 的命令共享一个 shell,因此 cwd、导出的环境变量、已激活环境、函数和后台任务会跨调用保留。结果不包含私有完成标记。当 shell 在未打印完成标记的情况下再次读取 stdin 时——例如 `exec`、中断,或提供方能证明其 stdin 等待的交互式前台子进程——调用返回已捕获的部分输出,其末尾可能带有后端自己的提示符文本。经封装的命令以非零状态结束时,结果会追加 `[exit code: N]`;若 shell 在报告该状态前退出,则改为追加 `[shell exited: code N]`、`[shell killed by signal: SIG]`,或在后端既未提供退出码也未提供信号时追加 `[shell exited]`;随后重置 shell,并告知模型下次调用从新 shell 开始。长输出保留仍可读取的最早前缀并追加截断提示;若 PTY 已丢弃真正的开头,结果会明确说明,而不是把尾部伪装成完整输出。超时返回有界的部分输出、关闭状态不确定的 shell,并报告该重置。
|
|
37
37
|
|
|
38
38
|
#### Token 影响
|
|
39
39
|
|
|
@@ -46,5 +46,6 @@
|
|
|
46
46
|
## 已知限制与延后工作
|
|
47
47
|
|
|
48
48
|
- 工具需要拥有它的 Agent 和真实 PTY 后端。
|
|
49
|
+
- 交互式前台子进程(例如 REPL)只有在进程管理提供方能证明其 stdin 等待时才会提前返回部分输出;否则调用会一直运行到 `timeoutMs`。
|
|
49
50
|
- 显式 `exit` 与超时会丢弃 shell 状态。取消同样会重置 shell 并丢弃结果,即使已经能观察到完整状态标记也是如此;下次调用创建新 shell。
|
|
50
51
|
- 网络访问、软件包镜像等环境事实应写入配置的 `description`,而非包默认描述。
|
package/lib/index.js
CHANGED
|
@@ -68,7 +68,6 @@ var __disposeResources = (function(SuppressedError) {
|
|
|
68
68
|
const TRUNCATED_MESSAGE = "<response clipped><NOTE>To save on context only part of this file has been shown to you. You should retry this tool after you have searched inside the file with `grep -n` in order to find the line numbers of what you are looking for.</NOTE>";
|
|
69
69
|
const LOST_PREFIX_MESSAGE = "<response clipped><NOTE>The beginning of this command output was dropped by the terminal scrollback limit. The following text is the earliest retained output.</NOTE>\n";
|
|
70
70
|
const SHELL_RESET_MESSAGE = "The persistent bash shell was reset; the next bash call starts from the workspace with a fresh current directory and environment.";
|
|
71
|
-
const SHELL_PROMPT = "__DSH_PERSISTENT_BASH_PROMPT__ ";
|
|
72
71
|
const TIMEOUT_CODE = "PERSISTENT_BASH_TIMEOUT";
|
|
73
72
|
const SCROLLBACK_PAGE_LINES = 1e3;
|
|
74
73
|
const POLL_INTERVAL_MS = 25;
|
|
@@ -90,10 +89,8 @@ function quoteForBash(value) {
|
|
|
90
89
|
function wrapCommand(command, marker) {
|
|
91
90
|
return `printf '%s\\n' ${quoteForBash(marker.start)}; eval -- ${quoteForBash(command)}; __dsh_persistent_bash_status=$?; printf '%s%s\\n' ${quoteForBash(marker.end)} "$__dsh_persistent_bash_status"`;
|
|
92
91
|
}
|
|
93
|
-
function
|
|
94
|
-
|
|
95
|
-
while (result.endsWith(SHELL_PROMPT)) result = result.slice(0, -31);
|
|
96
|
-
return result.endsWith("\n") ? result.slice(0, -1) : result;
|
|
92
|
+
function trimTrailingNewline(text) {
|
|
93
|
+
return text.replace(/\r?\n$/, "");
|
|
97
94
|
}
|
|
98
95
|
function commandOutput(snapshot, marker) {
|
|
99
96
|
const text = snapshot.text;
|
|
@@ -103,25 +100,22 @@ function commandOutput(snapshot, marker) {
|
|
|
103
100
|
const startMarker = text.lastIndexOf(marker.start, end);
|
|
104
101
|
const start = startMarker < 0 ? 0 : startMarker + marker.start.length;
|
|
105
102
|
return {
|
|
106
|
-
text:
|
|
103
|
+
text: trimTrailingNewline(text.slice(start, end).replace(/^\r?\n/, "")),
|
|
107
104
|
incomplete: startMarker < 0,
|
|
108
105
|
exitCode: Number(status)
|
|
109
106
|
};
|
|
110
107
|
}
|
|
111
|
-
function promptCompleted(result) {
|
|
112
|
-
return result.viewport.endsWith(SHELL_PROMPT) || result.viewport.endsWith(`${SHELL_PROMPT}\r\n`) || result.viewport.endsWith(`${SHELL_PROMPT}\n`);
|
|
113
|
-
}
|
|
114
108
|
function partialOutput(snapshot, marker, fallback, fallbackTruncated = false) {
|
|
115
109
|
const startMarker = snapshot.text.lastIndexOf(marker.start);
|
|
116
110
|
if (startMarker >= 0) return {
|
|
117
|
-
text:
|
|
111
|
+
text: trimTrailingNewline(snapshot.text.slice(startMarker + marker.start.length).replace(/^\r?\n/, "")),
|
|
118
112
|
incomplete: false
|
|
119
113
|
};
|
|
120
114
|
const fallbackStart = fallback.lastIndexOf(marker.start);
|
|
121
115
|
const afterStart = fallbackStart < 0 ? fallback : fallback.slice(fallbackStart + marker.start.length).replace(/^\r?\n/, "");
|
|
122
116
|
const fallbackEnd = afterStart.lastIndexOf(marker.end);
|
|
123
117
|
return {
|
|
124
|
-
text:
|
|
118
|
+
text: trimTrailingNewline(fallbackEnd < 0 ? afterStart : afterStart.slice(0, fallbackEnd)),
|
|
125
119
|
incomplete: fallbackTruncated || fallbackStart < 0
|
|
126
120
|
};
|
|
127
121
|
}
|
|
@@ -212,7 +206,7 @@ function persistentShells(ctx, config) {
|
|
|
212
206
|
}, "tool-bash-persistent owner cache cleanup");
|
|
213
207
|
}
|
|
214
208
|
const result = await ctx.terminals.startSend(owner, spawned.sessionId, {
|
|
215
|
-
text:
|
|
209
|
+
text: "stty -echo",
|
|
216
210
|
submit: true,
|
|
217
211
|
signal: combinedSignal
|
|
218
212
|
}).done;
|
|
@@ -293,7 +287,7 @@ async function executeCommand(ctx, shells, owner, command, config, upstream) {
|
|
|
293
287
|
await shells.reset(owner, "persistent bash shell exited");
|
|
294
288
|
return [renderShellExitStatus(renderCaptured(partialOutput(snapshot, marker, fallback, fallbackTruncated), config.maxOutputChars), result.sessionStatus.exitCode, result.sessionStatus.signal), SHELL_RESET_MESSAGE].filter((part) => part.length > 0).join("\n");
|
|
295
289
|
}
|
|
296
|
-
if (
|
|
290
|
+
if (result.waitReason === "stdin_read") return renderCaptured(partialOutput(retainedScrollback(ctx, owner, id, latest), marker, fallback, fallbackTruncated), config.maxOutputChars);
|
|
297
291
|
await pause();
|
|
298
292
|
}
|
|
299
293
|
} catch (e_1) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-tool-bash-persistent",
|
|
3
3
|
"description": "Model-facing owner-scoped persistent Bash tool backed by the Harness PTY service",
|
|
4
|
-
"version": "0.1.0-rc.
|
|
4
|
+
"version": "0.1.0-rc.7",
|
|
5
5
|
"publishConfig": {
|
|
6
|
-
"access": "
|
|
6
|
+
"access": "public"
|
|
7
7
|
},
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
],
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@deepseek-ai/dsh-agent": "^0.1.0-rc.
|
|
35
|
-
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.
|
|
36
|
-
"@deepseek-ai/dsh-terminal": "^0.1.0-rc.
|
|
37
|
-
"@deepseek-ai/dsh-timeout": "^0.1.0-rc.
|
|
38
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.
|
|
34
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.7",
|
|
35
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.7",
|
|
36
|
+
"@deepseek-ai/dsh-terminal": "^0.1.0-rc.7",
|
|
37
|
+
"@deepseek-ai/dsh-timeout": "^0.1.0-rc.7",
|
|
38
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.7",
|
|
39
39
|
"@deepseek-ai/cordis": "^4.0.1"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
@@ -44,18 +44,18 @@
|
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@deepseek-ai/cordis-plugin-include": "^1.0.6",
|
|
46
46
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.2",
|
|
47
|
-
"@deepseek-ai/dsh-agent": "^0.1.0-rc.
|
|
48
|
-
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.
|
|
49
|
-
"@deepseek-ai/dsh-llm": "^0.1.0-rc.
|
|
50
|
-
"@deepseek-ai/dsh-terminal": "^0.1.0-rc.
|
|
51
|
-
"@deepseek-ai/dsh-terminal-bash": "^0.1.0-rc.
|
|
52
|
-
"@deepseek-ai/dsh-sandbox": "^0.1.0-rc.
|
|
53
|
-
"@deepseek-ai/dsh-session": "^0.1.0-rc.
|
|
54
|
-
"@deepseek-ai/dsh-subprocess-local": "^0.1.0-rc.
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
47
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.7",
|
|
48
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.7",
|
|
49
|
+
"@deepseek-ai/dsh-llm": "^0.1.0-rc.7",
|
|
50
|
+
"@deepseek-ai/dsh-terminal": "^0.1.0-rc.7",
|
|
51
|
+
"@deepseek-ai/dsh-terminal-bash": "^0.1.0-rc.7",
|
|
52
|
+
"@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7",
|
|
53
|
+
"@deepseek-ai/dsh-session": "^0.1.0-rc.7",
|
|
54
|
+
"@deepseek-ai/dsh-subprocess-local": "^0.1.0-rc.7",
|
|
55
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7",
|
|
56
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.7",
|
|
57
|
+
"@deepseek-ai/dsh-timeout": "^0.1.0-rc.7",
|
|
58
58
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
59
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7"
|
|
60
60
|
}
|
|
61
61
|
}
|