opencode-translate 1.0.6 → 2.0.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.
Files changed (45) hide show
  1. package/README.md +77 -6
  2. package/dist/index.js +873 -0
  3. package/index.d.ts +5 -0
  4. package/package.json +15 -16
  5. package/src/activation/chat-message.ts +0 -189
  6. package/src/activation/index.ts +0 -38
  7. package/src/activation/logging.ts +0 -11
  8. package/src/activation/messages-transform.ts +0 -44
  9. package/src/activation/metadata.ts +0 -41
  10. package/src/activation/parts.ts +0 -46
  11. package/src/activation/question-hooks.ts +0 -126
  12. package/src/activation/state.ts +0 -97
  13. package/src/activation/text-complete.ts +0 -50
  14. package/src/activation/trigger.ts +0 -57
  15. package/src/activation/types.ts +0 -47
  16. package/src/activation.ts +0 -1
  17. package/src/anthropic-oauth.ts +0 -148
  18. package/src/auth/codex-request.ts +0 -108
  19. package/src/auth/codex-response.ts +0 -78
  20. package/src/auth/codex-shared.ts +0 -3
  21. package/src/auth/headers.ts +0 -18
  22. package/src/auth/index.ts +0 -177
  23. package/src/auth/oauth-fetch.ts +0 -100
  24. package/src/auth/refresh.ts +0 -102
  25. package/src/auth/retry.ts +0 -70
  26. package/src/auth/store.ts +0 -98
  27. package/src/auth/types.ts +0 -27
  28. package/src/auth.ts +0 -1
  29. package/src/constants/errors.ts +0 -24
  30. package/src/constants/guards.ts +0 -33
  31. package/src/constants/options.ts +0 -55
  32. package/src/constants/plugin.ts +0 -9
  33. package/src/constants/types.ts +0 -159
  34. package/src/constants.ts +0 -5
  35. package/src/formatting.ts +0 -157
  36. package/src/index.ts +0 -7
  37. package/src/labels.ts +0 -3
  38. package/src/prompts.ts +0 -123
  39. package/src/question-tool.ts +0 -234
  40. package/src/translator/index.ts +0 -172
  41. package/src/translator/part-id.ts +0 -43
  42. package/src/translator/provider.ts +0 -411
  43. package/src/translator/retry.ts +0 -62
  44. package/src/translator/types.ts +0 -24
  45. package/src/translator.ts +0 -1
@@ -1,411 +0,0 @@
1
- import { type AuthInfo, type FetchLike, PLUGIN_NAME, type ProviderInfo, type ProviderModelInfo } from "../constants"
2
-
3
- const providerFactoryCache = new Map<string, unknown>()
4
-
5
- const PROVIDER_PACKAGE_FALLBACK: Record<string, string> = {
6
- anthropic: "@ai-sdk/anthropic",
7
- openai: "@ai-sdk/openai",
8
- google: "@ai-sdk/google",
9
- "google-vertex": "@ai-sdk/google-vertex",
10
- "amazon-bedrock": "@ai-sdk/amazon-bedrock",
11
- "github-copilot": "@ai-sdk/openai-compatible",
12
- }
13
-
14
- const CREATE_EXPORT_FALLBACK: Record<string, string[]> = {
15
- "@ai-sdk/amazon-bedrock": ["createAmazonBedrock", "bedrock"],
16
- "@ai-sdk/anthropic": ["createAnthropic", "anthropic"],
17
- "@ai-sdk/azure": ["createAzure", "azure"],
18
- "@ai-sdk/gateway": ["createGateway", "gateway"],
19
- "@ai-sdk/google": ["createGoogleGenerativeAI", "google"],
20
- "@ai-sdk/google-vertex": ["createVertex", "vertex"],
21
- "@ai-sdk/openai": ["createOpenAI", "openai"],
22
- "@ai-sdk/openai-compatible": ["createOpenAICompatible"],
23
- "@openrouter/ai-sdk-provider": ["createOpenRouter", "openrouter"],
24
- }
25
-
26
- const PROVIDER_OPTIONS_KEY: Record<string, string> = {
27
- "@ai-sdk/amazon-bedrock": "bedrock",
28
- "@ai-sdk/amazon-bedrock/mantle": "openai",
29
- "@ai-sdk/anthropic": "anthropic",
30
- "@ai-sdk/azure": "openai",
31
- "@ai-sdk/gateway": "gateway",
32
- "@ai-sdk/github-copilot": "openai",
33
- "@ai-sdk/google": "google",
34
- "@ai-sdk/google-vertex": "vertex",
35
- "@ai-sdk/google-vertex/anthropic": "anthropic",
36
- "@ai-sdk/openai": "openai",
37
- "@openrouter/ai-sdk-provider": "openrouter",
38
- "ai-gateway-provider": "openaiCompatible",
39
- }
40
-
41
- type JsonValue = null | string | number | boolean | JsonObject | JsonArray
42
- type JsonObject = { [key: string]: JsonValue | undefined }
43
- type JsonArray = JsonValue[]
44
- type VariantProviderOptions = Record<string, JsonObject>
45
-
46
- interface ProviderCredentials {
47
- provider?: ProviderInfo
48
- authInfo?: AuthInfo
49
- apiKey?: string
50
- fetch?: FetchLike
51
- }
52
-
53
- export function __resetProviderFactoryCacheForTest() {
54
- providerFactoryCache.clear()
55
- }
56
-
57
- function providerPackage(providerID: string, model?: ProviderModelInfo): string {
58
- const packageName = model?.api?.npm || PROVIDER_PACKAGE_FALLBACK[providerID]
59
- if (!packageName) throw new Error(`Unsupported translator provider "${providerID}"`)
60
- return packageName
61
- }
62
-
63
- function pickFactory(mod: Record<string, unknown>, packageName: string): unknown {
64
- for (const key of CREATE_EXPORT_FALLBACK[packageName] ?? []) {
65
- if (typeof mod[key] === "function") return mod[key]
66
- }
67
- const createKey = Object.keys(mod).find((key) => key.startsWith("create") && typeof mod[key] === "function")
68
- return createKey ? mod[createKey] : undefined
69
- }
70
-
71
- export async function loadFactory(providerID: string, model?: ProviderModelInfo): Promise<unknown> {
72
- const packageName = providerPackage(providerID, model)
73
- const cached = providerFactoryCache.get(packageName)
74
- if (cached) return cached
75
-
76
- let mod: Record<string, unknown>
77
- try {
78
- mod = (await import(packageName)) as Record<string, unknown>
79
- } catch (error) {
80
- throw new Error(`Unable to load provider package "${packageName}" for "${providerID}": ${String(error)}`)
81
- }
82
- const factory = pickFactory(mod, packageName)
83
-
84
- if (typeof factory !== "function") {
85
- throw new Error(`Unable to load provider factory from "${packageName}" for "${providerID}"`)
86
- }
87
-
88
- providerFactoryCache.set(packageName, factory)
89
- return factory
90
- }
91
-
92
- export function resolveModelInfo(provider: ProviderInfo | undefined, modelID: string): ProviderModelInfo {
93
- return provider?.models?.[modelID] ?? { id: modelID, api: { id: modelID } }
94
- }
95
-
96
- function sdkProviderOptionsKey(providerID: string, model?: ProviderModelInfo): string {
97
- const packageName = model?.api?.npm
98
- if (packageName && PROVIDER_OPTIONS_KEY[packageName]) return PROVIDER_OPTIONS_KEY[packageName]
99
- if (packageName === "@ai-sdk/openai-compatible" || packageName === "@ai-sdk/openai") return providerID.split(".")[0]
100
- return providerID
101
- }
102
-
103
- function invalidVariantError(providerID: string, modelID: string, model: ProviderModelInfo, variant: string) {
104
- const variants = Object.keys(model.variants ?? {}).sort()
105
- const modelName = `${providerID}/${modelID}`
106
- if (variants.length === 0) {
107
- return new Error(
108
- `[${PLUGIN_NAME}:INVALID_VARIANT] options.variant "${variant}" is not available for "${modelName}". This model has no configurable variants.`,
109
- )
110
- }
111
- return new Error(
112
- `[${PLUGIN_NAME}:INVALID_VARIANT] options.variant "${variant}" is not available for "${modelName}". Available variants: ${variants.join(", ")}.`,
113
- )
114
- }
115
-
116
- export function buildVariantProviderOptions(
117
- providerID: string,
118
- modelID: string,
119
- model: ProviderModelInfo,
120
- variant?: string,
121
- ): VariantProviderOptions | undefined {
122
- if (!variant) return undefined
123
- const selected = model.variants?.[variant]
124
- if (!selected) throw invalidVariantError(providerID, modelID, model, variant)
125
- const providerOptions = selected as JsonObject
126
- if (model.api?.npm === "@ai-sdk/azure") return { openai: providerOptions, azure: providerOptions }
127
- return { [sdkProviderOptionsKey(providerID, model)]: providerOptions }
128
- }
129
-
130
- function headerRecord(value: unknown): Record<string, string> {
131
- if (!value || typeof value !== "object" || Array.isArray(value)) return {}
132
- return Object.fromEntries(
133
- Object.entries(value as Record<string, unknown>).filter((entry): entry is [string, string] => {
134
- return typeof entry[1] === "string"
135
- }),
136
- )
137
- }
138
-
139
- function substitutionVars(options: Record<string, unknown>, authInfo?: AuthInfo): Record<string, string | undefined> {
140
- const metadata = authInfo?.type === "api" ? authInfo.metadata : undefined
141
- const location =
142
- stringOption(options.location) ?? process.env.GOOGLE_VERTEX_LOCATION ?? process.env.GOOGLE_CLOUD_LOCATION
143
- const vertexEndpoint =
144
- location === "global" ? "aiplatform.googleapis.com" : location ? `${location}-aiplatform.googleapis.com` : undefined
145
- return {
146
- ...process.env,
147
- AZURE_RESOURCE_NAME:
148
- stringOption(options.resourceName) ?? metadata?.resourceName ?? process.env.AZURE_RESOURCE_NAME,
149
- GOOGLE_VERTEX_PROJECT:
150
- stringOption(options.project) ??
151
- process.env.GOOGLE_VERTEX_PROJECT ??
152
- process.env.GOOGLE_CLOUD_PROJECT ??
153
- process.env.GCP_PROJECT ??
154
- process.env.GCLOUD_PROJECT,
155
- GOOGLE_VERTEX_LOCATION: location,
156
- GOOGLE_VERTEX_ENDPOINT: vertexEndpoint ?? process.env.GOOGLE_VERTEX_ENDPOINT,
157
- CLOUDFLARE_ACCOUNT_ID: metadata?.accountId ?? process.env.CLOUDFLARE_ACCOUNT_ID,
158
- CLOUDFLARE_GATEWAY_ID: metadata?.gatewayId ?? process.env.CLOUDFLARE_GATEWAY_ID,
159
- }
160
- }
161
-
162
- function stringOption(value: unknown): string | undefined {
163
- return typeof value === "string" && value.length > 0 ? value : undefined
164
- }
165
-
166
- function resolveBaseURL(baseURL: unknown, apiURL: unknown, options: Record<string, unknown>, authInfo?: AuthInfo) {
167
- let url = stringOption(baseURL) ?? stringOption(apiURL)
168
- if (!url) return undefined
169
- const vars = substitutionVars(options, authInfo)
170
- url = url.replace(/\$\{([^}]+)\}/g, (match, key) => vars[String(key)] ?? match)
171
- return url
172
- }
173
-
174
- function wrapSSE(response: Response, ms: number, controller: AbortController) {
175
- if (typeof ms !== "number" || ms <= 0) return response
176
- if (!response.body) return response
177
- if (!response.headers.get("content-type")?.includes("text/event-stream")) return response
178
-
179
- const reader = response.body.getReader()
180
- const body = new ReadableStream<Uint8Array>({
181
- async pull(ctrl) {
182
- const part = await new Promise<Awaited<ReturnType<typeof reader.read>>>((resolve, reject) => {
183
- const id = setTimeout(() => {
184
- const error = new Error("SSE read timed out")
185
- controller.abort(error)
186
- void reader.cancel(error)
187
- reject(error)
188
- }, ms)
189
-
190
- reader.read().then(
191
- (value) => {
192
- clearTimeout(id)
193
- resolve(value)
194
- },
195
- (error) => {
196
- clearTimeout(id)
197
- reject(error)
198
- },
199
- )
200
- })
201
-
202
- if (part.done) {
203
- ctrl.close()
204
- return
205
- }
206
-
207
- ctrl.enqueue(part.value)
208
- },
209
- async cancel(reason) {
210
- controller.abort(reason)
211
- await reader.cancel(reason)
212
- },
213
- })
214
-
215
- return new Response(body, {
216
- headers: new Headers(response.headers),
217
- status: response.status,
218
- statusText: response.statusText,
219
- })
220
- }
221
-
222
- function anySignal(signals: AbortSignal[]): AbortSignal | undefined {
223
- if (signals.length === 0) return undefined
224
- if (signals.length === 1) return signals[0]
225
- const signalAny = (AbortSignal as typeof AbortSignal & { any?: (signals: AbortSignal[]) => AbortSignal }).any
226
- return signalAny ? signalAny(signals) : signals[0]
227
- }
228
-
229
- function stripOpenAIItemIDs(packageName: string, init: RequestInit) {
230
- if (packageName !== "@ai-sdk/openai" && packageName !== "@ai-sdk/azure") return
231
- if (!init.body || init.method !== "POST" || typeof init.body !== "string") return
232
- try {
233
- const body = JSON.parse(init.body) as Record<string, unknown>
234
- if (body.store === true || !Array.isArray(body.input)) return
235
- for (const item of body.input) {
236
- if (item && typeof item === "object" && !Array.isArray(item)) delete (item as Record<string, unknown>).id
237
- }
238
- init.body = JSON.stringify(body)
239
- } catch {}
240
- }
241
-
242
- function withOpenCodeFetch(config: Record<string, unknown>, packageName: string) {
243
- const configuredFetch = typeof config.fetch === "function" ? (config.fetch as FetchLike) : undefined
244
- const chunkTimeout = typeof config.chunkTimeout === "number" ? config.chunkTimeout : undefined
245
- delete config.chunkTimeout
246
-
247
- config.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
248
- const requestInit = { ...(init ?? {}) }
249
- const signals: AbortSignal[] = []
250
- const chunkController = chunkTimeout && chunkTimeout > 0 ? new AbortController() : undefined
251
- if (requestInit.signal) signals.push(requestInit.signal)
252
- if (chunkController) signals.push(chunkController.signal)
253
- if (typeof config.timeout === "number" && config.timeout > 0) signals.push(AbortSignal.timeout(config.timeout))
254
- const signal = anySignal(signals)
255
- if (signal) requestInit.signal = signal
256
- stripOpenAIItemIDs(packageName, requestInit)
257
-
258
- const response = await (configuredFetch ?? fetch)(input, { ...requestInit, timeout: false } as RequestInit)
259
- return chunkController && chunkTimeout ? wrapSSE(response, chunkTimeout, chunkController) : response
260
- }
261
- }
262
-
263
- function providerConfig(
264
- providerID: string,
265
- credentials: ProviderCredentials,
266
- model?: ProviderModelInfo,
267
- ): Record<string, unknown> {
268
- const provider = credentials.provider
269
- const packageName = providerPackage(providerID, model)
270
- const config: Record<string, unknown> = { ...(provider?.options ?? {}) }
271
-
272
- if (providerID === "google-vertex" && !packageName.includes("@ai-sdk/openai-compatible")) delete config.fetch
273
- if (packageName.includes("@ai-sdk/openai-compatible") && config.includeUsage !== false) config.includeUsage = true
274
-
275
- const baseURL = resolveBaseURL(config.baseURL, model?.api?.url, config, credentials.authInfo)
276
- if (baseURL !== undefined) config.baseURL = baseURL
277
- if (credentials.apiKey !== undefined) config.apiKey = credentials.apiKey
278
- if (credentials.fetch) config.fetch = credentials.fetch
279
- if (model?.headers) config.headers = { ...headerRecord(config.headers), ...model.headers }
280
- if (providerID === "github-copilot" && config.baseURL === undefined) config.baseURL = "https://api.githubcopilot.com"
281
- if (
282
- providerID === "amazon-bedrock" &&
283
- credentials.authInfo?.type === "api" &&
284
- !process.env.AWS_BEARER_TOKEN_BEDROCK
285
- ) {
286
- process.env.AWS_BEARER_TOKEN_BEDROCK = credentials.authInfo.key
287
- }
288
-
289
- withOpenCodeFetch(config, packageName)
290
- return { name: providerID, ...config }
291
- }
292
-
293
- export function instantiateProvider(
294
- factory: unknown,
295
- providerID: string,
296
- credentials: ProviderCredentials,
297
- model?: ProviderModelInfo,
298
- ): unknown {
299
- if (typeof factory !== "function") throw new Error(`Invalid provider factory for "${providerID}"`)
300
- return (factory as (config: Record<string, unknown>) => unknown)(providerConfig(providerID, credentials, model))
301
- }
302
-
303
- function shouldUseCopilotResponsesApi(modelID: string): boolean {
304
- const match = /^gpt-(\d+)/.exec(modelID)
305
- if (!match) return false
306
- return Number(match[1]) >= 5 && !modelID.startsWith("gpt-5-mini")
307
- }
308
-
309
- function selectAzureLanguageModel(record: Record<string, unknown>, modelID: string, useChat: boolean): unknown {
310
- if (useChat && typeof record.chat === "function") return (record.chat as (id: string) => unknown)(modelID)
311
- if (typeof record.responses === "function") return (record.responses as (id: string) => unknown)(modelID)
312
- if (typeof record.messages === "function") return (record.messages as (id: string) => unknown)(modelID)
313
- if (typeof record.chat === "function") return (record.chat as (id: string) => unknown)(modelID)
314
- if (typeof record.languageModel === "function") return (record.languageModel as (id: string) => unknown)(modelID)
315
- }
316
-
317
- function bedrockModelID(modelID: string, region: unknown): string {
318
- const crossRegionPrefixes = ["global.", "us.", "eu.", "jp.", "apac.", "au."]
319
- if (crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))) return modelID
320
- if (typeof region !== "string") return modelID
321
-
322
- let regionPrefix = region.split("-")[0]
323
- if (regionPrefix === "us") {
324
- const modelRequiresPrefix = [
325
- "nova-micro",
326
- "nova-lite",
327
- "nova-pro",
328
- "nova-premier",
329
- "nova-2",
330
- "claude",
331
- "deepseek",
332
- ].some((value) => modelID.includes(value))
333
- if (modelRequiresPrefix && !region.startsWith("us-gov")) return `${regionPrefix}.${modelID}`
334
- }
335
- if (regionPrefix === "eu") {
336
- const regionRequiresPrefix = [
337
- "eu-west-1",
338
- "eu-west-2",
339
- "eu-west-3",
340
- "eu-north-1",
341
- "eu-central-1",
342
- "eu-south-1",
343
- "eu-south-2",
344
- ].some((value) => region.includes(value))
345
- const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "llama3", "pixtral"].some((value) =>
346
- modelID.includes(value),
347
- )
348
- if (regionRequiresPrefix && modelRequiresPrefix) return `${regionPrefix}.${modelID}`
349
- }
350
- if (regionPrefix === "ap") {
351
- const isAustraliaRegion = ["ap-southeast-2", "ap-southeast-4"].includes(region)
352
- const isTokyoRegion = region === "ap-northeast-1"
353
- if (
354
- isAustraliaRegion &&
355
- ["anthropic.claude-sonnet-4-5", "anthropic.claude-haiku"].some((value) => modelID.includes(value))
356
- ) {
357
- regionPrefix = "au"
358
- return `${regionPrefix}.${modelID}`
359
- }
360
- const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((value) =>
361
- modelID.includes(value),
362
- )
363
- if (modelRequiresPrefix) return `${isTokyoRegion ? "jp" : "apac"}.${modelID}`
364
- }
365
- return modelID
366
- }
367
-
368
- export function instantiateModel(
369
- provider: unknown,
370
- modelID: string,
371
- providerID?: string,
372
- model?: ProviderModelInfo,
373
- providerOptions?: Record<string, unknown>,
374
- ): unknown {
375
- const apiID = model?.api?.id || model?.id || modelID
376
- if (typeof provider === "function") return provider(modelID)
377
- if (provider && typeof provider === "object") {
378
- const record = provider as Record<string, unknown>
379
- if ((providerID === "openai" || providerID === "xai") && typeof record.responses === "function") {
380
- return (record.responses as (id: string) => unknown)(apiID)
381
- }
382
- if (
383
- providerID === "github-copilot" &&
384
- typeof record.responses === "function" &&
385
- typeof record.chat === "function"
386
- ) {
387
- return shouldUseCopilotResponsesApi(apiID)
388
- ? (record.responses as (id: string) => unknown)(apiID)
389
- : (record.chat as (id: string) => unknown)(apiID)
390
- }
391
- if (providerID === "azure" || providerID === "azure-cognitive-services") {
392
- const selected = selectAzureLanguageModel(record, apiID, providerOptions?.useCompletionUrls === true)
393
- if (selected) return selected
394
- }
395
- if (providerID === "amazon-bedrock" && typeof record.languageModel === "function") {
396
- return (record.languageModel as (id: string) => unknown)(bedrockModelID(apiID, providerOptions?.region))
397
- }
398
- if (typeof record.chatModel === "function") return (record.chatModel as (id: string) => unknown)(modelID)
399
- if (typeof record.languageModel === "function") return (record.languageModel as (id: string) => unknown)(apiID)
400
- if (typeof record.chat === "function") return (record.chat as (id: string) => unknown)(apiID)
401
- if (typeof record.responses === "function") return (record.responses as (id: string) => unknown)(apiID)
402
- }
403
- throw new Error(`Unable to instantiate model "${modelID}"`)
404
- }
405
-
406
- export function supportsTemperature(providerID: string, modelID: string, model?: ProviderModelInfo): boolean {
407
- if (typeof model?.capabilities?.temperature === "boolean") return model.capabilities.temperature
408
- if (providerID !== "openai") return true
409
- if (modelID.startsWith("o1") || modelID.startsWith("o3") || modelID.startsWith("o4-mini")) return false
410
- return !(modelID.startsWith("gpt-5") && !modelID.startsWith("gpt-5-chat"))
411
- }
@@ -1,62 +0,0 @@
1
- import { normalizeReason } from "../constants"
2
-
3
- function getStatus(error: unknown): number | undefined {
4
- if (!error || typeof error !== "object") return undefined
5
- const record = error as Record<string, unknown>
6
- if (typeof record.status === "number") return record.status
7
- if (typeof record.statusCode === "number") return record.statusCode
8
- const response = record.response
9
- if (response && typeof response === "object") {
10
- const status = (response as Record<string, unknown>).status
11
- if (typeof status === "number") return status
12
- }
13
- return undefined
14
- }
15
-
16
- function getRetryAfterMs(error: unknown): number {
17
- if (!error || typeof error !== "object") return 2000
18
- const response = (error as Record<string, unknown>).response
19
- if (!response || typeof response !== "object") return 2000
20
- const headers = (response as { headers?: Headers }).headers
21
- if (!(headers instanceof Headers)) return 2000
22
- const retryAfter = headers.get("retry-after")
23
- if (!retryAfter) return 2000
24
- const seconds = Number(retryAfter)
25
- if (Number.isFinite(seconds)) return Math.max(0, seconds * 1000)
26
- const date = Date.parse(retryAfter)
27
- return Number.isFinite(date) ? Math.max(0, date - Date.now()) : 2000
28
- }
29
-
30
- function isRetryable(error: unknown): boolean {
31
- const status = getStatus(error)
32
- if (status === 429) return true
33
- if (status !== undefined) return status >= 500
34
- const message = normalizeReason(error).toLowerCase()
35
- return (
36
- message.includes("network") ||
37
- message.includes("fetch") ||
38
- message.includes("timeout") ||
39
- message.includes("socket") ||
40
- message.includes("econn")
41
- )
42
- }
43
-
44
- export async function withRetry<T>(task: () => Promise<T>, sleepImpl: (ms: number) => Promise<void>): Promise<T> {
45
- let lastError: unknown
46
- for (let attempt = 0; attempt < 3; attempt += 1) {
47
- try {
48
- return await task()
49
- } catch (error) {
50
- lastError = error
51
- if (!isRetryable(error)) throw error
52
- if (getStatus(error) === 429) {
53
- if (attempt >= 1) throw error
54
- await sleepImpl(getRetryAfterMs(error))
55
- continue
56
- }
57
- if (attempt >= 2) throw error
58
- await sleepImpl(attempt === 0 ? 500 : 1500)
59
- }
60
- }
61
- throw lastError
62
- }
@@ -1,24 +0,0 @@
1
- import type { generateText } from "ai"
2
- import type { createCredentialResolver } from "../auth"
3
-
4
- export interface TranslatorDependencies {
5
- generateTextImpl?: typeof generateText
6
- sleep?: (ms: number) => Promise<void>
7
- now?: () => number
8
- credentialResolver?: ReturnType<typeof createCredentialResolver>
9
- timeoutMs?: number
10
- }
11
-
12
- export interface TranslateTextInput {
13
- text: string
14
- sourceLanguage: string
15
- targetLanguage: string
16
- direction: "inbound" | "outbound"
17
- }
18
-
19
- export interface TranslateTextsInput {
20
- texts: readonly string[]
21
- sourceLanguage: string
22
- targetLanguage: string
23
- direction: "inbound" | "outbound"
24
- }
package/src/translator.ts DELETED
@@ -1 +0,0 @@
1
- export * from "./translator/index"