@kontextmind/kxm 0.7.163 → 0.7.165
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 +22 -0
- package/README.md +2 -0
- package/docs/README.md +1 -0
- package/docs/architecture/inventory.md +4 -3
- package/docs/contributing/harness-routing-internals.md +28 -27
- package/docs/glossary.md +3 -3
- package/docs/operations/troubleshooting.md +3 -0
- package/docs/operations.md +154 -0
- package/docs/reference/cli-reference.md +4 -3
- package/docs/reference/configuration.md +11 -1
- package/docs/reference/harness-routing.md +17 -15
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +2 -2
- package/plugins/kxm/README.md +2 -2
- package/plugins/kxm/dist/claude-hook.js +120 -16
- package/plugins/kxm/dist/cli.js +14929 -14542
- package/plugins/kxm/dist/extension.js +299 -122
- package/plugins/kxm/dist/mcp-server.js +7690 -106
- package/plugins/kxm/dist/runtime-supervisor.js +151 -4
- package/plugins/kxm/dist/runtime.js +158 -11
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +5 -1
- package/plugins/kxm/src/cli/context-skills.ts +64 -10
- package/plugins/kxm/src/cli/hub.ts +128 -17
- package/plugins/kxm/src/cli/project.ts +7 -3
- package/plugins/kxm/src/cli/types.ts +6 -0
- package/plugins/kxm/src/cli/workflows.ts +12 -1
- package/plugins/kxm/src/cli.ts +23 -5
- package/plugins/kxm/src/extension.ts +7 -3
- package/plugins/kxm/src/hub-autostart.ts +3 -0
- package/plugins/kxm/src/hub-binding.ts +182 -2
- package/plugins/kxm/src/hub-env.ts +71 -0
- package/plugins/kxm/src/mcp-server.ts +3 -2
- package/plugins/kxm/src/project-name.ts +34 -7
- package/plugins/kxm/src/runtime-supervisor.ts +9 -3
- package/plugins/kxm/src/tenant-status.ts +9 -2
- package/scripts/build-runtime.mjs +5 -0
|
@@ -10319,7 +10319,7 @@ var require_compile = __commonJS({
|
|
|
10319
10319
|
const schOrFunc = root.refs[ref];
|
|
10320
10320
|
if (schOrFunc)
|
|
10321
10321
|
return schOrFunc;
|
|
10322
|
-
let _sch =
|
|
10322
|
+
let _sch = resolve9.call(this, root, ref);
|
|
10323
10323
|
if (_sch === void 0) {
|
|
10324
10324
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
10325
10325
|
const { schemaId } = this.opts;
|
|
@@ -10346,7 +10346,7 @@ var require_compile = __commonJS({
|
|
|
10346
10346
|
function sameSchemaEnv(s1, s2) {
|
|
10347
10347
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
10348
10348
|
}
|
|
10349
|
-
function
|
|
10349
|
+
function resolve9(root, ref) {
|
|
10350
10350
|
let sch;
|
|
10351
10351
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
10352
10352
|
ref = sch;
|
|
@@ -11171,7 +11171,7 @@ var require_fast_uri = __commonJS({
|
|
|
11171
11171
|
}
|
|
11172
11172
|
return uri;
|
|
11173
11173
|
}
|
|
11174
|
-
function
|
|
11174
|
+
function resolve9(baseURI, relativeURI, options) {
|
|
11175
11175
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
11176
11176
|
const {
|
|
11177
11177
|
parsed: baseParsed,
|
|
@@ -11533,7 +11533,7 @@ var require_fast_uri = __commonJS({
|
|
|
11533
11533
|
var fastUri = {
|
|
11534
11534
|
SCHEMES,
|
|
11535
11535
|
normalize,
|
|
11536
|
-
resolve:
|
|
11536
|
+
resolve: resolve9,
|
|
11537
11537
|
resolveComponent,
|
|
11538
11538
|
equal,
|
|
11539
11539
|
serialize,
|
|
@@ -14523,9 +14523,9 @@ var require_dist2 = __commonJS({
|
|
|
14523
14523
|
});
|
|
14524
14524
|
|
|
14525
14525
|
// plugins/kxm/src/extension.ts
|
|
14526
|
-
import { spawnSync as
|
|
14527
|
-
import { existsSync as
|
|
14528
|
-
import { dirname as
|
|
14526
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
14527
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync14, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "node:fs";
|
|
14528
|
+
import { dirname as dirname8, join as join15 } from "node:path";
|
|
14529
14529
|
|
|
14530
14530
|
// plugins/kxm/src/commands.ts
|
|
14531
14531
|
import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
@@ -14967,7 +14967,7 @@ var HubClient = class {
|
|
|
14967
14967
|
if (signal?.aborted) throw new MeshWaitError("aborted", messageId);
|
|
14968
14968
|
const message = await this.getMessage(messageId);
|
|
14969
14969
|
if (["replied", "cancelled", "expired", "error"].includes(message.status)) return message;
|
|
14970
|
-
await new Promise((
|
|
14970
|
+
await new Promise((resolve9, reject) => {
|
|
14971
14971
|
const onAbort = () => {
|
|
14972
14972
|
signal?.removeEventListener("abort", onAbort);
|
|
14973
14973
|
clearTimeout(timer);
|
|
@@ -14975,7 +14975,7 @@ var HubClient = class {
|
|
|
14975
14975
|
};
|
|
14976
14976
|
const timer = setTimeout(() => {
|
|
14977
14977
|
signal?.removeEventListener("abort", onAbort);
|
|
14978
|
-
|
|
14978
|
+
resolve9();
|
|
14979
14979
|
}, Math.min(500, Math.max(1, deadline - Date.now())));
|
|
14980
14980
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
14981
14981
|
if (signal?.aborted) onAbort();
|
|
@@ -15030,7 +15030,7 @@ var HubClient = class {
|
|
|
15030
15030
|
} catch (error2) {
|
|
15031
15031
|
if (this.stopped || error2 instanceof Error && error2.name === "AbortError") return;
|
|
15032
15032
|
}
|
|
15033
|
-
if (!this.stopped) await new Promise((
|
|
15033
|
+
if (!this.stopped) await new Promise((resolve9) => setTimeout(resolve9, this.options.reconnectMs));
|
|
15034
15034
|
}
|
|
15035
15035
|
}
|
|
15036
15036
|
headers(includeIdentity = true) {
|
|
@@ -16145,15 +16145,27 @@ function loadKxmConfig(repoRoot = process.cwd(), options = {}) {
|
|
|
16145
16145
|
|
|
16146
16146
|
// plugins/kxm/src/hub-autostart.ts
|
|
16147
16147
|
import { spawn } from "node:child_process";
|
|
16148
|
-
import { closeSync, mkdirSync as mkdirSync5, openSync, readFileSync as
|
|
16149
|
-
import { join as
|
|
16148
|
+
import { closeSync, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync6 } from "node:fs";
|
|
16149
|
+
import { join as join7, resolve as resolve6 } from "node:path";
|
|
16150
16150
|
|
|
16151
16151
|
// plugins/kxm/src/hub-binding.ts
|
|
16152
|
+
import { spawnSync } from "node:child_process";
|
|
16152
16153
|
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
16153
16154
|
import { homedir as homedir3 } from "node:os";
|
|
16154
16155
|
import { dirname as dirname3, isAbsolute, join as join3, resolve as resolve3 } from "node:path";
|
|
16155
16156
|
var HUB_BINDING_SCHEMA = "kxm.hub-binding.v1";
|
|
16156
16157
|
var HUB_HEALTH_PROBE_MS = 300;
|
|
16158
|
+
var CloudTokenError = class extends Error {
|
|
16159
|
+
code;
|
|
16160
|
+
constructor(code, message) {
|
|
16161
|
+
super(message);
|
|
16162
|
+
this.name = "CloudTokenError";
|
|
16163
|
+
this.code = code;
|
|
16164
|
+
}
|
|
16165
|
+
};
|
|
16166
|
+
var TOKEN_ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
|
|
16167
|
+
var TOKEN_COMMAND_TIMEOUT_MS = 15e3;
|
|
16168
|
+
var TOKEN_COMMAND_MAX_BUFFER = 4096;
|
|
16157
16169
|
var HubBindingError = class extends Error {
|
|
16158
16170
|
constructor(message) {
|
|
16159
16171
|
super(message);
|
|
@@ -16191,6 +16203,99 @@ function validateHubUrl(raw) {
|
|
|
16191
16203
|
}
|
|
16192
16204
|
return parsed.href.replace(/\/$/, "");
|
|
16193
16205
|
}
|
|
16206
|
+
function splitTokenCommand(raw) {
|
|
16207
|
+
if (/[|&;<>$`\n\r]/.test(raw)) {
|
|
16208
|
+
throw new CloudTokenError(
|
|
16209
|
+
"cloud_token_command_invalid",
|
|
16210
|
+
"token command must be a program and arguments, not a shell pipeline"
|
|
16211
|
+
);
|
|
16212
|
+
}
|
|
16213
|
+
const args = [];
|
|
16214
|
+
let current = "";
|
|
16215
|
+
let quote;
|
|
16216
|
+
for (const ch of raw) {
|
|
16217
|
+
if (quote) {
|
|
16218
|
+
if (ch === quote) quote = void 0;
|
|
16219
|
+
else current += ch;
|
|
16220
|
+
continue;
|
|
16221
|
+
}
|
|
16222
|
+
if (ch === "'" || ch === '"') {
|
|
16223
|
+
quote = ch;
|
|
16224
|
+
continue;
|
|
16225
|
+
}
|
|
16226
|
+
if (ch === " " || ch === " ") {
|
|
16227
|
+
if (current.length > 0) {
|
|
16228
|
+
args.push(current);
|
|
16229
|
+
current = "";
|
|
16230
|
+
}
|
|
16231
|
+
continue;
|
|
16232
|
+
}
|
|
16233
|
+
current += ch;
|
|
16234
|
+
}
|
|
16235
|
+
if (quote) {
|
|
16236
|
+
throw new CloudTokenError("cloud_token_command_invalid", "token command has an unclosed quote");
|
|
16237
|
+
}
|
|
16238
|
+
if (current.length > 0) args.push(current);
|
|
16239
|
+
if (args.length === 0) {
|
|
16240
|
+
throw new CloudTokenError("cloud_token_command_invalid", "token command is empty");
|
|
16241
|
+
}
|
|
16242
|
+
return args;
|
|
16243
|
+
}
|
|
16244
|
+
function isCloudTokenEnvName(value) {
|
|
16245
|
+
return TOKEN_ENV_NAME.test(value);
|
|
16246
|
+
}
|
|
16247
|
+
function resolveHubServerUrl(env = process.env) {
|
|
16248
|
+
const fromEnv = env.KXM_SERVER_URL?.trim();
|
|
16249
|
+
if (fromEnv) return fromEnv.replace(/\/$/, "");
|
|
16250
|
+
try {
|
|
16251
|
+
const binding = readHubBinding(env);
|
|
16252
|
+
if (binding?.url) return binding.url;
|
|
16253
|
+
} catch (error2) {
|
|
16254
|
+
if (!(error2 instanceof HubBindingError)) throw error2;
|
|
16255
|
+
}
|
|
16256
|
+
return "http://127.0.0.1:7331";
|
|
16257
|
+
}
|
|
16258
|
+
function resolveCloudHubToken(binding, env = process.env) {
|
|
16259
|
+
if (!binding.cloud) {
|
|
16260
|
+
throw new CloudTokenError("cloud_token_missing", "cloud hub token is missing; the local hub-env token was not used");
|
|
16261
|
+
}
|
|
16262
|
+
if (binding.tokenEnv) {
|
|
16263
|
+
const value = env[binding.tokenEnv]?.trim();
|
|
16264
|
+
if (value) return value;
|
|
16265
|
+
}
|
|
16266
|
+
if (binding.tokenCommand) return runTokenCommand(binding.tokenCommand, env);
|
|
16267
|
+
const source = binding.tokenEnv ? `${binding.tokenEnv} is unset or empty` : "no token source is configured";
|
|
16268
|
+
throw new CloudTokenError(
|
|
16269
|
+
"cloud_token_missing",
|
|
16270
|
+
`cloud hub token is missing: ${source}; the local hub-env token was not used`
|
|
16271
|
+
);
|
|
16272
|
+
}
|
|
16273
|
+
function runTokenCommand(command, env) {
|
|
16274
|
+
const argv = splitTokenCommand(command);
|
|
16275
|
+
const [program, ...args] = argv;
|
|
16276
|
+
const result2 = spawnSync(program, args, {
|
|
16277
|
+
encoding: "utf8",
|
|
16278
|
+
shell: false,
|
|
16279
|
+
timeout: TOKEN_COMMAND_TIMEOUT_MS,
|
|
16280
|
+
maxBuffer: TOKEN_COMMAND_MAX_BUFFER,
|
|
16281
|
+
env,
|
|
16282
|
+
windowsHide: true
|
|
16283
|
+
});
|
|
16284
|
+
if (result2.error || result2.status !== 0) {
|
|
16285
|
+
throw new CloudTokenError(
|
|
16286
|
+
"cloud_token_command_failed",
|
|
16287
|
+
"token command failed; the local hub-env token was not used"
|
|
16288
|
+
);
|
|
16289
|
+
}
|
|
16290
|
+
const stdout = result2.stdout ?? "";
|
|
16291
|
+
if (stdout.trim().length === 0 || stdout.trim() !== stdout.trim().split(/\r?\n/)[0]) {
|
|
16292
|
+
throw new CloudTokenError(
|
|
16293
|
+
"cloud_token_command_failed",
|
|
16294
|
+
"token command did not print a single token; the local hub-env token was not used"
|
|
16295
|
+
);
|
|
16296
|
+
}
|
|
16297
|
+
return stdout.trim();
|
|
16298
|
+
}
|
|
16194
16299
|
function isIsoTimestamp(value) {
|
|
16195
16300
|
if (Number.isNaN(Date.parse(value))) return false;
|
|
16196
16301
|
return value === new Date(value).toISOString();
|
|
@@ -16214,7 +16319,9 @@ function readHubBinding(env = process.env) {
|
|
|
16214
16319
|
}
|
|
16215
16320
|
const row = parsed;
|
|
16216
16321
|
const keys = Object.keys(row);
|
|
16217
|
-
|
|
16322
|
+
const allowed = /* @__PURE__ */ new Set(["schema", "url", "boundAt", "cloud", "tokenEnv", "tokenCommand"]);
|
|
16323
|
+
const cloudish = keys.some((key) => key === "cloud" || key === "tokenEnv" || key === "tokenCommand");
|
|
16324
|
+
if (keys.some((key) => !allowed.has(key)) || !cloudish && keys.length !== 3 || row.schema !== HUB_BINDING_SCHEMA || typeof row.url !== "string" || typeof row.boundAt !== "string" || !isIsoTimestamp(row.boundAt)) {
|
|
16218
16325
|
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16219
16326
|
}
|
|
16220
16327
|
let url;
|
|
@@ -16223,7 +16330,34 @@ function readHubBinding(env = process.env) {
|
|
|
16223
16330
|
} catch {
|
|
16224
16331
|
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16225
16332
|
}
|
|
16226
|
-
return { schema: HUB_BINDING_SCHEMA, url, boundAt: row.boundAt };
|
|
16333
|
+
if (!cloudish) return { schema: HUB_BINDING_SCHEMA, url, boundAt: row.boundAt };
|
|
16334
|
+
if (row.cloud !== true) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16335
|
+
let tokenEnv;
|
|
16336
|
+
let tokenCommand;
|
|
16337
|
+
if (row.tokenEnv !== void 0) {
|
|
16338
|
+
if (typeof row.tokenEnv !== "string" || !isCloudTokenEnvName(row.tokenEnv)) {
|
|
16339
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16340
|
+
}
|
|
16341
|
+
tokenEnv = row.tokenEnv;
|
|
16342
|
+
}
|
|
16343
|
+
if (row.tokenCommand !== void 0) {
|
|
16344
|
+
if (typeof row.tokenCommand !== "string") throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16345
|
+
try {
|
|
16346
|
+
splitTokenCommand(row.tokenCommand);
|
|
16347
|
+
} catch {
|
|
16348
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16349
|
+
}
|
|
16350
|
+
tokenCommand = row.tokenCommand;
|
|
16351
|
+
}
|
|
16352
|
+
if (!tokenEnv && !tokenCommand) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16353
|
+
return {
|
|
16354
|
+
schema: HUB_BINDING_SCHEMA,
|
|
16355
|
+
url,
|
|
16356
|
+
boundAt: row.boundAt,
|
|
16357
|
+
cloud: true,
|
|
16358
|
+
...tokenEnv ? { tokenEnv } : {},
|
|
16359
|
+
...tokenCommand ? { tokenCommand } : {}
|
|
16360
|
+
};
|
|
16227
16361
|
}
|
|
16228
16362
|
async function probeHubHealth(url, fetchImpl, timeoutMs = HUB_HEALTH_PROBE_MS) {
|
|
16229
16363
|
const started = Date.now();
|
|
@@ -16250,10 +16384,50 @@ async function probeHubHealth(url, fetchImpl, timeoutMs = HUB_HEALTH_PROBE_MS) {
|
|
|
16250
16384
|
}
|
|
16251
16385
|
|
|
16252
16386
|
// plugins/kxm/src/hub-env.ts
|
|
16253
|
-
import { existsSync as
|
|
16387
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync5, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
16254
16388
|
import { homedir as homedir4 } from "node:os";
|
|
16255
16389
|
import { randomBytes } from "node:crypto";
|
|
16256
|
-
import { dirname as
|
|
16390
|
+
import { dirname as dirname5, isAbsolute as isAbsolute2, join as join5, resolve as resolve5 } from "node:path";
|
|
16391
|
+
|
|
16392
|
+
// plugins/kxm/src/project-name.ts
|
|
16393
|
+
var import_yaml2 = __toESM(require_dist(), 1);
|
|
16394
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
16395
|
+
import { basename, dirname as dirname4, join as join4, resolve as resolve4 } from "node:path";
|
|
16396
|
+
function defaultProjectName(cwd, env = process.env, explicit) {
|
|
16397
|
+
const fromExplicit = explicit?.trim();
|
|
16398
|
+
if (fromExplicit) return fromExplicit;
|
|
16399
|
+
const fromEnv = env.KXM_PROJECT?.trim();
|
|
16400
|
+
if (fromEnv) return fromEnv;
|
|
16401
|
+
const fromProject = readProjectYamlId(cwd);
|
|
16402
|
+
if (fromProject) return fromProject;
|
|
16403
|
+
try {
|
|
16404
|
+
const pkg = JSON.parse(readFileSync4(join4(cwd, "package.json"), "utf8"));
|
|
16405
|
+
if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
|
|
16406
|
+
} catch {
|
|
16407
|
+
}
|
|
16408
|
+
return basename(cwd);
|
|
16409
|
+
}
|
|
16410
|
+
function readProjectYamlId(start) {
|
|
16411
|
+
let dir = resolve4(start);
|
|
16412
|
+
for (; ; ) {
|
|
16413
|
+
const file = join4(dir, ".kxm", "project.yaml");
|
|
16414
|
+
if (existsSync4(file)) {
|
|
16415
|
+
try {
|
|
16416
|
+
const doc = (0, import_yaml2.parse)(readFileSync4(file, "utf8"));
|
|
16417
|
+
if (doc && typeof doc === "object" && !Array.isArray(doc) && typeof doc.id === "string" && doc.id.trim()) {
|
|
16418
|
+
return doc.id.trim();
|
|
16419
|
+
}
|
|
16420
|
+
} catch {
|
|
16421
|
+
}
|
|
16422
|
+
return void 0;
|
|
16423
|
+
}
|
|
16424
|
+
const parent = dirname4(dir);
|
|
16425
|
+
if (parent === dir) return void 0;
|
|
16426
|
+
dir = parent;
|
|
16427
|
+
}
|
|
16428
|
+
}
|
|
16429
|
+
|
|
16430
|
+
// plugins/kxm/src/hub-env.ts
|
|
16257
16431
|
var HUB_ENV_SCHEMA = "kxm.hub-env.v1";
|
|
16258
16432
|
var HubEnvError = class extends Error {
|
|
16259
16433
|
constructor(message) {
|
|
@@ -16265,30 +16439,30 @@ function resolveUserStateRoot2(env) {
|
|
|
16265
16439
|
const explicit = env.KXM_STATE_HOME?.trim();
|
|
16266
16440
|
if (explicit) {
|
|
16267
16441
|
if (!isAbsolute2(explicit)) throw new HubEnvError("local_state_root_not_absolute");
|
|
16268
|
-
return
|
|
16442
|
+
return resolve5(explicit);
|
|
16269
16443
|
}
|
|
16270
16444
|
if (process.platform === "win32") {
|
|
16271
16445
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
16272
|
-
const base2 = localAppData && isAbsolute2(localAppData) ? localAppData :
|
|
16273
|
-
return
|
|
16446
|
+
const base2 = localAppData && isAbsolute2(localAppData) ? localAppData : join5(homedir4(), "AppData", "Local");
|
|
16447
|
+
return resolve5(base2, "KXM");
|
|
16274
16448
|
}
|
|
16275
|
-
if (process.platform === "darwin") return
|
|
16449
|
+
if (process.platform === "darwin") return resolve5(homedir4(), "Library", "Application Support", "KXM");
|
|
16276
16450
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
16277
|
-
const base = xdgState && isAbsolute2(xdgState) ? xdgState :
|
|
16278
|
-
return
|
|
16451
|
+
const base = xdgState && isAbsolute2(xdgState) ? xdgState : join5(homedir4(), ".local", "state");
|
|
16452
|
+
return resolve5(base, "kxm");
|
|
16279
16453
|
}
|
|
16280
16454
|
function hubEnvFile(env = process.env) {
|
|
16281
|
-
return
|
|
16455
|
+
return join5(resolveUserStateRoot2(env), "hub-env.json");
|
|
16282
16456
|
}
|
|
16283
16457
|
function generateHubAuthToken() {
|
|
16284
16458
|
return `kxm_admin_${randomBytes(24).toString("base64url")}`;
|
|
16285
16459
|
}
|
|
16286
16460
|
function readHubEnvRecord(env = process.env) {
|
|
16287
16461
|
const file = hubEnvFile(env);
|
|
16288
|
-
if (!
|
|
16462
|
+
if (!existsSync5(file)) return void 0;
|
|
16289
16463
|
let parsed;
|
|
16290
16464
|
try {
|
|
16291
|
-
parsed = JSON.parse(
|
|
16465
|
+
parsed = JSON.parse(readFileSync5(file, "utf8"));
|
|
16292
16466
|
} catch (error2) {
|
|
16293
16467
|
throw new HubEnvError(`hub env file is malformed at ${file}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
16294
16468
|
}
|
|
@@ -16322,9 +16496,9 @@ function readHubEnvRecord(env = process.env) {
|
|
|
16322
16496
|
}
|
|
16323
16497
|
function writeHubEnvRecord(record2, env = process.env) {
|
|
16324
16498
|
const file = hubEnvFile(env);
|
|
16325
|
-
const directory =
|
|
16499
|
+
const directory = dirname5(file);
|
|
16326
16500
|
mkdirSync4(directory, { recursive: true });
|
|
16327
|
-
const temporary =
|
|
16501
|
+
const temporary = join5(directory, `.hub-env-${process.pid}.tmp`);
|
|
16328
16502
|
writeFileSync4(temporary, `${JSON.stringify(record2, void 0, 2)}
|
|
16329
16503
|
`, { encoding: "utf8", mode: 384 });
|
|
16330
16504
|
try {
|
|
@@ -16393,7 +16567,22 @@ function resolveHubCredentials(options = {}) {
|
|
|
16393
16567
|
written: needsPersist === true
|
|
16394
16568
|
};
|
|
16395
16569
|
}
|
|
16570
|
+
function activeCloudBinding(env) {
|
|
16571
|
+
try {
|
|
16572
|
+
const binding = readHubBinding(env);
|
|
16573
|
+
return binding?.cloud ? binding : void 0;
|
|
16574
|
+
} catch (error2) {
|
|
16575
|
+
if (error2 instanceof HubBindingError) {
|
|
16576
|
+
throw new HubEnvError(
|
|
16577
|
+
`${error2.message}; refusing to guess a credential \u2014 repair or remove ${hubBindingFile(env)}`
|
|
16578
|
+
);
|
|
16579
|
+
}
|
|
16580
|
+
throw error2;
|
|
16581
|
+
}
|
|
16582
|
+
}
|
|
16396
16583
|
function resolveAgentHubAuthToken(env, project) {
|
|
16584
|
+
const cloud = activeCloudBinding(env);
|
|
16585
|
+
if (cloud) return resolveCloudHubToken(cloud, env);
|
|
16397
16586
|
const envToken = env.KXM_AUTH_TOKEN?.trim();
|
|
16398
16587
|
if (envToken) return envToken;
|
|
16399
16588
|
const tokens = readHubEnvRecord(env)?.projectTokens;
|
|
@@ -16413,16 +16602,16 @@ var AgentProjectTokenMissingError = class extends Error {
|
|
|
16413
16602
|
};
|
|
16414
16603
|
|
|
16415
16604
|
// plugins/kxm/src/repo-root.ts
|
|
16416
|
-
import { existsSync as
|
|
16417
|
-
import { dirname as
|
|
16605
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
16606
|
+
import { dirname as dirname6, join as join6 } from "node:path";
|
|
16418
16607
|
import { fileURLToPath } from "node:url";
|
|
16419
16608
|
var ROOT_MARKERS = ["scripts/kxm-hub.mjs", "scripts/kxm.mjs"];
|
|
16420
16609
|
var MAX_WALK_DEPTH = 10;
|
|
16421
16610
|
function tryFindKxmRepoRoot(fromUrl = import.meta.url) {
|
|
16422
|
-
let dir =
|
|
16611
|
+
let dir = dirname6(fileURLToPath(fromUrl));
|
|
16423
16612
|
for (let depth = 0; depth < MAX_WALK_DEPTH; depth += 1) {
|
|
16424
|
-
if (ROOT_MARKERS.some((marker) =>
|
|
16425
|
-
const parent =
|
|
16613
|
+
if (ROOT_MARKERS.some((marker) => existsSync6(join6(dir, marker)))) return dir;
|
|
16614
|
+
const parent = dirname6(dir);
|
|
16426
16615
|
if (parent === dir) break;
|
|
16427
16616
|
dir = parent;
|
|
16428
16617
|
}
|
|
@@ -16455,7 +16644,7 @@ function defaultProcessExists(pid) {
|
|
|
16455
16644
|
function readLiveHubClaim(stateDir, processExists2 = defaultProcessExists) {
|
|
16456
16645
|
let parsed;
|
|
16457
16646
|
try {
|
|
16458
|
-
parsed = JSON.parse(
|
|
16647
|
+
parsed = JSON.parse(readFileSync6(join7(stateDir, "hub.pid"), "utf8"));
|
|
16459
16648
|
} catch {
|
|
16460
16649
|
return void 0;
|
|
16461
16650
|
}
|
|
@@ -16470,7 +16659,7 @@ function readLiveHubClaim(stateDir, processExists2 = defaultProcessExists) {
|
|
|
16470
16659
|
};
|
|
16471
16660
|
}
|
|
16472
16661
|
function defaultHubWrapperScriptPath(moduleUrl = import.meta.url) {
|
|
16473
|
-
return
|
|
16662
|
+
return join7(findKxmRepoRoot(moduleUrl), "scripts", "kxm-hub.mjs");
|
|
16474
16663
|
}
|
|
16475
16664
|
function defaultHubSpawner(command, args, options) {
|
|
16476
16665
|
const child = spawn(command, [...args], options);
|
|
@@ -16479,7 +16668,7 @@ function defaultHubSpawner(command, args, options) {
|
|
|
16479
16668
|
}
|
|
16480
16669
|
function logTail(logPath, maxChars = 2e3) {
|
|
16481
16670
|
try {
|
|
16482
|
-
return redactSecrets(
|
|
16671
|
+
return redactSecrets(readFileSync6(logPath, "utf8").trim().slice(-maxChars));
|
|
16483
16672
|
} catch {
|
|
16484
16673
|
return "";
|
|
16485
16674
|
}
|
|
@@ -16492,11 +16681,12 @@ async function ensureHubRunning(options) {
|
|
|
16492
16681
|
if (binding) {
|
|
16493
16682
|
const { health } = await probeHubHealth(binding.url, fetchImpl);
|
|
16494
16683
|
if (health === "on") return { status: "bound-healthy", url: binding.url };
|
|
16684
|
+
if (binding.cloud) return { status: "failed", reason: "cloud_hub_unreachable", logPath: "" };
|
|
16495
16685
|
}
|
|
16496
|
-
const workdir =
|
|
16497
|
-
const workspaceDir =
|
|
16498
|
-
const stateDir =
|
|
16499
|
-
const logsDir =
|
|
16686
|
+
const workdir = resolve6(env.KXM_WORKDIR?.trim() || options.cwd);
|
|
16687
|
+
const workspaceDir = resolve6(workdir, env.KXM_WORKSPACE_DIR?.trim() || ".kxm");
|
|
16688
|
+
const stateDir = resolve6(workdir, env.KXM_STATE_DIR?.trim() || join7(workspaceDir, "state"));
|
|
16689
|
+
const logsDir = resolve6(workdir, env.KXM_LOGS_DIR?.trim() || join7(workspaceDir, "logs"));
|
|
16500
16690
|
const processExists2 = options.processExists ?? defaultProcessExists;
|
|
16501
16691
|
const live = readLiveHubClaim(stateDir, processExists2);
|
|
16502
16692
|
if (live) return { status: "claim-alive", pid: live.pid };
|
|
@@ -16506,7 +16696,7 @@ async function ensureHubRunning(options) {
|
|
|
16506
16696
|
if (health === "on") return { status: "url-healthy", url: serverUrl };
|
|
16507
16697
|
}
|
|
16508
16698
|
const credentials = resolveHubCredentials({ env });
|
|
16509
|
-
const logPath =
|
|
16699
|
+
const logPath = join7(logsDir, HUB_AUTOSTART_LOG_NAME);
|
|
16510
16700
|
mkdirSync5(logsDir, { recursive: true });
|
|
16511
16701
|
const logFd = openSync(logPath, "a");
|
|
16512
16702
|
let child;
|
|
@@ -16553,20 +16743,6 @@ async function ensureHubRunning(options) {
|
|
|
16553
16743
|
}
|
|
16554
16744
|
}
|
|
16555
16745
|
|
|
16556
|
-
// plugins/kxm/src/project-name.ts
|
|
16557
|
-
import { readFileSync as readFileSync6 } from "node:fs";
|
|
16558
|
-
import { basename, join as join7 } from "node:path";
|
|
16559
|
-
function defaultProjectName(cwd, env = process.env) {
|
|
16560
|
-
const fromEnv = env.KXM_PROJECT?.trim();
|
|
16561
|
-
if (fromEnv) return fromEnv;
|
|
16562
|
-
try {
|
|
16563
|
-
const pkg = JSON.parse(readFileSync6(join7(cwd, "package.json"), "utf8"));
|
|
16564
|
-
if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
|
|
16565
|
-
} catch {
|
|
16566
|
-
}
|
|
16567
|
-
return basename(cwd);
|
|
16568
|
-
}
|
|
16569
|
-
|
|
16570
16746
|
// plugins/kxm/src/nous-pi.ts
|
|
16571
16747
|
import { readFile } from "node:fs/promises";
|
|
16572
16748
|
|
|
@@ -18437,7 +18613,7 @@ function closeServerGracefully(server) {
|
|
|
18437
18613
|
server.close();
|
|
18438
18614
|
}
|
|
18439
18615
|
function startCallbackServer(expectedState) {
|
|
18440
|
-
return new Promise((
|
|
18616
|
+
return new Promise((resolve9, reject) => {
|
|
18441
18617
|
let settled = false;
|
|
18442
18618
|
let timeout;
|
|
18443
18619
|
let resolveCode;
|
|
@@ -18516,7 +18692,7 @@ function startCallbackServer(expectedState) {
|
|
|
18516
18692
|
finish(() => rejectCode(new Error("OAuth callback timed out waiting for browser login")));
|
|
18517
18693
|
close();
|
|
18518
18694
|
}, OAUTH_CALLBACK_TIMEOUT_MS);
|
|
18519
|
-
|
|
18695
|
+
resolve9({ server, waitForCode: () => codePromise, cleanup });
|
|
18520
18696
|
});
|
|
18521
18697
|
});
|
|
18522
18698
|
}
|
|
@@ -19135,8 +19311,8 @@ var AssistantMessageEventStream = class {
|
|
|
19135
19311
|
finalResultPromise;
|
|
19136
19312
|
resolveFinalResult;
|
|
19137
19313
|
constructor() {
|
|
19138
|
-
this.finalResultPromise = new Promise((
|
|
19139
|
-
this.resolveFinalResult =
|
|
19314
|
+
this.finalResultPromise = new Promise((resolve9) => {
|
|
19315
|
+
this.resolveFinalResult = resolve9;
|
|
19140
19316
|
});
|
|
19141
19317
|
}
|
|
19142
19318
|
push(event) {
|
|
@@ -19166,8 +19342,8 @@ var AssistantMessageEventStream = class {
|
|
|
19166
19342
|
} else if (this.done) {
|
|
19167
19343
|
return;
|
|
19168
19344
|
} else {
|
|
19169
|
-
const next = await new Promise((
|
|
19170
|
-
this.waiting.push(
|
|
19345
|
+
const next = await new Promise((resolve9) => {
|
|
19346
|
+
this.waiting.push(resolve9);
|
|
19171
19347
|
});
|
|
19172
19348
|
if (next.done) return;
|
|
19173
19349
|
if (next.value) yield next.value;
|
|
@@ -20486,8 +20662,8 @@ var AssistantMessageEventStream2 = class {
|
|
|
20486
20662
|
finalResultPromise;
|
|
20487
20663
|
resolveFinalResult;
|
|
20488
20664
|
constructor() {
|
|
20489
|
-
this.finalResultPromise = new Promise((
|
|
20490
|
-
this.resolveFinalResult =
|
|
20665
|
+
this.finalResultPromise = new Promise((resolve9) => {
|
|
20666
|
+
this.resolveFinalResult = resolve9;
|
|
20491
20667
|
});
|
|
20492
20668
|
}
|
|
20493
20669
|
push(event) {
|
|
@@ -20517,8 +20693,8 @@ var AssistantMessageEventStream2 = class {
|
|
|
20517
20693
|
} else if (this.done) {
|
|
20518
20694
|
return;
|
|
20519
20695
|
} else {
|
|
20520
|
-
const next = await new Promise((
|
|
20521
|
-
this.waiting.push(
|
|
20696
|
+
const next = await new Promise((resolve9) => {
|
|
20697
|
+
this.waiting.push(resolve9);
|
|
20522
20698
|
});
|
|
20523
20699
|
if (next.done) return;
|
|
20524
20700
|
if (next.value) yield next.value;
|
|
@@ -20544,11 +20720,11 @@ function emptyUsage() {
|
|
|
20544
20720
|
}
|
|
20545
20721
|
|
|
20546
20722
|
// plugins/kxm/src/providers/claude-bridge/config.ts
|
|
20547
|
-
import { existsSync as
|
|
20723
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
|
|
20548
20724
|
import { homedir as homedir5 } from "node:os";
|
|
20549
20725
|
import { join as join8 } from "node:path";
|
|
20550
20726
|
function tryParseJson(path) {
|
|
20551
|
-
if (!
|
|
20727
|
+
if (!existsSync7(path)) return {};
|
|
20552
20728
|
try {
|
|
20553
20729
|
return JSON.parse(readFileSync7(path, "utf-8"));
|
|
20554
20730
|
} catch (error2) {
|
|
@@ -33576,7 +33752,7 @@ var Protocol = class {
|
|
|
33576
33752
|
return;
|
|
33577
33753
|
}
|
|
33578
33754
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
33579
|
-
await new Promise((
|
|
33755
|
+
await new Promise((resolve9) => setTimeout(resolve9, pollInterval));
|
|
33580
33756
|
options?.signal?.throwIfAborted();
|
|
33581
33757
|
}
|
|
33582
33758
|
} catch (error2) {
|
|
@@ -33593,7 +33769,7 @@ var Protocol = class {
|
|
|
33593
33769
|
*/
|
|
33594
33770
|
request(request, resultSchema, options) {
|
|
33595
33771
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
33596
|
-
return new Promise((
|
|
33772
|
+
return new Promise((resolve9, reject) => {
|
|
33597
33773
|
const earlyReject = (error2) => {
|
|
33598
33774
|
reject(error2);
|
|
33599
33775
|
};
|
|
@@ -33671,7 +33847,7 @@ var Protocol = class {
|
|
|
33671
33847
|
if (!parseResult.success) {
|
|
33672
33848
|
reject(parseResult.error);
|
|
33673
33849
|
} else {
|
|
33674
|
-
|
|
33850
|
+
resolve9(parseResult.data);
|
|
33675
33851
|
}
|
|
33676
33852
|
} catch (error2) {
|
|
33677
33853
|
reject(error2);
|
|
@@ -33932,12 +34108,12 @@ var Protocol = class {
|
|
|
33932
34108
|
}
|
|
33933
34109
|
} catch {
|
|
33934
34110
|
}
|
|
33935
|
-
return new Promise((
|
|
34111
|
+
return new Promise((resolve9, reject) => {
|
|
33936
34112
|
if (signal.aborted) {
|
|
33937
34113
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
33938
34114
|
return;
|
|
33939
34115
|
}
|
|
33940
|
-
const timeoutId = setTimeout(
|
|
34116
|
+
const timeoutId = setTimeout(resolve9, interval);
|
|
33941
34117
|
signal.addEventListener("abort", () => {
|
|
33942
34118
|
clearTimeout(timeoutId);
|
|
33943
34119
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -35028,7 +35204,7 @@ var McpServer = class {
|
|
|
35028
35204
|
let task = createTaskResult.task;
|
|
35029
35205
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
35030
35206
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
35031
|
-
await new Promise((
|
|
35207
|
+
await new Promise((resolve9) => setTimeout(resolve9, pollInterval));
|
|
35032
35208
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
35033
35209
|
if (!updatedTask) {
|
|
35034
35210
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -35646,8 +35822,8 @@ function makePromptStream() {
|
|
|
35646
35822
|
try {
|
|
35647
35823
|
while (true) {
|
|
35648
35824
|
while (queue.length === 0 && !done && !failure) {
|
|
35649
|
-
await new Promise((
|
|
35650
|
-
wake =
|
|
35825
|
+
await new Promise((resolve9) => {
|
|
35826
|
+
wake = resolve9;
|
|
35651
35827
|
});
|
|
35652
35828
|
}
|
|
35653
35829
|
if (failure) throw failure;
|
|
@@ -35668,8 +35844,8 @@ function makePromptStream() {
|
|
|
35668
35844
|
}
|
|
35669
35845
|
return {
|
|
35670
35846
|
stream: gen(),
|
|
35671
|
-
push: (msg) => failure || done ? Promise.reject(failure ?? new Error("prompt stream closed")) : new Promise((
|
|
35672
|
-
queue.push({ msg, resolve:
|
|
35847
|
+
push: (msg) => failure || done ? Promise.reject(failure ?? new Error("prompt stream closed")) : new Promise((resolve9, reject) => {
|
|
35848
|
+
queue.push({ msg, resolve: resolve9, reject });
|
|
35673
35849
|
kick();
|
|
35674
35850
|
}),
|
|
35675
35851
|
end: () => {
|
|
@@ -36080,8 +36256,8 @@ function buildMcpServers(tools, queryCtx) {
|
|
|
36080
36256
|
queryCtx.pendingResults.delete(toolCallId);
|
|
36081
36257
|
return result2;
|
|
36082
36258
|
}
|
|
36083
|
-
return new Promise((
|
|
36084
|
-
queryCtx.pendingToolCalls.set(toolCallId, { toolName: tool.name, resolve:
|
|
36259
|
+
return new Promise((resolve9) => {
|
|
36260
|
+
queryCtx.pendingToolCalls.set(toolCallId, { toolName: tool.name, resolve: resolve9 });
|
|
36085
36261
|
});
|
|
36086
36262
|
}
|
|
36087
36263
|
}));
|
|
@@ -36601,20 +36777,20 @@ async function consumeWorkerRecoveryEnvelope(client, stateDir, agentName, projec
|
|
|
36601
36777
|
}
|
|
36602
36778
|
|
|
36603
36779
|
// plugins/kxm/src/session-work.ts
|
|
36604
|
-
import { spawnSync } from "node:child_process";
|
|
36780
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
36605
36781
|
import { randomUUID } from "node:crypto";
|
|
36606
|
-
import { existsSync as
|
|
36782
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync12, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
36607
36783
|
import { join as join13 } from "node:path";
|
|
36608
36784
|
|
|
36609
36785
|
// plugins/kxm/src/local-snapshot.ts
|
|
36610
|
-
import { existsSync as
|
|
36786
|
+
import { existsSync as existsSync9, readdirSync, readFileSync as readFileSync10 } from "node:fs";
|
|
36611
36787
|
import { homedir as homedir6 } from "node:os";
|
|
36612
|
-
import { isAbsolute as isAbsolute3, join as join11, resolve as
|
|
36788
|
+
import { isAbsolute as isAbsolute3, join as join11, resolve as resolve8 } from "node:path";
|
|
36613
36789
|
|
|
36614
36790
|
// plugins/kxm/src/sqlite.ts
|
|
36615
|
-
import { existsSync as
|
|
36791
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
36616
36792
|
import { createRequire as createRequire2 } from "node:module";
|
|
36617
|
-
import { resolve as
|
|
36793
|
+
import { resolve as resolve7 } from "node:path";
|
|
36618
36794
|
import { pathToFileURL } from "node:url";
|
|
36619
36795
|
var requireFromHere = createRequire2(import.meta.url);
|
|
36620
36796
|
function loadNative() {
|
|
@@ -36653,15 +36829,15 @@ var DatabaseSync = class {
|
|
|
36653
36829
|
}
|
|
36654
36830
|
};
|
|
36655
36831
|
function openReadOnlyDatabase(path) {
|
|
36656
|
-
if (
|
|
36657
|
-
const uri = pathToFileURL(
|
|
36832
|
+
if (existsSync8(`${path}-wal`)) return new DatabaseSync(path, { readOnly: true });
|
|
36833
|
+
const uri = pathToFileURL(resolve7(path));
|
|
36658
36834
|
uri.searchParams.set("immutable", "1");
|
|
36659
36835
|
return new DatabaseSync(uri.href, { readOnly: true });
|
|
36660
36836
|
}
|
|
36661
36837
|
|
|
36662
36838
|
// plugins/kxm/src/telemetry.ts
|
|
36663
36839
|
import { appendFileSync, mkdirSync as mkdirSync6, readFileSync as readFileSync9 } from "node:fs";
|
|
36664
|
-
import { dirname as
|
|
36840
|
+
import { dirname as dirname7, join as join10 } from "node:path";
|
|
36665
36841
|
function telemetryPath(logsDir) {
|
|
36666
36842
|
return join10(logsDir, "telemetry.jsonl");
|
|
36667
36843
|
}
|
|
@@ -36825,34 +37001,34 @@ function readOpenMessageMetadata(database, where = OPEN_MESSAGE_WHERE, params =
|
|
|
36825
37001
|
function resolveKxmSnapshotPaths(cwd, env = process.env) {
|
|
36826
37002
|
const stateDir = env.KXM_STATE_DIR?.trim() || join11(cwd, ".kxm", "state");
|
|
36827
37003
|
const configured = env.KXM_DATA_PATH?.trim();
|
|
36828
|
-
const dataPath = configured ?
|
|
37004
|
+
const dataPath = configured ? resolve8(cwd, configured) : join11(stateDir, "kxm.db");
|
|
36829
37005
|
return { dataPath, stateDir };
|
|
36830
37006
|
}
|
|
36831
37007
|
function resolveKxmStateRoot(stateDir, options) {
|
|
36832
|
-
if (options?.kxmStateRoot &&
|
|
36833
|
-
return
|
|
37008
|
+
if (options?.kxmStateRoot && existsSync9(options.kxmStateRoot)) {
|
|
37009
|
+
return resolve8(options.kxmStateRoot);
|
|
36834
37010
|
}
|
|
36835
|
-
if (
|
|
37011
|
+
if (existsSync9(join11(stateDir, "runtime", "registry.db")) || existsSync9(join11(stateDir, "runtime", "projects"))) {
|
|
36836
37012
|
return stateDir;
|
|
36837
37013
|
}
|
|
36838
37014
|
const env = options?.env ?? process.env;
|
|
36839
37015
|
const explicit = env.KXM_STATE_HOME?.trim() || env.KXM_USER_STATE_DIR?.trim() || env.KXM_STATE_ROOT?.trim();
|
|
36840
|
-
if (explicit && isAbsolute3(explicit) &&
|
|
36841
|
-
return
|
|
37016
|
+
if (explicit && isAbsolute3(explicit) && existsSync9(resolve8(explicit))) {
|
|
37017
|
+
return resolve8(explicit);
|
|
36842
37018
|
}
|
|
36843
37019
|
let base;
|
|
36844
37020
|
if (process.platform === "win32") {
|
|
36845
37021
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
36846
37022
|
base = localAppData && isAbsolute3(localAppData) ? localAppData : join11(homedir6(), "AppData", "Local");
|
|
36847
|
-
base =
|
|
37023
|
+
base = resolve8(base, "KXM");
|
|
36848
37024
|
} else if (process.platform === "darwin") {
|
|
36849
|
-
base =
|
|
37025
|
+
base = resolve8(homedir6(), "Library", "Application Support", "KXM");
|
|
36850
37026
|
} else {
|
|
36851
37027
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
36852
37028
|
base = xdgState && isAbsolute3(xdgState) ? xdgState : join11(homedir6(), ".local", "state");
|
|
36853
|
-
base =
|
|
37029
|
+
base = resolve8(base, "kxm");
|
|
36854
37030
|
}
|
|
36855
|
-
if (
|
|
37031
|
+
if (existsSync9(base)) return base;
|
|
36856
37032
|
return void 0;
|
|
36857
37033
|
}
|
|
36858
37034
|
function readRuntimeRuns(eventDb, projectId) {
|
|
@@ -36885,7 +37061,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
36885
37061
|
let legacyRuns = [];
|
|
36886
37062
|
let legacyRunTotal = 0;
|
|
36887
37063
|
let plans = [];
|
|
36888
|
-
if (
|
|
37064
|
+
if (existsSync9(dataPath)) {
|
|
36889
37065
|
hasLegacy = true;
|
|
36890
37066
|
const database = openReadOnlyDatabase(dataPath);
|
|
36891
37067
|
try {
|
|
@@ -36920,7 +37096,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
36920
37096
|
const registryDbPath = join11(runtimeDir, "registry.db");
|
|
36921
37097
|
const projectsDir = join11(runtimeDir, "projects");
|
|
36922
37098
|
const projectKeys = /* @__PURE__ */ new Set();
|
|
36923
|
-
if (
|
|
37099
|
+
if (existsSync9(registryDbPath)) {
|
|
36924
37100
|
hasKxm = true;
|
|
36925
37101
|
try {
|
|
36926
37102
|
const regDb = openReadOnlyDatabase(registryDbPath);
|
|
@@ -36936,7 +37112,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
36936
37112
|
} catch {
|
|
36937
37113
|
}
|
|
36938
37114
|
}
|
|
36939
|
-
if (!scope &&
|
|
37115
|
+
if (!scope && existsSync9(projectsDir)) {
|
|
36940
37116
|
try {
|
|
36941
37117
|
for (const entry of readdirSync(projectsDir, { withFileTypes: true })) {
|
|
36942
37118
|
if (entry.isDirectory()) {
|
|
@@ -36949,7 +37125,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
36949
37125
|
for (const key of projectKeys) {
|
|
36950
37126
|
if (scope && !RUNTIME_PROJECT_KEY.test(key)) continue;
|
|
36951
37127
|
const eventDbPath = join11(projectsDir, key, "run-events.db");
|
|
36952
|
-
if (
|
|
37128
|
+
if (existsSync9(eventDbPath)) {
|
|
36953
37129
|
hasKxm = true;
|
|
36954
37130
|
try {
|
|
36955
37131
|
const eventDb = openReadOnlyDatabase(eventDbPath);
|
|
@@ -36967,7 +37143,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
36967
37143
|
}
|
|
36968
37144
|
}
|
|
36969
37145
|
const pids = [];
|
|
36970
|
-
if (
|
|
37146
|
+
if (existsSync9(stateDir)) {
|
|
36971
37147
|
for (const file of readdirSync(stateDir).filter((name) => name.endsWith(".pid"))) {
|
|
36972
37148
|
try {
|
|
36973
37149
|
const record2 = JSON.parse(readFileSync10(join11(stateDir, file), "utf8"));
|
|
@@ -37010,7 +37186,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
37010
37186
|
source = "legacy";
|
|
37011
37187
|
}
|
|
37012
37188
|
const telemetryFile = join11(stateDir, "telemetry.jsonl");
|
|
37013
|
-
const spend =
|
|
37189
|
+
const spend = existsSync9(telemetryFile) ? readRoutingRecords(telemetryFile) : [];
|
|
37014
37190
|
return {
|
|
37015
37191
|
source,
|
|
37016
37192
|
agents: agents.sort((a, b) => Number(b.online) - Number(a.online) || a.name.localeCompare(b.name)),
|
|
@@ -37025,13 +37201,13 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
37025
37201
|
}
|
|
37026
37202
|
|
|
37027
37203
|
// plugins/kxm/src/kxm-update.ts
|
|
37028
|
-
import { existsSync as
|
|
37204
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync7 } from "node:fs";
|
|
37029
37205
|
import { join as join12 } from "node:path";
|
|
37030
37206
|
var KXM_UPDATE_CACHE = "update-check.json";
|
|
37031
37207
|
var CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
37032
37208
|
function readUpdateCache(stateDir, now = Date.now()) {
|
|
37033
37209
|
const path = join12(stateDir, KXM_UPDATE_CACHE);
|
|
37034
|
-
if (!
|
|
37210
|
+
if (!existsSync10(path)) return void 0;
|
|
37035
37211
|
try {
|
|
37036
37212
|
const row = JSON.parse(readFileSync11(path, "utf8"));
|
|
37037
37213
|
if (typeof row.checkedAt !== "number" || !row.notice || now - row.checkedAt > CACHE_TTL_MS) return void 0;
|
|
@@ -37099,10 +37275,10 @@ function formatShipLine(ship) {
|
|
|
37099
37275
|
}
|
|
37100
37276
|
function readGitShip(cwd) {
|
|
37101
37277
|
try {
|
|
37102
|
-
const dirty =
|
|
37278
|
+
const dirty = spawnSync2("git", ["--no-optional-locks", "-C", cwd, "status", "--porcelain"], { encoding: "utf8", windowsHide: true });
|
|
37103
37279
|
if (dirty.status !== 0) return void 0;
|
|
37104
37280
|
const isDirty2 = dirty.stdout.trim().length > 0;
|
|
37105
|
-
const upstream =
|
|
37281
|
+
const upstream = spawnSync2("git", ["-C", cwd, "rev-list", "--count", "@{u}..HEAD"], { encoding: "utf8", windowsHide: true });
|
|
37106
37282
|
if (upstream.status === 0) {
|
|
37107
37283
|
return {
|
|
37108
37284
|
dirty: isDirty2,
|
|
@@ -37110,9 +37286,9 @@ function readGitShip(cwd) {
|
|
|
37110
37286
|
};
|
|
37111
37287
|
}
|
|
37112
37288
|
for (const baseRef of ["origin/HEAD", "main", "origin/main", "master", "origin/master"]) {
|
|
37113
|
-
const mb =
|
|
37289
|
+
const mb = spawnSync2("git", ["-C", cwd, "merge-base", baseRef, "HEAD"], { encoding: "utf8", windowsHide: true });
|
|
37114
37290
|
if (mb.status === 0 && mb.stdout.trim()) {
|
|
37115
|
-
const count =
|
|
37291
|
+
const count = spawnSync2("git", ["-C", cwd, "rev-list", "--count", `${mb.stdout.trim()}..HEAD`], { encoding: "utf8", windowsHide: true });
|
|
37116
37292
|
if (count.status === 0) {
|
|
37117
37293
|
return {
|
|
37118
37294
|
dirty: isDirty2,
|
|
@@ -37202,7 +37378,7 @@ function buildSessionBrief(snapshot, current, hub, ship, updateLatest, cost, ses
|
|
|
37202
37378
|
function readCachedSessionBrief(stateDir) {
|
|
37203
37379
|
const file = join13(stateDir, "session-brief.json");
|
|
37204
37380
|
try {
|
|
37205
|
-
if (!
|
|
37381
|
+
if (!existsSync11(file)) return void 0;
|
|
37206
37382
|
const raw = readFileSync12(file, "utf8");
|
|
37207
37383
|
const parsed = JSON.parse(raw);
|
|
37208
37384
|
if (parsed && parsed.schema === "kxm.session-brief.v1" && typeof parsed.generatedAt === "string") {
|
|
@@ -37229,7 +37405,7 @@ function writeCachedSessionBrief(stateDir, brief) {
|
|
|
37229
37405
|
function estimateSessionCost(stateDir) {
|
|
37230
37406
|
try {
|
|
37231
37407
|
const telemetryFile = join13(stateDir, "telemetry.jsonl");
|
|
37232
|
-
if (!
|
|
37408
|
+
if (!existsSync11(telemetryFile)) return void 0;
|
|
37233
37409
|
const records = readRoutingRecords(telemetryFile);
|
|
37234
37410
|
if (records.length === 0) return void 0;
|
|
37235
37411
|
let totalCost = 0;
|
|
@@ -37404,11 +37580,11 @@ function kxmSlashCompletions(prefix) {
|
|
|
37404
37580
|
}
|
|
37405
37581
|
|
|
37406
37582
|
// plugins/kxm/src/workflow-tui.ts
|
|
37407
|
-
import { existsSync as
|
|
37583
|
+
import { existsSync as existsSync12, readFileSync as readFileSync13 } from "node:fs";
|
|
37408
37584
|
import { join as join14 } from "node:path";
|
|
37409
37585
|
function loadActiveWorkflowProgress(repoRoot = process.cwd(), targetRunId) {
|
|
37410
37586
|
const dbPath = join14(repoConfigDirectory(repoRoot), "state", "kxm.db");
|
|
37411
|
-
if (!
|
|
37587
|
+
if (!existsSync12(dbPath)) return void 0;
|
|
37412
37588
|
let db;
|
|
37413
37589
|
try {
|
|
37414
37590
|
db = new DatabaseSync(dbPath, { readOnly: true });
|
|
@@ -37445,7 +37621,7 @@ function loadActiveWorkflowProgress(repoRoot = process.cwd(), targetRunId) {
|
|
|
37445
37621
|
try {
|
|
37446
37622
|
const logsDir = join14(repoConfigDirectory(repoRoot), "logs");
|
|
37447
37623
|
const telemFile = telemetryPath(logsDir);
|
|
37448
|
-
if (
|
|
37624
|
+
if (existsSync12(telemFile)) {
|
|
37449
37625
|
const records = readRoutingRecords(telemFile);
|
|
37450
37626
|
const routingRunId = (routing) => "runId" in routing ? routing.runId : routing.workflowRunId;
|
|
37451
37627
|
let matching = records.filter((r) => routingRunId(r.routing) === runId);
|
|
@@ -37737,7 +37913,7 @@ function piMeshExtension(pi) {
|
|
|
37737
37913
|
messageId: message.id,
|
|
37738
37914
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
37739
37915
|
};
|
|
37740
|
-
mkdirSync9(
|
|
37916
|
+
mkdirSync9(dirname8(path), { recursive: true });
|
|
37741
37917
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
37742
37918
|
writeFileSync7(tmp, `${JSON.stringify(request)}
|
|
37743
37919
|
`, { encoding: "utf8", mode: 384 });
|
|
@@ -37768,7 +37944,7 @@ function piMeshExtension(pi) {
|
|
|
37768
37944
|
removeMatchingLegacyRecoveryContext();
|
|
37769
37945
|
return;
|
|
37770
37946
|
}
|
|
37771
|
-
mkdirSync9(
|
|
37947
|
+
mkdirSync9(dirname8(path), { recursive: true });
|
|
37772
37948
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
37773
37949
|
writeFileSync7(tmp, `${JSON.stringify({ version: 1, agentName, project: projectName, runId: runId ?? null, stageId: recoveryStageId ?? null, activeMessageIds, pendingMessageIds, artifactPointers: recoveryArtifacts.slice(0, 16), updatedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
37774
37950
|
`, { encoding: "utf8", mode: 384 });
|
|
@@ -37818,7 +37994,7 @@ function piMeshExtension(pi) {
|
|
|
37818
37994
|
ctx2.ui.setEditorText?.(item.prompt);
|
|
37819
37995
|
}
|
|
37820
37996
|
async function showKxmHub(ctx2) {
|
|
37821
|
-
const url = (process.env
|
|
37997
|
+
const url = resolveHubServerUrl(process.env);
|
|
37822
37998
|
let health = "unreachable";
|
|
37823
37999
|
try {
|
|
37824
38000
|
const response = await fetch(`${url}/health`);
|
|
@@ -38108,7 +38284,7 @@ function piMeshExtension(pi) {
|
|
|
38108
38284
|
return;
|
|
38109
38285
|
}
|
|
38110
38286
|
currentPiSessionId = ctx2.sessionManager?.getSessionId();
|
|
38111
|
-
const serverUrl = process.env
|
|
38287
|
+
const serverUrl = resolveHubServerUrl(process.env);
|
|
38112
38288
|
const project = defaultProjectName(ctx2.cwd, process.env);
|
|
38113
38289
|
const name = process.env.KXM_AGENT_NAME ?? pi.getSessionName() ?? `pi-${process.pid}`;
|
|
38114
38290
|
agentName = name;
|
|
@@ -38137,7 +38313,8 @@ function piMeshExtension(pi) {
|
|
|
38137
38313
|
try {
|
|
38138
38314
|
hubAuthToken = resolveAgentHubAuthToken(process.env, project);
|
|
38139
38315
|
} catch (error2) {
|
|
38140
|
-
|
|
38316
|
+
const detail = error2 instanceof CloudTokenError ? error2.message : `kxm could not read persisted hub credentials: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
38317
|
+
ctx2.ui.notify(detail, "error");
|
|
38141
38318
|
await applySessionChrome(ctx2, event, true);
|
|
38142
38319
|
return;
|
|
38143
38320
|
}
|
|
@@ -38356,12 +38533,12 @@ function piMeshExtension(pi) {
|
|
|
38356
38533
|
if (command === "memory") {
|
|
38357
38534
|
const cwd = typeof ctx2.cwd === "string" ? ctx2.cwd : process.cwd();
|
|
38358
38535
|
const kxmBin = process.env.KXM_BIN || "kxm";
|
|
38359
|
-
const res =
|
|
38536
|
+
const res = spawnSync3(kxmBin, ["memory", "brief"], { cwd, encoding: "utf8", windowsHide: true });
|
|
38360
38537
|
let memText = res.status === 0 && res.stdout ? res.stdout.trim() : "";
|
|
38361
38538
|
if (!memText) {
|
|
38362
38539
|
const script = join15(cwd, "scripts", "kxm.mjs");
|
|
38363
|
-
if (
|
|
38364
|
-
const scriptRes =
|
|
38540
|
+
if (existsSync13(script)) {
|
|
38541
|
+
const scriptRes = spawnSync3(process.execPath, [script, "memory", "brief"], { cwd, encoding: "utf8", windowsHide: true });
|
|
38365
38542
|
if (scriptRes.status === 0 && scriptRes.stdout) memText = scriptRes.stdout.trim();
|
|
38366
38543
|
}
|
|
38367
38544
|
}
|