dsh-bash-terminal-ts 0.5.1 → 0.6.1

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.
@@ -28,7 +28,7 @@ var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
28
28
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
29
29
  var import_jsx_runtime = require("react/jsx-runtime");
30
30
  var SETTINGS_NS = "settings.bash-terminal";
31
- var SETTINGS_NAMESPACE = "bash-terminal";
31
+ var ENTRY_ID = "tool-bash-terminal";
32
32
  var SHELLS = ["powershell", "gitbash", "msys2", "wsl"];
33
33
  var ROW_CSS = ".btRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}.btRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}.btTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}.btDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.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}.btSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}.btChevron{flex:none}";
34
34
  if (typeof document !== "undefined" && document.querySelector('style[data-plugin-css="bash-terminal-row"]') === null) {
@@ -54,7 +54,7 @@ var en = {
54
54
  "shell.msys2": "MSYS2",
55
55
  "shell.wsl": "WSL"
56
56
  };
57
- var inject = ["slots", "locale", "settingsScope"];
57
+ var inject = ["slots", "locale", "configForms"];
58
58
  function ShellPreferenceRow({ t, useStore, setShell }) {
59
59
  const shell = useStore((s) => s.shell);
60
60
  const writable = useStore((s) => s.writable);
@@ -100,7 +100,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
100
100
  }
101
101
  function apply(ctx) {
102
102
  ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
103
- const scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
103
+ const scope = ctx.configForms.get(ENTRY_ID);
104
104
  const store = (0, import_dsh_client_store.defineStore)({
105
105
  init: () => ({ shell: "powershell", revision: -1, writable: false }),
106
106
  actions: {
package/dist/client.js CHANGED
@@ -33,7 +33,7 @@ var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
33
33
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
34
34
  var import_jsx_runtime = require("react/jsx-runtime");
35
35
  var SETTINGS_NS = "settings.bash-terminal";
36
- var SETTINGS_NAMESPACE = "bash-terminal";
36
+ var ENTRY_ID = "tool-bash-terminal";
37
37
  var SHELLS = ["powershell", "gitbash", "msys2", "wsl"];
38
38
  var ROW_CSS = ".btRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}.btRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}.btTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}.btDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.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}.btSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}.btChevron{flex:none}";
39
39
  if (typeof document !== "undefined" && document.querySelector('style[data-plugin-css="bash-terminal-row"]') === null) {
@@ -59,7 +59,7 @@ var en = {
59
59
  "shell.msys2": "MSYS2",
60
60
  "shell.wsl": "WSL"
61
61
  };
62
- var inject = ["slots", "locale", "settingsScope"];
62
+ var inject = ["slots", "locale", "configForms"];
63
63
  function ShellPreferenceRow({ t, useStore, setShell }) {
64
64
  const shell = useStore((s) => s.shell);
65
65
  const writable = useStore((s) => s.writable);
@@ -105,7 +105,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
105
105
  }
106
106
  function apply(ctx) {
107
107
  ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
108
- const scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
108
+ const scope = ctx.configForms.get(ENTRY_ID);
109
109
  const store = (0, import_dsh_client_store.defineStore)({
110
110
  init: () => ({ shell: "powershell", revision: -1, writable: false }),
111
111
  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.5.1",
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.5-rc.1 <0.1.6-0"
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
@@ -33,7 +33,7 @@ var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
33
33
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
34
34
  var import_jsx_runtime = require("react/jsx-runtime");
35
35
  var SETTINGS_NS = "settings.bash-terminal";
36
- var SETTINGS_NAMESPACE = "bash-terminal";
36
+ var ENTRY_ID = "tool-bash-terminal";
37
37
  var SHELLS = ["powershell", "gitbash", "msys2", "wsl"];
38
38
  var ROW_CSS = ".btRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}.btRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}.btTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}.btDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.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}.btSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}.btChevron{flex:none}";
39
39
  if (typeof document !== "undefined" && document.querySelector('style[data-plugin-css="bash-terminal-row"]') === null) {
@@ -59,7 +59,7 @@ var en = {
59
59
  "shell.msys2": "MSYS2",
60
60
  "shell.wsl": "WSL"
61
61
  };
62
- var inject = ["slots", "locale", "settingsScope"];
62
+ var inject = ["slots", "locale", "configForms"];
63
63
  function ShellPreferenceRow({ t, useStore, setShell }) {
64
64
  const shell = useStore((s) => s.shell);
65
65
  const writable = useStore((s) => s.writable);
@@ -105,7 +105,7 @@ function ShellPreferenceRow({ t, useStore, setShell }) {
105
105
  }
106
106
  function apply(ctx) {
107
107
  ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
108
- const scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
108
+ const scope = ctx.configForms.get(ENTRY_ID);
109
109
  const store = (0, import_dsh_client_store.defineStore)({
110
110
  init: () => ({ shell: "powershell", revision: -1, writable: false }),
111
111
  actions: {
@@ -250,7 +250,6 @@ export interface BashTerminalContext {
250
250
  tools: ToolsSeam;
251
251
  on(event: "system-prompt/assemble", handler: AssembleHandler): void;
252
252
  shellEnv: ShellEnvSeam;
253
- settings: SettingsSeam;
254
253
  sandboxPolicy: SandboxPolicySeam;
255
254
  sandbox: SandboxSeam;
256
255
  get(key: string): unknown;
package/lib/dsh.d.ts CHANGED
@@ -20,6 +20,8 @@ export declare const escalationHintMarker: (subject: string) => string;
20
20
  /** Runtime config schema factory (schemastery fork). */
21
21
  export interface SchemasterySchema {
22
22
  default(value: unknown): SchemasterySchema;
23
+ /** 0.1.7+: expose the field on the auto-generated settings form. */
24
+ volatile(): SchemasterySchema;
23
25
  }
24
26
  export interface Schemastery {
25
27
  object(fields: Record<string, SchemasterySchema>): SchemasterySchema;
package/lib/index.d.ts CHANGED
@@ -7,8 +7,6 @@ export declare const inject: string[];
7
7
  export declare const SHELLS: readonly ["powershell", "gitbash", "msys2", "wsl"];
8
8
  /** The backend used when the caller does not name one. */
9
9
  export declare const DEFAULT_SHELL: ShellId;
10
- /** Settings namespace backing the user-chosen default terminal. */
11
- export declare const SETTINGS_NAMESPACE = "bash-terminal";
12
10
  /** Static shape of the runtime configuration schema. */
13
11
  export interface ConfigValues {
14
12
  defaultShell: string;
package/lib/index.js CHANGED
@@ -33,8 +33,6 @@ export const inject = ["tools", "systemPrompt", "shellEnv", "subprocess", "setti
33
33
  export const SHELLS = ["powershell", "gitbash", "msys2", "wsl"];
34
34
  /** The backend used when the caller does not name one. */
35
35
  export const DEFAULT_SHELL = "powershell";
36
- /** Settings namespace backing the user-chosen default terminal. */
37
- export const SETTINGS_NAMESPACE = "bash-terminal";
38
36
  /** Default per-command timeout (ms). */
39
37
  const DEFAULT_TIMEOUT_MS = 120000;
40
38
  /** Upper bound a caller's timeoutMs is capped to. */
@@ -56,7 +54,7 @@ const ENV_OVERRIDES = {
56
54
  };
57
55
  /** Runtime configuration schema. */
58
56
  export const Config = z.object({
59
- defaultShell: z.string().default(DEFAULT_SHELL),
57
+ defaultShell: z.string().default(DEFAULT_SHELL).volatile(),
60
58
  timeoutMs: z.number().default(DEFAULT_TIMEOUT_MS),
61
59
  maxTimeoutMs: z.number().default(MAX_TIMEOUT_MS),
62
60
  pwshPath: z.string().default(""),
@@ -500,11 +498,19 @@ export function apply(ctx, config = {}) {
500
498
  }
501
499
  const backgroundEnabled = true;
502
500
  const paths = resolveAllPaths(config);
503
- const defaultShell = config.defaultShell ?? DEFAULT_SHELL;
504
- if (!SHELLS.includes(defaultShell)) {
505
- throw new Error(`dsh-bash-terminal: invalid defaultShell ${JSON.stringify(defaultShell)}`);
501
+ // 0.1.7: `defaultShell` is a `.volatile()` config field — the loader hands
502
+ // `apply` a live ref and the latest value is resolved on every read; there
503
+ // is no settings registration call anymore (removed with the 0.1.7 host).
504
+ const currentShell = () => {
505
+ const v = config.defaultShell;
506
+ if (typeof v === "string")
507
+ return v;
508
+ const got = typeof v?.get === "function" ? v.get() : undefined;
509
+ return typeof got === "string" ? got : DEFAULT_SHELL;
510
+ };
511
+ if (!SHELLS.includes(currentShell())) {
512
+ throw new Error(`dsh-bash-terminal: invalid defaultShell ${JSON.stringify(currentShell())}`);
506
513
  }
507
- const settingsScope = ctx.settings.register(SETTINGS_NAMESPACE, z.object({ defaultShell: z.union(SHELLS.map((s) => z.const(s))).default(defaultShell) }), { base: { defaultShell } });
508
514
  /** Official sandbox-escalation surface (mirrors tool-bash): advertise the
509
515
  * escalation modes whenever the deployment confines. */
510
516
  const escalationModes = ESCALATION_TARGETS;
@@ -529,7 +535,7 @@ export function apply(ctx, config = {}) {
529
535
  });
530
536
  const toolName = "shell";
531
537
  const terminalRegistry = createTerminalRegistry(ctx);
532
- ctx.tools.register(terminalTool(ctx, terminalRegistry, paths, () => settingsScope.get().defaultShell));
538
+ ctx.tools.register(terminalTool(ctx, terminalRegistry, paths, () => currentShell()));
533
539
  // The model-facing description must track the user's chosen default
534
540
  // terminal: a static description listing every backend leaves the model
535
541
  // guessing which syntax applies. Re-render it on every prompt assembly —
@@ -537,7 +543,7 @@ export function apply(ctx, config = {}) {
537
543
  // without a restart.
538
544
  ctx.on("system-prompt/assemble", async (_assembly, _context, next) => {
539
545
  const assembled = await next();
540
- const description = toolDescription(backgroundEnabled, settingsScope.get().defaultShell);
546
+ const description = toolDescription(backgroundEnabled, currentShell());
541
547
  const tools = Array.isArray(assembled.tools)
542
548
  ? assembled.tools.map((tool) => (tool.name === toolName ? { ...tool, description } : tool))
543
549
  : assembled.tools;
@@ -545,7 +551,7 @@ export function apply(ctx, config = {}) {
545
551
  });
546
552
  ctx.tools.register(defineTool({
547
553
  name: toolName,
548
- description: toolDescription(backgroundEnabled, settingsScope.get().defaultShell),
554
+ description: toolDescription(backgroundEnabled, currentShell()),
549
555
  parameters: {
550
556
  command: {
551
557
  type: "string",
@@ -644,7 +650,7 @@ export function apply(ctx, config = {}) {
644
650
  },
645
651
  async execute(args, exec) {
646
652
  const v = validateArgs(args);
647
- const shell = settingsScope.get().defaultShell;
653
+ const shell = currentShell();
648
654
  const argv0 = buildArgv(shell, v.command, paths, v.distro);
649
655
  if (argv0[0] === undefined) {
650
656
  throw new Error(`dsh-bash-terminal: ${shell} backend unavailable - executable not found. Install it or set the corresponding *Path config.`);
package/package.json CHANGED
@@ -1,10 +1,8 @@
1
1
  {
2
2
  "name": "dsh-bash-terminal-ts",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "publishConfig": {
5
- "registry": "https://registry.npmjs.org",
6
- "access": "public",
7
- "tag": "dsh-0.1.5"
5
+ "tag": "dsh-0.1.7"
8
6
  },
9
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.",
10
8
  "author": "drscrewdriver",
@@ -31,7 +29,7 @@
31
29
  ],
32
30
  "engines": {
33
31
  "node": ">=22",
34
- "dsh": ">=0.1.5-rc.1 <0.1.6-0"
32
+ "dsh": ">=0.1.7-rc.1 <0.1.8-0"
35
33
  },
36
34
  "type": "module",
37
35
  "main": "lib/index.js",
@@ -76,21 +74,21 @@
76
74
  },
77
75
  "peerDependencies": {
78
76
  "@deepseek-ai/cordis": "^4.0.2",
79
- "@deepseek-ai/dsh-tools": ">=0.1.5-rc.1 <0.1.6-0",
80
- "@deepseek-ai/dsh-settings": ">=0.1.5-rc.1 <0.1.6-0",
81
- "@deepseek-ai/dsh-llm": ">=0.1.5-rc.1 <0.1.6-0",
82
- "@deepseek-ai/dsh-shell": ">=0.1.5-rc.1 <0.1.6-0",
83
- "@deepseek-ai/dsh-sandbox": ">=0.1.5-rc.1 <0.1.6-0",
84
- "@deepseek-ai/dsh-timeout": ">=0.1.5-rc.1 <0.1.6-0",
85
- "@deepseek-ai/dsh-client-store": ">=0.1.5-rc.1 <0.1.6-0",
86
- "@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1 <0.1.6-0",
87
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.1 <0.1.6-0",
88
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.1 <0.1.6-0",
89
- "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.5-rc.1 <0.1.6-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",
90
88
  "react": "^18.2.0"
91
89
  },
92
90
  "dependencies": {
93
- "@deepseek-ai/schemastery": "^3.18.1",
91
+ "@deepseek-ai/schemastery": "^3.18.4",
94
92
  "node-pty": "^1.1.0"
95
93
  },
96
94
  "devDependencies": {
package/src/client.tsx CHANGED
@@ -16,7 +16,8 @@ import { defineStore } from "@deepseek-ai/dsh-client-store";
16
16
  import { IconChevronDownOutline14, Menu } from "@deepseek-ai/dsh-client-ui-primitives";
17
17
 
18
18
  const SETTINGS_NS = "settings.bash-terminal";
19
- 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";
20
21
  const SHELLS = ["powershell", "gitbash", "msys2", "wsl"] as const;
21
22
 
22
23
  type ShellOption = (typeof SHELLS)[number];
@@ -55,7 +56,7 @@ const en: Record<string, string> = {
55
56
  "shell.wsl": "WSL"
56
57
  };
57
58
 
58
- export const inject = ["slots", "locale", "settingsScope"];
59
+ export const inject = ["slots", "locale", "configForms"];
59
60
 
60
61
  /** Row state snapshot served through the settings store. */
61
62
  interface RowState {
@@ -112,23 +113,23 @@ function ShellPreferenceRow({ t, useStore, setShell }: ShellPreferenceRowProps)
112
113
  }
113
114
 
114
115
  interface SettingsSnapshot {
115
- status: string;
116
+ status: "loading" | "ready" | "unavailable";
116
117
  value?: { defaultShell?: string };
117
- revision: number;
118
+ revision: number | undefined;
118
119
  writable: boolean;
119
120
  }
120
121
 
121
- interface SettingsScopeBinding {
122
+ interface ConfigFormBinding {
122
123
  getSnapshot(): SettingsSnapshot;
123
124
  subscribe(fn: () => void): () => void;
124
- set(field: string, value: string): void;
125
- unset(): void;
125
+ set(field: string, value: string): Promise<boolean>;
126
+ unset(field: string): Promise<boolean>;
126
127
  }
127
128
 
128
129
  interface ClientContext {
129
130
  effect(fn: () => unknown, name?: string): unknown;
130
131
  locale: { register(ns: string, dicts: Record<string, Record<string, string>>): unknown };
131
- settingsScope: { bind(options: { namespace: string }): SettingsScopeBinding };
132
+ configForms: { get(entryId: string): ConfigFormBinding };
132
133
  slots: {
133
134
  inject(slot: string, fn: () => unknown, name?: string): void;
134
135
  register(options: Record<string, unknown>, Component: unknown): Record<string, unknown>;
@@ -145,7 +146,7 @@ interface RowStore {
145
146
 
146
147
  export function apply(ctx: ClientContext): void {
147
148
  ctx.effect(() => ctx.locale.register(SETTINGS_NS, { zh, en }), "bash-terminal: settings dictionaries");
148
- const scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
149
+ const scope = ctx.configForms.get(ENTRY_ID);
149
150
  const store = defineStore<RowState, { sync: (draft: RowState, shell?: string, revision?: number, writable?: boolean) => void }>({
150
151
  init: (): RowState => ({ shell: "powershell", revision: -1, writable: false }),
151
152
  actions: {
package/src/dsh-types.ts CHANGED
@@ -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 {
package/src/index.ts CHANGED
@@ -61,8 +61,6 @@ export const inject = ["tools", "systemPrompt", "shellEnv", "subprocess", "setti
61
61
  export const SHELLS = ["powershell", "gitbash", "msys2", "wsl"] as const;
62
62
  /** The backend used when the caller does not name one. */
63
63
  export const DEFAULT_SHELL: ShellId = "powershell";
64
- /** Settings namespace backing the user-chosen default terminal. */
65
- export const SETTINGS_NAMESPACE = "bash-terminal";
66
64
  /** Default per-command timeout (ms). */
67
65
  const DEFAULT_TIMEOUT_MS = 120000;
68
66
  /** Upper bound a caller's timeoutMs is capped to. */
@@ -84,6 +82,11 @@ const ENV_OVERRIDES: Record<string, string> = {
84
82
  GIT_PAGER: "cat"
85
83
  };
86
84
 
85
+ /** Live reference the 0.1.7 loader hands `apply` for `.volatile()` config fields. */
86
+ interface VolatileRef<T> {
87
+ get(): T;
88
+ }
89
+
87
90
  /** Static shape of the runtime configuration schema. */
88
91
  export interface ConfigValues {
89
92
  defaultShell: string;
@@ -97,7 +100,7 @@ export interface ConfigValues {
97
100
 
98
101
  /** Runtime configuration schema. */
99
102
  export const Config = z.object({
100
- defaultShell: z.string().default(DEFAULT_SHELL),
103
+ defaultShell: z.string().default(DEFAULT_SHELL).volatile(),
101
104
  timeoutMs: z.number().default(DEFAULT_TIMEOUT_MS),
102
105
  maxTimeoutMs: z.number().default(MAX_TIMEOUT_MS),
103
106
  pwshPath: z.string().default(""),
@@ -671,15 +674,18 @@ export function apply(ctx: BashTerminalContext, config: Partial<ConfigValues> =
671
674
  }
672
675
  const backgroundEnabled = true;
673
676
  const paths = resolveAllPaths(config);
674
- const defaultShell = config.defaultShell ?? DEFAULT_SHELL;
675
- if (!(SHELLS as readonly string[]).includes(defaultShell)) {
676
- throw new Error(`dsh-bash-terminal: invalid defaultShell ${JSON.stringify(defaultShell)}`);
677
+ // 0.1.7: `defaultShell` is a `.volatile()` config field — the loader hands
678
+ // `apply` a live ref and the latest value is resolved on every read; there
679
+ // is no settings registration call anymore (removed with the 0.1.7 host).
680
+ const currentShell = (): string => {
681
+ const v = config.defaultShell as string | VolatileRef<string> | undefined;
682
+ if (typeof v === "string") return v;
683
+ const got = typeof v?.get === "function" ? v.get() : undefined;
684
+ return typeof got === "string" ? got : DEFAULT_SHELL;
685
+ };
686
+ if (!(SHELLS as readonly string[]).includes(currentShell())) {
687
+ throw new Error(`dsh-bash-terminal: invalid defaultShell ${JSON.stringify(currentShell())}`);
677
688
  }
678
- const settingsScope = ctx.settings.register(
679
- SETTINGS_NAMESPACE,
680
- z.object({ defaultShell: z.union(SHELLS.map((s) => z.const(s))).default(defaultShell) }),
681
- { base: { defaultShell } }
682
- );
683
689
  /** Official sandbox-escalation surface (mirrors tool-bash): advertise the
684
690
  * escalation modes whenever the deployment confines. */
685
691
  const escalationModes = ESCALATION_TARGETS;
@@ -711,7 +717,7 @@ export function apply(ctx: BashTerminalContext, config: Partial<ConfigValues> =
711
717
 
712
718
  const toolName = "shell";
713
719
  const terminalRegistry = createTerminalRegistry(ctx);
714
- ctx.tools.register(terminalTool(ctx, terminalRegistry, paths, () => settingsScope.get().defaultShell));
720
+ ctx.tools.register(terminalTool(ctx, terminalRegistry, paths, () => currentShell()));
715
721
 
716
722
  // The model-facing description must track the user's chosen default
717
723
  // terminal: a static description listing every backend leaves the model
@@ -720,7 +726,7 @@ export function apply(ctx: BashTerminalContext, config: Partial<ConfigValues> =
720
726
  // without a restart.
721
727
  ctx.on("system-prompt/assemble", async (_assembly, _context, next) => {
722
728
  const assembled = await next();
723
- const description = toolDescription(backgroundEnabled, settingsScope.get().defaultShell);
729
+ const description = toolDescription(backgroundEnabled, currentShell());
724
730
  const tools = Array.isArray(assembled.tools)
725
731
  ? assembled.tools.map((tool) => (tool.name === toolName ? { ...tool, description } : tool))
726
732
  : assembled.tools;
@@ -729,7 +735,7 @@ export function apply(ctx: BashTerminalContext, config: Partial<ConfigValues> =
729
735
 
730
736
  ctx.tools.register(defineTool<ShellToolResult>({
731
737
  name: toolName,
732
- description: toolDescription(backgroundEnabled, settingsScope.get().defaultShell),
738
+ description: toolDescription(backgroundEnabled, currentShell()),
733
739
  parameters: {
734
740
  command: {
735
741
  type: "string",
@@ -826,7 +832,7 @@ export function apply(ctx: BashTerminalContext, config: Partial<ConfigValues> =
826
832
  },
827
833
  async execute(args, exec) {
828
834
  const v = validateArgs(args);
829
- const shell = settingsScope.get().defaultShell;
835
+ const shell = currentShell();
830
836
  const argv0 = buildArgv(shell, v.command, paths, v.distro);
831
837
  if (argv0[0] === undefined) {
832
838
  throw new Error(`dsh-bash-terminal: ${shell} backend unavailable - executable not found. Install it or set the corresponding *Path config.`);