@warmdrift/kgauto-compiler 2.0.0-alpha.90 → 2.0.0-alpha.92

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 (35) hide show
  1. package/dist/{chunk-ENELVMJI.mjs → chunk-4G73BYES.mjs} +10 -5
  2. package/dist/{chunk-BVEXV5KC.mjs → chunk-FEMPY6EC.mjs} +5 -1
  3. package/dist/{chunk-4LYNDEHJ.mjs → chunk-QOQV66PU.mjs} +1 -1
  4. package/dist/{chunk-OK2TMFRR.mjs → chunk-T53ISC2F.mjs} +133 -4
  5. package/dist/dialect.d.mts +11 -1
  6. package/dist/dialect.d.ts +11 -1
  7. package/dist/dialect.js +7 -2
  8. package/dist/dialect.mjs +5 -3
  9. package/dist/glassbox/index.d.mts +3 -3
  10. package/dist/glassbox/index.d.ts +3 -3
  11. package/dist/glassbox-routes/format.d.mts +2 -2
  12. package/dist/glassbox-routes/format.d.ts +2 -2
  13. package/dist/glassbox-routes/index.d.mts +4 -4
  14. package/dist/glassbox-routes/index.d.ts +4 -4
  15. package/dist/glassbox-routes/index.js +142 -8
  16. package/dist/glassbox-routes/index.mjs +2 -2
  17. package/dist/glassbox-routes/react/index.d.mts +2 -2
  18. package/dist/glassbox-routes/react/index.d.ts +2 -2
  19. package/dist/index.d.mts +15 -4
  20. package/dist/index.d.ts +15 -4
  21. package/dist/index.js +233 -17
  22. package/dist/index.mjs +93 -13
  23. package/dist/{ir-DeYMLWge.d.mts → ir-BPYh68mv.d.mts} +95 -1
  24. package/dist/{ir-CTx026t0.d.ts → ir-BWnE6LaB.d.ts} +95 -1
  25. package/dist/key-health.js +1 -1
  26. package/dist/key-health.mjs +1 -1
  27. package/dist/profiles.d.mts +1 -1
  28. package/dist/profiles.d.ts +1 -1
  29. package/dist/profiles.js +133 -4
  30. package/dist/profiles.mjs +1 -1
  31. package/dist/{types-Cp9ot1HV.d.ts → types-BCHv34P7.d.ts} +1 -1
  32. package/dist/{types-cBzinzUR.d.mts → types-BgvLmT3s.d.mts} +1 -1
  33. package/dist/{types-BKbRtmUb.d.ts → types-BhxC4hdx.d.ts} +1 -1
  34. package/dist/{types-DD36cCbZ.d.mts → types-eLelJBj-.d.mts} +1 -1
  35. package/package.json +1 -1
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, S as SystemModelMessage, e as CompileResult, B as BestPracticeAdvisory, F as FallbackReason, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OutcomeSource, i as OracleScore, j as Adapter, k as PerAxisMetrics, l as Provider, m as ChainEntry, G as Grounding } from './ir-DeYMLWge.mjs';
2
- export { n as CallAttempt, o as CallError, p as ChainModelEntry, q as ChainWithGrounding, r as Constraints, E as EffortLevel, s as GoldenCaptureOptions, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, t as MutationApplied, u as NormalizedTokens, v as OutcomeKind, w as PerAxisMetricsByModel, x as PromptSection, y as SectionKind, z as ShadowProbeConfig, T as ToolCall, D as ToolDefinition, J as captureGoldenIr, K as hasMutation, L as mutationId, Q as parseGoldenCaptureRate, U as resolveGoldenCaptureRate, V as shouldCaptureGolden } from './ir-DeYMLWge.mjs';
1
+ import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, S as SystemModelMessage, e as CompileResult, B as BestPracticeAdvisory, F as FallbackReason, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OutcomeSource, i as OracleScore, j as Adapter, k as PerAxisMetrics, l as Provider, m as ChainEntry, G as Grounding } from './ir-BPYh68mv.mjs';
2
+ export { n as CallAttempt, o as CallError, p as ChainModelEntry, q as ChainWithGrounding, r as Constraints, E as EffortLevel, s as GoldenCaptureOptions, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, t as MutationApplied, u as NormalizedTokens, v as OutcomeKind, w as PerAxisMetricsByModel, x as PromptSection, y as SectionKind, z as ShadowProbeConfig, T as ToolCall, D as ToolDefinition, J as captureGoldenIr, K as hasMutation, L as mutationId, Q as parseGoldenCaptureRate, U as resolveGoldenCaptureRate, V as shouldCaptureGolden } from './ir-BPYh68mv.mjs';
3
3
  import { ModelProfile, ArchetypeConvention } from './profiles.mjs';
4
4
  export { ALIASES, CacheStrategy, CliffRule, LATENCY_TIER_MS, LatencyTier, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, _testClearConsumerProfiles, allProfiles, bestEffortProfile, getProfile, inferProviderFromId, latencyTierOf, profilesByProvider, registerProfiles, resolveModelAlias, tryGetProfile } from './profiles.mjs';
5
5
  export { BrainForwardConfig, BrainForwardRoutes, createBrainForwardRoutes } from './brain-proxy.mjs';
@@ -47,6 +47,13 @@ interface CompileOptions {
47
47
  * time. `registerCompile` reads it to derive the linkage. Absent ⇒ root call.
48
48
  */
49
49
  parentHandle?: string;
50
+ /**
51
+ * alpha.92 — lower for a gateway route (execute-leg contract). Threaded
52
+ * from `CallOptions.route`. The canonical profile drives every pass
53
+ * (cliffs, scoring, budgets) unchanged; only the wire destination and the
54
+ * learning-key encoding change. Absent ⇒ direct vendor wire.
55
+ */
56
+ route?: 'direct' | 'openrouter';
50
57
  }
51
58
 
52
59
  /**
@@ -666,6 +673,10 @@ interface OutcomePayload {
666
673
  provider?: string;
667
674
  shape_key?: string;
668
675
  learning_key?: string;
676
+ /** alpha.92 (migration 067) — route identity: 'direct' | 'openrouter'. */
677
+ route?: string;
678
+ /** alpha.92 — gateway-reported serving host (OpenRouter `provider` field). */
679
+ route_host?: string;
669
680
  mutations_applied: string[];
670
681
  tokens_in: number;
671
682
  tokens_out: number;
@@ -1270,7 +1281,7 @@ declare function runStrategyEvalWithAttribution(opts: Omit<GoldenEvalOptions, 'a
1270
1281
  * guard in `tests/version.test.ts` fails the suite (and therefore
1271
1282
  * `prepublishOnly`) when they diverge — a stale constant cannot reach npm.
1272
1283
  */
1273
- declare const LIBRARY_VERSION = "2.0.0-alpha.90";
1284
+ declare const LIBRARY_VERSION = "2.0.0-alpha.92";
1274
1285
 
1275
1286
  /**
1276
1287
  * Oracle contract — how an app tells the brain whether a response was good.
@@ -2668,7 +2679,7 @@ declare function getPerAxisMetrics(opts: GetPerAxisMetricsOpts): Promise<PerAxis
2668
2679
  * no execute() handler, no env-var convention). Narrowing here keeps the
2669
2680
  * reachability check structurally honest.
2670
2681
  */
2671
- type SupportedProvider = 'anthropic' | 'google' | 'openai' | 'deepseek' | 'zai' | 'moonshot';
2682
+ type SupportedProvider = 'anthropic' | 'google' | 'openai' | 'deepseek' | 'zai' | 'moonshot' | 'openrouter';
2672
2683
  /**
2673
2684
  * Per-provider env var names kgauto recognizes. Order doesn't matter —
2674
2685
  * first-present wins. Multiple names per provider supported because Google
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, S as SystemModelMessage, e as CompileResult, B as BestPracticeAdvisory, F as FallbackReason, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OutcomeSource, i as OracleScore, j as Adapter, k as PerAxisMetrics, l as Provider, m as ChainEntry, G as Grounding } from './ir-CTx026t0.js';
2
- export { n as CallAttempt, o as CallError, p as ChainModelEntry, q as ChainWithGrounding, r as Constraints, E as EffortLevel, s as GoldenCaptureOptions, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, t as MutationApplied, u as NormalizedTokens, v as OutcomeKind, w as PerAxisMetricsByModel, x as PromptSection, y as SectionKind, z as ShadowProbeConfig, T as ToolCall, D as ToolDefinition, J as captureGoldenIr, K as hasMutation, L as mutationId, Q as parseGoldenCaptureRate, U as resolveGoldenCaptureRate, V as shouldCaptureGolden } from './ir-CTx026t0.js';
1
+ import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, S as SystemModelMessage, e as CompileResult, B as BestPracticeAdvisory, F as FallbackReason, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OutcomeSource, i as OracleScore, j as Adapter, k as PerAxisMetrics, l as Provider, m as ChainEntry, G as Grounding } from './ir-BWnE6LaB.js';
2
+ export { n as CallAttempt, o as CallError, p as ChainModelEntry, q as ChainWithGrounding, r as Constraints, E as EffortLevel, s as GoldenCaptureOptions, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, t as MutationApplied, u as NormalizedTokens, v as OutcomeKind, w as PerAxisMetricsByModel, x as PromptSection, y as SectionKind, z as ShadowProbeConfig, T as ToolCall, D as ToolDefinition, J as captureGoldenIr, K as hasMutation, L as mutationId, Q as parseGoldenCaptureRate, U as resolveGoldenCaptureRate, V as shouldCaptureGolden } from './ir-BWnE6LaB.js';
3
3
  import { ModelProfile, ArchetypeConvention } from './profiles.js';
4
4
  export { ALIASES, CacheStrategy, CliffRule, LATENCY_TIER_MS, LatencyTier, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, _testClearConsumerProfiles, allProfiles, bestEffortProfile, getProfile, inferProviderFromId, latencyTierOf, profilesByProvider, registerProfiles, resolveModelAlias, tryGetProfile } from './profiles.js';
5
5
  export { BrainForwardConfig, BrainForwardRoutes, createBrainForwardRoutes } from './brain-proxy.js';
@@ -47,6 +47,13 @@ interface CompileOptions {
47
47
  * time. `registerCompile` reads it to derive the linkage. Absent ⇒ root call.
48
48
  */
49
49
  parentHandle?: string;
50
+ /**
51
+ * alpha.92 — lower for a gateway route (execute-leg contract). Threaded
52
+ * from `CallOptions.route`. The canonical profile drives every pass
53
+ * (cliffs, scoring, budgets) unchanged; only the wire destination and the
54
+ * learning-key encoding change. Absent ⇒ direct vendor wire.
55
+ */
56
+ route?: 'direct' | 'openrouter';
50
57
  }
51
58
 
52
59
  /**
@@ -666,6 +673,10 @@ interface OutcomePayload {
666
673
  provider?: string;
667
674
  shape_key?: string;
668
675
  learning_key?: string;
676
+ /** alpha.92 (migration 067) — route identity: 'direct' | 'openrouter'. */
677
+ route?: string;
678
+ /** alpha.92 — gateway-reported serving host (OpenRouter `provider` field). */
679
+ route_host?: string;
669
680
  mutations_applied: string[];
670
681
  tokens_in: number;
671
682
  tokens_out: number;
@@ -1270,7 +1281,7 @@ declare function runStrategyEvalWithAttribution(opts: Omit<GoldenEvalOptions, 'a
1270
1281
  * guard in `tests/version.test.ts` fails the suite (and therefore
1271
1282
  * `prepublishOnly`) when they diverge — a stale constant cannot reach npm.
1272
1283
  */
1273
- declare const LIBRARY_VERSION = "2.0.0-alpha.90";
1284
+ declare const LIBRARY_VERSION = "2.0.0-alpha.92";
1274
1285
 
1275
1286
  /**
1276
1287
  * Oracle contract — how an app tells the brain whether a response was good.
@@ -2668,7 +2679,7 @@ declare function getPerAxisMetrics(opts: GetPerAxisMetricsOpts): Promise<PerAxis
2668
2679
  * no execute() handler, no env-var convention). Narrowing here keeps the
2669
2680
  * reachability check structurally honest.
2670
2681
  */
2671
- type SupportedProvider = 'anthropic' | 'google' | 'openai' | 'deepseek' | 'zai' | 'moonshot';
2682
+ type SupportedProvider = 'anthropic' | 'google' | 'openai' | 'deepseek' | 'zai' | 'moonshot' | 'openrouter';
2672
2683
  /**
2673
2684
  * Per-provider env var names kgauto recognizes. Order doesn't matter —
2674
2685
  * first-present wins. Multiple names per provider supported because Google
package/dist/index.js CHANGED
@@ -889,9 +889,19 @@ var PROFILES_RAW = [
889
889
  // thresholds. The brain will validate/relax these as evidence accumulates
890
890
  // per (archetype, model) tuple. Currently ZERO brain rows for this model.
891
891
  id: "gemini-2.5-flash-lite",
892
- verifiedAgainstDocs: "2026-08-14",
892
+ verifiedAgainstDocs: "2026-08-27",
893
893
  provider: "google",
894
- status: "current",
894
+ // alpha.91 — AVAILABILITY demotion, same class as gemini-2.5-pro below.
895
+ // Google refuses the model for newer account cohorts: "This model is no
896
+ // longer available to new users. Please update your code to use
897
+ // models/gemini-3.5-flash-lite" (tt-intel TT-49 runtime evidence,
898
+ // 2026-08-26, interfaces/kgauto.md ## Requested). It ranked FIRST in
899
+ // getFallbackChain('gemini-2.5-pro') — a dead-for-new-accounts model as
900
+ // the cheapest fallback pick. `legacy` removes it from chains and new
901
+ // selection; explicit-id consumers still resolve it. Successor is the
902
+ // one Google's own error names: gemini-3.5-flash-lite (onboarded this
903
+ // release, same price point).
904
+ status: "legacy",
895
905
  maxContextTokens: 1048576,
896
906
  maxOutputTokens: 65536,
897
907
  maxTools: 128,
@@ -1616,9 +1626,12 @@ var PROFILES_RAW = [
1616
1626
  //
1617
1627
  // Cliffs are HYPOTHESIZED from 2.5-flash family; brain evidence pending.
1618
1628
  id: "gemini-3.1-flash-lite",
1619
- verifiedAgainstDocs: "2026-05-21",
1629
+ verifiedAgainstDocs: "2026-08-27",
1620
1630
  provider: "google",
1621
- status: "preview",
1631
+ // alpha.91 — docs page now labels it "Stable" and the brain row has been
1632
+ // `current` since catalog-sync moved it; the bundle lagged (the L-073
1633
+ // layer-parity shape, caught during the TT-49 delisting release).
1634
+ status: "current",
1622
1635
  maxContextTokens: 1048576,
1623
1636
  maxOutputTokens: 65536,
1624
1637
  maxTools: 128,
@@ -1710,6 +1723,122 @@ var PROFILES_RAW = [
1710
1723
  }
1711
1724
  },
1712
1725
  // ─────────────────────────────────────────────────────────────────────────
1726
+ // Gemini 3.5 Flash-Lite — onboarded s91 (2026-08-27)
1727
+ //
1728
+ // The successor Google's own delisting error names: "This model
1729
+ // [gemini-2.5-flash-lite] is no longer available to new users. Please
1730
+ // update your code to use models/gemini-3.5-flash-lite" (tt-intel TT-49,
1731
+ // 2026-08-26). Same price point as the 2.5 Lite rung it replaces in the
1732
+ // summarize/classify starter chains ($0.30/$2.50 vs the old $0.10/$0.40
1733
+ // era pricing), same 1M/65K limits, same 10× cache discount ($0.03 vs
1734
+ // $0.30 input). Positioning: "fastest, most cost-effective 3.5 model for
1735
+ // high-throughput execution … high-volume agentic tasks, translation, and
1736
+ // simple data processing."
1737
+ //
1738
+ // Cliffs + archetypePerf inherited from the Flash-Lite family as starter
1739
+ // hypotheses — ZERO brain rows on this id yet; first 50 rows per archetype
1740
+ // validate or relax.
1741
+ //
1742
+ // Specs verified 2026-08-27 against:
1743
+ // ai.google.dev/gemini-api/docs/models/gemini-3.5-flash-lite
1744
+ // (Stable; input limit 1,048,576; output limit 65,536; function
1745
+ // calling / structured outputs / thinking / caching all Supported)
1746
+ // ai.google.dev/gemini-api/docs/pricing ($0.30 in / $2.50 out incl.
1747
+ // thinking tokens; context caching $0.03)
1748
+ // ─────────────────────────────────────────────────────────────────────────
1749
+ {
1750
+ id: "gemini-3.5-flash-lite",
1751
+ verifiedAgainstDocs: "2026-08-27",
1752
+ provider: "google",
1753
+ status: "current",
1754
+ maxContextTokens: 1048576,
1755
+ maxOutputTokens: 65536,
1756
+ maxTools: 128,
1757
+ parallelToolCalls: true,
1758
+ structuredOutput: "native",
1759
+ systemPromptMode: "separate",
1760
+ streaming: true,
1761
+ cliffs: [
1762
+ {
1763
+ metric: "input_tokens",
1764
+ threshold: 8e3,
1765
+ action: "downgrade_quality_warning",
1766
+ reason: "Inherited from Flash family: quality degrades above ~8K. Lite tier \u2014 assume it degrades at least as fast. Re-tune from brain after n\u226520."
1767
+ },
1768
+ {
1769
+ metric: "tool_count",
1770
+ threshold: 10,
1771
+ action: "drop_to_top_relevant",
1772
+ reason: "Conservative: Flash drops at 20, Lite tier is smaller \u2014 assume tighter ceiling until brain proves otherwise."
1773
+ },
1774
+ {
1775
+ metric: "thinking_with_short_output",
1776
+ threshold: 1,
1777
+ action: "force_thinking_budget_zero",
1778
+ reason: "Thinking Supported per model page \u2014 same drain risk as Flash; thinking tokens consume maxOutputTokens."
1779
+ },
1780
+ {
1781
+ // Strong prior: Flash hit 5/5 empty rate on summarize+tools (s11
1782
+ // trust artifact). Flash-Lite siblings carry the guard preemptively;
1783
+ // brain telemetry confirms or relaxes per id.
1784
+ metric: "tool_count",
1785
+ threshold: 1,
1786
+ whenIntent: "summarize",
1787
+ action: "strip_tools",
1788
+ reason: "Inherited from Flash s11 cliff: summarize+tools \u2192 empty response. Preemptive guard until brain evidence on 3.5 Flash-Lite specifically."
1789
+ }
1790
+ ],
1791
+ costInputPer1m: 0.3,
1792
+ costOutputPer1m: 2.5,
1793
+ lowering: {
1794
+ ...GOOGLE_LOWERING_BASE,
1795
+ // Cache discount 10× — pricing page: $0.03/M cached vs $0.30/M input.
1796
+ // Material for repeat-prompt workloads (classify shape).
1797
+ cache: { ...GOOGLE_LOWERING_BASE.cache, discount: 0.1 },
1798
+ thinking: { field: "generationConfig.thinkingConfig.thinkingBudget", default: "auto" }
1799
+ },
1800
+ recovery: [
1801
+ {
1802
+ signal: "empty_response_after_tool",
1803
+ action: "retry_with_params",
1804
+ retryParams: { "generationConfig.thinkingConfig.thinkingBudget": 0 },
1805
+ maxRetries: 1,
1806
+ reason: "Known on Flash family: empty after tool result \u2014 retry with thinking off."
1807
+ },
1808
+ {
1809
+ signal: "empty_response",
1810
+ action: "retry_with_params",
1811
+ retryParams: { "generationConfig.thinkingConfig.thinkingBudget": 0 },
1812
+ maxRetries: 1,
1813
+ reason: "Empty response \u2014 try with thinking off."
1814
+ },
1815
+ {
1816
+ signal: "malformed_function_call",
1817
+ action: "escalate",
1818
+ reason: "MALFORMED_FUNCTION_CALL maps to stop \u2014 escalate to next target."
1819
+ }
1820
+ ],
1821
+ strengths: ["low_cost", "speed", "volume", "classification", "summarize", "1m_context", "cache_friendly"],
1822
+ weaknesses: ["complex_reasoning", "large_tool_sets", "complex_schemas", "structured_output_unproven", "long_context_quality"],
1823
+ notes: 'Onboarded s91 (2026-08-27) as the Google-named successor to availability-restricted gemini-2.5-flash-lite. $0.30/$2.50 per 1M, 1M context, 65K max output, cache $0.03/M (10\xD7 discount). "Fastest, most cost-effective 3.5 model for high-throughput execution." Cliffs hypothesized from the Flash family \u2014 brain evidence pending.',
1824
+ // Lite-tier floor for summarize/classify chains. ZERO brain rows — all
1825
+ // values are starter hypotheses anchored to the Flash-Lite family shape.
1826
+ archetypePerf: {
1827
+ classify: 6,
1828
+ // starter hypothesis — verify (Flash is 7, lite likely ≤)
1829
+ summarize: 6,
1830
+ // starter hypothesis — verify; cliff strips tools
1831
+ transform: 6,
1832
+ // starter hypothesis — verify
1833
+ ask: 5,
1834
+ hunt: 5,
1835
+ generate: 4,
1836
+ extract: 4,
1837
+ plan: 3,
1838
+ critique: 3
1839
+ }
1840
+ },
1841
+ // ─────────────────────────────────────────────────────────────────────────
1713
1842
  // Gemini 3.5 Flash — hand-onboarded s37 (2026-05-21)
1714
1843
  //
1715
1844
  // Google positioning ("Most intelligent for sustained frontier performance
@@ -2848,6 +2977,9 @@ function hashShape(s) {
2848
2977
  function learningKey(archetype, model, shape) {
2849
2978
  return `${DIALECT_VERSION}::${archetype}::${model}::${hashShape(shape)}`;
2850
2979
  }
2980
+ function routeScopedModel(model, route) {
2981
+ return route === "openrouter" ? `${model}@openrouter` : model;
2982
+ }
2851
2983
 
2852
2984
  // src/passes.ts
2853
2985
  function passSlice(ir) {
@@ -3505,7 +3637,26 @@ function passApplyConventions(ir, profile) {
3505
3637
  }
3506
3638
 
3507
3639
  // src/lower.ts
3640
+ var OPENROUTER_VENDOR_SLUG = {
3641
+ anthropic: "anthropic",
3642
+ google: "google",
3643
+ openai: "openai",
3644
+ deepseek: "deepseek",
3645
+ zai: "z-ai",
3646
+ moonshot: "moonshotai"
3647
+ };
3648
+ var OPENROUTER_ID_OVERRIDES = Object.freeze({});
3649
+ function openRouterModelId(profile) {
3650
+ const override = OPENROUTER_ID_OVERRIDES[profile.id];
3651
+ if (override) return override;
3652
+ const slug = OPENROUTER_VENDOR_SLUG[profile.provider];
3653
+ if (!slug) throw new Error(`No OpenRouter vendor slug for provider ${profile.provider} (model ${profile.id})`);
3654
+ return `${slug}/${profile.id}`;
3655
+ }
3508
3656
  function lower(ir, profile, hints = {}) {
3657
+ if (hints.route === "openrouter") {
3658
+ return lowerOpenRouter(ir, profile);
3659
+ }
3509
3660
  switch (profile.provider) {
3510
3661
  case "anthropic":
3511
3662
  return lowerAnthropic(ir, profile, hints);
@@ -3858,6 +4009,23 @@ function lowerZai(ir, profile, hints) {
3858
4009
  }
3859
4010
  };
3860
4011
  }
4012
+ function lowerOpenRouter(ir, profile) {
4013
+ const parts = buildOpenAICompatibleParts(ir);
4014
+ return {
4015
+ request: {
4016
+ provider: "openrouter",
4017
+ model: openRouterModelId(profile),
4018
+ messages: parts.messages,
4019
+ tools: parts.tools,
4020
+ response_format: parts.response_format
4021
+ },
4022
+ diagnostics: {
4023
+ cacheableTokens: 0,
4024
+ historyCacheableTokens: parts.historyCacheableTokens,
4025
+ estimatedCacheSavingsUsd: 0
4026
+ }
4027
+ };
4028
+ }
3861
4029
  function lowerMoonshot(ir, profile) {
3862
4030
  const parts = buildOpenAICompatibleParts(ir);
3863
4031
  return {
@@ -3959,7 +4127,8 @@ var SUPPORTED_PROVIDERS = Object.freeze([
3959
4127
  "openai",
3960
4128
  "deepseek",
3961
4129
  "zai",
3962
- "moonshot"
4130
+ "moonshot",
4131
+ "openrouter"
3963
4132
  ]);
3964
4133
  function isSupportedProvider(p) {
3965
4134
  return SUPPORTED_PROVIDERS.includes(p);
@@ -3980,7 +4149,11 @@ var PROVIDER_ENV_KEYS = Object.freeze({
3980
4149
  // alpha.65 — Moonshot AI (Kimi family). MOONSHOT_API_KEY is canonical
3981
4150
  // (api.moonshot.ai); KIMI_API_KEY covers the platform.kimi.ai rebrand
3982
4151
  // surface so consumers keyed under either name resolve.
3983
- moonshot: Object.freeze(["MOONSHOT_API_KEY", "KIMI_API_KEY"])
4152
+ moonshot: Object.freeze(["MOONSHOT_API_KEY", "KIMI_API_KEY"]),
4153
+ // alpha.92 — the OpenRouter gateway route (execute-leg contract). This is
4154
+ // a ROUTE key, not a vendor key: it never makes a vendor "reachable" for
4155
+ // chain composition — only explicit `route: 'openrouter'` calls use it.
4156
+ openrouter: Object.freeze(["OPENROUTER_API_KEY"])
3984
4157
  });
3985
4158
  function defaultEnv() {
3986
4159
  return typeof process !== "undefined" && process.env ? process.env : {};
@@ -4186,7 +4359,7 @@ var STARTER_CHAINS_GROUNDED = {
4186
4359
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
4187
4360
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 for cost-sensitive summarize workloads", n: 169 },
4188
4361
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
4189
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" },
4362
+ { id: "gemini-3.5-flash-lite", grounding: "judgment", reason: "Emergency floor. alpha.91: retargeted from availability-restricted gemini-2.5-flash-lite (Google refuses it for new accounts, TT-49 2026-08-26); 3.5-flash-lite is the successor Google\u2019s own error names" },
4190
4363
  { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI, matches summarize cost-band" }
4191
4364
  ],
4192
4365
  // Brain-validated DeepSeek tier 1 (169 rows, 0% empty rate).
@@ -4194,7 +4367,7 @@ var STARTER_CHAINS_GROUNDED = {
4194
4367
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
4195
4368
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 (169 rows, 0% empty rate)", n: 169 },
4196
4369
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
4197
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" },
4370
+ { id: "gemini-3.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads ($0.03/M cached). alpha.91: retargeted from availability-restricted gemini-2.5-flash-lite" },
4198
4371
  { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI for classify" }
4199
4372
  ]
4200
4373
  };
@@ -6058,12 +6231,13 @@ function compile(ir, opts = {}) {
6058
6231
  const lowered = lower(workingIR, profile, {
6059
6232
  forceThinkingZero: cliffs.value.loweringHints.forceThinkingZero,
6060
6233
  forceTerseOutput: cliffs.value.loweringHints.forceTerseOutput,
6061
- wireOverrides
6234
+ wireOverrides,
6235
+ route: opts.route
6062
6236
  });
6063
6237
  validateFinalFit(workingIR, profile, inputTokens);
6064
6238
  const handle = makeHandle();
6065
6239
  const finalShape = computeShape(workingIR, inputTokens);
6066
- const _learningKey = learningKey(ir.intent.archetype, profile.id, finalShape);
6240
+ const _learningKey = learningKey(ir.intent.archetype, routeScopedModel(profile.id, opts.route), finalShape);
6067
6241
  const historyCacheMarkIndex = computeHistoryCacheMarkIndex(workingIR);
6068
6242
  const systemMessages = buildSystemMessages(workingIR, profile.provider);
6069
6243
  const systemCacheMarkIndex = lastCacheableSystemIndex(systemMessages);
@@ -6290,7 +6464,7 @@ function validateFinalFit(ir, profile, tokens) {
6290
6464
  }
6291
6465
 
6292
6466
  // src/version.ts
6293
- var LIBRARY_VERSION = "2.0.0-alpha.90";
6467
+ var LIBRARY_VERSION = "2.0.0-alpha.92";
6294
6468
 
6295
6469
  // src/pricing-brain.ts
6296
6470
  function isPricingRow(x) {
@@ -6565,7 +6739,7 @@ async function flushBrainDeadLetter() {
6565
6739
  }
6566
6740
  var compileRegistry = /* @__PURE__ */ new Map();
6567
6741
  var REGISTRY_MAX_ENTRIES = 1e4;
6568
- function registerCompile(appId, archetype, ir, result, parentHandle) {
6742
+ function registerCompile(appId, archetype, ir, result, parentHandle, route) {
6569
6743
  if (compileRegistry.size >= REGISTRY_MAX_ENTRIES) {
6570
6744
  const cutoff = Math.floor(REGISTRY_MAX_ENTRIES * 0.25);
6571
6745
  let evicted = 0;
@@ -6597,7 +6771,10 @@ function registerCompile(appId, archetype, ir, result, parentHandle) {
6597
6771
  model: result.target,
6598
6772
  provider: result.provider,
6599
6773
  shapeKey,
6600
- learningKey: learningKey(archetype, result.target, shape),
6774
+ route: route ?? "direct",
6775
+ // alpha.92 — route-scoped for non-direct routes: the same model id on a
6776
+ // gateway is a different serving stack (Venice/StreamLake, 2026-08-26).
6777
+ learningKey: learningKey(archetype, routeScopedModel(result.target, route), shape),
6601
6778
  estimatedTokensIn: tokens,
6602
6779
  mutationsApplied: result.mutationsApplied.map((m) => m.id),
6603
6780
  // alpha.30: cache the in-memory advisories so record() can auto-persist
@@ -6791,6 +6968,11 @@ function buildPayload(input, reg) {
6791
6968
  provider: reg?.provider,
6792
6969
  shape_key: reg?.shapeKey,
6793
6970
  learning_key: reg?.learningKey,
6971
+ // alpha.92 (migration 067) — route identity on every row. Input wins
6972
+ // (a manual record() replaying through a gateway states its own route);
6973
+ // registry fills the call() path; column default covers legacy writers.
6974
+ route: input.route ?? reg?.route ?? "direct",
6975
+ route_host: input.routeHost,
6794
6976
  mutations_applied: mutationsApplied,
6795
6977
  tokens_in: input.tokensIn,
6796
6978
  tokens_out: input.tokensOut,
@@ -7585,6 +7767,7 @@ var OPENAI_URL = "https://api.openai.com/v1/chat/completions";
7585
7767
  var DEEPSEEK_URL = "https://api.deepseek.com/chat/completions";
7586
7768
  var ZAI_URL = "https://api.z.ai/api/paas/v4/chat/completions";
7587
7769
  var MOONSHOT_URL = "https://api.moonshot.ai/v1/chat/completions";
7770
+ var OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions";
7588
7771
  async function execute(request, opts = {}) {
7589
7772
  const merged = applyOverrides(request, opts.providerOverrides);
7590
7773
  switch (merged.provider) {
@@ -7608,6 +7791,12 @@ async function execute(request, opts = {}) {
7608
7791
  opts,
7609
7792
  { provider: "moonshot", url: MOONSHOT_URL, missingKeyMessage: "MOONSHOT_API_KEY missing" }
7610
7793
  );
7794
+ case "openrouter":
7795
+ return executeOpenAICompatible(
7796
+ merged,
7797
+ opts,
7798
+ { provider: "openrouter", url: OPENROUTER_URL, missingKeyMessage: "OPENROUTER_API_KEY missing" }
7799
+ );
7611
7800
  default: {
7612
7801
  const _exhaustive = merged;
7613
7802
  throw new Error(`execute(): no executor for provider: ${JSON.stringify(_exhaustive)}`);
@@ -7807,6 +7996,7 @@ function normalizeOpenAILike(raw) {
7807
7996
  const r = raw;
7808
7997
  const choice = r.choices?.[0];
7809
7998
  const text = choice?.message?.content ?? "";
7999
+ const routeHost = typeof raw?.provider === "string" ? raw.provider : void 0;
7810
8000
  const toolCalls = (choice?.message?.tool_calls ?? []).filter((tc) => tc.function?.name).map((tc, i) => ({
7811
8001
  id: tc.id ?? `tc-${i}`,
7812
8002
  name: tc.function.name,
@@ -7819,7 +8009,7 @@ function normalizeOpenAILike(raw) {
7819
8009
  total: u.total_tokens ?? (u.prompt_tokens ?? 0) + (u.completion_tokens ?? 0),
7820
8010
  cached: u.prompt_tokens_details?.cached_tokens
7821
8011
  };
7822
- return { text, structuredOutput: null, toolCalls, tokens, finishReason: choice?.finish_reason, raw };
8012
+ return { text, structuredOutput: null, toolCalls, tokens, finishReason: choice?.finish_reason, routeHost, raw };
7823
8013
  }
7824
8014
  function applyOverrides(request, overrides) {
7825
8015
  if (!overrides) return request;
@@ -7844,6 +8034,9 @@ function classifyHttpError2(status, body) {
7844
8034
  if (status === 404) {
7845
8035
  return { ok: false, status, errorType: "retryable", errorCode: "model_not_found", message, raw: body };
7846
8036
  }
8037
+ if (status >= 400 && status < 500 && isModelUnavailableMessage(message)) {
8038
+ return { ok: false, status, errorType: "retryable", errorCode: "model_not_found", message, raw: body };
8039
+ }
7847
8040
  if (status === 401 || status === 403) {
7848
8041
  return { ok: false, status, errorType: "terminal", errorCode: "auth", message, raw: body };
7849
8042
  }
@@ -7855,6 +8048,12 @@ function classifyHttpError2(status, body) {
7855
8048
  }
7856
8049
  return { ok: false, status, errorType: "terminal", errorCode: "unknown", message, raw: body };
7857
8050
  }
8051
+ function isModelUnavailableMessage(message) {
8052
+ if (!message) return false;
8053
+ return /no longer (available|supported)|not available to new users|has been (deprecated|retired|discontinued|shut ?down)/i.test(
8054
+ message
8055
+ );
8056
+ }
7858
8057
  function extractErrorMessage2(body) {
7859
8058
  if (!body || typeof body !== "object") return void 0;
7860
8059
  const b = body;
@@ -8249,6 +8448,7 @@ async function call(ir, opts = {}) {
8249
8448
  handle: initial.handle,
8250
8449
  source: opts.source,
8251
8450
  endUserId: opts.endUserId,
8451
+ route: opts.route,
8252
8452
  tokensIn: 0,
8253
8453
  tokensOut: 0,
8254
8454
  latencyMs: latencyMs2,
@@ -8303,6 +8503,7 @@ async function call(ir, opts = {}) {
8303
8503
  handle: initial.handle,
8304
8504
  source: opts.source,
8305
8505
  endUserId: opts.endUserId,
8506
+ route: opts.route,
8306
8507
  tokensIn: 0,
8307
8508
  tokensOut: 0,
8308
8509
  latencyMs: latencyMs2,
@@ -8446,6 +8647,11 @@ async function call(ir, opts = {}) {
8446
8647
  handle: initial.handle,
8447
8648
  source: opts.source,
8448
8649
  endUserId: opts.endUserId,
8650
+ // alpha.92 — route identity on the row (registry also carries it;
8651
+ // input wins in buildPayload, so state it explicitly here with the
8652
+ // host the gateway reported for the WINNING attempt).
8653
+ route: opts.route,
8654
+ routeHost: validated.response.routeHost,
8449
8655
  tokensIn: validated.response.tokens.input,
8450
8656
  tokensOut: validated.response.tokens.output,
8451
8657
  latencyMs: latencyMs2,
@@ -8526,6 +8732,12 @@ async function call(ir, opts = {}) {
8526
8732
  provider: activeCompile.provider,
8527
8733
  response: validated.response,
8528
8734
  latencyMs: latencyMs2,
8735
+ // alpha.92 — route identity + the served profile's cliffs flagged
8736
+ // route-unverified on a non-direct route (guards still fired; their
8737
+ // evidence is vendor-route evidence — see the execute-leg contract).
8738
+ route: opts.route ?? "direct",
8739
+ routeHost: validated.response.routeHost,
8740
+ routeUnverifiedCliffs: opts.route === "openrouter" ? (tryGetProfile(targetModel)?.cliffs ?? []).map((c) => c.metric) : void 0,
8529
8741
  mutationsApplied: activeCompile.mutationsApplied,
8530
8742
  attempts,
8531
8743
  servedBy: targetModel,
@@ -8570,6 +8782,7 @@ async function call(ir, opts = {}) {
8570
8782
  handle: initial.handle,
8571
8783
  source: opts.source,
8572
8784
  endUserId: opts.endUserId,
8785
+ route: opts.route,
8573
8786
  tokensIn: lastErr?.tokens?.input ?? 0,
8574
8787
  tokensOut: lastErr?.tokens?.output ?? 0,
8575
8788
  latencyMs,
@@ -8613,9 +8826,12 @@ function compileAndRegister(ir, opts) {
8613
8826
  toolRelevanceThreshold: opts.toolRelevanceThreshold,
8614
8827
  compressHistoryAfter: opts.compressHistoryAfter,
8615
8828
  // alpha.68 / Release A — carry the fan-out parent handle through to compile.
8616
- parentHandle: opts.parentHandle
8829
+ parentHandle: opts.parentHandle,
8830
+ // alpha.92 — gateway route (execute-leg contract): changes the wire +
8831
+ // learning-key encoding, never the pass pipeline.
8832
+ route: opts.route
8617
8833
  });
8618
- registerCompile(ir.appId, ir.intent.archetype, ir, result, opts.parentHandle);
8834
+ registerCompile(ir.appId, ir.intent.archetype, ir, result, opts.parentHandle, opts.route);
8619
8835
  return result;
8620
8836
  }
8621
8837
  function extractPromptPreview(ir) {
@@ -11054,7 +11270,7 @@ function planDecomposition(args) {
11054
11270
  // src/index.ts
11055
11271
  function compile2(ir, opts) {
11056
11272
  const result = compile(ir, opts);
11057
- registerCompile(ir.appId, ir.intent.archetype, ir, result, opts?.parentHandle);
11273
+ registerCompile(ir.appId, ir.intent.archetype, ir, result, opts?.parentHandle, opts?.route);
11058
11274
  return result;
11059
11275
  }
11060
11276
  // Annotate the CommonJS export names for ESM import in node: