@wrongstack/providers 0.265.1 → 0.268.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import * as _wrongstack_core from '@wrongstack/core';
1
2
  import { Provider, Capabilities, Request, Response, StreamEvent, ProviderError, TextBlock, Message, Tool, WireFamily, ProviderFactory, Usage, StopReason, ModelsRegistry, CustomModelDefinition, ContentBlock, Logger, ProviderConfig } from '@wrongstack/core';
2
3
 
3
4
  /**
@@ -92,7 +93,7 @@ declare abstract class WireAdapter implements Provider {
92
93
  /** Map Request fields to the wire request body. */
93
94
  protected abstract buildBody(req: Request): Record<string, unknown>;
94
95
  /** Translate wire SSE events into canonical StreamEvent[]. */
95
- protected abstract parseStream(body: ReadableStream<Uint8Array> | NodeJS.ReadableStream | null, fallbackModel: string): AsyncIterable<StreamEvent>;
96
+ protected abstract parseStream(body: ReadableStream<Uint8Array> | NodeJS.ReadableStream | null, fallbackModel: string, req: Request): AsyncIterable<StreamEvent>;
96
97
  /** Build a ProviderError from an HTTP failure response. */
97
98
  protected translateError(status: number, body: string): ProviderError;
98
99
  }
@@ -107,14 +108,14 @@ interface AnthropicProviderOptions {
107
108
  streamOpts?: WireAdapterStreamOptions | undefined;
108
109
  }
109
110
  declare class AnthropicProvider extends WireAdapter {
110
- readonly id = "anthropic";
111
+ readonly id: string;
111
112
  readonly capabilities: Capabilities;
112
113
  private readonly opts;
113
114
  constructor(opts: AnthropicProviderOptions);
114
115
  protected buildUrl(_req: Request): string;
115
116
  protected buildHeaders(req: Request): Record<string, string>;
116
117
  protected buildBody(req: Request): Record<string, unknown>;
117
- protected parseStream(body: Parameters<typeof parseSSE>[0], fallbackModel: string): AsyncIterable<StreamEvent>;
118
+ protected parseStream(body: Parameters<typeof parseSSE>[0], fallbackModel: string, req: Request): AsyncIterable<StreamEvent>;
118
119
  protected translateError(status: number, text: string): ProviderError;
119
120
  private normalizeMessage;
120
121
  }
@@ -196,6 +197,7 @@ interface OpenAIProviderOptions {
196
197
  quirks?: ConvertOptions & {
197
198
  parallelToolsDisabled?: boolean | undefined;
198
199
  jsonArgumentsBuggy?: boolean | undefined;
200
+ thinkingParam?: 'zai-glm' | 'kimi-toggle' | 'always-on' | undefined;
199
201
  } | undefined;
200
202
  id?: string | undefined;
201
203
  capabilities?: Partial<Capabilities> | undefined;
@@ -230,6 +232,7 @@ interface CompatibilityQuirks {
230
232
  parallelToolsDisabled?: boolean | undefined;
231
233
  jsonArgumentsBuggy?: boolean | undefined;
232
234
  emptyToolCallContent?: 'null' | 'empty_string' | undefined;
235
+ thinkingParam?: 'zai-glm' | 'kimi-toggle' | 'always-on' | undefined;
233
236
  }
234
237
  interface OpenAICompatibleOptions {
235
238
  id: string;
@@ -259,6 +262,7 @@ declare class OpenAICompatibleProvider extends OpenAIProvider {
259
262
  * OpenAI's newer `max_completion_tokens`. Keep the legacy field here. See #10.
260
263
  */
261
264
  protected tokenLimitParam(): string;
265
+ protected buildBody(req: Request): Record<string, unknown>;
262
266
  protected buildHeaders(req: Request): Record<string, string>;
263
267
  }
264
268
 
@@ -295,6 +299,212 @@ declare class GoogleProvider extends WireAdapter {
295
299
  private buildGenConfig;
296
300
  }
297
301
 
302
+ /**
303
+ * `openai-codex` wire family — the ChatGPT-backend Responses API.
304
+ *
305
+ * This is the transport used by "Sign in with ChatGPT" (OAuth) credentials.
306
+ * It speaks the OpenAI **Responses** wire format (NOT chat/completions) and
307
+ * targets `https://chatgpt.com/backend-api/codex/responses`, authenticating
308
+ * with the OAuth access token + `chatgpt-account-id` header. It deliberately
309
+ * leaves the API-key `openai` family (api.openai.com/chat/completions)
310
+ * untouched — the two coexist as separate providers.
311
+ *
312
+ * Token lifecycle: the access token is short-lived. This adapter refreshes it
313
+ * transparently — before a request when it is near expiry, and once more on a
314
+ * 401 — using the stored refresh token, then invokes `onRefresh` so the CLI
315
+ * can persist the rotated tokens back to the vault.
316
+ *
317
+ * The refresh endpoint + client id are duplicated here (rather than imported
318
+ * from the CLI) to respect the package layering: `providers` must not depend
319
+ * on `cli`. They are tiny constants that match the CLI login module.
320
+ */
321
+
322
+ interface CodexOAuthTokens {
323
+ access: string;
324
+ refresh: string;
325
+ /** Absolute expiry in epoch milliseconds. */
326
+ expires: number;
327
+ }
328
+ /** Refresh an expired Codex access token using its refresh token. */
329
+ declare function refreshCodexAccessToken(refreshToken: string, signal?: AbortSignal): Promise<CodexOAuthTokens>;
330
+ /** Extract `chatgpt_account_id` from an access-token JWT, or null. */
331
+ declare function extractAccountId(token: string): string | null;
332
+ interface CodexCredentials {
333
+ /** The OAuth access token (a JWT). */
334
+ accessToken: string;
335
+ /** The refresh token, used to mint a new access token before/at expiry. */
336
+ refreshToken?: string | undefined;
337
+ /** Access-token expiry, epoch ms. When absent, refresh only fires on 401. */
338
+ expiresAt?: number | undefined;
339
+ /** Cached ChatGPT account id. Re-derived from the live token when missing. */
340
+ accountId?: string | undefined;
341
+ }
342
+ interface OpenAICodexProviderOptions {
343
+ credentials: CodexCredentials;
344
+ baseUrl?: string | undefined;
345
+ id?: string | undefined;
346
+ fetchImpl?: typeof fetch | undefined;
347
+ capabilities?: Partial<Capabilities> | undefined;
348
+ streamOpts?: WireAdapterStreamOptions | undefined;
349
+ /**
350
+ * Persist rotated tokens after a successful refresh. The CLI wires this to
351
+ * write back to the encrypted config so the new access/refresh pair survive
352
+ * the session.
353
+ */
354
+ onRefresh?: ((creds: {
355
+ accessToken: string;
356
+ refreshToken: string;
357
+ expiresAt: number;
358
+ accountId: string | undefined;
359
+ }) => void) | undefined;
360
+ /** Override the refresh call (tests). */
361
+ refreshFn?: ((refreshToken: string, signal?: AbortSignal) => Promise<CodexOAuthTokens>) | undefined;
362
+ /**
363
+ * Reasoning effort for the Codex (gpt-5.x) reasoning models. Sent as
364
+ * `reasoning.effort` with `summary: 'auto'` so chain-of-thought streams back
365
+ * as thinking deltas. Default 'medium'. Set 'none' to omit reasoning entirely.
366
+ */
367
+ reasoningEffort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | undefined;
368
+ }
369
+ declare class OpenAICodexProvider extends WireAdapter {
370
+ readonly id: string;
371
+ readonly capabilities: Capabilities;
372
+ private access;
373
+ private refresh;
374
+ private expiresAt;
375
+ private accountId;
376
+ private readonly onRefresh;
377
+ private readonly refreshFn;
378
+ private readonly reasoningEffort;
379
+ constructor(opts: OpenAICodexProviderOptions);
380
+ stream(req: Request, opts: {
381
+ signal: AbortSignal;
382
+ }): AsyncIterable<StreamEvent>;
383
+ private ensureFreshToken;
384
+ private doRefresh;
385
+ protected buildUrl(_req: Request): string;
386
+ protected buildHeaders(_req: Request): Record<string, string>;
387
+ protected buildBody(req: Request): Record<string, unknown>;
388
+ protected parseStream(body: ReadableStream<Uint8Array> | NodeJS.ReadableStream | null, fallbackModel: string): AsyncIterable<StreamEvent>;
389
+ protected translateError(status: number, text: string): ProviderError;
390
+ }
391
+ /** Normalize a base URL to the `/codex/responses` endpoint. */
392
+ declare function resolveCodexUrl(baseUrl: string | undefined): string;
393
+
394
+ /**
395
+ * `anthropic-oauth` wire family — Claude Pro/Max via "Sign in with Claude".
396
+ *
397
+ * Same wire as the API-key `anthropic` family (api.anthropic.com/v1/messages),
398
+ * but authenticated with an OAuth access token instead of an API key. Three
399
+ * things differ from the API-key path, all REQUIRED for the subscription
400
+ * backend to accept the request:
401
+ * 1. `Authorization: Bearer <access>` (no `x-api-key`).
402
+ * 2. `anthropic-beta: claude-code-20250219,oauth-2025-04-20`.
403
+ * 3. The first system block MUST be exactly the Claude Code identity line —
404
+ * Anthropic rejects OAuth requests whose system prompt doesn't lead with it.
405
+ *
406
+ * The API-key `anthropic` family is untouched. Tokens self-refresh (near-expiry
407
+ * + once on 401) via the refresh token; rotated tokens persist through the same
408
+ * `setOAuthTokenPersister` hook the codex family uses.
409
+ */
410
+
411
+ /** Required first system block for OAuth/subscription requests. */
412
+ declare const CLAUDE_CODE_SYSTEM_PROMPT = "You are Claude Code, Anthropic's official CLI for Claude.";
413
+ interface AnthropicOAuthTokens {
414
+ access: string;
415
+ refresh: string;
416
+ /** Absolute expiry in epoch milliseconds. */
417
+ expires: number;
418
+ }
419
+ /** Refresh an expired Claude OAuth access token. */
420
+ declare function refreshAnthropicOAuthToken(refreshToken: string, signal?: AbortSignal): Promise<AnthropicOAuthTokens>;
421
+ interface AnthropicOAuthCredentials {
422
+ accessToken: string;
423
+ refreshToken?: string | undefined;
424
+ expiresAt?: number | undefined;
425
+ }
426
+ interface AnthropicOAuthProviderOptions {
427
+ credentials: AnthropicOAuthCredentials;
428
+ baseUrl?: string | undefined;
429
+ id?: string | undefined;
430
+ fetchImpl?: typeof fetch | undefined;
431
+ streamOpts?: WireAdapterStreamOptions | undefined;
432
+ onRefresh?: ((creds: {
433
+ accessToken: string;
434
+ refreshToken: string;
435
+ expiresAt: number;
436
+ }) => void) | undefined;
437
+ refreshFn?: ((refreshToken: string, signal?: AbortSignal) => Promise<AnthropicOAuthTokens>) | undefined;
438
+ }
439
+ declare class AnthropicOAuthProvider extends AnthropicProvider {
440
+ readonly id: string;
441
+ readonly capabilities: Capabilities;
442
+ private access;
443
+ private refresh;
444
+ private expiresAt;
445
+ private readonly onRefresh;
446
+ private readonly refreshFn;
447
+ constructor(opts: AnthropicOAuthProviderOptions);
448
+ stream(req: Request, opts: {
449
+ signal: AbortSignal;
450
+ }): AsyncGenerator<StreamEvent, void, any>;
451
+ /** Map Claude-Code-cased tool_use names in the stream back to real names. */
452
+ private remapToolNames;
453
+ private ensureFreshToken;
454
+ private doRefresh;
455
+ protected buildHeaders(_req: Request): Record<string, string>;
456
+ protected buildBody(req: Request): Record<string, unknown>;
457
+ }
458
+
459
+ /** Derive the Copilot API base URL from a Copilot token's `proxy-ep` field. */
460
+ declare function copilotBaseUrlFromToken(token: string | undefined): string;
461
+ interface CopilotTokenResult {
462
+ /** The short-lived Copilot token (the access token used for chat). */
463
+ token: string;
464
+ /** Absolute expiry in epoch milliseconds. */
465
+ expires: number;
466
+ }
467
+ /** Mint a fresh Copilot token from the long-lived GitHub OAuth token. */
468
+ declare function refreshCopilotToken(githubToken: string, signal?: AbortSignal): Promise<CopilotTokenResult>;
469
+ interface CopilotCredentials {
470
+ /** Current Copilot token (access). May be empty → minted on first request. */
471
+ copilotToken: string;
472
+ /** Long-lived GitHub OAuth token (refresh; does not rotate). */
473
+ githubToken?: string | undefined;
474
+ /** Copilot-token expiry, epoch ms. */
475
+ expiresAt?: number | undefined;
476
+ }
477
+ interface GitHubCopilotProviderOptions {
478
+ credentials: CopilotCredentials;
479
+ id?: string | undefined;
480
+ fetchImpl?: typeof fetch | undefined;
481
+ capabilities?: Partial<Capabilities> | undefined;
482
+ streamOpts?: WireAdapterStreamOptions | undefined;
483
+ onRefresh?: ((creds: {
484
+ accessToken: string;
485
+ refreshToken: string;
486
+ expiresAt: number;
487
+ }) => void) | undefined;
488
+ refreshFn?: ((githubToken: string, signal?: AbortSignal) => Promise<CopilotTokenResult>) | undefined;
489
+ }
490
+ declare class GitHubCopilotProvider extends OpenAIProvider {
491
+ readonly capabilities: Capabilities;
492
+ private copilotToken;
493
+ private readonly githubToken;
494
+ private expiresAt;
495
+ private apiBase;
496
+ private readonly onRefresh;
497
+ private readonly refreshFn;
498
+ constructor(opts: GitHubCopilotProviderOptions);
499
+ stream(req: Request, opts: {
500
+ signal: AbortSignal;
501
+ }): AsyncGenerator<_wrongstack_core.StreamEvent, void, any>;
502
+ private ensureFreshToken;
503
+ private doRefresh;
504
+ protected buildUrl(_req: Request): string;
505
+ protected buildHeaders(_req: Request): Record<string, string>;
506
+ }
507
+
298
508
  /**
299
509
  * Singleton gate for stream debug logging.
300
510
  *
@@ -608,6 +818,19 @@ interface BuildFactoriesOptions {
608
818
  /** Used to log unsupported families during boot. */
609
819
  log?: Logger | undefined;
610
820
  }
821
+ /** Rotated-token payload handed to the OAuth persister after a refresh. */
822
+ interface OAuthRefreshedTokens {
823
+ accessToken: string;
824
+ refreshToken: string;
825
+ expiresAt: number;
826
+ /** ChatGPT account id (codex only); undefined for other OAuth families. */
827
+ accountId?: string | undefined;
828
+ }
829
+ /** @deprecated use OAuthRefreshedTokens */
830
+ type CodexRefreshedTokens = OAuthRefreshedTokens;
831
+ declare function setOAuthTokenPersister(fn: ((providerId: string, creds: OAuthRefreshedTokens) => void) | undefined): void;
832
+ /** @deprecated use setOAuthTokenPersister */
833
+ declare const setCodexTokenPersister: typeof setOAuthTokenPersister;
611
834
  /**
612
835
  * Build one ProviderFactory per provider known to models.dev. The factory's
613
836
  * `create(cfg)` resolves the wire-family at construction time and returns the
@@ -621,4 +844,4 @@ declare function buildProviderFactoriesFromRegistry(opts: BuildFactoriesOptions)
621
844
  */
622
845
  declare function makeProviderFromConfig(id: string, cfg: ProviderConfig): Provider;
623
846
 
624
- export { AnthropicProvider, type AnthropicProviderOptions, type BuildFactoriesOptions, CAPABILITIES_BY_FAMILY, type CompatibilityQuirks, type ConvertOptions, type DebugStreamCallback, type DebugStreamStats, GoogleProvider, type GoogleProviderOptions, type OpenAIChoice, type OpenAICompatibleOptions, OpenAICompatibleProvider, type OpenAIMessage, OpenAIProvider, type OpenAIProviderOptions, type OpenAIToolCall, WireAdapter, type WireAdapterStreamOptions, type WireFactoryOptions, type WireFormatConfig, WireFormatProvider, anthropicWireFormat, buildProviderFactoriesFromRegistry, capabilitiesFor, capabilitiesForFamily, contentFromAnthropic, contentFromOpenAI, createWireFormatFactory, defaultDebugStreamCallback, defineWireFormat, googleWireFormat, isDebugStreamEnabled, makeProviderFromConfig, messagesToOpenAI, mistralWireFormat, normalizeAnthropic, normalizeOpenAI, openaiWireFormat, parseProviderHttpError, pushDebugChunkStats, setDebugStreamCallback, setDebugStreamEnabled, toolsToAnthropic, toolsToOpenAI };
847
+ export { type AnthropicOAuthCredentials, AnthropicOAuthProvider, type AnthropicOAuthProviderOptions, type AnthropicOAuthTokens, AnthropicProvider, type AnthropicProviderOptions, type BuildFactoriesOptions, CAPABILITIES_BY_FAMILY, CLAUDE_CODE_SYSTEM_PROMPT, type CodexCredentials, type CodexOAuthTokens, type CodexRefreshedTokens, type CompatibilityQuirks, type ConvertOptions, type CopilotCredentials, type CopilotTokenResult, type DebugStreamCallback, type DebugStreamStats, GitHubCopilotProvider, type GitHubCopilotProviderOptions, GoogleProvider, type GoogleProviderOptions, type OAuthRefreshedTokens, type OpenAIChoice, OpenAICodexProvider, type OpenAICodexProviderOptions, type OpenAICompatibleOptions, OpenAICompatibleProvider, type OpenAIMessage, OpenAIProvider, type OpenAIProviderOptions, type OpenAIToolCall, WireAdapter, type WireAdapterStreamOptions, type WireFactoryOptions, type WireFormatConfig, WireFormatProvider, anthropicWireFormat, buildProviderFactoriesFromRegistry, capabilitiesFor, capabilitiesForFamily, contentFromAnthropic, contentFromOpenAI, copilotBaseUrlFromToken, createWireFormatFactory, defaultDebugStreamCallback, defineWireFormat, extractAccountId, googleWireFormat, isDebugStreamEnabled, makeProviderFromConfig, messagesToOpenAI, mistralWireFormat, normalizeAnthropic, normalizeOpenAI, openaiWireFormat, parseProviderHttpError, pushDebugChunkStats, refreshAnthropicOAuthToken, refreshCodexAccessToken, refreshCopilotToken, resolveCodexUrl, setCodexTokenPersister, setDebugStreamCallback, setDebugStreamEnabled, setOAuthTokenPersister, toolsToAnthropic, toolsToOpenAI };