dsh-bash-terminal-ts 0.6.0 → 0.6.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/dist/client.core.js +6 -4
- package/dist/client.js +6 -4
- package/dsh.plugin.json +2 -2
- package/lib/client.js +6 -4
- package/package.json +29 -25
- package/screenshots.json +5 -5
- package/src/client.tsx +192 -186
package/dist/client.core.js
CHANGED
|
@@ -90,7 +90,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
|
|
|
90
90
|
style: !writable ? { opacity: 0.5, cursor: "not-allowed" } : void 0,
|
|
91
91
|
children: [
|
|
92
92
|
t("shell." + shell),
|
|
93
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.
|
|
93
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconChevronDownOutlineMedium, { className: "btChevron" })
|
|
94
94
|
]
|
|
95
95
|
}
|
|
96
96
|
)
|
|
@@ -98,6 +98,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
|
|
|
98
98
|
)
|
|
99
99
|
] });
|
|
100
100
|
}
|
|
101
|
+
var zhDictTitle = () => zh["shell.title"] ?? "\u7EC8\u7AEF";
|
|
101
102
|
function apply(ctx) {
|
|
102
103
|
ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
|
|
103
104
|
const scope = ctx.configForms.get(ENTRY_ID);
|
|
@@ -117,12 +118,13 @@ function apply(ctx) {
|
|
|
117
118
|
bound?.sync(snap.value?.defaultShell, snap.revision, snap.writable);
|
|
118
119
|
};
|
|
119
120
|
ctx.slots.inject(
|
|
120
|
-
"
|
|
121
|
+
"dsh-family.tab",
|
|
121
122
|
() => ctx.slots.register(
|
|
122
123
|
{
|
|
123
|
-
name: "
|
|
124
|
+
name: "dsh-family.tab",
|
|
124
125
|
id: "bash-terminal-shell",
|
|
125
|
-
order:
|
|
126
|
+
order: 60,
|
|
127
|
+
label: () => zhDictTitle(),
|
|
126
128
|
store,
|
|
127
129
|
locale: SETTINGS_NS,
|
|
128
130
|
inject: (actions) => {
|
package/dist/client.js
CHANGED
|
@@ -95,7 +95,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
|
|
|
95
95
|
style: !writable ? { opacity: 0.5, cursor: "not-allowed" } : void 0,
|
|
96
96
|
children: [
|
|
97
97
|
t("shell." + shell),
|
|
98
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.
|
|
98
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconChevronDownOutlineMedium, { className: "btChevron" })
|
|
99
99
|
]
|
|
100
100
|
}
|
|
101
101
|
)
|
|
@@ -103,6 +103,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
|
|
|
103
103
|
)
|
|
104
104
|
] });
|
|
105
105
|
}
|
|
106
|
+
var zhDictTitle = () => zh["shell.title"] ?? "\u7EC8\u7AEF";
|
|
106
107
|
function apply(ctx) {
|
|
107
108
|
ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
|
|
108
109
|
const scope = ctx.configForms.get(ENTRY_ID);
|
|
@@ -122,12 +123,13 @@ function apply(ctx) {
|
|
|
122
123
|
bound?.sync(snap.value?.defaultShell, snap.revision, snap.writable);
|
|
123
124
|
};
|
|
124
125
|
ctx.slots.inject(
|
|
125
|
-
"
|
|
126
|
+
"dsh-family.tab",
|
|
126
127
|
() => ctx.slots.register(
|
|
127
128
|
{
|
|
128
|
-
name: "
|
|
129
|
+
name: "dsh-family.tab",
|
|
129
130
|
id: "bash-terminal-shell",
|
|
130
|
-
order:
|
|
131
|
+
order: 60,
|
|
132
|
+
label: () => zhDictTitle(),
|
|
131
133
|
store,
|
|
132
134
|
locale: SETTINGS_NS,
|
|
133
135
|
inject: (actions) => {
|
package/dsh.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-bash-terminal",
|
|
3
3
|
"name": "dsh-bash-terminal",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.1",
|
|
5
5
|
"description": {
|
|
6
6
|
"en": "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.",
|
|
7
7
|
"zh": "一个 shell 工具,可在 Windows 上通过 PowerShell / Git Bash / MSYS2 / WSL 执行命令,默认终端在 Web UI 设置中选择。"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"engines": {
|
|
16
|
-
"dsh": ">=0.1.
|
|
16
|
+
"dsh": ">=0.1.7-rc.1 <0.1.8-0"
|
|
17
17
|
},
|
|
18
18
|
"components": {
|
|
19
19
|
"host": "lib/index.js",
|
package/lib/client.js
CHANGED
|
@@ -95,7 +95,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
|
|
|
95
95
|
style: !writable ? { opacity: 0.5, cursor: "not-allowed" } : void 0,
|
|
96
96
|
children: [
|
|
97
97
|
t("shell." + shell),
|
|
98
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.
|
|
98
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconChevronDownOutlineMedium, { className: "btChevron" })
|
|
99
99
|
]
|
|
100
100
|
}
|
|
101
101
|
)
|
|
@@ -103,6 +103,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
|
|
|
103
103
|
)
|
|
104
104
|
] });
|
|
105
105
|
}
|
|
106
|
+
var zhDictTitle = () => zh["shell.title"] ?? "\u7EC8\u7AEF";
|
|
106
107
|
function apply(ctx) {
|
|
107
108
|
ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
|
|
108
109
|
const scope = ctx.configForms.get(ENTRY_ID);
|
|
@@ -122,12 +123,13 @@ function apply(ctx) {
|
|
|
122
123
|
bound?.sync(snap.value?.defaultShell, snap.revision, snap.writable);
|
|
123
124
|
};
|
|
124
125
|
ctx.slots.inject(
|
|
125
|
-
"
|
|
126
|
+
"dsh-family.tab",
|
|
126
127
|
() => ctx.slots.register(
|
|
127
128
|
{
|
|
128
|
-
name: "
|
|
129
|
+
name: "dsh-family.tab",
|
|
129
130
|
id: "bash-terminal-shell",
|
|
130
|
-
order:
|
|
131
|
+
order: 60,
|
|
132
|
+
label: () => zhDictTitle(),
|
|
131
133
|
store,
|
|
132
134
|
locale: SETTINGS_NS,
|
|
133
135
|
inject: (actions) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-bash-terminal-ts",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"tag": "dsh-0.1.7"
|
|
6
6
|
},
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=22",
|
|
32
|
-
"dsh": ">=0.1.7-rc.1 <0.
|
|
32
|
+
"dsh": ">=0.1.7-rc.1 <0.1.8-0"
|
|
33
33
|
},
|
|
34
34
|
"type": "module",
|
|
35
35
|
"main": "lib/index.js",
|
|
@@ -74,17 +74,17 @@
|
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
77
|
-
"@deepseek-ai/dsh-tools": ">=0.1.7-rc.1 <0.
|
|
78
|
-
"@deepseek-ai/dsh-settings": ">=0.1.7-rc.1 <0.
|
|
79
|
-
"@deepseek-ai/dsh-llm": ">=0.1.7-rc.1 <0.
|
|
80
|
-
"@deepseek-ai/dsh-shell": ">=0.1.7-rc.1 <0.
|
|
81
|
-
"@deepseek-ai/dsh-sandbox": ">=0.1.7-rc.1 <0.
|
|
82
|
-
"@deepseek-ai/dsh-timeout": ">=0.1.7-rc.1 <0.
|
|
83
|
-
"@deepseek-ai/dsh-client-store": ">=0.1.7-rc.1 <0.
|
|
84
|
-
"@deepseek-ai/dsh-client-locale": ">=0.1.7-rc.1 <0.
|
|
85
|
-
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.1 <0.
|
|
86
|
-
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-rc.1 <0.
|
|
87
|
-
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-rc.1 <0.
|
|
77
|
+
"@deepseek-ai/dsh-tools": ">=0.1.7-rc.1 <0.1.8-0",
|
|
78
|
+
"@deepseek-ai/dsh-settings": ">=0.1.7-rc.1 <0.1.8-0",
|
|
79
|
+
"@deepseek-ai/dsh-llm": ">=0.1.7-rc.1 <0.1.8-0",
|
|
80
|
+
"@deepseek-ai/dsh-shell": ">=0.1.7-rc.1 <0.1.8-0",
|
|
81
|
+
"@deepseek-ai/dsh-sandbox": ">=0.1.7-rc.1 <0.1.8-0",
|
|
82
|
+
"@deepseek-ai/dsh-timeout": ">=0.1.7-rc.1 <0.1.8-0",
|
|
83
|
+
"@deepseek-ai/dsh-client-store": ">=0.1.7-rc.1 <0.1.8-0",
|
|
84
|
+
"@deepseek-ai/dsh-client-locale": ">=0.1.7-rc.1 <0.1.8-0",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.1 <0.1.8-0",
|
|
86
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-rc.1 <0.1.8-0",
|
|
87
|
+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-rc.1 <0.1.8-0",
|
|
88
88
|
"react": "^18.2.0"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
@@ -93,23 +93,27 @@
|
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
96
|
-
"@deepseek-ai/dsh-client-locale": "0.1.
|
|
97
|
-
"@deepseek-ai/dsh-client-store": "0.1.
|
|
98
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1.
|
|
99
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.
|
|
100
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.
|
|
101
|
-
"@deepseek-ai/dsh-llm": "0.1.
|
|
102
|
-
"@deepseek-ai/dsh-sandbox": "0.1.
|
|
103
|
-
"@deepseek-ai/dsh-settings": "0.1.
|
|
104
|
-
"@deepseek-ai/dsh-shell": "0.1.
|
|
105
|
-
"@deepseek-ai/dsh-timeout": "0.1.
|
|
106
|
-
"@deepseek-ai/dsh-tools": "0.1.
|
|
96
|
+
"@deepseek-ai/dsh-client-locale": "0.1.7-rc.2",
|
|
97
|
+
"@deepseek-ai/dsh-client-store": "0.1.7-rc.2",
|
|
98
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
|
|
99
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.2",
|
|
100
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2",
|
|
101
|
+
"@deepseek-ai/dsh-llm": "0.1.7-rc.2",
|
|
102
|
+
"@deepseek-ai/dsh-sandbox": "0.1.7-rc.2",
|
|
103
|
+
"@deepseek-ai/dsh-settings": "0.1.7-rc.2",
|
|
104
|
+
"@deepseek-ai/dsh-shell": "0.1.7-rc.2",
|
|
105
|
+
"@deepseek-ai/dsh-timeout": "0.1.7-rc.2",
|
|
106
|
+
"@deepseek-ai/dsh-tools": "0.1.7-rc.2",
|
|
107
107
|
"@types/node": "^22.10.0",
|
|
108
108
|
"@types/react": "^18.2.0",
|
|
109
109
|
"@types/react-dom": "^18.2.0",
|
|
110
110
|
"esbuild": "^0.28.2",
|
|
111
111
|
"react": "^18.2.0",
|
|
112
112
|
"react-dom": "^18.2.0",
|
|
113
|
-
"typescript": "^5.9.0"
|
|
113
|
+
"typescript": "^5.9.0",
|
|
114
|
+
"@deepseek-ai/dsh-scope": "0.1.7-rc.2",
|
|
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"
|
|
114
118
|
}
|
|
115
119
|
}
|
package/screenshots.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
{
|
|
2
|
-
"screenshots": [
|
|
3
|
-
"assets/shells.png"
|
|
4
|
-
]
|
|
5
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"screenshots": [
|
|
3
|
+
"assets/shells.png"
|
|
4
|
+
]
|
|
5
|
+
}
|
package/src/client.tsx
CHANGED
|
@@ -1,186 +1,192 @@
|
|
|
1
|
-
// dsh-bash-terminal 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 {
|
|
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
|
-
type ShellOption = (typeof SHELLS)[number];
|
|
24
|
-
|
|
25
|
-
// Injected once when the browser loads the bundle (node tests guard on document).
|
|
26
|
-
const ROW_CSS =
|
|
27
|
-
".btRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}" +
|
|
28
|
-
".btRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}" +
|
|
29
|
-
".btTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}" +
|
|
30
|
-
".btDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}" +
|
|
31
|
-
".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}" +
|
|
32
|
-
".btSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}" +
|
|
33
|
-
".btChevron{flex:none}";
|
|
34
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"bash-terminal-row\"]") === null) {
|
|
35
|
-
const tag = document.createElement("style");
|
|
36
|
-
tag.dataset.plugin = "dsh-bash-terminal";
|
|
37
|
-
tag.dataset.pluginCss = "bash-terminal-row";
|
|
38
|
-
tag.textContent = ROW_CSS;
|
|
39
|
-
document.head.appendChild(tag);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const zh: Record<string, string> = {
|
|
43
|
-
"shell.title": "默认终端",
|
|
44
|
-
"shell.description": "shell 工具执行命令时使用的终端",
|
|
45
|
-
"shell.powershell": "PowerShell",
|
|
46
|
-
"shell.gitbash": "Git Bash",
|
|
47
|
-
"shell.msys2": "MSYS2",
|
|
48
|
-
"shell.wsl": "WSL"
|
|
49
|
-
};
|
|
50
|
-
const en: Record<string, string> = {
|
|
51
|
-
"shell.title": "Default terminal",
|
|
52
|
-
"shell.description": "Terminal used by the shell tool",
|
|
53
|
-
"shell.powershell": "PowerShell",
|
|
54
|
-
"shell.gitbash": "Git Bash",
|
|
55
|
-
"shell.msys2": "MSYS2",
|
|
56
|
-
"shell.wsl": "WSL"
|
|
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
|
-
}
|
|
67
|
-
|
|
68
|
-
interface ShellPreferenceRowProps {
|
|
69
|
-
t: (key: string) => string;
|
|
70
|
-
useStore: <S>(selector: (state: RowState) => S) => S;
|
|
71
|
-
setShell: (id: string) => void;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function ShellPreferenceRow({ t, useStore, setShell }: ShellPreferenceRowProps) {
|
|
75
|
-
const shell = useStore((s) => s.shell);
|
|
76
|
-
const writable = useStore((s) => s.writable);
|
|
77
|
-
const [open, setOpen] = useState(false);
|
|
78
|
-
const items = SHELLS.map((id) => ({ id, label: t("shell." + id) }));
|
|
79
|
-
return (
|
|
80
|
-
<div className="btRow">
|
|
81
|
-
<div className="btRowText">
|
|
82
|
-
<div className="btTitle">{t("shell.title")}</div>
|
|
83
|
-
<div className="btDesc">{t("shell.description")}</div>
|
|
84
|
-
</div>
|
|
85
|
-
<Menu
|
|
86
|
-
open={open}
|
|
87
|
-
onClose={() => setOpen(false)}
|
|
88
|
-
items={items}
|
|
89
|
-
selectedId={shell}
|
|
90
|
-
onSelect={(id) => {
|
|
91
|
-
setOpen(false);
|
|
92
|
-
setShell(id);
|
|
93
|
-
}}
|
|
94
|
-
align="end"
|
|
95
|
-
portal
|
|
96
|
-
anchor={
|
|
97
|
-
<button
|
|
98
|
-
type="button"
|
|
99
|
-
className="btSelector"
|
|
100
|
-
aria-haspopup="menu"
|
|
101
|
-
aria-expanded={open}
|
|
102
|
-
disabled={!writable}
|
|
103
|
-
onClick={() => setOpen(!open)}
|
|
104
|
-
style={!writable ? { opacity: 0.5, cursor: "not-allowed" } : undefined}
|
|
105
|
-
>
|
|
106
|
-
{t("shell." + shell)}
|
|
107
|
-
<
|
|
108
|
-
</button>
|
|
109
|
-
}
|
|
110
|
-
/>
|
|
111
|
-
</div>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
interface SettingsSnapshot {
|
|
116
|
-
status: "loading" | "ready" | "unavailable";
|
|
117
|
-
value?: { defaultShell?: string };
|
|
118
|
-
revision: number | undefined;
|
|
119
|
-
writable: boolean;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
interface ConfigFormBinding {
|
|
123
|
-
getSnapshot(): SettingsSnapshot;
|
|
124
|
-
subscribe(fn: () => void): () => void;
|
|
125
|
-
set(field: string, value: string): Promise<boolean>;
|
|
126
|
-
unset(field: string): Promise<boolean>;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
interface ClientContext {
|
|
130
|
-
effect(fn: () => unknown, name?: string): unknown;
|
|
131
|
-
locale: { register(ns: string, dicts: Record<string, Record<string, string>>): unknown };
|
|
132
|
-
configForms: { get(entryId: string): ConfigFormBinding };
|
|
133
|
-
slots: {
|
|
134
|
-
inject(slot: string, fn: () => unknown, name?: string): void;
|
|
135
|
-
register(options: Record<string, unknown>, Component: unknown): Record<string, unknown>;
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
interface RowStoreActions {
|
|
140
|
-
sync(shell?: string, revision?: number, writable?: boolean): void;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
interface RowStore {
|
|
144
|
-
actions: RowStoreActions;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (
|
|
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
|
-
}
|
|
1
|
+
// dsh-bash-terminal 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
|
+
type ShellOption = (typeof SHELLS)[number];
|
|
24
|
+
|
|
25
|
+
// Injected once when the browser loads the bundle (node tests guard on document).
|
|
26
|
+
const ROW_CSS =
|
|
27
|
+
".btRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}" +
|
|
28
|
+
".btRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}" +
|
|
29
|
+
".btTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}" +
|
|
30
|
+
".btDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}" +
|
|
31
|
+
".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}" +
|
|
32
|
+
".btSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}" +
|
|
33
|
+
".btChevron{flex:none}";
|
|
34
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"bash-terminal-row\"]") === null) {
|
|
35
|
+
const tag = document.createElement("style");
|
|
36
|
+
tag.dataset.plugin = "dsh-bash-terminal";
|
|
37
|
+
tag.dataset.pluginCss = "bash-terminal-row";
|
|
38
|
+
tag.textContent = ROW_CSS;
|
|
39
|
+
document.head.appendChild(tag);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const zh: Record<string, string> = {
|
|
43
|
+
"shell.title": "默认终端",
|
|
44
|
+
"shell.description": "shell 工具执行命令时使用的终端",
|
|
45
|
+
"shell.powershell": "PowerShell",
|
|
46
|
+
"shell.gitbash": "Git Bash",
|
|
47
|
+
"shell.msys2": "MSYS2",
|
|
48
|
+
"shell.wsl": "WSL"
|
|
49
|
+
};
|
|
50
|
+
const en: Record<string, string> = {
|
|
51
|
+
"shell.title": "Default terminal",
|
|
52
|
+
"shell.description": "Terminal used by the shell tool",
|
|
53
|
+
"shell.powershell": "PowerShell",
|
|
54
|
+
"shell.gitbash": "Git Bash",
|
|
55
|
+
"shell.msys2": "MSYS2",
|
|
56
|
+
"shell.wsl": "WSL"
|
|
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
|
+
}
|
|
67
|
+
|
|
68
|
+
interface ShellPreferenceRowProps {
|
|
69
|
+
t: (key: string) => string;
|
|
70
|
+
useStore: <S>(selector: (state: RowState) => S) => S;
|
|
71
|
+
setShell: (id: string) => void;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function ShellPreferenceRow({ t, useStore, setShell }: ShellPreferenceRowProps) {
|
|
75
|
+
const shell = useStore((s) => s.shell);
|
|
76
|
+
const writable = useStore((s) => s.writable);
|
|
77
|
+
const [open, setOpen] = useState(false);
|
|
78
|
+
const items = SHELLS.map((id) => ({ id, label: t("shell." + id) }));
|
|
79
|
+
return (
|
|
80
|
+
<div className="btRow">
|
|
81
|
+
<div className="btRowText">
|
|
82
|
+
<div className="btTitle">{t("shell.title")}</div>
|
|
83
|
+
<div className="btDesc">{t("shell.description")}</div>
|
|
84
|
+
</div>
|
|
85
|
+
<Menu
|
|
86
|
+
open={open}
|
|
87
|
+
onClose={() => setOpen(false)}
|
|
88
|
+
items={items}
|
|
89
|
+
selectedId={shell}
|
|
90
|
+
onSelect={(id) => {
|
|
91
|
+
setOpen(false);
|
|
92
|
+
setShell(id);
|
|
93
|
+
}}
|
|
94
|
+
align="end"
|
|
95
|
+
portal
|
|
96
|
+
anchor={
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
className="btSelector"
|
|
100
|
+
aria-haspopup="menu"
|
|
101
|
+
aria-expanded={open}
|
|
102
|
+
disabled={!writable}
|
|
103
|
+
onClick={() => setOpen(!open)}
|
|
104
|
+
style={!writable ? { opacity: 0.5, cursor: "not-allowed" } : undefined}
|
|
105
|
+
>
|
|
106
|
+
{t("shell." + shell)}
|
|
107
|
+
<IconChevronDownOutlineMedium className="btChevron" />
|
|
108
|
+
</button>
|
|
109
|
+
}
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface SettingsSnapshot {
|
|
116
|
+
status: "loading" | "ready" | "unavailable";
|
|
117
|
+
value?: { defaultShell?: string };
|
|
118
|
+
revision: number | undefined;
|
|
119
|
+
writable: boolean;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
interface ConfigFormBinding {
|
|
123
|
+
getSnapshot(): SettingsSnapshot;
|
|
124
|
+
subscribe(fn: () => void): () => void;
|
|
125
|
+
set(field: string, value: string): Promise<boolean>;
|
|
126
|
+
unset(field: string): Promise<boolean>;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface ClientContext {
|
|
130
|
+
effect(fn: () => unknown, name?: string): unknown;
|
|
131
|
+
locale: { register(ns: string, dicts: Record<string, Record<string, string>>): unknown };
|
|
132
|
+
configForms: { get(entryId: string): ConfigFormBinding };
|
|
133
|
+
slots: {
|
|
134
|
+
inject(slot: string, fn: () => unknown, name?: string): void;
|
|
135
|
+
register(options: Record<string, unknown>, Component: unknown): Record<string, unknown>;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface RowStoreActions {
|
|
140
|
+
sync(shell?: string, revision?: number, writable?: boolean): void;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
interface RowStore {
|
|
144
|
+
actions: RowStoreActions;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** 账本 label:从 zh/en 字典取「默认终端」标题(无宿主 locale 依赖)。 */
|
|
148
|
+
const zhDictTitle = (): string => (zh as Record<string, string>)["shell.title"] ?? "终端";
|
|
149
|
+
|
|
150
|
+
export function apply(ctx: ClientContext): void {
|
|
151
|
+
ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
|
|
152
|
+
const scope = ctx.configForms.get(ENTRY_ID);
|
|
153
|
+
const store = defineStore<RowState, { sync: (draft: RowState, shell?: string, revision?: number, writable?: boolean) => void }>({
|
|
154
|
+
init: (): RowState => ({ shell: "powershell", revision: -1, writable: false }),
|
|
155
|
+
actions: {
|
|
156
|
+
sync: (d, shell, revision, writable) => {
|
|
157
|
+
if (revision !== undefined && revision <= d.revision) return;
|
|
158
|
+
if (shell !== undefined) d.shell = shell;
|
|
159
|
+
if (revision !== undefined) d.revision = revision;
|
|
160
|
+
if (writable !== undefined) d.writable = writable;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
let bound: RowStoreActions | undefined;
|
|
165
|
+
const push = (snap: SettingsSnapshot): void => {
|
|
166
|
+
bound?.sync(snap.value?.defaultShell, snap.revision, snap.writable);
|
|
167
|
+
};
|
|
168
|
+
// 插件族共用设置 tab(dsh-thinking-levels 顶级「起子插件设置」节声明该子席位)。
|
|
169
|
+
// thinking-levels 缺席时本 inject 静默等待,不阻塞客户端半。
|
|
170
|
+
ctx.slots.inject(
|
|
171
|
+
"dsh-family.tab",
|
|
172
|
+
() =>
|
|
173
|
+
ctx.slots.register(
|
|
174
|
+
{
|
|
175
|
+
name: "dsh-family.tab",
|
|
176
|
+
id: "bash-terminal-shell",
|
|
177
|
+
order: 60,
|
|
178
|
+
label: () => zhDictTitle(),
|
|
179
|
+
store,
|
|
180
|
+
locale: SETTINGS_NS,
|
|
181
|
+
inject: (actions: unknown) => {
|
|
182
|
+
bound = actions as RowStoreActions;
|
|
183
|
+
push(scope.getSnapshot());
|
|
184
|
+
return { setShell: (value: string) => void scope.set("defaultShell", value) };
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
ShellPreferenceRow
|
|
188
|
+
),
|
|
189
|
+
"bash-terminal: settings row"
|
|
190
|
+
);
|
|
191
|
+
ctx.effect(() => scope.subscribe(() => push(scope.getSnapshot())), "bash-terminal: settings watch");
|
|
192
|
+
}
|