@aiwayds/dsh-tui-pi 2.20.0 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -8
- package/README.zh-CN.md +19 -8
- package/cordis.patch.yml +11 -2
- package/icon.svg +7 -0
- package/lib/agents.js +23 -3
- package/lib/agents.js.map +1 -1
- package/lib/btw-overlay.d.ts +18 -2
- package/lib/btw-overlay.js +55 -15
- package/lib/btw-overlay.js.map +1 -1
- package/lib/btw.d.ts +43 -5
- package/lib/btw.js +40 -6
- package/lib/btw.js.map +1 -1
- package/lib/dsh-events.d.ts +23 -9
- package/lib/dsh-events.js +20 -8
- package/lib/dsh-events.js.map +1 -1
- package/lib/history.d.ts +8 -2
- package/lib/history.js +4 -1
- package/lib/history.js.map +1 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.js +119 -61
- package/lib/index.js.map +1 -1
- package/lib/live-widgets.js +6 -3
- package/lib/live-widgets.js.map +1 -1
- package/lib/login.js.map +1 -1
- package/lib/messages.d.ts +10 -0
- package/lib/messages.js +39 -0
- package/lib/messages.js.map +1 -1
- package/lib/preset.d.ts +128 -58
- package/lib/preset.js +208 -113
- package/lib/preset.js.map +1 -1
- package/lib/remote-tail.js +3 -0
- package/lib/remote-tail.js.map +1 -1
- package/lib/selectors.d.ts +4 -1
- package/lib/selectors.js +8 -3
- package/lib/selectors.js.map +1 -1
- package/lib/session.d.ts +3 -1
- package/lib/session.js +16 -11
- package/lib/session.js.map +1 -1
- package/lib/sessions.d.ts +7 -0
- package/lib/sessions.js +15 -1
- package/lib/sessions.js.map +1 -1
- package/lib/settings.d.ts +17 -11
- package/lib/settings.js +35 -26
- package/lib/settings.js.map +1 -1
- package/lib/source-kind.d.ts +26 -0
- package/lib/source-kind.js +17 -0
- package/lib/source-kind.js.map +1 -0
- package/lib/subagent-policy.js +1 -1
- package/lib/subagent-policy.js.map +1 -1
- package/lib/subagent-viewer.d.ts +3 -3
- package/lib/subagent-viewer.js +9 -6
- package/lib/subagent-viewer.js.map +1 -1
- package/lib/theme-settings.d.ts +353 -159
- package/lib/theme-settings.js +258 -336
- package/lib/theme-settings.js.map +1 -1
- package/lib/tokens.d.ts +5 -3
- package/lib/tokens.js +5 -8
- package/lib/tokens.js.map +1 -1
- package/locale/en.json +6 -0
- package/locale/ja.json +6 -0
- package/locale/ko.json +6 -0
- package/locale/zh-CN.json +6 -0
- package/locales/en.json +7 -2
- package/locales/ja.json +7 -2
- package/locales/ko.json +7 -2
- package/locales/zh-CN.json +7 -2
- package/package.json +22 -16
- package/scripts/diagnose-container-tui.sh +3 -3
- package/scripts/smoke-boot.mjs +2 -2
- package/skills/dsh-tui-pi-config/SKILL.md +11 -7
package/lib/index.js
CHANGED
|
@@ -28,7 +28,12 @@ import { AGENT_TICK_MS, LiveWidgets } from "./live-widgets.js";
|
|
|
28
28
|
import { displayPermissionPreset } from "./permission.js";
|
|
29
29
|
import { pickEffort, pickModel, pickPermission, pickPreset, pickTheme } from "./selectors.js";
|
|
30
30
|
import { DshSessionBridge, persistDefaultModel, stashSessionIdForReload, takeStashedSessionId } from "./session.js";
|
|
31
|
-
import { currentCacheHitMode, currentRememberPreset, currentThemePreference, readAskUserExplicit, readFooterHintsPreference, readIconSetPreference, readLanguagePreference, readPanelHeightPreference, readRememberPreset, readSessionManagementExplicit, readSubagentLimits, readThemePreference,
|
|
31
|
+
import { bindTuiConfig, currentCacheHitMode, currentRememberPreset, currentThemePreference, readAskUserExplicit, readFooterHintsPreference, readIconSetPreference, readLanguagePreference, readPanelHeightPreference, readRememberPreset, readSessionManagementExplicit, readSubagentLimits, readThemePreference, subscribeThemeSettings, writeLanguagePreference, writeThemePreference, } from "./theme-settings.js";
|
|
32
|
+
// The plugin's user-facing configuration schema. Exported at the module root:
|
|
33
|
+
// the loader reads `plugin.Config` off the entry module and projects every
|
|
34
|
+
// `.volatile()` field into the settings surface (the 0.1.7 replacement of the
|
|
35
|
+
// 0.1.5 runtime registration call).
|
|
36
|
+
export { Config } from "./theme-settings.js";
|
|
32
37
|
import { currentLocale, initI18n, listLocales, setLocale, t } from "./i18n/index.js";
|
|
33
38
|
import { loadWorkspacePresets, rememberedPresetFor, saveWorkspacePresets, withRememberedPreset, workspacePresetsPath, } from "./workspace-presets.js";
|
|
34
39
|
import { applyIconSet, resolveIconSet, stopIcon } from "./icons.js";
|
|
@@ -102,7 +107,7 @@ const SKILL_RESOURCE_BASE = {
|
|
|
102
107
|
};
|
|
103
108
|
const SKILL_INVOCATION = { modelInvocable: true, userInvocable: true };
|
|
104
109
|
/** Routing description; must stay identical to the SKILL.md frontmatter (asserted in tests). */
|
|
105
|
-
const SKILL_DESCRIPTION = 'dsh TUI 增强套件使用与配置指南。凡涉及 TUI 主题/面板/footer、界面语言、子代理并发与轮数限制、模型收藏与隐藏、会话保留与 /resume 过滤、ask_user 超时、preset 记忆,或要配置 dsh-tui
|
|
110
|
+
const SKILL_DESCRIPTION = 'dsh TUI 增强套件使用与配置指南。凡涉及 TUI 主题/面板/footer、界面语言、子代理并发与轮数限制、模型收藏与隐藏、会话保留与 /resume 过滤、ask_user 超时、preset 记忆,或要配置 dsh-tui 段时先读本指南:插件配置 entry `dsh-tui` 的 17 键(language/theme/panelHeight/maxAgents/maxRounds/maxRoundsGrace/disableSubagent/registeredOnly/footerHints/cacheHitMode/iconSet/rememberPreset/favoriteModels/hiddenModels/retention/resume/askUser)、DSH_TUI_* 环境变量、快速上手向导、keybindings.json 与 /hotkeys。触发词:tui、主题、theme、面板、footer、语言、language、收藏模型、隐藏模型、保留策略、panelHeight、resume、preset。';
|
|
106
111
|
const SKILL_CANDIDATE = {
|
|
107
112
|
name: SKILL_PROVIDER_NAME,
|
|
108
113
|
description: SKILL_DESCRIPTION,
|
|
@@ -155,7 +160,14 @@ export function stripFrontmatter(raw) {
|
|
|
155
160
|
}
|
|
156
161
|
return raw;
|
|
157
162
|
}
|
|
158
|
-
export function apply(ctx) {
|
|
163
|
+
export function apply(ctx, config) {
|
|
164
|
+
// Bind the loader-resolved entry config: every field is a live Volatile
|
|
165
|
+
// reference the loader swaps in place on a volatile-only commit, so every
|
|
166
|
+
// theme-settings reader (readThemePreference, readSubagentLimits, …) sees
|
|
167
|
+
// the latest committed values through `.get()` from here on. A test driving
|
|
168
|
+
// `apply(ctx)` without a loader passes nothing — the readers then degrade
|
|
169
|
+
// to the schema defaults.
|
|
170
|
+
bindTuiConfig(config);
|
|
159
171
|
// Host floor guard, before any side effect: a host older than the peer
|
|
160
172
|
// floor would only crash deeper in boot with raw TypeErrors (the
|
|
161
173
|
// alpha-era and rc/stable-era host APIs diverged), so warn in plain
|
|
@@ -180,7 +192,7 @@ export function apply(ctx) {
|
|
|
180
192
|
let handle;
|
|
181
193
|
// Theme registry: bundled themes/ plus $DSH_HOME/themes (user overrides
|
|
182
194
|
// bundled by name). Built ONCE per apply() and handed to every resolveTheme
|
|
183
|
-
// / pickTheme call site (startup, the settings
|
|
195
|
+
// / pickTheme call site (startup, the settings hot-reload sink, the /theme
|
|
184
196
|
// handler), so a custom theme named by DSH_TUI_THEME or by the persisted
|
|
185
197
|
// preference resolves through the same snapshot. `themeUserNames` marks
|
|
186
198
|
// which registry ids are user-owned (for the picker's "user theme" /
|
|
@@ -209,26 +221,27 @@ export function apply(ctx) {
|
|
|
209
221
|
void ensureAppendSystemFile();
|
|
210
222
|
void migrateAgentsMdTodoSection();
|
|
211
223
|
/**
|
|
212
|
-
* Live theme hot-reload sink, wired to the settings
|
|
224
|
+
* Live theme hot-reload sink, wired to the settings/document-updated
|
|
225
|
+
* subscription: a committed
|
|
213
226
|
* `dsh-tui` theme change (this TUI's /theme write included) is applied to
|
|
214
227
|
* the running TUI. Set inside runTui once the renderer exists; the first
|
|
215
228
|
* commit can only follow a user write, long after startup.
|
|
216
229
|
*/
|
|
217
230
|
let applyThemeRef;
|
|
218
231
|
/**
|
|
219
|
-
* Live panel-height hot-reload sink, wired to the same
|
|
232
|
+
* Live panel-height hot-reload sink, wired to the same subscription: a
|
|
220
233
|
* committed `dsh-tui` panelHeight change re-budgets the fixed think/tool
|
|
221
234
|
* panels above the chat input. Armed inside runTui once the widgets exist.
|
|
222
235
|
*/
|
|
223
236
|
let applyPanelHeightRef;
|
|
224
237
|
/**
|
|
225
|
-
* Live footer-hints hot-reload sink, wired to the same
|
|
238
|
+
* Live footer-hints hot-reload sink, wired to the same subscription: a
|
|
226
239
|
* committed `dsh-tui` footerHints change repaints the footer hint bar with
|
|
227
240
|
* the new segment selection. Armed inside runTui once the TUI exists.
|
|
228
241
|
*/
|
|
229
242
|
let applyFooterHintsRef;
|
|
230
243
|
/**
|
|
231
|
-
* Live icon-set hot-reload sink, wired to the same
|
|
244
|
+
* Live icon-set hot-reload sink, wired to the same subscription: a committed
|
|
232
245
|
* `dsh-tui` iconSet change re-resolves the risky glyphs (an 'auto' change
|
|
233
246
|
* resolves against the startup font-detection snapshot) and repaints the
|
|
234
247
|
* footer/notices/panels that carry them. Armed inside runTui once the TUI
|
|
@@ -238,19 +251,19 @@ export function apply(ctx) {
|
|
|
238
251
|
ctx.effect(async () => {
|
|
239
252
|
// The theme bundle is built once at TUI startup and held by every
|
|
240
253
|
// component, so the persisted preference must land before startTui — the
|
|
241
|
-
//
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
// external edit) hot-
|
|
246
|
-
// applyFooterHintsRef.
|
|
254
|
+
// startup readers resolve the bound entry config synchronously (volatile
|
|
255
|
+
// references, already seeded by the loader before apply ran; a
|
|
256
|
+
// config-less deployment degrades to the schema defaults). The
|
|
257
|
+
// subscription below keeps later commits (the /theme picker, the
|
|
258
|
+
// /settings browser, an external patch edit) hot-applying through
|
|
259
|
+
// applyThemeRef / applyPanelHeightRef / applyFooterHintsRef.
|
|
247
260
|
// Panel height FIRST, theme second: a single commit of both fields (a
|
|
248
|
-
//
|
|
261
|
+
// config reset, an external edit) must not replay at the wrong
|
|
249
262
|
// height. setPanelHeight re-budgets the fixed think/tool panels; the
|
|
250
263
|
// setTheme replay that follows already renders at that new height.
|
|
251
264
|
// applyTheme carries the theme-bundle identity guard, so a height-only
|
|
252
265
|
// commit never triggers a second rebuild.
|
|
253
|
-
|
|
266
|
+
subscribeThemeSettings(ctx, (pref, height, footerHints, iconSet, language) => {
|
|
254
267
|
setLocale(language);
|
|
255
268
|
applyPanelHeightRef?.(height);
|
|
256
269
|
applyThemeRef?.(pref);
|
|
@@ -259,15 +272,13 @@ export function apply(ctx) {
|
|
|
259
272
|
});
|
|
260
273
|
// Session log retention (async, fire-and-forget): prune jsonl session
|
|
261
274
|
// directories outside the retention window so the store the core only
|
|
262
|
-
// appends to never grows unbounded. Fired AFTER
|
|
275
|
+
// appends to never grows unbounded. Fired AFTER subscribeThemeSettings —
|
|
263
276
|
// the janitor resolves its knobs through the precedence chain
|
|
264
|
-
// (settings
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
//
|
|
269
|
-
// TUI's sink, see setNoticeSink below); process-global one-shot so a
|
|
270
|
-
// /reload re-running apply does not start a second pass
|
|
277
|
+
// (settings explicit > env > default), where the explicit layer rides the
|
|
278
|
+
// settings service's describe() (readSettings below). Silent and
|
|
279
|
+
// non-fatal; the pass reports its result through the shared notice bridge
|
|
280
|
+
// (deferred to the TUI's sink, see setNoticeSink below); process-global
|
|
281
|
+
// one-shot so a /reload re-running apply does not start a second pass
|
|
271
282
|
// (src/retention.ts).
|
|
272
283
|
void runSessionRetentionOnce({
|
|
273
284
|
getSessionId: () => {
|
|
@@ -282,9 +293,9 @@ export function apply(ctx) {
|
|
|
282
293
|
const id = bridgeRef?.getResumingSessionId();
|
|
283
294
|
return id === undefined ? undefined : String(id);
|
|
284
295
|
},
|
|
285
|
-
// Explicit dsh-tui.retention overrides from
|
|
286
|
-
// layer —
|
|
287
|
-
//
|
|
296
|
+
// Explicit dsh-tui.retention overrides from the profile patch (the
|
|
297
|
+
// descriptor's user layer — a settings-less deployment degrades to
|
|
298
|
+
// env/defaults).
|
|
288
299
|
readSettings: async () => (await readSessionManagementExplicit(ctx))?.retention,
|
|
289
300
|
});
|
|
290
301
|
const themePreference = await readThemePreference(ctx);
|
|
@@ -292,9 +303,9 @@ export function apply(ctx) {
|
|
|
292
303
|
const footerHints = await readFooterHintsPreference(ctx);
|
|
293
304
|
// UI language (`dsh-tui.language`, default 'en'): discover the language
|
|
294
305
|
// files and activate the persisted id BEFORE the TUI's first frame, so
|
|
295
|
-
// the boot UI speaks it from the start. The
|
|
296
|
-
// re-applies later commits live via setLocale. An unknown id
|
|
297
|
-
// 'en' inside initI18n.
|
|
306
|
+
// the boot UI speaks it from the start. The settings/document-updated
|
|
307
|
+
// subscription re-applies later commits live via setLocale. An unknown id
|
|
308
|
+
// degrades to 'en' inside initI18n.
|
|
298
309
|
initI18n({ id: await readLanguagePreference(ctx), warn: message => emitNotice(message) });
|
|
299
310
|
// Icon-set self-adaptation: probe the platform once at startup (the
|
|
300
311
|
// memoised snapshot shared with every later 'auto' resolution), resolve
|
|
@@ -304,7 +315,7 @@ export function apply(ctx) {
|
|
|
304
315
|
const iconSetPreference = await readIconSetPreference(ctx);
|
|
305
316
|
const nerdfontAvailable = await detectNerdFontAvailable();
|
|
306
317
|
applyIconSet(resolveIconSet(iconSetPreference, nerdfontAvailable));
|
|
307
|
-
const presetRoster = await fetchPresetRoster();
|
|
318
|
+
const presetRoster = await fetchPresetRoster(ctx);
|
|
308
319
|
// Preset memory (`dsh-tui.rememberPreset`, default ON): the last /preset
|
|
309
320
|
// selection committed in THIS workspace (keyed by the session backend's
|
|
310
321
|
// project key of the cwd) becomes the launch selection — runTui seeds it
|
|
@@ -357,21 +368,22 @@ export function apply(ctx) {
|
|
|
357
368
|
const keyBindings = loadKeyBindings(keyFile);
|
|
358
369
|
// Preset state: /preset owns the selection (Tab is deliberately unbound —
|
|
359
370
|
// switching is an explicit, confirmed action). The roster is fetched once
|
|
360
|
-
// at startup from the
|
|
361
|
-
// presets)
|
|
371
|
+
// at startup from the host's `agentPresets` registry (dsh 0.1.7
|
|
372
|
+
// declarative presets); an empty roster (no service / no presets)
|
|
373
|
+
// disables the feature gracefully (/preset errors, footer shows
|
|
362
374
|
// plain "dsh"). The initial selection is the workspace's REMEMBERED
|
|
363
375
|
// preset when preset memory is on and the id is still on the roster
|
|
364
|
-
// (initialPresetIndex prefers it), else the
|
|
365
|
-
// first-
|
|
366
|
-
// display only: before the user switches via
|
|
367
|
-
// `meta.agentPreset` is sent at session create, so the
|
|
368
|
-
// default (`
|
|
369
|
-
// governs. WITH memory the remembered
|
|
370
|
-
// below (bridge.setAgentPreset), which
|
|
371
|
-
//
|
|
372
|
-
// default. We deliberately seed ONLY a
|
|
373
|
-
// DEFAULT_PRESET_ID — that would override the
|
|
374
|
-
// a client-side assumption.
|
|
376
|
+
// (initialPresetIndex prefers it), else the roster's own default row,
|
|
377
|
+
// else `standard`, else the first-listed one. Without memory the launch
|
|
378
|
+
// selection is a local display only: before the user switches via
|
|
379
|
+
// /preset, NO `meta.agentPreset` is sent at session create, so the
|
|
380
|
+
// registry's deployment default (`default`/`selectedDefault` config of
|
|
381
|
+
// the agent-preset-registry entry) governs. WITH memory the remembered
|
|
382
|
+
// id is ALSO seeded into the bridge below (bridge.setAgentPreset), which
|
|
383
|
+
// is the point: the first session of the launch composes under the
|
|
384
|
+
// remembered preset, not the server default. We deliberately seed ONLY a
|
|
385
|
+
// remembered id, never DEFAULT_PRESET_ID — that would override the
|
|
386
|
+
// server-side default with a client-side assumption.
|
|
375
387
|
const rememberedPresetEntry = rememberedPresetId !== undefined
|
|
376
388
|
? presetRoster.find(preset => preset.id === rememberedPresetId)
|
|
377
389
|
: undefined;
|
|
@@ -606,7 +618,7 @@ export function apply(ctx) {
|
|
|
606
618
|
if (!cancelled && stoppedChildren === 0)
|
|
607
619
|
renderer.renderNotice(t('tui.stop.nothingRunning'), 'info');
|
|
608
620
|
};
|
|
609
|
-
// Arm the settings
|
|
621
|
+
// Arm the settings hot-reload sink now that the renderer exists (see apply()).
|
|
610
622
|
applyThemeRef = (pref) => {
|
|
611
623
|
themePreferenceRef = pref;
|
|
612
624
|
// 'auto' subscribes to the terminal's live color-scheme pushes; an
|
|
@@ -621,8 +633,7 @@ export function apply(ctx) {
|
|
|
621
633
|
renderer.renderNotice(t('tui.keys.warningPrefix', { warning }), 'error');
|
|
622
634
|
}
|
|
623
635
|
// Arm the shared notice sink now that the TUI is up. Every operator
|
|
624
|
-
// trace that fired before this point —
|
|
625
|
-
// registration failure, invalid dsh-tui.retention/resume values, a
|
|
636
|
+
// trace that fired before this point — invalid dsh-tui.retention/resume values, a
|
|
626
637
|
// missing userQuestions service, the janitor's result line — has been
|
|
627
638
|
// queueing on the bridge (src/notice-bridge.ts); registering here
|
|
628
639
|
// drains that batch as stacked transient notices above the footer
|
|
@@ -641,7 +652,7 @@ export function apply(ctx) {
|
|
|
641
652
|
// Live maxRounds for the compact running-agent lines' `round N/M` — read
|
|
642
653
|
// at every rebuild (the /agents limits panel hot-applies).
|
|
643
654
|
() => readSubagentLimits(ctx).maxRounds);
|
|
644
|
-
// Arm the panel-height
|
|
655
|
+
// Arm the panel-height hot-reload sink now that the widgets exist: a committed
|
|
645
656
|
// panelHeight change re-budgets the think/tool panels — they are
|
|
646
657
|
// self-drawing, so the next frame already renders at the new height.
|
|
647
658
|
applyPanelHeightRef = (height) => {
|
|
@@ -744,6 +755,10 @@ export function apply(ctx) {
|
|
|
744
755
|
liveWidgets.clear();
|
|
745
756
|
const session = resumed.agent.session;
|
|
746
757
|
const adopted = 'adopted' in resumed && resumed.adopted === true;
|
|
758
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
759
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
760
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
761
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
747
762
|
bridge.replay(adopted ? session.snapshotEvents() : session.snapshotEvents().filter(event => event.seq < session.firstLiveSeq));
|
|
748
763
|
for (const text of bridge.takePendingRemoteFollowups()) {
|
|
749
764
|
await bridge.prompt(text);
|
|
@@ -768,7 +783,7 @@ export function apply(ctx) {
|
|
|
768
783
|
// child's cap and hard-stops it after the grace window — the per-agent
|
|
769
784
|
// tier reads the agent file's frontmatter `maxRounds` through the
|
|
770
785
|
// registry contract. Limits are read live from the `dsh-tui` settings
|
|
771
|
-
//
|
|
786
|
+
// entry config (/agents → l limits).
|
|
772
787
|
const subagentPolicy = applySubagentPolicy(ctx, {
|
|
773
788
|
getLive: () => bridge.getLiveChildren(),
|
|
774
789
|
getRoundCount: childId => bridge.getRoundCount(childId),
|
|
@@ -925,6 +940,10 @@ export function apply(ctx) {
|
|
|
925
940
|
const agent = bridge.getAgent();
|
|
926
941
|
return agent === undefined
|
|
927
942
|
? []
|
|
943
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
944
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
945
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
946
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
928
947
|
: buildBtwSnapshot(agent.session.snapshotEvents(), btwSnapshotLimit);
|
|
929
948
|
},
|
|
930
949
|
requestRender: () => ui.requestRender(),
|
|
@@ -1133,6 +1152,10 @@ export function apply(ctx) {
|
|
|
1133
1152
|
// log is the stable source (dispose drops the registry handle), and
|
|
1134
1153
|
// slicing here keeps the running turn out of the seed (the same
|
|
1135
1154
|
// completed-turn rule /new obeys by cancelling it).
|
|
1155
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1156
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1157
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1158
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1136
1159
|
const seed = completedTurnSeed(agent.session.snapshotEvents());
|
|
1137
1160
|
if (seed.length === 0) {
|
|
1138
1161
|
// No completed turn to carry — a fork is indistinguishable from a
|
|
@@ -1163,6 +1186,10 @@ export function apply(ctx) {
|
|
|
1163
1186
|
// rebuild rides the same replay. `firstLiveSeq` excludes nothing
|
|
1164
1187
|
// published (constructor seeds never emit).
|
|
1165
1188
|
const session = handle.agent.session;
|
|
1189
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1190
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1191
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1192
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1166
1193
|
bridge.replay(session.snapshotEvents().filter(event => event.seq < session.firstLiveSeq));
|
|
1167
1194
|
ui.requestRender();
|
|
1168
1195
|
}
|
|
@@ -1277,9 +1304,10 @@ export function apply(ctx) {
|
|
|
1277
1304
|
let picked;
|
|
1278
1305
|
try {
|
|
1279
1306
|
const currentId = bridge.getSessionId();
|
|
1280
|
-
// Explicit dsh-tui.resume overrides from
|
|
1281
|
-
// layer): the picker resolves them against
|
|
1282
|
-
// so a committed settings change applies to
|
|
1307
|
+
// Explicit dsh-tui.resume overrides from the profile patch (the
|
|
1308
|
+
// descriptor's user layer): the picker resolves them against
|
|
1309
|
+
// env/defaults per open, so a committed settings change applies to
|
|
1310
|
+
// the next /resume.
|
|
1283
1311
|
const resumeSettings = (await readSessionManagementExplicit(ctx))?.resume;
|
|
1284
1312
|
picked = await pickPersistedSession(ctx, ui.tui, ui.theme, currentId === undefined ? undefined : String(currentId), refocusEditor, resumeSettings);
|
|
1285
1313
|
}
|
|
@@ -1371,6 +1399,10 @@ export function apply(ctx) {
|
|
|
1371
1399
|
// everything the other surface did. Cold resumes keep the firstLiveSeq
|
|
1372
1400
|
// filter (seeded history replays once; live events re-arrive).
|
|
1373
1401
|
const adopted = 'adopted' in resumed && resumed.adopted === true;
|
|
1402
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1403
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1404
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1405
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1374
1406
|
bridge.replay(adopted ? session.snapshotEvents() : session.snapshotEvents().filter(event => event.seq < session.firstLiveSeq));
|
|
1375
1407
|
ui.requestRender();
|
|
1376
1408
|
return {
|
|
@@ -1447,6 +1479,10 @@ export function apply(ctx) {
|
|
|
1447
1479
|
const id = bridge.getSessionId();
|
|
1448
1480
|
return id === undefined ? undefined : String(id);
|
|
1449
1481
|
},
|
|
1482
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1483
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1484
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1485
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1450
1486
|
getLiveEvents: () => bridge.getAgent()?.session.snapshotEvents(),
|
|
1451
1487
|
copyToEditor: text => {
|
|
1452
1488
|
ui.editor.setText(text);
|
|
@@ -1473,6 +1509,10 @@ export function apply(ctx) {
|
|
|
1473
1509
|
// the seed IS the point, so it replays in full (`firstLiveSeq`
|
|
1474
1510
|
// covers seed + end-seed).
|
|
1475
1511
|
const session = handle.agent.session;
|
|
1512
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1513
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1514
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1515
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1476
1516
|
bridge.replay(session.snapshotEvents().filter(event => event.seq < session.firstLiveSeq));
|
|
1477
1517
|
ui.requestRender();
|
|
1478
1518
|
}
|
|
@@ -1515,6 +1555,10 @@ export function apply(ctx) {
|
|
|
1515
1555
|
renderer.clear();
|
|
1516
1556
|
liveWidgets.clear();
|
|
1517
1557
|
const session = resumed.agent.session;
|
|
1558
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1559
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1560
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1561
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1518
1562
|
bridge.replay(session.snapshotEvents().filter(event => event.seq < session.firstLiveSeq));
|
|
1519
1563
|
ui.requestRender();
|
|
1520
1564
|
}
|
|
@@ -1538,6 +1582,10 @@ export function apply(ctx) {
|
|
|
1538
1582
|
renderer.clear();
|
|
1539
1583
|
liveWidgets.clear();
|
|
1540
1584
|
const session = resumed.agent.session;
|
|
1585
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1586
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1587
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1588
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1541
1589
|
bridge.replay(session.snapshotEvents().filter(event => event.seq < session.firstLiveSeq));
|
|
1542
1590
|
ui.requestRender();
|
|
1543
1591
|
}
|
|
@@ -1560,6 +1608,10 @@ export function apply(ctx) {
|
|
|
1560
1608
|
description: t('tui.cmd.export.description'),
|
|
1561
1609
|
input: { hint: '[path]' },
|
|
1562
1610
|
handler: async (invocation) => {
|
|
1611
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1612
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1613
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1614
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1563
1615
|
const events = invocation.agent.session.snapshotEvents();
|
|
1564
1616
|
const fallback = join(homedir(), 'Downloads', `dsh-session-${clipToWidth(String(invocation.agent.session.id), 8)}.jsonl`);
|
|
1565
1617
|
const target = invocation.rawInput.trim() === '' ? fallback : resolve(invocation.rawInput.trim());
|
|
@@ -1611,6 +1663,10 @@ export function apply(ctx) {
|
|
|
1611
1663
|
renderer.clear();
|
|
1612
1664
|
liveWidgets.clear();
|
|
1613
1665
|
const session = restored.agent.session;
|
|
1666
|
+
// dsh 0.1.7 soft-deprecation: snapshotEvents is deprecated upstream in favor of
|
|
1667
|
+
// projection registration / sessionPersistence.handle.read() pagination. Kept
|
|
1668
|
+
// here deliberately — this path re-consumes RAW events (renderer/stats
|
|
1669
|
+
// replay), which the projection successor does not serve. (T14 review.)
|
|
1614
1670
|
bridge.replay(session.snapshotEvents().filter(event => event.seq < session.firstLiveSeq));
|
|
1615
1671
|
}
|
|
1616
1672
|
catch (error) {
|
|
@@ -1627,7 +1683,8 @@ export function apply(ctx) {
|
|
|
1627
1683
|
registerLocalCommand('new', t('tui.cmd.new.description'), newHandler);
|
|
1628
1684
|
// /settings: text-based configuration browser — the terminal counterpart
|
|
1629
1685
|
// of the web GUI's settings surface. Enumerates ctx.settings.describe()
|
|
1630
|
-
//
|
|
1686
|
+
// (one descriptor per settings-bearing plugin entry) and walks each
|
|
1687
|
+
// entry's schema (drill-ins, cycle rows, inline editors,
|
|
1631
1688
|
// reset-to-defaults), writing through settings.mutate path ops.
|
|
1632
1689
|
const settingsHandler = async () => {
|
|
1633
1690
|
if (ctx.get('settings') === undefined) {
|
|
@@ -1665,11 +1722,12 @@ export function apply(ctx) {
|
|
|
1665
1722
|
};
|
|
1666
1723
|
registerLocalCommand('skills', t('tui.cmd.skills.description'), skillsHandler);
|
|
1667
1724
|
// /theme: pick a color scheme and apply it immediately — the choice is
|
|
1668
|
-
// persisted to the dsh-tui
|
|
1669
|
-
//
|
|
1670
|
-
// the running TUI: footer hint,
|
|
1671
|
-
// repaint on the next frame, no
|
|
1672
|
-
// mirrors /settings: without the
|
|
1725
|
+
// persisted to the dsh-tui entry config (a volatile-only write: the
|
|
1726
|
+
// document-updated subscription re-applies the same value anyway, an
|
|
1727
|
+
// idempotent echo) and hot-swapped into the running TUI: footer hint,
|
|
1728
|
+
// editor border and the whole transcript repaint on the next frame, no
|
|
1729
|
+
// restart needed. The settings guard mirrors /settings: without the
|
|
1730
|
+
// service there is nowhere to write.
|
|
1673
1731
|
const themeHandler = async () => {
|
|
1674
1732
|
if (ctx.get('settings') === undefined) {
|
|
1675
1733
|
return { kind: 'error', text: t('tui.settings.unavailable') };
|
|
@@ -1817,7 +1875,7 @@ export function apply(ctx) {
|
|
|
1817
1875
|
registerLocalCommand('login', t('tui.cmd.login.description'), loginHandler);
|
|
1818
1876
|
// /logout: unsubscribe a provider — pi-agent's /logout on the dsh side.
|
|
1819
1877
|
// Lists the providers with a stored credential; on selection removes the
|
|
1820
|
-
// key AND the
|
|
1878
|
+
// key AND the profile patch's llm-pi-ai provider entry, so the provider's models
|
|
1821
1879
|
// leave /model right away (the llm-pi-ai adapter keeps a route
|
|
1822
1880
|
// registered for every profile key). /login re-subscribes and serves
|
|
1823
1881
|
// the installed catalog's current model list.
|
|
@@ -1922,12 +1980,12 @@ export function apply(ctx) {
|
|
|
1922
1980
|
let footerHintsRef = footerHints;
|
|
1923
1981
|
const footerHint = new FooterHint(() => ui.theme, () => footerHintsRef);
|
|
1924
1982
|
ui.footer.addChild(footerHint);
|
|
1925
|
-
// Arm the footer-hints
|
|
1983
|
+
// Arm the footer-hints hot-reload sink now that the TUI exists (see apply()).
|
|
1926
1984
|
applyFooterHintsRef = (hints) => {
|
|
1927
1985
|
footerHintsRef = hints;
|
|
1928
1986
|
ui.requestRender();
|
|
1929
1987
|
};
|
|
1930
|
-
// Arm the icon-set
|
|
1988
|
+
// Arm the icon-set hot-reload sink: a committed iconSet change hot-applies the
|
|
1931
1989
|
// risky glyphs (an 'auto' change resolves against the startup font-
|
|
1932
1990
|
// detection snapshot, matching the startup glyph choice) and repaints the
|
|
1933
1991
|
// footer/notices/panels that carry them on the next frame.
|