@kontextmind/kxm 0.7.22 → 0.7.24
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/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +55 -13
- package/plugins/kxm/dist/mcp-server.js +104 -32
- package/plugins/kxm/dist/runtime.js +307 -7
- package/plugins/kxm/dist/vnext-runtime-supervisor.js +300 -6
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/hub.ts +2 -1
- package/plugins/kxm/src/cli/vnext.ts +46 -3
- package/plugins/kxm/src/cli.ts +3 -13
- package/plugins/kxm/src/database.ts +3 -1
- package/plugins/kxm/src/hub-env.ts +15 -0
- package/plugins/kxm/src/mcp-server.ts +5 -7
- package/plugins/kxm/src/vnext-config.ts +31 -0
- package/plugins/kxm/src/vnext-engine-fold.ts +24 -0
- package/plugins/kxm/src/vnext-engine.ts +172 -2
- package/plugins/kxm/src/vnext-runtime-owner.ts +1 -0
- package/plugins/kxm/src/vnext-runtime-store.ts +151 -2
- package/plugins/kxm/src/vnext-runtime-supervisor.ts +23 -2
- package/schemas/vnext/common.schema.json +1 -0
- package/schemas/vnext/drive-receipt.schema.json +79 -0
- package/schemas/vnext/run-event.schema.json +10 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "kxm",
|
|
4
4
|
"displayName": "KXM",
|
|
5
|
-
"version": "0.7.
|
|
5
|
+
"version": "0.7.24",
|
|
6
6
|
"description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "KontextMind",
|
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -19657,6 +19657,12 @@ function readHubEnvRecord(env = process.env) {
|
|
|
19657
19657
|
...record.projectTokens !== void 0 ? { projectTokens: record.projectTokens } : {}
|
|
19658
19658
|
};
|
|
19659
19659
|
}
|
|
19660
|
+
function resolveClientHubAuthToken(env, project) {
|
|
19661
|
+
const envToken = env.KXM_AUTH_TOKEN?.trim();
|
|
19662
|
+
if (envToken) return envToken;
|
|
19663
|
+
const record = readHubEnvRecord(env);
|
|
19664
|
+
return record?.projectTokens?.[project]?.trim() || record?.authToken?.trim() || void 0;
|
|
19665
|
+
}
|
|
19660
19666
|
|
|
19661
19667
|
// plugins/kxm/src/project-name.ts
|
|
19662
19668
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
@@ -22044,6 +22050,7 @@ var VnextSchemaRegistry = class {
|
|
|
22044
22050
|
migrationReceiptValidator;
|
|
22045
22051
|
permissionDiffValidator;
|
|
22046
22052
|
runEventValidator;
|
|
22053
|
+
driveReceiptValidator;
|
|
22047
22054
|
constructor(schemasDir = DEFAULT_SCHEMA_DIR) {
|
|
22048
22055
|
this.schemasDir = resolve3(schemasDir);
|
|
22049
22056
|
this.ajv = new import__.Ajv2020({ allErrors: true, strict: true, strictRequired: false });
|
|
@@ -22060,6 +22067,7 @@ var VnextSchemaRegistry = class {
|
|
|
22060
22067
|
const migrationReceiptFile = "migration-receipt.schema.json";
|
|
22061
22068
|
const permissionDiffFile = "permission-diff.schema.json";
|
|
22062
22069
|
const runEventFile = "run-event.schema.json";
|
|
22070
|
+
const driveReceiptFile = "drive-receipt.schema.json";
|
|
22063
22071
|
this.ajv.addSchema(readJsonObject(join6(this.schemasDir, localBindingsFile)));
|
|
22064
22072
|
this.ajv.addSchema(readJsonObject(join6(this.schemasDir, templateProvenanceFile)));
|
|
22065
22073
|
this.ajv.addSchema(readJsonObject(join6(this.schemasDir, initOperationFile)));
|
|
@@ -22068,6 +22076,7 @@ var VnextSchemaRegistry = class {
|
|
|
22068
22076
|
this.ajv.addSchema(readJsonObject(join6(this.schemasDir, migrationReceiptFile)));
|
|
22069
22077
|
this.ajv.addSchema(readJsonObject(join6(this.schemasDir, permissionDiffFile)));
|
|
22070
22078
|
this.ajv.addSchema(readJsonObject(join6(this.schemasDir, runEventFile)));
|
|
22079
|
+
this.ajv.addSchema(readJsonObject(join6(this.schemasDir, driveReceiptFile)));
|
|
22071
22080
|
for (const [kind, definition] of Object.entries(RESOURCE_SCHEMA)) {
|
|
22072
22081
|
const validator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${definition.file}`);
|
|
22073
22082
|
if (!validator) throw new Error(`schema did not compile: ${definition.file}`);
|
|
@@ -22081,6 +22090,7 @@ var VnextSchemaRegistry = class {
|
|
|
22081
22090
|
const migrationReceiptValidator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${migrationReceiptFile}`);
|
|
22082
22091
|
const permissionDiffValidator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${permissionDiffFile}`);
|
|
22083
22092
|
const runEventValidator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${runEventFile}`);
|
|
22093
|
+
const driveReceiptValidator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${driveReceiptFile}`);
|
|
22084
22094
|
if (!localBindingsValidator) throw new Error(`schema did not compile: ${localBindingsFile}`);
|
|
22085
22095
|
if (!templateProvenanceValidator) throw new Error(`schema did not compile: ${templateProvenanceFile}`);
|
|
22086
22096
|
if (!initOperationValidator) throw new Error(`schema did not compile: ${initOperationFile}`);
|
|
@@ -22089,6 +22099,7 @@ var VnextSchemaRegistry = class {
|
|
|
22089
22099
|
if (!migrationReceiptValidator) throw new Error(`schema did not compile: ${migrationReceiptFile}`);
|
|
22090
22100
|
if (!permissionDiffValidator) throw new Error(`schema did not compile: ${permissionDiffFile}`);
|
|
22091
22101
|
if (!runEventValidator) throw new Error(`schema did not compile: ${runEventFile}`);
|
|
22102
|
+
if (!driveReceiptValidator) throw new Error(`schema did not compile: ${driveReceiptFile}`);
|
|
22092
22103
|
this.localBindingsValidator = localBindingsValidator;
|
|
22093
22104
|
this.templateProvenanceValidator = templateProvenanceValidator;
|
|
22094
22105
|
this.initOperationValidator = initOperationValidator;
|
|
@@ -22097,6 +22108,7 @@ var VnextSchemaRegistry = class {
|
|
|
22097
22108
|
this.migrationReceiptValidator = migrationReceiptValidator;
|
|
22098
22109
|
this.permissionDiffValidator = permissionDiffValidator;
|
|
22099
22110
|
this.runEventValidator = runEventValidator;
|
|
22111
|
+
this.driveReceiptValidator = driveReceiptValidator;
|
|
22100
22112
|
}
|
|
22101
22113
|
validate(kind, value, file) {
|
|
22102
22114
|
const definition = RESOURCE_SCHEMA[kind];
|
|
@@ -22129,6 +22141,9 @@ var VnextSchemaRegistry = class {
|
|
|
22129
22141
|
validatePermissionDiff(value, file) {
|
|
22130
22142
|
return this.validateAuxiliary(value, file, "kxm.permission-diff.v1", this.permissionDiffValidator);
|
|
22131
22143
|
}
|
|
22144
|
+
validateDriveReceipt(value, file) {
|
|
22145
|
+
return this.validateAuxiliary(value, file, "kxm.drive-receipt.v1", this.driveReceiptValidator);
|
|
22146
|
+
}
|
|
22132
22147
|
validateAuxiliary(value, file, identity, validator) {
|
|
22133
22148
|
if (value.schema !== identity) {
|
|
22134
22149
|
return [issue2("schema", "schema_identity_mismatch", file, `expected ${identity}, received ${String(value.schema)}`)];
|
|
@@ -23912,7 +23927,7 @@ function discoverProjectStores(projectRoot, options = {}) {
|
|
|
23912
23927
|
stores.push({
|
|
23913
23928
|
storeId: `events:${key}`,
|
|
23914
23929
|
sourcePath: join8(eventsDir, entry.name),
|
|
23915
|
-
maxSupportedVersion:
|
|
23930
|
+
maxSupportedVersion: 4
|
|
23916
23931
|
});
|
|
23917
23932
|
}
|
|
23918
23933
|
}
|
|
@@ -24002,6 +24017,8 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
24002
24017
|
let maxSupported = 3;
|
|
24003
24018
|
if (store.storeId === "registry" || store.storeId === "binding-store") {
|
|
24004
24019
|
maxSupported = 1;
|
|
24020
|
+
} else if (store.storeId.startsWith("events:")) {
|
|
24021
|
+
maxSupported = 4;
|
|
24005
24022
|
}
|
|
24006
24023
|
let targetPath = store.sourcePath;
|
|
24007
24024
|
if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
|
|
@@ -24242,6 +24259,7 @@ var VnextRuntimeRegistry = class {
|
|
|
24242
24259
|
} : void 0;
|
|
24243
24260
|
}
|
|
24244
24261
|
};
|
|
24262
|
+
var DRIVE_RECEIPT_MAX_BYTES = 8 * 1024;
|
|
24245
24263
|
|
|
24246
24264
|
// plugins/kxm/src/vnext-engine-compile.ts
|
|
24247
24265
|
var VNEXT_COMPILED_WORKFLOW_SCHEMA = "kxm.compiled-workflow.v1";
|
|
@@ -33624,6 +33642,28 @@ ${RUN_ENGINE_NOTICE}`);
|
|
|
33624
33642
|
return 1;
|
|
33625
33643
|
}
|
|
33626
33644
|
}
|
|
33645
|
+
function formatDriveStatusLine(runStatus, drive) {
|
|
33646
|
+
if (!drive || typeof drive.driveId !== "string" || drive.driveId.length === 0) return void 0;
|
|
33647
|
+
const receipt = drive.receipt ?? null;
|
|
33648
|
+
if (receipt === null) {
|
|
33649
|
+
if (runStatus === "running" || runStatus === "blocked_uncertain") {
|
|
33650
|
+
return `drive ${drive.driveId}: open`;
|
|
33651
|
+
}
|
|
33652
|
+
return `drive ${drive.driveId}: no receipt (orphaned)`;
|
|
33653
|
+
}
|
|
33654
|
+
const kind = receipt.settlement?.kind;
|
|
33655
|
+
const reason = typeof receipt.settlement?.reason === "string" ? receipt.settlement.reason : "";
|
|
33656
|
+
if (kind === "unsettled") {
|
|
33657
|
+
return `drive ${drive.driveId}: unsettled ${reason}`.trimEnd();
|
|
33658
|
+
}
|
|
33659
|
+
if (kind === "handoff") {
|
|
33660
|
+
return drive.verified === true ? `drive ${drive.driveId}: handoff (receipt verified)` : `drive ${drive.driveId}: handoff`;
|
|
33661
|
+
}
|
|
33662
|
+
if (drive.verified === true) {
|
|
33663
|
+
return `drive ${drive.driveId}: completed (receipt verified)`;
|
|
33664
|
+
}
|
|
33665
|
+
return `drive ${drive.driveId}: completed`;
|
|
33666
|
+
}
|
|
33627
33667
|
async function cmdVnextRunStatus(runtime, runId) {
|
|
33628
33668
|
try {
|
|
33629
33669
|
const projectRoot = discoverVnextProjectRoot(runtime.cwd);
|
|
@@ -33631,10 +33671,18 @@ async function cmdVnextRunStatus(runtime, runId) {
|
|
|
33631
33671
|
print(runtime.io, runtime.json, { ok: false, command: "runs status", error: "project_required" }, "kxm runs status requires a vNext project (run kxm init first)");
|
|
33632
33672
|
return 1;
|
|
33633
33673
|
}
|
|
33634
|
-
const supervisor = await ensureVnextSupervisor({ env: runtime.env });
|
|
33635
|
-
const result = await vnextRuntimeRequest(supervisor, "GET", `/v1/runs/${encodeURIComponent(runId)}?projectRoot=${encodeURIComponent(projectRoot)}`);
|
|
33674
|
+
const supervisor = await (vnextDriveCliSeams.ensureSupervisor ?? ensureVnextSupervisor)({ env: runtime.env });
|
|
33675
|
+
const result = await (vnextDriveCliSeams.runtimeRequest ?? vnextRuntimeRequest)(supervisor, "GET", `/v1/runs/${encodeURIComponent(runId)}?projectRoot=${encodeURIComponent(projectRoot)}`);
|
|
33636
33676
|
const run = result.run;
|
|
33637
|
-
|
|
33677
|
+
const drive = result.drive;
|
|
33678
|
+
const driveLine = formatDriveStatusLine(run.status, drive);
|
|
33679
|
+
print(
|
|
33680
|
+
runtime.io,
|
|
33681
|
+
runtime.json,
|
|
33682
|
+
{ ok: true, command: "runs status", run, ...drive !== void 0 ? { drive } : {} },
|
|
33683
|
+
`run ${run.runId}: ${run.status} (workflow ${run.workflowId}, updated ${run.updatedAt})${driveLine ? `
|
|
33684
|
+
${driveLine}` : ""}`
|
|
33685
|
+
);
|
|
33638
33686
|
return 0;
|
|
33639
33687
|
} catch (error) {
|
|
33640
33688
|
if (error instanceof VnextConfigError) {
|
|
@@ -45480,7 +45528,7 @@ async function cmdDash(runtime, options = {}) {
|
|
|
45480
45528
|
return 2;
|
|
45481
45529
|
}
|
|
45482
45530
|
const project = defaultProjectName(runtime.dirs.workdir, runtime.env) || "project";
|
|
45483
|
-
const authToken = runtime.env
|
|
45531
|
+
const authToken = resolveClientHubAuthToken(runtime.env, project);
|
|
45484
45532
|
return await runMeshTui({
|
|
45485
45533
|
serverUrl: runtime.serverUrl,
|
|
45486
45534
|
dataPath,
|
|
@@ -48456,12 +48504,6 @@ async function cmdRoutingBenchmark(runtime, options) {
|
|
|
48456
48504
|
|
|
48457
48505
|
// plugins/kxm/src/cli.ts
|
|
48458
48506
|
var CLI_NAME2 = "kxm";
|
|
48459
|
-
function resolveCliAuthToken(runtime, project) {
|
|
48460
|
-
const envToken = runtime.env.KXM_AUTH_TOKEN?.trim();
|
|
48461
|
-
if (envToken) return envToken;
|
|
48462
|
-
const record = readHubEnvRecord(runtime.env);
|
|
48463
|
-
return record?.projectTokens?.[project]?.trim() || record?.authToken?.trim() || void 0;
|
|
48464
|
-
}
|
|
48465
48507
|
var USAGE_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
48466
48508
|
"commander.help",
|
|
48467
48509
|
"commander.helpDisplayed",
|
|
@@ -48483,7 +48525,7 @@ async function ensureCliClient(runtime) {
|
|
|
48483
48525
|
const project = defaultProjectName(runtime.cwd, runtime.env);
|
|
48484
48526
|
const name = runtime.env.KXM_AGENT_NAME?.trim() || `cli-${process.pid}`;
|
|
48485
48527
|
const purpose = runtime.env.KXM_AGENT_PURPOSE?.trim() || "CLI agent client";
|
|
48486
|
-
const authToken =
|
|
48528
|
+
const authToken = resolveClientHubAuthToken(runtime.env, project);
|
|
48487
48529
|
const client = new HubClient({
|
|
48488
48530
|
serverUrl,
|
|
48489
48531
|
name,
|
|
@@ -48638,7 +48680,7 @@ function createProgram(ctx, result) {
|
|
|
48638
48680
|
}));
|
|
48639
48681
|
const runCmd = addGlobalOptions(program2.command("runs").description("Inspect vNext runs"));
|
|
48640
48682
|
runCmd.helpCommand("help", "Show runs help");
|
|
48641
|
-
addGlobalOptions(runCmd.command("status").description("Show the projected status of a run")).argument("<runId>", "Run id").action(async function runStatusAction(runId) {
|
|
48683
|
+
addGlobalOptions(runCmd.command("status").description("Show the projected status of a run, including durable drive receipt state (open / receipt verified / unsettled / orphaned)")).argument("<runId>", "Run id").action(async function runStatusAction(runId) {
|
|
48642
48684
|
result.code = await cmdVnextRunStatus(runtimeFrom(ctx, this), runId);
|
|
48643
48685
|
});
|
|
48644
48686
|
addGlobalOptions(runCmd.command("drive").description("Drive a run with an explicit model-free simulation")).argument("<runId>", "Run id").option("--simulated", "Use the model-free simulation producer").action(async function runDriveAction(runId, options) {
|
|
@@ -2984,7 +2984,7 @@ var require_compile = __commonJS({
|
|
|
2984
2984
|
const schOrFunc = root.refs[ref];
|
|
2985
2985
|
if (schOrFunc)
|
|
2986
2986
|
return schOrFunc;
|
|
2987
|
-
let _sch =
|
|
2987
|
+
let _sch = resolve3.call(this, root, ref);
|
|
2988
2988
|
if (_sch === void 0) {
|
|
2989
2989
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
2990
2990
|
const { schemaId } = this.opts;
|
|
@@ -3011,7 +3011,7 @@ var require_compile = __commonJS({
|
|
|
3011
3011
|
function sameSchemaEnv(s1, s2) {
|
|
3012
3012
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3013
3013
|
}
|
|
3014
|
-
function
|
|
3014
|
+
function resolve3(root, ref) {
|
|
3015
3015
|
let sch;
|
|
3016
3016
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3017
3017
|
ref = sch;
|
|
@@ -3836,7 +3836,7 @@ var require_fast_uri = __commonJS({
|
|
|
3836
3836
|
}
|
|
3837
3837
|
return uri;
|
|
3838
3838
|
}
|
|
3839
|
-
function
|
|
3839
|
+
function resolve3(baseURI, relativeURI, options) {
|
|
3840
3840
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3841
3841
|
const {
|
|
3842
3842
|
parsed: baseParsed,
|
|
@@ -4198,7 +4198,7 @@ var require_fast_uri = __commonJS({
|
|
|
4198
4198
|
var fastUri = {
|
|
4199
4199
|
SCHEMES,
|
|
4200
4200
|
normalize,
|
|
4201
|
-
resolve:
|
|
4201
|
+
resolve: resolve3,
|
|
4202
4202
|
resolveComponent,
|
|
4203
4203
|
equal,
|
|
4204
4204
|
serialize,
|
|
@@ -14505,7 +14505,7 @@ var Protocol = class {
|
|
|
14505
14505
|
return;
|
|
14506
14506
|
}
|
|
14507
14507
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
14508
|
-
await new Promise((
|
|
14508
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
|
|
14509
14509
|
options?.signal?.throwIfAborted();
|
|
14510
14510
|
}
|
|
14511
14511
|
} catch (error2) {
|
|
@@ -14522,7 +14522,7 @@ var Protocol = class {
|
|
|
14522
14522
|
*/
|
|
14523
14523
|
request(request, resultSchema, options) {
|
|
14524
14524
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
14525
|
-
return new Promise((
|
|
14525
|
+
return new Promise((resolve3, reject) => {
|
|
14526
14526
|
const earlyReject = (error2) => {
|
|
14527
14527
|
reject(error2);
|
|
14528
14528
|
};
|
|
@@ -14600,7 +14600,7 @@ var Protocol = class {
|
|
|
14600
14600
|
if (!parseResult.success) {
|
|
14601
14601
|
reject(parseResult.error);
|
|
14602
14602
|
} else {
|
|
14603
|
-
|
|
14603
|
+
resolve3(parseResult.data);
|
|
14604
14604
|
}
|
|
14605
14605
|
} catch (error2) {
|
|
14606
14606
|
reject(error2);
|
|
@@ -14861,12 +14861,12 @@ var Protocol = class {
|
|
|
14861
14861
|
}
|
|
14862
14862
|
} catch {
|
|
14863
14863
|
}
|
|
14864
|
-
return new Promise((
|
|
14864
|
+
return new Promise((resolve3, reject) => {
|
|
14865
14865
|
if (signal.aborted) {
|
|
14866
14866
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
14867
14867
|
return;
|
|
14868
14868
|
}
|
|
14869
|
-
const timeoutId = setTimeout(
|
|
14869
|
+
const timeoutId = setTimeout(resolve3, interval);
|
|
14870
14870
|
signal.addEventListener("abort", () => {
|
|
14871
14871
|
clearTimeout(timeoutId);
|
|
14872
14872
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -15742,12 +15742,12 @@ var StdioServerTransport = class {
|
|
|
15742
15742
|
this.onclose?.();
|
|
15743
15743
|
}
|
|
15744
15744
|
send(message) {
|
|
15745
|
-
return new Promise((
|
|
15745
|
+
return new Promise((resolve3) => {
|
|
15746
15746
|
const json = serializeMessage(message);
|
|
15747
15747
|
if (this._stdout.write(json)) {
|
|
15748
|
-
|
|
15748
|
+
resolve3();
|
|
15749
15749
|
} else {
|
|
15750
|
-
this._stdout.once("drain",
|
|
15750
|
+
this._stdout.once("drain", resolve3);
|
|
15751
15751
|
}
|
|
15752
15752
|
});
|
|
15753
15753
|
}
|
|
@@ -16022,7 +16022,7 @@ var HubClient = class {
|
|
|
16022
16022
|
if (signal?.aborted) throw new MeshWaitError("aborted", messageId);
|
|
16023
16023
|
const message = await this.getMessage(messageId);
|
|
16024
16024
|
if (["replied", "cancelled", "expired", "error"].includes(message.status)) return message;
|
|
16025
|
-
await new Promise((
|
|
16025
|
+
await new Promise((resolve3, reject) => {
|
|
16026
16026
|
const onAbort = () => {
|
|
16027
16027
|
signal?.removeEventListener("abort", onAbort);
|
|
16028
16028
|
clearTimeout(timer);
|
|
@@ -16030,7 +16030,7 @@ var HubClient = class {
|
|
|
16030
16030
|
};
|
|
16031
16031
|
const timer = setTimeout(() => {
|
|
16032
16032
|
signal?.removeEventListener("abort", onAbort);
|
|
16033
|
-
|
|
16033
|
+
resolve3();
|
|
16034
16034
|
}, Math.min(500, Math.max(1, deadline - Date.now())));
|
|
16035
16035
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
16036
16036
|
if (signal?.aborted) onAbort();
|
|
@@ -16085,7 +16085,7 @@ var HubClient = class {
|
|
|
16085
16085
|
} catch (error2) {
|
|
16086
16086
|
if (this.stopped || error2 instanceof Error && error2.name === "AbortError") return;
|
|
16087
16087
|
}
|
|
16088
|
-
if (!this.stopped) await new Promise((
|
|
16088
|
+
if (!this.stopped) await new Promise((resolve3) => setTimeout(resolve3, this.options.reconnectMs));
|
|
16089
16089
|
}
|
|
16090
16090
|
}
|
|
16091
16091
|
headers(includeIdentity = true) {
|
|
@@ -16166,14 +16166,88 @@ var HubClient = class {
|
|
|
16166
16166
|
}
|
|
16167
16167
|
};
|
|
16168
16168
|
|
|
16169
|
+
// plugins/kxm/src/hub-env.ts
|
|
16170
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
16171
|
+
import { homedir } from "node:os";
|
|
16172
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
16173
|
+
var HUB_ENV_SCHEMA = "kxm.hub-env.v1";
|
|
16174
|
+
var HubEnvError = class extends Error {
|
|
16175
|
+
constructor(message) {
|
|
16176
|
+
super(message);
|
|
16177
|
+
this.name = "HubEnvError";
|
|
16178
|
+
}
|
|
16179
|
+
};
|
|
16180
|
+
function resolveUserStateRoot(env) {
|
|
16181
|
+
const explicit = env.KXM_STATE_HOME?.trim();
|
|
16182
|
+
if (explicit) {
|
|
16183
|
+
if (!isAbsolute(explicit)) throw new HubEnvError("local_state_root_not_absolute");
|
|
16184
|
+
return resolve(explicit);
|
|
16185
|
+
}
|
|
16186
|
+
if (process.platform === "win32") {
|
|
16187
|
+
const localAppData = env.LOCALAPPDATA?.trim();
|
|
16188
|
+
const base2 = localAppData && isAbsolute(localAppData) ? localAppData : join(homedir(), "AppData", "Local");
|
|
16189
|
+
return resolve(base2, "KXM");
|
|
16190
|
+
}
|
|
16191
|
+
if (process.platform === "darwin") return resolve(homedir(), "Library", "Application Support", "KXM");
|
|
16192
|
+
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
16193
|
+
const base = xdgState && isAbsolute(xdgState) ? xdgState : join(homedir(), ".local", "state");
|
|
16194
|
+
return resolve(base, "kxm");
|
|
16195
|
+
}
|
|
16196
|
+
function hubEnvFile(env = process.env) {
|
|
16197
|
+
return join(resolveUserStateRoot(env), "hub-env.json");
|
|
16198
|
+
}
|
|
16199
|
+
function readHubEnvRecord(env = process.env) {
|
|
16200
|
+
const file = hubEnvFile(env);
|
|
16201
|
+
if (!existsSync(file)) return void 0;
|
|
16202
|
+
let parsed;
|
|
16203
|
+
try {
|
|
16204
|
+
parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
16205
|
+
} catch (error2) {
|
|
16206
|
+
throw new HubEnvError(`hub env file is malformed at ${file}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
16207
|
+
}
|
|
16208
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
16209
|
+
throw new HubEnvError(`hub env file is malformed at ${file}: expected a JSON object`);
|
|
16210
|
+
}
|
|
16211
|
+
const record2 = parsed;
|
|
16212
|
+
if (record2.schema !== HUB_ENV_SCHEMA) {
|
|
16213
|
+
throw new HubEnvError(`hub env file at ${file} has unsupported schema ${String(record2.schema)}`);
|
|
16214
|
+
}
|
|
16215
|
+
if (record2.authToken !== void 0 && (typeof record2.authToken !== "string" || record2.authToken.trim().length === 0)) {
|
|
16216
|
+
throw new HubEnvError(`hub env file at ${file} has an invalid authToken`);
|
|
16217
|
+
}
|
|
16218
|
+
if (record2.projectTokens !== void 0) {
|
|
16219
|
+
const tokens = record2.projectTokens;
|
|
16220
|
+
if (!tokens || typeof tokens !== "object" || Array.isArray(tokens)) {
|
|
16221
|
+
throw new HubEnvError(`hub env file at ${file} has invalid projectTokens`);
|
|
16222
|
+
}
|
|
16223
|
+
for (const [project, token] of Object.entries(tokens)) {
|
|
16224
|
+
if (!project.trim() || typeof token !== "string" || !token.trim()) {
|
|
16225
|
+
throw new HubEnvError(`hub env file at ${file} has an empty project name or token`);
|
|
16226
|
+
}
|
|
16227
|
+
}
|
|
16228
|
+
}
|
|
16229
|
+
return {
|
|
16230
|
+
schema: HUB_ENV_SCHEMA,
|
|
16231
|
+
createdAt: typeof record2.createdAt === "string" ? record2.createdAt : "",
|
|
16232
|
+
...record2.authToken !== void 0 ? { authToken: record2.authToken } : {},
|
|
16233
|
+
...record2.projectTokens !== void 0 ? { projectTokens: record2.projectTokens } : {}
|
|
16234
|
+
};
|
|
16235
|
+
}
|
|
16236
|
+
function resolveClientHubAuthToken(env, project) {
|
|
16237
|
+
const envToken = env.KXM_AUTH_TOKEN?.trim();
|
|
16238
|
+
if (envToken) return envToken;
|
|
16239
|
+
const record2 = readHubEnvRecord(env);
|
|
16240
|
+
return record2?.projectTokens?.[project]?.trim() || record2?.authToken?.trim() || void 0;
|
|
16241
|
+
}
|
|
16242
|
+
|
|
16169
16243
|
// plugins/kxm/src/project-name.ts
|
|
16170
|
-
import { readFileSync } from "node:fs";
|
|
16171
|
-
import { basename, join } from "node:path";
|
|
16244
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
16245
|
+
import { basename, join as join2 } from "node:path";
|
|
16172
16246
|
function defaultProjectName(cwd, env = process.env) {
|
|
16173
16247
|
const fromEnv = env.KXM_PROJECT?.trim();
|
|
16174
16248
|
if (fromEnv) return fromEnv;
|
|
16175
16249
|
try {
|
|
16176
|
-
const pkg = JSON.parse(
|
|
16250
|
+
const pkg = JSON.parse(readFileSync2(join2(cwd, "package.json"), "utf8"));
|
|
16177
16251
|
if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
|
|
16178
16252
|
} catch {
|
|
16179
16253
|
}
|
|
@@ -16181,9 +16255,9 @@ function defaultProjectName(cwd, env = process.env) {
|
|
|
16181
16255
|
}
|
|
16182
16256
|
|
|
16183
16257
|
// plugins/kxm/src/commands.ts
|
|
16184
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync as
|
|
16185
|
-
import { homedir } from "node:os";
|
|
16186
|
-
import { dirname, join as
|
|
16258
|
+
import { chmodSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
16259
|
+
import { homedir as homedir2 } from "node:os";
|
|
16260
|
+
import { dirname as dirname2, join as join3, resolve as resolve2 } from "node:path";
|
|
16187
16261
|
function requiredString(value, name) {
|
|
16188
16262
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`${name} is required`);
|
|
16189
16263
|
return value.trim();
|
|
@@ -16918,11 +16992,11 @@ function parseSessionToken(token) {
|
|
|
16918
16992
|
return void 0;
|
|
16919
16993
|
}
|
|
16920
16994
|
function resolveUserConfigDirectory(overrideDir) {
|
|
16921
|
-
if (overrideDir) return
|
|
16922
|
-
return
|
|
16995
|
+
if (overrideDir) return resolve2(overrideDir);
|
|
16996
|
+
return resolve2(process.env.KXM_USER_CONFIG_DIR?.trim() || join3(homedir2(), ".config", "kxm"));
|
|
16923
16997
|
}
|
|
16924
16998
|
function sessionTokenPath(userConfigDir) {
|
|
16925
|
-
return
|
|
16999
|
+
return join3(resolveUserConfigDirectory(userConfigDir), "session.token");
|
|
16926
17000
|
}
|
|
16927
17001
|
function matchToolPattern(pattern, toolName) {
|
|
16928
17002
|
if (pattern === "*" || pattern === toolName) return true;
|
|
@@ -17015,10 +17089,10 @@ function enforceToolPolicy(commandName, env = process.env, options) {
|
|
|
17015
17089
|
return { allowed: true };
|
|
17016
17090
|
}
|
|
17017
17091
|
const tokenFile = sessionTokenPath(env.KXM_USER_CONFIG_DIR);
|
|
17018
|
-
if (
|
|
17092
|
+
if (existsSync2(tokenFile)) {
|
|
17019
17093
|
let tokenRaw;
|
|
17020
17094
|
try {
|
|
17021
|
-
tokenRaw =
|
|
17095
|
+
tokenRaw = readFileSync3(tokenFile, "utf8").trim();
|
|
17022
17096
|
} catch {
|
|
17023
17097
|
return { allowed: false, error: "session_token_invalid", detail: "Session token file on disk could not be read" };
|
|
17024
17098
|
}
|
|
@@ -17047,7 +17121,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
|
|
|
17047
17121
|
}
|
|
17048
17122
|
|
|
17049
17123
|
// plugins/kxm/src/mcp-server.ts
|
|
17050
|
-
var VERSION = "0.7.
|
|
17124
|
+
var VERSION = "0.7.24";
|
|
17051
17125
|
var inbox = /* @__PURE__ */ new Map();
|
|
17052
17126
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
|
17053
17127
|
var meshClient;
|
|
@@ -17071,9 +17145,6 @@ var mcp = new Server(
|
|
|
17071
17145
|
function textResult(value) {
|
|
17072
17146
|
return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }] };
|
|
17073
17147
|
}
|
|
17074
|
-
function optionalString2(value) {
|
|
17075
|
-
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
17076
|
-
}
|
|
17077
17148
|
function asRecord2(value) {
|
|
17078
17149
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
17079
17150
|
}
|
|
@@ -17115,12 +17186,13 @@ async function ensureClient() {
|
|
|
17115
17186
|
if (starting) return starting;
|
|
17116
17187
|
starting = (async () => {
|
|
17117
17188
|
const projectDir = process.env.KXM_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
17118
|
-
const
|
|
17189
|
+
const project = defaultProjectName(projectDir, process.env);
|
|
17190
|
+
const authToken = resolveClientHubAuthToken(process.env, project);
|
|
17119
17191
|
const candidate = new HubClient({
|
|
17120
17192
|
serverUrl: process.env.KXM_SERVER_URL?.trim() || "http://127.0.0.1:7331",
|
|
17121
17193
|
name: process.env.KXM_AGENT_NAME?.trim() || `claude-${process.pid}`,
|
|
17122
17194
|
purpose: process.env.KXM_AGENT_PURPOSE?.trim() || "Claude Code implementation and review agent",
|
|
17123
|
-
project
|
|
17195
|
+
project,
|
|
17124
17196
|
model: "claude-code",
|
|
17125
17197
|
...authToken ? { authToken } : {}
|
|
17126
17198
|
});
|