@kontextmind/kxm 0.7.167 → 0.7.169
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 +30 -0
- package/docs/contributing/ci-and-release.md +6 -1
- package/docs/operations/runtime-sync.md +2 -1
- package/docs/operations/troubleshooting.md +4 -0
- package/docs/operations/upgrade.md +18 -3
- package/docs/operations.md +70 -7
- package/docs/reference/cli-reference.md +21 -6
- package/docs/reference/config-reference.md +28 -13
- package/docs/start/install.md +1 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/claude-hook.js +170 -36
- package/plugins/kxm/dist/cli.js +451 -132
- package/plugins/kxm/dist/extension.js +184 -53
- package/plugins/kxm/dist/mcp-server.js +97 -40
- package/plugins/kxm/dist/runtime-supervisor.js +240 -47
- package/plugins/kxm/dist/runtime.js +240 -47
- package/plugins/kxm/dist/server.js +9 -0
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm-definitions/SKILL.md +3 -2
- package/plugins/kxm/skills/kxm-harness-auth/SKILL.md +4 -2
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +9 -4
- package/plugins/kxm/src/cli/hub.ts +42 -7
- package/plugins/kxm/src/cli/system.ts +3 -1
- package/plugins/kxm/src/cli/types.ts +5 -3
- package/plugins/kxm/src/cli.ts +2 -1
- package/plugins/kxm/src/engine.ts +105 -8
- package/plugins/kxm/src/hub-binding.ts +301 -55
- package/plugins/kxm/src/hub-identity.ts +17 -9
- package/plugins/kxm/src/kxm-update.ts +29 -6
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/project-config.ts +63 -1
- package/plugins/kxm/src/runtime-supervisor.ts +22 -4
- package/scripts/kxm-publish-npm.mjs +47 -1
|
@@ -16349,6 +16349,9 @@ function resolveUserStateRoot(env) {
|
|
|
16349
16349
|
function hubBindingFile(env = process.env) {
|
|
16350
16350
|
return join3(resolveUserStateRoot(env), "hub-binding.json");
|
|
16351
16351
|
}
|
|
16352
|
+
function hubBindingCloudFile(env = process.env) {
|
|
16353
|
+
return join3(resolveUserStateRoot(env), "hub-binding.cloud.json");
|
|
16354
|
+
}
|
|
16352
16355
|
function validateHubUrl(raw) {
|
|
16353
16356
|
let parsed;
|
|
16354
16357
|
try {
|
|
@@ -16463,33 +16466,37 @@ function isAbortError(error2) {
|
|
|
16463
16466
|
error2 && typeof error2 === "object" && ("name" in error2 && error2.name === "AbortError" || "code" in error2 && error2.code === "ABORT_ERR")
|
|
16464
16467
|
);
|
|
16465
16468
|
}
|
|
16466
|
-
|
|
16467
|
-
|
|
16468
|
-
|
|
16469
|
+
var LEGACY_BINDING_KEYS = ["schema", "url", "boundAt"];
|
|
16470
|
+
var BINDING_KEYS = /* @__PURE__ */ new Set([...LEGACY_BINDING_KEYS, "cloud", "tokenEnv", "tokenCommand"]);
|
|
16471
|
+
function bindingFallbackWarning(file, reason) {
|
|
16472
|
+
return `hub binding at ${file} ${reason}; falling back to the local hub. Restart the Runtime supervisor, the hub, and workers after upgrading and before a cloud bind.`;
|
|
16473
|
+
}
|
|
16474
|
+
function writeBindingJson(file, value) {
|
|
16475
|
+
mkdirSync3(dirname3(file), { recursive: true, mode: 448 });
|
|
16476
|
+
const temporary = join3(dirname3(file), `.${file.endsWith("cloud.json") ? "hub-binding-cloud" : "hub-binding"}-${process.pid}.tmp`);
|
|
16477
|
+
try {
|
|
16478
|
+
writeFileSync3(temporary, `${JSON.stringify(value, null, 2)}
|
|
16479
|
+
`, { encoding: "utf8", mode: 384 });
|
|
16480
|
+
renameSync(temporary, file);
|
|
16481
|
+
} finally {
|
|
16482
|
+
rmSync(temporary, { force: true });
|
|
16483
|
+
}
|
|
16484
|
+
}
|
|
16485
|
+
function parseBindingObject(file) {
|
|
16486
|
+
if (!existsSync3(file)) return new HubBindingError(`missing hub binding at ${file}`);
|
|
16469
16487
|
let parsed;
|
|
16470
16488
|
try {
|
|
16471
16489
|
parsed = JSON.parse(readFileSync3(file, "utf8"));
|
|
16472
16490
|
} catch {
|
|
16473
|
-
|
|
16491
|
+
return new HubBindingError(`malformed hub binding at ${file}`);
|
|
16474
16492
|
}
|
|
16475
16493
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
16476
|
-
|
|
16494
|
+
return new HubBindingError(`malformed hub binding at ${file}`);
|
|
16477
16495
|
}
|
|
16478
|
-
|
|
16479
|
-
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
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)) {
|
|
16483
|
-
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16484
|
-
}
|
|
16485
|
-
let url;
|
|
16486
|
-
try {
|
|
16487
|
-
url = validateHubUrl(row.url);
|
|
16488
|
-
} catch {
|
|
16489
|
-
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16490
|
-
}
|
|
16491
|
-
if (!cloudish) return { schema: HUB_BINDING_SCHEMA, url, boundAt: row.boundAt };
|
|
16492
|
-
if (row.cloud !== true) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16496
|
+
return parsed;
|
|
16497
|
+
}
|
|
16498
|
+
function cloudRecordFromRow(file, row, url, boundAt) {
|
|
16499
|
+
if (row.cloud !== true) return void 0;
|
|
16493
16500
|
let tokenEnv;
|
|
16494
16501
|
let tokenCommand;
|
|
16495
16502
|
if (row.tokenEnv !== void 0) {
|
|
@@ -16511,31 +16518,158 @@ function readHubBinding(env = process.env) {
|
|
|
16511
16518
|
return {
|
|
16512
16519
|
schema: HUB_BINDING_SCHEMA,
|
|
16513
16520
|
url,
|
|
16514
|
-
boundAt
|
|
16521
|
+
boundAt,
|
|
16515
16522
|
cloud: true,
|
|
16516
16523
|
...tokenEnv ? { tokenEnv } : {},
|
|
16517
16524
|
...tokenCommand ? { tokenCommand } : {}
|
|
16518
16525
|
};
|
|
16519
16526
|
}
|
|
16527
|
+
function interpretBindingFile(file) {
|
|
16528
|
+
if (!existsSync3(file)) return {};
|
|
16529
|
+
const parsed = parseBindingObject(file);
|
|
16530
|
+
if (parsed instanceof HubBindingError) throw parsed;
|
|
16531
|
+
const keys = Object.keys(parsed);
|
|
16532
|
+
const unknown2 = keys.filter((key) => !BINDING_KEYS.has(key));
|
|
16533
|
+
if (parsed.schema !== HUB_BINDING_SCHEMA || unknown2.length > 0) {
|
|
16534
|
+
return { warning: bindingFallbackWarning(file, `is newer than this build understands (${String(parsed.schema)})`) };
|
|
16535
|
+
}
|
|
16536
|
+
if (typeof parsed.url !== "string" || typeof parsed.boundAt !== "string" || !isIsoTimestamp(parsed.boundAt)) {
|
|
16537
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16538
|
+
}
|
|
16539
|
+
let url;
|
|
16540
|
+
try {
|
|
16541
|
+
url = validateHubUrl(parsed.url);
|
|
16542
|
+
} catch {
|
|
16543
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16544
|
+
}
|
|
16545
|
+
const cloudish = keys.some((key) => key === "cloud" || key === "tokenEnv" || key === "tokenCommand");
|
|
16546
|
+
if (!cloudish) {
|
|
16547
|
+
if (keys.length !== 3) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16548
|
+
return { record: { schema: HUB_BINDING_SCHEMA, url, boundAt: parsed.boundAt } };
|
|
16549
|
+
}
|
|
16550
|
+
const record2 = cloudRecordFromRow(file, parsed, url, parsed.boundAt);
|
|
16551
|
+
if (!record2) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
16552
|
+
return { record: record2, legacyCloud: true };
|
|
16553
|
+
}
|
|
16554
|
+
function loadHubBinding(env = process.env) {
|
|
16555
|
+
const cloudFile = hubBindingCloudFile(env);
|
|
16556
|
+
const cloud = interpretBindingFile(cloudFile);
|
|
16557
|
+
if (cloud.warning && !cloud.record) {
|
|
16558
|
+
const local = existsSync3(hubBindingFile(env)) ? interpretBindingFile(hubBindingFile(env)) : {};
|
|
16559
|
+
if (local.record && !local.record.cloud) return { record: local.record, warning: cloud.warning };
|
|
16560
|
+
return { warning: cloud.warning };
|
|
16561
|
+
}
|
|
16562
|
+
if (cloud.record?.cloud) return { record: cloud.record, ...cloud.warning ? { warning: cloud.warning } : {} };
|
|
16563
|
+
const main = interpretBindingFile(hubBindingFile(env));
|
|
16564
|
+
if (main.legacyCloud && main.record) {
|
|
16565
|
+
writeBindingJson(cloudFile, main.record);
|
|
16566
|
+
rmSync(hubBindingFile(env), { force: true });
|
|
16567
|
+
return {
|
|
16568
|
+
record: main.record,
|
|
16569
|
+
warning: bindingFallbackWarning(
|
|
16570
|
+
hubBindingFile(env),
|
|
16571
|
+
"stored a cloud bind in the pre-0.7.160 file"
|
|
16572
|
+
)
|
|
16573
|
+
};
|
|
16574
|
+
}
|
|
16575
|
+
return { ...main.record ? { record: main.record } : {}, ...main.warning ? { warning: main.warning } : {} };
|
|
16576
|
+
}
|
|
16577
|
+
function readHubBinding(env = process.env) {
|
|
16578
|
+
return loadHubBinding(env).record;
|
|
16579
|
+
}
|
|
16580
|
+
function contentTypeBase(header) {
|
|
16581
|
+
return (header ?? "").split(";")[0].trim().toLowerCase();
|
|
16582
|
+
}
|
|
16583
|
+
function looksLikeHtml(contentType, body) {
|
|
16584
|
+
if (contentType === "text/html" || contentType === "application/xhtml+xml") return true;
|
|
16585
|
+
const sample = body.slice(0, 800).trim().toLowerCase();
|
|
16586
|
+
return sample.startsWith("<!doctype html") || sample.startsWith("<html") || sample.includes("<form") && (sample.includes("login") || sample.includes("authentik") || sample.includes("password"));
|
|
16587
|
+
}
|
|
16588
|
+
function jsonObject(text) {
|
|
16589
|
+
try {
|
|
16590
|
+
const parsed = JSON.parse(text);
|
|
16591
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
16592
|
+
return parsed;
|
|
16593
|
+
} catch {
|
|
16594
|
+
return void 0;
|
|
16595
|
+
}
|
|
16596
|
+
}
|
|
16597
|
+
function hubEndpointShape(role, body) {
|
|
16598
|
+
if (role === "health") return body.ok === true && typeof body.agents === "number";
|
|
16599
|
+
return body.ok === true && (body.storage === "sqlite" || body.storage === "memory");
|
|
16600
|
+
}
|
|
16601
|
+
function classifyHubResponse(input) {
|
|
16602
|
+
const contentType = contentTypeBase(input.contentType);
|
|
16603
|
+
if (input.status >= 300 && input.status < 400) {
|
|
16604
|
+
return {
|
|
16605
|
+
ok: false,
|
|
16606
|
+
status: input.status,
|
|
16607
|
+
kind: "redirect",
|
|
16608
|
+
detail: `HTTP ${input.status} redirect; this looks like an auth proxy or a redirect, not a kxm hub`,
|
|
16609
|
+
body: { error: "auth_proxy", detail: `HTTP ${input.status} redirect` }
|
|
16610
|
+
};
|
|
16611
|
+
}
|
|
16612
|
+
if (looksLikeHtml(contentType, input.bodyText)) {
|
|
16613
|
+
return {
|
|
16614
|
+
ok: false,
|
|
16615
|
+
status: input.status,
|
|
16616
|
+
kind: "auth_proxy",
|
|
16617
|
+
detail: `HTTP ${input.status} returned an HTML login page${contentType ? ` (${contentType})` : ""}; this looks like an auth proxy, not a kxm hub`,
|
|
16618
|
+
body: { error: "auth_proxy", detail: "HTML login page" }
|
|
16619
|
+
};
|
|
16620
|
+
}
|
|
16621
|
+
const jsonType = contentType === "application/json" || contentType === "text/plain" || contentType === "";
|
|
16622
|
+
const body = jsonType ? jsonObject(input.bodyText) : void 0;
|
|
16623
|
+
if (body && hubEndpointShape(input.role, body) && input.status >= 200 && input.status < 300) {
|
|
16624
|
+
if (contentType !== "" && contentType !== "application/json" && contentType !== "text/plain") {
|
|
16625
|
+
return {
|
|
16626
|
+
ok: false,
|
|
16627
|
+
status: input.status,
|
|
16628
|
+
kind: "not_hub",
|
|
16629
|
+
detail: `HTTP ${input.status} content-type ${contentType} is not application/json`,
|
|
16630
|
+
body: { error: "not_hub", detail: contentType }
|
|
16631
|
+
};
|
|
16632
|
+
}
|
|
16633
|
+
return { ok: true, status: input.status, kind: "hub", detail: "kxm hub", body };
|
|
16634
|
+
}
|
|
16635
|
+
const typeNote = contentType && contentType !== "application/json" ? ` content-type ${contentType}` : "";
|
|
16636
|
+
return {
|
|
16637
|
+
ok: false,
|
|
16638
|
+
status: input.status,
|
|
16639
|
+
kind: "not_hub",
|
|
16640
|
+
detail: `HTTP ${input.status}${typeNote} is not a kxm hub ${input.role} response`,
|
|
16641
|
+
body: { error: "not_hub", detail: `HTTP ${input.status}${typeNote}` }
|
|
16642
|
+
};
|
|
16643
|
+
}
|
|
16644
|
+
async function readHubEndpoint(url, role, fetchImpl, init = {}) {
|
|
16645
|
+
try {
|
|
16646
|
+
const response = await fetchImpl(`${url}/${role}`, {
|
|
16647
|
+
...init.headers ? { headers: init.headers } : {},
|
|
16648
|
+
...init.signal ? { signal: init.signal } : {},
|
|
16649
|
+
redirect: "manual"
|
|
16650
|
+
});
|
|
16651
|
+
const bodyText = await response.text();
|
|
16652
|
+
return classifyHubResponse({
|
|
16653
|
+
role,
|
|
16654
|
+
status: response.status,
|
|
16655
|
+
contentType: response.headers.get("content-type"),
|
|
16656
|
+
bodyText
|
|
16657
|
+
});
|
|
16658
|
+
} catch (error2) {
|
|
16659
|
+
if (isAbortError(error2)) {
|
|
16660
|
+
return { ok: false, status: 0, kind: "timeout", detail: "no reply within the probe budget", body: { error: "hub_unreachable" } };
|
|
16661
|
+
}
|
|
16662
|
+
return { ok: false, status: 0, kind: "unreachable", detail: "nothing answered", body: { error: "hub_unreachable" } };
|
|
16663
|
+
}
|
|
16664
|
+
}
|
|
16520
16665
|
async function probeHubHealth(url, fetchImpl, timeoutMs = HUB_HEALTH_PROBE_MS) {
|
|
16521
16666
|
const started = Date.now();
|
|
16522
16667
|
const controller = new AbortController();
|
|
16523
16668
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
16524
16669
|
try {
|
|
16525
|
-
const
|
|
16526
|
-
|
|
16527
|
-
|
|
16528
|
-
try {
|
|
16529
|
-
body = await response.json();
|
|
16530
|
-
} catch {
|
|
16531
|
-
return { health: "unknown", probeMs: Date.now() - started };
|
|
16532
|
-
}
|
|
16533
|
-
if (body && typeof body === "object" && body.ok === true) {
|
|
16534
|
-
return { health: "on", probeMs: Date.now() - started };
|
|
16535
|
-
}
|
|
16536
|
-
return { health: "unknown", probeMs: Date.now() - started };
|
|
16537
|
-
} catch (error2) {
|
|
16538
|
-
return { health: isAbortError(error2) ? "unknown" : "off", probeMs: Date.now() - started };
|
|
16670
|
+
const verdict = await readHubEndpoint(url, "health", fetchImpl, { signal: controller.signal });
|
|
16671
|
+
const health = verdict.kind === "hub" ? "on" : verdict.kind === "unreachable" ? "off" : "unknown";
|
|
16672
|
+
return { health, probeMs: Date.now() - started, kind: verdict.kind, detail: verdict.detail, status: verdict.status };
|
|
16539
16673
|
} finally {
|
|
16540
16674
|
clearTimeout(timer);
|
|
16541
16675
|
}
|
|
@@ -16610,15 +16744,6 @@ function resolveProjectIdentity(cwd, env = process.env, explicit) {
|
|
|
16610
16744
|
if (fromPackage) return { project: fromPackage, source: "package.json", sourceLabel: "package.json name" };
|
|
16611
16745
|
return { project: basename(cwd), source: "directory", sourceLabel: "directory name" };
|
|
16612
16746
|
}
|
|
16613
|
-
function opReferenceFromTokenCommand(command) {
|
|
16614
|
-
try {
|
|
16615
|
-
const args = splitTokenCommand(command);
|
|
16616
|
-
if (args[0] === "op" && args[1] === "read" && args[2] && isHubOpReference(args[2])) return args[2];
|
|
16617
|
-
} catch {
|
|
16618
|
-
return void 0;
|
|
16619
|
-
}
|
|
16620
|
-
return void 0;
|
|
16621
|
-
}
|
|
16622
16747
|
function defaultOpRead(reference, env) {
|
|
16623
16748
|
if (!isHubOpReference(reference)) {
|
|
16624
16749
|
throw new CloudTokenError("cloud_token_command_invalid", `refusing to resolve ${reference}; an op:// reference is required`);
|
|
@@ -16663,18 +16788,24 @@ function resolveKeyReference(ref, env, opRead = defaultOpRead) {
|
|
|
16663
16788
|
}
|
|
16664
16789
|
function keySourceFor(input) {
|
|
16665
16790
|
const ref = input.endpoint?.key;
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
|
|
16791
|
+
const envName = (name) => {
|
|
16792
|
+
if (!name) return void 0;
|
|
16793
|
+
return input.env[name]?.trim() ? `env:${name}` : void 0;
|
|
16794
|
+
};
|
|
16670
16795
|
if (input.mode === "cloud") {
|
|
16671
|
-
|
|
16672
|
-
if (
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
|
|
16796
|
+
const fromEnv2 = envName(ref?.env);
|
|
16797
|
+
if (fromEnv2) return fromEnv2;
|
|
16798
|
+
if (ref?.op) return `op:${ref.op}`;
|
|
16799
|
+
const fromBindingEnv = envName(input.binding?.tokenEnv);
|
|
16800
|
+
if (fromBindingEnv) return fromBindingEnv;
|
|
16801
|
+
if (input.binding?.tokenCommand) return "token-command";
|
|
16676
16802
|
return "missing";
|
|
16677
16803
|
}
|
|
16804
|
+
const fromAuth = envName("KXM_AUTH_TOKEN");
|
|
16805
|
+
if (fromAuth) return fromAuth;
|
|
16806
|
+
const fromEnv = envName(ref?.env);
|
|
16807
|
+
if (fromEnv) return fromEnv;
|
|
16808
|
+
if (ref?.op) return `op:${ref.op}`;
|
|
16678
16809
|
if (input.hasSavedProjectToken?.(input.project)) return "hub-env";
|
|
16679
16810
|
return "missing";
|
|
16680
16811
|
}
|
|
@@ -24015,6 +24015,9 @@ function resolveUserStateRoot(env) {
|
|
|
24015
24015
|
function hubBindingFile(env = process.env) {
|
|
24016
24016
|
return join2(resolveUserStateRoot(env), "hub-binding.json");
|
|
24017
24017
|
}
|
|
24018
|
+
function hubBindingCloudFile(env = process.env) {
|
|
24019
|
+
return join2(resolveUserStateRoot(env), "hub-binding.cloud.json");
|
|
24020
|
+
}
|
|
24018
24021
|
function validateHubUrl(raw) {
|
|
24019
24022
|
let parsed;
|
|
24020
24023
|
try {
|
|
@@ -24124,33 +24127,37 @@ function isIsoTimestamp(value) {
|
|
|
24124
24127
|
if (Number.isNaN(Date.parse(value))) return false;
|
|
24125
24128
|
return value === new Date(value).toISOString();
|
|
24126
24129
|
}
|
|
24127
|
-
|
|
24128
|
-
|
|
24129
|
-
|
|
24130
|
+
var LEGACY_BINDING_KEYS = ["schema", "url", "boundAt"];
|
|
24131
|
+
var BINDING_KEYS = /* @__PURE__ */ new Set([...LEGACY_BINDING_KEYS, "cloud", "tokenEnv", "tokenCommand"]);
|
|
24132
|
+
function bindingFallbackWarning(file, reason) {
|
|
24133
|
+
return `hub binding at ${file} ${reason}; falling back to the local hub. Restart the Runtime supervisor, the hub, and workers after upgrading and before a cloud bind.`;
|
|
24134
|
+
}
|
|
24135
|
+
function writeBindingJson(file, value) {
|
|
24136
|
+
mkdirSync2(dirname2(file), { recursive: true, mode: 448 });
|
|
24137
|
+
const temporary = join2(dirname2(file), `.${file.endsWith("cloud.json") ? "hub-binding-cloud" : "hub-binding"}-${process.pid}.tmp`);
|
|
24138
|
+
try {
|
|
24139
|
+
writeFileSync2(temporary, `${JSON.stringify(value, null, 2)}
|
|
24140
|
+
`, { encoding: "utf8", mode: 384 });
|
|
24141
|
+
renameSync(temporary, file);
|
|
24142
|
+
} finally {
|
|
24143
|
+
rmSync(temporary, { force: true });
|
|
24144
|
+
}
|
|
24145
|
+
}
|
|
24146
|
+
function parseBindingObject(file) {
|
|
24147
|
+
if (!existsSync2(file)) return new HubBindingError(`missing hub binding at ${file}`);
|
|
24130
24148
|
let parsed;
|
|
24131
24149
|
try {
|
|
24132
24150
|
parsed = JSON.parse(readFileSync2(file, "utf8"));
|
|
24133
24151
|
} catch {
|
|
24134
|
-
|
|
24152
|
+
return new HubBindingError(`malformed hub binding at ${file}`);
|
|
24135
24153
|
}
|
|
24136
24154
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
24137
|
-
|
|
24138
|
-
}
|
|
24139
|
-
const row = parsed;
|
|
24140
|
-
const keys = Object.keys(row);
|
|
24141
|
-
const allowed = /* @__PURE__ */ new Set(["schema", "url", "boundAt", "cloud", "tokenEnv", "tokenCommand"]);
|
|
24142
|
-
const cloudish = keys.some((key) => key === "cloud" || key === "tokenEnv" || key === "tokenCommand");
|
|
24143
|
-
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)) {
|
|
24144
|
-
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
24145
|
-
}
|
|
24146
|
-
let url;
|
|
24147
|
-
try {
|
|
24148
|
-
url = validateHubUrl(row.url);
|
|
24149
|
-
} catch {
|
|
24150
|
-
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
24155
|
+
return new HubBindingError(`malformed hub binding at ${file}`);
|
|
24151
24156
|
}
|
|
24152
|
-
|
|
24153
|
-
|
|
24157
|
+
return parsed;
|
|
24158
|
+
}
|
|
24159
|
+
function cloudRecordFromRow(file, row, url, boundAt) {
|
|
24160
|
+
if (row.cloud !== true) return void 0;
|
|
24154
24161
|
let tokenEnv;
|
|
24155
24162
|
let tokenCommand;
|
|
24156
24163
|
if (row.tokenEnv !== void 0) {
|
|
@@ -24172,12 +24179,65 @@ function readHubBinding(env = process.env) {
|
|
|
24172
24179
|
return {
|
|
24173
24180
|
schema: HUB_BINDING_SCHEMA,
|
|
24174
24181
|
url,
|
|
24175
|
-
boundAt
|
|
24182
|
+
boundAt,
|
|
24176
24183
|
cloud: true,
|
|
24177
24184
|
...tokenEnv ? { tokenEnv } : {},
|
|
24178
24185
|
...tokenCommand ? { tokenCommand } : {}
|
|
24179
24186
|
};
|
|
24180
24187
|
}
|
|
24188
|
+
function interpretBindingFile(file) {
|
|
24189
|
+
if (!existsSync2(file)) return {};
|
|
24190
|
+
const parsed = parseBindingObject(file);
|
|
24191
|
+
if (parsed instanceof HubBindingError) throw parsed;
|
|
24192
|
+
const keys = Object.keys(parsed);
|
|
24193
|
+
const unknown2 = keys.filter((key) => !BINDING_KEYS.has(key));
|
|
24194
|
+
if (parsed.schema !== HUB_BINDING_SCHEMA || unknown2.length > 0) {
|
|
24195
|
+
return { warning: bindingFallbackWarning(file, `is newer than this build understands (${String(parsed.schema)})`) };
|
|
24196
|
+
}
|
|
24197
|
+
if (typeof parsed.url !== "string" || typeof parsed.boundAt !== "string" || !isIsoTimestamp(parsed.boundAt)) {
|
|
24198
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
24199
|
+
}
|
|
24200
|
+
let url;
|
|
24201
|
+
try {
|
|
24202
|
+
url = validateHubUrl(parsed.url);
|
|
24203
|
+
} catch {
|
|
24204
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
24205
|
+
}
|
|
24206
|
+
const cloudish = keys.some((key) => key === "cloud" || key === "tokenEnv" || key === "tokenCommand");
|
|
24207
|
+
if (!cloudish) {
|
|
24208
|
+
if (keys.length !== 3) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
24209
|
+
return { record: { schema: HUB_BINDING_SCHEMA, url, boundAt: parsed.boundAt } };
|
|
24210
|
+
}
|
|
24211
|
+
const record2 = cloudRecordFromRow(file, parsed, url, parsed.boundAt);
|
|
24212
|
+
if (!record2) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
24213
|
+
return { record: record2, legacyCloud: true };
|
|
24214
|
+
}
|
|
24215
|
+
function loadHubBinding(env = process.env) {
|
|
24216
|
+
const cloudFile = hubBindingCloudFile(env);
|
|
24217
|
+
const cloud = interpretBindingFile(cloudFile);
|
|
24218
|
+
if (cloud.warning && !cloud.record) {
|
|
24219
|
+
const local = existsSync2(hubBindingFile(env)) ? interpretBindingFile(hubBindingFile(env)) : {};
|
|
24220
|
+
if (local.record && !local.record.cloud) return { record: local.record, warning: cloud.warning };
|
|
24221
|
+
return { warning: cloud.warning };
|
|
24222
|
+
}
|
|
24223
|
+
if (cloud.record?.cloud) return { record: cloud.record, ...cloud.warning ? { warning: cloud.warning } : {} };
|
|
24224
|
+
const main = interpretBindingFile(hubBindingFile(env));
|
|
24225
|
+
if (main.legacyCloud && main.record) {
|
|
24226
|
+
writeBindingJson(cloudFile, main.record);
|
|
24227
|
+
rmSync(hubBindingFile(env), { force: true });
|
|
24228
|
+
return {
|
|
24229
|
+
record: main.record,
|
|
24230
|
+
warning: bindingFallbackWarning(
|
|
24231
|
+
hubBindingFile(env),
|
|
24232
|
+
"stored a cloud bind in the pre-0.7.160 file"
|
|
24233
|
+
)
|
|
24234
|
+
};
|
|
24235
|
+
}
|
|
24236
|
+
return { ...main.record ? { record: main.record } : {}, ...main.warning ? { warning: main.warning } : {} };
|
|
24237
|
+
}
|
|
24238
|
+
function readHubBinding(env = process.env) {
|
|
24239
|
+
return loadHubBinding(env).record;
|
|
24240
|
+
}
|
|
24181
24241
|
|
|
24182
24242
|
// plugins/kxm/src/hub-identity.ts
|
|
24183
24243
|
var OP_TIMEOUT_MS = 15e3;
|
|
@@ -24244,15 +24304,6 @@ function resolveProjectIdentity(cwd, env = process.env, explicit) {
|
|
|
24244
24304
|
if (fromPackage) return { project: fromPackage, source: "package.json", sourceLabel: "package.json name" };
|
|
24245
24305
|
return { project: basename(cwd), source: "directory", sourceLabel: "directory name" };
|
|
24246
24306
|
}
|
|
24247
|
-
function opReferenceFromTokenCommand(command) {
|
|
24248
|
-
try {
|
|
24249
|
-
const args = splitTokenCommand(command);
|
|
24250
|
-
if (args[0] === "op" && args[1] === "read" && args[2] && isHubOpReference(args[2])) return args[2];
|
|
24251
|
-
} catch {
|
|
24252
|
-
return void 0;
|
|
24253
|
-
}
|
|
24254
|
-
return void 0;
|
|
24255
|
-
}
|
|
24256
24307
|
function defaultOpRead(reference, env) {
|
|
24257
24308
|
if (!isHubOpReference(reference)) {
|
|
24258
24309
|
throw new CloudTokenError("cloud_token_command_invalid", `refusing to resolve ${reference}; an op:// reference is required`);
|
|
@@ -24297,18 +24348,24 @@ function resolveKeyReference(ref, env, opRead = defaultOpRead) {
|
|
|
24297
24348
|
}
|
|
24298
24349
|
function keySourceFor(input) {
|
|
24299
24350
|
const ref = input.endpoint?.key;
|
|
24300
|
-
|
|
24301
|
-
|
|
24302
|
-
|
|
24303
|
-
|
|
24351
|
+
const envName = (name) => {
|
|
24352
|
+
if (!name) return void 0;
|
|
24353
|
+
return input.env[name]?.trim() ? `env:${name}` : void 0;
|
|
24354
|
+
};
|
|
24304
24355
|
if (input.mode === "cloud") {
|
|
24305
|
-
|
|
24306
|
-
if (
|
|
24307
|
-
|
|
24308
|
-
|
|
24309
|
-
|
|
24356
|
+
const fromEnv2 = envName(ref?.env);
|
|
24357
|
+
if (fromEnv2) return fromEnv2;
|
|
24358
|
+
if (ref?.op) return `op:${ref.op}`;
|
|
24359
|
+
const fromBindingEnv = envName(input.binding?.tokenEnv);
|
|
24360
|
+
if (fromBindingEnv) return fromBindingEnv;
|
|
24361
|
+
if (input.binding?.tokenCommand) return "token-command";
|
|
24310
24362
|
return "missing";
|
|
24311
24363
|
}
|
|
24364
|
+
const fromAuth = envName("KXM_AUTH_TOKEN");
|
|
24365
|
+
if (fromAuth) return fromAuth;
|
|
24366
|
+
const fromEnv = envName(ref?.env);
|
|
24367
|
+
if (fromEnv) return fromEnv;
|
|
24368
|
+
if (ref?.op) return `op:${ref.op}`;
|
|
24312
24369
|
if (input.hasSavedProjectToken?.(input.project)) return "hub-env";
|
|
24313
24370
|
return "missing";
|
|
24314
24371
|
}
|
|
@@ -25381,7 +25438,7 @@ function sessionTokenFixHint(policy) {
|
|
|
25381
25438
|
}
|
|
25382
25439
|
|
|
25383
25440
|
// plugins/kxm/src/mcp-server.ts
|
|
25384
|
-
var VERSION = "0.7.
|
|
25441
|
+
var VERSION = "0.7.169";
|
|
25385
25442
|
var CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
|
|
25386
25443
|
var inbox = /* @__PURE__ */ new Map();
|
|
25387
25444
|
var notifiedInbox = /* @__PURE__ */ new Set();
|