dsh-bash-terminal-ts 0.4.0 → 0.6.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/package.json CHANGED
@@ -1,137 +1,115 @@
1
- {
2
- "name": "dsh-bash-terminal-ts",
3
- "version": "0.4.0",
4
- "publishConfig": {
5
- "registry": "https://registry.npmjs.org",
6
- "access": "public",
7
- "tag": "dsh-0.1.2"
8
- },
9
- "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.",
10
- "author": "drscrewdriver",
11
- "contributors": [
12
- "MAXeaglet (original dsh-bash-terminal)"
13
- ],
14
- "license": "MIT",
15
- "repository": {
16
- "type": "git",
17
- "url": "git+https://github.com/drscrewdriver/dsh-bash-terminal-ts.git"
18
- },
19
- "bugs": {
20
- "url": "https://github.com/drscrewdriver/dsh-bash-terminal-ts/issues"
21
- },
22
- "homepage": "https://github.com/drscrewdriver/dsh-bash-terminal-ts#readme",
23
- "keywords": [
24
- "deepseek-harness",
25
- "dsh",
26
- "plugin",
27
- "terminal",
28
- "shell",
29
- "powershell",
30
- "git-bash",
31
- "msys2",
32
- "mingw64",
33
- "wsl",
34
- "windows",
35
- "typescript"
36
- ],
37
- "engines": {
38
- "node": ">=22",
39
- "dsh": ">=0.1.2-rc.1 <0.2.0-0"
40
- },
41
- "type": "module",
42
- "main": "lib/index.js",
43
- "exports": {
44
- ".": "./lib/index.js",
45
- "./client": "./dist/client.js",
46
- "./package.json": "./package.json"
47
- },
48
- "files": [
49
- "lib",
50
- "dist",
51
- "src",
52
- "scripts",
53
- "tsconfig.json",
54
- "tsconfig.client.json",
55
- "tsconfig.test.json",
56
- "README.md",
57
- "README.en.md",
58
- "README.ja.md",
59
- "README.ko.md",
60
- "LICENSE",
61
- "cordis.patch.yml",
62
- "dsh.plugin.json"
63
- ],
64
- "scripts": {
65
- "build": "tsc -p tsconfig.json && tsc -p tsconfig.client.json && node scripts/build-client.mjs && tsc -p tsconfig.test.json",
66
- "build:client": "node scripts/build-client.mjs",
67
- "test": "node test-dist/unit.js && node test-dist/apply.js && node test-dist/client.js"
68
- },
69
- "dsh": {
70
- "bundle": {
71
- "patch": "./cordis.patch.yml"
72
- },
73
- "client": {
74
- "platform": "web",
75
- "immediately": true,
76
- "inject": [
77
- "@deepseek-ai/dsh-client-store",
78
- "@deepseek-ai/dsh-client-locale",
79
- "@deepseek-ai/dsh-client-ui-settings",
80
- "@deepseek-ai/dsh-client-ui-slots"
81
- ]
82
- }
83
- },
84
- "peerDependencies": {
85
- "@deepseek-ai/cordis": "^4.0.2",
86
- "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
87
- "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
88
- "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
89
- "@deepseek-ai/dsh-shell": "^0.1.2-rc.1",
90
- "@deepseek-ai/dsh-timeout": "^0.1.2-rc.1",
91
- "@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
92
- "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
93
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1",
94
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
95
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
96
- "@deepseek-ai/dsh-sandbox": "^0.1.2-rc.1",
97
- "react": "^18.2.0"
98
- },
99
- "peerDependenciesMeta": {
100
- "@deepseek-ai/cordis": { "optional": true },
101
- "@deepseek-ai/dsh-tools": { "optional": true },
102
- "@deepseek-ai/dsh-settings": { "optional": true },
103
- "@deepseek-ai/dsh-llm": { "optional": true },
104
- "@deepseek-ai/dsh-shell": { "optional": true },
105
- "@deepseek-ai/dsh-timeout": { "optional": true },
106
- "@deepseek-ai/dsh-client-store": { "optional": true },
107
- "@deepseek-ai/dsh-client-locale": { "optional": true },
108
- "@deepseek-ai/dsh-client-ui-settings": { "optional": true },
109
- "@deepseek-ai/dsh-client-ui-slots": { "optional": true },
110
- "@deepseek-ai/dsh-client-ui-primitives": { "optional": true },
111
- "@deepseek-ai/dsh-sandbox": { "optional": true },
112
- "react": { "optional": true }
113
- },
114
- "dependencies": {
115
- "@deepseek-ai/schemastery": "^3.18.1"
116
- },
117
- "devDependencies": {
118
- "@deepseek-ai/cordis": "^4.0.2",
119
- "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
120
- "@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
121
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
122
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1",
123
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
124
- "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
125
- "@deepseek-ai/dsh-sandbox": "^0.1.2-rc.1",
126
- "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
127
- "@deepseek-ai/dsh-shell": "^0.1.2-rc.1",
128
- "@deepseek-ai/dsh-timeout": "^0.1.2-rc.1",
129
- "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
130
- "@types/node": "^24.13.4",
131
- "@types/react": "^18.2.0",
132
- "@types/react-dom": "^18.2.0",
133
- "esbuild": "^0.28.2",
134
- "react": "^18.2.0",
135
- "typescript": "^5.9.0"
136
- }
137
- }
1
+ {
2
+ "name": "dsh-bash-terminal-ts",
3
+ "version": "0.6.0",
4
+ "publishConfig": {
5
+ "tag": "dsh-0.1.7"
6
+ },
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
+ "author": "drscrewdriver",
9
+ "license": "MIT",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/drscrewdriver/dsh-bash-terminal-ts.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/drscrewdriver/dsh-bash-terminal-ts/issues"
16
+ },
17
+ "homepage": "https://github.com/drscrewdriver/dsh-bash-terminal-ts#readme",
18
+ "keywords": [
19
+ "deepseek-harness",
20
+ "dsh",
21
+ "plugin",
22
+ "terminal",
23
+ "shell",
24
+ "powershell",
25
+ "git-bash",
26
+ "wsl",
27
+ "windows",
28
+ "typescript"
29
+ ],
30
+ "engines": {
31
+ "node": ">=22",
32
+ "dsh": ">=0.1.7-rc.1 <0.2.0-0"
33
+ },
34
+ "type": "module",
35
+ "main": "lib/index.js",
36
+ "exports": {
37
+ ".": "./lib/index.js",
38
+ "./client": "./lib/client.js",
39
+ "./package.json": "./package.json"
40
+ },
41
+ "files": [
42
+ "lib",
43
+ "dist",
44
+ "src",
45
+ "scripts",
46
+ "template",
47
+ "tsconfig.json",
48
+ "tsconfig.client.json",
49
+ "tsconfig.test.json",
50
+ "README.md",
51
+ "LICENSE",
52
+ "cordis.patch.yml",
53
+ "dsh.plugin.json",
54
+ "screenshots.json"
55
+ ],
56
+ "scripts": {
57
+ "build": "tsc -p tsconfig.json && tsc -p tsconfig.client.json && node scripts/build-client.mjs && tsc -p tsconfig.test.json",
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"
60
+ },
61
+ "dsh": {
62
+ "bundle": {
63
+ "patch": "./cordis.patch.yml"
64
+ },
65
+ "client": {
66
+ "platform": "web",
67
+ "immediately": true,
68
+ "inject": [
69
+ "@deepseek-ai/dsh-client-locale",
70
+ "@deepseek-ai/dsh-client-ui-settings",
71
+ "@deepseek-ai/dsh-api-remotes"
72
+ ]
73
+ }
74
+ },
75
+ "peerDependencies": {
76
+ "@deepseek-ai/cordis": "^4.0.2",
77
+ "@deepseek-ai/dsh-tools": ">=0.1.7-rc.1 <0.2.0-0",
78
+ "@deepseek-ai/dsh-settings": ">=0.1.7-rc.1 <0.2.0-0",
79
+ "@deepseek-ai/dsh-llm": ">=0.1.7-rc.1 <0.2.0-0",
80
+ "@deepseek-ai/dsh-shell": ">=0.1.7-rc.1 <0.2.0-0",
81
+ "@deepseek-ai/dsh-sandbox": ">=0.1.7-rc.1 <0.2.0-0",
82
+ "@deepseek-ai/dsh-timeout": ">=0.1.7-rc.1 <0.2.0-0",
83
+ "@deepseek-ai/dsh-client-store": ">=0.1.7-rc.1 <0.2.0-0",
84
+ "@deepseek-ai/dsh-client-locale": ">=0.1.7-rc.1 <0.2.0-0",
85
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.1 <0.2.0-0",
86
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-rc.1 <0.2.0-0",
87
+ "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-rc.1 <0.2.0-0",
88
+ "react": "^18.2.0"
89
+ },
90
+ "dependencies": {
91
+ "@deepseek-ai/schemastery": "^3.18.4",
92
+ "node-pty": "^1.1.0"
93
+ },
94
+ "devDependencies": {
95
+ "@deepseek-ai/cordis": "^4.0.2",
96
+ "@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
97
+ "@deepseek-ai/dsh-client-store": "0.1.5-rc.2",
98
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.5-rc.2",
99
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
100
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
101
+ "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
102
+ "@deepseek-ai/dsh-sandbox": "0.1.5-rc.2",
103
+ "@deepseek-ai/dsh-settings": "0.1.5-rc.2",
104
+ "@deepseek-ai/dsh-shell": "0.1.5-rc.2",
105
+ "@deepseek-ai/dsh-timeout": "0.1.5-rc.2",
106
+ "@deepseek-ai/dsh-tools": "0.1.5-rc.2",
107
+ "@types/node": "^22.10.0",
108
+ "@types/react": "^18.2.0",
109
+ "@types/react-dom": "^18.2.0",
110
+ "esbuild": "^0.28.2",
111
+ "react": "^18.2.0",
112
+ "react-dom": "^18.2.0",
113
+ "typescript": "^5.9.0"
114
+ }
115
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "screenshots": [
3
+ "assets/shells.png"
4
+ ]
5
+ }
@@ -1,7 +1,8 @@
1
- // Build the browser client bundle for dsh-bash-terminal-ts.
2
- // Output: dist/client.js — a __ModuleLoader__.load({ id, factory }) wrapper
3
- // around the esbuild CJS bundle; shared deps (react, @deepseek-ai/*) resolve
4
- // through the loader's require.
1
+ // Build the browser client bundle for dsh-bash-terminal.
2
+ // Output: lib/client.js (primary, consumed by DSH loader/reload precheck) and
3
+ // dist/client.js (legacy compatibility) — a __ModuleLoader__.load({ id, factory })
4
+ // wrapper around the esbuild CJS bundle; shared deps (react, @deepseek-ai/*)
5
+ // resolve through the loader's require.
5
6
 
6
7
  import { build } from "esbuild";
7
8
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
@@ -10,6 +11,7 @@ import { dirname, join } from "node:path";
10
11
 
11
12
  const root = dirname(dirname(fileURLToPath(import.meta.url)));
12
13
  mkdirSync(join(root, "dist"), { recursive: true });
14
+ mkdirSync(join(root, "lib"), { recursive: true });
13
15
 
14
16
  await build({
15
17
  entryPoints: [join(root, "src", "client.tsx")],
@@ -20,20 +22,18 @@ await build({
20
22
  external: ["react", "react/jsx-runtime", "react-dom", "@deepseek-ai/*"],
21
23
  jsx: "automatic",
22
24
  // Pin the TS options instead of letting esbuild discover a tsconfig by walking
23
- // up from the entry point. The repo root has a tsconfig.json, so in-repo builds
24
- // silently inherited it and emitted a leading "use strict"; while a byte-for-byte
25
- // identical build from a worktree outside the repo (no tsconfig above it) did not
26
- // — same source, two different committed artifacts. These values are what the
27
- // root tsconfig actually supplied. The one observable delta is that stray
28
- // "use strict"; (inert: the core is wrapped in a function expression by the
29
- // loader shim below, so it was never a directive prologue), now gone everywhere.
25
+ // up from the entry point: an in-repo build found the repo-root tsconfig.json
26
+ // (emitting a leading "use strict";) while the same source built from an
27
+ // out-of-repo worktree did not — two different committed artifacts for one
28
+ // source. These are the values that tsconfig actually supplied, so behavior is
29
+ // unchanged; only the stray line disappears.
30
30
  tsconfigRaw: { compilerOptions: { target: "ES2022", useDefineForClassFields: true } },
31
31
  logLevel: "warning"
32
32
  });
33
33
 
34
34
  const core = readFileSync(join(root, "dist", "client.core.js"), "utf8");
35
35
  const wrapper = `window.__ModuleLoader__.load({
36
- id: "dsh-bash-terminal-ts",
36
+ id: "dsh-bash-terminal",
37
37
  factory: (require) => {
38
38
  var module = { exports: {} };
39
39
  var exports = module.exports;
@@ -42,5 +42,6 @@ ${core}
42
42
  }
43
43
  });
44
44
  `;
45
+ writeFileSync(join(root, "lib", "client.js"), wrapper);
45
46
  writeFileSync(join(root, "dist", "client.js"), wrapper);
46
- console.log("built dist/client.js (" + wrapper.length + " bytes)");
47
+ console.log("built lib/client.js + dist/client.js (" + wrapper.length + " bytes)");
package/src/client.tsx CHANGED
@@ -1,20 +1,47 @@
1
- // dsh-bash-terminal-ts client plugin: a "Default terminal" preference row in the
2
- // Web UI General settings. The user picks powershell / gitbash / msys2 / wsl;
3
- // the host shell tool obeys that choice (the model cannot change it).
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
4
  //
5
- // The option list below must stay in lockstep with SHELLS in ./index.ts: every
6
- // id gets an <option> here and a `shell.<id>` entry in both dictionaries. The
7
- // shipped bundle cannot import the host module (it pulls node: builtins), so
8
- // test/client.ts asserts the bundle covers every host shell id instead.
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.
9
13
 
14
+ import { useState } from "react";
10
15
  import { defineStore } from "@deepseek-ai/dsh-client-store";
16
+ import { IconChevronDownOutline14, Menu } from "@deepseek-ai/dsh-client-ui-primitives";
11
17
 
12
18
  const SETTINGS_NS = "settings.bash-terminal";
13
- const SETTINGS_NAMESPACE = "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
+ }
14
41
 
15
42
  const zh: Record<string, string> = {
16
43
  "shell.title": "默认终端",
17
- "shell.description": "shell 工具执行命令时使用的终端(由你决定,AI 无法更改)",
44
+ "shell.description": "shell 工具执行命令时使用的终端",
18
45
  "shell.powershell": "PowerShell",
19
46
  "shell.gitbash": "Git Bash",
20
47
  "shell.msys2": "MSYS2",
@@ -22,14 +49,14 @@ const zh: Record<string, string> = {
22
49
  };
23
50
  const en: Record<string, string> = {
24
51
  "shell.title": "Default terminal",
25
- "shell.description": "Terminal used by the shell tool (you control this; the AI cannot change it)",
52
+ "shell.description": "Terminal used by the shell tool",
26
53
  "shell.powershell": "PowerShell",
27
54
  "shell.gitbash": "Git Bash",
28
55
  "shell.msys2": "MSYS2",
29
56
  "shell.wsl": "WSL"
30
57
  };
31
58
 
32
- export const inject = ["slots", "locale", "settingsScope"];
59
+ export const inject = ["slots", "locale", "configForms"];
33
60
 
34
61
  /** Row state snapshot served through the settings store. */
35
62
  interface RowState {
@@ -47,65 +74,62 @@ interface ShellPreferenceRowProps {
47
74
  function ShellPreferenceRow({ t, useStore, setShell }: ShellPreferenceRowProps) {
48
75
  const shell = useStore((s) => s.shell);
49
76
  const writable = useStore((s) => s.writable);
77
+ const [open, setOpen] = useState(false);
78
+ const items = SHELLS.map((id) => ({ id, label: t("shell." + id) }));
50
79
  return (
51
- <div
52
- style={{
53
- display: "flex",
54
- alignItems: "center",
55
- justifyContent: "space-between",
56
- gap: 16,
57
- padding: "12px 0"
58
- }}
59
- >
60
- <div style={{ minWidth: 0 }}>
61
- <div style={{ fontSize: 14, fontWeight: 500, lineHeight: "22px", color: "var(--dsw-alias-label-primary, inherit)" }}>
62
- {t("shell.title")}
63
- </div>
64
- <div style={{ fontSize: 12, lineHeight: "18px", opacity: 0.65 }}>{t("shell.description")}</div>
80
+ <div className="btRow">
81
+ <div className="btRowText">
82
+ <div className="btTitle">{t("shell.title")}</div>
83
+ <div className="btDesc">{t("shell.description")}</div>
65
84
  </div>
66
- <select
67
- value={shell}
68
- disabled={!writable}
69
- onChange={(e) => setShell(e.target.value)}
70
- style={{
71
- fontSize: 14,
72
- padding: "6px 10px",
73
- borderRadius: 8,
74
- border: "1px solid var(--dsw-alias-line-strong, #ccc)",
75
- background: "var(--dsw-alias-bg-layer-2, #fff)",
76
- color: "var(--dsw-alias-label-primary, inherit)",
77
- outline: "none",
78
- cursor: writable ? "pointer" : "not-allowed",
79
- maxWidth: 180
85
+ <Menu
86
+ open={open}
87
+ onClose={() => setOpen(false)}
88
+ items={items}
89
+ selectedId={shell}
90
+ onSelect={(id) => {
91
+ setOpen(false);
92
+ setShell(id);
80
93
  }}
81
- >
82
- <option value="powershell">{t("shell.powershell")}</option>
83
- <option value="gitbash">{t("shell.gitbash")}</option>
84
- <option value="msys2">{t("shell.msys2")}</option>
85
- <option value="wsl">{t("shell.wsl")}</option>
86
- </select>
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
+ <IconChevronDownOutline14 className="btChevron" />
108
+ </button>
109
+ }
110
+ />
87
111
  </div>
88
112
  );
89
113
  }
90
114
 
91
115
  interface SettingsSnapshot {
92
- status: string;
116
+ status: "loading" | "ready" | "unavailable";
93
117
  value?: { defaultShell?: string };
94
- revision: number;
118
+ revision: number | undefined;
95
119
  writable: boolean;
96
120
  }
97
121
 
98
- interface SettingsScopeBinding {
122
+ interface ConfigFormBinding {
99
123
  getSnapshot(): SettingsSnapshot;
100
124
  subscribe(fn: () => void): () => void;
101
- set(field: string, value: string): void;
102
- unset(): void;
125
+ set(field: string, value: string): Promise<boolean>;
126
+ unset(field: string): Promise<boolean>;
103
127
  }
104
128
 
105
129
  interface ClientContext {
106
130
  effect(fn: () => unknown, name?: string): unknown;
107
131
  locale: { register(ns: string, dicts: Record<string, Record<string, string>>): unknown };
108
- settingsScope: { bind(options: { namespace: string }): SettingsScopeBinding };
132
+ configForms: { get(entryId: string): ConfigFormBinding };
109
133
  slots: {
110
134
  inject(slot: string, fn: () => unknown, name?: string): void;
111
135
  register(options: Record<string, unknown>, Component: unknown): Record<string, unknown>;
@@ -116,9 +140,13 @@ interface RowStoreActions {
116
140
  sync(shell?: string, revision?: number, writable?: boolean): void;
117
141
  }
118
142
 
143
+ interface RowStore {
144
+ actions: RowStoreActions;
145
+ }
146
+
119
147
  export function apply(ctx: ClientContext): void {
120
148
  ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
121
- const scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
149
+ const scope = ctx.configForms.get(ENTRY_ID);
122
150
  const store = defineStore<RowState, { sync: (draft: RowState, shell?: string, revision?: number, writable?: boolean) => void }>({
123
151
  init: (): RowState => ({ shell: "powershell", revision: -1, writable: false }),
124
152
  actions: {
@@ -130,9 +158,6 @@ export function apply(ctx: ClientContext): void {
130
158
  }
131
159
  }
132
160
  });
133
- // defineStore() yields a { spec, create } factory; slots.register creates
134
- // the live store, so we bind the actions in the inject callback and push
135
- // the initial snapshot there too (mirrors the theme row pattern).
136
161
  let bound: RowStoreActions | undefined;
137
162
  const push = (snap: SettingsSnapshot): void => {
138
163
  bound?.sync(snap.value?.defaultShell, snap.revision, snap.writable);
package/src/dsh-types.ts CHANGED
@@ -294,7 +294,7 @@ export interface ApprovalSeam {
294
294
  // ---- plugin context (server side) ----------------------------------------------
295
295
 
296
296
  /**
297
- * The structural context face dsh-bash-terminal-ts programs against: the union
297
+ * The structural context face dsh-bash-terminal programs against: the union
298
298
  * of every `ctx.*` member touched by src/index.ts and src/terminal.ts.
299
299
  */
300
300
  export interface BashTerminalContext {
@@ -303,7 +303,6 @@ export interface BashTerminalContext {
303
303
  tools: ToolsSeam;
304
304
  on(event: "system-prompt/assemble", handler: AssembleHandler): void;
305
305
  shellEnv: ShellEnvSeam;
306
- settings: SettingsSeam;
307
306
  sandboxPolicy: SandboxPolicySeam;
308
307
  sandbox: SandboxSeam;
309
308
  get(key: string): unknown;
package/src/dsh.ts CHANGED
@@ -52,6 +52,8 @@ export const escalationHintMarker = sandboxNs.escalationHintMarker as unknown as
52
52
  /** Runtime config schema factory (schemastery fork). */
53
53
  export interface SchemasterySchema {
54
54
  default(value: unknown): SchemasterySchema;
55
+ /** 0.1.7+: expose the field on the auto-generated settings form. */
56
+ volatile(): SchemasterySchema;
55
57
  }
56
58
 
57
59
  export interface Schemastery {