@warmdrift/kgauto-compiler 2.0.0-alpha.39 → 2.0.0-alpha.41
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/glassbox/index.d.mts +3 -3
- package/dist/glassbox/index.d.ts +3 -3
- package/dist/glassbox-routes/format.d.mts +2 -2
- package/dist/glassbox-routes/format.d.ts +2 -2
- package/dist/glassbox-routes/index.d.mts +4 -4
- package/dist/glassbox-routes/index.d.ts +4 -4
- package/dist/glassbox-routes/react/index.d.mts +2 -2
- package/dist/glassbox-routes/react/index.d.ts +2 -2
- package/dist/index.d.mts +234 -3
- package/dist/index.d.ts +234 -3
- package/dist/index.js +710 -138
- package/dist/index.mjs +706 -138
- package/dist/{ir-CZ9Ng96k.d.ts → ir-DYpvUSEw.d.ts} +32 -3
- package/dist/{ir-BiZSAVCJ.d.mts → ir-D_kgJcaV.d.mts} +32 -3
- package/dist/profiles.d.mts +28 -1
- package/dist/profiles.d.ts +28 -1
- package/dist/{types-HEl2tS4P.d.ts → types-C8gOJ7hV.d.ts} +1 -1
- package/dist/{types-kzYpX7wB.d.mts → types-CYY769Ls.d.mts} +1 -1
- package/dist/{types-CsFP-H-U.d.ts → types-DigtHnEt.d.ts} +1 -1
- package/dist/{types-f7idIVsm.d.mts → types-MkiWUPM8.d.mts} +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -342,7 +342,8 @@ function passScoreTargets(ir, opts) {
|
|
|
342
342
|
const preferredSet = new Set(policy.preferredModels ?? []);
|
|
343
343
|
const scores = [];
|
|
344
344
|
const policyMutations = [];
|
|
345
|
-
|
|
345
|
+
const modelIds = ir.models.filter((m) => typeof m === "string");
|
|
346
|
+
for (const modelId of modelIds) {
|
|
346
347
|
let profile;
|
|
347
348
|
try {
|
|
348
349
|
profile = opts.profilesById(modelId);
|
|
@@ -386,7 +387,7 @@ function passScoreTargets(ir, opts) {
|
|
|
386
387
|
}
|
|
387
388
|
const baseQuality = profile.strengths.includes("reasoning") ? 0.85 : profile.strengths.includes("quality") ? 0.8 : 0.6;
|
|
388
389
|
const qualityScore = Math.max(0, baseQuality - qualityPenalty);
|
|
389
|
-
const callerOrderBoost = (
|
|
390
|
+
const callerOrderBoost = (modelIds.length - modelIds.indexOf(modelId)) * 0.1;
|
|
390
391
|
const costPenalty = estimatedCostUsd * 5;
|
|
391
392
|
const preferredBoost = preferredSet.has(modelId) ? 0.5 : 0;
|
|
392
393
|
const rank = qualityScore + callerOrderBoost - costPenalty - reasons.length * 10 + preferredBoost;
|
|
@@ -944,6 +945,393 @@ function defaultOnError(err) {
|
|
|
944
945
|
);
|
|
945
946
|
}
|
|
946
947
|
|
|
948
|
+
// src/promote-ready-brain.ts
|
|
949
|
+
function isRawPromoteReadyRow(x) {
|
|
950
|
+
if (!x || typeof x !== "object") return false;
|
|
951
|
+
const r = x;
|
|
952
|
+
return typeof r.intent_archetype === "string" && typeof r.family === "string" && typeof r.candidate_model === "string" && typeof r.current_model === "string" && typeof r.detected_at === "string";
|
|
953
|
+
}
|
|
954
|
+
function coerceNumber(v) {
|
|
955
|
+
if (typeof v === "number") return Number.isFinite(v) ? v : null;
|
|
956
|
+
if (typeof v === "string") {
|
|
957
|
+
const n = Number(v);
|
|
958
|
+
return Number.isFinite(n) ? n : null;
|
|
959
|
+
}
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
function mapRowsToFindings2(rows) {
|
|
963
|
+
const out = [];
|
|
964
|
+
for (const row of rows) {
|
|
965
|
+
if (!isRawPromoteReadyRow(row)) continue;
|
|
966
|
+
const sampleN = coerceNumber(row.sample_n);
|
|
967
|
+
const passRate = coerceNumber(row.judge_pass_rate);
|
|
968
|
+
const avgScore = coerceNumber(row.judge_avg_score);
|
|
969
|
+
if (sampleN === null || passRate === null || avgScore === null) continue;
|
|
970
|
+
out.push({
|
|
971
|
+
archetype: row.intent_archetype,
|
|
972
|
+
family: row.family,
|
|
973
|
+
candidateModel: row.candidate_model,
|
|
974
|
+
currentModel: row.current_model,
|
|
975
|
+
sampleN,
|
|
976
|
+
judgePassRate: passRate,
|
|
977
|
+
judgeAvgScore: avgScore,
|
|
978
|
+
costDeltaPct: coerceNumber(row.cost_delta_pct),
|
|
979
|
+
detectedAt: row.detected_at
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
return out;
|
|
983
|
+
}
|
|
984
|
+
var snapshots2 = /* @__PURE__ */ new Map();
|
|
985
|
+
var runtime2;
|
|
986
|
+
var warnedOnce2 = false;
|
|
987
|
+
function isPromoteReadyBrainActive() {
|
|
988
|
+
return runtime2 !== void 0;
|
|
989
|
+
}
|
|
990
|
+
function loadPromoteReadyFindings(opts) {
|
|
991
|
+
const rt = runtime2;
|
|
992
|
+
if (!rt) return [];
|
|
993
|
+
const appId = opts.appId;
|
|
994
|
+
if (!appId) return [];
|
|
995
|
+
let snap = snapshots2.get(appId);
|
|
996
|
+
if (!snap) {
|
|
997
|
+
snap = { data: [], expiresAt: 0, refreshing: false };
|
|
998
|
+
snapshots2.set(appId, snap);
|
|
999
|
+
}
|
|
1000
|
+
const now = Date.now();
|
|
1001
|
+
const stale = snap.expiresAt <= now;
|
|
1002
|
+
if (stale && !snap.refreshing) {
|
|
1003
|
+
snap.refreshing = true;
|
|
1004
|
+
void asyncRefresh2(rt, appId);
|
|
1005
|
+
}
|
|
1006
|
+
let rows = snap.data;
|
|
1007
|
+
if (opts.archetype) {
|
|
1008
|
+
rows = rows.filter((f) => f.archetype === opts.archetype);
|
|
1009
|
+
}
|
|
1010
|
+
if (opts.family) {
|
|
1011
|
+
rows = rows.filter((f) => f.family === opts.family);
|
|
1012
|
+
}
|
|
1013
|
+
return rows;
|
|
1014
|
+
}
|
|
1015
|
+
var pendingRefreshes2 = /* @__PURE__ */ new Map();
|
|
1016
|
+
async function asyncRefresh2(rt, appId) {
|
|
1017
|
+
const promise = doRefresh2(rt, appId);
|
|
1018
|
+
pendingRefreshes2.set(appId, promise);
|
|
1019
|
+
try {
|
|
1020
|
+
await promise;
|
|
1021
|
+
} finally {
|
|
1022
|
+
if (pendingRefreshes2.get(appId) === promise) {
|
|
1023
|
+
pendingRefreshes2.delete(appId);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
async function doRefresh2(rt, appId) {
|
|
1028
|
+
const url = `${rt.endpoint}?app_id=${encodeURIComponent(appId)}`;
|
|
1029
|
+
let snap = snapshots2.get(appId);
|
|
1030
|
+
if (!snap) {
|
|
1031
|
+
snap = { data: [], expiresAt: 0, refreshing: false };
|
|
1032
|
+
snapshots2.set(appId, snap);
|
|
1033
|
+
}
|
|
1034
|
+
try {
|
|
1035
|
+
const res = await rt.fetchImpl(url, { method: "GET" });
|
|
1036
|
+
if (!res.ok) {
|
|
1037
|
+
throw new Error(`promote-ready ${res.status}: ${res.statusText}`);
|
|
1038
|
+
}
|
|
1039
|
+
const body = await res.json();
|
|
1040
|
+
if (runtime2 !== rt) return;
|
|
1041
|
+
const rows = Array.isArray(body) ? mapRowsToFindings2(body) : [];
|
|
1042
|
+
snap.data = rows;
|
|
1043
|
+
snap.expiresAt = Date.now() + rt.ttlMs;
|
|
1044
|
+
snap.refreshing = false;
|
|
1045
|
+
} catch (err) {
|
|
1046
|
+
if (runtime2 !== rt) return;
|
|
1047
|
+
snap.refreshing = false;
|
|
1048
|
+
snap.expiresAt = Date.now() + rt.ttlMs;
|
|
1049
|
+
if (!warnedOnce2) {
|
|
1050
|
+
warnedOnce2 = true;
|
|
1051
|
+
(rt.onError ?? defaultOnError2)(err);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
function defaultOnError2(err) {
|
|
1056
|
+
console.warn(
|
|
1057
|
+
"[kgauto] promote-ready fetch failed (using empty fallback):",
|
|
1058
|
+
err
|
|
1059
|
+
);
|
|
1060
|
+
}
|
|
1061
|
+
function resolveFetchImpl(injected) {
|
|
1062
|
+
return injected ?? ((...args) => globalThis.fetch(...args));
|
|
1063
|
+
}
|
|
1064
|
+
function normalizeEndpoint(endpoint) {
|
|
1065
|
+
return endpoint.replace(/\/+$/, "");
|
|
1066
|
+
}
|
|
1067
|
+
async function markPromoteReadyHandled(opts) {
|
|
1068
|
+
const {
|
|
1069
|
+
appId,
|
|
1070
|
+
archetype,
|
|
1071
|
+
family,
|
|
1072
|
+
resolution,
|
|
1073
|
+
resolutionNote,
|
|
1074
|
+
brainEndpoint,
|
|
1075
|
+
brainJwt,
|
|
1076
|
+
brainAnonKey,
|
|
1077
|
+
fetch: injectedFetch
|
|
1078
|
+
} = opts;
|
|
1079
|
+
if (!appId) return { ok: false, reason: "app_id_required" };
|
|
1080
|
+
if (!archetype) return { ok: false, reason: "archetype_required" };
|
|
1081
|
+
if (!family) return { ok: false, reason: "family_required" };
|
|
1082
|
+
if (resolution !== "promoted" && resolution !== "declined" && resolution !== "still-evaluating") {
|
|
1083
|
+
return { ok: false, reason: "resolution_invalid" };
|
|
1084
|
+
}
|
|
1085
|
+
const doFetch = resolveFetchImpl(injectedFetch);
|
|
1086
|
+
const base = normalizeEndpoint(brainEndpoint);
|
|
1087
|
+
const url = `${base}/rest/v1/promote_ready_findings?app_id=eq.${encodeURIComponent(appId)}&intent_archetype=eq.${encodeURIComponent(archetype)}&family=eq.${encodeURIComponent(family)}&resolved_at=is.null`;
|
|
1088
|
+
const patchBody = {
|
|
1089
|
+
resolved_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1090
|
+
resolution
|
|
1091
|
+
};
|
|
1092
|
+
if (resolutionNote !== void 0) {
|
|
1093
|
+
patchBody.resolution_note = resolutionNote;
|
|
1094
|
+
}
|
|
1095
|
+
let res;
|
|
1096
|
+
try {
|
|
1097
|
+
res = await doFetch(url, {
|
|
1098
|
+
method: "PATCH",
|
|
1099
|
+
headers: {
|
|
1100
|
+
Authorization: `Bearer ${brainJwt}`,
|
|
1101
|
+
apikey: brainAnonKey,
|
|
1102
|
+
"Content-Type": "application/json",
|
|
1103
|
+
Accept: "application/json",
|
|
1104
|
+
Prefer: "return=minimal"
|
|
1105
|
+
},
|
|
1106
|
+
body: JSON.stringify(patchBody)
|
|
1107
|
+
});
|
|
1108
|
+
} catch (err) {
|
|
1109
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1110
|
+
return { ok: false, reason: `network_error:${msg}` };
|
|
1111
|
+
}
|
|
1112
|
+
if (res.status === 401 || res.status === 403) {
|
|
1113
|
+
return { ok: false, reason: "brain_auth_misconfig" };
|
|
1114
|
+
}
|
|
1115
|
+
if (res.status >= 500) {
|
|
1116
|
+
return { ok: false, reason: "brain_unavailable" };
|
|
1117
|
+
}
|
|
1118
|
+
if (!res.ok) {
|
|
1119
|
+
return { ok: false, reason: `patch_failed:${res.status}` };
|
|
1120
|
+
}
|
|
1121
|
+
return { ok: true };
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// src/advisor-rules/promote-ready.ts
|
|
1125
|
+
var PROMOTE_READY_THRESHOLDS = {
|
|
1126
|
+
minPassRate: 0.8,
|
|
1127
|
+
minAvgScore: 4
|
|
1128
|
+
};
|
|
1129
|
+
function shouldFirePromoteReady(finding, resolvedPrimary) {
|
|
1130
|
+
if (finding.currentModel !== resolvedPrimary) return false;
|
|
1131
|
+
if (finding.judgePassRate < PROMOTE_READY_THRESHOLDS.minPassRate) return false;
|
|
1132
|
+
if (finding.judgeAvgScore < PROMOTE_READY_THRESHOLDS.minAvgScore) return false;
|
|
1133
|
+
return true;
|
|
1134
|
+
}
|
|
1135
|
+
function deriveFamilyLocal(modelId) {
|
|
1136
|
+
if (modelId.startsWith("claude-opus-")) return "claude-opus";
|
|
1137
|
+
if (modelId.startsWith("claude-sonnet-")) return "claude-sonnet";
|
|
1138
|
+
if (modelId.startsWith("claude-haiku-")) return "claude-haiku";
|
|
1139
|
+
if (/^gemini-.*-flash-lite/.test(modelId)) return "gemini-flash-lite";
|
|
1140
|
+
if (/^gemini-.*-flash/.test(modelId)) return "gemini-flash";
|
|
1141
|
+
if (/^gemini-.*-pro/.test(modelId)) return "gemini-pro";
|
|
1142
|
+
if (/^deepseek-.*-pro/.test(modelId)) return "deepseek-reasoner";
|
|
1143
|
+
if (modelId.startsWith("deepseek-")) return "deepseek-chat";
|
|
1144
|
+
if (modelId.startsWith("gpt-")) return "openai-gpt";
|
|
1145
|
+
return null;
|
|
1146
|
+
}
|
|
1147
|
+
function advisorRulePromoteReady(ctx) {
|
|
1148
|
+
if (!isPromoteReadyBrainActive()) return [];
|
|
1149
|
+
if (!ctx.appId) return [];
|
|
1150
|
+
if (!ctx.resolvedPrimary) return [];
|
|
1151
|
+
const family = deriveFamilyLocal(ctx.resolvedPrimary);
|
|
1152
|
+
if (!family) return [];
|
|
1153
|
+
const findings = loadPromoteReadyFindings({
|
|
1154
|
+
appId: ctx.appId,
|
|
1155
|
+
archetype: ctx.archetype,
|
|
1156
|
+
family
|
|
1157
|
+
});
|
|
1158
|
+
if (findings.length === 0) return [];
|
|
1159
|
+
const qualifying = findings.filter(
|
|
1160
|
+
(f) => shouldFirePromoteReady(f, ctx.resolvedPrimary)
|
|
1161
|
+
);
|
|
1162
|
+
if (qualifying.length === 0) return [];
|
|
1163
|
+
qualifying.sort((a, b) => {
|
|
1164
|
+
if (a.judgeAvgScore !== b.judgeAvgScore) {
|
|
1165
|
+
return b.judgeAvgScore - a.judgeAvgScore;
|
|
1166
|
+
}
|
|
1167
|
+
return b.judgePassRate - a.judgePassRate;
|
|
1168
|
+
});
|
|
1169
|
+
const top = qualifying[0];
|
|
1170
|
+
const pctPass = Math.round(top.judgePassRate * 100);
|
|
1171
|
+
const score = top.judgeAvgScore.toFixed(2);
|
|
1172
|
+
let costClause = "";
|
|
1173
|
+
if (top.costDeltaPct !== null) {
|
|
1174
|
+
const sign = top.costDeltaPct < 0 ? "cheaper" : "more expensive";
|
|
1175
|
+
const magnitude = Math.abs(top.costDeltaPct * 100).toFixed(1);
|
|
1176
|
+
costClause = `, cost ${magnitude}% ${sign}`;
|
|
1177
|
+
}
|
|
1178
|
+
const message = `Probe found ${top.candidateModel} produces equivalent-or-better outputs vs ${top.currentModel} on ${top.sampleN} recent ${top.archetype} prompts (pass rate ${pctPass}%, avg score ${score}/5${costClause}). Consider promoting via markPromoteReadyHandled.`;
|
|
1179
|
+
return [
|
|
1180
|
+
{
|
|
1181
|
+
level: "info",
|
|
1182
|
+
code: "promote-ready",
|
|
1183
|
+
message,
|
|
1184
|
+
suggestion: `Migrate ${top.archetype} traffic from ${top.currentModel} to ${top.candidateModel}, then call markPromoteReadyHandled({ appId, archetype: '${top.archetype}', family: '${top.family}', resolution: 'promoted' }) to silence this advisory.`,
|
|
1185
|
+
// alpha.36 architectural field — not a no-ai-needed case.
|
|
1186
|
+
recommendedArchitecture: void 0,
|
|
1187
|
+
docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
|
|
1188
|
+
}
|
|
1189
|
+
];
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
// src/advisor-rules/consumer-on-stale-model.ts
|
|
1193
|
+
function isStaleStatus(v) {
|
|
1194
|
+
return v === "legacy" || v === "deprecated";
|
|
1195
|
+
}
|
|
1196
|
+
function asString(v) {
|
|
1197
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
1198
|
+
}
|
|
1199
|
+
function mapRowsToFindings3(rows) {
|
|
1200
|
+
const out = [];
|
|
1201
|
+
for (const raw of rows) {
|
|
1202
|
+
if (!raw || typeof raw !== "object") continue;
|
|
1203
|
+
const r = raw;
|
|
1204
|
+
const archetype = asString(r.intent_archetype) ?? asString(r.applies_to_archetype);
|
|
1205
|
+
const staleModel = asString(r.stale_model) ?? asString(r.applies_to_model);
|
|
1206
|
+
const staleProvider = asString(r.stale_provider);
|
|
1207
|
+
const recommendedModel = asString(r.recommended_model);
|
|
1208
|
+
const family = asString(r.family);
|
|
1209
|
+
const message = asString(r.message);
|
|
1210
|
+
if (!archetype || !staleModel || !recommendedModel || !family || !message) {
|
|
1211
|
+
continue;
|
|
1212
|
+
}
|
|
1213
|
+
if (!isStaleStatus(r.stale_status)) continue;
|
|
1214
|
+
const row = {
|
|
1215
|
+
archetype,
|
|
1216
|
+
staleModel,
|
|
1217
|
+
staleProvider: staleProvider ?? "unknown",
|
|
1218
|
+
staleStatus: r.stale_status,
|
|
1219
|
+
recommendedModel,
|
|
1220
|
+
family,
|
|
1221
|
+
message
|
|
1222
|
+
};
|
|
1223
|
+
const suggestion = asString(r.suggestion);
|
|
1224
|
+
if (suggestion) row.suggestion = suggestion;
|
|
1225
|
+
if (typeof r.observation_count === "number" && Number.isFinite(r.observation_count)) {
|
|
1226
|
+
row.observationCount = r.observation_count;
|
|
1227
|
+
}
|
|
1228
|
+
out.push(row);
|
|
1229
|
+
}
|
|
1230
|
+
return out;
|
|
1231
|
+
}
|
|
1232
|
+
var snapshots3 = /* @__PURE__ */ new Map();
|
|
1233
|
+
var runtime3;
|
|
1234
|
+
var warnedOnce3 = false;
|
|
1235
|
+
var pendingRefreshes3 = /* @__PURE__ */ new Map();
|
|
1236
|
+
function isStaleModelFindingsBrainActive() {
|
|
1237
|
+
return runtime3 !== void 0;
|
|
1238
|
+
}
|
|
1239
|
+
function getStaleModelFindings(opts) {
|
|
1240
|
+
const rt = runtime3;
|
|
1241
|
+
if (!rt) return [];
|
|
1242
|
+
const appId = opts.appId;
|
|
1243
|
+
if (!appId) return [];
|
|
1244
|
+
let snap = snapshots3.get(appId);
|
|
1245
|
+
if (!snap) {
|
|
1246
|
+
snap = { data: [], expiresAt: 0, refreshing: false };
|
|
1247
|
+
snapshots3.set(appId, snap);
|
|
1248
|
+
}
|
|
1249
|
+
const now = Date.now();
|
|
1250
|
+
const stale = snap.expiresAt <= now;
|
|
1251
|
+
if (stale && !snap.refreshing) {
|
|
1252
|
+
snap.refreshing = true;
|
|
1253
|
+
void asyncRefresh3(rt, appId);
|
|
1254
|
+
}
|
|
1255
|
+
if (opts.archetype) {
|
|
1256
|
+
return snap.data.filter((f) => f.archetype === opts.archetype);
|
|
1257
|
+
}
|
|
1258
|
+
return snap.data;
|
|
1259
|
+
}
|
|
1260
|
+
async function asyncRefresh3(rt, appId) {
|
|
1261
|
+
const promise = doRefresh3(rt, appId);
|
|
1262
|
+
pendingRefreshes3.set(appId, promise);
|
|
1263
|
+
try {
|
|
1264
|
+
await promise;
|
|
1265
|
+
} finally {
|
|
1266
|
+
if (pendingRefreshes3.get(appId) === promise) {
|
|
1267
|
+
pendingRefreshes3.delete(appId);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
async function doRefresh3(rt, appId) {
|
|
1272
|
+
const url = `${rt.endpoint}?app_id=${encodeURIComponent(appId)}`;
|
|
1273
|
+
let snap = snapshots3.get(appId);
|
|
1274
|
+
if (!snap) {
|
|
1275
|
+
snap = { data: [], expiresAt: 0, refreshing: false };
|
|
1276
|
+
snapshots3.set(appId, snap);
|
|
1277
|
+
}
|
|
1278
|
+
try {
|
|
1279
|
+
const res = await rt.fetchImpl(url, { method: "GET" });
|
|
1280
|
+
if (!res.ok) {
|
|
1281
|
+
throw new Error(`stale-model findings ${res.status}: ${res.statusText}`);
|
|
1282
|
+
}
|
|
1283
|
+
const body = await res.json();
|
|
1284
|
+
if (runtime3 !== rt) return;
|
|
1285
|
+
const rows = Array.isArray(body) ? mapRowsToFindings3(body) : [];
|
|
1286
|
+
snap.data = rows;
|
|
1287
|
+
snap.expiresAt = Date.now() + rt.ttlMs;
|
|
1288
|
+
snap.refreshing = false;
|
|
1289
|
+
} catch (err) {
|
|
1290
|
+
if (runtime3 !== rt) return;
|
|
1291
|
+
snap.refreshing = false;
|
|
1292
|
+
snap.expiresAt = Date.now() + rt.ttlMs;
|
|
1293
|
+
if (!warnedOnce3) {
|
|
1294
|
+
warnedOnce3 = true;
|
|
1295
|
+
(rt.onError ?? defaultOnError3)(err);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
function defaultOnError3(err) {
|
|
1300
|
+
console.warn(
|
|
1301
|
+
"[kgauto] stale-model findings fetch failed (using empty fallback):",
|
|
1302
|
+
err
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
var CONSUMER_ON_STALE_MODEL_RULE_CODE = "consumer-on-stale-model";
|
|
1306
|
+
function advisorRuleConsumerOnStaleModel(ir) {
|
|
1307
|
+
if (!isStaleModelFindingsBrainActive()) return [];
|
|
1308
|
+
if (!ir.appId) return [];
|
|
1309
|
+
const findings = getStaleModelFindings({
|
|
1310
|
+
appId: ir.appId,
|
|
1311
|
+
archetype: ir.intent.archetype
|
|
1312
|
+
});
|
|
1313
|
+
if (findings.length === 0) return [];
|
|
1314
|
+
const ranked = [...findings].sort((a, b) => {
|
|
1315
|
+
if (a.staleStatus !== b.staleStatus) {
|
|
1316
|
+
return a.staleStatus === "deprecated" ? -1 : 1;
|
|
1317
|
+
}
|
|
1318
|
+
return a.staleModel.localeCompare(b.staleModel);
|
|
1319
|
+
});
|
|
1320
|
+
const top = ranked[0];
|
|
1321
|
+
const extraCount = findings.length - 1;
|
|
1322
|
+
const extraNote = extraCount > 0 ? ` (+ ${extraCount} more stale model${extraCount === 1 ? "" : "s"} for this archetype)` : "";
|
|
1323
|
+
return [
|
|
1324
|
+
{
|
|
1325
|
+
level: "warn",
|
|
1326
|
+
code: CONSUMER_ON_STALE_MODEL_RULE_CODE,
|
|
1327
|
+
message: `${top.message}${extraNote}`,
|
|
1328
|
+
suggestion: top.suggestion ?? `Migrate ${top.staleModel} \u2192 ${top.recommendedModel} for archetype "${top.archetype}". The newer model is the current latest in the "${top.family}" family; the stale one is ${top.staleStatus}.`,
|
|
1329
|
+
recommendationType: "model-swap",
|
|
1330
|
+
docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
|
|
1331
|
+
}
|
|
1332
|
+
];
|
|
1333
|
+
}
|
|
1334
|
+
|
|
947
1335
|
// src/advisor.ts
|
|
948
1336
|
var QUALITY_FLOOR_FOR_RECOMMENDATION = 6;
|
|
949
1337
|
var TIER_DOWN_COST_RATIO = 0.5;
|
|
@@ -966,6 +1354,16 @@ function runAdvisor(ir, result, profile, policy, phase2) {
|
|
|
966
1354
|
if (policy?.posture !== "locked") {
|
|
967
1355
|
out.push(...detectStaleExclusionCandidate(ir));
|
|
968
1356
|
}
|
|
1357
|
+
if (policy?.posture !== "locked" && ir.appId) {
|
|
1358
|
+
out.push(
|
|
1359
|
+
...advisorRulePromoteReady({
|
|
1360
|
+
appId: ir.appId,
|
|
1361
|
+
archetype: ir.intent.archetype,
|
|
1362
|
+
resolvedPrimary: profile.id
|
|
1363
|
+
})
|
|
1364
|
+
);
|
|
1365
|
+
out.push(...advisorRuleConsumerOnStaleModel(ir));
|
|
1366
|
+
}
|
|
969
1367
|
return out;
|
|
970
1368
|
}
|
|
971
1369
|
function translatorClearedToolCallCliff(phase2) {
|
|
@@ -1277,6 +1675,261 @@ ${originalText}`;
|
|
|
1277
1675
|
return { rewrittenIR, rewrites };
|
|
1278
1676
|
}
|
|
1279
1677
|
|
|
1678
|
+
// src/models-brain.ts
|
|
1679
|
+
function isModelRow(x) {
|
|
1680
|
+
if (!x || typeof x !== "object") return false;
|
|
1681
|
+
const r = x;
|
|
1682
|
+
return typeof r.model_id === "string" && typeof r.provider === "string";
|
|
1683
|
+
}
|
|
1684
|
+
function isAliasRow(x) {
|
|
1685
|
+
if (!x || typeof x !== "object") return false;
|
|
1686
|
+
const r = x;
|
|
1687
|
+
return typeof r.alias_id === "string" && typeof r.canonical_id === "string";
|
|
1688
|
+
}
|
|
1689
|
+
function rowToProfile(row) {
|
|
1690
|
+
try {
|
|
1691
|
+
if (row.cliffs !== void 0 && row.cliffs !== null && !Array.isArray(row.cliffs)) {
|
|
1692
|
+
return null;
|
|
1693
|
+
}
|
|
1694
|
+
if (row.recovery !== void 0 && row.recovery !== null && !Array.isArray(row.recovery)) {
|
|
1695
|
+
return null;
|
|
1696
|
+
}
|
|
1697
|
+
if (row.lowering !== void 0 && row.lowering !== null && (typeof row.lowering !== "object" || Array.isArray(row.lowering))) {
|
|
1698
|
+
return null;
|
|
1699
|
+
}
|
|
1700
|
+
return {
|
|
1701
|
+
id: row.model_id,
|
|
1702
|
+
provider: row.provider,
|
|
1703
|
+
status: row.status ?? "current",
|
|
1704
|
+
maxContextTokens: row.max_context_tokens ?? 0,
|
|
1705
|
+
maxOutputTokens: row.max_output_tokens ?? 0,
|
|
1706
|
+
maxTools: row.max_tools ?? 0,
|
|
1707
|
+
parallelToolCalls: row.parallel_tool_calls ?? false,
|
|
1708
|
+
structuredOutput: row.structured_output ?? "none",
|
|
1709
|
+
systemPromptMode: row.system_prompt_mode ?? "inline",
|
|
1710
|
+
streaming: row.streaming ?? true,
|
|
1711
|
+
cliffs: row.cliffs ?? [],
|
|
1712
|
+
costInputPer1m: row.cost_input_per_1m ?? 0,
|
|
1713
|
+
costOutputPer1m: row.cost_output_per_1m ?? 0,
|
|
1714
|
+
lowering: row.lowering ?? { system: { mode: "inline" }, cache: { strategy: "unsupported" } },
|
|
1715
|
+
recovery: row.recovery ?? [],
|
|
1716
|
+
strengths: row.strengths ?? [],
|
|
1717
|
+
weaknesses: row.weaknesses ?? [],
|
|
1718
|
+
notes: row.notes ?? void 0,
|
|
1719
|
+
verifiedAgainstDocs: row.verified_against_docs ?? void 0,
|
|
1720
|
+
archetypePerf: row.archetype_perf ?? void 0,
|
|
1721
|
+
// alpha.41 — family-resolution fields. `family` may be null pre-
|
|
1722
|
+
// migration 024; runtime falls back to deriveFamilyFromModelId at
|
|
1723
|
+
// resolution time (see family-resolution.ts, G1).
|
|
1724
|
+
family: row.family ?? void 0,
|
|
1725
|
+
versionAdded: row.version_added ?? void 0,
|
|
1726
|
+
active: row.active ?? void 0
|
|
1727
|
+
};
|
|
1728
|
+
} catch {
|
|
1729
|
+
return null;
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
function profileToRow(profile, opts = {}) {
|
|
1733
|
+
const row = {
|
|
1734
|
+
model_id: profile.id,
|
|
1735
|
+
provider: profile.provider,
|
|
1736
|
+
status: profile.status,
|
|
1737
|
+
max_context_tokens: profile.maxContextTokens,
|
|
1738
|
+
max_output_tokens: profile.maxOutputTokens,
|
|
1739
|
+
max_tools: profile.maxTools,
|
|
1740
|
+
parallel_tool_calls: profile.parallelToolCalls,
|
|
1741
|
+
structured_output: profile.structuredOutput,
|
|
1742
|
+
system_prompt_mode: profile.systemPromptMode,
|
|
1743
|
+
streaming: profile.streaming,
|
|
1744
|
+
cliffs: profile.cliffs,
|
|
1745
|
+
cost_input_per_1m: profile.costInputPer1m,
|
|
1746
|
+
cost_output_per_1m: profile.costOutputPer1m,
|
|
1747
|
+
lowering: profile.lowering,
|
|
1748
|
+
recovery: profile.recovery,
|
|
1749
|
+
strengths: profile.strengths,
|
|
1750
|
+
weaknesses: profile.weaknesses,
|
|
1751
|
+
notes: profile.notes ?? null,
|
|
1752
|
+
archetype_perf: profile.archetypePerf ?? null,
|
|
1753
|
+
active: opts.active ?? profile.active ?? true,
|
|
1754
|
+
// alpha.41 — round-trip family + version_added when present on profile.
|
|
1755
|
+
// version_added is operator-controlled via opts; profile-side value is
|
|
1756
|
+
// used only when opts didn't override.
|
|
1757
|
+
family: profile.family ?? null
|
|
1758
|
+
};
|
|
1759
|
+
if (opts.verifiedAgainstDocs !== void 0) {
|
|
1760
|
+
row.verified_against_docs = opts.verifiedAgainstDocs;
|
|
1761
|
+
} else if (profile.verifiedAgainstDocs !== void 0) {
|
|
1762
|
+
const v = profile.verifiedAgainstDocs;
|
|
1763
|
+
row.verified_against_docs = /^\d{4}-\d{2}-\d{2}/.test(v) ? v : null;
|
|
1764
|
+
}
|
|
1765
|
+
if (opts.versionAdded !== void 0) row.version_added = opts.versionAdded;
|
|
1766
|
+
else if (profile.versionAdded !== void 0) row.version_added = profile.versionAdded;
|
|
1767
|
+
if (opts.versionRemoved !== void 0) row.version_removed = opts.versionRemoved;
|
|
1768
|
+
return row;
|
|
1769
|
+
}
|
|
1770
|
+
function mapRowsToModels(rows) {
|
|
1771
|
+
const out = /* @__PURE__ */ new Map();
|
|
1772
|
+
for (const row of rows) {
|
|
1773
|
+
if (!isModelRow(row)) continue;
|
|
1774
|
+
const profile = rowToProfile(row);
|
|
1775
|
+
if (profile) out.set(profile.id, profile);
|
|
1776
|
+
}
|
|
1777
|
+
return out;
|
|
1778
|
+
}
|
|
1779
|
+
function mapRowsToAliases(rows) {
|
|
1780
|
+
const out = {};
|
|
1781
|
+
for (const row of rows) {
|
|
1782
|
+
if (!isAliasRow(row)) continue;
|
|
1783
|
+
out[row.alias_id] = row.canonical_id;
|
|
1784
|
+
}
|
|
1785
|
+
return out;
|
|
1786
|
+
}
|
|
1787
|
+
function bundledModels() {
|
|
1788
|
+
return new Map(allProfilesRaw().map((p) => [p.id, p]));
|
|
1789
|
+
}
|
|
1790
|
+
function bundledAliases() {
|
|
1791
|
+
return { ...ALIASES };
|
|
1792
|
+
}
|
|
1793
|
+
var loadModelsFromBrain = createBrainQueryCache({
|
|
1794
|
+
table: "kgauto_models",
|
|
1795
|
+
mapRows: mapRowsToModels,
|
|
1796
|
+
bundledFallback: bundledModels
|
|
1797
|
+
});
|
|
1798
|
+
var loadAliasesFromBrain = createBrainQueryCache({
|
|
1799
|
+
table: "kgauto_aliases",
|
|
1800
|
+
mapRows: mapRowsToAliases,
|
|
1801
|
+
bundledFallback: bundledAliases
|
|
1802
|
+
});
|
|
1803
|
+
_setProfileBrainHook({
|
|
1804
|
+
getProfile: (canonical) => loadModelsFromBrain().get(canonical),
|
|
1805
|
+
resolveAlias: (id) => loadAliasesFromBrain()[id]
|
|
1806
|
+
});
|
|
1807
|
+
|
|
1808
|
+
// src/family-resolution.ts
|
|
1809
|
+
var FamilyResolutionError = class extends Error {
|
|
1810
|
+
family;
|
|
1811
|
+
cause;
|
|
1812
|
+
constructor(family, cause) {
|
|
1813
|
+
super(
|
|
1814
|
+
`Family "${family}" did not resolve to any current+active model. ${cause}. Pass a literal model id in ir.models, or call getRecommendedPrimary({ family, fallback }) at IR-construction time.`
|
|
1815
|
+
);
|
|
1816
|
+
this.name = "FamilyResolutionError";
|
|
1817
|
+
this.family = family;
|
|
1818
|
+
this.cause = cause;
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
1821
|
+
function deriveFamilyFromModelId(modelId) {
|
|
1822
|
+
if (typeof modelId !== "string" || modelId.length === 0) return null;
|
|
1823
|
+
if (modelId.startsWith("claude-opus-")) return "claude-opus";
|
|
1824
|
+
if (modelId.startsWith("claude-sonnet-")) return "claude-sonnet";
|
|
1825
|
+
if (modelId.startsWith("claude-haiku-")) return "claude-haiku";
|
|
1826
|
+
if (modelId.startsWith("gemini-") && modelId.includes("flash-lite")) {
|
|
1827
|
+
return "gemini-flash-lite";
|
|
1828
|
+
}
|
|
1829
|
+
if (modelId.startsWith("gemini-") && modelId.includes("flash")) {
|
|
1830
|
+
return "gemini-flash";
|
|
1831
|
+
}
|
|
1832
|
+
if (modelId.startsWith("gemini-") && modelId.includes("pro")) {
|
|
1833
|
+
return "gemini-pro";
|
|
1834
|
+
}
|
|
1835
|
+
if (modelId.startsWith("deepseek-") && modelId.includes("pro")) {
|
|
1836
|
+
return "deepseek-reasoner";
|
|
1837
|
+
}
|
|
1838
|
+
if (modelId.startsWith("deepseek-")) return "deepseek-chat";
|
|
1839
|
+
if (modelId.startsWith("gpt-")) return "openai-gpt";
|
|
1840
|
+
return null;
|
|
1841
|
+
}
|
|
1842
|
+
function familyOf(profile) {
|
|
1843
|
+
return profile.family ?? deriveFamilyFromModelId(profile.id);
|
|
1844
|
+
}
|
|
1845
|
+
function archetypePerfFor(profile, archetype) {
|
|
1846
|
+
if (!archetype) return 0;
|
|
1847
|
+
const score = profile.archetypePerf?.[archetype];
|
|
1848
|
+
return typeof score === "number" ? score : 5;
|
|
1849
|
+
}
|
|
1850
|
+
function selectCandidates(registry, family, archetype, appId) {
|
|
1851
|
+
const out = [];
|
|
1852
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
1853
|
+
if (appId && archetype) {
|
|
1854
|
+
const findings = getStaleExclusionFindings({ appId, archetype });
|
|
1855
|
+
for (const f of findings) {
|
|
1856
|
+
if (f.verdict === "stay-excluded") excluded.add(f.excludedModel);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
for (const profile of registry.values()) {
|
|
1860
|
+
if (familyOf(profile) !== family) continue;
|
|
1861
|
+
if (profile.status !== "current") continue;
|
|
1862
|
+
if (profile.active === false) continue;
|
|
1863
|
+
if (archetype) {
|
|
1864
|
+
if (archetypePerfFor(profile, archetype) < ARCHETYPE_FLOOR_DEFAULT) continue;
|
|
1865
|
+
}
|
|
1866
|
+
if (excluded.has(profile.id)) continue;
|
|
1867
|
+
out.push(profile);
|
|
1868
|
+
}
|
|
1869
|
+
return out;
|
|
1870
|
+
}
|
|
1871
|
+
function sortCandidates(candidates, archetype) {
|
|
1872
|
+
const sorted = [...candidates];
|
|
1873
|
+
sorted.sort((a, b) => {
|
|
1874
|
+
const perfA = archetypePerfFor(a, archetype);
|
|
1875
|
+
const perfB = archetypePerfFor(b, archetype);
|
|
1876
|
+
if (perfA !== perfB) return perfB - perfA;
|
|
1877
|
+
const vA = a.versionAdded ?? "";
|
|
1878
|
+
const vB = b.versionAdded ?? "";
|
|
1879
|
+
if (vA !== vB) return vA < vB ? 1 : -1;
|
|
1880
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
1881
|
+
});
|
|
1882
|
+
return sorted;
|
|
1883
|
+
}
|
|
1884
|
+
function getRecommendedPrimary(opts) {
|
|
1885
|
+
if (opts.posture === "locked") return opts.fallback;
|
|
1886
|
+
const registry = loadModelsFromBrain();
|
|
1887
|
+
const candidates = selectCandidates(
|
|
1888
|
+
registry,
|
|
1889
|
+
opts.family,
|
|
1890
|
+
opts.archetype,
|
|
1891
|
+
opts.appId
|
|
1892
|
+
);
|
|
1893
|
+
if (candidates.length === 0) return opts.fallback;
|
|
1894
|
+
const sorted = sortCandidates(candidates, opts.archetype);
|
|
1895
|
+
return sorted[0]?.id ?? opts.fallback;
|
|
1896
|
+
}
|
|
1897
|
+
function resolveFamilyEntry(family, ctx) {
|
|
1898
|
+
if (typeof family !== "string" || family.length === 0) {
|
|
1899
|
+
throw new FamilyResolutionError(
|
|
1900
|
+
String(family),
|
|
1901
|
+
"Family tag must be a non-empty string"
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1904
|
+
const registry = loadModelsFromBrain();
|
|
1905
|
+
const candidates = selectCandidates(
|
|
1906
|
+
registry,
|
|
1907
|
+
family,
|
|
1908
|
+
ctx.archetype,
|
|
1909
|
+
ctx.appId
|
|
1910
|
+
);
|
|
1911
|
+
if (candidates.length === 0) {
|
|
1912
|
+
let anyInFamily = false;
|
|
1913
|
+
for (const profile of registry.values()) {
|
|
1914
|
+
if (familyOf(profile) === family) {
|
|
1915
|
+
anyInFamily = true;
|
|
1916
|
+
break;
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
const cause = anyInFamily ? `Family has registered models but none are current+active${ctx.archetype ? ` at archetype-perf >= ${ARCHETYPE_FLOOR_DEFAULT} for "${ctx.archetype}"` : ""}${ctx.appId ? ` and not excluded for app "${ctx.appId}"` : ""}` : `No models in brain registry carry family="${family}". Check the taxonomy table in family-resolution.ts or migration 024`;
|
|
1920
|
+
throw new FamilyResolutionError(family, cause);
|
|
1921
|
+
}
|
|
1922
|
+
const sorted = sortCandidates(candidates, ctx.archetype);
|
|
1923
|
+
const winner = sorted[0];
|
|
1924
|
+
if (!winner) {
|
|
1925
|
+
throw new FamilyResolutionError(
|
|
1926
|
+
family,
|
|
1927
|
+
"Candidates non-empty but sort returned undefined \u2014 internal invariant violation"
|
|
1928
|
+
);
|
|
1929
|
+
}
|
|
1930
|
+
return winner.id;
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1280
1933
|
// src/compile.ts
|
|
1281
1934
|
var counter = 0;
|
|
1282
1935
|
function makeHandle() {
|
|
@@ -1286,6 +1939,7 @@ function makeHandle() {
|
|
|
1286
1939
|
function compile(ir, opts = {}) {
|
|
1287
1940
|
const resolver = opts.profileResolver ?? getProfile;
|
|
1288
1941
|
validateIR(ir);
|
|
1942
|
+
ir = resolveModelEntries(ir);
|
|
1289
1943
|
const sliced = passSlice(ir);
|
|
1290
1944
|
const deduped = passDedupe(sliced.value);
|
|
1291
1945
|
const toolFiltered = passToolRelevance(deduped.value, {
|
|
@@ -1472,6 +2126,29 @@ function validateIR(ir) {
|
|
|
1472
2126
|
throw new Error("compile(): ir.sections must be an array");
|
|
1473
2127
|
}
|
|
1474
2128
|
}
|
|
2129
|
+
function resolveModelEntries(ir) {
|
|
2130
|
+
const out = [];
|
|
2131
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2132
|
+
for (const entry of ir.models) {
|
|
2133
|
+
let id;
|
|
2134
|
+
if (typeof entry === "string") {
|
|
2135
|
+
id = entry;
|
|
2136
|
+
} else if (entry && typeof entry === "object" && "family" in entry) {
|
|
2137
|
+
id = resolveFamilyEntry(entry.family, {
|
|
2138
|
+
archetype: ir.intent.archetype,
|
|
2139
|
+
appId: ir.appId
|
|
2140
|
+
});
|
|
2141
|
+
} else {
|
|
2142
|
+
throw new Error(
|
|
2143
|
+
`compile(): ir.models entry must be a string or { family: string }; got ${JSON.stringify(entry)}`
|
|
2144
|
+
);
|
|
2145
|
+
}
|
|
2146
|
+
if (seen.has(id)) continue;
|
|
2147
|
+
seen.add(id);
|
|
2148
|
+
out.push(id);
|
|
2149
|
+
}
|
|
2150
|
+
return { ...ir, models: out };
|
|
2151
|
+
}
|
|
1475
2152
|
function pickTarget(ir, scores) {
|
|
1476
2153
|
if (ir.constraints?.forceModel) {
|
|
1477
2154
|
const forced = scores.find((s) => s.modelId === ir.constraints.forceModel);
|
|
@@ -1698,7 +2375,7 @@ async function record(input) {
|
|
|
1698
2375
|
}
|
|
1699
2376
|
outcomeId = await tryExtractOutcomeId(res);
|
|
1700
2377
|
} catch (err) {
|
|
1701
|
-
(config.onError ??
|
|
2378
|
+
(config.onError ?? defaultOnError4)(err);
|
|
1702
2379
|
return;
|
|
1703
2380
|
}
|
|
1704
2381
|
const advisories = input.advisories ?? reg?.advisoriesFromCompile;
|
|
@@ -1720,7 +2397,7 @@ async function record(input) {
|
|
|
1720
2397
|
throw new Error(`brain advisories ${res.status}: ${text}`);
|
|
1721
2398
|
}
|
|
1722
2399
|
} catch (err) {
|
|
1723
|
-
(config.onError ??
|
|
2400
|
+
(config.onError ?? defaultOnError4)(err);
|
|
1724
2401
|
}
|
|
1725
2402
|
};
|
|
1726
2403
|
if (config.sync) {
|
|
@@ -1729,7 +2406,7 @@ async function record(input) {
|
|
|
1729
2406
|
void send();
|
|
1730
2407
|
}
|
|
1731
2408
|
}
|
|
1732
|
-
function
|
|
2409
|
+
function defaultOnError4(err) {
|
|
1733
2410
|
console.warn("[kgauto] brain record failed:", err);
|
|
1734
2411
|
}
|
|
1735
2412
|
function buildPayload(input, reg) {
|
|
@@ -1861,12 +2538,12 @@ async function recordOutcome(input) {
|
|
|
1861
2538
|
if (!res.ok) {
|
|
1862
2539
|
const text = await res.text().catch(() => "<no body>");
|
|
1863
2540
|
const err = new Error(`brain ${res.status}: ${text}`);
|
|
1864
|
-
(config.onError ??
|
|
2541
|
+
(config.onError ?? defaultOnError4)(err);
|
|
1865
2542
|
return { ok: false, reason: "persistence_failed" };
|
|
1866
2543
|
}
|
|
1867
2544
|
return { ok: true };
|
|
1868
2545
|
} catch (err) {
|
|
1869
|
-
(config.onError ??
|
|
2546
|
+
(config.onError ?? defaultOnError4)(err);
|
|
1870
2547
|
return { ok: false, reason: "persistence_failed" };
|
|
1871
2548
|
}
|
|
1872
2549
|
};
|
|
@@ -2421,7 +3098,13 @@ async function call(ir, opts = {}) {
|
|
|
2421
3098
|
() => emitCompileStart(traceId, ir.appId, {
|
|
2422
3099
|
appId: ir.appId,
|
|
2423
3100
|
archetype: ir.intent.archetype,
|
|
2424
|
-
|
|
3101
|
+
// alpha.41: ir.models is ChainModelEntry[] (string | { family }).
|
|
3102
|
+
// Glass-Box renderer carries string ids only; surface family entries
|
|
3103
|
+
// as their family tag prefixed so the panel still shows them in the
|
|
3104
|
+
// pre-resolution log.
|
|
3105
|
+
models: ir.models.map(
|
|
3106
|
+
(m) => typeof m === "string" ? m : `family:${m.family}`
|
|
3107
|
+
)
|
|
2425
3108
|
})
|
|
2426
3109
|
);
|
|
2427
3110
|
const initial = compileAndRegister(ir, opts);
|
|
@@ -2887,7 +3570,7 @@ var RESOLUTION_SOURCE_SET = /* @__PURE__ */ new Set([
|
|
|
2887
3570
|
"consumer-marked",
|
|
2888
3571
|
"declined"
|
|
2889
3572
|
]);
|
|
2890
|
-
function
|
|
3573
|
+
function asString2(v) {
|
|
2891
3574
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
2892
3575
|
}
|
|
2893
3576
|
function asSeverity(v) {
|
|
@@ -2909,10 +3592,10 @@ function asResolutionSource(v) {
|
|
|
2909
3592
|
return void 0;
|
|
2910
3593
|
}
|
|
2911
3594
|
function rowToAdvisory(row) {
|
|
2912
|
-
const archetype =
|
|
2913
|
-
const model =
|
|
2914
|
-
const docsLink =
|
|
2915
|
-
const suggestion =
|
|
3595
|
+
const archetype = asString2(row.applies_to_archetype);
|
|
3596
|
+
const model = asString2(row.applies_to_model);
|
|
3597
|
+
const docsLink = asString2(row.docs_url);
|
|
3598
|
+
const suggestion = asString2(row.suggestion);
|
|
2916
3599
|
let suggestedFix = null;
|
|
2917
3600
|
if (docsLink || suggestion) {
|
|
2918
3601
|
suggestedFix = { type: "manual" };
|
|
@@ -2936,18 +3619,18 @@ function rowToAdvisory(row) {
|
|
|
2936
3619
|
// reserved — alpha.30+
|
|
2937
3620
|
status: asStatus(row.status)
|
|
2938
3621
|
};
|
|
2939
|
-
const resolvedAt =
|
|
3622
|
+
const resolvedAt = asString2(row.resolved_at);
|
|
2940
3623
|
if (resolvedAt) out.resolvedAt = resolvedAt;
|
|
2941
3624
|
const resolutionSource = asResolutionSource(row.resolution_source);
|
|
2942
3625
|
if (resolutionSource) out.resolutionSource = resolutionSource;
|
|
2943
|
-
const resolutionNote =
|
|
3626
|
+
const resolutionNote = asString2(row.resolution_note);
|
|
2944
3627
|
if (resolutionNote) out.resolutionNote = resolutionNote;
|
|
2945
3628
|
return out;
|
|
2946
3629
|
}
|
|
2947
3630
|
function resolveFetch(injected) {
|
|
2948
3631
|
return injected ?? ((...args) => globalThis.fetch(...args));
|
|
2949
3632
|
}
|
|
2950
|
-
function
|
|
3633
|
+
function normalizeEndpoint2(endpoint) {
|
|
2951
3634
|
return endpoint.replace(/\/+$/, "");
|
|
2952
3635
|
}
|
|
2953
3636
|
async function getActionableAdvisories(opts) {
|
|
@@ -2964,7 +3647,7 @@ async function getActionableAdvisories(opts) {
|
|
|
2964
3647
|
throw new Error("getActionableAdvisories: appId is required");
|
|
2965
3648
|
}
|
|
2966
3649
|
const doFetch = resolveFetch(injectedFetch);
|
|
2967
|
-
const base =
|
|
3650
|
+
const base = normalizeEndpoint2(brainEndpoint);
|
|
2968
3651
|
const qs = new URLSearchParams();
|
|
2969
3652
|
qs.set("app_id", `eq.${appId}`);
|
|
2970
3653
|
if (severity) qs.set("severity", `eq.${severity}`);
|
|
@@ -3027,7 +3710,7 @@ async function markAdvisoryResolved(opts) {
|
|
|
3027
3710
|
return { ok: false, reason: "id_required" };
|
|
3028
3711
|
}
|
|
3029
3712
|
const doFetch = resolveFetch(injectedFetch);
|
|
3030
|
-
const base =
|
|
3713
|
+
const base = normalizeEndpoint2(brainEndpoint);
|
|
3031
3714
|
const lookupUrl = `${base}/rest/v1/actionable_advisories_v?id=eq.${encodeURIComponent(id)}&select=app_id,rule`;
|
|
3032
3715
|
let lookupRes;
|
|
3033
3716
|
try {
|
|
@@ -3171,7 +3854,7 @@ async function markExclusionFindingHandled(opts) {
|
|
|
3171
3854
|
return { ok: false, reason: "resolution_invalid" };
|
|
3172
3855
|
}
|
|
3173
3856
|
const doFetch = resolveFetch(injectedFetch);
|
|
3174
|
-
const base =
|
|
3857
|
+
const base = normalizeEndpoint2(brainEndpoint);
|
|
3175
3858
|
const url = `${base}/rest/v1/exclusion_findings?app_id=eq.${encodeURIComponent(appId)}&intent_archetype=eq.${encodeURIComponent(archetype)}&excluded_model=eq.${encodeURIComponent(excludedModel)}&resolved_at=is.null`;
|
|
3176
3859
|
const patchBody = {
|
|
3177
3860
|
resolved_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3211,125 +3894,6 @@ async function markExclusionFindingHandled(opts) {
|
|
|
3211
3894
|
return { ok: true };
|
|
3212
3895
|
}
|
|
3213
3896
|
|
|
3214
|
-
// src/models-brain.ts
|
|
3215
|
-
function isModelRow(x) {
|
|
3216
|
-
if (!x || typeof x !== "object") return false;
|
|
3217
|
-
const r = x;
|
|
3218
|
-
return typeof r.model_id === "string" && typeof r.provider === "string";
|
|
3219
|
-
}
|
|
3220
|
-
function isAliasRow(x) {
|
|
3221
|
-
if (!x || typeof x !== "object") return false;
|
|
3222
|
-
const r = x;
|
|
3223
|
-
return typeof r.alias_id === "string" && typeof r.canonical_id === "string";
|
|
3224
|
-
}
|
|
3225
|
-
function rowToProfile(row) {
|
|
3226
|
-
try {
|
|
3227
|
-
if (row.cliffs !== void 0 && row.cliffs !== null && !Array.isArray(row.cliffs)) {
|
|
3228
|
-
return null;
|
|
3229
|
-
}
|
|
3230
|
-
if (row.recovery !== void 0 && row.recovery !== null && !Array.isArray(row.recovery)) {
|
|
3231
|
-
return null;
|
|
3232
|
-
}
|
|
3233
|
-
if (row.lowering !== void 0 && row.lowering !== null && (typeof row.lowering !== "object" || Array.isArray(row.lowering))) {
|
|
3234
|
-
return null;
|
|
3235
|
-
}
|
|
3236
|
-
return {
|
|
3237
|
-
id: row.model_id,
|
|
3238
|
-
provider: row.provider,
|
|
3239
|
-
status: row.status ?? "current",
|
|
3240
|
-
maxContextTokens: row.max_context_tokens ?? 0,
|
|
3241
|
-
maxOutputTokens: row.max_output_tokens ?? 0,
|
|
3242
|
-
maxTools: row.max_tools ?? 0,
|
|
3243
|
-
parallelToolCalls: row.parallel_tool_calls ?? false,
|
|
3244
|
-
structuredOutput: row.structured_output ?? "none",
|
|
3245
|
-
systemPromptMode: row.system_prompt_mode ?? "inline",
|
|
3246
|
-
streaming: row.streaming ?? true,
|
|
3247
|
-
cliffs: row.cliffs ?? [],
|
|
3248
|
-
costInputPer1m: row.cost_input_per_1m ?? 0,
|
|
3249
|
-
costOutputPer1m: row.cost_output_per_1m ?? 0,
|
|
3250
|
-
lowering: row.lowering ?? { system: { mode: "inline" }, cache: { strategy: "unsupported" } },
|
|
3251
|
-
recovery: row.recovery ?? [],
|
|
3252
|
-
strengths: row.strengths ?? [],
|
|
3253
|
-
weaknesses: row.weaknesses ?? [],
|
|
3254
|
-
notes: row.notes ?? void 0,
|
|
3255
|
-
verifiedAgainstDocs: row.verified_against_docs ?? void 0,
|
|
3256
|
-
archetypePerf: row.archetype_perf ?? void 0
|
|
3257
|
-
};
|
|
3258
|
-
} catch {
|
|
3259
|
-
return null;
|
|
3260
|
-
}
|
|
3261
|
-
}
|
|
3262
|
-
function profileToRow(profile, opts = {}) {
|
|
3263
|
-
const row = {
|
|
3264
|
-
model_id: profile.id,
|
|
3265
|
-
provider: profile.provider,
|
|
3266
|
-
status: profile.status,
|
|
3267
|
-
max_context_tokens: profile.maxContextTokens,
|
|
3268
|
-
max_output_tokens: profile.maxOutputTokens,
|
|
3269
|
-
max_tools: profile.maxTools,
|
|
3270
|
-
parallel_tool_calls: profile.parallelToolCalls,
|
|
3271
|
-
structured_output: profile.structuredOutput,
|
|
3272
|
-
system_prompt_mode: profile.systemPromptMode,
|
|
3273
|
-
streaming: profile.streaming,
|
|
3274
|
-
cliffs: profile.cliffs,
|
|
3275
|
-
cost_input_per_1m: profile.costInputPer1m,
|
|
3276
|
-
cost_output_per_1m: profile.costOutputPer1m,
|
|
3277
|
-
lowering: profile.lowering,
|
|
3278
|
-
recovery: profile.recovery,
|
|
3279
|
-
strengths: profile.strengths,
|
|
3280
|
-
weaknesses: profile.weaknesses,
|
|
3281
|
-
notes: profile.notes ?? null,
|
|
3282
|
-
archetype_perf: profile.archetypePerf ?? null,
|
|
3283
|
-
active: opts.active ?? true
|
|
3284
|
-
};
|
|
3285
|
-
if (opts.verifiedAgainstDocs !== void 0) {
|
|
3286
|
-
row.verified_against_docs = opts.verifiedAgainstDocs;
|
|
3287
|
-
} else if (profile.verifiedAgainstDocs !== void 0) {
|
|
3288
|
-
const v = profile.verifiedAgainstDocs;
|
|
3289
|
-
row.verified_against_docs = /^\d{4}-\d{2}-\d{2}/.test(v) ? v : null;
|
|
3290
|
-
}
|
|
3291
|
-
if (opts.versionAdded !== void 0) row.version_added = opts.versionAdded;
|
|
3292
|
-
if (opts.versionRemoved !== void 0) row.version_removed = opts.versionRemoved;
|
|
3293
|
-
return row;
|
|
3294
|
-
}
|
|
3295
|
-
function mapRowsToModels(rows) {
|
|
3296
|
-
const out = /* @__PURE__ */ new Map();
|
|
3297
|
-
for (const row of rows) {
|
|
3298
|
-
if (!isModelRow(row)) continue;
|
|
3299
|
-
const profile = rowToProfile(row);
|
|
3300
|
-
if (profile) out.set(profile.id, profile);
|
|
3301
|
-
}
|
|
3302
|
-
return out;
|
|
3303
|
-
}
|
|
3304
|
-
function mapRowsToAliases(rows) {
|
|
3305
|
-
const out = {};
|
|
3306
|
-
for (const row of rows) {
|
|
3307
|
-
if (!isAliasRow(row)) continue;
|
|
3308
|
-
out[row.alias_id] = row.canonical_id;
|
|
3309
|
-
}
|
|
3310
|
-
return out;
|
|
3311
|
-
}
|
|
3312
|
-
function bundledModels() {
|
|
3313
|
-
return new Map(allProfilesRaw().map((p) => [p.id, p]));
|
|
3314
|
-
}
|
|
3315
|
-
function bundledAliases() {
|
|
3316
|
-
return { ...ALIASES };
|
|
3317
|
-
}
|
|
3318
|
-
var loadModelsFromBrain = createBrainQueryCache({
|
|
3319
|
-
table: "kgauto_models",
|
|
3320
|
-
mapRows: mapRowsToModels,
|
|
3321
|
-
bundledFallback: bundledModels
|
|
3322
|
-
});
|
|
3323
|
-
var loadAliasesFromBrain = createBrainQueryCache({
|
|
3324
|
-
table: "kgauto_aliases",
|
|
3325
|
-
mapRows: mapRowsToAliases,
|
|
3326
|
-
bundledFallback: bundledAliases
|
|
3327
|
-
});
|
|
3328
|
-
_setProfileBrainHook({
|
|
3329
|
-
getProfile: (canonical) => loadModelsFromBrain().get(canonical),
|
|
3330
|
-
resolveAlias: (id) => loadAliasesFromBrain()[id]
|
|
3331
|
-
});
|
|
3332
|
-
|
|
3333
3897
|
// src/index.ts
|
|
3334
3898
|
function compile2(ir, opts) {
|
|
3335
3899
|
const result = compile(ir, opts);
|
|
@@ -3344,6 +3908,7 @@ export {
|
|
|
3344
3908
|
CallError,
|
|
3345
3909
|
DEFAULT_FINDINGS_ENDPOINT,
|
|
3346
3910
|
DIALECT_VERSION,
|
|
3911
|
+
FamilyResolutionError,
|
|
3347
3912
|
INTENT_ARCHETYPES,
|
|
3348
3913
|
MEASURED_GROUNDING_MIN_N,
|
|
3349
3914
|
PROVIDER_ENV_KEYS,
|
|
@@ -3361,6 +3926,7 @@ export {
|
|
|
3361
3926
|
compile2 as compile,
|
|
3362
3927
|
configureBrain,
|
|
3363
3928
|
countTokens,
|
|
3929
|
+
deriveFamilyFromModelId,
|
|
3364
3930
|
execute,
|
|
3365
3931
|
getActionableAdvisories,
|
|
3366
3932
|
getAllStarterChains,
|
|
@@ -3372,6 +3938,7 @@ export {
|
|
|
3372
3938
|
getPerAxisMetrics,
|
|
3373
3939
|
getProfile,
|
|
3374
3940
|
getReachabilityDiagnostic,
|
|
3941
|
+
getRecommendedPrimary,
|
|
3375
3942
|
getSequentialStarterChain,
|
|
3376
3943
|
getSequentialStarterChainWithGrounding,
|
|
3377
3944
|
getStaleExclusionFindings,
|
|
@@ -3392,6 +3959,7 @@ export {
|
|
|
3392
3959
|
loadPricingFromBrain,
|
|
3393
3960
|
markAdvisoryResolved,
|
|
3394
3961
|
markExclusionFindingHandled,
|
|
3962
|
+
markPromoteReadyHandled,
|
|
3395
3963
|
profileToRow,
|
|
3396
3964
|
profilesByProvider,
|
|
3397
3965
|
record,
|