@kontextmind/kxm 0.7.178 → 0.7.180
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/CHANGELOG.md +11 -0
- package/docs/contributing/decisions.md +27 -1
- package/docs/reference/cli-reference.md +34 -5
- package/docs/reference/tools.md +6 -4
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/claude-hook.js +36 -45
- package/plugins/kxm/dist/cli.js +376 -259
- package/plugins/kxm/dist/extension.js +29 -37
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/plugins.ts +193 -25
- package/plugins/kxm/src/cli.ts +2 -1
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/session-work.ts +34 -50
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -20760,8 +20760,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
20760
20760
|
const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
|
|
20761
20761
|
if (maxWriteRepositories > writable) issues.push(issue3("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
|
|
20762
20762
|
}
|
|
20763
|
-
const
|
|
20764
|
-
const minimumPassed =
|
|
20763
|
+
const join60 = objectValue(step.join);
|
|
20764
|
+
const minimumPassed = join60 && typeof join60.minimumPassed === "number" ? join60.minimumPassed : void 0;
|
|
20765
20765
|
if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue3("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
|
|
20766
20766
|
const distinctBy = names(assignment?.distinctBy);
|
|
20767
20767
|
if (distinctBy.length > 0) {
|
|
@@ -25101,7 +25101,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
25101
25101
|
const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
|
|
25102
25102
|
const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
|
|
25103
25103
|
const assignments = compileAssignments(step, id, agent, sink);
|
|
25104
|
-
const
|
|
25104
|
+
const join60 = compileJoin(step, id, sink);
|
|
25105
25105
|
const requiredEvidence = compileEvidence(step, id, sink);
|
|
25106
25106
|
const transitions = compileTransitions(step, id, index, stepIndex, sink);
|
|
25107
25107
|
const outcomes = Object.keys(transitions).sort(compareCodeUnits5);
|
|
@@ -25129,7 +25129,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
25129
25129
|
transitions: orderedTransitions,
|
|
25130
25130
|
requiresPlanHash: requirePlanHash.includes(id),
|
|
25131
25131
|
assignments,
|
|
25132
|
-
join:
|
|
25132
|
+
join: join60
|
|
25133
25133
|
};
|
|
25134
25134
|
if (kind === "agent" || kind === "moa") {
|
|
25135
25135
|
if (!agent) return void 0;
|
|
@@ -25179,15 +25179,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
|
|
|
25179
25179
|
};
|
|
25180
25180
|
}
|
|
25181
25181
|
function compileJoin(step, stepId, sink) {
|
|
25182
|
-
const
|
|
25183
|
-
if (!
|
|
25184
|
-
const declared = stringValue2(
|
|
25182
|
+
const join60 = objectValue2(step.join);
|
|
25183
|
+
if (!join60) return { strategy: "all" };
|
|
25184
|
+
const declared = stringValue2(join60.strategy);
|
|
25185
25185
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
25186
|
-
const minimumPassed = compileOptionalCount(
|
|
25186
|
+
const minimumPassed = compileOptionalCount(join60.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
25187
25187
|
const compiled = {
|
|
25188
25188
|
strategy,
|
|
25189
25189
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
25190
|
-
...typeof
|
|
25190
|
+
...typeof join60.cancelRemaining === "boolean" ? { cancelRemaining: join60.cancelRemaining } : {}
|
|
25191
25191
|
};
|
|
25192
25192
|
return compiled;
|
|
25193
25193
|
}
|
|
@@ -40403,11 +40403,114 @@ ${lines.join("\n")}`
|
|
|
40403
40403
|
init_project();
|
|
40404
40404
|
|
|
40405
40405
|
// plugins/kxm/src/cli/plugins.ts
|
|
40406
|
+
var import_yaml19 = __toESM(require_dist(), 1);
|
|
40406
40407
|
init_repo_root();
|
|
40407
40408
|
init_harness();
|
|
40408
40409
|
init_types();
|
|
40409
40410
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
40411
|
+
import { existsSync as existsSync32, readFileSync as readFileSync30 } from "node:fs";
|
|
40412
|
+
import { isAbsolute as isAbsolute10, join as join36 } from "node:path";
|
|
40410
40413
|
var PLUGIN_SUPPORTED_HARNESSES = Object.freeze(["pi", "omp", "claude"]);
|
|
40414
|
+
var OMP_STATUS_SETTINGS = [
|
|
40415
|
+
{ key: "statusLine.leftSegments", configKey: "leftSegments", value: ["model", "mode", "git", "pr", "subagents"] },
|
|
40416
|
+
{ key: "statusLine.rightSegments", configKey: "rightSegments", value: ["usage", "cost", "context_pct"] },
|
|
40417
|
+
{ key: "statusLine.preset", configKey: "preset", value: "custom" }
|
|
40418
|
+
];
|
|
40419
|
+
function spawnHarness(runtime, command, args) {
|
|
40420
|
+
return runtime.io.spawnSync ? runtime.io.spawnSync(command, args) : spawnSync9(command, args, { encoding: "utf8", windowsHide: true, env: runtime.env });
|
|
40421
|
+
}
|
|
40422
|
+
function spawnFailed(run) {
|
|
40423
|
+
return Boolean(run.error) || run.status !== 0;
|
|
40424
|
+
}
|
|
40425
|
+
function spawnFailureDetail(run, fallback) {
|
|
40426
|
+
return (run.stderr || run.stdout || run.error?.message || fallback).trim();
|
|
40427
|
+
}
|
|
40428
|
+
function ompConfigValueArg(value) {
|
|
40429
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
40430
|
+
}
|
|
40431
|
+
function readOmpGlobalStatusSettings(runtime, command) {
|
|
40432
|
+
const args = ["config", "path"];
|
|
40433
|
+
const run = spawnHarness(runtime, command, args);
|
|
40434
|
+
if (spawnFailed(run)) return { args, run, rollbackAttempted: false, rollbackFailed: false };
|
|
40435
|
+
const agentDir = run.stdout.trim();
|
|
40436
|
+
if (!agentDir || !isAbsolute10(agentDir) || !existsSync32(agentDir)) {
|
|
40437
|
+
return {
|
|
40438
|
+
args,
|
|
40439
|
+
run: { status: 1, stdout: run.stdout, stderr: "omp config path did not return an existing absolute directory" },
|
|
40440
|
+
rollbackAttempted: false,
|
|
40441
|
+
rollbackFailed: false
|
|
40442
|
+
};
|
|
40443
|
+
}
|
|
40444
|
+
const configPath = ["config.yml", "config.yaml"].map((name) => join36(agentDir, name)).find(existsSync32);
|
|
40445
|
+
let document = {};
|
|
40446
|
+
try {
|
|
40447
|
+
if (configPath) document = (0, import_yaml19.parse)(readFileSync30(configPath, "utf8"));
|
|
40448
|
+
} catch {
|
|
40449
|
+
return {
|
|
40450
|
+
args,
|
|
40451
|
+
run: { status: 1, stdout: run.stdout, stderr: `could not read OMP global config at ${configPath}` },
|
|
40452
|
+
rollbackAttempted: false,
|
|
40453
|
+
rollbackFailed: false
|
|
40454
|
+
};
|
|
40455
|
+
}
|
|
40456
|
+
const root = document && typeof document === "object" && !Array.isArray(document) ? document : {};
|
|
40457
|
+
const rawStatusLine = "statusLine" in root ? root.statusLine : void 0;
|
|
40458
|
+
const statusLine = rawStatusLine && typeof rawStatusLine === "object" && !Array.isArray(rawStatusLine) ? rawStatusLine : {};
|
|
40459
|
+
const previous = {};
|
|
40460
|
+
for (const setting of OMP_STATUS_SETTINGS) {
|
|
40461
|
+
const value = statusLine[setting.configKey];
|
|
40462
|
+
previous[setting.key] = Object.hasOwn(statusLine, setting.configKey) && value !== null && value !== void 0 ? { present: true, value } : { present: false };
|
|
40463
|
+
}
|
|
40464
|
+
return { previous };
|
|
40465
|
+
}
|
|
40466
|
+
function rollbackOmpStatusBand(runtime, command, settings, previous) {
|
|
40467
|
+
let failed2 = false;
|
|
40468
|
+
for (const setting of [...settings].reverse()) {
|
|
40469
|
+
const snapshot = previous[setting.key];
|
|
40470
|
+
const args = snapshot?.present ? ["config", "set", setting.key, ompConfigValueArg(snapshot.value), "--json"] : ["config", "reset", setting.key, "--json"];
|
|
40471
|
+
if (spawnFailed(spawnHarness(runtime, command, args))) failed2 = true;
|
|
40472
|
+
}
|
|
40473
|
+
return failed2;
|
|
40474
|
+
}
|
|
40475
|
+
function configureOmpStatusBand(runtime, command) {
|
|
40476
|
+
const snapshot = readOmpGlobalStatusSettings(runtime, command);
|
|
40477
|
+
if ("run" in snapshot) return snapshot;
|
|
40478
|
+
const written = [];
|
|
40479
|
+
for (const setting of OMP_STATUS_SETTINGS) {
|
|
40480
|
+
const args = ["config", "set", setting.key, ompConfigValueArg(setting.value), "--json"];
|
|
40481
|
+
written.push(setting);
|
|
40482
|
+
const run = spawnHarness(runtime, command, args);
|
|
40483
|
+
if (spawnFailed(run)) {
|
|
40484
|
+
return {
|
|
40485
|
+
args,
|
|
40486
|
+
run,
|
|
40487
|
+
rollbackAttempted: true,
|
|
40488
|
+
rollbackFailed: rollbackOmpStatusBand(runtime, command, written, snapshot.previous)
|
|
40489
|
+
};
|
|
40490
|
+
}
|
|
40491
|
+
}
|
|
40492
|
+
for (const setting of OMP_STATUS_SETTINGS) {
|
|
40493
|
+
const args = ["config", "get", setting.key, "--json"];
|
|
40494
|
+
const run = spawnHarness(runtime, command, args);
|
|
40495
|
+
let actual;
|
|
40496
|
+
try {
|
|
40497
|
+
const parsed = JSON.parse(run.stdout);
|
|
40498
|
+
actual = parsed && typeof parsed === "object" && "value" in parsed ? parsed.value : void 0;
|
|
40499
|
+
} catch {
|
|
40500
|
+
actual = void 0;
|
|
40501
|
+
}
|
|
40502
|
+
if (spawnFailed(run) || JSON.stringify(actual) !== JSON.stringify(setting.value)) {
|
|
40503
|
+
const mismatch = spawnFailed(run) ? run : { status: 1, stdout: run.stdout, stderr: `effective ${setting.key} is shadowed or did not persist` };
|
|
40504
|
+
return {
|
|
40505
|
+
args,
|
|
40506
|
+
run: mismatch,
|
|
40507
|
+
rollbackAttempted: true,
|
|
40508
|
+
rollbackFailed: rollbackOmpStatusBand(runtime, command, written, snapshot.previous)
|
|
40509
|
+
};
|
|
40510
|
+
}
|
|
40511
|
+
}
|
|
40512
|
+
return void 0;
|
|
40513
|
+
}
|
|
40411
40514
|
async function cmdPluginInstall(runtime, options) {
|
|
40412
40515
|
const repoRoot = findKxmRepoRoot(import.meta.url);
|
|
40413
40516
|
const env = runtime.env.PATH ? runtime.env : { ...process.env, ...runtime.env };
|
|
@@ -40418,12 +40521,22 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
40418
40521
|
if (options.omp) requestedHarnesses.push("omp");
|
|
40419
40522
|
if (options.claude) requestedHarnesses.push("claude");
|
|
40420
40523
|
const targetHarnesses = isExplicit ? requestedHarnesses : PLUGIN_SUPPORTED_HARNESSES;
|
|
40524
|
+
if (options.statusBand && isExplicit && !options.omp) {
|
|
40525
|
+
const detail = "--status-band requires OMP to be among the selected harnesses";
|
|
40526
|
+
print(
|
|
40527
|
+
runtime.io,
|
|
40528
|
+
runtime.json,
|
|
40529
|
+
{ ok: false, command: "plugin install", error: "omp_status_band_requires_omp", results: [] },
|
|
40530
|
+
detail
|
|
40531
|
+
);
|
|
40532
|
+
return 1;
|
|
40533
|
+
}
|
|
40421
40534
|
const results = [];
|
|
40422
40535
|
for (const harnessId of targetHarnesses) {
|
|
40423
40536
|
const status = inventory.harnesses.find((h) => h.id === harnessId);
|
|
40424
40537
|
const detected = Boolean(status?.detected && status?.command);
|
|
40425
40538
|
if (!detected) {
|
|
40426
|
-
if (isExplicit) {
|
|
40539
|
+
if (isExplicit || options.statusBand && harnessId === "omp") {
|
|
40427
40540
|
results.push({
|
|
40428
40541
|
harness: harnessId,
|
|
40429
40542
|
status: "failed",
|
|
@@ -40445,15 +40558,15 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
40445
40558
|
detail: `would install kxm plugin into pi: ${command} ${args.join(" ")}`
|
|
40446
40559
|
});
|
|
40447
40560
|
} else {
|
|
40448
|
-
const run = runtime
|
|
40449
|
-
if (run
|
|
40561
|
+
const run = spawnHarness(runtime, command, args);
|
|
40562
|
+
if (spawnFailed(run)) {
|
|
40450
40563
|
results.push({
|
|
40451
40564
|
harness: "pi",
|
|
40452
40565
|
status: "failed",
|
|
40453
40566
|
command,
|
|
40454
40567
|
args,
|
|
40455
40568
|
error: run.error?.message || "install_failed",
|
|
40456
|
-
detail: (run
|
|
40569
|
+
detail: spawnFailureDetail(run, "pi install exited with error")
|
|
40457
40570
|
});
|
|
40458
40571
|
} else {
|
|
40459
40572
|
results.push({
|
|
@@ -40473,27 +40586,39 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
40473
40586
|
status: "would",
|
|
40474
40587
|
command,
|
|
40475
40588
|
args,
|
|
40476
|
-
detail: `would install kxm plugin into omp: ${command} ${args.join(" ")}`
|
|
40589
|
+
detail: options.statusBand ? `would install kxm plugin into omp and configure the focused subscription status band: ${command} ${args.join(" ")}` : `would install kxm plugin into omp: ${command} ${args.join(" ")}`
|
|
40477
40590
|
});
|
|
40478
40591
|
} else {
|
|
40479
|
-
const run = runtime
|
|
40480
|
-
if (run
|
|
40592
|
+
const run = spawnHarness(runtime, command, args);
|
|
40593
|
+
if (spawnFailed(run)) {
|
|
40481
40594
|
results.push({
|
|
40482
40595
|
harness: "omp",
|
|
40483
40596
|
status: "failed",
|
|
40484
40597
|
command,
|
|
40485
40598
|
args,
|
|
40486
40599
|
error: run.error?.message || "install_failed",
|
|
40487
|
-
detail: (run
|
|
40600
|
+
detail: spawnFailureDetail(run, "omp plugin install exited with error")
|
|
40488
40601
|
});
|
|
40489
40602
|
} else {
|
|
40490
|
-
|
|
40491
|
-
|
|
40492
|
-
|
|
40493
|
-
|
|
40494
|
-
|
|
40495
|
-
|
|
40496
|
-
|
|
40603
|
+
const configFailure = options.statusBand ? configureOmpStatusBand(runtime, command) : void 0;
|
|
40604
|
+
if (configFailure) {
|
|
40605
|
+
results.push({
|
|
40606
|
+
harness: "omp",
|
|
40607
|
+
status: "failed",
|
|
40608
|
+
command,
|
|
40609
|
+
args: configFailure.args,
|
|
40610
|
+
error: "status_band_config_failed",
|
|
40611
|
+
detail: `installed kxm plugin into omp, but ${configFailure.args.slice(0, 3).join(" ")} failed: ${spawnFailureDetail(configFailure.run, "omp status band configuration exited with error")}${configFailure.rollbackAttempted ? configFailure.rollbackFailed ? "; previous settings could not be fully restored" : "; previous settings restored" : ""}`
|
|
40612
|
+
});
|
|
40613
|
+
} else {
|
|
40614
|
+
results.push({
|
|
40615
|
+
harness: "omp",
|
|
40616
|
+
status: "passed",
|
|
40617
|
+
command,
|
|
40618
|
+
args,
|
|
40619
|
+
detail: options.statusBand ? "installed kxm plugin into omp and configured the focused subscription status band; restart omp" : "installed kxm plugin into omp"
|
|
40620
|
+
});
|
|
40621
|
+
}
|
|
40497
40622
|
}
|
|
40498
40623
|
}
|
|
40499
40624
|
} else if (harnessId === "claude") {
|
|
@@ -40513,15 +40638,15 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
40513
40638
|
} else {
|
|
40514
40639
|
spawnSync9(command, marketplaceArgs, { encoding: "utf8", windowsHide: true, env: runtime.env });
|
|
40515
40640
|
}
|
|
40516
|
-
const run = runtime
|
|
40517
|
-
if (run
|
|
40641
|
+
const run = spawnHarness(runtime, command, installArgs);
|
|
40642
|
+
if (spawnFailed(run)) {
|
|
40518
40643
|
results.push({
|
|
40519
40644
|
harness: "claude",
|
|
40520
40645
|
status: "failed",
|
|
40521
40646
|
command,
|
|
40522
40647
|
args: installArgs,
|
|
40523
40648
|
error: run.error?.message || "install_failed",
|
|
40524
|
-
detail: (run
|
|
40649
|
+
detail: spawnFailureDetail(run, "claude install exited with error")
|
|
40525
40650
|
});
|
|
40526
40651
|
} else {
|
|
40527
40652
|
results.push({
|
|
@@ -40565,8 +40690,8 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
40565
40690
|
init_project_config();
|
|
40566
40691
|
init_types();
|
|
40567
40692
|
import { spawn as spawn4 } from "node:child_process";
|
|
40568
|
-
import { existsSync as
|
|
40569
|
-
import { join as
|
|
40693
|
+
import { existsSync as existsSync33 } from "node:fs";
|
|
40694
|
+
import { join as join37 } from "node:path";
|
|
40570
40695
|
var GENERATOR = "plans/kxm-roadmap/update-dashboard.mjs";
|
|
40571
40696
|
var SERVER = "ops/docs-site/serve.py";
|
|
40572
40697
|
function requireProject(runtime, command) {
|
|
@@ -40583,8 +40708,8 @@ function requireProject(runtime, command) {
|
|
|
40583
40708
|
return root;
|
|
40584
40709
|
}
|
|
40585
40710
|
function requireFile(runtime, command, root, relative8, error) {
|
|
40586
|
-
const file =
|
|
40587
|
-
if (
|
|
40711
|
+
const file = join37(root, relative8);
|
|
40712
|
+
if (existsSync33(file)) return file;
|
|
40588
40713
|
print(
|
|
40589
40714
|
runtime.io,
|
|
40590
40715
|
runtime.json,
|
|
@@ -40638,15 +40763,15 @@ init_runtime_store();
|
|
|
40638
40763
|
init_runtime_supervisor();
|
|
40639
40764
|
init_types();
|
|
40640
40765
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
40641
|
-
import { chmodSync as chmodSync6, existsSync as
|
|
40642
|
-
import { basename as basename8, dirname as dirname18, join as
|
|
40766
|
+
import { chmodSync as chmodSync6, existsSync as existsSync34, mkdirSync as mkdirSync24, readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
|
|
40767
|
+
import { basename as basename8, dirname as dirname18, join as join38, resolve as resolve25 } from "node:path";
|
|
40643
40768
|
var LANE_SCHEMA = "kxm.lanes.v1";
|
|
40644
40769
|
var SHA_RE = /^[a-f0-9]{40,64}$/;
|
|
40645
40770
|
var TIMESTAMP_RE = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]{1,9})?Z$/;
|
|
40646
40771
|
var SETTLED_RUN = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
40647
40772
|
var LANE_RUN_LIST_LIMIT = 1e4;
|
|
40648
40773
|
function lanesFile(runtime) {
|
|
40649
|
-
return
|
|
40774
|
+
return join38(runtime.dirs.state, "lanes.json");
|
|
40650
40775
|
}
|
|
40651
40776
|
function gitEnv2() {
|
|
40652
40777
|
return Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_")));
|
|
@@ -40694,9 +40819,9 @@ function isLaneFile(value) {
|
|
|
40694
40819
|
}
|
|
40695
40820
|
function loadLanes(runtime, command) {
|
|
40696
40821
|
const file = lanesFile(runtime);
|
|
40697
|
-
if (!
|
|
40822
|
+
if (!existsSync34(file)) return { schema: LANE_SCHEMA, lanes: {} };
|
|
40698
40823
|
try {
|
|
40699
|
-
const parsed = JSON.parse(
|
|
40824
|
+
const parsed = JSON.parse(readFileSync31(file, "utf8"));
|
|
40700
40825
|
if (!isLaneFile(parsed)) return refuse(runtime, command, "lanes_unreadable", `lane record ${file} is malformed`);
|
|
40701
40826
|
return parsed;
|
|
40702
40827
|
} catch {
|
|
@@ -40753,7 +40878,7 @@ function withLaneCwd(runtime, unit, command = "lane") {
|
|
|
40753
40878
|
const loaded2 = loadLanes(runtime, command);
|
|
40754
40879
|
if (typeof loaded2 === "number") return loaded2;
|
|
40755
40880
|
const lane = loaded2.lanes[unit];
|
|
40756
|
-
if (!lane || !
|
|
40881
|
+
if (!lane || !existsSync34(lane.path)) {
|
|
40757
40882
|
return refuse(runtime, command, "lane_missing", `lane ${unit} is not recorded or its worktree is absent`, { unit });
|
|
40758
40883
|
}
|
|
40759
40884
|
return {
|
|
@@ -40807,7 +40932,7 @@ async function cmdKxmRunCli(runtime, workflow, promptParts, options = {}) {
|
|
|
40807
40932
|
}
|
|
40808
40933
|
function readRunBrief(runtime, file, command) {
|
|
40809
40934
|
try {
|
|
40810
|
-
return { text:
|
|
40935
|
+
return { text: readFileSync31(resolve25(runtime.cwd, file), "utf8").trim() };
|
|
40811
40936
|
} catch {
|
|
40812
40937
|
return refuse(runtime, command, "brief_unreadable", `cannot read brief ${file}`, { brief: file });
|
|
40813
40938
|
}
|
|
@@ -40824,7 +40949,7 @@ function aheadBehind(path4, baseSha) {
|
|
|
40824
40949
|
return { behind: Number(match[1]), ahead: Number(match[2]) };
|
|
40825
40950
|
}
|
|
40826
40951
|
function laneView(unit, record) {
|
|
40827
|
-
const exists =
|
|
40952
|
+
const exists = existsSync34(record.path);
|
|
40828
40953
|
const counts = exists ? aheadBehind(record.path, record.baseSha) : { ahead: null, behind: null };
|
|
40829
40954
|
return {
|
|
40830
40955
|
unit,
|
|
@@ -40901,7 +41026,7 @@ async function laneStoreRuns(runtime, lanePath) {
|
|
|
40901
41026
|
}
|
|
40902
41027
|
}
|
|
40903
41028
|
const eventsPath = kxmProjectRunEventsPath(lanePath, runtime.env);
|
|
40904
|
-
if (!
|
|
41029
|
+
if (!existsSync34(eventsPath)) return void 0;
|
|
40905
41030
|
const store = new KxmRunEventStore(eventsPath);
|
|
40906
41031
|
try {
|
|
40907
41032
|
return store.runsForProject(projectId(), LANE_RUN_LIST_LIMIT).map((run) => ({ runId: run.runId, status: run.status }));
|
|
@@ -40970,7 +41095,7 @@ async function cmdLaneCreate(runtime, unit, options = {}) {
|
|
|
40970
41095
|
const loaded2 = loadLanes(runtime, command);
|
|
40971
41096
|
if (typeof loaded2 === "number") return loaded2;
|
|
40972
41097
|
const path4 = laneWorktreePath(root, unit);
|
|
40973
|
-
if (loaded2.lanes[unit] ||
|
|
41098
|
+
if (loaded2.lanes[unit] || existsSync34(path4) || branchExists(root, unit)) {
|
|
40974
41099
|
return refuse(runtime, command, "lane_exists", `lane ${unit} already exists`, { unit });
|
|
40975
41100
|
}
|
|
40976
41101
|
const baseSha = resolveBase(root, base);
|
|
@@ -40995,7 +41120,7 @@ async function cmdLaneCreate(runtime, unit, options = {}) {
|
|
|
40995
41120
|
return refuse(runtime, command, "lane_git_failed", `git worktree add failed: ${added.stderr.trim().slice(0, 300)}`, { unit });
|
|
40996
41121
|
}
|
|
40997
41122
|
const recordedPath = discoverKxmProjectRoot(path4) ?? path4;
|
|
40998
|
-
if (!
|
|
41123
|
+
if (!existsSync34(join38(recordedPath, ".kxm", "project.yaml"))) {
|
|
40999
41124
|
git2(root, ["worktree", "remove", "--force", path4]);
|
|
41000
41125
|
return refuse(runtime, command, "lane_not_project", `lane ${recordedPath} has no .kxm/project.yaml; the worktree was removed`, { unit, path: recordedPath });
|
|
41001
41126
|
}
|
|
@@ -41061,7 +41186,7 @@ async function unregisterLaneRoot(runtime, projectRoot, force) {
|
|
|
41061
41186
|
return void 0;
|
|
41062
41187
|
}
|
|
41063
41188
|
const paths = kxmRuntimePaths({ env: runtime.env });
|
|
41064
|
-
if (!
|
|
41189
|
+
if (!existsSync34(paths.registryDb)) return void 0;
|
|
41065
41190
|
const registry = new KxmRuntimeRegistry(paths.registryDb);
|
|
41066
41191
|
let outcome;
|
|
41067
41192
|
try {
|
|
@@ -41091,7 +41216,7 @@ async function cmdLaneDrop(runtime, unit, options = {}) {
|
|
|
41091
41216
|
if (!record) return refuse(runtime, command, "lane_missing", `lane ${unit} is not recorded`, { unit });
|
|
41092
41217
|
const force = options.force === true;
|
|
41093
41218
|
if (!force) {
|
|
41094
|
-
if (
|
|
41219
|
+
if (existsSync34(record.path)) {
|
|
41095
41220
|
const dirty = porcelainCount(record.path);
|
|
41096
41221
|
if (dirty === null) {
|
|
41097
41222
|
return refuse(runtime, command, "lane_git_failed", `lane ${unit} worktree status could not be read`, { unit });
|
|
@@ -41117,7 +41242,7 @@ async function cmdLaneDrop(runtime, unit, options = {}) {
|
|
|
41117
41242
|
if (unregistered !== void 0) {
|
|
41118
41243
|
return refuse(runtime, command, "lane_unregister_failed", `lane ${unit} could not be unregistered: ${unregistered.slice(0, 300)}`, { unit });
|
|
41119
41244
|
}
|
|
41120
|
-
if (
|
|
41245
|
+
if (existsSync34(record.path)) {
|
|
41121
41246
|
const removed = git2(root, ["worktree", "remove", ...force ? ["--force"] : [], record.path]);
|
|
41122
41247
|
if (removed.status !== 0) {
|
|
41123
41248
|
return refuse(runtime, command, "lane_git_failed", `git worktree remove failed: ${removed.stderr.trim().slice(0, 300)}`, { unit });
|
|
@@ -41188,7 +41313,7 @@ init_project_config();
|
|
|
41188
41313
|
init_repo_root();
|
|
41189
41314
|
init_types();
|
|
41190
41315
|
import { spawn as spawn5 } from "node:child_process";
|
|
41191
|
-
import { join as
|
|
41316
|
+
import { join as join39 } from "node:path";
|
|
41192
41317
|
function childEnv() {
|
|
41193
41318
|
const env = {};
|
|
41194
41319
|
for (const [name, value] of Object.entries(process.env)) {
|
|
@@ -41207,7 +41332,7 @@ function cmdLand(runtime, options = {}) {
|
|
|
41207
41332
|
if (!root) {
|
|
41208
41333
|
return Promise.resolve(refuse2(runtime, "project_required", "land requires a KXM project (run kxm init first)"));
|
|
41209
41334
|
}
|
|
41210
|
-
const script =
|
|
41335
|
+
const script = join39(findKxmRepoRoot(import.meta.url), "scripts", "pr-land.mjs");
|
|
41211
41336
|
const args = [script];
|
|
41212
41337
|
if (options.pr) args.push("--pr", options.pr);
|
|
41213
41338
|
if (options.stage) args.push("--stage", options.stage);
|
|
@@ -41227,19 +41352,19 @@ function cmdLand(runtime, options = {}) {
|
|
|
41227
41352
|
// plugins/kxm/src/cli/supervise.ts
|
|
41228
41353
|
init_project_config();
|
|
41229
41354
|
import { appendFileSync as appendFileSync2, chmodSync as chmodSync8, mkdirSync as mkdirSync26 } from "node:fs";
|
|
41230
|
-
import { join as
|
|
41355
|
+
import { join as join41 } from "node:path";
|
|
41231
41356
|
|
|
41232
41357
|
// plugins/kxm/src/supervise-state.ts
|
|
41233
41358
|
init_project_config();
|
|
41234
|
-
import { chmodSync as chmodSync7, existsSync as
|
|
41235
|
-
import { join as
|
|
41359
|
+
import { chmodSync as chmodSync7, existsSync as existsSync35, mkdirSync as mkdirSync25, readFileSync as readFileSync32, renameSync as renameSync8, writeFileSync as writeFileSync23 } from "node:fs";
|
|
41360
|
+
import { join as join40 } from "node:path";
|
|
41236
41361
|
var SUPERVISOR_SCHEMA = "kxm.supervisor.v1";
|
|
41237
41362
|
var TIMESTAMP_RE2 = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]{1,9})?Z$/;
|
|
41238
41363
|
var MERGE_STATE_RE = /^[A-Z][A-Z0-9_]{0,31}$/;
|
|
41239
41364
|
var CI_TOKEN_RE = /^[a-z][a-z0-9_-]{0,31}$/;
|
|
41240
41365
|
var MAX_BACKOFF_MS = 24 * 60 * 60 * 1e3;
|
|
41241
41366
|
function supervisorStatePath(stateDir) {
|
|
41242
|
-
return
|
|
41367
|
+
return join40(stateDir, "supervisor.json");
|
|
41243
41368
|
}
|
|
41244
41369
|
function emptySupervisorState(now) {
|
|
41245
41370
|
return { schema: SUPERVISOR_SCHEMA, updatedAt: now, lanes: {} };
|
|
@@ -41288,10 +41413,10 @@ function isState(value) {
|
|
|
41288
41413
|
}
|
|
41289
41414
|
function loadSupervisorState(stateDir, now) {
|
|
41290
41415
|
const path4 = supervisorStatePath(stateDir);
|
|
41291
|
-
if (!
|
|
41416
|
+
if (!existsSync35(path4)) return emptySupervisorState(now);
|
|
41292
41417
|
let parsed;
|
|
41293
41418
|
try {
|
|
41294
|
-
parsed = JSON.parse(
|
|
41419
|
+
parsed = JSON.parse(readFileSync32(path4, "utf8"));
|
|
41295
41420
|
} catch {
|
|
41296
41421
|
return "supervisor_unreadable";
|
|
41297
41422
|
}
|
|
@@ -41454,7 +41579,7 @@ function cmdSuperviseStatus(runtime) {
|
|
|
41454
41579
|
}
|
|
41455
41580
|
function appendTick(runtime, line) {
|
|
41456
41581
|
mkdirSync26(runtime.dirs.logs, { recursive: true });
|
|
41457
|
-
const path4 =
|
|
41582
|
+
const path4 = join41(runtime.dirs.logs, "supervisor.log");
|
|
41458
41583
|
appendFileSync2(path4, `${line}
|
|
41459
41584
|
`, { encoding: "utf8", mode: 384 });
|
|
41460
41585
|
try {
|
|
@@ -41473,8 +41598,8 @@ function cmdSuperviseTick(runtime) {
|
|
|
41473
41598
|
const line = formatTickLine(now, tick.resumed, tick.waiting);
|
|
41474
41599
|
if (runtime.dryRun) {
|
|
41475
41600
|
printPlan(runtime, { command: "supervise", resumed: tick.resumed, waiting: tick.waiting, log: line, state: tick.state }, [
|
|
41476
|
-
{ action: "write", target:
|
|
41477
|
-
{ action: "write", target:
|
|
41601
|
+
{ action: "write", target: join41(runtime.dirs.state, "supervisor.json") },
|
|
41602
|
+
{ action: "write", target: join41(runtime.dirs.logs, "supervisor.log") }
|
|
41478
41603
|
], "resume lanes whose backoff has elapsed");
|
|
41479
41604
|
return 0;
|
|
41480
41605
|
}
|
|
@@ -41521,7 +41646,7 @@ function cmdSuperviseRecord(runtime, options) {
|
|
|
41521
41646
|
}
|
|
41522
41647
|
if (runtime.dryRun) {
|
|
41523
41648
|
printPlan(runtime, { command: "supervise", state: next }, [
|
|
41524
|
-
{ action: "write", target:
|
|
41649
|
+
{ action: "write", target: join41(runtime.dirs.state, "supervisor.json") }
|
|
41525
41650
|
], `record lane ${options.lane}`);
|
|
41526
41651
|
return 0;
|
|
41527
41652
|
}
|
|
@@ -41533,8 +41658,8 @@ function cmdSuperviseRecord(runtime, options) {
|
|
|
41533
41658
|
init_project_config();
|
|
41534
41659
|
init_types();
|
|
41535
41660
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
41536
|
-
import { existsSync as
|
|
41537
|
-
import { join as
|
|
41661
|
+
import { existsSync as existsSync36 } from "node:fs";
|
|
41662
|
+
import { join as join42 } from "node:path";
|
|
41538
41663
|
var kxmAssignCliSeams = {};
|
|
41539
41664
|
var RUNNER_REL = "scripts/assignment-run.mjs";
|
|
41540
41665
|
function refuse4(runtime, command, error, text) {
|
|
@@ -41606,7 +41731,7 @@ async function cmdAssign(runtime, subcommand, args) {
|
|
|
41606
41731
|
const command = `assign ${subcommand}`;
|
|
41607
41732
|
const root = discoverKxmProjectRoot(runtime.cwd);
|
|
41608
41733
|
if (!root) return refuse4(runtime, command, "project_required", `${command} requires a KXM project (run kxm init first)`);
|
|
41609
|
-
if (!
|
|
41734
|
+
if (!existsSync36(join42(root, "scripts", "assignment-run.mjs"))) {
|
|
41610
41735
|
return refuse4(runtime, command, "assign_runner_missing", `${command} requires scripts/assignment-run.mjs in the project root`);
|
|
41611
41736
|
}
|
|
41612
41737
|
const argv = ["node", RUNNER_REL, ...runnerArgv(subcommand, args)];
|
|
@@ -41642,8 +41767,8 @@ init_config();
|
|
|
41642
41767
|
init_hub_identity();
|
|
41643
41768
|
init_envelope();
|
|
41644
41769
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
41645
|
-
import { existsSync as
|
|
41646
|
-
import { join as
|
|
41770
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync30, readFileSync as readFileSync38, readdirSync as readdirSync13, rmSync as rmSync11, writeFileSync as writeFileSync26 } from "node:fs";
|
|
41771
|
+
import { join as join52, resolve as resolve28 } from "node:path";
|
|
41647
41772
|
|
|
41648
41773
|
// node_modules/marked/lib/marked.esm.js
|
|
41649
41774
|
function A() {
|
|
@@ -47635,7 +47760,7 @@ import * as path2 from "node:path";
|
|
|
47635
47760
|
|
|
47636
47761
|
// node_modules/@earendil-works/pi-tui/dist/native-module-path.js
|
|
47637
47762
|
import { createRequire as createRequire2 } from "node:module";
|
|
47638
|
-
import { dirname as dirname19, join as
|
|
47763
|
+
import { dirname as dirname19, join as join43 } from "node:path";
|
|
47639
47764
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
47640
47765
|
var moduleRequire = createRequire2(import.meta.url);
|
|
47641
47766
|
var TUI_PACKAGE_NAME = "@earendil-works/pi-tui";
|
|
@@ -47644,10 +47769,10 @@ function getNativeModuleCandidates(nativePath, options = {}) {
|
|
|
47644
47769
|
const candidates = [];
|
|
47645
47770
|
try {
|
|
47646
47771
|
const packageEntry = (options.resolvePackage ?? moduleRequire.resolve)(TUI_PACKAGE_NAME);
|
|
47647
|
-
candidates.push(
|
|
47772
|
+
candidates.push(join43(dirname19(packageEntry), "..", nativePath));
|
|
47648
47773
|
} catch {
|
|
47649
47774
|
}
|
|
47650
|
-
candidates.push(
|
|
47775
|
+
candidates.push(join43(moduleDir, "..", nativePath), join43(moduleDir, nativePath), join43(dirname19(options.execPath ?? process.execPath), nativePath));
|
|
47651
47776
|
return Array.from(new Set(candidates));
|
|
47652
47777
|
}
|
|
47653
47778
|
|
|
@@ -50475,7 +50600,7 @@ var MAX_RENDER_WRITE_CHARS = 1024 * 1024;
|
|
|
50475
50600
|
|
|
50476
50601
|
// plugins/kxm/src/tui.ts
|
|
50477
50602
|
import { mkdirSync as mkdirSync27 } from "node:fs";
|
|
50478
|
-
import { join as
|
|
50603
|
+
import { join as join47, resolve as resolve27, dirname as dirname20 } from "node:path";
|
|
50479
50604
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
50480
50605
|
|
|
50481
50606
|
// packages/core/tui/src/types/surface.ts
|
|
@@ -51791,9 +51916,9 @@ var SHARED_EFFECT_KINDS = Object.freeze([
|
|
|
51791
51916
|
// plugins/kxm/src/local-snapshot.ts
|
|
51792
51917
|
init_sqlite();
|
|
51793
51918
|
init_telemetry();
|
|
51794
|
-
import { existsSync as
|
|
51919
|
+
import { existsSync as existsSync37, readdirSync as readdirSync12, readFileSync as readFileSync33 } from "node:fs";
|
|
51795
51920
|
import { homedir as homedir6 } from "node:os";
|
|
51796
|
-
import { isAbsolute as
|
|
51921
|
+
import { isAbsolute as isAbsolute11, join as join46, resolve as resolve26 } from "node:path";
|
|
51797
51922
|
var DEFAULT_BUSY_TIMEOUT_MS = 5e3;
|
|
51798
51923
|
var RUNTIME_PROJECT_KEY = /^[A-Za-z0-9_-][A-Za-z0-9._-]*$/;
|
|
51799
51924
|
function processExists2(pid) {
|
|
@@ -51918,36 +52043,36 @@ function readOpenMessageMetadata(database, where = OPEN_MESSAGE_WHERE, params =
|
|
|
51918
52043
|
return messages;
|
|
51919
52044
|
}
|
|
51920
52045
|
function resolveKxmSnapshotPaths(cwd, env = process.env) {
|
|
51921
|
-
const stateDir = env.KXM_STATE_DIR?.trim() ||
|
|
52046
|
+
const stateDir = env.KXM_STATE_DIR?.trim() || join46(cwd, ".kxm", "state");
|
|
51922
52047
|
const configured = env.KXM_DATA_PATH?.trim();
|
|
51923
|
-
const dataPath = configured ? resolve26(cwd, configured) :
|
|
52048
|
+
const dataPath = configured ? resolve26(cwd, configured) : join46(stateDir, "kxm.db");
|
|
51924
52049
|
return { dataPath, stateDir };
|
|
51925
52050
|
}
|
|
51926
52051
|
function resolveKxmStateRoot(stateDir, options) {
|
|
51927
|
-
if (options?.kxmStateRoot &&
|
|
52052
|
+
if (options?.kxmStateRoot && existsSync37(options.kxmStateRoot)) {
|
|
51928
52053
|
return resolve26(options.kxmStateRoot);
|
|
51929
52054
|
}
|
|
51930
|
-
if (
|
|
52055
|
+
if (existsSync37(join46(stateDir, "runtime", "registry.db")) || existsSync37(join46(stateDir, "runtime", "projects"))) {
|
|
51931
52056
|
return stateDir;
|
|
51932
52057
|
}
|
|
51933
52058
|
const env = options?.env ?? process.env;
|
|
51934
52059
|
const explicit = env.KXM_STATE_HOME?.trim() || env.KXM_USER_STATE_DIR?.trim() || env.KXM_STATE_ROOT?.trim();
|
|
51935
|
-
if (explicit &&
|
|
52060
|
+
if (explicit && isAbsolute11(explicit) && existsSync37(resolve26(explicit))) {
|
|
51936
52061
|
return resolve26(explicit);
|
|
51937
52062
|
}
|
|
51938
52063
|
let base;
|
|
51939
52064
|
if (process.platform === "win32") {
|
|
51940
52065
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
51941
|
-
base = localAppData &&
|
|
52066
|
+
base = localAppData && isAbsolute11(localAppData) ? localAppData : join46(homedir6(), "AppData", "Local");
|
|
51942
52067
|
base = resolve26(base, "KXM");
|
|
51943
52068
|
} else if (process.platform === "darwin") {
|
|
51944
52069
|
base = resolve26(homedir6(), "Library", "Application Support", "KXM");
|
|
51945
52070
|
} else {
|
|
51946
52071
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
51947
|
-
base = xdgState &&
|
|
52072
|
+
base = xdgState && isAbsolute11(xdgState) ? xdgState : join46(homedir6(), ".local", "state");
|
|
51948
52073
|
base = resolve26(base, "kxm");
|
|
51949
52074
|
}
|
|
51950
|
-
if (
|
|
52075
|
+
if (existsSync37(base)) return base;
|
|
51951
52076
|
return void 0;
|
|
51952
52077
|
}
|
|
51953
52078
|
function readRuntimeRuns(eventDb, projectId) {
|
|
@@ -51980,7 +52105,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
51980
52105
|
let legacyRuns = [];
|
|
51981
52106
|
let legacyRunTotal = 0;
|
|
51982
52107
|
let plans = [];
|
|
51983
|
-
if (
|
|
52108
|
+
if (existsSync37(dataPath)) {
|
|
51984
52109
|
hasLegacy = true;
|
|
51985
52110
|
const database = openReadOnlyDatabase(dataPath);
|
|
51986
52111
|
try {
|
|
@@ -52011,11 +52136,11 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
52011
52136
|
let kxmRunTotal = 0;
|
|
52012
52137
|
const kxmStateRoot = scope && !scope.runtimeProjectId ? void 0 : resolveKxmStateRoot(stateDir, options);
|
|
52013
52138
|
if (kxmStateRoot) {
|
|
52014
|
-
const runtimeDir =
|
|
52015
|
-
const registryDbPath =
|
|
52016
|
-
const projectsDir =
|
|
52139
|
+
const runtimeDir = join46(kxmStateRoot, "runtime");
|
|
52140
|
+
const registryDbPath = join46(runtimeDir, "registry.db");
|
|
52141
|
+
const projectsDir = join46(runtimeDir, "projects");
|
|
52017
52142
|
const projectKeys = /* @__PURE__ */ new Set();
|
|
52018
|
-
if (
|
|
52143
|
+
if (existsSync37(registryDbPath)) {
|
|
52019
52144
|
hasKxm = true;
|
|
52020
52145
|
try {
|
|
52021
52146
|
const regDb = openReadOnlyDatabase(registryDbPath);
|
|
@@ -52031,7 +52156,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
52031
52156
|
} catch {
|
|
52032
52157
|
}
|
|
52033
52158
|
}
|
|
52034
|
-
if (!scope &&
|
|
52159
|
+
if (!scope && existsSync37(projectsDir)) {
|
|
52035
52160
|
try {
|
|
52036
52161
|
for (const entry of readdirSync12(projectsDir, { withFileTypes: true })) {
|
|
52037
52162
|
if (entry.isDirectory()) {
|
|
@@ -52043,8 +52168,8 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
52043
52168
|
}
|
|
52044
52169
|
for (const key of projectKeys) {
|
|
52045
52170
|
if (scope && !RUNTIME_PROJECT_KEY.test(key)) continue;
|
|
52046
|
-
const eventDbPath =
|
|
52047
|
-
if (
|
|
52171
|
+
const eventDbPath = join46(projectsDir, key, "run-events.db");
|
|
52172
|
+
if (existsSync37(eventDbPath)) {
|
|
52048
52173
|
hasKxm = true;
|
|
52049
52174
|
try {
|
|
52050
52175
|
const eventDb = openReadOnlyDatabase(eventDbPath);
|
|
@@ -52062,10 +52187,10 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
52062
52187
|
}
|
|
52063
52188
|
}
|
|
52064
52189
|
const pids = [];
|
|
52065
|
-
if (
|
|
52190
|
+
if (existsSync37(stateDir)) {
|
|
52066
52191
|
for (const file of readdirSync12(stateDir).filter((name) => name.endsWith(".pid"))) {
|
|
52067
52192
|
try {
|
|
52068
|
-
const record = JSON.parse(
|
|
52193
|
+
const record = JSON.parse(readFileSync33(join46(stateDir, file), "utf8"));
|
|
52069
52194
|
pids.push({
|
|
52070
52195
|
file,
|
|
52071
52196
|
...record.role ? { role: record.role } : {},
|
|
@@ -52104,8 +52229,8 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
52104
52229
|
} else {
|
|
52105
52230
|
source = "legacy";
|
|
52106
52231
|
}
|
|
52107
|
-
const telemetryFile =
|
|
52108
|
-
const spend =
|
|
52232
|
+
const telemetryFile = join46(stateDir, "telemetry.jsonl");
|
|
52233
|
+
const spend = existsSync37(telemetryFile) ? readRoutingRecords(telemetryFile) : [];
|
|
52109
52234
|
return {
|
|
52110
52235
|
source,
|
|
52111
52236
|
agents: agents.sort((a, b2) => Number(b2.online) - Number(a.online) || a.name.localeCompare(b2.name)),
|
|
@@ -52239,7 +52364,7 @@ function spawnDegradeWorktree(repoRoot, runId, options) {
|
|
|
52239
52364
|
const cleanRunId = runId.replace(/^run_/, "");
|
|
52240
52365
|
const desc = options?.description ? slugifyBranchPart(options.description, 30) : "degrade";
|
|
52241
52366
|
const branchName = `kxm/run-${cleanRunId}-${desc}`;
|
|
52242
|
-
const relativeWtPath =
|
|
52367
|
+
const relativeWtPath = join47(".kxm", "worktrees", `run-${cleanRunId}-${desc}`);
|
|
52243
52368
|
const absoluteWtPath = resolve27(repoRoot, relativeWtPath);
|
|
52244
52369
|
const jumpCommand = `cd "${absoluteWtPath}"`;
|
|
52245
52370
|
try {
|
|
@@ -53008,20 +53133,20 @@ async function runMeshTui(input) {
|
|
|
53008
53133
|
// plugins/kxm/src/session-work.ts
|
|
53009
53134
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
53010
53135
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
53011
|
-
import { existsSync as
|
|
53012
|
-
import { join as
|
|
53136
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync28, readFileSync as readFileSync34, renameSync as renameSync9, writeFileSync as writeFileSync24 } from "node:fs";
|
|
53137
|
+
import { join as join48 } from "node:path";
|
|
53013
53138
|
init_hub_binding();
|
|
53014
53139
|
init_telemetry();
|
|
53015
53140
|
var MAX_SESSION_BRIEF_TASKS = 5;
|
|
53016
53141
|
var MAX_SESSION_BRIEF_PLANS = 5;
|
|
53017
53142
|
var SESSION_BRIEF_SCHEMA = "kxm.session-brief.v1";
|
|
53018
53143
|
var DEFAULT_SESSION_BRIEF_STALE_SECONDS = 5;
|
|
53019
|
-
function
|
|
53144
|
+
function hubStatusPart(hub) {
|
|
53020
53145
|
const suffix = hub?.scope === "remote" ? "/remote" : "";
|
|
53021
|
-
if (hub?.state === "
|
|
53022
|
-
if (hub?.state === "
|
|
53023
|
-
if (hub?.
|
|
53024
|
-
return
|
|
53146
|
+
if (hub?.state === "off" || hub?.state === void 0 && hub?.online === false) return `hub:off${suffix}`;
|
|
53147
|
+
if (hub?.state === "unknown") return `hub:unknown${suffix}`;
|
|
53148
|
+
if (hub?.scope === "remote") return "hub:remote";
|
|
53149
|
+
return void 0;
|
|
53025
53150
|
}
|
|
53026
53151
|
function truncate(value, width) {
|
|
53027
53152
|
const text = value.replace(/\s+/g, " ").trim();
|
|
@@ -53097,40 +53222,34 @@ function readGitShip(cwd) {
|
|
|
53097
53222
|
return void 0;
|
|
53098
53223
|
}
|
|
53099
53224
|
}
|
|
53100
|
-
function formatSessionStatusLine(stats, current, hub, ship, updateLatest
|
|
53101
|
-
const
|
|
53102
|
-
|
|
53103
|
-
|
|
53104
|
-
|
|
53105
|
-
|
|
53106
|
-
|
|
53107
|
-
return finalLine.length <= 80 ? finalLine : `${finalLine.slice(0, 79)}\u2026`;
|
|
53108
|
-
}
|
|
53109
|
-
const parts = [];
|
|
53110
|
-
if (current?.kind === "task") parts.push(`${head} ${current.detail}`);
|
|
53111
|
-
else if (current?.kind === "plan") parts.push(`${head} plan ${truncate(current.detail, 36)}`);
|
|
53112
|
-
else parts.push(head);
|
|
53113
|
-
parts.push(`${stats.activeTasks} task${stats.activeTasks === 1 ? "" : "s"}`);
|
|
53225
|
+
function formatSessionStatusLine(stats, current, hub, ship, updateLatest) {
|
|
53226
|
+
const parts = ["kxm"];
|
|
53227
|
+
const hubPart = hubStatusPart(hub);
|
|
53228
|
+
if (hubPart) parts.push(hubPart);
|
|
53229
|
+
if (current?.kind === "task") parts.push(current.detail);
|
|
53230
|
+
else if (current?.kind === "plan") parts.push(`plan ${truncate(current.detail, 36)}`);
|
|
53231
|
+
if (stats.activeTasks > 0) parts.push(`${stats.activeTasks} task${stats.activeTasks === 1 ? "" : "s"}`);
|
|
53114
53232
|
if (stats.waitingTasks > 0) parts.push(`${stats.waitingTasks} waiting`);
|
|
53115
|
-
parts.push(`${stats.planCount} plan${stats.planCount === 1 ? "" : "s"}`);
|
|
53233
|
+
if (stats.planCount > 0) parts.push(`${stats.planCount} plan${stats.planCount === 1 ? "" : "s"}`);
|
|
53116
53234
|
if (stats.inbox > 0) parts.push(`inbox ${stats.inbox}`);
|
|
53117
53235
|
if (ship?.dirty) parts.push("dirty");
|
|
53118
53236
|
else if (ship && ship.ahead > 0) parts.push(`${ship.ahead} local`);
|
|
53119
|
-
if (cost) parts.push(cost);
|
|
53120
53237
|
if (updateLatest) parts.push(`upd ${updateLatest}`);
|
|
53121
|
-
|
|
53122
|
-
return line.length <= 80 ? line : `${line.slice(0, 79)}\u2026`;
|
|
53238
|
+
return truncate(parts.join(" \xB7 "), 80);
|
|
53123
53239
|
}
|
|
53124
53240
|
function formatSessionWidget(stats, current, hub, ship, updateLatest, cost) {
|
|
53125
|
-
const
|
|
53126
|
-
const
|
|
53127
|
-
|
|
53128
|
-
|
|
53241
|
+
const suffix = hub?.scope === "remote" ? "/remote" : "";
|
|
53242
|
+
const hubMark = hub?.state === "on" || hub?.state === void 0 && hub?.online === true ? `hub:on${suffix}` : hub?.state === "off" || hub?.state === void 0 && hub?.online === false ? `hub:off${suffix}` : hub?.state === "unknown" ? `hub:unknown${suffix}` : void 0;
|
|
53243
|
+
const summary = ["KXM", hubMark];
|
|
53244
|
+
if (stats.activeTasks > 0) summary.push(`${stats.activeTasks} task${stats.activeTasks === 1 ? "" : "s"}`);
|
|
53245
|
+
if (stats.waitingTasks > 0) summary.push(`${stats.waitingTasks} waiting`);
|
|
53246
|
+
if (stats.planCount > 0) summary.push(`${stats.planCount} plan${stats.planCount === 1 ? "" : "s"}`);
|
|
53247
|
+
if (stats.inbox > 0) summary.push(`inbox ${stats.inbox}`);
|
|
53248
|
+
const lines = [summary.filter(Boolean).join(" \xB7 ")];
|
|
53129
53249
|
if (current) lines.push(`now ${current.kind} ${truncate(current.detail, 56)}`);
|
|
53130
|
-
else if (stats.latestPlan) lines.push(`plan
|
|
53131
|
-
|
|
53132
|
-
lines.push(
|
|
53133
|
-
if (cost) lines.push(`cost ${cost}`);
|
|
53250
|
+
else if (stats.latestPlan) lines.push(`plan ${truncate(stats.latestPlan, 60)}`);
|
|
53251
|
+
if (ship?.dirty || ship && ship.ahead > 0) lines.push(formatShipLine(ship));
|
|
53252
|
+
if (cost && cost !== "unknown") lines.push(`cost ${cost}`);
|
|
53134
53253
|
if (updateLatest) lines.push(`update ${updateLatest} available \xB7 kxm update --kxm`);
|
|
53135
53254
|
return lines;
|
|
53136
53255
|
}
|
|
@@ -53150,7 +53269,7 @@ function buildSessionBrief(snapshot, current, hub, ship, updateLatest, cost, ses
|
|
|
53150
53269
|
const tasks = uniqueLabels(recentTasks(snapshot.runs).map(taskItem));
|
|
53151
53270
|
const plans = uniqueLabels(snapshot.plans.slice(0, MAX_SESSION_BRIEF_PLANS).map(planItem));
|
|
53152
53271
|
const resolvedHub = hub ?? { state: "off", evidence: "unconfigured", online: false };
|
|
53153
|
-
const statusLine = formatSessionStatusLine(stats, current, resolvedHub, ship, updateLatest
|
|
53272
|
+
const statusLine = formatSessionStatusLine(stats, current, resolvedHub, ship, updateLatest);
|
|
53154
53273
|
const widgetLines = formatSessionWidget(stats, current, resolvedHub, ship, updateLatest, cost);
|
|
53155
53274
|
return {
|
|
53156
53275
|
schema: SESSION_BRIEF_SCHEMA,
|
|
@@ -53168,10 +53287,10 @@ function buildSessionBrief(snapshot, current, hub, ship, updateLatest, cost, ses
|
|
|
53168
53287
|
};
|
|
53169
53288
|
}
|
|
53170
53289
|
function readCachedSessionBrief(stateDir) {
|
|
53171
|
-
const file =
|
|
53290
|
+
const file = join48(stateDir, "session-brief.json");
|
|
53172
53291
|
try {
|
|
53173
|
-
if (!
|
|
53174
|
-
const raw =
|
|
53292
|
+
if (!existsSync38(file)) return void 0;
|
|
53293
|
+
const raw = readFileSync34(file, "utf8");
|
|
53175
53294
|
const parsed = JSON.parse(raw);
|
|
53176
53295
|
if (parsed && parsed.schema === "kxm.session-brief.v1" && typeof parsed.generatedAt === "string") {
|
|
53177
53296
|
const ageMs = Date.now() - Date.parse(parsed.generatedAt);
|
|
@@ -53187,7 +53306,7 @@ function readCachedSessionBrief(stateDir) {
|
|
|
53187
53306
|
function writeCachedSessionBrief(stateDir, brief) {
|
|
53188
53307
|
try {
|
|
53189
53308
|
mkdirSync28(stateDir, { recursive: true, mode: 448 });
|
|
53190
|
-
const file =
|
|
53309
|
+
const file = join48(stateDir, "session-brief.json");
|
|
53191
53310
|
const tmp = `${file}.tmp.${randomUUID13().slice(0, 8)}`;
|
|
53192
53311
|
writeFileSync24(tmp, JSON.stringify(brief, null, 2), { encoding: "utf8", mode: 384 });
|
|
53193
53312
|
renameSync9(tmp, file);
|
|
@@ -53196,8 +53315,8 @@ function writeCachedSessionBrief(stateDir, brief) {
|
|
|
53196
53315
|
}
|
|
53197
53316
|
function estimateSessionCost(stateDir) {
|
|
53198
53317
|
try {
|
|
53199
|
-
const telemetryFile =
|
|
53200
|
-
if (!
|
|
53318
|
+
const telemetryFile = join48(stateDir, "telemetry.jsonl");
|
|
53319
|
+
if (!existsSync38(telemetryFile)) return void 0;
|
|
53201
53320
|
const records = readRoutingRecords(telemetryFile);
|
|
53202
53321
|
if (records.length === 0) return void 0;
|
|
53203
53322
|
let totalCost = 0;
|
|
@@ -53214,7 +53333,7 @@ function estimateSessionCost(stateDir) {
|
|
|
53214
53333
|
latestModel = r.effectiveModel ?? r.requestedModel ?? latestModel;
|
|
53215
53334
|
latestHarness = r.harness ?? latestHarness;
|
|
53216
53335
|
}
|
|
53217
|
-
if (!hasMetered) return
|
|
53336
|
+
if (!hasMetered) return void 0;
|
|
53218
53337
|
const route = latestHarness && latestModel ? `${latestHarness}/${latestModel}` : latestModel;
|
|
53219
53338
|
return `$${totalCost.toFixed(2)} sess${route ? ` \xB7 ${route}` : ""}`;
|
|
53220
53339
|
} catch {
|
|
@@ -53251,8 +53370,7 @@ function loadSessionBrief(cwd, env = process.env, current, hub, options = {}) {
|
|
|
53251
53370
|
current,
|
|
53252
53371
|
effectiveHub,
|
|
53253
53372
|
options.ship,
|
|
53254
|
-
options.updateLatest
|
|
53255
|
-
effectiveCost
|
|
53373
|
+
options.updateLatest
|
|
53256
53374
|
);
|
|
53257
53375
|
const widgetLines = formatSessionWidget(
|
|
53258
53376
|
cached.stats,
|
|
@@ -53317,8 +53435,7 @@ async function loadSessionBriefAsync(cwd, env = process.env, current, hub, optio
|
|
|
53317
53435
|
current,
|
|
53318
53436
|
effectiveHub,
|
|
53319
53437
|
options.ship,
|
|
53320
|
-
void 0
|
|
53321
|
-
effectiveCost
|
|
53438
|
+
void 0
|
|
53322
53439
|
);
|
|
53323
53440
|
const widgetLines = formatSessionWidget(
|
|
53324
53441
|
cached.stats,
|
|
@@ -53369,16 +53486,16 @@ init_hub_binding();
|
|
|
53369
53486
|
|
|
53370
53487
|
// plugins/kxm/src/kxm-install-kind.ts
|
|
53371
53488
|
init_bindings();
|
|
53372
|
-
import { existsSync as
|
|
53373
|
-
import { dirname as dirname21, join as
|
|
53489
|
+
import { existsSync as existsSync39, readFileSync as readFileSync35 } from "node:fs";
|
|
53490
|
+
import { dirname as dirname21, join as join49 } from "node:path";
|
|
53374
53491
|
function kxmSourceCheckoutRoot(dir) {
|
|
53375
|
-
if (!
|
|
53492
|
+
if (!existsSync39(join49(dir, ".git"))) return void 0;
|
|
53376
53493
|
if (!packageIsKxm(dir)) return void 0;
|
|
53377
53494
|
return dir;
|
|
53378
53495
|
}
|
|
53379
53496
|
function packageIsKxm(root) {
|
|
53380
53497
|
try {
|
|
53381
|
-
const pkg = JSON.parse(
|
|
53498
|
+
const pkg = JSON.parse(readFileSync35(join49(root, "package.json"), "utf8"));
|
|
53382
53499
|
return pkg.name === "@kontextmind/kxm";
|
|
53383
53500
|
} catch {
|
|
53384
53501
|
return false;
|
|
@@ -53427,12 +53544,12 @@ function report(kind, root) {
|
|
|
53427
53544
|
return { kind, root, instruction: installKindInstruction(kind, root) };
|
|
53428
53545
|
}
|
|
53429
53546
|
function classifyInstallRoot(probe) {
|
|
53430
|
-
const piGitRoot =
|
|
53547
|
+
const piGitRoot = join49(probe.homeDir, ".pi", "agent", "git");
|
|
53431
53548
|
if (isUnder(probe.repoRoot, piGitRoot, probe.platform)) return report("pi-git", probe.repoRoot);
|
|
53432
|
-
const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() ||
|
|
53433
|
-
const pluginsRoot =
|
|
53549
|
+
const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() || join49(probe.homeDir, ".claude");
|
|
53550
|
+
const pluginsRoot = join49(claudeHome, "plugins");
|
|
53434
53551
|
if (isUnder(probe.moduleDir, pluginsRoot, probe.platform)) return report("claude-marketplace", probe.moduleDir);
|
|
53435
|
-
const hasGit =
|
|
53552
|
+
const hasGit = existsSync39(join49(probe.repoRoot, ".git"));
|
|
53436
53553
|
if (hasGit && packageIsKxm(probe.repoRoot)) return report("source", probe.repoRoot);
|
|
53437
53554
|
if (isNpmPackageLayout(probe.repoRoot, probe.platform) && packageIsKxm(probe.repoRoot) && !hasGit) {
|
|
53438
53555
|
return report("npm-package", probe.repoRoot);
|
|
@@ -53455,16 +53572,16 @@ function resolveInstallKind(probe, npmGlobalRoot) {
|
|
|
53455
53572
|
init_bindings();
|
|
53456
53573
|
|
|
53457
53574
|
// plugins/kxm/src/kxm-update-config.ts
|
|
53458
|
-
var
|
|
53459
|
-
import { existsSync as
|
|
53460
|
-
import { join as
|
|
53575
|
+
var import_yaml20 = __toESM(require_dist(), 1);
|
|
53576
|
+
import { existsSync as existsSync40, readFileSync as readFileSync36 } from "node:fs";
|
|
53577
|
+
import { join as join50 } from "node:path";
|
|
53461
53578
|
init_bindings();
|
|
53462
53579
|
function loadKxmUpdateConfig(env = process.env) {
|
|
53463
|
-
const path4 =
|
|
53464
|
-
if (!
|
|
53580
|
+
const path4 = join50(kxmUserStateRoot({ env }), "update.yaml");
|
|
53581
|
+
if (!existsSync40(path4)) return { schema: KXM_UPDATE_SCHEMA, auto: false, source: "npm" };
|
|
53465
53582
|
let parsed;
|
|
53466
53583
|
try {
|
|
53467
|
-
parsed = (0,
|
|
53584
|
+
parsed = (0, import_yaml20.parse)(readFileSync36(path4, "utf8"));
|
|
53468
53585
|
} catch {
|
|
53469
53586
|
throw new KxmUpdateConfigError("update.yaml is not valid YAML");
|
|
53470
53587
|
}
|
|
@@ -53492,8 +53609,8 @@ function loadKxmUpdateConfig(env = process.env) {
|
|
|
53492
53609
|
// plugins/kxm/src/session.ts
|
|
53493
53610
|
init_protocol();
|
|
53494
53611
|
init_envelope();
|
|
53495
|
-
import { existsSync as
|
|
53496
|
-
import { join as
|
|
53612
|
+
import { existsSync as existsSync41, mkdirSync as mkdirSync29, readFileSync as readFileSync37, writeFileSync as writeFileSync25 } from "node:fs";
|
|
53613
|
+
import { join as join51 } from "node:path";
|
|
53497
53614
|
var SESSION_SCHEMA = "kxm.session.v1";
|
|
53498
53615
|
var SessionConfigError = class extends Error {
|
|
53499
53616
|
code = "session_config_invalid";
|
|
@@ -53503,12 +53620,12 @@ var SessionConfigError = class extends Error {
|
|
|
53503
53620
|
}
|
|
53504
53621
|
};
|
|
53505
53622
|
function workflowAssetDirs(assetsDir, workflowId) {
|
|
53506
|
-
const root =
|
|
53507
|
-
return [root,
|
|
53623
|
+
const root = join51(assetsDir, "workflows", workflowId);
|
|
53624
|
+
return [root, join51(root, "inputs"), join51(root, "outputs"), join51(root, "generated")];
|
|
53508
53625
|
}
|
|
53509
53626
|
function sessionAssetDirs(assetsDir, sessionId) {
|
|
53510
|
-
const root =
|
|
53511
|
-
return [root,
|
|
53627
|
+
const root = join51(assetsDir, "sessions", sessionId);
|
|
53628
|
+
return [root, join51(root, "inputs"), join51(root, "outputs")];
|
|
53512
53629
|
}
|
|
53513
53630
|
function rosterNames(configDir) {
|
|
53514
53631
|
return [...loadRosterMap(configDir).values()].map((row) => String(row.name));
|
|
@@ -53558,7 +53675,7 @@ function workerFromRosterRow(name, row, project) {
|
|
|
53558
53675
|
function loadRosterMap(configDir) {
|
|
53559
53676
|
const byName = /* @__PURE__ */ new Map();
|
|
53560
53677
|
for (const [file, key] of [["agents.json", "agents"], ["gates.json", "gates"]]) {
|
|
53561
|
-
const path4 =
|
|
53678
|
+
const path4 = join51(configDir, file);
|
|
53562
53679
|
for (const row of loadRoster(path4, key)) {
|
|
53563
53680
|
const name = String(row.name).trim();
|
|
53564
53681
|
const lowered = name.toLowerCase();
|
|
@@ -53572,10 +53689,10 @@ function loadRosterMap(configDir) {
|
|
|
53572
53689
|
return byName;
|
|
53573
53690
|
}
|
|
53574
53691
|
function loadRoster(path4, key) {
|
|
53575
|
-
if (!
|
|
53692
|
+
if (!existsSync41(path4)) return [];
|
|
53576
53693
|
let parsed;
|
|
53577
53694
|
try {
|
|
53578
|
-
parsed = JSON.parse(
|
|
53695
|
+
parsed = JSON.parse(readFileSync37(path4, "utf8"));
|
|
53579
53696
|
} catch (error) {
|
|
53580
53697
|
throw new SessionConfigError(
|
|
53581
53698
|
`${key} roster at ${path4} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -53600,7 +53717,7 @@ function loadRoster(path4, key) {
|
|
|
53600
53717
|
});
|
|
53601
53718
|
}
|
|
53602
53719
|
function createSession(input) {
|
|
53603
|
-
const assetDir = input.mode === "workflow" && input.workflowId ?
|
|
53720
|
+
const assetDir = input.mode === "workflow" && input.workflowId ? join51("assets", "workflows", input.workflowId) : join51("assets", "sessions", input.id);
|
|
53604
53721
|
return {
|
|
53605
53722
|
schema: SESSION_SCHEMA,
|
|
53606
53723
|
id: input.id,
|
|
@@ -53613,8 +53730,8 @@ function createSession(input) {
|
|
|
53613
53730
|
};
|
|
53614
53731
|
}
|
|
53615
53732
|
function writeSession(assetsDir, session, dryRun = false) {
|
|
53616
|
-
const dir =
|
|
53617
|
-
const path4 =
|
|
53733
|
+
const dir = join51(assetsDir, "sessions", session.id);
|
|
53734
|
+
const path4 = join51(dir, "session.json");
|
|
53618
53735
|
if (!dryRun) {
|
|
53619
53736
|
mkdirSync29(dir, { recursive: true });
|
|
53620
53737
|
writeFileSync25(path4, `${JSON.stringify(session, null, 2)}
|
|
@@ -53656,9 +53773,9 @@ function moduleInstallRoot() {
|
|
|
53656
53773
|
}
|
|
53657
53774
|
}
|
|
53658
53775
|
function warnIgnoredProjectUpdateYaml(runtime) {
|
|
53659
|
-
const projectFile =
|
|
53660
|
-
if (!
|
|
53661
|
-
const userFile =
|
|
53776
|
+
const projectFile = join52(runtime.dirs.workspace, "update.yaml");
|
|
53777
|
+
if (!existsSync42(projectFile)) return;
|
|
53778
|
+
const userFile = join52(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
53662
53779
|
runtime.io.stderr(`kxm: ignoring .kxm/update.yaml in ${runtime.dirs.workdir}; update settings are read only from ${userFile}
|
|
53663
53780
|
`);
|
|
53664
53781
|
}
|
|
@@ -53742,7 +53859,7 @@ async function cmdDash(runtime, options = {}) {
|
|
|
53742
53859
|
return 2;
|
|
53743
53860
|
}
|
|
53744
53861
|
const screen = requested;
|
|
53745
|
-
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
53862
|
+
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join52(runtime.dirs.state, "kxm.db"));
|
|
53746
53863
|
if (runtime.dryRun) {
|
|
53747
53864
|
print(runtime.io, runtime.json, {
|
|
53748
53865
|
ok: true,
|
|
@@ -53797,7 +53914,7 @@ async function cmdHub(runtime) {
|
|
|
53797
53914
|
config = loadKxmUpdateConfig(runtime.env);
|
|
53798
53915
|
} catch (error) {
|
|
53799
53916
|
if (error instanceof KxmUpdateConfigError) {
|
|
53800
|
-
const yamlPath =
|
|
53917
|
+
const yamlPath = join52(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
53801
53918
|
runtime.io.stderr(`kxm: ${error.message}; update check skipped; fix or remove ${yamlPath}
|
|
53802
53919
|
`);
|
|
53803
53920
|
} else {
|
|
@@ -53952,7 +54069,7 @@ async function cmdHubBind(runtime, rawUrl, options = {}) {
|
|
|
53952
54069
|
...cloudFields
|
|
53953
54070
|
};
|
|
53954
54071
|
const identity = resolveProjectIdentity(runtime.dirs.workdir, runtime.env);
|
|
53955
|
-
const configFile =
|
|
54072
|
+
const configFile = join52(findConfigRoot(runtime.dirs.workdir), ".kxm", "config.yaml");
|
|
53956
54073
|
const key = {
|
|
53957
54074
|
...keyOp ? { op: keyOp } : {},
|
|
53958
54075
|
...tokenEnv ? { env: tokenEnv } : {}
|
|
@@ -54112,7 +54229,7 @@ async function cmdWorker(runtime, options) {
|
|
|
54112
54229
|
return await (runtime.io.spawnWorker ?? ((launchEnv) => spawnScript("kxm-worker.mjs", launchEnv)))(extraEnv);
|
|
54113
54230
|
}
|
|
54114
54231
|
async function cmdStop(runtime, waitMsFlag) {
|
|
54115
|
-
const pids =
|
|
54232
|
+
const pids = existsSync42(runtime.dirs.state) ? readdirSync13(runtime.dirs.state).filter((name) => name.endsWith(".pid")) : [];
|
|
54116
54233
|
if (runtime.dryRun) {
|
|
54117
54234
|
print(runtime.io, runtime.json, { ok: true, command: "stop", dryRun: true, pidFiles: pids }, "would signal pid files");
|
|
54118
54235
|
return 0;
|
|
@@ -54127,7 +54244,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
54127
54244
|
const orphans = [];
|
|
54128
54245
|
for (const file of pids) {
|
|
54129
54246
|
try {
|
|
54130
|
-
const record = JSON.parse(
|
|
54247
|
+
const record = JSON.parse(readFileSync38(join52(runtime.dirs.state, file), "utf8"));
|
|
54131
54248
|
const expectedControl = file === "hub.pid" ? "hub.stop" : file.startsWith("worker-") ? `${file.slice(0, -4)}.stop` : void 0;
|
|
54132
54249
|
const expectedRole = file === "hub.pid" ? "hub" : file.startsWith("worker-") ? "worker" : void 0;
|
|
54133
54250
|
if (record.version !== 1 || !Number.isInteger(record.pid) || record.pid <= 0 || !record.startedAt || !expectedControl || record.controlFile !== expectedControl || record.role !== expectedRole) {
|
|
@@ -54147,7 +54264,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
54147
54264
|
ignored.push(file);
|
|
54148
54265
|
continue;
|
|
54149
54266
|
}
|
|
54150
|
-
writeFileSync26(
|
|
54267
|
+
writeFileSync26(join52(runtime.dirs.state, record.controlFile), `${JSON.stringify({ startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {}, requestedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
54151
54268
|
`, { encoding: "utf8", mode: 384 });
|
|
54152
54269
|
requested.push(file);
|
|
54153
54270
|
records.set(file, { pid: record.pid, startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {} });
|
|
@@ -54165,7 +54282,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
54165
54282
|
while (Date.now() <= deadline && stopped.size < requested.length) {
|
|
54166
54283
|
for (const [file, record] of records) {
|
|
54167
54284
|
try {
|
|
54168
|
-
const current = JSON.parse(
|
|
54285
|
+
const current = JSON.parse(readFileSync38(join52(runtime.dirs.state, file), "utf8"));
|
|
54169
54286
|
if (current.pid !== record.pid || current.startedAt !== record.startedAt || current.generation !== record.generation || !processExists(record.pid)) stopped.add(file);
|
|
54170
54287
|
} catch {
|
|
54171
54288
|
stopped.add(file);
|
|
@@ -54178,7 +54295,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
54178
54295
|
for (const file of orphans) {
|
|
54179
54296
|
while (Date.now() <= deadlineOrphans) {
|
|
54180
54297
|
try {
|
|
54181
|
-
const current = JSON.parse(
|
|
54298
|
+
const current = JSON.parse(readFileSync38(join52(runtime.dirs.state, file), "utf8"));
|
|
54182
54299
|
if (!Number.isInteger(current.serverPid) || !processExists(current.serverPid)) break;
|
|
54183
54300
|
} catch {
|
|
54184
54301
|
break;
|
|
@@ -54186,14 +54303,14 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
54186
54303
|
await (runtime.io.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms))))(100);
|
|
54187
54304
|
}
|
|
54188
54305
|
try {
|
|
54189
|
-
const current = JSON.parse(
|
|
54306
|
+
const current = JSON.parse(readFileSync38(join52(runtime.dirs.state, file), "utf8"));
|
|
54190
54307
|
if (Number.isInteger(current.serverPid) && processExists(current.serverPid)) {
|
|
54191
54308
|
try {
|
|
54192
54309
|
process.kill(current.serverPid, "SIGKILL");
|
|
54193
54310
|
} catch {
|
|
54194
54311
|
}
|
|
54195
54312
|
}
|
|
54196
|
-
rmSync11(
|
|
54313
|
+
rmSync11(join52(runtime.dirs.state, file), { force: true });
|
|
54197
54314
|
} catch {
|
|
54198
54315
|
}
|
|
54199
54316
|
stopped.add(file);
|
|
@@ -54204,11 +54321,11 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
54204
54321
|
}
|
|
54205
54322
|
async function cmdSessionStatus(runtime) {
|
|
54206
54323
|
const stateDir = runtime.dirs.state;
|
|
54207
|
-
const names3 =
|
|
54324
|
+
const names3 = existsSync42(stateDir) ? readdirSync13(stateDir) : [];
|
|
54208
54325
|
const claims = [];
|
|
54209
54326
|
for (const file of names3.filter((name) => name.endsWith(".pid"))) {
|
|
54210
54327
|
try {
|
|
54211
|
-
const record = JSON.parse(
|
|
54328
|
+
const record = JSON.parse(readFileSync38(join52(stateDir, file), "utf8"));
|
|
54212
54329
|
claims.push({
|
|
54213
54330
|
file,
|
|
54214
54331
|
role: record.role,
|
|
@@ -54223,7 +54340,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
54223
54340
|
const recoveries = [];
|
|
54224
54341
|
for (const file of names3.filter((name) => name.startsWith("worker-recovery-") && name.endsWith(".json"))) {
|
|
54225
54342
|
try {
|
|
54226
|
-
const envelope2 = JSON.parse(
|
|
54343
|
+
const envelope2 = JSON.parse(readFileSync38(join52(stateDir, file), "utf8"));
|
|
54227
54344
|
recoveries.push({
|
|
54228
54345
|
file,
|
|
54229
54346
|
reason: envelope2.reason,
|
|
@@ -54249,7 +54366,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
54249
54366
|
async function cmdAuthToken(runtime, options = {}) {
|
|
54250
54367
|
const tokenFile = sessionTokenPath(runtime.env.KXM_USER_CONFIG_DIR);
|
|
54251
54368
|
if (options.clear && runtime.dryRun) {
|
|
54252
|
-
const present =
|
|
54369
|
+
const present = existsSync42(tokenFile);
|
|
54253
54370
|
printPlan(runtime, { command: "auth token", cleared: present }, present ? [{ action: "delete", target: tokenFile }] : [], present ? "clear the session token from disk" : "no session token file to clear");
|
|
54254
54371
|
return 0;
|
|
54255
54372
|
}
|
|
@@ -54338,7 +54455,7 @@ async function cmdSessionBrief(runtime, options = {}) {
|
|
|
54338
54455
|
print(runtime.io, runtime.json, { ok: true, command: "session brief", sessionToken }, sessionToken);
|
|
54339
54456
|
return 0;
|
|
54340
54457
|
}
|
|
54341
|
-
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
54458
|
+
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join52(runtime.dirs.state, "kxm.db"));
|
|
54342
54459
|
const env = {
|
|
54343
54460
|
...runtime.env,
|
|
54344
54461
|
KXM_STATE_DIR: runtime.dirs.state,
|
|
@@ -54364,7 +54481,7 @@ async function cmdSessionBrief(runtime, options = {}) {
|
|
|
54364
54481
|
writeCache: !runtime.dryRun
|
|
54365
54482
|
});
|
|
54366
54483
|
if (runtime.dryRun) {
|
|
54367
|
-
if (!readCachedSessionBrief(runtime.dirs.state)) planned.push({ action: "write", target:
|
|
54484
|
+
if (!readCachedSessionBrief(runtime.dirs.state)) planned.push({ action: "write", target: join52(runtime.dirs.state, "session-brief.json") });
|
|
54368
54485
|
print(runtime.io, runtime.json, { ...brief, dryRun: true, planned }, [
|
|
54369
54486
|
options.status ? brief.statusLine : formatSessionBriefText(brief),
|
|
54370
54487
|
...planned.map((change) => `dry run: would ${change.action} ${change.target}`)
|
|
@@ -54448,9 +54565,9 @@ init_routing();
|
|
|
54448
54565
|
init_prices();
|
|
54449
54566
|
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
54450
54567
|
import { createHash as createHash19 } from "node:crypto";
|
|
54451
|
-
import { existsSync as
|
|
54568
|
+
import { existsSync as existsSync50, mkdtempSync as mkdtempSync3, readFileSync as readFileSync44, rmSync as rmSync13 } from "node:fs";
|
|
54452
54569
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
54453
|
-
import { basename as basename11, extname as extname3, join as
|
|
54570
|
+
import { basename as basename11, extname as extname3, join as join58, resolve as resolve33 } from "node:path";
|
|
54454
54571
|
import { createInterface as createInterface3 } from "node:readline";
|
|
54455
54572
|
|
|
54456
54573
|
// plugins/kxm/src/improve.ts
|
|
@@ -54458,8 +54575,8 @@ init_routing();
|
|
|
54458
54575
|
init_protocol();
|
|
54459
54576
|
init_relevance();
|
|
54460
54577
|
import { createHash as createHash18 } from "node:crypto";
|
|
54461
|
-
import { existsSync as
|
|
54462
|
-
import { join as
|
|
54578
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync31, writeFileSync as writeFileSync27 } from "node:fs";
|
|
54579
|
+
import { join as join53, relative as relative7, resolve as resolve29 } from "node:path";
|
|
54463
54580
|
var CANDIDATE_SCHEMA = "kxm.candidate.v1";
|
|
54464
54581
|
var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
|
|
54465
54582
|
function classifyCandidateKind(stepId, agentRole) {
|
|
@@ -54715,7 +54832,7 @@ function groupRoutingRecords(records, options = {}) {
|
|
|
54715
54832
|
}
|
|
54716
54833
|
function buildImprovementReport(records, options = {}) {
|
|
54717
54834
|
const projectRoot = options.projectRoot ? resolve29(options.projectRoot) : process.cwd();
|
|
54718
|
-
const candidatesDir = options.candidatesDir ? resolve29(options.candidatesDir) :
|
|
54835
|
+
const candidatesDir = options.candidatesDir ? resolve29(options.candidatesDir) : join53(projectRoot, ".kxm", "candidates");
|
|
54719
54836
|
const promotionPolicy = options.promotionPolicy ?? "manual_pr";
|
|
54720
54837
|
const groups = groupRoutingRecords(records, options);
|
|
54721
54838
|
const candidates = [];
|
|
@@ -54729,7 +54846,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
54729
54846
|
group.workflowId
|
|
54730
54847
|
);
|
|
54731
54848
|
const diffFileName = `${group.candidateId}.diff`;
|
|
54732
|
-
const diffFilePath =
|
|
54849
|
+
const diffFilePath = join53(candidatesDir, diffFileName);
|
|
54733
54850
|
const relDiffPath = relative7(projectRoot, diffFilePath).replace(/\\/g, "/");
|
|
54734
54851
|
const candidate = {
|
|
54735
54852
|
schema: CANDIDATE_SCHEMA,
|
|
@@ -54751,11 +54868,11 @@ function buildImprovementReport(records, options = {}) {
|
|
|
54751
54868
|
createdAt: nowIso()
|
|
54752
54869
|
};
|
|
54753
54870
|
if (!options.dryRun) {
|
|
54754
|
-
if (!
|
|
54871
|
+
if (!existsSync43(candidatesDir)) {
|
|
54755
54872
|
mkdirSync31(candidatesDir, { recursive: true });
|
|
54756
54873
|
}
|
|
54757
54874
|
writeFileSync27(diffFilePath, diff, "utf8");
|
|
54758
|
-
const jsonFilePath =
|
|
54875
|
+
const jsonFilePath = join53(candidatesDir, `${group.candidateId}.json`);
|
|
54759
54876
|
writeFileSync27(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
|
|
54760
54877
|
}
|
|
54761
54878
|
candidates.push(candidate);
|
|
@@ -54786,7 +54903,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
54786
54903
|
}
|
|
54787
54904
|
function writeImprovementReport(improvementsDir, report2, dryRun = false) {
|
|
54788
54905
|
const stamp = report2.createdAt.replace(/[:.]/g, "-");
|
|
54789
|
-
const path4 =
|
|
54906
|
+
const path4 = join53(improvementsDir, `${stamp}.json`);
|
|
54790
54907
|
if (!dryRun) {
|
|
54791
54908
|
mkdirSync31(improvementsDir, { recursive: true });
|
|
54792
54909
|
writeFileSync27(path4, `${JSON.stringify(report2, null, 2)}
|
|
@@ -54879,7 +54996,7 @@ init_runtime_store();
|
|
|
54879
54996
|
init_route_switch();
|
|
54880
54997
|
init_routing();
|
|
54881
54998
|
init_telemetry();
|
|
54882
|
-
import { existsSync as
|
|
54999
|
+
import { existsSync as existsSync44 } from "node:fs";
|
|
54883
55000
|
import { resolve as resolve30 } from "node:path";
|
|
54884
55001
|
var ENGINE_EVENTS_SQL = "SELECT run_id, sequence, event_type, payload FROM events WHERE event_type IN ('routing.attempt.recorded','routing.route_switched','step.entered','run.status_changed') ORDER BY run_id, sequence";
|
|
54885
55002
|
var SIMULATED_HARNESS = "driver-simulated";
|
|
@@ -54902,7 +55019,7 @@ function readEngineRoutingRecords(path4) {
|
|
|
54902
55019
|
undecided: 0,
|
|
54903
55020
|
duplicatesDropped: 0
|
|
54904
55021
|
};
|
|
54905
|
-
if (!
|
|
55022
|
+
if (!existsSync44(path4)) return { records: [], source, routeSwitches: [] };
|
|
54906
55023
|
source.exists = true;
|
|
54907
55024
|
let rows;
|
|
54908
55025
|
let database;
|
|
@@ -54988,7 +55105,7 @@ function readEngineRoutingRecords(path4) {
|
|
|
54988
55105
|
};
|
|
54989
55106
|
}
|
|
54990
55107
|
function readJsonlSource(kind, path4) {
|
|
54991
|
-
const exists =
|
|
55108
|
+
const exists = existsSync44(path4);
|
|
54992
55109
|
const records = exists ? readRoutingRecords(path4).map((entry) => entry.routing) : [];
|
|
54993
55110
|
return { records, source: { kind, path: path4, exists, records: records.length, duplicatesDropped: 0 } };
|
|
54994
55111
|
}
|
|
@@ -55032,10 +55149,10 @@ function loadRoutingSources(options) {
|
|
|
55032
55149
|
}
|
|
55033
55150
|
|
|
55034
55151
|
// plugins/kxm/src/modes.ts
|
|
55035
|
-
var
|
|
55152
|
+
var import_yaml21 = __toESM(require_dist(), 1);
|
|
55036
55153
|
init_prices();
|
|
55037
|
-
import { existsSync as
|
|
55038
|
-
import { join as
|
|
55154
|
+
import { existsSync as existsSync45, readFileSync as readFileSync40 } from "node:fs";
|
|
55155
|
+
import { join as join54 } from "node:path";
|
|
55039
55156
|
var DEFAULT_MODES_CONFIG = Object.freeze({
|
|
55040
55157
|
schema: "kxm.modes.v1",
|
|
55041
55158
|
majorModes: {
|
|
@@ -55098,13 +55215,13 @@ function loadModesConfig(projectRoot) {
|
|
|
55098
55215
|
if (!projectRoot) {
|
|
55099
55216
|
return DEFAULT_MODES_CONFIG;
|
|
55100
55217
|
}
|
|
55101
|
-
const modesPath =
|
|
55102
|
-
if (!
|
|
55218
|
+
const modesPath = join54(projectRoot, ".kxm", "modes.yaml");
|
|
55219
|
+
if (!existsSync45(modesPath)) {
|
|
55103
55220
|
return DEFAULT_MODES_CONFIG;
|
|
55104
55221
|
}
|
|
55105
55222
|
try {
|
|
55106
|
-
const raw =
|
|
55107
|
-
const parsed = (0,
|
|
55223
|
+
const raw = readFileSync40(modesPath, "utf8");
|
|
55224
|
+
const parsed = (0, import_yaml21.parse)(raw);
|
|
55108
55225
|
if (parsed && parsed.schema === "kxm.modes.v1" && parsed.majorModes) {
|
|
55109
55226
|
return {
|
|
55110
55227
|
schema: "kxm.modes.v1",
|
|
@@ -55189,11 +55306,11 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
|
|
|
55189
55306
|
estimatedTokens: estimateTokens(baseSystemPromptChars)
|
|
55190
55307
|
});
|
|
55191
55308
|
for (const relPath of resolved.contextFiles) {
|
|
55192
|
-
const fullPath =
|
|
55309
|
+
const fullPath = join54(projectRoot, relPath);
|
|
55193
55310
|
let chars = 0;
|
|
55194
|
-
if (
|
|
55311
|
+
if (existsSync45(fullPath)) {
|
|
55195
55312
|
try {
|
|
55196
|
-
chars =
|
|
55313
|
+
chars = readFileSync40(fullPath, "utf8").length;
|
|
55197
55314
|
} catch {
|
|
55198
55315
|
chars = 0;
|
|
55199
55316
|
}
|
|
@@ -55326,9 +55443,9 @@ ${divider}
|
|
|
55326
55443
|
// plugins/kxm/src/ssh-remote.ts
|
|
55327
55444
|
init_safety_integrity();
|
|
55328
55445
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
55329
|
-
import { existsSync as
|
|
55446
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync32, readFileSync as readFileSync41, readdirSync as readdirSync14, rmSync as rmSync12, statSync as statSync7 } from "node:fs";
|
|
55330
55447
|
import { homedir as homedir8 } from "node:os";
|
|
55331
|
-
import { join as
|
|
55448
|
+
import { join as join55, resolve as resolve31 } from "node:path";
|
|
55332
55449
|
var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
|
|
55333
55450
|
var MAX_SSH_OUTPUT_LINES = 2e3;
|
|
55334
55451
|
var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
|
|
@@ -55354,12 +55471,12 @@ function truncateSshOutput(raw) {
|
|
|
55354
55471
|
return { text, truncated };
|
|
55355
55472
|
}
|
|
55356
55473
|
function parseSshConfig(configPath) {
|
|
55357
|
-
const targetPath = configPath ??
|
|
55358
|
-
if (!
|
|
55474
|
+
const targetPath = configPath ?? join55(homedir8(), ".ssh", "config");
|
|
55475
|
+
if (!existsSync46(targetPath)) {
|
|
55359
55476
|
return [];
|
|
55360
55477
|
}
|
|
55361
55478
|
try {
|
|
55362
|
-
const content =
|
|
55479
|
+
const content = readFileSync41(targetPath, "utf-8");
|
|
55363
55480
|
const lines = content.split("\n");
|
|
55364
55481
|
const hosts = [];
|
|
55365
55482
|
let currentHosts = [];
|
|
@@ -55437,14 +55554,14 @@ function resolveSshHostG(host, execFn = spawnSync14) {
|
|
|
55437
55554
|
}
|
|
55438
55555
|
function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
|
|
55439
55556
|
const resolved = resolve31(socketDir);
|
|
55440
|
-
if (!
|
|
55557
|
+
if (!existsSync46(resolved)) {
|
|
55441
55558
|
mkdirSync32(resolved, { recursive: true, mode: 448 });
|
|
55442
55559
|
}
|
|
55443
55560
|
return resolved;
|
|
55444
55561
|
}
|
|
55445
55562
|
function buildSshArgs(options) {
|
|
55446
55563
|
const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
|
|
55447
|
-
const controlPath =
|
|
55564
|
+
const controlPath = join55(socketDir, "%C");
|
|
55448
55565
|
const persist = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
|
|
55449
55566
|
const args = [
|
|
55450
55567
|
"-o",
|
|
@@ -55469,7 +55586,7 @@ function buildSshArgs(options) {
|
|
|
55469
55586
|
}
|
|
55470
55587
|
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync14) {
|
|
55471
55588
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
55472
|
-
const controlPath =
|
|
55589
|
+
const controlPath = join55(resolvedDir, "%C");
|
|
55473
55590
|
try {
|
|
55474
55591
|
const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
|
|
55475
55592
|
encoding: "utf-8"
|
|
@@ -55481,7 +55598,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
55481
55598
|
}
|
|
55482
55599
|
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync14) {
|
|
55483
55600
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
55484
|
-
const controlPath =
|
|
55601
|
+
const controlPath = join55(resolvedDir, "%C");
|
|
55485
55602
|
try {
|
|
55486
55603
|
const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
|
|
55487
55604
|
encoding: "utf-8"
|
|
@@ -55694,8 +55811,8 @@ function executeSshRun(params) {
|
|
|
55694
55811
|
init_config();
|
|
55695
55812
|
|
|
55696
55813
|
// plugins/kxm/src/config-editor.ts
|
|
55697
|
-
var
|
|
55698
|
-
import { existsSync as
|
|
55814
|
+
var import_yaml22 = __toESM(require_dist(), 1);
|
|
55815
|
+
import { existsSync as existsSync47, readFileSync as readFileSync42 } from "node:fs";
|
|
55699
55816
|
init_config();
|
|
55700
55817
|
var KXM_CONFIG_EDITOR_SOURCE = "kxm/config";
|
|
55701
55818
|
var INTEGER_TEXT = /^(0|[1-9][0-9]*)$/;
|
|
@@ -55945,8 +56062,8 @@ function parseEditorValue(field, raw) {
|
|
|
55945
56062
|
return parsed;
|
|
55946
56063
|
}
|
|
55947
56064
|
function readScopeDocument(file) {
|
|
55948
|
-
if (!
|
|
55949
|
-
const parsed = (0,
|
|
56065
|
+
if (!existsSync47(file)) return void 0;
|
|
56066
|
+
const parsed = (0, import_yaml22.parse)(readFileSync42(file, "utf8"));
|
|
55950
56067
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
55951
56068
|
throw new KxmConfigEditorError(`config file ${file} must be a mapping`);
|
|
55952
56069
|
}
|
|
@@ -56230,9 +56347,9 @@ complete -c kxm -n "__fish_seen_subcommand_from goal" -a "create list get"
|
|
|
56230
56347
|
}
|
|
56231
56348
|
|
|
56232
56349
|
// plugins/kxm/src/completion-install.ts
|
|
56233
|
-
import { existsSync as
|
|
56350
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync33, readFileSync as readFileSync43, writeFileSync as writeFileSync28 } from "node:fs";
|
|
56234
56351
|
import { homedir as homedir9 } from "node:os";
|
|
56235
|
-
import { basename as basename10, delimiter, dirname as dirname24, isAbsolute as
|
|
56352
|
+
import { basename as basename10, delimiter, dirname as dirname24, isAbsolute as isAbsolute12, join as join56, resolve as resolve32 } from "node:path";
|
|
56236
56353
|
var COMPLETION_MARKER = "# kxm completion";
|
|
56237
56354
|
var PATH_MARKER = "# kxm path";
|
|
56238
56355
|
function detectShell(env = process.env, platform = process.platform) {
|
|
@@ -56254,25 +56371,25 @@ function completionScriptPath(shell, options = {}) {
|
|
|
56254
56371
|
const env = options.env ?? process.env;
|
|
56255
56372
|
const explicit = options.configDir ?? env.KXM_USER_CONFIG_DIR?.trim();
|
|
56256
56373
|
const base = explicit && explicit.length > 0 ? resolve32(explicit) : resolve32(effectiveHome(options), ".config", "kxm");
|
|
56257
|
-
return
|
|
56374
|
+
return join56(base, "completions", `kxm.${shell}`);
|
|
56258
56375
|
}
|
|
56259
56376
|
function bashRcCandidate(options) {
|
|
56260
56377
|
const home = effectiveHome(options);
|
|
56261
|
-
const candidates = [
|
|
56262
|
-
const existing = candidates.find((candidate) =>
|
|
56378
|
+
const candidates = [join56(home, ".bashrc"), join56(home, ".bash_profile")];
|
|
56379
|
+
const existing = candidates.find((candidate) => existsSync48(candidate));
|
|
56263
56380
|
return existing ?? candidates[0];
|
|
56264
56381
|
}
|
|
56265
56382
|
function zshRcCandidate(options) {
|
|
56266
56383
|
const env = options.env ?? process.env;
|
|
56267
56384
|
const home = effectiveHome(options);
|
|
56268
|
-
if (env.ZDOTDIR?.trim()) return
|
|
56269
|
-
return
|
|
56385
|
+
if (env.ZDOTDIR?.trim()) return join56(resolve32(env.ZDOTDIR.trim()), ".zshrc");
|
|
56386
|
+
return join56(home, ".zshrc");
|
|
56270
56387
|
}
|
|
56271
56388
|
function fishCompletionTarget(shell, options) {
|
|
56272
56389
|
const env = options.env ?? process.env;
|
|
56273
56390
|
const home = effectiveHome(options);
|
|
56274
|
-
if (env.XDG_CONFIG_HOME?.trim()) return
|
|
56275
|
-
return
|
|
56391
|
+
if (env.XDG_CONFIG_HOME?.trim()) return join56(resolve32(env.XDG_CONFIG_HOME.trim()), "fish", "completions", "kxm.fish");
|
|
56392
|
+
return join56(home, ".config", "fish", "completions", "kxm.fish");
|
|
56276
56393
|
}
|
|
56277
56394
|
function completionRcTarget(shell, options = {}) {
|
|
56278
56395
|
if (shell === "fish") {
|
|
@@ -56304,13 +56421,13 @@ function installShellCompletion(shellInput, options = {}) {
|
|
|
56304
56421
|
const scriptPath = completionScriptPath(shell, options);
|
|
56305
56422
|
const { rcFile } = completionRcTarget(shell, options);
|
|
56306
56423
|
const script = generateShellCompletion(shell);
|
|
56307
|
-
const existingScript =
|
|
56308
|
-
const existingScriptMatches = existingScript &&
|
|
56424
|
+
const existingScript = existsSync48(scriptPath);
|
|
56425
|
+
const existingScriptMatches = existingScript && readFileSync43(scriptPath, "utf8") === script;
|
|
56309
56426
|
let rcModified = false;
|
|
56310
56427
|
let alreadyInstalled = false;
|
|
56311
56428
|
if (shell === "fish") {
|
|
56312
56429
|
const fishTarget = fishCompletionTarget(shell, options);
|
|
56313
|
-
const fishInstalled =
|
|
56430
|
+
const fishInstalled = existsSync48(fishTarget) && readFileSync43(fishTarget, "utf8") === script;
|
|
56314
56431
|
alreadyInstalled = fishInstalled;
|
|
56315
56432
|
if (!options.dryRun && (!fishInstalled || options.overwrite)) {
|
|
56316
56433
|
mkdirSync33(resolve32(fishTarget, ".."), { recursive: true });
|
|
@@ -56327,7 +56444,7 @@ function installShellCompletion(shellInput, options = {}) {
|
|
|
56327
56444
|
}
|
|
56328
56445
|
if (rcFile) {
|
|
56329
56446
|
const line = sourceLine(shell, scriptPath);
|
|
56330
|
-
const rcContent =
|
|
56447
|
+
const rcContent = existsSync48(rcFile) ? readFileSync43(rcFile, "utf8") : "";
|
|
56331
56448
|
alreadyInstalled = rcContent.includes(line) || rcContent.includes(`${COMPLETION_MARKER}`);
|
|
56332
56449
|
}
|
|
56333
56450
|
if (!options.dryRun) {
|
|
@@ -56343,7 +56460,7 @@ ${marker}
|
|
|
56343
56460
|
${line}
|
|
56344
56461
|
`;
|
|
56345
56462
|
mkdirSync33(resolve32(rcFile, ".."), { recursive: true });
|
|
56346
|
-
writeFileSync28(rcFile, (
|
|
56463
|
+
writeFileSync28(rcFile, (existsSync48(rcFile) ? readFileSync43(rcFile, "utf8") : "") + stanza, { encoding: "utf8" });
|
|
56347
56464
|
rcModified = true;
|
|
56348
56465
|
}
|
|
56349
56466
|
}
|
|
@@ -56358,15 +56475,15 @@ ${line}
|
|
|
56358
56475
|
}
|
|
56359
56476
|
function kxmBinDir(env = process.env) {
|
|
56360
56477
|
const argv1 = env.KXM_ENTRY ?? process.argv[1];
|
|
56361
|
-
if (argv1 &&
|
|
56478
|
+
if (argv1 && isAbsolute12(argv1)) {
|
|
56362
56479
|
const dir = dirname24(argv1);
|
|
56363
|
-
if (
|
|
56480
|
+
if (existsSync48(join56(dir, process.platform === "win32" ? "kxm.cmd" : "kxm"))) return dir;
|
|
56364
56481
|
}
|
|
56365
56482
|
const pathEnv = env.PATH ?? "";
|
|
56366
56483
|
for (const part of pathEnv.split(delimiter)) {
|
|
56367
56484
|
if (!part) continue;
|
|
56368
56485
|
const candidate = resolve32(part, process.platform === "win32" ? "kxm.cmd" : "kxm");
|
|
56369
|
-
if (
|
|
56486
|
+
if (existsSync48(candidate)) return resolve32(part);
|
|
56370
56487
|
}
|
|
56371
56488
|
return void 0;
|
|
56372
56489
|
}
|
|
@@ -56384,7 +56501,7 @@ function installPathEntry(shellInput, options = {}) {
|
|
|
56384
56501
|
}
|
|
56385
56502
|
const { rcFile } = completionRcTarget(shell, options);
|
|
56386
56503
|
const line = pathLine(binDir);
|
|
56387
|
-
const rcContent =
|
|
56504
|
+
const rcContent = existsSync48(rcFile ?? "") ? readFileSync43(rcFile, "utf8") : "";
|
|
56388
56505
|
const alreadyInstalled = rcContent.includes(binDir) || (options.env?.PATH ?? process.env.PATH ?? "").split(delimiter).includes(binDir);
|
|
56389
56506
|
if (!options.dryRun && rcFile && !alreadyInstalled) {
|
|
56390
56507
|
mkdirSync33(dirname24(rcFile), { recursive: true });
|
|
@@ -56397,10 +56514,10 @@ ${line}
|
|
|
56397
56514
|
}
|
|
56398
56515
|
|
|
56399
56516
|
// plugins/kxm/src/init-guide-setup.ts
|
|
56400
|
-
var
|
|
56517
|
+
var import_yaml23 = __toESM(require_dist(), 1);
|
|
56401
56518
|
init_routes();
|
|
56402
|
-
import { existsSync as
|
|
56403
|
-
import { dirname as dirname25, join as
|
|
56519
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync34, writeFileSync as writeFileSync29 } from "node:fs";
|
|
56520
|
+
import { dirname as dirname25, join as join57 } from "node:path";
|
|
56404
56521
|
var ADMITTED_GUIDE_BINDINGS = Object.freeze({
|
|
56405
56522
|
"anthropic/claude-fable-5.1": { harness: "claude", provider: "anthropic", model: "fable" },
|
|
56406
56523
|
"anthropic/fable": { harness: "claude", provider: "anthropic", model: "fable" },
|
|
@@ -56831,8 +56948,8 @@ function renderGuideSetupFiles(projectRoot, plan) {
|
|
|
56831
56948
|
const piMatch = binding.harness === "pi" && guidePiNoteMatches(binding);
|
|
56832
56949
|
if (binding.harness === "pi" && !piMatch) {
|
|
56833
56950
|
files.push({
|
|
56834
|
-
path:
|
|
56835
|
-
content: (0,
|
|
56951
|
+
path: join57(projectRoot, ".kxm", "agents", `${role}.yaml`),
|
|
56952
|
+
content: (0, import_yaml23.stringify)(agentDocument(role, stage))
|
|
56836
56953
|
});
|
|
56837
56954
|
continue;
|
|
56838
56955
|
}
|
|
@@ -56849,23 +56966,23 @@ function renderGuideSetupFiles(projectRoot, plan) {
|
|
|
56849
56966
|
modelDocument.origin = { source: GUIDE_PI_EVIDENCE_SOURCE, sha256: GUIDE_PI_EVIDENCE_SHA256 };
|
|
56850
56967
|
if (!evidenceQueued) {
|
|
56851
56968
|
files.push({
|
|
56852
|
-
path:
|
|
56969
|
+
path: join57(projectRoot, GUIDE_PI_EVIDENCE_SOURCE),
|
|
56853
56970
|
content: GUIDE_PI_EVIDENCE_NOTE
|
|
56854
56971
|
});
|
|
56855
56972
|
evidenceQueued = true;
|
|
56856
56973
|
}
|
|
56857
56974
|
}
|
|
56858
56975
|
files.push({
|
|
56859
|
-
path:
|
|
56860
|
-
content: (0,
|
|
56976
|
+
path: join57(projectRoot, ".kxm", "agents", `${role}.yaml`),
|
|
56977
|
+
content: (0, import_yaml23.stringify)(agentDocument(role, stage))
|
|
56861
56978
|
});
|
|
56862
56979
|
files.push({
|
|
56863
|
-
path:
|
|
56864
|
-
content: (0,
|
|
56980
|
+
path: join57(projectRoot, ".kxm", "models", `${routeId2}.yaml`),
|
|
56981
|
+
content: (0, import_yaml23.stringify)(modelDocument)
|
|
56865
56982
|
});
|
|
56866
56983
|
files.push({
|
|
56867
|
-
path:
|
|
56868
|
-
content: (0,
|
|
56984
|
+
path: join57(projectRoot, ".kxm", "roles", `${role}.yaml`),
|
|
56985
|
+
content: (0, import_yaml23.stringify)({
|
|
56869
56986
|
schema: "kxm.role.v2",
|
|
56870
56987
|
id: role,
|
|
56871
56988
|
purpose: writer ? "writer" : "experiment",
|
|
@@ -56877,8 +56994,8 @@ function renderGuideSetupFiles(projectRoot, plan) {
|
|
|
56877
56994
|
}
|
|
56878
56995
|
for (const workflow of plan.workflows) {
|
|
56879
56996
|
files.push({
|
|
56880
|
-
path:
|
|
56881
|
-
content: (0,
|
|
56997
|
+
path: join57(projectRoot, ".kxm", "workflows", `${workflow.slug}.yaml`),
|
|
56998
|
+
content: (0, import_yaml23.stringify)(workflowDocument(workflow))
|
|
56882
56999
|
});
|
|
56883
57000
|
}
|
|
56884
57001
|
return files;
|
|
@@ -56894,16 +57011,16 @@ function mergeGuideRouteAdmission(projectRoot, plan) {
|
|
|
56894
57011
|
}
|
|
56895
57012
|
if (added.length === 0) return added;
|
|
56896
57013
|
policy.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
56897
|
-
const path4 =
|
|
57014
|
+
const path4 = join57(projectRoot, ".kxm", "routes.yaml");
|
|
56898
57015
|
mkdirSync34(dirname25(path4), { recursive: true });
|
|
56899
|
-
writeFileSync29(path4, (0,
|
|
57016
|
+
writeFileSync29(path4, (0, import_yaml23.stringify)(policy), "utf8");
|
|
56900
57017
|
return added;
|
|
56901
57018
|
}
|
|
56902
57019
|
function writeGuideSetupFiles(files) {
|
|
56903
57020
|
const written = [];
|
|
56904
57021
|
const existed = [];
|
|
56905
57022
|
for (const file of files) {
|
|
56906
|
-
if (
|
|
57023
|
+
if (existsSync49(file.path)) {
|
|
56907
57024
|
existed.push(file.path);
|
|
56908
57025
|
continue;
|
|
56909
57026
|
}
|
|
@@ -56974,7 +57091,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
56974
57091
|
detail: `release v${notice.latest} has no sha256 digest for ${name}; refusing to install`
|
|
56975
57092
|
};
|
|
56976
57093
|
}
|
|
56977
|
-
const releaseDir = mkdtempSync3(
|
|
57094
|
+
const releaseDir = mkdtempSync3(join58(tmpdir3(), "kxm-pkg-update-"));
|
|
56978
57095
|
try {
|
|
56979
57096
|
const downloader = notice.source === "github" && !ghReleaseDownloadAvailable(runtime.env) ? "curl" : "gh";
|
|
56980
57097
|
const planned = planKxmPackageUpdate(notice.source, notice.latest, releaseDir, notice.asset, downloader, notice.localRoot);
|
|
@@ -56984,7 +57101,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
56984
57101
|
for (const step of planned) {
|
|
56985
57102
|
if (step.kind === "verify") {
|
|
56986
57103
|
if (!verifyReleaseAssetDigest(step.path, step.sha256)) {
|
|
56987
|
-
const actual =
|
|
57104
|
+
const actual = existsSync50(step.path) ? createHash19("sha256").update(readFileSync44(step.path)).digest("hex") : "missing";
|
|
56988
57105
|
return {
|
|
56989
57106
|
ok: false,
|
|
56990
57107
|
error: "release_digest_mismatch",
|
|
@@ -57312,12 +57429,12 @@ async function cmdValidate(runtime, fileFlag) {
|
|
|
57312
57429
|
}
|
|
57313
57430
|
const selectedFile = explicitFile || configuredFile;
|
|
57314
57431
|
const file = selectedFile ? resolve33(runtime.cwd, selectedFile) : void 0;
|
|
57315
|
-
if (file && !
|
|
57432
|
+
if (file && !existsSync50(file)) {
|
|
57316
57433
|
printWorker(runtime, worker, { ok: false, command: "validate", error: "file_not_found", file }, `workflow file not found: ${file}`);
|
|
57317
57434
|
return 1;
|
|
57318
57435
|
}
|
|
57319
57436
|
try {
|
|
57320
|
-
const raw = file ?
|
|
57437
|
+
const raw = file ? readFileSync44(file, "utf8") : inline;
|
|
57321
57438
|
if (explicitFile && file && !raw.trimStart().startsWith("[")) {
|
|
57322
57439
|
const value = parseRestrictedYaml2(raw, file);
|
|
57323
57440
|
const issues = new KxmSchemaRegistry().validate("workflow", value, file);
|
|
@@ -57412,7 +57529,7 @@ async function cmdImprove(runtime, options = {}) {
|
|
|
57412
57529
|
print(runtime.io, runtime.json, { ok: false, command: "improve", error: "config_invalid", detail: message }, `config_invalid: ${message}`);
|
|
57413
57530
|
return 1;
|
|
57414
57531
|
}
|
|
57415
|
-
const candidatesDir = options.outDir ? resolve33(runtime.cwd, options.outDir) :
|
|
57532
|
+
const candidatesDir = options.outDir ? resolve33(runtime.cwd, options.outDir) : join58(root, ".kxm", "candidates");
|
|
57416
57533
|
const report2 = buildImprovementReport(loaded2.records, {
|
|
57417
57534
|
candidatesDir,
|
|
57418
57535
|
projectRoot: root,
|
|
@@ -57422,7 +57539,7 @@ async function cmdImprove(runtime, options = {}) {
|
|
|
57422
57539
|
halfLifeDays: config.improvement.telemetryHalfLifeDays,
|
|
57423
57540
|
routeSwitches: loaded2.routeSwitches
|
|
57424
57541
|
});
|
|
57425
|
-
const reportDir =
|
|
57542
|
+
const reportDir = join58(runtime.dirs.assets, "improvements");
|
|
57426
57543
|
const reportPath = writeImprovementReport(reportDir, report2, runtime.dryRun);
|
|
57427
57544
|
const text = [
|
|
57428
57545
|
"Sources:",
|
|
@@ -57597,9 +57714,9 @@ async function maybeOfferCompletionInstall(runtime) {
|
|
|
57597
57714
|
if (!pathNeeded) {
|
|
57598
57715
|
const scriptPath = completionScriptPath(shell, { env: runtime.env, configDir: runtime.env.KXM_USER_CONFIG_DIR });
|
|
57599
57716
|
const { rcFile } = completionRcTarget(shell, { env: runtime.env });
|
|
57600
|
-
if (rcFile &&
|
|
57717
|
+
if (rcFile && existsSync50(rcFile)) {
|
|
57601
57718
|
try {
|
|
57602
|
-
if (
|
|
57719
|
+
if (readFileSync44(rcFile, "utf8").includes(scriptPath)) return;
|
|
57603
57720
|
} catch {
|
|
57604
57721
|
}
|
|
57605
57722
|
}
|
|
@@ -57764,7 +57881,7 @@ async function cmdRoutingReport(runtime, options) {
|
|
|
57764
57881
|
let catalog;
|
|
57765
57882
|
if (includeEquivalentListCost) {
|
|
57766
57883
|
try {
|
|
57767
|
-
const pricesPath = options.prices ? resolve33(runtime.cwd, options.prices) :
|
|
57884
|
+
const pricesPath = options.prices ? resolve33(runtime.cwd, options.prices) : join58(runtime.dirs.workspace, "prices.yaml");
|
|
57768
57885
|
catalog = loadPriceCatalog(pricesPath);
|
|
57769
57886
|
} catch {
|
|
57770
57887
|
}
|
|
@@ -58381,7 +58498,7 @@ function createProgram(ctx, result, argv) {
|
|
|
58381
58498
|
addGlobalOptions(harnessCmd.command("list").description("Show installed harnesses, auth, and native updaters")).action(bind(cmdHarnessList));
|
|
58382
58499
|
const pluginCmd = addGlobalOptions(program2.command("plugin").description("Install or manage KXM harness plugins"));
|
|
58383
58500
|
pluginCmd.helpCommand("help", "Show plugin help");
|
|
58384
|
-
addGlobalOptions(pluginCmd.command("install", { isDefault: true }).description("Install the KXM plugin into discovered or specified harnesses")).option("--all", "Install plugin for all discovered harnesses (default)").option("--claude", "Install plugin for Claude Code").option("--omp", "Install plugin for Oh My Pi (OMP)").option("--pi", "Install plugin for Pi").action(async function pluginInstallAction(options) {
|
|
58501
|
+
addGlobalOptions(pluginCmd.command("install", { isDefault: true }).description("Install the KXM plugin into discovered or specified harnesses")).option("--all", "Install plugin for all discovered harnesses (default)").option("--claude", "Install plugin for Claude Code").option("--omp", "Install plugin for Oh My Pi (OMP)").option("--pi", "Install plugin for Pi").option("--status-band", "Configure OMP's focused status band with live subscription usage").action(async function pluginInstallAction(options) {
|
|
58385
58502
|
result.code = await cmdPluginInstall(runtimeFrom(ctx, this), options);
|
|
58386
58503
|
});
|
|
58387
58504
|
const authCmd = addGlobalOptions(program2.command("auth").description("Manage credentials, tokens, and authorization"));
|