@lynn123411/dsh-chat-translate 2.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -12
- package/docs//351/205/215/347/275/256.md +9 -13
- package/lib/client.js +813 -837
- package/lib/client.js.map +4 -4
- package/lib/index.js +100 -264
- package/lib/index.js.map +4 -4
- package/lib/types/client/chat/assistant-step.d.ts +79 -0
- package/lib/types/client/chat/click-guard.d.ts +27 -0
- package/lib/types/client/chat/presentation.d.ts +51 -0
- package/lib/types/client/chat/row-plan.d.ts +72 -0
- package/lib/types/client/chat/styles.d.ts +19 -0
- package/lib/types/client/chat/translate-store.d.ts +73 -0
- package/lib/types/client/composer/dock-toggle.d.ts +26 -0
- package/lib/types/client/index.d.ts +26 -17
- package/lib/types/client/locales.d.ts +5 -2
- package/lib/types/index.d.ts +8 -11
- package/lib/types/server/cache.d.ts +4 -19
- package/lib/types/server/config.d.ts +6 -72
- package/lib/types/server/credentials.d.ts +3 -3
- package/lib/types/server/dispatcher.d.ts +6 -0
- package/lib/types/server/pipeline/mask-tokens.d.ts +4 -22
- package/lib/types/server/pipeline/masking.d.ts +7 -12
- package/lib/types/server/prompt-revision.d.ts +14 -0
- package/lib/types/server/router.d.ts +2 -2
- package/lib/types/server/types.d.ts +0 -1
- package/package.json +11 -11
- package/lib/types/client/translate/client-cache.d.ts +0 -17
- package/lib/types/client/translate/lazy.d.ts +0 -16
- package/lib/types/client/translate/mount.d.ts +0 -57
- package/lib/types/client/translate/observer.d.ts +0 -52
- package/lib/types/client/translate/reply.d.ts +0 -38
|
@@ -24,14 +24,20 @@ export declare class TranslationDispatcher {
|
|
|
24
24
|
* 调用都独立决定成败,不会出现「前一段已挂译文、后一段失败」的半截结果。
|
|
25
25
|
*/
|
|
26
26
|
translateReplyBlocks(blocks: string[]): Promise<ReplyBlockResult[]>;
|
|
27
|
+
/** 熔断授予之后的正文执行段:切块、打包、请求、拼装。 */
|
|
28
|
+
private serveReplyBlocks;
|
|
27
29
|
/**
|
|
28
30
|
* 一整批一次请求;失败则该批逐片段单发重试一次,仍失败的片段直接放弃
|
|
29
31
|
* (保留原文),不在界面上留提示。失败的片段不进缓存,因此下一次滚回视口
|
|
30
32
|
* 时会自然重试。
|
|
31
33
|
*
|
|
32
34
|
* 熔断记账按「批」算:一次批请求失败记一次,逐片段重试失败再各记一次。
|
|
35
|
+
* 内容级拒收除外:响应都正常回来了,通道是活的——拒收记一次成功,
|
|
36
|
+
* 坏内容只作废坏内容自己,不把其他行挡在冷却期外。
|
|
33
37
|
*/
|
|
34
38
|
private translateReplyBatch;
|
|
39
|
+
/** 失败记账的分类:传输故障计数,内容拒收证明通道活着。 */
|
|
40
|
+
private accountBatch;
|
|
35
41
|
/** 发出一次正文请求并把结果还原成每个片段的最终译文。 */
|
|
36
42
|
private requestReplyBatch;
|
|
37
43
|
/** 串行执行器:同时最多一个在途请求。 */
|
|
@@ -5,13 +5,11 @@
|
|
|
5
5
|
* Wire format: `⟦xkbdt3⟧` — U+27E6/U+27E7 (mathematical white square brackets)
|
|
6
6
|
* around `<4-letter random id><index>`.
|
|
7
7
|
*
|
|
8
|
-
* Design constraints, each one a measured failure
|
|
9
|
-
* real MT engines:
|
|
8
|
+
* Design constraints, each one a measured failure against real MT engines:
|
|
10
9
|
*
|
|
11
|
-
* - No letters spelling a pronounceable word and no underscores
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* the protected fragments.
|
|
10
|
+
* - No letters spelling a pronounceable word and no underscores: engines
|
|
11
|
+
* abbreviate tokens with such a shape back to their recognizable core, and
|
|
12
|
+
* bare `DSH` runs then show in the UI instead of the protected fragments.
|
|
15
13
|
* - Random letters keep two mask passes in the same session from colliding and
|
|
16
14
|
* make the token unambiguous in the translated text.
|
|
17
15
|
* - `matchMaskToken` accepts exactly what this module emits (plus the same
|
|
@@ -41,8 +39,6 @@ export declare const MASK_TOKEN_PATTERN_SOURCE = "\u27E6([a-z]{4})(\\d+)\u27E7";
|
|
|
41
39
|
* bracket. Used to resolve a token the engine truncated.
|
|
42
40
|
*/
|
|
43
41
|
export declare const MASK_TOKEN_PREFIX_PATTERN_SOURCE = "\u27E6\\s*([a-z]{4})(\\d+)";
|
|
44
|
-
/** Regex source for one retired-format token, for text that still contains one. */
|
|
45
|
-
export declare const LEGACY_MASK_TOKEN_PATTERN_SOURCE = "_{1,2}DSH\\s*_*\\s*MASKx?\\s*(?:_?\\s*\\d+|_*([a-z]{2,8})\\s*_+\\s*(\\d+))_{0,2}";
|
|
46
42
|
export interface MaskTokenMatch {
|
|
47
43
|
/** Index into the mask list of the `mask()` call that produced the token. */
|
|
48
44
|
index: number;
|
|
@@ -66,17 +62,3 @@ export declare function findMaskTokens(text: string): Array<{
|
|
|
66
62
|
}>;
|
|
67
63
|
/** True when `text` still carries a token of the current format. */
|
|
68
64
|
export declare function hasMaskResidue(text: string): boolean;
|
|
69
|
-
/** True when `text` carries a token of a retired format. */
|
|
70
|
-
export declare function hasLegacyMaskResidue(text: string): boolean;
|
|
71
|
-
/**
|
|
72
|
-
* Residue test for a value that must never be shown or cached: either a
|
|
73
|
-
* current-format token or any retired-format token.
|
|
74
|
-
*/
|
|
75
|
-
export declare function hasAnyMaskResidue(text: string): boolean;
|
|
76
|
-
/**
|
|
77
|
-
* Retired-format tokens inside source text, so `mask()` can protect them with a
|
|
78
|
-
* current-format token of their own. A source that talks about the old
|
|
79
|
-
* placeholder format must survive translation, and the unmask step rejects any
|
|
80
|
-
* retired-format token it sees.
|
|
81
|
-
*/
|
|
82
|
-
export declare function findLegacyMaskTokens(text: string): string[];
|
|
@@ -7,11 +7,6 @@ export interface MaskResult {
|
|
|
7
7
|
* must discard that translation instead of showing a repaired guess.
|
|
8
8
|
*/
|
|
9
9
|
unmask: (translatedText: string) => string;
|
|
10
|
-
/**
|
|
11
|
-
* Retired-format tokens the source itself contained. They come back on
|
|
12
|
-
* purpose and are content, so the caller's leak check must not flag them.
|
|
13
|
-
*/
|
|
14
|
-
legacyFragments: string[];
|
|
15
10
|
}
|
|
16
11
|
/** Which spaces `mask()` inserted directly before and after a token. */
|
|
17
12
|
export interface InsertedSpacing {
|
|
@@ -36,15 +31,15 @@ export declare class ContentMaskingPipeline {
|
|
|
36
31
|
* spacing the translation produced around the fragment survives untouched.
|
|
37
32
|
*
|
|
38
33
|
* @throws MaskRestoreError when the text does not carry every token exactly
|
|
39
|
-
* once, or still shows a
|
|
40
|
-
*
|
|
41
|
-
* instead of rendering a repaired guess.
|
|
34
|
+
* once, or still shows a token of some other pass or a damaged one — the
|
|
35
|
+
* caller discards such a translation instead of rendering a repaired guess.
|
|
42
36
|
*/
|
|
43
|
-
export declare function replaceMaskTokens(text: string, id: string, masks: string[], inserted?: InsertedSpacing[]
|
|
37
|
+
export declare function replaceMaskTokens(text: string, id: string, masks: string[], inserted?: InsertedSpacing[]): string;
|
|
44
38
|
/**
|
|
45
|
-
* True when a translated string still shows a mask token to the user.
|
|
46
|
-
*
|
|
47
|
-
*
|
|
39
|
+
* True when a translated string still shows a mask token to the user. Callers
|
|
40
|
+
* use it to discard a poisoned translation, to keep it out of the caches, and
|
|
41
|
+
* to drop poisoned entries when a cache document is loaded (the file on disk
|
|
42
|
+
* outlives the process and may carry anything).
|
|
48
43
|
*/
|
|
49
44
|
export declare function isMaskLeak(translatedText: string): boolean;
|
|
50
45
|
export { hasMaskResidue };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single registration of the translation prompt's semantic revision.
|
|
3
|
+
*
|
|
4
|
+
* The reply cache stores results keyed by source text; a cache document
|
|
5
|
+
* written under a different prompt semantics would replay stale translations
|
|
6
|
+
* into a new policy (the exact poisoning that makes "already-Chinese blocks
|
|
7
|
+
* look untranslated" persist for a TTL after a prompt change). The document
|
|
8
|
+
* therefore carries this revision, and a load whose revision differs starts
|
|
9
|
+
* from an empty pool.
|
|
10
|
+
*
|
|
11
|
+
* Bump it — and only here — whenever the prompt below `buildSystemPrompt`
|
|
12
|
+
* changes what the model is asked to do. Copy-only edits may ride.
|
|
13
|
+
*/
|
|
14
|
+
export declare const PROMPT_REVISION = "r1";
|
|
@@ -4,8 +4,8 @@ import type { TranslationDispatcher } from './dispatcher.ts';
|
|
|
4
4
|
* Translation proxy surface, carried by Connection's exact Fetch routes below
|
|
5
5
|
* the shared `/api` channel.
|
|
6
6
|
*
|
|
7
|
-
* Config and credentials have no HTTP endpoints:
|
|
8
|
-
*
|
|
7
|
+
* Config and credentials have no HTTP endpoints: the settings panel reads and
|
|
8
|
+
* writes through DSH's own channels — the shared configuration form
|
|
9
9
|
* (`ctx.configForms`) over the profile entry, and the `credentials` Remote API
|
|
10
10
|
* for the key — so the plugin owns exactly two routes: reply-body block
|
|
11
11
|
* translation, and the channel probe.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynn123411/dsh-chat-translate",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Assistant reply-body translation for the DeepSeek Harness Web UI (OpenAI-compatible channel)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "lynn123411",
|
|
@@ -61,22 +61,22 @@
|
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "node build.mjs",
|
|
63
63
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
64
|
-
"test": "node scripts/test-client-wiring.mjs && node scripts/test-
|
|
64
|
+
"test": "node scripts/test-client-wiring.mjs && node scripts/test-chat-translate.mjs && node scripts/test-regression-suite.mjs && node scripts/test-channel-logic.mjs && node scripts/test-store.mjs && node scripts/test-reply-pipeline.mjs",
|
|
65
65
|
"assert:lib-untracked": "node scripts/assert-lib-untracked.mjs",
|
|
66
66
|
"check": "pnpm typecheck && pnpm build && pnpm test && pnpm assert:lib-untracked"
|
|
67
67
|
},
|
|
68
68
|
"engines": {
|
|
69
69
|
"node": "^22.19 || >=24",
|
|
70
|
-
"dsh": "0.1.7-rc.2"
|
|
70
|
+
"dsh": ">=0.1.7-rc.2"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@deepseek-ai/cordis": "^4.0.4",
|
|
74
|
-
"@deepseek-ai/dsh-client-connection": "0.1.7-rc.2",
|
|
75
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
|
|
76
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
|
|
77
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.2",
|
|
78
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2",
|
|
79
|
-
"@deepseek-ai/dsh-home-paths": "0.1.7-rc.2",
|
|
74
|
+
"@deepseek-ai/dsh-client-connection": ">=0.1.7-rc.2",
|
|
75
|
+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-rc.2",
|
|
76
|
+
"@deepseek-ai/dsh-client-ui-renderer": ">=0.1.7-rc.2",
|
|
77
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.2",
|
|
78
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-rc.2",
|
|
79
|
+
"@deepseek-ai/dsh-home-paths": ">=0.1.7-rc.2",
|
|
80
80
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
81
81
|
"@eslint/js": "^9.30.0",
|
|
82
82
|
"@types/node": "^22.19.0",
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
"typescript": "^6.0.0"
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
|
|
90
|
-
"@deepseek-ai/dsh-home-paths": "0.1.7-rc.2"
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-rc.2",
|
|
90
|
+
"@deepseek-ai/dsh-home-paths": ">=0.1.7-rc.2"
|
|
91
91
|
},
|
|
92
92
|
"peerDependenciesMeta": {
|
|
93
93
|
"@deepseek-ai/dsh-client-ui-primitives": {
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export declare class ClientCache {
|
|
2
|
-
private memCache;
|
|
3
|
-
private dirty;
|
|
4
|
-
private saveTimer;
|
|
5
|
-
private storageKey;
|
|
6
|
-
private maxEntries;
|
|
7
|
-
constructor(storageKey?: string, maxEntries?: number);
|
|
8
|
-
private load;
|
|
9
|
-
get(text: string): string | undefined;
|
|
10
|
-
set(text: string, translated: string): void;
|
|
11
|
-
private scheduleSave;
|
|
12
|
-
flushSync(): void;
|
|
13
|
-
clear(): void;
|
|
14
|
-
size(): number;
|
|
15
|
-
}
|
|
16
|
-
/** 正文译文缓存:本插件唯一的客户端缓存池。 */
|
|
17
|
-
export declare const clientCache: ClientCache;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
declare class LazyTranslationQueue {
|
|
2
|
-
private enabled;
|
|
3
|
-
private observer;
|
|
4
|
-
private pending;
|
|
5
|
-
setEnabled(enabled: boolean): void;
|
|
6
|
-
observe(body: HTMLElement, immediate?: boolean): void;
|
|
7
|
-
private intersectionObserver;
|
|
8
|
-
/**
|
|
9
|
-
* 进入视口后稍等一拍再翻,避开「刚出现、还在布局」的那一瞬。已经在等的那条
|
|
10
|
-
* 不重复排队。
|
|
11
|
-
*/
|
|
12
|
-
private scheduleTranslation;
|
|
13
|
-
disconnect(): void;
|
|
14
|
-
}
|
|
15
|
-
export declare const lazyQueue: LazyTranslationQueue;
|
|
16
|
-
export {};
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Non-destructive translation DOM mount mechanism.
|
|
3
|
-
*
|
|
4
|
-
* Preserves the original React Fiber tree, event listeners, and nested DOM nodes
|
|
5
|
-
* by wrapping them in a hidden container (<span class="dsh-tidy-original-hidden">)
|
|
6
|
-
* rather than destroying them with `element.textContent = translated`.
|
|
7
|
-
*
|
|
8
|
-
* Displays the translated text in a companion container (<span class="dsh-tidy-translated-block">).
|
|
9
|
-
* Clicking the translation switches that one block back to its original, and
|
|
10
|
-
* clicking the original switches it back to the translation.
|
|
11
|
-
*/
|
|
12
|
-
export declare const CLASS_ORIGINAL_HIDDEN = "dsh-tidy-original-hidden";
|
|
13
|
-
export declare const CLASS_ORIGINAL_SHOWN = "dsh-tidy-original-shown";
|
|
14
|
-
export declare const CLASS_TRANSLATED_BLOCK = "dsh-tidy-translated-block";
|
|
15
|
-
/** 混合块里的行内片段容器(我们自建、自拆)。 */
|
|
16
|
-
export declare const CLASS_RUN = "dsh-tidy-run";
|
|
17
|
-
export interface MountOptions {
|
|
18
|
-
originalText?: string;
|
|
19
|
-
interactive?: boolean;
|
|
20
|
-
}
|
|
21
|
-
export declare class NonDestructiveTranslationMount {
|
|
22
|
-
/**
|
|
23
|
-
* Mounts a translated string onto the target element non-destructively.
|
|
24
|
-
*/
|
|
25
|
-
static mount(element: HTMLElement, translated: string, options?: MountOptions): void;
|
|
26
|
-
/**
|
|
27
|
-
* 把一段连续的行内节点包进自建容器后挂载译文。
|
|
28
|
-
*
|
|
29
|
-
* 混合块(列表项文字 + 子列表 / 代码块)里的行内片段没有自己的元素,
|
|
30
|
-
* 只能先包一层再走同一条非侵入式挂载;嵌套的块级子节点留在容器之外,
|
|
31
|
-
* 排版原样保留。
|
|
32
|
-
* @returns 自建容器;节点不再相邻或没有共同父节点时返回 null。
|
|
33
|
-
*/
|
|
34
|
-
static mountRun(nodes: Node[], translated: string, options?: MountOptions): HTMLElement | null;
|
|
35
|
-
/** 还原行内片段并撤掉自建容器。 */
|
|
36
|
-
static unmountRun(run: HTMLElement): void;
|
|
37
|
-
/** 还原一个作用域内我们挂过的全部译文(元素单位与行内片段都算)。 */
|
|
38
|
-
static restore(scope: ParentNode): void;
|
|
39
|
-
/** 我们自己的挂载容器与还原容器,观察器必须跳过它们。 */
|
|
40
|
-
static isOwnNode(element: HTMLElement): boolean;
|
|
41
|
-
/**
|
|
42
|
-
* Unmounts translation and restores original DOM nodes completely.
|
|
43
|
-
*/
|
|
44
|
-
static unmount(element: HTMLElement): void;
|
|
45
|
-
/**
|
|
46
|
-
* Checks if an element has non-destructive translation mounted.
|
|
47
|
-
*/
|
|
48
|
-
static isMounted(element: HTMLElement): boolean;
|
|
49
|
-
/**
|
|
50
|
-
* Gets the original text recorded on the element or contained in origWrapper.
|
|
51
|
-
*/
|
|
52
|
-
static getOriginal(element: HTMLElement): string | undefined;
|
|
53
|
-
/**
|
|
54
|
-
* Extracts text content excluding our own translation wrappers.
|
|
55
|
-
*/
|
|
56
|
-
static extractVisibleText(element: HTMLElement): string;
|
|
57
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
export declare class ChatTranslateObserver {
|
|
2
|
-
private observer;
|
|
3
|
-
private rootElement;
|
|
4
|
-
private rootCheckTimer;
|
|
5
|
-
private isEnabled;
|
|
6
|
-
/**
|
|
7
|
-
* 已经交给翻译器的正文容器,避免同一条回答在每次 DOM 变动时重扫。总开关重开
|
|
8
|
-
* 时清空:关着的那段时间落定的回答需要补翻。
|
|
9
|
-
*/
|
|
10
|
-
private handled;
|
|
11
|
-
constructor();
|
|
12
|
-
setEnabled(enabled: boolean): void;
|
|
13
|
-
private restoreOriginals;
|
|
14
|
-
/**
|
|
15
|
-
* The active session's scroll container. Only the currently-viewed session
|
|
16
|
-
* is translated; switching sessions replaces this subtree and the observer
|
|
17
|
-
* naturally follows the new content.
|
|
18
|
-
*/
|
|
19
|
-
private isVisible;
|
|
20
|
-
private findRoot;
|
|
21
|
-
start(documentRef?: Document): () => void;
|
|
22
|
-
private scheduleRootCheck;
|
|
23
|
-
private restart;
|
|
24
|
-
private handleMutations;
|
|
25
|
-
/**
|
|
26
|
-
* 扫一棵子树,把里面**全部**该翻的正文容器交给翻译器。
|
|
27
|
-
*
|
|
28
|
-
* 不再「命中第一个就返回」:一个容器里可以有好几行 response(折叠块里每一步
|
|
29
|
-
* 露出的一段正文就是一行),只取第一个会把后面那些整片漏掉。
|
|
30
|
-
*/
|
|
31
|
-
private scanContainer;
|
|
32
|
-
/** 扫一个刚变动过的节点(含它所在的这一行,以及它内部的每一行)。 */
|
|
33
|
-
private scanNode;
|
|
34
|
-
/** 一行 flow item 里的**每一个**正文容器;工具行、Think 卡会被排除规则挡掉。 */
|
|
35
|
-
private tryRow;
|
|
36
|
-
/** 判定并交给翻译器:这个元素自己或它内部的每一条落定正文容器。 */
|
|
37
|
-
private tryBodies;
|
|
38
|
-
/** 判定并交给翻译器:这一个元素自己是不是一条该翻的正文容器。 */
|
|
39
|
-
private tryBody;
|
|
40
|
-
/**
|
|
41
|
-
* 这个元素自己是不是一条该翻的正文容器:落定的、落在过程折叠块里的 markdown
|
|
42
|
-
* 正文,且不被排除规则挡住(Think 卡、工具行、最终汇总都不算)。
|
|
43
|
-
*/
|
|
44
|
-
private isTranslatableBody;
|
|
45
|
-
/**
|
|
46
|
-
* 把一条落定的正文交给视口懒队列:视口内立刻翻、视口外的等滚到再翻,
|
|
47
|
-
* 命中缓存的由翻译器立即挂上。同一条回答只登记一次。
|
|
48
|
-
*/
|
|
49
|
-
private requestTranslate;
|
|
50
|
-
disconnect(): void;
|
|
51
|
-
}
|
|
52
|
-
export declare const chatTranslateObserver: ChatTranslateObserver;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/** 稳定的翻译单位:一块级元素,或一段行内节点。 */
|
|
2
|
-
export interface ReplyUnit {
|
|
3
|
-
element?: HTMLElement;
|
|
4
|
-
nodes?: Node[];
|
|
5
|
-
text: string;
|
|
6
|
-
anchor: Node;
|
|
7
|
-
}
|
|
8
|
-
/** 该单位是否需要翻译:含拉丁字母才送,纯中文块原样留着。 */
|
|
9
|
-
export declare function needsTranslation(text: string): boolean;
|
|
10
|
-
/** 收集正文里全部可翻译单位,跳过已挂译文的部分、代码块与纯中文块。 */
|
|
11
|
-
export declare function collectReplyUnits(body: HTMLElement): ReplyUnit[];
|
|
12
|
-
/** 按估算 token 把单位切成若干次客户端请求,顺序不变。 */
|
|
13
|
-
export declare function chunkUnits(units: ReplyUnit[], maxTokens?: number): ReplyUnit[][];
|
|
14
|
-
/**
|
|
15
|
-
* 一条回答正文的翻译控制器。观察器把落定的正文容器交给 {@link translateBody};
|
|
16
|
-
* 同一条回答的在途翻译只跑一次。
|
|
17
|
-
*/
|
|
18
|
-
declare class ReplyTranslateController {
|
|
19
|
-
/** 正文容器 → 在途 Promise,避免同一条回答被重复翻译。 */
|
|
20
|
-
private inFlight;
|
|
21
|
-
/**
|
|
22
|
-
* 翻译一条回答的正文容器。已命中缓存的单位立即挂上,其余按块请求;
|
|
23
|
-
* 失败的块保留原文(结果不入缓存,下次滚回视口会自然重试)。
|
|
24
|
-
* @param body - 正文容器(markdown body)。
|
|
25
|
-
* @returns 本次翻译完成后结算(已在途则返回同一次在途)。
|
|
26
|
-
*/
|
|
27
|
-
translateBody(body: HTMLElement): Promise<void>;
|
|
28
|
-
private run;
|
|
29
|
-
/**
|
|
30
|
-
* 逐块请求并挂载。失败的块保持原文:界面上不留提示,控制台留一条警告,结果
|
|
31
|
-
* 不进缓存,因此这一块在下次进入视口时会自然重试。
|
|
32
|
-
*/
|
|
33
|
-
private translateUnits;
|
|
34
|
-
/** 把译文挂到单位上;期间文本或节点已经变动的单位直接放弃(结果已进缓存)。 */
|
|
35
|
-
private applyUnit;
|
|
36
|
-
}
|
|
37
|
-
export declare const replyTranslator: ReplyTranslateController;
|
|
38
|
-
export {};
|