@kontextmind/kxm 0.7.130 → 0.7.131
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/README.md +4 -1
- package/.kxm/agents/coordinator.yaml +1 -0
- package/.kxm/agents/critic-arch.yaml +1 -4
- package/.kxm/agents/critic-cli.yaml +1 -4
- package/.kxm/agents/implementer.yaml +1 -4
- package/.kxm/workflows/implement-only.yaml +1 -1
- package/.kxm/workflows/review-arch-only.yaml +1 -1
- package/.kxm/workflows/review-cli-only.yaml +1 -1
- package/CHANGELOG.md +22 -1
- package/docs/concepts/architecture.md +1 -1
- package/docs/contracts/routing.md +3 -3
- package/docs/contributing/assignment-runner.md +14 -15
- package/docs/contributing/development.md +19 -5
- package/docs/contributing/harness-routing-internals.md +8 -8
- package/docs/glossary.md +1 -1
- package/docs/guides/agent-skills.md +1 -1
- package/docs/operations/backup-and-restore.md +4 -4
- package/docs/reference/cli-reference.md +26 -8
- package/docs/reference/config-reference.md +76 -153
- package/docs/reference/harness-routing.md +29 -21
- package/docs/reference/workflow-catalog.md +4 -4
- package/docs/start/first-workflow.md +1 -1
- package/examples/project/.kxm/agents/coordinator.yaml +1 -2
- package/examples/project/.kxm/agents/critic-1.yaml +1 -3
- package/examples/project/.kxm/agents/critic-2.yaml +1 -2
- package/examples/project/.kxm/agents/critic-3.yaml +2 -3
- package/examples/project/.kxm/agents/implementer.yaml +1 -2
- package/examples/project/.kxm/agents/planner.yaml +1 -2
- package/examples/project/.kxm/agents/reproducer.yaml +1 -2
- package/examples/project/.kxm/agents/reviewer.yaml +1 -2
- package/examples/project/.kxm/workflows/fix.yaml +0 -12
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +287 -249
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime-supervisor.js +222 -242
- package/plugins/kxm/dist/runtime.js +224 -244
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-definitions/SKILL.md +8 -0
- package/plugins/kxm/src/cli/project.ts +4 -4
- package/plugins/kxm/src/engine.ts +168 -163
- package/plugins/kxm/src/init-guide-setup.ts +75 -15
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/oneshot-producer.ts +3 -15
- package/plugins/kxm/src/project-config.ts +83 -70
- package/plugins/kxm/src/routes.ts +26 -18
- package/plugins/kxm/src/runtime-supervisor.ts +0 -18
- package/plugins/kxm/src/suggest.ts +2 -2
- package/plugins/kxm/src/template.ts +2 -14
- package/schemas/agent.schema.json +8 -0
- package/scripts/roster-policy.d.mts +2 -1
- package/scripts/roster-policy.mjs +119 -22
|
@@ -15636,21 +15636,9 @@ function coreTemplate(projectId, projectName, variant) {
|
|
|
15636
15636
|
]);
|
|
15637
15637
|
if (variant === "v4-registry") {
|
|
15638
15638
|
const coordinator = files.get(".kxm/agents/coordinator.yaml");
|
|
15639
|
-
if (coordinator) {
|
|
15640
|
-
files.set(".kxm/agents/coordinator.yaml", {
|
|
15641
|
-
...coordinator,
|
|
15642
|
-
harness: "claude",
|
|
15643
|
-
model: { provider: "anthropic", model: "fable" }
|
|
15644
|
-
});
|
|
15645
|
-
}
|
|
15639
|
+
if (coordinator) files.set(".kxm/agents/coordinator.yaml", { ...coordinator, role: "planner" });
|
|
15646
15640
|
const implementer = files.get(".kxm/agents/implementer.yaml");
|
|
15647
|
-
if (implementer) {
|
|
15648
|
-
files.set(".kxm/agents/implementer.yaml", {
|
|
15649
|
-
...implementer,
|
|
15650
|
-
harness: "grok",
|
|
15651
|
-
model: { provider: "xai", model: "grok-4.6" }
|
|
15652
|
-
});
|
|
15653
|
-
}
|
|
15641
|
+
if (implementer) files.set(".kxm/agents/implementer.yaml", { ...implementer, role: "writer" });
|
|
15654
15642
|
const workflow = files.get(".kxm/workflows/default.yaml");
|
|
15655
15643
|
if (workflow) {
|
|
15656
15644
|
const limits = { ...workflow.limits };
|
|
@@ -17486,7 +17474,7 @@ function readTemplateProvenance(registry, root) {
|
|
|
17486
17474
|
}
|
|
17487
17475
|
return value;
|
|
17488
17476
|
}
|
|
17489
|
-
function listNamedResources(registry, root, directory, logicalDirectory, kind, replacedId) {
|
|
17477
|
+
function listNamedResources(registry, root, directory, logicalDirectory, kind, replacedId, collected) {
|
|
17490
17478
|
const resources = /* @__PURE__ */ new Map();
|
|
17491
17479
|
if (!existsSync3(directory)) return resources;
|
|
17492
17480
|
const stat = lstatSync(directory);
|
|
@@ -17525,7 +17513,10 @@ function listNamedResources(registry, root, directory, logicalDirectory, kind, r
|
|
|
17525
17513
|
else throw error;
|
|
17526
17514
|
}
|
|
17527
17515
|
}
|
|
17528
|
-
if (issues.length > 0)
|
|
17516
|
+
if (issues.length > 0) {
|
|
17517
|
+
if (collected) collected.push(...issues);
|
|
17518
|
+
else throw new KxmConfigError(issues);
|
|
17519
|
+
}
|
|
17529
17520
|
return resources;
|
|
17530
17521
|
}
|
|
17531
17522
|
function valuesOf(object, field) {
|
|
@@ -17789,6 +17780,9 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
17789
17780
|
for (const repositoryId of Object.keys(objectValue(step.repositories) ?? {})) {
|
|
17790
17781
|
if (!repositories.has(repositoryId)) issues.push(issue3("reference", "repository_unknown", file, `${stepId} references unknown repository ${repositoryId}`));
|
|
17791
17782
|
}
|
|
17783
|
+
if ((kind === "agent" || kind === "moa") && step.model !== void 0) {
|
|
17784
|
+
issues.push(issue3("semantic", "producer_route_unsupported", file, `${stepId} model is not honored; remove model from the step`));
|
|
17785
|
+
}
|
|
17792
17786
|
selectorCandidates(step.model, models, file, `${stepId}.model`, issues);
|
|
17793
17787
|
const assignment = objectValue(step.assignments);
|
|
17794
17788
|
const declaredAgents = assignment ? names(assignment.allowedAgents) : [];
|
|
@@ -17971,7 +17965,7 @@ function validateModelReferences(models, issues) {
|
|
|
17971
17965
|
};
|
|
17972
17966
|
for (const id of models.keys()) walk(id, []);
|
|
17973
17967
|
}
|
|
17974
|
-
function validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, projectRoot,
|
|
17968
|
+
function validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, projectRoot, roles = /* @__PURE__ */ new Map()) {
|
|
17975
17969
|
const issues = [];
|
|
17976
17970
|
const entries = valuesOf(project.value, "repositories").map((candidate) => objectValue(candidate)).filter((candidate) => Boolean(candidate));
|
|
17977
17971
|
const repositoryIds = /* @__PURE__ */ new Set();
|
|
@@ -18012,84 +18006,84 @@ function validateBundle(project, repositories, agents, models, workflows, enviro
|
|
|
18012
18006
|
const defaultHarness = stringValue(project.value.defaultHarness) ?? DEFAULT_HARNESS;
|
|
18013
18007
|
if (!harnesses.has(defaultHarness)) issues.push(issue3("reference", "harness_unknown", project.logicalPath, `defaultHarness ${defaultHarness} is not registered`));
|
|
18014
18008
|
for (const agent of agents.values()) {
|
|
18009
|
+
if (agent.value.model !== void 0 || agent.value.harness !== void 0) {
|
|
18010
|
+
issues.push(issue3("semantic", "retired_agent_routing_fields", agent.logicalPath, "routing resolves from role; remove model and harness"));
|
|
18011
|
+
}
|
|
18015
18012
|
validateToolPolicy(agent, objectValue(agent.value.tools), "tools", issues);
|
|
18016
18013
|
const executor = stringValue(agent.value.executor);
|
|
18017
18014
|
if (executor && !executors.has(executor)) issues.push(issue3("reference", "executor_unknown", agent.logicalPath, `executor ${executor} is not registered`));
|
|
18018
|
-
const harness = stringValue(agent.value.harness) ?? defaultHarness;
|
|
18019
|
-
if (!harnesses.has(harness)) issues.push(issue3("reference", "harness_unknown", agent.logicalPath, `harness ${harness} is not registered`));
|
|
18020
18015
|
const preset = stringValue(objectValue(agent.value.tools)?.preset);
|
|
18021
18016
|
if (preset && !presets.has(preset)) issues.push(issue3("reference", "tool_preset_unknown", agent.logicalPath, `tool preset ${preset} is not registered`));
|
|
18022
18017
|
for (const repositoryId of Object.keys(objectValue(agent.value.repositories) ?? {})) {
|
|
18023
18018
|
if (!repositoryIds.has(repositoryId)) issues.push(issue3("reference", "repository_unknown", agent.logicalPath, `references unknown repository ${repositoryId}`));
|
|
18024
18019
|
}
|
|
18025
|
-
const candidates = selectorCandidates(agent.value.model, models, agent.logicalPath, "model", issues);
|
|
18026
|
-
const declaredHarness = stringValue(agent.value.harness);
|
|
18027
|
-
if (declaredHarness && harnesses.has(declaredHarness)) {
|
|
18028
|
-
for (const candidate of candidates) {
|
|
18029
|
-
const candidateProvider = stringValue(candidate.value.provider);
|
|
18030
|
-
const candidateModel = stringValue(candidate.value.model);
|
|
18031
|
-
const validation = validateHarnessModelPair(declaredHarness, { provider: candidateProvider, model: candidateModel });
|
|
18032
|
-
if (!validation.valid) {
|
|
18033
|
-
issues.push(issue3("semantic", validation.issue ?? "harness_unhosted_model", agent.logicalPath, validation.message ?? `harness ${declaredHarness} cannot host model ${candidateModel ?? candidate.logicalPath}`));
|
|
18034
|
-
}
|
|
18035
|
-
}
|
|
18036
|
-
}
|
|
18037
18020
|
}
|
|
18038
18021
|
validateModelReferences(models, issues);
|
|
18039
18022
|
const defaultWorkflow = stringValue(project.value.defaultWorkflow) ?? "default";
|
|
18040
18023
|
if (!workflows.has(defaultWorkflow)) issues.push(issue3("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
|
|
18041
18024
|
for (const workflow of workflows.values()) validateWorkflow(workflow, agents, models, repositoryIds, gates, issues);
|
|
18025
|
+
if (projectRoot && existsSync3(join2(projectRoot, ".kxm", "roster.yaml"))) {
|
|
18026
|
+
issues.push(issue3("semantic", "retired_roster_file", ".kxm/roster.yaml", "create the role and model files and delete roster.yaml"));
|
|
18027
|
+
}
|
|
18028
|
+
if (projectRoot && existsSync3(join2(projectRoot, ".kxm", "roles"))) {
|
|
18029
|
+
issues.push(...developerRolePolicyIssues(projectRoot));
|
|
18030
|
+
}
|
|
18042
18031
|
if (projectRoot) {
|
|
18043
|
-
|
|
18044
|
-
|
|
18045
|
-
|
|
18032
|
+
issues.push(...rosterModelIssues(projectRoot, roles));
|
|
18033
|
+
issues.push(...originHashIssues(projectRoot, models));
|
|
18034
|
+
}
|
|
18035
|
+
return sortIssues3(issues);
|
|
18036
|
+
}
|
|
18037
|
+
function rosterModelIssues(projectRoot, roles) {
|
|
18038
|
+
const issues = [];
|
|
18039
|
+
for (const role of roles.values()) {
|
|
18040
|
+
for (const entry of valuesOf(role.value, "roster")) {
|
|
18041
|
+
const route = stringValue(objectValue(entry)?.route);
|
|
18042
|
+
if (!route) continue;
|
|
18043
|
+
const logical = `.kxm/models/${route}.yaml`;
|
|
18044
|
+
const file = join2(projectRoot, ".kxm", "models", `${route}.yaml`);
|
|
18045
|
+
let harness;
|
|
18046
18046
|
try {
|
|
18047
|
-
|
|
18048
|
-
|
|
18049
|
-
|
|
18050
|
-
|
|
18051
|
-
|
|
18052
|
-
|
|
18053
|
-
const named = direct ? [direct] : [];
|
|
18054
|
-
if (route) {
|
|
18055
|
-
const modelFile = join2(projectRoot, ".kxm", "models", `${route}.yaml`);
|
|
18056
|
-
if (existsSync3(modelFile)) {
|
|
18057
|
-
try {
|
|
18058
|
-
const modelDoc = objectValue(parseRestrictedYaml2(readFileSync(modelFile, "utf8"), modelFile));
|
|
18059
|
-
const model = modelDoc ? stringValue(modelDoc.model) : void 0;
|
|
18060
|
-
const vendor = modelDoc ? stringValue(modelDoc.vendor) : void 0;
|
|
18061
|
-
const harness = modelDoc ? stringValue(modelDoc.harness) : void 0;
|
|
18062
|
-
if (model) named.push(model);
|
|
18063
|
-
if (vendor && model) named.push(`${vendor}/${model}`);
|
|
18064
|
-
if (harness && model) named.push(`${harness}/${model}`);
|
|
18065
|
-
} catch {
|
|
18066
|
-
}
|
|
18067
|
-
}
|
|
18068
|
-
}
|
|
18069
|
-
return named;
|
|
18070
|
-
});
|
|
18071
|
-
const agentModelObj = objectValue(implementerAgent.value.model);
|
|
18072
|
-
const agentModelStr = stringValue(implementerAgent.value.model);
|
|
18073
|
-
const agentProvider = agentModelObj ? stringValue(agentModelObj.provider) : void 0;
|
|
18074
|
-
const agentModel = agentModelObj ? stringValue(agentModelObj.model) : agentModelStr;
|
|
18075
|
-
const canonicalAgentModel = agentProvider && agentModel ? `${agentProvider}/${agentModel}` : agentModel;
|
|
18076
|
-
if (enabledRosterModels.length > 0 && canonicalAgentModel) {
|
|
18077
|
-
const matches = enabledRosterModels.some((rm) => rm === canonicalAgentModel || rm === agentModel || rm.endsWith(`/${agentModel}`));
|
|
18078
|
-
if (!matches) {
|
|
18079
|
-
issues.push(issue3("semantic", "role_roster_conflicts_with_agent", ".kxm/roles/writer.yaml", `role roster in .kxm/roles/writer.yaml does not include agent model ${canonicalAgentModel} from ${implementerAgent.logicalPath}`));
|
|
18080
|
-
}
|
|
18081
|
-
}
|
|
18082
|
-
} catch (error) {
|
|
18083
|
-
if (error instanceof KxmConfigError) {
|
|
18084
|
-
issues.push(...error.issues);
|
|
18085
|
-
}
|
|
18047
|
+
if (existsSync3(file)) harness = stringValue(parseRestrictedYaml2(readFileSync(file, "utf8"), logical).harness);
|
|
18048
|
+
} catch {
|
|
18049
|
+
harness = void 0;
|
|
18050
|
+
}
|
|
18051
|
+
if (!harness) {
|
|
18052
|
+
issues.push(issue3("semantic", "roster_model_unreadable", role.logicalPath, `roster route ${route} does not resolve to a readable ${logical} carrying harness`));
|
|
18086
18053
|
}
|
|
18087
18054
|
}
|
|
18088
18055
|
}
|
|
18089
|
-
|
|
18090
|
-
|
|
18056
|
+
return issues;
|
|
18057
|
+
}
|
|
18058
|
+
function originHashIssues(projectRoot, models) {
|
|
18059
|
+
const issues = [];
|
|
18060
|
+
for (const model of models.values()) {
|
|
18061
|
+
const origin = objectValue(model.value.origin);
|
|
18062
|
+
const source = origin ? stringValue(origin.source) : void 0;
|
|
18063
|
+
const digest2 = origin ? stringValue(origin.sha256) : void 0;
|
|
18064
|
+
if (!source || !digest2) continue;
|
|
18065
|
+
const file = resolve(projectRoot, source);
|
|
18066
|
+
const escaped = relative(projectRoot, file);
|
|
18067
|
+
if (isAbsolute(source) || escaped.startsWith("..") || isAbsolute(escaped)) {
|
|
18068
|
+
issues.push(issue3("semantic", "origin_evidence_missing", model.logicalPath, `missing evidence bytes for ${source}`));
|
|
18069
|
+
continue;
|
|
18070
|
+
}
|
|
18071
|
+
let actual;
|
|
18072
|
+
try {
|
|
18073
|
+
actual = createHash3("sha256").update(readFileSync(file, "utf8"), "utf8").digest("hex");
|
|
18074
|
+
} catch (error) {
|
|
18075
|
+
const code = error.code;
|
|
18076
|
+
if (code === "ENOENT" || code === "EACCES" || code === "EPERM" || code === "EISDIR") {
|
|
18077
|
+
issues.push(issue3("semantic", "origin_evidence_missing", model.logicalPath, `missing evidence bytes for ${source}`));
|
|
18078
|
+
continue;
|
|
18079
|
+
}
|
|
18080
|
+
throw error;
|
|
18081
|
+
}
|
|
18082
|
+
if (actual !== digest2) {
|
|
18083
|
+
issues.push(issue3("semantic", "origin_hash_mismatch", model.logicalPath, "origin evidence hash does not match supplied bytes"));
|
|
18084
|
+
}
|
|
18091
18085
|
}
|
|
18092
|
-
return
|
|
18086
|
+
return issues;
|
|
18093
18087
|
}
|
|
18094
18088
|
function developerCeilings() {
|
|
18095
18089
|
const script = join2(findKxmRepoRoot(import.meta.url), "scripts", "harness-run.mjs");
|
|
@@ -18118,6 +18112,7 @@ function developerCeilings() {
|
|
|
18118
18112
|
}
|
|
18119
18113
|
}
|
|
18120
18114
|
function developerRolePolicyIssues(projectRoot) {
|
|
18115
|
+
if (resolve(projectRoot) !== findKxmRepoRoot(import.meta.url)) return [];
|
|
18121
18116
|
const rolesDir = join2(projectRoot, ".kxm", "roles");
|
|
18122
18117
|
const modelsDir = join2(projectRoot, ".kxm", "models");
|
|
18123
18118
|
const roles = {};
|
|
@@ -18138,6 +18133,7 @@ function developerRolePolicyIssues(projectRoot) {
|
|
|
18138
18133
|
parseIssues.push(...error.issues);
|
|
18139
18134
|
continue;
|
|
18140
18135
|
}
|
|
18136
|
+
throw error;
|
|
18141
18137
|
}
|
|
18142
18138
|
}
|
|
18143
18139
|
};
|
|
@@ -18152,7 +18148,7 @@ function developerRolePolicyIssues(projectRoot) {
|
|
|
18152
18148
|
}
|
|
18153
18149
|
const ceilings = developerCeilings();
|
|
18154
18150
|
if (!ceilings.ok) {
|
|
18155
|
-
return [...parseIssues, issue3("semantic", "developer_ceilings_unavailable", ".kxm/
|
|
18151
|
+
return [...parseIssues, issue3("semantic", "developer_ceilings_unavailable", ".kxm/models", `developer ceilings could not be loaded: ${ceilings.detail}`)];
|
|
18156
18152
|
}
|
|
18157
18153
|
const result = validatePolicyDraft({ models, roles, evidence }, {
|
|
18158
18154
|
ceilings: ceilings.ROUTES,
|
|
@@ -18241,7 +18237,8 @@ function loadProjectBundle(projectRoot, options, candidate) {
|
|
|
18241
18237
|
}
|
|
18242
18238
|
if (earlyIssues.length > 0) throw new KxmConfigError(earlyIssues);
|
|
18243
18239
|
const agents = listNamedResources(registry, root, join2(root, ".kxm", "agents"), ".kxm/agents", "agent");
|
|
18244
|
-
const
|
|
18240
|
+
const modelIssues = [];
|
|
18241
|
+
const models = listNamedResources(registry, root, join2(root, ".kxm", "models"), ".kxm/models", "model", void 0, modelIssues);
|
|
18245
18242
|
const roles = listNamedResources(registry, root, join2(root, ".kxm", "roles"), ".kxm/roles", "role", writerRole === void 0 ? void 0 : "writer");
|
|
18246
18243
|
if (writerRole !== void 0) {
|
|
18247
18244
|
const logicalPath = ".kxm/roles/writer.yaml";
|
|
@@ -18368,8 +18365,8 @@ function loadProjectBundle(projectRoot, options, candidate) {
|
|
|
18368
18365
|
}
|
|
18369
18366
|
}
|
|
18370
18367
|
}
|
|
18371
|
-
if (loadIssues.length > 0) throw new KxmConfigError(loadIssues);
|
|
18372
|
-
const issues = validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, root,
|
|
18368
|
+
if (loadIssues.length > 0) throw new KxmConfigError([...loadIssues, ...modelIssues]);
|
|
18369
|
+
const issues = [...modelIssues, ...validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, root, roles)];
|
|
18373
18370
|
if (issues.length > 0) throw new KxmConfigError(issues);
|
|
18374
18371
|
const resources = [project, ...repositories.values(), ...agents.values(), ...models.values(), ...roles.values(), ...workflows.values(), ...environments, ...gateRegistry ? [gateRegistry] : []].sort((left, right) => compareCodeUnits4(left.logicalPath, right.logicalPath));
|
|
18375
18372
|
return {
|
|
@@ -25206,14 +25203,14 @@ var import_yaml4 = __toESM(require_dist(), 1);
|
|
|
25206
25203
|
|
|
25207
25204
|
// plugins/kxm/src/routes.ts
|
|
25208
25205
|
var RETIRED_POLICY = ".kxm/producers.yaml";
|
|
25209
|
-
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: []
|
|
25206
|
+
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [] });
|
|
25210
25207
|
function loadRoutePolicy(root) {
|
|
25211
25208
|
if (existsSync9(join10(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
|
|
25212
25209
|
const path = join10(root, ".kxm", "routes.yaml");
|
|
25213
25210
|
if (!existsSync9(path)) return empty();
|
|
25214
25211
|
const value = (0, import_yaml6.parse)(readFileSync7(path, "utf8"));
|
|
25215
25212
|
if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
|
|
25216
|
-
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") : []
|
|
25213
|
+
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") : [] };
|
|
25217
25214
|
}
|
|
25218
25215
|
function listRoleBindings(root) {
|
|
25219
25216
|
const dir = join10(root, ".kxm", "roles");
|
|
@@ -25226,10 +25223,6 @@ function listRoleBindings(root) {
|
|
|
25226
25223
|
}
|
|
25227
25224
|
return result;
|
|
25228
25225
|
}
|
|
25229
|
-
function isRouteAdmitted(root, modelId) {
|
|
25230
|
-
const policy = loadRoutePolicy(root);
|
|
25231
|
-
return policy.admitted.includes(modelId) && !policy.disabled.includes(modelId);
|
|
25232
|
-
}
|
|
25233
25226
|
|
|
25234
25227
|
// plugins/kxm/src/worktree-witness.ts
|
|
25235
25228
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -28818,25 +28811,18 @@ function commitCommandUncertainty(context, prepared, token, reason, observation,
|
|
|
28818
28811
|
}
|
|
28819
28812
|
}
|
|
28820
28813
|
var kxmPanelDispatchSeams = {};
|
|
28821
|
-
function
|
|
28822
|
-
|
|
28823
|
-
|
|
28824
|
-
|
|
28825
|
-
|
|
28826
|
-
|
|
28827
|
-
|
|
28828
|
-
|
|
28829
|
-
|
|
28830
|
-
|
|
28831
|
-
|
|
28832
|
-
const model = typeof parsed.model === "string" ? parsed.model : "";
|
|
28833
|
-
const vendor = typeof parsed.vendor === "string" ? parsed.vendor : "";
|
|
28834
|
-
const harness = typeof parsed.harness === "string" ? parsed.harness : "";
|
|
28835
|
-
if (model) selectors.add(model);
|
|
28836
|
-
if (vendor && model) selectors.add(`${vendor}/${model}`);
|
|
28837
|
-
if (harness && model) selectors.add(`${harness}/${model}`);
|
|
28814
|
+
function readYamlFile(file) {
|
|
28815
|
+
return readModelDocument(file);
|
|
28816
|
+
}
|
|
28817
|
+
function readModelDocument(file) {
|
|
28818
|
+
if (!existsSync12(file)) return void 0;
|
|
28819
|
+
try {
|
|
28820
|
+
const parsed = (0, import_yaml9.parse)(readFileSync10(file, "utf8"));
|
|
28821
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
28822
|
+
return parsed;
|
|
28823
|
+
} catch {
|
|
28824
|
+
return void 0;
|
|
28838
28825
|
}
|
|
28839
|
-
return [...selectors];
|
|
28840
28826
|
}
|
|
28841
28827
|
function unreconciledPanelAttemptId(state) {
|
|
28842
28828
|
const current = state.currentStep;
|
|
@@ -28853,82 +28839,118 @@ function unreconciledPanelAttemptId(state) {
|
|
|
28853
28839
|
return void 0;
|
|
28854
28840
|
}
|
|
28855
28841
|
function resolveProducerRoute(projectRoot, step, agentId) {
|
|
28856
|
-
|
|
28857
|
-
const agentFile = join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`);
|
|
28858
|
-
if (existsSync12(agentFile)) {
|
|
28859
|
-
try {
|
|
28860
|
-
const parsed = (0, import_yaml9.parse)(readFileSync10(agentFile, "utf8"));
|
|
28861
|
-
if (typeof parsed?.model === "string") {
|
|
28862
|
-
agentModel = parsed.model;
|
|
28863
|
-
} else if (parsed?.model && typeof parsed.model === "object" && !Array.isArray(parsed.model)) {
|
|
28864
|
-
const declared = parsed.model;
|
|
28865
|
-
const providerOk = typeof declared.provider === "string" && declared.provider.length > 0 && !declared.provider.includes("/");
|
|
28866
|
-
const modelOk = typeof declared.model === "string" && declared.model.length > 0 && !declared.model.startsWith("/") && !declared.model.endsWith("/");
|
|
28867
|
-
if (providerOk && modelOk) {
|
|
28868
|
-
agentModel = `${declared.provider}/${declared.model}`;
|
|
28869
|
-
} else {
|
|
28870
|
-
return {
|
|
28871
|
-
error: {
|
|
28872
|
-
reason: "step_unsupported",
|
|
28873
|
-
field: "model",
|
|
28874
|
-
detail: "producer_route_unsupported: invalid model declaration"
|
|
28875
|
-
}
|
|
28876
|
-
};
|
|
28877
|
-
}
|
|
28878
|
-
}
|
|
28879
|
-
} catch {
|
|
28880
|
-
}
|
|
28881
|
-
}
|
|
28882
|
-
let selector = typeof step.model === "string" ? step.model : agentModel;
|
|
28883
|
-
if (!selector) {
|
|
28884
|
-
if (agentId === "implementer") {
|
|
28885
|
-
selector = "xai/grok-4.6";
|
|
28886
|
-
}
|
|
28887
|
-
}
|
|
28888
|
-
if (!selector) {
|
|
28842
|
+
if ((step.kind === "agent" || step.kind === "moa") && step.model !== void 0) {
|
|
28889
28843
|
return {
|
|
28890
28844
|
error: {
|
|
28891
28845
|
reason: "step_unsupported",
|
|
28892
28846
|
field: "model",
|
|
28893
|
-
detail: "producer_route_unsupported: agent
|
|
28847
|
+
detail: "producer_route_unsupported: agent step model is not honored"
|
|
28894
28848
|
}
|
|
28895
28849
|
};
|
|
28896
28850
|
}
|
|
28897
|
-
const
|
|
28898
|
-
|
|
28851
|
+
const agent = readYamlFile(join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`));
|
|
28852
|
+
const role = typeof agent?.role === "string" ? agent.role : "";
|
|
28853
|
+
if (!role) {
|
|
28899
28854
|
return {
|
|
28900
28855
|
error: {
|
|
28901
28856
|
reason: "step_unsupported",
|
|
28902
28857
|
field: "model",
|
|
28903
|
-
detail:
|
|
28858
|
+
detail: "producer_route_unsupported: agent has no role"
|
|
28904
28859
|
}
|
|
28905
28860
|
};
|
|
28906
28861
|
}
|
|
28907
|
-
|
|
28862
|
+
const roleDoc = readYamlFile(join15(projectRoot, ".kxm", "roles", `${role}.yaml`));
|
|
28863
|
+
const roster = Array.isArray(roleDoc?.roster) ? roleDoc.roster : void 0;
|
|
28864
|
+
if (!roster) {
|
|
28908
28865
|
return {
|
|
28909
28866
|
error: {
|
|
28910
28867
|
reason: "step_unsupported",
|
|
28911
28868
|
field: "model",
|
|
28912
|
-
detail: `producer_route_unsupported:
|
|
28869
|
+
detail: `producer_route_unsupported: role '${role}' has no roster`
|
|
28913
28870
|
}
|
|
28914
28871
|
};
|
|
28915
28872
|
}
|
|
28916
|
-
const
|
|
28917
|
-
const
|
|
28918
|
-
|
|
28919
|
-
|
|
28920
|
-
|
|
28873
|
+
const policy = loadRoutePolicy(projectRoot);
|
|
28874
|
+
for (const entry of roster) {
|
|
28875
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
28876
|
+
const record2 = entry;
|
|
28877
|
+
if (typeof record2.route !== "string" || record2.route.length === 0) continue;
|
|
28878
|
+
const modelPath = join15(projectRoot, ".kxm", "models", `${record2.route}.yaml`);
|
|
28879
|
+
const doc = readModelDocument(modelPath);
|
|
28880
|
+
if (!doc) {
|
|
28881
|
+
return {
|
|
28882
|
+
error: {
|
|
28883
|
+
reason: "step_unsupported",
|
|
28884
|
+
field: "model",
|
|
28885
|
+
detail: `producer_route_unsupported: model file '.kxm/models/${record2.route}.yaml' is missing or unreadable`
|
|
28886
|
+
}
|
|
28887
|
+
};
|
|
28888
|
+
}
|
|
28889
|
+
if (doc.status !== "admitted") continue;
|
|
28890
|
+
const modelName = typeof doc.model === "string" ? doc.model : "";
|
|
28891
|
+
const vendor = typeof doc.vendor === "string" ? doc.vendor : "";
|
|
28892
|
+
const harness = typeof doc.harness === "string" ? doc.harness : "";
|
|
28893
|
+
if (!modelName || !vendor || !harness) continue;
|
|
28894
|
+
const candidates = [modelName, `${vendor}/${modelName}`, `${harness}/${modelName}`];
|
|
28895
|
+
const admittedSelector = candidates.find((candidate) => policy.admitted.includes(candidate));
|
|
28896
|
+
const disabledSelector = candidates.find((candidate) => policy.disabled.includes(candidate));
|
|
28897
|
+
if (!admittedSelector && disabledSelector) {
|
|
28898
|
+
return {
|
|
28899
|
+
error: {
|
|
28900
|
+
reason: "step_unsupported",
|
|
28901
|
+
field: "model",
|
|
28902
|
+
detail: `producer_route_unsupported: first admitted route '${record2.route}' for role '${role}' is disabled`
|
|
28903
|
+
}
|
|
28904
|
+
};
|
|
28905
|
+
}
|
|
28906
|
+
const selector = admittedSelector ?? (modelName.includes("/") ? modelName : `${vendor}/${modelName}`);
|
|
28907
|
+
if (policy.disabled.includes(selector)) {
|
|
28908
|
+
return {
|
|
28909
|
+
error: {
|
|
28910
|
+
reason: "step_unsupported",
|
|
28911
|
+
field: "model",
|
|
28912
|
+
detail: `producer_route_unsupported: first admitted route '${record2.route}' for role '${role}' is disabled`
|
|
28913
|
+
}
|
|
28914
|
+
};
|
|
28915
|
+
}
|
|
28916
|
+
if (!policy.admitted.includes(selector)) {
|
|
28917
|
+
return {
|
|
28918
|
+
error: {
|
|
28919
|
+
reason: "step_unsupported",
|
|
28920
|
+
field: "model",
|
|
28921
|
+
detail: `producer_route_unsupported: model '${selector}' is not admitted`
|
|
28922
|
+
}
|
|
28923
|
+
};
|
|
28924
|
+
}
|
|
28925
|
+
const slash = selector.indexOf("/");
|
|
28926
|
+
if (slash <= 0 || slash === selector.length - 1) {
|
|
28927
|
+
return {
|
|
28928
|
+
error: {
|
|
28929
|
+
reason: "step_unsupported",
|
|
28930
|
+
field: "model",
|
|
28931
|
+
detail: `producer_route_unsupported: invalid selector '${selector}'`
|
|
28932
|
+
}
|
|
28933
|
+
};
|
|
28934
|
+
}
|
|
28935
|
+
const permissions = Array.isArray(doc.permissions) ? doc.permissions.filter((item) => typeof item === "string") : [];
|
|
28921
28936
|
return {
|
|
28922
|
-
|
|
28923
|
-
|
|
28924
|
-
|
|
28925
|
-
|
|
28926
|
-
|
|
28937
|
+
provider: selector.slice(0, slash),
|
|
28938
|
+
model: selector.slice(slash + 1),
|
|
28939
|
+
selector,
|
|
28940
|
+
harness,
|
|
28941
|
+
routeId: record2.route,
|
|
28942
|
+
role,
|
|
28943
|
+
permissions,
|
|
28944
|
+
...typeof record2.effort === "string" ? { effort: record2.effort } : {}
|
|
28927
28945
|
};
|
|
28928
28946
|
}
|
|
28929
|
-
|
|
28930
|
-
|
|
28931
|
-
|
|
28947
|
+
return {
|
|
28948
|
+
error: {
|
|
28949
|
+
reason: "step_unsupported",
|
|
28950
|
+
field: "model",
|
|
28951
|
+
detail: `producer_route_unsupported: role '${role}' has no admitted route`
|
|
28952
|
+
}
|
|
28953
|
+
};
|
|
28932
28954
|
}
|
|
28933
28955
|
function projectAgentStepTimeoutMs(context, run) {
|
|
28934
28956
|
return loadKxmRunPlanEnvelope(context.eventStore, run).projectLimits.agentStepTimeoutMs ?? KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS;
|
|
@@ -29146,8 +29168,7 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
|
29146
29168
|
const writeRefusal = unsupportedLiveWrite(
|
|
29147
29169
|
context.projectRoot,
|
|
29148
29170
|
step,
|
|
29149
|
-
|
|
29150
|
-
resolvedRoute.selector,
|
|
29171
|
+
resolvedRoute,
|
|
29151
29172
|
loadKxmRunPlanEnvelope(context.eventStore, run).projectLimits.maxConcurrentRuns
|
|
29152
29173
|
);
|
|
29153
29174
|
if (writeRefusal) return { kind: "return", state, handoff: { ...writeRefusal, stepId } };
|
|
@@ -29176,7 +29197,7 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
|
29176
29197
|
for (const event of events) context.eventStore.appendEvent(event);
|
|
29177
29198
|
const entered = foldStoredKxmRun(context, run);
|
|
29178
29199
|
persistKxmRunState(context, runId, entered, events[events.length - 1].sequence);
|
|
29179
|
-
const
|
|
29200
|
+
const firstBirth = birthMember(context, {
|
|
29180
29201
|
run,
|
|
29181
29202
|
plan,
|
|
29182
29203
|
step,
|
|
@@ -29187,6 +29208,10 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
|
29187
29208
|
resolvedRoute,
|
|
29188
29209
|
dispatchSources
|
|
29189
29210
|
});
|
|
29211
|
+
if ("handoff" in firstBirth) {
|
|
29212
|
+
return { kind: "return", state: entered, handoff: firstBirth.handoff };
|
|
29213
|
+
}
|
|
29214
|
+
const first = firstBirth;
|
|
29190
29215
|
return {
|
|
29191
29216
|
kind: "panel",
|
|
29192
29217
|
panel: {
|
|
@@ -29249,9 +29274,10 @@ function birthMember(context, input) {
|
|
|
29249
29274
|
let resolvedRoute = input.resolvedRoute;
|
|
29250
29275
|
if (!resolvedRoute && input.producerId && input.producerId !== "driver-simulated") {
|
|
29251
29276
|
const routeResult = resolveProducerRoute(context.projectRoot, input.step, agentId);
|
|
29252
|
-
if (
|
|
29253
|
-
|
|
29277
|
+
if ("error" in routeResult) {
|
|
29278
|
+
return { handoff: { ...routeResult.error, stepId: input.stepId } };
|
|
29254
29279
|
}
|
|
29280
|
+
resolvedRoute = routeResult;
|
|
29255
29281
|
}
|
|
29256
29282
|
const dispatchContext = assembleDispatchContext(input.dispatchSources, {
|
|
29257
29283
|
projectId: run.projectId,
|
|
@@ -29358,11 +29384,11 @@ function birthMember(context, input) {
|
|
|
29358
29384
|
prompt: input.step.instructions ? `${input.step.instructions}
|
|
29359
29385
|
|
|
29360
29386
|
${generatedPrompt}` : generatedPrompt,
|
|
29361
|
-
thinking: input.stepAttempt <= 1 ? "low" : "medium",
|
|
29362
29387
|
permission: Object.values(input.step.repositories).some((access) => access === "write") ? "edit" : "read-only",
|
|
29363
29388
|
...(input.step.kind === "agent" || input.step.kind === "moa") && input.step.timeoutMs !== void 0 ? { timeoutMs: input.step.timeoutMs } : {},
|
|
29364
29389
|
contextPacket,
|
|
29365
|
-
...resolvedRoute ? {
|
|
29390
|
+
...resolvedRoute?.effort !== void 0 ? { thinking: resolvedRoute.effort } : {},
|
|
29391
|
+
...resolvedRoute ? { harness: resolvedRoute.harness, provider: resolvedRoute.provider, model: resolvedRoute.model } : {}
|
|
29366
29392
|
},
|
|
29367
29393
|
controller,
|
|
29368
29394
|
state: next
|
|
@@ -29507,13 +29533,14 @@ async function drivePanel(context, panel, producer) {
|
|
|
29507
29533
|
})();
|
|
29508
29534
|
pending.set(member.attemptId, work);
|
|
29509
29535
|
};
|
|
29536
|
+
let routeHandoff;
|
|
29510
29537
|
const tryBirth = () => {
|
|
29511
|
-
if (stopBirths) return void 0;
|
|
29538
|
+
if (stopBirths || routeHandoff) return void 0;
|
|
29512
29539
|
return context.eventStore.transaction(() => {
|
|
29513
29540
|
const run = requireRun(context, runId);
|
|
29514
29541
|
const state = foldStoredKxmRun(context, run);
|
|
29515
29542
|
if (!birthAllowed(state, panel.step)) return void 0;
|
|
29516
|
-
|
|
29543
|
+
const born = birthMember(context, {
|
|
29517
29544
|
run,
|
|
29518
29545
|
plan: panel.plan,
|
|
29519
29546
|
step: panel.step,
|
|
@@ -29522,6 +29549,11 @@ async function drivePanel(context, panel, producer) {
|
|
|
29522
29549
|
producerId: producer.id,
|
|
29523
29550
|
dispatchSources: panel.dispatchSources
|
|
29524
29551
|
});
|
|
29552
|
+
if ("handoff" in born) {
|
|
29553
|
+
routeHandoff = born.handoff;
|
|
29554
|
+
return void 0;
|
|
29555
|
+
}
|
|
29556
|
+
return born;
|
|
29525
29557
|
});
|
|
29526
29558
|
};
|
|
29527
29559
|
const settleInvoked = (member, produced) => {
|
|
@@ -29565,6 +29597,10 @@ async function drivePanel(context, panel, producer) {
|
|
|
29565
29597
|
while (!stopBirths && !settlementFailed) {
|
|
29566
29598
|
try {
|
|
29567
29599
|
const next = tryBirth();
|
|
29600
|
+
if (routeHandoff) {
|
|
29601
|
+
stopBirths = true;
|
|
29602
|
+
break;
|
|
29603
|
+
}
|
|
29568
29604
|
if (!next) break;
|
|
29569
29605
|
launch(next);
|
|
29570
29606
|
} catch {
|
|
@@ -29575,6 +29611,13 @@ async function drivePanel(context, panel, producer) {
|
|
|
29575
29611
|
return unreconciledHandoff(state, panel.stepId);
|
|
29576
29612
|
}
|
|
29577
29613
|
}
|
|
29614
|
+
if (routeHandoff) {
|
|
29615
|
+
const handoff = routeHandoff;
|
|
29616
|
+
abortOwned();
|
|
29617
|
+
await drainPendingInvoked();
|
|
29618
|
+
const state = foldStoredKxmRun(context, requireRun(context, runId));
|
|
29619
|
+
return { state, handoff };
|
|
29620
|
+
}
|
|
29578
29621
|
if (pending.size === 0) break;
|
|
29579
29622
|
const finished = await Promise.race(pending.values());
|
|
29580
29623
|
pending.delete(finished.attemptId);
|
|
@@ -30138,25 +30181,7 @@ function unsupportedStep(plan, step, producerId) {
|
|
|
30138
30181
|
}
|
|
30139
30182
|
return void 0;
|
|
30140
30183
|
}
|
|
30141
|
-
function
|
|
30142
|
-
if (!existsSync12(path)) return void 0;
|
|
30143
|
-
try {
|
|
30144
|
-
const parsed = (0, import_yaml9.parse)(readFileSync10(path, "utf8"));
|
|
30145
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
|
|
30146
|
-
} catch {
|
|
30147
|
-
return void 0;
|
|
30148
|
-
}
|
|
30149
|
-
return void 0;
|
|
30150
|
-
}
|
|
30151
|
-
function agentHarness(projectRoot, agentId) {
|
|
30152
|
-
const harness = readYamlRecord(join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`))?.harness;
|
|
30153
|
-
return typeof harness === "string" && harness.length > 0 ? harness : void 0;
|
|
30154
|
-
}
|
|
30155
|
-
function projectDefaultHarness(projectRoot) {
|
|
30156
|
-
const harness = readYamlRecord(join15(projectRoot, ".kxm", "project.yaml"))?.defaultHarness;
|
|
30157
|
-
return typeof harness === "string" && harness.length > 0 ? harness : "pi";
|
|
30158
|
-
}
|
|
30159
|
-
function unsupportedLiveWrite(projectRoot, step, agentId, selector, maxConcurrentRuns) {
|
|
30184
|
+
function unsupportedLiveWrite(projectRoot, step, route, maxConcurrentRuns) {
|
|
30160
30185
|
if (!Object.values(step.repositories).some((access) => access === "write")) return void 0;
|
|
30161
30186
|
if (step.assignments.maximum !== 1) {
|
|
30162
30187
|
return {
|
|
@@ -30172,42 +30197,23 @@ function unsupportedLiveWrite(projectRoot, step, agentId, selector, maxConcurren
|
|
|
30172
30197
|
detail: "live write steps require limits.maxConcurrentRuns of 1; concurrent runs share one checkout"
|
|
30173
30198
|
};
|
|
30174
30199
|
}
|
|
30175
|
-
|
|
30176
|
-
if (!oneShotWriterArgs(harness)) {
|
|
30200
|
+
if (!oneShotWriterArgs(route.harness)) {
|
|
30177
30201
|
return {
|
|
30178
30202
|
reason: "step_unsupported",
|
|
30179
30203
|
field: "repositories",
|
|
30180
|
-
detail: `live write steps require an audited writer profile; ${harness} has none`
|
|
30181
|
-
};
|
|
30182
|
-
}
|
|
30183
|
-
const
|
|
30184
|
-
if (!
|
|
30185
|
-
|
|
30186
|
-
|
|
30187
|
-
|
|
30188
|
-
|
|
30189
|
-
const routes = roster.routes;
|
|
30190
|
-
const lineup = roster.lineup;
|
|
30191
|
-
const writerIds = lineup && typeof lineup === "object" && !Array.isArray(lineup) ? lineup.writer : void 0;
|
|
30192
|
-
if (!routes || typeof routes !== "object" || Array.isArray(routes) || !Array.isArray(writerIds)) {
|
|
30193
|
-
return { reason: "step_unsupported", field: "model", detail: "developer roster has no writer lineup" };
|
|
30194
|
-
}
|
|
30195
|
-
const allowed = writerIds.some((id) => {
|
|
30196
|
-
if (typeof id !== "string") return false;
|
|
30197
|
-
const route = routes[id];
|
|
30198
|
-
if (!route || typeof route !== "object" || Array.isArray(route)) return false;
|
|
30199
|
-
const record2 = route;
|
|
30200
|
-
if (record2.harness !== harness || record2.status !== "admitted") return false;
|
|
30201
|
-
if (!Array.isArray(record2.permissions) || !record2.permissions.includes("edit")) return false;
|
|
30202
|
-
const model = typeof record2.model === "string" ? record2.model : "";
|
|
30203
|
-
const vendor = typeof record2.vendor === "string" ? record2.vendor : "";
|
|
30204
|
-
return model === selector || vendor.length > 0 && `${vendor}/${model}` === selector;
|
|
30205
|
-
});
|
|
30206
|
-
if (!allowed) {
|
|
30204
|
+
detail: `live write steps require an audited writer profile; ${route.harness} has none`
|
|
30205
|
+
};
|
|
30206
|
+
}
|
|
30207
|
+
const writerIds = listRoleBindings(projectRoot).writer;
|
|
30208
|
+
if (!Array.isArray(writerIds) || writerIds.length === 0) {
|
|
30209
|
+
return { reason: "step_unsupported", field: "model", detail: "writer roster has no admitted edit route" };
|
|
30210
|
+
}
|
|
30211
|
+
const named = writerIds.includes(route.routeId);
|
|
30212
|
+
if (!named || !route.permissions.includes("edit")) {
|
|
30207
30213
|
return {
|
|
30208
30214
|
reason: "step_unsupported",
|
|
30209
30215
|
field: "model",
|
|
30210
|
-
detail: `live write route ${selector} on ${harness} is not on the
|
|
30216
|
+
detail: `live write route ${route.selector} on ${route.harness} is not an admitted edit route on the writer roster`
|
|
30211
30217
|
};
|
|
30212
30218
|
}
|
|
30213
30219
|
return void 0;
|
|
@@ -30644,20 +30650,11 @@ function determineOutcome(text, allowedOutcomes) {
|
|
|
30644
30650
|
return "failed";
|
|
30645
30651
|
}
|
|
30646
30652
|
function createKxmOneShotProducer(options = {}) {
|
|
30647
|
-
const defaultHarness = options.defaultHarness ?? "claude";
|
|
30648
30653
|
const running = /* @__PURE__ */ new Map();
|
|
30649
30654
|
let closed = false;
|
|
30650
|
-
function
|
|
30655
|
+
function requireHarness(request) {
|
|
30651
30656
|
if (request.harness) return request.harness;
|
|
30652
|
-
|
|
30653
|
-
const resolved = options.resolveHarness(request.agentId, request.runId);
|
|
30654
|
-
if (resolved) return resolved;
|
|
30655
|
-
}
|
|
30656
|
-
if (options.resolveModel) {
|
|
30657
|
-
const resolved = options.resolveModel(request.agentId, request.runId);
|
|
30658
|
-
if (resolved?.harness) return resolved.harness;
|
|
30659
|
-
}
|
|
30660
|
-
return defaultHarness;
|
|
30657
|
+
throw new Error("producer_harness_required");
|
|
30661
30658
|
}
|
|
30662
30659
|
function parseModelString(spec, harness) {
|
|
30663
30660
|
const trimmed = spec.trim();
|
|
@@ -30719,7 +30716,7 @@ function createKxmOneShotProducer(options = {}) {
|
|
|
30719
30716
|
}
|
|
30720
30717
|
async function executeRequest(request) {
|
|
30721
30718
|
const startTime = Date.now();
|
|
30722
|
-
const harness =
|
|
30719
|
+
const harness = requireHarness(request);
|
|
30723
30720
|
const resolved = resolveModelForRequest(request, harness);
|
|
30724
30721
|
if (closed) throw new Error("oneshot_producer_closed");
|
|
30725
30722
|
const cancelled = () => ({
|
|
@@ -31969,24 +31966,7 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, e
|
|
|
31969
31966
|
const delayMs = typeof body.delayMs === "number" && body.delayMs > 0 ? body.delayMs : 0;
|
|
31970
31967
|
const createProducer = () => body.mode === "live" ? createKxmOneShotProducer({
|
|
31971
31968
|
projectRoot,
|
|
31972
|
-
timeoutMs: kxmProjectAdmissionLimits(bundle).agentStepTimeoutMs
|
|
31973
|
-
defaultHarness: String(bundle.project.value.defaultHarness ?? "pi"),
|
|
31974
|
-
resolveHarness: (agentId) => {
|
|
31975
|
-
const agent = bundle.agents.get(agentId);
|
|
31976
|
-
return typeof agent?.value.harness === "string" ? agent.value.harness : void 0;
|
|
31977
|
-
},
|
|
31978
|
-
resolveModel: (agentId) => {
|
|
31979
|
-
const agent = bundle.agents.get(agentId);
|
|
31980
|
-
const model = agent?.value.model;
|
|
31981
|
-
if (!model || typeof model !== "object" || Array.isArray(model)) return void 0;
|
|
31982
|
-
const value = model;
|
|
31983
|
-
const provider = typeof value.provider === "string" ? value.provider : void 0;
|
|
31984
|
-
const modelName = typeof value.model === "string" ? value.model : void 0;
|
|
31985
|
-
if (!provider || !modelName || !isRouteAdmitted(projectRoot, `${provider}/${modelName}`)) {
|
|
31986
|
-
throw new Error("producer_route_not_admitted");
|
|
31987
|
-
}
|
|
31988
|
-
return { provider, model: modelName };
|
|
31989
|
-
}
|
|
31969
|
+
timeoutMs: kxmProjectAdmissionLimits(bundle).agentStepTimeoutMs
|
|
31990
31970
|
}) : createKxmSimulatedProducer(async () => {
|
|
31991
31971
|
if (delayMs > 0) {
|
|
31992
31972
|
await new Promise((r) => setTimeout(r, delayMs));
|