@graphorin/provider 0.5.0 → 0.6.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.
Files changed (82) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +14 -9
  3. package/dist/adapters/llamacpp-server.d.ts +1 -1
  4. package/dist/adapters/llamacpp-server.js +1 -1
  5. package/dist/adapters/llamacpp-server.js.map +1 -1
  6. package/dist/adapters/ollama.d.ts.map +1 -1
  7. package/dist/adapters/ollama.js +3 -2
  8. package/dist/adapters/ollama.js.map +1 -1
  9. package/dist/adapters/openai-compatible.d.ts +14 -1
  10. package/dist/adapters/openai-compatible.d.ts.map +1 -1
  11. package/dist/adapters/openai-compatible.js +2 -0
  12. package/dist/adapters/openai-compatible.js.map +1 -1
  13. package/dist/adapters/vercel-messages.js +245 -0
  14. package/dist/adapters/vercel-messages.js.map +1 -0
  15. package/dist/adapters/vercel.d.ts +10 -8
  16. package/dist/adapters/vercel.d.ts.map +1 -1
  17. package/dist/adapters/vercel.js +54 -14
  18. package/dist/adapters/vercel.js.map +1 -1
  19. package/dist/counters/anthropic-wire.js +149 -0
  20. package/dist/counters/anthropic-wire.js.map +1 -0
  21. package/dist/counters/anthropic.d.ts +6 -1
  22. package/dist/counters/anthropic.d.ts.map +1 -1
  23. package/dist/counters/anthropic.js +25 -4
  24. package/dist/counters/anthropic.js.map +1 -1
  25. package/dist/counters/bedrock.js.map +1 -1
  26. package/dist/counters/dispatcher.d.ts.map +1 -1
  27. package/dist/counters/dispatcher.js +6 -4
  28. package/dist/counters/dispatcher.js.map +1 -1
  29. package/dist/counters/google.js.map +1 -1
  30. package/dist/counters/js-tiktoken.js.map +1 -1
  31. package/dist/errors/errors.d.ts +39 -11
  32. package/dist/errors/errors.d.ts.map +1 -1
  33. package/dist/errors/errors.js +54 -11
  34. package/dist/errors/errors.js.map +1 -1
  35. package/dist/errors/index.d.ts +2 -2
  36. package/dist/errors/index.js +2 -2
  37. package/dist/index.d.ts +5 -5
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +7 -6
  40. package/dist/index.js.map +1 -1
  41. package/dist/internal/abort.js +2 -2
  42. package/dist/internal/abort.js.map +1 -1
  43. package/dist/internal/http.js +19 -4
  44. package/dist/internal/http.js.map +1 -1
  45. package/dist/internal/openai-shaped.js +8 -3
  46. package/dist/internal/openai-shaped.js.map +1 -1
  47. package/dist/middleware/compose.d.ts +6 -6
  48. package/dist/middleware/compose.js +7 -7
  49. package/dist/middleware/compose.js.map +1 -1
  50. package/dist/middleware/production-hook.js.map +1 -1
  51. package/dist/middleware/with-cost-limit.d.ts +1 -1
  52. package/dist/middleware/with-cost-limit.js.map +1 -1
  53. package/dist/middleware/with-cost-tracking.d.ts +17 -4
  54. package/dist/middleware/with-cost-tracking.d.ts.map +1 -1
  55. package/dist/middleware/with-cost-tracking.js +12 -2
  56. package/dist/middleware/with-cost-tracking.js.map +1 -1
  57. package/dist/middleware/with-fallback.js +4 -2
  58. package/dist/middleware/with-fallback.js.map +1 -1
  59. package/dist/middleware/with-rate-limit.d.ts +2 -2
  60. package/dist/middleware/with-rate-limit.js.map +1 -1
  61. package/dist/middleware/with-redaction.d.ts +1 -1
  62. package/dist/middleware/with-redaction.js.map +1 -1
  63. package/dist/middleware/with-retry.js +3 -1
  64. package/dist/middleware/with-retry.js.map +1 -1
  65. package/dist/middleware/with-tracing.js +27 -6
  66. package/dist/middleware/with-tracing.js.map +1 -1
  67. package/dist/model-tier/classify.d.ts +1 -1
  68. package/dist/model-tier/classify.js +13 -5
  69. package/dist/model-tier/classify.js.map +1 -1
  70. package/dist/package.js +6 -0
  71. package/dist/package.js.map +1 -0
  72. package/dist/provider.js.map +1 -1
  73. package/dist/reasoning/apply-policy.js.map +1 -1
  74. package/dist/reasoning/classify-contract.js +14 -5
  75. package/dist/reasoning/classify-contract.js.map +1 -1
  76. package/dist/reasoning/retention.js.map +1 -1
  77. package/dist/tool-examples.d.ts +1 -1
  78. package/dist/tool-examples.js +1 -1
  79. package/dist/tool-examples.js.map +1 -1
  80. package/dist/trust/classify-local-provider.d.ts +1 -1
  81. package/dist/trust/classify-local-provider.js.map +1 -1
  82. package/package.json +6 -4
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.js","names":["#modelId","#apiKey","#baseUrl","#fetchImpl","#fallback"],"sources":["../../src/counters/anthropic.ts"],"sourcesContent":["/**\n * `AnthropicAPICounter` uses Anthropic's native count-tokens\n * endpoint when an API key is configured, otherwise falls back to\n * `JsTiktokenCounter`. The native call is opt-in: the user supplies\n * an explicit `apiKey`. The framework never makes the call without\n * one.\n *\n * @packageDocumentation\n */\n\nimport type { Message, TokenCounter } from '@graphorin/core';\n\nimport { stripTrailingSlashes } from '../internal/url-utils.js';\nimport { JsTiktokenCounter } from './js-tiktoken.js';\n\n/**\n * Options for {@link AnthropicAPICounter}.\n *\n * @stable\n */\nexport interface AnthropicAPICounterOptions {\n readonly modelId: string;\n readonly apiKey?: string;\n readonly baseUrl?: string;\n readonly fetchImpl?: typeof fetch;\n /** Identifier carried on the produced counter. */\n readonly id?: string;\n}\n\n/**\n * Counter that talks to `POST /v1/messages/count_tokens` when an API\n * key is configured. Without an API key, the counter delegates to\n * `JsTiktokenCounter('cl100k_base')` the closest publicly-available\n * proxy for Anthropic's tokenizer.\n *\n * @stable\n */\nexport class AnthropicAPICounter implements TokenCounter {\n readonly id: string;\n readonly version: string;\n readonly #modelId: string;\n readonly #apiKey?: string;\n readonly #baseUrl: string;\n readonly #fetchImpl: typeof fetch;\n readonly #fallback: JsTiktokenCounter;\n\n constructor(options: AnthropicAPICounterOptions) {\n this.#modelId = options.modelId;\n if (options.apiKey !== undefined) this.#apiKey = options.apiKey;\n this.#baseUrl = stripTrailingSlashes(options.baseUrl ?? 'https://api.anthropic.com');\n this.#fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);\n this.#fallback = new JsTiktokenCounter({ encoding: 'cl100k_base', modelId: options.modelId });\n this.id = options.id ?? `anthropic-native@${options.modelId}`;\n this.version = `anthropic-native-${options.modelId}-v1`;\n }\n\n async count(messages: ReadonlyArray<Message>): Promise<number> {\n if (this.#apiKey === undefined) return this.#fallback.count(messages);\n try {\n const resp = await this.#fetchImpl(`${this.#baseUrl}/v1/messages/count_tokens`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': this.#apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify({ model: this.#modelId, messages }),\n });\n if (!resp.ok) return this.#fallback.count(messages);\n const json = (await resp.json()) as { input_tokens?: number };\n if (typeof json.input_tokens === 'number') return json.input_tokens;\n return this.#fallback.count(messages);\n } catch {\n return this.#fallback.count(messages);\n }\n }\n\n async countText(text: string): Promise<number> {\n return this.#fallback.countText(text);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAqCA,IAAa,sBAAb,MAAyD;CACvD,AAAS;CACT,AAAS;CACT,CAASA;CACT,CAASC;CACT,CAASC;CACT,CAASC;CACT,CAASC;CAET,YAAY,SAAqC;AAC/C,QAAKJ,UAAW,QAAQ;AACxB,MAAI,QAAQ,WAAW,OAAW,OAAKC,SAAU,QAAQ;AACzD,QAAKC,UAAW,qBAAqB,QAAQ,WAAW,4BAA4B;AACpF,QAAKC,YAAa,QAAQ,aAAa,WAAW,MAAM,KAAK,WAAW;AACxE,QAAKC,WAAY,IAAI,kBAAkB;GAAE,UAAU;GAAe,SAAS,QAAQ;GAAS,CAAC;AAC7F,OAAK,KAAK,QAAQ,MAAM,oBAAoB,QAAQ;AACpD,OAAK,UAAU,oBAAoB,QAAQ,QAAQ;;CAGrD,MAAM,MAAM,UAAmD;AAC7D,MAAI,MAAKH,WAAY,OAAW,QAAO,MAAKG,SAAU,MAAM,SAAS;AACrE,MAAI;GACF,MAAM,OAAO,MAAM,MAAKD,UAAW,GAAG,MAAKD,QAAS,4BAA4B;IAC9E,QAAQ;IACR,SAAS;KACP,gBAAgB;KAChB,aAAa,MAAKD;KAClB,qBAAqB;KACtB;IACD,MAAM,KAAK,UAAU;KAAE,OAAO,MAAKD;KAAU;KAAU,CAAC;IACzD,CAAC;AACF,OAAI,CAAC,KAAK,GAAI,QAAO,MAAKI,SAAU,MAAM,SAAS;GACnD,MAAM,OAAQ,MAAM,KAAK,MAAM;AAC/B,OAAI,OAAO,KAAK,iBAAiB,SAAU,QAAO,KAAK;AACvD,UAAO,MAAKA,SAAU,MAAM,SAAS;UAC/B;AACN,UAAO,MAAKA,SAAU,MAAM,SAAS;;;CAIzC,MAAM,UAAU,MAA+B;AAC7C,SAAO,MAAKA,SAAU,UAAU,KAAK"}
1
+ {"version":3,"file":"anthropic.js","names":["#modelId","#apiKey","#baseUrl","#fetchImpl","#fallback","#logger","#warnFallback","#fallbackWarned"],"sources":["../../src/counters/anthropic.ts"],"sourcesContent":["/**\n * `AnthropicAPICounter` - uses Anthropic's native count-tokens\n * endpoint when an API key is configured, otherwise falls back to\n * `JsTiktokenCounter`. The native call is opt-in: the user supplies\n * an explicit `apiKey`. The framework never makes the call without\n * one.\n *\n * @packageDocumentation\n */\n\nimport type { Message, TokenCounter } from '@graphorin/core';\n\nimport { stripTrailingSlashes } from '../internal/url-utils.js';\nimport { toAnthropicCountPayload } from './anthropic-wire.js';\nimport { JsTiktokenCounter } from './js-tiktoken.js';\n\n/**\n * Options for {@link AnthropicAPICounter}.\n *\n * @stable\n */\nexport interface AnthropicAPICounterOptions {\n readonly modelId: string;\n readonly apiKey?: string;\n readonly baseUrl?: string;\n readonly fetchImpl?: typeof fetch;\n /** Identifier carried on the produced counter. */\n readonly id?: string;\n /**\n * Log sink for the WARN emitted (once per counter) when the native\n * call degrades to the tiktoken fallback. Defaults to `console.warn`.\n */\n readonly logger?: (message: string, meta?: object) => void;\n}\n\n/**\n * Counter that talks to `POST /v1/messages/count_tokens` when an API\n * key is configured. Without an API key, the counter delegates to\n * `JsTiktokenCounter('cl100k_base')` - the closest publicly-available\n * proxy for Anthropic's tokenizer.\n *\n * @stable\n */\nexport class AnthropicAPICounter implements TokenCounter {\n readonly id: string;\n readonly version: string;\n readonly #modelId: string;\n readonly #apiKey?: string;\n readonly #baseUrl: string;\n readonly #fetchImpl: typeof fetch;\n readonly #fallback: JsTiktokenCounter;\n readonly #logger: (message: string, meta?: object) => void;\n #fallbackWarned = false;\n\n constructor(options: AnthropicAPICounterOptions) {\n this.#modelId = options.modelId;\n if (options.apiKey !== undefined) this.#apiKey = options.apiKey;\n this.#baseUrl = stripTrailingSlashes(options.baseUrl ?? 'https://api.anthropic.com');\n this.#fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);\n this.#fallback = new JsTiktokenCounter({ encoding: 'cl100k_base', modelId: options.modelId });\n this.#logger = options.logger ?? ((message, meta) => console.warn(message, meta ?? ''));\n this.id = options.id ?? `anthropic-native@${options.modelId}`;\n this.version = `anthropic-native-${options.modelId}-v1`;\n }\n\n async count(messages: ReadonlyArray<Message>): Promise<number> {\n if (this.#apiKey === undefined) return this.#fallback.count(messages);\n // core-provider-04: the endpoint accepts only Anthropic wire-shaped\n // bodies. Posting Graphorin messages 400s on any transcript with a\n // system / tool message or `toolCalls`, so convert first.\n const payload = toAnthropicCountPayload(messages);\n if (payload === null) return this.#fallback.count(messages);\n try {\n const resp = await this.#fetchImpl(`${this.#baseUrl}/v1/messages/count_tokens`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': this.#apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify({ model: this.#modelId, ...payload }),\n });\n if (!resp.ok) {\n this.#warnFallback(`HTTP ${resp.status}`);\n return this.#fallback.count(messages);\n }\n const json = (await resp.json()) as { input_tokens?: number };\n if (typeof json.input_tokens === 'number') return json.input_tokens;\n this.#warnFallback('response missing input_tokens');\n return this.#fallback.count(messages);\n } catch (cause) {\n this.#warnFallback((cause as Error).message);\n return this.#fallback.count(messages);\n }\n }\n\n async countText(text: string): Promise<number> {\n return this.#fallback.countText(text);\n }\n\n /**\n * WARN once per counter when the native path degrades - a silent\n * fallback to cl100k tiktoken undercounts Claude tokens by ~15-20%,\n * so the degradation must be visible.\n */\n #warnFallback(reason: string): void {\n if (this.#fallbackWarned) return;\n this.#fallbackWarned = true;\n this.#logger(\n `[graphorin/provider] AnthropicAPICounter(${this.#modelId}): native count_tokens failed (${reason}); ` +\n 'falling back to cl100k tiktoken (undercounts Claude by ~15-20%). Further fallbacks are silent.',\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA2CA,IAAa,sBAAb,MAAyD;CACvD,AAAS;CACT,AAAS;CACT,CAASA;CACT,CAASC;CACT,CAASC;CACT,CAASC;CACT,CAASC;CACT,CAASC;CACT,kBAAkB;CAElB,YAAY,SAAqC;AAC/C,QAAKL,UAAW,QAAQ;AACxB,MAAI,QAAQ,WAAW,OAAW,OAAKC,SAAU,QAAQ;AACzD,QAAKC,UAAW,qBAAqB,QAAQ,WAAW,4BAA4B;AACpF,QAAKC,YAAa,QAAQ,aAAa,WAAW,MAAM,KAAK,WAAW;AACxE,QAAKC,WAAY,IAAI,kBAAkB;GAAE,UAAU;GAAe,SAAS,QAAQ;GAAS,CAAC;AAC7F,QAAKC,SAAU,QAAQ,YAAY,SAAS,SAAS,QAAQ,KAAK,SAAS,QAAQ,GAAG;AACtF,OAAK,KAAK,QAAQ,MAAM,oBAAoB,QAAQ;AACpD,OAAK,UAAU,oBAAoB,QAAQ,QAAQ;;CAGrD,MAAM,MAAM,UAAmD;AAC7D,MAAI,MAAKJ,WAAY,OAAW,QAAO,MAAKG,SAAU,MAAM,SAAS;EAIrE,MAAM,UAAU,wBAAwB,SAAS;AACjD,MAAI,YAAY,KAAM,QAAO,MAAKA,SAAU,MAAM,SAAS;AAC3D,MAAI;GACF,MAAM,OAAO,MAAM,MAAKD,UAAW,GAAG,MAAKD,QAAS,4BAA4B;IAC9E,QAAQ;IACR,SAAS;KACP,gBAAgB;KAChB,aAAa,MAAKD;KAClB,qBAAqB;KACtB;IACD,MAAM,KAAK,UAAU;KAAE,OAAO,MAAKD;KAAU,GAAG;KAAS,CAAC;IAC3D,CAAC;AACF,OAAI,CAAC,KAAK,IAAI;AACZ,UAAKM,aAAc,QAAQ,KAAK,SAAS;AACzC,WAAO,MAAKF,SAAU,MAAM,SAAS;;GAEvC,MAAM,OAAQ,MAAM,KAAK,MAAM;AAC/B,OAAI,OAAO,KAAK,iBAAiB,SAAU,QAAO,KAAK;AACvD,SAAKE,aAAc,gCAAgC;AACnD,UAAO,MAAKF,SAAU,MAAM,SAAS;WAC9B,OAAO;AACd,SAAKE,aAAe,MAAgB,QAAQ;AAC5C,UAAO,MAAKF,SAAU,MAAM,SAAS;;;CAIzC,MAAM,UAAU,MAA+B;AAC7C,SAAO,MAAKA,SAAU,UAAU,KAAK;;;;;;;CAQvC,cAAc,QAAsB;AAClC,MAAI,MAAKG,eAAiB;AAC1B,QAAKA,iBAAkB;AACvB,QAAKF,OACH,4CAA4C,MAAKL,QAAS,iCAAiC,OAAO,mGAEnG"}
@@ -1 +1 @@
1
- {"version":3,"file":"bedrock.js","names":["#fallback"],"sources":["../../src/counters/bedrock.ts"],"sourcesContent":["/**\n * `BedrockAPICounter` placeholder counter that delegates to\n * `JsTiktokenCounter('cl100k_base')` for now (Bedrock's native\n * `count_tokens` API requires AWS Signature v4; full integration\n * lands in Phase 16). The proxy is sufficient for v0.1 within the\n * documented ±5% accuracy envelope.\n *\n * @packageDocumentation\n */\n\nimport type { Message, TokenCounter } from '@graphorin/core';\n\nimport { JsTiktokenCounter } from './js-tiktoken.js';\n\n/**\n * Options for {@link BedrockAPICounter}.\n *\n * @stable\n */\nexport interface BedrockAPICounterOptions {\n readonly modelId: string;\n readonly id?: string;\n}\n\n/**\n * @stable\n */\nexport class BedrockAPICounter implements TokenCounter {\n readonly id: string;\n readonly version: string;\n readonly #fallback: JsTiktokenCounter;\n\n constructor(options: BedrockAPICounterOptions) {\n this.#fallback = new JsTiktokenCounter({ encoding: 'cl100k_base', modelId: options.modelId });\n this.id = options.id ?? `bedrock-proxy@${options.modelId}`;\n this.version = `bedrock-cl100k-proxy-${options.modelId}-v1`;\n }\n\n count(messages: ReadonlyArray<Message>): Promise<number> {\n return this.#fallback.count(messages);\n }\n\n countText(text: string): Promise<number> {\n return this.#fallback.countText(text);\n }\n}\n"],"mappings":";;;;;;AA2BA,IAAa,oBAAb,MAAuD;CACrD,AAAS;CACT,AAAS;CACT,CAASA;CAET,YAAY,SAAmC;AAC7C,QAAKA,WAAY,IAAI,kBAAkB;GAAE,UAAU;GAAe,SAAS,QAAQ;GAAS,CAAC;AAC7F,OAAK,KAAK,QAAQ,MAAM,iBAAiB,QAAQ;AACjD,OAAK,UAAU,wBAAwB,QAAQ,QAAQ;;CAGzD,MAAM,UAAmD;AACvD,SAAO,MAAKA,SAAU,MAAM,SAAS;;CAGvC,UAAU,MAA+B;AACvC,SAAO,MAAKA,SAAU,UAAU,KAAK"}
1
+ {"version":3,"file":"bedrock.js","names":["#fallback"],"sources":["../../src/counters/bedrock.ts"],"sourcesContent":["/**\n * `BedrockAPICounter` - placeholder counter that delegates to\n * `JsTiktokenCounter('cl100k_base')` for now (Bedrock's native\n * `count_tokens` API requires AWS Signature v4; full integration\n * lands in Phase 16). The proxy is sufficient for v0.1 within the\n * documented ±5% accuracy envelope.\n *\n * @packageDocumentation\n */\n\nimport type { Message, TokenCounter } from '@graphorin/core';\n\nimport { JsTiktokenCounter } from './js-tiktoken.js';\n\n/**\n * Options for {@link BedrockAPICounter}.\n *\n * @stable\n */\nexport interface BedrockAPICounterOptions {\n readonly modelId: string;\n readonly id?: string;\n}\n\n/**\n * @stable\n */\nexport class BedrockAPICounter implements TokenCounter {\n readonly id: string;\n readonly version: string;\n readonly #fallback: JsTiktokenCounter;\n\n constructor(options: BedrockAPICounterOptions) {\n this.#fallback = new JsTiktokenCounter({ encoding: 'cl100k_base', modelId: options.modelId });\n this.id = options.id ?? `bedrock-proxy@${options.modelId}`;\n this.version = `bedrock-cl100k-proxy-${options.modelId}-v1`;\n }\n\n count(messages: ReadonlyArray<Message>): Promise<number> {\n return this.#fallback.count(messages);\n }\n\n countText(text: string): Promise<number> {\n return this.#fallback.countText(text);\n }\n}\n"],"mappings":";;;;;;AA2BA,IAAa,oBAAb,MAAuD;CACrD,AAAS;CACT,AAAS;CACT,CAASA;CAET,YAAY,SAAmC;AAC7C,QAAKA,WAAY,IAAI,kBAAkB;GAAE,UAAU;GAAe,SAAS,QAAQ;GAAS,CAAC;AAC7F,OAAK,KAAK,QAAQ,MAAM,iBAAiB,QAAQ;AACjD,OAAK,UAAU,wBAAwB,QAAQ,QAAQ;;CAGzD,MAAM,UAAmD;AACvD,SAAO,MAAKA,SAAU,MAAM,SAAS;;CAGvC,UAAU,MAA+B;AACvC,SAAO,MAAKA,SAAU,UAAU,KAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.d.ts","names":[],"sources":["../../src/counters/dispatcher.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UAuBiB,2BAAA;;;;;;;;;;;;;;;;;;;;;iBAuDD,oBAAA,UAA8B,8BAA8B"}
1
+ {"version":3,"file":"dispatcher.d.ts","names":[],"sources":["../../src/counters/dispatcher.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UAuBiB,2BAAA;;;;;;;;;;;;;;;;;;;;;iBA8DD,oBAAA,UAA8B,8BAA8B"}
@@ -14,13 +14,15 @@ import { HeuristicCounter } from "./heuristic.js";
14
14
  */
15
15
  function detectProviderFamily(args) {
16
16
  const provider = args.provider?.toLowerCase();
17
- const modelLower = args.model.toLowerCase();
18
- if (provider === "anthropic" || modelLower.startsWith("claude") || modelLower.startsWith("anthropic.claude")) {
19
- if (provider === "bedrock" || modelLower.startsWith("anthropic.claude")) return "bedrock";
17
+ const modelLower = args.model.toLowerCase().replace(/^(?:us|eu|apac|jp|au|us-gov)\./, "");
18
+ const providerIsAnthropic = provider?.startsWith("anthropic");
19
+ const providerIsBedrock = provider?.includes("bedrock");
20
+ if (providerIsAnthropic || modelLower.startsWith("claude") || modelLower.startsWith("anthropic.claude")) {
21
+ if (providerIsBedrock || modelLower.startsWith("anthropic.claude")) return "bedrock";
20
22
  return "anthropic";
21
23
  }
22
24
  if (provider === "google" || modelLower.startsWith("gemini")) return "google";
23
- if (provider === "bedrock") return "bedrock";
25
+ if (providerIsBedrock) return "bedrock";
24
26
  if (provider === "openai" || provider === "azure-openai" || /^(gpt-|o1|o3|o4)/.test(modelLower)) return "openai";
25
27
  if (provider === "ollama" || modelLower.startsWith("ollama-")) return "ollama";
26
28
  if (provider === "openai-compatible" || provider === "lmstudio" || provider === "vllm") return "openai-compatible";
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.js","names":[],"sources":["../../src/counters/dispatcher.ts"],"sourcesContent":["/**\n * `createDefaultCounter` model-id classifier that returns the\n * recommended {@link TokenCounter} for a given `(provider, model)`\n * pair. The same classifier is reused by the model-tier dispatcher\n * (`@graphorin/provider/model-tier`) so provider-family detection\n * lives in exactly one place.\n *\n * @packageDocumentation\n */\n\nimport type { TokenCounter } from '@graphorin/core';\n\nimport { AnthropicAPICounter } from './anthropic.js';\nimport { BedrockAPICounter } from './bedrock.js';\nimport { GoogleAPICounter } from './google.js';\nimport { HeuristicCounter } from './heuristic.js';\nimport { JsTiktokenCounter } from './js-tiktoken.js';\n\n/**\n * Options for {@link createDefaultCounter}.\n *\n * @stable\n */\nexport interface CreateDefaultCounterOptions {\n /** Concrete model id (e.g. `'gpt-4o'`, `'claude-opus-4-7'`). */\n readonly model: string;\n /** Optional provider hint to short-circuit the regex matching. */\n readonly provider?: string;\n /** Optional Anthropic API key threaded through to {@link AnthropicAPICounter}. */\n readonly anthropicApiKey?: string;\n}\n\n/**\n * Detect the provider family for a model id. Exposed for downstream\n * consumers (the model-tier classifier; future per-tool counters) so\n * provider-family detection is centralised here.\n *\n * @stable\n */\nexport function detectProviderFamily(args: {\n readonly model: string;\n readonly provider?: string;\n}): 'anthropic' | 'openai' | 'google' | 'bedrock' | 'ollama' | 'openai-compatible' | 'unknown' {\n const provider = args.provider?.toLowerCase();\n const modelLower = args.model.toLowerCase();\n if (\n provider === 'anthropic' ||\n modelLower.startsWith('claude') ||\n modelLower.startsWith('anthropic.claude')\n ) {\n if (provider === 'bedrock' || modelLower.startsWith('anthropic.claude')) return 'bedrock';\n return 'anthropic';\n }\n if (provider === 'google' || modelLower.startsWith('gemini')) return 'google';\n if (provider === 'bedrock') return 'bedrock';\n if (provider === 'openai' || provider === 'azure-openai' || /^(gpt-|o1|o3|o4)/.test(modelLower)) {\n return 'openai';\n }\n if (provider === 'ollama' || modelLower.startsWith('ollama-')) return 'ollama';\n if (provider === 'openai-compatible' || provider === 'lmstudio' || provider === 'vllm') {\n return 'openai-compatible';\n }\n return 'unknown';\n}\n\n/**\n * Build the recommended {@link TokenCounter} for the given\n * `(provider, model)` pair. The dispatch table:\n *\n * - Anthropic Claude → `AnthropicAPICounter` (native if `apiKey` set,\n * otherwise `cl100k_base` proxy).\n * - OpenAI / OpenAI-compatible → `JsTiktokenCounter('cl100k_base')`.\n * - Google Gemini → `GoogleAPICounter` (cl100k_base proxy in v0.1).\n * - Bedrock Claude → `BedrockAPICounter` (cl100k_base proxy in v0.1).\n * - Ollama / unknown → `HeuristicCounter` with one WARN per process.\n *\n * @stable\n */\nexport function createDefaultCounter(options: CreateDefaultCounterOptions): TokenCounter {\n const family = detectProviderFamily({\n model: options.model,\n ...(options.provider !== undefined ? { provider: options.provider } : {}),\n });\n switch (family) {\n case 'anthropic':\n return new AnthropicAPICounter({\n modelId: options.model,\n ...(options.anthropicApiKey !== undefined ? { apiKey: options.anthropicApiKey } : {}),\n });\n case 'bedrock':\n return new BedrockAPICounter({ modelId: options.model });\n case 'google':\n return new GoogleAPICounter({ modelId: options.model });\n case 'openai':\n case 'openai-compatible':\n return new JsTiktokenCounter({\n encoding: defaultOpenAiEncoding(options.model),\n modelId: options.model,\n });\n default:\n return new HeuristicCounter({ modelId: options.model });\n }\n}\n\n/**\n * PS-20: pick the fallback tiktoken encoding by model family. `js-tiktoken`'s\n * `encodingForModel` handles ids it recognises; this is the explicit fallback\n * for ids it does not (the 2025/2026 families). gpt-4o / gpt-4.1 / gpt-5+ and\n * the o-series reasoning models use `o200k_base`; legacy gpt-4 / gpt-3.5 stay\n * on `cl100k_base`.\n */\nexport function defaultOpenAiEncoding(model: string | undefined): 'o200k_base' | 'cl100k_base' {\n if (model === undefined) return 'cl100k_base';\n const id = model.toLowerCase();\n const sep = Math.max(id.lastIndexOf('/'), id.lastIndexOf(':'));\n const bare = sep === -1 ? id : id.slice(sep + 1);\n return /^(?:gpt-4o|gpt-4\\.1|gpt-[5-9]|gpt-\\d{2}|o[1-9])/.test(bare)\n ? 'o200k_base'\n : 'cl100k_base';\n}\n"],"mappings":";;;;;;;;;;;;;;AAuCA,SAAgB,qBAAqB,MAG0D;CAC7F,MAAM,WAAW,KAAK,UAAU,aAAa;CAC7C,MAAM,aAAa,KAAK,MAAM,aAAa;AAC3C,KACE,aAAa,eACb,WAAW,WAAW,SAAS,IAC/B,WAAW,WAAW,mBAAmB,EACzC;AACA,MAAI,aAAa,aAAa,WAAW,WAAW,mBAAmB,CAAE,QAAO;AAChF,SAAO;;AAET,KAAI,aAAa,YAAY,WAAW,WAAW,SAAS,CAAE,QAAO;AACrE,KAAI,aAAa,UAAW,QAAO;AACnC,KAAI,aAAa,YAAY,aAAa,kBAAkB,mBAAmB,KAAK,WAAW,CAC7F,QAAO;AAET,KAAI,aAAa,YAAY,WAAW,WAAW,UAAU,CAAE,QAAO;AACtE,KAAI,aAAa,uBAAuB,aAAa,cAAc,aAAa,OAC9E,QAAO;AAET,QAAO;;;;;;;;;;;;;;;AAgBT,SAAgB,qBAAqB,SAAoD;AAKvF,SAJe,qBAAqB;EAClC,OAAO,QAAQ;EACf,GAAI,QAAQ,aAAa,SAAY,EAAE,UAAU,QAAQ,UAAU,GAAG,EAAE;EACzE,CAAC,EACF;EACE,KAAK,YACH,QAAO,IAAI,oBAAoB;GAC7B,SAAS,QAAQ;GACjB,GAAI,QAAQ,oBAAoB,SAAY,EAAE,QAAQ,QAAQ,iBAAiB,GAAG,EAAE;GACrF,CAAC;EACJ,KAAK,UACH,QAAO,IAAI,kBAAkB,EAAE,SAAS,QAAQ,OAAO,CAAC;EAC1D,KAAK,SACH,QAAO,IAAI,iBAAiB,EAAE,SAAS,QAAQ,OAAO,CAAC;EACzD,KAAK;EACL,KAAK,oBACH,QAAO,IAAI,kBAAkB;GAC3B,UAAU,sBAAsB,QAAQ,MAAM;GAC9C,SAAS,QAAQ;GAClB,CAAC;EACJ,QACE,QAAO,IAAI,iBAAiB,EAAE,SAAS,QAAQ,OAAO,CAAC;;;;;;;;;;AAW7D,SAAgB,sBAAsB,OAAyD;AAC7F,KAAI,UAAU,OAAW,QAAO;CAChC,MAAM,KAAK,MAAM,aAAa;CAC9B,MAAM,MAAM,KAAK,IAAI,GAAG,YAAY,IAAI,EAAE,GAAG,YAAY,IAAI,CAAC;CAC9D,MAAM,OAAO,QAAQ,KAAK,KAAK,GAAG,MAAM,MAAM,EAAE;AAChD,QAAO,kDAAkD,KAAK,KAAK,GAC/D,eACA"}
1
+ {"version":3,"file":"dispatcher.js","names":[],"sources":["../../src/counters/dispatcher.ts"],"sourcesContent":["/**\n * `createDefaultCounter` - model-id classifier that returns the\n * recommended {@link TokenCounter} for a given `(provider, model)`\n * pair. The same classifier is reused by the model-tier dispatcher\n * (`@graphorin/provider/model-tier`) so provider-family detection\n * lives in exactly one place.\n *\n * @packageDocumentation\n */\n\nimport type { TokenCounter } from '@graphorin/core';\n\nimport { AnthropicAPICounter } from './anthropic.js';\nimport { BedrockAPICounter } from './bedrock.js';\nimport { GoogleAPICounter } from './google.js';\nimport { HeuristicCounter } from './heuristic.js';\nimport { JsTiktokenCounter } from './js-tiktoken.js';\n\n/**\n * Options for {@link createDefaultCounter}.\n *\n * @stable\n */\nexport interface CreateDefaultCounterOptions {\n /** Concrete model id (e.g. `'gpt-4o'`, `'claude-opus-4-7'`). */\n readonly model: string;\n /** Optional provider hint to short-circuit the regex matching. */\n readonly provider?: string;\n /** Optional Anthropic API key threaded through to {@link AnthropicAPICounter}. */\n readonly anthropicApiKey?: string;\n}\n\n/**\n * Detect the provider family for a model id. Exposed for downstream\n * consumers (the model-tier classifier; future per-tool counters) so\n * provider-family detection is centralised here.\n *\n * @stable\n */\nexport function detectProviderFamily(args: {\n readonly model: string;\n readonly provider?: string;\n}): 'anthropic' | 'openai' | 'google' | 'bedrock' | 'ollama' | 'openai-compatible' | 'unknown' {\n const provider = args.provider?.toLowerCase();\n // Strip the Bedrock cross-region inference-profile prefix\n // (`us.anthropic.claude-…`) so region-qualified ids classify like\n // their bare form (core-provider-11).\n const modelLower = args.model.toLowerCase().replace(/^(?:us|eu|apac|jp|au|us-gov)\\./, '');\n // The AI SDK reports dotted provider ids ('anthropic.messages',\n // 'amazon-bedrock.messages'), so match by prefix / substring.\n const providerIsAnthropic = provider?.startsWith('anthropic');\n const providerIsBedrock = provider?.includes('bedrock');\n if (\n providerIsAnthropic ||\n modelLower.startsWith('claude') ||\n modelLower.startsWith('anthropic.claude')\n ) {\n if (providerIsBedrock || modelLower.startsWith('anthropic.claude')) return 'bedrock';\n return 'anthropic';\n }\n if (provider === 'google' || modelLower.startsWith('gemini')) return 'google';\n if (providerIsBedrock) return 'bedrock';\n if (provider === 'openai' || provider === 'azure-openai' || /^(gpt-|o1|o3|o4)/.test(modelLower)) {\n return 'openai';\n }\n if (provider === 'ollama' || modelLower.startsWith('ollama-')) return 'ollama';\n if (provider === 'openai-compatible' || provider === 'lmstudio' || provider === 'vllm') {\n return 'openai-compatible';\n }\n return 'unknown';\n}\n\n/**\n * Build the recommended {@link TokenCounter} for the given\n * `(provider, model)` pair. The dispatch table:\n *\n * - Anthropic Claude → `AnthropicAPICounter` (native if `apiKey` set,\n * otherwise `cl100k_base` proxy).\n * - OpenAI / OpenAI-compatible → `JsTiktokenCounter('cl100k_base')`.\n * - Google Gemini → `GoogleAPICounter` (cl100k_base proxy in v0.1).\n * - Bedrock Claude → `BedrockAPICounter` (cl100k_base proxy in v0.1).\n * - Ollama / unknown → `HeuristicCounter` with one WARN per process.\n *\n * @stable\n */\nexport function createDefaultCounter(options: CreateDefaultCounterOptions): TokenCounter {\n const family = detectProviderFamily({\n model: options.model,\n ...(options.provider !== undefined ? { provider: options.provider } : {}),\n });\n switch (family) {\n case 'anthropic':\n return new AnthropicAPICounter({\n modelId: options.model,\n ...(options.anthropicApiKey !== undefined ? { apiKey: options.anthropicApiKey } : {}),\n });\n case 'bedrock':\n return new BedrockAPICounter({ modelId: options.model });\n case 'google':\n return new GoogleAPICounter({ modelId: options.model });\n case 'openai':\n case 'openai-compatible':\n return new JsTiktokenCounter({\n encoding: defaultOpenAiEncoding(options.model),\n modelId: options.model,\n });\n default:\n return new HeuristicCounter({ modelId: options.model });\n }\n}\n\n/**\n * PS-20: pick the fallback tiktoken encoding by model family. `js-tiktoken`'s\n * `encodingForModel` handles ids it recognises; this is the explicit fallback\n * for ids it does not (the 2025/2026 families). gpt-4o / gpt-4.1 / gpt-5+ and\n * the o-series reasoning models use `o200k_base`; legacy gpt-4 / gpt-3.5 stay\n * on `cl100k_base`.\n */\nexport function defaultOpenAiEncoding(model: string | undefined): 'o200k_base' | 'cl100k_base' {\n if (model === undefined) return 'cl100k_base';\n const id = model.toLowerCase();\n const sep = Math.max(id.lastIndexOf('/'), id.lastIndexOf(':'));\n const bare = sep === -1 ? id : id.slice(sep + 1);\n return /^(?:gpt-4o|gpt-4\\.1|gpt-[5-9]|gpt-\\d{2}|o[1-9])/.test(bare)\n ? 'o200k_base'\n : 'cl100k_base';\n}\n"],"mappings":";;;;;;;;;;;;;;AAuCA,SAAgB,qBAAqB,MAG0D;CAC7F,MAAM,WAAW,KAAK,UAAU,aAAa;CAI7C,MAAM,aAAa,KAAK,MAAM,aAAa,CAAC,QAAQ,kCAAkC,GAAG;CAGzF,MAAM,sBAAsB,UAAU,WAAW,YAAY;CAC7D,MAAM,oBAAoB,UAAU,SAAS,UAAU;AACvD,KACE,uBACA,WAAW,WAAW,SAAS,IAC/B,WAAW,WAAW,mBAAmB,EACzC;AACA,MAAI,qBAAqB,WAAW,WAAW,mBAAmB,CAAE,QAAO;AAC3E,SAAO;;AAET,KAAI,aAAa,YAAY,WAAW,WAAW,SAAS,CAAE,QAAO;AACrE,KAAI,kBAAmB,QAAO;AAC9B,KAAI,aAAa,YAAY,aAAa,kBAAkB,mBAAmB,KAAK,WAAW,CAC7F,QAAO;AAET,KAAI,aAAa,YAAY,WAAW,WAAW,UAAU,CAAE,QAAO;AACtE,KAAI,aAAa,uBAAuB,aAAa,cAAc,aAAa,OAC9E,QAAO;AAET,QAAO;;;;;;;;;;;;;;;AAgBT,SAAgB,qBAAqB,SAAoD;AAKvF,SAJe,qBAAqB;EAClC,OAAO,QAAQ;EACf,GAAI,QAAQ,aAAa,SAAY,EAAE,UAAU,QAAQ,UAAU,GAAG,EAAE;EACzE,CAAC,EACF;EACE,KAAK,YACH,QAAO,IAAI,oBAAoB;GAC7B,SAAS,QAAQ;GACjB,GAAI,QAAQ,oBAAoB,SAAY,EAAE,QAAQ,QAAQ,iBAAiB,GAAG,EAAE;GACrF,CAAC;EACJ,KAAK,UACH,QAAO,IAAI,kBAAkB,EAAE,SAAS,QAAQ,OAAO,CAAC;EAC1D,KAAK,SACH,QAAO,IAAI,iBAAiB,EAAE,SAAS,QAAQ,OAAO,CAAC;EACzD,KAAK;EACL,KAAK,oBACH,QAAO,IAAI,kBAAkB;GAC3B,UAAU,sBAAsB,QAAQ,MAAM;GAC9C,SAAS,QAAQ;GAClB,CAAC;EACJ,QACE,QAAO,IAAI,iBAAiB,EAAE,SAAS,QAAQ,OAAO,CAAC;;;;;;;;;;AAW7D,SAAgB,sBAAsB,OAAyD;AAC7F,KAAI,UAAU,OAAW,QAAO;CAChC,MAAM,KAAK,MAAM,aAAa;CAC9B,MAAM,MAAM,KAAK,IAAI,GAAG,YAAY,IAAI,EAAE,GAAG,YAAY,IAAI,CAAC;CAC9D,MAAM,OAAO,QAAQ,KAAK,KAAK,GAAG,MAAM,MAAM,EAAE;AAChD,QAAO,kDAAkD,KAAK,KAAK,GAC/D,eACA"}
@@ -1 +1 @@
1
- {"version":3,"file":"google.js","names":["#fallback"],"sources":["../../src/counters/google.ts"],"sourcesContent":["/**\n * `GoogleAPICounter` placeholder counter that delegates to\n * `JsTiktokenCounter('cl100k_base')` for now. The full Google `:countTokens`\n * implementation lands in Phase 16 alongside the optional pricing\n * refresher; for v0.1 the proxy is sufficient (verified within ±5% on\n * the standard fixture corpus per the existing DEC-131 acceptance).\n *\n * @packageDocumentation\n */\n\nimport type { Message, TokenCounter } from '@graphorin/core';\n\nimport { JsTiktokenCounter } from './js-tiktoken.js';\n\n/**\n * Options for {@link GoogleAPICounter}.\n *\n * @stable\n */\nexport interface GoogleAPICounterOptions {\n readonly modelId: string;\n readonly id?: string;\n}\n\n/**\n * @stable\n */\nexport class GoogleAPICounter implements TokenCounter {\n readonly id: string;\n readonly version: string;\n readonly #fallback: JsTiktokenCounter;\n\n constructor(options: GoogleAPICounterOptions) {\n this.#fallback = new JsTiktokenCounter({ encoding: 'cl100k_base', modelId: options.modelId });\n this.id = options.id ?? `google-proxy@${options.modelId}`;\n this.version = `google-cl100k-proxy-${options.modelId}-v1`;\n }\n\n count(messages: ReadonlyArray<Message>): Promise<number> {\n return this.#fallback.count(messages);\n }\n\n countText(text: string): Promise<number> {\n return this.#fallback.countText(text);\n }\n}\n"],"mappings":";;;;;;AA2BA,IAAa,mBAAb,MAAsD;CACpD,AAAS;CACT,AAAS;CACT,CAASA;CAET,YAAY,SAAkC;AAC5C,QAAKA,WAAY,IAAI,kBAAkB;GAAE,UAAU;GAAe,SAAS,QAAQ;GAAS,CAAC;AAC7F,OAAK,KAAK,QAAQ,MAAM,gBAAgB,QAAQ;AAChD,OAAK,UAAU,uBAAuB,QAAQ,QAAQ;;CAGxD,MAAM,UAAmD;AACvD,SAAO,MAAKA,SAAU,MAAM,SAAS;;CAGvC,UAAU,MAA+B;AACvC,SAAO,MAAKA,SAAU,UAAU,KAAK"}
1
+ {"version":3,"file":"google.js","names":["#fallback"],"sources":["../../src/counters/google.ts"],"sourcesContent":["/**\n * `GoogleAPICounter` - placeholder counter that delegates to\n * `JsTiktokenCounter('cl100k_base')` for now. The full Google `:countTokens`\n * implementation lands in Phase 16 alongside the optional pricing\n * refresher; for v0.1 the proxy is sufficient (verified within ±5% on\n * the standard fixture corpus per the existing DEC-131 acceptance).\n *\n * @packageDocumentation\n */\n\nimport type { Message, TokenCounter } from '@graphorin/core';\n\nimport { JsTiktokenCounter } from './js-tiktoken.js';\n\n/**\n * Options for {@link GoogleAPICounter}.\n *\n * @stable\n */\nexport interface GoogleAPICounterOptions {\n readonly modelId: string;\n readonly id?: string;\n}\n\n/**\n * @stable\n */\nexport class GoogleAPICounter implements TokenCounter {\n readonly id: string;\n readonly version: string;\n readonly #fallback: JsTiktokenCounter;\n\n constructor(options: GoogleAPICounterOptions) {\n this.#fallback = new JsTiktokenCounter({ encoding: 'cl100k_base', modelId: options.modelId });\n this.id = options.id ?? `google-proxy@${options.modelId}`;\n this.version = `google-cl100k-proxy-${options.modelId}-v1`;\n }\n\n count(messages: ReadonlyArray<Message>): Promise<number> {\n return this.#fallback.count(messages);\n }\n\n countText(text: string): Promise<number> {\n return this.#fallback.countText(text);\n }\n}\n"],"mappings":";;;;;;AA2BA,IAAa,mBAAb,MAAsD;CACpD,AAAS;CACT,AAAS;CACT,CAASA;CAET,YAAY,SAAkC;AAC5C,QAAKA,WAAY,IAAI,kBAAkB;GAAE,UAAU;GAAe,SAAS,QAAQ;GAAS,CAAC;AAC7F,OAAK,KAAK,QAAQ,MAAM,gBAAgB,QAAQ;AAChD,OAAK,UAAU,uBAAuB,QAAQ,QAAQ;;CAGxD,MAAM,UAAmD;AACvD,SAAO,MAAKA,SAAU,MAAM,SAAS;;CAGvC,UAAU,MAA+B;AACvC,SAAO,MAAKA,SAAU,UAAU,KAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"js-tiktoken.js","names":["cachedModule: TiktokenModule | null","#encoding","#modelId","#moduleOverride","#getEncoder","#encoder","mod: TiktokenModule"],"sources":["../../src/counters/js-tiktoken.ts"],"sourcesContent":["/**\n * `JsTiktokenCounter` default counter for OpenAI / OpenAI-compatible\n * models. The package depends on the `js-tiktoken` peer; when the peer\n * is missing, instantiation throws at first call rather than silently\n * downgrading to a heuristic.\n *\n * @packageDocumentation\n */\n\nimport type { Message, TokenCounter } from '@graphorin/core';\n\nimport { serialiseMessageForCount, serializedToString } from './serialize.js';\n\n/**\n * Loose shape of a `js-tiktoken` encoding. Matches the public\n * `Tiktoken` instance returned by `getEncoding(...)` in the upstream\n * package (we only use `encode` / `name`).\n *\n * @internal\n */\ninterface TiktokenEncoding {\n readonly name?: string;\n encode(text: string): { length: number };\n}\n\ninterface TiktokenModule {\n getEncoding(name: string): TiktokenEncoding;\n encodingForModel?: (model: string) => TiktokenEncoding;\n}\n\n/**\n * Options for {@link JsTiktokenCounter}.\n *\n * @stable\n */\nexport interface JsTiktokenCounterOptions {\n /** Encoding name (`'cl100k_base'`, `'o200k_base'`, …). Default `'cl100k_base'`. */\n readonly encoding?: string;\n /** Optional model id used by `encodingForModel`. Falls back to the explicit `encoding`. */\n readonly modelId?: string;\n /**\n * Override the dynamically-loaded module. Used by tests to inject a\n * stub without taking the real `js-tiktoken` peer dependency.\n */\n readonly moduleOverride?: TiktokenModule;\n /** Identifier carried on the produced counter. */\n readonly id?: string;\n}\n\nlet cachedModule: TiktokenModule | null = null;\n\n/**\n * Counter that delegates to the `js-tiktoken` package. Caches the\n * dynamically-loaded module per process; tests use `moduleOverride`\n * to supply a fixture-shaped substitute.\n *\n * @stable\n */\nexport class JsTiktokenCounter implements TokenCounter {\n readonly id: string;\n readonly version: string;\n readonly #encoding: string;\n readonly #modelId?: string;\n readonly #moduleOverride?: TiktokenModule;\n #encoder: TiktokenEncoding | null = null;\n\n constructor(options: JsTiktokenCounterOptions = {}) {\n this.#encoding = options.encoding ?? 'cl100k_base';\n if (options.modelId !== undefined) this.#modelId = options.modelId;\n if (options.moduleOverride !== undefined) this.#moduleOverride = options.moduleOverride;\n this.id = options.id ?? `js-tiktoken@${this.#encoding}`;\n this.version = `js-tiktoken-${this.#encoding}-v1`;\n }\n\n async count(messages: ReadonlyArray<Message>): Promise<number> {\n const enc = await this.#getEncoder();\n let total = 0;\n for (const msg of messages) {\n const serialised = serialiseMessageForCount(msg);\n total += enc.encode(serializedToString(serialised)).length;\n }\n return total;\n }\n\n async countText(text: string): Promise<number> {\n if (text.length === 0) return 0;\n const enc = await this.#getEncoder();\n return enc.encode(text).length;\n }\n\n async #getEncoder(): Promise<TiktokenEncoding> {\n if (this.#encoder !== null) return this.#encoder;\n const mod = this.#moduleOverride ?? (await loadTiktokenModule());\n if (this.#modelId !== undefined && mod.encodingForModel !== undefined) {\n try {\n this.#encoder = mod.encodingForModel(this.#modelId);\n return this.#encoder;\n } catch {\n // Fall through to the explicit encoding.\n }\n }\n this.#encoder = mod.getEncoding(this.#encoding);\n return this.#encoder;\n }\n}\n\nasync function loadTiktokenModule(): Promise<TiktokenModule> {\n if (cachedModule !== null) return cachedModule;\n let mod: TiktokenModule;\n try {\n mod = (await import('js-tiktoken')) as TiktokenModule;\n } catch (cause) {\n throw new Error(\n \"[graphorin/provider] JsTiktokenCounter requires the 'js-tiktoken' peer dependency. \" +\n 'Install it with `pnpm add js-tiktoken` or pass moduleOverride for tests.',\n { cause },\n );\n }\n if (typeof mod.getEncoding !== 'function') {\n throw new Error(\n '[graphorin/provider] JsTiktokenCounter: installed js-tiktoken does not expose getEncoding().',\n );\n }\n cachedModule = mod;\n return cachedModule;\n}\n\n/**\n * Test-only hook that resets the cached `js-tiktoken` module loader.\n *\n * @internal\n */\nexport function __resetTiktokenCache(): void {\n cachedModule = null;\n}\n"],"mappings":";;;AAiDA,IAAIA,eAAsC;;;;;;;;AAS1C,IAAa,oBAAb,MAAuD;CACrD,AAAS;CACT,AAAS;CACT,CAASC;CACT,CAASC;CACT,CAASC;CACT,WAAoC;CAEpC,YAAY,UAAoC,EAAE,EAAE;AAClD,QAAKF,WAAY,QAAQ,YAAY;AACrC,MAAI,QAAQ,YAAY,OAAW,OAAKC,UAAW,QAAQ;AAC3D,MAAI,QAAQ,mBAAmB,OAAW,OAAKC,iBAAkB,QAAQ;AACzE,OAAK,KAAK,QAAQ,MAAM,eAAe,MAAKF;AAC5C,OAAK,UAAU,eAAe,MAAKA,SAAU;;CAG/C,MAAM,MAAM,UAAmD;EAC7D,MAAM,MAAM,MAAM,MAAKG,YAAa;EACpC,IAAI,QAAQ;AACZ,OAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,aAAa,yBAAyB,IAAI;AAChD,YAAS,IAAI,OAAO,mBAAmB,WAAW,CAAC,CAAC;;AAEtD,SAAO;;CAGT,MAAM,UAAU,MAA+B;AAC7C,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,UADY,MAAM,MAAKA,YAAa,EACzB,OAAO,KAAK,CAAC;;CAG1B,OAAMA,aAAyC;AAC7C,MAAI,MAAKC,YAAa,KAAM,QAAO,MAAKA;EACxC,MAAM,MAAM,MAAKF,kBAAoB,MAAM,oBAAoB;AAC/D,MAAI,MAAKD,YAAa,UAAa,IAAI,qBAAqB,OAC1D,KAAI;AACF,SAAKG,UAAW,IAAI,iBAAiB,MAAKH,QAAS;AACnD,UAAO,MAAKG;UACN;AAIV,QAAKA,UAAW,IAAI,YAAY,MAAKJ,SAAU;AAC/C,SAAO,MAAKI;;;AAIhB,eAAe,qBAA8C;AAC3D,KAAI,iBAAiB,KAAM,QAAO;CAClC,IAAIC;AACJ,KAAI;AACF,QAAO,MAAM,OAAO;UACb,OAAO;AACd,QAAM,IAAI,MACR,+JAEA,EAAE,OAAO,CACV;;AAEH,KAAI,OAAO,IAAI,gBAAgB,WAC7B,OAAM,IAAI,MACR,+FACD;AAEH,gBAAe;AACf,QAAO;;;;;;;AAQT,SAAgB,uBAA6B;AAC3C,gBAAe"}
1
+ {"version":3,"file":"js-tiktoken.js","names":["cachedModule: TiktokenModule | null","#encoding","#modelId","#moduleOverride","#getEncoder","#encoder","mod: TiktokenModule"],"sources":["../../src/counters/js-tiktoken.ts"],"sourcesContent":["/**\n * `JsTiktokenCounter` - default counter for OpenAI / OpenAI-compatible\n * models. The package depends on the `js-tiktoken` peer; when the peer\n * is missing, instantiation throws at first call rather than silently\n * downgrading to a heuristic.\n *\n * @packageDocumentation\n */\n\nimport type { Message, TokenCounter } from '@graphorin/core';\n\nimport { serialiseMessageForCount, serializedToString } from './serialize.js';\n\n/**\n * Loose shape of a `js-tiktoken` encoding. Matches the public\n * `Tiktoken` instance returned by `getEncoding(...)` in the upstream\n * package (we only use `encode` / `name`).\n *\n * @internal\n */\ninterface TiktokenEncoding {\n readonly name?: string;\n encode(text: string): { length: number };\n}\n\ninterface TiktokenModule {\n getEncoding(name: string): TiktokenEncoding;\n encodingForModel?: (model: string) => TiktokenEncoding;\n}\n\n/**\n * Options for {@link JsTiktokenCounter}.\n *\n * @stable\n */\nexport interface JsTiktokenCounterOptions {\n /** Encoding name (`'cl100k_base'`, `'o200k_base'`, …). Default `'cl100k_base'`. */\n readonly encoding?: string;\n /** Optional model id used by `encodingForModel`. Falls back to the explicit `encoding`. */\n readonly modelId?: string;\n /**\n * Override the dynamically-loaded module. Used by tests to inject a\n * stub without taking the real `js-tiktoken` peer dependency.\n */\n readonly moduleOverride?: TiktokenModule;\n /** Identifier carried on the produced counter. */\n readonly id?: string;\n}\n\nlet cachedModule: TiktokenModule | null = null;\n\n/**\n * Counter that delegates to the `js-tiktoken` package. Caches the\n * dynamically-loaded module per process; tests use `moduleOverride`\n * to supply a fixture-shaped substitute.\n *\n * @stable\n */\nexport class JsTiktokenCounter implements TokenCounter {\n readonly id: string;\n readonly version: string;\n readonly #encoding: string;\n readonly #modelId?: string;\n readonly #moduleOverride?: TiktokenModule;\n #encoder: TiktokenEncoding | null = null;\n\n constructor(options: JsTiktokenCounterOptions = {}) {\n this.#encoding = options.encoding ?? 'cl100k_base';\n if (options.modelId !== undefined) this.#modelId = options.modelId;\n if (options.moduleOverride !== undefined) this.#moduleOverride = options.moduleOverride;\n this.id = options.id ?? `js-tiktoken@${this.#encoding}`;\n this.version = `js-tiktoken-${this.#encoding}-v1`;\n }\n\n async count(messages: ReadonlyArray<Message>): Promise<number> {\n const enc = await this.#getEncoder();\n let total = 0;\n for (const msg of messages) {\n const serialised = serialiseMessageForCount(msg);\n total += enc.encode(serializedToString(serialised)).length;\n }\n return total;\n }\n\n async countText(text: string): Promise<number> {\n if (text.length === 0) return 0;\n const enc = await this.#getEncoder();\n return enc.encode(text).length;\n }\n\n async #getEncoder(): Promise<TiktokenEncoding> {\n if (this.#encoder !== null) return this.#encoder;\n const mod = this.#moduleOverride ?? (await loadTiktokenModule());\n if (this.#modelId !== undefined && mod.encodingForModel !== undefined) {\n try {\n this.#encoder = mod.encodingForModel(this.#modelId);\n return this.#encoder;\n } catch {\n // Fall through to the explicit encoding.\n }\n }\n this.#encoder = mod.getEncoding(this.#encoding);\n return this.#encoder;\n }\n}\n\nasync function loadTiktokenModule(): Promise<TiktokenModule> {\n if (cachedModule !== null) return cachedModule;\n let mod: TiktokenModule;\n try {\n mod = (await import('js-tiktoken')) as TiktokenModule;\n } catch (cause) {\n throw new Error(\n \"[graphorin/provider] JsTiktokenCounter requires the 'js-tiktoken' peer dependency. \" +\n 'Install it with `pnpm add js-tiktoken` or pass moduleOverride for tests.',\n { cause },\n );\n }\n if (typeof mod.getEncoding !== 'function') {\n throw new Error(\n '[graphorin/provider] JsTiktokenCounter: installed js-tiktoken does not expose getEncoding().',\n );\n }\n cachedModule = mod;\n return cachedModule;\n}\n\n/**\n * Test-only hook that resets the cached `js-tiktoken` module loader.\n *\n * @internal\n */\nexport function __resetTiktokenCache(): void {\n cachedModule = null;\n}\n"],"mappings":";;;AAiDA,IAAIA,eAAsC;;;;;;;;AAS1C,IAAa,oBAAb,MAAuD;CACrD,AAAS;CACT,AAAS;CACT,CAASC;CACT,CAASC;CACT,CAASC;CACT,WAAoC;CAEpC,YAAY,UAAoC,EAAE,EAAE;AAClD,QAAKF,WAAY,QAAQ,YAAY;AACrC,MAAI,QAAQ,YAAY,OAAW,OAAKC,UAAW,QAAQ;AAC3D,MAAI,QAAQ,mBAAmB,OAAW,OAAKC,iBAAkB,QAAQ;AACzE,OAAK,KAAK,QAAQ,MAAM,eAAe,MAAKF;AAC5C,OAAK,UAAU,eAAe,MAAKA,SAAU;;CAG/C,MAAM,MAAM,UAAmD;EAC7D,MAAM,MAAM,MAAM,MAAKG,YAAa;EACpC,IAAI,QAAQ;AACZ,OAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,aAAa,yBAAyB,IAAI;AAChD,YAAS,IAAI,OAAO,mBAAmB,WAAW,CAAC,CAAC;;AAEtD,SAAO;;CAGT,MAAM,UAAU,MAA+B;AAC7C,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,UADY,MAAM,MAAKA,YAAa,EACzB,OAAO,KAAK,CAAC;;CAG1B,OAAMA,aAAyC;AAC7C,MAAI,MAAKC,YAAa,KAAM,QAAO,MAAKA;EACxC,MAAM,MAAM,MAAKF,kBAAoB,MAAM,oBAAoB;AAC/D,MAAI,MAAKD,YAAa,UAAa,IAAI,qBAAqB,OAC1D,KAAI;AACF,SAAKG,UAAW,IAAI,iBAAiB,MAAKH,QAAS;AACnD,UAAO,MAAKG;UACN;AAIV,QAAKA,UAAW,IAAI,YAAY,MAAKJ,SAAU;AAC/C,SAAO,MAAKI;;;AAIhB,eAAe,qBAA8C;AAC3D,KAAI,iBAAiB,KAAM,QAAO;CAClC,IAAIC;AACJ,KAAI;AACF,QAAO,MAAM,OAAO;UACb,OAAO;AACd,QAAM,IAAI,MACR,+JAEA,EAAE,OAAO,CACV;;AAEH,KAAI,OAAO,IAAI,gBAAgB,WAC7B,OAAM,IAAI,MACR,+FACD;AAEH,gBAAe;AACf,QAAO;;;;;;;AAQT,SAAgB,uBAA6B;AAC3C,gBAAe"}
@@ -1,21 +1,17 @@
1
+ import { ProviderErrorKind } from "@graphorin/core";
2
+
1
3
  //#region src/errors/errors.d.ts
2
- /**
3
- * Typed error hierarchy for `@graphorin/provider`. Every error class
4
- * carries a stable `kind` discriminant (lowercase, kebab-case) plus an
5
- * optional `hint` string pointing the user at the recommended fix.
6
- *
7
- * @packageDocumentation
8
- */
4
+
9
5
  /**
10
6
  * Base class for every error thrown by `@graphorin/provider`. Consumers
11
- * narrow on the discriminant `kind` rather than `instanceof` both
7
+ * narrow on the discriminant `kind` rather than `instanceof` - both
12
8
  * work, but discriminants are subclass-friendly.
13
9
  *
14
10
  * @stable
15
11
  */
16
12
  declare class GraphorinProviderError extends Error {
17
13
  readonly name: string;
18
- /** Stable discriminant `'middleware-ordering'`, `'rate-limit-exceeded'`, … */
14
+ /** Stable discriminant - `'middleware-ordering'`, `'rate-limit-exceeded'`, … */
19
15
  readonly kind: string;
20
16
  /** Optional remediation hint shown alongside the message. */
21
17
  readonly hint?: string;
@@ -87,7 +83,7 @@ declare class RateLimitExceededError extends GraphorinProviderError {
87
83
  /**
88
84
  * `withRedaction` detected a hit AND the policy is configured for
89
85
  * `failClosed: true`. The matched value is **never** part of the
90
- * message only the pattern name and field path.
86
+ * message - only the pattern name and field path.
91
87
  *
92
88
  * @stable
93
89
  */
@@ -123,6 +119,23 @@ declare class LocalProviderInsecureTransportError extends GraphorinProviderError
123
119
  */
124
120
  declare const OllamaInsecureTransportError: typeof LocalProviderInsecureTransportError;
125
121
  type OllamaInsecureTransportError = LocalProviderInsecureTransportError;
122
+ /**
123
+ * Map an HTTP status (plus optional error-body text) onto the
124
+ * canonical {@link import('@graphorin/core').ProviderErrorKind}. One
125
+ * shared table so `withRetry` / `withFallback` and consumers switching
126
+ * on the documented kinds see consistent values from every HTTP
127
+ * adapter:
128
+ *
129
+ * - `429` → `'rate-limit'`
130
+ * - `401` / `403` → `'unauthorized'`
131
+ * - `400` / `404` / `422` → `'invalid-request'` (or
132
+ * `'context-length'` when the body says so)
133
+ * - `503` / `529` → `'capacity'` (529 is Anthropic's overloaded code)
134
+ * - other `5xx` and `0` (network failure) → `'transient'`
135
+ *
136
+ * @stable
137
+ */
138
+ declare function classifyHttpStatus(status: number, bodyText?: string): ProviderErrorKind;
126
139
  /**
127
140
  * Wrapped HTTP error returned by an adapter. Carries the original
128
141
  * status code so middleware (`withRetry`, `withFallback`) can decide
@@ -134,11 +147,26 @@ declare class ProviderHttpError extends GraphorinProviderError {
134
147
  readonly name = "ProviderHttpError";
135
148
  readonly status: number;
136
149
  readonly providerName: string;
150
+ /**
151
+ * The canonical `ProviderErrorKind` mapped from the HTTP status via
152
+ * {@link classifyHttpStatus} (the `kind` field keeps its stable
153
+ * `'provider-http'` discriminant). Middleware predicates consult
154
+ * this so a 429 fails over / retries as a rate limit.
155
+ */
156
+ readonly errorKind: ProviderErrorKind;
157
+ /**
158
+ * Backoff-relevant response headers captured from the failed
159
+ * response (`retry-after`, `x-ratelimit-*`), lowercased.
160
+ * `withRetry`'s Retry-After hint reader consumes them.
161
+ */
162
+ readonly headers?: Readonly<Record<string, string>>;
137
163
  constructor(args: {
138
164
  providerName: string;
139
165
  status: number;
140
166
  message: string;
141
167
  cause?: unknown;
168
+ errorKind?: ProviderErrorKind;
169
+ headers?: Readonly<Record<string, string>>;
142
170
  });
143
171
  }
144
172
  /**
@@ -163,5 +191,5 @@ declare class InvalidProviderError extends GraphorinProviderError {
163
191
  constructor(message: string);
164
192
  }
165
193
  //#endregion
166
- export { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError };
194
+ export { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError, classifyHttpStatus };
167
195
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/errors/errors.ts"],"sourcesContent":[],"mappings":";;AAeA;AAwBA;AAiCA;AAyBA;AA2BA;AAmBA;AA6BA;AAyBA;AACA;AASA;AAoBA;AAkBA;;cAtOa,sBAAA,SAA+B,KAAA;;;;;;;;;;;;;;;;;;;cAwB/B,uBAAA,SAAgC,sBAAA;;;;;;;;;;;;;;;;;cAiChC,gCAAA,SAAyC,sBAAA;;;;;;;;;;;;cAyBzC,uBAAA,SAAgC,sBAAA;;;;;;;;;;;;;;;;;;cA2BhC,sBAAA,SAA+B,sBAAA;;;;;;;;;;;;cAmB/B,oBAAA,SAA6B,sBAAA;;;;;;;;;;;;;;;;;;;cA6B7B,mCAAA,SAA4C,sBAAA;;;;;;;;;;;cAyB5C,qCAA4B;KAC7B,4BAAA,GAA+B;;;;;;;;cAS9B,iBAAA,SAA0B,sBAAA;;;;;;;;;;;;;;;;;cAoB1B,wBAAA,SAAiC,sBAAA;;;;;;;;;;;cAkBjC,oBAAA,SAA6B,sBAAA"}
1
+ {"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/errors/errors.ts"],"sourcesContent":[],"mappings":";;;;AAiJA;AA6BA;AAyBA;AACA;AA4BA;AAmBA;;AAgB8B,cAtPjB,sBAAA,SAA+B,KAAA,CAsPd;EAAT,SAAA,IAAA,EAAA,MAAA;EAOL;EACO,SAAA,IAAA,EAAA,MAAA;EAAT;EAxByB,SAAA,IAAA,CAAA,EAAA,MAAA;EAAsB,WAAA,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,QAAA,EAAA;IA0ChD,KAAA,CAAA,EAAA,OAAA;IAkBA,IAAA,CAAA,EAAA,MAAA;;;;;;;;;;;cA1QA,uBAAA,SAAgC,sBAAA;;;;;;;;;;;;;;;;;cAiChC,gCAAA,SAAyC,sBAAA;;;;;;;;;;;;cAyBzC,uBAAA,SAAgC,sBAAA;;;;;;;;;;;;;;;;;;cA2BhC,sBAAA,SAA+B,sBAAA;;;;;;;;;;;;cAmB/B,oBAAA,SAA6B,sBAAA;;;;;;;;;;;;;;;;;;;cA6B7B,mCAAA,SAA4C,sBAAA;;;;;;;;;;;cAyB5C,qCAA4B;KAC7B,4BAAA,GAA+B;;;;;;;;;;;;;;;;;iBA4B3B,kBAAA,qCAAuD;;;;;;;;cAmB1D,iBAAA,SAA0B,sBAAA;;;;;;;;;;sBAUjB;;;;;;qBAMD,SAAS;;;;;;gBAOd;cACF,SAAS;;;;;;;;;cAkBV,wBAAA,SAAiC,sBAAA;;;;;;;;;;;cAkBjC,oBAAA,SAA6B,sBAAA"}
@@ -1,21 +1,14 @@
1
1
  //#region src/errors/errors.ts
2
2
  /**
3
- * Typed error hierarchy for `@graphorin/provider`. Every error class
4
- * carries a stable `kind` discriminant (lowercase, kebab-case) plus an
5
- * optional `hint` string pointing the user at the recommended fix.
6
- *
7
- * @packageDocumentation
8
- */
9
- /**
10
3
  * Base class for every error thrown by `@graphorin/provider`. Consumers
11
- * narrow on the discriminant `kind` rather than `instanceof` both
4
+ * narrow on the discriminant `kind` rather than `instanceof` - both
12
5
  * work, but discriminants are subclass-friendly.
13
6
  *
14
7
  * @stable
15
8
  */
16
9
  var GraphorinProviderError = class extends Error {
17
10
  name = "GraphorinProviderError";
18
- /** Stable discriminant `'middleware-ordering'`, `'rate-limit-exceeded'`, … */
11
+ /** Stable discriminant - `'middleware-ordering'`, `'rate-limit-exceeded'`, … */
19
12
  kind;
20
13
  /** Optional remediation hint shown alongside the message. */
21
14
  hint;
@@ -94,7 +87,7 @@ var RateLimitExceededError = class extends GraphorinProviderError {
94
87
  /**
95
88
  * `withRedaction` detected a hit AND the policy is configured for
96
89
  * `failClosed: true`. The matched value is **never** part of the
97
- * message only the pattern name and field path.
90
+ * message - only the pattern name and field path.
98
91
  *
99
92
  * @stable
100
93
  */
@@ -134,6 +127,41 @@ var LocalProviderInsecureTransportError = class extends GraphorinProviderError {
134
127
  */
135
128
  const OllamaInsecureTransportError = LocalProviderInsecureTransportError;
136
129
  /**
130
+ * Body phrasings used by the major providers when the request blew the
131
+ * model's context window. Sniffed by {@link classifyHttpStatus} so a
132
+ * 400 that is really a context overflow surfaces as `'context-length'`
133
+ * (the kind the compaction / emergency tiers key on), not a generic
134
+ * `'invalid-request'`.
135
+ */
136
+ const CONTEXT_LENGTH_BODY_RE = /context[_ -]?length|context window|prompt is too long|maximum context|too many tokens|exceeds? the (?:model'?s? )?max/i;
137
+ /**
138
+ * Map an HTTP status (plus optional error-body text) onto the
139
+ * canonical {@link import('@graphorin/core').ProviderErrorKind}. One
140
+ * shared table so `withRetry` / `withFallback` and consumers switching
141
+ * on the documented kinds see consistent values from every HTTP
142
+ * adapter:
143
+ *
144
+ * - `429` → `'rate-limit'`
145
+ * - `401` / `403` → `'unauthorized'`
146
+ * - `400` / `404` / `422` → `'invalid-request'` (or
147
+ * `'context-length'` when the body says so)
148
+ * - `503` / `529` → `'capacity'` (529 is Anthropic's overloaded code)
149
+ * - other `5xx` and `0` (network failure) → `'transient'`
150
+ *
151
+ * @stable
152
+ */
153
+ function classifyHttpStatus(status, bodyText) {
154
+ if (status === 429) return "rate-limit";
155
+ if (status === 401 || status === 403) return "unauthorized";
156
+ if (status === 400 || status === 404 || status === 422) {
157
+ if (bodyText !== void 0 && CONTEXT_LENGTH_BODY_RE.test(bodyText)) return "context-length";
158
+ return "invalid-request";
159
+ }
160
+ if (status === 503 || status === 529) return "capacity";
161
+ if (status >= 500 || status === 0) return "transient";
162
+ return "unknown";
163
+ }
164
+ /**
137
165
  * Wrapped HTTP error returned by an adapter. Carries the original
138
166
  * status code so middleware (`withRetry`, `withFallback`) can decide
139
167
  * whether the error is retryable.
@@ -144,10 +172,25 @@ var ProviderHttpError = class extends GraphorinProviderError {
144
172
  name = "ProviderHttpError";
145
173
  status;
146
174
  providerName;
175
+ /**
176
+ * The canonical `ProviderErrorKind` mapped from the HTTP status via
177
+ * {@link classifyHttpStatus} (the `kind` field keeps its stable
178
+ * `'provider-http'` discriminant). Middleware predicates consult
179
+ * this so a 429 fails over / retries as a rate limit.
180
+ */
181
+ errorKind;
182
+ /**
183
+ * Backoff-relevant response headers captured from the failed
184
+ * response (`retry-after`, `x-ratelimit-*`), lowercased.
185
+ * `withRetry`'s Retry-After hint reader consumes them.
186
+ */
187
+ headers;
147
188
  constructor(args) {
148
189
  super("provider-http", `[${args.providerName}] HTTP ${args.status}: ${args.message}`, { ...args.cause !== void 0 ? { cause: args.cause } : {} });
149
190
  this.providerName = args.providerName;
150
191
  this.status = args.status;
192
+ this.errorKind = args.errorKind ?? classifyHttpStatus(args.status, args.message);
193
+ if (args.headers !== void 0) this.headers = args.headers;
151
194
  }
152
195
  };
153
196
  /**
@@ -178,5 +221,5 @@ var InvalidProviderError = class extends GraphorinProviderError {
178
221
  };
179
222
 
180
223
  //#endregion
181
- export { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError };
224
+ export { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError, classifyHttpStatus };
182
225
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../../src/errors/errors.ts"],"sourcesContent":["/**\n * Typed error hierarchy for `@graphorin/provider`. Every error class\n * carries a stable `kind` discriminant (lowercase, kebab-case) plus an\n * optional `hint` string pointing the user at the recommended fix.\n *\n * @packageDocumentation\n */\n\n/**\n * Base class for every error thrown by `@graphorin/provider`. Consumers\n * narrow on the discriminant `kind` rather than `instanceof` — both\n * work, but discriminants are subclass-friendly.\n *\n * @stable\n */\nexport class GraphorinProviderError extends Error {\n override readonly name: string = 'GraphorinProviderError';\n /** Stable discriminant — `'middleware-ordering'`, `'rate-limit-exceeded'`, … */\n readonly kind: string;\n /** Optional remediation hint shown alongside the message. */\n readonly hint?: string;\n\n constructor(kind: string, message: string, options?: { cause?: unknown; hint?: string }) {\n super(message, options?.cause !== undefined ? { cause: options.cause } : undefined);\n this.kind = kind;\n if (options?.hint !== undefined) {\n this.hint = options.hint;\n }\n }\n}\n\n/**\n * The middleware composer detected an out-of-order middleware. The\n * `offendingPair` field carries the `[outer, inner]` middleware names\n * that violated the canonical order so consumers can surface a precise\n * fix in IDE diagnostics.\n *\n * @stable\n */\nexport class MiddlewareOrderingError extends GraphorinProviderError {\n override readonly name = 'MiddlewareOrderingError';\n readonly offendingPair: readonly [string, string];\n readonly canonicalOrder: readonly string[];\n\n constructor(args: {\n offendingPair: readonly [string, string];\n canonicalOrder: readonly string[];\n message?: string;\n }) {\n super(\n 'middleware-ordering',\n args.message ??\n `Middleware order violation: '${args.offendingPair[0]}' must not wrap '${args.offendingPair[1]}'. ` +\n `Canonical order (outer → inner): ${args.canonicalOrder.join(' → ')}.`,\n {\n hint:\n 'Reorder the middleware array passed to composeProviderMiddleware([...]) to match the canonical order; ' +\n 'see @graphorin/provider/middleware for documentation.',\n },\n );\n this.offendingPair = args.offendingPair;\n this.canonicalOrder = args.canonicalOrder;\n }\n}\n\n/**\n * `withRedaction` was missing at production startup. Thrown by the\n * production hook applied to every composed provider when\n * `process.env.NODE_ENV === 'production'`.\n *\n * @stable\n */\nexport class MissingProductionMiddlewareError extends GraphorinProviderError {\n override readonly name = 'MissingProductionMiddlewareError';\n readonly missing: string;\n\n constructor(missing: string) {\n super(\n 'missing-production-middleware',\n `Production startup hook: required middleware '${missing}' is missing from the provider chain.`,\n {\n hint:\n `Compose '${missing}' as the innermost layer (closest to the underlying provider) before deploying. ` +\n 'See @graphorin/provider/middleware for the canonical composition order.',\n },\n );\n this.missing = missing;\n }\n}\n\n/**\n * `withCostLimit` exceeded its configured ceiling. Carries the\n * triggering scope (`session`, `agent`, `run`, …) so the caller can\n * decide how to surface the breach.\n *\n * @stable\n */\nexport class CostBudgetExceededError extends GraphorinProviderError {\n override readonly name = 'CostBudgetExceededError';\n readonly scope: string;\n readonly limit: number;\n readonly observed: number;\n\n constructor(args: { scope: string; limit: number; observed: number; currency?: string }) {\n super(\n 'cost-budget-exceeded',\n `Cost budget exceeded for '${args.scope}': observed ${args.observed.toFixed(4)} ${args.currency ?? 'USD'} ` +\n `> limit ${args.limit.toFixed(4)} ${args.currency ?? 'USD'}.`,\n {\n hint: 'Raise the limit in withCostLimit({...}), tighten the prompt, or switch to a cheaper model tier.',\n },\n );\n this.scope = args.scope;\n this.limit = args.limit;\n this.observed = args.observed;\n }\n}\n\n/**\n * `withRateLimit` exhausted its bucket and the caller did not opt\n * into `'queue'` mode.\n *\n * @stable\n */\nexport class RateLimitExceededError extends GraphorinProviderError {\n override readonly name = 'RateLimitExceededError';\n readonly retryAfterMs: number;\n\n constructor(retryAfterMs: number) {\n super('rate-limit-exceeded', `Rate limit exceeded; retry after ${retryAfterMs}ms.`, {\n hint: 'Slow down the request rate, raise the bucket size in withRateLimit({...}), or switch to mode: \"queue\".',\n });\n this.retryAfterMs = retryAfterMs;\n }\n}\n\n/**\n * `withRedaction` detected a hit AND the policy is configured for\n * `failClosed: true`. The matched value is **never** part of the\n * message — only the pattern name and field path.\n *\n * @stable\n */\nexport class PromptRedactionError extends GraphorinProviderError {\n override readonly name = 'PromptRedactionError';\n readonly patternName: string;\n readonly fieldPath: string;\n readonly role?: string;\n\n constructor(args: { patternName: string; fieldPath: string; role?: string }) {\n super(\n 'prompt-redaction-fail-closed',\n `Outbound prompt-redaction policy is fail-closed and matched pattern '${args.patternName}' ` +\n `at '${args.fieldPath}'${args.role ? ` (role: ${args.role})` : ''}.`,\n {\n hint: 'Sanitize the prompt before calling the provider, or disable failClosed in withRedaction({...}) for this environment.',\n },\n );\n this.patternName = args.patternName;\n this.fieldPath = args.fieldPath;\n if (args.role !== undefined) this.role = args.role;\n }\n}\n\n/**\n * Raised when a `baseUrl`-driven local adapter is configured against\n * a public host over plaintext HTTP. Adapters refuse to start unless\n * `allowInsecureTransport: true` is supplied (and the override is\n * audit-logged).\n *\n * @stable\n */\nexport class LocalProviderInsecureTransportError extends GraphorinProviderError {\n override readonly name = 'LocalProviderInsecureTransportError';\n readonly baseUrl: string;\n\n constructor(baseUrl: string) {\n super(\n 'local-provider-insecure-transport',\n `Refusing to start: the provider baseUrl '${baseUrl}' is public AND plaintext (http://). ` +\n `Switch to https:// or set allowInsecureTransport: true to acknowledge the risk.`,\n {\n hint:\n 'Public local-LLM endpoints must be served over TLS. Acceptable alternatives: terminate TLS in front of the model server, ' +\n 'tunnel through SSH / WireGuard / Tailscale, or pass allowInsecureTransport: true (audit-logged).',\n },\n );\n this.baseUrl = baseUrl;\n }\n}\n\n/**\n * Legacy alias preserved for one minor; prefer\n * {@link LocalProviderInsecureTransportError}. Removed in v0.2.\n *\n * @deprecated Use {@link LocalProviderInsecureTransportError} instead.\n */\nexport const OllamaInsecureTransportError = LocalProviderInsecureTransportError;\nexport type OllamaInsecureTransportError = LocalProviderInsecureTransportError;\n\n/**\n * Wrapped HTTP error returned by an adapter. Carries the original\n * status code so middleware (`withRetry`, `withFallback`) can decide\n * whether the error is retryable.\n *\n * @stable\n */\nexport class ProviderHttpError extends GraphorinProviderError {\n override readonly name = 'ProviderHttpError';\n readonly status: number;\n readonly providerName: string;\n\n constructor(args: { providerName: string; status: number; message: string; cause?: unknown }) {\n super('provider-http', `[${args.providerName}] HTTP ${args.status}: ${args.message}`, {\n ...(args.cause !== undefined ? { cause: args.cause } : {}),\n });\n this.providerName = args.providerName;\n this.status = args.status;\n }\n}\n\n/**\n * The streaming response did not match the documented wire format\n * (e.g. malformed SSE chunk, truncated JSON).\n *\n * @stable\n */\nexport class ProviderStreamParseError extends GraphorinProviderError {\n override readonly name = 'ProviderStreamParseError';\n readonly providerName: string;\n\n constructor(providerName: string, message: string, cause?: unknown) {\n super('provider-stream-parse', `[${providerName}] ${message}`, {\n ...(cause !== undefined ? { cause } : {}),\n });\n this.providerName = providerName;\n }\n}\n\n/**\n * The classifier dispatcher was given a non-Provider value. Programming\n * error; fail-fast at the boundary.\n *\n * @stable\n */\nexport class InvalidProviderError extends GraphorinProviderError {\n override readonly name = 'InvalidProviderError';\n\n constructor(message: string) {\n super('invalid-provider', message, {\n hint: 'Pass the value returned by createProvider(...) (or any adapter factory) instead of a raw object.',\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../src/errors/errors.ts"],"sourcesContent":["/**\n * Typed error hierarchy for `@graphorin/provider`. Every error class\n * carries a stable `kind` discriminant (lowercase, kebab-case) plus an\n * optional `hint` string pointing the user at the recommended fix.\n *\n * @packageDocumentation\n */\n\nimport type { ProviderErrorKind } from '@graphorin/core';\n\n/**\n * Base class for every error thrown by `@graphorin/provider`. Consumers\n * narrow on the discriminant `kind` rather than `instanceof` - both\n * work, but discriminants are subclass-friendly.\n *\n * @stable\n */\nexport class GraphorinProviderError extends Error {\n override readonly name: string = 'GraphorinProviderError';\n /** Stable discriminant - `'middleware-ordering'`, `'rate-limit-exceeded'`, … */\n readonly kind: string;\n /** Optional remediation hint shown alongside the message. */\n readonly hint?: string;\n\n constructor(kind: string, message: string, options?: { cause?: unknown; hint?: string }) {\n super(message, options?.cause !== undefined ? { cause: options.cause } : undefined);\n this.kind = kind;\n if (options?.hint !== undefined) {\n this.hint = options.hint;\n }\n }\n}\n\n/**\n * The middleware composer detected an out-of-order middleware. The\n * `offendingPair` field carries the `[outer, inner]` middleware names\n * that violated the canonical order so consumers can surface a precise\n * fix in IDE diagnostics.\n *\n * @stable\n */\nexport class MiddlewareOrderingError extends GraphorinProviderError {\n override readonly name = 'MiddlewareOrderingError';\n readonly offendingPair: readonly [string, string];\n readonly canonicalOrder: readonly string[];\n\n constructor(args: {\n offendingPair: readonly [string, string];\n canonicalOrder: readonly string[];\n message?: string;\n }) {\n super(\n 'middleware-ordering',\n args.message ??\n `Middleware order violation: '${args.offendingPair[0]}' must not wrap '${args.offendingPair[1]}'. ` +\n `Canonical order (outer → inner): ${args.canonicalOrder.join(' → ')}.`,\n {\n hint:\n 'Reorder the middleware array passed to composeProviderMiddleware([...]) to match the canonical order; ' +\n 'see @graphorin/provider/middleware for documentation.',\n },\n );\n this.offendingPair = args.offendingPair;\n this.canonicalOrder = args.canonicalOrder;\n }\n}\n\n/**\n * `withRedaction` was missing at production startup. Thrown by the\n * production hook applied to every composed provider when\n * `process.env.NODE_ENV === 'production'`.\n *\n * @stable\n */\nexport class MissingProductionMiddlewareError extends GraphorinProviderError {\n override readonly name = 'MissingProductionMiddlewareError';\n readonly missing: string;\n\n constructor(missing: string) {\n super(\n 'missing-production-middleware',\n `Production startup hook: required middleware '${missing}' is missing from the provider chain.`,\n {\n hint:\n `Compose '${missing}' as the innermost layer (closest to the underlying provider) before deploying. ` +\n 'See @graphorin/provider/middleware for the canonical composition order.',\n },\n );\n this.missing = missing;\n }\n}\n\n/**\n * `withCostLimit` exceeded its configured ceiling. Carries the\n * triggering scope (`session`, `agent`, `run`, …) so the caller can\n * decide how to surface the breach.\n *\n * @stable\n */\nexport class CostBudgetExceededError extends GraphorinProviderError {\n override readonly name = 'CostBudgetExceededError';\n readonly scope: string;\n readonly limit: number;\n readonly observed: number;\n\n constructor(args: { scope: string; limit: number; observed: number; currency?: string }) {\n super(\n 'cost-budget-exceeded',\n `Cost budget exceeded for '${args.scope}': observed ${args.observed.toFixed(4)} ${args.currency ?? 'USD'} ` +\n `> limit ${args.limit.toFixed(4)} ${args.currency ?? 'USD'}.`,\n {\n hint: 'Raise the limit in withCostLimit({...}), tighten the prompt, or switch to a cheaper model tier.',\n },\n );\n this.scope = args.scope;\n this.limit = args.limit;\n this.observed = args.observed;\n }\n}\n\n/**\n * `withRateLimit` exhausted its bucket and the caller did not opt\n * into `'queue'` mode.\n *\n * @stable\n */\nexport class RateLimitExceededError extends GraphorinProviderError {\n override readonly name = 'RateLimitExceededError';\n readonly retryAfterMs: number;\n\n constructor(retryAfterMs: number) {\n super('rate-limit-exceeded', `Rate limit exceeded; retry after ${retryAfterMs}ms.`, {\n hint: 'Slow down the request rate, raise the bucket size in withRateLimit({...}), or switch to mode: \"queue\".',\n });\n this.retryAfterMs = retryAfterMs;\n }\n}\n\n/**\n * `withRedaction` detected a hit AND the policy is configured for\n * `failClosed: true`. The matched value is **never** part of the\n * message - only the pattern name and field path.\n *\n * @stable\n */\nexport class PromptRedactionError extends GraphorinProviderError {\n override readonly name = 'PromptRedactionError';\n readonly patternName: string;\n readonly fieldPath: string;\n readonly role?: string;\n\n constructor(args: { patternName: string; fieldPath: string; role?: string }) {\n super(\n 'prompt-redaction-fail-closed',\n `Outbound prompt-redaction policy is fail-closed and matched pattern '${args.patternName}' ` +\n `at '${args.fieldPath}'${args.role ? ` (role: ${args.role})` : ''}.`,\n {\n hint: 'Sanitize the prompt before calling the provider, or disable failClosed in withRedaction({...}) for this environment.',\n },\n );\n this.patternName = args.patternName;\n this.fieldPath = args.fieldPath;\n if (args.role !== undefined) this.role = args.role;\n }\n}\n\n/**\n * Raised when a `baseUrl`-driven local adapter is configured against\n * a public host over plaintext HTTP. Adapters refuse to start unless\n * `allowInsecureTransport: true` is supplied (and the override is\n * audit-logged).\n *\n * @stable\n */\nexport class LocalProviderInsecureTransportError extends GraphorinProviderError {\n override readonly name = 'LocalProviderInsecureTransportError';\n readonly baseUrl: string;\n\n constructor(baseUrl: string) {\n super(\n 'local-provider-insecure-transport',\n `Refusing to start: the provider baseUrl '${baseUrl}' is public AND plaintext (http://). ` +\n `Switch to https:// or set allowInsecureTransport: true to acknowledge the risk.`,\n {\n hint:\n 'Public local-LLM endpoints must be served over TLS. Acceptable alternatives: terminate TLS in front of the model server, ' +\n 'tunnel through SSH / WireGuard / Tailscale, or pass allowInsecureTransport: true (audit-logged).',\n },\n );\n this.baseUrl = baseUrl;\n }\n}\n\n/**\n * Legacy alias preserved for one minor; prefer\n * {@link LocalProviderInsecureTransportError}. Removed in v0.2.\n *\n * @deprecated Use {@link LocalProviderInsecureTransportError} instead.\n */\nexport const OllamaInsecureTransportError = LocalProviderInsecureTransportError;\nexport type OllamaInsecureTransportError = LocalProviderInsecureTransportError;\n\n/**\n * Body phrasings used by the major providers when the request blew the\n * model's context window. Sniffed by {@link classifyHttpStatus} so a\n * 400 that is really a context overflow surfaces as `'context-length'`\n * (the kind the compaction / emergency tiers key on), not a generic\n * `'invalid-request'`.\n */\nconst CONTEXT_LENGTH_BODY_RE =\n /context[_ -]?length|context window|prompt is too long|maximum context|too many tokens|exceeds? the (?:model'?s? )?max/i;\n\n/**\n * Map an HTTP status (plus optional error-body text) onto the\n * canonical {@link import('@graphorin/core').ProviderErrorKind}. One\n * shared table so `withRetry` / `withFallback` and consumers switching\n * on the documented kinds see consistent values from every HTTP\n * adapter:\n *\n * - `429` → `'rate-limit'`\n * - `401` / `403` → `'unauthorized'`\n * - `400` / `404` / `422` → `'invalid-request'` (or\n * `'context-length'` when the body says so)\n * - `503` / `529` → `'capacity'` (529 is Anthropic's overloaded code)\n * - other `5xx` and `0` (network failure) → `'transient'`\n *\n * @stable\n */\nexport function classifyHttpStatus(status: number, bodyText?: string): ProviderErrorKind {\n if (status === 429) return 'rate-limit';\n if (status === 401 || status === 403) return 'unauthorized';\n if (status === 400 || status === 404 || status === 422) {\n if (bodyText !== undefined && CONTEXT_LENGTH_BODY_RE.test(bodyText)) return 'context-length';\n return 'invalid-request';\n }\n if (status === 503 || status === 529) return 'capacity';\n if (status >= 500 || status === 0) return 'transient';\n return 'unknown';\n}\n\n/**\n * Wrapped HTTP error returned by an adapter. Carries the original\n * status code so middleware (`withRetry`, `withFallback`) can decide\n * whether the error is retryable.\n *\n * @stable\n */\nexport class ProviderHttpError extends GraphorinProviderError {\n override readonly name = 'ProviderHttpError';\n readonly status: number;\n readonly providerName: string;\n /**\n * The canonical `ProviderErrorKind` mapped from the HTTP status via\n * {@link classifyHttpStatus} (the `kind` field keeps its stable\n * `'provider-http'` discriminant). Middleware predicates consult\n * this so a 429 fails over / retries as a rate limit.\n */\n readonly errorKind: ProviderErrorKind;\n /**\n * Backoff-relevant response headers captured from the failed\n * response (`retry-after`, `x-ratelimit-*`), lowercased.\n * `withRetry`'s Retry-After hint reader consumes them.\n */\n readonly headers?: Readonly<Record<string, string>>;\n\n constructor(args: {\n providerName: string;\n status: number;\n message: string;\n cause?: unknown;\n errorKind?: ProviderErrorKind;\n headers?: Readonly<Record<string, string>>;\n }) {\n super('provider-http', `[${args.providerName}] HTTP ${args.status}: ${args.message}`, {\n ...(args.cause !== undefined ? { cause: args.cause } : {}),\n });\n this.providerName = args.providerName;\n this.status = args.status;\n this.errorKind = args.errorKind ?? classifyHttpStatus(args.status, args.message);\n if (args.headers !== undefined) this.headers = args.headers;\n }\n}\n\n/**\n * The streaming response did not match the documented wire format\n * (e.g. malformed SSE chunk, truncated JSON).\n *\n * @stable\n */\nexport class ProviderStreamParseError extends GraphorinProviderError {\n override readonly name = 'ProviderStreamParseError';\n readonly providerName: string;\n\n constructor(providerName: string, message: string, cause?: unknown) {\n super('provider-stream-parse', `[${providerName}] ${message}`, {\n ...(cause !== undefined ? { cause } : {}),\n });\n this.providerName = providerName;\n }\n}\n\n/**\n * The classifier dispatcher was given a non-Provider value. Programming\n * error; fail-fast at the boundary.\n *\n * @stable\n */\nexport class InvalidProviderError extends GraphorinProviderError {\n override readonly name = 'InvalidProviderError';\n\n constructor(message: string) {\n super('invalid-provider', message, {\n hint: 'Pass the value returned by createProvider(...) (or any adapter factory) instead of a raw object.',\n });\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError } from "./errors.js";
2
- export { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError };
1
+ import { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError, classifyHttpStatus } from "./errors.js";
2
+ export { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError, classifyHttpStatus };
@@ -1,3 +1,3 @@
1
- import { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError } from "./errors.js";
1
+ import { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError, classifyHttpStatus } from "./errors.js";
2
2
 
3
- export { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError };
3
+ export { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError, classifyHttpStatus };
package/dist/index.d.ts CHANGED
@@ -11,7 +11,8 @@ import { HeuristicCounter, HeuristicCounterOptions } from "./counters/heuristic.
11
11
  import { JsTiktokenCounter, JsTiktokenCounterOptions, __resetTiktokenCache } from "./counters/js-tiktoken.js";
12
12
  import { SerializedMessage, serialiseMessageForCount, serializedToString } from "./counters/serialize.js";
13
13
  import "./counters/index.js";
14
- import { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError } from "./errors/errors.js";
14
+ import { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError, classifyHttpStatus } from "./errors/errors.js";
15
+ import "./errors/index.js";
15
16
  import "./adapters/index.js";
16
17
  import { CANONICAL_MIDDLEWARE_ORDER, MIDDLEWARE_KIND, composeProviderMiddleware, defineProviderMiddleware, getMiddlewareKind, providerHasMiddleware } from "./middleware/compose.js";
17
18
  import { ProductionStartupHookOptions, assertProductionMiddleware } from "./middleware/production-hook.js";
@@ -36,7 +37,7 @@ import { LocalProviderTrust, OllamaTrust } from "./trust/index.js";
36
37
 
37
38
  //#region src/index.d.ts
38
39
  /**
39
- * @graphorin/provider vendor-neutral LLM provider layer for the
40
+ * @graphorin/provider - vendor-neutral LLM provider layer for the
40
41
  * Graphorin framework.
41
42
  *
42
43
  * The package owns:
@@ -62,8 +63,7 @@ import { LocalProviderTrust, OllamaTrust } from "./trust/index.js";
62
63
  *
63
64
  * @packageDocumentation
64
65
  */
65
- /** Canonical version constant. Mirrors the `package.json` version. */
66
- declare const VERSION = "0.5.0";
66
+ declare const VERSION: string;
67
67
  //#endregion
68
- export { AnthropicAPICounter, AnthropicAPICounterOptions, ApplyReasoningPolicyInput, BedrockAPICounter, BedrockAPICounterOptions, CANONICAL_MIDDLEWARE_ORDER, CLASSIFIER_RULES, ClassifierRule, CostAccumulator, CostBudgetExceededError, CostTrackingTotals, CreateDefaultCounterOptions, CreateProviderOptions, GoogleAPICounter, GoogleAPICounterOptions, GraphorinProviderError, HeuristicCounter, HeuristicCounterOptions, InferReasoningContractInput, InvalidProviderError, JsTiktokenCounter, JsTiktokenCounterOptions, LlamaCppServerAdapterOptions, LocalProviderClassification, LocalProviderInsecureTransportError, LocalProviderTrust, MIDDLEWARE_KIND, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaAdapterOptions, OllamaInsecureTransportError, OllamaTrust, OpenAICompatibleAdapterOptions, PERMANENT_LOOPBACK_CLASSIFICATION, ProductionStartupHookOptions, PromptRedactionError, PromptRedactionPolicy, PromptRedactionScanScope, PromptRedactionViolation, ProviderHttpError, ProviderStreamParseError, REASONING_CONTRACT_RULES, REASONING_RETENTION_DEFAULTS, RateLimitExceededError, ReasoningContractRule, ResolveReasoningRetentionInput, SENSITIVITY_DEFAULTS_PER_TRUST, SerializedMessage, VERSION, VercelAdapterOptions, WithCostLimitOptions, WithCostTrackingOptions, WithFallbackOptions, WithRateLimitOptions, WithRetryOptions, WithTracingOptions, __resetGlobalTokenCounter, __resetTiktokenCache, applyReasoningPolicy, assertProductionMiddleware, classifyLocalProvider, classifyModelTier, composeProviderMiddleware, createCostAccumulator, createDefaultCounter, createProvider, defineProviderMiddleware, foldToolExamples, getGlobalTokenCounter, getMiddlewareKind, inferReasoningContract, llamaCppServerAdapter, ollamaAdapter, openAICompatibleAdapter, providerHasMiddleware, resolveReasoningRetention, serialiseMessageForCount, serializedToString, setGlobalTokenCounter, vercelAdapter, withCostLimit, withCostTracking, withFallback, withRateLimit, withRedaction, withRetry, withTracing };
68
+ export { AnthropicAPICounter, AnthropicAPICounterOptions, ApplyReasoningPolicyInput, BedrockAPICounter, BedrockAPICounterOptions, CANONICAL_MIDDLEWARE_ORDER, CLASSIFIER_RULES, ClassifierRule, CostAccumulator, CostBudgetExceededError, CostTrackingTotals, CreateDefaultCounterOptions, CreateProviderOptions, GoogleAPICounter, GoogleAPICounterOptions, GraphorinProviderError, HeuristicCounter, HeuristicCounterOptions, InferReasoningContractInput, InvalidProviderError, JsTiktokenCounter, JsTiktokenCounterOptions, LlamaCppServerAdapterOptions, LocalProviderClassification, LocalProviderInsecureTransportError, LocalProviderTrust, MIDDLEWARE_KIND, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaAdapterOptions, OllamaInsecureTransportError, OllamaTrust, OpenAICompatibleAdapterOptions, PERMANENT_LOOPBACK_CLASSIFICATION, ProductionStartupHookOptions, PromptRedactionError, PromptRedactionPolicy, PromptRedactionScanScope, PromptRedactionViolation, ProviderHttpError, ProviderStreamParseError, REASONING_CONTRACT_RULES, REASONING_RETENTION_DEFAULTS, RateLimitExceededError, ReasoningContractRule, ResolveReasoningRetentionInput, SENSITIVITY_DEFAULTS_PER_TRUST, SerializedMessage, VERSION, VercelAdapterOptions, WithCostLimitOptions, WithCostTrackingOptions, WithFallbackOptions, WithRateLimitOptions, WithRetryOptions, WithTracingOptions, __resetGlobalTokenCounter, __resetTiktokenCache, applyReasoningPolicy, assertProductionMiddleware, classifyHttpStatus, classifyLocalProvider, classifyModelTier, composeProviderMiddleware, createCostAccumulator, createDefaultCounter, createProvider, defineProviderMiddleware, foldToolExamples, getGlobalTokenCounter, getMiddlewareKind, inferReasoningContract, llamaCppServerAdapter, ollamaAdapter, openAICompatibleAdapter, providerHasMiddleware, resolveReasoningRetention, serialiseMessageForCount, serializedToString, setGlobalTokenCounter, vercelAdapter, withCostLimit, withCostTracking, withFallback, withRateLimit, withRedaction, withRetry, withTracing };
69
69
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6Ba,OAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+Ba"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
- import { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError } from "./errors/errors.js";
1
+ import { version } from "./package.js";
2
+ import { CostBudgetExceededError, GraphorinProviderError, InvalidProviderError, LocalProviderInsecureTransportError, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, RateLimitExceededError, classifyHttpStatus } from "./errors/errors.js";
2
3
  import { applyReasoningPolicy } from "./reasoning/apply-policy.js";
3
4
  import { REASONING_RETENTION_DEFAULTS, resolveReasoningRetention } from "./reasoning/retention.js";
5
+ import { foldToolExamples } from "./tool-examples.js";
4
6
  import { PERMANENT_LOOPBACK_CLASSIFICATION, SENSITIVITY_DEFAULTS_PER_TRUST, classifyLocalProvider } from "./trust/classify-local-provider.js";
5
7
  import { llamaCppServerAdapter } from "./adapters/llamacpp-server.js";
6
8
  import { ollamaAdapter } from "./adapters/ollama.js";
@@ -29,14 +31,13 @@ import { withTracing } from "./middleware/with-tracing.js";
29
31
  import "./middleware/index.js";
30
32
  import { CLASSIFIER_RULES, classifyModelTier } from "./model-tier/classify.js";
31
33
  import "./model-tier/index.js";
32
- import { foldToolExamples } from "./tool-examples.js";
33
34
  import { createProvider } from "./provider.js";
34
35
  import "./reasoning/index.js";
35
36
  import "./trust/index.js";
36
37
 
37
38
  //#region src/index.ts
38
39
  /**
39
- * @graphorin/provider vendor-neutral LLM provider layer for the
40
+ * @graphorin/provider - vendor-neutral LLM provider layer for the
40
41
  * Graphorin framework.
41
42
  *
42
43
  * The package owns:
@@ -62,9 +63,9 @@ import "./trust/index.js";
62
63
  *
63
64
  * @packageDocumentation
64
65
  */
65
- /** Canonical version constant. Mirrors the `package.json` version. */
66
- const VERSION = "0.5.0";
66
+ /** Canonical version constant, derived from `package.json` at build time. */
67
+ const VERSION = version;
67
68
 
68
69
  //#endregion
69
- export { AnthropicAPICounter, BedrockAPICounter, CANONICAL_MIDDLEWARE_ORDER, CLASSIFIER_RULES, CostBudgetExceededError, GoogleAPICounter, GraphorinProviderError, HeuristicCounter, InvalidProviderError, JsTiktokenCounter, LocalProviderInsecureTransportError, MIDDLEWARE_KIND, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PERMANENT_LOOPBACK_CLASSIFICATION, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, REASONING_CONTRACT_RULES, REASONING_RETENTION_DEFAULTS, RateLimitExceededError, SENSITIVITY_DEFAULTS_PER_TRUST, VERSION, __resetGlobalTokenCounter, __resetTiktokenCache, applyReasoningPolicy, assertProductionMiddleware, classifyLocalProvider, classifyModelTier, composeProviderMiddleware, createCostAccumulator, createDefaultCounter, createProvider, defineProviderMiddleware, foldToolExamples, getGlobalTokenCounter, getMiddlewareKind, inferReasoningContract, llamaCppServerAdapter, ollamaAdapter, openAICompatibleAdapter, providerHasMiddleware, resolveReasoningRetention, serialiseMessageForCount, serializedToString, setGlobalTokenCounter, vercelAdapter, withCostLimit, withCostTracking, withFallback, withRateLimit, withRedaction, withRetry, withTracing };
70
+ export { AnthropicAPICounter, BedrockAPICounter, CANONICAL_MIDDLEWARE_ORDER, CLASSIFIER_RULES, CostBudgetExceededError, GoogleAPICounter, GraphorinProviderError, HeuristicCounter, InvalidProviderError, JsTiktokenCounter, LocalProviderInsecureTransportError, MIDDLEWARE_KIND, MiddlewareOrderingError, MissingProductionMiddlewareError, OllamaInsecureTransportError, PERMANENT_LOOPBACK_CLASSIFICATION, PromptRedactionError, ProviderHttpError, ProviderStreamParseError, REASONING_CONTRACT_RULES, REASONING_RETENTION_DEFAULTS, RateLimitExceededError, SENSITIVITY_DEFAULTS_PER_TRUST, VERSION, __resetGlobalTokenCounter, __resetTiktokenCache, applyReasoningPolicy, assertProductionMiddleware, classifyHttpStatus, classifyLocalProvider, classifyModelTier, composeProviderMiddleware, createCostAccumulator, createDefaultCounter, createProvider, defineProviderMiddleware, foldToolExamples, getGlobalTokenCounter, getMiddlewareKind, inferReasoningContract, llamaCppServerAdapter, ollamaAdapter, openAICompatibleAdapter, providerHasMiddleware, resolveReasoningRetention, serialiseMessageForCount, serializedToString, setGlobalTokenCounter, vercelAdapter, withCostLimit, withCostTracking, withFallback, withRateLimit, withRedaction, withRetry, withTracing };
70
71
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @graphorin/provider vendor-neutral LLM provider layer for the\n * Graphorin framework.\n *\n * The package owns:\n *\n * - The `createProvider(...)` factory for wrapping adapter modules in\n * a stable `Provider` shape.\n * - Four adapters out of the box: the Vercel AI SDK adapter for the\n * default cloud path, plus three local-LLM adapters (Ollama HTTP,\n * llama-server HTTP, and a generic OpenAI-compatible adapter for\n * LMStudio / LocalAI / vLLM / Together-style endpoints). All three\n * `baseUrl`-driven adapters share the same {@link LocalProviderTrust}\n * classifier.\n * - The canonical-order middleware composer\n * ({@link composeProviderMiddleware}) and the seven built-in\n * middlewares (`withTracing`, `withRetry`, `withRateLimit`,\n * `withCostLimit`, `withCostTracking`, `withFallback`,\n * `withRedaction`).\n * - The pluggable `TokenCounter` dispatcher (`createDefaultCounter`)\n * plus the per-vendor strategies and a heuristic fallback.\n * - The per-provider model-tier auto-classifier\n * ({@link classifyModelTier}) that maps a `Provider`'s `modelId` to\n * one of `'fast' | 'balanced' | 'smart'`.\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant. Mirrors the `package.json` version. */\nexport const VERSION = '0.5.0';\n\nexport * from './adapters/index.js';\nexport * from './counters/index.js';\nexport * from './errors/index.js';\nexport * from './middleware/index.js';\nexport * from './model-tier/index.js';\nexport * from './provider.js';\nexport * from './reasoning/index.js';\nexport { foldToolExamples } from './tool-examples.js';\nexport * from './trust/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,UAAU"}
1
+ {"version":3,"file":"index.js","names":["VERSION: string","pkg.version"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @graphorin/provider - vendor-neutral LLM provider layer for the\n * Graphorin framework.\n *\n * The package owns:\n *\n * - The `createProvider(...)` factory for wrapping adapter modules in\n * a stable `Provider` shape.\n * - Four adapters out of the box: the Vercel AI SDK adapter for the\n * default cloud path, plus three local-LLM adapters (Ollama HTTP,\n * llama-server HTTP, and a generic OpenAI-compatible adapter for\n * LMStudio / LocalAI / vLLM / Together-style endpoints). All three\n * `baseUrl`-driven adapters share the same {@link LocalProviderTrust}\n * classifier.\n * - The canonical-order middleware composer\n * ({@link composeProviderMiddleware}) and the seven built-in\n * middlewares (`withTracing`, `withRetry`, `withRateLimit`,\n * `withCostLimit`, `withCostTracking`, `withFallback`,\n * `withRedaction`).\n * - The pluggable `TokenCounter` dispatcher (`createDefaultCounter`)\n * plus the per-vendor strategies and a heuristic fallback.\n * - The per-provider model-tier auto-classifier\n * ({@link classifyModelTier}) that maps a `Provider`'s `modelId` to\n * one of `'fast' | 'balanced' | 'smart'`.\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant, derived from `package.json` at build time. */\nimport pkg from '../package.json' with { type: 'json' };\n\nexport const VERSION: string = pkg.version;\n\nexport * from './adapters/index.js';\nexport * from './counters/index.js';\nexport * from './errors/index.js';\nexport * from './middleware/index.js';\nexport * from './model-tier/index.js';\nexport * from './provider.js';\nexport * from './reasoning/index.js';\nexport { foldToolExamples } from './tool-examples.js';\nexport * from './trust/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAaA,UAAkBC"}
@@ -3,7 +3,7 @@
3
3
  * Abort detection shared by the retry / fallback predicates (PS-2).
4
4
  *
5
5
  * A network failure surfaces as `ProviderHttpError{ status: 0, cause }`,
6
- * and a user/agent abort surfaces the same way the distinguishing
6
+ * and a user/agent abort surfaces the same way - the distinguishing
7
7
  * signal is an `AbortError` (DOMException) somewhere on the `cause`
8
8
  * chain. Network errors should be retried and failed over; an abort must
9
9
  * not be, even though the retry/fallback loops also short-circuit on
@@ -12,7 +12,7 @@
12
12
  * @packageDocumentation
13
13
  */
14
14
  /**
15
- * True when `err` or any error on its `cause` chain is an abort
15
+ * True when `err` - or any error on its `cause` chain - is an abort
16
16
  * (`name === 'AbortError'` or Node's `code === 'ABORT_ERR'`). Walks at
17
17
  * most a few links so a cyclic / pathological cause chain cannot loop.
18
18
  *
@@ -1 +1 @@
1
- {"version":3,"file":"abort.js","names":["cursor: unknown"],"sources":["../../src/internal/abort.ts"],"sourcesContent":["/**\n * Abort detection shared by the retry / fallback predicates (PS-2).\n *\n * A network failure surfaces as `ProviderHttpError{ status: 0, cause }`,\n * and a user/agent abort surfaces the same way the distinguishing\n * signal is an `AbortError` (DOMException) somewhere on the `cause`\n * chain. Network errors should be retried and failed over; an abort must\n * not be, even though the retry/fallback loops also short-circuit on\n * `req.signal?.aborted` independently.\n *\n * @packageDocumentation\n */\n\n/**\n * True when `err` or any error on its `cause` chain is an abort\n * (`name === 'AbortError'` or Node's `code === 'ABORT_ERR'`). Walks at\n * most a few links so a cyclic / pathological cause chain cannot loop.\n *\n * @internal\n */\nexport function isAbortError(err: unknown): boolean {\n let cursor: unknown = err;\n for (let depth = 0; depth < 8 && cursor !== null && typeof cursor === 'object'; depth++) {\n const e = cursor as { name?: unknown; code?: unknown; cause?: unknown };\n if (e.name === 'AbortError' || e.code === 'ABORT_ERR') return true;\n if (e.cause === cursor) break;\n cursor = e.cause;\n }\n return false;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,aAAa,KAAuB;CAClD,IAAIA,SAAkB;AACtB,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,WAAW,QAAQ,OAAO,WAAW,UAAU,SAAS;EACvF,MAAM,IAAI;AACV,MAAI,EAAE,SAAS,gBAAgB,EAAE,SAAS,YAAa,QAAO;AAC9D,MAAI,EAAE,UAAU,OAAQ;AACxB,WAAS,EAAE;;AAEb,QAAO"}
1
+ {"version":3,"file":"abort.js","names":["cursor: unknown"],"sources":["../../src/internal/abort.ts"],"sourcesContent":["/**\n * Abort detection shared by the retry / fallback predicates (PS-2).\n *\n * A network failure surfaces as `ProviderHttpError{ status: 0, cause }`,\n * and a user/agent abort surfaces the same way - the distinguishing\n * signal is an `AbortError` (DOMException) somewhere on the `cause`\n * chain. Network errors should be retried and failed over; an abort must\n * not be, even though the retry/fallback loops also short-circuit on\n * `req.signal?.aborted` independently.\n *\n * @packageDocumentation\n */\n\n/**\n * True when `err` - or any error on its `cause` chain - is an abort\n * (`name === 'AbortError'` or Node's `code === 'ABORT_ERR'`). Walks at\n * most a few links so a cyclic / pathological cause chain cannot loop.\n *\n * @internal\n */\nexport function isAbortError(err: unknown): boolean {\n let cursor: unknown = err;\n for (let depth = 0; depth < 8 && cursor !== null && typeof cursor === 'object'; depth++) {\n const e = cursor as { name?: unknown; code?: unknown; cause?: unknown };\n if (e.name === 'AbortError' || e.code === 'ABORT_ERR') return true;\n if (e.cause === cursor) break;\n cursor = e.cause;\n }\n return false;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,aAAa,KAAuB;CAClD,IAAIA,SAAkB;AACtB,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,WAAW,QAAQ,OAAO,WAAW,UAAU,SAAS;EACvF,MAAM,IAAI;AACV,MAAI,EAAE,SAAS,gBAAgB,EAAE,SAAS,YAAa,QAAO;AAC9D,MAAI,EAAE,UAAU,OAAQ;AACxB,WAAS,EAAE;;AAEb,QAAO"}