@kontextmind/kxm 0.7.123 → 0.7.125
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/workflows/implement-only.yaml +20 -0
- package/.kxm/workflows/review-arch-only.yaml +20 -0
- package/.kxm/workflows/review-cli-only.yaml +20 -0
- package/CHANGELOG.md +33 -3
- package/docs/contributing/assignment-runner.md +15 -4
- package/docs/reference/cli-reference.md +10 -6
- package/docs/reference/config-reference.md +2 -1
- package/docs/reference/workflow-catalog.md +10 -0
- package/docs/reference/workflow-definitions.md +1 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +83 -13
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime-supervisor.js +209 -72
- package/plugins/kxm/dist/runtime.js +233 -94
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/land.ts +2 -0
- package/plugins/kxm/src/cli/project.ts +14 -2
- package/plugins/kxm/src/cli.ts +62 -8
- package/plugins/kxm/src/engine-fold.ts +15 -7
- package/plugins/kxm/src/engine-plan.ts +10 -1
- package/plugins/kxm/src/engine.ts +105 -2
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/oneshot-evidence.ts +44 -0
- package/plugins/kxm/src/oneshot-producer.ts +5 -5
- package/plugins/kxm/src/runtime-service.ts +10 -0
- package/plugins/kxm/src/runtime-store.ts +1 -0
- package/plugins/kxm/src/runtime-supervisor.ts +2 -0
- package/schemas/drive-receipt.schema.json +1 -0
- package/schemas/project.schema.json +2 -1
- package/scripts/pr-land.mjs +68 -19
|
@@ -14781,9 +14781,9 @@ var require_dist = __commonJS({
|
|
|
14781
14781
|
// plugins/kxm/src/runtime-supervisor.ts
|
|
14782
14782
|
import { spawn as spawn3 } from "node:child_process";
|
|
14783
14783
|
import { createHash as createHash14, createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
14784
|
-
import { chmodSync as chmodSync2, existsSync as existsSync16, lstatSync as
|
|
14784
|
+
import { chmodSync as chmodSync2, existsSync as existsSync16, lstatSync as lstatSync6, mkdirSync as mkdirSync9, readFileSync as readFileSync13, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync9 } from "node:fs";
|
|
14785
14785
|
import { createServer } from "node:http";
|
|
14786
|
-
import { dirname as dirname11, isAbsolute as isAbsolute7, join as
|
|
14786
|
+
import { dirname as dirname11, isAbsolute as isAbsolute7, join as join18 } from "node:path";
|
|
14787
14787
|
|
|
14788
14788
|
// plugins/kxm/src/repo-root.ts
|
|
14789
14789
|
import { existsSync } from "node:fs";
|
|
@@ -17037,8 +17037,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
17037
17037
|
const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
|
|
17038
17038
|
if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
|
|
17039
17039
|
}
|
|
17040
|
-
const
|
|
17041
|
-
const minimumPassed =
|
|
17040
|
+
const join19 = objectValue(step.join);
|
|
17041
|
+
const minimumPassed = join19 && typeof join19.minimumPassed === "number" ? join19.minimumPassed : void 0;
|
|
17042
17042
|
if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
|
|
17043
17043
|
const distinctBy = names(assignment?.distinctBy);
|
|
17044
17044
|
if (distinctBy.length > 0) {
|
|
@@ -20015,9 +20015,12 @@ function authorizedCancelStep(state, step, current, status) {
|
|
|
20015
20015
|
}
|
|
20016
20016
|
const currentAttempt = currentAttemptOf(assignment);
|
|
20017
20017
|
if (!currentAttempt?.resultClass) return false;
|
|
20018
|
-
members.push({ resultClass: currentAttempt.resultClass, outcome: currentAttempt.outcome });
|
|
20018
|
+
members.push({ resultClass: currentAttempt.resultClass, outcome: currentAttempt.outcome, producerError: currentAttempt.producerError });
|
|
20019
20019
|
}
|
|
20020
20020
|
if (members.some((member) => member.resultClass === "outcome_unknown" || member.resultClass === "producer_rejected")) {
|
|
20021
|
+
if (members.every((member) => member.resultClass === "producer_rejected" && member.producerError === "executing_unrecorded")) {
|
|
20022
|
+
return true;
|
|
20023
|
+
}
|
|
20021
20024
|
return false;
|
|
20022
20025
|
}
|
|
20023
20026
|
const declared = members.filter((member) => member.resultClass === "outcome");
|
|
@@ -20371,8 +20374,8 @@ function isProvenFailure(state, plan) {
|
|
|
20371
20374
|
return Boolean(step && used >= step.maxAttempts);
|
|
20372
20375
|
}
|
|
20373
20376
|
function foldDriveOpened(state, event) {
|
|
20374
|
-
if (state.status !== "running" && state.status !== "blocked_uncertain") {
|
|
20375
|
-
throw runtimeError("run_events_illegal", state.runId, "run.drive_opened is only legal while running or
|
|
20377
|
+
if (state.status !== "running" && state.status !== "blocked_uncertain" && state.status !== "cancelling") {
|
|
20378
|
+
throw runtimeError("run_events_illegal", state.runId, "run.drive_opened is only legal while running, blocked_uncertain, or cancelling");
|
|
20376
20379
|
}
|
|
20377
20380
|
const driveId = stringPayload(event, "driveId");
|
|
20378
20381
|
const mode = stringPayload(event, "mode");
|
|
@@ -20706,9 +20709,13 @@ function foldAssignmentAdvance(state, plan, event, next) {
|
|
|
20706
20709
|
}
|
|
20707
20710
|
}
|
|
20708
20711
|
if (attemptId && attempt) {
|
|
20712
|
+
const producerError = typeof event.payload.producerError === "string" ? event.payload.producerError : void 0;
|
|
20709
20713
|
nextAssignment = {
|
|
20710
20714
|
...nextAssignment,
|
|
20711
|
-
attempts: {
|
|
20715
|
+
attempts: {
|
|
20716
|
+
...nextAssignment.attempts,
|
|
20717
|
+
[attemptId]: { ...attempt, resultClass, ...producerError !== void 0 ? { producerError } : {} }
|
|
20718
|
+
}
|
|
20712
20719
|
};
|
|
20713
20720
|
}
|
|
20714
20721
|
}
|
|
@@ -21223,7 +21230,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
21223
21230
|
const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
|
|
21224
21231
|
const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
|
|
21225
21232
|
const assignments = compileAssignments(step, id, agent, sink);
|
|
21226
|
-
const
|
|
21233
|
+
const join19 = compileJoin(step, id, sink);
|
|
21227
21234
|
const requiredEvidence = compileEvidence(step, id, sink);
|
|
21228
21235
|
const transitions = compileTransitions(step, id, index, stepIndex, sink);
|
|
21229
21236
|
const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
|
|
@@ -21251,7 +21258,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
21251
21258
|
transitions: orderedTransitions,
|
|
21252
21259
|
requiresPlanHash: requirePlanHash.includes(id),
|
|
21253
21260
|
assignments,
|
|
21254
|
-
join:
|
|
21261
|
+
join: join19
|
|
21255
21262
|
};
|
|
21256
21263
|
if (kind === "agent" || kind === "moa") {
|
|
21257
21264
|
if (!agent) return void 0;
|
|
@@ -21301,15 +21308,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
|
|
|
21301
21308
|
};
|
|
21302
21309
|
}
|
|
21303
21310
|
function compileJoin(step, stepId, sink) {
|
|
21304
|
-
const
|
|
21305
|
-
if (!
|
|
21306
|
-
const declared = stringValue2(
|
|
21311
|
+
const join19 = objectValue2(step.join);
|
|
21312
|
+
if (!join19) return { strategy: "all" };
|
|
21313
|
+
const declared = stringValue2(join19.strategy);
|
|
21307
21314
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
21308
|
-
const minimumPassed = compileOptionalCount(
|
|
21315
|
+
const minimumPassed = compileOptionalCount(join19.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
21309
21316
|
const compiled = {
|
|
21310
21317
|
strategy,
|
|
21311
21318
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
21312
|
-
...typeof
|
|
21319
|
+
...typeof join19.cancelRemaining === "boolean" ? { cancelRemaining: join19.cancelRemaining } : {}
|
|
21313
21320
|
};
|
|
21314
21321
|
return compiled;
|
|
21315
21322
|
}
|
|
@@ -21593,7 +21600,7 @@ var CONTROL_ROOT_REQUIRED = ["repositoryId", "projectKey"];
|
|
|
21593
21600
|
var GATE_REGISTRY_SCHEMA = "kxm.gate-registry.v1";
|
|
21594
21601
|
var REVISION_REQUIRED = ["config", "executorPolicy", "toolPolicy", "memory"];
|
|
21595
21602
|
var PROJECT_LIMIT_REQUIRED = ["maxConcurrentRuns"];
|
|
21596
|
-
var PROJECT_LIMIT_OPTIONAL = ["maxRunDurationMs", "maxAgentTimeMs"];
|
|
21603
|
+
var PROJECT_LIMIT_OPTIONAL = ["maxRunDurationMs", "maxAgentTimeMs", "agentStepTimeoutMs"];
|
|
21597
21604
|
var PLAN_REQUIRED = ["schema", "workflowId", "coordinator", "limits", "transitionBudget", "hasBackEdges", "entryStepId", "order", "steps", "requirePlanHash"];
|
|
21598
21605
|
var PLAN_OPTIONAL = ["sourcePath", "reproOracle", "planHash"];
|
|
21599
21606
|
var LIMIT_OPTIONAL = ["maxTransitions", "maxRunDurationMs", "maxAgentTimeMs", "maxModelCost", "currency"];
|
|
@@ -21745,7 +21752,8 @@ function parseEnvelope(parsed, run) {
|
|
|
21745
21752
|
const projectLimits = {
|
|
21746
21753
|
maxConcurrentRuns: asCount(limitsValue.maxConcurrentRuns, run.runId, "projectLimits.maxConcurrentRuns"),
|
|
21747
21754
|
...limitsValue.maxRunDurationMs !== void 0 ? { maxRunDurationMs: asDuration(limitsValue.maxRunDurationMs, run.runId, "projectLimits.maxRunDurationMs") } : {},
|
|
21748
|
-
...limitsValue.maxAgentTimeMs !== void 0 ? { maxAgentTimeMs: asDuration(limitsValue.maxAgentTimeMs, run.runId, "projectLimits.maxAgentTimeMs") } : {}
|
|
21755
|
+
...limitsValue.maxAgentTimeMs !== void 0 ? { maxAgentTimeMs: asDuration(limitsValue.maxAgentTimeMs, run.runId, "projectLimits.maxAgentTimeMs") } : {},
|
|
21756
|
+
...limitsValue.agentStepTimeoutMs !== void 0 ? { agentStepTimeoutMs: asAgentStepTimeout(limitsValue.agentStepTimeoutMs, run.runId, "projectLimits.agentStepTimeoutMs") } : {}
|
|
21749
21757
|
};
|
|
21750
21758
|
const plan = freezeKxmCompiledPlan(parseCompiledPlan(value.plan, run.runId));
|
|
21751
21759
|
return {
|
|
@@ -22148,6 +22156,12 @@ function asDuration(value, runId, label) {
|
|
|
22148
22156
|
}
|
|
22149
22157
|
return value;
|
|
22150
22158
|
}
|
|
22159
|
+
function asAgentStepTimeout(value, runId, label) {
|
|
22160
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 6e4) {
|
|
22161
|
+
throw runtimeError("run_plan_corrupt", runId, `${label} is below 60000`);
|
|
22162
|
+
}
|
|
22163
|
+
return value;
|
|
22164
|
+
}
|
|
22151
22165
|
function asCost(value, runId, label) {
|
|
22152
22166
|
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
22153
22167
|
throw runtimeError("run_plan_corrupt", runId, `${label} is not a positive cost`);
|
|
@@ -22780,13 +22794,18 @@ function kxmDeclaredExecutorIds(bundle) {
|
|
|
22780
22794
|
...[...bundle.agents.values()].map((agent) => agent.value.executor).filter((value) => typeof value === "string")
|
|
22781
22795
|
].filter((value) => value !== void 0))].sort();
|
|
22782
22796
|
}
|
|
22797
|
+
var KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS = 36e5;
|
|
22798
|
+
var KXM_MIN_AGENT_STEP_TIMEOUT_MS = 6e4;
|
|
22783
22799
|
function kxmProjectAdmissionLimits(bundle) {
|
|
22784
22800
|
const limits = objectValue3(bundle.project.value.limits);
|
|
22785
22801
|
const maxConcurrentRuns = typeof limits?.maxConcurrentRuns === "number" && Number.isInteger(limits.maxConcurrentRuns) && limits.maxConcurrentRuns >= 1 ? limits.maxConcurrentRuns : 1;
|
|
22802
|
+
const declared = limits?.agentStepTimeoutMs;
|
|
22803
|
+
const agentStepTimeoutMs = typeof declared === "number" && Number.isInteger(declared) && declared >= KXM_MIN_AGENT_STEP_TIMEOUT_MS ? declared : KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS;
|
|
22786
22804
|
return {
|
|
22787
22805
|
maxConcurrentRuns,
|
|
22788
22806
|
...typeof limits?.maxRunDurationMs === "number" ? { maxRunDurationMs: limits.maxRunDurationMs } : {},
|
|
22789
|
-
...typeof limits?.maxAgentTimeMs === "number" ? { maxAgentTimeMs: limits.maxAgentTimeMs } : {}
|
|
22807
|
+
...typeof limits?.maxAgentTimeMs === "number" ? { maxAgentTimeMs: limits.maxAgentTimeMs } : {},
|
|
22808
|
+
agentStepTimeoutMs
|
|
22790
22809
|
};
|
|
22791
22810
|
}
|
|
22792
22811
|
var closedRuntimeContexts = /* @__PURE__ */ new WeakSet();
|
|
@@ -23130,11 +23149,9 @@ function cancelKxmRun(context, runId, options = {}) {
|
|
|
23130
23149
|
return result;
|
|
23131
23150
|
}
|
|
23132
23151
|
|
|
23133
|
-
// plugins/kxm/src/oneshot-producer.ts
|
|
23134
|
-
import { join as join16 } from "node:path";
|
|
23135
|
-
|
|
23136
23152
|
// plugins/kxm/src/oneshot-evidence.ts
|
|
23137
23153
|
import { createHash as createHash8, randomUUID as randomUUID3 } from "node:crypto";
|
|
23154
|
+
import { lstatSync as lstatSync4, readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
23138
23155
|
import { lstat, mkdir, open, rename } from "node:fs/promises";
|
|
23139
23156
|
import { join as join8 } from "node:path";
|
|
23140
23157
|
var ONESHOT_EVIDENCE_SCHEMA = "kxm.oneshot-evidence.v2";
|
|
@@ -23159,6 +23176,37 @@ function parseOneShotEvidenceRecord(bytes) {
|
|
|
23159
23176
|
if (schema !== ONESHOT_EVIDENCE_SCHEMA) throw new Error("oneshot_evidence_schema_unknown");
|
|
23160
23177
|
return parsed;
|
|
23161
23178
|
}
|
|
23179
|
+
function oneShotEvidenceRoot() {
|
|
23180
|
+
return join8(kxmUserStateRoot(), "runtime", "oneshot-evidence");
|
|
23181
|
+
}
|
|
23182
|
+
function readOneShotObservedChildExit(runId, attemptId, root = oneShotEvidenceRoot()) {
|
|
23183
|
+
let names3;
|
|
23184
|
+
try {
|
|
23185
|
+
names3 = readdirSync4(root);
|
|
23186
|
+
} catch {
|
|
23187
|
+
return void 0;
|
|
23188
|
+
}
|
|
23189
|
+
let seenTrue = false;
|
|
23190
|
+
let seenFalse = false;
|
|
23191
|
+
const capped = names3.slice(0, 4096);
|
|
23192
|
+
for (const name of capped) {
|
|
23193
|
+
if (!name.startsWith("evd_")) continue;
|
|
23194
|
+
const dir = join8(root, name);
|
|
23195
|
+
try {
|
|
23196
|
+
const info = lstatSync4(dir);
|
|
23197
|
+
if (!info.isDirectory() || info.isSymbolicLink()) continue;
|
|
23198
|
+
const intent = parseOneShotEvidenceRecord(readFileSync5(join8(dir, "intent.json"), "utf8"));
|
|
23199
|
+
if (intent.runId !== runId || intent.attemptId !== attemptId) continue;
|
|
23200
|
+
const result = parseOneShotEvidenceRecord(readFileSync5(join8(dir, "result.json"), "utf8"));
|
|
23201
|
+
if (result.observedChildExit === true) seenTrue = true;
|
|
23202
|
+
else if (result.observedChildExit === false) seenFalse = true;
|
|
23203
|
+
} catch {
|
|
23204
|
+
}
|
|
23205
|
+
}
|
|
23206
|
+
if (seenFalse) return false;
|
|
23207
|
+
if (seenTrue) return true;
|
|
23208
|
+
return void 0;
|
|
23209
|
+
}
|
|
23162
23210
|
async function beginOneShotEvidence(root, intent, sensitive) {
|
|
23163
23211
|
await mkdir(root, { recursive: true, mode: 448 });
|
|
23164
23212
|
const stat = await lstat(root);
|
|
@@ -23217,6 +23265,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
23217
23265
|
harness: intent.harness,
|
|
23218
23266
|
provider: intent.provider,
|
|
23219
23267
|
requestedModel: intent.model,
|
|
23268
|
+
...intent.timeoutMs !== void 0 ? { timeoutMs: intent.timeoutMs } : {},
|
|
23220
23269
|
cwd: intent.cwd,
|
|
23221
23270
|
command: redact(intent.command),
|
|
23222
23271
|
argv: bounded(JSON.stringify(intent.args), ARGV_LIMIT),
|
|
@@ -23253,7 +23302,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
23253
23302
|
// plugins/kxm/src/prices.ts
|
|
23254
23303
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
23255
23304
|
import { createHash as createHash9 } from "node:crypto";
|
|
23256
|
-
import { existsSync as existsSync8, readFileSync as
|
|
23305
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
23257
23306
|
import { join as join9 } from "node:path";
|
|
23258
23307
|
|
|
23259
23308
|
// plugins/kxm/src/price-calc.ts
|
|
@@ -23410,19 +23459,19 @@ function loadPriceCatalog(rootOrPath) {
|
|
|
23410
23459
|
if (!candidatePath || !existsSync8(candidatePath)) {
|
|
23411
23460
|
return void 0;
|
|
23412
23461
|
}
|
|
23413
|
-
const content =
|
|
23462
|
+
const content = readFileSync6(candidatePath, "utf8");
|
|
23414
23463
|
return parsePriceCatalog(content);
|
|
23415
23464
|
}
|
|
23416
23465
|
|
|
23417
23466
|
// plugins/kxm/src/engine.ts
|
|
23418
23467
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
23419
23468
|
import { createHash as createHash13, randomBytes, timingSafeEqual } from "node:crypto";
|
|
23420
|
-
import { existsSync as existsSync12, readFileSync as
|
|
23469
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
|
|
23421
23470
|
import { join as join15 } from "node:path";
|
|
23422
23471
|
|
|
23423
23472
|
// plugins/kxm/src/routes.ts
|
|
23424
23473
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
23425
|
-
import { existsSync as existsSync9, readFileSync as
|
|
23474
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync5 } from "node:fs";
|
|
23426
23475
|
import { join as join10 } from "node:path";
|
|
23427
23476
|
var RETIRED_POLICY = ".kxm/producers.yaml";
|
|
23428
23477
|
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [], roles: {} });
|
|
@@ -23430,7 +23479,7 @@ function loadRoutePolicy(root) {
|
|
|
23430
23479
|
if (existsSync9(join10(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
|
|
23431
23480
|
const path = join10(root, ".kxm", "routes.yaml");
|
|
23432
23481
|
if (!existsSync9(path)) return empty();
|
|
23433
|
-
const value = (0, import_yaml4.parse)(
|
|
23482
|
+
const value = (0, import_yaml4.parse)(readFileSync7(path, "utf8"));
|
|
23434
23483
|
if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
|
|
23435
23484
|
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")])) : {} };
|
|
23436
23485
|
}
|
|
@@ -23438,9 +23487,9 @@ function listRoleBindings(root) {
|
|
|
23438
23487
|
const dir = join10(root, ".kxm", "roles");
|
|
23439
23488
|
const result = {};
|
|
23440
23489
|
if (!existsSync9(dir)) return result;
|
|
23441
|
-
for (const file of
|
|
23490
|
+
for (const file of readdirSync5(dir).filter((name) => name.endsWith(".yaml"))) {
|
|
23442
23491
|
const role = file.slice(0, -5);
|
|
23443
|
-
const value = (0, import_yaml4.parse)(
|
|
23492
|
+
const value = (0, import_yaml4.parse)(readFileSync7(join10(dir, file), "utf8"));
|
|
23444
23493
|
result[role] = (value.roster ?? []).map((entry) => entry.model).filter((model) => typeof model === "string");
|
|
23445
23494
|
}
|
|
23446
23495
|
return result;
|
|
@@ -23767,7 +23816,7 @@ function pruneContextPacket(packet, tokenBudget) {
|
|
|
23767
23816
|
|
|
23768
23817
|
// plugins/kxm/src/dispatch-context.ts
|
|
23769
23818
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
23770
|
-
import { readdirSync as
|
|
23819
|
+
import { readdirSync as readdirSync8 } from "node:fs";
|
|
23771
23820
|
import { extname as extname3, join as join13 } from "node:path";
|
|
23772
23821
|
|
|
23773
23822
|
// plugins/kxm/src/protocol.ts
|
|
@@ -24397,7 +24446,7 @@ function memoryRecordToContextItem(record2, project) {
|
|
|
24397
24446
|
|
|
24398
24447
|
// plugins/kxm/src/memory.ts
|
|
24399
24448
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
24400
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as
|
|
24449
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
|
|
24401
24450
|
import { extname as extname2, join as join11, resolve as resolve7 } from "node:path";
|
|
24402
24451
|
var MEMORY_SCHEMA = "kxm.memory.v1";
|
|
24403
24452
|
var VALID_SCOPES = /* @__PURE__ */ new Set(["agent", "project", "run", "operator"]);
|
|
@@ -24505,12 +24554,12 @@ function loadAuthoredMemory(repoRoot) {
|
|
|
24505
24554
|
const { memoryDir } = memoryDirectories(repoRoot);
|
|
24506
24555
|
if (!existsSync10(memoryDir)) return [];
|
|
24507
24556
|
const records = [];
|
|
24508
|
-
const entries =
|
|
24557
|
+
const entries = readdirSync6(memoryDir, { withFileTypes: true });
|
|
24509
24558
|
for (const entry of entries) {
|
|
24510
24559
|
if (entry.isFile() && extname2(entry.name) === ".md") {
|
|
24511
24560
|
const fullPath = join11(memoryDir, entry.name);
|
|
24512
24561
|
try {
|
|
24513
|
-
const text =
|
|
24562
|
+
const text = readFileSync8(fullPath, "utf8");
|
|
24514
24563
|
const record2 = parseMemoryRecord(text, entry.name);
|
|
24515
24564
|
if (record2.lifecycle === "active") {
|
|
24516
24565
|
records.push(record2);
|
|
@@ -24526,7 +24575,7 @@ function loadAuthoredMemory(repoRoot) {
|
|
|
24526
24575
|
// plugins/kxm/src/skills.ts
|
|
24527
24576
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
24528
24577
|
import { createHash as createHash10 } from "node:crypto";
|
|
24529
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync5, readdirSync as
|
|
24578
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync5, readdirSync as readdirSync7, readFileSync as readFileSync9, renameSync, rmSync, statSync as statSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
24530
24579
|
import { dirname as dirname7, join as join12 } from "node:path";
|
|
24531
24580
|
var SKILL_CANDIDATE_SCHEMA = "kxm.skill-candidate.v1";
|
|
24532
24581
|
var SKILL_EVALUATION_SCHEMA = "kxm.skill-evaluation.v1";
|
|
@@ -24646,7 +24695,7 @@ var SkillLifecycle = class {
|
|
|
24646
24695
|
const line = `${JSON.stringify(record2)}
|
|
24647
24696
|
`;
|
|
24648
24697
|
if (existsSync11(this.historyFile(id))) {
|
|
24649
|
-
const existing =
|
|
24698
|
+
const existing = readFileSync9(this.historyFile(id), "utf8");
|
|
24650
24699
|
const lines = existing.split("\n").filter((entry) => entry.trim());
|
|
24651
24700
|
this.write(this.historyFile(id), [...lines.slice(-499), line.trim()].join("\n") + "\n");
|
|
24652
24701
|
} else {
|
|
@@ -24656,14 +24705,14 @@ var SkillLifecycle = class {
|
|
|
24656
24705
|
history(id) {
|
|
24657
24706
|
const file = this.historyFile(id);
|
|
24658
24707
|
if (!existsSync11(file)) return [];
|
|
24659
|
-
return
|
|
24708
|
+
return readFileSync9(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
|
|
24660
24709
|
}
|
|
24661
24710
|
readMetadata(state, id) {
|
|
24662
24711
|
const { metadata } = this.paths(state, id);
|
|
24663
24712
|
if (!existsSync11(metadata)) {
|
|
24664
24713
|
throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${state}`);
|
|
24665
24714
|
}
|
|
24666
|
-
return JSON.parse(
|
|
24715
|
+
return JSON.parse(readFileSync9(metadata, "utf8"));
|
|
24667
24716
|
}
|
|
24668
24717
|
move(from, to, id) {
|
|
24669
24718
|
const fromDir = join12(this.dir(from), id);
|
|
@@ -24828,8 +24877,8 @@ var SkillLifecycle = class {
|
|
|
24828
24877
|
};
|
|
24829
24878
|
const candidatePaths = this.paths("candidate", candidateId);
|
|
24830
24879
|
const promotedPaths = this.paths("promoted", candidateId);
|
|
24831
|
-
const skillContent =
|
|
24832
|
-
const metadataContent =
|
|
24880
|
+
const skillContent = readFileSync9(candidatePaths.skill, "utf8");
|
|
24881
|
+
const metadataContent = readFileSync9(candidatePaths.metadata, "utf8");
|
|
24833
24882
|
this.write(promotedPaths.skill, skillContent);
|
|
24834
24883
|
this.write(promotedPaths.metadata, metadataContent);
|
|
24835
24884
|
const patchPath = join12(this.root, "patches", `${candidateId}.patch`);
|
|
@@ -24860,7 +24909,7 @@ var SkillLifecycle = class {
|
|
|
24860
24909
|
verify(state, id) {
|
|
24861
24910
|
const metadata = this.readMetadata(state, id);
|
|
24862
24911
|
const { skill } = this.paths(state, id);
|
|
24863
|
-
const content =
|
|
24912
|
+
const content = readFileSync9(skill, "utf8");
|
|
24864
24913
|
if (skillContentSha256(content) !== metadata.contentSha256) {
|
|
24865
24914
|
throw new SkillLifecycleError(
|
|
24866
24915
|
"skill_integrity_violation",
|
|
@@ -24891,7 +24940,7 @@ var SkillLifecycle = class {
|
|
|
24891
24940
|
read(state, id) {
|
|
24892
24941
|
const metadata = this.readMetadata(state, id);
|
|
24893
24942
|
const { skill } = this.paths(state, id);
|
|
24894
|
-
return { metadata, content:
|
|
24943
|
+
return { metadata, content: readFileSync9(skill, "utf8") };
|
|
24895
24944
|
}
|
|
24896
24945
|
};
|
|
24897
24946
|
function boundedList(value, field) {
|
|
@@ -24906,7 +24955,7 @@ function boundedList(value, field) {
|
|
|
24906
24955
|
return [...new Set(refs)];
|
|
24907
24956
|
}
|
|
24908
24957
|
function readdirSorted(dir) {
|
|
24909
|
-
return
|
|
24958
|
+
return readdirSync7(dir).filter((entry) => statSync2(join12(dir, entry)).isDirectory()).sort();
|
|
24910
24959
|
}
|
|
24911
24960
|
|
|
24912
24961
|
// plugins/kxm/src/dispatch-context.ts
|
|
@@ -24951,14 +25000,14 @@ function dispatchContextPresent(projectRoot) {
|
|
|
24951
25000
|
}
|
|
24952
25001
|
function hasTopLevelMarkdown(dir) {
|
|
24953
25002
|
try {
|
|
24954
|
-
return
|
|
25003
|
+
return readdirSync8(dir, { withFileTypes: true }).some((entry) => entry.isFile() && extname3(entry.name) === ".md");
|
|
24955
25004
|
} catch {
|
|
24956
25005
|
return false;
|
|
24957
25006
|
}
|
|
24958
25007
|
}
|
|
24959
25008
|
function hasAnyEntry(dir) {
|
|
24960
25009
|
try {
|
|
24961
|
-
return
|
|
25010
|
+
return readdirSync8(dir).length > 0;
|
|
24962
25011
|
} catch {
|
|
24963
25012
|
return false;
|
|
24964
25013
|
}
|
|
@@ -25109,7 +25158,7 @@ function assembleDispatchContext(sources, input) {
|
|
|
25109
25158
|
import { join as join14 } from "node:path";
|
|
25110
25159
|
|
|
25111
25160
|
// plugins/kxm/src/artifacts-exist.ts
|
|
25112
|
-
import { lstatSync as
|
|
25161
|
+
import { lstatSync as lstatSync5, realpathSync as realpathSync3, statSync as statSync3 } from "node:fs";
|
|
25113
25162
|
import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve8 } from "node:path";
|
|
25114
25163
|
function staysUnder(root, candidate) {
|
|
25115
25164
|
const child = relative4(root, candidate);
|
|
@@ -25137,7 +25186,7 @@ function verifyArtifactExists(rootInput, pathInput) {
|
|
|
25137
25186
|
return { ok: false, error: "artifact_outside_workspace_assets", path: lexicalPath };
|
|
25138
25187
|
}
|
|
25139
25188
|
try {
|
|
25140
|
-
const link =
|
|
25189
|
+
const link = lstatSync5(lexicalPath);
|
|
25141
25190
|
if (link.isSymbolicLink()) {
|
|
25142
25191
|
return { ok: false, error: "artifact_outside_workspace_assets", path: lexicalPath };
|
|
25143
25192
|
}
|
|
@@ -26382,6 +26431,10 @@ async function driveAdmitted(context, runId, producer, token, options = {}) {
|
|
|
26382
26431
|
if (started.handoff || isTerminalRunStatus(started.state.status)) return started;
|
|
26383
26432
|
}
|
|
26384
26433
|
let latest = { state: foldStoredKxmRun(context, requireRun(context, runId)) };
|
|
26434
|
+
if (latest.state.status === "cancelling") {
|
|
26435
|
+
latest = await stepLocked(context, runId, producer, token);
|
|
26436
|
+
if (latest.handoff || isTerminalRunStatus(latest.state.status)) return latest;
|
|
26437
|
+
}
|
|
26385
26438
|
while (latest.state.status === "running") {
|
|
26386
26439
|
const overBudget = cancelRunDurationIfExceeded(context, runId);
|
|
26387
26440
|
if (overBudget) return overBudget;
|
|
@@ -26410,7 +26463,8 @@ function receiptHandoff(handoff) {
|
|
|
26410
26463
|
reason: handoff.reason,
|
|
26411
26464
|
detail: handoff.detail,
|
|
26412
26465
|
...handoff.field !== void 0 ? { field: handoff.field } : {},
|
|
26413
|
-
...handoff.stepId !== void 0 ? { stepId: handoff.stepId } : {}
|
|
26466
|
+
...handoff.stepId !== void 0 ? { stepId: handoff.stepId } : {},
|
|
26467
|
+
...handoff.attemptId !== void 0 ? { attemptId: handoff.attemptId } : {}
|
|
26414
26468
|
};
|
|
26415
26469
|
}
|
|
26416
26470
|
function appendDriveOpened(context, runId, driveId, mode) {
|
|
@@ -26468,6 +26522,9 @@ function recordDriveReceipt(context, session, closeInfo) {
|
|
|
26468
26522
|
producer: { id: closeInfo.producerId, closed: closeInfo.producerClosed }
|
|
26469
26523
|
};
|
|
26470
26524
|
context.eventStore.insertDriveReceipt(receipt);
|
|
26525
|
+
if (closeInfo.kind === "handoff") {
|
|
26526
|
+
releaseKxmRun(context.eventStore.path, session.runId, session.token);
|
|
26527
|
+
}
|
|
26471
26528
|
} catch {
|
|
26472
26529
|
}
|
|
26473
26530
|
}
|
|
@@ -26609,7 +26666,7 @@ var KxmRunScheduler = class _KxmRunScheduler {
|
|
|
26609
26666
|
}
|
|
26610
26667
|
try {
|
|
26611
26668
|
const run = requireRun(this.context, runId);
|
|
26612
|
-
if (isTerminalRunStatus(run.status)
|
|
26669
|
+
if (isTerminalRunStatus(run.status)) {
|
|
26613
26670
|
return Promise.reject(runtimeError("run_busy", runId, `run ${runId} is already ${run.status}`));
|
|
26614
26671
|
}
|
|
26615
26672
|
} catch (error) {
|
|
@@ -27027,7 +27084,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
27027
27084
|
const agentFile = join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`);
|
|
27028
27085
|
if (existsSync12(agentFile)) {
|
|
27029
27086
|
try {
|
|
27030
|
-
const parsed = (0, import_yaml7.parse)(
|
|
27087
|
+
const parsed = (0, import_yaml7.parse)(readFileSync10(agentFile, "utf8"));
|
|
27031
27088
|
if (typeof parsed?.model === "string") {
|
|
27032
27089
|
agentModel = parsed.model;
|
|
27033
27090
|
} else if (parsed?.model && typeof parsed.model === "object" && !Array.isArray(parsed.model)) {
|
|
@@ -27099,6 +27156,63 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
27099
27156
|
const model = selector.slice(slash + 1);
|
|
27100
27157
|
return { provider, model, selector };
|
|
27101
27158
|
}
|
|
27159
|
+
function projectAgentStepTimeoutMs(context, run) {
|
|
27160
|
+
return loadKxmRunPlanEnvelope(context.eventStore, run).projectLimits.agentStepTimeoutMs ?? KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS;
|
|
27161
|
+
}
|
|
27162
|
+
function unsupportedAgentStepTimeout(step, limitMs) {
|
|
27163
|
+
if (step.kind !== "agent" && step.kind !== "moa") return void 0;
|
|
27164
|
+
if (step.timeoutMs === void 0 || step.timeoutMs <= limitMs) return void 0;
|
|
27165
|
+
return {
|
|
27166
|
+
reason: "step_unsupported",
|
|
27167
|
+
field: "timeoutMs",
|
|
27168
|
+
detail: "step timeoutMs is wider than project limits.agentStepTimeoutMs"
|
|
27169
|
+
};
|
|
27170
|
+
}
|
|
27171
|
+
function executingSingletonAttempt(plan, state) {
|
|
27172
|
+
const current = state.currentStep;
|
|
27173
|
+
if (!current || current.panel.order.length !== 1) return void 0;
|
|
27174
|
+
const step = plan.steps[current.stepId];
|
|
27175
|
+
if (!step || step.kind !== "agent" && step.kind !== "moa" || step.assignments.maximum > 1) return void 0;
|
|
27176
|
+
const attemptId = unreconciledPanelAttemptId(state);
|
|
27177
|
+
if (!attemptId) return void 0;
|
|
27178
|
+
const located = kxmFoldPanelAttempt(current, attemptId);
|
|
27179
|
+
if (located?.attempt.status !== "executing") return void 0;
|
|
27180
|
+
return { stepId: current.stepId, assignmentId: located.assignmentId, attemptId };
|
|
27181
|
+
}
|
|
27182
|
+
function settleExitedExecutingAttempt(context, run, executing) {
|
|
27183
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
27184
|
+
let sequence = context.eventStore.nextSequence(run.runId);
|
|
27185
|
+
let mono = kxmMonotonicNs();
|
|
27186
|
+
const events = [];
|
|
27187
|
+
const push = (eventType, payload) => {
|
|
27188
|
+
events.push({
|
|
27189
|
+
...kxmEventBase(context, run, now, mono),
|
|
27190
|
+
eventId: newKxmEventId(),
|
|
27191
|
+
eventType,
|
|
27192
|
+
sequence: sequence++,
|
|
27193
|
+
payload
|
|
27194
|
+
});
|
|
27195
|
+
mono = kxmIncrementMonotonicNs(mono);
|
|
27196
|
+
};
|
|
27197
|
+
push("attempt.status_changed", { attemptId: executing.attemptId, status: "settling" });
|
|
27198
|
+
push("assignment.result_recorded", {
|
|
27199
|
+
assignmentId: executing.assignmentId,
|
|
27200
|
+
resultClass: "producer_rejected",
|
|
27201
|
+
status: "result_recorded",
|
|
27202
|
+
producerError: "executing_unrecorded",
|
|
27203
|
+
reason: "executing_unrecorded"
|
|
27204
|
+
});
|
|
27205
|
+
push("attempt.status_changed", { attemptId: executing.attemptId, status: "terminal" });
|
|
27206
|
+
push("assignment.terminal", { assignmentId: executing.assignmentId, outcome: "failed", status: "terminal" });
|
|
27207
|
+
push("step.status_changed", { stepId: executing.stepId, status: "cancelled", previousStatus: "running" });
|
|
27208
|
+
push("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
|
|
27209
|
+
for (const event of events) context.eventStore.appendEvent(event);
|
|
27210
|
+
context.eventStore.settleCapability(executing.attemptId, "settled");
|
|
27211
|
+
const next = foldStoredKxmRun(context, run);
|
|
27212
|
+
persistKxmRunState(context, run.runId, next, events[events.length - 1].sequence);
|
|
27213
|
+
context.eventStore.updateRunStatus(run.runId, "cancelled", now);
|
|
27214
|
+
return next;
|
|
27215
|
+
}
|
|
27102
27216
|
function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
27103
27217
|
const run = requireRun(context, runId);
|
|
27104
27218
|
const plan = rehydrateKxmCompiledPlanFromStore(context.eventStore, run);
|
|
@@ -27107,6 +27221,23 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
|
27107
27221
|
return { kind: "return", state };
|
|
27108
27222
|
}
|
|
27109
27223
|
if (state.status === "cancelling" && kxmAttemptControllers(context.eventStore.path, runId).length === 0) {
|
|
27224
|
+
const executing = executingSingletonAttempt(plan, state);
|
|
27225
|
+
if (executing) {
|
|
27226
|
+
const exited = readOneShotObservedChildExit(runId, executing.attemptId);
|
|
27227
|
+
if (exited === true) {
|
|
27228
|
+
return { kind: "return", state: settleExitedExecutingAttempt(context, run, executing) };
|
|
27229
|
+
}
|
|
27230
|
+
return {
|
|
27231
|
+
kind: "return",
|
|
27232
|
+
state,
|
|
27233
|
+
handoff: {
|
|
27234
|
+
reason: "attempt_unreconciled",
|
|
27235
|
+
stepId: executing.stepId,
|
|
27236
|
+
attemptId: executing.attemptId,
|
|
27237
|
+
detail: "issued attempt is not held by this process"
|
|
27238
|
+
}
|
|
27239
|
+
};
|
|
27240
|
+
}
|
|
27110
27241
|
return {
|
|
27111
27242
|
kind: "return",
|
|
27112
27243
|
state,
|
|
@@ -27227,6 +27358,8 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
|
27227
27358
|
}
|
|
27228
27359
|
const unsupported = unsupportedStep(plan, step, producerId);
|
|
27229
27360
|
if (unsupported) return { kind: "return", state, handoff: { ...unsupported, stepId } };
|
|
27361
|
+
const wideTimeout = unsupportedAgentStepTimeout(step, projectAgentStepTimeoutMs(context, run));
|
|
27362
|
+
if (wideTimeout) return { kind: "return", state, handoff: { ...wideTimeout, stepId } };
|
|
27230
27363
|
let resolvedRoute;
|
|
27231
27364
|
if (producerId !== "driver-simulated") {
|
|
27232
27365
|
const allowed = step.assignments.allowedAgents;
|
|
@@ -27453,6 +27586,7 @@ function birthMember(context, input) {
|
|
|
27453
27586
|
${generatedPrompt}` : generatedPrompt,
|
|
27454
27587
|
thinking: input.stepAttempt <= 1 ? "low" : "medium",
|
|
27455
27588
|
permission: Object.values(input.step.repositories).some((access) => access === "write") ? "edit" : "read-only",
|
|
27589
|
+
...(input.step.kind === "agent" || input.step.kind === "moa") && input.step.timeoutMs !== void 0 ? { timeoutMs: input.step.timeoutMs } : {},
|
|
27456
27590
|
contextPacket,
|
|
27457
27591
|
...resolvedRoute ? { provider: resolvedRoute.provider, model: resolvedRoute.model } : {}
|
|
27458
27592
|
},
|
|
@@ -28233,7 +28367,7 @@ function unsupportedStep(plan, step, producerId) {
|
|
|
28233
28367
|
function readYamlRecord(path) {
|
|
28234
28368
|
if (!existsSync12(path)) return void 0;
|
|
28235
28369
|
try {
|
|
28236
|
-
const parsed = (0, import_yaml7.parse)(
|
|
28370
|
+
const parsed = (0, import_yaml7.parse)(readFileSync10(path, "utf8"));
|
|
28237
28371
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
|
|
28238
28372
|
} catch {
|
|
28239
28373
|
return void 0;
|
|
@@ -28916,7 +29050,8 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
|
|
|
28916
29050
|
}
|
|
28917
29051
|
const spawnFn = options.spawnProcess ?? defaultSpawn;
|
|
28918
29052
|
const cwd = options.projectRoot ?? process.cwd();
|
|
28919
|
-
const
|
|
29053
|
+
const timeoutMs = request.timeoutMs ?? options.timeoutMs;
|
|
29054
|
+
const evidence = await beginOneShotEvidence(options.evidenceRoot ?? oneShotEvidenceRoot(), {
|
|
28920
29055
|
runId: request.runId,
|
|
28921
29056
|
stepId: request.stepId,
|
|
28922
29057
|
attemptId: request.attemptId,
|
|
@@ -28927,11 +29062,12 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
|
|
|
28927
29062
|
cwd,
|
|
28928
29063
|
command,
|
|
28929
29064
|
args,
|
|
28930
|
-
input
|
|
29065
|
+
input,
|
|
29066
|
+
timeoutMs: timeoutMs ?? 12e4
|
|
28931
29067
|
}, [request.capability, ...Object.entries(env).filter(([key]) => /TOKEN|KEY|SECRET|PASSWORD|COOKIE|AUTH/i.test(key)).map(([, value]) => value ?? "")]);
|
|
28932
29068
|
let procResult;
|
|
28933
29069
|
try {
|
|
28934
|
-
procResult = request.signal.aborted ? { stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") } : await spawnFn(command, args, { cwd, env, input, timeoutMs
|
|
29070
|
+
procResult = request.signal.aborted ? { stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") } : await spawnFn(command, args, { cwd, env, input, timeoutMs, signal: request.signal });
|
|
28935
29071
|
} catch (error) {
|
|
28936
29072
|
procResult = { stdout: "", stderr: "", code: null, observedChildExit: false, error: error instanceof Error ? error : new Error("process_adapter_error") };
|
|
28937
29073
|
}
|
|
@@ -29154,9 +29290,9 @@ var RuntimeHubClient = class {
|
|
|
29154
29290
|
};
|
|
29155
29291
|
|
|
29156
29292
|
// plugins/kxm/src/hub-binding.ts
|
|
29157
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as
|
|
29293
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
29158
29294
|
import { homedir as homedir2 } from "node:os";
|
|
29159
|
-
import { dirname as dirname8, isAbsolute as isAbsolute5, join as
|
|
29295
|
+
import { dirname as dirname8, isAbsolute as isAbsolute5, join as join16, resolve as resolve9 } from "node:path";
|
|
29160
29296
|
var HUB_BINDING_SCHEMA = "kxm.hub-binding.v1";
|
|
29161
29297
|
var HubBindingError = class extends Error {
|
|
29162
29298
|
constructor(message) {
|
|
@@ -29172,16 +29308,16 @@ function resolveUserStateRoot(env) {
|
|
|
29172
29308
|
}
|
|
29173
29309
|
if (process.platform === "win32") {
|
|
29174
29310
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
29175
|
-
const base2 = localAppData && isAbsolute5(localAppData) ? localAppData :
|
|
29311
|
+
const base2 = localAppData && isAbsolute5(localAppData) ? localAppData : join16(homedir2(), "AppData", "Local");
|
|
29176
29312
|
return resolve9(base2, "KXM");
|
|
29177
29313
|
}
|
|
29178
29314
|
if (process.platform === "darwin") return resolve9(homedir2(), "Library", "Application Support", "KXM");
|
|
29179
29315
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
29180
|
-
const base = xdgState && isAbsolute5(xdgState) ? xdgState :
|
|
29316
|
+
const base = xdgState && isAbsolute5(xdgState) ? xdgState : join16(homedir2(), ".local", "state");
|
|
29181
29317
|
return resolve9(base, "kxm");
|
|
29182
29318
|
}
|
|
29183
29319
|
function hubBindingFile(env = process.env) {
|
|
29184
|
-
return
|
|
29320
|
+
return join16(resolveUserStateRoot(env), "hub-binding.json");
|
|
29185
29321
|
}
|
|
29186
29322
|
function validateHubUrl(raw) {
|
|
29187
29323
|
let parsed;
|
|
@@ -29204,7 +29340,7 @@ function readHubBinding(env = process.env) {
|
|
|
29204
29340
|
if (!existsSync13(file)) return void 0;
|
|
29205
29341
|
let parsed;
|
|
29206
29342
|
try {
|
|
29207
|
-
parsed = JSON.parse(
|
|
29343
|
+
parsed = JSON.parse(readFileSync11(file, "utf8"));
|
|
29208
29344
|
} catch {
|
|
29209
29345
|
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
29210
29346
|
}
|
|
@@ -29226,9 +29362,9 @@ function readHubBinding(env = process.env) {
|
|
|
29226
29362
|
}
|
|
29227
29363
|
|
|
29228
29364
|
// plugins/kxm/src/hub-env.ts
|
|
29229
|
-
import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as
|
|
29365
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync12, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
29230
29366
|
import { homedir as homedir3 } from "node:os";
|
|
29231
|
-
import { dirname as dirname9, isAbsolute as isAbsolute6, join as
|
|
29367
|
+
import { dirname as dirname9, isAbsolute as isAbsolute6, join as join17, resolve as resolve10 } from "node:path";
|
|
29232
29368
|
var HUB_ENV_SCHEMA = "kxm.hub-env.v1";
|
|
29233
29369
|
var HubEnvError = class extends Error {
|
|
29234
29370
|
constructor(message) {
|
|
@@ -29244,23 +29380,23 @@ function resolveUserStateRoot2(env) {
|
|
|
29244
29380
|
}
|
|
29245
29381
|
if (process.platform === "win32") {
|
|
29246
29382
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
29247
|
-
const base2 = localAppData && isAbsolute6(localAppData) ? localAppData :
|
|
29383
|
+
const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join17(homedir3(), "AppData", "Local");
|
|
29248
29384
|
return resolve10(base2, "KXM");
|
|
29249
29385
|
}
|
|
29250
29386
|
if (process.platform === "darwin") return resolve10(homedir3(), "Library", "Application Support", "KXM");
|
|
29251
29387
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
29252
|
-
const base = xdgState && isAbsolute6(xdgState) ? xdgState :
|
|
29388
|
+
const base = xdgState && isAbsolute6(xdgState) ? xdgState : join17(homedir3(), ".local", "state");
|
|
29253
29389
|
return resolve10(base, "kxm");
|
|
29254
29390
|
}
|
|
29255
29391
|
function hubEnvFile(env = process.env) {
|
|
29256
|
-
return
|
|
29392
|
+
return join17(resolveUserStateRoot2(env), "hub-env.json");
|
|
29257
29393
|
}
|
|
29258
29394
|
function readHubEnvRecord(env = process.env) {
|
|
29259
29395
|
const file = hubEnvFile(env);
|
|
29260
29396
|
if (!existsSync14(file)) return void 0;
|
|
29261
29397
|
let parsed;
|
|
29262
29398
|
try {
|
|
29263
|
-
parsed = JSON.parse(
|
|
29399
|
+
parsed = JSON.parse(readFileSync12(file, "utf8"));
|
|
29264
29400
|
} catch (error) {
|
|
29265
29401
|
throw new HubEnvError(`hub env file is malformed at ${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
29266
29402
|
}
|
|
@@ -29450,7 +29586,7 @@ function createLogger(options) {
|
|
|
29450
29586
|
|
|
29451
29587
|
// plugins/kxm/src/runtime-supervisor.ts
|
|
29452
29588
|
function kxmSupervisorTokenFile(paths) {
|
|
29453
|
-
return
|
|
29589
|
+
return join18(paths.runtimeDir, "supervisor.token");
|
|
29454
29590
|
}
|
|
29455
29591
|
function publishKxmSupervisorToken(paths, token) {
|
|
29456
29592
|
const file = kxmSupervisorTokenFile(paths);
|
|
@@ -29473,12 +29609,12 @@ function hashKxmSupervisorToken(token) {
|
|
|
29473
29609
|
}
|
|
29474
29610
|
function readKxmSupervisorToken(paths) {
|
|
29475
29611
|
const file = kxmSupervisorTokenFile(paths);
|
|
29476
|
-
const stat =
|
|
29612
|
+
const stat = lstatSync6(file, { throwIfNoEntry: false });
|
|
29477
29613
|
if (!stat) return void 0;
|
|
29478
29614
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
29479
29615
|
throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
|
|
29480
29616
|
}
|
|
29481
|
-
const token =
|
|
29617
|
+
const token = readFileSync13(file, "utf8").trim();
|
|
29482
29618
|
return token.length >= 32 ? token : void 0;
|
|
29483
29619
|
}
|
|
29484
29620
|
function processAlive(pid) {
|
|
@@ -29492,7 +29628,7 @@ function processAlive(pid) {
|
|
|
29492
29628
|
var HEARTBEAT_STALE_MS = 15e3;
|
|
29493
29629
|
var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
|
|
29494
29630
|
function supervisorErrorFile(paths) {
|
|
29495
|
-
return
|
|
29631
|
+
return join18(paths.runtimeDir, "supervisor.error");
|
|
29496
29632
|
}
|
|
29497
29633
|
function clearSupervisorError(paths) {
|
|
29498
29634
|
const file = supervisorErrorFile(paths);
|
|
@@ -29508,12 +29644,12 @@ function recordSupervisorError(paths, message) {
|
|
|
29508
29644
|
}
|
|
29509
29645
|
function readRecentSupervisorError(paths) {
|
|
29510
29646
|
const file = supervisorErrorFile(paths);
|
|
29511
|
-
const stat =
|
|
29647
|
+
const stat = lstatSync6(file, { throwIfNoEntry: false });
|
|
29512
29648
|
if (!stat) return void 0;
|
|
29513
29649
|
const ageMs = Date.now() - stat.mtimeMs;
|
|
29514
29650
|
if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
|
|
29515
29651
|
try {
|
|
29516
|
-
return
|
|
29652
|
+
return readFileSync13(file, "utf8").trim();
|
|
29517
29653
|
} catch {
|
|
29518
29654
|
return void 0;
|
|
29519
29655
|
}
|
|
@@ -29600,7 +29736,7 @@ async function ensureKxmSupervisor(options = {}) {
|
|
|
29600
29736
|
throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
|
|
29601
29737
|
}
|
|
29602
29738
|
clearSupervisorError(paths);
|
|
29603
|
-
const scriptPath =
|
|
29739
|
+
const scriptPath = join18(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
|
|
29604
29740
|
const spawnImpl = options.spawnImpl ?? ((script, env) => {
|
|
29605
29741
|
const child = spawn3(process.execPath, [script], {
|
|
29606
29742
|
detached: true,
|
|
@@ -29823,7 +29959,7 @@ function syncFailureText(error) {
|
|
|
29823
29959
|
return `${code ? `${code}: ` : ""}${message}`.replace(/(kxm_[A-Za-z0-9_]+|[A-Za-z0-9._-]{40,})/g, "[redacted]").slice(0, 300);
|
|
29824
29960
|
}
|
|
29825
29961
|
function runtimeSupervisorLogFile(paths) {
|
|
29826
|
-
return
|
|
29962
|
+
return join18(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
|
|
29827
29963
|
}
|
|
29828
29964
|
async function startKxmRuntimeSupervisor(options = {}) {
|
|
29829
29965
|
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -29985,6 +30121,7 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, e
|
|
|
29985
30121
|
const delayMs = typeof body.delayMs === "number" && body.delayMs > 0 ? body.delayMs : 0;
|
|
29986
30122
|
const createProducer = () => body.mode === "live" ? createKxmOneShotProducer({
|
|
29987
30123
|
projectRoot,
|
|
30124
|
+
timeoutMs: kxmProjectAdmissionLimits(bundle).agentStepTimeoutMs,
|
|
29988
30125
|
defaultHarness: String(bundle.project.value.defaultHarness ?? "pi"),
|
|
29989
30126
|
resolveHarness: (agentId) => {
|
|
29990
30127
|
const agent = bundle.agents.get(agentId);
|