@geolonia/yuuhitsu 0.1.16 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/provider/claude.d.ts +7 -1
- package/dist/provider/claude.d.ts.map +1 -1
- package/dist/provider/claude.js +61 -1
- package/dist/provider/claude.js.map +1 -1
- package/dist/provider/interface.d.ts +27 -0
- package/dist/provider/interface.d.ts.map +1 -1
- package/dist/tasks/translate.d.ts +31 -38
- package/dist/tasks/translate.d.ts.map +1 -1
- package/dist/tasks/translate.js +318 -297
- package/dist/tasks/translate.js.map +1 -1
- package/package.json +9 -2
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import type { AIProvider, ChatRequest, ChatResponse, StreamChunk } from "./interface.js";
|
|
1
|
+
import type { AIProvider, ChatRequest, ChatResponse, StreamChunk, StructuredTranslateRequest, StructuredTranslateResponse } from "./interface.js";
|
|
2
2
|
export declare class ClaudeProvider implements AIProvider {
|
|
3
3
|
private client;
|
|
4
4
|
private model;
|
|
5
5
|
constructor(model: string);
|
|
6
6
|
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
7
7
|
chatStream(request: ChatRequest): AsyncIterable<StreamChunk>;
|
|
8
|
+
/**
|
|
9
|
+
* Translate segments using Anthropic tool_use (structured output).
|
|
10
|
+
* Forces Claude to return a JSON object matching the translation schema —
|
|
11
|
+
* no prose wrapping, no schema deviations.
|
|
12
|
+
*/
|
|
13
|
+
translateStructured(request: StructuredTranslateRequest): Promise<StructuredTranslateResponse>;
|
|
8
14
|
}
|
|
9
15
|
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/provider/claude.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/provider/claude.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AA2BxB,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAYnB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAiChD,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC;IA8BnE;;;;OAIG;IACG,mBAAmB,CACvB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,2BAA2B,CAAC;CA2CxC"}
|
package/dist/provider/claude.js
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
|
+
const TRANSLATION_TOOL_NAME = "record_translations";
|
|
3
|
+
const TRANSLATION_TOOL = {
|
|
4
|
+
name: TRANSLATION_TOOL_NAME,
|
|
5
|
+
description: "Record the translated text segments in structured JSON format",
|
|
6
|
+
input_schema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
translations: {
|
|
10
|
+
type: "array",
|
|
11
|
+
items: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {
|
|
14
|
+
id: { type: "integer", description: "Segment ID (must match input ID exactly)" },
|
|
15
|
+
text: { type: "string", description: "Translated text for this segment" },
|
|
16
|
+
},
|
|
17
|
+
required: ["id", "text"],
|
|
18
|
+
},
|
|
19
|
+
description: "Translated segments — one entry per input segment, ID must match",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
required: ["translations"],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
2
25
|
export class ClaudeProvider {
|
|
3
26
|
client;
|
|
4
27
|
model;
|
|
5
28
|
constructor(model) {
|
|
6
|
-
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
29
|
+
const apiKey = process.env.ANTHROPIC_API_KEY?.trim();
|
|
7
30
|
if (!apiKey) {
|
|
8
31
|
throw new Error("ANTHROPIC_API_KEY environment variable is not set. " +
|
|
9
32
|
"Get your API key at https://console.anthropic.com/settings/keys");
|
|
@@ -65,5 +88,42 @@ export class ClaudeProvider {
|
|
|
65
88
|
}
|
|
66
89
|
yield { content: "", done: true };
|
|
67
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Translate segments using Anthropic tool_use (structured output).
|
|
93
|
+
* Forces Claude to return a JSON object matching the translation schema —
|
|
94
|
+
* no prose wrapping, no schema deviations.
|
|
95
|
+
*/
|
|
96
|
+
async translateStructured(request) {
|
|
97
|
+
const response = await this.client.messages.create({
|
|
98
|
+
model: request.model || this.model,
|
|
99
|
+
max_tokens: request.maxTokens ?? 4096,
|
|
100
|
+
system: request.systemPrompt,
|
|
101
|
+
messages: [
|
|
102
|
+
{
|
|
103
|
+
role: "user",
|
|
104
|
+
content: JSON.stringify({ segments: request.segments }),
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
tools: [TRANSLATION_TOOL],
|
|
108
|
+
tool_choice: { type: "tool", name: TRANSLATION_TOOL_NAME },
|
|
109
|
+
});
|
|
110
|
+
const toolUseBlock = response.content.find((b) => b.type === "tool_use");
|
|
111
|
+
if (!toolUseBlock) {
|
|
112
|
+
throw new Error(`[yuuhitsu] ClaudeProvider.translateStructured: no tool_use block in response` +
|
|
113
|
+
` (stop_reason: ${response.stop_reason})`);
|
|
114
|
+
}
|
|
115
|
+
const input = toolUseBlock.input;
|
|
116
|
+
if (!Array.isArray(input.translations)) {
|
|
117
|
+
throw new Error(`[yuuhitsu] ClaudeProvider.translateStructured: translations field is missing or not an array`);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
translations: input.translations,
|
|
121
|
+
usage: {
|
|
122
|
+
promptTokens: response.usage.input_tokens,
|
|
123
|
+
completionTokens: response.usage.output_tokens,
|
|
124
|
+
totalTokens: response.usage.input_tokens + response.usage.output_tokens,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
68
128
|
}
|
|
69
129
|
//# sourceMappingURL=claude.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/provider/claude.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/provider/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,8 +23,35 @@ export interface StreamChunk {
|
|
|
23
23
|
content: string;
|
|
24
24
|
done: boolean;
|
|
25
25
|
}
|
|
26
|
+
/** Request for structured output translation (tool_use path). */
|
|
27
|
+
export interface StructuredTranslateRequest {
|
|
28
|
+
segments: Array<{
|
|
29
|
+
id: number;
|
|
30
|
+
text: string;
|
|
31
|
+
}>;
|
|
32
|
+
systemPrompt: string;
|
|
33
|
+
model?: string;
|
|
34
|
+
maxTokens?: number;
|
|
35
|
+
}
|
|
36
|
+
/** Response from structured output translation. */
|
|
37
|
+
export interface StructuredTranslateResponse {
|
|
38
|
+
translations: Array<{
|
|
39
|
+
id: number;
|
|
40
|
+
text: string;
|
|
41
|
+
}>;
|
|
42
|
+
usage: {
|
|
43
|
+
promptTokens: number;
|
|
44
|
+
completionTokens: number;
|
|
45
|
+
totalTokens: number;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
26
48
|
export interface AIProvider {
|
|
27
49
|
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
28
50
|
chatStream(request: ChatRequest): AsyncIterable<StreamChunk>;
|
|
51
|
+
/**
|
|
52
|
+
* Structured output translation via provider-native JSON schema enforcement.
|
|
53
|
+
* Optional: implemented by Claude. Gemini and Ollama fall back to text mode.
|
|
54
|
+
*/
|
|
55
|
+
translateStructured?(request: StructuredTranslateRequest): Promise<StructuredTranslateResponse>;
|
|
29
56
|
}
|
|
30
57
|
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/provider/interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/provider/interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,iEAAiE;AACjE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,mDAAmD;AACnD,MAAM,WAAW,2BAA2B;IAC1C,YAAY,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC7D;;;OAGG;IACH,mBAAmB,CAAC,CAClB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACzC"}
|
|
@@ -6,43 +6,10 @@ interface FrontmatterSeparation {
|
|
|
6
6
|
body: string;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Separate frontmatter from Markdown content
|
|
9
|
+
* Separate frontmatter from Markdown content.
|
|
10
10
|
* Handles: LF, CRLF, no trailing newline after closing ---, trailing spaces, empty frontmatter
|
|
11
|
-
* @param content - Full Markdown content
|
|
12
|
-
* @returns Object with separated frontmatter and body
|
|
13
11
|
*/
|
|
14
12
|
export declare function separateFrontmatter(content: string): FrontmatterSeparation;
|
|
15
|
-
interface CodeProtection {
|
|
16
|
-
text: string;
|
|
17
|
-
map: Map<string, string>;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Replace fenced code blocks and inline code with placeholders.
|
|
21
|
-
* Uses a line-by-line parser instead of regex to avoid V8 stack overflow
|
|
22
|
-
* on files with many code blocks (backreference + [\s\S]*? causes recursive backtracking).
|
|
23
|
-
*/
|
|
24
|
-
export declare function protectCodeBlocks(content: string): CodeProtection;
|
|
25
|
-
/**
|
|
26
|
-
* Restore placeholders back to original code blocks/inline code.
|
|
27
|
-
*/
|
|
28
|
-
export declare function restoreCodeBlocks(content: string, map: Map<string, string>): string;
|
|
29
|
-
export declare const BLOCK_BOUNDARY_SENTINEL = "<!--BB-->";
|
|
30
|
-
/**
|
|
31
|
-
* Insert block boundary sentinels before structural Markdown elements
|
|
32
|
-
* (list items, headings, horizontal rules, code fences, code block placeholders).
|
|
33
|
-
* P-A4: prevents newline collapse around structural boundaries during LLM translation.
|
|
34
|
-
* When called after protectCodeBlocks, fenced blocks appear as __CODE_BLOCK_N__ placeholders;
|
|
35
|
-
* the function treats those placeholders as structural to protect fence-adjacent newlines.
|
|
36
|
-
*/
|
|
37
|
-
export declare function protectBlockBoundaries(content: string): string;
|
|
38
|
-
/**
|
|
39
|
-
* Remove block boundary sentinels and restore newlines lost during LLM translation.
|
|
40
|
-
* Uses a 3-pass strategy:
|
|
41
|
-
* Pass 1: normalize LLM-deformed variants (e.g. <!-- BB -->) to exact sentinel form
|
|
42
|
-
* Pass 2: split + restore newlines (handles both clean and collapsed sentinel cases)
|
|
43
|
-
* Pass 3: post-restore warning for residual sentinel-like patterns (silent failure prevention)
|
|
44
|
-
*/
|
|
45
|
-
export declare function restoreBlockBoundaries(content: string): string;
|
|
46
13
|
export interface TranslateOptions {
|
|
47
14
|
provider: AIProvider;
|
|
48
15
|
inputPath: string;
|
|
@@ -67,8 +34,8 @@ export interface TranslateResult {
|
|
|
67
34
|
*/
|
|
68
35
|
export declare function findHeadingPositions(lines: string[], level: number): number[];
|
|
69
36
|
/**
|
|
70
|
-
* Split lines at the given positions into chunks
|
|
71
|
-
*
|
|
37
|
+
* Split lines at the given positions into chunks. Segments exceeding maxChunkLines
|
|
38
|
+
* are further split using ### headings or safeSplitLines.
|
|
72
39
|
*/
|
|
73
40
|
export declare function splitAtPositions(lines: string[], positions: number[], maxChunkLines: number): string[];
|
|
74
41
|
/**
|
|
@@ -77,8 +44,7 @@ export declare function splitAtPositions(lines: string[], positions: number[], m
|
|
|
77
44
|
*/
|
|
78
45
|
export declare function safeSplitLines(lines: string[], maxChunkLines: number): string[];
|
|
79
46
|
/**
|
|
80
|
-
* Merge chunks smaller than MIN_CHUNK_LINES into the previous chunk
|
|
81
|
-
* as long as the merged result does not exceed maxLines.
|
|
47
|
+
* Merge chunks smaller than MIN_CHUNK_LINES into the previous chunk.
|
|
82
48
|
*/
|
|
83
49
|
export declare function mergeSmallChunks(chunks: string[], maxLines: number): string[];
|
|
84
50
|
/**
|
|
@@ -86,6 +52,33 @@ export declare function mergeSmallChunks(chunks: string[], maxLines: number): st
|
|
|
86
52
|
* Falls back to safe line-count splitting when no headings are present.
|
|
87
53
|
*/
|
|
88
54
|
export declare function splitIntoChunks(content: string, maxChunkLines?: number): string[];
|
|
55
|
+
interface CodeProtection {
|
|
56
|
+
text: string;
|
|
57
|
+
map: Map<string, string>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Replace fenced code blocks and inline code with placeholders.
|
|
61
|
+
* Used by glossary-fix.ts to protect code blocks before text replacement.
|
|
62
|
+
*/
|
|
63
|
+
export declare function protectCodeBlocks(content: string): CodeProtection;
|
|
64
|
+
/**
|
|
65
|
+
* Restore placeholders back to original code blocks/inline code.
|
|
66
|
+
*/
|
|
67
|
+
export declare function restoreCodeBlocks(content: string, map: Map<string, string>): string;
|
|
68
|
+
/**
|
|
69
|
+
* Translate a Markdown file using AST-based approach.
|
|
70
|
+
*
|
|
71
|
+
* Architecture (0.2.0):
|
|
72
|
+
* 1. Separate frontmatter (preserved verbatim)
|
|
73
|
+
* 2. Split body into chunks by heading boundaries
|
|
74
|
+
* 3. For each chunk: parse to AST → extract text nodes → translate via LLM → write back
|
|
75
|
+
* 4. Serialize AST → markdown → concatenate → write output
|
|
76
|
+
*
|
|
77
|
+
* Key properties:
|
|
78
|
+
* - Code blocks (fenced and inline) are never sent to LLM (AST handles them deterministically)
|
|
79
|
+
* - Markdown structure (headings, lists, tables, HR) is preserved by AST round-trip
|
|
80
|
+
* - No sentinel injection or removal needed
|
|
81
|
+
*/
|
|
89
82
|
export declare function translateFile(options: TranslateOptions): Promise<TranslateResult>;
|
|
90
83
|
export {};
|
|
91
84
|
//# sourceMappingURL=translate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAM3C,UAAU,qBAAqB;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAa1E;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAa7E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,MAAM,EAAE,EACnB,aAAa,EAAE,MAAM,GACpB,MAAM,EAAE,CAyBV;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAyB/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB7E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,aAAa,SAA0B,GACtC,MAAM,EAAE,CAcV;AAMD,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CA8CjE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAYnF;AAkRD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CA+E1B"}
|
package/dist/tasks/translate.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
2
|
import { dirname, basename, extname, join } from "path";
|
|
3
|
+
import { remark } from "remark";
|
|
4
|
+
import remarkGfm from "remark-gfm";
|
|
5
|
+
import { visit } from "unist-util-visit";
|
|
3
6
|
import { buildGlossaryPrompt } from "./glossary.js";
|
|
4
7
|
export const DEFAULT_MAX_CHUNK_LINES = 300;
|
|
5
8
|
const MIN_CHUNK_LINES = 50;
|
|
9
|
+
// P-A1: minimum ratio of output characters to input characters (truncation check)
|
|
10
|
+
const MIN_OUTPUT_RATIO = 0.3;
|
|
6
11
|
/**
|
|
7
|
-
* Separate frontmatter from Markdown content
|
|
12
|
+
* Separate frontmatter from Markdown content.
|
|
8
13
|
* Handles: LF, CRLF, no trailing newline after closing ---, trailing spaces, empty frontmatter
|
|
9
|
-
* @param content - Full Markdown content
|
|
10
|
-
* @returns Object with separated frontmatter and body
|
|
11
14
|
*/
|
|
12
15
|
export function separateFrontmatter(content) {
|
|
13
|
-
// Normalize CRLF to LF for regex matching
|
|
14
16
|
const normalized = content.replace(/\r\n/g, "\n");
|
|
15
|
-
// Match frontmatter (two alternations to keep closing --- on its own line):
|
|
16
|
-
// Case 1: non-empty body: ^---\n ... \n---[ \t]*(\n|$)
|
|
17
|
-
// Case 2: empty body: ^---\n---[ \t]*(\n|$)
|
|
18
|
-
// Using alternation avoids the \n? ambiguity that allows --- to match mid-line.
|
|
19
17
|
const frontmatterRegex = /^---\n([\s\S]*?)\n---[ \t]*(\n|$)|^---\n---[ \t]*(\n|$)/;
|
|
20
18
|
const match = normalized.match(frontmatterRegex);
|
|
21
19
|
if (match) {
|
|
@@ -26,253 +24,7 @@ export function separateFrontmatter(content) {
|
|
|
26
24
|
}
|
|
27
25
|
return { frontmatter: null, body: normalized };
|
|
28
26
|
}
|
|
29
|
-
|
|
30
|
-
* Replace fenced code blocks and inline code with placeholders.
|
|
31
|
-
* Uses a line-by-line parser instead of regex to avoid V8 stack overflow
|
|
32
|
-
* on files with many code blocks (backreference + [\s\S]*? causes recursive backtracking).
|
|
33
|
-
*/
|
|
34
|
-
export function protectCodeBlocks(content) {
|
|
35
|
-
const map = new Map();
|
|
36
|
-
let blockIndex = 0;
|
|
37
|
-
let inlineIndex = 0;
|
|
38
|
-
// Step 1: Replace fenced code blocks using line-by-line parsing
|
|
39
|
-
const lines = content.split("\n");
|
|
40
|
-
const resultLines = [];
|
|
41
|
-
let fenceOpen = null; // the backtick sequence that opened the current block
|
|
42
|
-
let blockLines = [];
|
|
43
|
-
for (const line of lines) {
|
|
44
|
-
const fenceMatch = line.match(/^(`{3,})/);
|
|
45
|
-
if (fenceOpen === null) {
|
|
46
|
-
// Not inside a code block
|
|
47
|
-
if (fenceMatch) {
|
|
48
|
-
// Opening fence found
|
|
49
|
-
fenceOpen = fenceMatch[1];
|
|
50
|
-
blockLines = [line];
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
resultLines.push(line);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
// Inside a code block — look for closing fence with same or more backticks
|
|
58
|
-
blockLines.push(line);
|
|
59
|
-
if (fenceMatch && fenceMatch[1].length >= fenceOpen.length && line.trim() === fenceMatch[1]) {
|
|
60
|
-
// Closing fence found — store as single-line placeholder (no padding).
|
|
61
|
-
// Padding was previously used to preserve line count, but it caused chunk
|
|
62
|
-
// boundaries to fall inside the placeholder's whitespace region, leading to
|
|
63
|
-
// non-deterministic LLM output when the code block exceeded --max-chunk-lines.
|
|
64
|
-
const original = blockLines.join("\n") + "\n";
|
|
65
|
-
const placeholder = `__CODE_BLOCK_${blockIndex++}__`;
|
|
66
|
-
map.set(placeholder, original);
|
|
67
|
-
resultLines.push(placeholder);
|
|
68
|
-
fenceOpen = null;
|
|
69
|
-
blockLines = [];
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// If we ended inside an unclosed fence, emit lines as-is
|
|
74
|
-
if (fenceOpen !== null) {
|
|
75
|
-
resultLines.push(...blockLines);
|
|
76
|
-
}
|
|
77
|
-
let result = resultLines.join("\n");
|
|
78
|
-
// Step 2: Replace inline code (single backtick, not within code blocks)
|
|
79
|
-
result = result.replace(/`([^`\n]+)`/g, (match) => {
|
|
80
|
-
const placeholder = `__INLINE_CODE_${inlineIndex++}__`;
|
|
81
|
-
map.set(placeholder, match);
|
|
82
|
-
return placeholder;
|
|
83
|
-
});
|
|
84
|
-
return { text: result, map };
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Restore placeholders back to original code blocks/inline code.
|
|
88
|
-
*/
|
|
89
|
-
export function restoreCodeBlocks(content, map) {
|
|
90
|
-
let result = content;
|
|
91
|
-
// Restore fenced code blocks (may have trailing newline added by protect)
|
|
92
|
-
for (const [placeholder, original] of map.entries()) {
|
|
93
|
-
// The placeholder may appear with or without trailing newline
|
|
94
|
-
result = result.split(placeholder + "\n").join(original);
|
|
95
|
-
result = result.split(placeholder).join(original);
|
|
96
|
-
}
|
|
97
|
-
return result;
|
|
98
|
-
}
|
|
99
|
-
export const BLOCK_BOUNDARY_SENTINEL = "<!--BB-->";
|
|
100
|
-
// Temporary escape for pre-existing <!--BB--> literals in user content.
|
|
101
|
-
// Uses a character sequence unlikely to appear in markdown documents.
|
|
102
|
-
const ESCAPED_SENTINEL = "\x01BB\x01";
|
|
103
|
-
// Fallback regex: catches LLM-deformed variants (e.g. <!-- BB -->, <!--BB__-->, <!--BBx-->)
|
|
104
|
-
const SENTINEL_FALLBACK = /<!--\s*BB[a-zA-Z0-9_-]*\s*-->/g;
|
|
105
|
-
// Broad check: detects severely-deformed residuals not caught by SENTINEL_FALLBACK
|
|
106
|
-
const SENTINEL_RESIDUAL_CHECK = /<!--[\s\S]*?BB[\s\S]*?-->/g;
|
|
107
|
-
/**
|
|
108
|
-
* Insert block boundary sentinels before structural Markdown elements
|
|
109
|
-
* (list items, headings, horizontal rules, code fences, code block placeholders).
|
|
110
|
-
* P-A4: prevents newline collapse around structural boundaries during LLM translation.
|
|
111
|
-
* When called after protectCodeBlocks, fenced blocks appear as __CODE_BLOCK_N__ placeholders;
|
|
112
|
-
* the function treats those placeholders as structural to protect fence-adjacent newlines.
|
|
113
|
-
*/
|
|
114
|
-
export function protectBlockBoundaries(content) {
|
|
115
|
-
// Escape all sentinel-like patterns (exact + variants) to prevent control-marker confusion.
|
|
116
|
-
// SENTINEL_FALLBACK covers <!--BB-->, <!-- BB -->, <!--BBx-->, <!--BB-x-->, etc.
|
|
117
|
-
// On restore, these all round-trip back to <!--BB--> (minor cosmetic vs. content deletion).
|
|
118
|
-
const escaped = content.replace(SENTINEL_FALLBACK, ESCAPED_SENTINEL);
|
|
119
|
-
const lines = escaped.split("\n");
|
|
120
|
-
const result = [];
|
|
121
|
-
for (const line of lines) {
|
|
122
|
-
const isStructural = /^\s*[-*+]\s/.test(line) || // unordered list
|
|
123
|
-
/^\s*\d+\.\s/.test(line) || // ordered list
|
|
124
|
-
/^ {0,3}#{1,6}\s/.test(line) || // heading (CommonMark: 0-3 leading spaces)
|
|
125
|
-
/^ {0,3}-{3,}\s*$/.test(line) || // hr (dash, 0-3 leading spaces)
|
|
126
|
-
/^ {0,3}\*{3,}\s*$/.test(line) || // hr (asterisk, 0-3 leading spaces)
|
|
127
|
-
/^ {0,3}_{3,}\s*$/.test(line) || // hr (underscore, 0-3 leading spaces)
|
|
128
|
-
/^\s*`{3,}/.test(line) || // fenced code (backtick)
|
|
129
|
-
/^\s*~{3,}/.test(line) || // fenced code (tilde)
|
|
130
|
-
/^__CODE_BLOCK_\d+__$/.test(line.trim()); // code block placeholder (after protectCodeBlocks)
|
|
131
|
-
if (isStructural) {
|
|
132
|
-
result.push(BLOCK_BOUNDARY_SENTINEL);
|
|
133
|
-
}
|
|
134
|
-
result.push(line);
|
|
135
|
-
}
|
|
136
|
-
return result.join("\n");
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Remove block boundary sentinels and restore newlines lost during LLM translation.
|
|
140
|
-
* Uses a 3-pass strategy:
|
|
141
|
-
* Pass 1: normalize LLM-deformed variants (e.g. <!-- BB -->) to exact sentinel form
|
|
142
|
-
* Pass 2: split + restore newlines (handles both clean and collapsed sentinel cases)
|
|
143
|
-
* Pass 3: post-restore warning for residual sentinel-like patterns (silent failure prevention)
|
|
144
|
-
*/
|
|
145
|
-
export function restoreBlockBoundaries(content) {
|
|
146
|
-
// Pass 1: normalize variant sentinels introduced by LLM deformation (cmd_389 Root Cause A/B)
|
|
147
|
-
const normalized = content.replace(SENTINEL_FALLBACK, BLOCK_BOUNDARY_SENTINEL);
|
|
148
|
-
// Pass 2: split + restore newlines
|
|
149
|
-
if (!normalized.includes(BLOCK_BOUNDARY_SENTINEL)) {
|
|
150
|
-
// Still unescape any escaped sentinels from original content
|
|
151
|
-
return normalized.includes(ESCAPED_SENTINEL)
|
|
152
|
-
? normalized.split(ESCAPED_SENTINEL).join(BLOCK_BOUNDARY_SENTINEL)
|
|
153
|
-
: normalized;
|
|
154
|
-
}
|
|
155
|
-
const parts = normalized.split(BLOCK_BOUNDARY_SENTINEL);
|
|
156
|
-
let restored = parts[0];
|
|
157
|
-
for (let i = 1; i < parts.length; i++) {
|
|
158
|
-
// Strip a leading newline from next part (present when LLM preserved sentinel on its own line)
|
|
159
|
-
const stripped = parts[i].replace(/^\n/, "");
|
|
160
|
-
if (restored.length === 0) {
|
|
161
|
-
// Sentinel was at the very start of content — no preceding text to separate from
|
|
162
|
-
restored = stripped;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
// Ensure restored ends with exactly one newline before appending next part
|
|
166
|
-
restored = restored.replace(/\n?$/, "\n") + stripped;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
// Pass 3: post-restore warning for patterns not caught by SENTINEL_FALLBACK
|
|
170
|
-
// Check before unescaping to avoid false positives from user-content <!--BB-->
|
|
171
|
-
const residuals = restored.match(SENTINEL_RESIDUAL_CHECK);
|
|
172
|
-
if (residuals && residuals.length > 0) {
|
|
173
|
-
console.warn(`[yuuhitsu] restoreBlockBoundaries: ${residuals.length} residual sentinel-like pattern(s) detected after restore:`, residuals.slice(0, 5));
|
|
174
|
-
}
|
|
175
|
-
// Unescape any pre-existing <!--BB--> that were escaped before protection
|
|
176
|
-
if (restored.includes(ESCAPED_SENTINEL)) {
|
|
177
|
-
restored = restored.split(ESCAPED_SENTINEL).join(BLOCK_BOUNDARY_SENTINEL);
|
|
178
|
-
}
|
|
179
|
-
return restored;
|
|
180
|
-
}
|
|
181
|
-
const DEFAULT_TEMPLATE = `You are a professional translator. Translate the following Markdown document to {{targetLanguage}}.
|
|
182
|
-
|
|
183
|
-
Rules:
|
|
184
|
-
- Preserve all Markdown formatting (headings, links, code blocks, tables, lists)
|
|
185
|
-
- Do not translate code blocks, URLs, or file paths
|
|
186
|
-
- Do not translate frontmatter keys (only translate values where appropriate)
|
|
187
|
-
- Maintain the same document structure
|
|
188
|
-
- Produce natural, fluent text in the target language
|
|
189
|
-
- Every opening \`\`\` you write MUST be followed by a language identifier on the same line (e.g., \`\`\`json, \`\`\`bash, \`\`\`typescript)
|
|
190
|
-
- If the language is unknown, use \`\`\`text — never emit a bare opening \`\`\`
|
|
191
|
-
|
|
192
|
-
CRITICAL - Link and URL preservation:
|
|
193
|
-
- NEVER modify any URLs or link paths. Keep all href/src values exactly as-is.
|
|
194
|
-
- NEVER change internal link paths (e.g., /ja/..., /en/..., ./relative-path). Preserve them verbatim.
|
|
195
|
-
- NEVER convert external URLs to different language versions.
|
|
196
|
-
- If the source has [text](/ja/changelog), the output must keep the same path, only translate the link text if needed.
|
|
197
|
-
- Example: [紹介](/ja/intro) → translate "紹介" but keep "/ja/intro" unchanged
|
|
198
|
-
- Example: [MDN](https://developer.mozilla.org/ja/) → keep the /ja/ in URL, translate "MDN" if needed
|
|
199
|
-
|
|
200
|
-
Additional rules for Japanese translation:
|
|
201
|
-
- Use full-width punctuation: 。、?! (not .,?!)
|
|
202
|
-
- Add half-width spaces around English words and numbers (e.g., "Vela とは", "NGSIv2 は", "3 つの")
|
|
203
|
-
- Use natural Japanese terms for technical words where appropriate (e.g., "registration" → "登録", "subscription" → "サブスクリプション")
|
|
204
|
-
- Keep product names, proper nouns, and abbreviations unchanged (e.g., Vela, FIWARE, NGSIv2, NGSI-LD, MCP)
|
|
205
|
-
|
|
206
|
-
Example — code fence with language identifier:
|
|
207
|
-
Bad: \`\`\` echo hello \`\`\`
|
|
208
|
-
Good: \`\`\`bash echo hello \`\`\``;
|
|
209
|
-
function buildPrompt(content, targetLang, hasPlaceholders, hasSentinels, templateContent, glossaryConfig) {
|
|
210
|
-
const template = templateContent || DEFAULT_TEMPLATE;
|
|
211
|
-
let systemPrompt = template
|
|
212
|
-
.replace(/\{\{targetLanguage\}\}/g, targetLang)
|
|
213
|
-
.replace(/\{\{content\}\}/g, "");
|
|
214
|
-
if (glossaryConfig) {
|
|
215
|
-
const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
|
|
216
|
-
if (glossarySection) {
|
|
217
|
-
systemPrompt += glossarySection;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (hasSentinels) {
|
|
221
|
-
systemPrompt +=
|
|
222
|
-
"\n\n## Block boundary markers (P-A4 v2)\n\n" +
|
|
223
|
-
"Lines containing the marker `<!--BB-->` are **block boundary markers** inserted\n" +
|
|
224
|
-
"by the translation pipeline to preserve newlines around structural elements.\n\n" +
|
|
225
|
-
"Rules for `<!--BB-->` markers (HTML comment form):\n" +
|
|
226
|
-
"- Output every `<!--BB-->` marker **verbatim and unchanged** in your translation.\n" +
|
|
227
|
-
"- Each marker must remain on its own line, in the same position relative to\n" +
|
|
228
|
-
" surrounding content.\n" +
|
|
229
|
-
"- Do not translate, remove, paraphrase, modify, normalize whitespace inside, or\n" +
|
|
230
|
-
" rename these markers.\n" +
|
|
231
|
-
"- Do not add new `<!--BB-->` markers; only preserve existing ones.\n\n" +
|
|
232
|
-
"Good example (correct preservation):\n" +
|
|
233
|
-
" Input:\n" +
|
|
234
|
-
" <!--BB-->\n" +
|
|
235
|
-
" - List item one\n" +
|
|
236
|
-
" <!--BB-->\n" +
|
|
237
|
-
" - List item two\n" +
|
|
238
|
-
" <!--BB-->\n" +
|
|
239
|
-
" ## Section heading\n" +
|
|
240
|
-
" Output:\n" +
|
|
241
|
-
" <!--BB-->\n" +
|
|
242
|
-
" - リスト項目その一\n" +
|
|
243
|
-
" <!--BB-->\n" +
|
|
244
|
-
" - リスト項目その二\n" +
|
|
245
|
-
" <!--BB-->\n" +
|
|
246
|
-
" ## セクション見出し\n\n" +
|
|
247
|
-
"Bad examples (DO NOT do these):\n" +
|
|
248
|
-
" - <!--BB--> ❌ → <!--BB__--> (added suffix — FORBIDDEN)\n" +
|
|
249
|
-
" - <!--BB--> ❌ → <!-- BB --> (added internal whitespace — FORBIDDEN)\n" +
|
|
250
|
-
" - <!--BB--> ❌ → <!--bb--> (case change — FORBIDDEN)\n" +
|
|
251
|
-
" - <!--BB--> ❌ → (omitted) (deleted — FORBIDDEN)\n" +
|
|
252
|
-
" - <!--BB--> ❌ → <!--BB-x--> (added suffix — FORBIDDEN)\n\n" +
|
|
253
|
-
"Preserve the marker exactly: 9 characters, opening `<!--`, content `BB`,\n" +
|
|
254
|
-
"closing `-->`, no whitespace, no case changes, no suffixes.";
|
|
255
|
-
}
|
|
256
|
-
if (hasPlaceholders) {
|
|
257
|
-
systemPrompt +=
|
|
258
|
-
"\n\nIMPORTANT - Placeholder preservation:\n" +
|
|
259
|
-
"- Tokens matching __CODE_BLOCK_N__ or __INLINE_CODE_N__ are placeholders for code blocks/inline code.\n" +
|
|
260
|
-
"- Output them VERBATIM and UNCHANGED. Do NOT translate, modify, or remove them.\n" +
|
|
261
|
-
"- Example: if input has __CODE_BLOCK_0__, output must contain __CODE_BLOCK_0__ exactly.";
|
|
262
|
-
}
|
|
263
|
-
return [
|
|
264
|
-
{ role: "system", content: systemPrompt },
|
|
265
|
-
{ role: "user", content },
|
|
266
|
-
];
|
|
267
|
-
}
|
|
268
|
-
function resolveOutputPath(inputPath, targetLang, outputPath) {
|
|
269
|
-
if (outputPath)
|
|
270
|
-
return outputPath;
|
|
271
|
-
const dir = dirname(inputPath);
|
|
272
|
-
const ext = extname(inputPath);
|
|
273
|
-
const base = basename(inputPath, ext);
|
|
274
|
-
return join(dir, `${base}.${targetLang}${ext}`);
|
|
275
|
-
}
|
|
27
|
+
// ─── Chunking utilities (kept for splitIntoChunks export) ───────────────────
|
|
276
28
|
/**
|
|
277
29
|
* Find positions (line indices) of Markdown headings at the given level,
|
|
278
30
|
* excluding lines inside fenced code blocks or table rows.
|
|
@@ -283,7 +35,7 @@ export function findHeadingPositions(lines, level) {
|
|
|
283
35
|
const prefix = "#".repeat(level) + " ";
|
|
284
36
|
for (let i = 0; i < lines.length; i++) {
|
|
285
37
|
const line = lines[i];
|
|
286
|
-
if (
|
|
38
|
+
if (/^(`{3,}|~{3,})/.test(line))
|
|
287
39
|
inCodeBlock = !inCodeBlock;
|
|
288
40
|
if (inCodeBlock)
|
|
289
41
|
continue;
|
|
@@ -295,8 +47,8 @@ export function findHeadingPositions(lines, level) {
|
|
|
295
47
|
return positions;
|
|
296
48
|
}
|
|
297
49
|
/**
|
|
298
|
-
* Split lines at the given positions into chunks
|
|
299
|
-
*
|
|
50
|
+
* Split lines at the given positions into chunks. Segments exceeding maxChunkLines
|
|
51
|
+
* are further split using ### headings or safeSplitLines.
|
|
300
52
|
*/
|
|
301
53
|
export function splitAtPositions(lines, positions, maxChunkLines) {
|
|
302
54
|
const result = [];
|
|
@@ -311,8 +63,6 @@ export function splitAtPositions(lines, positions, maxChunkLines) {
|
|
|
311
63
|
continue;
|
|
312
64
|
if (segmentLines.length > maxChunkLines) {
|
|
313
65
|
const subPositions = findHeadingPositions(segmentLines, 3);
|
|
314
|
-
// Filter out position 0: splitting at the start doesn't reduce segment size
|
|
315
|
-
// and causes infinite recursion when the only heading is at position 0.
|
|
316
66
|
const effectivePositions = subPositions.filter((p) => p > 0);
|
|
317
67
|
if (effectivePositions.length > 0) {
|
|
318
68
|
result.push(...splitAtPositions(segmentLines, effectivePositions, maxChunkLines));
|
|
@@ -337,12 +87,8 @@ export function safeSplitLines(lines, maxChunkLines) {
|
|
|
337
87
|
let inCodeBlock = false;
|
|
338
88
|
for (let i = 0; i < lines.length; i++) {
|
|
339
89
|
const line = lines[i];
|
|
340
|
-
const isFence =
|
|
90
|
+
const isFence = /^(`{3,}|~{3,})/.test(line);
|
|
341
91
|
const isTableLine = line.startsWith("|");
|
|
342
|
-
// Check split eligibility BEFORE toggling fence state:
|
|
343
|
-
// - never split inside a code block
|
|
344
|
-
// - never split ON a fence line (would separate opening/closing ``` from their block)
|
|
345
|
-
// - never split ON a table row
|
|
346
92
|
const canSplitHere = !inCodeBlock && !isFence && !isTableLine;
|
|
347
93
|
if (isFence)
|
|
348
94
|
inCodeBlock = !inCodeBlock;
|
|
@@ -357,8 +103,7 @@ export function safeSplitLines(lines, maxChunkLines) {
|
|
|
357
103
|
return chunks.filter((c) => c.trim().length > 0);
|
|
358
104
|
}
|
|
359
105
|
/**
|
|
360
|
-
* Merge chunks smaller than MIN_CHUNK_LINES into the previous chunk
|
|
361
|
-
* as long as the merged result does not exceed maxLines.
|
|
106
|
+
* Merge chunks smaller than MIN_CHUNK_LINES into the previous chunk.
|
|
362
107
|
*/
|
|
363
108
|
export function mergeSmallChunks(chunks, maxLines) {
|
|
364
109
|
if (chunks.length <= 1)
|
|
@@ -394,9 +139,290 @@ export function splitIntoChunks(content, maxChunkLines = DEFAULT_MAX_CHUNK_LINES
|
|
|
394
139
|
}
|
|
395
140
|
return safeSplitLines(lines, maxChunkLines);
|
|
396
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Replace fenced code blocks and inline code with placeholders.
|
|
144
|
+
* Used by glossary-fix.ts to protect code blocks before text replacement.
|
|
145
|
+
*/
|
|
146
|
+
export function protectCodeBlocks(content) {
|
|
147
|
+
const map = new Map();
|
|
148
|
+
let blockIndex = 0;
|
|
149
|
+
let inlineIndex = 0;
|
|
150
|
+
const lines = content.split("\n");
|
|
151
|
+
const resultLines = [];
|
|
152
|
+
let fenceOpen = null;
|
|
153
|
+
let blockLines = [];
|
|
154
|
+
for (const line of lines) {
|
|
155
|
+
const fenceMatch = line.match(/^(`{3,})/);
|
|
156
|
+
if (fenceOpen === null) {
|
|
157
|
+
if (fenceMatch) {
|
|
158
|
+
fenceOpen = fenceMatch[1];
|
|
159
|
+
blockLines = [line];
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
resultLines.push(line);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
blockLines.push(line);
|
|
167
|
+
if (fenceMatch && fenceMatch[1].length >= fenceOpen.length && line.trim() === fenceMatch[1]) {
|
|
168
|
+
const original = blockLines.join("\n") + "\n";
|
|
169
|
+
const placeholder = `__CODE_BLOCK_${blockIndex++}__`;
|
|
170
|
+
map.set(placeholder, original);
|
|
171
|
+
resultLines.push(placeholder);
|
|
172
|
+
fenceOpen = null;
|
|
173
|
+
blockLines = [];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (fenceOpen !== null) {
|
|
178
|
+
resultLines.push(...blockLines);
|
|
179
|
+
}
|
|
180
|
+
let result = resultLines.join("\n");
|
|
181
|
+
result = result.replace(/`([^`\n]+)`/g, (match) => {
|
|
182
|
+
const placeholder = `__INLINE_CODE_${inlineIndex++}__`;
|
|
183
|
+
map.set(placeholder, match);
|
|
184
|
+
return placeholder;
|
|
185
|
+
});
|
|
186
|
+
return { text: result, map };
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Restore placeholders back to original code blocks/inline code.
|
|
190
|
+
*/
|
|
191
|
+
export function restoreCodeBlocks(content, map) {
|
|
192
|
+
let result = content;
|
|
193
|
+
for (const [placeholder, original] of map.entries()) {
|
|
194
|
+
if (original.endsWith("\n")) {
|
|
195
|
+
result = result.split(placeholder + "\n").join(original);
|
|
196
|
+
result = result.split(placeholder).join(original);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
result = result.split(placeholder + "\n").join(original + "\n");
|
|
200
|
+
result = result.split(placeholder).join(original);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Extract all translatable text nodes from an mdast AST.
|
|
207
|
+
* remark AST guarantees text nodes cannot be inside code/inlineCode nodes,
|
|
208
|
+
* so we only skip empty/whitespace-only nodes.
|
|
209
|
+
*/
|
|
210
|
+
function extractTextNodes(ast) {
|
|
211
|
+
const nodes = [];
|
|
212
|
+
visit(ast, "text", (node) => {
|
|
213
|
+
if (!node.value.trim())
|
|
214
|
+
return;
|
|
215
|
+
nodes.push({ node, id: nodes.length });
|
|
216
|
+
});
|
|
217
|
+
return nodes;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Build system prompt for text-mode batch translation (Gemini / Ollama fallback).
|
|
221
|
+
* Includes JSON format instructions since we're relying on the LLM to output JSON.
|
|
222
|
+
*/
|
|
223
|
+
function buildBatchSystemPrompt(targetLang, templateContent, glossaryConfig) {
|
|
224
|
+
const basePrompt = templateContent
|
|
225
|
+
? templateContent.replace(/\{\{targetLanguage\}\}/g, targetLang)
|
|
226
|
+
: `You are a professional translator. Translate text segments to ${targetLang}.
|
|
227
|
+
|
|
228
|
+
Rules:
|
|
229
|
+
- Translate only the text content; do not add or remove punctuation structure
|
|
230
|
+
- Preserve proper nouns, code identifiers, URLs, and file paths unchanged
|
|
231
|
+
- Produce natural, fluent text in the target language
|
|
232
|
+
- For Japanese: use full-width punctuation (。、?!), add half-width spaces around English words/numbers
|
|
233
|
+
- Keep product names, abbreviations, and technical terms unchanged (e.g., NGSI-LD, MCP, GeoJSON)`;
|
|
234
|
+
let prompt = basePrompt;
|
|
235
|
+
if (glossaryConfig) {
|
|
236
|
+
const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
|
|
237
|
+
if (glossarySection)
|
|
238
|
+
prompt += glossarySection;
|
|
239
|
+
}
|
|
240
|
+
prompt += `
|
|
241
|
+
|
|
242
|
+
## Translation format
|
|
243
|
+
|
|
244
|
+
You will receive a JSON object with a "segments" array.
|
|
245
|
+
Each segment has an "id" (integer) and "text" (string to translate).
|
|
246
|
+
|
|
247
|
+
Return ONLY a valid JSON object with a "translations" array.
|
|
248
|
+
Each translation must have the same "id" and the translated "text".
|
|
249
|
+
Do not include any explanation, markdown, or text outside the JSON object.
|
|
250
|
+
|
|
251
|
+
Example input:
|
|
252
|
+
{"segments": [{"id": 0, "text": "Hello world"}, {"id": 1, "text": "This is a test."}]}
|
|
253
|
+
|
|
254
|
+
Example output:
|
|
255
|
+
{"translations": [{"id": 0, "text": "こんにちは世界"}, {"id": 1, "text": "これはテストです。"}]}`;
|
|
256
|
+
return prompt;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Build system prompt for structured output translation (Claude tool_use path).
|
|
260
|
+
* No JSON format instructions needed — the tool schema enforces the response shape.
|
|
261
|
+
*/
|
|
262
|
+
function buildStructuredSystemPrompt(targetLang, templateContent, glossaryConfig) {
|
|
263
|
+
const basePrompt = templateContent
|
|
264
|
+
? templateContent.replace(/\{\{targetLanguage\}\}/g, targetLang)
|
|
265
|
+
: `You are a professional translator. Translate each text segment to ${targetLang}.
|
|
266
|
+
|
|
267
|
+
Rules:
|
|
268
|
+
- Translate only the text content; do not alter structure or punctuation outside the text
|
|
269
|
+
- Preserve proper nouns, code identifiers, URLs, and file paths unchanged
|
|
270
|
+
- Produce natural, fluent text in the target language
|
|
271
|
+
- For Japanese: use full-width punctuation (。、?!), add half-width spaces around English words/numbers
|
|
272
|
+
- Keep product names, abbreviations, and technical terms unchanged (e.g., NGSI-LD, MCP, GeoJSON)
|
|
273
|
+
- Each segment is independent; translate it on its own`;
|
|
274
|
+
let prompt = basePrompt;
|
|
275
|
+
if (glossaryConfig) {
|
|
276
|
+
const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
|
|
277
|
+
if (glossarySection)
|
|
278
|
+
prompt += glossarySection;
|
|
279
|
+
}
|
|
280
|
+
return prompt;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Parse translation JSON response from LLM (text mode fallback).
|
|
284
|
+
* Handles both clean JSON and JSON embedded in prose (extracts first {...} block).
|
|
285
|
+
*/
|
|
286
|
+
function parseTranslationResponse(raw) {
|
|
287
|
+
const trimmed = raw.trim();
|
|
288
|
+
try {
|
|
289
|
+
return JSON.parse(trimmed);
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// Extract first JSON object if LLM added prose around it
|
|
293
|
+
const jsonMatch = trimmed.match(/\{[\s\S]*\}/);
|
|
294
|
+
if (jsonMatch) {
|
|
295
|
+
return JSON.parse(jsonMatch[0]);
|
|
296
|
+
}
|
|
297
|
+
throw new Error(`Failed to parse translation response: ${trimmed.slice(0, 200)}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function assertValidTranslations(value) {
|
|
301
|
+
if (!Array.isArray(value) ||
|
|
302
|
+
value.some((item) => {
|
|
303
|
+
if (typeof item !== "object" || item === null)
|
|
304
|
+
return true;
|
|
305
|
+
const candidate = item;
|
|
306
|
+
return typeof candidate.id !== "number" || typeof candidate.text !== "string";
|
|
307
|
+
})) {
|
|
308
|
+
throw new Error("[yuuhitsu] translateBatch: invalid translation payload — expected Array<{id: number, text: string}>");
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Translate a batch of text segments using the provider.
|
|
313
|
+
*
|
|
314
|
+
* - If the provider implements `translateStructured` (Claude): uses tool_use to
|
|
315
|
+
* enforce the JSON schema at the API level, guaranteeing 1:1 ID mapping.
|
|
316
|
+
* - Otherwise: falls back to text-mode JSON prompt (Gemini / Ollama).
|
|
317
|
+
*
|
|
318
|
+
* In both paths the 1:1 ID mapping is validated and an error is thrown on mismatch.
|
|
319
|
+
*/
|
|
320
|
+
async function translateBatch(provider, nodes, targetLang, templateContent, glossaryConfig) {
|
|
321
|
+
if (nodes.length === 0) {
|
|
322
|
+
return { usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 } };
|
|
323
|
+
}
|
|
324
|
+
const segments = nodes.map(({ node, id }) => ({ id, text: node.value }));
|
|
325
|
+
// P-A1: track total input character count for truncation detection
|
|
326
|
+
const totalInputChars = segments.reduce((sum, s) => sum + s.text.length, 0);
|
|
327
|
+
let translations;
|
|
328
|
+
let usage;
|
|
329
|
+
if (provider.translateStructured) {
|
|
330
|
+
// Structured output path: provider (Claude) enforces JSON schema via tool_use
|
|
331
|
+
const systemPrompt = buildStructuredSystemPrompt(targetLang, templateContent, glossaryConfig);
|
|
332
|
+
const result = await provider.translateStructured({ segments, systemPrompt });
|
|
333
|
+
assertValidTranslations(result.translations);
|
|
334
|
+
translations = result.translations;
|
|
335
|
+
usage = result.usage;
|
|
336
|
+
// P-A1: warn on truncation (compare translated chars to input chars)
|
|
337
|
+
const totalOutputChars = translations.reduce((sum, t) => sum + t.text.length, 0);
|
|
338
|
+
if (totalInputChars > 0 && totalOutputChars < totalInputChars * MIN_OUTPUT_RATIO) {
|
|
339
|
+
console.warn(`[yuuhitsu] translateBatch: output may be truncated ` +
|
|
340
|
+
`(input chars: ${totalInputChars}, output chars: ${totalOutputChars})`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
// Text mode fallback: Gemini / Ollama
|
|
345
|
+
const systemPrompt = buildBatchSystemPrompt(targetLang, templateContent, glossaryConfig);
|
|
346
|
+
const messages = [
|
|
347
|
+
{ role: "system", content: systemPrompt },
|
|
348
|
+
{ role: "user", content: JSON.stringify({ segments }) },
|
|
349
|
+
];
|
|
350
|
+
const response = await provider.chat({ model: "", messages });
|
|
351
|
+
const parsed = parseTranslationResponse(response.content);
|
|
352
|
+
assertValidTranslations(parsed.translations);
|
|
353
|
+
// P-A1: warn on truncation (compare translated text chars, not raw JSON string length)
|
|
354
|
+
const totalOutputChars = parsed.translations.reduce((sum, t) => sum + t.text.length, 0);
|
|
355
|
+
if (totalInputChars > 0 && totalOutputChars < totalInputChars * MIN_OUTPUT_RATIO) {
|
|
356
|
+
console.warn(`[yuuhitsu] translateBatch: output may be truncated ` +
|
|
357
|
+
`(input chars: ${totalInputChars}, output chars: ${totalOutputChars})`);
|
|
358
|
+
}
|
|
359
|
+
translations = parsed.translations;
|
|
360
|
+
usage = response.usage;
|
|
361
|
+
}
|
|
362
|
+
// Validate strict 1:1 ID mapping (both paths):
|
|
363
|
+
// - no duplicate output IDs (Map silently overwrites; we must detect before)
|
|
364
|
+
// - no unexpected IDs (IDs not present in the input set)
|
|
365
|
+
// - no missing IDs (input ID absent from output)
|
|
366
|
+
const inputIds = new Set(nodes.map(({ id }) => id));
|
|
367
|
+
const seenOutputIds = new Set();
|
|
368
|
+
const duplicateIds = [];
|
|
369
|
+
const unexpectedIds = [];
|
|
370
|
+
for (const t of translations) {
|
|
371
|
+
if (seenOutputIds.has(t.id)) {
|
|
372
|
+
duplicateIds.push(t.id);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
seenOutputIds.add(t.id);
|
|
376
|
+
}
|
|
377
|
+
if (!inputIds.has(t.id)) {
|
|
378
|
+
unexpectedIds.push(t.id);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
if (duplicateIds.length > 0) {
|
|
382
|
+
throw new Error(`[yuuhitsu] translateBatch: duplicate IDs in response (IDs: ${duplicateIds.join(", ")})`);
|
|
383
|
+
}
|
|
384
|
+
if (unexpectedIds.length > 0) {
|
|
385
|
+
throw new Error(`[yuuhitsu] translateBatch: unexpected IDs in response (IDs: ${unexpectedIds.join(", ")})`);
|
|
386
|
+
}
|
|
387
|
+
const translationMap = new Map(translations.map((t) => [t.id, t.text]));
|
|
388
|
+
const missingIds = nodes.filter(({ id }) => !translationMap.has(id)).map(({ id }) => id);
|
|
389
|
+
if (missingIds.length > 0) {
|
|
390
|
+
throw new Error(`[yuuhitsu] translateBatch: partial translation — ${missingIds.length} node(s) missing` +
|
|
391
|
+
` from response (IDs: ${missingIds.join(", ")})`);
|
|
392
|
+
}
|
|
393
|
+
// Apply translations back to AST nodes
|
|
394
|
+
for (const { node, id } of nodes) {
|
|
395
|
+
const translated = translationMap.get(id);
|
|
396
|
+
if (translated !== undefined && translated.trim()) {
|
|
397
|
+
node.value = translated;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return { usage };
|
|
401
|
+
}
|
|
402
|
+
function resolveOutputPath(inputPath, targetLang, outputPath) {
|
|
403
|
+
if (outputPath)
|
|
404
|
+
return outputPath;
|
|
405
|
+
const dir = dirname(inputPath);
|
|
406
|
+
const ext = extname(inputPath);
|
|
407
|
+
const base = basename(inputPath, ext);
|
|
408
|
+
return join(dir, `${base}.${targetLang}${ext}`);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Translate a Markdown file using AST-based approach.
|
|
412
|
+
*
|
|
413
|
+
* Architecture (0.2.0):
|
|
414
|
+
* 1. Separate frontmatter (preserved verbatim)
|
|
415
|
+
* 2. Split body into chunks by heading boundaries
|
|
416
|
+
* 3. For each chunk: parse to AST → extract text nodes → translate via LLM → write back
|
|
417
|
+
* 4. Serialize AST → markdown → concatenate → write output
|
|
418
|
+
*
|
|
419
|
+
* Key properties:
|
|
420
|
+
* - Code blocks (fenced and inline) are never sent to LLM (AST handles them deterministically)
|
|
421
|
+
* - Markdown structure (headings, lists, tables, HR) is preserved by AST round-trip
|
|
422
|
+
* - No sentinel injection or removal needed
|
|
423
|
+
*/
|
|
397
424
|
export async function translateFile(options) {
|
|
398
|
-
const { provider, inputPath, targetLang, templateContent, glossaryConfig, maxChunkLines } = options;
|
|
399
|
-
// Read input file
|
|
425
|
+
const { provider, inputPath, targetLang, templateContent, glossaryConfig, maxChunkLines, } = options;
|
|
400
426
|
let content;
|
|
401
427
|
try {
|
|
402
428
|
content = readFileSync(inputPath, "utf-8");
|
|
@@ -407,46 +433,41 @@ export async function translateFile(options) {
|
|
|
407
433
|
}
|
|
408
434
|
throw err;
|
|
409
435
|
}
|
|
410
|
-
// Check for empty file
|
|
411
436
|
if (content.trim().length === 0) {
|
|
412
437
|
throw new Error(`Input file is empty: ${inputPath}`);
|
|
413
438
|
}
|
|
414
439
|
const resolvedOutput = resolveOutputPath(inputPath, targetLang, options.outputPath);
|
|
415
|
-
// Ensure output directory exists
|
|
416
440
|
mkdirSync(dirname(resolvedOutput), { recursive: true });
|
|
417
|
-
// Separate frontmatter from body
|
|
418
441
|
const { frontmatter, body } = separateFrontmatter(content);
|
|
419
|
-
//
|
|
420
|
-
const
|
|
421
|
-
const
|
|
422
|
-
// Protect block boundaries: insert %%BB%% sentinels before structural elements (P-A4)
|
|
423
|
-
const bodyWithSentinels = protectBlockBoundaries(protectedBody);
|
|
424
|
-
const hasSentinels = bodyWithSentinels.includes(BLOCK_BOUNDARY_SENTINEL);
|
|
425
|
-
// Split body into chunks if needed (frontmatter is never sent to LLM)
|
|
426
|
-
const chunks = splitIntoChunks(bodyWithSentinels, maxChunkLines);
|
|
427
|
-
const translatedParts = [];
|
|
442
|
+
// Split body into text chunks (heading-based, same as before)
|
|
443
|
+
const chunks = splitIntoChunks(body, maxChunkLines ?? DEFAULT_MAX_CHUNK_LINES);
|
|
444
|
+
const translatedChunks = [];
|
|
428
445
|
let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
429
446
|
for (const chunk of chunks) {
|
|
430
|
-
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
447
|
+
// Parse chunk to AST (code blocks, inline code become typed nodes → never reach LLM)
|
|
448
|
+
const processor = remark().use(remarkGfm);
|
|
449
|
+
const ast = processor.parse(chunk);
|
|
450
|
+
// Extract translatable text nodes
|
|
451
|
+
const textNodes = extractTextNodes(ast);
|
|
452
|
+
if (textNodes.length > 0) {
|
|
453
|
+
const { usage } = await translateBatch(provider, textNodes, targetLang, templateContent, glossaryConfig);
|
|
454
|
+
totalUsage.promptTokens += usage.promptTokens;
|
|
455
|
+
totalUsage.completionTokens += usage.completionTokens;
|
|
456
|
+
totalUsage.totalTokens += usage.totalTokens;
|
|
457
|
+
}
|
|
458
|
+
// Serialize AST back to markdown
|
|
459
|
+
const translatedChunk = processor.stringify(ast);
|
|
460
|
+
translatedChunks.push(translatedChunk);
|
|
439
461
|
}
|
|
440
|
-
//
|
|
441
|
-
//
|
|
442
|
-
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
462
|
+
// Join chunks: normalize each chunk to exactly one trailing newline
|
|
463
|
+
// (preserves trailing spaces for Markdown hard line breaks), then join
|
|
464
|
+
// with a single "\n" so chunk boundaries produce exactly one blank line.
|
|
465
|
+
const translatedBody = translatedChunks
|
|
466
|
+
.map((c) => c.replace(/\n+$/, "\n"))
|
|
467
|
+
.join("\n");
|
|
446
468
|
const translatedContent = frontmatter
|
|
447
469
|
? frontmatter + translatedBody
|
|
448
470
|
: translatedBody;
|
|
449
|
-
// Write output
|
|
450
471
|
writeFileSync(resolvedOutput, translatedContent, "utf-8");
|
|
451
472
|
return {
|
|
452
473
|
outputPath: resolvedOutput,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geolonia/yuuhitsu",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "右筆 (Yuuhitsu) - AI-powered document operations CLI. Translate, generate, and sync documents using Claude, Gemini, or Ollama.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dev": "tsx src/cli/index.ts",
|
|
13
13
|
"test": "vitest run",
|
|
14
14
|
"test:watch": "vitest",
|
|
15
|
-
"test:integration": "vitest run
|
|
15
|
+
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
16
16
|
"lint": "tsc --noEmit"
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|
|
@@ -36,6 +36,9 @@
|
|
|
36
36
|
"dotenv": "^16.4.0",
|
|
37
37
|
"fast-glob": "^3.3.3",
|
|
38
38
|
"openai": "^4.77.0",
|
|
39
|
+
"remark": "^15.0.1",
|
|
40
|
+
"remark-gfm": "^4.0.1",
|
|
41
|
+
"unist-util-visit": "^5.1.0",
|
|
39
42
|
"yaml": "^2.7.0"
|
|
40
43
|
},
|
|
41
44
|
"devDependencies": {
|
|
@@ -43,5 +46,9 @@
|
|
|
43
46
|
"tsx": "^4.19.0",
|
|
44
47
|
"typescript": "^5.7.0",
|
|
45
48
|
"vitest": "^3.0.0"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public",
|
|
52
|
+
"registry": "https://registry.npmjs.org/"
|
|
46
53
|
}
|
|
47
54
|
}
|