dsh-crate-web 0.1.2-preview.3 → 0.1.2-preview.6
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 +14 -3
- package/core/dsh_pack/_version.py +1 -1
- package/core/dsh_pack/cli.py +2 -2
- package/core/dsh_pack/desktop_verify.py +6 -0
- package/core/dsh_pack/errors.py +14 -0
- package/core/dsh_pack/export.py +58 -15
- package/lib/index.js +6 -29
- package/package.json +7 -2
- package/packaging/windows-terminal/README.md +43 -0
- package/packaging/windows-terminal/build.py +258 -0
- package/packaging/windows-terminal/dsh__node_modules__@deepseek-ai__dsh-sandbox-local__lib__index.js.patch +21 -0
- package/packaging/windows-terminal/dsh__node_modules__@deepseek-ai__dsh-subprocess-local__lib__index.js.patch +51 -0
- package/packaging/windows-terminal/dsh__node_modules__@deepseek-ai__dsh-terminal-bash__lib__index.js.patch +38 -0
- package/packaging/windows-terminal/dsh__node_modules__node-pty__lib__windowsPtyAgent.js.patch +31 -0
- package/packaging/windows-terminal/dsh__node_modules__node-pty__lib__windowsTerminal.js.patch +107 -0
- package/packaging/windows-terminal/manifest.json +577 -0
- package/runtime-inventory.mjs +31 -0
- package/skills/dsh-crate-troubleshooting/compatibility.json +1 -1
- package/skills/dsh-crate-troubleshooting/reference/diagnostics.generated.md +1 -1
- package/verify-desktop.mjs +6 -2
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
--- a/dsh/node_modules/@deepseek-ai/dsh-subprocess-local/lib/index.js
|
|
2
|
+
+++ b/dsh/node_modules/@deepseek-ai/dsh-subprocess-local/lib/index.js
|
|
3
|
+
@@ -1226,6 +1226,8 @@
|
|
4
|
+
survivors = await this.stopDescendants();
|
|
5
|
+
if (survivors.length > 0) throw new Error(`terminal cleanup failed; surviving pids: ${survivors.map((member) => member.pid).join(", ")}`);
|
|
6
|
+
this.settleExitIfGone();
|
|
7
|
+
+ // shell及后代都已退出后释放 Windows PTY 传输端点。
|
|
8
|
+
+ if (this.platform === "win32") this.terminal.kill();
|
|
9
|
+
this.dataDisposable.dispose();
|
|
10
|
+
this.exitDisposable.dispose();
|
|
11
|
+
}
|
|
12
|
+
@@ -1643,6 +1645,7 @@
|
|
13
|
+
const linuxScope = containmentMode === "linux-scope" ? this.linuxScopeDecision : void 0;
|
|
14
|
+
let scope;
|
|
15
|
+
let terminal;
|
|
16
|
+
+ let cancelConnectingTerminal;
|
|
17
|
+
try {
|
|
18
|
+
scope = linuxScope === void 0 ? void 0 : prepareLinuxTerminalScope(launch, {
|
|
19
|
+
...activity?.env ?? env,
|
|
20
|
+
@@ -1654,10 +1657,31 @@
|
|
21
|
+
options.env = scope.env;
|
|
22
|
+
}
|
|
23
|
+
terminal = requireNodePty().spawn(scope?.command ?? file, scope?.args ?? [...launch.argv.slice(1)], options);
|
|
24
|
+
+ if (platform === "win32") {
|
|
25
|
+
+ if (terminal.processReady === void 0) throw new Error("subprocess-local: Windows PTY process readiness contract is missing");
|
|
26
|
+
+ if (spec.signal !== void 0) {
|
|
27
|
+
+ cancelConnectingTerminal = () => {
|
|
28
|
+
+ // 取消事件回调不抛出到 Host;kill 缓存失败,随后 catch 会保留清理错误。
|
|
29
|
+
+ try { terminal.kill(); } catch (_) { /* 由连接错误收尾路径读取并报告 */ }
|
|
30
|
+
+ };
|
|
31
|
+
+ spec.signal.addEventListener("abort", cancelConnectingTerminal, { once: true });
|
|
32
|
+
+ if (spec.signal.aborted) cancelConnectingTerminal();
|
|
33
|
+
+ }
|
|
34
|
+
+ await terminal.processReady;
|
|
35
|
+
+ spec.signal?.throwIfAborted();
|
|
36
|
+
+ if (!Number.isSafeInteger(terminal.pid) || terminal.pid <= 0) throw new Error("subprocess-local: Windows PTY returned an invalid child pid");
|
|
37
|
+
+ }
|
|
38
|
+
} catch (error) {
|
|
39
|
+
+ let cleanupError;
|
|
40
|
+
+ if (platform === "win32" && terminal !== void 0) {
|
|
41
|
+
+ try { terminal.kill(); } catch (failure) { cleanupError = failure; }
|
|
42
|
+
+ }
|
|
43
|
+
scope?.cleanup();
|
|
44
|
+
activity?.dispose();
|
|
45
|
+
+ if (cleanupError !== void 0) throw new AggregateError([error, cleanupError], "PTY connection and cleanup both failed");
|
|
46
|
+
throw error;
|
|
47
|
+
+ } finally {
|
|
48
|
+
+ if (cancelConnectingTerminal !== void 0) spec.signal?.removeEventListener("abort", cancelConnectingTerminal);
|
|
49
|
+
}
|
|
50
|
+
let handle;
|
|
51
|
+
const directSettlement = Promise.withResolvers();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
--- a/dsh/node_modules/@deepseek-ai/dsh-terminal-bash/lib/index.js
|
|
2
|
+
+++ b/dsh/node_modules/@deepseek-ai/dsh-terminal-bash/lib/index.js
|
|
3
|
+
@@ -498,7 +498,7 @@
|
|
4
|
+
submit: false,
|
|
5
|
+
...signal !== void 0 ? { signal } : {}
|
|
6
|
+
}).done;
|
|
7
|
+
- if (result.waitReason === "session_exit") throw new Error("PTY shell exited during startup");
|
|
8
|
+
+ if (result.waitReason === "session_exit") throw startupExitError(result);
|
|
9
|
+
if (result.waitReason === "timeout") throw new Error("PTY shell did not reach readiness before startup timeout");
|
|
10
|
+
this.motd = result.viewport;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
@@ -971,6 +971,17 @@
|
|
13
|
+
mode: policy.mode
|
|
14
|
+
}, signal)).argv;
|
|
15
|
+
}
|
|
16
|
+
+/** 保留实际退出结果和已收集的启动输出;不将缺失退出码伪装为0。 */
|
|
17
|
+
+function startupExitError(result) {
|
|
18
|
+
+ const status = result.sessionStatus;
|
|
19
|
+
+ const exitCode = status.kind === "exited" && typeof status.exitCode === "number" ? status.exitCode : null;
|
|
20
|
+
+ const signal = status.kind === "exited" ? status.signal ?? null : null;
|
|
21
|
+
+ const output = result.viewport;
|
|
22
|
+
+ const truncated = result.truncated === true;
|
|
23
|
+
+ const error = new Error(`PTY shell exited during startup (exitCode=${exitCode ?? "unknown"}, signal=${signal ?? "none"})${output.length ? `\n${output}` : ""}${truncated ? "\n[startup output reached the configured capture limit]" : ""}`);
|
|
24
|
+
+ Object.assign(error, { exitCode, signal, startupOutput: output, startupOutputTruncated: truncated });
|
|
25
|
+
+ return error;
|
|
26
|
+
+}
|
|
27
|
+
async function startupSession(session, dialect, timeoutMs, signal) {
|
|
28
|
+
let startupOperation;
|
|
29
|
+
const start = async () => {
|
|
30
|
+
@@ -987,7 +998,7 @@
|
|
31
|
+
...signal !== void 0 ? { signal } : {}
|
|
32
|
+
});
|
|
33
|
+
const result = await startupOperation.done;
|
|
34
|
+
- if (result.waitReason === "session_exit") throw new Error("PTY shell exited during startup");
|
|
35
|
+
+ if (result.waitReason === "session_exit") throw startupExitError(result);
|
|
36
|
+
if (result.waitReason === "timeout") throw new Error("PTY shell did not reach readiness before startup timeout");
|
|
37
|
+
viewport = result.viewport;
|
|
38
|
+
if (result.waitReason === "stdin_read") break;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
--- a/dsh/node_modules/node-pty/lib/windowsPtyAgent.js
|
|
2
|
+
+++ b/dsh/node_modules/node-pty/lib/windowsPtyAgent.js
|
|
3
|
+
@@ -38,6 +38,8 @@
|
|
4
|
+
this._useConptyDll = _useConptyDll;
|
|
5
|
+
this._innerPid = 0;
|
|
6
|
+
this._onError = new eventEmitter2_1.EventEmitter2();
|
|
7
|
+
+ // 原生进程退出与输出管道关闭分别通知,避免将管道 EOF 当作完整退出结果。
|
|
8
|
+
+ this._onProcessExit = new eventEmitter2_1.EventEmitter2();
|
|
9
|
+
if (!conptyNative) {
|
|
10
|
+
conptyNative = (0, utils_1.loadNativeModule)('conpty').module;
|
|
11
|
+
}
|
|
12
|
+
@@ -91,6 +93,11 @@
|
|
13
|
+
});
|
|
14
|
+
this._inSocket.setEncoding('utf8');
|
|
15
|
+
}
|
|
16
|
+
+ Object.defineProperty(WindowsPtyAgent.prototype, "onProcessExit", {
|
|
17
|
+
+ get: function () { return this._onProcessExit.event; },
|
|
18
|
+
+ enumerable: false,
|
|
19
|
+
+ configurable: true
|
|
20
|
+
+ });
|
|
21
|
+
Object.defineProperty(WindowsPtyAgent.prototype, "onError", {
|
|
22
|
+
get: function () { return this._onError.event; },
|
|
23
|
+
enumerable: false,
|
|
24
|
+
@@ -248,6 +255,7 @@
|
|
25
|
+
WindowsPtyAgent.prototype._$onProcessExit = function (exitCode) {
|
|
26
|
+
var _this = this;
|
|
27
|
+
this._exitCode = exitCode;
|
|
28
|
+
+ this._onProcessExit.fire(exitCode);
|
|
29
|
+
if (!this._useConptyDll) {
|
|
30
|
+
this._flushDataAndCleanUp();
|
|
31
|
+
this._outSocket.on('data', function () { return _this._flushDataAndCleanUp(); });
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
--- a/dsh/node_modules/node-pty/lib/windowsTerminal.js
|
|
2
|
+
+++ b/dsh/node_modules/node-pty/lib/windowsTerminal.js
|
|
3
|
+
@@ -49,14 +49,32 @@
|
|
4
|
+
_this._isReady = false;
|
|
5
|
+
// Functions that need to run after `ready` event is emitted.
|
|
6
|
+
_this._deferreds = [];
|
|
7
|
+
+ _this._outputClosed = false;
|
|
8
|
+
+ _this._exitPublished = false;
|
|
9
|
+
+ _this._killRequested = false;
|
|
10
|
+
+ _this._processReadySettled = false;
|
|
11
|
+
+ _this.processReady = new Promise(function (resolve, reject) {
|
|
12
|
+
+ _this._resolveProcessReady = resolve;
|
|
13
|
+
+ _this._rejectProcessReady = reject;
|
|
14
|
+
+ });
|
|
15
|
+
+ // 原始 node-pty 调用方可能不消费该附加 Promise;保留拒绝结果但防止未处理拒绝。
|
|
16
|
+
+ _this.processReady.catch(function () {});
|
|
17
|
+
// Create new termal.
|
|
18
|
+
_this._agent = new windowsPtyAgent_1.WindowsPtyAgent(file, args, parsedEnv, cwd, _this._cols, _this._rows, false, opt.useConptyDll, opt.conptyInheritCursor);
|
|
19
|
+
_this._socket = _this._agent.outSocket;
|
|
20
|
+
// The socket 'close' handler that drives 'exit' is only attached after
|
|
21
|
+
// ready_datapipe, which never fires when connect() fails.
|
|
22
|
+
- _this._agent.onError(function () {
|
|
23
|
+
+ _this._agent.onError(function (error) {
|
|
24
|
+
+ if (!_this._processReadySettled) {
|
|
25
|
+
+ _this._processReadySettled = true;
|
|
26
|
+
+ _this._rejectProcessReady(error);
|
|
27
|
+
+ }
|
|
28
|
+
_this._close();
|
|
29
|
+
- _this.emit('exit', _this._agent.exitCode);
|
|
30
|
+
+ // 创建/连接失败可能没有原生子进程;保留失败码,禁止等待不会到来的回调。
|
|
31
|
+
+ _this._emitExitOnce(typeof _this._agent.exitCode === 'number' ? _this._agent.exitCode : -1);
|
|
32
|
+
+ });
|
|
33
|
+
+ _this._processExitDisposable = _this._agent.onProcessExit(function () {
|
|
34
|
+
+ _this._publishExitWhenComplete();
|
|
35
|
+
});
|
|
36
|
+
// Not available until `ready` event emitted.
|
|
37
|
+
_this._pid = _this._agent.innerPid;
|
|
38
|
+
@@ -67,6 +85,11 @@
|
|
39
|
+
_this._socket.on('ready_datapipe', function () {
|
|
40
|
+
// Update pid now that the agent has connected
|
|
41
|
+
_this._pid = _this._agent.innerPid;
|
|
42
|
+
+ if (!_this._processReadySettled) {
|
|
43
|
+
+ _this._processReadySettled = true;
|
|
44
|
+
+ if (_this._pid > 0) _this._resolveProcessReady(_this._pid);
|
|
45
|
+
+ else _this._rejectProcessReady(new Error('ConPTY connected without a valid child pid'));
|
|
46
|
+
+ }
|
|
47
|
+
// Run deferreds and set ready state once the first data event is received.
|
|
48
|
+
_this._socket.once('data', function () {
|
|
49
|
+
// Wait until the first data event is fired then we can run deferreds.
|
|
50
|
+
@@ -105,8 +128,9 @@
|
|
51
|
+
});
|
|
52
|
+
// Cleanup after the socket is closed.
|
|
53
|
+
_this._socket.on('close', function () {
|
|
54
|
+
- _this.emit('exit', _this._agent.exitCode);
|
|
55
|
+
+ _this._outputClosed = true;
|
|
56
|
+
_this._close();
|
|
57
|
+
+ _this._publishExitWhenComplete();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
_this._file = file;
|
|
61
|
+
@@ -116,6 +140,17 @@
|
|
62
|
+
_this._forwardEvents();
|
|
63
|
+
return _this;
|
|
64
|
+
}
|
|
65
|
+
+ WindowsTerminal.prototype._publishExitWhenComplete = function () {
|
|
66
|
+
+ // 两个顺序均允许:进程先退出,或输出管道先关闭;不设置猜测性延时或退出码。
|
|
67
|
+
+ if (!this._outputClosed || typeof this._agent.exitCode !== 'number') return;
|
|
68
|
+
+ this._emitExitOnce(this._agent.exitCode);
|
|
69
|
+
+ };
|
|
70
|
+
+ WindowsTerminal.prototype._emitExitOnce = function (exitCode) {
|
|
71
|
+
+ if (this._exitPublished) return;
|
|
72
|
+
+ this._exitPublished = true;
|
|
73
|
+
+ if (this._processExitDisposable) this._processExitDisposable.dispose();
|
|
74
|
+
+ this.emit('exit', exitCode);
|
|
75
|
+
+ };
|
|
76
|
+
WindowsTerminal.prototype._write = function (data) {
|
|
77
|
+
this._defer(this._doWrite, data);
|
|
78
|
+
};
|
|
79
|
+
@@ -155,14 +190,20 @@
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
WindowsTerminal.prototype.kill = function (signal) {
|
|
83
|
+
- var _this = this;
|
|
84
|
+
- this._deferNoArgs(function () {
|
|
85
|
+
- if (signal) {
|
|
86
|
+
- throw new Error('Signals not supported on windows.');
|
|
87
|
+
- }
|
|
88
|
+
- _this._close();
|
|
89
|
+
- _this._agent.kill();
|
|
90
|
+
- });
|
|
91
|
+
+ if (signal) throw new Error('Signals not supported on windows.');
|
|
92
|
+
+ if (this._killRequested) {
|
|
93
|
+
+ if (this._killError) throw this._killError;
|
|
94
|
+
+ return;
|
|
95
|
+
+ }
|
|
96
|
+
+ this._killRequested = true;
|
|
97
|
+
+ // 释放连接中的 PTY 不依赖首屏数据,避免连接失败或取消时留下延迟 kill。
|
|
98
|
+
+ if (!this._processReadySettled) {
|
|
99
|
+
+ this._processReadySettled = true;
|
|
100
|
+
+ this._rejectProcessReady(new Error('Terminal was closed before its process connected'));
|
|
101
|
+
+ }
|
|
102
|
+
+ this._close();
|
|
103
|
+
+ try { this._agent.kill(); }
|
|
104
|
+
+ catch (error) { this._killError = error; throw error; }
|
|
105
|
+
};
|
|
106
|
+
WindowsTerminal.prototype._deferNoArgs = function (deferredFn) {
|
|
107
|
+
var _this = this;
|