@warmdrift/kgauto-compiler 2.0.0-alpha.16 → 2.0.0-alpha.18

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
@@ -18,6 +18,14 @@ import {
18
18
  profilesByProvider,
19
19
  tryGetProfile
20
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;
@@ -1723,7 +1731,31 @@ function ensureCrossProviderTail(opts) {
1723
1731
 
1724
1732
  // src/call.ts
1725
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
+ );
1726
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
+ }
1727
1759
  const start = Date.now();
1728
1760
  const attempts = [];
1729
1761
  const rawTargets = [initial.target, ...initial.fallbackChain];
@@ -1854,6 +1886,9 @@ async function call(ir, opts = {}) {
1854
1886
  continue;
1855
1887
  }
1856
1888
  }
1889
+ safeEmit(
1890
+ () => emitExecuteAttempt(traceId, { model: targetModel, attemptIndex: i })
1891
+ );
1857
1892
  const exec = await execute(activeCompile.request, {
1858
1893
  apiKeys: opts.apiKeys,
1859
1894
  fetchImpl: opts.fetchImpl,
@@ -1863,6 +1898,14 @@ async function call(ir, opts = {}) {
1863
1898
  if (validated.ok) {
1864
1899
  attempts.push({ model: targetModel, status: "success" });
1865
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
+ );
1866
1909
  await record({
1867
1910
  handle: initial.handle,
1868
1911
  tokensIn: validated.response.tokens.input,
@@ -1879,6 +1922,20 @@ async function call(ir, opts = {}) {
1879
1922
  cacheCreationInputTokens: validated.response.tokens.cacheCreated
1880
1923
  });
1881
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
+ }
1882
1939
  return {
1883
1940
  handle: initial.handle,
1884
1941
  actualModel: targetModel,
@@ -1890,9 +1947,10 @@ async function call(ir, opts = {}) {
1890
1947
  attempts,
1891
1948
  servedBy: targetModel,
1892
1949
  fellOverFrom: fellOver ? initial.target : void 0,
1893
- fallbackReason: fellOver ? normalizeFallbackReason(attempts) : void 0,
1950
+ fallbackReason,
1894
1951
  unreachableFiltered,
1895
- policyBlockedFiltered
1952
+ policyBlockedFiltered,
1953
+ traceId
1896
1954
  };
1897
1955
  }
1898
1956
  attempts.push({
@@ -1989,6 +2047,23 @@ function normalizeFallbackReason(attempts) {
1989
2047
  if (code === "auth" || code === "auth_inferred") return "provider_auth_failed";
1990
2048
  return "provider_error";
1991
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
+ }
1992
2067
 
1993
2068
  // src/oracle.ts
1994
2069
  var DEFAULT_DIMENSIONS = ["correctness", "completeness", "conciseness", "format"];
@@ -538,6 +538,18 @@ interface CallResult {
538
538
  * case.
539
539
  */
540
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;
541
553
  }
542
554
  /**
543
555
  * Thrown when call() exhausts the fallback chain without success.
@@ -624,137 +636,4 @@ interface RecordInput {
624
636
  ttftMs?: number;
625
637
  }
626
638
 
627
- /**
628
- * Model profiles — executable knowledge about each provider/model.
629
- *
630
- * Unlike v1 which carried `known_failures` as prose strings, v2 makes them
631
- * executable: cliffs trigger guards, lowering describes the wire format,
632
- * recovery handlers describe what to do after specific failures.
633
- *
634
- * Each profile is the answer to "if I want to call THIS model with THIS
635
- * shape of work, what does it need from me, and what should I do when it
636
- * fails?"
637
- */
638
-
639
- type StructuredOutputCapability = 'native' | 'grammar' | 'none';
640
- type SystemPromptMode = 'inline' | 'separate' | 'as_developer' | 'unsupported';
641
- type CacheStrategy = 'cache_control' | 'cachedContent' | 'unsupported';
642
- interface CliffRule {
643
- /** What metric triggers this cliff. */
644
- metric: 'input_tokens' | 'tool_count' | 'history_turns' | 'thinking_with_short_output';
645
- /** Threshold — meaning depends on metric. */
646
- threshold: number;
647
- /** What action to take when triggered. */
648
- action: 'downgrade_quality_warning' | 'drop_to_top_relevant' | 'force_thinking_budget_zero' | 'force_terse_output' | 'escalate_target' | 'strip_tools';
649
- /**
650
- * Optional: only fire this cliff when the IR's intent.archetype matches.
651
- * Used for archetype-specific failure modes (e.g. Gemini Flash returns
652
- * empty when summarize is offered tools).
653
- */
654
- whenIntent?: IntentArchetypeName;
655
- /** Human-readable reason for digest reporting. */
656
- reason: string;
657
- }
658
- interface RecoveryRule {
659
- /** What signal triggers recovery. */
660
- signal: 'empty_response_after_tool' | 'empty_response' | 'malformed_function_call' | 'rate_limit' | 'model_not_found' | 'context_overflow';
661
- /** Action: retry with adjusted params, or escalate to next fallback. */
662
- action: 'retry_with_params' | 'escalate' | 'log_only';
663
- /** When action=retry_with_params, the param adjustments to apply. */
664
- retryParams?: Record<string, unknown>;
665
- /** Max retries with this rule. */
666
- maxRetries?: number;
667
- /** Human-readable reason for digest reporting. */
668
- reason: string;
669
- }
670
- interface LoweringSpec {
671
- /** Where the system prompt goes. */
672
- system: {
673
- mode: SystemPromptMode;
674
- field?: string;
675
- };
676
- /** Cache strategy + parameters. */
677
- cache: {
678
- strategy: CacheStrategy;
679
- /** Min tokens before caching is worth it (provider rules). */
680
- minTokens?: number;
681
- /** Discount factor on cached input (0.1 = 10% of normal price). */
682
- discount?: number;
683
- /** TTL hint in seconds. */
684
- ttlSeconds?: number;
685
- };
686
- /** Tool format identifier — see lower.ts for supported formats. */
687
- tools?: {
688
- format: 'anthropic' | 'google' | 'openai' | 'deepseek';
689
- };
690
- /** Thinking config — present iff this model has a thinking knob. */
691
- thinking?: {
692
- /** Field path on the request. */
693
- field: string;
694
- /** Default value when caller hasn't specified. */
695
- default?: number | 'auto' | 'off';
696
- };
697
- }
698
- interface ModelProfile {
699
- id: string;
700
- provider: Provider;
701
- status: 'current' | 'preview' | 'legacy';
702
- maxContextTokens: number;
703
- maxOutputTokens: number;
704
- maxTools: number;
705
- parallelToolCalls: boolean;
706
- structuredOutput: StructuredOutputCapability;
707
- systemPromptMode: SystemPromptMode;
708
- streaming: boolean;
709
- cliffs: CliffRule[];
710
- costInputPer1m: number;
711
- costOutputPer1m: number;
712
- lowering: LoweringSpec;
713
- recovery: RecoveryRule[];
714
- strengths: string[];
715
- weaknesses: string[];
716
- notes?: string;
717
- verifiedAgainstDocs?: string;
718
- /**
719
- * Hand-curated per-archetype performance score on a 0-10 scale.
720
- *
721
- * 10 = frontier on this archetype (e.g. Opus 4.7 on critique)
722
- * 8 = strong second tier (Sonnet on plan, Pro on extract)
723
- * 7 = competent (Haiku on classify, Flash on hunt)
724
- * 5 = acceptable for tolerant archetypes (Flash-Lite on classify)
725
- * 3 = degraded (Flash on critique, DeepSeek on hunt)
726
- *
727
- * Missing archetypes default to `5` (no data, neutral). Each non-default
728
- * value should carry a one-line rationale in the profile's note or inline
729
- * comment citing brain evidence, family prior, or "starter hypothesis —
730
- * verify with telemetry."
731
- *
732
- * Source today: hand-curated from master plan §3.3 + §6.2 starter tables.
733
- * Source tomorrow (alpha.10+): brain `archetype_model_evidence` view.
734
- *
735
- * Anti-hallucination guardrail (master plan §2.5): when the watcher's
736
- * `--audit-fields` flag flags a profile stale (>90 days since
737
- * verifiedAgainstDocs), the archetypePerf values get re-audited
738
- * alongside capability fields. AI-trained intuition is NOT a valid
739
- * source — only docs or brain evidence.
740
- *
741
- * alpha.9.
742
- */
743
- archetypePerf?: Partial<Record<IntentArchetypeName, number>>;
744
- }
745
- declare const ALIASES: Record<string, string>;
746
- interface ProfileBrainHook {
747
- getProfile?: (canonicalId: string) => ModelProfile | undefined;
748
- resolveAlias?: (id: string) => string | undefined;
749
- }
750
- /** @internal — called by models-brain.ts at module load. */
751
- declare function _setProfileBrainHook(hook: ProfileBrainHook): void;
752
- declare function getProfile(id: string): ModelProfile;
753
- declare function tryGetProfile(id: string): ModelProfile | undefined;
754
- declare function allProfiles(): readonly ModelProfile[];
755
- /** @internal — bundled-only access for adapters that need a non-brain
756
- * fallback baseline (avoids a brain → profiles → brain re-entry). */
757
- declare function allProfilesRaw(): readonly ModelProfile[];
758
- declare function profilesByProvider(provider: Provider): readonly ModelProfile[];
759
-
760
- 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 };
@@ -538,6 +538,18 @@ interface CallResult {
538
538
  * case.
539
539
  */
540
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;
541
553
  }
542
554
  /**
543
555
  * Thrown when call() exhausts the fallback chain without success.
@@ -624,137 +636,4 @@ interface RecordInput {
624
636
  ttftMs?: number;
625
637
  }
626
638
 
627
- /**
628
- * Model profiles — executable knowledge about each provider/model.
629
- *
630
- * Unlike v1 which carried `known_failures` as prose strings, v2 makes them
631
- * executable: cliffs trigger guards, lowering describes the wire format,
632
- * recovery handlers describe what to do after specific failures.
633
- *
634
- * Each profile is the answer to "if I want to call THIS model with THIS
635
- * shape of work, what does it need from me, and what should I do when it
636
- * fails?"
637
- */
638
-
639
- type StructuredOutputCapability = 'native' | 'grammar' | 'none';
640
- type SystemPromptMode = 'inline' | 'separate' | 'as_developer' | 'unsupported';
641
- type CacheStrategy = 'cache_control' | 'cachedContent' | 'unsupported';
642
- interface CliffRule {
643
- /** What metric triggers this cliff. */
644
- metric: 'input_tokens' | 'tool_count' | 'history_turns' | 'thinking_with_short_output';
645
- /** Threshold — meaning depends on metric. */
646
- threshold: number;
647
- /** What action to take when triggered. */
648
- action: 'downgrade_quality_warning' | 'drop_to_top_relevant' | 'force_thinking_budget_zero' | 'force_terse_output' | 'escalate_target' | 'strip_tools';
649
- /**
650
- * Optional: only fire this cliff when the IR's intent.archetype matches.
651
- * Used for archetype-specific failure modes (e.g. Gemini Flash returns
652
- * empty when summarize is offered tools).
653
- */
654
- whenIntent?: IntentArchetypeName;
655
- /** Human-readable reason for digest reporting. */
656
- reason: string;
657
- }
658
- interface RecoveryRule {
659
- /** What signal triggers recovery. */
660
- signal: 'empty_response_after_tool' | 'empty_response' | 'malformed_function_call' | 'rate_limit' | 'model_not_found' | 'context_overflow';
661
- /** Action: retry with adjusted params, or escalate to next fallback. */
662
- action: 'retry_with_params' | 'escalate' | 'log_only';
663
- /** When action=retry_with_params, the param adjustments to apply. */
664
- retryParams?: Record<string, unknown>;
665
- /** Max retries with this rule. */
666
- maxRetries?: number;
667
- /** Human-readable reason for digest reporting. */
668
- reason: string;
669
- }
670
- interface LoweringSpec {
671
- /** Where the system prompt goes. */
672
- system: {
673
- mode: SystemPromptMode;
674
- field?: string;
675
- };
676
- /** Cache strategy + parameters. */
677
- cache: {
678
- strategy: CacheStrategy;
679
- /** Min tokens before caching is worth it (provider rules). */
680
- minTokens?: number;
681
- /** Discount factor on cached input (0.1 = 10% of normal price). */
682
- discount?: number;
683
- /** TTL hint in seconds. */
684
- ttlSeconds?: number;
685
- };
686
- /** Tool format identifier — see lower.ts for supported formats. */
687
- tools?: {
688
- format: 'anthropic' | 'google' | 'openai' | 'deepseek';
689
- };
690
- /** Thinking config — present iff this model has a thinking knob. */
691
- thinking?: {
692
- /** Field path on the request. */
693
- field: string;
694
- /** Default value when caller hasn't specified. */
695
- default?: number | 'auto' | 'off';
696
- };
697
- }
698
- interface ModelProfile {
699
- id: string;
700
- provider: Provider;
701
- status: 'current' | 'preview' | 'legacy';
702
- maxContextTokens: number;
703
- maxOutputTokens: number;
704
- maxTools: number;
705
- parallelToolCalls: boolean;
706
- structuredOutput: StructuredOutputCapability;
707
- systemPromptMode: SystemPromptMode;
708
- streaming: boolean;
709
- cliffs: CliffRule[];
710
- costInputPer1m: number;
711
- costOutputPer1m: number;
712
- lowering: LoweringSpec;
713
- recovery: RecoveryRule[];
714
- strengths: string[];
715
- weaknesses: string[];
716
- notes?: string;
717
- verifiedAgainstDocs?: string;
718
- /**
719
- * Hand-curated per-archetype performance score on a 0-10 scale.
720
- *
721
- * 10 = frontier on this archetype (e.g. Opus 4.7 on critique)
722
- * 8 = strong second tier (Sonnet on plan, Pro on extract)
723
- * 7 = competent (Haiku on classify, Flash on hunt)
724
- * 5 = acceptable for tolerant archetypes (Flash-Lite on classify)
725
- * 3 = degraded (Flash on critique, DeepSeek on hunt)
726
- *
727
- * Missing archetypes default to `5` (no data, neutral). Each non-default
728
- * value should carry a one-line rationale in the profile's note or inline
729
- * comment citing brain evidence, family prior, or "starter hypothesis —
730
- * verify with telemetry."
731
- *
732
- * Source today: hand-curated from master plan §3.3 + §6.2 starter tables.
733
- * Source tomorrow (alpha.10+): brain `archetype_model_evidence` view.
734
- *
735
- * Anti-hallucination guardrail (master plan §2.5): when the watcher's
736
- * `--audit-fields` flag flags a profile stale (>90 days since
737
- * verifiedAgainstDocs), the archetypePerf values get re-audited
738
- * alongside capability fields. AI-trained intuition is NOT a valid
739
- * source — only docs or brain evidence.
740
- *
741
- * alpha.9.
742
- */
743
- archetypePerf?: Partial<Record<IntentArchetypeName, number>>;
744
- }
745
- declare const ALIASES: Record<string, string>;
746
- interface ProfileBrainHook {
747
- getProfile?: (canonicalId: string) => ModelProfile | undefined;
748
- resolveAlias?: (id: string) => string | undefined;
749
- }
750
- /** @internal — called by models-brain.ts at module load. */
751
- declare function _setProfileBrainHook(hook: ProfileBrainHook): void;
752
- declare function getProfile(id: string): ModelProfile;
753
- declare function tryGetProfile(id: string): ModelProfile | undefined;
754
- declare function allProfiles(): readonly ModelProfile[];
755
- /** @internal — bundled-only access for adapters that need a non-brain
756
- * fallback baseline (avoids a brain → profiles → brain re-entry). */
757
- declare function allProfilesRaw(): readonly ModelProfile[];
758
- declare function profilesByProvider(provider: Provider): readonly ModelProfile[];
759
-
760
- 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 };
@@ -1,2 +1,137 @@
1
- export { g as ALIASES, h as CacheStrategy, k as CliffRule, L as LoweringSpec, M as ModelProfile, q as RecoveryRule, S as StructuredOutputCapability, r as SystemPromptMode, _ as _setProfileBrainHook, t as allProfiles, x as allProfilesRaw, u as getProfile, v as profilesByProvider, w as tryGetProfile } from './profiles-BoLYdl7F.mjs';
2
- import './dialect.mjs';
1
+ import { f as Provider } from './ir-C3P4gDt0.mjs';
2
+ import { IntentArchetypeName } from './dialect.mjs';
3
+
4
+ /**
5
+ * Model profiles — executable knowledge about each provider/model.
6
+ *
7
+ * Unlike v1 which carried `known_failures` as prose strings, v2 makes them
8
+ * executable: cliffs trigger guards, lowering describes the wire format,
9
+ * recovery handlers describe what to do after specific failures.
10
+ *
11
+ * Each profile is the answer to "if I want to call THIS model with THIS
12
+ * shape of work, what does it need from me, and what should I do when it
13
+ * fails?"
14
+ */
15
+
16
+ type StructuredOutputCapability = 'native' | 'grammar' | 'none';
17
+ type SystemPromptMode = 'inline' | 'separate' | 'as_developer' | 'unsupported';
18
+ type CacheStrategy = 'cache_control' | 'cachedContent' | 'unsupported';
19
+ interface CliffRule {
20
+ /** What metric triggers this cliff. */
21
+ metric: 'input_tokens' | 'tool_count' | 'history_turns' | 'thinking_with_short_output';
22
+ /** Threshold — meaning depends on metric. */
23
+ threshold: number;
24
+ /** What action to take when triggered. */
25
+ action: 'downgrade_quality_warning' | 'drop_to_top_relevant' | 'force_thinking_budget_zero' | 'force_terse_output' | 'escalate_target' | 'strip_tools';
26
+ /**
27
+ * Optional: only fire this cliff when the IR's intent.archetype matches.
28
+ * Used for archetype-specific failure modes (e.g. Gemini Flash returns
29
+ * empty when summarize is offered tools).
30
+ */
31
+ whenIntent?: IntentArchetypeName;
32
+ /** Human-readable reason for digest reporting. */
33
+ reason: string;
34
+ }
35
+ interface RecoveryRule {
36
+ /** What signal triggers recovery. */
37
+ signal: 'empty_response_after_tool' | 'empty_response' | 'malformed_function_call' | 'rate_limit' | 'model_not_found' | 'context_overflow';
38
+ /** Action: retry with adjusted params, or escalate to next fallback. */
39
+ action: 'retry_with_params' | 'escalate' | 'log_only';
40
+ /** When action=retry_with_params, the param adjustments to apply. */
41
+ retryParams?: Record<string, unknown>;
42
+ /** Max retries with this rule. */
43
+ maxRetries?: number;
44
+ /** Human-readable reason for digest reporting. */
45
+ reason: string;
46
+ }
47
+ interface LoweringSpec {
48
+ /** Where the system prompt goes. */
49
+ system: {
50
+ mode: SystemPromptMode;
51
+ field?: string;
52
+ };
53
+ /** Cache strategy + parameters. */
54
+ cache: {
55
+ strategy: CacheStrategy;
56
+ /** Min tokens before caching is worth it (provider rules). */
57
+ minTokens?: number;
58
+ /** Discount factor on cached input (0.1 = 10% of normal price). */
59
+ discount?: number;
60
+ /** TTL hint in seconds. */
61
+ ttlSeconds?: number;
62
+ };
63
+ /** Tool format identifier — see lower.ts for supported formats. */
64
+ tools?: {
65
+ format: 'anthropic' | 'google' | 'openai' | 'deepseek';
66
+ };
67
+ /** Thinking config — present iff this model has a thinking knob. */
68
+ thinking?: {
69
+ /** Field path on the request. */
70
+ field: string;
71
+ /** Default value when caller hasn't specified. */
72
+ default?: number | 'auto' | 'off';
73
+ };
74
+ }
75
+ interface ModelProfile {
76
+ id: string;
77
+ provider: Provider;
78
+ status: 'current' | 'preview' | 'legacy';
79
+ maxContextTokens: number;
80
+ maxOutputTokens: number;
81
+ maxTools: number;
82
+ parallelToolCalls: boolean;
83
+ structuredOutput: StructuredOutputCapability;
84
+ systemPromptMode: SystemPromptMode;
85
+ streaming: boolean;
86
+ cliffs: CliffRule[];
87
+ costInputPer1m: number;
88
+ costOutputPer1m: number;
89
+ lowering: LoweringSpec;
90
+ recovery: RecoveryRule[];
91
+ strengths: string[];
92
+ weaknesses: string[];
93
+ notes?: string;
94
+ verifiedAgainstDocs?: string;
95
+ /**
96
+ * Hand-curated per-archetype performance score on a 0-10 scale.
97
+ *
98
+ * 10 = frontier on this archetype (e.g. Opus 4.7 on critique)
99
+ * 8 = strong second tier (Sonnet on plan, Pro on extract)
100
+ * 7 = competent (Haiku on classify, Flash on hunt)
101
+ * 5 = acceptable for tolerant archetypes (Flash-Lite on classify)
102
+ * 3 = degraded (Flash on critique, DeepSeek on hunt)
103
+ *
104
+ * Missing archetypes default to `5` (no data, neutral). Each non-default
105
+ * value should carry a one-line rationale in the profile's note or inline
106
+ * comment citing brain evidence, family prior, or "starter hypothesis —
107
+ * verify with telemetry."
108
+ *
109
+ * Source today: hand-curated from master plan §3.3 + §6.2 starter tables.
110
+ * Source tomorrow (alpha.10+): brain `archetype_model_evidence` view.
111
+ *
112
+ * Anti-hallucination guardrail (master plan §2.5): when the watcher's
113
+ * `--audit-fields` flag flags a profile stale (>90 days since
114
+ * verifiedAgainstDocs), the archetypePerf values get re-audited
115
+ * alongside capability fields. AI-trained intuition is NOT a valid
116
+ * source — only docs or brain evidence.
117
+ *
118
+ * alpha.9.
119
+ */
120
+ archetypePerf?: Partial<Record<IntentArchetypeName, number>>;
121
+ }
122
+ declare const ALIASES: Record<string, string>;
123
+ interface ProfileBrainHook {
124
+ getProfile?: (canonicalId: string) => ModelProfile | undefined;
125
+ resolveAlias?: (id: string) => string | undefined;
126
+ }
127
+ /** @internal — called by models-brain.ts at module load. */
128
+ declare function _setProfileBrainHook(hook: ProfileBrainHook): void;
129
+ declare function getProfile(id: string): ModelProfile;
130
+ declare function tryGetProfile(id: string): ModelProfile | undefined;
131
+ declare function allProfiles(): readonly ModelProfile[];
132
+ /** @internal — bundled-only access for adapters that need a non-brain
133
+ * fallback baseline (avoids a brain → profiles → brain re-entry). */
134
+ declare function allProfilesRaw(): readonly ModelProfile[];
135
+ declare function profilesByProvider(provider: Provider): readonly ModelProfile[];
136
+
137
+ export { ALIASES, type CacheStrategy, type CliffRule, type LoweringSpec, type ModelProfile, type RecoveryRule, type StructuredOutputCapability, type SystemPromptMode, _setProfileBrainHook, allProfiles, allProfilesRaw, getProfile, profilesByProvider, tryGetProfile };