@jingyi0605/codingns4dsh 0.2.1-beta.10 → 0.2.1-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +3 -3
- package/README.md +6 -4
- package/data/build/dist/client/bundle.js +8958 -7380
- package/data/build/dist/client/bundle.js.map +1 -1
- package/data/build/dist/client/cli-slots.d.ts +11 -2
- package/data/build/dist/client/cli-slots.d.ts.map +1 -1
- package/data/build/dist/client/cli-slots.js +67 -16
- package/data/build/dist/client/cli-slots.js.map +1 -1
- package/data/build/dist/client/client.assistant-configuration-view.js +8 -7
- package/data/build/dist/client/client.assistant-configuration-view.js.map +1 -1
- package/data/build/dist/client/client.moss-voice-output.js +581 -0
- package/data/build/dist/client/client.moss-voice-output.js.map +1 -0
- package/data/build/dist/client/client.native-workspace-store.js +1 -1
- package/data/build/dist/client/client.native-workspace-store.js.map +1 -1
- package/data/build/dist/client/client.primitives-adapter.js.map +1 -1
- package/data/build/dist/client/client.react-dom.js +0 -570
- package/data/build/dist/client/client.react-dom.js.map +1 -1
- package/data/build/dist/client/client.session-translation.js +97 -2
- package/data/build/dist/client/client.session-translation.js.map +1 -1
- package/data/build/dist/client/client.transport.js +57 -11
- package/data/build/dist/client/client.transport.js.map +1 -1
- package/data/build/dist/client/desktop-assistant.js +57 -11
- package/data/build/dist/client/features/cli-adapters.d.ts.map +1 -1
- package/data/build/dist/client/features/cli-adapters.js +3 -1
- package/data/build/dist/client/features/cli-adapters.js.map +1 -1
- package/data/build/dist/client/features/session-translation.d.ts.map +1 -1
- package/data/build/dist/client/features/session-translation.js +43 -48
- package/data/build/dist/client/features/session-translation.js.map +1 -1
- package/data/build/dist/client/locales/panels.d.ts.map +1 -1
- package/data/build/dist/client/locales/panels.js +57 -11
- package/data/build/dist/client/locales/panels.js.map +1 -1
- package/data/build/dist/client/native-model-translation-menu.d.ts +6 -0
- package/data/build/dist/client/native-model-translation-menu.d.ts.map +1 -0
- package/data/build/dist/client/native-model-translation-menu.js +57 -0
- package/data/build/dist/client/native-model-translation-menu.js.map +1 -0
- package/data/build/dist/client/native-translation-default.d.ts +6 -0
- package/data/build/dist/client/native-translation-default.d.ts.map +1 -0
- package/data/build/dist/client/native-translation-default.js +30 -0
- package/data/build/dist/client/native-translation-default.js.map +1 -0
- package/data/build/dist/client/session-translation-chat.d.ts +15 -0
- package/data/build/dist/client/session-translation-chat.d.ts.map +1 -1
- package/data/build/dist/client/session-translation-chat.js +109 -41
- package/data/build/dist/client/session-translation-chat.js.map +1 -1
- package/data/build/dist/client/session-translation-interactions.d.ts +31 -0
- package/data/build/dist/client/session-translation-interactions.d.ts.map +1 -0
- package/data/build/dist/client/session-translation-interactions.js +158 -0
- package/data/build/dist/client/session-translation-interactions.js.map +1 -0
- package/data/build/dist/client/session-translation-model-pool.d.ts +16 -0
- package/data/build/dist/client/session-translation-model-pool.d.ts.map +1 -0
- package/data/build/dist/client/session-translation-model-pool.js +246 -0
- package/data/build/dist/client/session-translation-model-pool.js.map +1 -0
- package/data/build/dist/client/session-translation-pending-dom.d.ts +8 -0
- package/data/build/dist/client/session-translation-pending-dom.d.ts.map +1 -0
- package/data/build/dist/client/session-translation-pending-dom.js +58 -0
- package/data/build/dist/client/session-translation-pending-dom.js.map +1 -0
- package/data/build/dist/dsh-capabilities/client/interaction-presentation-adapter.d.ts +30 -0
- package/data/build/dist/dsh-capabilities/client/interaction-presentation-adapter.d.ts.map +1 -0
- package/data/build/dist/dsh-capabilities/client/interaction-presentation-adapter.js +102 -0
- package/data/build/dist/dsh-capabilities/client/interaction-presentation-adapter.js.map +1 -0
- package/data/build/dist/dsh-capabilities/client/interaction-text-dom.d.ts +12 -0
- package/data/build/dist/dsh-capabilities/client/interaction-text-dom.d.ts.map +1 -0
- package/data/build/dist/dsh-capabilities/client/interaction-text-dom.js +181 -0
- package/data/build/dist/dsh-capabilities/client/interaction-text-dom.js.map +1 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts +1 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.js +1 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.js.map +1 -1
- package/data/build/dist/dsh-capabilities/client/question-history-adapter.d.ts +20 -0
- package/data/build/dist/dsh-capabilities/client/question-history-adapter.d.ts.map +1 -0
- package/data/build/dist/dsh-capabilities/client/question-history-adapter.js +65 -0
- package/data/build/dist/dsh-capabilities/client/question-history-adapter.js.map +1 -0
- package/data/build/dist/dsh-capabilities/client/slot-presentation-mirror.d.ts +30 -0
- package/data/build/dist/dsh-capabilities/client/slot-presentation-mirror.d.ts.map +1 -0
- package/data/build/dist/dsh-capabilities/client/slot-presentation-mirror.js +62 -0
- package/data/build/dist/dsh-capabilities/client/slot-presentation-mirror.js.map +1 -0
- package/data/build/dist/dsh-capabilities/matrix.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/matrix.js +1 -0
- package/data/build/dist/dsh-capabilities/matrix.js.map +1 -1
- package/data/build/dist/dsh-capabilities/routes.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/routes.js +3 -0
- package/data/build/dist/dsh-capabilities/routes.js.map +1 -1
- package/data/build/dist/dsh-capabilities/types.d.ts +1 -1
- package/data/build/dist/dsh-capabilities/types.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/types.js.map +1 -1
- package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js +17 -8
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js.map +1 -1
- package/data/build/dist/host/cli-adapters/feature.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/feature.js +252 -39
- package/data/build/dist/host/cli-adapters/feature.js.map +1 -1
- package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js +2 -2
- package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js.map +1 -1
- package/data/build/dist/host/cli-adapters/registry.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/registry.js +2 -0
- package/data/build/dist/host/cli-adapters/registry.js.map +1 -1
- package/data/build/dist/host/features/interaction-translation.d.ts +9 -0
- package/data/build/dist/host/features/interaction-translation.d.ts.map +1 -0
- package/data/build/dist/host/features/interaction-translation.js +168 -0
- package/data/build/dist/host/features/interaction-translation.js.map +1 -0
- package/data/build/dist/host/features/session-translation-protection.d.ts +11 -0
- package/data/build/dist/host/features/session-translation-protection.d.ts.map +1 -0
- package/data/build/dist/host/features/session-translation-protection.js +165 -0
- package/data/build/dist/host/features/session-translation-protection.js.map +1 -0
- package/data/build/dist/host/features/session-translation-runtime.d.ts +16 -0
- package/data/build/dist/host/features/session-translation-runtime.d.ts.map +1 -0
- package/data/build/dist/host/features/session-translation-runtime.js +85 -0
- package/data/build/dist/host/features/session-translation-runtime.js.map +1 -0
- package/data/build/dist/host/features/session-translation-service.d.ts +10 -3
- package/data/build/dist/host/features/session-translation-service.d.ts.map +1 -1
- package/data/build/dist/host/features/session-translation-service.js +159 -197
- package/data/build/dist/host/features/session-translation-service.js.map +1 -1
- package/data/build/dist/host/features/session-translation.js +1 -1
- package/data/build/dist/host/features/session-translation.js.map +1 -1
- package/data/build/dist/host/native-session-bridge.js +2 -2
- package/data/build/dist/host/native-session-bridge.js.map +1 -1
- package/data/build/dist/host/settings.d.ts.map +1 -1
- package/data/build/dist/host/settings.js +6 -2
- package/data/build/dist/host/settings.js.map +1 -1
- package/data/build/dist/shared/contracts/interaction-presentation.d.ts +32 -0
- package/data/build/dist/shared/contracts/interaction-presentation.d.ts.map +1 -0
- package/data/build/dist/shared/contracts/interaction-presentation.js +2 -0
- package/data/build/dist/shared/contracts/interaction-presentation.js.map +1 -0
- package/data/build/dist/shared/contracts/interaction-translation.d.ts +53 -0
- package/data/build/dist/shared/contracts/interaction-translation.d.ts.map +1 -0
- package/data/build/dist/shared/contracts/interaction-translation.js +44 -0
- package/data/build/dist/shared/contracts/interaction-translation.js.map +1 -0
- package/data/build/dist/shared/contracts/session-translation.d.ts +62 -7
- package/data/build/dist/shared/contracts/session-translation.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/session-translation.js +122 -2
- package/data/build/dist/shared/contracts/session-translation.js.map +1 -1
- package/data/build/dist/shared/contracts/version.d.ts +1 -1
- package/data/build/dist/shared/contracts/version.js +1 -1
- package/data/build/dist/shared/index.d.ts +1 -1
- package/data/build/dist/shared/index.d.ts.map +1 -1
- package/data/build/dist/shared/index.js +1 -1
- package/data/build/dist/shared/index.js.map +1 -1
- package/data/build/dist/shared/translation-indicator.d.ts +26 -0
- package/data/build/dist/shared/translation-indicator.d.ts.map +1 -0
- package/data/build/dist/shared/translation-indicator.js +29 -0
- package/data/build/dist/shared/translation-indicator.js.map +1 -0
- package/package.json +1 -1
- package/profile/README.md +2 -2
- package/profile/package.json +2 -2
- package/profile/version.json +1 -1
- package/version.json +1 -1
|
@@ -31,7 +31,9 @@ import { containsDelegationCarrier, delegationAdapterIds, rewriteDelegationMessa
|
|
|
31
31
|
import { clearDelegationAuthorization, setDelegationAuthorization } from './delegation-authorization.js';
|
|
32
32
|
import { debugInfo } from '../../shared/debug.js';
|
|
33
33
|
import { hasLegacySessionAdapterHint } from './legacy-session-adapter.js';
|
|
34
|
-
import {} from '../../shared/contracts/session-translation.js';
|
|
34
|
+
import { DSH_NATIVE_SESSION_ADAPTER_ID, formatSessionTranslationOutput, readSessionTranslationMetrics, } from '../../shared/contracts/session-translation.js';
|
|
35
|
+
import { createInteractionTranslation } from '../features/interaction-translation.js';
|
|
36
|
+
import { ASSISTANT_AGENT_PREFIX } from '../../dsh-capabilities/host/assistant-agent-adapter.js';
|
|
35
37
|
export function createCliAdaptersFeature(options = {}) {
|
|
36
38
|
return {
|
|
37
39
|
descriptor: {
|
|
@@ -130,8 +132,10 @@ export function createCliAdaptersFeature(options = {}) {
|
|
|
130
132
|
});
|
|
131
133
|
context.resources.add(disposeNativeEvents);
|
|
132
134
|
}
|
|
133
|
-
registerDelegationAgentHooks(context.services.dshContext, registry, context.resources, publishExternalStatus, translation);
|
|
134
|
-
|
|
135
|
+
registerDelegationAgentHooks(context.services.dshContext, registry, context.resources, publishExternalStatus, translation, nativeSessions);
|
|
136
|
+
const interactionTranslation = createInteractionTranslation(translation, sessionId => registry.getSession(sessionId));
|
|
137
|
+
context.resources.add(() => interactionTranslation.dispose());
|
|
138
|
+
context.resources.add(context.services.rpc.register('cli', (action, payload, rpcContext) => {
|
|
135
139
|
switch (action) {
|
|
136
140
|
case 'catalog': return registry.catalog();
|
|
137
141
|
case 'catalog/refresh': return registry.refreshCatalog(asRecord(payload)?.adapterId === undefined ? undefined : readAdapterId(payload)).then((catalog) => {
|
|
@@ -143,6 +147,10 @@ export function createCliAdaptersFeature(options = {}) {
|
|
|
143
147
|
return adapterId === 'dsh' ? readDshModelCatalog(context.services.dshContext) : registry.models(adapterId);
|
|
144
148
|
}
|
|
145
149
|
case 'translation/models': return context.services.sessionTranslation?.catalog() ?? { models: [], default: null, errors: ['翻译模型目录不可用'] };
|
|
150
|
+
case 'translation/fields': {
|
|
151
|
+
const signal = asRecord(rpcContext)?.signal;
|
|
152
|
+
return interactionTranslation.translate(payload, isAbortSignal(signal) ? signal : undefined);
|
|
153
|
+
}
|
|
146
154
|
case 'skills': {
|
|
147
155
|
const request = readSkillsRequest(payload);
|
|
148
156
|
const cwd = resolveSessionCwd(context.services.nativeSessions, request.sessionId, null);
|
|
@@ -344,6 +352,18 @@ export function createCliAdaptersFeature(options = {}) {
|
|
|
344
352
|
if (sessionId !== '' && (selection.modelId !== undefined || selection.effortId !== undefined)) {
|
|
345
353
|
registry.setSession(sessionId, { adapterId: 'dsh', ...selection });
|
|
346
354
|
}
|
|
355
|
+
// Native-session output translation wraps only DSH's own Provider stream:
|
|
356
|
+
// preserve text/reasoning and attach the translation record; the client renders it.
|
|
357
|
+
if (!isSessionTranslationLlmRequest(value)
|
|
358
|
+
&& translation !== undefined
|
|
359
|
+
&& translation.enabled
|
|
360
|
+
&& (config.translationEnabled ?? translation.nativeEnabled === true)
|
|
361
|
+
&& sessionId !== ''
|
|
362
|
+
&& !isAssistantSession(sessionId)
|
|
363
|
+
&& readNativeSessionHeader(nativeSessions, sessionId)?.origin !== 'subagent') {
|
|
364
|
+
yield* guardDshNativeStream(() => translateNativeStream(next(), translation, translation.bilingual === true, isAbortSignal(value?.signal) ? value.signal : undefined));
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
347
367
|
yield* guardDshNativeStream(next);
|
|
348
368
|
return;
|
|
349
369
|
}
|
|
@@ -526,7 +546,7 @@ function createExternalSessionStatusPublisher(events, registry, sessionStore) {
|
|
|
526
546
|
* `messages`,会直接抛出只读属性异常。`agent/pre-step` 返回的新消息保留用户原文,并把
|
|
527
547
|
* 译文写入 source 元数据;外部适配器再据此构造发给 Agent 的译文。
|
|
528
548
|
*/
|
|
529
|
-
function registerDelegationAgentHooks(dshContext, registry, resources, publishExternalStatus, translation) {
|
|
549
|
+
function registerDelegationAgentHooks(dshContext, registry, resources, publishExternalStatus, translation, nativeSessions) {
|
|
530
550
|
if (dshContext === undefined || typeof dshContext.on !== 'function')
|
|
531
551
|
return;
|
|
532
552
|
const disposers = [];
|
|
@@ -588,7 +608,7 @@ function registerDelegationAgentHooks(dshContext, registry, resources, publishEx
|
|
|
588
608
|
messages = [...delegation.value.messages];
|
|
589
609
|
}
|
|
590
610
|
}
|
|
591
|
-
const translatedInput = await translatePreStepInput(translation, registry, sessionId, messages, dshContext, isAbortSignal(record?.signal) ? record.signal : undefined);
|
|
611
|
+
const translatedInput = await translatePreStepInput(translation, registry, sessionId, messages, dshContext, isAbortSignal(record?.signal) ? record.signal : undefined, nativePreStepContext(translation, registry, sessionId, nativeSessions));
|
|
592
612
|
if (translatedInput !== undefined)
|
|
593
613
|
messages = [...translatedInput];
|
|
594
614
|
const decision = await next();
|
|
@@ -999,9 +1019,42 @@ async function translateSteerPrompt(translation, registry, sessionId, prompt, fo
|
|
|
999
1019
|
* DSH 随后会把返回的消息写入 `user/message`。正文只放实际发送的译文;原文和模型
|
|
1000
1020
|
* 记录在 source 元数据中供 Client 详情按钮读取。外部 CLI 边界也会移除该元数据。
|
|
1001
1021
|
*/
|
|
1002
|
-
async function translatePreStepInput(translation, registry, sessionId, messages, dshContext, signal) {
|
|
1022
|
+
async function translatePreStepInput(translation, registry, sessionId, messages, dshContext, signal, nativeSession) {
|
|
1003
1023
|
if (translation === undefined || !translation.enabled || sessionId.trim() === '')
|
|
1004
1024
|
return undefined;
|
|
1025
|
+
const messageIndex = findLatestHumanMessage(messages);
|
|
1026
|
+
const current = messageIndex < 0 ? undefined : messages[messageIndex];
|
|
1027
|
+
if (current === undefined || readInputTranslation(current.source) !== undefined)
|
|
1028
|
+
return undefined;
|
|
1029
|
+
if (nativeSession !== undefined) {
|
|
1030
|
+
// DSH 原生会话:消息本身就是发给 Provider 的正文,直接替换为译文并把原文留在元数据。
|
|
1031
|
+
if (nativeSession.translationEnabled !== true)
|
|
1032
|
+
return undefined;
|
|
1033
|
+
const input = extractTurnInput(messages, dshContext);
|
|
1034
|
+
if (input.translationPrompt.trim() === '')
|
|
1035
|
+
return undefined;
|
|
1036
|
+
const result = await runInputTranslation(translation, nativeSession.adapterId, input.translationPrompt, signal);
|
|
1037
|
+
const translated = [result.translated, input.untranslatedPrompt].filter((part) => part.trim() !== '').join('\n\n').trim();
|
|
1038
|
+
if (translated === '')
|
|
1039
|
+
return undefined;
|
|
1040
|
+
const record = {
|
|
1041
|
+
original: input.prompt,
|
|
1042
|
+
translated,
|
|
1043
|
+
...(result.sourceLanguage === undefined ? {} : { sourceLanguage: result.sourceLanguage }),
|
|
1044
|
+
targetLanguage: readInputTargetLanguage(translation),
|
|
1045
|
+
...(result.alreadyTargetLanguage === true ? { alreadyTargetLanguage: true } : {}),
|
|
1046
|
+
...(result.model === undefined ? {} : { model: result.model }),
|
|
1047
|
+
...readSessionTranslationMetrics(result),
|
|
1048
|
+
...(result.failed === true ? { failed: true } : {}),
|
|
1049
|
+
};
|
|
1050
|
+
const next = [...messages];
|
|
1051
|
+
next[messageIndex] = {
|
|
1052
|
+
...current,
|
|
1053
|
+
content: [{ type: 'text', text: translated }],
|
|
1054
|
+
source: { ...(current.source ?? {}), kind: 'user', codingnsTranslationInput: record },
|
|
1055
|
+
};
|
|
1056
|
+
return next;
|
|
1057
|
+
}
|
|
1005
1058
|
let session;
|
|
1006
1059
|
try {
|
|
1007
1060
|
session = registry.getSession(sessionId);
|
|
@@ -1011,37 +1064,11 @@ async function translatePreStepInput(translation, registry, sessionId, messages,
|
|
|
1011
1064
|
}
|
|
1012
1065
|
if (session.adapterId === 'dsh' || session.translationEnabled !== true)
|
|
1013
1066
|
return undefined;
|
|
1014
|
-
const messageIndex = findLatestHumanMessage(messages);
|
|
1015
|
-
const current = messageIndex < 0 ? undefined : messages[messageIndex];
|
|
1016
|
-
if (current === undefined || readInputTranslation(current.source) !== undefined)
|
|
1017
|
-
return undefined;
|
|
1018
1067
|
const input = extractTurnInput(messages, dshContext);
|
|
1019
1068
|
if (input.translationPrompt.trim() === '')
|
|
1020
1069
|
return undefined;
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
let alreadyTargetLanguage = false;
|
|
1024
|
-
let translationModel;
|
|
1025
|
-
let translationFailed = false;
|
|
1026
|
-
try {
|
|
1027
|
-
if (translation.translateInputDetailed !== undefined) {
|
|
1028
|
-
const detailed = await translation.translateInputDetailed(session.adapterId, input.translationPrompt, signal, true);
|
|
1029
|
-
translatedNatural = detailed.translated;
|
|
1030
|
-
translationSourceLanguage = detailed.sourceLanguage;
|
|
1031
|
-
alreadyTargetLanguage = detailed.alreadyTargetLanguage === true;
|
|
1032
|
-
translationModel = detailed.model;
|
|
1033
|
-
translationFailed = detailed.failed === true;
|
|
1034
|
-
}
|
|
1035
|
-
else {
|
|
1036
|
-
translatedNatural = await translation.translateInput(session.adapterId, input.translationPrompt, signal, true);
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
catch {
|
|
1040
|
-
// 翻译只是增强能力;异常时保持现有外部 Agent 回合继续使用原文。
|
|
1041
|
-
translatedNatural = input.translationPrompt;
|
|
1042
|
-
translationFailed = true;
|
|
1043
|
-
}
|
|
1044
|
-
const translated = [translatedNatural, input.untranslatedPrompt]
|
|
1070
|
+
const result = await runInputTranslation(translation, session.adapterId, input.translationPrompt, signal);
|
|
1071
|
+
const translated = [result.translated, input.untranslatedPrompt]
|
|
1045
1072
|
.filter((part) => part.trim() !== '')
|
|
1046
1073
|
.join('\n\n')
|
|
1047
1074
|
.trim();
|
|
@@ -1050,11 +1077,12 @@ async function translatePreStepInput(translation, registry, sessionId, messages,
|
|
|
1050
1077
|
const record = {
|
|
1051
1078
|
original: input.prompt,
|
|
1052
1079
|
translated,
|
|
1053
|
-
...(
|
|
1054
|
-
targetLanguage: translation
|
|
1055
|
-
...(alreadyTargetLanguage ? { alreadyTargetLanguage: true } : {}),
|
|
1056
|
-
...(
|
|
1057
|
-
...(
|
|
1080
|
+
...(result.sourceLanguage === undefined ? {} : { sourceLanguage: result.sourceLanguage }),
|
|
1081
|
+
targetLanguage: readInputTargetLanguage(translation),
|
|
1082
|
+
...(result.alreadyTargetLanguage === true ? { alreadyTargetLanguage: true } : {}),
|
|
1083
|
+
...(result.model === undefined ? {} : { model: result.model }),
|
|
1084
|
+
...readSessionTranslationMetrics(result),
|
|
1085
|
+
...(result.failed === true ? { failed: true } : {}),
|
|
1058
1086
|
};
|
|
1059
1087
|
const next = [...messages];
|
|
1060
1088
|
next[messageIndex] = {
|
|
@@ -1067,6 +1095,191 @@ async function translatePreStepInput(translation, registry, sessionId, messages,
|
|
|
1067
1095
|
};
|
|
1068
1096
|
return next;
|
|
1069
1097
|
}
|
|
1098
|
+
/** 输入翻译统一入口:翻译只是增强能力,异常时回退原文并标记失败。 */
|
|
1099
|
+
async function runInputTranslation(translation, adapterId, text, signal) {
|
|
1100
|
+
try {
|
|
1101
|
+
if (translation.translateInputDetailed !== undefined) {
|
|
1102
|
+
const detailed = await translation.translateInputDetailed(adapterId, text, signal, true);
|
|
1103
|
+
return {
|
|
1104
|
+
translated: detailed.translated,
|
|
1105
|
+
...(detailed.sourceLanguage === undefined ? {} : { sourceLanguage: detailed.sourceLanguage }),
|
|
1106
|
+
...(detailed.alreadyTargetLanguage === true ? { alreadyTargetLanguage: true } : {}),
|
|
1107
|
+
...(detailed.model === undefined ? {} : { model: detailed.model }),
|
|
1108
|
+
...(detailed.failed === true ? { failed: true } : {}),
|
|
1109
|
+
...readSessionTranslationMetrics(detailed),
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
return { translated: await translation.translateInput(adapterId, text, signal, true) };
|
|
1113
|
+
}
|
|
1114
|
+
catch {
|
|
1115
|
+
return { translated: text, failed: true };
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
/** 旧测试替身没有 inputLanguage 时沿用历史默认值英语。 */
|
|
1119
|
+
function readInputTargetLanguage(translation) {
|
|
1120
|
+
const language = translation.inputLanguage;
|
|
1121
|
+
return language === undefined ? 'en' : language;
|
|
1122
|
+
}
|
|
1123
|
+
/**
|
|
1124
|
+
* 判断本次 pre-step 是否按 DSH 原生会话翻译。
|
|
1125
|
+
*
|
|
1126
|
+
* 原生会话的翻译记录来自全局 `nativeEnabled` 与适配器偏好(会话索引对 `dsh` 不落盘),
|
|
1127
|
+
* 子代理与插件自己的助理会话必须排除,避免把内部执行流水线翻译掉。
|
|
1128
|
+
*/
|
|
1129
|
+
function nativePreStepContext(translation, registry, sessionId, nativeSessions) {
|
|
1130
|
+
if (translation === undefined || !translation.enabled || sessionId.trim() === '')
|
|
1131
|
+
return undefined;
|
|
1132
|
+
if (isAssistantSession(sessionId))
|
|
1133
|
+
return undefined;
|
|
1134
|
+
if (readNativeSessionHeader(nativeSessions, sessionId)?.origin === 'subagent')
|
|
1135
|
+
return undefined;
|
|
1136
|
+
let session;
|
|
1137
|
+
try {
|
|
1138
|
+
session = registry.getSession(sessionId);
|
|
1139
|
+
}
|
|
1140
|
+
catch {
|
|
1141
|
+
return undefined;
|
|
1142
|
+
}
|
|
1143
|
+
if (session.adapterId !== DSH_NATIVE_SESSION_ADAPTER_ID)
|
|
1144
|
+
return undefined;
|
|
1145
|
+
return {
|
|
1146
|
+
adapterId: DSH_NATIVE_SESSION_ADAPTER_ID,
|
|
1147
|
+
// 会话级开关优先;用户没有单独设置过该会话时跟随「DSH 原生会话」总开关。
|
|
1148
|
+
translationEnabled: session.translationEnabled ?? translation.nativeEnabled === true,
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
/** 读取原生会话 header;测试替身或会话尚未装载时返回 undefined。 */
|
|
1152
|
+
function readNativeSessionHeader(nativeSessions, sessionId) {
|
|
1153
|
+
if (nativeSessions === undefined)
|
|
1154
|
+
return undefined;
|
|
1155
|
+
try {
|
|
1156
|
+
return asRecord(asRecord(nativeSessions.get(sessionId))?.header) ?? undefined;
|
|
1157
|
+
}
|
|
1158
|
+
catch {
|
|
1159
|
+
return undefined;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
/** 插件自己的全局助理会话不属于用户对话,不能被翻译改写。 */
|
|
1163
|
+
function isAssistantSession(sessionId) {
|
|
1164
|
+
// 复用助理适配器导出的会话前缀常量:会话身份的唯一定义在那里,重复字面量会漂移。
|
|
1165
|
+
return sessionId.startsWith(ASSISTANT_AGENT_PREFIX);
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* DSH 原生会话的输出翻译。
|
|
1169
|
+
*
|
|
1170
|
+
* 原生回复由 DSH 自己组装成 `assistant/message`,插件只能在 Provider 流边界改写:
|
|
1171
|
+
* 文本与思考增量先缓存,块结束时一次性发出原文,并把译文放进记录供客户端显示;
|
|
1172
|
+
* 工具调用、usage 与 finish 原样透传。翻译失败、流中断或异常都会补发原文块,保证回复不丢失。
|
|
1173
|
+
*/
|
|
1174
|
+
async function* translateNativeStream(stream, translation, bilingual, signal) {
|
|
1175
|
+
const blocks = new Map();
|
|
1176
|
+
const bufferOf = (index, kind) => {
|
|
1177
|
+
const existing = blocks.get(index);
|
|
1178
|
+
if (existing !== undefined)
|
|
1179
|
+
return existing.kind === kind && !existing.closed ? existing : undefined;
|
|
1180
|
+
const created = { index, kind, text: '', closed: false };
|
|
1181
|
+
blocks.set(index, created);
|
|
1182
|
+
return created;
|
|
1183
|
+
};
|
|
1184
|
+
const translateBlock = async (block) => {
|
|
1185
|
+
const original = block.text;
|
|
1186
|
+
if (original.trim() === '')
|
|
1187
|
+
return [];
|
|
1188
|
+
const kind = block.kind === 'reasoning' ? 'reasoning' : 'assistant';
|
|
1189
|
+
let record;
|
|
1190
|
+
try {
|
|
1191
|
+
const result = await translation.translateOutput(DSH_NATIVE_SESSION_ADAPTER_ID, kind, original, signal, true);
|
|
1192
|
+
if (result !== null && result !== undefined) {
|
|
1193
|
+
record = {
|
|
1194
|
+
original: result.original,
|
|
1195
|
+
translated: result.translated,
|
|
1196
|
+
...(result.sourceLanguage === undefined ? {} : { sourceLanguage: result.sourceLanguage }),
|
|
1197
|
+
targetLanguage: result.targetLanguage,
|
|
1198
|
+
outputKind: kind,
|
|
1199
|
+
bilingual: result.bilingual,
|
|
1200
|
+
...(result.alreadyTargetLanguage === true ? { alreadyTargetLanguage: true } : {}),
|
|
1201
|
+
...(result.model === undefined ? {} : { model: result.model }),
|
|
1202
|
+
...readSessionTranslationMetrics(result),
|
|
1203
|
+
...(result.failed === true ? { failed: true } : {}),
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
catch {
|
|
1208
|
+
record = { original, translated: original, targetLanguage: translation.outputLanguage ?? 'zh', outputKind: kind, bilingual, failed: true };
|
|
1209
|
+
}
|
|
1210
|
+
if (record === undefined)
|
|
1211
|
+
return [];
|
|
1212
|
+
const visible = formatSessionTranslationOutput(record);
|
|
1213
|
+
if (visible.trim() === '' || visible === original)
|
|
1214
|
+
return [];
|
|
1215
|
+
return [
|
|
1216
|
+
// Keep the provider text in the native history. The client chooses the translated
|
|
1217
|
+
// text for display from codingnsTranslation.translated.
|
|
1218
|
+
{ type: `${block.kind}-delta`, index: block.index, text: original, codingnsTranslation: record },
|
|
1219
|
+
{ type: 'block-end', index: block.index, block: { type: block.kind, text: original, codingnsTranslation: record }, codingnsTranslation: record },
|
|
1220
|
+
];
|
|
1221
|
+
};
|
|
1222
|
+
try {
|
|
1223
|
+
for await (const chunk of stream) {
|
|
1224
|
+
const record = asRecord(chunk);
|
|
1225
|
+
const type = typeof record?.type === 'string' ? record.type : '';
|
|
1226
|
+
const index = typeof record?.index === 'number' ? record.index : undefined;
|
|
1227
|
+
if (type === 'text-delta' || type === 'reasoning-delta') {
|
|
1228
|
+
if (index === undefined || typeof record?.text !== 'string') {
|
|
1229
|
+
yield chunk;
|
|
1230
|
+
continue;
|
|
1231
|
+
}
|
|
1232
|
+
const kind = type === 'text-delta' ? 'text' : 'reasoning';
|
|
1233
|
+
const block = bufferOf(index, kind);
|
|
1234
|
+
if (block === undefined) {
|
|
1235
|
+
yield chunk;
|
|
1236
|
+
continue;
|
|
1237
|
+
}
|
|
1238
|
+
block.text += record.text;
|
|
1239
|
+
continue;
|
|
1240
|
+
}
|
|
1241
|
+
if (type === 'block-end' && index !== undefined) {
|
|
1242
|
+
const block = blocks.get(index);
|
|
1243
|
+
if (block !== undefined && !block.closed) {
|
|
1244
|
+
block.closed = true;
|
|
1245
|
+
if (block.text.trim() !== '') {
|
|
1246
|
+
const emitted = await translateBlock(block);
|
|
1247
|
+
for (const item of emitted)
|
|
1248
|
+
yield item;
|
|
1249
|
+
if (emitted.length > 0)
|
|
1250
|
+
continue;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
yield chunk;
|
|
1254
|
+
continue;
|
|
1255
|
+
}
|
|
1256
|
+
yield chunk;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
catch (error) {
|
|
1260
|
+
// 流异常时先把缓存正文按原文补发,再把原始错误交给 DSH,保证回复不丢失。
|
|
1261
|
+
for (const item of flushBuffered())
|
|
1262
|
+
yield item;
|
|
1263
|
+
throw error;
|
|
1264
|
+
}
|
|
1265
|
+
for (const item of flushBuffered())
|
|
1266
|
+
yield item;
|
|
1267
|
+
/**
|
|
1268
|
+
* Provider 未发送 block-end(中断或异常)时,把缓存正文按原文补发。
|
|
1269
|
+
*
|
|
1270
|
+
* 不能用 `finally` 里的 `yield`:异常正在传播时生成器已经结束,后续 yield 会被
|
|
1271
|
+
* 直接丢弃,用户会看不到已经生成的半截回复。
|
|
1272
|
+
*/
|
|
1273
|
+
function* flushBuffered() {
|
|
1274
|
+
for (const block of [...blocks.values()]) {
|
|
1275
|
+
if (block.closed || block.text.trim() === '')
|
|
1276
|
+
continue;
|
|
1277
|
+
block.closed = true;
|
|
1278
|
+
yield { type: `${block.kind}-delta`, index: block.index, text: block.text };
|
|
1279
|
+
yield { type: 'block-end', index: block.index, block: { type: block.kind, text: block.text } };
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1070
1283
|
function extractTurnInput(messages, dshContext) {
|
|
1071
1284
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
1072
1285
|
const message = messages[index];
|