@l10nmonster/helpers-anthropic 3.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # L10nMonster Anthropic Helper
2
+
3
+ This package provides integration between L10nMonster and Anthropic's Claude models via both direct API and Google Vertex AI.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @l10nmonster/helpers-anthropic
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Direct API Configuration
14
+
15
+ ```javascript
16
+ import { AnthropicAgent } from '@l10nmonster/helpers-anthropic';
17
+
18
+ const agent = new AnthropicAgent({
19
+ id: 'claude-translator',
20
+ model: 'claude-3-5-sonnet-latest',
21
+ quality: 80,
22
+ temperature: 0.1,
23
+ maxTokens: 4096,
24
+ apiKey: 'your-anthropic-api-key' // Direct API access
25
+ });
26
+ ```
27
+
28
+ ### Vertex AI Configuration
29
+
30
+ ```javascript
31
+ import { AnthropicAgent } from '@l10nmonster/helpers-anthropic';
32
+
33
+ const agent = new AnthropicAgent({
34
+ id: 'claude-translator',
35
+ model: 'claude-3-5-sonnet@20241022',
36
+ quality: 80,
37
+ temperature: 0.1,
38
+ maxTokens: 4096,
39
+ vertexProject: 'your-gcp-project-id',
40
+ vertexLocation: 'us-central1'
41
+ });
42
+ ```
43
+
44
+ ### Authentication
45
+
46
+ The AnthropicAgent supports two authentication methods:
47
+
48
+ #### Direct API
49
+ 1. **API Key**: Obtain an API key from [Anthropic Console](https://console.anthropic.com/)
50
+ 2. **Set apiKey**: Pass your API key in the configuration
51
+
52
+ #### Vertex AI
53
+ 1. **Service Account**: Set up a service account with Vertex AI permissions
54
+ 2. **gcloud CLI**: Run `gcloud auth login` and `gcloud config set project YOUR_PROJECT_ID`
55
+ 3. **Environment Variables**: Set `GOOGLE_APPLICATION_CREDENTIALS` to point to your service account key file
56
+
57
+ ### Retry Behavior
58
+
59
+ The AnthropicAgent uses the native retry mechanism built into both the Anthropic SDK and Anthropic Vertex SDK:
60
+
61
+ - **Automatic Retries**: Both SDKs automatically handle retries with exponential backoff
62
+ - **Configurable**: Set `maxRetries` in the constructor to control retry attempts (passed directly to both SDKs)
63
+ - **Smart Error Handling**: Automatically retries on network errors, rate limits, and temporary service issues
64
+ - **No Manual Implementation**: Unlike other providers, this uses the SDK's native retry logic for better reliability
65
+ - **Consistent Behavior**: The same `maxRetries` value is used whether you're using direct API or Vertex AI
66
+
67
+ ### Configuration Options
68
+
69
+ - `model` (required): The Claude model to use
70
+ - `quality` (required): Quality score for translations (0-100)
71
+ - `apiKey`: Your Anthropic API key (for direct API access)
72
+ - `temperature`: Controls randomness (0.0-1.0, default: 0.1)
73
+ - `maxTokens`: Maximum output tokens (default: 4096)
74
+ - `maxRetries`: Maximum number of retries (passed to Anthropic SDK)
75
+ - `vertexProject`: GCP project ID (for Vertex AI, auto-detected if not provided)
76
+ - `vertexLocation`: GCP region (for Vertex AI, default: 'global')
77
+ - `persona`: Custom translator persona (optional)
78
+ - `customSchema`: Custom response schema (optional)
79
+
80
+ ## Testing
81
+
82
+ Run the test suite using Node.js built-in testing:
83
+
84
+ ```bash
85
+ # From the package directory
86
+ npm test
87
+
88
+ # From the workspace root
89
+ npm test --workspace=helpers-anthropic
90
+ ```
91
+
92
+ The test suite includes:
93
+ - Unit tests for all major functionality
94
+ - Integration tests with the LLMTranslationProvider inheritance
95
+ - Error handling and edge case scenarios
96
+ - Mock testing without external API calls
97
+
98
+ ## Requirements
99
+
100
+ - Node.js >= 18.0.0
101
+ - Google Cloud Project with Vertex AI API enabled
102
+ - Proper authentication setup for Google Cloud
103
+
104
+ ## License
105
+
106
+ MIT
@@ -0,0 +1,183 @@
1
+ import { AnthropicVertex } from '@anthropic-ai/vertex-sdk';
2
+ import Anthropic from '@anthropic-ai/sdk';
3
+ import { GoogleAuth } from 'google-auth-library';
4
+
5
+ import { logInfo, logVerbose, logWarn, providers, styleString } from '../core/index.js';
6
+
7
+ const TRANSLATION_TOOL = {
8
+ name: 'provide_translations',
9
+ description: 'Provide translations for the given strings',
10
+ input_schema: {
11
+ type: 'object',
12
+ properties: {
13
+ translations: {
14
+ type: 'array',
15
+ items: {
16
+ type: 'object',
17
+ properties: {
18
+ translation: { type: 'string', description: 'the translated string' },
19
+ confidence: { type: 'number', description: 'a confidence score between 0 and 100' },
20
+ notes: { type: 'string', description: 'any additional notes about the translation' }
21
+ },
22
+ required: ['translation', 'confidence', 'notes']
23
+ }
24
+ }
25
+ },
26
+ required: ['translations']
27
+ }
28
+ };
29
+
30
+ /**
31
+ * @typedef {object} AnthropicAgentOptions
32
+ * @extends LLMTranslationProviderOptions
33
+ * @property {string} [apiKey] - The Anthropic API key (if using direct API).
34
+ * @property {string} [vertexProject] - The VertexAI project ID.
35
+ * @property {string} [vertexLocation] - The VertexAI datacenter location.
36
+ * @property {number} [maxTokens] - Maximum number of output tokens (32000 by default)
37
+ */
38
+
39
+ /**
40
+ * Provider for Anthropic Claude LLMs via Vertex AI or direct API.
41
+ */
42
+ export class AnthropicAgent extends providers.LLMTranslationProvider {
43
+ #client;
44
+ #apiKey;
45
+ #vertexProject;
46
+ #vertexLocation;
47
+ #maxTokens;
48
+ #maxRetries;
49
+
50
+ /**
51
+ * Initializes a new instance of the AnthropicAgent class.
52
+ * @param {AnthropicAgentOptions} options - Configuration options for the provider.
53
+ */
54
+ constructor({ apiKey, vertexProject, vertexLocation, maxTokens, maxRetries, ...options }) {
55
+ super({...options, maxRetries: 0}); // bypass our own retry logic since Anthropic SDK has built-in support
56
+ this.#apiKey = apiKey;
57
+ this.#vertexProject = vertexProject;
58
+ this.#vertexLocation = vertexLocation ?? 'us-east5';
59
+ this.#maxTokens = maxTokens ?? 32000;
60
+ this.#maxRetries = maxRetries ?? 2;
61
+ }
62
+
63
+ // we initialize on first use so that constructor is fast and doesn't fail if auth is missing
64
+ // also, we need this to be async so that we can await for projectId if it's not provided
65
+ async lazyInit() {
66
+ if (this.#client) {
67
+ return;
68
+ }
69
+ if (this.#apiKey) {
70
+ // Direct Anthropic API
71
+ this.#client = new Anthropic({
72
+ apiKey: this.#apiKey,
73
+ maxRetries: this.#maxRetries,
74
+ timeout: 15 * 60000, // 15 minutes
75
+ });
76
+ logInfo`AnthropicAgent ${this.id} initialized with direct Anthropic API`;
77
+ } else {
78
+ if (!this.#vertexProject) {
79
+ try {
80
+ const auth = new GoogleAuth({});
81
+ this.#vertexProject = await auth.getProjectId();
82
+ } catch (e) {
83
+ throw new Error(`Couldn't get credentials, did you run 'gcloud auth login'?\n${e.message}`);
84
+ }
85
+ }
86
+ this.#client = new AnthropicVertex({
87
+ projectId: this.#vertexProject,
88
+ region: this.#vertexLocation,
89
+ maxRetries: this.#maxRetries,
90
+ timeout: 15 * 60000, // 15 minutes
91
+ });
92
+ logInfo`AnthropicAgent ${this.id} initialized with Vertex AI platform (${this.#vertexLocation}/${this.#vertexProject})`;
93
+ }
94
+ }
95
+
96
+ prepareTranslateChunkArgs({ sourceLang, targetLang, xmlTus, instructions }) {
97
+ const userPrompt = this.buildUserPrompt({ sourceLang, targetLang, xmlTus, instructions });
98
+
99
+ const messages = [
100
+ {
101
+ role: 'user',
102
+ content: userPrompt
103
+ }
104
+ ];
105
+
106
+ const toolConfig = this.customSchema ? {
107
+ tools: [{
108
+ name: 'provide_custom_translations',
109
+ description: 'Provide translations using custom schema',
110
+ input_schema: {
111
+ type: 'object',
112
+ properties: {
113
+ translations: {
114
+ type: 'array',
115
+ items: this.customSchema
116
+ }
117
+ },
118
+ required: ['translations']
119
+ }
120
+ }],
121
+ tool_choice: { type: 'tool', name: 'provide_custom_translations' }
122
+ } : {
123
+ tools: [TRANSLATION_TOOL],
124
+ tool_choice: { type: 'tool', name: 'provide_translations' }
125
+ };
126
+
127
+ return {
128
+ model: this.model,
129
+ max_tokens: this.#maxTokens,
130
+ temperature: this.temperature,
131
+ system: this.systemPrompt,
132
+ messages,
133
+ ...toolConfig
134
+ };
135
+ }
136
+
137
+ async generateContent(args) {
138
+ return await this.#client.messages.create(args);
139
+ }
140
+
141
+ convertTranslationResponse(res) {
142
+ try {
143
+ if (res.stop_reason !== 'tool_use') {
144
+ throw new Error(`Unexpected stop reason: ${res.stop_reason}`);
145
+ }
146
+
147
+ // Find the tool use content
148
+ const toolUse = res.content.find(content => content.type === 'tool_use');
149
+ if (!toolUse) {
150
+ throw new Error('No tool use found in response');
151
+ }
152
+
153
+ const translations = toolUse.input.translations;
154
+ if (!Array.isArray(translations)) {
155
+ throw new Error('Invalid translations format');
156
+ }
157
+
158
+ const cost = [
159
+ (res.usage.input_tokens ?? 0) / translations.length,
160
+ (res.usage.output_tokens ?? 0) / translations.length,
161
+ ((res.usage.input_tokens ?? 0) + (res.usage.output_tokens ?? 0)) / translations.length,
162
+ ];
163
+
164
+ return this.processTranslations(translations, cost);
165
+ } catch (e) {
166
+ logWarn`Unexpected convertTranslationResponse error: ${e.message}`;
167
+ return [];
168
+ }
169
+ }
170
+
171
+ async info() {
172
+ const info = await super.info();
173
+ try {
174
+ await this.lazyInit();
175
+ // SDK doesn't support listing models or getting model info on Vertex AI
176
+ const models = ['claude-opus-4-20250514', 'claude-sonnet-4-20250514'];
177
+ info.description.push(styleString`Supported models: ${models.join(', ')}`);
178
+ } catch (e) {
179
+ info.description.push(styleString`Unable to connect to Anthropic server: ${e.cause?.message ?? e.message}`);
180
+ }
181
+ return info;
182
+ }
183
+ }
package/example.js ADDED
@@ -0,0 +1,65 @@
1
+ import { AnthropicAgent } from './index.js';
2
+
3
+ // Example L10nMonster configuration using AnthropicAgent
4
+ export const exampleConfig = {
5
+ translationProviders: [
6
+ // Direct API configuration
7
+ {
8
+ id: 'claude-direct-api',
9
+ provider: AnthropicAgent,
10
+ options: {
11
+ model: 'claude-3-5-sonnet-latest',
12
+ quality: 90,
13
+ temperature: 0.1,
14
+ maxTokens: 4096,
15
+ maxRetries: 3, // Passed to Anthropic SDK for native retry handling
16
+ apiKey: process.env.ANTHROPIC_API_KEY, // Set your API key
17
+ persona: 'You are a professional translator specializing in technical documentation and user interfaces.',
18
+ }
19
+ },
20
+ // Vertex AI configuration
21
+ {
22
+ id: 'claude-vertex-sonnet',
23
+ provider: AnthropicAgent,
24
+ options: {
25
+ model: 'claude-3-5-sonnet@20241022',
26
+ quality: 85,
27
+ temperature: 0.1,
28
+ maxTokens: 4096,
29
+ // vertexProject: 'your-gcp-project-id', // Optional, auto-detected
30
+ vertexLocation: 'us-central1',
31
+ persona: 'You are a professional translator specializing in technical documentation and user interfaces.',
32
+ }
33
+ },
34
+ {
35
+ id: 'claude-vertex-haiku',
36
+ provider: AnthropicAgent,
37
+ options: {
38
+ model: 'claude-3-5-haiku@20241022',
39
+ quality: 80,
40
+ temperature: 0.1,
41
+ maxTokens: 2048,
42
+ vertexLocation: 'us-central1',
43
+ persona: 'You are a fast and efficient translator focused on accuracy and consistency.',
44
+ }
45
+ }
46
+ ],
47
+
48
+ // Example translation jobs configuration
49
+ jobs: [
50
+ {
51
+ id: 'ui-translation',
52
+ translationProvider: 'claude-direct-api',
53
+ instructions: 'Translate user interface strings. Keep labels concise and maintain consistent terminology.',
54
+ },
55
+ {
56
+ id: 'content-translation',
57
+ translationProvider: 'claude-vertex-haiku',
58
+ instructions: 'Translate general content while maintaining the original tone and style.',
59
+ }
60
+ ]
61
+ };
62
+
63
+ // Example usage
64
+ console.log('AnthropicAgent configuration example loaded');
65
+ console.log('Available providers:', exampleConfig.translationProviders.map(p => p.id));
package/index.js ADDED
@@ -0,0 +1 @@
1
+ export { AnthropicAgent } from './anthropicAgent.js';
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@l10nmonster/helpers-anthropic",
3
+ "version": "3.0.0-alpha.1",
4
+ "description": "Anthropic Claude LLM provider for l10nmonster using Vertex AI",
5
+ "type": "module",
6
+ "main": "anthropicAgent.js",
7
+ "scripts": {
8
+ "test": "node --test"
9
+ },
10
+ "dependencies": {
11
+ "@anthropic-ai/vertex-sdk": "latest",
12
+ "@anthropic-ai/sdk": "latest",
13
+ "google-auth-library": "^10"
14
+ },
15
+ "peerDependencies": {
16
+ "@l10nmonster/core": "file:../core"
17
+ },
18
+ "engines": {
19
+ "node": ">=18.0.0"
20
+ },
21
+ "license": "MIT"
22
+ }