@kontextmind/kxm 0.7.30 → 0.7.35
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/.claude-plugin/marketplace.json +1 -1
- package/.kxm/roles/planner.yaml +10 -0
- package/.kxm/roles/reviewer-arch.yaml +10 -0
- package/.kxm/roles/reviewer-cli.yaml +10 -0
- package/.kxm/roles/writer.yaml +14 -0
- package/package.json +5 -4
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +40 -45
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime.js +13 -11
- package/plugins/kxm/dist/vnext-runtime-supervisor.js +13 -11
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/vnext.ts +16 -17
- package/plugins/kxm/src/cli.ts +8 -8
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/routes.ts +68 -0
- package/plugins/kxm/src/vnext-engine.ts +2 -2
- package/plugins/kxm/src/vnext-runtime-supervisor.ts +2 -2
- package/.kxm/producers.yaml +0 -53
- package/plugins/kxm/src/producers.ts +0 -71
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
schema: kxm.role.v1
|
|
2
|
+
id: planner
|
|
3
|
+
# fable primary (proven planning); qwen3.8-max failover (admitted, planning-unproven)
|
|
4
|
+
roster:
|
|
5
|
+
- model: anthropic/fable
|
|
6
|
+
effort: medium
|
|
7
|
+
enabled: true
|
|
8
|
+
- model: qwen-token-plan/qwen3.8-max
|
|
9
|
+
effort: medium
|
|
10
|
+
enabled: true
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
schema: kxm.role.v1
|
|
2
|
+
id: reviewer-cli
|
|
3
|
+
# sol is the required cli critic; glm-5.3-flash failover (fast tier, review-unproven)
|
|
4
|
+
roster:
|
|
5
|
+
- model: openai/gpt-5.6-sol
|
|
6
|
+
effort: low
|
|
7
|
+
enabled: true
|
|
8
|
+
- model: zai-coding-cn/glm-5.3-flash
|
|
9
|
+
effort: low
|
|
10
|
+
enabled: true
|
package/.kxm/roles/writer.yaml
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
schema: kxm.role.v1
|
|
2
2
|
id: writer
|
|
3
|
+
# Rotation priority = order. Primaries first; subscription/unmetered models
|
|
4
|
+
# act as failover (verified edit probes 2026-09-16; see routes.yaml).
|
|
5
|
+
# Effort default: medium for implementation (AGENTS.md). agy ids bake in the
|
|
6
|
+
# effort tier, so those entries carry no effort field.
|
|
3
7
|
roster:
|
|
4
8
|
- model: xai/grok-4.6
|
|
9
|
+
effort: medium
|
|
5
10
|
enabled: true
|
|
6
11
|
- model: openrouter/qwen/qwen3-coder-plus
|
|
12
|
+
effort: medium
|
|
13
|
+
enabled: true
|
|
14
|
+
- model: zai-coding-cn/glm-5.3-flash
|
|
15
|
+
effort: medium
|
|
16
|
+
enabled: true
|
|
17
|
+
- model: qwen-token-plan/qwen3.8-flash
|
|
18
|
+
effort: medium
|
|
19
|
+
enabled: true
|
|
20
|
+
- model: google/gemini-3.8-flash-high
|
|
7
21
|
enabled: true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kontextmind/kxm",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.35",
|
|
4
4
|
"description": "KXM local-first multi-agent orchestration and operator dashboard",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "KontextMind",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"verify": "npm test && npm run check && npm run check:generated",
|
|
49
49
|
"validate:claude": "claude plugin validate . --strict && claude plugin validate plugins/kxm --strict",
|
|
50
50
|
"validate:ci": "npm run test:coverage && npm run check && npm pack --dry-run",
|
|
51
|
+
"validate:pr": "npm run test:core && npm run check && npm run check:generated",
|
|
51
52
|
"validate": "npm run validate:ci && npm run validate:claude"
|
|
52
53
|
},
|
|
53
54
|
"bin": {
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
]
|
|
71
72
|
},
|
|
72
73
|
"dependencies": {
|
|
73
|
-
"@anthropic-ai/claude-agent-sdk": "0.
|
|
74
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.270",
|
|
74
75
|
"@earendil-works/pi-tui": "0.85.1",
|
|
75
76
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
76
77
|
"yaml": "^2.9.0"
|
|
@@ -90,13 +91,13 @@
|
|
|
90
91
|
"devDependencies": {
|
|
91
92
|
"@earendil-works/pi-coding-agent": "0.85.1",
|
|
92
93
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
93
|
-
"@types/node": "26.
|
|
94
|
+
"@types/node": "26.5.1",
|
|
94
95
|
"ajv": "8.20.0",
|
|
95
96
|
"commander": "15.0.0",
|
|
96
97
|
"esbuild": "0.28.2",
|
|
97
98
|
"markdownlint-cli2": "0.23.2",
|
|
98
99
|
"tsx": "^4.23.13",
|
|
99
|
-
"typebox": "1.3.
|
|
100
|
+
"typebox": "1.3.30",
|
|
100
101
|
"typescript": "7.0.2"
|
|
101
102
|
},
|
|
102
103
|
"files": [
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "kxm",
|
|
4
4
|
"displayName": "KXM",
|
|
5
|
-
"version": "0.7.
|
|
5
|
+
"version": "0.7.35",
|
|
6
6
|
"description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "KontextMind",
|
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -24951,33 +24951,29 @@ function loadPriceCatalogForEstimate(options) {
|
|
|
24951
24951
|
// plugins/kxm/src/vnext-engine.ts
|
|
24952
24952
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
24953
24953
|
|
|
24954
|
-
// plugins/kxm/src/
|
|
24954
|
+
// plugins/kxm/src/routes.ts
|
|
24955
24955
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
24956
24956
|
import { existsSync as existsSync11, readFileSync as readFileSync10, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7, readdirSync as readdirSync3 } from "node:fs";
|
|
24957
24957
|
import { join as join11 } from "node:path";
|
|
24958
|
-
var
|
|
24959
|
-
|
|
24960
|
-
|
|
24958
|
+
var RETIRED_POLICY = ".kxm/producers.yaml";
|
|
24959
|
+
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [], roles: {} });
|
|
24960
|
+
function loadRoutePolicy(root) {
|
|
24961
|
+
if (existsSync11(join11(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
|
|
24962
|
+
const path4 = join11(root, ".kxm", "routes.yaml");
|
|
24961
24963
|
if (!existsSync11(path4)) return empty();
|
|
24962
24964
|
const value = (0, import_yaml4.parse)(readFileSync10(path4, "utf8"));
|
|
24963
|
-
if (value?.schema !== "kxm.
|
|
24964
|
-
return { schema: "kxm.
|
|
24965
|
-
}
|
|
24966
|
-
function
|
|
24967
|
-
|
|
24968
|
-
policy.promoted = policy.promoted.filter((x2) => x2 !== model);
|
|
24969
|
-
policy.demoted = policy.demoted.filter((x2) => x2 !== model);
|
|
24970
|
-
policy[status].push(model);
|
|
24971
|
-
policy.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
24972
|
-
mkdirSync7(join11(root, ".kxm"), { recursive: true });
|
|
24973
|
-
writeFileSync7(join11(root, ".kxm", "producers.yaml"), (0, import_yaml4.stringify)(policy), "utf8");
|
|
24974
|
-
return policy;
|
|
24965
|
+
if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
|
|
24966
|
+
return { schema: "kxm.routes.v2", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), admitted: value.admitted.filter((x2) => typeof x2 === "string"), disabled: Array.isArray(value.disabled) ? value.disabled.filter((x2) => typeof x2 === "string") : [], roles: value.roles && typeof value.roles === "object" ? Object.fromEntries(Object.entries(value.roles).filter(([, v2]) => Array.isArray(v2)).map(([k, v2]) => [k, v2.filter((x2) => typeof x2 === "string")])) : {} };
|
|
24967
|
+
}
|
|
24968
|
+
function updateRouteState(root, model, state) {
|
|
24969
|
+
return setRouteState(root, model, state);
|
|
24975
24970
|
}
|
|
24976
|
-
function
|
|
24977
|
-
const policy =
|
|
24978
|
-
policy.
|
|
24971
|
+
function setRouteState(root, model, state, role, removeRole2 = false) {
|
|
24972
|
+
const policy = loadRoutePolicy(root);
|
|
24973
|
+
policy.admitted = policy.admitted.filter((x2) => x2 !== model);
|
|
24979
24974
|
policy.disabled = policy.disabled.filter((x2) => x2 !== model);
|
|
24980
|
-
policy
|
|
24975
|
+
if (state === "admitted") policy.admitted.push(model);
|
|
24976
|
+
else policy.disabled.push(model);
|
|
24981
24977
|
if (role) {
|
|
24982
24978
|
if (!/^[a-z][a-z0-9_-]{0,63}$/i.test(role)) throw new Error("invalid role id");
|
|
24983
24979
|
const rolePath = join11(root, ".kxm", "roles", `${role}.yaml`);
|
|
@@ -24999,7 +24995,7 @@ function setModelState(root, model, state, role, removeRole2 = false) {
|
|
|
24999
24995
|
}
|
|
25000
24996
|
policy.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25001
24997
|
mkdirSync7(join11(root, ".kxm"), { recursive: true });
|
|
25002
|
-
writeFileSync7(join11(root, ".kxm", "
|
|
24998
|
+
writeFileSync7(join11(root, ".kxm", "routes.yaml"), (0, import_yaml4.stringify)(policy), "utf8");
|
|
25003
24999
|
return policy;
|
|
25004
25000
|
}
|
|
25005
25001
|
function listRoleBindings(root) {
|
|
@@ -33853,7 +33849,7 @@ async function cmdHarnessList(runtime) {
|
|
|
33853
33849
|
print(runtime.io, runtime.json, { ok: true, command: "harness list", ...inventory }, formatHarnessInventory(inventory));
|
|
33854
33850
|
return 0;
|
|
33855
33851
|
}
|
|
33856
|
-
async function
|
|
33852
|
+
async function selectInventoryModel(runtime, requested) {
|
|
33857
33853
|
const models = listInventoryModels(runtime.dirs.workdir);
|
|
33858
33854
|
if (requested) return models.find((model) => model.toLowerCase() === requested.toLowerCase());
|
|
33859
33855
|
if (runtime.json || !process.stdin.isTTY || models.length === 0) return void 0;
|
|
@@ -33864,18 +33860,18 @@ async function selectProducerModel(runtime, requested) {
|
|
|
33864
33860
|
const index = Number.parseInt(answer.trim(), 10) - 1;
|
|
33865
33861
|
return Number.isInteger(index) && index >= 0 && index < models.length ? models[index] : void 0;
|
|
33866
33862
|
}
|
|
33867
|
-
async function
|
|
33868
|
-
const model = await
|
|
33863
|
+
async function cmdRouteChange(runtime, status, requested) {
|
|
33864
|
+
const model = await selectInventoryModel(runtime, requested);
|
|
33869
33865
|
if (!model) {
|
|
33870
|
-
print(runtime.io, runtime.json, { ok: false, command: `
|
|
33866
|
+
print(runtime.io, runtime.json, { ok: false, command: `routes ${status}`, error: "model_selection_required" }, "select a model from the refreshed inventory");
|
|
33871
33867
|
return 2;
|
|
33872
33868
|
}
|
|
33873
33869
|
if (runtime.dryRun) {
|
|
33874
|
-
print(runtime.io, runtime.json, { ok: true, command: `
|
|
33870
|
+
print(runtime.io, runtime.json, { ok: true, command: `routes ${status}`, model, dryRun: true }, `would ${status === "admitted" ? "admit" : "disable"} ${model}`);
|
|
33875
33871
|
return 0;
|
|
33876
33872
|
}
|
|
33877
|
-
const policy =
|
|
33878
|
-
print(runtime.io, runtime.json, { ok: true, command: `
|
|
33873
|
+
const policy = updateRouteState(runtime.dirs.workdir, model, status);
|
|
33874
|
+
print(runtime.io, runtime.json, { ok: true, command: `routes ${status}`, model, policy }, `${status} ${model}`);
|
|
33879
33875
|
return 0;
|
|
33880
33876
|
}
|
|
33881
33877
|
async function cmdModelsScreen(runtime) {
|
|
@@ -33888,25 +33884,24 @@ async function cmdModelsScreen(runtime) {
|
|
|
33888
33884
|
const ask = (q2) => new Promise((resolve31) => rl.question(q2, resolve31));
|
|
33889
33885
|
try {
|
|
33890
33886
|
while (true) {
|
|
33891
|
-
const policy =
|
|
33887
|
+
const policy = loadRoutePolicy(runtime.dirs.workdir);
|
|
33892
33888
|
const roleBindings = listRoleBindings(runtime.dirs.workdir);
|
|
33893
|
-
runtime.io.stdout(models.map((m2, i) => `${i + 1}. ${m2} [${policy.
|
|
33894
|
-
const command = (await ask("[
|
|
33889
|
+
runtime.io.stdout(models.map((m2, i) => `${i + 1}. ${m2} [${policy.admitted.includes(m2) ? "admitted" : policy.disabled.includes(m2) ? "disabled" : "unset"}] roles:${Object.entries(roleBindings).filter(([, xs]) => xs.includes(m2)).map(([r]) => r).join(",") || "-"}`).join("\n") + "\n");
|
|
33890
|
+
const command = (await ask("[a]dmit [d]isable [r]ole-add [x]ole-remove [q]uit: ")).trim().toLowerCase();
|
|
33895
33891
|
if (command === "q" || command === "quit") return 0;
|
|
33896
33892
|
const index = Number.parseInt((await ask("model number: ")).trim(), 10) - 1;
|
|
33897
33893
|
if (!Number.isInteger(index) || !models[index]) continue;
|
|
33898
33894
|
const model = models[index];
|
|
33899
|
-
if (command === "
|
|
33900
|
-
else if (command === "
|
|
33901
|
-
else if (command === "a" || command === "r") setModelState(runtime.dirs.workdir, model, "enabled", (await ask("role: ")).trim(), command === "r");
|
|
33895
|
+
if (command === "a" || command === "d") setRouteState(runtime.dirs.workdir, model, command === "a" ? "admitted" : "disabled");
|
|
33896
|
+
else if (command === "r" || command === "x") setRouteState(runtime.dirs.workdir, model, "admitted", (await ask("role: ")).trim(), command === "x");
|
|
33902
33897
|
}
|
|
33903
33898
|
} finally {
|
|
33904
33899
|
rl.close();
|
|
33905
33900
|
}
|
|
33906
33901
|
}
|
|
33907
|
-
async function
|
|
33908
|
-
const policy =
|
|
33909
|
-
print(runtime.io, runtime.json, { ok: true, command: "
|
|
33902
|
+
async function cmdRouteList(runtime) {
|
|
33903
|
+
const policy = loadRoutePolicy(runtime.dirs.workdir);
|
|
33904
|
+
print(runtime.io, runtime.json, { ok: true, command: "routes list", policy }, [...policy.admitted.map((x2) => `admitted ${x2}`), ...policy.disabled.map((x2) => `disabled ${x2}`)].join("\n") || "no route decisions");
|
|
33910
33905
|
return 0;
|
|
33911
33906
|
}
|
|
33912
33907
|
async function cmdModelInventoryRefresh(runtime) {
|
|
@@ -48797,7 +48792,7 @@ function createProgram(ctx, result) {
|
|
|
48797
48792
|
addGlobalOptions(runCmd.command("list").description("List recent runs for the current project")).action(async function runListAction() {
|
|
48798
48793
|
result.code = await cmdVnextRunList(runtimeFrom(ctx, this));
|
|
48799
48794
|
});
|
|
48800
|
-
const modelsCmd = addGlobalOptions(program2.command("models").description("Manage model catalogs, roles, and
|
|
48795
|
+
const modelsCmd = addGlobalOptions(program2.command("models").description("Manage model catalogs, roles, and route state"));
|
|
48801
48796
|
modelsCmd.action(async function modelsScreenAction() {
|
|
48802
48797
|
result.code = await cmdModelsScreen(runtimeFrom(ctx, this));
|
|
48803
48798
|
});
|
|
@@ -48805,14 +48800,14 @@ function createProgram(ctx, result) {
|
|
|
48805
48800
|
addGlobalOptions(modelsCmd.command("inventory-refresh").alias("refresh").description("Refresh the YAML model inventory with standard and Nous/OpenRouter prices")).action(async function modelInventoryRefreshAction() {
|
|
48806
48801
|
result.code = await cmdModelInventoryRefresh(runtimeFrom(ctx, this));
|
|
48807
48802
|
});
|
|
48808
|
-
const
|
|
48809
|
-
|
|
48810
|
-
addGlobalOptions(
|
|
48811
|
-
result.code = await
|
|
48803
|
+
const routesCmd = addGlobalOptions(program2.command("routes").description("Admit or disable verified model routes"));
|
|
48804
|
+
routesCmd.helpCommand("help", "Show routes help");
|
|
48805
|
+
addGlobalOptions(routesCmd.command("list").description("List route decisions")).action(async function routesListAction() {
|
|
48806
|
+
result.code = await cmdRouteList(runtimeFrom(ctx, this));
|
|
48812
48807
|
});
|
|
48813
|
-
for (const status of ["
|
|
48814
|
-
addGlobalOptions(
|
|
48815
|
-
result.code = await
|
|
48808
|
+
for (const status of ["admit", "disable"]) {
|
|
48809
|
+
addGlobalOptions(routesCmd.command(status).description(`${status === "admit" ? "Admit" : "Disable"} a model route from the inventory`)).option("--model <id>", "Exact model id; omit to choose interactively").action(async function routeChangeAction(options) {
|
|
48810
|
+
result.code = await cmdRouteChange(runtimeFrom(ctx, this), status === "admit" ? "admitted" : "disabled", options.model);
|
|
48816
48811
|
});
|
|
48817
48812
|
}
|
|
48818
48813
|
const harnessCmd = addGlobalOptions(program2.command("harness").description("Detect coding-agent harnesses and authentication"));
|
|
@@ -17121,7 +17121,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
|
|
|
17121
17121
|
}
|
|
17122
17122
|
|
|
17123
17123
|
// plugins/kxm/src/mcp-server.ts
|
|
17124
|
-
var VERSION = "0.7.
|
|
17124
|
+
var VERSION = "0.7.35";
|
|
17125
17125
|
var inbox = /* @__PURE__ */ new Map();
|
|
17126
17126
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
|
17127
17127
|
var meshClient;
|
|
@@ -22945,17 +22945,19 @@ import { createHash as createHash11, randomBytes as randomBytes2, timingSafeEqua
|
|
|
22945
22945
|
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
|
|
22946
22946
|
import { join as join11 } from "node:path";
|
|
22947
22947
|
|
|
22948
|
-
// plugins/kxm/src/
|
|
22948
|
+
// plugins/kxm/src/routes.ts
|
|
22949
22949
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
22950
22950
|
import { existsSync as existsSync8, readFileSync as readFileSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, readdirSync as readdirSync4 } from "node:fs";
|
|
22951
22951
|
import { join as join9 } from "node:path";
|
|
22952
|
-
var
|
|
22953
|
-
|
|
22954
|
-
|
|
22952
|
+
var RETIRED_POLICY = ".kxm/producers.yaml";
|
|
22953
|
+
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [], roles: {} });
|
|
22954
|
+
function loadRoutePolicy(root) {
|
|
22955
|
+
if (existsSync8(join9(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
|
|
22956
|
+
const path = join9(root, ".kxm", "routes.yaml");
|
|
22955
22957
|
if (!existsSync8(path)) return empty();
|
|
22956
22958
|
const value = (0, import_yaml4.parse)(readFileSync6(path, "utf8"));
|
|
22957
|
-
if (value?.schema !== "kxm.
|
|
22958
|
-
return { schema: "kxm.
|
|
22959
|
+
if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
|
|
22960
|
+
return { schema: "kxm.routes.v2", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), admitted: value.admitted.filter((x) => typeof x === "string"), disabled: Array.isArray(value.disabled) ? value.disabled.filter((x) => typeof x === "string") : [], roles: value.roles && typeof value.roles === "object" ? Object.fromEntries(Object.entries(value.roles).filter(([, v]) => Array.isArray(v)).map(([k, v]) => [k, v.filter((x) => typeof x === "string")])) : {} };
|
|
22959
22961
|
}
|
|
22960
22962
|
function listRoleBindings(root) {
|
|
22961
22963
|
const dir = join9(root, ".kxm", "roles");
|
|
@@ -22968,9 +22970,9 @@ function listRoleBindings(root) {
|
|
|
22968
22970
|
}
|
|
22969
22971
|
return result;
|
|
22970
22972
|
}
|
|
22971
|
-
function
|
|
22972
|
-
const policy =
|
|
22973
|
-
return policy.
|
|
22973
|
+
function isRouteAdmitted(root, modelId) {
|
|
22974
|
+
const policy = loadRoutePolicy(root);
|
|
22975
|
+
return policy.admitted.includes(modelId) && !policy.disabled.includes(modelId);
|
|
22974
22976
|
}
|
|
22975
22977
|
|
|
22976
22978
|
// plugins/kxm/src/context-packet.ts
|
|
@@ -25164,7 +25166,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
25164
25166
|
}
|
|
25165
25167
|
};
|
|
25166
25168
|
}
|
|
25167
|
-
if (!
|
|
25169
|
+
if (!isRouteAdmitted(projectRoot, selector)) {
|
|
25168
25170
|
return {
|
|
25169
25171
|
error: {
|
|
25170
25172
|
reason: "step_unsupported",
|
|
@@ -27337,7 +27339,7 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
|
|
|
27337
27339
|
const value = model;
|
|
27338
27340
|
const provider = typeof value.provider === "string" ? value.provider : void 0;
|
|
27339
27341
|
const modelName = typeof value.model === "string" ? value.model : void 0;
|
|
27340
|
-
if (!provider || !modelName || !
|
|
27342
|
+
if (!provider || !modelName || !isRouteAdmitted(projectRoot, `${provider}/${modelName}`)) {
|
|
27341
27343
|
throw new Error("producer_route_not_admitted");
|
|
27342
27344
|
}
|
|
27343
27345
|
return { provider, model: modelName };
|
|
@@ -22470,17 +22470,19 @@ import { createHash as createHash10, randomBytes, timingSafeEqual } from "node:c
|
|
|
22470
22470
|
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
|
|
22471
22471
|
import { join as join11 } from "node:path";
|
|
22472
22472
|
|
|
22473
|
-
// plugins/kxm/src/
|
|
22473
|
+
// plugins/kxm/src/routes.ts
|
|
22474
22474
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
22475
22475
|
import { existsSync as existsSync8, readFileSync as readFileSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, readdirSync as readdirSync4 } from "node:fs";
|
|
22476
22476
|
import { join as join9 } from "node:path";
|
|
22477
|
-
var
|
|
22478
|
-
|
|
22479
|
-
|
|
22477
|
+
var RETIRED_POLICY = ".kxm/producers.yaml";
|
|
22478
|
+
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [], roles: {} });
|
|
22479
|
+
function loadRoutePolicy(root) {
|
|
22480
|
+
if (existsSync8(join9(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
|
|
22481
|
+
const path = join9(root, ".kxm", "routes.yaml");
|
|
22480
22482
|
if (!existsSync8(path)) return empty();
|
|
22481
22483
|
const value = (0, import_yaml4.parse)(readFileSync6(path, "utf8"));
|
|
22482
|
-
if (value?.schema !== "kxm.
|
|
22483
|
-
return { schema: "kxm.
|
|
22484
|
+
if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
|
|
22485
|
+
return { schema: "kxm.routes.v2", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), admitted: value.admitted.filter((x) => typeof x === "string"), disabled: Array.isArray(value.disabled) ? value.disabled.filter((x) => typeof x === "string") : [], roles: value.roles && typeof value.roles === "object" ? Object.fromEntries(Object.entries(value.roles).filter(([, v]) => Array.isArray(v)).map(([k, v]) => [k, v.filter((x) => typeof x === "string")])) : {} };
|
|
22484
22486
|
}
|
|
22485
22487
|
function listRoleBindings(root) {
|
|
22486
22488
|
const dir = join9(root, ".kxm", "roles");
|
|
@@ -22493,9 +22495,9 @@ function listRoleBindings(root) {
|
|
|
22493
22495
|
}
|
|
22494
22496
|
return result;
|
|
22495
22497
|
}
|
|
22496
|
-
function
|
|
22497
|
-
const policy =
|
|
22498
|
-
return policy.
|
|
22498
|
+
function isRouteAdmitted(root, modelId) {
|
|
22499
|
+
const policy = loadRoutePolicy(root);
|
|
22500
|
+
return policy.admitted.includes(modelId) && !policy.disabled.includes(modelId);
|
|
22499
22501
|
}
|
|
22500
22502
|
|
|
22501
22503
|
// plugins/kxm/src/context-packet.ts
|
|
@@ -24678,7 +24680,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
24678
24680
|
}
|
|
24679
24681
|
};
|
|
24680
24682
|
}
|
|
24681
|
-
if (!
|
|
24683
|
+
if (!isRouteAdmitted(projectRoot, selector)) {
|
|
24682
24684
|
return {
|
|
24683
24685
|
error: {
|
|
24684
24686
|
reason: "step_unsupported",
|
|
@@ -26851,7 +26853,7 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
|
|
|
26851
26853
|
const value = model;
|
|
26852
26854
|
const provider = typeof value.provider === "string" ? value.provider : void 0;
|
|
26853
26855
|
const modelName = typeof value.model === "string" ? value.model : void 0;
|
|
26854
|
-
if (!provider || !modelName || !
|
|
26856
|
+
if (!provider || !modelName || !isRouteAdmitted(projectRoot, `${provider}/${modelName}`)) {
|
|
26855
26857
|
throw new Error("producer_route_not_admitted");
|
|
26856
26858
|
}
|
|
26857
26859
|
return { provider, model: modelName };
|
package/plugins/kxm/package.json
CHANGED
|
@@ -5,7 +5,7 @@ import { join, resolve } from "node:path";
|
|
|
5
5
|
import { createInterface } from "node:readline";
|
|
6
6
|
import { createBackup, restoreBackup } from "../database.ts";
|
|
7
7
|
import { refreshModelInventory } from "../model-inventory.ts";
|
|
8
|
-
import { listInventoryModels, listRoleBindings,
|
|
8
|
+
import { listInventoryModels, listRoleBindings, loadRoutePolicy, setRouteState, updateRouteState } from "../routes.ts";
|
|
9
9
|
import {
|
|
10
10
|
VnextConfigError,
|
|
11
11
|
discoverVnextProjectRoot,
|
|
@@ -723,7 +723,7 @@ export async function cmdHarnessList(runtime: Runtime): Promise<number> {
|
|
|
723
723
|
return 0;
|
|
724
724
|
}
|
|
725
725
|
|
|
726
|
-
export async function
|
|
726
|
+
export async function selectInventoryModel(runtime: Runtime, requested?: string | undefined): Promise<string | undefined> {
|
|
727
727
|
const models = listInventoryModels(runtime.dirs.workdir);
|
|
728
728
|
if (requested) return models.find((model) => model.toLowerCase() === requested.toLowerCase());
|
|
729
729
|
if (runtime.json || !process.stdin.isTTY || models.length === 0) return undefined;
|
|
@@ -735,12 +735,12 @@ export async function selectProducerModel(runtime: Runtime, requested?: string |
|
|
|
735
735
|
return Number.isInteger(index) && index >= 0 && index < models.length ? models[index] : undefined;
|
|
736
736
|
}
|
|
737
737
|
|
|
738
|
-
export async function
|
|
739
|
-
const model = await
|
|
740
|
-
if (!model) { print(runtime.io, runtime.json, { ok: false, command: `
|
|
741
|
-
if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: `
|
|
742
|
-
const policy =
|
|
743
|
-
print(runtime.io, runtime.json, { ok: true, command: `
|
|
738
|
+
export async function cmdRouteChange(runtime: Runtime, status: "admitted" | "disabled", requested?: string | undefined): Promise<number> {
|
|
739
|
+
const model = await selectInventoryModel(runtime, requested);
|
|
740
|
+
if (!model) { print(runtime.io, runtime.json, { ok: false, command: `routes ${status}`, error: "model_selection_required" }, "select a model from the refreshed inventory"); return 2; }
|
|
741
|
+
if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: `routes ${status}`, model, dryRun: true }, `would ${status === "admitted" ? "admit" : "disable"} ${model}`); return 0; }
|
|
742
|
+
const policy = updateRouteState(runtime.dirs.workdir, model, status);
|
|
743
|
+
print(runtime.io, runtime.json, { ok: true, command: `routes ${status}`, model, policy }, `${status} ${model}`);
|
|
744
744
|
return 0;
|
|
745
745
|
}
|
|
746
746
|
|
|
@@ -751,24 +751,23 @@ export async function cmdModelsScreen(runtime: Runtime): Promise<number> {
|
|
|
751
751
|
const ask = (q: string) => new Promise<string>((resolve) => rl.question(q, resolve));
|
|
752
752
|
try {
|
|
753
753
|
while (true) {
|
|
754
|
-
const policy =
|
|
754
|
+
const policy = loadRoutePolicy(runtime.dirs.workdir);
|
|
755
755
|
const roleBindings = listRoleBindings(runtime.dirs.workdir);
|
|
756
|
-
runtime.io.stdout(models.map((m, i) => `${i + 1}. ${m} [${policy.
|
|
757
|
-
const command = (await ask("[
|
|
756
|
+
runtime.io.stdout(models.map((m, i) => `${i + 1}. ${m} [${policy.admitted.includes(m) ? "admitted" : policy.disabled.includes(m) ? "disabled" : "unset"}] roles:${Object.entries(roleBindings).filter(([, xs]) => xs.includes(m)).map(([r]) => r).join(",") || "-"}`).join("\n") + "\n");
|
|
757
|
+
const command = (await ask("[a]dmit [d]isable [r]ole-add [x]ole-remove [q]uit: ")).trim().toLowerCase();
|
|
758
758
|
if (command === "q" || command === "quit") return 0;
|
|
759
759
|
const index = Number.parseInt((await ask("model number: ")).trim(), 10) - 1;
|
|
760
760
|
if (!Number.isInteger(index) || !models[index]) continue;
|
|
761
761
|
const model = models[index];
|
|
762
|
-
if (command === "
|
|
763
|
-
else if (command === "
|
|
764
|
-
else if (command === "a" || command === "r") setModelState(runtime.dirs.workdir, model, "enabled", (await ask("role: ")).trim(), command === "r");
|
|
762
|
+
if (command === "a" || command === "d") setRouteState(runtime.dirs.workdir, model, command === "a" ? "admitted" : "disabled");
|
|
763
|
+
else if (command === "r" || command === "x") setRouteState(runtime.dirs.workdir, model, "admitted", (await ask("role: ")).trim(), command === "x");
|
|
765
764
|
}
|
|
766
765
|
} finally { rl.close(); }
|
|
767
766
|
}
|
|
768
767
|
|
|
769
|
-
export async function
|
|
770
|
-
const policy =
|
|
771
|
-
print(runtime.io, runtime.json, { ok: true, command: "
|
|
768
|
+
export async function cmdRouteList(runtime: Runtime): Promise<number> {
|
|
769
|
+
const policy = loadRoutePolicy(runtime.dirs.workdir);
|
|
770
|
+
print(runtime.io, runtime.json, { ok: true, command: "routes list", policy }, [...policy.admitted.map((x) => `admitted ${x}`), ...policy.disabled.map((x) => `disabled ${x}`)].join("\n") || "no route decisions");
|
|
772
771
|
return 0;
|
|
773
772
|
}
|
|
774
773
|
|
package/plugins/kxm/src/cli.ts
CHANGED
|
@@ -111,9 +111,9 @@ import {
|
|
|
111
111
|
cmdVnextRunCancel,
|
|
112
112
|
cmdVnextRunList,
|
|
113
113
|
cmdHarnessList,
|
|
114
|
-
|
|
114
|
+
cmdRouteChange,
|
|
115
115
|
cmdModelsScreen,
|
|
116
|
-
|
|
116
|
+
cmdRouteList,
|
|
117
117
|
cmdModelInventoryRefresh,
|
|
118
118
|
cmdVnextRuntime,
|
|
119
119
|
} from "./cli/vnext.ts";
|
|
@@ -415,7 +415,7 @@ function createProgram(ctx: CliContext, result: { code: number }): Command {
|
|
|
415
415
|
result.code = await cmdVnextRunList(runtimeFrom(ctx, this));
|
|
416
416
|
});
|
|
417
417
|
|
|
418
|
-
const modelsCmd = addGlobalOptions(program.command("models").description("Manage model catalogs, roles, and
|
|
418
|
+
const modelsCmd = addGlobalOptions(program.command("models").description("Manage model catalogs, roles, and route state"));
|
|
419
419
|
modelsCmd.action(async function modelsScreenAction(this: Command) { result.code = await cmdModelsScreen(runtimeFrom(ctx, this)); });
|
|
420
420
|
modelsCmd.helpCommand("help", "Show models help");
|
|
421
421
|
addGlobalOptions(modelsCmd.command("inventory-refresh").alias("refresh").description("Refresh the YAML model inventory with standard and Nous/OpenRouter prices"))
|
|
@@ -423,11 +423,11 @@ function createProgram(ctx: CliContext, result: { code: number }): Command {
|
|
|
423
423
|
result.code = await cmdModelInventoryRefresh(runtimeFrom(ctx, this));
|
|
424
424
|
});
|
|
425
425
|
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
addGlobalOptions(
|
|
429
|
-
for (const status of ["
|
|
430
|
-
addGlobalOptions(
|
|
426
|
+
const routesCmd = addGlobalOptions(program.command("routes").description("Admit or disable verified model routes"));
|
|
427
|
+
routesCmd.helpCommand("help", "Show routes help");
|
|
428
|
+
addGlobalOptions(routesCmd.command("list").description("List route decisions")).action(async function routesListAction(this: Command) { result.code = await cmdRouteList(runtimeFrom(ctx, this)); });
|
|
429
|
+
for (const status of ["admit", "disable"] as const) {
|
|
430
|
+
addGlobalOptions(routesCmd.command(status).description(`${status === "admit" ? "Admit" : "Disable"} a model route from the inventory`)).option("--model <id>", "Exact model id; omit to choose interactively").action(async function routeChangeAction(this: Command, options: { model?: string }) { result.code = await cmdRouteChange(runtimeFrom(ctx, this), status === "admit" ? "admitted" : "disabled", options.model); });
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
const harnessCmd = addGlobalOptions(program.command("harness").description("Detect coding-agent harnesses and authentication"));
|
|
@@ -8,7 +8,7 @@ import { AGENT_COMMANDS_MAP, enforceToolPolicy, getMcpTools, reconcileInbox } fr
|
|
|
8
8
|
import { deliverInboxNotification } from "./inbox.ts";
|
|
9
9
|
import type { HubEvent, MessageRecord } from "./protocol.ts";
|
|
10
10
|
|
|
11
|
-
const VERSION = "0.7.
|
|
11
|
+
const VERSION = "0.7.35";
|
|
12
12
|
const inbox = new Map<string, MessageRecord>();
|
|
13
13
|
const notifiedInbox = new Set<string>();
|
|
14
14
|
let meshClient: HubClient | undefined;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parse, stringify } from "yaml";
|
|
4
|
+
|
|
5
|
+
const RETIRED_POLICY = ".kxm/producers.yaml";
|
|
6
|
+
|
|
7
|
+
export interface RoutePolicy { schema: "kxm.routes.v2"; updatedAt: string; admitted: string[]; disabled: string[]; roles: Record<string, string[]>; }
|
|
8
|
+
const empty = (): RoutePolicy => ({ schema: "kxm.routes.v2", updatedAt: new Date().toISOString(), admitted: [], disabled: [], roles: {} });
|
|
9
|
+
export function loadRoutePolicy(root: string): RoutePolicy {
|
|
10
|
+
if (existsSync(join(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
|
|
11
|
+
const path = join(root, ".kxm", "routes.yaml");
|
|
12
|
+
if (!existsSync(path)) return empty();
|
|
13
|
+
const value = parse(readFileSync(path, "utf8")) as Partial<RoutePolicy>;
|
|
14
|
+
if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
|
|
15
|
+
return { schema: "kxm.routes.v2", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : new Date().toISOString(), admitted: value.admitted.filter((x): x is string => typeof x === "string"), disabled: Array.isArray(value.disabled) ? value.disabled.filter((x): x is string => typeof x === "string") : [], roles: value.roles && typeof value.roles === "object" ? Object.fromEntries(Object.entries(value.roles).filter(([, v]) => Array.isArray(v)).map(([k, v]) => [k, (v as unknown[]).filter((x): x is string => typeof x === "string")])) : {} };
|
|
16
|
+
}
|
|
17
|
+
export function updateRouteState(root: string, model: string, state: "admitted" | "disabled"): RoutePolicy {
|
|
18
|
+
return setRouteState(root, model, state);
|
|
19
|
+
}
|
|
20
|
+
export function setRouteState(root: string, model: string, state: "admitted" | "disabled", role?: string, removeRole = false): RoutePolicy {
|
|
21
|
+
const policy = loadRoutePolicy(root);
|
|
22
|
+
policy.admitted = policy.admitted.filter((x) => x !== model);
|
|
23
|
+
policy.disabled = policy.disabled.filter((x) => x !== model);
|
|
24
|
+
if (state === "admitted") policy.admitted.push(model);
|
|
25
|
+
else policy.disabled.push(model);
|
|
26
|
+
if (role) {
|
|
27
|
+
if (!/^[a-z][a-z0-9_-]{0,63}$/i.test(role)) throw new Error("invalid role id");
|
|
28
|
+
const rolePath = join(root, ".kxm", "roles", `${role}.yaml`);
|
|
29
|
+
let roleFile: Record<string, unknown> = {};
|
|
30
|
+
if (existsSync(rolePath)) {
|
|
31
|
+
const parsed = parse(readFileSync(rolePath, "utf8"));
|
|
32
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) roleFile = parsed as Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
const roster = Array.isArray(roleFile.roster) ? roleFile.roster.filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry)) : [];
|
|
35
|
+
const existing = roster.findIndex((entry) => entry.model === model);
|
|
36
|
+
if (removeRole) { if (existing >= 0) roster.splice(existing, 1); }
|
|
37
|
+
else if (existing < 0) roster.push({ model, enabled: true });
|
|
38
|
+
roleFile.schema ??= "kxm.role.v1"; roleFile.id ??= role; roleFile.roster = roster;
|
|
39
|
+
mkdirSync(join(root, ".kxm", "roles"), { recursive: true });
|
|
40
|
+
writeFileSync(rolePath, stringify(roleFile), "utf8");
|
|
41
|
+
}
|
|
42
|
+
policy.updatedAt = new Date().toISOString();
|
|
43
|
+
mkdirSync(join(root, ".kxm"), { recursive: true });
|
|
44
|
+
writeFileSync(join(root, ".kxm", "routes.yaml"), stringify(policy), "utf8");
|
|
45
|
+
return policy;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function listRoleBindings(root: string): Record<string, string[]> {
|
|
49
|
+
const dir = join(root, ".kxm", "roles"); const result: Record<string, string[]> = {};
|
|
50
|
+
if (!existsSync(dir)) return result;
|
|
51
|
+
for (const file of readdirSync(dir).filter((name) => name.endsWith(".yaml"))) {
|
|
52
|
+
const role = file.slice(0, -5); const value = parse(readFileSync(join(dir, file), "utf8")) as { roster?: Array<{ model?: unknown }> };
|
|
53
|
+
result[role] = (value.roster ?? []).map((entry) => entry.model).filter((model): model is string => typeof model === "string");
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function isRouteAdmitted(root: string, modelId: string): boolean {
|
|
59
|
+
const policy = loadRoutePolicy(root);
|
|
60
|
+
return policy.admitted.includes(modelId) && !policy.disabled.includes(modelId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function listInventoryModels(root: string): string[] {
|
|
64
|
+
const path = join(root, ".kxm", "models", "inventory.yaml");
|
|
65
|
+
if (!existsSync(path)) return [];
|
|
66
|
+
const value = parse(readFileSync(path, "utf8")) as { models?: Array<{ id?: unknown }> };
|
|
67
|
+
return (value.models ?? []).map((m) => m.id).filter((id): id is string => typeof id === "string");
|
|
68
|
+
}
|
|
@@ -2,7 +2,7 @@ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { parse } from "yaml";
|
|
5
|
-
import {
|
|
5
|
+
import { isRouteAdmitted, listRoleBindings } from "./routes.ts";
|
|
6
6
|
import {
|
|
7
7
|
buildFormalContextPacket,
|
|
8
8
|
buildHandoffManifest,
|
|
@@ -1317,7 +1317,7 @@ function resolveProducerRoute(
|
|
|
1317
1317
|
};
|
|
1318
1318
|
}
|
|
1319
1319
|
|
|
1320
|
-
if (!
|
|
1320
|
+
if (!isRouteAdmitted(projectRoot, selector)) {
|
|
1321
1321
|
return {
|
|
1322
1322
|
error: {
|
|
1323
1323
|
reason: "step_unsupported",
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
type VnextRuntimeContext,
|
|
24
24
|
} from "./vnext-runtime.ts";
|
|
25
25
|
import { createVnextOneShotProducer } from "./vnext-oneshot-producer.ts";
|
|
26
|
-
import {
|
|
26
|
+
import { isRouteAdmitted } from "./routes.ts";
|
|
27
27
|
import { VnextRunScheduler, createVnextSimulatedProducer, recordDriveReceipt, recoverVnextRun, vnextDrivePollProjection } from "./vnext-engine.ts";
|
|
28
28
|
import { vnextDriveSession, vnextOpenDriveSessions } from "./vnext-runtime-owner.ts";
|
|
29
29
|
|
|
@@ -487,7 +487,7 @@ async function startVnextRuntimeSupervisorInner(
|
|
|
487
487
|
const value = model as Record<string, unknown>;
|
|
488
488
|
const provider = typeof value.provider === "string" ? value.provider : undefined;
|
|
489
489
|
const modelName = typeof value.model === "string" ? value.model : undefined;
|
|
490
|
-
if (!provider || !modelName || !
|
|
490
|
+
if (!provider || !modelName || !isRouteAdmitted(projectRoot, `${provider}/${modelName}`)) {
|
|
491
491
|
throw new Error("producer_route_not_admitted");
|
|
492
492
|
}
|
|
493
493
|
return { provider, model: modelName };
|
package/.kxm/producers.yaml
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
schema: kxm.producers.v1
|
|
2
|
-
updatedAt: 2026-09-16T14:55:00.000Z
|
|
3
|
-
promoted:
|
|
4
|
-
- anthropic/fable
|
|
5
|
-
- openai/gpt-5.6-sol
|
|
6
|
-
- xai/grok-4.6
|
|
7
|
-
- openrouter/qwen/qwen3-coder-plus
|
|
8
|
-
# Qualified 2026-09-16 from the refreshed catalog (.kxm/models/inventory.yaml,
|
|
9
|
-
# fetchedAt 2026-09-16T14:54:53Z). Quality evidence (side-by-side runs) is
|
|
10
|
-
# queued — pending OpenRouter auth; not in any role rotation yet.
|
|
11
|
-
- openrouter/qwen/qwen3.8-flash # 1M ctx, thinking; $0.15/M in, $0.47/M out
|
|
12
|
-
- openrouter/z-ai/glm-5.3-flash # 1.31M ctx, thinking; $0.09/M in, $0.30/M out
|
|
13
|
-
# Qualified 2026-09-16 via live probes on the native z.ai coding plan
|
|
14
|
-
# (provider zai-coding-cn, subscription/unmetered): smoke + repo-shaped edit
|
|
15
|
-
# probe + vision probe (screenshot color read) all passed. glm-5.3-highspeed
|
|
16
|
-
# and glm-5v-turbo NOT admitted: plan returns 429 1311 (not in subscription).
|
|
17
|
-
# glm-4.6v verified for vision but not admitted (superseded by 5.3-flash).
|
|
18
|
-
- zai-coding-cn/glm-5.3 # 1M ctx, thinking; coding-plan subscription
|
|
19
|
-
- zai-coding-cn/glm-5.3-flash # 1M ctx, thinking, vision; coding-plan subscription
|
|
20
|
-
# Qualified 2026-09-16 via live probes (smoke; subscription/unmetered):
|
|
21
|
-
# agy = Antigravity CLI (google sub, Gemini kebab ids bake in the effort tier;
|
|
22
|
-
# harness default is flash-high). qwen-token-plan edit probe passed on
|
|
23
|
-
# qwen3.8-flash. deepseek-v4.1-flash and glm-5.x on qwen-token-plan are
|
|
24
|
-
# third-party models hosted by that plan.
|
|
25
|
-
- google/gemini-3.8-flash-medium # agy harness, 1M ctx
|
|
26
|
-
- google/gemini-3.8-flash-high # agy harness, 1M ctx; oneshot default for agy
|
|
27
|
-
- qwen-token-plan/qwen3.8-flash # 1M ctx, thinking, vision; edit probe passed
|
|
28
|
-
- qwen-token-plan/qwen3.8-max # 1M ctx, thinking, vision
|
|
29
|
-
- qwen-token-plan/deepseek-v4.1-flash # 1M ctx, thinking, vision
|
|
30
|
-
demoted: []
|
|
31
|
-
enabled:
|
|
32
|
-
- anthropic/fable
|
|
33
|
-
- openai/gpt-5.6-sol
|
|
34
|
-
- xai/grok-4.6
|
|
35
|
-
- openrouter/qwen/qwen3-coder-plus
|
|
36
|
-
- openrouter/qwen/qwen3.8-flash
|
|
37
|
-
- openrouter/z-ai/glm-5.3-flash
|
|
38
|
-
- zai-coding-cn/glm-5.3
|
|
39
|
-
- zai-coding-cn/glm-5.3-flash
|
|
40
|
-
- google/gemini-3.8-flash-medium
|
|
41
|
-
- google/gemini-3.8-flash-high
|
|
42
|
-
- qwen-token-plan/qwen3.8-flash
|
|
43
|
-
- qwen-token-plan/qwen3.8-max
|
|
44
|
-
- qwen-token-plan/deepseek-v4.1-flash
|
|
45
|
-
disabled: []
|
|
46
|
-
roles:
|
|
47
|
-
implementer:
|
|
48
|
-
- xai/grok-4.6
|
|
49
|
-
- openrouter/qwen/qwen3-coder-plus
|
|
50
|
-
critic-arch:
|
|
51
|
-
- anthropic/fable
|
|
52
|
-
critic-cli:
|
|
53
|
-
- openai/gpt-5.6-sol
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { parse, stringify } from "yaml";
|
|
4
|
-
|
|
5
|
-
export interface ProducerPolicy { schema: "kxm.producers.v1"; updatedAt: string; promoted: string[]; demoted: string[]; enabled: string[]; disabled: string[]; roles: Record<string, string[]>; }
|
|
6
|
-
const empty = (): ProducerPolicy => ({ schema: "kxm.producers.v1", updatedAt: new Date().toISOString(), promoted: [], demoted: [], enabled: [], disabled: [], roles: {} });
|
|
7
|
-
export function loadProducerPolicy(root: string): ProducerPolicy {
|
|
8
|
-
const path = join(root, ".kxm", "producers.yaml");
|
|
9
|
-
if (!existsSync(path)) return empty();
|
|
10
|
-
const value = parse(readFileSync(path, "utf8")) as Partial<ProducerPolicy>;
|
|
11
|
-
if (value?.schema !== "kxm.producers.v1" || !Array.isArray(value.promoted) || !Array.isArray(value.demoted)) throw new Error("invalid .kxm/producers.yaml");
|
|
12
|
-
return { schema: "kxm.producers.v1", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : new Date().toISOString(), promoted: value.promoted.filter((x): x is string => typeof x === "string"), demoted: value.demoted.filter((x): x is string => typeof x === "string"), enabled: Array.isArray(value.enabled) ? value.enabled.filter((x): x is string => typeof x === "string") : [], disabled: Array.isArray(value.disabled) ? value.disabled.filter((x): x is string => typeof x === "string") : [], roles: value.roles && typeof value.roles === "object" ? Object.fromEntries(Object.entries(value.roles).filter(([, v]) => Array.isArray(v)).map(([k, v]) => [k, (v as unknown[]).filter((x): x is string => typeof x === "string")])) : {} };
|
|
13
|
-
}
|
|
14
|
-
export function updateProducer(root: string, model: string, status: "promoted" | "demoted"): ProducerPolicy {
|
|
15
|
-
const policy = loadProducerPolicy(root);
|
|
16
|
-
policy.promoted = policy.promoted.filter((x) => x !== model);
|
|
17
|
-
policy.demoted = policy.demoted.filter((x) => x !== model);
|
|
18
|
-
policy[status].push(model);
|
|
19
|
-
policy.updatedAt = new Date().toISOString();
|
|
20
|
-
mkdirSync(join(root, ".kxm"), { recursive: true });
|
|
21
|
-
writeFileSync(join(root, ".kxm", "producers.yaml"), stringify(policy), "utf8");
|
|
22
|
-
return policy;
|
|
23
|
-
}
|
|
24
|
-
export function setModelState(root: string, model: string, state: "enabled" | "disabled", role?: string, removeRole = false): ProducerPolicy {
|
|
25
|
-
const policy = loadProducerPolicy(root);
|
|
26
|
-
policy.enabled = policy.enabled.filter((x) => x !== model);
|
|
27
|
-
policy.disabled = policy.disabled.filter((x) => x !== model);
|
|
28
|
-
policy[state].push(model);
|
|
29
|
-
if (role) {
|
|
30
|
-
if (!/^[a-z][a-z0-9_-]{0,63}$/i.test(role)) throw new Error("invalid role id");
|
|
31
|
-
const rolePath = join(root, ".kxm", "roles", `${role}.yaml`);
|
|
32
|
-
let roleFile: Record<string, unknown> = {};
|
|
33
|
-
if (existsSync(rolePath)) {
|
|
34
|
-
const parsed = parse(readFileSync(rolePath, "utf8"));
|
|
35
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) roleFile = parsed as Record<string, unknown>;
|
|
36
|
-
}
|
|
37
|
-
const roster = Array.isArray(roleFile.roster) ? roleFile.roster.filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry)) : [];
|
|
38
|
-
const existing = roster.findIndex((entry) => entry.model === model);
|
|
39
|
-
if (removeRole) { if (existing >= 0) roster.splice(existing, 1); }
|
|
40
|
-
else if (existing < 0) roster.push({ model, enabled: true });
|
|
41
|
-
roleFile.schema ??= "kxm.role.v1"; roleFile.id ??= role; roleFile.roster = roster;
|
|
42
|
-
mkdirSync(join(root, ".kxm", "roles"), { recursive: true });
|
|
43
|
-
writeFileSync(rolePath, stringify(roleFile), "utf8");
|
|
44
|
-
}
|
|
45
|
-
policy.updatedAt = new Date().toISOString();
|
|
46
|
-
mkdirSync(join(root, ".kxm"), { recursive: true });
|
|
47
|
-
writeFileSync(join(root, ".kxm", "producers.yaml"), stringify(policy), "utf8");
|
|
48
|
-
return policy;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function listRoleBindings(root: string): Record<string, string[]> {
|
|
52
|
-
const dir = join(root, ".kxm", "roles"); const result: Record<string, string[]> = {};
|
|
53
|
-
if (!existsSync(dir)) return result;
|
|
54
|
-
for (const file of readdirSync(dir).filter((name) => name.endsWith(".yaml"))) {
|
|
55
|
-
const role = file.slice(0, -5); const value = parse(readFileSync(join(dir, file), "utf8")) as { roster?: Array<{ model?: unknown }> };
|
|
56
|
-
result[role] = (value.roster ?? []).map((entry) => entry.model).filter((model): model is string => typeof model === "string");
|
|
57
|
-
}
|
|
58
|
-
return result;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function isProducerAdmitted(root: string, modelId: string): boolean {
|
|
62
|
-
const policy = loadProducerPolicy(root);
|
|
63
|
-
return policy.enabled.includes(modelId) && policy.promoted.includes(modelId) && !policy.disabled.includes(modelId) && !policy.demoted.includes(modelId);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function listInventoryModels(root: string): string[] {
|
|
67
|
-
const path = join(root, ".kxm", "models", "inventory.yaml");
|
|
68
|
-
if (!existsSync(path)) return [];
|
|
69
|
-
const value = parse(readFileSync(path, "utf8")) as { models?: Array<{ id?: unknown }> };
|
|
70
|
-
return (value.models ?? []).map((m) => m.id).filter((id): id is string => typeof id === "string");
|
|
71
|
-
}
|