@kontextmind/kxm 0.7.167 → 0.7.168
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 +18 -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 +4 -1
- 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 +332 -129
- package/plugins/kxm/dist/extension.js +184 -53
- package/plugins/kxm/dist/mcp-server.js +97 -40
- package/plugins/kxm/dist/runtime-supervisor.js +113 -42
- package/plugins/kxm/dist/runtime.js +113 -42
- package/plugins/kxm/dist/server.js +2 -0
- package/plugins/kxm/package.json +1 -1
- 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/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/runtime-supervisor.ts +22 -4
- package/scripts/kxm-publish-npm.mjs +47 -1
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -9409,7 +9409,7 @@ var init_config = __esm({
|
|
|
9409
9409
|
});
|
|
9410
9410
|
|
|
9411
9411
|
// plugins/kxm/src/hub-binding.ts
|
|
9412
|
-
import { spawnSync } from "node:child_process";
|
|
9412
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
9413
9413
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
9414
9414
|
import { homedir as homedir2 } from "node:os";
|
|
9415
9415
|
import { dirname as dirname3, isAbsolute, join as join4, resolve as resolve2 } from "node:path";
|
|
@@ -9432,6 +9432,9 @@ function resolveUserStateRoot(env) {
|
|
|
9432
9432
|
function hubBindingFile(env = process.env) {
|
|
9433
9433
|
return join4(resolveUserStateRoot(env), "hub-binding.json");
|
|
9434
9434
|
}
|
|
9435
|
+
function hubBindingCloudFile(env = process.env) {
|
|
9436
|
+
return join4(resolveUserStateRoot(env), "hub-binding.cloud.json");
|
|
9437
|
+
}
|
|
9435
9438
|
function validateHubUrl(raw) {
|
|
9436
9439
|
let parsed;
|
|
9437
9440
|
try {
|
|
@@ -9517,7 +9520,7 @@ function resolveCloudHubToken(binding, env = process.env) {
|
|
|
9517
9520
|
function runTokenCommand(command, env) {
|
|
9518
9521
|
const argv = splitTokenCommand(command);
|
|
9519
9522
|
const [program2, ...args] = argv;
|
|
9520
|
-
const result =
|
|
9523
|
+
const result = spawnSync2(program2, args, {
|
|
9521
9524
|
encoding: "utf8",
|
|
9522
9525
|
shell: false,
|
|
9523
9526
|
timeout: TOKEN_COMMAND_TIMEOUT_MS,
|
|
@@ -9560,33 +9563,35 @@ function isAbortError(error) {
|
|
|
9560
9563
|
error && typeof error === "object" && ("name" in error && error.name === "AbortError" || "code" in error && error.code === "ABORT_ERR")
|
|
9561
9564
|
);
|
|
9562
9565
|
}
|
|
9563
|
-
function
|
|
9564
|
-
|
|
9565
|
-
|
|
9566
|
+
function bindingFallbackWarning(file, reason) {
|
|
9567
|
+
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.`;
|
|
9568
|
+
}
|
|
9569
|
+
function writeBindingJson(file, value) {
|
|
9570
|
+
mkdirSync3(dirname3(file), { recursive: true, mode: 448 });
|
|
9571
|
+
const temporary = join4(dirname3(file), `.${file.endsWith("cloud.json") ? "hub-binding-cloud" : "hub-binding"}-${process.pid}.tmp`);
|
|
9572
|
+
try {
|
|
9573
|
+
writeFileSync3(temporary, `${JSON.stringify(value, null, 2)}
|
|
9574
|
+
`, { encoding: "utf8", mode: 384 });
|
|
9575
|
+
renameSync(temporary, file);
|
|
9576
|
+
} finally {
|
|
9577
|
+
rmSync(temporary, { force: true });
|
|
9578
|
+
}
|
|
9579
|
+
}
|
|
9580
|
+
function parseBindingObject(file) {
|
|
9581
|
+
if (!existsSync4(file)) return new HubBindingError(`missing hub binding at ${file}`);
|
|
9566
9582
|
let parsed;
|
|
9567
9583
|
try {
|
|
9568
9584
|
parsed = JSON.parse(readFileSync3(file, "utf8"));
|
|
9569
9585
|
} catch {
|
|
9570
|
-
|
|
9586
|
+
return new HubBindingError(`malformed hub binding at ${file}`);
|
|
9571
9587
|
}
|
|
9572
9588
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9573
|
-
|
|
9589
|
+
return new HubBindingError(`malformed hub binding at ${file}`);
|
|
9574
9590
|
}
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
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)) {
|
|
9580
|
-
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9581
|
-
}
|
|
9582
|
-
let url;
|
|
9583
|
-
try {
|
|
9584
|
-
url = validateHubUrl(row.url);
|
|
9585
|
-
} catch {
|
|
9586
|
-
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9587
|
-
}
|
|
9588
|
-
if (!cloudish) return { schema: HUB_BINDING_SCHEMA, url, boundAt: row.boundAt };
|
|
9589
|
-
if (row.cloud !== true) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9591
|
+
return parsed;
|
|
9592
|
+
}
|
|
9593
|
+
function cloudRecordFromRow(file, row, url, boundAt) {
|
|
9594
|
+
if (row.cloud !== true) return void 0;
|
|
9590
9595
|
let tokenEnv;
|
|
9591
9596
|
let tokenCommand;
|
|
9592
9597
|
if (row.tokenEnv !== void 0) {
|
|
@@ -9608,33 +9613,203 @@ function readHubBinding(env = process.env) {
|
|
|
9608
9613
|
return {
|
|
9609
9614
|
schema: HUB_BINDING_SCHEMA,
|
|
9610
9615
|
url,
|
|
9611
|
-
boundAt
|
|
9616
|
+
boundAt,
|
|
9612
9617
|
cloud: true,
|
|
9613
9618
|
...tokenEnv ? { tokenEnv } : {},
|
|
9614
9619
|
...tokenCommand ? { tokenCommand } : {}
|
|
9615
9620
|
};
|
|
9616
9621
|
}
|
|
9617
|
-
function
|
|
9622
|
+
function readLegacyV1HubBinding(env = process.env) {
|
|
9618
9623
|
const file = hubBindingFile(env);
|
|
9619
|
-
|
|
9620
|
-
const
|
|
9624
|
+
if (!existsSync4(file)) return void 0;
|
|
9625
|
+
const parsed = parseBindingObject(file);
|
|
9626
|
+
if (parsed instanceof HubBindingError) throw parsed;
|
|
9627
|
+
const keys = Object.keys(parsed);
|
|
9628
|
+
if (keys.length !== 3 || keys.some((key) => !LEGACY_BINDING_KEYS.includes(key)) || parsed.schema !== HUB_BINDING_SCHEMA || typeof parsed.url !== "string" || typeof parsed.boundAt !== "string" || !isIsoTimestamp(parsed.boundAt)) {
|
|
9629
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9630
|
+
}
|
|
9631
|
+
let url;
|
|
9621
9632
|
try {
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
} finally {
|
|
9626
|
-
rmSync(temporary, { force: true });
|
|
9633
|
+
url = validateHubUrl(parsed.url);
|
|
9634
|
+
} catch {
|
|
9635
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9627
9636
|
}
|
|
9637
|
+
return { schema: HUB_BINDING_SCHEMA, url, boundAt: parsed.boundAt };
|
|
9638
|
+
}
|
|
9639
|
+
function interpretBindingFile(file) {
|
|
9640
|
+
if (!existsSync4(file)) return {};
|
|
9641
|
+
const parsed = parseBindingObject(file);
|
|
9642
|
+
if (parsed instanceof HubBindingError) throw parsed;
|
|
9643
|
+
const keys = Object.keys(parsed);
|
|
9644
|
+
const unknown = keys.filter((key) => !BINDING_KEYS.has(key));
|
|
9645
|
+
if (parsed.schema !== HUB_BINDING_SCHEMA || unknown.length > 0) {
|
|
9646
|
+
return { warning: bindingFallbackWarning(file, `is newer than this build understands (${String(parsed.schema)})`) };
|
|
9647
|
+
}
|
|
9648
|
+
if (typeof parsed.url !== "string" || typeof parsed.boundAt !== "string" || !isIsoTimestamp(parsed.boundAt)) {
|
|
9649
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9650
|
+
}
|
|
9651
|
+
let url;
|
|
9652
|
+
try {
|
|
9653
|
+
url = validateHubUrl(parsed.url);
|
|
9654
|
+
} catch {
|
|
9655
|
+
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9656
|
+
}
|
|
9657
|
+
const cloudish = keys.some((key) => key === "cloud" || key === "tokenEnv" || key === "tokenCommand");
|
|
9658
|
+
if (!cloudish) {
|
|
9659
|
+
if (keys.length !== 3) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9660
|
+
return { record: { schema: HUB_BINDING_SCHEMA, url, boundAt: parsed.boundAt } };
|
|
9661
|
+
}
|
|
9662
|
+
const record = cloudRecordFromRow(file, parsed, url, parsed.boundAt);
|
|
9663
|
+
if (!record) throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
9664
|
+
return { record, legacyCloud: true };
|
|
9665
|
+
}
|
|
9666
|
+
function loadHubBinding(env = process.env) {
|
|
9667
|
+
const cloudFile = hubBindingCloudFile(env);
|
|
9668
|
+
const cloud = interpretBindingFile(cloudFile);
|
|
9669
|
+
if (cloud.warning && !cloud.record) {
|
|
9670
|
+
const local = existsSync4(hubBindingFile(env)) ? interpretBindingFile(hubBindingFile(env)) : {};
|
|
9671
|
+
if (local.record && !local.record.cloud) return { record: local.record, warning: cloud.warning };
|
|
9672
|
+
return { warning: cloud.warning };
|
|
9673
|
+
}
|
|
9674
|
+
if (cloud.record?.cloud) return { record: cloud.record, ...cloud.warning ? { warning: cloud.warning } : {} };
|
|
9675
|
+
const main = interpretBindingFile(hubBindingFile(env));
|
|
9676
|
+
if (main.legacyCloud && main.record) {
|
|
9677
|
+
writeBindingJson(cloudFile, main.record);
|
|
9678
|
+
rmSync(hubBindingFile(env), { force: true });
|
|
9679
|
+
return {
|
|
9680
|
+
record: main.record,
|
|
9681
|
+
warning: bindingFallbackWarning(
|
|
9682
|
+
hubBindingFile(env),
|
|
9683
|
+
"stored a cloud bind in the pre-0.7.160 file"
|
|
9684
|
+
)
|
|
9685
|
+
};
|
|
9686
|
+
}
|
|
9687
|
+
return { ...main.record ? { record: main.record } : {}, ...main.warning ? { warning: main.warning } : {} };
|
|
9688
|
+
}
|
|
9689
|
+
function readHubBinding(env = process.env) {
|
|
9690
|
+
return loadHubBinding(env).record;
|
|
9691
|
+
}
|
|
9692
|
+
function writeHubBinding(record, env = process.env) {
|
|
9693
|
+
if (record.cloud) {
|
|
9694
|
+
const file2 = hubBindingCloudFile(env);
|
|
9695
|
+
writeBindingJson(file2, record);
|
|
9696
|
+
const main = hubBindingFile(env);
|
|
9697
|
+
if (existsSync4(main)) {
|
|
9698
|
+
try {
|
|
9699
|
+
const legacy = readLegacyV1HubBinding(env);
|
|
9700
|
+
if (!legacy || legacy.url === record.url) rmSync(main, { force: true });
|
|
9701
|
+
} catch (error) {
|
|
9702
|
+
if (!(error instanceof HubBindingError)) throw error;
|
|
9703
|
+
rmSync(main, { force: true });
|
|
9704
|
+
}
|
|
9705
|
+
}
|
|
9706
|
+
return file2;
|
|
9707
|
+
}
|
|
9708
|
+
rmSync(hubBindingCloudFile(env), { force: true });
|
|
9709
|
+
const file = hubBindingFile(env);
|
|
9710
|
+
writeBindingJson(file, {
|
|
9711
|
+
schema: HUB_BINDING_SCHEMA,
|
|
9712
|
+
url: record.url,
|
|
9713
|
+
boundAt: record.boundAt
|
|
9714
|
+
});
|
|
9628
9715
|
return file;
|
|
9629
9716
|
}
|
|
9630
9717
|
function removeHubBinding(env = process.env) {
|
|
9631
|
-
const
|
|
9718
|
+
const files = [hubBindingFile(env), hubBindingCloudFile(env)];
|
|
9719
|
+
let removed = false;
|
|
9720
|
+
for (const file of files) {
|
|
9721
|
+
try {
|
|
9722
|
+
rmSync(file);
|
|
9723
|
+
removed = true;
|
|
9724
|
+
} catch (error) {
|
|
9725
|
+
if (error.code !== "ENOENT") throw error;
|
|
9726
|
+
}
|
|
9727
|
+
}
|
|
9728
|
+
return removed;
|
|
9729
|
+
}
|
|
9730
|
+
function contentTypeBase(header) {
|
|
9731
|
+
return (header ?? "").split(";")[0].trim().toLowerCase();
|
|
9732
|
+
}
|
|
9733
|
+
function looksLikeHtml(contentType, body) {
|
|
9734
|
+
if (contentType === "text/html" || contentType === "application/xhtml+xml") return true;
|
|
9735
|
+
const sample = body.slice(0, 800).trim().toLowerCase();
|
|
9736
|
+
return sample.startsWith("<!doctype html") || sample.startsWith("<html") || sample.includes("<form") && (sample.includes("login") || sample.includes("authentik") || sample.includes("password"));
|
|
9737
|
+
}
|
|
9738
|
+
function jsonObject(text) {
|
|
9632
9739
|
try {
|
|
9633
|
-
|
|
9634
|
-
return
|
|
9740
|
+
const parsed = JSON.parse(text);
|
|
9741
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
9742
|
+
return parsed;
|
|
9743
|
+
} catch {
|
|
9744
|
+
return void 0;
|
|
9745
|
+
}
|
|
9746
|
+
}
|
|
9747
|
+
function hubEndpointShape(role, body) {
|
|
9748
|
+
if (role === "health") return body.ok === true && typeof body.agents === "number";
|
|
9749
|
+
return body.ok === true && (body.storage === "sqlite" || body.storage === "memory");
|
|
9750
|
+
}
|
|
9751
|
+
function classifyHubResponse(input) {
|
|
9752
|
+
const contentType = contentTypeBase(input.contentType);
|
|
9753
|
+
if (input.status >= 300 && input.status < 400) {
|
|
9754
|
+
return {
|
|
9755
|
+
ok: false,
|
|
9756
|
+
status: input.status,
|
|
9757
|
+
kind: "redirect",
|
|
9758
|
+
detail: `HTTP ${input.status} redirect; this looks like an auth proxy or a redirect, not a kxm hub`,
|
|
9759
|
+
body: { error: "auth_proxy", detail: `HTTP ${input.status} redirect` }
|
|
9760
|
+
};
|
|
9761
|
+
}
|
|
9762
|
+
if (looksLikeHtml(contentType, input.bodyText)) {
|
|
9763
|
+
return {
|
|
9764
|
+
ok: false,
|
|
9765
|
+
status: input.status,
|
|
9766
|
+
kind: "auth_proxy",
|
|
9767
|
+
detail: `HTTP ${input.status} returned an HTML login page${contentType ? ` (${contentType})` : ""}; this looks like an auth proxy, not a kxm hub`,
|
|
9768
|
+
body: { error: "auth_proxy", detail: "HTML login page" }
|
|
9769
|
+
};
|
|
9770
|
+
}
|
|
9771
|
+
const jsonType = contentType === "application/json" || contentType === "text/plain" || contentType === "";
|
|
9772
|
+
const body = jsonType ? jsonObject(input.bodyText) : void 0;
|
|
9773
|
+
if (body && hubEndpointShape(input.role, body) && input.status >= 200 && input.status < 300) {
|
|
9774
|
+
if (contentType !== "" && contentType !== "application/json" && contentType !== "text/plain") {
|
|
9775
|
+
return {
|
|
9776
|
+
ok: false,
|
|
9777
|
+
status: input.status,
|
|
9778
|
+
kind: "not_hub",
|
|
9779
|
+
detail: `HTTP ${input.status} content-type ${contentType} is not application/json`,
|
|
9780
|
+
body: { error: "not_hub", detail: contentType }
|
|
9781
|
+
};
|
|
9782
|
+
}
|
|
9783
|
+
return { ok: true, status: input.status, kind: "hub", detail: "kxm hub", body };
|
|
9784
|
+
}
|
|
9785
|
+
const typeNote = contentType && contentType !== "application/json" ? ` content-type ${contentType}` : "";
|
|
9786
|
+
return {
|
|
9787
|
+
ok: false,
|
|
9788
|
+
status: input.status,
|
|
9789
|
+
kind: "not_hub",
|
|
9790
|
+
detail: `HTTP ${input.status}${typeNote} is not a kxm hub ${input.role} response`,
|
|
9791
|
+
body: { error: "not_hub", detail: `HTTP ${input.status}${typeNote}` }
|
|
9792
|
+
};
|
|
9793
|
+
}
|
|
9794
|
+
async function readHubEndpoint(url, role, fetchImpl, init = {}) {
|
|
9795
|
+
try {
|
|
9796
|
+
const response = await fetchImpl(`${url}/${role}`, {
|
|
9797
|
+
...init.headers ? { headers: init.headers } : {},
|
|
9798
|
+
...init.signal ? { signal: init.signal } : {},
|
|
9799
|
+
redirect: "manual"
|
|
9800
|
+
});
|
|
9801
|
+
const bodyText = await response.text();
|
|
9802
|
+
return classifyHubResponse({
|
|
9803
|
+
role,
|
|
9804
|
+
status: response.status,
|
|
9805
|
+
contentType: response.headers.get("content-type"),
|
|
9806
|
+
bodyText
|
|
9807
|
+
});
|
|
9635
9808
|
} catch (error) {
|
|
9636
|
-
if (error
|
|
9637
|
-
|
|
9809
|
+
if (isAbortError(error)) {
|
|
9810
|
+
return { ok: false, status: 0, kind: "timeout", detail: "no reply within the probe budget", body: { error: "hub_unreachable" } };
|
|
9811
|
+
}
|
|
9812
|
+
return { ok: false, status: 0, kind: "unreachable", detail: "nothing answered", body: { error: "hub_unreachable" } };
|
|
9638
9813
|
}
|
|
9639
9814
|
}
|
|
9640
9815
|
async function probeHubHealth(url, fetchImpl, timeoutMs = HUB_HEALTH_PROBE_MS) {
|
|
@@ -9642,25 +9817,14 @@ async function probeHubHealth(url, fetchImpl, timeoutMs = HUB_HEALTH_PROBE_MS) {
|
|
|
9642
9817
|
const controller = new AbortController();
|
|
9643
9818
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
9644
9819
|
try {
|
|
9645
|
-
const
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
try {
|
|
9649
|
-
body = await response.json();
|
|
9650
|
-
} catch {
|
|
9651
|
-
return { health: "unknown", probeMs: Date.now() - started };
|
|
9652
|
-
}
|
|
9653
|
-
if (body && typeof body === "object" && body.ok === true) {
|
|
9654
|
-
return { health: "on", probeMs: Date.now() - started };
|
|
9655
|
-
}
|
|
9656
|
-
return { health: "unknown", probeMs: Date.now() - started };
|
|
9657
|
-
} catch (error) {
|
|
9658
|
-
return { health: isAbortError(error) ? "unknown" : "off", probeMs: Date.now() - started };
|
|
9820
|
+
const verdict = await readHubEndpoint(url, "health", fetchImpl, { signal: controller.signal });
|
|
9821
|
+
const health = verdict.kind === "hub" ? "on" : verdict.kind === "unreachable" ? "off" : "unknown";
|
|
9822
|
+
return { health, probeMs: Date.now() - started, kind: verdict.kind, detail: verdict.detail, status: verdict.status };
|
|
9659
9823
|
} finally {
|
|
9660
9824
|
clearTimeout(timer);
|
|
9661
9825
|
}
|
|
9662
9826
|
}
|
|
9663
|
-
var HUB_BINDING_SCHEMA, HUB_HEALTH_PROBE_MS, CloudTokenError, TOKEN_ENV_NAME, TOKEN_COMMAND_TIMEOUT_MS, TOKEN_COMMAND_MAX_BUFFER, HubBindingError;
|
|
9827
|
+
var HUB_BINDING_SCHEMA, HUB_HEALTH_PROBE_MS, CloudTokenError, TOKEN_ENV_NAME, TOKEN_COMMAND_TIMEOUT_MS, TOKEN_COMMAND_MAX_BUFFER, HubBindingError, LEGACY_BINDING_KEYS, BINDING_KEYS;
|
|
9664
9828
|
var init_hub_binding = __esm({
|
|
9665
9829
|
"plugins/kxm/src/hub-binding.ts"() {
|
|
9666
9830
|
"use strict";
|
|
@@ -9683,11 +9847,13 @@ var init_hub_binding = __esm({
|
|
|
9683
9847
|
this.name = "HubBindingError";
|
|
9684
9848
|
}
|
|
9685
9849
|
};
|
|
9850
|
+
LEGACY_BINDING_KEYS = ["schema", "url", "boundAt"];
|
|
9851
|
+
BINDING_KEYS = /* @__PURE__ */ new Set([...LEGACY_BINDING_KEYS, "cloud", "tokenEnv", "tokenCommand"]);
|
|
9686
9852
|
}
|
|
9687
9853
|
});
|
|
9688
9854
|
|
|
9689
9855
|
// plugins/kxm/src/hub-identity.ts
|
|
9690
|
-
import { spawnSync as
|
|
9856
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
9691
9857
|
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
|
|
9692
9858
|
import { basename, dirname as dirname4, join as join5, resolve as resolve3 } from "node:path";
|
|
9693
9859
|
function normalizeUrl(raw) {
|
|
@@ -9768,7 +9934,7 @@ function defaultOpRead(reference, env) {
|
|
|
9768
9934
|
if (!isHubOpReference(reference)) {
|
|
9769
9935
|
throw new CloudTokenError("cloud_token_command_invalid", `refusing to resolve ${reference}; an op:// reference is required`);
|
|
9770
9936
|
}
|
|
9771
|
-
const result =
|
|
9937
|
+
const result = spawnSync3("op", ["read", reference], {
|
|
9772
9938
|
encoding: "utf8",
|
|
9773
9939
|
shell: false,
|
|
9774
9940
|
timeout: OP_TIMEOUT_MS,
|
|
@@ -9808,18 +9974,24 @@ function resolveKeyReference(ref, env, opRead = defaultOpRead) {
|
|
|
9808
9974
|
}
|
|
9809
9975
|
function keySourceFor(input) {
|
|
9810
9976
|
const ref = input.endpoint?.key;
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9977
|
+
const envName = (name) => {
|
|
9978
|
+
if (!name) return void 0;
|
|
9979
|
+
return input.env[name]?.trim() ? `env:${name}` : void 0;
|
|
9980
|
+
};
|
|
9815
9981
|
if (input.mode === "cloud") {
|
|
9816
|
-
|
|
9817
|
-
if (
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9982
|
+
const fromEnv2 = envName(ref?.env);
|
|
9983
|
+
if (fromEnv2) return fromEnv2;
|
|
9984
|
+
if (ref?.op) return `op:${ref.op}`;
|
|
9985
|
+
const fromBindingEnv = envName(input.binding?.tokenEnv);
|
|
9986
|
+
if (fromBindingEnv) return fromBindingEnv;
|
|
9987
|
+
if (input.binding?.tokenCommand) return "token-command";
|
|
9821
9988
|
return "missing";
|
|
9822
9989
|
}
|
|
9990
|
+
const fromAuth = envName("KXM_AUTH_TOKEN");
|
|
9991
|
+
if (fromAuth) return fromAuth;
|
|
9992
|
+
const fromEnv = envName(ref?.env);
|
|
9993
|
+
if (fromEnv) return fromEnv;
|
|
9994
|
+
if (ref?.op) return `op:${ref.op}`;
|
|
9823
9995
|
if (input.hasSavedProjectToken?.(input.project)) return "hub-env";
|
|
9824
9996
|
return "missing";
|
|
9825
9997
|
}
|
|
@@ -18919,7 +19091,7 @@ var init_oneshot_process = __esm({
|
|
|
18919
19091
|
});
|
|
18920
19092
|
|
|
18921
19093
|
// plugins/kxm/src/harness.ts
|
|
18922
|
-
import { spawnSync as
|
|
19094
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
18923
19095
|
import { existsSync as existsSync9 } from "node:fs";
|
|
18924
19096
|
import { win32 as win32Path } from "node:path";
|
|
18925
19097
|
function reportedModelId(value) {
|
|
@@ -19208,7 +19380,7 @@ function findWinNpmInnerExe(cliId, options = {}) {
|
|
|
19208
19380
|
function defaultRunner(env) {
|
|
19209
19381
|
return (command, args, timeoutMs) => {
|
|
19210
19382
|
try {
|
|
19211
|
-
const result =
|
|
19383
|
+
const result = spawnSync4(command, [...args], {
|
|
19212
19384
|
encoding: "utf8",
|
|
19213
19385
|
timeout: timeoutMs,
|
|
19214
19386
|
windowsHide: true,
|
|
@@ -19942,7 +20114,7 @@ var init_harness = __esm({
|
|
|
19942
20114
|
});
|
|
19943
20115
|
|
|
19944
20116
|
// plugins/kxm/src/project-config.ts
|
|
19945
|
-
import { spawnSync as
|
|
20117
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
19946
20118
|
import { createHash as createHash7 } from "node:crypto";
|
|
19947
20119
|
import { existsSync as existsSync10, lstatSync, readFileSync as readFileSync8, readdirSync as readdirSync2, realpathSync } from "node:fs";
|
|
19948
20120
|
import { basename as basename2, dirname as dirname7, extname, isAbsolute as isAbsolute3, join as join9, relative, resolve as resolve6, sep } from "node:path";
|
|
@@ -20821,7 +20993,7 @@ function developerCeilings() {
|
|
|
20821
20993
|
const script = join9(findKxmRepoRoot(import.meta.url), "scripts", "harness-run.mjs");
|
|
20822
20994
|
let loaded;
|
|
20823
20995
|
try {
|
|
20824
|
-
loaded =
|
|
20996
|
+
loaded = spawnSync5(process.execPath, ["--input-type=module", "-e", `const m = await import(${JSON.stringify(pathToFileURL(script).href)}); process.stdout.write(JSON.stringify({ROUTES:m.ROUTES,NATIVE_PI_BRAKE_PROVIDERS:m.NATIVE_PI_BRAKE_PROVIDERS,PI_ALLOWED_PROVIDERS:m.PI_ALLOWED_PROVIDERS,PI_NATIVE_VENDOR_PROVIDERS:m.PI_NATIVE_VENDOR_PROVIDERS}))`], {
|
|
20825
20997
|
encoding: "utf8",
|
|
20826
20998
|
timeout: 15e3
|
|
20827
20999
|
});
|
|
@@ -20917,7 +21089,7 @@ function gitEnvironment() {
|
|
|
20917
21089
|
function discoverGitRoot(start = process.cwd()) {
|
|
20918
21090
|
let current = resolve6(start);
|
|
20919
21091
|
if (existsSync10(current) && !lstatSync(current).isDirectory()) current = dirname7(current);
|
|
20920
|
-
const result =
|
|
21092
|
+
const result = spawnSync5("git", ["-C", current, "rev-parse", "--show-toplevel"], {
|
|
20921
21093
|
encoding: "utf8",
|
|
20922
21094
|
env: gitEnvironment(),
|
|
20923
21095
|
timeout: 5e3,
|
|
@@ -21437,7 +21609,7 @@ var init_sqlite = __esm({
|
|
|
21437
21609
|
});
|
|
21438
21610
|
|
|
21439
21611
|
// plugins/kxm/src/bindings.ts
|
|
21440
|
-
import { spawnSync as
|
|
21612
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
21441
21613
|
import { createHash as createHash8, randomUUID as randomUUID3 } from "node:crypto";
|
|
21442
21614
|
import {
|
|
21443
21615
|
chmodSync as chmodSync2,
|
|
@@ -21639,7 +21811,7 @@ function projectOperationLockFile(projectRoot) {
|
|
|
21639
21811
|
for (const key of Object.keys(env)) {
|
|
21640
21812
|
if (key.toLocaleUpperCase("en-US").startsWith("GIT_")) delete env[key];
|
|
21641
21813
|
}
|
|
21642
|
-
const result =
|
|
21814
|
+
const result = spawnSync6("git", ["-C", projectRoot, "rev-parse", "--absolute-git-dir"], {
|
|
21643
21815
|
encoding: "utf8",
|
|
21644
21816
|
env,
|
|
21645
21817
|
timeout: 5e3,
|
|
@@ -22816,7 +22988,7 @@ var init_database = __esm({
|
|
|
22816
22988
|
});
|
|
22817
22989
|
|
|
22818
22990
|
// plugins/kxm/src/runtime-store.ts
|
|
22819
|
-
import { spawnSync as
|
|
22991
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
22820
22992
|
import { createHash as createHash12, randomUUID as randomUUID4 } from "node:crypto";
|
|
22821
22993
|
import { existsSync as existsSync14, lstatSync as lstatSync4, mkdirSync as mkdirSync8, readFileSync as readFileSync11, realpathSync as realpathSync4, statSync, writeFileSync as writeFileSync8 } from "node:fs";
|
|
22822
22994
|
import { dirname as dirname10, isAbsolute as isAbsolute6, resolve as resolve11 } from "node:path";
|
|
@@ -22856,7 +23028,7 @@ function gitEnv() {
|
|
|
22856
23028
|
return Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_")));
|
|
22857
23029
|
}
|
|
22858
23030
|
function gitCommonDirectory(projectRoot) {
|
|
22859
|
-
const result =
|
|
23031
|
+
const result = spawnSync7("git", ["-C", projectRoot, "rev-parse", "--git-common-dir"], {
|
|
22860
23032
|
encoding: "utf8",
|
|
22861
23033
|
env: gitEnv(),
|
|
22862
23034
|
timeout: 3e4,
|
|
@@ -28369,10 +28541,13 @@ function runtimeFrom(ctx, command) {
|
|
|
28369
28541
|
const envServerUrl = ctx.env.KXM_SERVER_URL?.trim();
|
|
28370
28542
|
let boundHubUrl;
|
|
28371
28543
|
try {
|
|
28372
|
-
|
|
28544
|
+
const loaded = loadHubBinding(ctx.env);
|
|
28545
|
+
if (loaded.warning) ctx.io.stderr(`kxm: ${loaded.warning}
|
|
28546
|
+
`);
|
|
28547
|
+
boundHubUrl = loaded.record?.url;
|
|
28373
28548
|
} catch (error) {
|
|
28374
28549
|
if (error instanceof HubBindingError) {
|
|
28375
|
-
ctx.io.stderr(`kxm: ignoring malformed hub binding at ${hubBindingFile(ctx.env)};
|
|
28550
|
+
ctx.io.stderr(`kxm: ignoring malformed hub binding at ${hubBindingFile(ctx.env)}; falling back to the local hub. Run kxm hub bind <url> again
|
|
28376
28551
|
`);
|
|
28377
28552
|
} else {
|
|
28378
28553
|
throw error;
|
|
@@ -28621,7 +28796,7 @@ var init_vision_gate = __esm({
|
|
|
28621
28796
|
});
|
|
28622
28797
|
|
|
28623
28798
|
// plugins/kxm/src/permission.ts
|
|
28624
|
-
import { spawnSync as
|
|
28799
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
28625
28800
|
import { createHash as createHash17 } from "node:crypto";
|
|
28626
28801
|
import { existsSync as existsSync27, mkdtempSync, mkdirSync as mkdirSync20, readFileSync as readFileSync25, rmSync as rmSync8, writeFileSync as writeFileSync19 } from "node:fs";
|
|
28627
28802
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
@@ -29095,7 +29270,7 @@ function gitEnvironment2() {
|
|
|
29095
29270
|
return Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_")));
|
|
29096
29271
|
}
|
|
29097
29272
|
function git(root, args) {
|
|
29098
|
-
const result =
|
|
29273
|
+
const result = spawnSync8("git", ["-C", root, ...args], {
|
|
29099
29274
|
encoding: "utf8",
|
|
29100
29275
|
env: gitEnvironment2(),
|
|
29101
29276
|
timeout: 15e3,
|
|
@@ -29113,7 +29288,7 @@ function git(root, args) {
|
|
|
29113
29288
|
return result.stdout;
|
|
29114
29289
|
}
|
|
29115
29290
|
function gitBuffer(root, args) {
|
|
29116
|
-
const result =
|
|
29291
|
+
const result = spawnSync8("git", ["-C", root, ...args], {
|
|
29117
29292
|
env: gitEnvironment2(),
|
|
29118
29293
|
timeout: 15e3,
|
|
29119
29294
|
windowsHide: true,
|
|
@@ -29311,7 +29486,7 @@ function loadBaseProjectDeclarations(projectFile) {
|
|
|
29311
29486
|
return members;
|
|
29312
29487
|
}
|
|
29313
29488
|
function initShadowGitRoot(directory) {
|
|
29314
|
-
const result =
|
|
29489
|
+
const result = spawnSync8("git", ["-c", "init.defaultBranch=main", "init", "--quiet", directory], {
|
|
29315
29490
|
encoding: "utf8",
|
|
29316
29491
|
env: gitEnvironment2(),
|
|
29317
29492
|
timeout: 1e4,
|
|
@@ -35174,6 +35349,7 @@ function useColor() {
|
|
|
35174
35349
|
var program = new Command();
|
|
35175
35350
|
|
|
35176
35351
|
// plugins/kxm/src/kxm-update.ts
|
|
35352
|
+
import { spawnSync } from "node:child_process";
|
|
35177
35353
|
import { createHash } from "node:crypto";
|
|
35178
35354
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
35179
35355
|
import { join } from "node:path";
|
|
@@ -35192,6 +35368,18 @@ var KxmUpdateConfigError = class extends Error {
|
|
|
35192
35368
|
function kxmReleaseAssetName(version) {
|
|
35193
35369
|
return `kxm-${version}.tgz`;
|
|
35194
35370
|
}
|
|
35371
|
+
function kxmReleaseDownloadUrl(version, name = kxmReleaseAssetName(version)) {
|
|
35372
|
+
return `https://github.com/kontextmind/kxm/releases/download/v${version}/${name}`;
|
|
35373
|
+
}
|
|
35374
|
+
function ghReleaseDownloadAvailable(env = process.env) {
|
|
35375
|
+
const result = spawnSync("gh", ["--version"], {
|
|
35376
|
+
encoding: "utf8",
|
|
35377
|
+
env,
|
|
35378
|
+
windowsHide: true,
|
|
35379
|
+
timeout: 15e3
|
|
35380
|
+
});
|
|
35381
|
+
return !result.error && result.status === 0;
|
|
35382
|
+
}
|
|
35195
35383
|
function readInstalledKxmVersion(root) {
|
|
35196
35384
|
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
35197
35385
|
if (typeof pkg.version !== "string" || !parseSemver(pkg.version)) {
|
|
@@ -35340,13 +35528,17 @@ function verifyReleaseAssetDigest(path4, sha256) {
|
|
|
35340
35528
|
return false;
|
|
35341
35529
|
}
|
|
35342
35530
|
}
|
|
35343
|
-
function planKxmPackageUpdate(source, latest, releaseDir, asset) {
|
|
35531
|
+
function planKxmPackageUpdate(source, latest, releaseDir, asset, downloader = "gh") {
|
|
35344
35532
|
if (source === "npm") {
|
|
35345
35533
|
return [{ kind: "install", command: "npm", args: ["install", "--global", "--omit=peer", `@kontextmind/kxm@${latest}`] }];
|
|
35346
35534
|
}
|
|
35347
35535
|
const name = asset?.name ?? kxmReleaseAssetName(latest);
|
|
35348
35536
|
const steps = [
|
|
35349
|
-
{
|
|
35537
|
+
downloader === "curl" ? {
|
|
35538
|
+
kind: "download",
|
|
35539
|
+
command: "curl",
|
|
35540
|
+
args: ["--fail", "--silent", "--show-error", "--location", "--output", join(releaseDir, name), kxmReleaseDownloadUrl(latest, name)]
|
|
35541
|
+
} : {
|
|
35350
35542
|
kind: "download",
|
|
35351
35543
|
command: "gh",
|
|
35352
35544
|
args: ["release", "download", `v${latest}`, "--repo", "kontextmind/kxm", "--pattern", name, "--dir", releaseDir, "--clobber"]
|
|
@@ -40076,7 +40268,7 @@ init_project();
|
|
|
40076
40268
|
init_repo_root();
|
|
40077
40269
|
init_harness();
|
|
40078
40270
|
init_types();
|
|
40079
|
-
import { spawnSync as
|
|
40271
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
40080
40272
|
var PLUGIN_SUPPORTED_HARNESSES = Object.freeze(["pi", "omp", "claude"]);
|
|
40081
40273
|
async function cmdPluginInstall(runtime, options) {
|
|
40082
40274
|
const repoRoot = findKxmRepoRoot(import.meta.url);
|
|
@@ -40115,7 +40307,7 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
40115
40307
|
detail: `would install kxm plugin into pi: ${command} ${args.join(" ")}`
|
|
40116
40308
|
});
|
|
40117
40309
|
} else {
|
|
40118
|
-
const run = runtime.io.spawnSync ? runtime.io.spawnSync(command, args) :
|
|
40310
|
+
const run = runtime.io.spawnSync ? runtime.io.spawnSync(command, args) : spawnSync9(command, args, { encoding: "utf8", windowsHide: true, env: runtime.env });
|
|
40119
40311
|
if (run.error || run.status !== 0 && run.status !== null) {
|
|
40120
40312
|
results.push({
|
|
40121
40313
|
harness: "pi",
|
|
@@ -40146,7 +40338,7 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
40146
40338
|
detail: `would install kxm plugin into omp: ${command} ${args.join(" ")}`
|
|
40147
40339
|
});
|
|
40148
40340
|
} else {
|
|
40149
|
-
const run = runtime.io.spawnSync ? runtime.io.spawnSync(command, args) :
|
|
40341
|
+
const run = runtime.io.spawnSync ? runtime.io.spawnSync(command, args) : spawnSync9(command, args, { encoding: "utf8", windowsHide: true, env: runtime.env });
|
|
40150
40342
|
if (run.error || run.status !== 0 && run.status !== null) {
|
|
40151
40343
|
results.push({
|
|
40152
40344
|
harness: "omp",
|
|
@@ -40181,9 +40373,9 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
40181
40373
|
if (runtime.io.spawnSync) {
|
|
40182
40374
|
runtime.io.spawnSync(command, marketplaceArgs);
|
|
40183
40375
|
} else {
|
|
40184
|
-
|
|
40376
|
+
spawnSync9(command, marketplaceArgs, { encoding: "utf8", windowsHide: true, env: runtime.env });
|
|
40185
40377
|
}
|
|
40186
|
-
const run = runtime.io.spawnSync ? runtime.io.spawnSync(command, installArgs) :
|
|
40378
|
+
const run = runtime.io.spawnSync ? runtime.io.spawnSync(command, installArgs) : spawnSync9(command, installArgs, { encoding: "utf8", windowsHide: true, env: runtime.env });
|
|
40187
40379
|
if (run.error || run.status !== 0 && run.status !== null) {
|
|
40188
40380
|
results.push({
|
|
40189
40381
|
harness: "claude",
|
|
@@ -40307,7 +40499,7 @@ init_project_config();
|
|
|
40307
40499
|
init_runtime_store();
|
|
40308
40500
|
init_runtime_supervisor();
|
|
40309
40501
|
init_types();
|
|
40310
|
-
import { spawnSync as
|
|
40502
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
40311
40503
|
import { chmodSync as chmodSync6, existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as readFileSync30, writeFileSync as writeFileSync22 } from "node:fs";
|
|
40312
40504
|
import { basename as basename8, dirname as dirname18, join as join37, resolve as resolve25 } from "node:path";
|
|
40313
40505
|
var LANE_SCHEMA = "kxm.lanes.v1";
|
|
@@ -40322,7 +40514,7 @@ function gitEnv2() {
|
|
|
40322
40514
|
return Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_")));
|
|
40323
40515
|
}
|
|
40324
40516
|
function git2(cwd, args) {
|
|
40325
|
-
const result =
|
|
40517
|
+
const result = spawnSync10("git", ["-C", cwd, ...args], {
|
|
40326
40518
|
encoding: "utf8",
|
|
40327
40519
|
env: gitEnv2(),
|
|
40328
40520
|
timeout: 3e4,
|
|
@@ -40897,7 +41089,7 @@ function cmdLand(runtime, options = {}) {
|
|
|
40897
41089
|
// plugins/kxm/src/cli/assign.ts
|
|
40898
41090
|
init_project_config();
|
|
40899
41091
|
init_types();
|
|
40900
|
-
import { spawnSync as
|
|
41092
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
40901
41093
|
import { existsSync as existsSync34 } from "node:fs";
|
|
40902
41094
|
import { join as join39 } from "node:path";
|
|
40903
41095
|
var kxmAssignCliSeams = {};
|
|
@@ -40983,7 +41175,7 @@ async function cmdAssign(runtime, subcommand, args) {
|
|
|
40983
41175
|
return 0;
|
|
40984
41176
|
}
|
|
40985
41177
|
const spawn6 = kxmAssignCliSeams.spawn ?? ((commandName, commandArgs, options) => {
|
|
40986
|
-
const result2 =
|
|
41178
|
+
const result2 = spawnSync11(commandName, commandArgs, {
|
|
40987
41179
|
cwd: options.cwd,
|
|
40988
41180
|
stdio: options.stdio,
|
|
40989
41181
|
env: options.env,
|
|
@@ -49448,7 +49640,7 @@ var MAX_RENDER_WRITE_CHARS = 1024 * 1024;
|
|
|
49448
49640
|
// plugins/kxm/src/tui.ts
|
|
49449
49641
|
import { mkdirSync as mkdirSync25 } from "node:fs";
|
|
49450
49642
|
import { join as join44, resolve as resolve27, dirname as dirname20 } from "node:path";
|
|
49451
|
-
import { spawnSync as
|
|
49643
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
49452
49644
|
|
|
49453
49645
|
// packages/core/tui/src/types/surface.ts
|
|
49454
49646
|
var KXM_TUI_LIMITS = Object.freeze({
|
|
@@ -50005,16 +50197,16 @@ function applyMeshTuiKey(view, key, itemCount = 0) {
|
|
|
50005
50197
|
function copyToClipboard(text) {
|
|
50006
50198
|
try {
|
|
50007
50199
|
if (process.platform === "darwin") {
|
|
50008
|
-
const proc =
|
|
50200
|
+
const proc = spawnSync12("pbcopy", { input: text, encoding: "utf8", windowsHide: true });
|
|
50009
50201
|
return proc.status === 0;
|
|
50010
50202
|
}
|
|
50011
50203
|
if (process.platform === "win32") {
|
|
50012
|
-
const proc =
|
|
50204
|
+
const proc = spawnSync12("clip", { input: text, encoding: "utf8", windowsHide: true });
|
|
50013
50205
|
return proc.status === 0;
|
|
50014
50206
|
}
|
|
50015
|
-
const wl =
|
|
50207
|
+
const wl = spawnSync12("wl-copy", [text], { encoding: "utf8", windowsHide: true });
|
|
50016
50208
|
if (wl.status === 0) return true;
|
|
50017
|
-
const xclip =
|
|
50209
|
+
const xclip = spawnSync12("xclip", ["-selection", "clipboard"], { input: text, encoding: "utf8", windowsHide: true });
|
|
50018
50210
|
return xclip.status === 0;
|
|
50019
50211
|
} catch {
|
|
50020
50212
|
return false;
|
|
@@ -50022,7 +50214,7 @@ function copyToClipboard(text) {
|
|
|
50022
50214
|
}
|
|
50023
50215
|
function spawnDegradeWorktree(repoRoot, runId, options) {
|
|
50024
50216
|
const runner = options?.execFn ?? ((cmd, args) => {
|
|
50025
|
-
const res =
|
|
50217
|
+
const res = spawnSync12(cmd, args, {
|
|
50026
50218
|
cwd: repoRoot,
|
|
50027
50219
|
encoding: "utf8",
|
|
50028
50220
|
windowsHide: true,
|
|
@@ -50806,7 +50998,7 @@ async function runMeshTui(input) {
|
|
|
50806
50998
|
}
|
|
50807
50999
|
|
|
50808
51000
|
// plugins/kxm/src/session-work.ts
|
|
50809
|
-
import { spawnSync as
|
|
51001
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
50810
51002
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
50811
51003
|
import { existsSync as existsSync36, mkdirSync as mkdirSync26, readFileSync as readFileSync32, renameSync as renameSync8, writeFileSync as writeFileSync23 } from "node:fs";
|
|
50812
51004
|
import { join as join45 } from "node:path";
|
|
@@ -50867,10 +51059,10 @@ function formatShipLine(ship) {
|
|
|
50867
51059
|
}
|
|
50868
51060
|
function readGitShip(cwd) {
|
|
50869
51061
|
try {
|
|
50870
|
-
const dirty =
|
|
51062
|
+
const dirty = spawnSync13("git", ["--no-optional-locks", "-C", cwd, "status", "--porcelain"], { encoding: "utf8", windowsHide: true });
|
|
50871
51063
|
if (dirty.status !== 0) return void 0;
|
|
50872
51064
|
const isDirty = dirty.stdout.trim().length > 0;
|
|
50873
|
-
const upstream =
|
|
51065
|
+
const upstream = spawnSync13("git", ["-C", cwd, "rev-list", "--count", "@{u}..HEAD"], { encoding: "utf8", windowsHide: true });
|
|
50874
51066
|
if (upstream.status === 0) {
|
|
50875
51067
|
return {
|
|
50876
51068
|
dirty: isDirty,
|
|
@@ -50878,9 +51070,9 @@ function readGitShip(cwd) {
|
|
|
50878
51070
|
};
|
|
50879
51071
|
}
|
|
50880
51072
|
for (const baseRef of ["origin/HEAD", "main", "origin/main", "master", "origin/master"]) {
|
|
50881
|
-
const mb =
|
|
51073
|
+
const mb = spawnSync13("git", ["-C", cwd, "merge-base", baseRef, "HEAD"], { encoding: "utf8", windowsHide: true });
|
|
50882
51074
|
if (mb.status === 0 && mb.stdout.trim()) {
|
|
50883
|
-
const count =
|
|
51075
|
+
const count = spawnSync13("git", ["-C", cwd, "rev-list", "--count", `${mb.stdout.trim()}..HEAD`], { encoding: "utf8", windowsHide: true });
|
|
50884
51076
|
if (count.status === 0) {
|
|
50885
51077
|
return {
|
|
50886
51078
|
dirty: isDirty,
|
|
@@ -51424,20 +51616,6 @@ init_repo_root();
|
|
|
51424
51616
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
51425
51617
|
import { dirname as dirname22 } from "node:path";
|
|
51426
51618
|
import { homedir as homedir7 } from "node:os";
|
|
51427
|
-
async function hubGet(url, fetchImpl, headers) {
|
|
51428
|
-
try {
|
|
51429
|
-
const response = await fetchImpl(url, headers ? { headers } : void 0);
|
|
51430
|
-
const text = redactSecrets((await response.text()).slice(0, 8e3));
|
|
51431
|
-
let body = text;
|
|
51432
|
-
try {
|
|
51433
|
-
body = JSON.parse(text);
|
|
51434
|
-
} catch {
|
|
51435
|
-
}
|
|
51436
|
-
return { ok: response.ok, status: response.status, body };
|
|
51437
|
-
} catch {
|
|
51438
|
-
return { ok: false, status: 0, body: { error: "hub_unreachable" } };
|
|
51439
|
-
}
|
|
51440
|
-
}
|
|
51441
51619
|
function installProbeFrom(runtime) {
|
|
51442
51620
|
const partial = runtime.io.installProbe ?? {};
|
|
51443
51621
|
const moduleDir = partial.moduleDir ?? dirname22(fileURLToPath3(import.meta.url));
|
|
@@ -51512,8 +51690,11 @@ async function cmdStatus(runtime) {
|
|
|
51512
51690
|
}
|
|
51513
51691
|
if (!(error instanceof HubBindingError)) throw error;
|
|
51514
51692
|
}
|
|
51515
|
-
const health = await
|
|
51516
|
-
const ready = await
|
|
51693
|
+
const health = await readHubEndpoint(runtime.serverUrl, "health", runtime.fetchImpl, headers ? { headers } : {});
|
|
51694
|
+
const ready = await readHubEndpoint(runtime.serverUrl, "ready", runtime.fetchImpl, headers ? { headers } : {});
|
|
51695
|
+
const proxyKind = [health.kind, ready.kind].find((kind) => kind === "redirect" || kind === "auth_proxy");
|
|
51696
|
+
const notHub = !proxyKind && (health.kind === "not_hub" || ready.kind === "not_hub");
|
|
51697
|
+
const probeNote = proxyKind === "redirect" ? " \xB7 auth proxy or redirect" : proxyKind === "auth_proxy" ? " \xB7 auth proxy (HTML login page)" : notHub ? " \xB7 not a kxm hub" : "";
|
|
51517
51698
|
const effectiveScope = connection.scope;
|
|
51518
51699
|
const overridden = connection.urlSource === "env";
|
|
51519
51700
|
const identity = {
|
|
@@ -51537,7 +51718,7 @@ async function cmdStatus(runtime) {
|
|
|
51537
51718
|
runtime.io,
|
|
51538
51719
|
runtime.json,
|
|
51539
51720
|
payload,
|
|
51540
|
-
`hub health=${health.ok} ready=${ready.ok} \xB7 ${effectiveScope} hub${overridden ? " (KXM_SERVER_URL)" : ""} \xB7 mode=${identity.mode} project=${identity.project} (${connection.sourceLabel}) key=${identity.keySource}`
|
|
51721
|
+
`hub health=${health.ok} ready=${ready.ok} \xB7 ${effectiveScope} hub${overridden ? " (KXM_SERVER_URL)" : ""} \xB7 mode=${identity.mode} project=${identity.project} (${connection.sourceLabel}) key=${identity.keySource}${probeNote}`
|
|
51541
51722
|
);
|
|
51542
51723
|
return payload.ok ? 0 : 1;
|
|
51543
51724
|
}
|
|
@@ -51748,7 +51929,7 @@ async function cmdHubBind(runtime, rawUrl, options = {}) {
|
|
|
51748
51929
|
return 2;
|
|
51749
51930
|
}
|
|
51750
51931
|
}
|
|
51751
|
-
const file = hubBindingFile(runtime.env);
|
|
51932
|
+
const file = cloud ? hubBindingCloudFile(runtime.env) : hubBindingFile(runtime.env);
|
|
51752
51933
|
const bindingCommand = tokenCommand ?? (cloud && keyOp ? `op read ${keyOp}` : void 0);
|
|
51753
51934
|
const cloudFields = cloud ? { cloud: true, ...tokenEnv ? { tokenEnv } : {}, ...bindingCommand ? { tokenCommand: bindingCommand } : {} } : {};
|
|
51754
51935
|
const record = {
|
|
@@ -51773,6 +51954,27 @@ async function cmdHubBind(runtime, rawUrl, options = {}) {
|
|
|
51773
51954
|
);
|
|
51774
51955
|
return 0;
|
|
51775
51956
|
}
|
|
51957
|
+
const probe = await probeHubHealth(url, runtime.fetchImpl);
|
|
51958
|
+
const acceptable = probe.kind === "hub" || probe.kind === "timeout" || probe.kind === "unreachable";
|
|
51959
|
+
if (!acceptable && options.force !== true) {
|
|
51960
|
+
print(
|
|
51961
|
+
runtime.io,
|
|
51962
|
+
runtime.json,
|
|
51963
|
+
{
|
|
51964
|
+
ok: false,
|
|
51965
|
+
command: "hub bind",
|
|
51966
|
+
error: "hub_not_kxm",
|
|
51967
|
+
url,
|
|
51968
|
+
scope,
|
|
51969
|
+
kind: probe.kind,
|
|
51970
|
+
status: probe.status,
|
|
51971
|
+
detail: probe.detail,
|
|
51972
|
+
nextAction: "bind_a_kxm_hub_or_pass_force"
|
|
51973
|
+
},
|
|
51974
|
+
`refusing to bind ${url}: ${probe.detail}; no binding was written. Pass --force to bind anyway`
|
|
51975
|
+
);
|
|
51976
|
+
return 2;
|
|
51977
|
+
}
|
|
51776
51978
|
try {
|
|
51777
51979
|
writeHubEndpoint(runtime.dirs.workdir, {
|
|
51778
51980
|
mode: cloud ? "cloud" : "local",
|
|
@@ -51793,12 +51995,12 @@ async function cmdHubBind(runtime, rawUrl, options = {}) {
|
|
|
51793
51995
|
throw error;
|
|
51794
51996
|
}
|
|
51795
51997
|
writeHubBinding({ ...record, boundAt: (/* @__PURE__ */ new Date()).toISOString() }, runtime.env);
|
|
51796
|
-
const
|
|
51998
|
+
const healthText = acceptable ? formatHubBindHealth(probe.health) : `${probe.detail} (--force)`;
|
|
51797
51999
|
print(
|
|
51798
52000
|
runtime.io,
|
|
51799
52001
|
runtime.json,
|
|
51800
|
-
{ ok: true, command: "hub bind", url, scope, file, configFile, project: identity.project, health, probeMs, ...cloudFields },
|
|
51801
|
-
`bound hub ${url} \xB7 ${scope} \xB7 ${
|
|
52002
|
+
{ ok: true, command: "hub bind", url, scope, file, configFile, project: identity.project, health: probe.health, probeMs: probe.probeMs, kind: probe.kind, ...cloudFields },
|
|
52003
|
+
`bound hub ${url} \xB7 ${scope} \xB7 ${healthText}${cloud ? cloudNote : scope === "remote" ? " \xB7 token leaves this machine" : ""}`
|
|
51802
52004
|
);
|
|
51803
52005
|
return 0;
|
|
51804
52006
|
}
|
|
@@ -52231,7 +52433,7 @@ init_redact();
|
|
|
52231
52433
|
init_telemetry();
|
|
52232
52434
|
init_routing();
|
|
52233
52435
|
init_prices();
|
|
52234
|
-
import { spawnSync as
|
|
52436
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
52235
52437
|
import { createHash as createHash19 } from "node:crypto";
|
|
52236
52438
|
import { existsSync as existsSync47, mkdtempSync as mkdtempSync3, readFileSync as readFileSync41, rmSync as rmSync13 } from "node:fs";
|
|
52237
52439
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
@@ -53110,7 +53312,7 @@ ${divider}
|
|
|
53110
53312
|
|
|
53111
53313
|
// plugins/kxm/src/ssh-remote.ts
|
|
53112
53314
|
init_safety_integrity();
|
|
53113
|
-
import { spawnSync as
|
|
53315
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
53114
53316
|
import { existsSync as existsSync44, mkdirSync as mkdirSync30, readFileSync as readFileSync39, readdirSync as readdirSync14, rmSync as rmSync12, statSync as statSync7 } from "node:fs";
|
|
53115
53317
|
import { homedir as homedir8 } from "node:os";
|
|
53116
53318
|
import { join as join52, resolve as resolve31 } from "node:path";
|
|
@@ -53186,7 +53388,7 @@ function parseSshConfig(configPath) {
|
|
|
53186
53388
|
return [];
|
|
53187
53389
|
}
|
|
53188
53390
|
}
|
|
53189
|
-
function resolveSshHostG(host, execFn =
|
|
53391
|
+
function resolveSshHostG(host, execFn = spawnSync14) {
|
|
53190
53392
|
try {
|
|
53191
53393
|
const result = execFn("ssh", ["-G", host], { encoding: "utf-8" });
|
|
53192
53394
|
if (result.status !== 0 || !result.stdout) {
|
|
@@ -53252,7 +53454,7 @@ function buildSshArgs(options) {
|
|
|
53252
53454
|
args.push(options.host);
|
|
53253
53455
|
return args;
|
|
53254
53456
|
}
|
|
53255
|
-
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn =
|
|
53457
|
+
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync14) {
|
|
53256
53458
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
53257
53459
|
const controlPath = join52(resolvedDir, "%C");
|
|
53258
53460
|
try {
|
|
@@ -53264,7 +53466,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
53264
53466
|
return false;
|
|
53265
53467
|
}
|
|
53266
53468
|
}
|
|
53267
|
-
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn =
|
|
53469
|
+
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync14) {
|
|
53268
53470
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
53269
53471
|
const controlPath = join52(resolvedDir, "%C");
|
|
53270
53472
|
try {
|
|
@@ -53278,7 +53480,7 @@ function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
53278
53480
|
}
|
|
53279
53481
|
function executeSshRun(params) {
|
|
53280
53482
|
const startTime = Date.now();
|
|
53281
|
-
const execSyncFn = params.execFn ??
|
|
53483
|
+
const execSyncFn = params.execFn ?? spawnSync14;
|
|
53282
53484
|
if (params.action === "info") {
|
|
53283
53485
|
if (params.host) {
|
|
53284
53486
|
const hostInfo = resolveSshHostG(params.host, execSyncFn);
|
|
@@ -54423,7 +54625,7 @@ init_types();
|
|
|
54423
54625
|
init_repo_root();
|
|
54424
54626
|
function cliSpawn(runtime, command, args, extra) {
|
|
54425
54627
|
if (runtime.io.spawnSync) return runtime.io.spawnSync(command, args);
|
|
54426
|
-
const result =
|
|
54628
|
+
const result = spawnSync15(command, [...args], {
|
|
54427
54629
|
encoding: "utf8",
|
|
54428
54630
|
windowsHide: true,
|
|
54429
54631
|
shell: process.platform === "win32",
|
|
@@ -54463,7 +54665,8 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
54463
54665
|
}
|
|
54464
54666
|
const releaseDir = mkdtempSync3(join55(tmpdir3(), "kxm-pkg-update-"));
|
|
54465
54667
|
try {
|
|
54466
|
-
const
|
|
54668
|
+
const downloader = notice.source === "github" && !ghReleaseDownloadAvailable(runtime.env) ? "curl" : "gh";
|
|
54669
|
+
const planned = planKxmPackageUpdate(notice.source, notice.latest, releaseDir, notice.asset, downloader);
|
|
54467
54670
|
if (runtime.dryRun) {
|
|
54468
54671
|
return { ok: true, detail: planned.map(formatPackageUpdateStep).join(" && ") };
|
|
54469
54672
|
}
|
|
@@ -56042,7 +56245,7 @@ function createProgram(ctx, result, argv) {
|
|
|
56042
56245
|
addGlobalOptions(hub.command("stop").description("Request managed hub and worker shutdown")).option("--wait-ms <ms>", "How long to wait for PID files to clear").action(async function hubStopAction(options) {
|
|
56043
56246
|
result.code = await cmdStop(runtimeFrom(ctx, this), options.waitMs);
|
|
56044
56247
|
});
|
|
56045
|
-
addGlobalOptions(hub.command("bind").description("Bind this machine to a running hub").argument("<url>", "Hub base URL (http or https)")).option("--cloud", "Mark the hub remote even when the URL is a loopback forward").option("--token-env <name>", "Environment variable that holds the hub token; the token is not stored").option("--token-command <command>", "Program that prints the hub token; the token is not stored").option("--key-op <ref>", "op:// reference for the hub token; resolved with op read, never stored").action(async function hubBindAction(url, options) {
|
|
56248
|
+
addGlobalOptions(hub.command("bind").description("Bind this machine to a running hub").argument("<url>", "Hub base URL (http or https)")).option("--cloud", "Mark the hub remote even when the URL is a loopback forward").option("--token-env <name>", "Environment variable that holds the hub token; the token is not stored").option("--token-command <command>", "Program that prints the hub token; the token is not stored").option("--key-op <ref>", "op:// reference for the hub token; resolved with op read, never stored").option("--force", "Bind even when the URL is not a kxm hub").action(async function hubBindAction(url, options) {
|
|
56046
56249
|
result.code = await cmdHubBind(runtimeFrom(ctx, this), url, options);
|
|
56047
56250
|
});
|
|
56048
56251
|
addGlobalOptions(hub.command("unbind").description("Remove this machine's hub binding")).action(bind(cmdHubUnbind));
|