@verbatra/sdk 0.5.0-next.0 → 0.5.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.
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,6 +82,18 @@ 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 {
@@ -86,7 +105,7 @@ interface TranslateResult {
86
105
  /** The translated value for each requested key. */
87
106
  readonly values: ReadonlyMap<string, string>;
88
107
  /** The placeholder-integrity outcome for each key (source vs translated placeholder sets). */
89
- readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult>;
108
+ readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult$1>;
90
109
  /** Token usage when the provider reports it; absent for token-less providers. */
91
110
  readonly usage?: Usage;
92
111
  }
@@ -187,8 +206,9 @@ type OpenAiModel = OpenAI.ChatModel;
187
206
 
188
207
  /**
189
208
  * 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; the provider reads its
191
- * API key from the environment at construction.
209
+ * provider's own config schema. There is no key field anywhere in this union except
210
+ * openai-compatible's optional `apiKeyEnvVar`, which names an environment variable rather than carrying
211
+ * a key value; every provider still reads its actual key from the environment at construction.
192
212
  */
193
213
  declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
194
214
  id: z.ZodLiteral<"anthropic">;
@@ -213,6 +233,14 @@ declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
213
233
  options: z.ZodObject<{
214
234
  glossaryId: z.ZodOptional<z.ZodString>;
215
235
  }, z.core.$strict>;
236
+ }, z.core.$strip>, z.ZodObject<{
237
+ id: z.ZodLiteral<"openai-compatible">;
238
+ options: z.ZodObject<{
239
+ baseUrl: z.ZodURL;
240
+ model: z.ZodString;
241
+ maxOutputTokens: z.ZodNumber;
242
+ apiKeyEnvVar: z.ZodOptional<z.ZodString>;
243
+ }, z.core.$strict>;
216
244
  }, z.core.$strip>], "id">;
217
245
  type ProviderConfig = z.infer<typeof providerConfigSchema>;
218
246
  type ProviderId = ProviderConfig["id"];
@@ -260,6 +288,14 @@ declare const verbatraConfigSchema: z.ZodObject<{
260
288
  options: z.ZodObject<{
261
289
  glossaryId: z.ZodOptional<z.ZodString>;
262
290
  }, z.core.$strict>;
291
+ }, z.core.$strip>, z.ZodObject<{
292
+ id: z.ZodLiteral<"openai-compatible">;
293
+ options: z.ZodObject<{
294
+ baseUrl: z.ZodURL;
295
+ model: z.ZodString;
296
+ maxOutputTokens: z.ZodNumber;
297
+ apiKeyEnvVar: z.ZodOptional<z.ZodString>;
298
+ }, z.core.$strict>;
263
299
  }, z.core.$strip>], "id">;
264
300
  glossary: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodString]>>;
265
301
  tone: z.ZodOptional<z.ZodEnum<{
@@ -307,6 +343,9 @@ type AuthoringProviderVariant = {
307
343
  deepl: Extract<ProviderConfig, {
308
344
  id: "deepl";
309
345
  }>;
346
+ "openai-compatible": Extract<ProviderConfig, {
347
+ id: "openai-compatible";
348
+ }>;
310
349
  };
311
350
  /**
312
351
  * The authoring view of the whole config for a provider id: a {@link VerbatraConfigInput} whose
@@ -495,7 +534,8 @@ declare function loadConfig(options?: LoadConfigOptions): Promise<VerbatraConfig
495
534
  * - `SOURCE_UNREADABLE`: the source locale file is absent (thrown by `translate`, and by `watch` at startup).
496
535
  * - `SOURCE_INVALID`: the source locale file could not be read or parsed; wraps the adapter read error
497
536
  * (thrown by `translate`).
498
- * - `LOCK_FILE_INVALID`: the lock-file is present but corrupt or oversized (thrown by `translate`).
537
+ * - `LOCK_FILE_INVALID`: the lock-file is present but corrupt, oversized, or at an unsupported
538
+ * version (thrown by `translate`, `check`, `diff`, `exportWorkbook`, and `importWorkbook`).
499
539
  * - `LOCALE_FAILED` (NOT thrown): the fallback `code` recorded on a failed `LocaleSummary` when a
500
540
  * per-locale failure carries no string code of its own. See the surfaced-not-thrown distinction on
501
541
  * `translate`.
@@ -552,6 +592,21 @@ interface LocaleResource {
552
592
  readonly entries: ReadonlyMap<string, TranslationEntry>;
553
593
  }
554
594
 
595
+ /**
596
+ * Result of comparing source placeholders against translated-output placeholders as MULTISETS
597
+ * (counts matter). Always returned (never thrown) for an ordinary mismatch.
598
+ */
599
+ interface PlaceholderIntegrityResult {
600
+ /** True when nothing is missing or extra: the multisets match, regardless of order. */
601
+ readonly matches: boolean;
602
+ /** Occurrences present in source but absent from the translation, one per dropped occurrence. Sorted. */
603
+ readonly missing: readonly string[];
604
+ /** Occurrences present in the translation but absent from source, one per surplus occurrence. Sorted. */
605
+ readonly extra: readonly string[];
606
+ /** Same multiset present in both, but in a different order. */
607
+ readonly reordered: boolean;
608
+ }
609
+
555
610
  /**
556
611
  * The result of reading a file into core's intermediate representation.
557
612
  */
@@ -628,6 +683,18 @@ interface FormatAdapter {
628
683
  * unparseable value returns false.
629
684
  */
630
685
  validateMessage(value: string): boolean;
686
+ /**
687
+ * Optional branch-aware placeholder comparison for formats with plural/select sub-message structure.
688
+ * When present, callers use it instead of independently extracting each side's placeholders with
689
+ * {@link extractPlaceholders} and diffing the flat lists, since flattening a plural/select value loses
690
+ * which branch a placeholder came from. Absent for every non-ICU adapter, which is compared via
691
+ * `extractPlaceholders` plus `checkPlaceholders` as before.
692
+ *
693
+ * @param sourceValue - The source value.
694
+ * @param targetValue - The translated value to check against it.
695
+ * @returns The merged placeholder-integrity result across every branch. Does not throw.
696
+ */
697
+ comparePlaceholders?(sourceValue: string, targetValue: string): PlaceholderIntegrityResult;
631
698
  }
632
699
 
633
700
  /** Outcome of resolving an adapter for a file. Structured; never throws. */
@@ -1108,13 +1175,24 @@ interface LoadLockFileDeps {
1108
1175
  * @param input - The directory the lock-file resolves against.
1109
1176
  * @param deps - Optional composition seam (file system) for tests.
1110
1177
  * @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 or oversized.
1178
+ * @throws {@link SdkError} `LOCK_FILE_INVALID` when the lock-file is present but corrupt, oversized,
1179
+ * or at an unsupported version.
1112
1180
  */
1113
1181
  declare function loadLockFile(input?: LoadLockFileInput, deps?: LoadLockFileDeps): Promise<LockFile>;
1114
1182
 
1115
1183
  /** The committed lock-file name, chosen to be obviously JSON and to not match a `*.lock` ignore rule. */
1116
1184
  declare const LOCK_FILE_NAME = "verbatra.lock.json";
1117
1185
 
1186
+ /**
1187
+ * The subset of {@link ProviderId} that `init` can scaffold: every provider with a single required
1188
+ * environment variable. "openai-compatible" is deliberately excluded: unlike every other provider it
1189
+ * has no single required environment variable, only a three-tier
1190
+ * apiKeyEnvVar/OPENAI_COMPATIBLE_API_KEY/placeholder fallback (see resolveOpenAiCompatibleKey in
1191
+ * @verbatra/ai-providers), so it does not fit the `providerEnv` table below and `init` scaffolding does
1192
+ * not offer it. This is the single source of truth for the exclusion; other packages import this type
1193
+ * rather than re-deriving `Exclude<ProviderId, "openai-compatible">` themselves.
1194
+ */
1195
+ type ScaffoldableProviderId = Exclude<ProviderId, "openai-compatible">;
1118
1196
  /**
1119
1197
  * Read-only metadata the CLI `init` scaffold derives its tables from, so the CLI never restates the
1120
1198
  * provider, env-var, model, or format truth owned by core and ai-providers.
@@ -1229,4 +1307,4 @@ interface WatchController {
1229
1307
  */
1230
1308
  declare function watch(input: WatchInput, deps?: WatchDeps): Promise<WatchController>;
1231
1309
 
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 };
1310
+ 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,6 +82,18 @@ 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 {
@@ -86,7 +105,7 @@ interface TranslateResult {
86
105
  /** The translated value for each requested key. */
87
106
  readonly values: ReadonlyMap<string, string>;
88
107
  /** The placeholder-integrity outcome for each key (source vs translated placeholder sets). */
89
- readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult>;
108
+ readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult$1>;
90
109
  /** Token usage when the provider reports it; absent for token-less providers. */
91
110
  readonly usage?: Usage;
92
111
  }
@@ -187,8 +206,9 @@ type OpenAiModel = OpenAI.ChatModel;
187
206
 
188
207
  /**
189
208
  * 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; the provider reads its
191
- * API key from the environment at construction.
209
+ * provider's own config schema. There is no key field anywhere in this union except
210
+ * openai-compatible's optional `apiKeyEnvVar`, which names an environment variable rather than carrying
211
+ * a key value; every provider still reads its actual key from the environment at construction.
192
212
  */
193
213
  declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
194
214
  id: z.ZodLiteral<"anthropic">;
@@ -213,6 +233,14 @@ declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
213
233
  options: z.ZodObject<{
214
234
  glossaryId: z.ZodOptional<z.ZodString>;
215
235
  }, z.core.$strict>;
236
+ }, z.core.$strip>, z.ZodObject<{
237
+ id: z.ZodLiteral<"openai-compatible">;
238
+ options: z.ZodObject<{
239
+ baseUrl: z.ZodURL;
240
+ model: z.ZodString;
241
+ maxOutputTokens: z.ZodNumber;
242
+ apiKeyEnvVar: z.ZodOptional<z.ZodString>;
243
+ }, z.core.$strict>;
216
244
  }, z.core.$strip>], "id">;
217
245
  type ProviderConfig = z.infer<typeof providerConfigSchema>;
218
246
  type ProviderId = ProviderConfig["id"];
@@ -260,6 +288,14 @@ declare const verbatraConfigSchema: z.ZodObject<{
260
288
  options: z.ZodObject<{
261
289
  glossaryId: z.ZodOptional<z.ZodString>;
262
290
  }, z.core.$strict>;
291
+ }, z.core.$strip>, z.ZodObject<{
292
+ id: z.ZodLiteral<"openai-compatible">;
293
+ options: z.ZodObject<{
294
+ baseUrl: z.ZodURL;
295
+ model: z.ZodString;
296
+ maxOutputTokens: z.ZodNumber;
297
+ apiKeyEnvVar: z.ZodOptional<z.ZodString>;
298
+ }, z.core.$strict>;
263
299
  }, z.core.$strip>], "id">;
264
300
  glossary: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodString]>>;
265
301
  tone: z.ZodOptional<z.ZodEnum<{
@@ -307,6 +343,9 @@ type AuthoringProviderVariant = {
307
343
  deepl: Extract<ProviderConfig, {
308
344
  id: "deepl";
309
345
  }>;
346
+ "openai-compatible": Extract<ProviderConfig, {
347
+ id: "openai-compatible";
348
+ }>;
310
349
  };
311
350
  /**
312
351
  * The authoring view of the whole config for a provider id: a {@link VerbatraConfigInput} whose
@@ -495,7 +534,8 @@ declare function loadConfig(options?: LoadConfigOptions): Promise<VerbatraConfig
495
534
  * - `SOURCE_UNREADABLE`: the source locale file is absent (thrown by `translate`, and by `watch` at startup).
496
535
  * - `SOURCE_INVALID`: the source locale file could not be read or parsed; wraps the adapter read error
497
536
  * (thrown by `translate`).
498
- * - `LOCK_FILE_INVALID`: the lock-file is present but corrupt or oversized (thrown by `translate`).
537
+ * - `LOCK_FILE_INVALID`: the lock-file is present but corrupt, oversized, or at an unsupported
538
+ * version (thrown by `translate`, `check`, `diff`, `exportWorkbook`, and `importWorkbook`).
499
539
  * - `LOCALE_FAILED` (NOT thrown): the fallback `code` recorded on a failed `LocaleSummary` when a
500
540
  * per-locale failure carries no string code of its own. See the surfaced-not-thrown distinction on
501
541
  * `translate`.
@@ -552,6 +592,21 @@ interface LocaleResource {
552
592
  readonly entries: ReadonlyMap<string, TranslationEntry>;
553
593
  }
554
594
 
595
+ /**
596
+ * Result of comparing source placeholders against translated-output placeholders as MULTISETS
597
+ * (counts matter). Always returned (never thrown) for an ordinary mismatch.
598
+ */
599
+ interface PlaceholderIntegrityResult {
600
+ /** True when nothing is missing or extra: the multisets match, regardless of order. */
601
+ readonly matches: boolean;
602
+ /** Occurrences present in source but absent from the translation, one per dropped occurrence. Sorted. */
603
+ readonly missing: readonly string[];
604
+ /** Occurrences present in the translation but absent from source, one per surplus occurrence. Sorted. */
605
+ readonly extra: readonly string[];
606
+ /** Same multiset present in both, but in a different order. */
607
+ readonly reordered: boolean;
608
+ }
609
+
555
610
  /**
556
611
  * The result of reading a file into core's intermediate representation.
557
612
  */
@@ -628,6 +683,18 @@ interface FormatAdapter {
628
683
  * unparseable value returns false.
629
684
  */
630
685
  validateMessage(value: string): boolean;
686
+ /**
687
+ * Optional branch-aware placeholder comparison for formats with plural/select sub-message structure.
688
+ * When present, callers use it instead of independently extracting each side's placeholders with
689
+ * {@link extractPlaceholders} and diffing the flat lists, since flattening a plural/select value loses
690
+ * which branch a placeholder came from. Absent for every non-ICU adapter, which is compared via
691
+ * `extractPlaceholders` plus `checkPlaceholders` as before.
692
+ *
693
+ * @param sourceValue - The source value.
694
+ * @param targetValue - The translated value to check against it.
695
+ * @returns The merged placeholder-integrity result across every branch. Does not throw.
696
+ */
697
+ comparePlaceholders?(sourceValue: string, targetValue: string): PlaceholderIntegrityResult;
631
698
  }
632
699
 
633
700
  /** Outcome of resolving an adapter for a file. Structured; never throws. */
@@ -1108,13 +1175,24 @@ interface LoadLockFileDeps {
1108
1175
  * @param input - The directory the lock-file resolves against.
1109
1176
  * @param deps - Optional composition seam (file system) for tests.
1110
1177
  * @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 or oversized.
1178
+ * @throws {@link SdkError} `LOCK_FILE_INVALID` when the lock-file is present but corrupt, oversized,
1179
+ * or at an unsupported version.
1112
1180
  */
1113
1181
  declare function loadLockFile(input?: LoadLockFileInput, deps?: LoadLockFileDeps): Promise<LockFile>;
1114
1182
 
1115
1183
  /** The committed lock-file name, chosen to be obviously JSON and to not match a `*.lock` ignore rule. */
1116
1184
  declare const LOCK_FILE_NAME = "verbatra.lock.json";
1117
1185
 
1186
+ /**
1187
+ * The subset of {@link ProviderId} that `init` can scaffold: every provider with a single required
1188
+ * environment variable. "openai-compatible" is deliberately excluded: unlike every other provider it
1189
+ * has no single required environment variable, only a three-tier
1190
+ * apiKeyEnvVar/OPENAI_COMPATIBLE_API_KEY/placeholder fallback (see resolveOpenAiCompatibleKey in
1191
+ * @verbatra/ai-providers), so it does not fit the `providerEnv` table below and `init` scaffolding does
1192
+ * not offer it. This is the single source of truth for the exclusion; other packages import this type
1193
+ * rather than re-deriving `Exclude<ProviderId, "openai-compatible">` themselves.
1194
+ */
1195
+ type ScaffoldableProviderId = Exclude<ProviderId, "openai-compatible">;
1118
1196
  /**
1119
1197
  * Read-only metadata the CLI `init` scaffold derives its tables from, so the CLI never restates the
1120
1198
  * provider, env-var, model, or format truth owned by core and ai-providers.
@@ -1229,4 +1307,4 @@ interface WatchController {
1229
1307
  */
1230
1308
  declare function watch(input: WatchInput, deps?: WatchDeps): Promise<WatchController>;
1231
1309
 
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 };
1310
+ 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 };