@askdkc/dsh-cli 0.13.1 → 0.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dsh-tui.js +2 -2
- package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/bundled-presets.js +9 -0
- package/lib/types/dsh-adapter/index.d.ts +1 -1
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +3 -1
- package/lib/types/dsh-adapter/recap.d.ts.map +1 -1
- package/lib/types/dsh-adapter/recap.js +5 -1
- package/lib/types/dsh-adapter/response-language.d.ts +6 -0
- package/lib/types/dsh-adapter/response-language.d.ts.map +1 -0
- package/lib/types/dsh-adapter/response-language.js +11 -0
- package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sideQuestion.js +3 -0
- package/lib/types/i18n.d.ts +5 -6
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +6 -7
- package/node_modules/@askdkc/dsh-auth/lib/opencode-codec.js +16 -3
- package/node_modules/@askdkc/dsh-auth/lib/opencode-replay.d.ts +1 -0
- package/node_modules/@askdkc/dsh-auth/lib/opencode-replay.js +7 -2
- package/node_modules/dsh-working-activity/lib/types/index.js +4 -6
- package/node_modules/dsh-working-activity/lib/types/lang.d.ts +10 -8
- package/node_modules/dsh-working-activity/lib/types/lang.js +11 -12
- package/node_modules/dsh-working-activity/src/index.ts +4 -6
- package/node_modules/dsh-working-activity/src/lang.ts +12 -13
- package/package.json +3 -2
- package/presets/liangshen/agent.cordis.yml +2 -1
- package/presets/response-language.txt +5 -0
package/bin/dsh-tui.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* 可用。shellQuote 等小工具在此内联。
|
|
26
26
|
*
|
|
27
27
|
* 面向用户的消息走 MSG 双语表:与 TUI 的语言契约一致——
|
|
28
|
-
* `DSH_TUI_LANG`
|
|
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 === '
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundled-presets.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/bundled-presets.ts"],"names":[],"mappings":"
|
|
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
|
}
|
|
@@ -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 `
|
|
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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAA2C,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACzK,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEzE,eAAO,MAAM,IAAI,YAAY,CAAA;AAU7B,eAAO,MAAM,MAAM,UAAa,CAAA;AAEhC;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;yEAKqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;gDAC4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;gFAE4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;oCACgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;sBAIkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;2BAGuB;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;wDAEoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;+DAI2D;IAC3D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;kFAE8E;IAC9E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/plugin.ts"],"names":[],"mappings":"
|
|
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 `
|
|
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":"
|
|
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
|
-
|
|
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":"
|
|
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.
|
package/lib/types/i18n.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* dsh-tui localization — UI strings for Chinese (`zh
|
|
2
|
+
* dsh-tui localization — UI strings for Chinese (`zh`) and
|
|
3
3
|
* English (`en`).
|
|
4
4
|
*
|
|
5
5
|
* Resolution order mirrors the `/theme` mechanism (see themePrefs.ts):
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 2. `lang` cordis.yml config key (see Config in index.ts)
|
|
9
9
|
* 3. the persisted `/lang` choice in `~/.dsh-tui/lang.json`
|
|
10
10
|
* 4. the OS locale guess (`LC_ALL` / `LC_MESSAGES` / `LANG`)
|
|
11
|
-
* 5. `
|
|
11
|
+
* 5. `en` (the fallback language)
|
|
12
12
|
*
|
|
13
13
|
* `/lang` switches at runtime and hot-swaps the whole UI. The dictionary is
|
|
14
14
|
* a flat key → per-language text map; `t(key, params)` substitutes
|
|
@@ -4434,16 +4434,15 @@ export declare function writeLangPref(lang: Lang, dir?: string): boolean;
|
|
|
4434
4434
|
* user must not get a Chinese UI. The POSIX/C locale means "no locale
|
|
4435
4435
|
* selected" and conventionally maps to English — importantly it is what
|
|
4436
4436
|
* CI runners (LANG=C.UTF-8) report, so tests asserting English UI copy
|
|
4437
|
-
* stay deterministic.
|
|
4438
|
-
*
|
|
4439
|
-
* the zh default.
|
|
4437
|
+
* stay deterministic. An absent locale (typical on Windows) also uses
|
|
4438
|
+
* the English fallback.
|
|
4440
4439
|
*/
|
|
4441
4440
|
export declare function detectLocaleLang(): Lang;
|
|
4442
4441
|
/**
|
|
4443
4442
|
* Resolve the startup language: `DSH_TUI_LANG` when it holds a valid value
|
|
4444
4443
|
* (pinned at process start — the repro/verify scripts rely on this for
|
|
4445
4444
|
* deterministic UI copy), else the persisted `/lang` choice, else the OS
|
|
4446
|
-
* locale guess, else `
|
|
4445
|
+
* locale guess, else `en` (the fallback language). The
|
|
4447
4446
|
* cordis.yml `lang` precedence lives in plugin.apply.
|
|
4448
4447
|
*/
|
|
4449
4448
|
export declare function resolveStartupLang(): Lang;
|
package/lib/types/i18n.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAMH,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAI9B,+DAA+D;AAC/D,eAAO,MAAM,KAAK,uBAAwB,CAAA;AAE1C;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9D,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAMH,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAI9B,+DAA+D;AAC/D,eAAO,MAAM,KAAK,uBAAwB,CAAA;AAE1C;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9D,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|
package/lib/types/i18n.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* dsh-tui localization — UI strings for Chinese (`zh
|
|
2
|
+
* dsh-tui localization — UI strings for Chinese (`zh`) and
|
|
3
3
|
* English (`en`).
|
|
4
4
|
*
|
|
5
5
|
* Resolution order mirrors the `/theme` mechanism (see themePrefs.ts):
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 2. `lang` cordis.yml config key (see Config in index.ts)
|
|
9
9
|
* 3. the persisted `/lang` choice in `~/.dsh-tui/lang.json`
|
|
10
10
|
* 4. the OS locale guess (`LC_ALL` / `LC_MESSAGES` / `LANG`)
|
|
11
|
-
* 5. `
|
|
11
|
+
* 5. `en` (the fallback language)
|
|
12
12
|
*
|
|
13
13
|
* `/lang` switches at runtime and hot-swaps the whole UI. The dictionary is
|
|
14
14
|
* a flat key → per-language text map; `t(key, params)` substitutes
|
|
@@ -1474,9 +1474,8 @@ export function writeLangPref(lang, dir = PREFS_DIR) {
|
|
|
1474
1474
|
* user must not get a Chinese UI. The POSIX/C locale means "no locale
|
|
1475
1475
|
* selected" and conventionally maps to English — importantly it is what
|
|
1476
1476
|
* CI runners (LANG=C.UTF-8) report, so tests asserting English UI copy
|
|
1477
|
-
* stay deterministic.
|
|
1478
|
-
*
|
|
1479
|
-
* the zh default.
|
|
1477
|
+
* stay deterministic. An absent locale (typical on Windows) also uses
|
|
1478
|
+
* the English fallback.
|
|
1480
1479
|
*/
|
|
1481
1480
|
export function detectLocaleLang() {
|
|
1482
1481
|
// `||` (not `??`): an EMPTY locale variable means "unset" and must fall
|
|
@@ -1487,14 +1486,14 @@ export function detectLocaleLang() {
|
|
|
1487
1486
|
'';
|
|
1488
1487
|
const locale = raw.split('.')[0]?.toLowerCase() ?? '';
|
|
1489
1488
|
if (locale === '')
|
|
1490
|
-
return '
|
|
1489
|
+
return 'en';
|
|
1491
1490
|
return locale.startsWith('zh') ? 'zh' : 'en';
|
|
1492
1491
|
}
|
|
1493
1492
|
/**
|
|
1494
1493
|
* Resolve the startup language: `DSH_TUI_LANG` when it holds a valid value
|
|
1495
1494
|
* (pinned at process start — the repro/verify scripts rely on this for
|
|
1496
1495
|
* deterministic UI copy), else the persisted `/lang` choice, else the OS
|
|
1497
|
-
* locale guess, else `
|
|
1496
|
+
* locale guess, else `en` (the fallback language). The
|
|
1498
1497
|
* cordis.yml `lang` precedence lives in plugin.apply.
|
|
1499
1498
|
*/
|
|
1500
1499
|
export function resolveStartupLang() {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/** Convert DSH conversation blocks into low-level SDK prompts without an agent loop. */
|
|
2
2
|
import { LlmError, projectToolUpdates, fileHandleText } from '@deepseek-ai/dsh-llm';
|
|
3
3
|
import { projectReplay, requireReplaySignature } from './opencode-replay.js';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
4
5
|
export async function encodePrompt(options, model, attachments, warn) {
|
|
5
6
|
const prompt = [];
|
|
6
7
|
const names = new Map();
|
|
7
8
|
const callIds = new Map();
|
|
9
|
+
const wireIds = new Set();
|
|
8
10
|
if (options.system)
|
|
9
11
|
prompt.push({ role: 'system', content: options.system });
|
|
10
12
|
const projection = projectToolUpdates(options.messages, options.tools, undefined, options.toolHistory);
|
|
@@ -61,14 +63,24 @@ export async function encodePrompt(options, model, attachments, warn) {
|
|
|
61
63
|
else if (block.type === 'file')
|
|
62
64
|
content.push({ type: 'text', text: fileHandleText(block.attachment, attachments?.()?.fileHostPath(block.attachment)) });
|
|
63
65
|
else if (block.type === 'reasoning' && message.role === 'assistant') {
|
|
66
|
+
if (replay.foreign)
|
|
67
|
+
continue;
|
|
64
68
|
requireReplaySignature(block, model.protocol, providerOptions);
|
|
65
69
|
content.push({ type: 'reasoning', text: block.text, providerOptions });
|
|
66
70
|
}
|
|
67
71
|
else if (block.type === 'tool-call' && message.role === 'assistant') {
|
|
68
|
-
|
|
72
|
+
// Foreign pi Responses ids contain an opaque item suffix. Give the
|
|
73
|
+
// call/result pair a portable id without restoring that foreign item.
|
|
74
|
+
if (replay.foreign && model.protocol === 'responses' && block.id.includes('|'))
|
|
75
|
+
callIds.set(block.id, `dsh_${createHash('sha256').update(block.id).digest('hex').slice(0, 48)}`);
|
|
76
|
+
if (model.protocol === 'responses' && block.id.includes('|') && !callIds.has(block.id))
|
|
69
77
|
throw new LlmError('Cannot restore legacy Responses tool call pairing', 'INVALID_REPLAY_STATE');
|
|
70
78
|
if (names.has(block.id))
|
|
71
79
|
throw new LlmError('Duplicate stored tool call id', 'INVALID_REPLAY_STATE');
|
|
80
|
+
const wireId = callIds.get(block.id) ?? block.id;
|
|
81
|
+
if (wireIds.has(wireId))
|
|
82
|
+
throw new LlmError('Duplicate wire tool call id', 'INVALID_REPLAY_STATE');
|
|
83
|
+
wireIds.add(wireId);
|
|
72
84
|
if (model.protocol === 'google' && model.reasoning && !providerOptions?.google?.thoughtSignature && !message.content.slice(0, index).some(part => part.type === 'tool-call'))
|
|
73
85
|
throw new LlmError('Cannot replay Google tool call without its verified thought signature', 'INVALID_REPLAY_STATE');
|
|
74
86
|
names.set(block.id, block.name);
|
|
@@ -79,7 +91,7 @@ export async function encodePrompt(options, model, attachments, warn) {
|
|
|
79
91
|
catch {
|
|
80
92
|
throw new LlmError('Stored tool arguments are not valid JSON', 'INVALID_REPLAY_STATE');
|
|
81
93
|
}
|
|
82
|
-
content.push({ type: 'tool-call', toolCallId:
|
|
94
|
+
content.push({ type: 'tool-call', toolCallId: wireId, toolName: block.name, input, providerOptions });
|
|
83
95
|
}
|
|
84
96
|
else if (block.type === 'image') {
|
|
85
97
|
if (message.role === 'assistant')
|
|
@@ -87,7 +99,8 @@ export async function encodePrompt(options, model, attachments, warn) {
|
|
|
87
99
|
content.push(await imagePart(block));
|
|
88
100
|
}
|
|
89
101
|
}
|
|
90
|
-
|
|
102
|
+
if (content.length || !replay.foreign)
|
|
103
|
+
prompt.push({ role: message.role, content });
|
|
91
104
|
}
|
|
92
105
|
return prompt;
|
|
93
106
|
}
|
|
@@ -8,6 +8,7 @@ export interface ReplayProjection {
|
|
|
8
8
|
blocks: (SharedV4ProviderOptions | undefined)[];
|
|
9
9
|
callIds: Map<string, string>;
|
|
10
10
|
trusted: boolean;
|
|
11
|
+
foreign: boolean;
|
|
11
12
|
}
|
|
12
13
|
/** Validate the entire aligned envelope before restoring any signature or item id. */
|
|
13
14
|
export declare function projectReplay(source: unknown, content: readonly ContentBlock[], model: OpenCodeModel, route: string, warn?: (reason: string) => void): ReplayProjection;
|
|
@@ -33,9 +33,14 @@ function completeResponseSignatures(blocks, content) {
|
|
|
33
33
|
const APIS = { messages: 'anthropic-messages', responses: 'openai-responses', chat: 'openai-completions', google: 'google-generative-ai' };
|
|
34
34
|
/** Validate the entire aligned envelope before restoring any signature or item id. */
|
|
35
35
|
export function projectReplay(source, content, model, route, warn) {
|
|
36
|
-
const empty = () => ({ blocks: content.map(() => undefined), callIds: new Map(), trusted: false });
|
|
37
36
|
const message = record(source);
|
|
38
37
|
const envelope = record(message?.replayState);
|
|
38
|
+
// A model switch deliberately discards provider-specific replay data. It is
|
|
39
|
+
// distinct from a damaged native envelope, whose signature checks still apply.
|
|
40
|
+
const foreign = typeof message?.provider === 'string' && !!message.provider && typeof message.model === 'string' && !!message.model && (message.provider !== route || message.model !== model.id);
|
|
41
|
+
const empty = () => ({ blocks: content.map(() => undefined), callIds: new Map(), trusted: false, foreign });
|
|
42
|
+
if (foreign)
|
|
43
|
+
return empty();
|
|
39
44
|
if (!envelope) {
|
|
40
45
|
if (message?.replayState !== undefined)
|
|
41
46
|
warn?.('OpenCode history: malformed replay envelope; retaining message content');
|
|
@@ -122,7 +127,7 @@ export function projectReplay(source, content, model, route, warn) {
|
|
|
122
127
|
});
|
|
123
128
|
if (model.protocol === 'responses')
|
|
124
129
|
completeResponseSignatures(blocks, content);
|
|
125
|
-
return { blocks, callIds, trusted: true };
|
|
130
|
+
return { blocks, callIds, trusted: true, foreign: false };
|
|
126
131
|
}
|
|
127
132
|
catch (error) {
|
|
128
133
|
warn?.(`OpenCode history: ${error instanceof Error ? error.message : 'invalid replay'}; retaining message content`);
|
|
@@ -22,7 +22,7 @@ import { ActivityTracker } from './status.js';
|
|
|
22
22
|
import { feedStreamFrame } from './compat/assistant-stream.js';
|
|
23
23
|
import { createActivityProjection, ACTIVITY_PROJECTION_KEY } from './projection.js';
|
|
24
24
|
import { registerActivityEventType } from './registration.js';
|
|
25
|
-
import { langNow, setLangOverride
|
|
25
|
+
import { NARRATE_INSTRUCTION, langNow, setLangOverride } from './lang.js';
|
|
26
26
|
import { DEFAULT_PRESET } from './frames.js';
|
|
27
27
|
import { featureOn } from './config.js';
|
|
28
28
|
export const name = 'working-activity';
|
|
@@ -100,16 +100,14 @@ export function apply(ctx, config = {}) {
|
|
|
100
100
|
const prompt = ctx.get('tuiPrompt', false);
|
|
101
101
|
const promptHandle = prompt?.register('activity', undefined);
|
|
102
102
|
// The `⏵` self-narration contract rides the stable system-prompt sections:
|
|
103
|
-
// injected when the systemPrompt service is composed
|
|
104
|
-
//
|
|
105
|
-
// assembly in the live language, so a `/lang` switch applies to the next
|
|
106
|
-
// turn without rebuilding the agent.
|
|
103
|
+
// injected when the systemPrompt service is composed and removed with this
|
|
104
|
+
// fiber. Model instructions stay in English independently of UI settings.
|
|
107
105
|
if (resolved.narrate) {
|
|
108
106
|
ctx.inject(['systemPrompt'], (promptCtx) => {
|
|
109
107
|
promptCtx.systemPrompt.section({
|
|
110
108
|
name: 'working-activity:narrate',
|
|
111
109
|
order: 60,
|
|
112
|
-
text:
|
|
110
|
+
text: NARRATE_INSTRUCTION,
|
|
113
111
|
});
|
|
114
112
|
});
|
|
115
113
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The plugin follows the dsh-tui UI language without importing it: the same
|
|
5
5
|
* chain dsh-tui resolves (`DSH_TUI_LANG` env → `~/.dsh-tui/lang.json` → OS
|
|
6
|
-
* locale →
|
|
7
|
-
* /settings language pick) hot-swaps
|
|
8
|
-
*
|
|
6
|
+
* locale → en) is read here directly, so a `/lang en|zh` switch (or the
|
|
7
|
+
* /settings language pick) hot-swaps rendered status-line copy. Model-facing
|
|
8
|
+
* narration instructions are locale-independent.
|
|
9
9
|
*
|
|
10
10
|
* Resolution order:
|
|
11
11
|
* 1. `setLangOverride()` — a plugin-level `lang: zh|en` config key
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* so the per-tick status render never re-reads an unchanged file.
|
|
16
16
|
* 4. OS locale guess (`LC_ALL` / `LC_MESSAGES` / `LANG`); POSIX/C means
|
|
17
17
|
* "no locale selected" and maps to English.
|
|
18
|
-
* 5. `
|
|
18
|
+
* 5. `en` — the fallback for unsupported or absent locales.
|
|
19
19
|
*
|
|
20
20
|
* The dictionary is a flat key → per-language string map; `t(key, params)`
|
|
21
21
|
* substitutes `{{name}}` placeholders. Missing keys render the key itself so
|
|
@@ -31,10 +31,12 @@ export declare function withProgressLang<T>(lang: Lang, render: () => T): T;
|
|
|
31
31
|
export declare function terminalProgressLang(): Lang;
|
|
32
32
|
/** Detect only confident language signals in user-authored prose. */
|
|
33
33
|
export declare function detectInputLanguage(input: string): Lang | undefined;
|
|
34
|
+
/** Model instructions never inherit the interface or terminal language. */
|
|
35
|
+
export declare const NARRATE_INSTRUCTION = "[Status line] You have a status line visible to the user. [Required] At the start of each step or subtask (not only before tool calls), write exactly one standalone line at the very beginning of your response: \u23F5 a concrete description of what you are doing (20 words max), then continue with the normal response on the next line. Write only one \u23F5 line per response and do not repeat it. Prioritize information so the user can understand the current work at a glance; keep the style natural and optionally playful. Examples: \u23F5 Fixing the login page styles, \u23F5 Investigating the error, \u23F5 Running validation for the patch. Update it when the task changes. Write the status description in the same response language chosen for the user request; use English when unclear.";
|
|
34
36
|
declare const dict: {
|
|
35
37
|
readonly 'narrate-instruction': {
|
|
36
|
-
readonly zh: "[
|
|
37
|
-
readonly en: "[Status line] You have a status line visible to the user. [Required] At the start of each step or subtask (not only before tool calls), write exactly one standalone line at the very beginning of your response: ⏵ a concrete description of what you are doing (20 words max), then continue with the normal response on the next line. Write only one ⏵ line per response and do not repeat it. Prioritize information so the user can understand the current work at a glance; keep the style natural and optionally playful. Examples: ⏵ Fixing the login page styles, ⏵ Investigating the error, ⏵ Running validation for the patch. Update it when the task changes.";
|
|
38
|
+
readonly zh: "[Status line] You have a status line visible to the user. [Required] At the start of each step or subtask (not only before tool calls), write exactly one standalone line at the very beginning of your response: ⏵ a concrete description of what you are doing (20 words max), then continue with the normal response on the next line. Write only one ⏵ line per response and do not repeat it. Prioritize information so the user can understand the current work at a glance; keep the style natural and optionally playful. Examples: ⏵ Fixing the login page styles, ⏵ Investigating the error, ⏵ Running validation for the patch. Update it when the task changes. Write the status description in the same response language chosen for the user request; use English when unclear.";
|
|
39
|
+
readonly en: "[Status line] You have a status line visible to the user. [Required] At the start of each step or subtask (not only before tool calls), write exactly one standalone line at the very beginning of your response: ⏵ a concrete description of what you are doing (20 words max), then continue with the normal response on the next line. Write only one ⏵ line per response and do not repeat it. Prioritize information so the user can understand the current work at a glance; keep the style natural and optionally playful. Examples: ⏵ Fixing the login page styles, ⏵ Investigating the error, ⏵ Running validation for the patch. Update it when the task changes. Write the status description in the same response language chosen for the user request; use English when unclear.";
|
|
38
40
|
};
|
|
39
41
|
/** Plain (non-playful) phase labels. */
|
|
40
42
|
readonly 'waiting-label': {
|
|
@@ -132,9 +134,9 @@ export declare function readLangFile(nowMs?: number): Lang | undefined;
|
|
|
132
134
|
export declare function invalidateLangCache(): void;
|
|
133
135
|
/**
|
|
134
136
|
* Guess the language from the OS locale (`LC_ALL`, `LC_MESSAGES`, `LANG`),
|
|
135
|
-
* defaulting to `
|
|
137
|
+
* defaulting to `en`. POSIX/C means "no locale selected" and conventionally
|
|
136
138
|
* maps to English (what CI runners report). An absent locale variable
|
|
137
|
-
* (typical on Windows) defaults to `
|
|
139
|
+
* (typical on Windows) defaults to `en`.
|
|
138
140
|
*/
|
|
139
141
|
export declare function detectLocaleLang(): Lang;
|
|
140
142
|
export {};
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The plugin follows the dsh-tui UI language without importing it: the same
|
|
5
5
|
* chain dsh-tui resolves (`DSH_TUI_LANG` env → `~/.dsh-tui/lang.json` → OS
|
|
6
|
-
* locale →
|
|
7
|
-
* /settings language pick) hot-swaps
|
|
8
|
-
*
|
|
6
|
+
* locale → en) is read here directly, so a `/lang en|zh` switch (or the
|
|
7
|
+
* /settings language pick) hot-swaps rendered status-line copy. Model-facing
|
|
8
|
+
* narration instructions are locale-independent.
|
|
9
9
|
*
|
|
10
10
|
* Resolution order:
|
|
11
11
|
* 1. `setLangOverride()` — a plugin-level `lang: zh|en` config key
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* so the per-tick status render never re-reads an unchanged file.
|
|
16
16
|
* 4. OS locale guess (`LC_ALL` / `LC_MESSAGES` / `LANG`); POSIX/C means
|
|
17
17
|
* "no locale selected" and maps to English.
|
|
18
|
-
* 5. `
|
|
18
|
+
* 5. `en` — the fallback for unsupported or absent locales.
|
|
19
19
|
*
|
|
20
20
|
* The dictionary is a flat key → per-language string map; `t(key, params)`
|
|
21
21
|
* substitutes `{{name}}` placeholders. Missing keys render the key itself so
|
|
@@ -62,12 +62,11 @@ export function detectInputLanguage(input) {
|
|
|
62
62
|
}
|
|
63
63
|
/** The dsh-tui prefs file this plugin mirrors (shared language contract). */
|
|
64
64
|
const LANG_FILE = join(homedir(), '.dsh-tui', 'lang.json');
|
|
65
|
+
/** Model instructions never inherit the interface or terminal language. */
|
|
66
|
+
export const NARRATE_INSTRUCTION = '[Status line] You have a status line visible to the user. [Required] At the start of each step or subtask (not only before tool calls), write exactly one standalone line at the very beginning of your response: ⏵ a concrete description of what you are doing (20 words max), then continue with the normal response on the next line. Write only one ⏵ line per response and do not repeat it. Prioritize information so the user can understand the current work at a glance; keep the style natural and optionally playful. Examples: ⏵ Fixing the login page styles, ⏵ Investigating the error, ⏵ Running validation for the patch. Update it when the task changes. Write the status description in the same response language chosen for the user request; use English when unclear.';
|
|
65
67
|
const dict = {
|
|
66
|
-
//
|
|
67
|
-
'narrate-instruction': {
|
|
68
|
-
zh: '[状态栏] 你有一个状态栏展示给用户。【必须】在每个步骤/子任务开始时(不只是调用工具前),在回复正文的最前面单独写一行:⏵ 你在做的具体事情(不超过20字),然后换行继续正常回复。整轮回复只写一行 ⏵,不要重复。信息为主——让人一眼知道你在干什么,风格自然、可以带点俏皮。例:⏵ 修复登录页样式、⏵ 查一下报错原因、⏵ 给补丁跑个验证。切换任务时必须更新。',
|
|
69
|
-
en: '[Status line] You have a status line visible to the user. [Required] At the start of each step or subtask (not only before tool calls), write exactly one standalone line at the very beginning of your response: ⏵ a concrete description of what you are doing (20 words max), then continue with the normal response on the next line. Write only one ⏵ line per response and do not repeat it. Prioritize information so the user can understand the current work at a glance; keep the style natural and optionally playful. Examples: ⏵ Fixing the login page styles, ⏵ Investigating the error, ⏵ Running validation for the patch. Update it when the task changes.',
|
|
70
|
-
},
|
|
68
|
+
// Retain the existing translation key without localizing model instructions.
|
|
69
|
+
'narrate-instruction': { zh: NARRATE_INSTRUCTION, en: NARRATE_INSTRUCTION },
|
|
71
70
|
// ── status-line structural copy ─────────────────────────────────────
|
|
72
71
|
/** Plain (non-playful) phase labels. */
|
|
73
72
|
'waiting-label': { zh: '等待模型响应', en: 'Waiting for model', ja: 'モデルの応答待ち' },
|
|
@@ -189,9 +188,9 @@ let cachedLang;
|
|
|
189
188
|
let lastProbeAt = 0;
|
|
190
189
|
/**
|
|
191
190
|
* Guess the language from the OS locale (`LC_ALL`, `LC_MESSAGES`, `LANG`),
|
|
192
|
-
* defaulting to `
|
|
191
|
+
* defaulting to `en`. POSIX/C means "no locale selected" and conventionally
|
|
193
192
|
* maps to English (what CI runners report). An absent locale variable
|
|
194
|
-
* (typical on Windows) defaults to `
|
|
193
|
+
* (typical on Windows) defaults to `en`.
|
|
195
194
|
*/
|
|
196
195
|
export function detectLocaleLang() {
|
|
197
196
|
const raw = process.env.LC_ALL ||
|
|
@@ -205,5 +204,5 @@ export function detectLocaleLang() {
|
|
|
205
204
|
return 'en';
|
|
206
205
|
if (locale === 'c' || locale === 'posix')
|
|
207
206
|
return 'en';
|
|
208
|
-
return '
|
|
207
|
+
return 'en';
|
|
209
208
|
}
|
|
@@ -30,7 +30,7 @@ import type { TrackerConfig } from './status.js'
|
|
|
30
30
|
import { feedStreamFrame } from './compat/assistant-stream.js'
|
|
31
31
|
import { createActivityProjection, ACTIVITY_PROJECTION_KEY } from './projection.js'
|
|
32
32
|
import { registerActivityEventType } from './registration.js'
|
|
33
|
-
import { langNow, setLangOverride, t } from './lang.js'
|
|
33
|
+
import { NARRATE_INSTRUCTION, langNow, setLangOverride, t } from './lang.js'
|
|
34
34
|
import { DEFAULT_PRESET } from './frames.js'
|
|
35
35
|
import { featureOn, type FeatureFlag } from './config.js'
|
|
36
36
|
import type { ActivityState } from './status.js'
|
|
@@ -211,16 +211,14 @@ export function apply(ctx: Context, config: Config = {}): void {
|
|
|
211
211
|
const promptHandle = prompt?.register('activity', undefined)
|
|
212
212
|
|
|
213
213
|
// The `⏵` self-narration contract rides the stable system-prompt sections:
|
|
214
|
-
// injected when the systemPrompt service is composed
|
|
215
|
-
//
|
|
216
|
-
// assembly in the live language, so a `/lang` switch applies to the next
|
|
217
|
-
// turn without rebuilding the agent.
|
|
214
|
+
// injected when the systemPrompt service is composed and removed with this
|
|
215
|
+
// fiber. Model instructions stay in English independently of UI settings.
|
|
218
216
|
if (resolved.narrate) {
|
|
219
217
|
ctx.inject(['systemPrompt'], (promptCtx) => {
|
|
220
218
|
promptCtx.systemPrompt.section({
|
|
221
219
|
name: 'working-activity:narrate',
|
|
222
220
|
order: 60,
|
|
223
|
-
text:
|
|
221
|
+
text: NARRATE_INSTRUCTION,
|
|
224
222
|
})
|
|
225
223
|
})
|
|
226
224
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The plugin follows the dsh-tui UI language without importing it: the same
|
|
5
5
|
* chain dsh-tui resolves (`DSH_TUI_LANG` env → `~/.dsh-tui/lang.json` → OS
|
|
6
|
-
* locale →
|
|
7
|
-
* /settings language pick) hot-swaps
|
|
8
|
-
*
|
|
6
|
+
* locale → en) is read here directly, so a `/lang en|zh` switch (or the
|
|
7
|
+
* /settings language pick) hot-swaps rendered status-line copy. Model-facing
|
|
8
|
+
* narration instructions are locale-independent.
|
|
9
9
|
*
|
|
10
10
|
* Resolution order:
|
|
11
11
|
* 1. `setLangOverride()` — a plugin-level `lang: zh|en` config key
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* so the per-tick status render never re-reads an unchanged file.
|
|
16
16
|
* 4. OS locale guess (`LC_ALL` / `LC_MESSAGES` / `LANG`); POSIX/C means
|
|
17
17
|
* "no locale selected" and maps to English.
|
|
18
|
-
* 5. `
|
|
18
|
+
* 5. `en` — the fallback for unsupported or absent locales.
|
|
19
19
|
*
|
|
20
20
|
* The dictionary is a flat key → per-language string map; `t(key, params)`
|
|
21
21
|
* substitutes `{{name}}` placeholders. Missing keys render the key itself so
|
|
@@ -67,13 +67,12 @@ export function detectInputLanguage(input: string): Lang | undefined {
|
|
|
67
67
|
/** The dsh-tui prefs file this plugin mirrors (shared language contract). */
|
|
68
68
|
const LANG_FILE = join(homedir(), '.dsh-tui', 'lang.json')
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
'narrate-instruction': {
|
|
73
|
-
zh: '[状态栏] 你有一个状态栏展示给用户。【必须】在每个步骤/子任务开始时(不只是调用工具前),在回复正文的最前面单独写一行:⏵ 你在做的具体事情(不超过20字),然后换行继续正常回复。整轮回复只写一行 ⏵,不要重复。信息为主——让人一眼知道你在干什么,风格自然、可以带点俏皮。例:⏵ 修复登录页样式、⏵ 查一下报错原因、⏵ 给补丁跑个验证。切换任务时必须更新。',
|
|
74
|
-
en: '[Status line] You have a status line visible to the user. [Required] At the start of each step or subtask (not only before tool calls), write exactly one standalone line at the very beginning of your response: ⏵ a concrete description of what you are doing (20 words max), then continue with the normal response on the next line. Write only one ⏵ line per response and do not repeat it. Prioritize information so the user can understand the current work at a glance; keep the style natural and optionally playful. Examples: ⏵ Fixing the login page styles, ⏵ Investigating the error, ⏵ Running validation for the patch. Update it when the task changes.',
|
|
75
|
-
},
|
|
70
|
+
/** Model instructions never inherit the interface or terminal language. */
|
|
71
|
+
export const NARRATE_INSTRUCTION = '[Status line] You have a status line visible to the user. [Required] At the start of each step or subtask (not only before tool calls), write exactly one standalone line at the very beginning of your response: ⏵ a concrete description of what you are doing (20 words max), then continue with the normal response on the next line. Write only one ⏵ line per response and do not repeat it. Prioritize information so the user can understand the current work at a glance; keep the style natural and optionally playful. Examples: ⏵ Fixing the login page styles, ⏵ Investigating the error, ⏵ Running validation for the patch. Update it when the task changes. Write the status description in the same response language chosen for the user request; use English when unclear.'
|
|
76
72
|
|
|
73
|
+
const dict = {
|
|
74
|
+
// Retain the existing translation key without localizing model instructions.
|
|
75
|
+
'narrate-instruction': { zh: NARRATE_INSTRUCTION, en: NARRATE_INSTRUCTION },
|
|
77
76
|
// ── status-line structural copy ─────────────────────────────────────
|
|
78
77
|
/** Plain (non-playful) phase labels. */
|
|
79
78
|
'waiting-label': { zh: '等待模型响应', en: 'Waiting for model', ja: 'モデルの応答待ち' },
|
|
@@ -203,9 +202,9 @@ let lastProbeAt = 0
|
|
|
203
202
|
|
|
204
203
|
/**
|
|
205
204
|
* Guess the language from the OS locale (`LC_ALL`, `LC_MESSAGES`, `LANG`),
|
|
206
|
-
* defaulting to `
|
|
205
|
+
* defaulting to `en`. POSIX/C means "no locale selected" and conventionally
|
|
207
206
|
* maps to English (what CI runners report). An absent locale variable
|
|
208
|
-
* (typical on Windows) defaults to `
|
|
207
|
+
* (typical on Windows) defaults to `en`.
|
|
209
208
|
*/
|
|
210
209
|
export function detectLocaleLang(): Lang {
|
|
211
210
|
const raw =
|
|
@@ -217,5 +216,5 @@ export function detectLocaleLang(): Lang {
|
|
|
217
216
|
if (locale.startsWith('zh')) return 'zh'
|
|
218
217
|
if (locale.startsWith('en')) return 'en'
|
|
219
218
|
if (locale === 'c' || locale === 'posix') return 'en'
|
|
220
|
-
return '
|
|
219
|
+
return 'en'
|
|
221
220
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askdkc/dsh-cli",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.3",
|
|
4
4
|
"description": "Interactive terminal interface for DeepSeek Harness agents, sessions and tools.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"tui": "node --import tsx/esm scripts/run.ts",
|
|
129
129
|
"smoke": "node --import tsx/esm scripts/smoke.tsx",
|
|
130
130
|
"verify:build": "node scripts/run-verify-build.mjs",
|
|
131
|
-
"verify:build:inner": "npm run verify:boundary && npm run verify:contract && npm run verify:herdr && npm run verify:manifest-deps && npm run verify:patch-surface && npm run verify:web-coexistence && npm run verify:plugin-spec && npm run verify:plugin-grants && npm run verify:plugin-storage && npm run verify:plugin-messages && npm run verify:plugin-ledger && npm run verify:plugin-commands && npm run verify:plugin-negotiation && npm run verify:plugin-lifecycle && npm run verify:runtime-themes && npm run verify:packaged-presets && npm run verify:history-search && npm run verify:initial-prompt && npm run verify:minimal-preset-tools && npm run verify:liangshen-bootstrap && npm run verify:inject-channel && npm run verify:wheel-selection && npm run verify:win32-protocol && npm run verify:selection-resize && npm run verify:selection-stale-guard && npm run verify:liangshen-instruction-hint && npm run verify:pointer-events && npm run verify:terminal-images && npm run verify:overlay-occlusion && npm run verify:transcript-images && npm run verify:image-preview && npm run verify:backdrop-dim && npm run verify:composer-image-tokens && npm run verify:image-downsample && npm run verify:chat-overlay && npm run verify:i18n && npm run verify:approval-visibility && npm run verify:adapter-skeleton && npm run verify:adapter-ports && npm run verify:adapter-effect-class && npm run verify:adapter-shadow && npm run verify:adapter-descriptor && npm run verify:adapter-upstream-driver && npm run verify:adapter-kernel-runtime && npm run verify:adapter-live-probes && npm run verify:adapter-slices && npm run verify:adapter-channel && npm run verify:binding-transaction && npm run verify:session-extraction && npm run verify:rewind-edit && npm run verify:model-mode-workspace-extraction && npm run verify:model-lifecycle-fences && npm run verify:reports-metadata && npm run verify:background-extraction && npm run verify:plugin-catalog-extraction && npm run verify:session-reset && npm run verify:channel-ui && npm run verify:adapter-detection && npm run verify:adapter-replay-harness && npm run verify:adapter-channel-conformance && npm run verify:protocol-single-source && npm run verify:compat-removal && npm run verify:terminal-images-sixel && npm run verify:sixel-transcript && npm run verify:migrate-sessions && npm run verify:fixed-window && npm run verify:source-hygiene && npm run verify:renderer-primitives && npm run verify:product-migration && npm run verify:spinner-identity && npm run verify:table-layout && npm run verify:mermaid-diagram && npm run verify:btw && npm run verify:session-mounts && npm run verify:progress-language",
|
|
131
|
+
"verify:build:inner": "npm run verify:boundary && npm run verify:contract && npm run verify:herdr && npm run verify:manifest-deps && npm run verify:patch-surface && npm run verify:web-coexistence && npm run verify:plugin-spec && npm run verify:plugin-grants && npm run verify:plugin-storage && npm run verify:plugin-messages && npm run verify:plugin-ledger && npm run verify:plugin-commands && npm run verify:plugin-negotiation && npm run verify:plugin-lifecycle && npm run verify:runtime-themes && npm run verify:packaged-presets && npm run verify:history-search && npm run verify:initial-prompt && npm run verify:minimal-preset-tools && npm run verify:liangshen-bootstrap && npm run verify:inject-channel && npm run verify:wheel-selection && npm run verify:win32-protocol && npm run verify:selection-resize && npm run verify:selection-stale-guard && npm run verify:liangshen-instruction-hint && npm run verify:pointer-events && npm run verify:terminal-images && npm run verify:overlay-occlusion && npm run verify:transcript-images && npm run verify:image-preview && npm run verify:backdrop-dim && npm run verify:composer-image-tokens && npm run verify:image-downsample && npm run verify:chat-overlay && npm run verify:i18n && npm run verify:approval-visibility && npm run verify:adapter-skeleton && npm run verify:adapter-ports && npm run verify:adapter-effect-class && npm run verify:adapter-shadow && npm run verify:adapter-descriptor && npm run verify:adapter-upstream-driver && npm run verify:adapter-kernel-runtime && npm run verify:adapter-live-probes && npm run verify:adapter-slices && npm run verify:adapter-channel && npm run verify:binding-transaction && npm run verify:session-extraction && npm run verify:rewind-edit && npm run verify:model-mode-workspace-extraction && npm run verify:model-lifecycle-fences && npm run verify:reports-metadata && npm run verify:background-extraction && npm run verify:plugin-catalog-extraction && npm run verify:session-reset && npm run verify:channel-ui && npm run verify:adapter-detection && npm run verify:adapter-replay-harness && npm run verify:adapter-channel-conformance && npm run verify:protocol-single-source && npm run verify:compat-removal && npm run verify:terminal-images-sixel && npm run verify:sixel-transcript && npm run verify:migrate-sessions && npm run verify:fixed-window && npm run verify:source-hygiene && npm run verify:renderer-primitives && npm run verify:product-migration && npm run verify:spinner-identity && npm run verify:table-layout && npm run verify:mermaid-diagram && npm run verify:btw && npm run verify:session-mounts && npm run verify:progress-language && npm run verify:response-language",
|
|
132
132
|
"verify:boundary": "node --import tsx/esm scripts/verify-adapter-boundary.ts",
|
|
133
133
|
"verify:i18n": "node --import tsx/esm scripts/verify-i18n.ts",
|
|
134
134
|
"verify:contract": "node --import tsx/esm scripts/verify-upstream-contract.ts",
|
|
@@ -230,6 +230,7 @@
|
|
|
230
230
|
"verify:activity-store": "node --import tsx/esm scripts/verify-activity-store.ts",
|
|
231
231
|
"verify:activity-store-render": "node --import tsx/esm scripts/verify-activity-store-render.tsx",
|
|
232
232
|
"verify:activity-ownership": "node --import tsx/esm scripts/verify-activity-ownership.ts",
|
|
233
|
+
"verify:response-language": "node --import tsx/esm scripts/verify-response-language.mjs",
|
|
233
234
|
"verify:progress-language": "node --import tsx/esm scripts/verify-progress-language.mjs",
|
|
234
235
|
"verify:opencode-profile": "node scripts/verify-opencode-profile.mjs",
|
|
235
236
|
"verify:upstream-source": "node scripts/verify-upstream-source.mjs"
|
|
@@ -76,7 +76,8 @@
|
|
|
76
76
|
config: !!js >-
|
|
77
77
|
(() => {
|
|
78
78
|
const shared = { complete: true, includeRuntimeContext: false }
|
|
79
|
-
const
|
|
79
|
+
const policy = process.getBuiltinModule('node:fs').readFileSync(new URL('../response-language.txt', ctx.baseUrl), 'utf8').trim()
|
|
80
|
+
const persona = 'You are a helpful software engineer assistant.\n\n' + policy
|
|
80
81
|
try {
|
|
81
82
|
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
|
|
82
83
|
const fs = process.getBuiltinModule('node:fs')
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Response language policy:
|
|
2
|
+
Use, in order: (1) the user's explicit language request for this task; (2) an explicit continuing language preference from the same conversation; (3) the clearly identifiable language of the current user-authored request; otherwise English.
|
|
3
|
+
If the language is unclear, respond in English. Ask for clarification in English only when the task itself needs clarification. Ambiguous short text such as "chinn korone" or "OK", identifiers, numbers, and code alone do not establish a language. Do not carry forward a previously inferred language when the current request is unclear. Recognizable languages, including Japanese and Chinese, remain supported; Latin script alone does not mean English.
|
|
4
|
+
Apply this rule to prose, progress narration, and every user-facing question header, question, option label, and option description.
|
|
5
|
+
Do not infer the response language from UI settings, OS locale, instruction prose, wrappers, quoted text, attachments, files, tool output, or prior assistant replies. These are not user language preferences. An explicit user language instruction still applies. For delegated work, follow the originating user's language request rather than the language of the generated delegation wrapper.
|