@verbatra/sdk 0.5.0-next.0 → 0.5.0-next.2
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 +1 -2
- package/dist/index.cjs +705 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +123 -35
- package/dist/index.d.ts +123 -35
- package/dist/index.js +709 -132
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -36,7 +36,7 @@ type TranslationEntry$1 = Readonly<z.infer<typeof translationEntrySchema$1>>;
|
|
|
36
36
|
* Result of comparing source placeholders against translated-output placeholders as MULTISETS
|
|
37
37
|
* (counts matter). Always returned (never thrown) for an ordinary mismatch.
|
|
38
38
|
*/
|
|
39
|
-
interface PlaceholderIntegrityResult {
|
|
39
|
+
interface PlaceholderIntegrityResult$1 {
|
|
40
40
|
/** True when nothing is missing or extra: the multisets match, regardless of order. */
|
|
41
41
|
readonly matches: boolean;
|
|
42
42
|
/** Occurrences present in source but absent from the translation, one per dropped occurrence. Sorted. */
|
|
@@ -57,6 +57,13 @@ type Tone = "formal" | "informal" | "neutral";
|
|
|
57
57
|
* derives placeholders itself.
|
|
58
58
|
*/
|
|
59
59
|
type PlaceholderExtractor = (value: string) => readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* Compares a source and translated value's placeholders directly, branch-aware, instead of
|
|
62
|
+
* independently extracting each side's flat placeholder list first. Supplied by the caller (the SDK, for
|
|
63
|
+
* a format whose adapter defines one, for example ICU plural/select) so it matches the entries' format;
|
|
64
|
+
* ai-providers never derives it itself and never parses a specific format's message syntax.
|
|
65
|
+
*/
|
|
66
|
+
type PlaceholderComparator = (source: string, translated: string) => PlaceholderIntegrityResult$1;
|
|
60
67
|
/**
|
|
61
68
|
* A batch translation request. Format- and provider-neutral: it carries no prompt,
|
|
62
69
|
* model, key, or other provider-specific field. The placeholder extractor is
|
|
@@ -75,20 +82,62 @@ interface TranslateRequest {
|
|
|
75
82
|
readonly tone?: Tone;
|
|
76
83
|
/** Mandatory placeholder extractor; the output integrity check runs against it. */
|
|
77
84
|
readonly extractPlaceholders: PlaceholderExtractor;
|
|
85
|
+
/**
|
|
86
|
+
* Optional branch-aware placeholder comparator. When present, the output integrity check uses it
|
|
87
|
+
* instead of independently extracting each side's placeholders with {@link extractPlaceholders} and
|
|
88
|
+
* diffing the flat lists. Absent for a format with no plural/select sub-message structure.
|
|
89
|
+
*/
|
|
90
|
+
readonly comparePlaceholders?: PlaceholderComparator;
|
|
91
|
+
/**
|
|
92
|
+
* Optional cancellation signal for this batch. When aborted, an in-flight provider call rejects
|
|
93
|
+
* with the abort, unwrapped, instead of a {@link ProviderError} (see `guardProviderCall`). Not a
|
|
94
|
+
* plain-data field: it is never validated by `requestDataSchema` and never sent to a provider.
|
|
95
|
+
*/
|
|
96
|
+
readonly signal?: AbortSignal;
|
|
78
97
|
}
|
|
79
98
|
/** Token usage, when the provider reports it. Absent for providers without tokens (DeepL). */
|
|
80
99
|
interface Usage {
|
|
81
100
|
readonly inputTokens: number;
|
|
82
101
|
readonly outputTokens: number;
|
|
83
102
|
}
|
|
84
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Stable codes for a provider's graceful-degradation notices. These are returned DATA on a
|
|
105
|
+
* successful result, NOT thrown:
|
|
106
|
+
*
|
|
107
|
+
* - `FORMALITY_DOWNGRADED`: a requested formality was not applied (DeepL's free tier does not
|
|
108
|
+
* support it).
|
|
109
|
+
* - `GLOSSARY_IGNORED`: a supplied generic glossary term map was not applied (DeepL only applies a
|
|
110
|
+
* native glossary id, never a term map).
|
|
111
|
+
* - `PLACEHOLDER_UNSUPPORTED`: at least one placeholder- or ICU-bearing entry was left untranslated
|
|
112
|
+
* because the provider cannot preserve those tokens; such entries are withheld (absent from the
|
|
113
|
+
* result maps) rather than sent to the provider and mangled.
|
|
114
|
+
*/
|
|
115
|
+
type ProviderNoticeCode = "FORMALITY_DOWNGRADED" | "GLOSSARY_IGNORED" | "PLACEHOLDER_UNSUPPORTED";
|
|
116
|
+
/**
|
|
117
|
+
* An observable, structured signal that something was gracefully degraded (not an
|
|
118
|
+
* error). Carries only a stable code and a static message, never a key or content.
|
|
119
|
+
* Surfaced as result data, never thrown; callers inspect it but need not treat it as a failure.
|
|
120
|
+
*/
|
|
121
|
+
interface ProviderNotice {
|
|
122
|
+
/** The stable {@link ProviderNoticeCode} for what was degraded. */
|
|
123
|
+
readonly code: ProviderNoticeCode;
|
|
124
|
+
/** A static, safe description; never a key or translatable content. */
|
|
125
|
+
readonly message: string;
|
|
126
|
+
}
|
|
127
|
+
/** Result of a batch translation: per-key values, per-key integrity outcomes, and any notices. */
|
|
85
128
|
interface TranslateResult {
|
|
86
129
|
/** The translated value for each requested key. */
|
|
87
130
|
readonly values: ReadonlyMap<string, string>;
|
|
88
131
|
/** The placeholder-integrity outcome for each key (source vs translated placeholder sets). */
|
|
89
|
-
readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult>;
|
|
132
|
+
readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult$1>;
|
|
90
133
|
/** Token usage when the provider reports it; absent for token-less providers. */
|
|
91
134
|
readonly usage?: Usage;
|
|
135
|
+
/**
|
|
136
|
+
* Graceful-degradation notices for this batch. Every provider populates this as a present array:
|
|
137
|
+
* DeepL reports real notices (for example `GLOSSARY_IGNORED`); an LLM provider with nothing to
|
|
138
|
+
* report returns an empty array rather than omitting the field.
|
|
139
|
+
*/
|
|
140
|
+
readonly notices?: readonly ProviderNotice[];
|
|
92
141
|
}
|
|
93
142
|
/**
|
|
94
143
|
* The single contract every provider implements. It is narrow enough that a machine-translation API like
|
|
@@ -147,28 +196,6 @@ interface TranslationProvider {
|
|
|
147
196
|
* are still accepted. This drives editor completions only; the runtime schema validates.
|
|
148
197
|
*/
|
|
149
198
|
type AnthropicModel = Anthropic.Messages.Model;
|
|
150
|
-
/**
|
|
151
|
-
* Stable codes for the DeepL graceful-degradation notices, DeepL only. These are returned DATA on a
|
|
152
|
-
* successful result, NOT thrown:
|
|
153
|
-
*
|
|
154
|
-
* - `FORMALITY_DOWNGRADED`: a requested formality was not applied (the free tier does not support it).
|
|
155
|
-
* - `GLOSSARY_IGNORED`: a supplied generic glossary was not applied.
|
|
156
|
-
* - `PLACEHOLDER_UNSUPPORTED`: at least one placeholder- or ICU-bearing entry was left untranslated
|
|
157
|
-
* because DeepL cannot preserve those tokens; such entries are withheld (absent from the result maps)
|
|
158
|
-
* rather than sent to DeepL and mangled.
|
|
159
|
-
*/
|
|
160
|
-
type ProviderNoticeCode = "FORMALITY_DOWNGRADED" | "GLOSSARY_IGNORED" | "PLACEHOLDER_UNSUPPORTED";
|
|
161
|
-
/**
|
|
162
|
-
* An observable, structured signal that something was gracefully degraded (not an
|
|
163
|
-
* error). Carries only a stable code and a static message, never a key or content.
|
|
164
|
-
* Surfaced as result data, never thrown; callers inspect it but need not treat it as a failure.
|
|
165
|
-
*/
|
|
166
|
-
interface ProviderNotice {
|
|
167
|
-
/** The stable {@link ProviderNoticeCode} for what was degraded. */
|
|
168
|
-
readonly code: ProviderNoticeCode;
|
|
169
|
-
/** A static, safe description; never a key or translatable content. */
|
|
170
|
-
readonly message: string;
|
|
171
|
-
}
|
|
172
199
|
|
|
173
200
|
/**
|
|
174
201
|
* The Gemini authoring model type, sourced from the installed SDK's own model union so
|
|
@@ -187,8 +214,9 @@ type OpenAiModel = OpenAI.ChatModel;
|
|
|
187
214
|
|
|
188
215
|
/**
|
|
189
216
|
* The provider section of the config: a discriminated union over the provider id, reusing each
|
|
190
|
-
* provider's own config schema. There is no key field anywhere in this union
|
|
191
|
-
*
|
|
217
|
+
* provider's own config schema. There is no key field anywhere in this union except
|
|
218
|
+
* openai-compatible's optional `apiKeyEnvVar`, which names an environment variable rather than carrying
|
|
219
|
+
* a key value; every provider still reads its actual key from the environment at construction.
|
|
192
220
|
*/
|
|
193
221
|
declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
194
222
|
id: z.ZodLiteral<"anthropic">;
|
|
@@ -213,6 +241,14 @@ declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
213
241
|
options: z.ZodObject<{
|
|
214
242
|
glossaryId: z.ZodOptional<z.ZodString>;
|
|
215
243
|
}, z.core.$strict>;
|
|
244
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
245
|
+
id: z.ZodLiteral<"openai-compatible">;
|
|
246
|
+
options: z.ZodObject<{
|
|
247
|
+
baseUrl: z.ZodURL;
|
|
248
|
+
model: z.ZodString;
|
|
249
|
+
maxOutputTokens: z.ZodNumber;
|
|
250
|
+
apiKeyEnvVar: z.ZodOptional<z.ZodString>;
|
|
251
|
+
}, z.core.$strict>;
|
|
216
252
|
}, z.core.$strip>], "id">;
|
|
217
253
|
type ProviderConfig = z.infer<typeof providerConfigSchema>;
|
|
218
254
|
type ProviderId = ProviderConfig["id"];
|
|
@@ -260,6 +296,14 @@ declare const verbatraConfigSchema: z.ZodObject<{
|
|
|
260
296
|
options: z.ZodObject<{
|
|
261
297
|
glossaryId: z.ZodOptional<z.ZodString>;
|
|
262
298
|
}, z.core.$strict>;
|
|
299
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
300
|
+
id: z.ZodLiteral<"openai-compatible">;
|
|
301
|
+
options: z.ZodObject<{
|
|
302
|
+
baseUrl: z.ZodURL;
|
|
303
|
+
model: z.ZodString;
|
|
304
|
+
maxOutputTokens: z.ZodNumber;
|
|
305
|
+
apiKeyEnvVar: z.ZodOptional<z.ZodString>;
|
|
306
|
+
}, z.core.$strict>;
|
|
263
307
|
}, z.core.$strip>], "id">;
|
|
264
308
|
glossary: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodString]>>;
|
|
265
309
|
tone: z.ZodOptional<z.ZodEnum<{
|
|
@@ -307,6 +351,9 @@ type AuthoringProviderVariant = {
|
|
|
307
351
|
deepl: Extract<ProviderConfig, {
|
|
308
352
|
id: "deepl";
|
|
309
353
|
}>;
|
|
354
|
+
"openai-compatible": Extract<ProviderConfig, {
|
|
355
|
+
id: "openai-compatible";
|
|
356
|
+
}>;
|
|
310
357
|
};
|
|
311
358
|
/**
|
|
312
359
|
* The authoring view of the whole config for a provider id: a {@link VerbatraConfigInput} whose
|
|
@@ -495,7 +542,8 @@ declare function loadConfig(options?: LoadConfigOptions): Promise<VerbatraConfig
|
|
|
495
542
|
* - `SOURCE_UNREADABLE`: the source locale file is absent (thrown by `translate`, and by `watch` at startup).
|
|
496
543
|
* - `SOURCE_INVALID`: the source locale file could not be read or parsed; wraps the adapter read error
|
|
497
544
|
* (thrown by `translate`).
|
|
498
|
-
* - `LOCK_FILE_INVALID`: the lock-file is present but corrupt or
|
|
545
|
+
* - `LOCK_FILE_INVALID`: the lock-file is present but corrupt, oversized, or at an unsupported
|
|
546
|
+
* version (thrown by `translate`, `check`, `diff`, `exportWorkbook`, and `importWorkbook`).
|
|
499
547
|
* - `LOCALE_FAILED` (NOT thrown): the fallback `code` recorded on a failed `LocaleSummary` when a
|
|
500
548
|
* per-locale failure carries no string code of its own. See the surfaced-not-thrown distinction on
|
|
501
549
|
* `translate`.
|
|
@@ -552,6 +600,21 @@ interface LocaleResource {
|
|
|
552
600
|
readonly entries: ReadonlyMap<string, TranslationEntry>;
|
|
553
601
|
}
|
|
554
602
|
|
|
603
|
+
/**
|
|
604
|
+
* Result of comparing source placeholders against translated-output placeholders as MULTISETS
|
|
605
|
+
* (counts matter). Always returned (never thrown) for an ordinary mismatch.
|
|
606
|
+
*/
|
|
607
|
+
interface PlaceholderIntegrityResult {
|
|
608
|
+
/** True when nothing is missing or extra: the multisets match, regardless of order. */
|
|
609
|
+
readonly matches: boolean;
|
|
610
|
+
/** Occurrences present in source but absent from the translation, one per dropped occurrence. Sorted. */
|
|
611
|
+
readonly missing: readonly string[];
|
|
612
|
+
/** Occurrences present in the translation but absent from source, one per surplus occurrence. Sorted. */
|
|
613
|
+
readonly extra: readonly string[];
|
|
614
|
+
/** Same multiset present in both, but in a different order. */
|
|
615
|
+
readonly reordered: boolean;
|
|
616
|
+
}
|
|
617
|
+
|
|
555
618
|
/**
|
|
556
619
|
* The result of reading a file into core's intermediate representation.
|
|
557
620
|
*/
|
|
@@ -628,6 +691,18 @@ interface FormatAdapter {
|
|
|
628
691
|
* unparseable value returns false.
|
|
629
692
|
*/
|
|
630
693
|
validateMessage(value: string): boolean;
|
|
694
|
+
/**
|
|
695
|
+
* Optional branch-aware placeholder comparison for formats with plural/select sub-message structure.
|
|
696
|
+
* When present, callers use it instead of independently extracting each side's placeholders with
|
|
697
|
+
* {@link extractPlaceholders} and diffing the flat lists, since flattening a plural/select value loses
|
|
698
|
+
* which branch a placeholder came from. Absent for every non-ICU adapter, which is compared via
|
|
699
|
+
* `extractPlaceholders` plus `checkPlaceholders` as before.
|
|
700
|
+
*
|
|
701
|
+
* @param sourceValue - The source value.
|
|
702
|
+
* @param targetValue - The translated value to check against it.
|
|
703
|
+
* @returns The merged placeholder-integrity result across every branch. Does not throw.
|
|
704
|
+
*/
|
|
705
|
+
comparePlaceholders?(sourceValue: string, targetValue: string): PlaceholderIntegrityResult;
|
|
631
706
|
}
|
|
632
707
|
|
|
633
708
|
/** Outcome of resolving an adapter for a file. Structured; never throws. */
|
|
@@ -876,11 +951,13 @@ interface LocaleSummary {
|
|
|
876
951
|
*/
|
|
877
952
|
readonly integrityMismatches: readonly string[];
|
|
878
953
|
/**
|
|
879
|
-
* Keys withheld because
|
|
880
|
-
*
|
|
881
|
-
*
|
|
882
|
-
* {@link LocaleSummary.notices} entry carries the secret-free failure code
|
|
883
|
-
*
|
|
954
|
+
* Keys withheld because nothing was translated for them this run, as distinct from a translation
|
|
955
|
+
* that came back and failed the placeholder-integrity check. This covers two causes: the provider
|
|
956
|
+
* call itself failed (for example a revoked API key, a rate limit, or a network timeout), in which
|
|
957
|
+
* case the corresponding {@link LocaleSummary.notices} entry carries the secret-free failure code
|
|
958
|
+
* and message; or the call succeeded but the key was still missing or duplicated in the response
|
|
959
|
+
* after the shared LLM layer's bounded reconcile repair round, in which case no notice is added.
|
|
960
|
+
* Empty in a dry-run.
|
|
884
961
|
*/
|
|
885
962
|
readonly providerFailures: readonly string[];
|
|
886
963
|
/**
|
|
@@ -1108,13 +1185,24 @@ interface LoadLockFileDeps {
|
|
|
1108
1185
|
* @param input - The directory the lock-file resolves against.
|
|
1109
1186
|
* @param deps - Optional composition seam (file system) for tests.
|
|
1110
1187
|
* @returns The parsed lock-file, or an empty lock when none exists yet.
|
|
1111
|
-
* @throws {@link SdkError} `LOCK_FILE_INVALID` when the lock-file is present but corrupt
|
|
1188
|
+
* @throws {@link SdkError} `LOCK_FILE_INVALID` when the lock-file is present but corrupt, oversized,
|
|
1189
|
+
* or at an unsupported version.
|
|
1112
1190
|
*/
|
|
1113
1191
|
declare function loadLockFile(input?: LoadLockFileInput, deps?: LoadLockFileDeps): Promise<LockFile>;
|
|
1114
1192
|
|
|
1115
1193
|
/** The committed lock-file name, chosen to be obviously JSON and to not match a `*.lock` ignore rule. */
|
|
1116
1194
|
declare const LOCK_FILE_NAME = "verbatra.lock.json";
|
|
1117
1195
|
|
|
1196
|
+
/**
|
|
1197
|
+
* The subset of {@link ProviderId} that `init` can scaffold: every provider with a single required
|
|
1198
|
+
* environment variable. "openai-compatible" is deliberately excluded: unlike every other provider it
|
|
1199
|
+
* has no single required environment variable, only a three-tier
|
|
1200
|
+
* apiKeyEnvVar/OPENAI_COMPATIBLE_API_KEY/placeholder fallback (see resolveOpenAiCompatibleKey in
|
|
1201
|
+
* @verbatra/ai-providers), so it does not fit the `providerEnv` table below and `init` scaffolding does
|
|
1202
|
+
* not offer it. This is the single source of truth for the exclusion; other packages import this type
|
|
1203
|
+
* rather than re-deriving `Exclude<ProviderId, "openai-compatible">` themselves.
|
|
1204
|
+
*/
|
|
1205
|
+
type ScaffoldableProviderId = Exclude<ProviderId, "openai-compatible">;
|
|
1118
1206
|
/**
|
|
1119
1207
|
* Read-only metadata the CLI `init` scaffold derives its tables from, so the CLI never restates the
|
|
1120
1208
|
* provider, env-var, model, or format truth owned by core and ai-providers.
|
|
@@ -1229,4 +1317,4 @@ interface WatchController {
|
|
|
1229
1317
|
*/
|
|
1230
1318
|
declare function watch(input: WatchInput, deps?: WatchDeps): Promise<WatchController>;
|
|
1231
1319
|
|
|
1232
|
-
export { type CheckDeps, type CheckInput, type CheckSummary, type ConfigSource, type CreateProvider, type CreateWatcher, DEFAULT_WORKBOOK_PATH, type DiffDeps, type DiffInput, type DiffSummary, type ExportWorkbookDeps, type ExportWorkbookInput, type ExportWorkbookResult, type GlossaryProvenance, type ImportWorkbookDeps, type ImportWorkbookInput, LOCK_FILE_NAME, type LoadConfigOptions, type LoadLockFileDeps, type LoadLockFileInput, type LoadedConfig, type LocaleCheckSummary, type LocaleDiff, type LocaleNotice, type LocaleSummary, type LockFile, type LockLocaleState, type LockStateDeps, type LockStateInput, type LockStateResult, type ProviderConfig, type ProviderId, type RunSummary, type RunTranslate, SdkError, type SdkErrorCode, type SdkFs, type SdkNotice, type SdkNoticeCode, type SupportedFormat$1 as SupportedFormat, type TranslateDeps, type TranslateInput, type VerbatraConfig, type VerbatraConfigInput, type WatchController, type WatchDeps, type WatchInput, type WatchRunResult, type Watcher, check, defineConfig, diff, exportWorkbook, importWorkbook, loadConfig, loadConfigWithMeta, loadLockFile, lockState, scaffoldingMetadata, translate, verbatraConfigSchema, watch };
|
|
1320
|
+
export { type CheckDeps, type CheckInput, type CheckSummary, type ConfigSource, type CreateProvider, type CreateWatcher, DEFAULT_WORKBOOK_PATH, type DiffDeps, type DiffInput, type DiffSummary, type ExportWorkbookDeps, type ExportWorkbookInput, type ExportWorkbookResult, type GlossaryProvenance, type ImportWorkbookDeps, type ImportWorkbookInput, LOCK_FILE_NAME, type LoadConfigOptions, type LoadLockFileDeps, type LoadLockFileInput, type LoadedConfig, type LocaleCheckSummary, type LocaleDiff, type LocaleNotice, type LocaleSummary, type LockFile, type LockLocaleState, type LockStateDeps, type LockStateInput, type LockStateResult, type ProviderConfig, type ProviderId, type RunSummary, type RunTranslate, type ScaffoldableProviderId, SdkError, type SdkErrorCode, type SdkFs, type SdkNotice, type SdkNoticeCode, type SupportedFormat$1 as SupportedFormat, type TranslateDeps, type TranslateInput, type VerbatraConfig, type VerbatraConfigInput, type WatchController, type WatchDeps, type WatchInput, type WatchRunResult, type Watcher, check, defineConfig, diff, exportWorkbook, importWorkbook, loadConfig, loadConfigWithMeta, loadLockFile, lockState, scaffoldingMetadata, translate, verbatraConfigSchema, watch };
|
package/dist/index.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ type TranslationEntry$1 = Readonly<z.infer<typeof translationEntrySchema$1>>;
|
|
|
36
36
|
* Result of comparing source placeholders against translated-output placeholders as MULTISETS
|
|
37
37
|
* (counts matter). Always returned (never thrown) for an ordinary mismatch.
|
|
38
38
|
*/
|
|
39
|
-
interface PlaceholderIntegrityResult {
|
|
39
|
+
interface PlaceholderIntegrityResult$1 {
|
|
40
40
|
/** True when nothing is missing or extra: the multisets match, regardless of order. */
|
|
41
41
|
readonly matches: boolean;
|
|
42
42
|
/** Occurrences present in source but absent from the translation, one per dropped occurrence. Sorted. */
|
|
@@ -57,6 +57,13 @@ type Tone = "formal" | "informal" | "neutral";
|
|
|
57
57
|
* derives placeholders itself.
|
|
58
58
|
*/
|
|
59
59
|
type PlaceholderExtractor = (value: string) => readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* Compares a source and translated value's placeholders directly, branch-aware, instead of
|
|
62
|
+
* independently extracting each side's flat placeholder list first. Supplied by the caller (the SDK, for
|
|
63
|
+
* a format whose adapter defines one, for example ICU plural/select) so it matches the entries' format;
|
|
64
|
+
* ai-providers never derives it itself and never parses a specific format's message syntax.
|
|
65
|
+
*/
|
|
66
|
+
type PlaceholderComparator = (source: string, translated: string) => PlaceholderIntegrityResult$1;
|
|
60
67
|
/**
|
|
61
68
|
* A batch translation request. Format- and provider-neutral: it carries no prompt,
|
|
62
69
|
* model, key, or other provider-specific field. The placeholder extractor is
|
|
@@ -75,20 +82,62 @@ interface TranslateRequest {
|
|
|
75
82
|
readonly tone?: Tone;
|
|
76
83
|
/** Mandatory placeholder extractor; the output integrity check runs against it. */
|
|
77
84
|
readonly extractPlaceholders: PlaceholderExtractor;
|
|
85
|
+
/**
|
|
86
|
+
* Optional branch-aware placeholder comparator. When present, the output integrity check uses it
|
|
87
|
+
* instead of independently extracting each side's placeholders with {@link extractPlaceholders} and
|
|
88
|
+
* diffing the flat lists. Absent for a format with no plural/select sub-message structure.
|
|
89
|
+
*/
|
|
90
|
+
readonly comparePlaceholders?: PlaceholderComparator;
|
|
91
|
+
/**
|
|
92
|
+
* Optional cancellation signal for this batch. When aborted, an in-flight provider call rejects
|
|
93
|
+
* with the abort, unwrapped, instead of a {@link ProviderError} (see `guardProviderCall`). Not a
|
|
94
|
+
* plain-data field: it is never validated by `requestDataSchema` and never sent to a provider.
|
|
95
|
+
*/
|
|
96
|
+
readonly signal?: AbortSignal;
|
|
78
97
|
}
|
|
79
98
|
/** Token usage, when the provider reports it. Absent for providers without tokens (DeepL). */
|
|
80
99
|
interface Usage {
|
|
81
100
|
readonly inputTokens: number;
|
|
82
101
|
readonly outputTokens: number;
|
|
83
102
|
}
|
|
84
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Stable codes for a provider's graceful-degradation notices. These are returned DATA on a
|
|
105
|
+
* successful result, NOT thrown:
|
|
106
|
+
*
|
|
107
|
+
* - `FORMALITY_DOWNGRADED`: a requested formality was not applied (DeepL's free tier does not
|
|
108
|
+
* support it).
|
|
109
|
+
* - `GLOSSARY_IGNORED`: a supplied generic glossary term map was not applied (DeepL only applies a
|
|
110
|
+
* native glossary id, never a term map).
|
|
111
|
+
* - `PLACEHOLDER_UNSUPPORTED`: at least one placeholder- or ICU-bearing entry was left untranslated
|
|
112
|
+
* because the provider cannot preserve those tokens; such entries are withheld (absent from the
|
|
113
|
+
* result maps) rather than sent to the provider and mangled.
|
|
114
|
+
*/
|
|
115
|
+
type ProviderNoticeCode = "FORMALITY_DOWNGRADED" | "GLOSSARY_IGNORED" | "PLACEHOLDER_UNSUPPORTED";
|
|
116
|
+
/**
|
|
117
|
+
* An observable, structured signal that something was gracefully degraded (not an
|
|
118
|
+
* error). Carries only a stable code and a static message, never a key or content.
|
|
119
|
+
* Surfaced as result data, never thrown; callers inspect it but need not treat it as a failure.
|
|
120
|
+
*/
|
|
121
|
+
interface ProviderNotice {
|
|
122
|
+
/** The stable {@link ProviderNoticeCode} for what was degraded. */
|
|
123
|
+
readonly code: ProviderNoticeCode;
|
|
124
|
+
/** A static, safe description; never a key or translatable content. */
|
|
125
|
+
readonly message: string;
|
|
126
|
+
}
|
|
127
|
+
/** Result of a batch translation: per-key values, per-key integrity outcomes, and any notices. */
|
|
85
128
|
interface TranslateResult {
|
|
86
129
|
/** The translated value for each requested key. */
|
|
87
130
|
readonly values: ReadonlyMap<string, string>;
|
|
88
131
|
/** The placeholder-integrity outcome for each key (source vs translated placeholder sets). */
|
|
89
|
-
readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult>;
|
|
132
|
+
readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult$1>;
|
|
90
133
|
/** Token usage when the provider reports it; absent for token-less providers. */
|
|
91
134
|
readonly usage?: Usage;
|
|
135
|
+
/**
|
|
136
|
+
* Graceful-degradation notices for this batch. Every provider populates this as a present array:
|
|
137
|
+
* DeepL reports real notices (for example `GLOSSARY_IGNORED`); an LLM provider with nothing to
|
|
138
|
+
* report returns an empty array rather than omitting the field.
|
|
139
|
+
*/
|
|
140
|
+
readonly notices?: readonly ProviderNotice[];
|
|
92
141
|
}
|
|
93
142
|
/**
|
|
94
143
|
* The single contract every provider implements. It is narrow enough that a machine-translation API like
|
|
@@ -147,28 +196,6 @@ interface TranslationProvider {
|
|
|
147
196
|
* are still accepted. This drives editor completions only; the runtime schema validates.
|
|
148
197
|
*/
|
|
149
198
|
type AnthropicModel = Anthropic.Messages.Model;
|
|
150
|
-
/**
|
|
151
|
-
* Stable codes for the DeepL graceful-degradation notices, DeepL only. These are returned DATA on a
|
|
152
|
-
* successful result, NOT thrown:
|
|
153
|
-
*
|
|
154
|
-
* - `FORMALITY_DOWNGRADED`: a requested formality was not applied (the free tier does not support it).
|
|
155
|
-
* - `GLOSSARY_IGNORED`: a supplied generic glossary was not applied.
|
|
156
|
-
* - `PLACEHOLDER_UNSUPPORTED`: at least one placeholder- or ICU-bearing entry was left untranslated
|
|
157
|
-
* because DeepL cannot preserve those tokens; such entries are withheld (absent from the result maps)
|
|
158
|
-
* rather than sent to DeepL and mangled.
|
|
159
|
-
*/
|
|
160
|
-
type ProviderNoticeCode = "FORMALITY_DOWNGRADED" | "GLOSSARY_IGNORED" | "PLACEHOLDER_UNSUPPORTED";
|
|
161
|
-
/**
|
|
162
|
-
* An observable, structured signal that something was gracefully degraded (not an
|
|
163
|
-
* error). Carries only a stable code and a static message, never a key or content.
|
|
164
|
-
* Surfaced as result data, never thrown; callers inspect it but need not treat it as a failure.
|
|
165
|
-
*/
|
|
166
|
-
interface ProviderNotice {
|
|
167
|
-
/** The stable {@link ProviderNoticeCode} for what was degraded. */
|
|
168
|
-
readonly code: ProviderNoticeCode;
|
|
169
|
-
/** A static, safe description; never a key or translatable content. */
|
|
170
|
-
readonly message: string;
|
|
171
|
-
}
|
|
172
199
|
|
|
173
200
|
/**
|
|
174
201
|
* The Gemini authoring model type, sourced from the installed SDK's own model union so
|
|
@@ -187,8 +214,9 @@ type OpenAiModel = OpenAI.ChatModel;
|
|
|
187
214
|
|
|
188
215
|
/**
|
|
189
216
|
* The provider section of the config: a discriminated union over the provider id, reusing each
|
|
190
|
-
* provider's own config schema. There is no key field anywhere in this union
|
|
191
|
-
*
|
|
217
|
+
* provider's own config schema. There is no key field anywhere in this union except
|
|
218
|
+
* openai-compatible's optional `apiKeyEnvVar`, which names an environment variable rather than carrying
|
|
219
|
+
* a key value; every provider still reads its actual key from the environment at construction.
|
|
192
220
|
*/
|
|
193
221
|
declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
194
222
|
id: z.ZodLiteral<"anthropic">;
|
|
@@ -213,6 +241,14 @@ declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
213
241
|
options: z.ZodObject<{
|
|
214
242
|
glossaryId: z.ZodOptional<z.ZodString>;
|
|
215
243
|
}, z.core.$strict>;
|
|
244
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
245
|
+
id: z.ZodLiteral<"openai-compatible">;
|
|
246
|
+
options: z.ZodObject<{
|
|
247
|
+
baseUrl: z.ZodURL;
|
|
248
|
+
model: z.ZodString;
|
|
249
|
+
maxOutputTokens: z.ZodNumber;
|
|
250
|
+
apiKeyEnvVar: z.ZodOptional<z.ZodString>;
|
|
251
|
+
}, z.core.$strict>;
|
|
216
252
|
}, z.core.$strip>], "id">;
|
|
217
253
|
type ProviderConfig = z.infer<typeof providerConfigSchema>;
|
|
218
254
|
type ProviderId = ProviderConfig["id"];
|
|
@@ -260,6 +296,14 @@ declare const verbatraConfigSchema: z.ZodObject<{
|
|
|
260
296
|
options: z.ZodObject<{
|
|
261
297
|
glossaryId: z.ZodOptional<z.ZodString>;
|
|
262
298
|
}, z.core.$strict>;
|
|
299
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
300
|
+
id: z.ZodLiteral<"openai-compatible">;
|
|
301
|
+
options: z.ZodObject<{
|
|
302
|
+
baseUrl: z.ZodURL;
|
|
303
|
+
model: z.ZodString;
|
|
304
|
+
maxOutputTokens: z.ZodNumber;
|
|
305
|
+
apiKeyEnvVar: z.ZodOptional<z.ZodString>;
|
|
306
|
+
}, z.core.$strict>;
|
|
263
307
|
}, z.core.$strip>], "id">;
|
|
264
308
|
glossary: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodString]>>;
|
|
265
309
|
tone: z.ZodOptional<z.ZodEnum<{
|
|
@@ -307,6 +351,9 @@ type AuthoringProviderVariant = {
|
|
|
307
351
|
deepl: Extract<ProviderConfig, {
|
|
308
352
|
id: "deepl";
|
|
309
353
|
}>;
|
|
354
|
+
"openai-compatible": Extract<ProviderConfig, {
|
|
355
|
+
id: "openai-compatible";
|
|
356
|
+
}>;
|
|
310
357
|
};
|
|
311
358
|
/**
|
|
312
359
|
* The authoring view of the whole config for a provider id: a {@link VerbatraConfigInput} whose
|
|
@@ -495,7 +542,8 @@ declare function loadConfig(options?: LoadConfigOptions): Promise<VerbatraConfig
|
|
|
495
542
|
* - `SOURCE_UNREADABLE`: the source locale file is absent (thrown by `translate`, and by `watch` at startup).
|
|
496
543
|
* - `SOURCE_INVALID`: the source locale file could not be read or parsed; wraps the adapter read error
|
|
497
544
|
* (thrown by `translate`).
|
|
498
|
-
* - `LOCK_FILE_INVALID`: the lock-file is present but corrupt or
|
|
545
|
+
* - `LOCK_FILE_INVALID`: the lock-file is present but corrupt, oversized, or at an unsupported
|
|
546
|
+
* version (thrown by `translate`, `check`, `diff`, `exportWorkbook`, and `importWorkbook`).
|
|
499
547
|
* - `LOCALE_FAILED` (NOT thrown): the fallback `code` recorded on a failed `LocaleSummary` when a
|
|
500
548
|
* per-locale failure carries no string code of its own. See the surfaced-not-thrown distinction on
|
|
501
549
|
* `translate`.
|
|
@@ -552,6 +600,21 @@ interface LocaleResource {
|
|
|
552
600
|
readonly entries: ReadonlyMap<string, TranslationEntry>;
|
|
553
601
|
}
|
|
554
602
|
|
|
603
|
+
/**
|
|
604
|
+
* Result of comparing source placeholders against translated-output placeholders as MULTISETS
|
|
605
|
+
* (counts matter). Always returned (never thrown) for an ordinary mismatch.
|
|
606
|
+
*/
|
|
607
|
+
interface PlaceholderIntegrityResult {
|
|
608
|
+
/** True when nothing is missing or extra: the multisets match, regardless of order. */
|
|
609
|
+
readonly matches: boolean;
|
|
610
|
+
/** Occurrences present in source but absent from the translation, one per dropped occurrence. Sorted. */
|
|
611
|
+
readonly missing: readonly string[];
|
|
612
|
+
/** Occurrences present in the translation but absent from source, one per surplus occurrence. Sorted. */
|
|
613
|
+
readonly extra: readonly string[];
|
|
614
|
+
/** Same multiset present in both, but in a different order. */
|
|
615
|
+
readonly reordered: boolean;
|
|
616
|
+
}
|
|
617
|
+
|
|
555
618
|
/**
|
|
556
619
|
* The result of reading a file into core's intermediate representation.
|
|
557
620
|
*/
|
|
@@ -628,6 +691,18 @@ interface FormatAdapter {
|
|
|
628
691
|
* unparseable value returns false.
|
|
629
692
|
*/
|
|
630
693
|
validateMessage(value: string): boolean;
|
|
694
|
+
/**
|
|
695
|
+
* Optional branch-aware placeholder comparison for formats with plural/select sub-message structure.
|
|
696
|
+
* When present, callers use it instead of independently extracting each side's placeholders with
|
|
697
|
+
* {@link extractPlaceholders} and diffing the flat lists, since flattening a plural/select value loses
|
|
698
|
+
* which branch a placeholder came from. Absent for every non-ICU adapter, which is compared via
|
|
699
|
+
* `extractPlaceholders` plus `checkPlaceholders` as before.
|
|
700
|
+
*
|
|
701
|
+
* @param sourceValue - The source value.
|
|
702
|
+
* @param targetValue - The translated value to check against it.
|
|
703
|
+
* @returns The merged placeholder-integrity result across every branch. Does not throw.
|
|
704
|
+
*/
|
|
705
|
+
comparePlaceholders?(sourceValue: string, targetValue: string): PlaceholderIntegrityResult;
|
|
631
706
|
}
|
|
632
707
|
|
|
633
708
|
/** Outcome of resolving an adapter for a file. Structured; never throws. */
|
|
@@ -876,11 +951,13 @@ interface LocaleSummary {
|
|
|
876
951
|
*/
|
|
877
952
|
readonly integrityMismatches: readonly string[];
|
|
878
953
|
/**
|
|
879
|
-
* Keys withheld because
|
|
880
|
-
*
|
|
881
|
-
*
|
|
882
|
-
* {@link LocaleSummary.notices} entry carries the secret-free failure code
|
|
883
|
-
*
|
|
954
|
+
* Keys withheld because nothing was translated for them this run, as distinct from a translation
|
|
955
|
+
* that came back and failed the placeholder-integrity check. This covers two causes: the provider
|
|
956
|
+
* call itself failed (for example a revoked API key, a rate limit, or a network timeout), in which
|
|
957
|
+
* case the corresponding {@link LocaleSummary.notices} entry carries the secret-free failure code
|
|
958
|
+
* and message; or the call succeeded but the key was still missing or duplicated in the response
|
|
959
|
+
* after the shared LLM layer's bounded reconcile repair round, in which case no notice is added.
|
|
960
|
+
* Empty in a dry-run.
|
|
884
961
|
*/
|
|
885
962
|
readonly providerFailures: readonly string[];
|
|
886
963
|
/**
|
|
@@ -1108,13 +1185,24 @@ interface LoadLockFileDeps {
|
|
|
1108
1185
|
* @param input - The directory the lock-file resolves against.
|
|
1109
1186
|
* @param deps - Optional composition seam (file system) for tests.
|
|
1110
1187
|
* @returns The parsed lock-file, or an empty lock when none exists yet.
|
|
1111
|
-
* @throws {@link SdkError} `LOCK_FILE_INVALID` when the lock-file is present but corrupt
|
|
1188
|
+
* @throws {@link SdkError} `LOCK_FILE_INVALID` when the lock-file is present but corrupt, oversized,
|
|
1189
|
+
* or at an unsupported version.
|
|
1112
1190
|
*/
|
|
1113
1191
|
declare function loadLockFile(input?: LoadLockFileInput, deps?: LoadLockFileDeps): Promise<LockFile>;
|
|
1114
1192
|
|
|
1115
1193
|
/** The committed lock-file name, chosen to be obviously JSON and to not match a `*.lock` ignore rule. */
|
|
1116
1194
|
declare const LOCK_FILE_NAME = "verbatra.lock.json";
|
|
1117
1195
|
|
|
1196
|
+
/**
|
|
1197
|
+
* The subset of {@link ProviderId} that `init` can scaffold: every provider with a single required
|
|
1198
|
+
* environment variable. "openai-compatible" is deliberately excluded: unlike every other provider it
|
|
1199
|
+
* has no single required environment variable, only a three-tier
|
|
1200
|
+
* apiKeyEnvVar/OPENAI_COMPATIBLE_API_KEY/placeholder fallback (see resolveOpenAiCompatibleKey in
|
|
1201
|
+
* @verbatra/ai-providers), so it does not fit the `providerEnv` table below and `init` scaffolding does
|
|
1202
|
+
* not offer it. This is the single source of truth for the exclusion; other packages import this type
|
|
1203
|
+
* rather than re-deriving `Exclude<ProviderId, "openai-compatible">` themselves.
|
|
1204
|
+
*/
|
|
1205
|
+
type ScaffoldableProviderId = Exclude<ProviderId, "openai-compatible">;
|
|
1118
1206
|
/**
|
|
1119
1207
|
* Read-only metadata the CLI `init` scaffold derives its tables from, so the CLI never restates the
|
|
1120
1208
|
* provider, env-var, model, or format truth owned by core and ai-providers.
|
|
@@ -1229,4 +1317,4 @@ interface WatchController {
|
|
|
1229
1317
|
*/
|
|
1230
1318
|
declare function watch(input: WatchInput, deps?: WatchDeps): Promise<WatchController>;
|
|
1231
1319
|
|
|
1232
|
-
export { type CheckDeps, type CheckInput, type CheckSummary, type ConfigSource, type CreateProvider, type CreateWatcher, DEFAULT_WORKBOOK_PATH, type DiffDeps, type DiffInput, type DiffSummary, type ExportWorkbookDeps, type ExportWorkbookInput, type ExportWorkbookResult, type GlossaryProvenance, type ImportWorkbookDeps, type ImportWorkbookInput, LOCK_FILE_NAME, type LoadConfigOptions, type LoadLockFileDeps, type LoadLockFileInput, type LoadedConfig, type LocaleCheckSummary, type LocaleDiff, type LocaleNotice, type LocaleSummary, type LockFile, type LockLocaleState, type LockStateDeps, type LockStateInput, type LockStateResult, type ProviderConfig, type ProviderId, type RunSummary, type RunTranslate, SdkError, type SdkErrorCode, type SdkFs, type SdkNotice, type SdkNoticeCode, type SupportedFormat$1 as SupportedFormat, type TranslateDeps, type TranslateInput, type VerbatraConfig, type VerbatraConfigInput, type WatchController, type WatchDeps, type WatchInput, type WatchRunResult, type Watcher, check, defineConfig, diff, exportWorkbook, importWorkbook, loadConfig, loadConfigWithMeta, loadLockFile, lockState, scaffoldingMetadata, translate, verbatraConfigSchema, watch };
|
|
1320
|
+
export { type CheckDeps, type CheckInput, type CheckSummary, type ConfigSource, type CreateProvider, type CreateWatcher, DEFAULT_WORKBOOK_PATH, type DiffDeps, type DiffInput, type DiffSummary, type ExportWorkbookDeps, type ExportWorkbookInput, type ExportWorkbookResult, type GlossaryProvenance, type ImportWorkbookDeps, type ImportWorkbookInput, LOCK_FILE_NAME, type LoadConfigOptions, type LoadLockFileDeps, type LoadLockFileInput, type LoadedConfig, type LocaleCheckSummary, type LocaleDiff, type LocaleNotice, type LocaleSummary, type LockFile, type LockLocaleState, type LockStateDeps, type LockStateInput, type LockStateResult, type ProviderConfig, type ProviderId, type RunSummary, type RunTranslate, type ScaffoldableProviderId, SdkError, type SdkErrorCode, type SdkFs, type SdkNotice, type SdkNoticeCode, type SupportedFormat$1 as SupportedFormat, type TranslateDeps, type TranslateInput, type VerbatraConfig, type VerbatraConfigInput, type WatchController, type WatchDeps, type WatchInput, type WatchRunResult, type Watcher, check, defineConfig, diff, exportWorkbook, importWorkbook, loadConfig, loadConfigWithMeta, loadLockFile, lockState, scaffoldingMetadata, translate, verbatraConfigSchema, watch };
|