@llm-translate/cli 1.0.0-next.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.
Files changed (157) hide show
  1. package/.dockerignore +51 -0
  2. package/.env.example +33 -0
  3. package/.github/workflows/docs-pages.yml +57 -0
  4. package/.github/workflows/release.yml +49 -0
  5. package/.translaterc.json +44 -0
  6. package/CLAUDE.md +243 -0
  7. package/Dockerfile +55 -0
  8. package/README.md +371 -0
  9. package/RFC.md +1595 -0
  10. package/dist/cli/index.d.ts +2 -0
  11. package/dist/cli/index.js +4494 -0
  12. package/dist/cli/index.js.map +1 -0
  13. package/dist/index.d.ts +1152 -0
  14. package/dist/index.js +3841 -0
  15. package/dist/index.js.map +1 -0
  16. package/docker-compose.yml +56 -0
  17. package/docs/.vitepress/config.ts +161 -0
  18. package/docs/api/agent.md +262 -0
  19. package/docs/api/engine.md +274 -0
  20. package/docs/api/index.md +171 -0
  21. package/docs/api/providers.md +304 -0
  22. package/docs/changelog.md +64 -0
  23. package/docs/cli/dir.md +243 -0
  24. package/docs/cli/file.md +213 -0
  25. package/docs/cli/glossary.md +273 -0
  26. package/docs/cli/index.md +129 -0
  27. package/docs/cli/init.md +158 -0
  28. package/docs/cli/serve.md +211 -0
  29. package/docs/glossary.json +235 -0
  30. package/docs/guide/chunking.md +272 -0
  31. package/docs/guide/configuration.md +139 -0
  32. package/docs/guide/cost-optimization.md +237 -0
  33. package/docs/guide/docker.md +371 -0
  34. package/docs/guide/getting-started.md +150 -0
  35. package/docs/guide/glossary.md +241 -0
  36. package/docs/guide/index.md +86 -0
  37. package/docs/guide/ollama.md +515 -0
  38. package/docs/guide/prompt-caching.md +221 -0
  39. package/docs/guide/providers.md +232 -0
  40. package/docs/guide/quality-control.md +206 -0
  41. package/docs/guide/vitepress-integration.md +265 -0
  42. package/docs/index.md +63 -0
  43. package/docs/ja/api/agent.md +262 -0
  44. package/docs/ja/api/engine.md +274 -0
  45. package/docs/ja/api/index.md +171 -0
  46. package/docs/ja/api/providers.md +304 -0
  47. package/docs/ja/changelog.md +64 -0
  48. package/docs/ja/cli/dir.md +243 -0
  49. package/docs/ja/cli/file.md +213 -0
  50. package/docs/ja/cli/glossary.md +273 -0
  51. package/docs/ja/cli/index.md +111 -0
  52. package/docs/ja/cli/init.md +158 -0
  53. package/docs/ja/guide/chunking.md +271 -0
  54. package/docs/ja/guide/configuration.md +139 -0
  55. package/docs/ja/guide/cost-optimization.md +30 -0
  56. package/docs/ja/guide/getting-started.md +150 -0
  57. package/docs/ja/guide/glossary.md +214 -0
  58. package/docs/ja/guide/index.md +32 -0
  59. package/docs/ja/guide/ollama.md +410 -0
  60. package/docs/ja/guide/prompt-caching.md +221 -0
  61. package/docs/ja/guide/providers.md +232 -0
  62. package/docs/ja/guide/quality-control.md +137 -0
  63. package/docs/ja/guide/vitepress-integration.md +265 -0
  64. package/docs/ja/index.md +58 -0
  65. package/docs/ko/api/agent.md +262 -0
  66. package/docs/ko/api/engine.md +274 -0
  67. package/docs/ko/api/index.md +171 -0
  68. package/docs/ko/api/providers.md +304 -0
  69. package/docs/ko/changelog.md +64 -0
  70. package/docs/ko/cli/dir.md +243 -0
  71. package/docs/ko/cli/file.md +213 -0
  72. package/docs/ko/cli/glossary.md +273 -0
  73. package/docs/ko/cli/index.md +111 -0
  74. package/docs/ko/cli/init.md +158 -0
  75. package/docs/ko/guide/chunking.md +271 -0
  76. package/docs/ko/guide/configuration.md +139 -0
  77. package/docs/ko/guide/cost-optimization.md +30 -0
  78. package/docs/ko/guide/getting-started.md +150 -0
  79. package/docs/ko/guide/glossary.md +214 -0
  80. package/docs/ko/guide/index.md +32 -0
  81. package/docs/ko/guide/ollama.md +410 -0
  82. package/docs/ko/guide/prompt-caching.md +221 -0
  83. package/docs/ko/guide/providers.md +232 -0
  84. package/docs/ko/guide/quality-control.md +137 -0
  85. package/docs/ko/guide/vitepress-integration.md +265 -0
  86. package/docs/ko/index.md +58 -0
  87. package/docs/zh/api/agent.md +262 -0
  88. package/docs/zh/api/engine.md +274 -0
  89. package/docs/zh/api/index.md +171 -0
  90. package/docs/zh/api/providers.md +304 -0
  91. package/docs/zh/changelog.md +64 -0
  92. package/docs/zh/cli/dir.md +243 -0
  93. package/docs/zh/cli/file.md +213 -0
  94. package/docs/zh/cli/glossary.md +273 -0
  95. package/docs/zh/cli/index.md +111 -0
  96. package/docs/zh/cli/init.md +158 -0
  97. package/docs/zh/guide/chunking.md +271 -0
  98. package/docs/zh/guide/configuration.md +139 -0
  99. package/docs/zh/guide/cost-optimization.md +30 -0
  100. package/docs/zh/guide/getting-started.md +150 -0
  101. package/docs/zh/guide/glossary.md +214 -0
  102. package/docs/zh/guide/index.md +32 -0
  103. package/docs/zh/guide/ollama.md +410 -0
  104. package/docs/zh/guide/prompt-caching.md +221 -0
  105. package/docs/zh/guide/providers.md +232 -0
  106. package/docs/zh/guide/quality-control.md +137 -0
  107. package/docs/zh/guide/vitepress-integration.md +265 -0
  108. package/docs/zh/index.md +58 -0
  109. package/package.json +91 -0
  110. package/release.config.mjs +15 -0
  111. package/schemas/glossary.schema.json +110 -0
  112. package/src/cli/commands/dir.ts +469 -0
  113. package/src/cli/commands/file.ts +291 -0
  114. package/src/cli/commands/glossary.ts +221 -0
  115. package/src/cli/commands/init.ts +68 -0
  116. package/src/cli/commands/serve.ts +60 -0
  117. package/src/cli/index.ts +64 -0
  118. package/src/cli/options.ts +59 -0
  119. package/src/core/agent.ts +1119 -0
  120. package/src/core/chunker.ts +391 -0
  121. package/src/core/engine.ts +634 -0
  122. package/src/errors.ts +188 -0
  123. package/src/index.ts +147 -0
  124. package/src/integrations/vitepress.ts +549 -0
  125. package/src/parsers/markdown.ts +383 -0
  126. package/src/providers/claude.ts +259 -0
  127. package/src/providers/interface.ts +109 -0
  128. package/src/providers/ollama.ts +379 -0
  129. package/src/providers/openai.ts +308 -0
  130. package/src/providers/registry.ts +153 -0
  131. package/src/server/index.ts +152 -0
  132. package/src/server/middleware/auth.ts +93 -0
  133. package/src/server/middleware/logger.ts +90 -0
  134. package/src/server/routes/health.ts +84 -0
  135. package/src/server/routes/translate.ts +210 -0
  136. package/src/server/types.ts +138 -0
  137. package/src/services/cache.ts +899 -0
  138. package/src/services/config.ts +217 -0
  139. package/src/services/glossary.ts +247 -0
  140. package/src/types/analysis.ts +164 -0
  141. package/src/types/index.ts +265 -0
  142. package/src/types/modes.ts +121 -0
  143. package/src/types/mqm.ts +157 -0
  144. package/src/utils/logger.ts +141 -0
  145. package/src/utils/tokens.ts +116 -0
  146. package/tests/fixtures/glossaries/ml-glossary.json +53 -0
  147. package/tests/fixtures/input/lynq-installation.ko.md +350 -0
  148. package/tests/fixtures/input/lynq-installation.md +350 -0
  149. package/tests/fixtures/input/simple.ko.md +27 -0
  150. package/tests/fixtures/input/simple.md +27 -0
  151. package/tests/unit/chunker.test.ts +229 -0
  152. package/tests/unit/glossary.test.ts +146 -0
  153. package/tests/unit/markdown.test.ts +205 -0
  154. package/tests/unit/tokens.test.ts +81 -0
  155. package/tsconfig.json +28 -0
  156. package/tsup.config.ts +34 -0
  157. package/vitest.config.ts +16 -0
@@ -0,0 +1,262 @@
1
+ # TranslationAgent
2
+
3
+ ::: info 翻译说明
4
+ 所有非英文文档均使用 Claude Sonnet 4 自动翻译。
5
+ :::
6
+
7
+ 实现 Self-Refine 算法的底层翻译代理。
8
+
9
+ ## 构造函数
10
+
11
+ ```typescript
12
+ import { TranslationAgent } from '@llm-translate/cli';
13
+
14
+ const agent = new TranslationAgent(options: TranslationAgentOptions);
15
+ ```
16
+
17
+ ### 选项
18
+
19
+ ```typescript
20
+ interface TranslationAgentOptions {
21
+ provider: LLMProvider;
22
+ qualityThreshold?: number; // Default: 85
23
+ maxIterations?: number; // Default: 4
24
+ verbose?: boolean; // Default: false
25
+ strictQuality?: boolean; // Default: false
26
+ enableCaching?: boolean; // Default: true for Claude
27
+ }
28
+ ```
29
+
30
+ ## 方法
31
+
32
+ ### translate
33
+
34
+ 使用 Self-Refine 循环翻译内容。
35
+
36
+ ```typescript
37
+ const result = await agent.translate(request: TranslationRequest);
38
+ ```
39
+
40
+ #### 请求
41
+
42
+ ```typescript
43
+ interface TranslationRequest {
44
+ content: string; // Source text to translate
45
+ sourceLang: string; // Source language code
46
+ targetLang: string; // Target language code
47
+ glossary?: ResolvedGlossary; // Resolved glossary for target language
48
+ context?: {
49
+ documentPurpose?: string;
50
+ previousChunks?: string[];
51
+ documentSummary?: string;
52
+ };
53
+ }
54
+ ```
55
+
56
+ #### 结果
57
+
58
+ ```typescript
59
+ interface TranslationResult {
60
+ content: string; // Translated text
61
+ metadata: {
62
+ qualityScore: number;
63
+ qualityThreshold: number;
64
+ thresholdMet: boolean;
65
+ iterations: number;
66
+ tokensUsed: {
67
+ input: number;
68
+ output: number;
69
+ cacheRead?: number;
70
+ cacheWrite?: number;
71
+ };
72
+ duration: number;
73
+ provider: string;
74
+ model: string;
75
+ };
76
+ glossaryCompliance?: {
77
+ applied: string[]; // Terms successfully applied
78
+ missed: string[]; // Terms not found in translation
79
+ };
80
+ }
81
+ ```
82
+
83
+ ## Self-Refine 算法
84
+
85
+ 代理实现了这个迭代优化过程:
86
+
87
+ ```typescript
88
+ // Pseudocode
89
+ async translate(request) {
90
+ // 1. Initial translation with glossary
91
+ let translation = await generateInitialTranslation(request);
92
+ let iterations = 1;
93
+
94
+ while (iterations < maxIterations) {
95
+ // 2. Evaluate quality
96
+ const evaluation = await evaluateQuality(translation);
97
+
98
+ if (evaluation.score >= qualityThreshold) {
99
+ break; // Quality met
100
+ }
101
+
102
+ // 3. Generate improvement suggestions
103
+ const suggestions = await generateReflection(translation);
104
+
105
+ // 4. Apply improvements
106
+ translation = await improveTranslation(translation, suggestions);
107
+ iterations++;
108
+ }
109
+
110
+ return { content: translation, metadata: { ... } };
111
+ }
112
+ ```
113
+
114
+ ## 使用示例
115
+
116
+ ### 基础翻译
117
+
118
+ ```typescript
119
+ import { TranslationAgent, createClaudeProvider } from '@llm-translate/cli';
120
+
121
+ const provider = createClaudeProvider();
122
+ const agent = new TranslationAgent({
123
+ provider,
124
+ qualityThreshold: 85,
125
+ });
126
+
127
+ const result = await agent.translate({
128
+ content: 'Hello, world!',
129
+ sourceLang: 'en',
130
+ targetLang: 'ko',
131
+ });
132
+
133
+ console.log(result.content); // 안녕하세요, 세계!
134
+ console.log(result.metadata.qualityScore); // 92
135
+ ```
136
+
137
+ ### 使用术语表
138
+
139
+ ```typescript
140
+ import { loadGlossary, resolveGlossary } from '@llm-translate/cli';
141
+
142
+ const glossary = await loadGlossary('./glossary.json');
143
+ const resolved = resolveGlossary(glossary, 'ko');
144
+
145
+ const result = await agent.translate({
146
+ content: 'The component renders a prop.',
147
+ sourceLang: 'en',
148
+ targetLang: 'ko',
149
+ glossary: resolved,
150
+ });
151
+
152
+ console.log(result.glossaryCompliance);
153
+ // { applied: ['component', 'prop'], missed: [] }
154
+ ```
155
+
156
+ ### 使用上下文
157
+
158
+ ```typescript
159
+ const result = await agent.translate({
160
+ content: 'Click the button to continue.',
161
+ sourceLang: 'en',
162
+ targetLang: 'ko',
163
+ context: {
164
+ documentPurpose: 'User interface instructions',
165
+ previousChunks: [
166
+ '이전 단계에서 설정을 완료했습니다.', // Previous translation
167
+ ],
168
+ },
169
+ });
170
+ ```
171
+
172
+ ### 严格质量模式
173
+
174
+ ```typescript
175
+ import { TranslationError, ErrorCode } from '@llm-translate/cli';
176
+
177
+ const agent = new TranslationAgent({
178
+ provider,
179
+ qualityThreshold: 95,
180
+ strictQuality: true, // Throw if threshold not met
181
+ });
182
+
183
+ try {
184
+ const result = await agent.translate(request);
185
+ } catch (error) {
186
+ if (error instanceof TranslationError &&
187
+ error.code === ErrorCode.QUALITY_THRESHOLD_NOT_MET) {
188
+ console.log(`Quality: ${error.details.score}/${error.details.threshold}`);
189
+ console.log(`Issues: ${error.details.issues.join(', ')}`);
190
+ }
191
+ }
192
+ ```
193
+
194
+ ## 质量评估
195
+
196
+ 代理根据四个标准评估翻译:
197
+
198
+ | 标准 | 权重 | 描述 |
199
+ |-----------|--------|-------------|
200
+ | 语义准确性 | 40% | 意义保持 |
201
+ | 流畅性 | 25% | 自然语言流 |
202
+ | 术语表合规性 | 20% | 术语一致性 |
203
+ | 格式保持 | 15% | 结构维护 |
204
+
205
+ ### 评估结果
206
+
207
+ ```typescript
208
+ interface QualityEvaluation {
209
+ score: number; // 0-100
210
+ breakdown: {
211
+ accuracy: number; // 0-40
212
+ fluency: number; // 0-25
213
+ glossary: number; // 0-20
214
+ format: number; // 0-15
215
+ };
216
+ issues: string[]; // Specific problems identified
217
+ }
218
+ ```
219
+
220
+ ## 提示缓存
221
+
222
+ 当 `enableCaching` 为 true(Claude 的默认值)时,代理会为缓存构建提示:
223
+
224
+ ```
225
+ ┌─────────────────────────────────┐
226
+ │ System Instructions (CACHED) │ ← Reused across chunks
227
+ ├─────────────────────────────────┤
228
+ │ Glossary (CACHED) │ ← Reused across chunks
229
+ ├─────────────────────────────────┤
230
+ │ Source Text (NOT cached) │ ← Changes per chunk
231
+ └─────────────────────────────────┘
232
+ ```
233
+
234
+ 这可以为多分块文档减少 40-50% 的成本。
235
+
236
+ ## 高级:自定义评估
237
+
238
+ 覆盖默认评估逻辑:
239
+
240
+ ```typescript
241
+ class CustomAgent extends TranslationAgent {
242
+ protected async evaluateQuality(
243
+ source: string,
244
+ translation: string,
245
+ sourceLang: string,
246
+ targetLang: string
247
+ ): Promise<QualityEvaluation> {
248
+ // Custom evaluation logic
249
+ const baseEval = await super.evaluateQuality(
250
+ source, translation, sourceLang, targetLang
251
+ );
252
+
253
+ // Add custom checks
254
+ if (translation.length < source.length * 0.5) {
255
+ baseEval.score -= 10;
256
+ baseEval.issues.push('Translation suspiciously short');
257
+ }
258
+
259
+ return baseEval;
260
+ }
261
+ }
262
+ ```
@@ -0,0 +1,274 @@
1
+ # TranslationEngine
2
+
3
+ ::: info 翻译说明
4
+ 所有非英文文档均使用 Claude Sonnet 4 自动翻译。
5
+ :::
6
+
7
+ 翻译操作的主要入口点。
8
+
9
+ ## 构造函数
10
+
11
+ ```typescript
12
+ import { TranslationEngine } from '@llm-translate/cli';
13
+
14
+ const engine = new TranslationEngine(options: TranslationEngineOptions);
15
+ ```
16
+
17
+ ### 选项
18
+
19
+ ```typescript
20
+ interface TranslationEngineOptions {
21
+ provider: LLMProvider;
22
+ qualityThreshold?: number; // Default: 85
23
+ maxIterations?: number; // Default: 4
24
+ chunkingConfig?: ChunkingConfig;
25
+ verbose?: boolean; // Default: false
26
+ }
27
+ ```
28
+
29
+ ## 方法
30
+
31
+ ### translateFile
32
+
33
+ 翻译单个文件。
34
+
35
+ ```typescript
36
+ const result = await engine.translateFile(options: TranslateFileOptions);
37
+ ```
38
+
39
+ #### 选项
40
+
41
+ ```typescript
42
+ interface TranslateFileOptions {
43
+ input: string; // Input file path
44
+ output?: string; // Output file path (optional)
45
+ sourceLang?: string; // Source language (auto-detect if omitted)
46
+ targetLang: string; // Target language (required)
47
+ glossary?: string | Glossary; // Glossary path or object
48
+ context?: {
49
+ documentPurpose?: string;
50
+ preserveFormatting?: boolean;
51
+ };
52
+ }
53
+ ```
54
+
55
+ #### 返回值
56
+
57
+ ```typescript
58
+ interface TranslateFileResult {
59
+ content: string;
60
+ outputPath?: string;
61
+ metadata: {
62
+ qualityScore: number;
63
+ qualityThreshold: number;
64
+ thresholdMet: boolean;
65
+ iterations: number;
66
+ tokensUsed: {
67
+ input: number;
68
+ output: number;
69
+ cacheRead?: number;
70
+ cacheWrite?: number;
71
+ };
72
+ duration: number;
73
+ chunks: number;
74
+ };
75
+ }
76
+ ```
77
+
78
+ #### 示例
79
+
80
+ ```typescript
81
+ const result = await engine.translateFile({
82
+ input: 'docs/guide.md',
83
+ output: 'docs/guide.ko.md',
84
+ targetLang: 'ko',
85
+ glossary: './glossary.json',
86
+ context: {
87
+ documentPurpose: 'Technical documentation for developers',
88
+ },
89
+ });
90
+
91
+ console.log(`Quality: ${result.metadata.qualityScore}`);
92
+ console.log(`Output: ${result.outputPath}`);
93
+ ```
94
+
95
+ ### translateContent
96
+
97
+ 直接翻译内容(无需文件 I/O)。
98
+
99
+ ```typescript
100
+ const result = await engine.translateContent(
101
+ content: string,
102
+ options: TranslateContentOptions
103
+ );
104
+ ```
105
+
106
+ #### 选项
107
+
108
+ ```typescript
109
+ interface TranslateContentOptions {
110
+ sourceLang?: string;
111
+ targetLang: string;
112
+ glossary?: ResolvedGlossary;
113
+ format?: 'markdown' | 'html' | 'text';
114
+ context?: {
115
+ documentPurpose?: string;
116
+ previousChunks?: string[];
117
+ };
118
+ }
119
+ ```
120
+
121
+ #### 示例
122
+
123
+ ```typescript
124
+ const content = `
125
+ # Hello World
126
+
127
+ This is a **markdown** document.
128
+ `;
129
+
130
+ const result = await engine.translateContent(content, {
131
+ targetLang: 'ko',
132
+ format: 'markdown',
133
+ });
134
+
135
+ console.log(result.content);
136
+ // # 안녕하세요
137
+ //
138
+ // 이것은 **마크다운** 문서입니다.
139
+ ```
140
+
141
+ ### translateDirectory
142
+
143
+ 翻译目录中的所有文件。
144
+
145
+ ```typescript
146
+ const results = await engine.translateDirectory(options: TranslateDirectoryOptions);
147
+ ```
148
+
149
+ #### 选项
150
+
151
+ ```typescript
152
+ interface TranslateDirectoryOptions {
153
+ input: string; // Input directory
154
+ output: string; // Output directory
155
+ targetLang: string;
156
+ glossary?: string | Glossary;
157
+ pattern?: string; // Glob pattern (default: '**/*.md')
158
+ exclude?: string[]; // Patterns to exclude
159
+ concurrency?: number; // Parallel processing (default: 3)
160
+ continueOnError?: boolean;
161
+ }
162
+ ```
163
+
164
+ #### 返回值
165
+
166
+ ```typescript
167
+ interface TranslateDirectoryResult {
168
+ successful: TranslateFileResult[];
169
+ failed: Array<{
170
+ file: string;
171
+ error: Error;
172
+ }>;
173
+ summary: {
174
+ total: number;
175
+ successful: number;
176
+ failed: number;
177
+ totalDuration: number;
178
+ averageQuality: number;
179
+ };
180
+ }
181
+ ```
182
+
183
+ #### 示例
184
+
185
+ ```typescript
186
+ const results = await engine.translateDirectory({
187
+ input: './docs',
188
+ output: './docs-ko',
189
+ targetLang: 'ko',
190
+ glossary: './glossary.json',
191
+ concurrency: 5,
192
+ continueOnError: true,
193
+ });
194
+
195
+ console.log(`Translated: ${results.summary.successful}/${results.summary.total}`);
196
+ console.log(`Average quality: ${results.summary.averageQuality}`);
197
+ ```
198
+
199
+ ## 事件
200
+
201
+ TranslationEngine 继承自 EventEmitter:
202
+
203
+ ```typescript
204
+ engine.on('chunk:start', (data) => {
205
+ console.log(`Starting chunk ${data.index}/${data.total}`);
206
+ });
207
+
208
+ engine.on('chunk:complete', (data) => {
209
+ console.log(`Chunk ${data.index}: quality ${data.quality}`);
210
+ });
211
+
212
+ engine.on('file:start', (data) => {
213
+ console.log(`Translating: ${data.file}`);
214
+ });
215
+
216
+ engine.on('file:complete', (data) => {
217
+ console.log(`Completed: ${data.file} (${data.quality})`);
218
+ });
219
+ ```
220
+
221
+ ## 完整示例
222
+
223
+ ```typescript
224
+ import {
225
+ TranslationEngine,
226
+ createClaudeProvider,
227
+ loadGlossary,
228
+ resolveGlossary,
229
+ } from '@llm-translate/cli';
230
+
231
+ async function translateDocs() {
232
+ // Setup provider
233
+ const provider = createClaudeProvider({
234
+ apiKey: process.env.ANTHROPIC_API_KEY,
235
+ defaultModel: 'claude-sonnet-4-5-20250929',
236
+ });
237
+
238
+ // Load and resolve glossary
239
+ const glossary = await loadGlossary('./glossary.json');
240
+
241
+ // Create engine
242
+ const engine = new TranslationEngine({
243
+ provider,
244
+ qualityThreshold: 90,
245
+ maxIterations: 5,
246
+ verbose: true,
247
+ });
248
+
249
+ // Track progress
250
+ engine.on('chunk:complete', ({ index, total, quality }) => {
251
+ console.log(`Progress: ${index}/${total} (quality: ${quality})`);
252
+ });
253
+
254
+ // Translate
255
+ try {
256
+ const result = await engine.translateFile({
257
+ input: 'README.md',
258
+ output: 'README.ko.md',
259
+ targetLang: 'ko',
260
+ glossary,
261
+ });
262
+
263
+ console.log('Translation complete!');
264
+ console.log(`Quality: ${result.metadata.qualityScore}`);
265
+ console.log(`Tokens: ${result.metadata.tokensUsed.input} in / ${result.metadata.tokensUsed.output} out`);
266
+
267
+ if (result.metadata.tokensUsed.cacheRead) {
268
+ console.log(`Cache hit: ${result.metadata.tokensUsed.cacheRead} tokens`);
269
+ }
270
+ } catch (error) {
271
+ console.error('Translation failed:', error.message);
272
+ }
273
+ }
274
+ ```
@@ -0,0 +1,171 @@
1
+ # API 参考
2
+
3
+ ::: info 翻译说明
4
+ 所有非英文文档均使用 Claude Sonnet 4 自动翻译。
5
+ :::
6
+
7
+ llm-translate 可以在您的 Node.js 应用程序中以编程方式使用。
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ npm install @llm-translate/cli
13
+ ```
14
+
15
+ ## 快速开始
16
+
17
+ ```typescript
18
+ import { TranslationEngine, createClaudeProvider } from '@llm-translate/cli';
19
+
20
+ // Create provider
21
+ const provider = createClaudeProvider({
22
+ apiKey: process.env.ANTHROPIC_API_KEY,
23
+ });
24
+
25
+ // Create engine
26
+ const engine = new TranslationEngine({
27
+ provider,
28
+ qualityThreshold: 85,
29
+ });
30
+
31
+ // Translate
32
+ const result = await engine.translateFile({
33
+ input: 'README.md',
34
+ output: 'README.ko.md',
35
+ sourceLang: 'en',
36
+ targetLang: 'ko',
37
+ });
38
+
39
+ console.log(result.metadata);
40
+ ```
41
+
42
+ ## 核心类
43
+
44
+ ### [TranslationEngine](./engine)
45
+
46
+ 翻译操作的主要入口点。
47
+
48
+ ```typescript
49
+ const engine = new TranslationEngine(options);
50
+ await engine.translateFile({ input, output, targetLang });
51
+ await engine.translateContent(content, options);
52
+ ```
53
+
54
+ ### [TranslationAgent](./agent)
55
+
56
+ 带有 Self-Refine 循环的低级翻译代理。
57
+
58
+ ```typescript
59
+ const agent = new TranslationAgent({ provider, qualityThreshold });
60
+ const result = await agent.translate(request);
61
+ ```
62
+
63
+ ### [Providers](./providers)
64
+
65
+ LLM 提供商实现。
66
+
67
+ ```typescript
68
+ import {
69
+ createClaudeProvider,
70
+ createOpenAIProvider,
71
+ createOllamaProvider,
72
+ } from '@llm-translate/cli';
73
+ ```
74
+
75
+ ## 类型导出
76
+
77
+ ```typescript
78
+ import type {
79
+ // Configuration
80
+ TranslationConfig,
81
+ ProviderConfig,
82
+
83
+ // Requests/Results
84
+ TranslationRequest,
85
+ TranslationResult,
86
+
87
+ // Glossary
88
+ Glossary,
89
+ GlossaryTerm,
90
+ ResolvedGlossary,
91
+
92
+ // Quality
93
+ QualityEvaluation,
94
+
95
+ // Provider
96
+ LLMProvider,
97
+ ChatMessage,
98
+ ChatResponse,
99
+ } from '@llm-translate/cli';
100
+ ```
101
+
102
+ ## 实用函数
103
+
104
+ ### Chunking
105
+
106
+ ```typescript
107
+ import { chunkContent, chunkMarkdown } from '@llm-translate/cli';
108
+
109
+ const chunks = chunkContent(text, { maxTokens: 1024 });
110
+ const mdChunks = chunkMarkdown(markdown, { maxTokens: 1024 });
111
+ ```
112
+
113
+ ### 术语表
114
+
115
+ ```typescript
116
+ import { loadGlossary, resolveGlossary, createGlossaryLookup } from '@llm-translate/cli';
117
+
118
+ const glossary = await loadGlossary('./glossary.json');
119
+ const resolved = resolveGlossary(glossary, 'ko');
120
+ const lookup = createGlossaryLookup(resolved);
121
+
122
+ const terms = lookup.findAll(sourceText);
123
+ ```
124
+
125
+ ### 令牌估算
126
+
127
+ ```typescript
128
+ import { estimateTokens, calculateTokenBudget } from '@llm-translate/cli';
129
+
130
+ const tokens = estimateTokens(text);
131
+ const budget = calculateTokenBudget(text, { glossaryTokens: 500 });
132
+ ```
133
+
134
+ ## 错误处理
135
+
136
+ ```typescript
137
+ import { TranslationError, ErrorCode } from '@llm-translate/cli';
138
+
139
+ try {
140
+ await engine.translateFile(options);
141
+ } catch (error) {
142
+ if (error instanceof TranslationError) {
143
+ switch (error.code) {
144
+ case ErrorCode.FILE_NOT_FOUND:
145
+ // Handle missing file
146
+ break;
147
+ case ErrorCode.QUALITY_THRESHOLD_NOT_MET:
148
+ // Handle quality issue
149
+ console.log('Score:', error.details.score);
150
+ break;
151
+ case ErrorCode.PROVIDER_RATE_LIMITED:
152
+ // Handle rate limit
153
+ break;
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ ## 错误代码
160
+
161
+ | 代码 | 描述 |
162
+ |------|-------------|
163
+ |`FILE_NOT_FOUND`| 输入文件不存在 |
164
+ |`INVALID_CONFIG`| 配置验证失败 |
165
+ |`GLOSSARY_NOT_FOUND`| 术语表文件未找到 |
166
+ |`GLOSSARY_INVALID`| 术语表验证失败 |
167
+ |`PROVIDER_AUTH_FAILED`| API 密钥无效 |
168
+ |`PROVIDER_RATE_LIMITED`| 超出速率限制 |
169
+ |`PROVIDER_ERROR`| 一般提供商错误 |
170
+ |`QUALITY_THRESHOLD_NOT_MET`| 翻译质量低于阈值 |
171
+ |`PARSE_ERROR`| 文档解析失败 |