@warmdrift/kgauto-compiler 2.0.0-alpha.15 → 2.0.0-alpha.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -17,7 +17,15 @@ import {
17
17
  getProfile,
18
18
  profilesByProvider,
19
19
  tryGetProfile
20
- } from "./chunk-SFF5EVTL.mjs";
20
+ } from "./chunk-7MTHFSNY.mjs";
21
+ import {
22
+ emitAdvisoryFired,
23
+ emitCompileDone,
24
+ emitCompileStart,
25
+ emitExecuteAttempt,
26
+ emitExecuteSuccess,
27
+ emitFallbackWalked
28
+ } from "./chunk-NUTC7NUC.mjs";
21
29
 
22
30
  // src/tokenizer.ts
23
31
  var tokenizerImpl = defaultCharBasedCounter;
@@ -1568,10 +1576,14 @@ var loadChainsFromBrain = createBrainQueryCache({
1568
1576
  // src/fallback.ts
1569
1577
  var STARTER_CHAINS = {
1570
1578
  // Reasoning floor — never degrade. Walk UP on 429 to Opus → cross-provider.
1579
+ // alpha.16: gpt-5.5 appended as third-provider critique floor (frontier-tier,
1580
+ // archetypePerf=9). Cross-provider-tail invariant has somewhere to land when
1581
+ // both Anthropic + Google are unreachable (consumer adds only OpenAI key).
1571
1582
  critique: [
1572
1583
  "claude-opus-4-7",
1573
1584
  "claude-sonnet-4-6",
1574
- "gemini-2.5-pro"
1585
+ "gemini-2.5-pro",
1586
+ "gpt-5.5"
1575
1587
  ],
1576
1588
  // Reasoning matters — Sonnet primary; walk UP to Opus on 429 (rare exception
1577
1589
  // to "always cheaper"); cross-provider via Pro; DeepSeek Pro as tier 3 floor.
@@ -1582,25 +1594,29 @@ var STARTER_CHAINS = {
1582
1594
  "deepseek-v4-pro"
1583
1595
  ],
1584
1596
  // Quality + cost match. Walk Sonnet → Haiku same-provider, Pro cross,
1585
- // Flash floor for the open-posture chain.
1597
+ // gpt-5.4-mini as third-provider tail (alpha.16 — closes the mono-Anthropic
1598
+ // gap when consumer has only ANTHROPIC + OPENAI keys; archetypePerf=7).
1586
1599
  generate: [
1587
1600
  "claude-sonnet-4-6",
1588
1601
  "claude-haiku-4-5",
1589
1602
  "gemini-2.5-pro",
1590
- "gemini-2.5-flash"
1603
+ "gpt-5.4-mini"
1591
1604
  ],
1592
1605
  ask: [
1593
1606
  "claude-sonnet-4-6",
1594
1607
  "claude-haiku-4-5",
1595
1608
  "gemini-2.5-pro",
1596
- "gemini-2.5-flash"
1609
+ "gpt-5.4-mini"
1597
1610
  ],
1598
1611
  // Structured-output archetype — Flash skipped (alpha.8 MAX_TOKENS cliff),
1599
- // DeepSeek skipped (no brain evidence). Floor at Haiku.
1612
+ // DeepSeek skipped (no brain evidence). Floor at Haiku. alpha.16: gpt-5.4
1613
+ // appended as third-provider extract floor (archetypePerf=8, native
1614
+ // structured-output support).
1600
1615
  extract: [
1601
1616
  "claude-sonnet-4-6",
1602
1617
  "claude-haiku-4-5",
1603
- "gemini-2.5-pro"
1618
+ "gemini-2.5-pro",
1619
+ "gpt-5.4"
1604
1620
  ],
1605
1621
  // Forgiving archetype — Sonnet primary but Flash safely floors it.
1606
1622
  transform: [
@@ -1715,7 +1731,31 @@ function ensureCrossProviderTail(opts) {
1715
1731
 
1716
1732
  // src/call.ts
1717
1733
  async function call(ir, opts = {}) {
1734
+ const traceId = generateTraceId();
1735
+ safeEmit(
1736
+ () => emitCompileStart(traceId, {
1737
+ appId: ir.appId,
1738
+ archetype: ir.intent.archetype,
1739
+ models: ir.models
1740
+ })
1741
+ );
1718
1742
  const initial = compileAndRegister(ir, opts);
1743
+ safeEmit(
1744
+ () => emitCompileDone(traceId, {
1745
+ target: initial.target,
1746
+ provider: initial.provider,
1747
+ fallbackChain: initial.fallbackChain,
1748
+ tokensIn: initial.tokensIn,
1749
+ estimatedCostUsd: initial.estimatedCostUsd,
1750
+ mutationsApplied: initial.mutationsApplied,
1751
+ advisories: initial.advisories
1752
+ })
1753
+ );
1754
+ for (const adv of initial.advisories) {
1755
+ safeEmit(
1756
+ () => emitAdvisoryFired(traceId, { code: adv.code, message: adv.message })
1757
+ );
1758
+ }
1719
1759
  const start = Date.now();
1720
1760
  const attempts = [];
1721
1761
  const rawTargets = [initial.target, ...initial.fallbackChain];
@@ -1770,6 +1810,47 @@ async function call(ir, opts = {}) {
1770
1810
  }
1771
1811
  }
1772
1812
  }
1813
+ let policyBlockedFiltered;
1814
+ if (opts.policy?.blockedModels && opts.policy.blockedModels.length > 0) {
1815
+ const blocked = new Set(opts.policy.blockedModels);
1816
+ const filtered = [];
1817
+ const dropped = [];
1818
+ for (const t of targetsToTry) {
1819
+ if (blocked.has(t)) {
1820
+ dropped.push(t);
1821
+ } else {
1822
+ filtered.push(t);
1823
+ }
1824
+ }
1825
+ if (dropped.length > 0) {
1826
+ policyBlockedFiltered = dropped;
1827
+ targetsToTry = filtered;
1828
+ }
1829
+ if (targetsToTry.length === 0) {
1830
+ const latencyMs2 = Date.now() - start;
1831
+ await record({
1832
+ handle: initial.handle,
1833
+ tokensIn: 0,
1834
+ tokensOut: 0,
1835
+ latencyMs: latencyMs2,
1836
+ success: false,
1837
+ errorType: "all_blocked_by_policy",
1838
+ promptPreview: extractPromptPreview(ir)
1839
+ });
1840
+ const blockedAttempts = dropped.map((m) => ({
1841
+ model: m,
1842
+ status: "terminal",
1843
+ errorCode: "blocked_by_policy",
1844
+ message: `Skipped \u2014 model ${m} is in CompilePolicy.blockedModels`
1845
+ }));
1846
+ throw new CallError(
1847
+ `call(): all chain targets blocked by CompilePolicy.blockedModels: [${dropped.join(", ")}]`,
1848
+ blockedAttempts,
1849
+ void 0,
1850
+ "all_blocked_by_policy"
1851
+ );
1852
+ }
1853
+ }
1773
1854
  let activeCompile = initial;
1774
1855
  let lastErr;
1775
1856
  const failedProviders = /* @__PURE__ */ new Set();
@@ -1805,6 +1886,9 @@ async function call(ir, opts = {}) {
1805
1886
  continue;
1806
1887
  }
1807
1888
  }
1889
+ safeEmit(
1890
+ () => emitExecuteAttempt(traceId, { model: targetModel, attemptIndex: i })
1891
+ );
1808
1892
  const exec = await execute(activeCompile.request, {
1809
1893
  apiKeys: opts.apiKeys,
1810
1894
  fetchImpl: opts.fetchImpl,
@@ -1814,6 +1898,14 @@ async function call(ir, opts = {}) {
1814
1898
  if (validated.ok) {
1815
1899
  attempts.push({ model: targetModel, status: "success" });
1816
1900
  const latencyMs2 = Date.now() - start;
1901
+ safeEmit(
1902
+ () => emitExecuteSuccess(traceId, {
1903
+ model: targetModel,
1904
+ tokensIn: validated.response.tokens.input,
1905
+ tokensOut: validated.response.tokens.output,
1906
+ latencyMs: latencyMs2
1907
+ })
1908
+ );
1817
1909
  await record({
1818
1910
  handle: initial.handle,
1819
1911
  tokensIn: validated.response.tokens.input,
@@ -1830,6 +1922,20 @@ async function call(ir, opts = {}) {
1830
1922
  cacheCreationInputTokens: validated.response.tokens.cacheCreated
1831
1923
  });
1832
1924
  const fellOver = targetModel !== initial.target;
1925
+ const fallbackReason = fellOver ? normalizeFallbackReason(attempts) : void 0;
1926
+ if (fellOver) {
1927
+ const firstFailed = attempts.find((a) => a.status !== "success");
1928
+ if (firstFailed) {
1929
+ safeEmit(
1930
+ () => emitFallbackWalked(traceId, {
1931
+ from: initial.target,
1932
+ to: targetModel,
1933
+ reason: fallbackReason ?? "unknown",
1934
+ attempt: firstFailed
1935
+ })
1936
+ );
1937
+ }
1938
+ }
1833
1939
  return {
1834
1940
  handle: initial.handle,
1835
1941
  actualModel: targetModel,
@@ -1841,8 +1947,10 @@ async function call(ir, opts = {}) {
1841
1947
  attempts,
1842
1948
  servedBy: targetModel,
1843
1949
  fellOverFrom: fellOver ? initial.target : void 0,
1844
- fallbackReason: fellOver ? normalizeFallbackReason(attempts) : void 0,
1845
- unreachableFiltered
1950
+ fallbackReason,
1951
+ unreachableFiltered,
1952
+ policyBlockedFiltered,
1953
+ traceId
1846
1954
  };
1847
1955
  }
1848
1956
  attempts.push({
@@ -1871,8 +1979,9 @@ async function call(ir, opts = {}) {
1871
1979
  promptPreview: extractPromptPreview(ir)
1872
1980
  });
1873
1981
  const filteredNote = unreachableFiltered && unreachableFiltered.length > 0 ? ` (also auto-filtered: [${unreachableFiltered.join(", ")}] \u2014 no API key)` : "";
1982
+ const blockedNote = policyBlockedFiltered && policyBlockedFiltered.length > 0 ? ` (also policy-blocked: [${policyBlockedFiltered.join(", ")}])` : "";
1874
1983
  throw new CallError(
1875
- `call(): all attempts failed${lastErr ? ` \u2014 ${lastErr.errorCode}: ${lastErr.message}` : ""}${filteredNote}`,
1984
+ `call(): all attempts failed${lastErr ? ` \u2014 ${lastErr.errorCode}: ${lastErr.message}` : ""}${filteredNote}${blockedNote}`,
1876
1985
  attempts,
1877
1986
  lastErr?.status,
1878
1987
  lastErr?.errorCode
@@ -1938,6 +2047,23 @@ function normalizeFallbackReason(attempts) {
1938
2047
  if (code === "auth" || code === "auth_inferred") return "provider_auth_failed";
1939
2048
  return "provider_error";
1940
2049
  }
2050
+ function generateTraceId() {
2051
+ try {
2052
+ const g = globalThis;
2053
+ if (g.crypto && typeof g.crypto.randomUUID === "function") {
2054
+ return g.crypto.randomUUID();
2055
+ }
2056
+ } catch {
2057
+ }
2058
+ const hex = (n) => Math.floor(Math.random() * Math.pow(16, n)).toString(16).padStart(n, "0");
2059
+ return `${hex(8)}-${hex(4)}-${hex(4)}-${hex(4)}-${hex(12)}`;
2060
+ }
2061
+ function safeEmit(fn) {
2062
+ try {
2063
+ fn();
2064
+ } catch {
2065
+ }
2066
+ }
1941
2067
 
1942
2068
  // src/oracle.ts
1943
2069
  var DEFAULT_DIMENSIONS = ["correctness", "completeness", "conciseness", "format"];
@@ -521,6 +521,35 @@ interface CallResult {
521
521
  * when `noAutoFilter: true`).
522
522
  */
523
523
  unreachableFiltered?: string[];
524
+ /**
525
+ * alpha.16. Models that policy.blockedModels filtering dropped from the
526
+ * fallback walk. Defense-in-depth at the call() boundary — compile()'s
527
+ * passScoreTargets already excludes blocked entries from the initial
528
+ * target + fallbackChain, but if a consumer re-shapes the chain and
529
+ * threads policy through only partially, this filter catches the gap.
530
+ *
531
+ * Resolves TT-40 follow-on `policy-block-not-enforced-on-fallback-chain`
532
+ * (2026-05-15) where mutations_applied recorded the block intent but
533
+ * the call walker landed on the blocked model anyway.
534
+ *
535
+ * Undefined when no filter ran (no blockedModels set). Populated only
536
+ * when filter ran AND dropped at least one entry — empty drops are
537
+ * stored as `undefined` to keep brain telemetry quiet on the common
538
+ * case.
539
+ */
540
+ policyBlockedFiltered?: string[];
541
+ /**
542
+ * alpha.17. Unique identifier for this call() invocation, generated at
543
+ * call() entry via crypto.randomUUID(). Returned on success and emitted
544
+ * as the routing key for Glass-Box observability events
545
+ * (compile.start, compile.done, execute.attempt, execute.success,
546
+ * fallback.walked, advisory.fired). Pass the same id to
547
+ * `subscribe(traceId)` from `@warmdrift/kgauto-compiler/glassbox` to
548
+ * tap the in-flight event stream.
549
+ *
550
+ * Always present on success. Additive, non-breaking.
551
+ */
552
+ traceId: string;
524
553
  }
525
554
  /**
526
555
  * Thrown when call() exhausts the fallback chain without success.
@@ -607,137 +636,4 @@ interface RecordInput {
607
636
  ttftMs?: number;
608
637
  }
609
638
 
610
- /**
611
- * Model profiles — executable knowledge about each provider/model.
612
- *
613
- * Unlike v1 which carried `known_failures` as prose strings, v2 makes them
614
- * executable: cliffs trigger guards, lowering describes the wire format,
615
- * recovery handlers describe what to do after specific failures.
616
- *
617
- * Each profile is the answer to "if I want to call THIS model with THIS
618
- * shape of work, what does it need from me, and what should I do when it
619
- * fails?"
620
- */
621
-
622
- type StructuredOutputCapability = 'native' | 'grammar' | 'none';
623
- type SystemPromptMode = 'inline' | 'separate' | 'as_developer' | 'unsupported';
624
- type CacheStrategy = 'cache_control' | 'cachedContent' | 'unsupported';
625
- interface CliffRule {
626
- /** What metric triggers this cliff. */
627
- metric: 'input_tokens' | 'tool_count' | 'history_turns' | 'thinking_with_short_output';
628
- /** Threshold — meaning depends on metric. */
629
- threshold: number;
630
- /** What action to take when triggered. */
631
- action: 'downgrade_quality_warning' | 'drop_to_top_relevant' | 'force_thinking_budget_zero' | 'force_terse_output' | 'escalate_target' | 'strip_tools';
632
- /**
633
- * Optional: only fire this cliff when the IR's intent.archetype matches.
634
- * Used for archetype-specific failure modes (e.g. Gemini Flash returns
635
- * empty when summarize is offered tools).
636
- */
637
- whenIntent?: IntentArchetypeName;
638
- /** Human-readable reason for digest reporting. */
639
- reason: string;
640
- }
641
- interface RecoveryRule {
642
- /** What signal triggers recovery. */
643
- signal: 'empty_response_after_tool' | 'empty_response' | 'malformed_function_call' | 'rate_limit' | 'model_not_found' | 'context_overflow';
644
- /** Action: retry with adjusted params, or escalate to next fallback. */
645
- action: 'retry_with_params' | 'escalate' | 'log_only';
646
- /** When action=retry_with_params, the param adjustments to apply. */
647
- retryParams?: Record<string, unknown>;
648
- /** Max retries with this rule. */
649
- maxRetries?: number;
650
- /** Human-readable reason for digest reporting. */
651
- reason: string;
652
- }
653
- interface LoweringSpec {
654
- /** Where the system prompt goes. */
655
- system: {
656
- mode: SystemPromptMode;
657
- field?: string;
658
- };
659
- /** Cache strategy + parameters. */
660
- cache: {
661
- strategy: CacheStrategy;
662
- /** Min tokens before caching is worth it (provider rules). */
663
- minTokens?: number;
664
- /** Discount factor on cached input (0.1 = 10% of normal price). */
665
- discount?: number;
666
- /** TTL hint in seconds. */
667
- ttlSeconds?: number;
668
- };
669
- /** Tool format identifier — see lower.ts for supported formats. */
670
- tools?: {
671
- format: 'anthropic' | 'google' | 'openai' | 'deepseek';
672
- };
673
- /** Thinking config — present iff this model has a thinking knob. */
674
- thinking?: {
675
- /** Field path on the request. */
676
- field: string;
677
- /** Default value when caller hasn't specified. */
678
- default?: number | 'auto' | 'off';
679
- };
680
- }
681
- interface ModelProfile {
682
- id: string;
683
- provider: Provider;
684
- status: 'current' | 'preview' | 'legacy';
685
- maxContextTokens: number;
686
- maxOutputTokens: number;
687
- maxTools: number;
688
- parallelToolCalls: boolean;
689
- structuredOutput: StructuredOutputCapability;
690
- systemPromptMode: SystemPromptMode;
691
- streaming: boolean;
692
- cliffs: CliffRule[];
693
- costInputPer1m: number;
694
- costOutputPer1m: number;
695
- lowering: LoweringSpec;
696
- recovery: RecoveryRule[];
697
- strengths: string[];
698
- weaknesses: string[];
699
- notes?: string;
700
- verifiedAgainstDocs?: string;
701
- /**
702
- * Hand-curated per-archetype performance score on a 0-10 scale.
703
- *
704
- * 10 = frontier on this archetype (e.g. Opus 4.7 on critique)
705
- * 8 = strong second tier (Sonnet on plan, Pro on extract)
706
- * 7 = competent (Haiku on classify, Flash on hunt)
707
- * 5 = acceptable for tolerant archetypes (Flash-Lite on classify)
708
- * 3 = degraded (Flash on critique, DeepSeek on hunt)
709
- *
710
- * Missing archetypes default to `5` (no data, neutral). Each non-default
711
- * value should carry a one-line rationale in the profile's note or inline
712
- * comment citing brain evidence, family prior, or "starter hypothesis —
713
- * verify with telemetry."
714
- *
715
- * Source today: hand-curated from master plan §3.3 + §6.2 starter tables.
716
- * Source tomorrow (alpha.10+): brain `archetype_model_evidence` view.
717
- *
718
- * Anti-hallucination guardrail (master plan §2.5): when the watcher's
719
- * `--audit-fields` flag flags a profile stale (>90 days since
720
- * verifiedAgainstDocs), the archetypePerf values get re-audited
721
- * alongside capability fields. AI-trained intuition is NOT a valid
722
- * source — only docs or brain evidence.
723
- *
724
- * alpha.9.
725
- */
726
- archetypePerf?: Partial<Record<IntentArchetypeName, number>>;
727
- }
728
- declare const ALIASES: Record<string, string>;
729
- interface ProfileBrainHook {
730
- getProfile?: (canonicalId: string) => ModelProfile | undefined;
731
- resolveAlias?: (id: string) => string | undefined;
732
- }
733
- /** @internal — called by models-brain.ts at module load. */
734
- declare function _setProfileBrainHook(hook: ProfileBrainHook): void;
735
- declare function getProfile(id: string): ModelProfile;
736
- declare function tryGetProfile(id: string): ModelProfile | undefined;
737
- declare function allProfiles(): readonly ModelProfile[];
738
- /** @internal — bundled-only access for adapters that need a non-brain
739
- * fallback baseline (avoids a brain → profiles → brain re-entry). */
740
- declare function allProfilesRaw(): readonly ModelProfile[];
741
- declare function profilesByProvider(provider: Provider): readonly ModelProfile[];
742
-
743
- export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type FallbackReason as F, type HistoryCachePolicy as H, type IntentDeclaration as I, type LoweringSpec as L, type ModelProfile as M, type NormalizedResponse as N, type OracleScore as O, type ProviderOverrides as P, type RecordInput as R, type StructuredOutputCapability as S, type ToolCall as T, _setProfileBrainHook as _, type CompiledRequest as a, type PromptIR as b, type CallOptions as c, type CallResult as d, type CompileResult as e, type Provider as f, ALIASES as g, type CacheStrategy as h, type CallAttempt as i, CallError as j, type CliffRule as k, type Constraints as l, type Message as m, type MutationApplied as n, type NormalizedTokens as o, type PromptSection as p, type RecoveryRule as q, type SystemPromptMode as r, type ToolDefinition as s, allProfiles as t, getProfile as u, profilesByProvider as v, tryGetProfile as w, allProfilesRaw as x };
639
+ export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type FallbackReason as F, type HistoryCachePolicy as H, type IntentDeclaration as I, type Message as M, type NormalizedResponse as N, type OracleScore as O, type ProviderOverrides as P, type RecordInput as R, type ToolCall as T, type CompiledRequest as a, type PromptIR as b, type CallOptions as c, type CallResult as d, type CompileResult as e, type Provider as f, type CallAttempt as g, CallError as h, type Constraints as i, type MutationApplied as j, type NormalizedTokens as k, type PromptSection as l, type ToolDefinition as m };
@@ -521,6 +521,35 @@ interface CallResult {
521
521
  * when `noAutoFilter: true`).
522
522
  */
523
523
  unreachableFiltered?: string[];
524
+ /**
525
+ * alpha.16. Models that policy.blockedModels filtering dropped from the
526
+ * fallback walk. Defense-in-depth at the call() boundary — compile()'s
527
+ * passScoreTargets already excludes blocked entries from the initial
528
+ * target + fallbackChain, but if a consumer re-shapes the chain and
529
+ * threads policy through only partially, this filter catches the gap.
530
+ *
531
+ * Resolves TT-40 follow-on `policy-block-not-enforced-on-fallback-chain`
532
+ * (2026-05-15) where mutations_applied recorded the block intent but
533
+ * the call walker landed on the blocked model anyway.
534
+ *
535
+ * Undefined when no filter ran (no blockedModels set). Populated only
536
+ * when filter ran AND dropped at least one entry — empty drops are
537
+ * stored as `undefined` to keep brain telemetry quiet on the common
538
+ * case.
539
+ */
540
+ policyBlockedFiltered?: string[];
541
+ /**
542
+ * alpha.17. Unique identifier for this call() invocation, generated at
543
+ * call() entry via crypto.randomUUID(). Returned on success and emitted
544
+ * as the routing key for Glass-Box observability events
545
+ * (compile.start, compile.done, execute.attempt, execute.success,
546
+ * fallback.walked, advisory.fired). Pass the same id to
547
+ * `subscribe(traceId)` from `@warmdrift/kgauto-compiler/glassbox` to
548
+ * tap the in-flight event stream.
549
+ *
550
+ * Always present on success. Additive, non-breaking.
551
+ */
552
+ traceId: string;
524
553
  }
525
554
  /**
526
555
  * Thrown when call() exhausts the fallback chain without success.
@@ -607,137 +636,4 @@ interface RecordInput {
607
636
  ttftMs?: number;
608
637
  }
609
638
 
610
- /**
611
- * Model profiles — executable knowledge about each provider/model.
612
- *
613
- * Unlike v1 which carried `known_failures` as prose strings, v2 makes them
614
- * executable: cliffs trigger guards, lowering describes the wire format,
615
- * recovery handlers describe what to do after specific failures.
616
- *
617
- * Each profile is the answer to "if I want to call THIS model with THIS
618
- * shape of work, what does it need from me, and what should I do when it
619
- * fails?"
620
- */
621
-
622
- type StructuredOutputCapability = 'native' | 'grammar' | 'none';
623
- type SystemPromptMode = 'inline' | 'separate' | 'as_developer' | 'unsupported';
624
- type CacheStrategy = 'cache_control' | 'cachedContent' | 'unsupported';
625
- interface CliffRule {
626
- /** What metric triggers this cliff. */
627
- metric: 'input_tokens' | 'tool_count' | 'history_turns' | 'thinking_with_short_output';
628
- /** Threshold — meaning depends on metric. */
629
- threshold: number;
630
- /** What action to take when triggered. */
631
- action: 'downgrade_quality_warning' | 'drop_to_top_relevant' | 'force_thinking_budget_zero' | 'force_terse_output' | 'escalate_target' | 'strip_tools';
632
- /**
633
- * Optional: only fire this cliff when the IR's intent.archetype matches.
634
- * Used for archetype-specific failure modes (e.g. Gemini Flash returns
635
- * empty when summarize is offered tools).
636
- */
637
- whenIntent?: IntentArchetypeName;
638
- /** Human-readable reason for digest reporting. */
639
- reason: string;
640
- }
641
- interface RecoveryRule {
642
- /** What signal triggers recovery. */
643
- signal: 'empty_response_after_tool' | 'empty_response' | 'malformed_function_call' | 'rate_limit' | 'model_not_found' | 'context_overflow';
644
- /** Action: retry with adjusted params, or escalate to next fallback. */
645
- action: 'retry_with_params' | 'escalate' | 'log_only';
646
- /** When action=retry_with_params, the param adjustments to apply. */
647
- retryParams?: Record<string, unknown>;
648
- /** Max retries with this rule. */
649
- maxRetries?: number;
650
- /** Human-readable reason for digest reporting. */
651
- reason: string;
652
- }
653
- interface LoweringSpec {
654
- /** Where the system prompt goes. */
655
- system: {
656
- mode: SystemPromptMode;
657
- field?: string;
658
- };
659
- /** Cache strategy + parameters. */
660
- cache: {
661
- strategy: CacheStrategy;
662
- /** Min tokens before caching is worth it (provider rules). */
663
- minTokens?: number;
664
- /** Discount factor on cached input (0.1 = 10% of normal price). */
665
- discount?: number;
666
- /** TTL hint in seconds. */
667
- ttlSeconds?: number;
668
- };
669
- /** Tool format identifier — see lower.ts for supported formats. */
670
- tools?: {
671
- format: 'anthropic' | 'google' | 'openai' | 'deepseek';
672
- };
673
- /** Thinking config — present iff this model has a thinking knob. */
674
- thinking?: {
675
- /** Field path on the request. */
676
- field: string;
677
- /** Default value when caller hasn't specified. */
678
- default?: number | 'auto' | 'off';
679
- };
680
- }
681
- interface ModelProfile {
682
- id: string;
683
- provider: Provider;
684
- status: 'current' | 'preview' | 'legacy';
685
- maxContextTokens: number;
686
- maxOutputTokens: number;
687
- maxTools: number;
688
- parallelToolCalls: boolean;
689
- structuredOutput: StructuredOutputCapability;
690
- systemPromptMode: SystemPromptMode;
691
- streaming: boolean;
692
- cliffs: CliffRule[];
693
- costInputPer1m: number;
694
- costOutputPer1m: number;
695
- lowering: LoweringSpec;
696
- recovery: RecoveryRule[];
697
- strengths: string[];
698
- weaknesses: string[];
699
- notes?: string;
700
- verifiedAgainstDocs?: string;
701
- /**
702
- * Hand-curated per-archetype performance score on a 0-10 scale.
703
- *
704
- * 10 = frontier on this archetype (e.g. Opus 4.7 on critique)
705
- * 8 = strong second tier (Sonnet on plan, Pro on extract)
706
- * 7 = competent (Haiku on classify, Flash on hunt)
707
- * 5 = acceptable for tolerant archetypes (Flash-Lite on classify)
708
- * 3 = degraded (Flash on critique, DeepSeek on hunt)
709
- *
710
- * Missing archetypes default to `5` (no data, neutral). Each non-default
711
- * value should carry a one-line rationale in the profile's note or inline
712
- * comment citing brain evidence, family prior, or "starter hypothesis —
713
- * verify with telemetry."
714
- *
715
- * Source today: hand-curated from master plan §3.3 + §6.2 starter tables.
716
- * Source tomorrow (alpha.10+): brain `archetype_model_evidence` view.
717
- *
718
- * Anti-hallucination guardrail (master plan §2.5): when the watcher's
719
- * `--audit-fields` flag flags a profile stale (>90 days since
720
- * verifiedAgainstDocs), the archetypePerf values get re-audited
721
- * alongside capability fields. AI-trained intuition is NOT a valid
722
- * source — only docs or brain evidence.
723
- *
724
- * alpha.9.
725
- */
726
- archetypePerf?: Partial<Record<IntentArchetypeName, number>>;
727
- }
728
- declare const ALIASES: Record<string, string>;
729
- interface ProfileBrainHook {
730
- getProfile?: (canonicalId: string) => ModelProfile | undefined;
731
- resolveAlias?: (id: string) => string | undefined;
732
- }
733
- /** @internal — called by models-brain.ts at module load. */
734
- declare function _setProfileBrainHook(hook: ProfileBrainHook): void;
735
- declare function getProfile(id: string): ModelProfile;
736
- declare function tryGetProfile(id: string): ModelProfile | undefined;
737
- declare function allProfiles(): readonly ModelProfile[];
738
- /** @internal — bundled-only access for adapters that need a non-brain
739
- * fallback baseline (avoids a brain → profiles → brain re-entry). */
740
- declare function allProfilesRaw(): readonly ModelProfile[];
741
- declare function profilesByProvider(provider: Provider): readonly ModelProfile[];
742
-
743
- export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type FallbackReason as F, type HistoryCachePolicy as H, type IntentDeclaration as I, type LoweringSpec as L, type ModelProfile as M, type NormalizedResponse as N, type OracleScore as O, type ProviderOverrides as P, type RecordInput as R, type StructuredOutputCapability as S, type ToolCall as T, _setProfileBrainHook as _, type CompiledRequest as a, type PromptIR as b, type CallOptions as c, type CallResult as d, type CompileResult as e, type Provider as f, ALIASES as g, type CacheStrategy as h, type CallAttempt as i, CallError as j, type CliffRule as k, type Constraints as l, type Message as m, type MutationApplied as n, type NormalizedTokens as o, type PromptSection as p, type RecoveryRule as q, type SystemPromptMode as r, type ToolDefinition as s, allProfiles as t, getProfile as u, profilesByProvider as v, tryGetProfile as w, allProfilesRaw as x };
639
+ export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type FallbackReason as F, type HistoryCachePolicy as H, type IntentDeclaration as I, type Message as M, type NormalizedResponse as N, type OracleScore as O, type ProviderOverrides as P, type RecordInput as R, type ToolCall as T, type CompiledRequest as a, type PromptIR as b, type CallOptions as c, type CallResult as d, type CompileResult as e, type Provider as f, type CallAttempt as g, CallError as h, type Constraints as i, type MutationApplied as j, type NormalizedTokens as k, type PromptSection as l, type ToolDefinition as m };