@gajae-code/ai 0.15.4 → 0.15.6

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 (77) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/dist/types/auth-broker/client.d.ts +6 -2
  3. package/dist/types/auth-broker/remote-store.d.ts +14 -2
  4. package/dist/types/auth-broker/types.d.ts +6 -0
  5. package/dist/types/auth-broker/wire-schemas.d.ts +19 -0
  6. package/dist/types/auth-gateway/server.d.ts +39 -5
  7. package/dist/types/auth-gateway/types.d.ts +16 -2
  8. package/dist/types/auth-storage.d.ts +116 -34
  9. package/dist/types/provider-models/openai-compat.d.ts +1 -0
  10. package/dist/types/provider-models/special.d.ts +2 -1
  11. package/dist/types/providers/kiro-api-key.d.ts +50 -0
  12. package/dist/types/providers/kiro-codewhisperer.d.ts +3 -0
  13. package/dist/types/providers/register-builtins.d.ts +12 -12
  14. package/dist/types/stream.d.ts +2 -1
  15. package/dist/types/types.d.ts +35 -24
  16. package/dist/types/utils/fallback-transport.d.ts +7 -0
  17. package/dist/types/utils/json-parse.d.ts +5 -3
  18. package/dist/types/utils/oauth/api-key-login.d.ts +4 -1
  19. package/dist/types/utils/oauth/api-key-validation.d.ts +12 -6
  20. package/dist/types/utils/oauth/commandcode.d.ts +1 -0
  21. package/dist/types/utils/oauth/types.d.ts +1 -1
  22. package/dist/types/utils/retry.d.ts +2 -0
  23. package/dist/types/utils/tool-call-healing.d.ts +4 -4
  24. package/package.json +3 -3
  25. package/src/auth-broker/client.ts +41 -13
  26. package/src/auth-broker/redact.ts +25 -1
  27. package/src/auth-broker/remote-store.ts +374 -115
  28. package/src/auth-broker/server.ts +131 -91
  29. package/src/auth-broker/types.ts +6 -0
  30. package/src/auth-broker/wire-schemas.ts +6 -0
  31. package/src/auth-gateway/server.ts +447 -79
  32. package/src/auth-gateway/types.ts +28 -2
  33. package/src/auth-storage.ts +742 -157
  34. package/src/cli.ts +1 -0
  35. package/src/model-thinking.ts +16 -0
  36. package/src/models.json +1054 -0
  37. package/src/models.ts +9 -1
  38. package/src/provider-models/descriptors.ts +3 -1
  39. package/src/provider-models/openai-compat.ts +41 -1
  40. package/src/provider-models/special.ts +15 -3
  41. package/src/providers/anthropic.ts +7 -1
  42. package/src/providers/azure-openai-responses.ts +4 -1
  43. package/src/providers/cursor.ts +256 -101
  44. package/src/providers/gitlab-duo.ts +18 -1
  45. package/src/providers/google-gemini-cli.ts +3 -0
  46. package/src/providers/google-shared.ts +3 -0
  47. package/src/providers/kiro-api-key.d.ts +50 -0
  48. package/src/providers/kiro-api-key.ts +786 -0
  49. package/src/providers/kiro-codewhisperer.d.ts +3 -0
  50. package/src/providers/kiro-codewhisperer.ts +34 -9
  51. package/src/providers/ollama.ts +3 -0
  52. package/src/providers/openai-codex-responses.ts +24 -6
  53. package/src/providers/openai-completions.ts +11 -1
  54. package/src/providers/openai-responses-shared.ts +23 -2
  55. package/src/providers/openai-responses.ts +10 -1
  56. package/src/providers/pi-native-client.ts +1 -0
  57. package/src/providers/pi-native-server.ts +24 -0
  58. package/src/providers/register-builtins.d.ts +12 -12
  59. package/src/providers/register-builtins.ts +16 -3
  60. package/src/stream.d.ts +2 -1
  61. package/src/stream.ts +180 -70
  62. package/src/types.d.ts +35 -24
  63. package/src/types.ts +40 -23
  64. package/src/utils/fallback-transport.d.ts +7 -0
  65. package/src/utils/fallback-transport.ts +21 -4
  66. package/src/utils/json-parse.d.ts +5 -3
  67. package/src/utils/json-parse.ts +6 -6
  68. package/src/utils/oauth/api-key-login.ts +13 -2
  69. package/src/utils/oauth/api-key-validation.ts +242 -41
  70. package/src/utils/oauth/commandcode.ts +17 -0
  71. package/src/utils/oauth/index.ts +20 -5
  72. package/src/utils/oauth/types.d.ts +1 -1
  73. package/src/utils/oauth/types.ts +1 -0
  74. package/src/utils/retry.d.ts +2 -0
  75. package/src/utils/retry.ts +15 -2
  76. package/src/utils/tool-call-healing.d.ts +4 -4
  77. package/src/utils/tool-call-healing.ts +4 -4
@@ -15,6 +15,11 @@ export type ApiKeyCredential = {
15
15
  type: "api_key";
16
16
  key: string;
17
17
  };
18
+ /**
19
+ * Extracts the bearer token from the structured API-key form used by OAuth
20
+ * providers that need to carry token metadata alongside the access token.
21
+ */
22
+ export declare function extractStructuredApiKeyToken(apiKey: string): string | undefined;
18
23
  export interface MCPOAuthBinding {
19
24
  /** Exact HTTP(S) origin of the MCP resource endpoint. */
20
25
  resourceOrigin: string;
@@ -203,6 +208,7 @@ export interface AuthCredentialSnapshotEntry {
203
208
  provider: string;
204
209
  credential: SnapshotCredential;
205
210
  identityKey: string | null;
211
+ revision?: number;
206
212
  }
207
213
  export type AuthCredentialIfAbsentReason = "inserted" | "updated-existing" | "skipped-existing" | "skipped-existing-runtime" | "skipped-existing-config" | "skipped-existing-env" | "skipped-existing-fallback" | "skipped-invalid";
208
214
  export interface AuthCredentialIfAbsentResult {
@@ -253,8 +259,20 @@ export type OAuthRefreshLeaseClaim = {
253
259
  } | {
254
260
  kind: "missing";
255
261
  };
262
+ /**
263
+ * Store-owned ticket that orders a provider admission against remote
264
+ * credential snapshot application. The ticket is intentionally released at
265
+ * provider admission, not response completion.
266
+ */
267
+ export interface CredentialDispatchTicket {
268
+ release(): void;
269
+ }
256
270
  export interface AuthCredentialStore {
257
271
  close(): void;
272
+ refreshSnapshot?(signal?: AbortSignal): Promise<unknown>;
273
+ onSnapshotChanged?(listener: () => void): () => void;
274
+ /** Order provider admission with remote snapshot authority application. */
275
+ acquireCredentialDispatchTicket?(provider: Provider, signal?: AbortSignal): Promise<CredentialDispatchTicket>;
258
276
  listAuthCredentials(provider?: string): StoredAuthCredential[];
259
277
  /** Payload-free account inventory; active and soft-disabled rows are included. */
260
278
  listCredentialInventory?(provider?: string): CredentialInventoryRecord[];
@@ -265,6 +283,7 @@ export interface AuthCredentialStore {
265
283
  updateAuthCredential(id: number, credential: AuthCredential): void;
266
284
  deleteAuthCredential(id: number, disabledCause: string): void;
267
285
  tryDisableAuthCredentialIfMatches(id: number, expectedData: string, disabledCause: string): boolean;
286
+ tryDisableAuthCredentialIfRevision?(id: number, expectedRevision: number, disabledCause: string): boolean;
268
287
  replaceAuthCredentialsForProvider(provider: string, credentials: AuthCredential[]): StoredAuthCredential[];
269
288
  upsertAuthCredentialForProvider(provider: string, credential: AuthCredential): StoredAuthCredential[];
270
289
  upsertAuthCredentialForProviderIfAbsent(provider: string, credential: AuthCredential): AuthCredentialIfAbsentResult;
@@ -273,6 +292,8 @@ export interface AuthCredentialStore {
273
292
  includeExpired?: boolean;
274
293
  }): string | null;
275
294
  setCache(key: string, value: string, expiresAtSec: number): void;
295
+ /** Atomically allocate a durable sequence for broker restart epochs. */
296
+ allocateMonotonicSequence(key: string, expiresAtSec: number): number;
276
297
  deleteCachePrefix?(prefix: string): void;
277
298
  cleanExpiredCache(): void;
278
299
  /**
@@ -320,6 +341,7 @@ export interface AuthCredentialStore {
320
341
  * `signal` propagates the agent's cancel down to the broker fetch.
321
342
  */
322
343
  fetchUsageReports?(signal?: AbortSignal): Promise<UsageReport[] | null>;
344
+ fetchUsageReportsForProvider?(provider: Provider, signal?: AbortSignal): Promise<UsageReport[] | null>;
323
345
  /** Synchronous, zero-network usage presentation peek. */
324
346
  peekCachedUsagePresentation?(provider: Provider, credentialId: number): CachedUsagePresentation | undefined;
325
347
  /** Record a safe usage observation after an explicit fetch/check. */
@@ -360,6 +382,16 @@ export interface AuthCredentialStore {
360
382
  markCredentialSuspect?(credentialId: number, opts?: {
361
383
  signal?: AbortSignal;
362
384
  }): Promise<void>;
385
+ /**
386
+ * Optional async write hook to disable one credential through an authoritative
387
+ * remote store. Remote clients MUST use this hook instead of the synchronous
388
+ * local delete methods when an OAuth refresh fails definitively.
389
+ *
390
+ * Returns `false` when the row is already absent (for example, a peer
391
+ * disabled it first). Implementations MUST NOT treat a failed remote write as
392
+ * a successful local deletion.
393
+ */
394
+ disableAuthCredentialRemote?(credentialId: number, disabledCause: string, signal?: AbortSignal, expectedRevision?: number): Promise<boolean>;
363
395
  /**
364
396
  * Optional async write hook for upserting a single credential. When present,
365
397
  * `AuthStorage.#upsertOAuthCredential` routes through this instead of the
@@ -468,10 +500,13 @@ export type AuthStorageOptions = {
468
500
  * AuthStorage caller surfaces that to its own consumer unchanged.
469
501
  */
470
502
  fetchUsageReports?: (signal?: AbortSignal) => Promise<UsageReport[] | null>;
503
+ fetchUsageReportsForProvider?: (provider: Provider, signal?: AbortSignal) => Promise<UsageReport[] | null>;
471
504
  };
472
- type AuthApiKeyOptions = {
505
+ export type AuthApiKeyOptions = {
473
506
  baseUrl?: string;
474
507
  modelId?: string;
508
+ /** Select config registrations owned by one caller (for example a ModelRegistry). */
509
+ owner?: object;
475
510
  /**
476
511
  * Caller's cancel signal. Threaded into any broker-bound OAuth refresh so
477
512
  * `ESC` / request abort actually kills a hung broker fetch instead of
@@ -506,7 +541,11 @@ export interface OAuthAccess {
506
541
  export interface InvalidateCredentialMatchingOptions {
507
542
  signal?: AbortSignal;
508
543
  sessionId?: string;
544
+ owner?: object;
509
545
  }
546
+ /** Read optional broker error detail without allowing hostile objects to escape classification. */
547
+ /** @internal Tested directly because hostile accessors must preserve the original error identity. */
548
+ export declare function readBrokerErrorBody(error: unknown): string | undefined;
510
549
  /**
511
550
  * Credential storage backed by an AuthCredentialStore.
512
551
  * Reads from storage on reload(), manages round-robin credential selection,
@@ -528,9 +567,14 @@ export declare class AuthStorage {
528
567
  */
529
568
  close(): void;
530
569
  getGeneration(): number;
570
+ getCache(key: string, options?: {
571
+ includeExpired?: boolean;
572
+ }): string | null;
573
+ setCache(key: string, value: string, expiresAtSec: number): void;
574
+ allocateMonotonicSequence(key: string, expiresAtSec: number): number;
531
575
  getProviderConfigurationGeneration(provider: string): number;
532
576
  getProviderOAuthRefreshGeneration(provider: string): number;
533
- getProviderEvidenceGeneration(provider: string, resolvedApiKey?: string): string;
577
+ getProviderEvidenceGeneration(provider: string, resolvedApiKey?: string, owner?: object): string;
534
578
  onGenerationChanged(listener: (generation: number) => void): () => void;
535
579
  offGenerationChanged(listener: (generation: number) => void): void;
536
580
  /**
@@ -568,8 +612,12 @@ export declare class AuthStorage {
568
612
  hasCredentialScopeLease(scopeId: string): boolean;
569
613
  /** Release one credential-scope lease; final release clears only that scope's derived state. */
570
614
  releaseCredentialScope(scopeId: string): void;
571
- /** Set the selector derived from a durable session pin or a session seed. */
572
- setSessionCredentialSelector(scopeId: string, provider: string, selector: AuthCredentialSelector): void;
615
+ /**
616
+ * Set the selector derived from a durable session pin or a session seed.
617
+ * `owner` scopes config-override validation to one ModelRegistry; omitted
618
+ * owners retain process-wide caller semantics.
619
+ */
620
+ setSessionCredentialSelector(scopeId: string, provider: string, selector: AuthCredentialSelector, owner?: object): void;
573
621
  /** Explicitly mask persistent/process-global selection and return the provider to AUTO for one scope. */
574
622
  setSessionCredentialAuto(provider: string, scopeId: string): void;
575
623
  /** Clear a scope's explicit selector and AUTO mask, restoring normal precedence. */
@@ -581,9 +629,13 @@ export declare class AuthStorage {
581
629
  /** Resolve the effective selector precedence for a provider/scope. */
582
630
  resolveEffectiveCredentialSelector(provider: string, scopeId?: string, explicitSelector?: AuthCredentialSelector): AuthCredentialSelector | undefined;
583
631
  /** @internal Return cache provenance for an exact stored literal API-key row without resolving its value. */
584
- getStoredLiteralApiKeyEvidenceGeneration(provider: string, selector: AuthCredentialSelector): string | undefined;
585
- /** Validate and canonicalize an OAuth-only selector for account pinning. */
586
- resolveOAuthPinTarget(provider: string, selector: AuthCredentialSelector): OAuthPinTarget;
632
+ getStoredLiteralApiKeyEvidenceGeneration(provider: string, selector: AuthCredentialSelector, owner?: object): string | undefined;
633
+ /**
634
+ * Validate and canonicalize an OAuth-only selector for account pinning.
635
+ * `owner` scopes config-override checks to one ModelRegistry; omitted owners
636
+ * retain process-wide caller semantics.
637
+ */
638
+ resolveOAuthPinTarget(provider: string, selector: AuthCredentialSelector, owner?: object): OAuthPinTarget;
587
639
  /** Return all local inventory rows, including soft-disabled metadata, without payloads. */
588
640
  listCredentialInventory(provider?: string): CredentialInventoryRecord[];
589
641
  /** Return local credential hard-removal action targets, including disabled rows. */
@@ -617,7 +669,7 @@ export declare class AuthStorage {
617
669
  /** Whether a provider is currently authenticated by a runtime API-key override. */
618
670
  hasRuntimeApiKey(provider: string): boolean;
619
671
  /** Whether a provider is currently authenticated by a config API-key override. */
620
- hasConfigApiKey(provider: string): boolean;
672
+ hasConfigApiKey(provider: string, owner?: object): boolean;
621
673
  /**
622
674
  * Whether credential selection for a provider is pinned to one stored row by
623
675
  * a runtime selector (`--credential`).
@@ -664,7 +716,8 @@ export declare class AuthStorage {
664
716
  * runtime API-key override (`--api-key`), or a config-sourced API key
665
717
  * (`models.yml` `apiKey`) would each re-decide the credential on the very
666
718
  * next {@link AuthStorage.getApiKey} call and make this switch appear to
667
- * silently do nothing.
719
+ * silently do nothing. `owner` scopes the config-override check to one
720
+ * ModelRegistry; omitted owners retain process-wide caller semantics.
668
721
  *
669
722
  * Deliberately does not touch credential-blocked state: if the target row
670
723
  * is still backoff-blocked from a prior quota failure, the existing
@@ -672,7 +725,7 @@ export declare class AuthStorage {
672
725
  * falls back to a usable account instead of re-issuing a request that would
673
726
  * just draw another 429/quota error.
674
727
  */
675
- switchSessionCredential(provider: string, sessionId: string, selector: AuthCredentialSelector): void;
728
+ switchSessionCredential(provider: string, sessionId: string, selector: AuthCredentialSelector, owner?: object): void;
676
729
  /**
677
730
  * Register a per-provider API key sourced from user configuration
678
731
  * (e.g. `models.yml` `providers.<name>.apiKey`). Higher priority than
@@ -682,26 +735,46 @@ export declare class AuthStorage {
682
735
  *
683
736
  * Lower priority than {@link setRuntimeApiKey} so a CLI `--api-key`
684
737
  * still wins for the duration of a single invocation.
685
- */
686
- setConfigApiKey(provider: string, apiKey: string): void;
738
+ *
739
+ * `options.owner` scopes the override to one registry or other caller. The
740
+ * unscoped form is process-wide and is retained for standalone callers.
741
+ *
742
+ * `options.envSourced` marks the value as resolved from a models.yml
743
+ * `apiKeyEnv` indirection. Unlike a literal pin, an env pointer only says
744
+ * where to look for a key; when the user has since run `auth login`, the
745
+ * stored api_key credential is the fresher, actively-managed secret and
746
+ * wins over the indirection (stored OAuth credentials still yield, so a
747
+ * custom-endpoint bearer is never replaced by an upstream OAuth token).
748
+ */
749
+ setConfigApiKey(provider: string, apiKey: string, options?: {
750
+ envSourced?: boolean;
751
+ owner?: object;
752
+ }): void;
687
753
  /**
688
754
  * Remove a single config-sourced API key override.
689
755
  */
690
- removeConfigApiKey(provider: string): void;
756
+ removeConfigApiKey(provider: string, owner?: object): void;
691
757
  /**
692
- * Drop every config-sourced API key. Called by `ModelRegistry` before
693
- * re-parsing `models.yml` so removed entries actually disappear.
758
+ * Drop config-sourced API keys. An owner removes only its own registrations;
759
+ * the unscoped form remains an explicit global reset for callers that own the
760
+ * entire AuthStorage instance.
694
761
  */
695
- clearConfigApiKeys(): void;
762
+ clearConfigApiKeys(owner?: object): void;
696
763
  /**
697
764
  * Set a fallback resolver for API keys not found in storage or env vars.
698
765
  * Used for custom provider keys from models.json.
699
766
  */
700
- setFallbackResolver(resolver: (provider: string) => string | undefined): void;
767
+ setFallbackResolver(resolver: (provider: string) => string | undefined, owner?: object): () => void;
701
768
  /**
702
769
  * Reload credentials from storage.
703
770
  */
704
771
  reload(): Promise<void>;
772
+ /**
773
+ * Acquire a store-owned provider-admission ticket when the backing store
774
+ * provides one (for example, a remote broker snapshot store). Local stores
775
+ * need no additional ordering and return `undefined`.
776
+ */
777
+ acquireCredentialDispatchTicket(provider: Provider, signal?: AbortSignal): Promise<CredentialDispatchTicket | undefined>;
705
778
  /** Returns the credential type selected for a provider/session, if one has been recorded. */
706
779
  getSessionCredentialType(provider: string, sessionId?: string): AuthCredential["type"] | undefined;
707
780
  /**
@@ -712,7 +785,7 @@ export declare class AuthStorage {
712
785
  * Set credential for a provider.
713
786
  */
714
787
  set(provider: string, credential: AuthCredentialEntry): Promise<void>;
715
- importCredentialIfAbsent(provider: string, credential: AuthCredential): Promise<AuthCredentialIfAbsentSnapshotResult>;
788
+ importCredentialIfAbsent(provider: string, credential: AuthCredential, owner?: object): Promise<AuthCredentialIfAbsentSnapshotResult>;
716
789
  /**
717
790
  * Remove credential for a provider.
718
791
  */
@@ -725,17 +798,18 @@ export declare class AuthStorage {
725
798
  * Check if credentials exist for a provider in storage.
726
799
  */
727
800
  has(provider: string): boolean;
728
- hasAuth(provider: string, sessionId?: string): boolean;
801
+ disableCredentialByIdIfRevision(id: number, expectedRevision: number, disabledCause: string): boolean;
802
+ hasAuth(provider: string, sessionId?: string, options?: Pick<AuthApiKeyOptions, "owner">): boolean;
729
803
  /**
730
804
  * Credential type that a provider/session will dispatch first without performing I/O.
731
805
  * Mirrors getApiKey selector validation, overrides, session OAuth stickiness,
732
806
  * cached command-key usability, OAuth retry, and environment fallback order.
733
807
  */
734
- getEffectiveCredentialType(provider: string, sessionId?: string): AuthCredential["type"] | undefined;
808
+ getEffectiveCredentialType(provider: string, sessionId?: string, options?: Pick<AuthApiKeyOptions, "owner">): AuthCredential["type"] | undefined;
735
809
  /**
736
810
  * Check whether configured auth is currently usable without resolving credentials.
737
811
  */
738
- hasUsableAuth(provider: string): boolean;
812
+ hasUsableAuth(provider: string, options?: Pick<AuthApiKeyOptions, "owner">): boolean;
739
813
  /**
740
814
  * Check if OAuth credentials are configured for a provider.
741
815
  */
@@ -743,7 +817,7 @@ export declare class AuthStorage {
743
817
  /**
744
818
  * Get OAuth credentials for a provider.
745
819
  */
746
- getOAuthCredential(provider: string, sessionId?: string): OAuthCredential | undefined;
820
+ getOAuthCredential(provider: string, sessionId?: string, options?: Pick<AuthApiKeyOptions, "owner">): OAuthCredential | undefined;
747
821
  /**
748
822
  * Get the OAuth `accountId` for a provider, preferring the credential that is
749
823
  * session-sticky for `sessionId` when multiple OAuth credentials are configured.
@@ -751,7 +825,7 @@ export declare class AuthStorage {
751
825
  * first call before any `getApiKey` has been issued, or single-credential setups).
752
826
  * Returns `undefined` when no OAuth credential carries an `accountId`.
753
827
  */
754
- getOAuthAccountId(provider: string, sessionId?: string): string | undefined;
828
+ getOAuthAccountId(provider: string, sessionId?: string, options?: Pick<AuthApiKeyOptions, "owner">): string | undefined;
755
829
  /**
756
830
  * Get all credentials.
757
831
  */
@@ -776,6 +850,7 @@ export declare class AuthStorage {
776
850
  */
777
851
  logout(provider: string): Promise<void>;
778
852
  fetchUsageReports(options?: {
853
+ provider?: Provider;
779
854
  baseUrlResolver?: (provider: Provider) => string | undefined;
780
855
  /** Caller's cancel signal; only rejects this caller, never the shared upstream fetch. */
781
856
  signal?: AbortSignal;
@@ -820,6 +895,7 @@ export declare class AuthStorage {
820
895
  retryAfterMs?: number;
821
896
  baseUrl?: string;
822
897
  signal?: AbortSignal;
898
+ owner?: object;
823
899
  }): Promise<boolean>;
824
900
  /**
825
901
  * Earliest instant at which any currently blocked stored credential for this
@@ -835,18 +911,21 @@ export declare class AuthStorage {
835
911
  * and get a best-effort token. For GitHub Copilot we preserve enterprise
836
912
  * routing metadata so discovery can hit the correct host.
837
913
  */
838
- peekApiKey(provider: string): Promise<string | undefined>;
914
+ peekApiKey(provider: string, options?: Pick<AuthApiKeyOptions, "owner">): Promise<string | undefined>;
839
915
  /**
840
916
  * Get API key for a provider.
841
917
  * Priority:
842
918
  * 1. Runtime override (CLI --api-key)
843
- * 2. Config override (models.yml `providers.<name>.apiKey`)
844
- * 3. Session-selected OAuth credential, when present
845
- * 4. Usable or unresolved API key from storage
846
- * 5. OAuth token from storage (auto-refreshed)
847
- * 6. Previously unusable command-backed API key retry
848
- * 7. Environment variable
849
- * 8. Fallback resolver (models.yml custom providers, last-resort)
919
+ * 2. Config override (models.yml `providers.<name>.apiKey` literal pin)
920
+ * 3. Stored api_key credential from `auth login`, when the config override
921
+ * is only an `apiKeyEnv` indirection
922
+ * 4. Config override sourced from models.yml `providers.<name>.apiKeyEnv`
923
+ * 5. Session-selected OAuth credential, when present
924
+ * 6. Usable or unresolved API key from storage
925
+ * 7. OAuth token from storage (auto-refreshed)
926
+ * 8. Previously unusable command-backed API key retry
927
+ * 9. Environment variable
928
+ * 10. Fallback resolver (models.yml custom providers, last-resort)
850
929
  */
851
930
  getApiKey(provider: string, sessionId?: string, options?: AuthApiKeyOptions): Promise<string | undefined>;
852
931
  /**
@@ -915,14 +994,16 @@ export declare class AuthStorage {
915
994
  *
916
995
  * Surfaces four layers, highest precedence first:
917
996
  * 1. Runtime override (`--api-key`).
918
- * 2. Config override (`models.yml` `providers.<name>.apiKey`).
997
+ * 2. Config override (`models.yml` `providers.<name>.apiKey` literal pin,
998
+ * or an `apiKeyEnv` indirection when no stored api_key credential
999
+ * outranks it).
919
1000
  * 3. Stored credential (the one this session is currently sticky to, or the
920
1001
  * one round-robin would pick next when no session id is supplied).
921
1002
  * 4. Env var / fallback resolver — when no stored credential exists.
922
1003
  *
923
1004
  * The string is purely informational; consumers must not parse it.
924
1005
  */
925
- describeCredentialSource(provider: string, sessionId?: string): string | undefined;
1006
+ describeCredentialSource(provider: string, sessionId?: string, options?: Pick<AuthApiKeyOptions, "owner">): string | undefined;
926
1007
  }
927
1008
  /**
928
1009
  * Default SQLite-backed implementation of {@link AuthCredentialStore}.
@@ -955,11 +1036,13 @@ export declare class SqliteAuthCredentialStore implements AuthCredentialStore {
955
1036
  * row between our pre-check and the disable.
956
1037
  */
957
1038
  tryDisableAuthCredentialIfMatches(id: number, expectedData: string, disabledCause: string): boolean;
1039
+ tryDisableAuthCredentialIfRevision(id: number, expectedRevision: number, disabledCause: string): boolean;
958
1040
  deleteAuthCredentialsForProvider(provider: string, disabledCause: string): void;
959
1041
  getCache(key: string, options?: {
960
1042
  includeExpired?: boolean;
961
1043
  }): string | null;
962
1044
  setCache(key: string, value: string, expiresAtSec: number): void;
1045
+ allocateMonotonicSequence(key: string, expiresAtSec: number): number;
963
1046
  deleteCachePrefix(prefix: string): void;
964
1047
  cleanExpiredCache(): void;
965
1048
  /**
@@ -989,4 +1072,3 @@ export declare class SqliteAuthCredentialStore implements AuthCredentialStore {
989
1072
  deleteProvider(provider: string): void;
990
1073
  close(): void;
991
1074
  }
992
- export {};
@@ -98,6 +98,7 @@ export interface OpenCodeModelManagerConfig {
98
98
  }
99
99
  export declare function opencodeZenModelManagerOptions(config?: OpenCodeModelManagerConfig): ModelManagerOptions<"openai-completions">;
100
100
  export declare function opencodeGoModelManagerOptions(config?: OpenCodeModelManagerConfig): ModelManagerOptions<"openai-completions">;
101
+ export declare function commandCodeModelManagerOptions(config?: OpenCodeModelManagerConfig): ModelManagerOptions<Api>;
101
102
  export interface OllamaModelManagerConfig {
102
103
  apiKey?: string;
103
104
  baseUrl?: string;
@@ -24,5 +24,6 @@ export interface JetBrainsJunieModelManagerConfig {
24
24
  }
25
25
  export declare function jetbrainsJunieModelManagerOptions(_config?: JetBrainsJunieModelManagerConfig): ModelManagerOptions<"anthropic-messages">;
26
26
  export interface KiroModelManagerConfig {
27
+ apiKey?: string;
27
28
  }
28
- export declare function kiroModelManagerOptions(_config?: KiroModelManagerConfig): ModelManagerOptions<"kiro-codewhisperer-stream">;
29
+ export declare function kiroModelManagerOptions(config?: KiroModelManagerConfig): ModelManagerOptions<"kiro-codewhisperer-stream">;
@@ -0,0 +1,50 @@
1
+ import type { Model, StreamFunction } from "../types";
2
+ export declare function isKiroApiKey(value: string | undefined): value is string;
3
+ export declare function kiroApiRegion(options?: {
4
+ region?: string;
5
+ }): string;
6
+ export declare function kiroApiBaseUrl(region: string): string;
7
+ export declare function toKiroModelId(modelId: string): string;
8
+ export declare function kiroApiStaticModels(): Model<"kiro-codewhisperer-stream">[];
9
+ /** Discover models this API key can use. Returns null when the key is missing. */
10
+ export declare function fetchKiroApiModels(apiKey: string, region?: string): Promise<Model<"kiro-codewhisperer-stream">[]>;
11
+ type KiroStreamEvent = {
12
+ type: "content";
13
+ data: string;
14
+ } | {
15
+ type: "toolUse";
16
+ data: {
17
+ name: string;
18
+ toolUseId: string;
19
+ input: string;
20
+ stop?: boolean;
21
+ };
22
+ } | {
23
+ type: "toolUseInput";
24
+ data: {
25
+ input: string;
26
+ };
27
+ } | {
28
+ type: "toolUseStop";
29
+ data: {
30
+ stop: boolean;
31
+ };
32
+ } | {
33
+ type: "usage";
34
+ data: {
35
+ inputTokens?: number;
36
+ outputTokens?: number;
37
+ };
38
+ } | {
39
+ type: "error";
40
+ data: {
41
+ error: string;
42
+ message?: string;
43
+ };
44
+ };
45
+ export declare function parseKiroApiEvents(buffer: string): {
46
+ events: KiroStreamEvent[];
47
+ remaining: string;
48
+ };
49
+ export declare const streamKiroApiKey: StreamFunction<"kiro-codewhisperer-stream">;
50
+ export {};
@@ -1,5 +1,8 @@
1
+ import type { Effort } from "../model-thinking";
1
2
  import type { StreamFunction, StreamOptions } from "../types";
2
3
  export interface KiroCodeWhispererOptions extends StreamOptions {
4
+ /** Effort level for Kiro API-key reasoning. */
5
+ reasoning?: Effort | boolean;
3
6
  /** AWS region for the CodeWhisperer streaming endpoint. */
4
7
  region?: string;
5
8
  /** Profile ARN for enterprise IAM Identity Center accounts. */
@@ -44,16 +44,16 @@ export declare function resolveLazyStreamFirstEventFallbackMs(provider: string,
44
44
  export declare const PROVIDER_RUNTIME_DESCRIPTORS: readonly ProviderRuntimeDescriptor<Api, unknown>[];
45
45
  /** Return the lazy descriptor for a built-in API, if one is registered. */
46
46
  export declare function getProviderRuntimeDescriptor<TApi extends Api>(api: TApi): ProviderRuntimeDescriptor<TApi, unknown> | undefined;
47
- export declare const streamAnthropic: (model: Model<"anthropic-messages">, context: Context, options: OptionsForApi<"anthropic-messages">) => EventStreamImpl;
48
- export declare const streamAzureOpenAIResponses: (model: Model<"azure-openai-responses">, context: Context, options: OptionsForApi<"azure-openai-responses">) => EventStreamImpl;
49
- export declare const streamGoogle: (model: Model<"google-generative-ai">, context: Context, options: OptionsForApi<"google-generative-ai">) => EventStreamImpl;
50
- export declare const streamGoogleGeminiCli: (model: Model<"google-gemini-cli">, context: Context, options: OptionsForApi<"google-gemini-cli">) => EventStreamImpl;
51
- export declare const streamGoogleVertex: (model: Model<"google-vertex">, context: Context, options: OptionsForApi<"google-vertex">) => EventStreamImpl;
52
- export declare const streamOpenAICodexResponses: (model: Model<"openai-codex-responses">, context: Context, options: OptionsForApi<"openai-codex-responses">) => EventStreamImpl;
53
- export declare const streamOpenAICompletions: (model: Model<"openai-completions">, context: Context, options: OptionsForApi<"openai-completions">) => EventStreamImpl;
54
- export declare const streamOpenAIResponses: (model: Model<"openai-responses">, context: Context, options: OptionsForApi<"openai-responses">) => EventStreamImpl;
55
- export declare const streamCursor: (model: Model<"cursor-agent">, context: Context, options: OptionsForApi<"cursor-agent">) => EventStreamImpl;
56
- export declare const streamOllama: (model: Model<"ollama-chat">, context: Context, options: OptionsForApi<"ollama-chat">) => EventStreamImpl;
57
- export declare const streamBedrock: (model: Model<"bedrock-converse-stream">, context: Context, options: OptionsForApi<"bedrock-converse-stream">) => EventStreamImpl;
58
- export declare const streamKiroCodeWhisperer: (model: Model<"kiro-codewhisperer-stream">, context: Context, options: OptionsForApi<"kiro-codewhisperer-stream">) => EventStreamImpl;
47
+ export declare const streamAnthropic: (model: Model<"anthropic-messages">, context: Context, options: OptionsForApi<"anthropic-messages">, onStreamCreated?: () => void) => EventStreamImpl;
48
+ export declare const streamAzureOpenAIResponses: (model: Model<"azure-openai-responses">, context: Context, options: OptionsForApi<"azure-openai-responses">, onStreamCreated?: () => void) => EventStreamImpl;
49
+ export declare const streamGoogle: (model: Model<"google-generative-ai">, context: Context, options: OptionsForApi<"google-generative-ai">, onStreamCreated?: () => void) => EventStreamImpl;
50
+ export declare const streamGoogleGeminiCli: (model: Model<"google-gemini-cli">, context: Context, options: OptionsForApi<"google-gemini-cli">, onStreamCreated?: () => void) => EventStreamImpl;
51
+ export declare const streamGoogleVertex: (model: Model<"google-vertex">, context: Context, options: OptionsForApi<"google-vertex">, onStreamCreated?: () => void) => EventStreamImpl;
52
+ export declare const streamOpenAICodexResponses: (model: Model<"openai-codex-responses">, context: Context, options: OptionsForApi<"openai-codex-responses">, onStreamCreated?: () => void) => EventStreamImpl;
53
+ export declare const streamOpenAICompletions: (model: Model<"openai-completions">, context: Context, options: OptionsForApi<"openai-completions">, onStreamCreated?: () => void) => EventStreamImpl;
54
+ export declare const streamOpenAIResponses: (model: Model<"openai-responses">, context: Context, options: OptionsForApi<"openai-responses">, onStreamCreated?: () => void) => EventStreamImpl;
55
+ export declare const streamCursor: (model: Model<"cursor-agent">, context: Context, options: OptionsForApi<"cursor-agent">, onStreamCreated?: () => void) => EventStreamImpl;
56
+ export declare const streamOllama: (model: Model<"ollama-chat">, context: Context, options: OptionsForApi<"ollama-chat">, onStreamCreated?: () => void) => EventStreamImpl;
57
+ export declare const streamBedrock: (model: Model<"bedrock-converse-stream">, context: Context, options: OptionsForApi<"bedrock-converse-stream">, onStreamCreated?: () => void) => EventStreamImpl;
58
+ export declare const streamKiroCodeWhisperer: (model: Model<"kiro-codewhisperer-stream">, context: Context, options: OptionsForApi<"kiro-codewhisperer-stream">, onStreamCreated?: () => void) => EventStreamImpl;
59
59
  export {};
@@ -29,12 +29,13 @@ export declare function listProvidersWithEnvKey(): string[];
29
29
  * handling, so callers can append it unconditionally.
30
30
  */
31
31
  export declare function formatProviderCredentialHint(provider: string): string;
32
+ export declare function streamFromLazyImport(createInner: () => Promise<AssistantMessageEventStream>, signal?: AbortSignal, onStreamCreated?: () => void): AssistantMessageEventStream;
32
33
  /**
33
34
  * Build an actionable "missing API key" error for a provider, used by the
34
35
  * low-level `stream`/`complete` entry points (#755).
35
36
  */
36
37
  export declare function formatMissingApiKeyError(provider: string): string;
37
- export declare function stream<TApi extends Api>(model: Model<TApi>, context: Context, options?: OptionsForApi<TApi>): AssistantMessageEventStream;
38
+ export declare function stream<TApi extends Api>(model: Model<TApi>, context: Context, options?: OptionsForApi<TApi>, onStreamCreated?: () => void): AssistantMessageEventStream;
38
39
  export declare function complete<TApi extends Api>(model: Model<TApi>, context: Context, options?: OptionsForApi<TApi>): Promise<AssistantMessage>;
39
40
  export declare function streamSimple<TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;
40
41
  export declare function completeSimple<TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): Promise<AssistantMessage>;
@@ -54,7 +54,7 @@ export interface ThinkingConfig {
54
54
  /** Provider-specific transport used to encode the selected effort. */
55
55
  mode: ThinkingControlMode;
56
56
  }
57
- export declare const KNOWN_PROVIDERS: readonly ["alibaba-token-plan", "amazon-bedrock", "kiro", "azure-openai", "anthropic", "google", "google-gemini-cli", "google-antigravity", "google-vertex", "openai", "openai-codex", "opencodex", "kimi-code", "minimax-code", "minimax-code-cn", "github-copilot", "fireworks", "firepass", "fugu", "gitlab-duo", "cursor", "jetbrains-junie", "deepseek", "deepinfra", "xai", "groq", "cerebras", "openrouter", "kilo", "vercel-ai-gateway", "zai", "glm-zcode", "mistral", "minimax", "opencode-go", "opencode-zen", "opengateway", "bizrouter", "mara", "synthetic", "cloudflare-ai-gateway", "huggingface", "litellm", "moonshot", "nvidia", "nanogpt", "ollama", "ollama-cloud", "qianfan", "qwen-portal", "sglang", "together", "venice", "vllm", "xiaomi", "xiaomi-token-plan-sgp", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "zenmux", "lm-studio", "omlx"];
57
+ export declare const KNOWN_PROVIDERS: readonly ["alibaba-token-plan", "amazon-bedrock", "kiro", "azure-openai", "anthropic", "google", "google-gemini-cli", "google-antigravity", "google-vertex", "openai", "openai-codex", "opencodex", "kimi-code", "minimax-code", "minimax-code-cn", "github-copilot", "fireworks", "firepass", "fugu", "gitlab-duo", "cursor", "jetbrains-junie", "deepseek", "deepinfra", "xai", "groq", "cerebras", "openrouter", "kilo", "vercel-ai-gateway", "zai", "glm-zcode", "mistral", "minimax", "opencode-go", "commandcode-goat", "opencode-zen", "opengateway", "bizrouter", "mara", "synthetic", "cloudflare-ai-gateway", "huggingface", "litellm", "moonshot", "nvidia", "nanogpt", "ollama", "ollama-cloud", "qianfan", "qwen-portal", "sglang", "together", "venice", "vllm", "xiaomi", "xiaomi-token-plan-sgp", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "zenmux", "lm-studio", "omlx"];
58
58
  export type KnownProvider = (typeof KNOWN_PROVIDERS)[number];
59
59
  export declare function isKnownProvider(provider: string): provider is KnownProvider;
60
60
  export type Provider = KnownProvider | string;
@@ -155,6 +155,18 @@ export interface RawSseEvent {
155
155
  export type FetchImpl = ((input: string | URL | Request, init?: RequestInit) => Promise<Response>) & {
156
156
  preconnect?: typeof globalThis.fetch.preconnect;
157
157
  };
158
+ /**
159
+ * Credential returned by an auth retry resolver.
160
+ *
161
+ * The optional admission callback lets an authority-bearing caller retain a
162
+ * credential lease until the replacement provider request is actually
163
+ * admitted. Ordinary callers can continue returning a string from
164
+ * {@link StreamOptions.onAuthError}.
165
+ */
166
+ export interface AuthRetryCredential {
167
+ apiKey: string;
168
+ onStreamCreated?: () => void;
169
+ }
158
170
  export interface StreamOptions {
159
171
  temperature?: number;
160
172
  topP?: number;
@@ -186,7 +198,7 @@ export interface StreamOptions {
186
198
  * event has been emitted. Returning a different key retries the provider
187
199
  * request once.
188
200
  */
189
- onAuthError?: (provider: string, apiKey: string, error: unknown) => Promise<string | undefined>;
201
+ onAuthError?: (provider: string, apiKey: string, error: unknown) => Promise<string | AuthRetryCredential | undefined>;
190
202
  cacheRetention?: CacheRetention;
191
203
  /**
192
204
  * Additional headers to include in provider requests.
@@ -243,6 +255,14 @@ export interface StreamOptions {
243
255
  * The `scope` parameter carries the per-attempt identity for execution attribution.
244
256
  */
245
257
  onResponse?: (response: ProviderResponseMetadata, model?: Model<Api>, scope?: AttemptScopeRef) => void | Promise<void>;
258
+ /**
259
+ * Internal dispatch-admission hook. Providers invoke this immediately before
260
+ * submitting an outbound request; stream forwarding retains a first-response
261
+ * fallback for custom providers that do not expose a transport seam.
262
+ */
263
+ onStreamCreated?: () => void;
264
+ /** Internal authority policy: disable provider-owned retries and corrective replays. */
265
+ disableProviderRetries?: boolean;
246
266
  /**
247
267
  * Optional callback for raw Server-Sent Events as they arrive from HTTP streaming providers.
248
268
  *
@@ -399,31 +419,22 @@ export interface ToolCall {
399
419
  */
400
420
  incompleteArgumentsReason?: "truncated" | "malformed" | "conflicting" | "ambiguous";
401
421
  /**
402
- * Set when the raw argument JSON spelled a printable character as a `\uXXXX`
403
- * escape instead of a literal character. This includes ASCII landings because
404
- * a one-nibble mutation can move an intended non-ASCII scalar below U+0080.
405
- * Such a payload parses cleanly but
406
- * is unverifiable: one mistyped hex digit decodes to a different, equally
407
- * valid character, so the text can be silently wrong with no in-band evidence.
408
- * The agent loop resamples the turn a bounded number of times and then
409
- * rejects the call instead of executing it. The single bounded exception
410
- * is a tool that enumerated its display-only fields
411
- * (`displaySafeEscapedArgFields`): when every escaped scalar corroborates
412
- * a decoded non-ASCII character inside those fields, the call executes
413
- * with a warning instead — rendered question text, never executable
414
- * content, ids, or durable metadata.
415
- * Escapes that are required (control characters) or unavoidable (lone
416
- * surrogates) never set this.
422
+ * Set by current producers when raw argument JSON carries unsafe Unicode
423
+ * data, such as malformed escape evidence or a decoded unpaired surrogate.
424
+ * Valid JSON `\uXXXX` escapes are canonical spellings of the decoded string
425
+ * and current producers do not set this flag for them.
426
+ *
427
+ * Legacy producers may still set the flag for any escaped non-ASCII spelling.
428
+ * The agent loop keeps its bounded legacy resample/display-safe behavior for
429
+ * those calls while consuming the transient evidence below.
417
430
  */
418
431
  escapedNonAsciiArguments?: boolean;
419
432
  /**
420
- * Bounded, payload-free evidence for the original raw escape positions and
421
- * process-keyed scalar/path identities. Required for the display-safe terminal exemption: decoded values
422
- * alone cannot prove that an ASCII landing such as `\u0077` was not a
423
- * one-nibble mutation of a non-ASCII escape. Presence of this evidence implies
424
- * the guarded state even if a legacy producer omitted
425
- * `escapedNonAsciiArguments`. The agent consumes and removes this transient
426
- * field before the tool-call message can become durable.
433
+ * Bounded, payload-free evidence for raw Unicode argument data. Current
434
+ * producers attach it only for unsafe data; legacy producers may attach
435
+ * non-malformed positional evidence used by the display-safe compatibility
436
+ * path. The agent consumes and removes this transient field before the
437
+ * tool-call message can become durable.
427
438
  */
428
439
  escapedUnicodeArgumentEvidence?: UnicodeEscapeEvidence;
429
440
  }
@@ -23,6 +23,13 @@ export interface FallbackTrigger {
23
23
  export declare const STREAM_FIRST_EVENT_TIMEOUT_PROVIDER_CODE = "stream_first_event_timeout";
24
24
  /** Stable code for a nominally successful response with no content or token usage. */
25
25
  export declare const EMPTY_RESPONSE_PROVIDER_CODE = "empty_response";
26
+ /**
27
+ * OpenAI's typed capacity-overload code. It arrives without an HTTP status —
28
+ * inside an HTTP 200 terminal Responses envelope or a Codex error event — so the
29
+ * code itself is the only structured evidence of the failure and must survive
30
+ * the existence gate below. It is always compared case-sensitively.
31
+ */
32
+ export declare const SERVER_OVERLOADED_PROVIDER_CODE = "server_is_overloaded";
26
33
  export type TransportHeaders = Headers | Record<string, string | undefined>;
27
34
  /**
28
35
  * Structured facts from an upstream HTTP or transport failure. Retry decisions
@@ -67,9 +67,11 @@ export declare function collectUnicodeEscapeEvidence(json: string): UnicodeEscap
67
67
  /**
68
68
  * Return evidence only when decoded tool arguments are unsafe to execute.
69
69
  *
70
- * Valid JSON escapes and literal UTF-8 have the same canonical decoded value.
71
- * Malformed JSON, duplicate/deep evidence, and unpaired UTF-16 surrogates keep
72
- * the existing fail-closed path.
70
+ * Valid JSON escapes and literal UTF-8 have the same canonical decoded value,
71
+ * including a valid scalar whose hex digits differ from what a caller intended:
72
+ * runtime syntax validation cannot infer author intent after decoding.
73
+ * Malformed escape-bearing JSON, duplicate/deep suspicious escape evidence, and
74
+ * unpaired UTF-16 surrogates keep the fail-closed path.
73
75
  */
74
76
  export declare function collectUnsafeUnicodeEscapeEvidence(json: string): UnicodeEscapeEvidence | undefined;
75
77
  /** Attach unsafe raw evidence while preserving the existing call-level guard flag. */