@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
package/src/errors.ts ADDED
@@ -0,0 +1,188 @@
1
+ // ============================================================================
2
+ // Error Codes
3
+ // ============================================================================
4
+
5
+ export enum ErrorCode {
6
+ // Configuration Errors
7
+ CONFIG_NOT_FOUND = 'CONFIG_NOT_FOUND',
8
+ CONFIG_INVALID = 'CONFIG_INVALID',
9
+
10
+ // Glossary Errors
11
+ GLOSSARY_NOT_FOUND = 'GLOSSARY_NOT_FOUND',
12
+ GLOSSARY_INVALID = 'GLOSSARY_INVALID',
13
+
14
+ // Provider Errors
15
+ PROVIDER_NOT_FOUND = 'PROVIDER_NOT_FOUND',
16
+ PROVIDER_AUTH_FAILED = 'PROVIDER_AUTH_FAILED',
17
+ PROVIDER_RATE_LIMITED = 'PROVIDER_RATE_LIMITED',
18
+ PROVIDER_ERROR = 'PROVIDER_ERROR',
19
+
20
+ // Translation Errors
21
+ QUALITY_THRESHOLD_NOT_MET = 'QUALITY_THRESHOLD_NOT_MET',
22
+ GLOSSARY_COMPLIANCE_FAILED = 'GLOSSARY_COMPLIANCE_FAILED',
23
+
24
+ // File Errors
25
+ FILE_NOT_FOUND = 'FILE_NOT_FOUND',
26
+ FILE_READ_ERROR = 'FILE_READ_ERROR',
27
+ FILE_WRITE_ERROR = 'FILE_WRITE_ERROR',
28
+
29
+ // Format Errors
30
+ UNSUPPORTED_FORMAT = 'UNSUPPORTED_FORMAT',
31
+ CHUNK_TOO_LARGE = 'CHUNK_TOO_LARGE',
32
+
33
+ // General Errors
34
+ UNKNOWN_ERROR = 'UNKNOWN_ERROR',
35
+ }
36
+
37
+ // ============================================================================
38
+ // Error Messages
39
+ // ============================================================================
40
+
41
+ const errorMessages: Record<ErrorCode, string> = {
42
+ [ErrorCode.CONFIG_NOT_FOUND]:
43
+ 'Configuration file not found. Run `llm-translate init` to create one.',
44
+ [ErrorCode.CONFIG_INVALID]:
45
+ 'Configuration file is invalid. Please check the format and required fields.',
46
+ [ErrorCode.GLOSSARY_NOT_FOUND]:
47
+ 'Glossary file not found at the specified path.',
48
+ [ErrorCode.GLOSSARY_INVALID]:
49
+ 'Glossary file is invalid. Please check the JSON format and structure.',
50
+ [ErrorCode.PROVIDER_NOT_FOUND]:
51
+ 'The specified LLM provider is not available. Supported providers: claude, openai, ollama.',
52
+ [ErrorCode.PROVIDER_AUTH_FAILED]:
53
+ 'Authentication failed. Check your API key in environment variables.',
54
+ [ErrorCode.PROVIDER_RATE_LIMITED]:
55
+ 'Rate limited by the LLM provider. Please wait and try again.',
56
+ [ErrorCode.PROVIDER_ERROR]:
57
+ 'An error occurred while communicating with the LLM provider.',
58
+ [ErrorCode.QUALITY_THRESHOLD_NOT_MET]:
59
+ 'Translation quality ({score}) did not meet threshold ({threshold}). Use --quality to adjust or --max-iterations to allow more refinement.',
60
+ [ErrorCode.GLOSSARY_COMPLIANCE_FAILED]:
61
+ 'Glossary compliance failed. Missing terms: {missed}. Use --no-strict-glossary to allow partial compliance.',
62
+ [ErrorCode.FILE_NOT_FOUND]: 'The specified file was not found.',
63
+ [ErrorCode.FILE_READ_ERROR]: 'Failed to read the file.',
64
+ [ErrorCode.FILE_WRITE_ERROR]: 'Failed to write to the output file.',
65
+ [ErrorCode.UNSUPPORTED_FORMAT]:
66
+ 'The file format is not supported. Supported formats: markdown, html, text.',
67
+ [ErrorCode.CHUNK_TOO_LARGE]:
68
+ 'A chunk exceeds the maximum token limit and cannot be processed.',
69
+ [ErrorCode.UNKNOWN_ERROR]: 'An unexpected error occurred.',
70
+ };
71
+
72
+ // ============================================================================
73
+ // Translation Error Class
74
+ // ============================================================================
75
+
76
+ export class TranslationError extends Error {
77
+ public readonly code: ErrorCode;
78
+ public readonly details?: Record<string, unknown>;
79
+
80
+ constructor(
81
+ code: ErrorCode,
82
+ details?: Record<string, unknown>,
83
+ customMessage?: string
84
+ ) {
85
+ const message = customMessage ?? formatErrorMessage(code, details);
86
+ super(message);
87
+
88
+ this.name = 'TranslationError';
89
+ this.code = code;
90
+ this.details = details;
91
+
92
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
93
+ if (Error.captureStackTrace) {
94
+ Error.captureStackTrace(this, TranslationError);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Create a JSON representation of the error
100
+ */
101
+ toJSON(): Record<string, unknown> {
102
+ return {
103
+ name: this.name,
104
+ code: this.code,
105
+ message: this.message,
106
+ details: this.details,
107
+ };
108
+ }
109
+ }
110
+
111
+ // ============================================================================
112
+ // Helper Functions
113
+ // ============================================================================
114
+
115
+ function formatErrorMessage(
116
+ code: ErrorCode,
117
+ details?: Record<string, unknown>
118
+ ): string {
119
+ let message = errorMessages[code] ?? errorMessages[ErrorCode.UNKNOWN_ERROR];
120
+
121
+ if (details) {
122
+ // Replace placeholders like {score} with actual values
123
+ for (const [key, value] of Object.entries(details)) {
124
+ message = message.replace(`{${key}}`, String(value));
125
+ }
126
+ }
127
+
128
+ return message;
129
+ }
130
+
131
+ // ============================================================================
132
+ // Error Type Guards
133
+ // ============================================================================
134
+
135
+ export function isTranslationError(error: unknown): error is TranslationError {
136
+ return error instanceof TranslationError;
137
+ }
138
+
139
+ export function isErrorCode(error: unknown, code: ErrorCode): boolean {
140
+ return isTranslationError(error) && error.code === code;
141
+ }
142
+
143
+ // ============================================================================
144
+ // Exit Codes (for CLI)
145
+ // ============================================================================
146
+
147
+ export const ExitCode = {
148
+ SUCCESS: 0,
149
+ GENERAL_ERROR: 1,
150
+ INVALID_ARGUMENTS: 2,
151
+ FILE_NOT_FOUND: 3,
152
+ QUALITY_THRESHOLD_NOT_MET: 4,
153
+ PROVIDER_ERROR: 5,
154
+ GLOSSARY_VALIDATION_FAILED: 6,
155
+ } as const;
156
+
157
+ export type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];
158
+
159
+ /**
160
+ * Map error codes to exit codes
161
+ */
162
+ export function getExitCode(error: TranslationError): ExitCode {
163
+ switch (error.code) {
164
+ case ErrorCode.FILE_NOT_FOUND:
165
+ case ErrorCode.CONFIG_NOT_FOUND:
166
+ case ErrorCode.GLOSSARY_NOT_FOUND:
167
+ return ExitCode.FILE_NOT_FOUND;
168
+
169
+ case ErrorCode.CONFIG_INVALID:
170
+ case ErrorCode.UNSUPPORTED_FORMAT:
171
+ return ExitCode.INVALID_ARGUMENTS;
172
+
173
+ case ErrorCode.QUALITY_THRESHOLD_NOT_MET:
174
+ return ExitCode.QUALITY_THRESHOLD_NOT_MET;
175
+
176
+ case ErrorCode.PROVIDER_NOT_FOUND:
177
+ case ErrorCode.PROVIDER_AUTH_FAILED:
178
+ case ErrorCode.PROVIDER_RATE_LIMITED:
179
+ case ErrorCode.PROVIDER_ERROR:
180
+ return ExitCode.PROVIDER_ERROR;
181
+
182
+ case ErrorCode.GLOSSARY_INVALID:
183
+ return ExitCode.GLOSSARY_VALIDATION_FAILED;
184
+
185
+ default:
186
+ return ExitCode.GENERAL_ERROR;
187
+ }
188
+ }
package/src/index.ts ADDED
@@ -0,0 +1,147 @@
1
+ // ============================================================================
2
+ // llm-translate - LLM-powered CLI Translation Tool
3
+ // ============================================================================
4
+
5
+ // Types
6
+ export type {
7
+ TranslateConfig,
8
+ ProviderName,
9
+ Glossary,
10
+ GlossaryTerm,
11
+ ResolvedGlossary,
12
+ ResolvedGlossaryTerm,
13
+ TranslationRequest,
14
+ TranslationResult,
15
+ DocumentResult,
16
+ ChunkResult,
17
+ Chunk,
18
+ ChunkingConfig,
19
+ QualityEvaluation,
20
+ DocumentFormat,
21
+ CacheEntry,
22
+ CacheIndex,
23
+ } from './types/index.js';
24
+
25
+ // Provider Interface
26
+ export type {
27
+ LLMProvider,
28
+ ProviderConfig,
29
+ ChatMessage,
30
+ ChatRequest,
31
+ ChatResponse,
32
+ ModelInfo,
33
+ } from './providers/interface.js';
34
+
35
+ // Errors
36
+ export {
37
+ TranslationError,
38
+ ErrorCode,
39
+ ExitCode,
40
+ isTranslationError,
41
+ isErrorCode,
42
+ getExitCode,
43
+ } from './errors.js';
44
+
45
+ // Services
46
+ export { loadConfig, mergeConfig } from './services/config.js';
47
+ export {
48
+ loadGlossary,
49
+ resolveGlossary,
50
+ createGlossaryLookup,
51
+ checkGlossaryCompliance,
52
+ } from './services/glossary.js';
53
+ export {
54
+ CacheManager,
55
+ createCacheManager,
56
+ createNullCacheManager,
57
+ hashContent,
58
+ generateCacheKey,
59
+ // Invalidation Policies
60
+ GlossaryChangePolicy,
61
+ TTLPolicy,
62
+ ProviderChangePolicy,
63
+ QualityThresholdPolicy,
64
+ CompositePolicy,
65
+ // Preset Policy Configurations
66
+ createDefaultPolicies,
67
+ createStrictPolicies,
68
+ createMinimalPolicies,
69
+ } from './services/cache.js';
70
+ export type {
71
+ CacheOptions,
72
+ CacheKey,
73
+ CacheStats,
74
+ CacheResult,
75
+ CacheMetadata,
76
+ // Invalidation Policy Types
77
+ InvalidationPolicy,
78
+ InvalidationContext,
79
+ InvalidationResult,
80
+ } from './services/cache.js';
81
+
82
+ // Provider Registry
83
+ export {
84
+ registerProvider,
85
+ getProvider,
86
+ hasProvider,
87
+ getAvailableProviders,
88
+ getProviderConfigFromEnv,
89
+ createProviderWithFallback,
90
+ } from './providers/registry.js';
91
+
92
+ // Claude Provider
93
+ export { ClaudeProvider, createClaudeProvider } from './providers/claude.js';
94
+
95
+ // Core - Chunker
96
+ export {
97
+ chunkContent,
98
+ reassembleChunks,
99
+ getChunkStats,
100
+ } from './core/chunker.js';
101
+
102
+ // Core - Translation Agent
103
+ export {
104
+ TranslationAgent,
105
+ createTranslationAgent,
106
+ } from './core/agent.js';
107
+
108
+ // Core - Translation Engine
109
+ export {
110
+ TranslationEngine,
111
+ createTranslationEngine,
112
+ translateText,
113
+ } from './core/engine.js';
114
+
115
+ // Parsers
116
+ export {
117
+ parseMarkdown,
118
+ applyTranslations,
119
+ getTranslatableText,
120
+ createTranslationMap,
121
+ extractTextForTranslation,
122
+ restorePreservedSections,
123
+ translateMarkdownContent,
124
+ } from './parsers/markdown.js';
125
+
126
+ // Utilities
127
+ export { estimateTokens, exceedsTokenLimit, truncateToTokenLimit } from './utils/tokens.js';
128
+ export { logger, configureLogger, createTimer } from './utils/logger.js';
129
+
130
+ // VitePress Integration
131
+ export {
132
+ generateLocaleConfig,
133
+ generateLocale,
134
+ generateSidebarConfig,
135
+ detectLocales,
136
+ detectSidebarDirs,
137
+ } from './integrations/vitepress.js';
138
+ export type {
139
+ LocaleConfig,
140
+ ThemeConfig,
141
+ NavItem,
142
+ NavItemWithLink,
143
+ NavItemWithChildren,
144
+ SidebarItem,
145
+ GenerateOptions,
146
+ LocaleTranslations,
147
+ } from './integrations/vitepress.js';