@askdkc/dsh-cli 0.12.2 → 0.13.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 +6 -1
- package/cordis.patch.yml +12 -131
- package/lib/types/adapter/channel/session-projection.d.ts.map +1 -1
- package/lib/types/adapter/channel/session-projection.js +0 -7
- package/lib/types/adapter/ports/channel-view.d.ts +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/dsh-adapter/bundled-presets.d.ts +3 -8
- package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/bundled-presets.js +5 -20
- package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +2 -9
- package/lib/types/dsh-adapter/channel/external-commands.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/external-commands.js +9 -33
- package/lib/types/dsh-adapter/channel/local-actions.d.ts +2 -1
- package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/local-actions.js +6 -2
- package/lib/types/dsh-adapter/channel/model-actions.js +3 -3
- package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-switch.js +0 -1
- package/lib/types/dsh-adapter/channel/permissions.d.ts +1 -6
- package/lib/types/dsh-adapter/channel/permissions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/permissions.js +2 -54
- package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/projection.js +15 -70
- package/lib/types/dsh-adapter/channel/session-fork.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-fork.js +0 -1
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-metadata.js +1 -4
- package/lib/types/dsh-adapter/channel/session-resume.js +2 -2
- package/lib/types/dsh-adapter/channel/session-rewind.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-rewind.js +0 -1
- package/lib/types/dsh-adapter/channel/session-tree-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-tree-actions.js +1 -2
- package/lib/types/dsh-adapter/channel/session-tree.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-tree.js +9 -62
- package/lib/types/dsh-adapter/channel/skill-catalog.js +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +2 -8
- package/lib/types/dsh-adapter/channel/transcript.d.ts +0 -16
- package/lib/types/dsh-adapter/channel/transcript.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/transcript.js +0 -43
- package/lib/types/dsh-adapter/channel.js +2 -2
- package/lib/types/dsh-adapter/compat/index.d.ts +5 -25
- package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/index.js +5 -25
- package/lib/types/dsh-adapter/compat/liveSession.d.ts +12 -23
- package/lib/types/dsh-adapter/compat/liveSession.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/liveSession.js +15 -68
- package/lib/types/dsh-adapter/compat/messages.d.ts +1 -3
- package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/messages.js +2 -10
- package/lib/types/dsh-adapter/compat/persistence.d.ts +2 -3
- package/lib/types/dsh-adapter/compat/persistence.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/persistence.js +9 -14
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +10 -144
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/sessionLog.js +45 -275
- package/lib/types/dsh-adapter/compat/settings.d.ts +4 -10
- package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/settings.js +6 -23
- package/lib/types/dsh-adapter/compat/shell.d.ts +2 -3
- package/lib/types/dsh-adapter/compat/shell.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/shell.js +2 -7
- package/lib/types/dsh-adapter/contract.d.ts +4 -34
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +8 -83
- package/lib/types/dsh-adapter/packaged-presets.d.ts +0 -19
- package/lib/types/dsh-adapter/packaged-presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/packaged-presets.js +1 -83
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +25 -168
- package/lib/types/dsh-adapter/preset-resolution.d.ts +1 -22
- package/lib/types/dsh-adapter/preset-resolution.d.ts.map +1 -1
- package/lib/types/dsh-adapter/preset-resolution.js +0 -34
- package/lib/types/dsh-adapter/presets.d.ts +1 -4
- package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/presets.js +3 -6
- package/lib/types/dsh-adapter/questions-answerer.d.ts +5 -43
- package/lib/types/dsh-adapter/questions-answerer.d.ts.map +1 -1
- package/lib/types/dsh-adapter/questions-answerer.js +7 -63
- package/lib/types/dsh-adapter/sessionTree.d.ts +0 -19
- package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessionTree.js +2 -112
- package/lib/types/dsh-adapter/sessions/header.d.ts +2 -2
- package/lib/types/dsh-adapter/sessions/header.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/header.js +2 -8
- package/lib/types/dsh-adapter/sessions/list.d.ts +7 -28
- package/lib/types/dsh-adapter/sessions/list.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/list.js +48 -103
- package/lib/types/dsh-adapter/sessions/store.d.ts +1 -2
- package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/store.js +7 -10
- package/lib/types/dsh-adapter/sharp.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sharp.js +0 -1
- package/lib/types/dsh-adapter/subagents.d.ts +1 -2
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +1 -12
- package/lib/types/dsh-adapter/trajectory/aggregate.d.ts +1 -1
- package/lib/types/dsh-adapter/trajectory/aggregate.js +1 -1
- package/lib/types/dsh-adapter/trajectory/guards.d.ts +5 -22
- package/lib/types/dsh-adapter/trajectory/guards.d.ts.map +1 -1
- package/lib/types/dsh-adapter/trajectory/guards.js +5 -23
- package/lib/types/dsh-adapter/trajectory/projection.d.ts +5 -21
- package/lib/types/dsh-adapter/trajectory/projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/trajectory/projection.js +4 -38
- package/lib/types/dsh-adapter/trajectory/types.d.ts +1 -1
- package/lib/types/dsh-adapter/trajectory/types.d.ts.map +1 -1
- package/lib/types/i18n.d.ts +2 -22
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +2 -10
- package/lib/types/presetPrefs.d.ts +1 -3
- package/lib/types/presetPrefs.d.ts.map +1 -1
- package/lib/types/presetPrefs.js +2 -4
- package/node_modules/@askdkc/dsh-auth/README.ja.md +28 -3
- package/node_modules/@askdkc/dsh-auth/README.md +19 -3
- package/node_modules/@askdkc/dsh-auth/dsh-plugin.json +3 -3
- package/node_modules/@askdkc/dsh-auth/lib/THIRD_PARTY_NOTICES.txt +168 -0
- package/node_modules/@askdkc/dsh-auth/lib/abortable.d.ts +2 -0
- package/node_modules/@askdkc/dsh-auth/lib/abortable.js +9 -0
- package/node_modules/@askdkc/dsh-auth/lib/auth-contract.d.ts +66 -0
- package/node_modules/@askdkc/dsh-auth/lib/auth-contract.js +1 -0
- package/node_modules/@askdkc/dsh-auth/lib/command.js +15 -1
- package/node_modules/@askdkc/dsh-auth/lib/credentials.d.ts +8 -14
- package/node_modules/@askdkc/dsh-auth/lib/credentials.js +1 -1
- package/node_modules/@askdkc/dsh-auth/lib/index.d.ts +8 -27
- package/node_modules/@askdkc/dsh-auth/lib/index.js +67 -64
- package/node_modules/@askdkc/dsh-auth/lib/interaction.d.ts +5 -5
- package/node_modules/@askdkc/dsh-auth/lib/opencode-adapter.d.ts +37 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-adapter.js +197 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-catalog.d.ts +72 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-catalog.js +252 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-codec.d.ts +6 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-codec.js +93 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-owned.generated.d.ts +113 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-owned.generated.js +2866 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-replay.d.ts +15 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-replay.js +141 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-sdk.d.ts +5 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-sdk.js +43465 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-sdk.js.map +7 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-transport.d.ts +5 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-transport.js +69 -0
- package/node_modules/@askdkc/dsh-auth/lib/pi-ai.d.ts +2 -1
- package/node_modules/@askdkc/dsh-auth/lib/pi-ai.js +2 -1
- package/node_modules/@askdkc/dsh-auth/lib/pi-routes.d.ts +32 -0
- package/node_modules/@askdkc/dsh-auth/lib/pi-routes.js +45 -0
- package/node_modules/@askdkc/dsh-auth/lib/profiles.d.ts +2 -20
- package/node_modules/@askdkc/dsh-auth/lib/profiles.js +6 -35
- package/node_modules/@askdkc/dsh-auth/lib/routes.d.ts +20 -0
- package/node_modules/@askdkc/dsh-auth/lib/routes.js +13 -0
- package/node_modules/@askdkc/dsh-auth/lib/service.d.ts +11 -2
- package/node_modules/@askdkc/dsh-auth/lib/service.js +26 -16
- package/node_modules/@askdkc/dsh-auth/package.json +26 -14
- package/package.json +100 -96
- package/lib/types/dsh-adapter/providerGuard.d.ts +0 -75
- package/lib/types/dsh-adapter/providerGuard.d.ts.map +0 -1
- package/lib/types/dsh-adapter/providerGuard.js +0 -104
- package/lib/types/migrationPrefs.d.ts +0 -60
- package/lib/types/migrationPrefs.d.ts.map +0 -1
- package/lib/types/migrationPrefs.js +0 -97
- package/presets/liangshen/.dsh-tui-managed.json +0 -5
|
@@ -3,7 +3,6 @@ import React from 'react';
|
|
|
3
3
|
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
4
4
|
import UserQuestionService from '@deepseek-ai/dsh-user-questions';
|
|
5
5
|
import * as toolAskUser from '@deepseek-ai/dsh-tool-ask-user';
|
|
6
|
-
import Schema from '@deepseek-ai/schemastery';
|
|
7
6
|
import { Config } from './index.js';
|
|
8
7
|
import { configValues, createSettingsScope, resolveSettingsNamespace } from './compat/settings.js';
|
|
9
8
|
import { createChannel } from './channel.js';
|
|
@@ -16,26 +15,24 @@ import { removeClipboardImageDir } from '../utils/clipboard.js';
|
|
|
16
15
|
import { logForDebugging } from '../utils/debug.js';
|
|
17
16
|
import { isEnvTruthy } from '../utils/envUtils.js';
|
|
18
17
|
import { QuestionStore, bindQuestionStore } from './questions.js';
|
|
19
|
-
import {
|
|
18
|
+
import { registerQuestionAnswerer } from './questions-answerer.js';
|
|
20
19
|
import { adapterRuntimeFor } from '../adapter/kernel/runtime-context.js';
|
|
21
20
|
import { ApprovalStore, bindApprovalStore } from './approvals.js';
|
|
22
21
|
import { registerPromptDebug } from './promptDebug.js';
|
|
23
22
|
import { readActivityFrames } from '../activityPrefs.js';
|
|
24
|
-
import { commitFullscreenFactoryMigration, planFullscreenFactoryMigration, readAppliedMigrations } from '../migrationPrefs.js';
|
|
25
23
|
import { readModelPref } from '../modelPrefs.js';
|
|
26
24
|
import { explicitModelRoute, recordedModelRoute, resolveModelRoute, validateModelRoute } from '../modelRoute.js';
|
|
27
25
|
import { migratePresetPref, readPresetPref } from '../presetPrefs.js';
|
|
28
26
|
import { readEffortPref } from '../effortPrefs.js';
|
|
29
27
|
import { composePreset, filterMinimalPresetTools, resolvePersistedPreset, resolvePersistedRoute, runningPresetOf } from './presets.js';
|
|
30
|
-
import { ensurePackagedPresets } from './packaged-presets.js';
|
|
31
28
|
import { registerBundledPresets } from './bundled-presets.js';
|
|
32
|
-
import {
|
|
29
|
+
import { registerTuiSessionEventTypes, snapshotLiveSessionEvents } from './compat/index.js';
|
|
33
30
|
import { clearResumeTarget, resumeTargetFromArgv, writeResumeTarget } from '../sessionHistory.js';
|
|
34
31
|
import { readHomePrefs } from '../homePrefs.js';
|
|
35
32
|
import { resolveSessionCwd } from '../utils/workspaceRoot.js';
|
|
36
33
|
import { beginRestartAttempt, checkForTuiUpdate, installedTuiVersion, isBootDeadlockTarget, isStandaloneRuntime, isVersionNewer, logRestartEvent, resolveDshProfileName, resolveTuiUpdateTarget, restartTui, updateTuiAndRestart, writeHandoffNotice } from '../update.js';
|
|
37
34
|
import { getLang, isLang, resolveStartupLang, setLang, t, writeLangPref } from '../i18n.js';
|
|
38
|
-
import { DEFAULT_PAGE_MARGIN,
|
|
35
|
+
import { DEFAULT_PAGE_MARGIN, applyMermaidDiagrams, applyPageMargin, isPageMarginMode, normalizePageMargin, normalizeScrollGutter, normalizeStatusBar, normalizeToolBackground, parsePageMarginSpec } from '../tuiDisplayPrefs.js';
|
|
39
36
|
import { draftComboConflicts, effectiveComboString, parseComboDraft, setKeymapOverrides, SHORTCUT_ACTIONS, } from '../utils/keymap.js';
|
|
40
37
|
import { attachHerdrIntegration } from '../herdr.js';
|
|
41
38
|
import { logMouseDebug } from '../utils/debug.js';
|
|
@@ -73,7 +70,7 @@ import { CLEAR_ITERM2_PROGRESS, CLEAR_TAB_STATUS, supportsTabStatus, wrapForMult
|
|
|
73
70
|
* Fullscreen decision latched across host recomposes. The launcher disposes
|
|
74
71
|
* and re-mounts the plugin tree (teardown → apply() runs again) — a fresh
|
|
75
72
|
* apply() re-resolves `bootedFullscreen` from cordis config, and the
|
|
76
|
-
*
|
|
73
|
+
* profile configuration can arrive after the 300ms
|
|
77
74
|
* `settingsReady` bound when the recompose is also re-mounting the settings
|
|
78
75
|
* service. The tree would then mount INLINE and `rendererSettingsFrozen` would
|
|
79
76
|
* swallow the late application — the app lands on the main screen
|
|
@@ -189,23 +186,9 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
189
186
|
}
|
|
190
187
|
// Validate settings before creating an agent or taking over the terminal.
|
|
191
188
|
const tuiSettingsNs = resolveSettingsNamespace(configOwner, Config);
|
|
192
|
-
|
|
193
|
-
// A modern bundle failure must not silently fall back to obsolete files.
|
|
194
|
-
if (!await registerBundledPresets(ctx))
|
|
195
|
-
try {
|
|
196
|
-
for (const result of ensurePackagedPresets()) {
|
|
197
|
-
if (result.status === 'conflict') {
|
|
198
|
-
ctx.logger.warn(`dsh-tui: packaged preset "${result.id}" was not installed because an unmanaged preset already uses that id`);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
catch (error) {
|
|
203
|
-
// A read-only home must not make the whole terminal unusable; the other
|
|
204
|
-
// official and user presets remain available.
|
|
205
|
-
ctx.logger.warn(`dsh-tui: unable to install packaged presets (${error instanceof Error ? error.message : String(error)})`);
|
|
206
|
-
}
|
|
189
|
+
await registerBundledPresets(ctx);
|
|
207
190
|
// UI language resolution: DSH_TUI_LANG env var wins, then the
|
|
208
|
-
//
|
|
191
|
+
// active profile `dsh-tui.lang` configuration (applied once the settings
|
|
209
192
|
// namespace registers below), then cordis.yml `lang`, then the
|
|
210
193
|
// persisted `/lang` choice, then `zh`. Must settle before the first
|
|
211
194
|
// render so every module resolves strings in the same language.
|
|
@@ -269,10 +252,8 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
269
252
|
// service when the composition doesn't (the official dsh-base
|
|
270
253
|
// user-interaction config row does; a bare plugin mount creates it on
|
|
271
254
|
// this context), then expose the model-facing tool before resolving the
|
|
272
|
-
// agent so per-step assembly includes ask_user_question.
|
|
273
|
-
//
|
|
274
|
-
// channel owner and is therefore registered immediately after the channel
|
|
275
|
-
// is created. Optional-service access goes through `ctx.get`, not the
|
|
255
|
+
// agent so per-step assembly includes ask_user_question. The answerer needs
|
|
256
|
+
// the channel owner and registers immediately after channel creation. Optional-service access goes through `ctx.get`, not the
|
|
276
257
|
// inject proxy.
|
|
277
258
|
const userQuestions = ctx.get('userQuestions') ?? new UserQuestionService(ctx);
|
|
278
259
|
ctx.plugin(toolAskUser);
|
|
@@ -288,31 +269,11 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
288
269
|
});
|
|
289
270
|
const questionStore = new QuestionStore(adapterRuntimeFor(ctx));
|
|
290
271
|
bindQuestionStore(ctx, questionStore);
|
|
291
|
-
//
|
|
292
|
-
// adapter binds either registration to this Cordis fiber; this separate
|
|
293
|
-
// effect rejects asks still parked in the UI during teardown.
|
|
272
|
+
// Reject questions still parked in the UI when its fiber is disposed.
|
|
294
273
|
ctx.effect(() => () => questionStore.rejectAll());
|
|
295
274
|
// `/debug-prompt` snapshots the final provider-neutral request at the
|
|
296
275
|
// llm/stream boundary, after every prompt and tool contributor has run.
|
|
297
276
|
registerPromptDebug(ctx);
|
|
298
|
-
// API selection and registration live behind one adapter boundary. The UI
|
|
299
|
-
// bootstrap only translates a legacy seat conflict into its visible notice.
|
|
300
|
-
const questionAnswererRegistration = prepareQuestionAnswerer(ctx, userQuestions, questionStore);
|
|
301
|
-
const questionSeatDecision = questionAnswererRegistration.kind === 'legacy'
|
|
302
|
-
? questionAnswererRegistration.yieldDecision
|
|
303
|
-
: undefined;
|
|
304
|
-
let questionSeatNotice;
|
|
305
|
-
if (questionSeatDecision?.action === 'alert-unverified') {
|
|
306
|
-
ctx.logger.error(`dsh-tui: user-questions provider seat is held by a component self-reporting as ${questionSeatDecision.incumbentId} ` +
|
|
307
|
-
'(identity not host-verified); this TUI will not register its questionnaire and model questions may be answered by it');
|
|
308
|
-
questionSeatNotice = t('question-provider-occupied-unverified', { id: questionSeatDecision.incumbentId ?? '' });
|
|
309
|
-
}
|
|
310
|
-
else if (questionSeatDecision?.action === 'alert') {
|
|
311
|
-
const displayId = questionSeatDecision.incumbentId ?? t('question-provider-occupied-unknown');
|
|
312
|
-
ctx.logger.error(`dsh-tui: user-questions provider seat is held by a non-host component (${displayId}); ` +
|
|
313
|
-
'this TUI will not register its questionnaire and model questions may be answered by it');
|
|
314
|
-
questionSeatNotice = t('question-provider-occupied', { id: displayId });
|
|
315
|
-
}
|
|
316
277
|
// Child-process stderr guard (issue #17): MCP servers spawned with an
|
|
317
278
|
// inherited stderr (the MCP SDK's stdio default) write straight to the
|
|
318
279
|
// terminal device from the child process, bypassing the renderer's own
|
|
@@ -550,11 +511,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
550
511
|
toastStore?.setSink(delivery => {
|
|
551
512
|
notifyChannel(delivery.text, { color: delivery.color, timeoutMs: delivery.timeoutMs });
|
|
552
513
|
});
|
|
553
|
-
|
|
554
|
-
// Ownership follows the mutable channel; registration cleanup belongs to
|
|
555
|
-
// this Cordis fiber.
|
|
556
|
-
questionAnswererRegistration.register(channel);
|
|
557
|
-
}
|
|
514
|
+
registerQuestionAnswerer(ctx, channel, questionStore);
|
|
558
515
|
// Fullscreen layout decision: the settings user layer (edited through the
|
|
559
516
|
// /settings screen) overrides cordis.yml when set. The settings injection
|
|
560
517
|
// below resolves it synchronously when the host settings service is up —
|
|
@@ -578,81 +535,10 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
578
535
|
resolveSettingsReady = () => resolve();
|
|
579
536
|
setTimeout(resolve, 300);
|
|
580
537
|
});
|
|
581
|
-
//
|
|
582
|
-
// volatile Config fields instead; both paths apply edits without remounting.
|
|
538
|
+
// Apply volatile Config edits without remounting the agent.
|
|
583
539
|
ctx.inject(['settings'], (settingsCtx) => {
|
|
584
540
|
// Loader targets the Config owner's fiber, not the injected child fiber.
|
|
585
|
-
const scope = createSettingsScope(configOwner,
|
|
586
|
-
diffLayout: Schema.union(['auto', 'split', 'unified']).default('auto'),
|
|
587
|
-
thinkingFold: Schema.union(['preview', 'full']).default('preview'),
|
|
588
|
-
toolBackground: Schema.union(['none', 'subtle', 'strong']).default('none'),
|
|
589
|
-
scrollGutter: Schema.union(['timeline', 'scrollbar', 'hidden']).default('timeline'),
|
|
590
|
-
// Preset names AND custom `NxM` specs (the settings field's parse
|
|
591
|
-
// gate keeps junk out of the user layer; the transform normalizes
|
|
592
|
-
// whatever survives — cordis.yml junk included).
|
|
593
|
-
pageMargin: Schema.transform(Schema.string().default('normal'), value => normalizePageMargin(value)),
|
|
594
|
-
// No default on purpose (same rule as `fullscreen` below): a schema
|
|
595
|
-
// default here would come back from scope.get()/watch() and shadow
|
|
596
|
-
// an explicit cordis.yml `foldTerminalCommand: true` while the
|
|
597
|
-
// settings user layer is unset — applyDisplay's
|
|
598
|
-
// `?? config.foldTerminalCommand ?? false` already supplies the
|
|
599
|
-
// default and keeps cordis.yml decisive.
|
|
600
|
-
foldTerminalCommand: Schema.boolean(),
|
|
601
|
-
promptSessionLabel: Schema.boolean().default(false),
|
|
602
|
-
// No schema default (same rule as foldTerminalCommand): applyDisplay
|
|
603
|
-
// resolves `?? config.expandEditor ?? true` so cordis.yml stays
|
|
604
|
-
// decisive while the user layer is unset.
|
|
605
|
-
expandEditor: Schema.boolean(),
|
|
606
|
-
// Same no-default rule: applyDisplay resolves `?? config.smoothStreaming ?? true`.
|
|
607
|
-
smoothStreaming: Schema.boolean(),
|
|
608
|
-
// Same no-default rule: applyDisplay resolves `?? config.mermaidDiagrams ?? true`.
|
|
609
|
-
mermaidDiagrams: Schema.boolean(),
|
|
610
|
-
// No default on purpose: unset keeps the boot chain decisive
|
|
611
|
-
// (applyEffortDefault hands `undefined` to channel.setDefaultEffort,
|
|
612
|
-
// which resolves cordis.yml `effort` → effort.json → adapter default).
|
|
613
|
-
effortDefault: Schema.string(),
|
|
614
|
-
statusBar: Schema.object({
|
|
615
|
-
compact: Schema.boolean().default(DEFAULT_STATUS_BAR.compact),
|
|
616
|
-
model: Schema.boolean().default(DEFAULT_STATUS_BAR.model),
|
|
617
|
-
thinking: Schema.boolean().default(DEFAULT_STATUS_BAR.thinking),
|
|
618
|
-
cwd: Schema.boolean().default(DEFAULT_STATUS_BAR.cwd),
|
|
619
|
-
contextUsage: Schema.boolean().default(DEFAULT_STATUS_BAR.contextUsage),
|
|
620
|
-
cache: Schema.boolean().default(DEFAULT_STATUS_BAR.cache),
|
|
621
|
-
tokens: Schema.boolean().default(DEFAULT_STATUS_BAR.tokens),
|
|
622
|
-
tps: Schema.boolean().default(DEFAULT_STATUS_BAR.tps),
|
|
623
|
-
gitBranch: Schema.boolean().default(DEFAULT_STATUS_BAR.gitBranch),
|
|
624
|
-
sessionTitle: Schema.boolean().default(DEFAULT_STATUS_BAR.sessionTitle),
|
|
625
|
-
sessionId: Schema.boolean().default(DEFAULT_STATUS_BAR.sessionId),
|
|
626
|
-
goal: Schema.boolean().default(DEFAULT_STATUS_BAR.goal),
|
|
627
|
-
mode: Schema.boolean().default(DEFAULT_STATUS_BAR.mode),
|
|
628
|
-
contextBar: Schema.boolean().default(DEFAULT_STATUS_BAR.contextBar),
|
|
629
|
-
activity: Schema.boolean().default(DEFAULT_STATUS_BAR.activity),
|
|
630
|
-
trajectory: Schema.boolean().default(DEFAULT_STATUS_BAR.trajectory),
|
|
631
|
-
shortcutHint: Schema.boolean().default(DEFAULT_STATUS_BAR.shortcutHint),
|
|
632
|
-
}).default({ ...DEFAULT_STATUS_BAR }),
|
|
633
|
-
// Header pixel whale art; on unless settings.yaml says otherwise.
|
|
634
|
-
whale: Schema.boolean().default(true),
|
|
635
|
-
// Idle whale behaviors after the intro settles; on by default —
|
|
636
|
-
// the idle-wakeup gate stays: an explicit `false` keeps the settled
|
|
637
|
-
// header timer-free.
|
|
638
|
-
whaleIdle: Schema.boolean().default(true),
|
|
639
|
-
// Minimal mode: strips the header splash, emoji glyphs, and
|
|
640
|
-
// decorative colors; code highlight and tool colors stay.
|
|
641
|
-
minimal: Schema.boolean().default(false),
|
|
642
|
-
// No default on purpose: an unset `lang` keeps the field showing
|
|
643
|
-
// the effective language (see the section's format below) and lets
|
|
644
|
-
// cordis.yml / lang.json keep their precedence.
|
|
645
|
-
lang: Schema.union(['zh', 'en']),
|
|
646
|
-
// Same no-default rule: unset keeps cordis.yml's `fullscreen`
|
|
647
|
-
// decisive; set overrides it from the next boot on.
|
|
648
|
-
fullscreen: Schema.boolean(),
|
|
649
|
-
// Unset inherits cordis.yml; a saved choice takes effect after restart.
|
|
650
|
-
terminalImages: Schema.boolean(),
|
|
651
|
-
// Built-in action-shortcut overrides, one optional combo string per
|
|
652
|
-
// action (see the keymap utility). Unset keeps the default binding
|
|
653
|
-
// and the section's format() shows the effective combos.
|
|
654
|
-
shortcuts: Schema.object(Object.fromEntries(SHORTCUT_ACTIONS.map(action => [action.id, Schema.string().required(false)]))).required(false),
|
|
655
|
-
}), () => {
|
|
541
|
+
const scope = createSettingsScope(configOwner, () => {
|
|
656
542
|
const current = configValues(runtimeConfig);
|
|
657
543
|
return { ...current, lang: isLang(current.lang) ? current.lang : undefined };
|
|
658
544
|
});
|
|
@@ -715,19 +601,16 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
715
601
|
applyMermaidDiagrams(value.mermaidDiagrams ?? config.mermaidDiagrams);
|
|
716
602
|
channel.setStatusBar(normalizeStatusBar(value.statusBar ?? config.statusBar));
|
|
717
603
|
};
|
|
718
|
-
//
|
|
719
|
-
// resolved: an unset action must not revive its startup override.
|
|
604
|
+
// Config is already resolved: an unset action must not revive its startup override.
|
|
720
605
|
// Applied live so the very next keypress matches the new combos.
|
|
721
606
|
const applyShortcuts = (value) => {
|
|
722
607
|
const userLayer = value.shortcuts ?? {};
|
|
723
|
-
const configLayer = scope.legacy ? config.shortcuts ?? {} : {};
|
|
724
608
|
const merged = {};
|
|
725
609
|
for (const action of SHORTCUT_ACTIONS) {
|
|
726
610
|
const user = userLayer[action.id];
|
|
727
|
-
const pinned = configLayer[action.id];
|
|
728
611
|
const chosen = typeof user === 'string' && user.trim() !== ''
|
|
729
612
|
? user
|
|
730
|
-
:
|
|
613
|
+
: undefined;
|
|
731
614
|
if (chosen !== undefined)
|
|
732
615
|
merged[action.id] = chosen;
|
|
733
616
|
}
|
|
@@ -758,30 +641,8 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
758
641
|
applyShortcuts(next);
|
|
759
642
|
applyRendererSettings(next);
|
|
760
643
|
};
|
|
761
|
-
// One-time fullscreen factory-default migration (companion to the
|
|
762
|
-
// schema + cordis.patch.yml flip false→true): a `fullscreen: false`
|
|
763
|
-
// pinned in the settings user layer BEFORE the flip keeps overriding
|
|
764
|
-
// the new default on every boot. The first boot past this code clears
|
|
765
|
-
// that stale explicit choice; the migrations.json marker makes it
|
|
766
|
-
// strictly once, so a `false` re-pinned afterwards always stands. The
|
|
767
|
-
// boot decision cannot wait for the async doc write — the stale value
|
|
768
|
-
// is shadowed out of the first apply below (destructuring omission,
|
|
769
|
-
// not an explicit undefined), and the later watch commit (fullscreen
|
|
770
|
-
// back to undefined) leaves the fullscreen decision unchanged.
|
|
771
644
|
const bootSettings = scope.get();
|
|
772
|
-
|
|
773
|
-
// profile's explicit inline Config must never be mistaken for that layer.
|
|
774
|
-
const fullscreenMigration = scope.legacy
|
|
775
|
-
? planFullscreenFactoryMigration(bootSettings.fullscreen, readAppliedMigrations())
|
|
776
|
-
: 'done';
|
|
777
|
-
void commitFullscreenFactoryMigration(fullscreenMigration, {
|
|
778
|
-
unset: () => settingsCtx.settings.mutate(tuiSettingsNs, [{ op: 'unset', path: ['fullscreen'] }]),
|
|
779
|
-
});
|
|
780
|
-
if (fullscreenMigration === 'unset') {
|
|
781
|
-
notifyChannel(t('settings-fullscreen-migrated'), { color: 'warning' });
|
|
782
|
-
}
|
|
783
|
-
const { fullscreen: staleFullscreen, ...migratedSettings } = bootSettings;
|
|
784
|
-
apply(fullscreenMigration === 'unset' ? migratedSettings : bootSettings);
|
|
645
|
+
apply(bootSettings);
|
|
785
646
|
let lastTerminalImages = bootSettings.terminalImages ?? config.terminalImages ?? true;
|
|
786
647
|
settingsCtx.effect(() => scope.watch(next => {
|
|
787
648
|
apply(next);
|
|
@@ -934,7 +795,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
934
795
|
{ value: 'en', label: 'English', descriptions: { zh: '英文' } },
|
|
935
796
|
],
|
|
936
797
|
format(value) {
|
|
937
|
-
// Unset in
|
|
798
|
+
// Unset in profile configuration: show the effective UI language
|
|
938
799
|
// (env / cordis.yml / lang.json resolution) instead of a
|
|
939
800
|
// blank "unset" that hides the current choice.
|
|
940
801
|
return value === undefined || value === null ? getLang() : String(value);
|
|
@@ -951,7 +812,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
951
812
|
hintDescriptions: { zh: '开启:接管整个终端(同 vim/less),应用内鼠标;关闭:终端原生滚动选择;整屏页两种模式都有鼠标。重启生效。' },
|
|
952
813
|
kind: 'boolean',
|
|
953
814
|
format(value) {
|
|
954
|
-
// Unset in
|
|
815
|
+
// Unset in profile configuration: show what THIS session booted with
|
|
955
816
|
// (the cordis.yml resolution) instead of a misleading false.
|
|
956
817
|
return value === undefined || value === null ? String(bootedFullscreen) : String(value);
|
|
957
818
|
},
|
|
@@ -1060,7 +921,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1060
921
|
hintDescriptions: { zh: '终端卡(Bash/PowerShell):多行命令头部折叠为首行 + 计数;Ctrl+O 或点击卡片展开。' },
|
|
1061
922
|
kind: 'boolean',
|
|
1062
923
|
format(value) {
|
|
1063
|
-
// Unset in
|
|
924
|
+
// Unset in profile configuration: show the effective resolution (cordis.yml
|
|
1064
925
|
// → off) instead of a blank — same rule as `fullscreen`'s field.
|
|
1065
926
|
return String(typeof value === 'boolean' ? value : config.foldTerminalCommand === true);
|
|
1066
927
|
},
|
|
@@ -1081,7 +942,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1081
942
|
hintDescriptions: { zh: '开启:输入行尾 ⛶ 按钮与全屏编辑快捷键(默认 Ctrl+Shift+E)把草稿展开成整屏编辑器(Enter 换行、Ctrl+Enter 发送)。关闭:两个入口都不显示。默认开启。' },
|
|
1082
943
|
kind: 'boolean',
|
|
1083
944
|
format(value) {
|
|
1084
|
-
// Unset in
|
|
945
|
+
// Unset in profile configuration: the effective default is on.
|
|
1085
946
|
return String(typeof value === 'boolean' ? value : config.expandEditor !== false);
|
|
1086
947
|
},
|
|
1087
948
|
},
|
|
@@ -1093,7 +954,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1093
954
|
hintDescriptions: { zh: '把实时回复、展开的思考与工具卡正文按 ~30fps 匀速揭示,不再随供应商突发一跳一跳;一次性到达的非流式回复也会平滑打出。回放/历史内容始终完整直出。默认开启。' },
|
|
1094
955
|
kind: 'boolean',
|
|
1095
956
|
format(value) {
|
|
1096
|
-
// Unset in
|
|
957
|
+
// Unset in profile configuration: the effective default is on.
|
|
1097
958
|
return String(typeof value === 'boolean' ? value : config.smoothStreaming !== false);
|
|
1098
959
|
},
|
|
1099
960
|
},
|
|
@@ -1105,7 +966,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1105
966
|
hintDescriptions: { zh: '把回复中的 ```mermaid 代码块画成字符图(flowchart、sequence、state、class、ER、pie、mindmap、timeline、gitGraph)。比终端宽或类型不支持的图保留源码。立即生效。默认开启。' },
|
|
1106
967
|
kind: 'boolean',
|
|
1107
968
|
format(value) {
|
|
1108
|
-
// Unset in
|
|
969
|
+
// Unset in profile configuration: the effective default is on.
|
|
1109
970
|
return String(typeof value === 'boolean' ? value : config.mermaidDiagrams !== false);
|
|
1110
971
|
},
|
|
1111
972
|
},
|
|
@@ -1117,7 +978,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1117
978
|
hintDescriptions: { zh: '开启:打开/恢复会话时自动把最近活动总结成一行灰字显示在会话底部(可悬停/点击查看或应用建议标题);关闭:手动使用 /recap。' },
|
|
1118
979
|
kind: 'boolean',
|
|
1119
980
|
format(value) {
|
|
1120
|
-
// Unset in
|
|
981
|
+
// Unset in profile configuration: the default is on.
|
|
1121
982
|
return value === undefined || value === null ? 'true' : String(value);
|
|
1122
983
|
},
|
|
1123
984
|
},
|
|
@@ -1136,7 +997,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1136
997
|
{ value: 'max', label: 'Max', descriptions: { zh: '最高' } },
|
|
1137
998
|
],
|
|
1138
999
|
format(value) {
|
|
1139
|
-
// Unset in
|
|
1000
|
+
// Unset in profile configuration: show what a boot would actually start
|
|
1140
1001
|
// on (the cordis effort pin → the persisted /effort choice)
|
|
1141
1002
|
// instead of a misleading blank.
|
|
1142
1003
|
if (value === undefined || value === null || value === 'auto') {
|
|
@@ -1386,10 +1247,6 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
|
|
|
1386
1247
|
notifyStderr = (text, options) => notifyChannel(text, options);
|
|
1387
1248
|
// The question-seat alert was raised before the channel existed; flush it
|
|
1388
1249
|
// now so it lands as an in-UI notice, not only in the log file.
|
|
1389
|
-
if (questionSeatNotice !== undefined) {
|
|
1390
|
-
notifyChannel(questionSeatNotice, { color: 'error' });
|
|
1391
|
-
questionSeatNotice = undefined;
|
|
1392
|
-
}
|
|
1393
1250
|
for (const [text, options] of stderrBacklog.splice(0)) {
|
|
1394
1251
|
notifyStderr(text, options);
|
|
1395
1252
|
}
|
|
@@ -1762,10 +1619,10 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
|
|
|
1762
1619
|
// between would otherwise drop the claim this boot just committed.
|
|
1763
1620
|
const reservation = reserved.reservation;
|
|
1764
1621
|
try {
|
|
1765
|
-
//
|
|
1622
|
+
// Register current TUI-owned event types before the
|
|
1766
1623
|
// strict read path (issue #153) — same seam as the /resume picker,
|
|
1767
1624
|
// here for the launch-time --resume flow. In-process only.
|
|
1768
|
-
|
|
1625
|
+
registerTuiSessionEventTypes();
|
|
1769
1626
|
// The resumed session keeps the preset its log records (last
|
|
1770
1627
|
// `agent-preset/selected` wins over the creation header), never the
|
|
1771
1628
|
// caller's current preference.
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent-preset resolution across upstream prerelease lines.
|
|
3
|
-
*
|
|
4
|
-
* Legacy rc.2 exports `resolveSessionPreset` and ships `code`; the 0.1.2 line
|
|
5
|
-
* replaces the helper with a projection definition and renames that preset to `ptc`.
|
|
6
|
-
* Keeping both compatibility decisions here prevents composition and channel
|
|
7
|
-
* code from acquiring prerelease-specific branches.
|
|
8
|
-
*/
|
|
1
|
+
/** Current DSH agent-preset roster and durable selection. */
|
|
9
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
10
3
|
/** One roster entry, as returned by `agentPresets.list()`/`resolve()`. */
|
|
11
4
|
export interface AgentPresetInfo {
|
|
@@ -40,18 +33,4 @@ export declare function resolveRecordedPreset(session: {
|
|
|
40
33
|
data: unknown;
|
|
41
34
|
}[];
|
|
42
35
|
}): string | undefined;
|
|
43
|
-
/**
|
|
44
|
-
* Resolve an exact roster id first, then bridge the official rename in either
|
|
45
|
-
* direction. A successful list is required before aliasing so roster I/O or
|
|
46
|
-
* a broken exact preset can never be mistaken for an unknown id.
|
|
47
|
-
*/
|
|
48
|
-
export declare function resolveCompatiblePreset(presets: AgentPresetsLike, requested?: string): Promise<AgentPresetInfo>;
|
|
49
|
-
/**
|
|
50
|
-
* The i18n dictionary id a roster preset's localized display text resolves
|
|
51
|
-
* under. The 0.1.2 line renamed the official PTC preset `code` → `ptc`, but
|
|
52
|
-
* the dictionary keys still use the legacy `code` id (`preset-name-code` /
|
|
53
|
-
* `preset-desc-code`), so the `/preset` picker's display lookup must bridge
|
|
54
|
-
* the roster id back. User-authored ids pass through untouched.
|
|
55
|
-
*/
|
|
56
|
-
export declare function presetDisplayId(id: string): string;
|
|
57
36
|
//# sourceMappingURL=preset-resolution.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset-resolution.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/preset-resolution.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"preset-resolution.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/preset-resolution.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAA;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,+DAA+D;AAC/D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,IAAI,IAAI,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAAA;IAC3C,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC9C,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC/D,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAClE,yEAAyE;IACzE,UAAU,CAAC,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAC3D;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAEnE;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,MAAM,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChC,MAAM,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;CACnD,GAAG,MAAM,GAAG,SAAS,CASrB"}
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent-preset resolution across upstream prerelease lines.
|
|
3
|
-
*
|
|
4
|
-
* Legacy rc.2 exports `resolveSessionPreset` and ships `code`; the 0.1.2 line
|
|
5
|
-
* replaces the helper with a projection definition and renames that preset to `ptc`.
|
|
6
|
-
* Keeping both compatibility decisions here prevents composition and channel
|
|
7
|
-
* code from acquiring prerelease-specific branches.
|
|
8
|
-
*/
|
|
9
1
|
/** The mounted preset roster, or undefined in a rosterless composition. */
|
|
10
2
|
export function rosterOf(ctx) {
|
|
11
3
|
return ctx.get('agentPresets');
|
|
@@ -24,29 +16,3 @@ export function resolveRecordedPreset(session) {
|
|
|
24
16
|
}
|
|
25
17
|
return session.header.agentPreset;
|
|
26
18
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Resolve an exact roster id first, then bridge the official rename in either
|
|
29
|
-
* direction. A successful list is required before aliasing so roster I/O or
|
|
30
|
-
* a broken exact preset can never be mistaken for an unknown id.
|
|
31
|
-
*/
|
|
32
|
-
export async function resolveCompatiblePreset(presets, requested) {
|
|
33
|
-
const fallback = requested === 'code' ? 'ptc' : requested === 'ptc' ? 'code' : undefined;
|
|
34
|
-
if (fallback === undefined)
|
|
35
|
-
return presets.resolve(requested);
|
|
36
|
-
const roster = await presets.list();
|
|
37
|
-
if (roster.some(preset => preset.id === requested))
|
|
38
|
-
return presets.resolve(requested);
|
|
39
|
-
if (roster.some(preset => preset.id === fallback))
|
|
40
|
-
return presets.resolve(fallback);
|
|
41
|
-
return presets.resolve(requested);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* The i18n dictionary id a roster preset's localized display text resolves
|
|
45
|
-
* under. The 0.1.2 line renamed the official PTC preset `code` → `ptc`, but
|
|
46
|
-
* the dictionary keys still use the legacy `code` id (`preset-name-code` /
|
|
47
|
-
* `preset-desc-code`), so the `/preset` picker's display lookup must bridge
|
|
48
|
-
* the roster id back. User-authored ids pass through untouched.
|
|
49
|
-
*/
|
|
50
|
-
export function presetDisplayId(id) {
|
|
51
|
-
return id === 'ptc' ? 'code' : id;
|
|
52
|
-
}
|
|
@@ -10,10 +10,7 @@
|
|
|
10
10
|
* factory's `setup(agentCtx)` hook, where a composition failure rolls the
|
|
11
11
|
* whole creation back instead of publishing a half-configured agent.
|
|
12
12
|
*
|
|
13
|
-
* A
|
|
14
|
-
* older CLI without the shipped preset root) composes nothing: callers get
|
|
15
|
-
* no `setup` and every session shares the host composition — the behavior
|
|
16
|
-
* before presets existed.
|
|
13
|
+
* A composition without a preset registry supplies no preset setup.
|
|
17
14
|
*/
|
|
18
15
|
import type { Context } from '@deepseek-ai/cordis';
|
|
19
16
|
import type { AgentSetup } from '@deepseek-ai/dsh-agent';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/presets.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAUtE,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmBhG;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAW5G;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGpE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAW/G;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAM/G;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAKpG"}
|
|
@@ -10,15 +10,12 @@
|
|
|
10
10
|
* factory's `setup(agentCtx)` hook, where a composition failure rolls the
|
|
11
11
|
* whole creation back instead of publishing a half-configured agent.
|
|
12
12
|
*
|
|
13
|
-
* A
|
|
14
|
-
* older CLI without the shipped preset root) composes nothing: callers get
|
|
15
|
-
* no `setup` and every session shares the host composition — the behavior
|
|
16
|
-
* before presets existed.
|
|
13
|
+
* A composition without a preset registry supplies no preset setup.
|
|
17
14
|
*/
|
|
18
15
|
import { recordedModelRoute } from '../modelRoute.js';
|
|
19
16
|
import { snapshotLiveSessionEvents } from './compat/liveSession.js';
|
|
20
17
|
import { readPersistedSession } from './compat/persistence.js';
|
|
21
|
-
import {
|
|
18
|
+
import { resolveRecordedPreset, rosterOf, } from './preset-resolution.js';
|
|
22
19
|
const ASK_USER_TOOL = 'ask_user_question';
|
|
23
20
|
/**
|
|
24
21
|
* Resolve the preset one new/resumed session will run under and the setup
|
|
@@ -39,7 +36,7 @@ export async function composePreset(ctx, requested) {
|
|
|
39
36
|
return {};
|
|
40
37
|
let resolvedId;
|
|
41
38
|
try {
|
|
42
|
-
resolvedId = (await
|
|
39
|
+
resolvedId = (await presets.resolve(requested)).id;
|
|
43
40
|
}
|
|
44
41
|
catch (error) {
|
|
45
42
|
ctx.logger.warn(`dsh-tui: agent preset ${requested === undefined ? '(default)' : `"${requested}"`} unavailable ` +
|
|
@@ -1,51 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User-question answerer compatibility.
|
|
3
|
-
*
|
|
4
|
-
* Legacy rc.2 exposes one global `registerProvider` seat. The 0.1.2 line removed that
|
|
5
|
-
* API in favour of a scope-aware `user-questions/request` waterfall. Keep the
|
|
6
|
-
* capability probe and both registration paths here so the TUI bootstrap only
|
|
7
|
-
* consumes a small prepared-registration result.
|
|
8
|
-
*/
|
|
1
|
+
/** Scope-aware question routing. Registration belongs to the TUI fiber. */
|
|
9
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
10
3
|
import type { AskUserQuestionAnswer, AskUserQuestionRequest } from '@deepseek-ai/dsh-user-questions';
|
|
11
|
-
import { type QuestionProviderYieldDecision } from './providerGuard.js';
|
|
12
4
|
export interface QuestionAnswerer {
|
|
13
5
|
ask(request: AskUserQuestionRequest, options?: {
|
|
14
6
|
redact?: boolean;
|
|
15
7
|
}): Promise<AskUserQuestionAnswer>;
|
|
16
8
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} | {
|
|
22
|
-
readonly kind: 'waterfall';
|
|
23
|
-
/** Bind ownership after the mutable channel has been created. */
|
|
24
|
-
register(owner: {
|
|
25
|
-
readonly agentId: string;
|
|
26
|
-
}): () => void;
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Prepare the answerer against whichever upstream API the active package
|
|
30
|
-
* exposes. The legacy path registers immediately and binds the returned
|
|
31
|
-
* disposer to this TUI fiber. The waterfall path returns a late binder because
|
|
32
|
-
* channel.agentId changes across `/new`, `/resume`, and rewind.
|
|
33
|
-
*
|
|
34
|
-
* Agentless waterfall requests are claimed deliberately: dsh-auth's `/auth`
|
|
35
|
-
* wizard asks through the same service without an agent. Foreign-agent
|
|
36
|
-
* requests continue to the next answerer.
|
|
37
|
-
*
|
|
38
|
-
* Security scope (#586): the provider-seat guard (DUPLICATE_PROVIDER probe +
|
|
39
|
-
* private symbol check) exists ONLY on the legacy path. The waterfall has no
|
|
40
|
-
* seat. Agent-bearing requests are scope-filtered; agentless requests such as
|
|
41
|
-
* dsh-auth `/auth` are dispatched without a scope carrier. Under the answerer
|
|
42
|
-
* contract, the first eligible listener that returns instead of delegating
|
|
43
|
-
* with `next()` claims the request. Cordis waterfall is around middleware,
|
|
44
|
-
* however: an outer listener can call `next()` and then observe, replace, or
|
|
45
|
-
* reject the downstream result, while `{ prepend: true }` inserts a listener
|
|
46
|
-
* at the front. Upstream exposes no supported way to discover or reserve an
|
|
47
|
-
* exclusive claimant, so the legacy guard and its warning cannot be
|
|
48
|
-
* reproduced here.
|
|
49
|
-
*/
|
|
50
|
-
export declare function prepareQuestionAnswerer(ctx: Context, service: unknown, answerer: QuestionAnswerer): PreparedQuestionAnswerer;
|
|
9
|
+
/** Read the mutable channel identity for every request, including after resume. */
|
|
10
|
+
export declare function registerQuestionAnswerer(ctx: Context, owner: {
|
|
11
|
+
readonly agentId: string;
|
|
12
|
+
}, answerer: QuestionAnswerer): () => void;
|
|
51
13
|
//# sourceMappingURL=questions-answerer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"questions-answerer.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/questions-answerer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"questions-answerer.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/questions-answerer.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AAEpG,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,OAAO,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAA;CACrG;AAED,mFAAmF;AACnF,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACnC,QAAQ,EAAE,gBAAgB,GACzB,MAAM,IAAI,CAKZ"}
|
|
@@ -1,64 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*/
|
|
9
|
-
import { decideQuestionProviderYield, incumbentQuestionProviderId, tagTuiQuestionProvider, } from './providerGuard.js';
|
|
10
|
-
function secretRequest(request) {
|
|
11
|
-
return request.questions.some(question => question.id === 'dsh-auth-secret');
|
|
12
|
-
}
|
|
13
|
-
function hasLegacyProvider(service) {
|
|
14
|
-
return typeof service.registerProvider === 'function';
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Prepare the answerer against whichever upstream API the active package
|
|
18
|
-
* exposes. The legacy path registers immediately and binds the returned
|
|
19
|
-
* disposer to this TUI fiber. The waterfall path returns a late binder because
|
|
20
|
-
* channel.agentId changes across `/new`, `/resume`, and rewind.
|
|
21
|
-
*
|
|
22
|
-
* Agentless waterfall requests are claimed deliberately: dsh-auth's `/auth`
|
|
23
|
-
* wizard asks through the same service without an agent. Foreign-agent
|
|
24
|
-
* requests continue to the next answerer.
|
|
25
|
-
*
|
|
26
|
-
* Security scope (#586): the provider-seat guard (DUPLICATE_PROVIDER probe +
|
|
27
|
-
* private symbol check) exists ONLY on the legacy path. The waterfall has no
|
|
28
|
-
* seat. Agent-bearing requests are scope-filtered; agentless requests such as
|
|
29
|
-
* dsh-auth `/auth` are dispatched without a scope carrier. Under the answerer
|
|
30
|
-
* contract, the first eligible listener that returns instead of delegating
|
|
31
|
-
* with `next()` claims the request. Cordis waterfall is around middleware,
|
|
32
|
-
* however: an outer listener can call `next()` and then observe, replace, or
|
|
33
|
-
* reject the downstream result, while `{ prepend: true }` inserts a listener
|
|
34
|
-
* at the front. Upstream exposes no supported way to discover or reserve an
|
|
35
|
-
* exclusive claimant, so the legacy guard and its warning cannot be
|
|
36
|
-
* reproduced here.
|
|
37
|
-
*/
|
|
38
|
-
export function prepareQuestionAnswerer(ctx, service, answerer) {
|
|
39
|
-
if (!hasLegacyProvider(service)) {
|
|
40
|
-
const events = ctx;
|
|
41
|
-
return {
|
|
42
|
-
kind: 'waterfall',
|
|
43
|
-
register: owner => events.on('user-questions/request', (request, next) => {
|
|
44
|
-
if (request.agent !== undefined && String(request.agent.id) !== owner.agentId)
|
|
45
|
-
return next();
|
|
46
|
-
return answerer.ask(request, { redact: secretRequest(request) });
|
|
47
|
-
}),
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
const provider = { ask: request => answerer.ask(request, { redact: secretRequest(request) }) };
|
|
51
|
-
tagTuiQuestionProvider(provider);
|
|
52
|
-
try {
|
|
53
|
-
ctx.effect(() => service.registerProvider(provider), 'dsh-tui.questions.legacy-provider');
|
|
54
|
-
return { kind: 'legacy' };
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
if (error.code !== 'DUPLICATE_PROVIDER')
|
|
58
|
-
throw error;
|
|
59
|
-
return {
|
|
60
|
-
kind: 'legacy',
|
|
61
|
-
yieldDecision: decideQuestionProviderYield(incumbentQuestionProviderId(service)),
|
|
62
|
-
};
|
|
63
|
-
}
|
|
1
|
+
/** Read the mutable channel identity for every request, including after resume. */
|
|
2
|
+
export function registerQuestionAnswerer(ctx, owner, answerer) {
|
|
3
|
+
return ctx.on('user-questions/request', (request, next) => {
|
|
4
|
+
if (request.agent !== undefined && String(request.agent.id) !== owner.agentId)
|
|
5
|
+
return next();
|
|
6
|
+
return answerer.ask(request, { redact: request.questions.some(question => question.id === 'dsh-auth-secret') });
|
|
7
|
+
});
|
|
64
8
|
}
|