@warmdrift/kgauto-compiler 2.0.0-alpha.21 → 2.0.0-alpha.22
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.d.mts +35 -2
- package/dist/index.d.ts +35 -2
- package/dist/index.js +246 -137
- package/dist/index.mjs +245 -137
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -326,14 +326,47 @@ declare function countTokens(text: string): number;
|
|
|
326
326
|
|
|
327
327
|
/** Subset of CompileResult fields the advisor needs. */
|
|
328
328
|
type AdvisorContext = Pick<CompileResult, 'target' | 'provider' | 'tokensIn' | 'diagnostics'>;
|
|
329
|
+
/**
|
|
330
|
+
* Optional Phase 2 (alpha.22) context — fallback chain + a profile resolver
|
|
331
|
+
* for cross-model comparison. Three new rules
|
|
332
|
+
* (`cost-mismatched-archetype`, `model-stale-evidence`, `tier-down`) consume
|
|
333
|
+
* this to surface measurement-substrate signals (alpha.20 clean-attribution +
|
|
334
|
+
* alpha.21 grounding labels) as actionable consumer guidance.
|
|
335
|
+
*
|
|
336
|
+
* When `fallbackChain` is empty, rules 1 + 3 stay silent (nothing to
|
|
337
|
+
* compare against). When `profileResolver` is omitted, the rules degrade
|
|
338
|
+
* gracefully — they can still inspect the chosen profile but not chain
|
|
339
|
+
* alternatives. Rule 2 (`model-stale-evidence`) is independent of chain
|
|
340
|
+
* shape and works on the chosen model alone.
|
|
341
|
+
*/
|
|
342
|
+
interface RunAdvisorPhase2Context {
|
|
343
|
+
fallbackChain: string[];
|
|
344
|
+
profileResolver?: (id: string) => ModelProfile | undefined;
|
|
345
|
+
}
|
|
329
346
|
/**
|
|
330
347
|
* Run all phased rules and return collected advisories. Order is fixed so
|
|
331
348
|
* output is stable across runs. The `policy` argument is alpha.9 — the
|
|
332
349
|
* `single-model-array` rule needs to know whether the consumer explicitly
|
|
333
350
|
* declared `posture: 'locked'` (in which case single-model is intentional
|
|
334
351
|
* and shouldn't warn).
|
|
352
|
+
*
|
|
353
|
+
* `phase2` is alpha.22 — gives the advisor access to the fallback chain +
|
|
354
|
+
* a profile resolver so the three new compile-time recommendation rules
|
|
355
|
+
* (`cost-mismatched-archetype`, `model-stale-evidence`, `tier-down`) can
|
|
356
|
+
* compare the chosen model against in-chain alternatives. Optional for
|
|
357
|
+
* backward compatibility with consumers calling `runAdvisor()` directly.
|
|
358
|
+
*/
|
|
359
|
+
declare function runAdvisor(ir: PromptIR, result: AdvisorContext, profile: ModelProfile, policy?: CompilePolicy, phase2?: RunAdvisorPhase2Context): BestPracticeAdvisory[];
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* alpha.22 — sync introspection: is brain-query mode active for a given
|
|
363
|
+
* table? Used by the advisor (`model-stale-evidence` rule) to decide
|
|
364
|
+
* whether a `judgment`-grounded chosen model is a measurement gap worth
|
|
365
|
+
* surfacing. Returns false on cold start, when configureBrain() was never
|
|
366
|
+
* called, or when the consumer explicitly opted the table out via
|
|
367
|
+
* `BrainConfig.brainQuery.<table> = false`.
|
|
335
368
|
*/
|
|
336
|
-
declare function
|
|
369
|
+
declare function isBrainQueryActiveFor(table: string): boolean;
|
|
337
370
|
|
|
338
371
|
/**
|
|
339
372
|
* env.ts — provider env-key resolution + reachability predicates.
|
|
@@ -870,4 +903,4 @@ declare const loadAliasesFromBrain: () => Record<string, string>;
|
|
|
870
903
|
*/
|
|
871
904
|
declare function compile(ir: PromptIR, opts?: CompileOptions): CompileResult;
|
|
872
905
|
|
|
873
|
-
export { ApiKeys, type AppOracle, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetDefaultFallbackChainOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type ModelBrainRow, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type SupportedProvider, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
|
|
906
|
+
export { ApiKeys, type AppOracle, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetDefaultFallbackChainOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type ModelBrainRow, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, type SupportedProvider, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
|
package/dist/index.d.ts
CHANGED
|
@@ -326,14 +326,47 @@ declare function countTokens(text: string): number;
|
|
|
326
326
|
|
|
327
327
|
/** Subset of CompileResult fields the advisor needs. */
|
|
328
328
|
type AdvisorContext = Pick<CompileResult, 'target' | 'provider' | 'tokensIn' | 'diagnostics'>;
|
|
329
|
+
/**
|
|
330
|
+
* Optional Phase 2 (alpha.22) context — fallback chain + a profile resolver
|
|
331
|
+
* for cross-model comparison. Three new rules
|
|
332
|
+
* (`cost-mismatched-archetype`, `model-stale-evidence`, `tier-down`) consume
|
|
333
|
+
* this to surface measurement-substrate signals (alpha.20 clean-attribution +
|
|
334
|
+
* alpha.21 grounding labels) as actionable consumer guidance.
|
|
335
|
+
*
|
|
336
|
+
* When `fallbackChain` is empty, rules 1 + 3 stay silent (nothing to
|
|
337
|
+
* compare against). When `profileResolver` is omitted, the rules degrade
|
|
338
|
+
* gracefully — they can still inspect the chosen profile but not chain
|
|
339
|
+
* alternatives. Rule 2 (`model-stale-evidence`) is independent of chain
|
|
340
|
+
* shape and works on the chosen model alone.
|
|
341
|
+
*/
|
|
342
|
+
interface RunAdvisorPhase2Context {
|
|
343
|
+
fallbackChain: string[];
|
|
344
|
+
profileResolver?: (id: string) => ModelProfile | undefined;
|
|
345
|
+
}
|
|
329
346
|
/**
|
|
330
347
|
* Run all phased rules and return collected advisories. Order is fixed so
|
|
331
348
|
* output is stable across runs. The `policy` argument is alpha.9 — the
|
|
332
349
|
* `single-model-array` rule needs to know whether the consumer explicitly
|
|
333
350
|
* declared `posture: 'locked'` (in which case single-model is intentional
|
|
334
351
|
* and shouldn't warn).
|
|
352
|
+
*
|
|
353
|
+
* `phase2` is alpha.22 — gives the advisor access to the fallback chain +
|
|
354
|
+
* a profile resolver so the three new compile-time recommendation rules
|
|
355
|
+
* (`cost-mismatched-archetype`, `model-stale-evidence`, `tier-down`) can
|
|
356
|
+
* compare the chosen model against in-chain alternatives. Optional for
|
|
357
|
+
* backward compatibility with consumers calling `runAdvisor()` directly.
|
|
358
|
+
*/
|
|
359
|
+
declare function runAdvisor(ir: PromptIR, result: AdvisorContext, profile: ModelProfile, policy?: CompilePolicy, phase2?: RunAdvisorPhase2Context): BestPracticeAdvisory[];
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* alpha.22 — sync introspection: is brain-query mode active for a given
|
|
363
|
+
* table? Used by the advisor (`model-stale-evidence` rule) to decide
|
|
364
|
+
* whether a `judgment`-grounded chosen model is a measurement gap worth
|
|
365
|
+
* surfacing. Returns false on cold start, when configureBrain() was never
|
|
366
|
+
* called, or when the consumer explicitly opted the table out via
|
|
367
|
+
* `BrainConfig.brainQuery.<table> = false`.
|
|
335
368
|
*/
|
|
336
|
-
declare function
|
|
369
|
+
declare function isBrainQueryActiveFor(table: string): boolean;
|
|
337
370
|
|
|
338
371
|
/**
|
|
339
372
|
* env.ts — provider env-key resolution + reachability predicates.
|
|
@@ -870,4 +903,4 @@ declare const loadAliasesFromBrain: () => Record<string, string>;
|
|
|
870
903
|
*/
|
|
871
904
|
declare function compile(ir: PromptIR, opts?: CompileOptions): CompileResult;
|
|
872
905
|
|
|
873
|
-
export { ApiKeys, type AppOracle, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetDefaultFallbackChainOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type ModelBrainRow, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type SupportedProvider, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
|
|
906
|
+
export { ApiKeys, type AppOracle, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetDefaultFallbackChainOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type ModelBrainRow, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, type SupportedProvider, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ __export(index_exports, {
|
|
|
51
51
|
getStarterChainWithGrounding: () => getStarterChainWithGrounding,
|
|
52
52
|
hashShape: () => hashShape,
|
|
53
53
|
isArchetype: () => isArchetype,
|
|
54
|
+
isBrainQueryActiveFor: () => isBrainQueryActiveFor,
|
|
54
55
|
isModelReachable: () => isModelReachable,
|
|
55
56
|
isProviderReachable: () => isProviderReachable,
|
|
56
57
|
learningKey: () => learningKey,
|
|
@@ -1944,14 +1945,160 @@ function profilesByProvider(provider) {
|
|
|
1944
1945
|
return PROFILES_RAW.filter((p) => p.provider === provider);
|
|
1945
1946
|
}
|
|
1946
1947
|
|
|
1948
|
+
// src/brain-query.ts
|
|
1949
|
+
var FRESH_SNAPSHOT = {
|
|
1950
|
+
data: null,
|
|
1951
|
+
expiresAt: 0,
|
|
1952
|
+
refreshing: false,
|
|
1953
|
+
warned: false
|
|
1954
|
+
};
|
|
1955
|
+
var snapshot = { ...FRESH_SNAPSHOT };
|
|
1956
|
+
var runtime;
|
|
1957
|
+
function configureBrainQuery(rt) {
|
|
1958
|
+
runtime = rt;
|
|
1959
|
+
snapshot = { ...FRESH_SNAPSHOT };
|
|
1960
|
+
}
|
|
1961
|
+
function createBrainQueryCache(opts) {
|
|
1962
|
+
return () => {
|
|
1963
|
+
const rt = runtime;
|
|
1964
|
+
if (!rt || !rt.enabledTables.has(opts.table)) {
|
|
1965
|
+
return opts.bundledFallback();
|
|
1966
|
+
}
|
|
1967
|
+
const now = Date.now();
|
|
1968
|
+
const stale = snapshot.expiresAt <= now;
|
|
1969
|
+
if (stale && !snapshot.refreshing) {
|
|
1970
|
+
snapshot.refreshing = true;
|
|
1971
|
+
void asyncRefresh(rt);
|
|
1972
|
+
}
|
|
1973
|
+
if (snapshot.data) {
|
|
1974
|
+
const rows = snapshot.data[opts.table];
|
|
1975
|
+
if (Array.isArray(rows) && rows.length > 0) {
|
|
1976
|
+
try {
|
|
1977
|
+
return opts.mapRows(rows);
|
|
1978
|
+
} catch {
|
|
1979
|
+
return opts.bundledFallback();
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
return opts.bundledFallback();
|
|
1984
|
+
};
|
|
1985
|
+
}
|
|
1986
|
+
var pendingRefresh;
|
|
1987
|
+
async function asyncRefresh(rt) {
|
|
1988
|
+
const promise = doRefresh(rt);
|
|
1989
|
+
pendingRefresh = promise;
|
|
1990
|
+
try {
|
|
1991
|
+
await promise;
|
|
1992
|
+
} finally {
|
|
1993
|
+
if (pendingRefresh === promise) pendingRefresh = void 0;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
var DEFAULT_CONFIG_URL = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/config";
|
|
1997
|
+
async function doRefresh(rt) {
|
|
1998
|
+
const url = rt.configEndpoint ?? DEFAULT_CONFIG_URL;
|
|
1999
|
+
try {
|
|
2000
|
+
const res = await rt.fetchImpl(url, { method: "GET" });
|
|
2001
|
+
if (!res.ok) {
|
|
2002
|
+
throw new Error(`brain-query ${res.status}: ${res.statusText}`);
|
|
2003
|
+
}
|
|
2004
|
+
const body = await res.json();
|
|
2005
|
+
if (runtime !== rt) return;
|
|
2006
|
+
snapshot = {
|
|
2007
|
+
data: body,
|
|
2008
|
+
expiresAt: Date.now() + rt.ttlMs,
|
|
2009
|
+
refreshing: false,
|
|
2010
|
+
warned: snapshot.warned
|
|
2011
|
+
};
|
|
2012
|
+
} catch (err) {
|
|
2013
|
+
if (runtime !== rt) return;
|
|
2014
|
+
snapshot.refreshing = false;
|
|
2015
|
+
snapshot.expiresAt = Date.now() + rt.ttlMs;
|
|
2016
|
+
if (!snapshot.warned) {
|
|
2017
|
+
snapshot.warned = true;
|
|
2018
|
+
(rt.onError ?? defaultOnError)(err);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
function defaultOnError(err) {
|
|
2023
|
+
console.warn("[kgauto] brain-query failed (using bundled fallback):", err);
|
|
2024
|
+
}
|
|
2025
|
+
function isBrainQueryActiveFor(table) {
|
|
2026
|
+
return runtime !== void 0 && runtime.enabledTables.has(table);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
// src/archetype-perf-brain.ts
|
|
2030
|
+
function isPerfRow(x) {
|
|
2031
|
+
if (!x || typeof x !== "object") return false;
|
|
2032
|
+
const r = x;
|
|
2033
|
+
return typeof r.model_id === "string" && typeof r.archetype === "string" && typeof r.perf_score === "number";
|
|
2034
|
+
}
|
|
2035
|
+
function mapRowsToPerfMap(rows) {
|
|
2036
|
+
const out = /* @__PURE__ */ new Map();
|
|
2037
|
+
for (const row of rows) {
|
|
2038
|
+
if (!isPerfRow(row)) continue;
|
|
2039
|
+
const existing = out.get(row.model_id) ?? {};
|
|
2040
|
+
existing[row.archetype] = row.perf_score;
|
|
2041
|
+
out.set(row.model_id, existing);
|
|
2042
|
+
}
|
|
2043
|
+
return out;
|
|
2044
|
+
}
|
|
2045
|
+
function mapRowsToNMap(rows) {
|
|
2046
|
+
const out = /* @__PURE__ */ new Map();
|
|
2047
|
+
for (const row of rows) {
|
|
2048
|
+
if (!isPerfRow(row)) continue;
|
|
2049
|
+
if (typeof row.n !== "number") continue;
|
|
2050
|
+
const existing = out.get(row.model_id) ?? {};
|
|
2051
|
+
existing[row.archetype] = row.n;
|
|
2052
|
+
out.set(row.model_id, existing);
|
|
2053
|
+
}
|
|
2054
|
+
return out;
|
|
2055
|
+
}
|
|
2056
|
+
function bundledArchetypePerf() {
|
|
2057
|
+
const out = /* @__PURE__ */ new Map();
|
|
2058
|
+
for (const profile of allProfiles()) {
|
|
2059
|
+
if (profile.archetypePerf) out.set(profile.id, profile.archetypePerf);
|
|
2060
|
+
}
|
|
2061
|
+
return out;
|
|
2062
|
+
}
|
|
2063
|
+
function bundledArchetypePerfN() {
|
|
2064
|
+
return /* @__PURE__ */ new Map();
|
|
2065
|
+
}
|
|
2066
|
+
var loadArchetypePerfFromBrain = createBrainQueryCache({
|
|
2067
|
+
table: "kgauto_archetype_perf",
|
|
2068
|
+
mapRows: mapRowsToPerfMap,
|
|
2069
|
+
bundledFallback: bundledArchetypePerf
|
|
2070
|
+
});
|
|
2071
|
+
var loadArchetypePerfNFromBrain = createBrainQueryCache(
|
|
2072
|
+
{
|
|
2073
|
+
table: "kgauto_archetype_perf",
|
|
2074
|
+
mapRows: mapRowsToNMap,
|
|
2075
|
+
bundledFallback: bundledArchetypePerfN
|
|
2076
|
+
}
|
|
2077
|
+
);
|
|
2078
|
+
var MEASURED_GROUNDING_MIN_N = 10;
|
|
2079
|
+
function getArchetypePerfScore(modelId, archetype) {
|
|
2080
|
+
const score = loadArchetypePerfFromBrain().get(modelId)?.[archetype] ?? 5;
|
|
2081
|
+
const n = loadArchetypePerfNFromBrain().get(modelId)?.[archetype] ?? 0;
|
|
2082
|
+
const grounding = n >= MEASURED_GROUNDING_MIN_N ? "measured" : "judgment";
|
|
2083
|
+
return { score, n, grounding };
|
|
2084
|
+
}
|
|
2085
|
+
|
|
1947
2086
|
// src/advisor.ts
|
|
1948
|
-
|
|
2087
|
+
var QUALITY_FLOOR_FOR_RECOMMENDATION = 6;
|
|
2088
|
+
var TIER_DOWN_COST_RATIO = 0.5;
|
|
2089
|
+
var COST_MISMATCHED_CHOSEN_SCORE_CEILING = 7;
|
|
2090
|
+
function runAdvisor(ir, result, profile, policy, phase2) {
|
|
1949
2091
|
const out = [];
|
|
1950
2092
|
out.push(...detectCachingOff(ir, profile));
|
|
1951
2093
|
out.push(...detectSingleChunkSystem(ir, profile));
|
|
1952
2094
|
out.push(...detectToolBloat(ir, result));
|
|
1953
2095
|
out.push(...detectHistoryUncached(ir, profile));
|
|
1954
2096
|
out.push(...detectSingleModelArray(ir, policy));
|
|
2097
|
+
if (policy?.posture !== "locked") {
|
|
2098
|
+
out.push(...detectCostMismatchedArchetype(ir, profile, phase2));
|
|
2099
|
+
out.push(...detectModelStaleEvidence(ir, profile));
|
|
2100
|
+
out.push(...detectTierDown(ir, profile, phase2));
|
|
2101
|
+
}
|
|
1955
2102
|
return out;
|
|
1956
2103
|
}
|
|
1957
2104
|
function detectCachingOff(ir, profile) {
|
|
@@ -2037,6 +2184,91 @@ function detectSingleModelArray(ir, policy) {
|
|
|
2037
2184
|
}
|
|
2038
2185
|
];
|
|
2039
2186
|
}
|
|
2187
|
+
function detectCostMismatchedArchetype(ir, profile, phase2) {
|
|
2188
|
+
if (!phase2 || phase2.fallbackChain.length === 0) return [];
|
|
2189
|
+
if (!phase2.profileResolver) return [];
|
|
2190
|
+
const archetype = ir.intent.archetype;
|
|
2191
|
+
const chosenScore = getArchetypePerfScore(profile.id, archetype);
|
|
2192
|
+
const chosenHasRoomToGrow = chosenScore.grounding === "judgment" || chosenScore.score < COST_MISMATCHED_CHOSEN_SCORE_CEILING;
|
|
2193
|
+
if (!chosenHasRoomToGrow) return [];
|
|
2194
|
+
let bestAlt = null;
|
|
2195
|
+
for (const altId of phase2.fallbackChain) {
|
|
2196
|
+
const altProfile = phase2.profileResolver(altId);
|
|
2197
|
+
if (!altProfile) continue;
|
|
2198
|
+
if (altProfile.id === profile.id) continue;
|
|
2199
|
+
const altScore = getArchetypePerfScore(altProfile.id, archetype);
|
|
2200
|
+
if (altScore.score < QUALITY_FLOOR_FOR_RECOMMENDATION) continue;
|
|
2201
|
+
if (altScore.score < chosenScore.score) continue;
|
|
2202
|
+
if (altProfile.costInputPer1m >= profile.costInputPer1m) continue;
|
|
2203
|
+
if (!bestAlt || altScore.score > bestAlt.score.score || altScore.score === bestAlt.score.score && altProfile.costInputPer1m < bestAlt.profile.costInputPer1m) {
|
|
2204
|
+
bestAlt = { id: altId, profile: altProfile, score: altScore };
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
if (!bestAlt) return [];
|
|
2208
|
+
const tierDownWouldFire = bestAlt.score.grounding === "measured" && bestAlt.profile.costInputPer1m <= profile.costInputPer1m * TIER_DOWN_COST_RATIO;
|
|
2209
|
+
if (tierDownWouldFire) return [];
|
|
2210
|
+
const chosenGrounding = chosenScore.grounding === "judgment" ? `archetypePerf.${archetype}=judgment` : `archetypePerf.${archetype}=${chosenScore.score}`;
|
|
2211
|
+
const altGrounding = bestAlt.score.grounding === "measured" ? `archetypePerf.${archetype}=${bestAlt.score.score}, measured, n=${bestAlt.score.n}` : `archetypePerf.${archetype}=${bestAlt.score.score}, judgment`;
|
|
2212
|
+
return [
|
|
2213
|
+
{
|
|
2214
|
+
level: "warn",
|
|
2215
|
+
code: "cost-mismatched-archetype",
|
|
2216
|
+
message: `Cost-mismatched-archetype: target=${profile.id} (${chosenGrounding}) selected for ${archetype}. Alternative ${bestAlt.id} (${altGrounding}) is cheaper ($${bestAlt.profile.costInputPer1m}/$${bestAlt.profile.costOutputPer1m} vs $${profile.costInputPer1m}/$${profile.costOutputPer1m} per 1M) at equal-or-better quality.`,
|
|
2217
|
+
suggestion: `Consider declaring \`${bestAlt.id}\` as the primary model for this archetype, or relax to posture='open' to let kgauto select among the chain. If the chosen model is required for compliance/brand reasons, set \`policy.posture = 'locked'\` to silence this rule.`,
|
|
2218
|
+
recommendationType: profile.provider === bestAlt.profile.provider ? "tier-down" : "model-swap",
|
|
2219
|
+
docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
|
|
2220
|
+
}
|
|
2221
|
+
];
|
|
2222
|
+
}
|
|
2223
|
+
function detectModelStaleEvidence(ir, profile) {
|
|
2224
|
+
if (!isBrainQueryActiveFor("kgauto_archetype_perf")) return [];
|
|
2225
|
+
const archetype = ir.intent.archetype;
|
|
2226
|
+
const chosen = getArchetypePerfScore(profile.id, archetype);
|
|
2227
|
+
if (chosen.grounding !== "judgment") return [];
|
|
2228
|
+
return [
|
|
2229
|
+
{
|
|
2230
|
+
level: "info",
|
|
2231
|
+
code: "model-stale-evidence",
|
|
2232
|
+
message: `Model-stale-evidence: target=${profile.id} archetype=${archetype} is judgment-grounded (n=${chosen.n}) despite brain-query mode being active. Measurement substrate is wired but the brain hasn't accumulated >=10 outcomes for this (model, archetype) tuple yet \u2014 routing decisions remain pre-measured for this slot.`,
|
|
2233
|
+
suggestion: "Verify that `record()` is being called on every call() outcome with the appropriate `actualModel` and `mutationsApplied` fields. Once the brain accumulates n>=10 rows on this tuple, the score promotes from judgment to measured automatically (5-min SWR cache). No code change required from your side \u2014 this is the substrate signaling the gap.",
|
|
2234
|
+
recommendationType: "prompt-fix",
|
|
2235
|
+
docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
|
|
2236
|
+
}
|
|
2237
|
+
];
|
|
2238
|
+
}
|
|
2239
|
+
function detectTierDown(ir, profile, phase2) {
|
|
2240
|
+
if (!phase2 || phase2.fallbackChain.length === 0) return [];
|
|
2241
|
+
if (!phase2.profileResolver) return [];
|
|
2242
|
+
const archetype = ir.intent.archetype;
|
|
2243
|
+
const chosenScore = getArchetypePerfScore(profile.id, archetype);
|
|
2244
|
+
const chosenCost = profile.costInputPer1m;
|
|
2245
|
+
let bestAlt = null;
|
|
2246
|
+
for (const altId of phase2.fallbackChain) {
|
|
2247
|
+
const altProfile = phase2.profileResolver(altId);
|
|
2248
|
+
if (!altProfile) continue;
|
|
2249
|
+
if (altProfile.id === profile.id) continue;
|
|
2250
|
+
const altScore = getArchetypePerfScore(altProfile.id, archetype);
|
|
2251
|
+
if (altScore.grounding !== "measured") continue;
|
|
2252
|
+
if (altScore.score < QUALITY_FLOOR_FOR_RECOMMENDATION) continue;
|
|
2253
|
+
if (altScore.score < chosenScore.score) continue;
|
|
2254
|
+
if (altProfile.costInputPer1m > chosenCost * TIER_DOWN_COST_RATIO) continue;
|
|
2255
|
+
if (!bestAlt || altProfile.costInputPer1m < bestAlt.profile.costInputPer1m || altProfile.costInputPer1m === bestAlt.profile.costInputPer1m && altScore.score > bestAlt.score.score) {
|
|
2256
|
+
bestAlt = { id: altId, profile: altProfile, score: altScore };
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
if (!bestAlt) return [];
|
|
2260
|
+
const chosenDesc = chosenScore.grounding === "measured" ? `archetypePerf.${archetype}=${chosenScore.score} (measured, n=${chosenScore.n})` : `archetypePerf.${archetype}=${chosenScore.score} (${chosenScore.grounding})`;
|
|
2261
|
+
return [
|
|
2262
|
+
{
|
|
2263
|
+
level: "warn",
|
|
2264
|
+
code: "tier-down",
|
|
2265
|
+
message: `Tier-down: target=${profile.id} (${chosenDesc}) selected for ${archetype}. Brain shows ${bestAlt.id} delivers equal-or-better quality (archetypePerf.${archetype}=${bestAlt.score.score}, measured, n=${bestAlt.score.n}) at $${bestAlt.profile.costInputPer1m}/$${bestAlt.profile.costOutputPer1m} per 1M vs $${profile.costInputPer1m}/$${profile.costOutputPer1m} \u2014 a measured tier-down opportunity.`,
|
|
2266
|
+
suggestion: `Move \`${bestAlt.id}\` to primary for this archetype. The brain has n=${bestAlt.score.n} measured outcomes backing the recommendation; this is data, not opinion. If posture='locked' is required (compliance/brand promise), set it explicitly to silence this rule.`,
|
|
2267
|
+
recommendationType: "tier-down",
|
|
2268
|
+
docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
|
|
2269
|
+
}
|
|
2270
|
+
];
|
|
2271
|
+
}
|
|
2040
2272
|
|
|
2041
2273
|
// src/compile.ts
|
|
2042
2274
|
var counter = 0;
|
|
@@ -2112,6 +2344,13 @@ function compile(ir, opts = {}) {
|
|
|
2112
2344
|
description: "ir.constraints.toolOrchestration='sequential' selected the DeepSeek-tier-0 hunt chain overlay (L-040 parallel-tool cliff doesn't apply at single-step granularity)."
|
|
2113
2345
|
});
|
|
2114
2346
|
}
|
|
2347
|
+
const phase2ProfileResolver = opts.profileResolver ? (id) => {
|
|
2348
|
+
try {
|
|
2349
|
+
return opts.profileResolver(id);
|
|
2350
|
+
} catch {
|
|
2351
|
+
return void 0;
|
|
2352
|
+
}
|
|
2353
|
+
} : tryGetProfile;
|
|
2115
2354
|
const advisories = runAdvisor(
|
|
2116
2355
|
ir,
|
|
2117
2356
|
{
|
|
@@ -2121,7 +2360,11 @@ function compile(ir, opts = {}) {
|
|
|
2121
2360
|
diagnostics
|
|
2122
2361
|
},
|
|
2123
2362
|
profile,
|
|
2124
|
-
opts.policy
|
|
2363
|
+
opts.policy,
|
|
2364
|
+
{
|
|
2365
|
+
fallbackChain,
|
|
2366
|
+
profileResolver: phase2ProfileResolver
|
|
2367
|
+
}
|
|
2125
2368
|
);
|
|
2126
2369
|
return {
|
|
2127
2370
|
handle,
|
|
@@ -2174,84 +2417,6 @@ function validateFinalFit(ir, profile, tokens) {
|
|
|
2174
2417
|
}
|
|
2175
2418
|
}
|
|
2176
2419
|
|
|
2177
|
-
// src/brain-query.ts
|
|
2178
|
-
var FRESH_SNAPSHOT = {
|
|
2179
|
-
data: null,
|
|
2180
|
-
expiresAt: 0,
|
|
2181
|
-
refreshing: false,
|
|
2182
|
-
warned: false
|
|
2183
|
-
};
|
|
2184
|
-
var snapshot = { ...FRESH_SNAPSHOT };
|
|
2185
|
-
var runtime;
|
|
2186
|
-
function configureBrainQuery(rt) {
|
|
2187
|
-
runtime = rt;
|
|
2188
|
-
snapshot = { ...FRESH_SNAPSHOT };
|
|
2189
|
-
}
|
|
2190
|
-
function createBrainQueryCache(opts) {
|
|
2191
|
-
return () => {
|
|
2192
|
-
const rt = runtime;
|
|
2193
|
-
if (!rt || !rt.enabledTables.has(opts.table)) {
|
|
2194
|
-
return opts.bundledFallback();
|
|
2195
|
-
}
|
|
2196
|
-
const now = Date.now();
|
|
2197
|
-
const stale = snapshot.expiresAt <= now;
|
|
2198
|
-
if (stale && !snapshot.refreshing) {
|
|
2199
|
-
snapshot.refreshing = true;
|
|
2200
|
-
void asyncRefresh(rt);
|
|
2201
|
-
}
|
|
2202
|
-
if (snapshot.data) {
|
|
2203
|
-
const rows = snapshot.data[opts.table];
|
|
2204
|
-
if (Array.isArray(rows) && rows.length > 0) {
|
|
2205
|
-
try {
|
|
2206
|
-
return opts.mapRows(rows);
|
|
2207
|
-
} catch {
|
|
2208
|
-
return opts.bundledFallback();
|
|
2209
|
-
}
|
|
2210
|
-
}
|
|
2211
|
-
}
|
|
2212
|
-
return opts.bundledFallback();
|
|
2213
|
-
};
|
|
2214
|
-
}
|
|
2215
|
-
var pendingRefresh;
|
|
2216
|
-
async function asyncRefresh(rt) {
|
|
2217
|
-
const promise = doRefresh(rt);
|
|
2218
|
-
pendingRefresh = promise;
|
|
2219
|
-
try {
|
|
2220
|
-
await promise;
|
|
2221
|
-
} finally {
|
|
2222
|
-
if (pendingRefresh === promise) pendingRefresh = void 0;
|
|
2223
|
-
}
|
|
2224
|
-
}
|
|
2225
|
-
var DEFAULT_CONFIG_URL = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/config";
|
|
2226
|
-
async function doRefresh(rt) {
|
|
2227
|
-
const url = rt.configEndpoint ?? DEFAULT_CONFIG_URL;
|
|
2228
|
-
try {
|
|
2229
|
-
const res = await rt.fetchImpl(url, { method: "GET" });
|
|
2230
|
-
if (!res.ok) {
|
|
2231
|
-
throw new Error(`brain-query ${res.status}: ${res.statusText}`);
|
|
2232
|
-
}
|
|
2233
|
-
const body = await res.json();
|
|
2234
|
-
if (runtime !== rt) return;
|
|
2235
|
-
snapshot = {
|
|
2236
|
-
data: body,
|
|
2237
|
-
expiresAt: Date.now() + rt.ttlMs,
|
|
2238
|
-
refreshing: false,
|
|
2239
|
-
warned: snapshot.warned
|
|
2240
|
-
};
|
|
2241
|
-
} catch (err) {
|
|
2242
|
-
if (runtime !== rt) return;
|
|
2243
|
-
snapshot.refreshing = false;
|
|
2244
|
-
snapshot.expiresAt = Date.now() + rt.ttlMs;
|
|
2245
|
-
if (!snapshot.warned) {
|
|
2246
|
-
snapshot.warned = true;
|
|
2247
|
-
(rt.onError ?? defaultOnError)(err);
|
|
2248
|
-
}
|
|
2249
|
-
}
|
|
2250
|
-
}
|
|
2251
|
-
function defaultOnError(err) {
|
|
2252
|
-
console.warn("[kgauto] brain-query failed (using bundled fallback):", err);
|
|
2253
|
-
}
|
|
2254
|
-
|
|
2255
2420
|
// src/pricing-brain.ts
|
|
2256
2421
|
function isPricingRow(x) {
|
|
2257
2422
|
if (!x || typeof x !== "object") return false;
|
|
@@ -3923,63 +4088,6 @@ function clamp(n) {
|
|
|
3923
4088
|
return Math.max(0, Math.min(1, n));
|
|
3924
4089
|
}
|
|
3925
4090
|
|
|
3926
|
-
// src/archetype-perf-brain.ts
|
|
3927
|
-
function isPerfRow(x) {
|
|
3928
|
-
if (!x || typeof x !== "object") return false;
|
|
3929
|
-
const r = x;
|
|
3930
|
-
return typeof r.model_id === "string" && typeof r.archetype === "string" && typeof r.perf_score === "number";
|
|
3931
|
-
}
|
|
3932
|
-
function mapRowsToPerfMap(rows) {
|
|
3933
|
-
const out = /* @__PURE__ */ new Map();
|
|
3934
|
-
for (const row of rows) {
|
|
3935
|
-
if (!isPerfRow(row)) continue;
|
|
3936
|
-
const existing = out.get(row.model_id) ?? {};
|
|
3937
|
-
existing[row.archetype] = row.perf_score;
|
|
3938
|
-
out.set(row.model_id, existing);
|
|
3939
|
-
}
|
|
3940
|
-
return out;
|
|
3941
|
-
}
|
|
3942
|
-
function mapRowsToNMap(rows) {
|
|
3943
|
-
const out = /* @__PURE__ */ new Map();
|
|
3944
|
-
for (const row of rows) {
|
|
3945
|
-
if (!isPerfRow(row)) continue;
|
|
3946
|
-
if (typeof row.n !== "number") continue;
|
|
3947
|
-
const existing = out.get(row.model_id) ?? {};
|
|
3948
|
-
existing[row.archetype] = row.n;
|
|
3949
|
-
out.set(row.model_id, existing);
|
|
3950
|
-
}
|
|
3951
|
-
return out;
|
|
3952
|
-
}
|
|
3953
|
-
function bundledArchetypePerf() {
|
|
3954
|
-
const out = /* @__PURE__ */ new Map();
|
|
3955
|
-
for (const profile of allProfiles()) {
|
|
3956
|
-
if (profile.archetypePerf) out.set(profile.id, profile.archetypePerf);
|
|
3957
|
-
}
|
|
3958
|
-
return out;
|
|
3959
|
-
}
|
|
3960
|
-
function bundledArchetypePerfN() {
|
|
3961
|
-
return /* @__PURE__ */ new Map();
|
|
3962
|
-
}
|
|
3963
|
-
var loadArchetypePerfFromBrain = createBrainQueryCache({
|
|
3964
|
-
table: "kgauto_archetype_perf",
|
|
3965
|
-
mapRows: mapRowsToPerfMap,
|
|
3966
|
-
bundledFallback: bundledArchetypePerf
|
|
3967
|
-
});
|
|
3968
|
-
var loadArchetypePerfNFromBrain = createBrainQueryCache(
|
|
3969
|
-
{
|
|
3970
|
-
table: "kgauto_archetype_perf",
|
|
3971
|
-
mapRows: mapRowsToNMap,
|
|
3972
|
-
bundledFallback: bundledArchetypePerfN
|
|
3973
|
-
}
|
|
3974
|
-
);
|
|
3975
|
-
var MEASURED_GROUNDING_MIN_N = 10;
|
|
3976
|
-
function getArchetypePerfScore(modelId, archetype) {
|
|
3977
|
-
const score = loadArchetypePerfFromBrain().get(modelId)?.[archetype] ?? 5;
|
|
3978
|
-
const n = loadArchetypePerfNFromBrain().get(modelId)?.[archetype] ?? 0;
|
|
3979
|
-
const grounding = n >= MEASURED_GROUNDING_MIN_N ? "measured" : "judgment";
|
|
3980
|
-
return { score, n, grounding };
|
|
3981
|
-
}
|
|
3982
|
-
|
|
3983
4091
|
// src/models-brain.ts
|
|
3984
4092
|
function isModelRow(x) {
|
|
3985
4093
|
if (!x || typeof x !== "object") return false;
|
|
@@ -4138,6 +4246,7 @@ function compile2(ir, opts) {
|
|
|
4138
4246
|
getStarterChainWithGrounding,
|
|
4139
4247
|
hashShape,
|
|
4140
4248
|
isArchetype,
|
|
4249
|
+
isBrainQueryActiveFor,
|
|
4141
4250
|
isModelReachable,
|
|
4142
4251
|
isProviderReachable,
|
|
4143
4252
|
learningKey,
|
package/dist/index.mjs
CHANGED
|
@@ -740,14 +740,160 @@ function setNestedField(obj, path, value) {
|
|
|
740
740
|
cursor[parts[parts.length - 1]] = value;
|
|
741
741
|
}
|
|
742
742
|
|
|
743
|
+
// src/brain-query.ts
|
|
744
|
+
var FRESH_SNAPSHOT = {
|
|
745
|
+
data: null,
|
|
746
|
+
expiresAt: 0,
|
|
747
|
+
refreshing: false,
|
|
748
|
+
warned: false
|
|
749
|
+
};
|
|
750
|
+
var snapshot = { ...FRESH_SNAPSHOT };
|
|
751
|
+
var runtime;
|
|
752
|
+
function configureBrainQuery(rt) {
|
|
753
|
+
runtime = rt;
|
|
754
|
+
snapshot = { ...FRESH_SNAPSHOT };
|
|
755
|
+
}
|
|
756
|
+
function createBrainQueryCache(opts) {
|
|
757
|
+
return () => {
|
|
758
|
+
const rt = runtime;
|
|
759
|
+
if (!rt || !rt.enabledTables.has(opts.table)) {
|
|
760
|
+
return opts.bundledFallback();
|
|
761
|
+
}
|
|
762
|
+
const now = Date.now();
|
|
763
|
+
const stale = snapshot.expiresAt <= now;
|
|
764
|
+
if (stale && !snapshot.refreshing) {
|
|
765
|
+
snapshot.refreshing = true;
|
|
766
|
+
void asyncRefresh(rt);
|
|
767
|
+
}
|
|
768
|
+
if (snapshot.data) {
|
|
769
|
+
const rows = snapshot.data[opts.table];
|
|
770
|
+
if (Array.isArray(rows) && rows.length > 0) {
|
|
771
|
+
try {
|
|
772
|
+
return opts.mapRows(rows);
|
|
773
|
+
} catch {
|
|
774
|
+
return opts.bundledFallback();
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return opts.bundledFallback();
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
var pendingRefresh;
|
|
782
|
+
async function asyncRefresh(rt) {
|
|
783
|
+
const promise = doRefresh(rt);
|
|
784
|
+
pendingRefresh = promise;
|
|
785
|
+
try {
|
|
786
|
+
await promise;
|
|
787
|
+
} finally {
|
|
788
|
+
if (pendingRefresh === promise) pendingRefresh = void 0;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
var DEFAULT_CONFIG_URL = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/config";
|
|
792
|
+
async function doRefresh(rt) {
|
|
793
|
+
const url = rt.configEndpoint ?? DEFAULT_CONFIG_URL;
|
|
794
|
+
try {
|
|
795
|
+
const res = await rt.fetchImpl(url, { method: "GET" });
|
|
796
|
+
if (!res.ok) {
|
|
797
|
+
throw new Error(`brain-query ${res.status}: ${res.statusText}`);
|
|
798
|
+
}
|
|
799
|
+
const body = await res.json();
|
|
800
|
+
if (runtime !== rt) return;
|
|
801
|
+
snapshot = {
|
|
802
|
+
data: body,
|
|
803
|
+
expiresAt: Date.now() + rt.ttlMs,
|
|
804
|
+
refreshing: false,
|
|
805
|
+
warned: snapshot.warned
|
|
806
|
+
};
|
|
807
|
+
} catch (err) {
|
|
808
|
+
if (runtime !== rt) return;
|
|
809
|
+
snapshot.refreshing = false;
|
|
810
|
+
snapshot.expiresAt = Date.now() + rt.ttlMs;
|
|
811
|
+
if (!snapshot.warned) {
|
|
812
|
+
snapshot.warned = true;
|
|
813
|
+
(rt.onError ?? defaultOnError)(err);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
function defaultOnError(err) {
|
|
818
|
+
console.warn("[kgauto] brain-query failed (using bundled fallback):", err);
|
|
819
|
+
}
|
|
820
|
+
function isBrainQueryActiveFor(table) {
|
|
821
|
+
return runtime !== void 0 && runtime.enabledTables.has(table);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// src/archetype-perf-brain.ts
|
|
825
|
+
function isPerfRow(x) {
|
|
826
|
+
if (!x || typeof x !== "object") return false;
|
|
827
|
+
const r = x;
|
|
828
|
+
return typeof r.model_id === "string" && typeof r.archetype === "string" && typeof r.perf_score === "number";
|
|
829
|
+
}
|
|
830
|
+
function mapRowsToPerfMap(rows) {
|
|
831
|
+
const out = /* @__PURE__ */ new Map();
|
|
832
|
+
for (const row of rows) {
|
|
833
|
+
if (!isPerfRow(row)) continue;
|
|
834
|
+
const existing = out.get(row.model_id) ?? {};
|
|
835
|
+
existing[row.archetype] = row.perf_score;
|
|
836
|
+
out.set(row.model_id, existing);
|
|
837
|
+
}
|
|
838
|
+
return out;
|
|
839
|
+
}
|
|
840
|
+
function mapRowsToNMap(rows) {
|
|
841
|
+
const out = /* @__PURE__ */ new Map();
|
|
842
|
+
for (const row of rows) {
|
|
843
|
+
if (!isPerfRow(row)) continue;
|
|
844
|
+
if (typeof row.n !== "number") continue;
|
|
845
|
+
const existing = out.get(row.model_id) ?? {};
|
|
846
|
+
existing[row.archetype] = row.n;
|
|
847
|
+
out.set(row.model_id, existing);
|
|
848
|
+
}
|
|
849
|
+
return out;
|
|
850
|
+
}
|
|
851
|
+
function bundledArchetypePerf() {
|
|
852
|
+
const out = /* @__PURE__ */ new Map();
|
|
853
|
+
for (const profile of allProfiles()) {
|
|
854
|
+
if (profile.archetypePerf) out.set(profile.id, profile.archetypePerf);
|
|
855
|
+
}
|
|
856
|
+
return out;
|
|
857
|
+
}
|
|
858
|
+
function bundledArchetypePerfN() {
|
|
859
|
+
return /* @__PURE__ */ new Map();
|
|
860
|
+
}
|
|
861
|
+
var loadArchetypePerfFromBrain = createBrainQueryCache({
|
|
862
|
+
table: "kgauto_archetype_perf",
|
|
863
|
+
mapRows: mapRowsToPerfMap,
|
|
864
|
+
bundledFallback: bundledArchetypePerf
|
|
865
|
+
});
|
|
866
|
+
var loadArchetypePerfNFromBrain = createBrainQueryCache(
|
|
867
|
+
{
|
|
868
|
+
table: "kgauto_archetype_perf",
|
|
869
|
+
mapRows: mapRowsToNMap,
|
|
870
|
+
bundledFallback: bundledArchetypePerfN
|
|
871
|
+
}
|
|
872
|
+
);
|
|
873
|
+
var MEASURED_GROUNDING_MIN_N = 10;
|
|
874
|
+
function getArchetypePerfScore(modelId, archetype) {
|
|
875
|
+
const score = loadArchetypePerfFromBrain().get(modelId)?.[archetype] ?? 5;
|
|
876
|
+
const n = loadArchetypePerfNFromBrain().get(modelId)?.[archetype] ?? 0;
|
|
877
|
+
const grounding = n >= MEASURED_GROUNDING_MIN_N ? "measured" : "judgment";
|
|
878
|
+
return { score, n, grounding };
|
|
879
|
+
}
|
|
880
|
+
|
|
743
881
|
// src/advisor.ts
|
|
744
|
-
|
|
882
|
+
var QUALITY_FLOOR_FOR_RECOMMENDATION = 6;
|
|
883
|
+
var TIER_DOWN_COST_RATIO = 0.5;
|
|
884
|
+
var COST_MISMATCHED_CHOSEN_SCORE_CEILING = 7;
|
|
885
|
+
function runAdvisor(ir, result, profile, policy, phase2) {
|
|
745
886
|
const out = [];
|
|
746
887
|
out.push(...detectCachingOff(ir, profile));
|
|
747
888
|
out.push(...detectSingleChunkSystem(ir, profile));
|
|
748
889
|
out.push(...detectToolBloat(ir, result));
|
|
749
890
|
out.push(...detectHistoryUncached(ir, profile));
|
|
750
891
|
out.push(...detectSingleModelArray(ir, policy));
|
|
892
|
+
if (policy?.posture !== "locked") {
|
|
893
|
+
out.push(...detectCostMismatchedArchetype(ir, profile, phase2));
|
|
894
|
+
out.push(...detectModelStaleEvidence(ir, profile));
|
|
895
|
+
out.push(...detectTierDown(ir, profile, phase2));
|
|
896
|
+
}
|
|
751
897
|
return out;
|
|
752
898
|
}
|
|
753
899
|
function detectCachingOff(ir, profile) {
|
|
@@ -833,6 +979,91 @@ function detectSingleModelArray(ir, policy) {
|
|
|
833
979
|
}
|
|
834
980
|
];
|
|
835
981
|
}
|
|
982
|
+
function detectCostMismatchedArchetype(ir, profile, phase2) {
|
|
983
|
+
if (!phase2 || phase2.fallbackChain.length === 0) return [];
|
|
984
|
+
if (!phase2.profileResolver) return [];
|
|
985
|
+
const archetype = ir.intent.archetype;
|
|
986
|
+
const chosenScore = getArchetypePerfScore(profile.id, archetype);
|
|
987
|
+
const chosenHasRoomToGrow = chosenScore.grounding === "judgment" || chosenScore.score < COST_MISMATCHED_CHOSEN_SCORE_CEILING;
|
|
988
|
+
if (!chosenHasRoomToGrow) return [];
|
|
989
|
+
let bestAlt = null;
|
|
990
|
+
for (const altId of phase2.fallbackChain) {
|
|
991
|
+
const altProfile = phase2.profileResolver(altId);
|
|
992
|
+
if (!altProfile) continue;
|
|
993
|
+
if (altProfile.id === profile.id) continue;
|
|
994
|
+
const altScore = getArchetypePerfScore(altProfile.id, archetype);
|
|
995
|
+
if (altScore.score < QUALITY_FLOOR_FOR_RECOMMENDATION) continue;
|
|
996
|
+
if (altScore.score < chosenScore.score) continue;
|
|
997
|
+
if (altProfile.costInputPer1m >= profile.costInputPer1m) continue;
|
|
998
|
+
if (!bestAlt || altScore.score > bestAlt.score.score || altScore.score === bestAlt.score.score && altProfile.costInputPer1m < bestAlt.profile.costInputPer1m) {
|
|
999
|
+
bestAlt = { id: altId, profile: altProfile, score: altScore };
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
if (!bestAlt) return [];
|
|
1003
|
+
const tierDownWouldFire = bestAlt.score.grounding === "measured" && bestAlt.profile.costInputPer1m <= profile.costInputPer1m * TIER_DOWN_COST_RATIO;
|
|
1004
|
+
if (tierDownWouldFire) return [];
|
|
1005
|
+
const chosenGrounding = chosenScore.grounding === "judgment" ? `archetypePerf.${archetype}=judgment` : `archetypePerf.${archetype}=${chosenScore.score}`;
|
|
1006
|
+
const altGrounding = bestAlt.score.grounding === "measured" ? `archetypePerf.${archetype}=${bestAlt.score.score}, measured, n=${bestAlt.score.n}` : `archetypePerf.${archetype}=${bestAlt.score.score}, judgment`;
|
|
1007
|
+
return [
|
|
1008
|
+
{
|
|
1009
|
+
level: "warn",
|
|
1010
|
+
code: "cost-mismatched-archetype",
|
|
1011
|
+
message: `Cost-mismatched-archetype: target=${profile.id} (${chosenGrounding}) selected for ${archetype}. Alternative ${bestAlt.id} (${altGrounding}) is cheaper ($${bestAlt.profile.costInputPer1m}/$${bestAlt.profile.costOutputPer1m} vs $${profile.costInputPer1m}/$${profile.costOutputPer1m} per 1M) at equal-or-better quality.`,
|
|
1012
|
+
suggestion: `Consider declaring \`${bestAlt.id}\` as the primary model for this archetype, or relax to posture='open' to let kgauto select among the chain. If the chosen model is required for compliance/brand reasons, set \`policy.posture = 'locked'\` to silence this rule.`,
|
|
1013
|
+
recommendationType: profile.provider === bestAlt.profile.provider ? "tier-down" : "model-swap",
|
|
1014
|
+
docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
|
|
1015
|
+
}
|
|
1016
|
+
];
|
|
1017
|
+
}
|
|
1018
|
+
function detectModelStaleEvidence(ir, profile) {
|
|
1019
|
+
if (!isBrainQueryActiveFor("kgauto_archetype_perf")) return [];
|
|
1020
|
+
const archetype = ir.intent.archetype;
|
|
1021
|
+
const chosen = getArchetypePerfScore(profile.id, archetype);
|
|
1022
|
+
if (chosen.grounding !== "judgment") return [];
|
|
1023
|
+
return [
|
|
1024
|
+
{
|
|
1025
|
+
level: "info",
|
|
1026
|
+
code: "model-stale-evidence",
|
|
1027
|
+
message: `Model-stale-evidence: target=${profile.id} archetype=${archetype} is judgment-grounded (n=${chosen.n}) despite brain-query mode being active. Measurement substrate is wired but the brain hasn't accumulated >=10 outcomes for this (model, archetype) tuple yet \u2014 routing decisions remain pre-measured for this slot.`,
|
|
1028
|
+
suggestion: "Verify that `record()` is being called on every call() outcome with the appropriate `actualModel` and `mutationsApplied` fields. Once the brain accumulates n>=10 rows on this tuple, the score promotes from judgment to measured automatically (5-min SWR cache). No code change required from your side \u2014 this is the substrate signaling the gap.",
|
|
1029
|
+
recommendationType: "prompt-fix",
|
|
1030
|
+
docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
|
|
1031
|
+
}
|
|
1032
|
+
];
|
|
1033
|
+
}
|
|
1034
|
+
function detectTierDown(ir, profile, phase2) {
|
|
1035
|
+
if (!phase2 || phase2.fallbackChain.length === 0) return [];
|
|
1036
|
+
if (!phase2.profileResolver) return [];
|
|
1037
|
+
const archetype = ir.intent.archetype;
|
|
1038
|
+
const chosenScore = getArchetypePerfScore(profile.id, archetype);
|
|
1039
|
+
const chosenCost = profile.costInputPer1m;
|
|
1040
|
+
let bestAlt = null;
|
|
1041
|
+
for (const altId of phase2.fallbackChain) {
|
|
1042
|
+
const altProfile = phase2.profileResolver(altId);
|
|
1043
|
+
if (!altProfile) continue;
|
|
1044
|
+
if (altProfile.id === profile.id) continue;
|
|
1045
|
+
const altScore = getArchetypePerfScore(altProfile.id, archetype);
|
|
1046
|
+
if (altScore.grounding !== "measured") continue;
|
|
1047
|
+
if (altScore.score < QUALITY_FLOOR_FOR_RECOMMENDATION) continue;
|
|
1048
|
+
if (altScore.score < chosenScore.score) continue;
|
|
1049
|
+
if (altProfile.costInputPer1m > chosenCost * TIER_DOWN_COST_RATIO) continue;
|
|
1050
|
+
if (!bestAlt || altProfile.costInputPer1m < bestAlt.profile.costInputPer1m || altProfile.costInputPer1m === bestAlt.profile.costInputPer1m && altScore.score > bestAlt.score.score) {
|
|
1051
|
+
bestAlt = { id: altId, profile: altProfile, score: altScore };
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
if (!bestAlt) return [];
|
|
1055
|
+
const chosenDesc = chosenScore.grounding === "measured" ? `archetypePerf.${archetype}=${chosenScore.score} (measured, n=${chosenScore.n})` : `archetypePerf.${archetype}=${chosenScore.score} (${chosenScore.grounding})`;
|
|
1056
|
+
return [
|
|
1057
|
+
{
|
|
1058
|
+
level: "warn",
|
|
1059
|
+
code: "tier-down",
|
|
1060
|
+
message: `Tier-down: target=${profile.id} (${chosenDesc}) selected for ${archetype}. Brain shows ${bestAlt.id} delivers equal-or-better quality (archetypePerf.${archetype}=${bestAlt.score.score}, measured, n=${bestAlt.score.n}) at $${bestAlt.profile.costInputPer1m}/$${bestAlt.profile.costOutputPer1m} per 1M vs $${profile.costInputPer1m}/$${profile.costOutputPer1m} \u2014 a measured tier-down opportunity.`,
|
|
1061
|
+
suggestion: `Move \`${bestAlt.id}\` to primary for this archetype. The brain has n=${bestAlt.score.n} measured outcomes backing the recommendation; this is data, not opinion. If posture='locked' is required (compliance/brand promise), set it explicitly to silence this rule.`,
|
|
1062
|
+
recommendationType: "tier-down",
|
|
1063
|
+
docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
|
|
1064
|
+
}
|
|
1065
|
+
];
|
|
1066
|
+
}
|
|
836
1067
|
|
|
837
1068
|
// src/compile.ts
|
|
838
1069
|
var counter = 0;
|
|
@@ -908,6 +1139,13 @@ function compile(ir, opts = {}) {
|
|
|
908
1139
|
description: "ir.constraints.toolOrchestration='sequential' selected the DeepSeek-tier-0 hunt chain overlay (L-040 parallel-tool cliff doesn't apply at single-step granularity)."
|
|
909
1140
|
});
|
|
910
1141
|
}
|
|
1142
|
+
const phase2ProfileResolver = opts.profileResolver ? (id) => {
|
|
1143
|
+
try {
|
|
1144
|
+
return opts.profileResolver(id);
|
|
1145
|
+
} catch {
|
|
1146
|
+
return void 0;
|
|
1147
|
+
}
|
|
1148
|
+
} : tryGetProfile;
|
|
911
1149
|
const advisories = runAdvisor(
|
|
912
1150
|
ir,
|
|
913
1151
|
{
|
|
@@ -917,7 +1155,11 @@ function compile(ir, opts = {}) {
|
|
|
917
1155
|
diagnostics
|
|
918
1156
|
},
|
|
919
1157
|
profile,
|
|
920
|
-
opts.policy
|
|
1158
|
+
opts.policy,
|
|
1159
|
+
{
|
|
1160
|
+
fallbackChain,
|
|
1161
|
+
profileResolver: phase2ProfileResolver
|
|
1162
|
+
}
|
|
921
1163
|
);
|
|
922
1164
|
return {
|
|
923
1165
|
handle,
|
|
@@ -970,84 +1212,6 @@ function validateFinalFit(ir, profile, tokens) {
|
|
|
970
1212
|
}
|
|
971
1213
|
}
|
|
972
1214
|
|
|
973
|
-
// src/brain-query.ts
|
|
974
|
-
var FRESH_SNAPSHOT = {
|
|
975
|
-
data: null,
|
|
976
|
-
expiresAt: 0,
|
|
977
|
-
refreshing: false,
|
|
978
|
-
warned: false
|
|
979
|
-
};
|
|
980
|
-
var snapshot = { ...FRESH_SNAPSHOT };
|
|
981
|
-
var runtime;
|
|
982
|
-
function configureBrainQuery(rt) {
|
|
983
|
-
runtime = rt;
|
|
984
|
-
snapshot = { ...FRESH_SNAPSHOT };
|
|
985
|
-
}
|
|
986
|
-
function createBrainQueryCache(opts) {
|
|
987
|
-
return () => {
|
|
988
|
-
const rt = runtime;
|
|
989
|
-
if (!rt || !rt.enabledTables.has(opts.table)) {
|
|
990
|
-
return opts.bundledFallback();
|
|
991
|
-
}
|
|
992
|
-
const now = Date.now();
|
|
993
|
-
const stale = snapshot.expiresAt <= now;
|
|
994
|
-
if (stale && !snapshot.refreshing) {
|
|
995
|
-
snapshot.refreshing = true;
|
|
996
|
-
void asyncRefresh(rt);
|
|
997
|
-
}
|
|
998
|
-
if (snapshot.data) {
|
|
999
|
-
const rows = snapshot.data[opts.table];
|
|
1000
|
-
if (Array.isArray(rows) && rows.length > 0) {
|
|
1001
|
-
try {
|
|
1002
|
-
return opts.mapRows(rows);
|
|
1003
|
-
} catch {
|
|
1004
|
-
return opts.bundledFallback();
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
return opts.bundledFallback();
|
|
1009
|
-
};
|
|
1010
|
-
}
|
|
1011
|
-
var pendingRefresh;
|
|
1012
|
-
async function asyncRefresh(rt) {
|
|
1013
|
-
const promise = doRefresh(rt);
|
|
1014
|
-
pendingRefresh = promise;
|
|
1015
|
-
try {
|
|
1016
|
-
await promise;
|
|
1017
|
-
} finally {
|
|
1018
|
-
if (pendingRefresh === promise) pendingRefresh = void 0;
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
var DEFAULT_CONFIG_URL = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/config";
|
|
1022
|
-
async function doRefresh(rt) {
|
|
1023
|
-
const url = rt.configEndpoint ?? DEFAULT_CONFIG_URL;
|
|
1024
|
-
try {
|
|
1025
|
-
const res = await rt.fetchImpl(url, { method: "GET" });
|
|
1026
|
-
if (!res.ok) {
|
|
1027
|
-
throw new Error(`brain-query ${res.status}: ${res.statusText}`);
|
|
1028
|
-
}
|
|
1029
|
-
const body = await res.json();
|
|
1030
|
-
if (runtime !== rt) return;
|
|
1031
|
-
snapshot = {
|
|
1032
|
-
data: body,
|
|
1033
|
-
expiresAt: Date.now() + rt.ttlMs,
|
|
1034
|
-
refreshing: false,
|
|
1035
|
-
warned: snapshot.warned
|
|
1036
|
-
};
|
|
1037
|
-
} catch (err) {
|
|
1038
|
-
if (runtime !== rt) return;
|
|
1039
|
-
snapshot.refreshing = false;
|
|
1040
|
-
snapshot.expiresAt = Date.now() + rt.ttlMs;
|
|
1041
|
-
if (!snapshot.warned) {
|
|
1042
|
-
snapshot.warned = true;
|
|
1043
|
-
(rt.onError ?? defaultOnError)(err);
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
function defaultOnError(err) {
|
|
1048
|
-
console.warn("[kgauto] brain-query failed (using bundled fallback):", err);
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
1215
|
// src/pricing-brain.ts
|
|
1052
1216
|
function isPricingRow(x) {
|
|
1053
1217
|
if (!x || typeof x !== "object") return false;
|
|
@@ -2431,63 +2595,6 @@ function clamp(n) {
|
|
|
2431
2595
|
return Math.max(0, Math.min(1, n));
|
|
2432
2596
|
}
|
|
2433
2597
|
|
|
2434
|
-
// src/archetype-perf-brain.ts
|
|
2435
|
-
function isPerfRow(x) {
|
|
2436
|
-
if (!x || typeof x !== "object") return false;
|
|
2437
|
-
const r = x;
|
|
2438
|
-
return typeof r.model_id === "string" && typeof r.archetype === "string" && typeof r.perf_score === "number";
|
|
2439
|
-
}
|
|
2440
|
-
function mapRowsToPerfMap(rows) {
|
|
2441
|
-
const out = /* @__PURE__ */ new Map();
|
|
2442
|
-
for (const row of rows) {
|
|
2443
|
-
if (!isPerfRow(row)) continue;
|
|
2444
|
-
const existing = out.get(row.model_id) ?? {};
|
|
2445
|
-
existing[row.archetype] = row.perf_score;
|
|
2446
|
-
out.set(row.model_id, existing);
|
|
2447
|
-
}
|
|
2448
|
-
return out;
|
|
2449
|
-
}
|
|
2450
|
-
function mapRowsToNMap(rows) {
|
|
2451
|
-
const out = /* @__PURE__ */ new Map();
|
|
2452
|
-
for (const row of rows) {
|
|
2453
|
-
if (!isPerfRow(row)) continue;
|
|
2454
|
-
if (typeof row.n !== "number") continue;
|
|
2455
|
-
const existing = out.get(row.model_id) ?? {};
|
|
2456
|
-
existing[row.archetype] = row.n;
|
|
2457
|
-
out.set(row.model_id, existing);
|
|
2458
|
-
}
|
|
2459
|
-
return out;
|
|
2460
|
-
}
|
|
2461
|
-
function bundledArchetypePerf() {
|
|
2462
|
-
const out = /* @__PURE__ */ new Map();
|
|
2463
|
-
for (const profile of allProfiles()) {
|
|
2464
|
-
if (profile.archetypePerf) out.set(profile.id, profile.archetypePerf);
|
|
2465
|
-
}
|
|
2466
|
-
return out;
|
|
2467
|
-
}
|
|
2468
|
-
function bundledArchetypePerfN() {
|
|
2469
|
-
return /* @__PURE__ */ new Map();
|
|
2470
|
-
}
|
|
2471
|
-
var loadArchetypePerfFromBrain = createBrainQueryCache({
|
|
2472
|
-
table: "kgauto_archetype_perf",
|
|
2473
|
-
mapRows: mapRowsToPerfMap,
|
|
2474
|
-
bundledFallback: bundledArchetypePerf
|
|
2475
|
-
});
|
|
2476
|
-
var loadArchetypePerfNFromBrain = createBrainQueryCache(
|
|
2477
|
-
{
|
|
2478
|
-
table: "kgauto_archetype_perf",
|
|
2479
|
-
mapRows: mapRowsToNMap,
|
|
2480
|
-
bundledFallback: bundledArchetypePerfN
|
|
2481
|
-
}
|
|
2482
|
-
);
|
|
2483
|
-
var MEASURED_GROUNDING_MIN_N = 10;
|
|
2484
|
-
function getArchetypePerfScore(modelId, archetype) {
|
|
2485
|
-
const score = loadArchetypePerfFromBrain().get(modelId)?.[archetype] ?? 5;
|
|
2486
|
-
const n = loadArchetypePerfNFromBrain().get(modelId)?.[archetype] ?? 0;
|
|
2487
|
-
const grounding = n >= MEASURED_GROUNDING_MIN_N ? "measured" : "judgment";
|
|
2488
|
-
return { score, n, grounding };
|
|
2489
|
-
}
|
|
2490
|
-
|
|
2491
2598
|
// src/models-brain.ts
|
|
2492
2599
|
function isModelRow(x) {
|
|
2493
2600
|
if (!x || typeof x !== "object") return false;
|
|
@@ -2645,6 +2752,7 @@ export {
|
|
|
2645
2752
|
getStarterChainWithGrounding,
|
|
2646
2753
|
hashShape,
|
|
2647
2754
|
isArchetype,
|
|
2755
|
+
isBrainQueryActiveFor,
|
|
2648
2756
|
isModelReachable,
|
|
2649
2757
|
isProviderReachable,
|
|
2650
2758
|
learningKey,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warmdrift/kgauto-compiler",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.22",
|
|
4
4
|
"description": "Prompt compiler + central learning brain for multi-model AI apps. Swap models without rewriting prompts.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|