@askdkc/dsh-cli 0.13.2 → 0.13.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +2 -2
  2. package/bin/dsh-tui.js +2 -2
  3. package/lib/types/components/LogoV2.d.ts +1 -5
  4. package/lib/types/components/LogoV2.d.ts.map +1 -1
  5. package/lib/types/components/LogoV2.js +3 -12
  6. package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -1
  7. package/lib/types/dsh-adapter/bundled-presets.js +9 -0
  8. package/lib/types/dsh-adapter/contract.d.ts +6 -55
  9. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  10. package/lib/types/dsh-adapter/contract.js +15 -129
  11. package/lib/types/dsh-adapter/index.d.ts +3 -3
  12. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  13. package/lib/types/dsh-adapter/index.js +6 -12
  14. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  15. package/lib/types/dsh-adapter/plugin.js +3 -1
  16. package/lib/types/dsh-adapter/recap.d.ts.map +1 -1
  17. package/lib/types/dsh-adapter/recap.js +5 -1
  18. package/lib/types/dsh-adapter/response-language.d.ts +6 -0
  19. package/lib/types/dsh-adapter/response-language.d.ts.map +1 -0
  20. package/lib/types/dsh-adapter/response-language.js +11 -0
  21. package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
  22. package/lib/types/dsh-adapter/sideQuestion.js +3 -0
  23. package/lib/types/i18n.d.ts +5 -22
  24. package/lib/types/i18n.d.ts.map +1 -1
  25. package/lib/types/i18n.js +6 -25
  26. package/lib/types/update.d.ts +2 -2
  27. package/lib/types/update.js +2 -2
  28. package/node_modules/@askdkc/dsh-auth/package.json +29 -11
  29. package/node_modules/dsh-working-activity/lib/types/index.js +4 -6
  30. package/node_modules/dsh-working-activity/lib/types/lang.d.ts +10 -8
  31. package/node_modules/dsh-working-activity/lib/types/lang.js +11 -12
  32. package/node_modules/dsh-working-activity/package.json +27 -9
  33. package/node_modules/dsh-working-activity/src/index.ts +4 -6
  34. package/node_modules/dsh-working-activity/src/lang.ts +12 -13
  35. package/package.json +108 -95
  36. package/presets/liangshen/agent.cordis.yml +2 -1
  37. package/presets/response-language.txt +5 -0
package/README.md CHANGED
@@ -42,8 +42,8 @@ This is dkc's independently developed fork of [dsh-TUI by chimney](https://githu
42
42
  Requires [Node.js](https://nodejs.org/en) `^22.19 || >=24`, pnpm 11, a
43
43
  [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) source
44
44
  checkout with dependencies installed, and `DEEPSEEK_API_KEY`. We aim to support
45
- the latest DSH release. The primary validated Harness version is `0.2.0-rc.2`;
46
- older supported versions are listed in [ADAPTER.md](ADAPTER.md).
45
+ current DSH APIs. Compatibility is checked against installed packages and the
46
+ upstream default branch, without a release allowlist; see [ADAPTER.md](ADAPTER.md).
47
47
 
48
48
  Clone recursively to fetch submodules. In an existing checkout, run
49
49
  `git submodule update --init --recursive` before installation.
package/bin/dsh-tui.js CHANGED
@@ -25,7 +25,7 @@
25
25
  * 可用。shellQuote 等小工具在此内联。
26
26
  *
27
27
  * 面向用户的消息走 MSG 双语表:与 TUI 的语言契约一致——
28
- * `DSH_TUI_LANG` 显式指定时从其值,否则默认中文(同 src/i18n.ts 的缺省)。
28
+ * `DSH_TUI_LANG` 显式指定时从其值,否则默认英文(同 src/i18n.ts 的缺省)。
29
29
  */
30
30
  import { spawn, spawnSync } from 'node:child_process'
31
31
  import { existsSync, readFileSync, readdirSync, realpathSync, rmSync } from 'node:fs'
@@ -133,7 +133,7 @@ const isVersionNewer = (a, b) => {
133
133
  return false
134
134
  }
135
135
 
136
- const lang = process.env.DSH_TUI_LANG === 'en' ? 'en' : 'zh'
136
+ const lang = process.env.DSH_TUI_LANG === 'zh' ? 'zh' : 'en'
137
137
  const MSG = {
138
138
  noDsh: {
139
139
  en: '[dsh-cli] dsh CLI not found. Install it or set DSH_TUI_DSH_ROOT to a built Harness checkout:\n npm install -g @deepseek-ai/dsh',
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { type Tip } from '../tips.js';
3
- import { type UpstreamDriftSummary } from '../dsh-adapter/contract.js';
4
3
  import { type WhaleIntroId } from './whaleFrames.js';
5
4
  /**
6
5
  * The header splash: one layout, two phases. The **opening** (~1.7–3.5s,
@@ -20,7 +19,7 @@ import { type WhaleIntroId } from './whaleFrames.js';
20
19
  * blue. Narrow terminals show complete big text, then the whale alone,
21
20
  * then a plain title as space runs out.
22
21
  */
23
- export declare function LogoV2({ model, effort, cwd, skipIntro, intro, tip, whale, whaleIdle, working, drift, }: {
22
+ export declare function LogoV2({ model, effort, cwd, skipIntro, intro, tip, whale, whaleIdle, working, }: {
24
23
  model: string;
25
24
  effort?: string | undefined;
26
25
  cwd: string;
@@ -42,8 +41,5 @@ export declare function LogoV2({ model, effort, cwd, skipIntro, intro, tip, whal
42
41
  * click-hearts are welcome-phase features); sustained !working before
43
42
  * that lets it fall asleep. */
44
43
  working?: boolean;
45
- /** Test seam: pin/suppress the upstream-drift notice (`null` forces it off;
46
- * `undefined` — the production default — auto-detects the install). */
47
- drift?: UpstreamDriftSummary | null;
48
44
  }): React.ReactNode;
49
45
  //# sourceMappingURL=LogoV2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogoV2.d.ts","sourceRoot":"","sources":["../../../src/components/LogoV2.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAoD,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAaxH,OAAO,EAA+E,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AA4CjI;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,MAAM,EACN,GAAG,EACH,SAAiB,EACjB,KAAK,EACL,GAAG,EACH,KAAY,EACZ,SAAgB,EAChB,OAAe,EACf,KAAK,GACN,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;4CAGwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;mCAG+B;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;2EACuE;IACvE,KAAK,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAA;CACpC,GAAG,KAAK,CAAC,SAAS,CAmOlB"}
1
+ {"version":3,"file":"LogoV2.d.ts","sourceRoot":"","sources":["../../../src/components/LogoV2.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,YAAY,CAAA;AAapD,OAAO,EAA+E,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AA4CjI;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,MAAM,EACN,GAAG,EACH,SAAiB,EACjB,KAAK,EACL,GAAG,EACH,KAAY,EACZ,SAAgB,EAChB,OAAe,GAChB,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;4CAGwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;mCAG+B;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG,KAAK,CAAC,SAAS,CA+MlB"}
@@ -1,8 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React from 'react';
3
- import { getLang, t as tr, tOr } from '../i18n.js';
3
+ import { getLang, t as tr } from '../i18n.js';
4
4
  import { pickRandomTip } from '../tips.js';
5
- import { upstreamDriftSummary, UPSTREAM_VALIDATED_VERSION } from '../dsh-adapter/contract.js';
6
5
  import { readFileSync } from 'node:fs';
7
6
  import { dirname, join } from 'node:path';
8
7
  import { fileURLToPath } from 'node:url';
@@ -69,7 +68,7 @@ function capitalize(text) {
69
68
  * blue. Narrow terminals show complete big text, then the whale alone,
70
69
  * then a plain title as space runs out.
71
70
  */
72
- export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whale = true, whaleIdle = true, working = false, drift, }) {
71
+ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whale = true, whaleIdle = true, working = false, }) {
73
72
  // One intro per logo mount: the production path rolls (startup splash
74
73
  // and each /deepseek replay roll independently), the `intro` seam pins
75
74
  // a specific animation for probes.
@@ -199,10 +198,6 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whal
199
198
  // repaint (language switch, terminal resize), or the line would flicker.
200
199
  // `tip` is a test seam; production always passes undefined and rolls.
201
200
  const [randomTip] = React.useState(() => tip ?? pickRandomTip());
202
- // Upstream-drift notice, merged to one line: computed once per mount from
203
- // the same memoized contract data the adapter checks (undefined when the
204
- // install matches). `drift` is a test seam to pin or suppress it.
205
- const [driftLine] = React.useState(() => drift === undefined ? upstreamDriftSummary() : drift);
206
201
  // Indent that centers the tagline under the whale art's bounding box.
207
202
  const welcomePad = showWhale
208
203
  ? Math.max(0, Math.round(WHALE_CENTER - stringWidth(tagline) / 2))
@@ -225,9 +220,5 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whal
225
220
  setHeartSeq(0);
226
221
  setHeartKey(k => k + 1);
227
222
  }
228
- }, children: _jsx(WhaleArt, { frameIndex: frameIndex, pose: settled && whaleIdle && !whaleFrozen ? (idlePose ?? RESTING_POSE) : undefined, width: WHALE_BOX_WIDTH }) })), (showBigTitle || showPlainTitle) && _jsxs(Box, { flexDirection: "column", flexShrink: 1, children: [_jsxs(Text, { wrap: "truncate-end", children: [sweep('✦ dsh-CLI', t, wordmarkRGB, wordmarkShimmerRGB, 60), _jsx(Text, { dimColor: true, children: ' v' + VERSION })] }), showBigTitle ? _jsxs(_Fragment, { children: [bigDeepSeek.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `ds-${index}`))), bigHarness.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `h-${index}`)))] }) : _jsx(Text, { color: "accent", bold: true, wrap: "truncate-end", children: "DeepSeek Harness" }), _jsxs(Text, { wrap: "truncate-end", children: [model, effort !== undefined && _jsx(Text, { dimColor: true, children: ' · ' + capitalize(effort) + ' effort' })] }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: cwd }), _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { dimColor: true, children: tr('logo-tip-prefix') }), getLang() === 'zh' ? randomTip.zh : randomTip.en, _jsx(Text, { dimColor: true, children: ' · /tips ' + tr('logo-tip-more') })] }), driftLine != null && (_jsxs(Text, { color: "warning", wrap: "wrap", children: ["\u26A0", ' ', tOr(`logo-drift-${driftLine.kind}`, `The dsh engine (${driftLine.versions.join(' / ')}) does not match the validated ${UPSTREAM_VALIDATED_VERSION}; reinstall via npm i -g @deepseek-ai/dsh@${UPSTREAM_VALIDATED_VERSION}.`, {
229
- installed: driftLine.versions.join(' / '),
230
- validated: UPSTREAM_VALIDATED_VERSION,
231
- primary: UPSTREAM_VALIDATED_VERSION,
232
- })] }))] })] }), _jsx(Box, { marginTop: 1, paddingLeft: welcomePad, children: _jsx(Text, { children: sweep(tagline, t, taglineRGB, FLASH, 60) }) })] }));
223
+ }, children: _jsx(WhaleArt, { frameIndex: frameIndex, pose: settled && whaleIdle && !whaleFrozen ? (idlePose ?? RESTING_POSE) : undefined, width: WHALE_BOX_WIDTH }) })), (showBigTitle || showPlainTitle) && _jsxs(Box, { flexDirection: "column", flexShrink: 1, children: [_jsxs(Text, { wrap: "truncate-end", children: [sweep('✦ dsh-CLI', t, wordmarkRGB, wordmarkShimmerRGB, 60), _jsx(Text, { dimColor: true, children: ' v' + VERSION })] }), showBigTitle ? _jsxs(_Fragment, { children: [bigDeepSeek.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `ds-${index}`))), bigHarness.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `h-${index}`)))] }) : _jsx(Text, { color: "accent", bold: true, wrap: "truncate-end", children: "DeepSeek Harness" }), _jsxs(Text, { wrap: "truncate-end", children: [model, effort !== undefined && _jsx(Text, { dimColor: true, children: ' · ' + capitalize(effort) + ' effort' })] }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: cwd }), _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { dimColor: true, children: tr('logo-tip-prefix') }), getLang() === 'zh' ? randomTip.zh : randomTip.en, _jsx(Text, { dimColor: true, children: ' · /tips ' + tr('logo-tip-more') })] })] })] }), _jsx(Box, { marginTop: 1, paddingLeft: welcomePad, children: _jsx(Text, { children: sweep(tagline, t, taglineRGB, FLASH, 60) }) })] }));
233
224
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bundled-presets.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/bundled-presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AA4BlD;qFACqF;AACrF,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCxE"}
1
+ {"version":3,"file":"bundled-presets.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/bundled-presets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAoClD;qFACqF;AACrF,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCxE"}
@@ -1,3 +1,4 @@
1
+ import { RESPONSE_LANGUAGE_POLICY } from './response-language.js';
1
2
  import { readFileSync } from 'node:fs';
2
3
  import { createRequire } from 'node:module';
3
4
  import { join } from 'node:path';
@@ -13,6 +14,14 @@ function readPresetPatch(path) {
13
14
  const row = patches[0]?.insert?.[0];
14
15
  if (row?.name === '@deepseek-ai/dsh-agent-preset'
15
16
  && typeof row.config?.id === 'string' && Array.isArray(row.config.plugins)) {
17
+ // Only adapt our bundled complete persona; profile-owned declarations bypass this reader.
18
+ if (row.config.id === 'minimal') {
19
+ const persona = row.config.plugins.find((plugin) => plugin.id === 'persona');
20
+ if (persona?.config?.complete !== true || typeof persona.config.prefix !== 'string') {
21
+ throw new Error('dsh-tui: bundled Minimal complete persona is missing');
22
+ }
23
+ persona.config.prefix += `\n\n${RESPONSE_LANGUAGE_POLICY}`;
24
+ }
16
25
  return row.config;
17
26
  }
18
27
  }
@@ -1,62 +1,13 @@
1
- /** Primary validated upstream line (newest). */
2
- export declare const UPSTREAM_VALIDATED_VERSION = "0.2.0-rc.2";
3
- /** Update the baseline in place; older releases are unsupported. */
4
- export declare const UPSTREAM_VALIDATED_VERSIONS: readonly ["0.2.0-rc.2"];
5
- /**
6
- * Framework packages version on their own lines; the contract validates
7
- * their MAJOR (breaking surface), not the harness prerelease number.
8
- */
1
+ /** Frameworks have independent, breaking major versions. */
9
2
  export declare const UPSTREAM_FRAMEWORK_MAJORS: Record<string, number>;
10
3
  /** Official packages the adapter consumes at runtime or as types. */
11
4
  export declare const UPSTREAM_BLESSED_PACKAGES: readonly ["@deepseek-ai/cordis", "@deepseek-ai/schemastery", "@deepseek-ai/dsh-invariants", "@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-agent-instructions", "@deepseek-ai/dsh-agent-preset-registry", "@deepseek-ai/dsh-atomic-write", "@deepseek-ai/dsh-ptc-runtime-node", "@deepseek-ai/dsh-commands", "@deepseek-ai/dsh-cordis-host-runner", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-llm-pi-ai", "@deepseek-ai/dsh-persona", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-settings", "@deepseek-ai/dsh-skill", "@deepseek-ai/dsh-storage", "@deepseek-ai/dsh-storage-domain", "@deepseek-ai/dsh-storage-json", "@deepseek-ai/dsh-workspace", "@deepseek-ai/dsh-web-app", "@deepseek-ai/dsh-system-prompt", "@deepseek-ai/dsh-terminal", "@deepseek-ai/dsh-terminal-bash", "@deepseek-ai/dsh-tool-ask-user", "@deepseek-ai/dsh-tool-bash-persistent", "@deepseek-ai/dsh-tool-cordis", "@deepseek-ai/dsh-tool-subagent", "@deepseek-ai/dsh-user-approval", "@deepseek-ai/dsh-user-questions"];
12
- export interface UpstreamDriftEntry {
5
+ export declare function installedUpstreamVersions(): Record<string, string | undefined>;
6
+ export interface UpstreamDependencyIssue {
13
7
  package: string;
14
8
  installed: string | undefined;
15
- validated: string;
16
- }
17
- /** Supported upstream prerelease channels in ascending precedence order. */
18
- export type UpstreamPrereleaseChannel = 'alpha' | 'beta' | 'rc';
19
- /** A parsed upstream prerelease version, e.g. `0.1.2-alpha.1` → `[0, 1, 2, 'alpha', 1]`. */
20
- export type UpstreamVersionTuple = readonly [number, number, number, UpstreamPrereleaseChannel, number];
21
- /** Parse an upstream prerelease version; undefined when unparseable. */
22
- export declare function parseUpstreamVersion(version: string | undefined): UpstreamVersionTuple | undefined;
23
- /** Order two parsed versions: negative/positive/zero as a `<`/`>`/`=`. */
24
- export declare function compareVersions(a: UpstreamVersionTuple, b: UpstreamVersionTuple): number;
25
- /** Human-readable supported release. */
26
- export declare const UPSTREAM_VALIDATED_LABEL = "0.2.0-rc.2";
27
- export declare function installedUpstreamVersions(): Record<string, string | undefined>;
28
- /**
29
- * The distinct installed prerelease versions across the blessed harness
30
- * packages (framework packages excluded). One entry = coherent install;
31
- * several = a mixed tree, which the per-package drift check cannot see.
32
- * Empty when nothing (or no harness package) is installed.
33
- */
34
- export declare function installedUpstreamLines(installedVersions?: Readonly<Record<string, string | undefined>>): string[];
35
- /**
36
- * Report every blessed package whose installed version is NOT one of the
37
- * validated release lines. Empty array = the running install matches the
38
- * contract.
39
- */
40
- export declare function upstreamDrift(installedVersions?: Readonly<Record<string, string | undefined>>): UpstreamDriftEntry[];
41
- /**
42
- * Classification of a drifted install for the one-line boot notice:
43
- * `newer` / `older` — every drifted harness package sits on a single
44
- * parseable version off one end of the validated window; `mixed` — several
45
- * distinct versions coexist (unstable tree); `broken` — something is
46
- * missing or unparseable and wording cannot get more specific.
47
- */
48
- export type UpstreamDriftKind = 'newer' | 'older' | 'mixed' | 'broken';
49
- /** Merged drift verdict consumed by the logo header notice (LogoV2). */
50
- export interface UpstreamDriftSummary {
51
- kind: UpstreamDriftKind;
52
- /** Distinct installed versions among drifted packages ('missing' for absent ones). */
53
- versions: string[];
9
+ reason: string;
54
10
  }
55
- /**
56
- * Collapse {@link upstreamDrift} into a single summary for the boot notice:
57
- * undefined when the install matches the contract. Only harness prerelease packages
58
- * decide newer/older/mixed; a framework-only drift (e.g. a cordis major
59
- * bump) reports `broken`, since its version line is not comparable.
60
- */
61
- export declare function upstreamDriftSummary(installedVersions?: Readonly<Record<string, string | undefined>>): UpstreamDriftSummary | undefined;
11
+ /** Require the development dependency surface without restricting DSH releases. */
12
+ export declare function upstreamDependencyIssues(installedVersions?: Readonly<Record<string, string | undefined>>): UpstreamDependencyIssue[];
62
13
  //# sourceMappingURL=contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/contract.ts"],"names":[],"mappings":"AAeA,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,eAAe,CAAA;AAEtD,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,yBAAwC,CAAA;AAEhF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAG5D,CAAA;AAED,qEAAqE;AACrE,eAAO,MAAM,yBAAyB,o8BA+B5B,CAAA;AAEV,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB;AASD,4EAA4E;AAC5E,MAAM,MAAM,yBAAyB,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAA;AAE/D,4FAA4F;AAC5F,MAAM,MAAM,oBAAoB,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,MAAM,CAAC,CAAA;AAEvG,wEAAwE;AACxE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAKlG;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAQxF;AAED,wCAAwC;AACxC,eAAO,MAAM,wBAAwB,eAA6B,CAAA;AAYlE,wBAAgB,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAqB9E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,iBAAiB,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAA+B,GAC5F,MAAM,EAAE,CAQV;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,iBAAiB,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAA+B,GAC5F,kBAAkB,EAAE,CAuBtB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEtE,wEAAwE;AACxE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,iBAAiB,CAAA;IACvB,sFAAsF;IACtF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,iBAAiB,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAA+B,GAC5F,oBAAoB,GAAG,SAAS,CA0BlC"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/contract.ts"],"names":[],"mappings":"AAIA,4DAA4D;AAC5D,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAG5D,CAAA;AAED,qEAAqE;AACrE,eAAO,MAAM,yBAAyB,o8BA+B5B,CAAA;AAYV,wBAAgB,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAqB9E;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,mFAAmF;AACnF,wBAAgB,wBAAwB,CACtC,iBAAiB,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAA+B,GAC5F,uBAAuB,EAAE,CAY3B"}
@@ -1,25 +1,7 @@
1
- /**
2
- * Upstream compatibility contract.
3
- *
4
- * The TUI supports one validated upstream release: 0.2.0-rc.2.
5
- * Every official package this adapter touches is blessed here; anything
6
- * else must go through upstream channels or the adapter, never the UI.
7
- *
8
- * `upstreamDrift()` powers the CI gate (scripts/verify-upstream-contract.ts)
9
- * so a mismatched install fails in CI before it fails on a user's machine.
10
- * `upstreamDriftSummary()` collapses the per-package entries into the
11
- * single natural-language boot notice the logo header shows (see LogoV2).
12
- */
1
+ /** Host dependency boundary. Release labels are diagnostic data, not an allowlist. */
13
2
  import { readFileSync } from 'node:fs';
14
3
  import { fileURLToPath } from 'node:url';
15
- /** Primary validated upstream line (newest). */
16
- export const UPSTREAM_VALIDATED_VERSION = '0.2.0-rc.2';
17
- /** Update the baseline in place; older releases are unsupported. */
18
- export const UPSTREAM_VALIDATED_VERSIONS = [UPSTREAM_VALIDATED_VERSION];
19
- /**
20
- * Framework packages version on their own lines; the contract validates
21
- * their MAJOR (breaking surface), not the harness prerelease number.
22
- */
4
+ /** Frameworks have independent, breaking major versions. */
23
5
  export const UPSTREAM_FRAMEWORK_MAJORS = {
24
6
  '@deepseek-ai/cordis': 4,
25
7
  '@deepseek-ai/schemastery': 3,
@@ -57,33 +39,6 @@ export const UPSTREAM_BLESSED_PACKAGES = [
57
39
  '@deepseek-ai/dsh-user-approval',
58
40
  '@deepseek-ai/dsh-user-questions',
59
41
  ];
60
- // These capabilities are optional at runtime. CI requires the complete dev tree.
61
- const OPTIONAL_RUNTIME_PACKAGES = new Set([
62
- '@deepseek-ai/dsh-agent-preset-registry',
63
- '@deepseek-ai/dsh-ptc-runtime-node',
64
- '@deepseek-ai/dsh-web-app',
65
- ]);
66
- /** Parse an upstream prerelease version; undefined when unparseable. */
67
- export function parseUpstreamVersion(version) {
68
- const match = /^(\d+)\.(\d+)\.(\d+)-(alpha|beta|rc)\.(\d+)$/u.exec(version ?? '');
69
- return match === null
70
- ? undefined
71
- : [Number(match[1]), Number(match[2]), Number(match[3]), match[4], Number(match[5])];
72
- }
73
- /** Order two parsed versions: negative/positive/zero as a `<`/`>`/`=`. */
74
- export function compareVersions(a, b) {
75
- for (const index of [0, 1, 2]) {
76
- if (a[index] > b[index])
77
- return 1;
78
- if (a[index] < b[index])
79
- return -1;
80
- }
81
- const channelRank = { alpha: 0, beta: 1, rc: 2 };
82
- const channelOrder = channelRank[a[3]] - channelRank[b[3]];
83
- return channelOrder !== 0 ? channelOrder : a[4] - b[4];
84
- }
85
- /** Human-readable supported release. */
86
- export const UPSTREAM_VALIDATED_LABEL = UPSTREAM_VALIDATED_VERSION;
87
42
  function resolvePackageJson(packageName) {
88
43
  try {
89
44
  const path = import.meta.resolve(`${packageName}/package.json`);
@@ -95,7 +50,7 @@ function resolvePackageJson(packageName) {
95
50
  }
96
51
  let cachedVersions;
97
52
  export function installedUpstreamVersions() {
98
- // Package manifests do not change mid-process; memoize the boot diagnosis.
53
+ // Package manifests do not change during one verification process.
99
54
  // Frozen so callers can
100
55
  // never corrupt the shared cache.
101
56
  if (cachedVersions !== undefined)
@@ -107,7 +62,7 @@ export function installedUpstreamVersions() {
107
62
  if (path !== undefined) {
108
63
  try {
109
64
  const manifest = JSON.parse(readFileSync(path, 'utf8'));
110
- version = manifest.version;
65
+ version = typeof manifest.version === 'string' ? manifest.version : undefined;
111
66
  }
112
67
  catch {
113
68
  version = undefined;
@@ -118,87 +73,18 @@ export function installedUpstreamVersions() {
118
73
  cachedVersions = Object.freeze(result);
119
74
  return cachedVersions;
120
75
  }
121
- /**
122
- * The distinct installed prerelease versions across the blessed harness
123
- * packages (framework packages excluded). One entry = coherent install;
124
- * several = a mixed tree, which the per-package drift check cannot see.
125
- * Empty when nothing (or no harness package) is installed.
126
- */
127
- export function installedUpstreamLines(installedVersions = installedUpstreamVersions()) {
128
- const lines = new Set();
129
- for (const packageName of UPSTREAM_BLESSED_PACKAGES) {
130
- if (UPSTREAM_FRAMEWORK_MAJORS[packageName] !== undefined)
131
- continue;
132
- const version = installedVersions[packageName];
133
- if (version !== undefined && parseUpstreamVersion(version) !== undefined)
134
- lines.add(version);
135
- }
136
- return [...lines].sort((a, b) => compareVersions(parseUpstreamVersion(a), parseUpstreamVersion(b)));
137
- }
138
- /**
139
- * Report every blessed package whose installed version is NOT one of the
140
- * validated release lines. Empty array = the running install matches the
141
- * contract.
142
- */
143
- export function upstreamDrift(installedVersions = installedUpstreamVersions()) {
144
- const validated = new Set(UPSTREAM_VALIDATED_VERSIONS);
145
- const drift = [];
146
- for (const [packageName, installed] of Object.entries(installedVersions)) {
147
- const expected = UPSTREAM_BLESSED_PACKAGES.includes(packageName);
148
- if (!expected)
149
- continue;
150
- let matches;
151
- const frameworkMajor = UPSTREAM_FRAMEWORK_MAJORS[packageName];
152
- if (frameworkMajor !== undefined) {
153
- const installedMajor = Number((installed ?? '').split('.')[0]);
154
- matches = installedMajor === frameworkMajor;
155
- }
156
- else {
157
- matches = installed !== undefined && validated.has(installed);
76
+ /** Require the development dependency surface without restricting DSH releases. */
77
+ export function upstreamDependencyIssues(installedVersions = installedUpstreamVersions()) {
78
+ const issues = [];
79
+ for (const name of UPSTREAM_BLESSED_PACKAGES) {
80
+ const installed = installedVersions[name];
81
+ const major = UPSTREAM_FRAMEWORK_MAJORS[name];
82
+ if (typeof installed !== 'string' || installed.trim() === '') {
83
+ issues.push({ package: name, installed, reason: 'package manifest or version is missing' });
158
84
  }
159
- if (!matches) {
160
- drift.push({
161
- package: packageName,
162
- installed,
163
- validated: frameworkMajor !== undefined ? `major ${frameworkMajor}` : UPSTREAM_VALIDATED_LABEL,
164
- });
85
+ else if (major !== undefined && !installed.startsWith(`${major}.`)) {
86
+ issues.push({ package: name, installed, reason: `requires framework major ${major}` });
165
87
  }
166
88
  }
167
- return drift;
168
- }
169
- /**
170
- * Collapse {@link upstreamDrift} into a single summary for the boot notice:
171
- * undefined when the install matches the contract. Only harness prerelease packages
172
- * decide newer/older/mixed; a framework-only drift (e.g. a cordis major
173
- * bump) reports `broken`, since its version line is not comparable.
174
- */
175
- export function upstreamDriftSummary(installedVersions = installedUpstreamVersions()) {
176
- const installedLines = installedUpstreamLines(installedVersions);
177
- if (installedLines.length > 1)
178
- return { kind: 'mixed', versions: installedLines };
179
- const drift = upstreamDrift(installedVersions).filter(entry => entry.installed !== undefined || !OPTIONAL_RUNTIME_PACKAGES.has(entry.package));
180
- if (drift.length === 0)
181
- return undefined;
182
- const harness = drift.filter(entry => UPSTREAM_FRAMEWORK_MAJORS[entry.package] === undefined);
183
- const versions = [...new Set(drift.map(entry => entry.installed ?? 'missing'))];
184
- if (harness.some(entry => entry.installed === undefined)) {
185
- return { kind: 'broken', versions };
186
- }
187
- const harnessVersions = [...new Set(harness.map(entry => entry.installed))];
188
- if (harnessVersions.length > 1) {
189
- return { kind: 'mixed', versions };
190
- }
191
- const installed = parseUpstreamVersion(harnessVersions[0] ?? '');
192
- const validated = parseUpstreamVersion(UPSTREAM_VALIDATED_VERSION);
193
- if (installed === undefined) {
194
- return { kind: 'broken', versions };
195
- }
196
- const order = compareVersions(installed, validated);
197
- if (order > 0)
198
- return { kind: 'newer', versions };
199
- if (order < 0)
200
- return { kind: 'older', versions };
201
- // Identical to the primary validated version — cannot happen (it would
202
- // not be drift); report broken rather than staying silent.
203
- return { kind: 'broken', versions };
89
+ return issues;
204
90
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * dsh-tui plugin entry. The TUI implementation lives in `./plugin.tsx` (its
2
+ * dsh-tui plugin entry. The TUI implementation lives in `./plugin.ts` (its
3
3
  * render path is JSX); this module owns the plugin surface (`name`/`inject`/
4
4
  * `Config`/`apply`) at the package entry module and delegates
5
5
  * `apply` through a dynamic import so entry-scanning tooling and the Loader
@@ -73,7 +73,7 @@ export interface Config {
73
73
  * override DSH_TUI_DISABLE_TERMINAL_IMAGES can always force previews off. */
74
74
  terminalImages?: boolean;
75
75
  /** UI language: `en` / `zh`. When absent, the `DSH_TUI_LANG` env var wins,
76
- * then the `/lang` choice persisted in `~/.dsh-tui/lang.json`, then `zh`. */
76
+ * then the `/lang` choice persisted in `~/.dsh-tui/lang.json`, then the locale, falling back to `en`. */
77
77
  lang?: string;
78
78
  /** Agent preset id new sessions compose from (standard/ptc/minimal/
79
79
  * cordis/… when the roster is mounted). When absent, the `/preset` choice
@@ -142,7 +142,7 @@ export interface Config {
142
142
  export declare const Config: Schema<Config, RuntimeConfig<Config>>;
143
143
  /**
144
144
  * Start the interactive TUI front door, delegating to the JSX implementation
145
- * in `./plugin.tsx` (see its module doc for the full contract).
145
+ * in `./plugin.ts` (see its module doc for the full contract).
146
146
  * @param ctx - the plugin context.
147
147
  * @param config - the validated dsh-tui configuration.
148
148
  * @returns a promise settling when the Loader entry has scheduled its runtime.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/index.ts"],"names":[],"mappings":"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"}
@@ -86,26 +86,20 @@ export const Config = editableConfig(Schema.object({
86
86
  ]);
87
87
  /**
88
88
  * Start the interactive TUI front door, delegating to the JSX implementation
89
- * in `./plugin.tsx` (see its module doc for the full contract).
89
+ * in `./plugin.ts` (see its module doc for the full contract).
90
90
  * @param ctx - the plugin context.
91
91
  * @param config - the validated dsh-tui configuration.
92
92
  * @returns a promise settling when the Loader entry has scheduled its runtime.
93
93
  */
94
94
  export async function apply(ctx, config) {
95
- // Upstream drift is NO LONGER spammed to stderr here: per-package
96
- // console.warn lines interleave with the TUI frame redraw and arrive
97
- // garbled (typewriter animation repaints over them). The merged,
98
- // natural-language notice now renders in the logo header under the
99
- // startup tip (LogoV2 ← upstreamDriftSummary); CI keeps the hard gate
100
- // via scripts/verify-upstream-contract.ts.
101
95
  const { apply: tuiApply, handleStartupError } = await import('./plugin.js');
102
96
  let disposed = false;
103
97
  ctx.effect(() => () => { disposed = true; });
104
- // Registry diagnostics can await the whole Loader. Do not make this Host
105
- // row await the runtime in return. Let Host providers settle before starting
106
- // a Cordis-owned child; the original row still owns volatile Config.
107
- const loader = ctx.get('loader');
108
- void (loader?.await() ?? ctx.fiber.await()).then(() => {
98
+ // Entry injection already orders the required Host services. Waiting on the
99
+ // whole Loader here can capture this entry's own activation and never start
100
+ // the frontend. Wait for our owner to settle, then start its Cordis-owned
101
+ // child; the original row continues to own volatile Config.
102
+ void ctx.fiber.await().then(() => {
109
103
  if (disposed)
110
104
  return;
111
105
  return ctx.plugin({
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/plugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,wBAAwB,CAAA;AAGhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAA+D,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAuDtH,OAAO,EAAE,MAAM,EAAkC,MAAM,UAAU,CAAA;AAgCjE;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,CAcxF;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,yBAAyB,GAAG,eAAe,CAAA;AAErF,wBAAgB,kBAAkB,CAChC,WAAW,UAAgC,EAC3C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,WAAW,CASb;AAED,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW,GAAE,OAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAq+CzH;AAmMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,GAAG;IACjF,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB,CAcA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,KAAK,GAAG,SAAS,CAAA;IAC5B,YAAY,EAAE,KAAK,CAAA;CACpB,GAAG,OAAO,CAQV;AAgBD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,GAAG,SAAS,EACxD,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,EAAE,MAAM,IAAI,GACf,OAAO,CAAC,IAAI,CAAC,CAmFf;AA4HD,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAIrE"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/plugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,wBAAwB,CAAA;AAGhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAA+D,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAuDtH,OAAO,EAAE,MAAM,EAAkC,MAAM,UAAU,CAAA;AAgCjE;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,CAcxF;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,yBAAyB,GAAG,eAAe,CAAA;AAErF,wBAAgB,kBAAkB,CAChC,WAAW,UAAgC,EAC3C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,WAAW,CASb;AAED,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW,GAAE,OAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAs+CzH;AAmMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,GAAG;IACjF,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB,CAcA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,KAAK,GAAG,SAAS,CAAA;IAC5B,YAAY,EAAE,KAAK,CAAA;CACpB,GAAG,OAAO,CAQV;AAgBD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,GAAG,SAAS,EACxD,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,EAAE,MAAM,IAAI,GACf,OAAO,CAAC,IAAI,CAAC,CAmFf;AA4HD,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAIrE"}
@@ -1,3 +1,4 @@
1
+ import { registerResponseLanguage } from './response-language.js';
1
2
  import { randomUUID } from 'node:crypto';
2
3
  import React from 'react';
3
4
  import { SessionId } from '@deepseek-ai/dsh-session';
@@ -186,11 +187,12 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
186
187
  }
187
188
  // Validate settings before creating an agent or taking over the terminal.
188
189
  const tuiSettingsNs = resolveSettingsNamespace(configOwner, Config);
190
+ registerResponseLanguage(ctx);
189
191
  await registerBundledPresets(ctx);
190
192
  // UI language resolution: DSH_TUI_LANG env var wins, then the
191
193
  // active profile `dsh-tui.lang` configuration (applied once the settings
192
194
  // namespace registers below), then cordis.yml `lang`, then the
193
- // persisted `/lang` choice, then `zh`. Must settle before the first
195
+ // persisted `/lang` choice, then the locale, falling back to `en`. Must settle before the first
194
196
  // render so every module resolves strings in the same language.
195
197
  const envLang = process.env.DSH_TUI_LANG;
196
198
  setLang(isLang(envLang) ? envLang : isLang(config.lang) ? config.lang : resolveStartupLang());
@@ -1 +1 @@
1
- {"version":3,"file":"recap.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/recap.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AACvE;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAkBtC;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAkCjG;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAyBnF"}
1
+ {"version":3,"file":"recap.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/recap.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AACvE;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAkBtC;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAmCjG;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWxD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAyBnF"}
@@ -1,3 +1,4 @@
1
+ import { RESPONSE_LANGUAGE_POLICY } from './response-language.js';
1
2
  /** Max chars of recent activity fed to the recap call. */
2
3
  export const RECAP_RECENT_CHARS = 6000;
3
4
  /** How many exchanges (user + assistant) the recap looks back. */
@@ -32,6 +33,8 @@ export function collectRecentActivity(events, limitChars) {
32
33
  const record = event;
33
34
  if (record['type'] === 'user/message') {
34
35
  const data = record['data'];
36
+ if (data?.['source']?.kind !== 'user')
37
+ continue;
35
38
  const text = textOfContent(data?.['content']);
36
39
  if (text !== undefined)
37
40
  entries.push({ role: 'user', text });
@@ -70,7 +73,8 @@ export function collectRecentActivity(events, limitChars) {
70
73
  */
71
74
  export function wrapRecapPrompt(activity) {
72
75
  return `Create a compact session recap from the activity excerpt below.
73
- Use the user's language and describe the work and its current outcome accurately.
76
+ ${RESPONSE_LANGUAGE_POLICY}
77
+ Determine the language from the latest user-authored request in the excerpt and any explicit continuing user preference. Assistant replies and this wrapper are not language signals. Describe the work and its current outcome accurately.
74
78
  Return one JSON object with two string fields:
75
79
  - "title": a descriptive title of about 2-6 words.
76
80
  - "summary": one line of about 10-20 words covering the most recent progress.
@@ -0,0 +1,6 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ /** One packaged policy for ordinary, complete-persona and auxiliary requests. */
3
+ export declare const RESPONSE_LANGUAGE_POLICY: string;
4
+ /** Register independently of the replaceable deployment persona. */
5
+ export declare function registerResponseLanguage(ctx: Context): void;
6
+ //# sourceMappingURL=response-language.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-language.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/response-language.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAIlD,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,QAAmF,CAAA;AAExH,oEAAoE;AACpE,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAI3D"}
@@ -0,0 +1,11 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { packagedPresetRoot } from './packaged-presets.js';
4
+ /** One packaged policy for ordinary, complete-persona and auxiliary requests. */
5
+ export const RESPONSE_LANGUAGE_POLICY = readFileSync(join(packagedPresetRoot(), 'response-language.txt'), 'utf8').trim();
6
+ /** Register independently of the replaceable deployment persona. */
7
+ export function registerResponseLanguage(ctx) {
8
+ ctx.inject(['systemPrompt'], ready => {
9
+ ready.systemPrompt.section({ name: 'dsh-cli:response-language', order: 10300, text: RESPONSE_LANGUAGE_POLICY, interpolate: false });
10
+ });
11
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"sideQuestion.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/sideQuestion.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEvE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWzD;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,yEAAyE;IACzE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,aAAa,CAAC,WAAW,CAAC,CAAA;IACvD,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAA;IACf,iDAAiD;IACjD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,yEAAyE;IACzE,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuB/B"}
1
+ {"version":3,"file":"sideQuestion.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/sideQuestion.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEvE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAazD;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,yEAAyE;IACzE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,aAAa,CAAC,WAAW,CAAC,CAAA;IACvD,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAA;IACf,iDAAiD;IACjD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,yEAAyE;IACzE,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuB/B"}
@@ -1,3 +1,4 @@
1
+ import { RESPONSE_LANGUAGE_POLICY } from './response-language.js';
1
2
  /**
2
3
  * Side Question (`/btw`): a single-turn call without tools, replaying the
3
4
  * live session's derived history (prompt-cache reuse, compaction-style
@@ -13,6 +14,8 @@ import { BlockAssembler } from '@deepseek-ai/dsh-llm';
13
14
  */
14
15
  export function wrapSideQuestion(question) {
15
16
  return `<side-question-context>
17
+ ${RESPONSE_LANGUAGE_POLICY}
18
+ Determine the request language from the question after this wrapper, not from this wrapper.
16
19
  Give one concise answer to the question below using the conversation already provided.
17
20
  This auxiliary call runs alongside the main session. The main task continues independently;
18
21
  do not describe it as interrupted, resumed, or as work performed by this call.