@askdkc/dsh-cli 0.13.4 → 0.14.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/bin/{dsh-tui.js → dsh-cli.js} +27 -27
- package/cordis.patch.yml +32 -32
- package/cordis.yml +17 -17
- package/lib/types/activityPrefs.d.ts +2 -2
- package/lib/types/activityPrefs.js +2 -2
- package/lib/types/adapter/channel/actions.js +1 -1
- package/lib/types/adapter/channel/consumer.js +1 -1
- package/lib/types/adapter/channel/internal-token.js +1 -1
- package/lib/types/adapter/channel/plugins.js +1 -1
- package/lib/types/adapter/channel/session-projection.js +3 -3
- package/lib/types/adapter/channel/transcript.js +1 -1
- package/lib/types/adapter/channel/ui.js +3 -3
- package/lib/types/adapter/kernel/host-facade.d.ts +1 -1
- package/lib/types/adapter/kernel/host-facade.js +6 -6
- package/lib/types/adapter/kernel/host-probe-access.d.ts +1 -1
- package/lib/types/adapter/kernel/host-probe-access.js +6 -6
- package/lib/types/adapter/kernel/kernel-runtime.js +1 -1
- package/lib/types/adapter/kernel/legacy-facade.d.ts +1 -1
- package/lib/types/adapter/kernel/legacy-facade.js +1 -1
- package/lib/types/adapter/kernel/replay-isolation.js +1 -1
- package/lib/types/adapter/kernel/runtime.d.ts +1 -1
- package/lib/types/adapter/kernel/runtime.js +7 -7
- package/lib/types/adapter/ports/channel-display.d.ts +1 -1
- package/lib/types/adapter/ports/channel-ui.d.ts +15 -15
- package/lib/types/adapter/standard/descriptor.d.ts +1 -1
- package/lib/types/adapter/standard/descriptor.js +2 -2
- package/lib/types/adapter/standard/registry.d.ts +1 -1
- package/lib/types/adapter/standard/registry.js +2 -2
- package/lib/types/adapter/standard/tui-extension.d.ts +2 -2
- package/lib/types/adapter/standard/tui-extension.js +3 -3
- package/lib/types/adapter/upstream/channel-driver.js +10 -10
- package/lib/types/adapter/upstream/decisions-driver.js +3 -3
- package/lib/types/adapter/upstream/extensions-driver.js +18 -18
- package/lib/types/adapter/upstream/host-descriptor-driver.js +4 -4
- package/lib/types/adapter/upstream/presentation-driver.js +5 -5
- package/lib/types/adapter/upstream/scenes-driver.js +4 -4
- package/lib/types/adapter/upstream/settings-driver.js +4 -4
- package/lib/types/adapter/upstream/workspace-driver.js +2 -2
- package/lib/types/bootstrap/state.d.ts +4 -4
- package/lib/types/bootstrap/state.js +4 -4
- package/lib/types/{tuiDisplayPrefs.d.ts → cliDisplayPrefs.d.ts} +1 -1
- package/lib/types/{tuiDisplayPrefs.d.ts.map → cliDisplayPrefs.d.ts.map} +1 -1
- package/lib/types/{tuiDisplayPrefs.js → cliDisplayPrefs.js} +1 -1
- package/lib/types/commands.js +7 -7
- package/lib/types/components/AutoRecapRow.d.ts +1 -1
- package/lib/types/components/AutoRecapRow.js +1 -1
- package/lib/types/components/HelpMenu.d.ts +1 -1
- package/lib/types/components/HelpMenu.js +1 -1
- package/lib/types/components/LogoV2.d.ts +2 -2
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +5 -19
- package/lib/types/components/MermaidDiagram.js +1 -1
- package/lib/types/components/MessageList.d.ts +2 -2
- package/lib/types/components/MessageList.js +1 -1
- package/lib/types/components/PageMargin.d.ts +3 -3
- package/lib/types/components/PageMargin.js +1 -1
- package/lib/types/components/PluginSceneBoundary.d.ts +1 -1
- package/lib/types/components/PluginSceneBoundary.js +1 -1
- package/lib/types/components/PromptInput.d.ts +1 -1
- package/lib/types/components/PromptInput.js +3 -3
- package/lib/types/components/ScrollbarGutter.d.ts +1 -1
- package/lib/types/components/ScrollbarGutter.js +1 -1
- package/lib/types/components/Select.d.ts +1 -1
- package/lib/types/components/Select.js +1 -1
- package/lib/types/components/SplitDiffView.d.ts +1 -1
- package/lib/types/components/ThemePicker.d.ts +1 -1
- package/lib/types/components/ThemePicker.js +1 -1
- package/lib/types/components/activityFrames.d.ts +1 -1
- package/lib/types/components/activityFrames.js +1 -1
- package/lib/types/components/design-system/Byline.d.ts +1 -1
- package/lib/types/components/design-system/Byline.js +1 -1
- package/lib/types/components/design-system/Divider.d.ts +1 -1
- package/lib/types/components/design-system/Divider.js +1 -1
- package/lib/types/components/design-system/StatusIcon.d.ts +1 -1
- package/lib/types/components/design-system/StatusIcon.js +1 -1
- package/lib/types/components/design-system/ThemeProvider.d.ts +1 -1
- package/lib/types/components/design-system/ThemeProvider.js +11 -11
- package/lib/types/components/design-system/ThemedBox.d.ts +1 -1
- package/lib/types/components/design-system/ThemedBox.js +1 -1
- package/lib/types/components/design-system/ThemedText.d.ts +1 -1
- package/lib/types/components/design-system/ThemedText.js +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +3 -3
- package/lib/types/components/messages/AssistantToolUseMessage.js +1 -1
- package/lib/types/components/messages/originalImage.js +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +1 -1
- package/lib/types/components/smoothReveal.d.ts +1 -1
- package/lib/types/components/smoothReveal.js +1 -1
- package/lib/types/customTheme.d.ts +5 -5
- package/lib/types/customTheme.js +7 -7
- package/lib/types/dsh-adapter/activity-store.d.ts +1 -1
- package/lib/types/dsh-adapter/activity-store.js +3 -3
- package/lib/types/dsh-adapter/bundled-presets.js +2 -2
- package/lib/types/dsh-adapter/channel/action-readiness.js +2 -2
- package/lib/types/dsh-adapter/channel/agent-view-projection.js +1 -1
- package/lib/types/dsh-adapter/channel/background-action.js +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +1 -1
- package/lib/types/dsh-adapter/channel/binding.js +14 -14
- package/lib/types/dsh-adapter/channel/external-commands.js +3 -3
- package/lib/types/dsh-adapter/channel/input-delivery.js +1 -1
- package/lib/types/dsh-adapter/channel/job-projection.js +1 -1
- package/lib/types/dsh-adapter/channel/lifetime-resources.js +1 -1
- package/lib/types/dsh-adapter/channel/local-actions.js +1 -1
- package/lib/types/dsh-adapter/channel/mode-actions.js +1 -1
- package/lib/types/dsh-adapter/channel/mode-permission.js +6 -6
- package/lib/types/dsh-adapter/channel/mode-roster.js +1 -1
- package/lib/types/dsh-adapter/channel/owner.js +2 -2
- package/lib/types/dsh-adapter/channel/preferences.js +1 -1
- package/lib/types/dsh-adapter/channel/projection.js +1 -1
- package/lib/types/dsh-adapter/channel/reports.js +3 -3
- package/lib/types/dsh-adapter/channel/session-fork.js +1 -1
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts +4 -4
- package/lib/types/dsh-adapter/channel/session-metadata.js +2 -2
- package/lib/types/dsh-adapter/channel/session-rewind.js +2 -2
- package/lib/types/dsh-adapter/channel/state.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/state.js +1 -1
- package/lib/types/dsh-adapter/channel/types.d.ts +1 -1
- package/lib/types/dsh-adapter/channel-ui.js +2 -2
- package/lib/types/dsh-adapter/channel.js +9 -9
- package/lib/types/dsh-adapter/cli-registration.d.ts.map +1 -1
- package/lib/types/dsh-adapter/cli-registration.js +5 -4
- package/lib/types/dsh-adapter/command-trees.d.ts +1 -1
- package/lib/types/dsh-adapter/command-trees.js +2 -2
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +3 -3
- package/lib/types/dsh-adapter/compat/sessionLog.js +5 -5
- package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/settings.js +15 -7
- package/lib/types/dsh-adapter/decision-guard.d.ts +3 -3
- package/lib/types/dsh-adapter/decision-guard.js +6 -6
- package/lib/types/dsh-adapter/dialogs.d.ts +1 -1
- package/lib/types/dsh-adapter/dialogs.js +7 -7
- package/lib/types/dsh-adapter/effect-ledger.d.ts +2 -2
- package/lib/types/dsh-adapter/effect-ledger.js +5 -5
- package/lib/types/dsh-adapter/extension-events.js +10 -10
- package/lib/types/dsh-adapter/extensions.d.ts +3 -3
- package/lib/types/dsh-adapter/extensions.js +3 -3
- package/lib/types/dsh-adapter/host-access.js +11 -11
- package/lib/types/dsh-adapter/ide-channel.d.ts +6 -6
- package/lib/types/dsh-adapter/ide-channel.js +6 -6
- package/lib/types/dsh-adapter/index.d.ts +18 -18
- package/lib/types/dsh-adapter/index.js +5 -5
- package/lib/types/dsh-adapter/inject-channel.d.ts +4 -4
- package/lib/types/dsh-adapter/inject-channel.js +5 -5
- package/lib/types/dsh-adapter/invariant.d.ts +1 -1
- package/lib/types/dsh-adapter/invariant.js +1 -1
- package/lib/types/dsh-adapter/message-observer.d.ts +2 -2
- package/lib/types/dsh-adapter/message-observer.js +23 -23
- package/lib/types/dsh-adapter/migrate/adapters/scan.js +1 -1
- package/lib/types/dsh-adapter/migrate/bin-path.d.ts +1 -1
- package/lib/types/dsh-adapter/migrate/bin-path.js +4 -4
- package/lib/types/dsh-adapter/migrate/picker.d.ts +1 -1
- package/lib/types/dsh-adapter/migrate/picker.js +1 -1
- package/lib/types/dsh-adapter/migrate/uuid.js +1 -1
- package/lib/types/dsh-adapter/packaged-presets.js +1 -1
- package/lib/types/dsh-adapter/plugin-host.d.ts +2 -2
- package/lib/types/dsh-adapter/plugin-host.js +32 -32
- package/lib/types/dsh-adapter/plugin-storage.d.ts +3 -3
- package/lib/types/dsh-adapter/plugin-storage.js +5 -5
- package/lib/types/dsh-adapter/plugin.d.ts +4 -4
- package/lib/types/dsh-adapter/plugin.js +89 -89
- package/lib/types/dsh-adapter/preset-resolution.d.ts +1 -1
- package/lib/types/dsh-adapter/presets.js +1 -1
- package/lib/types/dsh-adapter/promptDebug.js +1 -1
- package/lib/types/dsh-adapter/questions.d.ts +1 -1
- package/lib/types/dsh-adapter/questions.js +1 -1
- package/lib/types/dsh-adapter/renderers.js +7 -7
- package/lib/types/dsh-adapter/scenes.d.ts +1 -1
- package/lib/types/dsh-adapter/scenes.js +6 -6
- package/lib/types/dsh-adapter/settings-sections.d.ts +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +5 -5
- package/lib/types/dsh-adapter/sharp.js +1 -1
- package/lib/types/dsh-adapter/shortcuts.js +9 -9
- package/lib/types/dsh-adapter/status.js +21 -21
- package/lib/types/dsh-adapter/themes.js +2 -2
- package/lib/types/dsh-adapter/toast.js +7 -7
- package/lib/types/dsh-adapter/workspaces.d.ts +1 -1
- package/lib/types/dsh-adapter/workspaces.js +6 -6
- package/lib/types/effortPrefs.d.ts +2 -2
- package/lib/types/effortPrefs.js +2 -2
- package/lib/types/force-production-react.js +1 -1
- package/lib/types/herdr.js +4 -4
- package/lib/types/homePrefs.js +1 -1
- package/lib/types/i18n.d.ts +54 -54
- package/lib/types/i18n.js +39 -39
- package/lib/types/ink/clearTerminal.d.ts +1 -1
- package/lib/types/ink/clearTerminal.js +1 -1
- package/lib/types/ink/colorize.js +1 -1
- package/lib/types/ink/components/App.d.ts +1 -1
- package/lib/types/ink/components/App.js +5 -5
- package/lib/types/ink/components/Text.d.ts +1 -1
- package/lib/types/ink/devtools.d.ts +1 -1
- package/lib/types/ink/dom.d.ts +1 -1
- package/lib/types/ink/dom.js +1 -1
- package/lib/types/ink/geometry-trace.js +4 -4
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +8 -19
- package/lib/types/ink/reconciler.d.ts +1 -1
- package/lib/types/ink/reconciler.d.ts.map +1 -1
- package/lib/types/ink/reconciler.js +6 -3
- package/lib/types/ink/render-to-screen.d.ts.map +1 -1
- package/lib/types/ink/render-to-screen.js +0 -5
- package/lib/types/ink/terminal.js +3 -3
- package/lib/types/ink/termio/osc.js +1 -1
- package/lib/types/ink/update-overflow-guard.js +2 -2
- package/lib/types/minimalMode.d.ts +2 -2
- package/lib/types/minimalMode.js +2 -2
- package/lib/types/modelGroups.d.ts +1 -1
- package/lib/types/modelGroups.js +1 -1
- package/lib/types/modelPrefs.d.ts +1 -1
- package/lib/types/modelPrefs.js +1 -1
- package/lib/types/modelRecents.d.ts +2 -2
- package/lib/types/modelRecents.js +2 -2
- package/lib/types/package-version.d.ts +3 -0
- package/lib/types/package-version.d.ts.map +1 -0
- package/lib/types/package-version.js +25 -0
- package/lib/types/presetPrefs.d.ts +1 -1
- package/lib/types/presetPrefs.js +1 -1
- package/lib/types/reload.d.ts +8 -8
- package/lib/types/reload.js +4 -4
- package/lib/types/screens/Chat.js +27 -27
- package/lib/types/screens/StatusLine.js +1 -1
- package/lib/types/screens/StatusMetrics.js +1 -1
- package/lib/types/sessionHistory.d.ts +3 -3
- package/lib/types/sessionHistory.js +7 -7
- package/lib/types/sessionModes.js +1 -1
- package/lib/types/sessionMounts.d.ts +1 -1
- package/lib/types/sessionMounts.js +1 -1
- package/lib/types/sessionPins.d.ts +1 -1
- package/lib/types/sessionPins.js +1 -1
- package/lib/types/terminal-utils/cliHighlight.d.ts +1 -1
- package/lib/types/terminal-utils/hash.d.ts +1 -1
- package/lib/types/terminal-utils/hash.js +1 -1
- package/lib/types/terminal-utils/mermaid.d.ts +1 -1
- package/lib/types/terminal-utils/syntaxTheme.js +1 -1
- package/lib/types/theme.d.ts +3 -3
- package/lib/types/theme.js +3 -3
- package/lib/types/themePrefs.d.ts +3 -3
- package/lib/types/themePrefs.js +3 -3
- package/lib/types/tips.js +4 -4
- package/lib/types/trajectory/effortIgnition.d.ts +1 -1
- package/lib/types/trajectoryPrefs.d.ts +1 -1
- package/lib/types/trajectoryPrefs.js +1 -1
- package/lib/types/ui.d.ts +1 -1
- package/lib/types/ui.js +1 -1
- package/lib/types/update.d.ts +25 -26
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +55 -73
- package/lib/types/utils/clipboard.js +1 -1
- package/lib/types/utils/credentials.js +2 -2
- package/lib/types/utils/debug.d.ts +3 -3
- package/lib/types/utils/debug.js +6 -6
- package/lib/types/utils/earlyInput.d.ts +1 -1
- package/lib/types/utils/earlyInput.js +1 -1
- package/lib/types/utils/externalEditor.js +1 -1
- package/lib/types/utils/fullscreen.d.ts +3 -3
- package/lib/types/utils/fullscreen.js +4 -4
- package/lib/types/utils/log.js +1 -1
- package/lib/types/utils/paths.d.ts +3 -3
- package/lib/types/utils/paths.js +4 -4
- package/lib/types/working-activity.js +1 -1
- package/node_modules/@askdkc/dsh-auth/dsh-plugin.json +1 -1
- package/node_modules/@askdkc/dsh-auth/lib/index.d.ts +2 -2
- package/node_modules/@askdkc/dsh-auth/lib/index.js +2 -2
- package/node_modules/@askdkc/dsh-auth/lib/pi-ai.d.ts +0 -2
- package/node_modules/@askdkc/dsh-auth/lib/pi-ai.js +0 -2
- package/node_modules/@askdkc/dsh-auth/lib/service.d.ts +1 -1
- package/node_modules/@askdkc/dsh-auth/lib/service.js +2 -2
- package/node_modules/dsh-working-activity/lib/client.js.map +1 -1
- package/node_modules/dsh-working-activity/lib/types/client/index.d.ts +1 -1
- package/node_modules/dsh-working-activity/lib/types/config.d.ts +2 -2
- package/node_modules/dsh-working-activity/lib/types/config.js +2 -2
- package/node_modules/dsh-working-activity/lib/types/frames.d.ts +1 -1
- package/node_modules/dsh-working-activity/lib/types/frames.js +1 -1
- package/node_modules/dsh-working-activity/lib/types/index.d.ts +1 -1
- package/node_modules/dsh-working-activity/lib/types/index.js +2 -2
- package/node_modules/dsh-working-activity/lib/types/lang.d.ts +5 -5
- package/node_modules/dsh-working-activity/lib/types/lang.js +8 -8
- package/node_modules/dsh-working-activity/lib/types/projection.d.ts +1 -1
- package/node_modules/dsh-working-activity/lib/types/projection.js +1 -1
- package/node_modules/dsh-working-activity/lib/types/status.d.ts +1 -1
- package/node_modules/dsh-working-activity/lib/types/status.js +1 -1
- package/node_modules/dsh-working-activity/src/client/index.ts +1 -1
- package/node_modules/dsh-working-activity/src/config.ts +2 -2
- package/node_modules/dsh-working-activity/src/frames.ts +1 -1
- package/node_modules/dsh-working-activity/src/index.ts +4 -4
- package/node_modules/dsh-working-activity/src/lang.ts +8 -8
- package/node_modules/dsh-working-activity/src/projection.ts +1 -1
- package/node_modules/dsh-working-activity/src/status.ts +1 -1
- package/package.json +8 -8
- package/presets/liangshen/agent.cordis.yml +1 -1
- package/presets/liangshen/custom-bash.mjs +2 -2
|
@@ -31,9 +31,9 @@ import { registerTuiSessionEventTypes, snapshotLiveSessionEvents } from './compa
|
|
|
31
31
|
import { clearResumeTarget, resumeCommand, resumeTargetFromArgv, writeResumeTarget } from '../sessionHistory.js';
|
|
32
32
|
import { readHomePrefs } from '../homePrefs.js';
|
|
33
33
|
import { resolveSessionCwd } from '../utils/workspaceRoot.js';
|
|
34
|
-
import { beginRestartAttempt,
|
|
34
|
+
import { beginRestartAttempt, checkForCliUpdate, installedCliVersion, isBootDeadlockTarget, isStandaloneRuntime, isVersionNewer, logRestartEvent, resolveDshProfileName, resolveCliUpdateTarget, restartCli, updateCliAndRestart, writeHandoffNotice } from '../update.js';
|
|
35
35
|
import { getLang, isLang, resolveStartupLang, setLang, t, writeLangPref } from '../i18n.js';
|
|
36
|
-
import { DEFAULT_PAGE_MARGIN, applyMermaidDiagrams, applyPageMargin, isPageMarginMode, normalizePageMargin, normalizeScrollGutter, normalizeStatusBar, normalizeToolBackground, parsePageMarginSpec } from '../
|
|
36
|
+
import { DEFAULT_PAGE_MARGIN, applyMermaidDiagrams, applyPageMargin, isPageMarginMode, normalizePageMargin, normalizeScrollGutter, normalizeStatusBar, normalizeToolBackground, parsePageMarginSpec } from '../cliDisplayPrefs.js';
|
|
37
37
|
import { draftComboConflicts, effectiveComboString, parseComboDraft, setKeymapOverrides, SHORTCUT_ACTIONS, } from '../utils/keymap.js';
|
|
38
38
|
import { attachHerdrIntegration } from '../herdr.js';
|
|
39
39
|
import { logMouseDebug } from '../utils/debug.js';
|
|
@@ -109,15 +109,15 @@ export function resolveTuiHostMode(stdoutIsTTY = process.stdout.isTTY === true,
|
|
|
109
109
|
if (stdoutIsTTY) {
|
|
110
110
|
return 'interactive';
|
|
111
111
|
}
|
|
112
|
-
const explicitTuiLaunch = env.
|
|
112
|
+
const explicitTuiLaunch = env.DSH_CLI_LAUNCHER_VERSION !== undefined || isStandaloneRuntime();
|
|
113
113
|
return explicitTuiLaunch ? 'invalid-explicit-launch' : 'headless-host';
|
|
114
114
|
}
|
|
115
115
|
export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
116
116
|
const config = configValues(runtimeConfig);
|
|
117
117
|
// /restart handoff diagnosis: the replacement process is marked by env and
|
|
118
|
-
// logs its boot progress to ~/.dsh-
|
|
118
|
+
// logs its boot progress to ~/.dsh-cli/restart.log (ordinary launches stay
|
|
119
119
|
// silent). First line lands before anything in this function can throw.
|
|
120
|
-
if (process.env.
|
|
120
|
+
if (process.env.DSH_CLI_RESTART_CHILD === '1') {
|
|
121
121
|
logRestartEvent('boot: plugin apply', {
|
|
122
122
|
stdoutTty: process.stdout.isTTY === true,
|
|
123
123
|
stdinTty: process.stdin.isTTY === true,
|
|
@@ -171,44 +171,44 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
171
171
|
}
|
|
172
172
|
const hostMode = resolveTuiHostMode();
|
|
173
173
|
if (hostMode === 'invalid-explicit-launch') {
|
|
174
|
-
if (process.env.
|
|
174
|
+
if (process.env.DSH_CLI_RESTART_CHILD === '1') {
|
|
175
175
|
logRestartEvent('boot: TTY gate failed - stdout is not a TTY');
|
|
176
176
|
}
|
|
177
|
-
throw new Error('dsh-
|
|
177
|
+
throw new Error('dsh-cli requires an interactive terminal (stdout must be a TTY).');
|
|
178
178
|
}
|
|
179
179
|
if (hostMode === 'headless-host') {
|
|
180
180
|
// Web / Tauri / GUI hosts load the plugin from the profile without being
|
|
181
|
-
// a dsh-
|
|
181
|
+
// a dsh-cli frontend (stdout is a pipe or null). Mounting a TUI there
|
|
182
182
|
// would fail the whole composition, so skip quietly and let the host
|
|
183
|
-
// boot. The launcher marker above keeps explicit `dsh-
|
|
183
|
+
// boot. The launcher marker above keeps explicit `dsh-cli` launches
|
|
184
184
|
// failing loudly instead of silently producing no UI.
|
|
185
|
-
ctx.logger.info('dsh-
|
|
185
|
+
ctx.logger.info('dsh-cli: non-interactive host detected (stdout is not a TTY); skipping the TUI frontend');
|
|
186
186
|
return;
|
|
187
187
|
}
|
|
188
188
|
// Validate settings before creating an agent or taking over the terminal.
|
|
189
189
|
const tuiSettingsNs = resolveSettingsNamespace(configOwner, Config);
|
|
190
190
|
registerResponseLanguage(ctx);
|
|
191
191
|
await registerBundledPresets(ctx);
|
|
192
|
-
// UI language resolution:
|
|
193
|
-
// active profile `dsh-
|
|
192
|
+
// UI language resolution: DSH_CLI_LANG env var wins, then the
|
|
193
|
+
// active profile `dsh-cli.lang` configuration (applied once the settings
|
|
194
194
|
// namespace registers below), then cordis.yml `lang`, then the
|
|
195
195
|
// persisted `/lang` choice, then the locale, falling back to `en`. Must settle before the first
|
|
196
196
|
// render so every module resolves strings in the same language.
|
|
197
|
-
const envLang = process.env.
|
|
197
|
+
const envLang = process.env.DSH_CLI_LANG;
|
|
198
198
|
setLang(isLang(envLang) ? envLang : isLang(config.lang) ? config.lang : resolveStartupLang());
|
|
199
199
|
if (resolveDshProfileName() === 'dsh-cli'
|
|
200
200
|
&& !isStandaloneRuntime()
|
|
201
201
|
&& !process.env.CI
|
|
202
|
-
&& process.env.
|
|
202
|
+
&& process.env.DSH_CLI_AUTO_REGISTER_CLI !== '0') {
|
|
203
203
|
try {
|
|
204
204
|
const result = ensureCliRegistered();
|
|
205
205
|
if (result.startsWith('Registered ') || result.startsWith('Kept '))
|
|
206
|
-
ctx.logger.info(`dsh-
|
|
206
|
+
ctx.logger.info(`dsh-cli: ${result}`);
|
|
207
207
|
else if (result.startsWith('Existing '))
|
|
208
|
-
ctx.logger.warn(`dsh-
|
|
208
|
+
ctx.logger.warn(`dsh-cli: ${result} Remove the conflicting command or adjust PATH, then restart the TUI.`);
|
|
209
209
|
}
|
|
210
210
|
catch (error) {
|
|
211
|
-
ctx.logger.warn(`dsh-
|
|
211
|
+
ctx.logger.warn(`dsh-cli: dsh-cli command registration failed: ${error instanceof Error ? error.message : String(error)}. Resolve the reported path or permission issue, then restart the TUI; set DSH_CLI_AUTO_REGISTER_CLI=0 to disable registration.`);
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
// /update restart verification: the pre-update process stamps the version
|
|
@@ -217,34 +217,34 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
217
217
|
// lag, cached manifest, wrong profile). Say so instead of silently
|
|
218
218
|
// pretending the update landed.
|
|
219
219
|
{
|
|
220
|
-
const updatedFrom = process.env.
|
|
220
|
+
const updatedFrom = process.env.DSH_CLI_UPDATED_FROM;
|
|
221
221
|
if (updatedFrom !== undefined) {
|
|
222
222
|
// Assigning undefined would stringify to "undefined" and leak the
|
|
223
223
|
// marker into every child process; remove it for real.
|
|
224
|
-
delete process.env.
|
|
225
|
-
const now =
|
|
224
|
+
delete process.env.DSH_CLI_UPDATED_FROM;
|
|
225
|
+
const now = installedCliVersion();
|
|
226
226
|
if (now === undefined || !isVersionNewer(now, updatedFrom)) {
|
|
227
|
-
ctx.logger.warn(`dsh-
|
|
227
|
+
ctx.logger.warn(`dsh-cli: /update restarted but the version did not advance (still ${now ?? 'unknown'}, was ${updatedFrom})`);
|
|
228
228
|
if (process.stderr.isTTY) {
|
|
229
|
-
process.stderr.write(`\ndsh-
|
|
229
|
+
process.stderr.write(`\ndsh-cli: 更新后版本未变化(仍为 ${now ?? 'unknown'},原为 ${updatedFrom});` +
|
|
230
230
|
`可能是镜像 registry 未同步,请稍后重试或检查 registry 配置。\n`);
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
else if (process.stderr.isTTY) {
|
|
234
234
|
// Launcher alignment bridge (0.8.3): /update only replaces the
|
|
235
|
-
// package inside the DSH profile; a globally installed `dsh-
|
|
235
|
+
// package inside the DSH profile; a globally installed `dsh-cli`
|
|
236
236
|
// launcher is a separate copy that keeps its old version. Launchers
|
|
237
|
-
// >=0.8.3 export
|
|
237
|
+
// >=0.8.3 export DSH_CLI_LAUNCHER_VERSION so we can tell whether
|
|
238
238
|
// the outer launcher lags the freshly installed profile. Launchers
|
|
239
239
|
// <=0.8.2 never set the marker — the generic branch below is
|
|
240
|
-
// intentionally one-shot:
|
|
240
|
+
// intentionally one-shot: DSH_CLI_UPDATED_FROM exists only on the
|
|
241
241
|
// replacement process immediately after /update.
|
|
242
|
-
const launcherVersion = process.env.
|
|
242
|
+
const launcherVersion = process.env.DSH_CLI_LAUNCHER_VERSION;
|
|
243
243
|
if (launcherVersion === undefined) {
|
|
244
|
-
process.stderr.write(`\n[dsh-
|
|
244
|
+
process.stderr.write(`\n[dsh-cli] ${t('update-launcher-align-unknown', { version: now })}\n`);
|
|
245
245
|
}
|
|
246
246
|
else if (isVersionNewer(now, launcherVersion)) {
|
|
247
|
-
process.stderr.write(`\n[dsh-
|
|
247
|
+
process.stderr.write(`\n[dsh-cli] ${t('update-launcher-outdated', { profile: now, launcher: launcherVersion })}\n`);
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
250
|
}
|
|
@@ -327,53 +327,53 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
327
327
|
// itself outside any worktree), so `@` completion and mention expansion
|
|
328
328
|
// see the repository, not an arbitrary launch subdirectory. Resolved ONCE
|
|
329
329
|
// here — the agent meta and the channel must agree.
|
|
330
|
-
const requestedWorkspace = config.workspace ?? process.env.
|
|
330
|
+
const requestedWorkspace = config.workspace ?? process.env.DSH_CLI_WORKSPACE_TARGET;
|
|
331
331
|
// Degraded boot (issue #183): a stale bundle patch without the
|
|
332
|
-
// dsh-
|
|
332
|
+
// dsh-cli-workspaces row leaves the service unmounted; resolve startup
|
|
333
333
|
// targets through the local-only runtime (provider URIs then fail loud
|
|
334
334
|
// below instead of crashing on an undefined service). A profile launch
|
|
335
|
-
// without the service means the patch came from an older dsh-
|
|
335
|
+
// without the service means the patch came from an older dsh-cli copy
|
|
336
336
|
// than the running code — warn once so the skew is diagnosable. Bare
|
|
337
337
|
// embedders (no --profile) take the same fallback by design, silently.
|
|
338
338
|
const mountedWorkspaceService = getHostWorkspaceRuntime(ctx.get('tuiWorkspaces'));
|
|
339
339
|
if (mountedWorkspaceService === undefined && resolveDshProfileName() !== undefined) {
|
|
340
|
-
ctx.logger.warn('dsh-
|
|
341
|
-
'The bundle patch is older than the installed dsh-
|
|
340
|
+
ctx.logger.warn('dsh-cli: tuiWorkspaces service is not mounted; /workspace runs with the local-only fallback. ' +
|
|
341
|
+
'The bundle patch is older than the installed dsh-cli package — update the globally installed dsh-cli launcher to match the profile (issue #183).');
|
|
342
342
|
}
|
|
343
343
|
const workspaceService = mountedWorkspaceService ?? createLocalWorkspaceRuntime();
|
|
344
|
-
// Same skew guard for the plugin-scene registry (dsh-
|
|
344
|
+
// Same skew guard for the plugin-scene registry (dsh-cli-scenes row): the
|
|
345
345
|
// channel degrades to never opening scenes when the service is absent, so
|
|
346
346
|
// say why on profile launches — a plugin's open() otherwise fails with only
|
|
347
347
|
// its own warn to go on.
|
|
348
348
|
if (ctx.get('tuiScenes') === undefined && resolveDshProfileName() !== undefined) {
|
|
349
|
-
ctx.logger.warn('dsh-
|
|
350
|
-
'The bundle patch is older than the installed dsh-
|
|
349
|
+
ctx.logger.warn('dsh-cli: tuiScenes service is not mounted; plugin scenes will never open. ' +
|
|
350
|
+
'The bundle patch is older than the installed dsh-cli package — update the globally installed dsh-cli launcher to match the profile (issue #183).');
|
|
351
351
|
}
|
|
352
|
-
// Same skew guard for the plugin-UI services (dsh-
|
|
352
|
+
// Same skew guard for the plugin-UI services (dsh-cli-extensions row):
|
|
353
353
|
// managed dialogs park unanswered, status contributions never render,
|
|
354
354
|
// shortcuts never match, custom-entry renderers stay invisible, and runtime
|
|
355
355
|
// themes stay out of the picker when the row is absent — say why on profile
|
|
356
356
|
// launches. The static JSON theme path remains available without this row.
|
|
357
357
|
const themeHost = getHostThemes(ctx.get('tuiThemes'));
|
|
358
358
|
if ((ctx.get('tuiDialogs') === undefined || themeHost === undefined) && resolveDshProfileName() !== undefined) {
|
|
359
|
-
ctx.logger.warn('dsh-
|
|
360
|
-
'Static ~/.dsh-
|
|
359
|
+
ctx.logger.warn('dsh-cli: tuiDialogs/tuiStatus/tuiShortcuts/tuiRenderers/tuiThemes services are not mounted; plugin dialogs, status contributions, shortcuts, custom-entry renderers and runtime themes are off. ' +
|
|
360
|
+
'Static ~/.dsh-cli/themes JSON remains available. The bundle patch is older than the installed dsh-cli package — update the globally installed dsh-cli launcher to match the profile (issue #183).');
|
|
361
361
|
}
|
|
362
|
-
// Same skew guard for the plugin-host row (dsh-
|
|
362
|
+
// Same skew guard for the plugin-host row (dsh-cli-plugin-host): without
|
|
363
363
|
// it there is no runtime generation id, no unified grant store service,
|
|
364
364
|
// and no Host Descriptor — plugin interop surfaces degrade silently
|
|
365
365
|
// otherwise. The D-7 decision gate does NOT depend on this row (the
|
|
366
366
|
// channel installs its own), so interception gating stays intact either
|
|
367
367
|
// way — what breaks is everything that rides on tuiPluginHost.
|
|
368
368
|
if (ctx.get('tuiPluginHost') === undefined && resolveDshProfileName() !== undefined) {
|
|
369
|
-
ctx.logger.warn('dsh-
|
|
370
|
-
'The bundle patch is older than the installed dsh-
|
|
369
|
+
ctx.logger.warn('dsh-cli: tuiPluginHost service is not mounted; plugin grant store, runtime generation and Host Descriptor are unavailable. ' +
|
|
370
|
+
'The bundle patch is older than the installed dsh-cli package — update the globally installed dsh-cli launcher to match the profile (issue #183).');
|
|
371
371
|
}
|
|
372
372
|
const initialWorkspace = requestedWorkspace === undefined
|
|
373
373
|
? undefined
|
|
374
374
|
: await workspaceService.resolve(requestedWorkspace);
|
|
375
375
|
if (requestedWorkspace !== undefined && initialWorkspace === undefined) {
|
|
376
|
-
throw new Error(`dsh-
|
|
376
|
+
throw new Error(`dsh-cli: unsupported or unavailable workspace target: ${requestedWorkspace}`);
|
|
377
377
|
}
|
|
378
378
|
const sessionCwd = initialWorkspace?.cwd ?? resolveSessionCwd(config.cwd);
|
|
379
379
|
const meta = { cwd: sessionCwd };
|
|
@@ -396,14 +396,14 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
396
396
|
// registration story.
|
|
397
397
|
const attached = await attachSessionToWorkspace(ctx, meta.cwd, agent.session.id);
|
|
398
398
|
if (!attached) {
|
|
399
|
-
ctx.logger.warn(`dsh-
|
|
399
|
+
ctx.logger.warn(`dsh-cli: session "${agent.session.id}" has no workspace ownership because workspaceRegistry is not mounted`);
|
|
400
400
|
}
|
|
401
401
|
}
|
|
402
402
|
catch (error) {
|
|
403
403
|
// The Session is already published and durable, matching Web's partial
|
|
404
404
|
// failure contract. Keep the TUI usable but make the missing ownership
|
|
405
405
|
// loud instead of silently leaving the conversation Ungrouped.
|
|
406
|
-
ctx.logger.warn(`dsh-
|
|
406
|
+
ctx.logger.warn(`dsh-cli: session "${agent.session.id}" workspace attachment failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
407
407
|
}
|
|
408
408
|
// Status-line route: the exact route the agent runs with — on create the
|
|
409
409
|
// validated startup resolution, on resume the route the target session's
|
|
@@ -457,7 +457,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
457
457
|
// plan/full cycle in sessionModes.ts).
|
|
458
458
|
modes: config.modes,
|
|
459
459
|
// Edit/Write diff presentation (schema default 'auto'); the /settings
|
|
460
|
-
// screen edits this key live through the dsh-
|
|
460
|
+
// screen edits this key live through the dsh-cli namespace.
|
|
461
461
|
diffLayout: config.diffLayout,
|
|
462
462
|
thinkingFold: config.thinkingFold,
|
|
463
463
|
toolBackground: config.toolBackground,
|
|
@@ -524,7 +524,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
524
524
|
let bootedFullscreen = config.fullscreen === true;
|
|
525
525
|
let bootedTerminalImages = lastBootedTerminalImages ?? config.terminalImages ?? true;
|
|
526
526
|
let rendererSettingsFrozen = false;
|
|
527
|
-
const terminalImagesDisabledByEnv = isEnvTruthy(process.env.
|
|
527
|
+
const terminalImagesDisabledByEnv = isEnvTruthy(process.env.DSH_CLI_DISABLE_TERMINAL_IMAGES);
|
|
528
528
|
// The settings service may come up AFTER this plugin's apply: the cordis
|
|
529
529
|
// inject callback defers until the service registers, so the first
|
|
530
530
|
// `apply(scope.get())` below can land after the mount (field report: the
|
|
@@ -573,11 +573,11 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
573
573
|
};
|
|
574
574
|
// The /settings language field writes `lang` through the settings
|
|
575
575
|
// service (user layer): apply it live and mirror it to lang.json so
|
|
576
|
-
// the /lang command and next-boot resolution agree.
|
|
576
|
+
// the /lang command and next-boot resolution agree. DSH_CLI_LANG
|
|
577
577
|
// stays the top precedence — a pinned env is never overridden by the
|
|
578
578
|
// document.
|
|
579
579
|
const applyLang = (value) => {
|
|
580
|
-
if (!isLang(process.env.
|
|
580
|
+
if (!isLang(process.env.DSH_CLI_LANG) && isLang(value.lang)) {
|
|
581
581
|
setLang(value.lang);
|
|
582
582
|
writeLangPref(value.lang);
|
|
583
583
|
}
|
|
@@ -659,7 +659,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
659
659
|
}));
|
|
660
660
|
resolveSettingsReady?.();
|
|
661
661
|
});
|
|
662
|
-
// The /settings screen's own section: the dsh-
|
|
662
|
+
// The /settings screen's own section: the dsh-cli namespace comes from
|
|
663
663
|
// the settings registration above, and the declared selects write `lang`
|
|
664
664
|
// and `diffLayout` back through the settings service's revision-fenced
|
|
665
665
|
// mutate (the watch applies both live).
|
|
@@ -770,7 +770,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
770
770
|
});
|
|
771
771
|
// Prefer the composition's sections service; fall back to the in-package
|
|
772
772
|
// local host. Real compositions have been observed disposing the whole
|
|
773
|
-
// dsh-
|
|
773
|
+
// dsh-cli-* host-seam insert list right after load (issue #557), which
|
|
774
774
|
// left this registration silently skipped and /settings read-only.
|
|
775
775
|
// channel.ts reads through the same fallback, so both sides meet in the
|
|
776
776
|
// same registry either way.
|
|
@@ -778,7 +778,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
778
778
|
const settingsSections = getHostSettingsSections(ctx.get('tuiSettingsSections')) ?? getLocalSettingsSectionsHost(ctx);
|
|
779
779
|
const unregister = settingsSections.register({
|
|
780
780
|
ns: tuiSettingsNs,
|
|
781
|
-
title: 'dsh-
|
|
781
|
+
title: 'dsh-cli',
|
|
782
782
|
groups: [
|
|
783
783
|
{ id: 'status-bar', title: 'Status bar', descriptions: { zh: '底栏设置' } },
|
|
784
784
|
{ id: 'shortcuts', title: 'Shortcuts', descriptions: { zh: '快捷键' } },
|
|
@@ -824,11 +824,11 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
824
824
|
label: terminalImagesDisabledByEnv ? 'Image previews (forced off)' : 'Terminal image previews',
|
|
825
825
|
descriptions: { zh: terminalImagesDisabledByEnv ? '图片预览(环境强制关闭)' : '终端图片预览' },
|
|
826
826
|
hint: terminalImagesDisabledByEnv
|
|
827
|
-
? 'Checkbox saves your preference. Relaunch without
|
|
827
|
+
? 'Checkbox saves your preference. Relaunch without DSH_CLI_DISABLE_TERMINAL_IMAGES to enable previews.'
|
|
828
828
|
: 'Preview images in supported terminals. Use /restart to apply. Sending images is unaffected.',
|
|
829
829
|
hintDescriptions: {
|
|
830
830
|
zh: terminalImagesDisabledByEnv
|
|
831
|
-
? '勾选框保存预览偏好;移除
|
|
831
|
+
? '勾选框保存预览偏好;移除 DSH_CLI_DISABLE_TERMINAL_IMAGES 后重新启动才能显示图片。'
|
|
832
832
|
: '在支持的终端中预览图片。修改后用 /restart 生效;不影响向模型发送图片。',
|
|
833
833
|
},
|
|
834
834
|
kind: 'boolean',
|
|
@@ -1233,7 +1233,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1233
1233
|
ctx.effect(() => () => herdr.dispose());
|
|
1234
1234
|
}
|
|
1235
1235
|
// Positional command-line arguments are the initial prompt (issue #53):
|
|
1236
|
-
// `dsh-
|
|
1236
|
+
// `dsh-cli "run the tests"` forwards positionals through the dsh CLI,
|
|
1237
1237
|
// which mounts them as ctx.cmdlineArgs. The service shape drifted across
|
|
1238
1238
|
// dsh-cmdline builds — `{ get() }` is the current contract, older builds
|
|
1239
1239
|
// exposed `{ args }` — so read both. Submit once the channel exists;
|
|
@@ -1285,8 +1285,8 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1285
1285
|
exited = true;
|
|
1286
1286
|
if (error !== undefined) {
|
|
1287
1287
|
const message = error instanceof Error ? error.message : String(error);
|
|
1288
|
-
ctx.logger.error(`dsh-
|
|
1289
|
-
void finishExit(ctx, instance, bootedFullscreen, undefined, `dsh-
|
|
1288
|
+
ctx.logger.error(`dsh-cli: exit after error: ${message}`);
|
|
1289
|
+
void finishExit(ctx, instance, bootedFullscreen, undefined, `dsh-cli crashed: ${message}`, () => disposeRootAndExit(ctx, 1));
|
|
1290
1290
|
return;
|
|
1291
1291
|
}
|
|
1292
1292
|
if (updateRequested) {
|
|
@@ -1381,7 +1381,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1381
1381
|
approvalStore,
|
|
1382
1382
|
injectControllerRef,
|
|
1383
1383
|
openHomeOnBoot,
|
|
1384
|
-
// The dsh-
|
|
1384
|
+
// The dsh-cli-extensions row's services (managed dialogs, status line,
|
|
1385
1385
|
// shortcuts). Soft-consumed: absent the row (stale patch, bare embed),
|
|
1386
1386
|
// Chat falls back to inert stores and no shortcut registry.
|
|
1387
1387
|
extensionDialogs: getHostDialogStore(ctx.get('tuiDialogs')),
|
|
@@ -1415,7 +1415,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1415
1415
|
// Confirm the target version before tearing the TUI down: on an
|
|
1416
1416
|
// already-latest install, an unconditional update+restart would churn
|
|
1417
1417
|
// the process and then trip the "version did not advance" warning.
|
|
1418
|
-
void
|
|
1418
|
+
void resolveCliUpdateTarget().then((target) => {
|
|
1419
1419
|
if (exited || updateRequested)
|
|
1420
1420
|
return;
|
|
1421
1421
|
if (target.kind === 'latest') {
|
|
@@ -1491,7 +1491,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1491
1491
|
// /restart handoff diagnosis: the replacement got all the way to a mounted
|
|
1492
1492
|
// UI, so any later death is post-boot (and its stderr keeps flowing to the
|
|
1493
1493
|
// parent only within the survival window — this line is the durable mark).
|
|
1494
|
-
if (process.env.
|
|
1494
|
+
if (process.env.DSH_CLI_RESTART_CHILD === '1') {
|
|
1495
1495
|
logRestartEvent('boot: UI mounted', { fullscreen: bootedFullscreen, isRecompose });
|
|
1496
1496
|
}
|
|
1497
1497
|
// External injection channel (dsh.nvim etc.): expose a per-session local
|
|
@@ -1501,7 +1501,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1501
1501
|
const injectChannel = openInjectChannel(agent.session.id, channel.cwd, {
|
|
1502
1502
|
append: (text) => injectControllerRef.current?.append(text),
|
|
1503
1503
|
submit: () => injectControllerRef.current?.submit(),
|
|
1504
|
-
}, (message) => ctx.logger.warn(`dsh-
|
|
1504
|
+
}, (message) => ctx.logger.warn(`dsh-cli: ${message}`));
|
|
1505
1505
|
if (injectChannel) {
|
|
1506
1506
|
ctx.effect(() => () => injectChannel.close());
|
|
1507
1507
|
}
|
|
@@ -1517,7 +1517,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1517
1517
|
// Check in the background so registry latency never delays the first frame.
|
|
1518
1518
|
// A failed/offline check is intentionally silent; the manual `/update`
|
|
1519
1519
|
// command remains available regardless of network access.
|
|
1520
|
-
void
|
|
1520
|
+
void checkForCliUpdate().then((update) => {
|
|
1521
1521
|
if (update === undefined || exited || updateRequested)
|
|
1522
1522
|
return;
|
|
1523
1523
|
const key = update.isStandalone ? 'update-standalone-available' : 'update-available';
|
|
@@ -1552,7 +1552,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1552
1552
|
void instance.waitUntilExit().then(handleExit, handleExit);
|
|
1553
1553
|
}
|
|
1554
1554
|
/**
|
|
1555
|
-
* Attach to an existing agent, resume a persisted session (`dsh-
|
|
1555
|
+
* Attach to an existing agent, resume a persisted session (`dsh-cli --resume`
|
|
1556
1556
|
* feeds the id through `config.sessionId`), or create a fresh one. Resume
|
|
1557
1557
|
* goes through the DSH persistence seam (`ctx.agents.resume` reads the
|
|
1558
1558
|
* session log written by dsh-session-persistence-jsonl); a missing artifact
|
|
@@ -1588,7 +1588,7 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
|
|
|
1588
1588
|
}
|
|
1589
1589
|
// The launch-time counterpart of the in-session `/resume` claim
|
|
1590
1590
|
// (`channel/session-resume.ts`), and it has to happen before ANY await:
|
|
1591
|
-
// without it `dsh-
|
|
1591
|
+
// without it `dsh-cli --resume <id>` mounts the log purely because the user
|
|
1592
1592
|
// asked for it, so a second terminal doing the same joins the first and
|
|
1593
1593
|
// both interleave writes into one append-only transcript. The mount
|
|
1594
1594
|
// publisher cannot cover this — it publishes the set, it never refuses a
|
|
@@ -1603,15 +1603,15 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
|
|
|
1603
1603
|
const reserved = await reserveMount(requestedSessionId);
|
|
1604
1604
|
if (!reserved.ok) {
|
|
1605
1605
|
if (reserved.reason === 'occupied') {
|
|
1606
|
-
throw new Error(`dsh-
|
|
1606
|
+
throw new Error(`dsh-cli: cannot resume session "${requestedSessionId}": it is mounted by another TUI terminal ` +
|
|
1607
1607
|
`(pid ${reserved.holders[0] ?? 0}) — two processes driving one session log would corrupt it. ` +
|
|
1608
1608
|
'Close that terminal, or drop --resume to start a fresh session.');
|
|
1609
1609
|
}
|
|
1610
1610
|
if (reserved.reason === 'busy') {
|
|
1611
|
-
throw new Error(`dsh-
|
|
1611
|
+
throw new Error(`dsh-cli: cannot resume session "${requestedSessionId}": another process is holding the ` +
|
|
1612
1612
|
'session mount ledger right now, so its occupancy could not be checked. Retry in a moment.');
|
|
1613
1613
|
}
|
|
1614
|
-
throw new Error(`dsh-
|
|
1614
|
+
throw new Error(`dsh-cli: cannot resume session "${requestedSessionId}": its occupancy could not be verified ` +
|
|
1615
1615
|
`(${reserved.detail}). Refusing rather than risk two processes writing one session log. ` +
|
|
1616
1616
|
'If that file is damaged, remove it (and the matching .lock) while no other TUI is running, ' +
|
|
1617
1617
|
'or drop --resume to start a fresh session.');
|
|
@@ -1661,7 +1661,7 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
|
|
|
1661
1661
|
// terminal). Fail the boot loudly instead; the loader surfaces this to
|
|
1662
1662
|
// stderr. The in-session /resume picker has its own error path.
|
|
1663
1663
|
const reason = error instanceof Error ? error.message : String(error);
|
|
1664
|
-
throw new Error(`dsh-
|
|
1664
|
+
throw new Error(`dsh-cli: cannot resume session "${requestedSessionId}": ${reason} — ` +
|
|
1665
1665
|
'the stored log is unreadable or corrupt; no fresh session was started instead. ' +
|
|
1666
1666
|
'Drop --resume to start fresh, or repair the session log first.', { cause: error });
|
|
1667
1667
|
}
|
|
@@ -1675,7 +1675,7 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
|
|
|
1675
1675
|
const presetPref = configuredPreset === undefined ? readPresetPref() : undefined;
|
|
1676
1676
|
const composed = await composePreset(ctx, configuredPreset ?? presetPref);
|
|
1677
1677
|
if (!migratePresetPref(presetPref, composed.agentPreset)) {
|
|
1678
|
-
ctx.logger.warn(`dsh-
|
|
1678
|
+
ctx.logger.warn(`dsh-cli: resolved preset preference "${presetPref}" as "${composed.agentPreset}" but could not persist the migrated id`);
|
|
1679
1679
|
}
|
|
1680
1680
|
// Fresh-session route precedence (issues #14/#30/#67): resolved atomically
|
|
1681
1681
|
// by the caller (complete cordis.yml route > the persisted `/model` choice
|
|
@@ -1685,7 +1685,7 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
|
|
|
1685
1685
|
const llm = ctx.get('llm');
|
|
1686
1686
|
const { route, rejected } = await validateModelRoute(llm, startupRoute);
|
|
1687
1687
|
if (rejected !== undefined) {
|
|
1688
|
-
ctx.logger.warn(`dsh-
|
|
1688
|
+
ctx.logger.warn(`dsh-cli: model route ${rejected.provider}/${rejected.model} is not advertised by provider "${rejected.provider}"; falling back to ${route.provider}/${route.model}`);
|
|
1689
1689
|
}
|
|
1690
1690
|
// Reserve the fresh id before the factory, exactly like the in-session
|
|
1691
1691
|
// creates: from the moment `agents.create` returns this process holds the
|
|
@@ -1695,7 +1695,7 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
|
|
|
1695
1695
|
// between the create and the next beat from being open.
|
|
1696
1696
|
const bootReserved = await reserveMount(String(sessionId));
|
|
1697
1697
|
if (!bootReserved.ok && bootReserved.reason !== 'occupied') {
|
|
1698
|
-
ctx.logger.warn(`dsh-
|
|
1698
|
+
ctx.logger.warn(`dsh-cli: could not announce the new session in the mount ledger: ${bootReserved.reason}`);
|
|
1699
1699
|
}
|
|
1700
1700
|
const bootReservation = bootReserved.ok ? bootReserved.reservation : undefined;
|
|
1701
1701
|
let created;
|
|
@@ -1716,7 +1716,7 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
|
|
|
1716
1716
|
// Fail loud with the reason on stderr — a dead TUI with no message is
|
|
1717
1717
|
// the worst outcome for a misconfigured leaf (unknown provider/model).
|
|
1718
1718
|
const message = error instanceof Error ? error.message : String(error);
|
|
1719
|
-
throw new Error(`dsh-
|
|
1719
|
+
throw new Error(`dsh-cli: failed to create agent (provider=${route.provider}, model=${route.model}): ${message}`, { cause: error });
|
|
1720
1720
|
}
|
|
1721
1721
|
bootReservation?.settle();
|
|
1722
1722
|
return { agent: created.agent, handle: created, agentPreset: composed.agentPreset, route };
|
|
@@ -1789,9 +1789,9 @@ export async function finishExit(ctx, instance, fullscreen, notice, stderrNotice
|
|
|
1789
1789
|
? undefined
|
|
1790
1790
|
: fromHandle);
|
|
1791
1791
|
if (runtime === undefined) {
|
|
1792
|
-
ctx.logger.debug('dsh-
|
|
1792
|
+
ctx.logger.debug('dsh-cli: Ink runtime unavailable during shutdown; using generic terminal cleanup');
|
|
1793
1793
|
if (instance !== undefined) {
|
|
1794
|
-
ctx.logger.debug('dsh-
|
|
1794
|
+
ctx.logger.debug('dsh-cli: Ink shutdown using full unmount as the terminal-restore fallback');
|
|
1795
1795
|
// Lookup-miss (custom stdout embedders / detach-less handles): the
|
|
1796
1796
|
// registry cannot hand us the detach hooks, so run the full Ink
|
|
1797
1797
|
// unmount first. It restores raw mode, alt screen and listeners
|
|
@@ -1801,12 +1801,12 @@ export async function finishExit(ctx, instance, fullscreen, notice, stderrNotice
|
|
|
1801
1801
|
instance.unmount();
|
|
1802
1802
|
}
|
|
1803
1803
|
catch {
|
|
1804
|
-
ctx.logger.debug('dsh-
|
|
1804
|
+
ctx.logger.debug('dsh-cli: Ink shutdown unmount fallback failed; continuing with generic terminal cleanup');
|
|
1805
1805
|
}
|
|
1806
1806
|
}
|
|
1807
1807
|
}
|
|
1808
1808
|
else if (fromMap === undefined) {
|
|
1809
|
-
ctx.logger.debug('dsh-
|
|
1809
|
+
ctx.logger.debug('dsh-cli: Ink runtime resolved from the render handle (instances map missed); detaching');
|
|
1810
1810
|
}
|
|
1811
1811
|
const cursor = fullscreen ? '' : cursorMoveToFrameEnd(runtime);
|
|
1812
1812
|
try {
|
|
@@ -1818,7 +1818,7 @@ export async function finishExit(ctx, instance, fullscreen, notice, stderrNotice
|
|
|
1818
1818
|
runtime?.detachStdinForHandoff?.();
|
|
1819
1819
|
}
|
|
1820
1820
|
catch {
|
|
1821
|
-
ctx.logger.debug('dsh-
|
|
1821
|
+
ctx.logger.debug('dsh-cli: Ink shutdown detach failed; continuing with generic terminal cleanup');
|
|
1822
1822
|
}
|
|
1823
1823
|
const cleanup = [
|
|
1824
1824
|
fullscreen ? EXIT_ALT_SCREEN : '',
|
|
@@ -1850,7 +1850,7 @@ export async function finishExit(ctx, instance, fullscreen, notice, stderrNotice
|
|
|
1850
1850
|
}
|
|
1851
1851
|
}
|
|
1852
1852
|
catch {
|
|
1853
|
-
ctx.logger.debug('dsh-
|
|
1853
|
+
ctx.logger.debug('dsh-cli: terminal cleanup failed; continuing with process shutdown');
|
|
1854
1854
|
}
|
|
1855
1855
|
// Filesystem-only: the exported clipboard images live in a per-process
|
|
1856
1856
|
// temp directory that nothing else removes.
|
|
@@ -1928,18 +1928,18 @@ function writeStream(stream, data) {
|
|
|
1928
1928
|
function runRestart(ctx, profile, sessionId) {
|
|
1929
1929
|
logRestartEvent('runRestart: entered, disposing cordis root');
|
|
1930
1930
|
disposeRootAndThen(ctx, () => {
|
|
1931
|
-
logRestartEvent('runRestart: root disposed, starting
|
|
1932
|
-
void
|
|
1933
|
-
logRestartEvent('runRestart:
|
|
1931
|
+
logRestartEvent('runRestart: root disposed, starting restartCli');
|
|
1932
|
+
void restartCli(sessionId).then(restartCode => {
|
|
1933
|
+
logRestartEvent('runRestart: restartCli resolved', { restartCode });
|
|
1934
1934
|
if (restartCode !== 0) {
|
|
1935
|
-
writeHandoffNotice(`\ndsh-
|
|
1935
|
+
writeHandoffNotice(`\ndsh-cli restart failed to spawn (exit ${restartCode}). Your session is preserved — resume with:\n` +
|
|
1936
1936
|
`${resumeCommand(profile, sessionId)}\n\n`);
|
|
1937
1937
|
}
|
|
1938
1938
|
process.exit(restartCode);
|
|
1939
1939
|
}, restartError => {
|
|
1940
1940
|
const message = restartError instanceof Error ? restartError.message : String(restartError);
|
|
1941
|
-
logRestartEvent('runRestart:
|
|
1942
|
-
writeHandoffNotice(`\ndsh-
|
|
1941
|
+
logRestartEvent('runRestart: restartCli rejected', { message });
|
|
1942
|
+
writeHandoffNotice(`\ndsh-cli restart failed: ${message}. Your session is preserved — resume with:\n` +
|
|
1943
1943
|
`${resumeCommand(profile, sessionId)}\n\n`);
|
|
1944
1944
|
process.exit(1);
|
|
1945
1945
|
});
|
|
@@ -1951,15 +1951,15 @@ function runUpdate(ctx, profile, sessionId, targetVersion) {
|
|
|
1951
1951
|
process.stderr.write(`\n${t('update-aborted-no-profile')}\n`);
|
|
1952
1952
|
process.exit(1);
|
|
1953
1953
|
}
|
|
1954
|
-
void
|
|
1954
|
+
void updateCliAndRestart(sessionId, profile, targetVersion).then(({ updateCode, restartCode }) => {
|
|
1955
1955
|
if (updateCode !== 0) {
|
|
1956
|
-
process.stderr.write(`\ndsh-
|
|
1956
|
+
process.stderr.write(`\ndsh-cli update failed (exit ${updateCode}). Your session is preserved — resume with:\n` +
|
|
1957
1957
|
`${resumeCommand(profile, sessionId)}\n\n`);
|
|
1958
1958
|
}
|
|
1959
1959
|
process.exit(restartCode);
|
|
1960
1960
|
}, updateError => {
|
|
1961
1961
|
const message = updateError instanceof Error ? updateError.message : String(updateError);
|
|
1962
|
-
process.stderr.write(`\ndsh-
|
|
1962
|
+
process.stderr.write(`\ndsh-cli update failed: ${message}. Your session is preserved — resume with:\n` +
|
|
1963
1963
|
`${resumeCommand(profile, sessionId)}\n\n`);
|
|
1964
1964
|
process.exit(1);
|
|
1965
1965
|
});
|
|
@@ -1968,11 +1968,11 @@ function runUpdate(ctx, profile, sessionId, targetVersion) {
|
|
|
1968
1968
|
/** Deferred runtime failures must restore the terminal and fail the process. */
|
|
1969
1969
|
export function handleStartupError(ctx, error) {
|
|
1970
1970
|
const message = error instanceof Error ? error.message : String(error);
|
|
1971
|
-
void finishExit(ctx, undefined, lastBootedFullscreen ?? true, undefined, `dsh-
|
|
1971
|
+
void finishExit(ctx, undefined, lastBootedFullscreen ?? true, undefined, `dsh-cli startup failed: ${message}`, () => disposeRootAndExit(ctx, 1));
|
|
1972
1972
|
}
|
|
1973
1973
|
/**
|
|
1974
1974
|
* Dispose the whole application before process exit, with a bounded fallback.
|
|
1975
|
-
* Mirrors the deleted dsh-
|
|
1975
|
+
* Mirrors the deleted dsh-cli front-door exit semantics.
|
|
1976
1976
|
*/
|
|
1977
1977
|
function disposeRootAndExit(ctx, code) {
|
|
1978
1978
|
disposeRootAndThen(ctx, () => process.exit(code), code);
|
|
@@ -9,7 +9,7 @@ export interface AgentPresetInfo {
|
|
|
9
9
|
/** Present when the preset cannot compose a session (human-readable). */
|
|
10
10
|
readonly broken?: string;
|
|
11
11
|
}
|
|
12
|
-
/** The `ctx.agentPresets` service surface dsh-
|
|
12
|
+
/** The `ctx.agentPresets` service surface dsh-cli consumes. */
|
|
13
13
|
export interface AgentPresetsLike {
|
|
14
14
|
readonly defaultId: string;
|
|
15
15
|
list(): Promise<readonly AgentPresetInfo[]>;
|
|
@@ -39,7 +39,7 @@ export async function composePreset(ctx, requested) {
|
|
|
39
39
|
resolvedId = (await presets.resolve(requested)).id;
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
42
|
-
ctx.logger.warn(`dsh-
|
|
42
|
+
ctx.logger.warn(`dsh-cli: agent preset ${requested === undefined ? '(default)' : `"${requested}"`} unavailable ` +
|
|
43
43
|
`(${error instanceof Error ? error.message : String(error)}) — composing the session without a preset`);
|
|
44
44
|
return {};
|
|
45
45
|
}
|
|
@@ -133,7 +133,7 @@ export function registerPromptDebug(ctx) {
|
|
|
133
133
|
schemaVersion: 2,
|
|
134
134
|
generatedAt: new Date().toISOString(),
|
|
135
135
|
captureStartedAt,
|
|
136
|
-
captureScope: 'Requests observed by this dsh-
|
|
136
|
+
captureScope: 'Requests observed by this dsh-cli process; requests from before a session resume cannot be reconstructed.',
|
|
137
137
|
warning: 'Sensitive debug data: contains system prompts, conversation messages, tool schemas, and tool results. It intentionally excludes credentials and transport headers.',
|
|
138
138
|
sessionId,
|
|
139
139
|
turnCount: turns.size,
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* harness promise when the user answers,
|
|
8
8
|
* cancels, or the owning tool's abort signal fires.
|
|
9
9
|
*
|
|
10
|
-
* Queue semantics mirror the official dsh-
|
|
10
|
+
* Queue semantics mirror the official dsh-cli chat/questions machine: asks
|
|
11
11
|
* arrive one at a time in practice (the tool blocks until answered), but
|
|
12
12
|
* concurrent asks from subagents are drained FIFO.
|
|
13
13
|
*/
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* harness promise when the user answers,
|
|
8
8
|
* cancels, or the owning tool's abort signal fires.
|
|
9
9
|
*
|
|
10
|
-
* Queue semantics mirror the official dsh-
|
|
10
|
+
* Queue semantics mirror the official dsh-cli chat/questions machine: asks
|
|
11
11
|
* arrive one at a time in practice (the tool blocks until answered), but
|
|
12
12
|
* concurrent asks from subagents are drained FIFO.
|
|
13
13
|
*/
|