dsh-bash-terminal-ts 0.6.4 → 0.7.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.en.md +8 -6
- package/README.md +10 -7
- package/dist/client.core.js +151 -151
- package/dist/client.js +160 -160
- package/dsh.plugin.json +2 -2
- package/lib/client.js +160 -160
- package/lib/dsh-types.d.ts +259 -259
- package/lib/dsh-types.js +9 -9
- package/lib/dsh.d.ts +35 -35
- package/lib/dsh.js +29 -29
- package/lib/index.d.ts +200 -200
- package/lib/index.js +765 -765
- package/lib/terminal.d.ts +110 -110
- package/lib/terminal.js +438 -438
- package/package.json +36 -30
- package/src/client.tsx +201 -207
- package/src/terminal.ts +1 -2
- package/template/README.md +82 -82
- package/template/terminal-adapter.ts +343 -343
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-bash-terminal-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"publishConfig": {
|
|
5
|
-
"tag": "dsh-0.
|
|
5
|
+
"tag": "dsh-0.2.0"
|
|
6
6
|
},
|
|
7
7
|
"description": "DSH plugin: one shell tool that runs commands through PowerShell, Git Bash, MSYS2, or WSL on Windows, with a user-chosen default terminal in the Web UI settings. TypeScript rewrite of MAXeaglet/dsh-bash-terminal with working MSYS2/MINGW64 support.",
|
|
8
8
|
"author": "drscrewdriver",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=22",
|
|
32
|
-
"dsh": ">=0.
|
|
32
|
+
"dsh": ">=0.2.0-rc.1 <0.2.1-0"
|
|
33
33
|
},
|
|
34
34
|
"type": "module",
|
|
35
35
|
"main": "lib/index.js",
|
|
@@ -56,7 +56,8 @@
|
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "tsc -p tsconfig.json && tsc -p tsconfig.client.json && node scripts/build-client.mjs && tsc -p tsconfig.test.json",
|
|
58
58
|
"build:client": "node scripts/build-client.mjs",
|
|
59
|
-
"test": "node test-dist/unit.js && node test-dist/apply.js && node test-dist/client.js && node test-dist/terminal.js"
|
|
59
|
+
"test": "node test-dist/unit.js && node test-dist/apply.js && node test-dist/client.js && node test-dist/terminal.js",
|
|
60
|
+
"lint": "eslint ."
|
|
60
61
|
},
|
|
61
62
|
"dsh": {
|
|
62
63
|
"bundle": {
|
|
@@ -74,17 +75,17 @@
|
|
|
74
75
|
},
|
|
75
76
|
"peerDependencies": {
|
|
76
77
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
77
|
-
"@deepseek-ai/dsh-
|
|
78
|
-
"@deepseek-ai/dsh-
|
|
79
|
-
"@deepseek-ai/dsh-
|
|
80
|
-
"@deepseek-ai/dsh-
|
|
81
|
-
"@deepseek-ai/dsh-
|
|
82
|
-
"@deepseek-ai/dsh-
|
|
83
|
-
"@deepseek-ai/dsh-
|
|
84
|
-
"@deepseek-ai/dsh-
|
|
85
|
-
"@deepseek-ai/dsh-
|
|
86
|
-
"@deepseek-ai/dsh-
|
|
87
|
-
"@deepseek-ai/dsh-
|
|
78
|
+
"@deepseek-ai/dsh-client-locale": ">=0.2.0-rc.1 <0.2.1-0",
|
|
79
|
+
"@deepseek-ai/dsh-client-store": ">=0.2.0-rc.1 <0.2.1-0",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.2.0-rc.1 <0.2.1-0",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.2.0-rc.1 <0.2.1-0",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.2.0-rc.1 <0.2.1-0",
|
|
83
|
+
"@deepseek-ai/dsh-llm": ">=0.2.0-rc.1 <0.2.1-0",
|
|
84
|
+
"@deepseek-ai/dsh-sandbox": ">=0.2.0-rc.1 <0.2.1-0",
|
|
85
|
+
"@deepseek-ai/dsh-settings": ">=0.2.0-rc.1 <0.2.1-0",
|
|
86
|
+
"@deepseek-ai/dsh-shell": ">=0.2.0-rc.1 <0.2.1-0",
|
|
87
|
+
"@deepseek-ai/dsh-timeout": ">=0.2.0-rc.1 <0.2.1-0",
|
|
88
|
+
"@deepseek-ai/dsh-tools": ">=0.2.0-rc.1 <0.2.1-0",
|
|
88
89
|
"react": "^18.2.0"
|
|
89
90
|
},
|
|
90
91
|
"dependencies": {
|
|
@@ -93,27 +94,32 @@
|
|
|
93
94
|
},
|
|
94
95
|
"devDependencies": {
|
|
95
96
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
96
|
-
"@deepseek-ai/dsh-client-locale": "0.
|
|
97
|
-
"@deepseek-ai/dsh-client-store": "0.
|
|
98
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.
|
|
99
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.
|
|
100
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.
|
|
101
|
-
"@deepseek-ai/dsh-
|
|
102
|
-
"@deepseek-ai/dsh-
|
|
103
|
-
"@deepseek-ai/dsh-
|
|
104
|
-
"@deepseek-ai/dsh-
|
|
105
|
-
"@deepseek-ai/dsh-
|
|
106
|
-
"@deepseek-ai/dsh-
|
|
97
|
+
"@deepseek-ai/dsh-client-locale": "0.2.0-rc.1",
|
|
98
|
+
"@deepseek-ai/dsh-client-store": "0.2.0-rc.1",
|
|
99
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.1",
|
|
100
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.1",
|
|
101
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.1",
|
|
102
|
+
"@deepseek-ai/dsh-http-proxy": "0.2.0-rc.1",
|
|
103
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.1",
|
|
104
|
+
"@deepseek-ai/dsh-sandbox": "0.2.0-rc.1",
|
|
105
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.1",
|
|
106
|
+
"@deepseek-ai/dsh-scope": "0.2.0-rc.1",
|
|
107
|
+
"@deepseek-ai/dsh-settings": "0.2.0-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-shell": "0.2.0-rc.1",
|
|
109
|
+
"@deepseek-ai/dsh-subprocess": "0.2.0-rc.1",
|
|
110
|
+
"@deepseek-ai/dsh-timeout": "0.2.0-rc.1",
|
|
111
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.1",
|
|
112
|
+
"@eslint/js": "^10.0.1",
|
|
107
113
|
"@types/node": "^22.10.0",
|
|
108
114
|
"@types/react": "^18.2.0",
|
|
109
115
|
"@types/react-dom": "^18.2.0",
|
|
110
116
|
"esbuild": "^0.28.2",
|
|
117
|
+
"eslint": "^10.11.0",
|
|
118
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
119
|
+
"globals": "^17.12.0",
|
|
111
120
|
"react": "^18.2.0",
|
|
112
121
|
"react-dom": "^18.2.0",
|
|
113
122
|
"typescript": "^5.9.0",
|
|
114
|
-
"
|
|
115
|
-
"@deepseek-ai/dsh-subprocess": "0.1.7-rc.2",
|
|
116
|
-
"@deepseek-ai/dsh-sandbox-policy": "0.1.7-rc.2",
|
|
117
|
-
"@deepseek-ai/dsh-http-proxy": "0.1.7-rc.2"
|
|
123
|
+
"typescript-eslint": "^8.71.0"
|
|
118
124
|
}
|
|
119
125
|
}
|
package/src/client.tsx
CHANGED
|
@@ -1,207 +1,201 @@
|
|
|
1
|
-
// dsh-bash-terminal-ts client plugin: a "Default terminal" preference row in the
|
|
2
|
-
// Web UI General settings, mirroring the shipped EnterBehaviorRow grammar
|
|
3
|
-
// (row layout, capsule selector with chevron, --dsw-* tokens).
|
|
4
|
-
//
|
|
5
|
-
// The row offers one entry per host shell id — powershell / gitbash / msys2 /
|
|
6
|
-
// wsl — in the same order as SHELLS in ./index.ts.
|
|
7
|
-
//
|
|
8
|
-
// DSH >= 0.1.5: the browser module table (PLATFORM_MODULES) seeds react,
|
|
9
|
-
// @deepseek-ai/cordis, @deepseek-ai/dsh-client-store, @deepseek-ai/dsh-client-ui-slots,
|
|
10
|
-
// @deepseek-ai/dsh-client-ui-primitives and @deepseek-ai/dsh-client-ui-dockkit by
|
|
11
|
-
// exact bare specifier. The old dsh-client-runtime name is gone from that table
|
|
12
|
-
// (and so is its /client subpath), so this bundle requests dsh-client-store.
|
|
13
|
-
|
|
14
|
-
import { useState } from "react";
|
|
15
|
-
import { defineStore } from "@deepseek-ai/dsh-client-store";
|
|
16
|
-
import { IconChevronDownOutlineMedium, Menu } from "@deepseek-ai/dsh-client-ui-primitives";
|
|
17
|
-
|
|
18
|
-
const SETTINGS_NS = "settings.bash-terminal";
|
|
19
|
-
/** Entry id of this plugin in the active profile (cordis.patch.yml). */
|
|
20
|
-
const ENTRY_ID = "tool-bash-terminal";
|
|
21
|
-
const SHELLS = ["powershell", "gitbash", "msys2", "wsl"] as const;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
".
|
|
28
|
-
".
|
|
29
|
-
".
|
|
30
|
-
".
|
|
31
|
-
".
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
tag.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"shell.
|
|
44
|
-
"shell.
|
|
45
|
-
"shell.
|
|
46
|
-
"shell.
|
|
47
|
-
"shell.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"shell.
|
|
53
|
-
"shell.
|
|
54
|
-
"shell.
|
|
55
|
-
"shell.
|
|
56
|
-
"shell.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
ShellPreferenceRow
|
|
203
|
-
),
|
|
204
|
-
"bash-terminal: settings row"
|
|
205
|
-
);
|
|
206
|
-
ctx.effect(() => scope.subscribe(() => push(scope.getSnapshot())), "bash-terminal: settings watch");
|
|
207
|
-
}
|
|
1
|
+
// dsh-bash-terminal-ts client plugin: a "Default terminal" preference row in the
|
|
2
|
+
// Web UI General settings, mirroring the shipped EnterBehaviorRow grammar
|
|
3
|
+
// (row layout, capsule selector with chevron, --dsw-* tokens).
|
|
4
|
+
//
|
|
5
|
+
// The row offers one entry per host shell id — powershell / gitbash / msys2 /
|
|
6
|
+
// wsl — in the same order as SHELLS in ./index.ts.
|
|
7
|
+
//
|
|
8
|
+
// DSH >= 0.1.5: the browser module table (PLATFORM_MODULES) seeds react,
|
|
9
|
+
// @deepseek-ai/cordis, @deepseek-ai/dsh-client-store, @deepseek-ai/dsh-client-ui-slots,
|
|
10
|
+
// @deepseek-ai/dsh-client-ui-primitives and @deepseek-ai/dsh-client-ui-dockkit by
|
|
11
|
+
// exact bare specifier. The old dsh-client-runtime name is gone from that table
|
|
12
|
+
// (and so is its /client subpath), so this bundle requests dsh-client-store.
|
|
13
|
+
|
|
14
|
+
import { useState } from "react";
|
|
15
|
+
import { defineStore } from "@deepseek-ai/dsh-client-store";
|
|
16
|
+
import { IconChevronDownOutlineMedium, Menu } from "@deepseek-ai/dsh-client-ui-primitives";
|
|
17
|
+
|
|
18
|
+
const SETTINGS_NS = "settings.bash-terminal";
|
|
19
|
+
/** Entry id of this plugin in the active profile (cordis.patch.yml). */
|
|
20
|
+
const ENTRY_ID = "tool-bash-terminal";
|
|
21
|
+
const SHELLS = ["powershell", "gitbash", "msys2", "wsl"] as const;
|
|
22
|
+
|
|
23
|
+
// Injected once when the browser loads the bundle (node tests guard on document).
|
|
24
|
+
const ROW_CSS =
|
|
25
|
+
".btRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}" +
|
|
26
|
+
".btRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}" +
|
|
27
|
+
".btTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}" +
|
|
28
|
+
".btDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}" +
|
|
29
|
+
".btSelector{background:var(--dsw-alias-bg-module-platform);height:36px;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:18px;align-items:center;gap:12px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}" +
|
|
30
|
+
".btSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}" +
|
|
31
|
+
".btChevron{flex:none}";
|
|
32
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"bash-terminal-row\"]") === null) {
|
|
33
|
+
const tag = document.createElement("style");
|
|
34
|
+
tag.dataset.plugin = "dsh-bash-terminal-ts";
|
|
35
|
+
tag.dataset.pluginCss = "bash-terminal-row";
|
|
36
|
+
tag.textContent = ROW_CSS;
|
|
37
|
+
document.head.appendChild(tag);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const zh: Record<string, string> = {
|
|
41
|
+
"shell.title": "默认终端",
|
|
42
|
+
"shell.description": "shell 工具执行命令时使用的终端",
|
|
43
|
+
"shell.powershell": "PowerShell",
|
|
44
|
+
"shell.gitbash": "Git Bash",
|
|
45
|
+
"shell.msys2": "MSYS2",
|
|
46
|
+
"shell.wsl": "WSL",
|
|
47
|
+
"shell.unavailable": "设置面不可用:宿主未提供本插件的 configForms 条目(检查 cordis.patch.yml 的 entry id)"
|
|
48
|
+
};
|
|
49
|
+
const en: Record<string, string> = {
|
|
50
|
+
"shell.title": "Default terminal",
|
|
51
|
+
"shell.description": "Terminal used by the shell tool",
|
|
52
|
+
"shell.powershell": "PowerShell",
|
|
53
|
+
"shell.gitbash": "Git Bash",
|
|
54
|
+
"shell.msys2": "MSYS2",
|
|
55
|
+
"shell.wsl": "WSL",
|
|
56
|
+
"shell.unavailable": "Settings unavailable: the host exposes no configForms entry for this plugin (check the cordis.patch.yml entry id)"
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const inject = ["slots", "locale", "configForms"];
|
|
60
|
+
|
|
61
|
+
/** Row state snapshot served through the settings store. */
|
|
62
|
+
interface RowState {
|
|
63
|
+
shell: string;
|
|
64
|
+
revision: number;
|
|
65
|
+
writable: boolean;
|
|
66
|
+
status: "loading" | "ready" | "unavailable";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface ShellPreferenceRowProps {
|
|
70
|
+
t: (key: string) => string;
|
|
71
|
+
useStore: <S>(selector: (state: RowState) => S) => S;
|
|
72
|
+
setShell: (id: string) => void;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function ShellPreferenceRow({ t, useStore, setShell }: ShellPreferenceRowProps) {
|
|
76
|
+
const shell = useStore((s) => s.shell);
|
|
77
|
+
const writable = useStore((s) => s.writable);
|
|
78
|
+
const status = useStore((s) => s.status);
|
|
79
|
+
const [open, setOpen] = useState(false);
|
|
80
|
+
const items = SHELLS.map((id) => ({ id, label: t("shell." + id) }));
|
|
81
|
+
if (status === "unavailable") {
|
|
82
|
+
return (
|
|
83
|
+
<div className="btRow">
|
|
84
|
+
<div className="btRowText">
|
|
85
|
+
<div className="btTitle">{t("shell.title")}</div>
|
|
86
|
+
<div className="btDesc">{t("shell.unavailable")}</div>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return (
|
|
92
|
+
<div className="btRow">
|
|
93
|
+
<div className="btRowText">
|
|
94
|
+
<div className="btTitle">{t("shell.title")}</div>
|
|
95
|
+
<div className="btDesc">{t("shell.description")}</div>
|
|
96
|
+
</div>
|
|
97
|
+
<Menu
|
|
98
|
+
open={open}
|
|
99
|
+
onClose={() => setOpen(false)}
|
|
100
|
+
items={items}
|
|
101
|
+
selectedId={shell}
|
|
102
|
+
onSelect={(id) => {
|
|
103
|
+
setOpen(false);
|
|
104
|
+
setShell(id);
|
|
105
|
+
}}
|
|
106
|
+
align="end"
|
|
107
|
+
portal
|
|
108
|
+
anchor={
|
|
109
|
+
<button
|
|
110
|
+
type="button"
|
|
111
|
+
className="btSelector"
|
|
112
|
+
aria-haspopup="menu"
|
|
113
|
+
aria-expanded={open}
|
|
114
|
+
disabled={!writable}
|
|
115
|
+
onClick={() => setOpen(!open)}
|
|
116
|
+
style={!writable ? { opacity: 0.5, cursor: "not-allowed" } : undefined}
|
|
117
|
+
>
|
|
118
|
+
{t("shell." + shell)}
|
|
119
|
+
<IconChevronDownOutlineMedium className="btChevron" />
|
|
120
|
+
</button>
|
|
121
|
+
}
|
|
122
|
+
/>
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface SettingsSnapshot {
|
|
128
|
+
status: "loading" | "ready" | "unavailable";
|
|
129
|
+
value?: { defaultShell?: string };
|
|
130
|
+
revision: number | undefined;
|
|
131
|
+
writable: boolean;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
interface ConfigFormBinding {
|
|
135
|
+
getSnapshot(): SettingsSnapshot;
|
|
136
|
+
subscribe(fn: () => void): () => void;
|
|
137
|
+
set(field: string, value: string): Promise<boolean>;
|
|
138
|
+
unset(field: string): Promise<boolean>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
interface ClientContext {
|
|
142
|
+
effect(fn: () => unknown, name?: string): unknown;
|
|
143
|
+
locale: { register(ns: string, dicts: Record<string, Record<string, string>>): unknown };
|
|
144
|
+
configForms: { get(entryId: string): ConfigFormBinding };
|
|
145
|
+
slots: {
|
|
146
|
+
inject(slot: string, fn: () => unknown, name?: string): void;
|
|
147
|
+
register(options: Record<string, unknown>, Component: unknown): Record<string, unknown>;
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface RowStoreActions {
|
|
152
|
+
sync(shell?: string, revision?: number, writable?: boolean, status?: RowState["status"]): void;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** 账本 label:从 zh/en 字典取「默认终端」标题(无宿主 locale 依赖)。 */
|
|
156
|
+
const zhDictTitle = (): string => (zh as Record<string, string>)["shell.title"] ?? "终端";
|
|
157
|
+
|
|
158
|
+
export function apply(ctx: ClientContext): void {
|
|
159
|
+
ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
|
|
160
|
+
const scope = ctx.configForms.get(ENTRY_ID);
|
|
161
|
+
const store = defineStore<RowState, { sync: (draft: RowState, shell?: string, revision?: number, writable?: boolean, status?: RowState["status"]) => void }>({
|
|
162
|
+
init: (): RowState => ({ shell: "powershell", revision: -1, writable: false, status: "loading" }),
|
|
163
|
+
actions: {
|
|
164
|
+
sync: (d, shell, revision, writable, status) => {
|
|
165
|
+
if (revision !== undefined && revision <= d.revision) return;
|
|
166
|
+
if (shell !== undefined) d.shell = shell;
|
|
167
|
+
if (revision !== undefined) d.revision = revision;
|
|
168
|
+
if (writable !== undefined) d.writable = writable;
|
|
169
|
+
if (status !== undefined) d.status = status;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
let bound: RowStoreActions | undefined;
|
|
174
|
+
const push = (snap: SettingsSnapshot): void => {
|
|
175
|
+
bound?.sync(snap.value?.defaultShell, snap.revision, snap.writable, snap.status);
|
|
176
|
+
};
|
|
177
|
+
// 插件族共用设置 tab(dsh-thinking-levels 顶级「起子插件设置」节声明该子席位)。
|
|
178
|
+
// thinking-levels 缺席时本 inject 静默等待,不阻塞客户端半。
|
|
179
|
+
ctx.slots.inject(
|
|
180
|
+
"dsh-family.tab",
|
|
181
|
+
() =>
|
|
182
|
+
ctx.slots.register(
|
|
183
|
+
{
|
|
184
|
+
name: "dsh-family.tab",
|
|
185
|
+
id: "bash-terminal-shell",
|
|
186
|
+
order: 60,
|
|
187
|
+
label: () => zhDictTitle(),
|
|
188
|
+
store,
|
|
189
|
+
locale: SETTINGS_NS,
|
|
190
|
+
inject: (actions: unknown) => {
|
|
191
|
+
bound = actions as RowStoreActions;
|
|
192
|
+
push(scope.getSnapshot());
|
|
193
|
+
return { setShell: (value: string) => void scope.set("defaultShell", value) };
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
ShellPreferenceRow
|
|
197
|
+
),
|
|
198
|
+
"bash-terminal: settings row"
|
|
199
|
+
);
|
|
200
|
+
ctx.effect(() => scope.subscribe(() => push(scope.getSnapshot())), "bash-terminal: settings watch");
|
|
201
|
+
}
|