@aiwayds/dsh-tui-pi 2.21.0 → 2.23.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.
Files changed (67) hide show
  1. package/README.md +14 -9
  2. package/README.zh-CN.md +14 -9
  3. package/cordis.patch.yml +11 -2
  4. package/icon.svg +7 -0
  5. package/lib/agents.js +23 -3
  6. package/lib/agents.js.map +1 -1
  7. package/lib/btw.d.ts +1 -1
  8. package/lib/btw.js +2 -2
  9. package/lib/btw.js.map +1 -1
  10. package/lib/dsh-events.d.ts +23 -9
  11. package/lib/dsh-events.js +20 -8
  12. package/lib/dsh-events.js.map +1 -1
  13. package/lib/history.d.ts +8 -2
  14. package/lib/history.js +4 -1
  15. package/lib/history.js.map +1 -1
  16. package/lib/index.d.ts +3 -1
  17. package/lib/index.js +119 -61
  18. package/lib/index.js.map +1 -1
  19. package/lib/live-widgets.js +6 -3
  20. package/lib/live-widgets.js.map +1 -1
  21. package/lib/login.js.map +1 -1
  22. package/lib/messages.d.ts +10 -0
  23. package/lib/messages.js +39 -0
  24. package/lib/messages.js.map +1 -1
  25. package/lib/preset.d.ts +128 -58
  26. package/lib/preset.js +208 -113
  27. package/lib/preset.js.map +1 -1
  28. package/lib/remote-tail.js +3 -0
  29. package/lib/remote-tail.js.map +1 -1
  30. package/lib/selectors.d.ts +4 -1
  31. package/lib/selectors.js +8 -3
  32. package/lib/selectors.js.map +1 -1
  33. package/lib/session.d.ts +18 -1
  34. package/lib/session.js +77 -17
  35. package/lib/session.js.map +1 -1
  36. package/lib/sessions.d.ts +7 -0
  37. package/lib/sessions.js +15 -1
  38. package/lib/sessions.js.map +1 -1
  39. package/lib/settings.d.ts +17 -11
  40. package/lib/settings.js +35 -26
  41. package/lib/settings.js.map +1 -1
  42. package/lib/source-kind.d.ts +26 -0
  43. package/lib/source-kind.js +17 -0
  44. package/lib/source-kind.js.map +1 -0
  45. package/lib/subagent-policy.js +1 -1
  46. package/lib/subagent-policy.js.map +1 -1
  47. package/lib/subagent-viewer.d.ts +3 -3
  48. package/lib/subagent-viewer.js +9 -6
  49. package/lib/subagent-viewer.js.map +1 -1
  50. package/lib/theme-settings.d.ts +353 -159
  51. package/lib/theme-settings.js +258 -336
  52. package/lib/theme-settings.js.map +1 -1
  53. package/lib/tokens.d.ts +5 -3
  54. package/lib/tokens.js +5 -8
  55. package/lib/tokens.js.map +1 -1
  56. package/locale/en.json +6 -0
  57. package/locale/ja.json +6 -0
  58. package/locale/ko.json +6 -0
  59. package/locale/zh-CN.json +6 -0
  60. package/locales/en.json +7 -2
  61. package/locales/ja.json +7 -2
  62. package/locales/ko.json +7 -2
  63. package/locales/zh-CN.json +7 -2
  64. package/package.json +22 -16
  65. package/scripts/diagnose-container-tui.sh +3 -3
  66. package/scripts/smoke-boot.mjs +2 -2
  67. package/skills/dsh-tui-pi-config/SKILL.md +11 -7
@@ -1,37 +1,51 @@
1
1
  /**
2
- * Theme settings: persists the user's theme preference, the think/tool panel
3
- * height, and the subagent concurrency/rounds limits under the `dsh-tui`
4
- * settings namespace, surfaced by the /settings browser and the /theme
5
- * command. The theme and panel-height preferences are read once at TUI
6
- * startup (`readThemePreference` / `readPanelHeightPreference`); the subagent
7
- * limits are read live at every policy decision (`readSubagentLimits`). The
8
- * namespace is marked `applies: 'live'`: a committed change (the /theme
9
- * picker, the /settings browser, an external edit) is pushed through the
10
- * watch hook, so the running TUI repaints without a restart.
2
+ * Theme settings: the dsh-tui entry configuration — the user's theme
3
+ * preference, the think/tool panel height, the UI language, the footer-hint
4
+ * selection, the icon-set mode and the subagent concurrency/rounds limits.
11
5
  *
12
- * The session-management sections (`retention`, `resume`) ride the same
13
- * namespace but are read from the descriptor's USER layer
14
- * (`readSessionManagementExplicit`), not the resolved value: only a field
15
- * the user explicitly wrote to settings.yaml is an override — the resolved
16
- * value's baked-in defaults must not shadow the DSH_TUI_RETENTION_* /
17
- * DSH_TUI_RESUME_* environment variables (precedence: settings explicit >
18
- * env > default; the janitor consumes its values at next startup, the
19
- * /resume filter at every picker open).
6
+ * dsh 0.1.7 model (breaking change from 0.1.5): the runtime
7
+ * namespace-registration API is GONE. A plugin declares its
8
+ * user-facing configuration as a `static Config` schema; the loader projects
9
+ * every `.volatile()` field into the settings surface (describe / update /
10
+ * mutate) and hands the resolved values to `apply(ctx, config)` — volatile
11
+ * fields arrive as live `Volatile<T>` references. Declaration IS
12
+ * registration: there is nothing to register at runtime anymore.
13
+ *
14
+ * Reading: `config.field.get()` — a deep-frozen snapshot, refreshed IN PLACE
15
+ * by the loader on every volatile-only commit (the fiber never remounts, the
16
+ * references stay identical), so a value read is always current.
17
+ *
18
+ * Hot-apply: the plugin subscribes to `settings/document-updated` (the
19
+ * 0.1.5 per-namespace watch-hook replacement) and re-reads the references on
20
+ * every event. The
21
+ * event also fires for this TUI's own writes; every sink downstream is an
22
+ * idempotent no-op on an unchanged value (theme-bundle identity guard, same
23
+ * height, same hints), so the echo is harmless.
24
+ *
25
+ * Session-management sections (`retention`, `resume`, `askUser`) keep their
26
+ * USER-layer precedence seam: only a field the user explicitly wrote into the
27
+ * profile patch (`cordis.patch.yml` → entry `dsh-tui` → `config:`; the 0.1.5
28
+ * `settings.yaml` document is auto-imported there once on first 0.1.7 boot)
29
+ * is an override — the resolved value's baked-in defaults must not shadow the
30
+ * DSH_TUI_RETENTION_* / DSH_TUI_RESUME_* / DSH_TUI_ASK_USER_* environment
31
+ * variables (precedence: settings explicit > env > default). Those readers
32
+ * go through `settings.describe()[].user`, the only channel exposing the raw
33
+ * explicit layer.
20
34
  */
21
- import type { Context } from '@deepseek-ai/cordis';
35
+ import type { Context, Volatile } from '@deepseek-ai/cordis';
36
+ import z from '@deepseek-ai/schemastery';
22
37
  import { type FooterHints } from './footer.ts';
23
38
  import { type PanelHeight } from './activity.ts';
24
39
  import type { IconSet } from './icons.ts';
25
40
  import type { ThemePreference } from './theme/index.ts';
26
41
  /**
27
- * Settings namespace carrying the persisted dsh-tui preferences.
42
+ * Settings entry id carrying the persisted dsh-tui preferences.
28
43
  *
29
- * dsh-settings 0.1.2-alpha.3 removed the runtime settingsNamespace() helper
30
- * (and the SettingsNamespace constructor it returned): a plain literal is the
31
- * supported spelling — register() brand-checks it at the type level
32
- * (SettingsNamespaceInput) and validates the same lowercase-hyphenated pattern
33
- * at runtime (parseSettingsNamespace). Comparisons against a descriptor's
34
- * branded `ns` stay exact string equality.
44
+ * This is BOTH the profile patch entry id (cordis.patch.yml mounts this
45
+ * package as `- id: dsh-tui`) and the legacy settings.yaml section name —
46
+ * keeping them identical is what lets the 0.1.7 one-time settings.yaml
47
+ * import (`settings.yaml` → renamed `.imported`, sections merged into the
48
+ * matching entry's config) pick up every existing user value without a shim.
35
49
  */
36
50
  export declare const THEME_SETTINGS_NAMESPACE = "dsh-tui";
37
51
  /**
@@ -83,108 +97,273 @@ export interface SubagentLimits {
83
97
  registeredOnly: boolean;
84
98
  }
85
99
  /**
86
- * Default subagent limits, applied whenever the settings service, namespace,
87
- * or a field cannot be read. 4 concurrent children and 75 rounds per child
88
- * are the documented out-of-the-box behavior (75 rounds = 75 LLM
89
- * round-trips, headroom for heavy delegated tasks while still capping a
90
- * runaway child); the native `subagent` tool is disabled by default — the
91
- * TUI's user delegates through registered agents (toggle it in /agents → l
92
- * limits when the plain tool is needed again).
100
+ * Default subagent limits, applied whenever the entry config cannot be read.
101
+ * 4 concurrent children and 75 rounds per child are the documented
102
+ * out-of-the-box behavior (75 rounds = 75 LLM round-trips, headroom for heavy
103
+ * delegated tasks while still capping a runaway child); the native `subagent`
104
+ * tool is disabled by default — the TUI's user delegates through registered
105
+ * agents (toggle it in /agents → l limits when the plain tool is needed again).
93
106
  */
94
107
  export declare const DEFAULT_SUBAGENT_LIMITS: SubagentLimits;
108
+ /** Grouped session-log retention knobs (see resolveRetentionConfig). */
109
+ export interface RetentionSettings {
110
+ maxCount: number;
111
+ maxAgeDays: number;
112
+ minIdleHours: number;
113
+ }
114
+ /** Grouped /resume display-window knobs. */
115
+ export interface ResumeSettings {
116
+ maxAgeDays: number;
117
+ minBytes: number;
118
+ }
119
+ /** Grouped ask-user auto-answer timeout knobs. */
120
+ export interface AskUserSettings {
121
+ idleMinutes: number;
122
+ absoluteMinutes: number;
123
+ }
95
124
  /**
96
- * Register the `dsh-tui` settings namespace with the settings provider.
97
- *
98
- * This registers directly through the provider (not through a
99
- * section-install helper): the registration rides the scoped injection fiber
100
- * and disappears with the settings service. `onPreferenceChange`, when given,
101
- * receives every committed change (including this TUI's own writes) through
102
- * the scope's watch hook; callers guard re-applies by theme-bundle identity
103
- * and height change, so an echoed self-write is a no-op. No source thunk is
104
- * needed — the read helpers read the resolved values on demand at TUI
105
- * startup.
125
+ * Runtime face of the `dsh-tui` entry config. Every field is `.volatile()` —
126
+ * user-editable through the settings surface and hot-applied without a
127
+ * plugin remount — so each arrives as a live `Volatile<T>` reference, read
128
+ * with `.get()`.
129
+ */
130
+ export interface TuiSettings {
131
+ language: Volatile<string>;
132
+ theme: Volatile<ThemePreference>;
133
+ panelHeight: Volatile<PanelHeight>;
134
+ maxAgents: Volatile<number>;
135
+ maxRounds: Volatile<number>;
136
+ maxRoundsGrace: Volatile<number>;
137
+ disableSubagent: Volatile<boolean>;
138
+ registeredOnly: Volatile<boolean>;
139
+ footerHints: Volatile<FooterHints>;
140
+ cacheHitMode: Volatile<CacheHitMode>;
141
+ iconSet: Volatile<IconSet>;
142
+ rememberPreset: Volatile<boolean>;
143
+ favoriteModels: Volatile<string[]>;
144
+ hiddenModels: Volatile<string[]>;
145
+ retention: Volatile<RetentionSettings>;
146
+ resume: Volatile<ResumeSettings>;
147
+ askUser: Volatile<AskUserSettings>;
148
+ }
149
+ /**
150
+ * The `dsh-tui` entry Config schema — the whole settings surface. Exported
151
+ * from the plugin root (src/index.ts re-exports it): the loader reads
152
+ * `plugin.Config` off the module namespace and validates + resolves the
153
+ * entry's config against it; every field is `.volatile()`, so the settings
154
+ * browser lists all of them and a legacy settings.yaml `dsh-tui:` section
155
+ * imports wholesale (an import carrying any non-volatile field would be
156
+ * rejected as a whole).
106
157
  *
107
- * @param ctx - plugin context; does nothing while no settings service is mounted.
108
- * @param onPreferenceChange - hot-reload sink for committed `dsh-tui` theme,
109
- * panel-height, footer-hints, icon-set and language changes; `undefined` when the
110
- * namespace is already registered (a reloaded plugin instance, a second mount
111
- * of this bundle) or registration fails.
158
+ * Plain z.number() (not z.natural()) inside `retention`/`resume`/`askUser` on
159
+ * purpose, same as the 0.1.5 schema: a range-constrained field lets one
160
+ * hand-edited out-of-range number get the whole volatile-only update refused
161
+ * (the write is rejected and the raw value still lands on disk — see the
162
+ * dsh 0.1.7 "not volatile / validation" semantics), so the per-field range
163
+ * check happens in the readers (resolveRetentionConfig / resolveResumeConfig /
164
+ * resolveAskUserTimeouts), which fall back to env/defaults with one stderr
165
+ * line instead.
166
+ */
167
+ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
168
+ language: z<string, string, "volatile-defined">;
169
+ theme: z<string, string, "volatile-defined">;
170
+ panelHeight: z<"1" | "5" | "7" | "10" | "all", "1" | "5" | "7" | "10" | "all", "volatile-defined">;
171
+ maxAgents: z<number, number, "volatile-defined">;
172
+ maxRounds: z<number, number, "volatile-defined">;
173
+ maxRoundsGrace: z<number, number, "volatile-defined">;
174
+ disableSubagent: z<boolean, boolean, "volatile-defined">;
175
+ registeredOnly: z<boolean, boolean, "volatile-defined">;
176
+ footerHints: z<NoInfer<Schemastery.ObjectS<NoInfer<{
177
+ send: z<boolean, boolean, "defined">;
178
+ stop: z<boolean, boolean, "defined">;
179
+ quit: z<boolean, boolean, "defined">;
180
+ quitEmpty: z<boolean, boolean, "defined">;
181
+ subagents: z<boolean, boolean, "defined">;
182
+ search: z<boolean, boolean, "defined">;
183
+ history: z<boolean, boolean, "defined">;
184
+ }>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
185
+ send: z<boolean, boolean, "defined">;
186
+ stop: z<boolean, boolean, "defined">;
187
+ quit: z<boolean, boolean, "defined">;
188
+ quitEmpty: z<boolean, boolean, "defined">;
189
+ subagents: z<boolean, boolean, "defined">;
190
+ search: z<boolean, boolean, "defined">;
191
+ history: z<boolean, boolean, "defined">;
192
+ }>>>, "volatile-defined">;
193
+ cacheHitMode: z<"session" | "lastMessage", "session" | "lastMessage", "volatile-defined">;
194
+ iconSet: z<"auto" | "plain" | "nerdfont", "auto" | "plain" | "nerdfont", "volatile-defined">;
195
+ rememberPreset: z<boolean, boolean, "volatile-defined">;
196
+ favoriteModels: z<NoInfer<string[]>, NoInfer<string[]>, "volatile-defined">;
197
+ hiddenModels: z<NoInfer<string[]>, NoInfer<string[]>, "volatile-defined">;
198
+ retention: z<NoInfer<Schemastery.ObjectS<NoInfer<{
199
+ maxCount: z<number, number, "defined">;
200
+ maxAgeDays: z<number, number, "defined">;
201
+ minIdleHours: z<number, number, "defined">;
202
+ }>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
203
+ maxCount: z<number, number, "defined">;
204
+ maxAgeDays: z<number, number, "defined">;
205
+ minIdleHours: z<number, number, "defined">;
206
+ }>>>, "volatile-defined">;
207
+ resume: z<NoInfer<Schemastery.ObjectS<NoInfer<{
208
+ maxAgeDays: z<number, number, "defined">;
209
+ minBytes: z<number, number, "defined">;
210
+ }>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
211
+ maxAgeDays: z<number, number, "defined">;
212
+ minBytes: z<number, number, "defined">;
213
+ }>>>, "volatile-defined">;
214
+ askUser: z<NoInfer<Schemastery.ObjectS<NoInfer<{
215
+ idleMinutes: z<number, number, "defined">;
216
+ absoluteMinutes: z<number, number, "defined">;
217
+ }>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
218
+ idleMinutes: z<number, number, "defined">;
219
+ absoluteMinutes: z<number, number, "defined">;
220
+ }>>>, "volatile-defined">;
221
+ }>>, Schemastery.ObjectT<NoInfer<{
222
+ language: z<string, string, "volatile-defined">;
223
+ theme: z<string, string, "volatile-defined">;
224
+ panelHeight: z<"1" | "5" | "7" | "10" | "all", "1" | "5" | "7" | "10" | "all", "volatile-defined">;
225
+ maxAgents: z<number, number, "volatile-defined">;
226
+ maxRounds: z<number, number, "volatile-defined">;
227
+ maxRoundsGrace: z<number, number, "volatile-defined">;
228
+ disableSubagent: z<boolean, boolean, "volatile-defined">;
229
+ registeredOnly: z<boolean, boolean, "volatile-defined">;
230
+ footerHints: z<NoInfer<Schemastery.ObjectS<NoInfer<{
231
+ send: z<boolean, boolean, "defined">;
232
+ stop: z<boolean, boolean, "defined">;
233
+ quit: z<boolean, boolean, "defined">;
234
+ quitEmpty: z<boolean, boolean, "defined">;
235
+ subagents: z<boolean, boolean, "defined">;
236
+ search: z<boolean, boolean, "defined">;
237
+ history: z<boolean, boolean, "defined">;
238
+ }>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
239
+ send: z<boolean, boolean, "defined">;
240
+ stop: z<boolean, boolean, "defined">;
241
+ quit: z<boolean, boolean, "defined">;
242
+ quitEmpty: z<boolean, boolean, "defined">;
243
+ subagents: z<boolean, boolean, "defined">;
244
+ search: z<boolean, boolean, "defined">;
245
+ history: z<boolean, boolean, "defined">;
246
+ }>>>, "volatile-defined">;
247
+ cacheHitMode: z<"session" | "lastMessage", "session" | "lastMessage", "volatile-defined">;
248
+ iconSet: z<"auto" | "plain" | "nerdfont", "auto" | "plain" | "nerdfont", "volatile-defined">;
249
+ rememberPreset: z<boolean, boolean, "volatile-defined">;
250
+ favoriteModels: z<NoInfer<string[]>, NoInfer<string[]>, "volatile-defined">;
251
+ hiddenModels: z<NoInfer<string[]>, NoInfer<string[]>, "volatile-defined">;
252
+ retention: z<NoInfer<Schemastery.ObjectS<NoInfer<{
253
+ maxCount: z<number, number, "defined">;
254
+ maxAgeDays: z<number, number, "defined">;
255
+ minIdleHours: z<number, number, "defined">;
256
+ }>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
257
+ maxCount: z<number, number, "defined">;
258
+ maxAgeDays: z<number, number, "defined">;
259
+ minIdleHours: z<number, number, "defined">;
260
+ }>>>, "volatile-defined">;
261
+ resume: z<NoInfer<Schemastery.ObjectS<NoInfer<{
262
+ maxAgeDays: z<number, number, "defined">;
263
+ minBytes: z<number, number, "defined">;
264
+ }>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
265
+ maxAgeDays: z<number, number, "defined">;
266
+ minBytes: z<number, number, "defined">;
267
+ }>>>, "volatile-defined">;
268
+ askUser: z<NoInfer<Schemastery.ObjectS<NoInfer<{
269
+ idleMinutes: z<number, number, "defined">;
270
+ absoluteMinutes: z<number, number, "defined">;
271
+ }>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
272
+ idleMinutes: z<number, number, "defined">;
273
+ absoluteMinutes: z<number, number, "defined">;
274
+ }>>>, "volatile-defined">;
275
+ }>>, "plain">;
276
+ /**
277
+ * Bind the loader-resolved entry config (the `config` parameter of
278
+ * `apply(ctx, config)`). Called once per plugin application; a `/reload`
279
+ * re-runs `apply` and re-binds. Volatile-only commits later swap the values
280
+ * behind the SAME references in place, so the bound object stays current
281
+ * without rebinding.
112
282
  */
113
- export declare function registerThemeSettings(ctx: Context, onPreferenceChange?: (pref: ThemePreference, panelHeight: PanelHeight, footerHints: FooterHints, iconSet: IconSet, language: string) => void): void;
283
+ export declare function bindTuiConfig(config: TuiSettings | undefined): void;
284
+ /** Resolve an export of the Config schema into a `TuiSettings`-shaped object (test helper). */
285
+ export declare function resolveTuiSettings(overrides?: Record<string, unknown>): TuiSettings;
114
286
  /** Validate an unknown `language` value (anything else narrows to the 'en' fallback). */
115
287
  export declare function narrowLanguage(value: unknown): string;
288
+ /**
289
+ * Subscribe the hot-reload sink to committed `dsh-tui` changes — the 0.1.7
290
+ * replacement of the 0.1.5 watch hook (the runtime registration call itself
291
+ * is gone: the static Config schema declares the entry config, the loader
292
+ * owns the projection).
293
+ *
294
+ * `settings/document-updated` carries `(ns, revision)` and fires whenever the
295
+ * entry's raw config changed — the /theme picker, the /settings browser, an
296
+ * external patch edit, or this TUI's own write (the echo). The handler
297
+ * re-reads the live volatile references (the loader updated them in place
298
+ * before the event) and forwards the narrowed bundle to the sink; callers
299
+ * guard re-applies by theme-bundle identity and height change, so an echoed
300
+ * self-write is a no-op. The whole commit → references → event → `.get()`
301
+ * → sink chain is synchronous per event.
302
+ *
303
+ * @param ctx - plugin context; the subscription dies with the plugin fiber.
304
+ * @param onPreferenceChange - hot-reload sink for committed `dsh-tui` theme,
305
+ * panel-height, footer-hints, icon-set and language changes; `undefined`
306
+ * registers nothing.
307
+ */
308
+ export declare function subscribeThemeSettings(ctx: Context, onPreferenceChange?: (pref: ThemePreference, panelHeight: PanelHeight, footerHints: FooterHints, iconSet: IconSet, language: string) => void): void;
116
309
  /**
117
310
  * Read the persisted theme preference (the startup snapshot).
118
311
  *
119
- * @param ctx - plugin context.
120
- * @returns the resolved `dsh-tui` theme value, or `'auto'` when the settings
121
- * service is absent or the namespace/value cannot be read.
312
+ * @returns the live `dsh-tui` theme value, or `'auto'` when the entry config
313
+ * is not bound (a `Config`-less deployment always has the schema default).
122
314
  */
123
- export declare function readThemePreference(ctx: Context): Promise<ThemePreference>;
315
+ export declare function readThemePreference(_ctx: Context): ThemePreference;
124
316
  /**
125
317
  * Read the persisted think/tool panel height (the startup snapshot).
126
318
  *
127
- * @param ctx - plugin context.
128
- * @returns the resolved `dsh-tui` panelHeight value, or DEFAULT_PANEL_HEIGHT
129
- * when the settings service is absent or the namespace/value cannot be read.
319
+ * @returns the live `dsh-tui` panelHeight value, or DEFAULT_PANEL_HEIGHT when
320
+ * the entry config is not bound.
130
321
  */
131
- export declare function readPanelHeightPreference(ctx: Context): Promise<PanelHeight>;
322
+ export declare function readPanelHeightPreference(_ctx: Context): PanelHeight;
132
323
  /**
133
324
  * Read the persisted footer-hint selection (the startup snapshot).
134
325
  *
135
- * @param ctx - plugin context.
136
- * @returns the resolved `dsh-tui` footerHints object, or DEFAULT_FOOTER_HINTS
137
- * when the settings service is absent or the namespace/value cannot be read.
326
+ * @returns the live `dsh-tui` footerHints object, or DEFAULT_FOOTER_HINTS
327
+ * when the entry config is not bound.
138
328
  */
139
- export declare function readFooterHintsPreference(ctx: Context): Promise<FooterHints>;
329
+ export declare function readFooterHintsPreference(_ctx: Context): FooterHints;
140
330
  /**
141
331
  * Read the persisted icon-set mode (the startup snapshot).
142
332
  *
143
- * @param ctx - plugin context.
144
- * @returns the resolved `dsh-tui` iconSet value, or `'auto'` when the settings
145
- * service is absent or the namespace/value cannot be read.
333
+ * @returns the live `dsh-tui` iconSet value, or `'auto'` when the entry
334
+ * config is not bound.
146
335
  */
147
- export declare function readIconSetPreference(ctx: Context): Promise<IconSet>;
336
+ export declare function readIconSetPreference(_ctx: Context): IconSet;
148
337
  /**
149
338
  * Read the persisted UI language (the startup snapshot).
150
339
  *
151
- * @param ctx - plugin context.
152
- * @returns the resolved `dsh-tui` language value, or DEFAULT_LANGUAGE ('en')
153
- * when the settings service is absent or the namespace/value cannot be read.
154
- * Whether the id is actually installed is decided by the i18n registry
155
- * (initI18n degrades unknown ids to 'en').
340
+ * @returns the live `dsh-tui` language value, or DEFAULT_LANGUAGE ('en') when
341
+ * the entry config is not bound. Whether the id is actually installed is
342
+ * decided by the i18n registry (initI18n degrades unknown ids to 'en').
156
343
  */
157
- export declare function readLanguagePreference(ctx: Context): Promise<string>;
344
+ export declare function readLanguagePreference(_ctx: Context): string;
158
345
  /**
159
346
  * Read the persisted preset-memory toggle (the startup snapshot). Default
160
347
  * TRUE: remembering is the out-of-the-box behavior; only an explicit
161
- * `dsh-tui.rememberPreset: false` turns it off.
348
+ * `rememberPreset: false` turns it off.
162
349
  *
163
- * @param ctx - plugin context.
164
- * @returns the resolved boolean, or `true` when the settings service is
165
- * absent or the namespace/value cannot be read.
166
- */
167
- export declare function readRememberPreset(ctx: Context): Promise<boolean>;
168
- /**
169
- * Read the currently persisted preset-memory toggle, synchronously. Unlike
170
- * `readRememberPreset` (the startup snapshot), this describes whatever the
171
- * settings service exposes right now — the /preset switch path calls it at
172
- * every commit, so a `/settings` toggle applies without a restart.
173
- * @returns `true` when the service, namespace, or value is absent.
350
+ * @returns the live boolean, or `true` when the entry config is not bound.
174
351
  */
175
- export declare function currentRememberPreset(ctx: Context): boolean;
352
+ export declare function readRememberPreset(_ctx: Context): boolean;
176
353
  /**
177
- * Explicit session-management overrides as the user wrote them in
178
- * settings.yaml — the raw `user` layer of the descriptor, NOT the resolved
179
- * value. This distinction is the precedence seam: the resolved value bakes
180
- * the schema defaults in (a missing `retention.maxCount` resolves to 100),
181
- * so reading it would make the defaults outrank the DSH_TUI_RETENTION and
182
- * DSH_TUI_RESUME environment variables; only a
183
- * field PRESENT in the user layer is an explicit override
184
- * (`settings.yaml explicit > env > default`, honored by
185
- * `resolveRetentionConfig` / `resolveResumeConfig`). Fields stay `unknown`
186
- * — a hand-edited document can carry anything, and the resolvers narrow
187
- * per field with one stderr line on garbage.
354
+ * Explicit session-management overrides as the user wrote them into the
355
+ * profile patch (entry `dsh-tui` → `config:`) — the raw `user` layer of the
356
+ * settings descriptor, NOT the resolved value. This distinction is the
357
+ * precedence seam: the resolved value bakes the schema defaults in (a missing
358
+ * `retention.maxCount` resolves to 100), so reading it would make the
359
+ * defaults outrank the DSH_TUI_RETENTION and DSH_TUI_RESUME environment
360
+ * variables; only a field PRESENT in the user layer is an explicit override
361
+ * (`settings explicit > env > default`, honored by `resolveRetentionConfig` /
362
+ * `resolveResumeConfig`). Fields stay `unknown` — a hand-edited document can
363
+ * carry anything, and the resolvers narrow per field with one stderr line on
364
+ * garbage. The user layer rides `settings.describe()` — the only public
365
+ * channel for the raw explicit layer (volatile `.get()` reads expose the
366
+ * RESOLVED value only).
188
367
  */
189
368
  export interface SessionManagementExplicit {
190
369
  retention?: {
@@ -198,27 +377,25 @@ export interface SessionManagementExplicit {
198
377
  };
199
378
  }
200
379
  /**
201
- * Read the explicit `dsh-tui.retention` / `dsh-tui.resume` sections from
202
- * the settings document's user layer (see `SessionManagementExplicit`).
203
- * Awaits the namespace registration bounded (same plumbing as the theme
204
- * readers), so the startup retention pass can call it without hanging a
205
- * settings-less deployment.
380
+ * Read the explicit `dsh-tui.retention` / `dsh-tui.resume` sections from the
381
+ * settings document's user layer (see `SessionManagementExplicit`).
206
382
  *
383
+ * @param ctx - plugin context.
207
384
  * @returns ALWAYS the two-key shape — a section absent from the user
208
- * layer (or the whole service/namespace missing) reads as
385
+ * layer (or the whole service/entry missing) reads as
209
386
  * `{ retention: undefined, resume: undefined }`, never a bare
210
387
  * `undefined`, so callers destructure one stable shape. "Nothing
211
388
  * explicitly configured" (env/defaults govern) and "nothing to read at
212
389
  * all" are the same outcome for every consumer.
213
390
  */
214
- export declare function readSessionManagementExplicit(ctx: Context): Promise<SessionManagementExplicit>;
391
+ export declare function readSessionManagementExplicit(ctx: Context): SessionManagementExplicit;
215
392
  /**
216
393
  * Raw user-layer `dsh-tui.askUser` section — the explicit ask-user timeout
217
- * overrides as written in settings.yaml (see `readSessionManagementExplicit`
218
- * for why the USER layer, not the resolved value, is the precedence seam:
219
- * the resolved value's schema defaults must not shadow the
220
- * DSH_TUI_ASK_USER_* environment variables). `undefined` = nothing
221
- * explicitly configured (env/defaults govern).
394
+ * overrides as written into the profile patch (see
395
+ * `readSessionManagementExplicit` for why the USER layer, not the resolved
396
+ * value, is the precedence seam: the resolved value's schema defaults must
397
+ * not shadow the DSH_TUI_ASK_USER_* environment variables). `undefined` =
398
+ * nothing explicitly configured (env/defaults govern).
222
399
  */
223
400
  export interface AskUserTimeoutExplicit {
224
401
  idleMinutes?: unknown;
@@ -226,70 +403,88 @@ export interface AskUserTimeoutExplicit {
226
403
  }
227
404
  /**
228
405
  * Read the explicit `dsh-tui.askUser` section from the settings document's
229
- * user layer. Awaits the namespace registration bounded (same plumbing as
230
- * `readSessionManagementExplicit`), so an ask arriving during startup
231
- * cannot hang on a settings-less deployment. Returns `undefined` when the
232
- * section, the user layer, the namespace, or the whole service is absent —
233
- * "nothing explicitly configured" for the ask-user resolver.
406
+ * user layer. Returns `undefined` when the section, the user layer, the
407
+ * entry, or the whole service is absent — "nothing explicitly configured"
408
+ * for the ask-user resolver.
409
+ */
410
+ export declare function readAskUserExplicit(ctx: Context): AskUserTimeoutExplicit | undefined;
411
+ /**
412
+ * Read the currently persisted footer-hint selection, synchronously — the
413
+ * live volatile reference, so a committed change applies on the next read.
414
+ * @returns DEFAULT_FOOTER_HINTS when the entry config is not bound.
234
415
  */
235
- export declare function readAskUserExplicit(ctx: Context): Promise<AskUserTimeoutExplicit | undefined>;
416
+ export declare function currentFooterHints(_ctx: Context): FooterHints;
236
417
  /**
237
- * Read the currently persisted footer-hint selection, synchronously.
238
- * Unlike `readFooterHintsPreference` (the startup snapshot), this does not
239
- * wait for the namespace registration - it describes whatever the settings
240
- * service exposes right now, so a caller can honor a live change immediately.
241
- * @returns DEFAULT_FOOTER_HINTS when the service, namespace, or value is absent.
418
+ * Read the currently persisted footer CH mode, synchronously — the footer
419
+ * calls it on every render, so a committed change applies on the next repaint.
420
+ * @returns DEFAULT_CACHE_HIT_MODE when the entry config is not bound.
242
421
  */
243
- export declare function currentFooterHints(ctx: Context): FooterHints;
422
+ export declare function currentCacheHitMode(_ctx: Context): CacheHitMode;
244
423
  /**
245
- * Read the currently persisted footer CH mode, synchronously. Unlike a
246
- * startup snapshot, this describes whatever the settings service exposes
247
- * right now — the footer calls it on every render, so a committed change
248
- * (the /settings browser, an external edit) applies on the next repaint.
249
- * @returns DEFAULT_CACHE_HIT_MODE when the service, namespace, or value is absent.
424
+ * Read the currently persisted theme preference, synchronously — the /theme
425
+ * picker preselects the live value.
426
+ * @returns 'auto' when the entry config is not bound.
250
427
  */
251
- export declare function currentCacheHitMode(ctx: Context): CacheHitMode;
428
+ export declare function currentThemePreference(_ctx: Context): ThemePreference;
252
429
  /**
253
- * Read the currently persisted theme preference, synchronously.
254
- * Unlike `readThemePreference` (the startup snapshot), this does not wait for
255
- * the namespace registration — it describes whatever the settings service
256
- * exposes right now, so the `/theme` picker preselects the live value, which
257
- * may have changed since startup (e.g. through the /settings browser).
258
- * @returns 'auto' when the service, namespace, or value cannot be read.
430
+ * Read the currently persisted preset-memory toggle, synchronously — the
431
+ * /preset switch path calls it at every commit, so a `/settings` toggle
432
+ * applies immediately.
433
+ * @returns `true` when the entry config is not bound.
259
434
  */
260
- export declare function currentThemePreference(ctx: Context): ThemePreference;
435
+ export declare function currentRememberPreset(_ctx: Context): boolean;
261
436
  /**
262
- * Persist the theme preference to the `dsh-tui` settings namespace. The
263
- * namespace is `applies: 'live'`, so the commit (observed through the
264
- * registration's watch hook) hot-applies the change to the running TUI.
437
+ * Persist the theme preference to the `dsh-tui` entry config. Volatile-only
438
+ * write: the commit hot-applies to the running TUI through the
439
+ * `settings/document-updated` subscription.
265
440
  * @returns undefined on success, the failure message otherwise.
266
441
  */
267
442
  export declare function writeThemePreference(ctx: Context, pref: ThemePreference): Promise<string | undefined>;
268
443
  /**
269
- * Persist the UI language to the `dsh-tui` settings namespace. The namespace
270
- * is `applies: 'live'`, so the commit (observed through the registration's
271
- * watch hook) hot-applies the language to the running TUI.
444
+ * Persist the UI language to the `dsh-tui` entry config. Volatile-only
445
+ * write: the commit hot-applies to the running TUI.
272
446
  * @returns undefined on success, the failure message otherwise.
273
447
  */
274
448
  export declare function writeLanguagePreference(ctx: Context, id: string): Promise<string | undefined>;
275
449
  /**
276
- * Read the currently resolved subagent limits, synchronously. Unlike the
277
- * startup-snapshot readers, this does not wait for the namespace registration
278
- * — it describes whatever the settings service exposes right now, so every
279
- * policy decision (the guard at each spawn, `onRoundCount` at each child
280
- * assistant message)
281
- * reflects the latest committed value without a watcher. Missing settings
282
- * service or namespace, or a non-integer/negative field, degrades to the
283
- * defaults — a settings-less deployment keeps the documented caps.
450
+ * Read the currently resolved subagent limits, synchronously — the live
451
+ * volatile references, so every policy decision (the guard at each spawn,
452
+ * `onRoundCount` at each child assistant message) reflects the latest
453
+ * committed value without a watcher. An unbound entry config or a
454
+ * non-integer/negative field degrades to the defaults — a config-less
455
+ * deployment keeps the documented caps.
456
+ */
457
+ export declare function readSubagentLimits(_ctx: Context): SubagentLimits;
458
+ /**
459
+ * The OFFICIAL dsh-subagent plugin's own caps (dsh 0.1.7: `static Config`
460
+ * with volatile `maxActiveSubagents` — concurrent continuable children,
461
+ * default 8 — and `maxDepth` — default delegation depth, default 1). These
462
+ * are the host-side concurrency/depth limits that compose with — and are
463
+ * independent of — this TUI's own maxAgents/maxRounds policy knobs. This
464
+ * reader is DISPLAY-ONLY (the /agents limits panel shows the currently
465
+ * effective official caps; editing them belongs to /settings, which owns
466
+ * the `subagent` entry).
467
+ */
468
+ export interface OfficialSubagentLimits {
469
+ /** Live official concurrent-children cap; undefined = entry not readable. */
470
+ maxActiveSubagents: number | undefined;
471
+ /** Live official delegation depth; undefined = entry not readable. */
472
+ maxDepth: number | undefined;
473
+ }
474
+ /**
475
+ * Read the official `subagent` entry's resolved config through the settings
476
+ * forms descriptor (the only public channel for ANOTHER entry's live
477
+ * values). Best-effort: no settings service, no such entry, or a malformed
478
+ * value reads as `undefined` per field — the panel then annotates the row
479
+ * instead of showing a number it cannot vouch for.
284
480
  */
285
- export declare function readSubagentLimits(ctx: Context): SubagentLimits;
481
+ export declare function readOfficialSubagentLimits(ctx: Context): OfficialSubagentLimits;
286
482
  /**
287
483
  * Persist one subagent policy knob (maxAgents, maxRounds, or disableSubagent)
288
- * to the `dsh-tui` settings namespace. The namespace is `applies: 'live'`, so
289
- * the commit hot-applies without a restart — the policy reads
290
- * `readSubagentLimits` at the next decision point. Never throws: a deployment
291
- * without the settings provider, or an unregistered namespace, surfaces a
292
- * failure message for the caller.
484
+ * to the `dsh-tui` entry config. Volatile-only write: the commit hot-applies
485
+ * without a restart — the policy reads `readSubagentLimits` at the next
486
+ * decision point. Never throws: a deployment without the settings service
487
+ * surfaces a failure message for the caller.
293
488
  * @returns undefined on success, the failure message otherwise.
294
489
  */
295
490
  export declare function writeSubagentLimit(ctx: Context, key: 'maxAgents' | 'maxRounds' | 'maxRoundsGrace' | 'disableSubagent' | 'registeredOnly', value: number | boolean): Promise<string | undefined>;
@@ -301,17 +496,16 @@ export interface ModelPrefs {
301
496
  hiddenModels: string[];
302
497
  }
303
498
  /**
304
- * Read the persisted model favorites/hiddens (the startup snapshot). Both
305
- * lists narrow through `narrowStringList` — a malformed or missing field
306
- * degrades to an empty list.
499
+ * Read the persisted model favorites/hiddens. Both lists narrow through
500
+ * `narrowStringList` — a malformed field degrades to an empty list.
307
501
  */
308
- export declare function readModelPrefs(ctx: Context): Promise<ModelPrefs>;
502
+ export declare function readModelPrefs(_ctx: Context): ModelPrefs;
309
503
  /**
310
504
  * Persist one model pref list (favoriteModels or hiddenModels) to the
311
- * `dsh-tui` settings namespace via `settings.mutate` (optimistic concurrency,
312
- * one retry on `SettingsConflictError`) — never a whole-file rewrite. The
313
- * caller invokes this on every f/h toggle, so each press lands immediately.
314
- * Best-effort: a deployment without the settings provider surfaces the
505
+ * `dsh-tui` entry config via `settings.mutate` (optimistic concurrency, one
506
+ * retry on `SettingsConflictError`) — never a whole-file rewrite. The caller
507
+ * invokes this on every f/h toggle, so each press lands immediately.
508
+ * Best-effort: a deployment without the settings service surfaces the
315
509
  * failure message; the in-panel state stays session-local either way.
316
510
  * @returns undefined on success, the failure message otherwise.
317
511
  */