@warmdrift/kgauto-compiler 2.0.0-alpha.10 → 2.0.0-alpha.12

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.js CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  countTokens: () => countTokens,
39
39
  execute: () => execute,
40
40
  getAllStarterChains: () => getAllStarterChains,
41
+ getArchetypePerfScore: () => getArchetypePerfScore,
41
42
  getDefaultFallbackChain: () => getDefaultFallbackChain,
42
43
  getProfile: () => getProfile,
43
44
  getReachabilityDiagnostic: () => getReachabilityDiagnostic,
@@ -47,9 +48,16 @@ __export(index_exports, {
47
48
  isModelReachable: () => isModelReachable,
48
49
  isProviderReachable: () => isProviderReachable,
49
50
  learningKey: () => learningKey,
51
+ loadAliasesFromBrain: () => loadAliasesFromBrain,
52
+ loadArchetypePerfFromBrain: () => loadArchetypePerfFromBrain,
53
+ loadChainsFromBrain: () => loadChainsFromBrain,
54
+ loadModelsFromBrain: () => loadModelsFromBrain,
55
+ loadPricingFromBrain: () => loadPricingFromBrain,
56
+ profileToRow: () => profileToRow,
50
57
  profilesByProvider: () => profilesByProvider,
51
58
  record: () => record,
52
59
  resetTokenizer: () => resetTokenizer,
60
+ resolvePricingAt: () => resolvePricingAt,
53
61
  resolveProviderKey: () => resolveProviderKey,
54
62
  runAdvisor: () => runAdvisor,
55
63
  setTokenizer: () => setTokenizer,
@@ -1439,14 +1447,20 @@ var ALIASES = {
1439
1447
  // Legacy kgauto typo — actual API alias is dash-form (alpha.1 had dot).
1440
1448
  "claude-haiku-4.5": "claude-haiku-4-5"
1441
1449
  };
1450
+ var brainHook = {};
1451
+ function _setProfileBrainHook(hook) {
1452
+ brainHook = hook;
1453
+ }
1442
1454
  function canonicalId(id) {
1443
- return ALIASES[id] ?? id;
1455
+ return brainHook.resolveAlias?.(id) ?? ALIASES[id] ?? id;
1444
1456
  }
1445
1457
  var PROFILE_INDEX = new Map(
1446
1458
  PROFILES_RAW.map((p) => [p.id, p])
1447
1459
  );
1448
1460
  function getProfile(id) {
1449
1461
  const canonical = canonicalId(id);
1462
+ const fromBrain = brainHook.getProfile?.(canonical);
1463
+ if (fromBrain) return fromBrain;
1450
1464
  const p = PROFILE_INDEX.get(canonical);
1451
1465
  if (!p) {
1452
1466
  const known = [...PROFILE_INDEX.keys(), ...Object.keys(ALIASES)].join(", ");
@@ -1455,11 +1469,15 @@ function getProfile(id) {
1455
1469
  return p;
1456
1470
  }
1457
1471
  function tryGetProfile(id) {
1458
- return PROFILE_INDEX.get(canonicalId(id));
1472
+ const canonical = canonicalId(id);
1473
+ return brainHook.getProfile?.(canonical) ?? PROFILE_INDEX.get(canonical);
1459
1474
  }
1460
1475
  function allProfiles() {
1461
1476
  return PROFILES_RAW;
1462
1477
  }
1478
+ function allProfilesRaw() {
1479
+ return PROFILES_RAW;
1480
+ }
1463
1481
  function profilesByProvider(provider) {
1464
1482
  return PROFILES_RAW.filter((p) => p.provider === provider);
1465
1483
  }
@@ -1683,14 +1701,170 @@ function validateFinalFit(ir, profile, tokens) {
1683
1701
  }
1684
1702
  }
1685
1703
 
1704
+ // src/brain-query.ts
1705
+ var FRESH_SNAPSHOT = {
1706
+ data: null,
1707
+ expiresAt: 0,
1708
+ refreshing: false,
1709
+ warned: false
1710
+ };
1711
+ var snapshot = { ...FRESH_SNAPSHOT };
1712
+ var runtime;
1713
+ function configureBrainQuery(rt) {
1714
+ runtime = rt;
1715
+ snapshot = { ...FRESH_SNAPSHOT };
1716
+ }
1717
+ function createBrainQueryCache(opts) {
1718
+ return () => {
1719
+ const rt = runtime;
1720
+ if (!rt || !rt.enabledTables.has(opts.table)) {
1721
+ return opts.bundledFallback();
1722
+ }
1723
+ const now = Date.now();
1724
+ const stale = snapshot.expiresAt <= now;
1725
+ if (stale && !snapshot.refreshing) {
1726
+ snapshot.refreshing = true;
1727
+ void asyncRefresh(rt);
1728
+ }
1729
+ if (snapshot.data) {
1730
+ const rows = snapshot.data[opts.table];
1731
+ if (Array.isArray(rows) && rows.length > 0) {
1732
+ try {
1733
+ return opts.mapRows(rows);
1734
+ } catch {
1735
+ return opts.bundledFallback();
1736
+ }
1737
+ }
1738
+ }
1739
+ return opts.bundledFallback();
1740
+ };
1741
+ }
1742
+ var pendingRefresh;
1743
+ async function asyncRefresh(rt) {
1744
+ const promise = doRefresh(rt);
1745
+ pendingRefresh = promise;
1746
+ try {
1747
+ await promise;
1748
+ } finally {
1749
+ if (pendingRefresh === promise) pendingRefresh = void 0;
1750
+ }
1751
+ }
1752
+ var DEFAULT_CONFIG_URL = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/config";
1753
+ async function doRefresh(rt) {
1754
+ const url = rt.configEndpoint ?? DEFAULT_CONFIG_URL;
1755
+ try {
1756
+ const res = await rt.fetchImpl(url, { method: "GET" });
1757
+ if (!res.ok) {
1758
+ throw new Error(`brain-query ${res.status}: ${res.statusText}`);
1759
+ }
1760
+ const body = await res.json();
1761
+ if (runtime !== rt) return;
1762
+ snapshot = {
1763
+ data: body,
1764
+ expiresAt: Date.now() + rt.ttlMs,
1765
+ refreshing: false,
1766
+ warned: snapshot.warned
1767
+ };
1768
+ } catch (err) {
1769
+ if (runtime !== rt) return;
1770
+ snapshot.refreshing = false;
1771
+ snapshot.expiresAt = Date.now() + rt.ttlMs;
1772
+ if (!snapshot.warned) {
1773
+ snapshot.warned = true;
1774
+ (rt.onError ?? defaultOnError)(err);
1775
+ }
1776
+ }
1777
+ }
1778
+ function defaultOnError(err) {
1779
+ console.warn("[kgauto] brain-query failed (using bundled fallback):", err);
1780
+ }
1781
+
1782
+ // src/pricing-brain.ts
1783
+ function isPricingRow(x) {
1784
+ if (!x || typeof x !== "object") return false;
1785
+ const r = x;
1786
+ return typeof r.model_id === "string" && typeof r.cost_input_per_1m === "number" && typeof r.cost_output_per_1m === "number" && typeof r.valid_from === "string";
1787
+ }
1788
+ function mapRowsToPricing(rows) {
1789
+ const out = [];
1790
+ for (const row of rows) {
1791
+ if (!isPricingRow(row)) continue;
1792
+ out.push({
1793
+ modelId: row.model_id,
1794
+ costInputPer1m: row.cost_input_per_1m,
1795
+ costOutputPer1m: row.cost_output_per_1m,
1796
+ cacheInputPer1m: row.cache_input_per_1m ?? void 0,
1797
+ cacheCreationPer1m: row.cache_creation_per_1m ?? void 0,
1798
+ validFrom: Date.parse(row.valid_from),
1799
+ validUntil: row.valid_until == null ? void 0 : Date.parse(row.valid_until),
1800
+ source: row.source ?? void 0
1801
+ });
1802
+ }
1803
+ return out;
1804
+ }
1805
+ function bundledPricing() {
1806
+ const out = [];
1807
+ for (const profile of allProfiles()) {
1808
+ out.push({
1809
+ modelId: profile.id,
1810
+ costInputPer1m: profile.costInputPer1m,
1811
+ costOutputPer1m: profile.costOutputPer1m,
1812
+ cacheInputPer1m: profile.lowering.cache.discount !== void 0 && profile.lowering.cache.discount > 0 ? profile.costInputPer1m * profile.lowering.cache.discount : void 0,
1813
+ validFrom: 0,
1814
+ validUntil: void 0,
1815
+ source: "profile_seed"
1816
+ });
1817
+ }
1818
+ return out;
1819
+ }
1820
+ var loadPricingFromBrain = createBrainQueryCache({
1821
+ table: "kgauto_pricing",
1822
+ mapRows: mapRowsToPricing,
1823
+ bundledFallback: bundledPricing
1824
+ });
1825
+ function resolvePricingAt(modelId, at = /* @__PURE__ */ new Date()) {
1826
+ const ts = at.getTime();
1827
+ const all = loadPricingFromBrain();
1828
+ let best;
1829
+ for (const row of all) {
1830
+ if (row.modelId !== modelId) continue;
1831
+ if (row.validFrom > ts) continue;
1832
+ if (row.validUntil !== void 0 && row.validUntil <= ts) continue;
1833
+ if (!best || row.validFrom > best.validFrom) best = row;
1834
+ }
1835
+ return best;
1836
+ }
1837
+
1686
1838
  // src/brain.ts
1687
1839
  var activeConfig;
1688
1840
  function configureBrain(config) {
1689
1841
  const endpoint = config.endpoint.replace(/\/outcomes\/?$/, "");
1690
1842
  activeConfig = { ...config, endpoint };
1843
+ const bq = config.brainQuery ?? {};
1844
+ const enabledTables = /* @__PURE__ */ new Set();
1845
+ if (bq.chains !== false) enabledTables.add("kgauto_chains");
1846
+ if (bq.perf !== false) enabledTables.add("kgauto_archetype_perf");
1847
+ if (bq.pricing !== false) enabledTables.add("kgauto_pricing");
1848
+ if (bq.models !== false) {
1849
+ enabledTables.add("kgauto_models");
1850
+ enabledTables.add("kgauto_aliases");
1851
+ }
1852
+ if (enabledTables.size === 0) {
1853
+ configureBrainQuery(void 0);
1854
+ return;
1855
+ }
1856
+ configureBrainQuery({
1857
+ endpoint,
1858
+ configEndpoint: bq.configEndpoint,
1859
+ ttlMs: bq.cacheTtlMs ?? 3e5,
1860
+ fetchImpl: config.fetchImpl ?? fetch,
1861
+ enabledTables,
1862
+ onError: config.onError
1863
+ });
1691
1864
  }
1692
1865
  function clearBrain() {
1693
1866
  activeConfig = void 0;
1867
+ configureBrainQuery(void 0);
1694
1868
  }
1695
1869
  var compileRegistry = /* @__PURE__ */ new Map();
1696
1870
  var REGISTRY_MAX_ENTRIES = 1e4;
@@ -1755,7 +1929,7 @@ async function record(input) {
1755
1929
  throw new Error(`brain ${res.status}: ${text}`);
1756
1930
  }
1757
1931
  } catch (err) {
1758
- (config.onError ?? defaultOnError)(err);
1932
+ (config.onError ?? defaultOnError2)(err);
1759
1933
  }
1760
1934
  };
1761
1935
  if (config.sync) {
@@ -1764,7 +1938,7 @@ async function record(input) {
1764
1938
  void send();
1765
1939
  }
1766
1940
  }
1767
- function defaultOnError(err) {
1941
+ function defaultOnError2(err) {
1768
1942
  console.warn("[kgauto] brain record failed:", err);
1769
1943
  }
1770
1944
  function buildPayload(input, reg) {
@@ -1808,6 +1982,12 @@ function buildPayload(input, reg) {
1808
1982
  }
1809
1983
  function computeCostUsd(modelId, tokensIn, tokensOut) {
1810
1984
  if (tokensIn === 0 && tokensOut === 0) return void 0;
1985
+ const brainRow = resolvePricingAt(modelId);
1986
+ if (brainRow && (brainRow.costInputPer1m > 0 || brainRow.costOutputPer1m > 0)) {
1987
+ const inUsd2 = tokensIn / 1e6 * brainRow.costInputPer1m;
1988
+ const outUsd2 = tokensOut / 1e6 * brainRow.costOutputPer1m;
1989
+ return Math.round((inUsd2 + outUsd2) * 1e6) / 1e6;
1990
+ }
1811
1991
  const profile = tryGetProfile(modelId);
1812
1992
  if (!profile) return void 0;
1813
1993
  const inUsd = tokensIn / 1e6 * profile.costInputPer1m;
@@ -2390,6 +2570,37 @@ function clamp(n) {
2390
2570
  return Math.max(0, Math.min(1, n));
2391
2571
  }
2392
2572
 
2573
+ // src/chains-brain.ts
2574
+ function isChainsRow(x) {
2575
+ if (!x || typeof x !== "object") return false;
2576
+ const r = x;
2577
+ return typeof r.archetype === "string" && typeof r.tier === "number" && typeof r.model_id === "string";
2578
+ }
2579
+ function mapRowsToChains(rows) {
2580
+ const grouped = /* @__PURE__ */ new Map();
2581
+ for (const row of rows) {
2582
+ if (!isChainsRow(row)) continue;
2583
+ const list = grouped.get(row.archetype) ?? [];
2584
+ list.push(row);
2585
+ grouped.set(row.archetype, list);
2586
+ }
2587
+ const out = {};
2588
+ for (const [archetype, group] of grouped.entries()) {
2589
+ group.sort((a, b) => a.tier - b.tier);
2590
+ out[archetype] = group.map((r) => r.model_id);
2591
+ }
2592
+ const bundled = getAllStarterChains();
2593
+ for (const archetype of Object.keys(bundled)) {
2594
+ if (!out[archetype]) out[archetype] = bundled[archetype];
2595
+ }
2596
+ return out;
2597
+ }
2598
+ var loadChainsFromBrain = createBrainQueryCache({
2599
+ table: "kgauto_chains",
2600
+ mapRows: mapRowsToChains,
2601
+ bundledFallback: getAllStarterChains
2602
+ });
2603
+
2393
2604
  // src/fallback.ts
2394
2605
  var STARTER_CHAINS = {
2395
2606
  // Reasoning floor — never degrade. Walk UP on 429 to Opus → cross-provider.
@@ -2467,10 +2678,11 @@ function getDefaultFallbackChain(opts) {
2467
2678
  `getDefaultFallbackChain: maxDepth must be >= 1, got ${maxDepth}`
2468
2679
  );
2469
2680
  }
2470
- const starter = STARTER_CHAINS[archetype];
2681
+ const allChains = loadChainsFromBrain();
2682
+ const starter = allChains[archetype];
2471
2683
  if (!starter) {
2472
2684
  throw new Error(
2473
- `getDefaultFallbackChain: unknown archetype "${archetype}". Known: ${Object.keys(STARTER_CHAINS).join(", ")}`
2685
+ `getDefaultFallbackChain: unknown archetype "${archetype}". Known: ${Object.keys(allChains).join(", ")}`
2474
2686
  );
2475
2687
  }
2476
2688
  let chain;
@@ -2514,6 +2726,157 @@ function getAllStarterChains() {
2514
2726
  return out;
2515
2727
  }
2516
2728
 
2729
+ // src/archetype-perf-brain.ts
2730
+ function isPerfRow(x) {
2731
+ if (!x || typeof x !== "object") return false;
2732
+ const r = x;
2733
+ return typeof r.model_id === "string" && typeof r.archetype === "string" && typeof r.perf_score === "number";
2734
+ }
2735
+ function mapRowsToPerfMap(rows) {
2736
+ const out = /* @__PURE__ */ new Map();
2737
+ for (const row of rows) {
2738
+ if (!isPerfRow(row)) continue;
2739
+ const existing = out.get(row.model_id) ?? {};
2740
+ existing[row.archetype] = row.perf_score;
2741
+ out.set(row.model_id, existing);
2742
+ }
2743
+ return out;
2744
+ }
2745
+ function bundledArchetypePerf() {
2746
+ const out = /* @__PURE__ */ new Map();
2747
+ for (const profile of allProfiles()) {
2748
+ if (profile.archetypePerf) out.set(profile.id, profile.archetypePerf);
2749
+ }
2750
+ return out;
2751
+ }
2752
+ var loadArchetypePerfFromBrain = createBrainQueryCache({
2753
+ table: "kgauto_archetype_perf",
2754
+ mapRows: mapRowsToPerfMap,
2755
+ bundledFallback: bundledArchetypePerf
2756
+ });
2757
+ function getArchetypePerfScore(modelId, archetype) {
2758
+ return loadArchetypePerfFromBrain().get(modelId)?.[archetype] ?? 5;
2759
+ }
2760
+
2761
+ // src/models-brain.ts
2762
+ function isModelRow(x) {
2763
+ if (!x || typeof x !== "object") return false;
2764
+ const r = x;
2765
+ return typeof r.model_id === "string" && typeof r.provider === "string";
2766
+ }
2767
+ function isAliasRow(x) {
2768
+ if (!x || typeof x !== "object") return false;
2769
+ const r = x;
2770
+ return typeof r.alias_id === "string" && typeof r.canonical_id === "string";
2771
+ }
2772
+ function rowToProfile(row) {
2773
+ try {
2774
+ if (row.cliffs !== void 0 && row.cliffs !== null && !Array.isArray(row.cliffs)) {
2775
+ return null;
2776
+ }
2777
+ if (row.recovery !== void 0 && row.recovery !== null && !Array.isArray(row.recovery)) {
2778
+ return null;
2779
+ }
2780
+ if (row.lowering !== void 0 && row.lowering !== null && (typeof row.lowering !== "object" || Array.isArray(row.lowering))) {
2781
+ return null;
2782
+ }
2783
+ return {
2784
+ id: row.model_id,
2785
+ provider: row.provider,
2786
+ status: row.status ?? "current",
2787
+ maxContextTokens: row.max_context_tokens ?? 0,
2788
+ maxOutputTokens: row.max_output_tokens ?? 0,
2789
+ maxTools: row.max_tools ?? 0,
2790
+ parallelToolCalls: row.parallel_tool_calls ?? false,
2791
+ structuredOutput: row.structured_output ?? "none",
2792
+ systemPromptMode: row.system_prompt_mode ?? "inline",
2793
+ streaming: row.streaming ?? true,
2794
+ cliffs: row.cliffs ?? [],
2795
+ costInputPer1m: row.cost_input_per_1m ?? 0,
2796
+ costOutputPer1m: row.cost_output_per_1m ?? 0,
2797
+ lowering: row.lowering ?? { system: { mode: "inline" }, cache: { strategy: "unsupported" } },
2798
+ recovery: row.recovery ?? [],
2799
+ strengths: row.strengths ?? [],
2800
+ weaknesses: row.weaknesses ?? [],
2801
+ notes: row.notes ?? void 0,
2802
+ verifiedAgainstDocs: row.verified_against_docs ?? void 0,
2803
+ archetypePerf: row.archetype_perf ?? void 0
2804
+ };
2805
+ } catch {
2806
+ return null;
2807
+ }
2808
+ }
2809
+ function profileToRow(profile, opts = {}) {
2810
+ const row = {
2811
+ model_id: profile.id,
2812
+ provider: profile.provider,
2813
+ status: profile.status,
2814
+ max_context_tokens: profile.maxContextTokens,
2815
+ max_output_tokens: profile.maxOutputTokens,
2816
+ max_tools: profile.maxTools,
2817
+ parallel_tool_calls: profile.parallelToolCalls,
2818
+ structured_output: profile.structuredOutput,
2819
+ system_prompt_mode: profile.systemPromptMode,
2820
+ streaming: profile.streaming,
2821
+ cliffs: profile.cliffs,
2822
+ cost_input_per_1m: profile.costInputPer1m,
2823
+ cost_output_per_1m: profile.costOutputPer1m,
2824
+ lowering: profile.lowering,
2825
+ recovery: profile.recovery,
2826
+ strengths: profile.strengths,
2827
+ weaknesses: profile.weaknesses,
2828
+ notes: profile.notes ?? null,
2829
+ archetype_perf: profile.archetypePerf ?? null,
2830
+ active: opts.active ?? true
2831
+ };
2832
+ if (opts.verifiedAgainstDocs !== void 0) {
2833
+ row.verified_against_docs = opts.verifiedAgainstDocs;
2834
+ } else if (profile.verifiedAgainstDocs !== void 0) {
2835
+ const v = profile.verifiedAgainstDocs;
2836
+ row.verified_against_docs = /^\d{4}-\d{2}-\d{2}/.test(v) ? v : null;
2837
+ }
2838
+ if (opts.versionAdded !== void 0) row.version_added = opts.versionAdded;
2839
+ if (opts.versionRemoved !== void 0) row.version_removed = opts.versionRemoved;
2840
+ return row;
2841
+ }
2842
+ function mapRowsToModels(rows) {
2843
+ const out = /* @__PURE__ */ new Map();
2844
+ for (const row of rows) {
2845
+ if (!isModelRow(row)) continue;
2846
+ const profile = rowToProfile(row);
2847
+ if (profile) out.set(profile.id, profile);
2848
+ }
2849
+ return out;
2850
+ }
2851
+ function mapRowsToAliases(rows) {
2852
+ const out = {};
2853
+ for (const row of rows) {
2854
+ if (!isAliasRow(row)) continue;
2855
+ out[row.alias_id] = row.canonical_id;
2856
+ }
2857
+ return out;
2858
+ }
2859
+ function bundledModels() {
2860
+ return new Map(allProfilesRaw().map((p) => [p.id, p]));
2861
+ }
2862
+ function bundledAliases() {
2863
+ return { ...ALIASES };
2864
+ }
2865
+ var loadModelsFromBrain = createBrainQueryCache({
2866
+ table: "kgauto_models",
2867
+ mapRows: mapRowsToModels,
2868
+ bundledFallback: bundledModels
2869
+ });
2870
+ var loadAliasesFromBrain = createBrainQueryCache({
2871
+ table: "kgauto_aliases",
2872
+ mapRows: mapRowsToAliases,
2873
+ bundledFallback: bundledAliases
2874
+ });
2875
+ _setProfileBrainHook({
2876
+ getProfile: (canonical) => loadModelsFromBrain().get(canonical),
2877
+ resolveAlias: (id) => loadAliasesFromBrain()[id]
2878
+ });
2879
+
2517
2880
  // src/index.ts
2518
2881
  function compile2(ir, opts) {
2519
2882
  const result = compile(ir, opts);
@@ -2540,6 +2903,7 @@ function compile2(ir, opts) {
2540
2903
  countTokens,
2541
2904
  execute,
2542
2905
  getAllStarterChains,
2906
+ getArchetypePerfScore,
2543
2907
  getDefaultFallbackChain,
2544
2908
  getProfile,
2545
2909
  getReachabilityDiagnostic,
@@ -2549,9 +2913,16 @@ function compile2(ir, opts) {
2549
2913
  isModelReachable,
2550
2914
  isProviderReachable,
2551
2915
  learningKey,
2916
+ loadAliasesFromBrain,
2917
+ loadArchetypePerfFromBrain,
2918
+ loadChainsFromBrain,
2919
+ loadModelsFromBrain,
2920
+ loadPricingFromBrain,
2921
+ profileToRow,
2552
2922
  profilesByProvider,
2553
2923
  record,
2554
2924
  resetTokenizer,
2925
+ resolvePricingAt,
2555
2926
  resolveProviderKey,
2556
2927
  runAdvisor,
2557
2928
  setTokenizer,