@kontextmind/kxm 0.7.165 → 0.7.167
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 +16 -0
- package/docs/README.md +1 -0
- package/docs/architecture/hosted-direction.md +9 -4
- package/docs/architecture/inventory.md +1 -0
- package/docs/concepts/trust-model.md +1 -1
- package/docs/contributing/decisions.md +153 -0
- package/docs/contributing/learnings.md +54 -53
- package/docs/contributing/operating-rules.md +19 -6
- package/docs/glossary.md +2 -2
- package/docs/operations/troubleshooting.md +2 -2
- package/docs/operations.md +62 -8
- package/docs/reference/cli-reference.md +11 -11
- package/docs/reference/config-reference.md +36 -11
- package/docs/reference/configuration.md +2 -2
- package/docs/reference/tools.md +1 -1
- package/docs/start/quickstart-claude-code.md +2 -2
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/README.md +3 -3
- package/plugins/kxm/dist/claude-hook.js +417 -66
- package/plugins/kxm/dist/cli.js +1399 -900
- package/plugins/kxm/dist/extension.js +399 -64
- package/plugins/kxm/dist/mcp-server.js +622 -135
- package/plugins/kxm/dist/runtime-supervisor.js +668 -166
- package/plugins/kxm/dist/runtime.js +713 -211
- package/plugins/kxm/dist/server.js +466 -58
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +15 -7
- package/plugins/kxm/src/cli/hub.ts +80 -21
- package/plugins/kxm/src/cli/types.ts +8 -1
- package/plugins/kxm/src/cli.ts +41 -7
- package/plugins/kxm/src/config.ts +246 -3
- package/plugins/kxm/src/extension.ts +8 -7
- package/plugins/kxm/src/hub-autostart.ts +20 -0
- package/plugins/kxm/src/hub-env.ts +83 -31
- package/plugins/kxm/src/hub-identity.ts +337 -0
- package/plugins/kxm/src/mcp-server.ts +17 -15
- package/plugins/kxm/src/project-name.ts +6 -47
- package/plugins/kxm/src/server.ts +22 -4
- package/scripts/kxm-hub.mjs +5 -0
|
@@ -2987,7 +2987,7 @@ var require_compile = __commonJS({
|
|
|
2987
2987
|
const schOrFunc = root.refs[ref];
|
|
2988
2988
|
if (schOrFunc)
|
|
2989
2989
|
return schOrFunc;
|
|
2990
|
-
let _sch =
|
|
2990
|
+
let _sch = resolve13.call(this, root, ref);
|
|
2991
2991
|
if (_sch === void 0) {
|
|
2992
2992
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2993
2993
|
const { schemaId } = this.opts;
|
|
@@ -3014,7 +3014,7 @@ var require_compile = __commonJS({
|
|
|
3014
3014
|
function sameSchemaEnv(s1, s2) {
|
|
3015
3015
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3016
3016
|
}
|
|
3017
|
-
function
|
|
3017
|
+
function resolve13(root, ref) {
|
|
3018
3018
|
let sch;
|
|
3019
3019
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3020
3020
|
ref = sch;
|
|
@@ -3839,7 +3839,7 @@ var require_fast_uri = __commonJS({
|
|
|
3839
3839
|
}
|
|
3840
3840
|
return uri;
|
|
3841
3841
|
}
|
|
3842
|
-
function
|
|
3842
|
+
function resolve13(baseURI, relativeURI, options) {
|
|
3843
3843
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3844
3844
|
const {
|
|
3845
3845
|
parsed: baseParsed,
|
|
@@ -4201,7 +4201,7 @@ var require_fast_uri = __commonJS({
|
|
|
4201
4201
|
var fastUri = {
|
|
4202
4202
|
SCHEMES,
|
|
4203
4203
|
normalize,
|
|
4204
|
-
resolve:
|
|
4204
|
+
resolve: resolve13,
|
|
4205
4205
|
resolveComponent,
|
|
4206
4206
|
equal,
|
|
4207
4207
|
serialize,
|
|
@@ -14781,9 +14781,9 @@ var require_dist = __commonJS({
|
|
|
14781
14781
|
// plugins/kxm/src/runtime-supervisor.ts
|
|
14782
14782
|
import { spawn as spawn3 } from "node:child_process";
|
|
14783
14783
|
import { createHash as createHash15, createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
14784
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
14784
|
+
import { chmodSync as chmodSync2, existsSync as existsSync20, lstatSync as lstatSync6, mkdirSync as mkdirSync10, readFileSync as readFileSync17, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
|
|
14785
14785
|
import { createServer } from "node:http";
|
|
14786
|
-
import { dirname as
|
|
14786
|
+
import { dirname as dirname13, isAbsolute as isAbsolute8, join as join22 } from "node:path";
|
|
14787
14787
|
|
|
14788
14788
|
// plugins/kxm/src/repo-root.ts
|
|
14789
14789
|
import { existsSync } from "node:fs";
|
|
@@ -16097,7 +16097,7 @@ function defaultSpawn(command, args, options) {
|
|
|
16097
16097
|
if (options.signal?.aborted) {
|
|
16098
16098
|
return Promise.resolve({ stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") });
|
|
16099
16099
|
}
|
|
16100
|
-
return new Promise((
|
|
16100
|
+
return new Promise((resolve13) => {
|
|
16101
16101
|
const stdout = [];
|
|
16102
16102
|
const stderr = [];
|
|
16103
16103
|
let outputBytes = 0;
|
|
@@ -16128,7 +16128,7 @@ function defaultSpawn(command, args, options) {
|
|
|
16128
16128
|
const started = Boolean(child?.pid);
|
|
16129
16129
|
if (started && !observedChildExit) error ??= new Error("process_exit_unobserved");
|
|
16130
16130
|
const unverifiedDescendants = stopping || started && !observedChildExit;
|
|
16131
|
-
|
|
16131
|
+
resolve13({
|
|
16132
16132
|
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
16133
16133
|
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
16134
16134
|
code,
|
|
@@ -17976,8 +17976,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
17976
17976
|
const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
|
|
17977
17977
|
if (maxWriteRepositories > writable) issues.push(issue3("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
|
|
17978
17978
|
}
|
|
17979
|
-
const
|
|
17980
|
-
const minimumPassed =
|
|
17979
|
+
const join23 = objectValue(step.join);
|
|
17980
|
+
const minimumPassed = join23 && typeof join23.minimumPassed === "number" ? join23.minimumPassed : void 0;
|
|
17981
17981
|
if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue3("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
|
|
17982
17982
|
const distinctBy = names(assignment?.distinctBy);
|
|
17983
17983
|
if (distinctBy.length > 0) {
|
|
@@ -22557,7 +22557,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
22557
22557
|
const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
|
|
22558
22558
|
const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
|
|
22559
22559
|
const assignments = compileAssignments(step, id, agent, sink);
|
|
22560
|
-
const
|
|
22560
|
+
const join23 = compileJoin(step, id, sink);
|
|
22561
22561
|
const requiredEvidence = compileEvidence(step, id, sink);
|
|
22562
22562
|
const transitions = compileTransitions(step, id, index, stepIndex, sink);
|
|
22563
22563
|
const outcomes = Object.keys(transitions).sort(compareCodeUnits5);
|
|
@@ -22585,7 +22585,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
22585
22585
|
transitions: orderedTransitions,
|
|
22586
22586
|
requiresPlanHash: requirePlanHash.includes(id),
|
|
22587
22587
|
assignments,
|
|
22588
|
-
join:
|
|
22588
|
+
join: join23
|
|
22589
22589
|
};
|
|
22590
22590
|
if (kind === "agent" || kind === "moa") {
|
|
22591
22591
|
if (!agent) return void 0;
|
|
@@ -22635,15 +22635,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
|
|
|
22635
22635
|
};
|
|
22636
22636
|
}
|
|
22637
22637
|
function compileJoin(step, stepId, sink) {
|
|
22638
|
-
const
|
|
22639
|
-
if (!
|
|
22640
|
-
const declared = stringValue2(
|
|
22638
|
+
const join23 = objectValue2(step.join);
|
|
22639
|
+
if (!join23) return { strategy: "all" };
|
|
22640
|
+
const declared = stringValue2(join23.strategy);
|
|
22641
22641
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
22642
|
-
const minimumPassed = compileOptionalCount(
|
|
22642
|
+
const minimumPassed = compileOptionalCount(join23.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
22643
22643
|
const compiled = {
|
|
22644
22644
|
strategy,
|
|
22645
22645
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
22646
|
-
...typeof
|
|
22646
|
+
...typeof join23.cancelRemaining === "boolean" ? { cancelRemaining: join23.cancelRemaining } : {}
|
|
22647
22647
|
};
|
|
22648
22648
|
return compiled;
|
|
22649
22649
|
}
|
|
@@ -23996,12 +23996,12 @@ function enqueueKxmScheduledRun(storePath, runId, configRevision, bound, start)
|
|
|
23996
23996
|
if (owner.admitted.has(runId) || owner.queue.some((item) => item.runId === runId)) {
|
|
23997
23997
|
return Promise.reject(runtimeError("run_busy", runId, `run ${runId} is already admitted or queued`));
|
|
23998
23998
|
}
|
|
23999
|
-
return new Promise((
|
|
23999
|
+
return new Promise((resolve13, reject) => {
|
|
24000
24000
|
owner.queue.push({
|
|
24001
24001
|
runId,
|
|
24002
24002
|
configRevision,
|
|
24003
24003
|
bound,
|
|
24004
|
-
start: (token) => start(token).then(
|
|
24004
|
+
start: (token) => start(token).then(resolve13, reject),
|
|
24005
24005
|
fail: (error) => reject(error)
|
|
24006
24006
|
});
|
|
24007
24007
|
pump(storePath, owner);
|
|
@@ -24794,38 +24794,344 @@ function loadPriceCatalog(rootOrPath) {
|
|
|
24794
24794
|
// plugins/kxm/src/engine.ts
|
|
24795
24795
|
var import_yaml11 = __toESM(require_dist(), 1);
|
|
24796
24796
|
import { createHash as createHash14, randomBytes, timingSafeEqual } from "node:crypto";
|
|
24797
|
-
import { existsSync as
|
|
24798
|
-
import { join as
|
|
24797
|
+
import { existsSync as existsSync15, readFileSync as readFileSync13 } from "node:fs";
|
|
24798
|
+
import { join as join18 } from "node:path";
|
|
24799
24799
|
|
|
24800
24800
|
// plugins/kxm/src/routes.ts
|
|
24801
24801
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
24802
|
-
import { existsSync as
|
|
24803
|
-
import { join as
|
|
24802
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5, readdirSync as readdirSync6 } from "node:fs";
|
|
24803
|
+
import { join as join12 } from "node:path";
|
|
24804
24804
|
|
|
24805
24805
|
// plugins/kxm/src/role.ts
|
|
24806
24806
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
24807
24807
|
|
|
24808
24808
|
// plugins/kxm/src/config.ts
|
|
24809
24809
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
24810
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "node:fs";
|
|
24811
|
+
import { tmpdir, homedir as homedir2 } from "node:os";
|
|
24812
|
+
import { dirname as dirname6, join as join11, resolve as resolve7 } from "node:path";
|
|
24813
|
+
var KXM_CONFIG_SCHEMA = "kxm.config.v1";
|
|
24814
|
+
var KxmHubConfigError = class extends Error {
|
|
24815
|
+
code = "hub_config_invalid";
|
|
24816
|
+
constructor(message) {
|
|
24817
|
+
super(message);
|
|
24818
|
+
this.name = "KxmHubConfigError";
|
|
24819
|
+
}
|
|
24820
|
+
};
|
|
24821
|
+
var HUB_ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
|
|
24822
|
+
var HUB_OP_REF = /^op:\/\/\S+\/\S+\/\S+$/;
|
|
24823
|
+
var LITERAL_SECRET_KEY = /^(token|secret|password|authToken|auth_token|apiKey|api_key|api_token|bearer|credential|access_token)$/i;
|
|
24824
|
+
function isHubKeyEnvName(value) {
|
|
24825
|
+
return HUB_ENV_NAME.test(value);
|
|
24826
|
+
}
|
|
24827
|
+
function isHubOpReference(value) {
|
|
24828
|
+
return HUB_OP_REF.test(value);
|
|
24829
|
+
}
|
|
24830
|
+
var IMPROVEMENT_PROMOTION_POLICIES = ["manual_pr", "critic_quorum", "auto_threshold"];
|
|
24831
|
+
var DEFAULT_KXM_CONFIG = {
|
|
24832
|
+
schema: KXM_CONFIG_SCHEMA,
|
|
24833
|
+
user: {
|
|
24834
|
+
theme: "dark",
|
|
24835
|
+
preferredCritics: ["reviewer-arch", "reviewer-cli"],
|
|
24836
|
+
tokenBudget: 16e3
|
|
24837
|
+
},
|
|
24838
|
+
defaults: {
|
|
24839
|
+
workflow: "software-engineering/feature-implementation",
|
|
24840
|
+
harness: "pi"
|
|
24841
|
+
},
|
|
24842
|
+
dash: {
|
|
24843
|
+
defaultScreen: "agents",
|
|
24844
|
+
refreshIntervalMs: 1e3,
|
|
24845
|
+
autoOpen: false
|
|
24846
|
+
},
|
|
24847
|
+
sync: {
|
|
24848
|
+
defaultTracker: "none"
|
|
24849
|
+
},
|
|
24850
|
+
hub: {
|
|
24851
|
+
autoStart: "background"
|
|
24852
|
+
},
|
|
24853
|
+
improvement: {
|
|
24854
|
+
promotionPolicy: "manual_pr",
|
|
24855
|
+
telemetryHalfLifeDays: 14,
|
|
24856
|
+
autoThreshold: {
|
|
24857
|
+
minRuns: 10,
|
|
24858
|
+
minPassRate: 0.95,
|
|
24859
|
+
minCostSavings: 0.5
|
|
24860
|
+
}
|
|
24861
|
+
},
|
|
24862
|
+
routing: {
|
|
24863
|
+
shadowExecution: {
|
|
24864
|
+
enabled: false,
|
|
24865
|
+
sampleRate: 0.05,
|
|
24866
|
+
candidateModels: []
|
|
24867
|
+
},
|
|
24868
|
+
circuitBreaker: {
|
|
24869
|
+
mode: "soft_demotion",
|
|
24870
|
+
failureThreshold: 3,
|
|
24871
|
+
windowSeconds: 3600,
|
|
24872
|
+
cooldownSeconds: 1800,
|
|
24873
|
+
penaltyMultiplier: 5
|
|
24874
|
+
}
|
|
24875
|
+
},
|
|
24876
|
+
telemetry: {
|
|
24877
|
+
federated: true,
|
|
24878
|
+
anonymize: true
|
|
24879
|
+
}
|
|
24880
|
+
};
|
|
24881
|
+
function userConfigDirectory(overrideDir) {
|
|
24882
|
+
if (overrideDir) return resolve7(overrideDir);
|
|
24883
|
+
return resolve7(process.env.KXM_USER_CONFIG_DIR?.trim() || join11(homedir2(), ".config", "kxm"));
|
|
24884
|
+
}
|
|
24885
|
+
function repoConfigDirectory(repoRoot) {
|
|
24886
|
+
return resolve7(repoRoot, ".kxm");
|
|
24887
|
+
}
|
|
24888
|
+
function deepMerge(target, source) {
|
|
24889
|
+
const result = { ...target };
|
|
24890
|
+
for (const [key, val] of Object.entries(source)) {
|
|
24891
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
24892
|
+
const existing = result[key] && typeof result[key] === "object" && !Array.isArray(result[key]) ? result[key] : {};
|
|
24893
|
+
result[key] = deepMerge(existing, val);
|
|
24894
|
+
} else if (val !== void 0) {
|
|
24895
|
+
result[key] = val;
|
|
24896
|
+
}
|
|
24897
|
+
}
|
|
24898
|
+
return result;
|
|
24899
|
+
}
|
|
24900
|
+
function literalSecretMessage(path) {
|
|
24901
|
+
return `refusing literal hub token at ${path}: store an op:// reference (key.op) or an environment variable name (key.env), never the token`;
|
|
24902
|
+
}
|
|
24903
|
+
function rejectLiteralHubSecrets(value, path) {
|
|
24904
|
+
if (Array.isArray(value)) {
|
|
24905
|
+
value.forEach((item, index) => rejectLiteralHubSecrets(item, `${path}[${index}]`));
|
|
24906
|
+
return;
|
|
24907
|
+
}
|
|
24908
|
+
if (!value || typeof value !== "object") return;
|
|
24909
|
+
for (const [key, child] of Object.entries(value)) {
|
|
24910
|
+
const childPath = `${path}.${key}`;
|
|
24911
|
+
if (typeof child === "string" && (key === "key" || LITERAL_SECRET_KEY.test(key))) {
|
|
24912
|
+
throw new KxmHubConfigError(literalSecretMessage(childPath));
|
|
24913
|
+
}
|
|
24914
|
+
if (child && typeof child === "object") rejectLiteralHubSecrets(child, childPath);
|
|
24915
|
+
}
|
|
24916
|
+
}
|
|
24917
|
+
function parseKeyRef(raw, path) {
|
|
24918
|
+
if (raw === void 0) return void 0;
|
|
24919
|
+
if (typeof raw === "string") throw new KxmHubConfigError(literalSecretMessage(path));
|
|
24920
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
24921
|
+
throw new KxmHubConfigError(`${path} must be a key reference with op and/or env, never a token`);
|
|
24922
|
+
}
|
|
24923
|
+
const row = raw;
|
|
24924
|
+
for (const key of Object.keys(row)) {
|
|
24925
|
+
if (key !== "op" && key !== "env") {
|
|
24926
|
+
throw new KxmHubConfigError(literalSecretMessage(`${path}.${key}`));
|
|
24927
|
+
}
|
|
24928
|
+
}
|
|
24929
|
+
const ref = {};
|
|
24930
|
+
if (row.op !== void 0) {
|
|
24931
|
+
if (typeof row.op !== "string" || !isHubOpReference(row.op)) {
|
|
24932
|
+
throw new KxmHubConfigError(`${path}.op must be an op://vault/item/field reference, not a token`);
|
|
24933
|
+
}
|
|
24934
|
+
ref.op = row.op;
|
|
24935
|
+
}
|
|
24936
|
+
if (row.env !== void 0) {
|
|
24937
|
+
if (typeof row.env !== "string" || !isHubKeyEnvName(row.env)) {
|
|
24938
|
+
throw new KxmHubConfigError(`${path}.env must be an environment variable name, not a token`);
|
|
24939
|
+
}
|
|
24940
|
+
ref.env = row.env;
|
|
24941
|
+
}
|
|
24942
|
+
if (!ref.op && !ref.env) throw new KxmHubConfigError(`${path} needs key.op, key.env, or both`);
|
|
24943
|
+
return ref;
|
|
24944
|
+
}
|
|
24945
|
+
function parseEndpoint(raw, path) {
|
|
24946
|
+
if (raw === void 0) return void 0;
|
|
24947
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
24948
|
+
throw new KxmHubConfigError(`${path} must be an object with url, project, and key`);
|
|
24949
|
+
}
|
|
24950
|
+
const row = raw;
|
|
24951
|
+
const endpoint = {};
|
|
24952
|
+
if (row.url !== void 0) {
|
|
24953
|
+
if (typeof row.url !== "string" || !isHubUrl(row.url)) {
|
|
24954
|
+
throw new KxmHubConfigError(`${path}.url must be an http or https URL without credentials, query, or fragment`);
|
|
24955
|
+
}
|
|
24956
|
+
endpoint.url = row.url.replace(/\/$/, "");
|
|
24957
|
+
}
|
|
24958
|
+
if (row.project !== void 0) {
|
|
24959
|
+
if (typeof row.project !== "string" || !isHubProjectId(row.project)) {
|
|
24960
|
+
throw new KxmHubConfigError(`${path}.project must be a single-line project id, not a token`);
|
|
24961
|
+
}
|
|
24962
|
+
endpoint.project = row.project.trim();
|
|
24963
|
+
}
|
|
24964
|
+
const key = parseKeyRef(row.key, `${path}.key`);
|
|
24965
|
+
if (key) endpoint.key = key;
|
|
24966
|
+
for (const name of Object.keys(row)) {
|
|
24967
|
+
if (name !== "url" && name !== "project" && name !== "key") {
|
|
24968
|
+
if (typeof row[name] === "string") throw new KxmHubConfigError(literalSecretMessage(`${path}.${name}`));
|
|
24969
|
+
throw new KxmHubConfigError(`${path}.${name} is not a hub endpoint field`);
|
|
24970
|
+
}
|
|
24971
|
+
}
|
|
24972
|
+
return endpoint;
|
|
24973
|
+
}
|
|
24974
|
+
function isHubUrl(raw) {
|
|
24975
|
+
try {
|
|
24976
|
+
const parsed = new URL(raw);
|
|
24977
|
+
return (parsed.protocol === "http:" || parsed.protocol === "https:") && parsed.username === "" && parsed.password === "" && parsed.search === "" && parsed.hash === "" && !raw.includes("?") && !raw.includes("#");
|
|
24978
|
+
} catch {
|
|
24979
|
+
return false;
|
|
24980
|
+
}
|
|
24981
|
+
}
|
|
24982
|
+
function isHubProjectId(raw) {
|
|
24983
|
+
const value = raw.trim();
|
|
24984
|
+
return value.length > 0 && value.length <= 200 && !/[\s\r\n]/.test(value);
|
|
24985
|
+
}
|
|
24986
|
+
function parseProjectMap(raw) {
|
|
24987
|
+
if (raw === void 0) return void 0;
|
|
24988
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
24989
|
+
throw new KxmHubConfigError("hub.projects must be a map of project id to key reference, never a token");
|
|
24990
|
+
}
|
|
24991
|
+
const projects = {};
|
|
24992
|
+
for (const [project, value] of Object.entries(raw)) {
|
|
24993
|
+
if (!isHubProjectId(project)) {
|
|
24994
|
+
throw new KxmHubConfigError(`hub.projects key ${JSON.stringify(project)} must be a project id, not a token`);
|
|
24995
|
+
}
|
|
24996
|
+
const ref = parseKeyRef(value, `hub.projects.${project}`);
|
|
24997
|
+
if (!ref) throw new KxmHubConfigError(`hub.projects.${project} needs an op:// reference or an environment variable name`);
|
|
24998
|
+
projects[project.trim()] = ref;
|
|
24999
|
+
}
|
|
25000
|
+
return projects;
|
|
25001
|
+
}
|
|
25002
|
+
function normalizeHubConfig(raw) {
|
|
25003
|
+
const autoStart = raw?.autoStart;
|
|
25004
|
+
const hub = {
|
|
25005
|
+
autoStart: autoStart === "off" || autoStart === "background" ? autoStart : DEFAULT_KXM_CONFIG.hub.autoStart
|
|
25006
|
+
};
|
|
25007
|
+
if (raw === void 0) return hub;
|
|
25008
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
25009
|
+
throw new KxmHubConfigError("hub must be an object");
|
|
25010
|
+
}
|
|
25011
|
+
rejectLiteralHubSecrets(raw, "hub");
|
|
25012
|
+
const row = raw;
|
|
25013
|
+
if (row.mode !== void 0) {
|
|
25014
|
+
if (row.mode !== "local" && row.mode !== "cloud") {
|
|
25015
|
+
throw new KxmHubConfigError("hub.mode must be local or cloud");
|
|
25016
|
+
}
|
|
25017
|
+
hub.mode = row.mode;
|
|
25018
|
+
}
|
|
25019
|
+
const local = parseEndpoint(row.local, "hub.local");
|
|
25020
|
+
const cloud = parseEndpoint(row.cloud, "hub.cloud");
|
|
25021
|
+
const projects = parseProjectMap(row.projects);
|
|
25022
|
+
if (local) hub.local = local;
|
|
25023
|
+
if (cloud) hub.cloud = cloud;
|
|
25024
|
+
if (projects && Object.keys(projects).length > 0) hub.projects = projects;
|
|
25025
|
+
return hub;
|
|
25026
|
+
}
|
|
25027
|
+
function findConfigRoot(start) {
|
|
25028
|
+
let dir = resolve7(start);
|
|
25029
|
+
for (; ; ) {
|
|
25030
|
+
if (existsSync10(join11(dir, ".kxm", "project.yaml")) || existsSync10(join11(dir, ".kxm", "config.yaml"))) return dir;
|
|
25031
|
+
const parent = dirname6(dir);
|
|
25032
|
+
if (parent === dir) return resolve7(start);
|
|
25033
|
+
dir = parent;
|
|
25034
|
+
}
|
|
25035
|
+
}
|
|
25036
|
+
function userConfigDirForEnv(env) {
|
|
25037
|
+
const explicit = env.KXM_USER_CONFIG_DIR?.trim();
|
|
25038
|
+
if (explicit) return explicit;
|
|
25039
|
+
if (env === process.env) return void 0;
|
|
25040
|
+
return join11(tmpdir(), "kxm-no-user-config");
|
|
25041
|
+
}
|
|
25042
|
+
function loadHubSettings(start, env = process.env) {
|
|
25043
|
+
const userConfigDir = userConfigDirForEnv(env);
|
|
25044
|
+
return loadKxmConfig(findConfigRoot(start), userConfigDir === void 0 ? {} : { userConfigDir }).hub;
|
|
25045
|
+
}
|
|
25046
|
+
function recordOf(raw) {
|
|
25047
|
+
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
25048
|
+
}
|
|
25049
|
+
function finiteNumber(value) {
|
|
25050
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
25051
|
+
}
|
|
25052
|
+
function normalizeImprovementConfig(raw) {
|
|
25053
|
+
const value = recordOf(raw);
|
|
25054
|
+
const threshold = recordOf(value.autoThreshold);
|
|
25055
|
+
const policy = value.promotionPolicy;
|
|
25056
|
+
const halfLife = finiteNumber(value.telemetryHalfLifeDays);
|
|
25057
|
+
const minRuns = finiteNumber(threshold.minRuns);
|
|
25058
|
+
const minPassRate = finiteNumber(threshold.minPassRate);
|
|
25059
|
+
const minCostSavings = finiteNumber(threshold.minCostSavings);
|
|
25060
|
+
return {
|
|
25061
|
+
promotionPolicy: IMPROVEMENT_PROMOTION_POLICIES.includes(policy) ? policy : "manual_pr",
|
|
25062
|
+
telemetryHalfLifeDays: halfLife !== void 0 && halfLife > 0 && halfLife <= 3650 ? halfLife : 14,
|
|
25063
|
+
autoThreshold: {
|
|
25064
|
+
minRuns: minRuns !== void 0 && Number.isInteger(minRuns) && minRuns >= 1 && minRuns <= 1e6 ? minRuns : 10,
|
|
25065
|
+
minPassRate: minPassRate !== void 0 && minPassRate >= 0 && minPassRate <= 1 ? minPassRate : 0.95,
|
|
25066
|
+
minCostSavings: minCostSavings !== void 0 && minCostSavings >= 0 ? minCostSavings : 0.5
|
|
25067
|
+
}
|
|
25068
|
+
};
|
|
25069
|
+
}
|
|
25070
|
+
function loadKxmConfig(repoRoot = process.cwd(), options = {}) {
|
|
25071
|
+
const userDir = userConfigDirectory(options.userConfigDir);
|
|
25072
|
+
const userConfigFile = join11(userDir, "config.yaml");
|
|
25073
|
+
const repoDir = repoConfigDirectory(repoRoot);
|
|
25074
|
+
const repoConfigFile = join11(repoDir, "config.yaml");
|
|
25075
|
+
let userRaw = {};
|
|
25076
|
+
let userLoadedPath;
|
|
25077
|
+
if (existsSync10(userConfigFile)) {
|
|
25078
|
+
try {
|
|
25079
|
+
const text = readFileSync8(userConfigFile, "utf8");
|
|
25080
|
+
userRaw = (0, import_yaml5.parse)(text) ?? {};
|
|
25081
|
+
userLoadedPath = userConfigFile;
|
|
25082
|
+
} catch (error) {
|
|
25083
|
+
throw new Error(`invalid user config YAML at ${userConfigFile}`, { cause: error });
|
|
25084
|
+
}
|
|
25085
|
+
}
|
|
25086
|
+
let repoRaw = {};
|
|
25087
|
+
let repoLoadedPath;
|
|
25088
|
+
if (existsSync10(repoConfigFile)) {
|
|
25089
|
+
try {
|
|
25090
|
+
const text = readFileSync8(repoConfigFile, "utf8");
|
|
25091
|
+
repoRaw = (0, import_yaml5.parse)(text) ?? {};
|
|
25092
|
+
repoLoadedPath = repoConfigFile;
|
|
25093
|
+
} catch (error) {
|
|
25094
|
+
throw new Error(`invalid project config YAML at ${repoConfigFile}`, { cause: error });
|
|
25095
|
+
}
|
|
25096
|
+
}
|
|
25097
|
+
const baseCopy = JSON.parse(JSON.stringify(DEFAULT_KXM_CONFIG));
|
|
25098
|
+
const mergedUser = deepMerge(baseCopy, userRaw);
|
|
25099
|
+
const mergedAll = deepMerge(mergedUser, repoRaw);
|
|
25100
|
+
return {
|
|
25101
|
+
schema: KXM_CONFIG_SCHEMA,
|
|
25102
|
+
user: mergedAll.user ?? {},
|
|
25103
|
+
defaults: mergedAll.defaults ?? {},
|
|
25104
|
+
dash: mergedAll.dash ?? {},
|
|
25105
|
+
sync: mergedAll.sync ?? {},
|
|
25106
|
+
hub: normalizeHubConfig(mergedAll.hub),
|
|
25107
|
+
improvement: normalizeImprovementConfig(mergedAll.improvement),
|
|
25108
|
+
routing: mergedAll.routing ?? DEFAULT_KXM_CONFIG.routing,
|
|
25109
|
+
telemetry: mergedAll.telemetry ?? DEFAULT_KXM_CONFIG.telemetry,
|
|
25110
|
+
loadedFrom: {
|
|
25111
|
+
userConfigPath: userLoadedPath,
|
|
25112
|
+
repoConfigPath: repoLoadedPath
|
|
25113
|
+
}
|
|
25114
|
+
};
|
|
25115
|
+
}
|
|
24810
25116
|
|
|
24811
25117
|
// plugins/kxm/src/routes.ts
|
|
24812
25118
|
var RETIRED_POLICY = ".kxm/producers.yaml";
|
|
24813
25119
|
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [] });
|
|
24814
25120
|
function loadRoutePolicy(root) {
|
|
24815
|
-
if (
|
|
24816
|
-
const path =
|
|
24817
|
-
if (!
|
|
24818
|
-
const value = (0, import_yaml7.parse)(
|
|
25121
|
+
if (existsSync11(join12(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
|
|
25122
|
+
const path = join12(root, ".kxm", "routes.yaml");
|
|
25123
|
+
if (!existsSync11(path)) return empty();
|
|
25124
|
+
const value = (0, import_yaml7.parse)(readFileSync9(path, "utf8"));
|
|
24819
25125
|
if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
|
|
24820
25126
|
return { schema: "kxm.routes.v2", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), admitted: value.admitted.filter((x) => typeof x === "string"), disabled: Array.isArray(value.disabled) ? value.disabled.filter((x) => typeof x === "string") : [] };
|
|
24821
25127
|
}
|
|
24822
25128
|
function listRoleBindings(root) {
|
|
24823
|
-
const dir =
|
|
25129
|
+
const dir = join12(root, ".kxm", "roles");
|
|
24824
25130
|
const result = {};
|
|
24825
|
-
if (!
|
|
25131
|
+
if (!existsSync11(dir)) return result;
|
|
24826
25132
|
for (const file of readdirSync6(dir).filter((name) => name.endsWith(".yaml"))) {
|
|
24827
25133
|
const role = file.slice(0, -5);
|
|
24828
|
-
const value = (0, import_yaml7.parse)(
|
|
25134
|
+
const value = (0, import_yaml7.parse)(readFileSync9(join12(dir, file), "utf8"));
|
|
24829
25135
|
result[role] = (value.roster ?? []).map((entry) => entry.route).filter((route) => typeof route === "string");
|
|
24830
25136
|
}
|
|
24831
25137
|
return result;
|
|
@@ -24833,8 +25139,8 @@ function listRoleBindings(root) {
|
|
|
24833
25139
|
|
|
24834
25140
|
// plugins/kxm/src/route-fallback.ts
|
|
24835
25141
|
var import_yaml8 = __toESM(require_dist(), 1);
|
|
24836
|
-
import { existsSync as
|
|
24837
|
-
import { join as
|
|
25142
|
+
import { existsSync as existsSync12, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "node:fs";
|
|
25143
|
+
import { join as join13 } from "node:path";
|
|
24838
25144
|
|
|
24839
25145
|
// plugins/kxm/src/route-switch.ts
|
|
24840
25146
|
var WALKABLE_CLASSES = ["rate_limit", "transport", "provider_unavailable", "context_overflow"];
|
|
@@ -25034,9 +25340,9 @@ ${lines.join("\n")}`;
|
|
|
25034
25340
|
${block}`;
|
|
25035
25341
|
}
|
|
25036
25342
|
function readYaml(file) {
|
|
25037
|
-
if (!
|
|
25343
|
+
if (!existsSync12(file)) return void 0;
|
|
25038
25344
|
try {
|
|
25039
|
-
const parsed = (0, import_yaml8.parse)(
|
|
25345
|
+
const parsed = (0, import_yaml8.parse)(readFileSync10(file, "utf8"));
|
|
25040
25346
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
25041
25347
|
return parsed;
|
|
25042
25348
|
} catch {
|
|
@@ -25048,7 +25354,7 @@ function stringList(value) {
|
|
|
25048
25354
|
}
|
|
25049
25355
|
function readSelectors(projectRoot, value) {
|
|
25050
25356
|
if (!Array.isArray(value)) return [];
|
|
25051
|
-
const modelsDir =
|
|
25357
|
+
const modelsDir = join13(projectRoot, ".kxm", "models");
|
|
25052
25358
|
const selectors = [];
|
|
25053
25359
|
for (const item of value) {
|
|
25054
25360
|
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
@@ -25067,9 +25373,9 @@ function readSelectors(projectRoot, value) {
|
|
|
25067
25373
|
return selectors;
|
|
25068
25374
|
}
|
|
25069
25375
|
function loadChainModel(projectRoot, routeId2, writerIds) {
|
|
25070
|
-
const modelsDir =
|
|
25376
|
+
const modelsDir = join13(projectRoot, ".kxm", "models");
|
|
25071
25377
|
const fileId = findYamlBasename(modelsDir, routeId2, "route") ?? routeId2;
|
|
25072
|
-
const doc = readYaml(
|
|
25378
|
+
const doc = readYaml(join13(modelsDir, `${fileId}.yaml`));
|
|
25073
25379
|
if (!doc || doc.schema !== "kxm.model.v2") return void 0;
|
|
25074
25380
|
const harness = typeof doc.harness === "string" ? doc.harness : "";
|
|
25075
25381
|
const model = typeof doc.model === "string" ? doc.model : "";
|
|
@@ -25096,7 +25402,7 @@ function loadChainModel(projectRoot, routeId2, writerIds) {
|
|
|
25096
25402
|
};
|
|
25097
25403
|
}
|
|
25098
25404
|
function canonicalRoster(projectRoot, entries) {
|
|
25099
|
-
const modelsDir =
|
|
25405
|
+
const modelsDir = join13(projectRoot, ".kxm", "models");
|
|
25100
25406
|
return entries.map((entry) => {
|
|
25101
25407
|
const route = findYamlBasename(modelsDir, entry.route, "route") ?? entry.route;
|
|
25102
25408
|
return entry.effort ? { route, effort: entry.effort } : { route };
|
|
@@ -25115,10 +25421,10 @@ function rosterEntries(doc) {
|
|
|
25115
25421
|
return entries;
|
|
25116
25422
|
}
|
|
25117
25423
|
function loadModelsFor(projectRoot, roster, writerIds) {
|
|
25118
|
-
const modelsDir =
|
|
25424
|
+
const modelsDir = join13(projectRoot, ".kxm", "models");
|
|
25119
25425
|
const wanted = /* @__PURE__ */ new Set();
|
|
25120
25426
|
for (const entry of roster) wanted.add(entry.route);
|
|
25121
|
-
if (
|
|
25427
|
+
if (existsSync12(modelsDir)) {
|
|
25122
25428
|
for (const name of readdirSync7(modelsDir)) {
|
|
25123
25429
|
if (!name.endsWith(".yaml") || name === "inventory.yaml") continue;
|
|
25124
25430
|
wanted.add(name.slice(0, -5));
|
|
@@ -25135,12 +25441,12 @@ function loadModelsFor(projectRoot, roster, writerIds) {
|
|
|
25135
25441
|
return models;
|
|
25136
25442
|
}
|
|
25137
25443
|
function criticVendors(projectRoot, writerIds) {
|
|
25138
|
-
const dir =
|
|
25139
|
-
if (!
|
|
25444
|
+
const dir = join13(projectRoot, ".kxm", "roles");
|
|
25445
|
+
if (!existsSync12(dir)) return [];
|
|
25140
25446
|
const vendors = [];
|
|
25141
25447
|
for (const name of readdirSync7(dir)) {
|
|
25142
25448
|
if (!name.endsWith(".yaml")) continue;
|
|
25143
|
-
const doc = readYaml(
|
|
25449
|
+
const doc = readYaml(join13(dir, name));
|
|
25144
25450
|
const purpose = doc?.purpose;
|
|
25145
25451
|
if (purpose !== "reviewer-arch" && purpose !== "reviewer-cli") continue;
|
|
25146
25452
|
const first = rosterEntries(doc)[0];
|
|
@@ -25151,12 +25457,12 @@ function criticVendors(projectRoot, writerIds) {
|
|
|
25151
25457
|
return vendors;
|
|
25152
25458
|
}
|
|
25153
25459
|
function loadAgentFallback(projectRoot, agentId, options) {
|
|
25154
|
-
const agentsDir =
|
|
25460
|
+
const agentsDir = join13(projectRoot, ".kxm", "agents");
|
|
25155
25461
|
const agentFile = findYamlBasename(agentsDir, agentId, "agent") ?? agentId;
|
|
25156
|
-
const agent = readYaml(
|
|
25462
|
+
const agent = readYaml(join13(agentsDir, `${agentFile}.yaml`));
|
|
25157
25463
|
const roleId = typeof agent?.role === "string" ? agent.role : "";
|
|
25158
25464
|
if (!roleId) return void 0;
|
|
25159
|
-
const role = readYaml(
|
|
25465
|
+
const role = readYaml(join13(projectRoot, ".kxm", "roles", `${roleId}.yaml`));
|
|
25160
25466
|
if (!role) return void 0;
|
|
25161
25467
|
const policyRecord = role.policy && typeof role.policy === "object" ? role.policy.fallback : void 0;
|
|
25162
25468
|
const policy = parseFallbackPolicy(policyRecord);
|
|
@@ -25167,7 +25473,7 @@ function loadAgentFallback(projectRoot, agentId, options) {
|
|
|
25167
25473
|
let cursor = typeof role.extends === "string" ? role.extends : "";
|
|
25168
25474
|
while (cursor && !seenRoles.has(cursor)) {
|
|
25169
25475
|
seenRoles.add(cursor);
|
|
25170
|
-
const parent = readYaml(
|
|
25476
|
+
const parent = readYaml(join13(projectRoot, ".kxm", "roles", `${cursor}.yaml`));
|
|
25171
25477
|
extendsRoster = extendsRoster.concat(canonicalRoster(projectRoot, rosterEntries(parent)));
|
|
25172
25478
|
cursor = typeof parent?.extends === "string" ? parent.extends : "";
|
|
25173
25479
|
}
|
|
@@ -25515,7 +25821,7 @@ function pruneContextPacket(packet, tokenBudget) {
|
|
|
25515
25821
|
// plugins/kxm/src/dispatch-context.ts
|
|
25516
25822
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
25517
25823
|
import { readdirSync as readdirSync10 } from "node:fs";
|
|
25518
|
-
import { extname as extname3, join as
|
|
25824
|
+
import { extname as extname3, join as join16 } from "node:path";
|
|
25519
25825
|
|
|
25520
25826
|
// plugins/kxm/src/protocol.ts
|
|
25521
25827
|
var DEFAULT_MESSAGE_TTL_MS = 24 * 60 * 6e4;
|
|
@@ -26144,8 +26450,8 @@ function memoryRecordToContextItem(record2, project) {
|
|
|
26144
26450
|
|
|
26145
26451
|
// plugins/kxm/src/memory.ts
|
|
26146
26452
|
var import_yaml9 = __toESM(require_dist(), 1);
|
|
26147
|
-
import { existsSync as
|
|
26148
|
-
import { extname as extname2, join as
|
|
26453
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
|
|
26454
|
+
import { extname as extname2, join as join14, resolve as resolve8 } from "node:path";
|
|
26149
26455
|
var MEMORY_SCHEMA = "kxm.memory.v1";
|
|
26150
26456
|
var VALID_SCOPES = /* @__PURE__ */ new Set(["agent", "project", "run", "operator"]);
|
|
26151
26457
|
var VALID_AUTHORITIES = /* @__PURE__ */ new Set(["instruction", "evidence", "promoted"]);
|
|
@@ -26243,21 +26549,21 @@ function parseMemoryRecord(raw, filename = "memory.md") {
|
|
|
26243
26549
|
};
|
|
26244
26550
|
}
|
|
26245
26551
|
function memoryDirectories(repoRoot) {
|
|
26246
|
-
const root =
|
|
26247
|
-
const memoryDir =
|
|
26248
|
-
const candidatesDir =
|
|
26552
|
+
const root = resolve8(repoRoot);
|
|
26553
|
+
const memoryDir = join14(root, ".kxm", "memory");
|
|
26554
|
+
const candidatesDir = join14(memoryDir, "candidates");
|
|
26249
26555
|
return { memoryDir, candidatesDir };
|
|
26250
26556
|
}
|
|
26251
26557
|
function loadAuthoredMemory(repoRoot) {
|
|
26252
26558
|
const { memoryDir } = memoryDirectories(repoRoot);
|
|
26253
|
-
if (!
|
|
26559
|
+
if (!existsSync13(memoryDir)) return [];
|
|
26254
26560
|
const records = [];
|
|
26255
26561
|
const entries = readdirSync8(memoryDir, { withFileTypes: true });
|
|
26256
26562
|
for (const entry of entries) {
|
|
26257
26563
|
if (entry.isFile() && extname2(entry.name) === ".md") {
|
|
26258
|
-
const fullPath =
|
|
26564
|
+
const fullPath = join14(memoryDir, entry.name);
|
|
26259
26565
|
try {
|
|
26260
|
-
const text =
|
|
26566
|
+
const text = readFileSync11(fullPath, "utf8");
|
|
26261
26567
|
const record2 = parseMemoryRecord(text, entry.name);
|
|
26262
26568
|
if (record2.lifecycle === "active") {
|
|
26263
26569
|
records.push(record2);
|
|
@@ -26273,8 +26579,8 @@ function loadAuthoredMemory(repoRoot) {
|
|
|
26273
26579
|
// plugins/kxm/src/skills.ts
|
|
26274
26580
|
var import_yaml10 = __toESM(require_dist(), 1);
|
|
26275
26581
|
import { createHash as createHash11 } from "node:crypto";
|
|
26276
|
-
import { existsSync as
|
|
26277
|
-
import { dirname as
|
|
26582
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync6, readdirSync as readdirSync9, readFileSync as readFileSync12, renameSync, rmSync, statSync as statSync3, writeFileSync as writeFileSync7 } from "node:fs";
|
|
26583
|
+
import { dirname as dirname8, join as join15 } from "node:path";
|
|
26278
26584
|
var SKILL_CANDIDATE_SCHEMA = "kxm.skill-candidate.v1";
|
|
26279
26585
|
var SKILL_EVALUATION_SCHEMA = "kxm.skill-evaluation.v1";
|
|
26280
26586
|
var SKILL_DECISION_SCHEMA = "kxm.skill-decision.v1";
|
|
@@ -26376,24 +26682,24 @@ var SkillLifecycle = class {
|
|
|
26376
26682
|
this.planned.push({ action: "write", target: file });
|
|
26377
26683
|
return;
|
|
26378
26684
|
}
|
|
26379
|
-
|
|
26380
|
-
|
|
26685
|
+
mkdirSync6(dirname8(file), { recursive: true });
|
|
26686
|
+
writeFileSync7(file, content);
|
|
26381
26687
|
}
|
|
26382
26688
|
dir(state) {
|
|
26383
|
-
return
|
|
26689
|
+
return join15(this.root, state === "candidate" ? "candidates" : `${state}s`.replace("rejecteds", "rejected").replace("promoteds", "promoted"));
|
|
26384
26690
|
}
|
|
26385
26691
|
historyFile(id) {
|
|
26386
|
-
return
|
|
26692
|
+
return join15(this.root, "history", `${id}.jsonl`);
|
|
26387
26693
|
}
|
|
26388
26694
|
paths(state, id) {
|
|
26389
|
-
const dir =
|
|
26390
|
-
return { dir, metadata:
|
|
26695
|
+
const dir = join15(this.dir(state), id);
|
|
26696
|
+
return { dir, metadata: join15(dir, "metadata.json"), skill: join15(dir, "SKILL.md") };
|
|
26391
26697
|
}
|
|
26392
26698
|
appendHistory(id, record2) {
|
|
26393
26699
|
const line = `${JSON.stringify(record2)}
|
|
26394
26700
|
`;
|
|
26395
|
-
if (
|
|
26396
|
-
const existing =
|
|
26701
|
+
if (existsSync14(this.historyFile(id))) {
|
|
26702
|
+
const existing = readFileSync12(this.historyFile(id), "utf8");
|
|
26397
26703
|
const lines = existing.split("\n").filter((entry) => entry.trim());
|
|
26398
26704
|
this.write(this.historyFile(id), [...lines.slice(-499), line.trim()].join("\n") + "\n");
|
|
26399
26705
|
} else {
|
|
@@ -26402,28 +26708,28 @@ var SkillLifecycle = class {
|
|
|
26402
26708
|
}
|
|
26403
26709
|
history(id) {
|
|
26404
26710
|
const file = this.historyFile(id);
|
|
26405
|
-
if (!
|
|
26406
|
-
return
|
|
26711
|
+
if (!existsSync14(file)) return [];
|
|
26712
|
+
return readFileSync12(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
|
|
26407
26713
|
}
|
|
26408
26714
|
readMetadata(state, id) {
|
|
26409
26715
|
const { metadata } = this.paths(state, id);
|
|
26410
|
-
if (!
|
|
26716
|
+
if (!existsSync14(metadata)) {
|
|
26411
26717
|
throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${state}`);
|
|
26412
26718
|
}
|
|
26413
|
-
return JSON.parse(
|
|
26719
|
+
return JSON.parse(readFileSync12(metadata, "utf8"));
|
|
26414
26720
|
}
|
|
26415
26721
|
move(from, to, id) {
|
|
26416
|
-
const fromDir =
|
|
26417
|
-
const toDir =
|
|
26418
|
-
if (!
|
|
26722
|
+
const fromDir = join15(this.dir(from), id);
|
|
26723
|
+
const toDir = join15(this.dir(to), id);
|
|
26724
|
+
if (!existsSync14(fromDir)) {
|
|
26419
26725
|
throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${from}`);
|
|
26420
26726
|
}
|
|
26421
26727
|
if (this.dryRun) {
|
|
26422
26728
|
this.planned.push({ action: "move", target: `${fromDir} -> ${toDir}` });
|
|
26423
26729
|
return;
|
|
26424
26730
|
}
|
|
26425
|
-
|
|
26426
|
-
if (
|
|
26731
|
+
mkdirSync6(this.dir(to), { recursive: true });
|
|
26732
|
+
if (existsSync14(toDir)) rmSync(toDir, { recursive: true, force: true });
|
|
26427
26733
|
renameSync(fromDir, toDir);
|
|
26428
26734
|
}
|
|
26429
26735
|
/** Submit a new skill candidate. Content is redacted of secret material at
|
|
@@ -26466,7 +26772,7 @@ var SkillLifecycle = class {
|
|
|
26466
26772
|
const contentSha256 = skillContentSha256(content);
|
|
26467
26773
|
const id = skillIdFor(name, contentSha256);
|
|
26468
26774
|
const { metadata, skill } = this.paths("candidate", id);
|
|
26469
|
-
if (
|
|
26775
|
+
if (existsSync14(metadata)) {
|
|
26470
26776
|
throw new SkillLifecycleError(
|
|
26471
26777
|
"skill_candidate_exists",
|
|
26472
26778
|
`identical candidate ${id} already exists; changed behavior requires changed content`
|
|
@@ -26575,11 +26881,11 @@ var SkillLifecycle = class {
|
|
|
26575
26881
|
};
|
|
26576
26882
|
const candidatePaths = this.paths("candidate", candidateId);
|
|
26577
26883
|
const promotedPaths = this.paths("promoted", candidateId);
|
|
26578
|
-
const skillContent =
|
|
26579
|
-
const metadataContent =
|
|
26884
|
+
const skillContent = readFileSync12(candidatePaths.skill, "utf8");
|
|
26885
|
+
const metadataContent = readFileSync12(candidatePaths.metadata, "utf8");
|
|
26580
26886
|
this.write(promotedPaths.skill, skillContent);
|
|
26581
26887
|
this.write(promotedPaths.metadata, metadataContent);
|
|
26582
|
-
const patchPath =
|
|
26888
|
+
const patchPath = join15(this.root, "patches", `${candidateId}.patch`);
|
|
26583
26889
|
const relSkillPath = `.kxm/skills/promoted/${candidateId}/SKILL.md`;
|
|
26584
26890
|
const relMetaPath = `.kxm/skills/promoted/${candidateId}/metadata.json`;
|
|
26585
26891
|
const patch = `${createUnifiedPatch(relSkillPath, skillContent)}${createUnifiedPatch(relMetaPath, metadataContent)}`;
|
|
@@ -26607,7 +26913,7 @@ var SkillLifecycle = class {
|
|
|
26607
26913
|
verify(state, id) {
|
|
26608
26914
|
const metadata = this.readMetadata(state, id);
|
|
26609
26915
|
const { skill } = this.paths(state, id);
|
|
26610
|
-
const content =
|
|
26916
|
+
const content = readFileSync12(skill, "utf8");
|
|
26611
26917
|
if (skillContentSha256(content) !== metadata.contentSha256) {
|
|
26612
26918
|
throw new SkillLifecycleError(
|
|
26613
26919
|
"skill_integrity_violation",
|
|
@@ -26625,7 +26931,7 @@ var SkillLifecycle = class {
|
|
|
26625
26931
|
}
|
|
26626
26932
|
list(state) {
|
|
26627
26933
|
const dir = this.dir(state);
|
|
26628
|
-
if (!
|
|
26934
|
+
if (!existsSync14(dir)) return [];
|
|
26629
26935
|
const ids = readdirSorted(dir);
|
|
26630
26936
|
return ids.map((id) => {
|
|
26631
26937
|
try {
|
|
@@ -26638,7 +26944,7 @@ var SkillLifecycle = class {
|
|
|
26638
26944
|
read(state, id) {
|
|
26639
26945
|
const metadata = this.readMetadata(state, id);
|
|
26640
26946
|
const { skill } = this.paths(state, id);
|
|
26641
|
-
return { metadata, content:
|
|
26947
|
+
return { metadata, content: readFileSync12(skill, "utf8") };
|
|
26642
26948
|
}
|
|
26643
26949
|
};
|
|
26644
26950
|
function boundedList(value, field) {
|
|
@@ -26653,7 +26959,7 @@ function boundedList(value, field) {
|
|
|
26653
26959
|
return [...new Set(refs)];
|
|
26654
26960
|
}
|
|
26655
26961
|
function readdirSorted(dir) {
|
|
26656
|
-
return readdirSync9(dir).filter((entry) => statSync3(
|
|
26962
|
+
return readdirSync9(dir).filter((entry) => statSync3(join15(dir, entry)).isDirectory()).sort();
|
|
26657
26963
|
}
|
|
26658
26964
|
|
|
26659
26965
|
// plugins/kxm/src/dispatch-context.ts
|
|
@@ -26694,7 +27000,7 @@ function contextRoleForAgent(agentId) {
|
|
|
26694
27000
|
return agentId;
|
|
26695
27001
|
}
|
|
26696
27002
|
function dispatchContextPresent(projectRoot) {
|
|
26697
|
-
return hasTopLevelMarkdown(
|
|
27003
|
+
return hasTopLevelMarkdown(join16(projectRoot, ".kxm", "memory")) || hasAnyEntry(join16(projectRoot, ".kxm", "skills", "promoted"));
|
|
26698
27004
|
}
|
|
26699
27005
|
function hasTopLevelMarkdown(dir) {
|
|
26700
27006
|
try {
|
|
@@ -26770,7 +27076,7 @@ function loadDispatchContextSources(input) {
|
|
|
26770
27076
|
}
|
|
26771
27077
|
const promoted = [];
|
|
26772
27078
|
try {
|
|
26773
|
-
const lifecycle = new SkillLifecycle(
|
|
27079
|
+
const lifecycle = new SkillLifecycle(join16(projectRoot, ".kxm", "skills"));
|
|
26774
27080
|
for (const metadata of lifecycle.list("promoted")) {
|
|
26775
27081
|
try {
|
|
26776
27082
|
promoted.push(lifecycle.verify("promoted", metadata.id));
|
|
@@ -26853,18 +27159,18 @@ function assembleDispatchContext(sources, input) {
|
|
|
26853
27159
|
}
|
|
26854
27160
|
|
|
26855
27161
|
// plugins/kxm/src/engine-artifacts.ts
|
|
26856
|
-
import { join as
|
|
27162
|
+
import { join as join17 } from "node:path";
|
|
26857
27163
|
|
|
26858
27164
|
// plugins/kxm/src/artifacts-exist.ts
|
|
26859
27165
|
import { lstatSync as lstatSync5, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
|
|
26860
|
-
import { isAbsolute as isAbsolute5, relative as relative4, resolve as
|
|
27166
|
+
import { isAbsolute as isAbsolute5, relative as relative4, resolve as resolve9 } from "node:path";
|
|
26861
27167
|
function staysUnder(root, candidate) {
|
|
26862
27168
|
const child = relative4(root, candidate);
|
|
26863
27169
|
return child === "" || !isAbsolute5(child) && child !== ".." && !child.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`);
|
|
26864
27170
|
}
|
|
26865
27171
|
function verifyArtifactExists(rootInput, pathInput) {
|
|
26866
|
-
const lexicalRoot =
|
|
26867
|
-
const lexicalPath =
|
|
27172
|
+
const lexicalRoot = resolve9(rootInput);
|
|
27173
|
+
const lexicalPath = resolve9(pathInput);
|
|
26868
27174
|
if (!staysUnder(lexicalRoot, lexicalPath)) {
|
|
26869
27175
|
return { ok: false, error: "artifact_outside_workspace_assets", path: lexicalPath };
|
|
26870
27176
|
}
|
|
@@ -26900,14 +27206,14 @@ function verifyArtifactExists(rootInput, pathInput) {
|
|
|
26900
27206
|
// plugins/kxm/src/engine-artifacts.ts
|
|
26901
27207
|
var kxmArtifactsGateSeams = {};
|
|
26902
27208
|
function evaluateArtifactsGate(context, definition) {
|
|
26903
|
-
const root =
|
|
27209
|
+
const root = join17(context.projectRoot, ".kxm", "assets");
|
|
26904
27210
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
26905
27211
|
const startTime = process.hrtime.bigint();
|
|
26906
27212
|
let checkedCount = 0;
|
|
26907
27213
|
let failedCount = 0;
|
|
26908
27214
|
for (const [index, path] of definition.paths.entries()) {
|
|
26909
27215
|
checkedCount += 1;
|
|
26910
|
-
const result = verifyArtifactExists(root,
|
|
27216
|
+
const result = verifyArtifactExists(root, join17(root, path));
|
|
26911
27217
|
if (!result.ok) failedCount += 1;
|
|
26912
27218
|
kxmArtifactsGateSeams.afterPathChecked?.({ path, index, checkedCount, failedCount });
|
|
26913
27219
|
}
|
|
@@ -27052,8 +27358,8 @@ var CommandObserver = class {
|
|
|
27052
27358
|
this.requestStop("error", "lost-close");
|
|
27053
27359
|
}
|
|
27054
27360
|
run() {
|
|
27055
|
-
return new Promise((
|
|
27056
|
-
this.resolveOutcome =
|
|
27361
|
+
return new Promise((resolve13) => {
|
|
27362
|
+
this.resolveOutcome = resolve13;
|
|
27057
27363
|
try {
|
|
27058
27364
|
this.start();
|
|
27059
27365
|
} catch (error) {
|
|
@@ -28380,8 +28686,8 @@ var KxmRunScheduler = class _KxmRunScheduler {
|
|
|
28380
28686
|
resolve: (_value) => void 0,
|
|
28381
28687
|
reject: (_error) => void 0
|
|
28382
28688
|
};
|
|
28383
|
-
const settled = new Promise((
|
|
28384
|
-
pending.resolve =
|
|
28689
|
+
const settled = new Promise((resolve13, reject) => {
|
|
28690
|
+
pending.resolve = resolve13;
|
|
28385
28691
|
pending.reject = reject;
|
|
28386
28692
|
});
|
|
28387
28693
|
void settled.then(void 0, () => void 0);
|
|
@@ -28920,9 +29226,9 @@ function readYamlFile(file) {
|
|
|
28920
29226
|
return readModelDocument(file);
|
|
28921
29227
|
}
|
|
28922
29228
|
function readModelDocument(file) {
|
|
28923
|
-
if (!
|
|
29229
|
+
if (!existsSync15(file)) return void 0;
|
|
28924
29230
|
try {
|
|
28925
|
-
const parsed = (0, import_yaml11.parse)(
|
|
29231
|
+
const parsed = (0, import_yaml11.parse)(readFileSync13(file, "utf8"));
|
|
28926
29232
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
28927
29233
|
return parsed;
|
|
28928
29234
|
} catch {
|
|
@@ -28953,8 +29259,8 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
28953
29259
|
}
|
|
28954
29260
|
};
|
|
28955
29261
|
}
|
|
28956
|
-
const agentFile = findYamlBasename(
|
|
28957
|
-
const agent = readYamlFile(
|
|
29262
|
+
const agentFile = findYamlBasename(join18(projectRoot, ".kxm", "agents"), agentId, "agent") ?? agentId;
|
|
29263
|
+
const agent = readYamlFile(join18(projectRoot, ".kxm", "agents", `${agentFile}.yaml`));
|
|
28958
29264
|
const role = typeof agent?.role === "string" ? agent.role : "";
|
|
28959
29265
|
if (!role) {
|
|
28960
29266
|
return {
|
|
@@ -28965,7 +29271,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
28965
29271
|
}
|
|
28966
29272
|
};
|
|
28967
29273
|
}
|
|
28968
|
-
const roleDoc = readYamlFile(
|
|
29274
|
+
const roleDoc = readYamlFile(join18(projectRoot, ".kxm", "roles", `${role}.yaml`));
|
|
28969
29275
|
const roster = Array.isArray(roleDoc?.roster) ? roleDoc.roster : void 0;
|
|
28970
29276
|
if (!roster) {
|
|
28971
29277
|
return {
|
|
@@ -28981,8 +29287,8 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
28981
29287
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
28982
29288
|
const record2 = entry;
|
|
28983
29289
|
if (typeof record2.route !== "string" || record2.route.length === 0) continue;
|
|
28984
|
-
const routeFile = findYamlBasename(
|
|
28985
|
-
const modelPath =
|
|
29290
|
+
const routeFile = findYamlBasename(join18(projectRoot, ".kxm", "models"), record2.route, "route") ?? record2.route;
|
|
29291
|
+
const modelPath = join18(projectRoot, ".kxm", "models", `${routeFile}.yaml`);
|
|
28986
29292
|
const doc = readModelDocument(modelPath);
|
|
28987
29293
|
if (!doc) {
|
|
28988
29294
|
return {
|
|
@@ -31322,9 +31628,9 @@ var RuntimeHubClient = class {
|
|
|
31322
31628
|
|
|
31323
31629
|
// plugins/kxm/src/hub-binding.ts
|
|
31324
31630
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
31325
|
-
import { existsSync as
|
|
31326
|
-
import { homedir as
|
|
31327
|
-
import { dirname as
|
|
31631
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync7, readFileSync as readFileSync14, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync8 } from "node:fs";
|
|
31632
|
+
import { homedir as homedir3 } from "node:os";
|
|
31633
|
+
import { dirname as dirname9, isAbsolute as isAbsolute6, join as join19, resolve as resolve10 } from "node:path";
|
|
31328
31634
|
var HUB_BINDING_SCHEMA = "kxm.hub-binding.v1";
|
|
31329
31635
|
var CloudTokenError = class extends Error {
|
|
31330
31636
|
code;
|
|
@@ -31347,20 +31653,20 @@ function resolveUserStateRoot(env) {
|
|
|
31347
31653
|
const explicit = env.KXM_STATE_HOME?.trim();
|
|
31348
31654
|
if (explicit) {
|
|
31349
31655
|
if (!isAbsolute6(explicit)) throw new HubBindingError("local_state_root_not_absolute");
|
|
31350
|
-
return
|
|
31656
|
+
return resolve10(explicit);
|
|
31351
31657
|
}
|
|
31352
31658
|
if (process.platform === "win32") {
|
|
31353
31659
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
31354
|
-
const base2 = localAppData && isAbsolute6(localAppData) ? localAppData :
|
|
31355
|
-
return
|
|
31660
|
+
const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join19(homedir3(), "AppData", "Local");
|
|
31661
|
+
return resolve10(base2, "KXM");
|
|
31356
31662
|
}
|
|
31357
|
-
if (process.platform === "darwin") return
|
|
31663
|
+
if (process.platform === "darwin") return resolve10(homedir3(), "Library", "Application Support", "KXM");
|
|
31358
31664
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
31359
|
-
const base = xdgState && isAbsolute6(xdgState) ? xdgState :
|
|
31360
|
-
return
|
|
31665
|
+
const base = xdgState && isAbsolute6(xdgState) ? xdgState : join19(homedir3(), ".local", "state");
|
|
31666
|
+
return resolve10(base, "kxm");
|
|
31361
31667
|
}
|
|
31362
31668
|
function hubBindingFile(env = process.env) {
|
|
31363
|
-
return
|
|
31669
|
+
return join19(resolveUserStateRoot(env), "hub-binding.json");
|
|
31364
31670
|
}
|
|
31365
31671
|
function validateHubUrl(raw) {
|
|
31366
31672
|
let parsed;
|
|
@@ -31456,16 +31762,27 @@ function runTokenCommand(command, env) {
|
|
|
31456
31762
|
}
|
|
31457
31763
|
return stdout.trim();
|
|
31458
31764
|
}
|
|
31765
|
+
function hubBindingScope(url) {
|
|
31766
|
+
let host;
|
|
31767
|
+
try {
|
|
31768
|
+
host = new URL(url).hostname.toLowerCase();
|
|
31769
|
+
} catch {
|
|
31770
|
+
return "remote";
|
|
31771
|
+
}
|
|
31772
|
+
if (host === "localhost" || host === "::1" || host === "[::1]" || host.endsWith(".localhost")) return "loopback";
|
|
31773
|
+
const v4 = /^127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/.exec(host);
|
|
31774
|
+
return v4 && [v4[1], v4[2], v4[3]].every((part) => Number(part) <= 255) ? "loopback" : "remote";
|
|
31775
|
+
}
|
|
31459
31776
|
function isIsoTimestamp(value) {
|
|
31460
31777
|
if (Number.isNaN(Date.parse(value))) return false;
|
|
31461
31778
|
return value === new Date(value).toISOString();
|
|
31462
31779
|
}
|
|
31463
31780
|
function readHubBinding(env = process.env) {
|
|
31464
31781
|
const file = hubBindingFile(env);
|
|
31465
|
-
if (!
|
|
31782
|
+
if (!existsSync16(file)) return void 0;
|
|
31466
31783
|
let parsed;
|
|
31467
31784
|
try {
|
|
31468
|
-
parsed = JSON.parse(
|
|
31785
|
+
parsed = JSON.parse(readFileSync14(file, "utf8"));
|
|
31469
31786
|
} catch {
|
|
31470
31787
|
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
31471
31788
|
}
|
|
@@ -31516,12 +31833,197 @@ function readHubBinding(env = process.env) {
|
|
|
31516
31833
|
}
|
|
31517
31834
|
|
|
31518
31835
|
// plugins/kxm/src/hub-env.ts
|
|
31519
|
-
import { existsSync as
|
|
31520
|
-
import { homedir as
|
|
31521
|
-
import { dirname as
|
|
31836
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync8, readFileSync as readFileSync16, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync9 } from "node:fs";
|
|
31837
|
+
import { homedir as homedir4 } from "node:os";
|
|
31838
|
+
import { dirname as dirname11, isAbsolute as isAbsolute7, join as join21, resolve as resolve12 } from "node:path";
|
|
31522
31839
|
|
|
31523
|
-
// plugins/kxm/src/
|
|
31840
|
+
// plugins/kxm/src/hub-identity.ts
|
|
31524
31841
|
var import_yaml12 = __toESM(require_dist(), 1);
|
|
31842
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
31843
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15 } from "node:fs";
|
|
31844
|
+
import { basename as basename4, dirname as dirname10, join as join20, resolve as resolve11 } from "node:path";
|
|
31845
|
+
var OP_TIMEOUT_MS = 15e3;
|
|
31846
|
+
var OP_MAX_BUFFER = 4096;
|
|
31847
|
+
function normalizeUrl(raw) {
|
|
31848
|
+
try {
|
|
31849
|
+
return validateHubUrl(raw);
|
|
31850
|
+
} catch {
|
|
31851
|
+
return void 0;
|
|
31852
|
+
}
|
|
31853
|
+
}
|
|
31854
|
+
function projectYamlId(start) {
|
|
31855
|
+
let dir = resolve11(start);
|
|
31856
|
+
for (; ; ) {
|
|
31857
|
+
const file = join20(dir, ".kxm", "project.yaml");
|
|
31858
|
+
if (existsSync17(file)) {
|
|
31859
|
+
try {
|
|
31860
|
+
const doc = (0, import_yaml12.parse)(readFileSync15(file, "utf8"));
|
|
31861
|
+
if (doc && typeof doc === "object" && !Array.isArray(doc) && typeof doc.id === "string" && doc.id.trim()) {
|
|
31862
|
+
return doc.id.trim();
|
|
31863
|
+
}
|
|
31864
|
+
} catch {
|
|
31865
|
+
}
|
|
31866
|
+
return void 0;
|
|
31867
|
+
}
|
|
31868
|
+
const parent = dirname10(dir);
|
|
31869
|
+
if (parent === dir) return void 0;
|
|
31870
|
+
dir = parent;
|
|
31871
|
+
}
|
|
31872
|
+
}
|
|
31873
|
+
function packageName(cwd) {
|
|
31874
|
+
try {
|
|
31875
|
+
const pkg = JSON.parse(readFileSync15(join20(cwd, "package.json"), "utf8"));
|
|
31876
|
+
if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
|
|
31877
|
+
} catch {
|
|
31878
|
+
}
|
|
31879
|
+
return void 0;
|
|
31880
|
+
}
|
|
31881
|
+
function activeBinding(env) {
|
|
31882
|
+
try {
|
|
31883
|
+
return readHubBinding(env);
|
|
31884
|
+
} catch (error) {
|
|
31885
|
+
if (error instanceof HubBindingError) return void 0;
|
|
31886
|
+
throw error;
|
|
31887
|
+
}
|
|
31888
|
+
}
|
|
31889
|
+
function endpointFor(mode, settings) {
|
|
31890
|
+
return mode === "cloud" ? settings.cloud : settings.local;
|
|
31891
|
+
}
|
|
31892
|
+
function resolveProjectIdentity(cwd, env = process.env, explicit) {
|
|
31893
|
+
const fromExplicit = explicit?.trim();
|
|
31894
|
+
if (fromExplicit) return { project: fromExplicit, source: "flag", sourceLabel: "--project" };
|
|
31895
|
+
const fromEnv = env.KXM_PROJECT?.trim();
|
|
31896
|
+
if (fromEnv) return { project: fromEnv, source: "env", sourceLabel: "KXM_PROJECT" };
|
|
31897
|
+
const settings = loadHubSettings(cwd, env);
|
|
31898
|
+
const mode = settings.mode ?? (activeBinding(env)?.cloud ? "cloud" : "local");
|
|
31899
|
+
const fromConfig = endpointFor(mode, settings)?.project?.trim();
|
|
31900
|
+
if (fromConfig) {
|
|
31901
|
+
return { project: fromConfig, source: "config", sourceLabel: `.kxm/config.yaml hub.${mode}.project` };
|
|
31902
|
+
}
|
|
31903
|
+
const fromProject = projectYamlId(cwd);
|
|
31904
|
+
if (fromProject) return { project: fromProject, source: "project.yaml", sourceLabel: ".kxm/project.yaml id" };
|
|
31905
|
+
const fromPackage = packageName(cwd);
|
|
31906
|
+
if (fromPackage) return { project: fromPackage, source: "package.json", sourceLabel: "package.json name" };
|
|
31907
|
+
return { project: basename4(cwd), source: "directory", sourceLabel: "directory name" };
|
|
31908
|
+
}
|
|
31909
|
+
function opReferenceFromTokenCommand(command) {
|
|
31910
|
+
try {
|
|
31911
|
+
const args = splitTokenCommand(command);
|
|
31912
|
+
if (args[0] === "op" && args[1] === "read" && args[2] && isHubOpReference(args[2])) return args[2];
|
|
31913
|
+
} catch {
|
|
31914
|
+
return void 0;
|
|
31915
|
+
}
|
|
31916
|
+
return void 0;
|
|
31917
|
+
}
|
|
31918
|
+
function defaultOpRead(reference, env) {
|
|
31919
|
+
if (!isHubOpReference(reference)) {
|
|
31920
|
+
throw new CloudTokenError("cloud_token_command_invalid", `refusing to resolve ${reference}; an op:// reference is required`);
|
|
31921
|
+
}
|
|
31922
|
+
const result = spawnSync7("op", ["read", reference], {
|
|
31923
|
+
encoding: "utf8",
|
|
31924
|
+
shell: false,
|
|
31925
|
+
timeout: OP_TIMEOUT_MS,
|
|
31926
|
+
maxBuffer: OP_MAX_BUFFER,
|
|
31927
|
+
env,
|
|
31928
|
+
windowsHide: true
|
|
31929
|
+
});
|
|
31930
|
+
if (result.error || result.status !== 0) {
|
|
31931
|
+
throw new CloudTokenError(
|
|
31932
|
+
"cloud_token_command_failed",
|
|
31933
|
+
`op read failed for ${reference}; the token was not saved`
|
|
31934
|
+
);
|
|
31935
|
+
}
|
|
31936
|
+
const line = (result.stdout ?? "").trim();
|
|
31937
|
+
if (!line || line.split(/\r?\n/).length !== 1) {
|
|
31938
|
+
throw new CloudTokenError(
|
|
31939
|
+
"cloud_token_command_failed",
|
|
31940
|
+
`op read did not print a single token for ${reference}; the token was not saved`
|
|
31941
|
+
);
|
|
31942
|
+
}
|
|
31943
|
+
return line;
|
|
31944
|
+
}
|
|
31945
|
+
function resolveKeyReference(ref, env, opRead = defaultOpRead) {
|
|
31946
|
+
if (!ref) return void 0;
|
|
31947
|
+
if (ref.env) {
|
|
31948
|
+
const value = env[ref.env]?.trim();
|
|
31949
|
+
if (value) return { value, source: `env:${ref.env}` };
|
|
31950
|
+
}
|
|
31951
|
+
if (ref.op) {
|
|
31952
|
+
const value = opRead(ref.op, env).trim();
|
|
31953
|
+
if (!value || value.split(/\r?\n/).length !== 1) {
|
|
31954
|
+
throw new CloudTokenError("cloud_token_command_failed", `op read did not print a single token for ${ref.op}`);
|
|
31955
|
+
}
|
|
31956
|
+
return { value, source: `op:${ref.op}` };
|
|
31957
|
+
}
|
|
31958
|
+
return void 0;
|
|
31959
|
+
}
|
|
31960
|
+
function keySourceFor(input) {
|
|
31961
|
+
const ref = input.endpoint?.key;
|
|
31962
|
+
if (input.mode === "local" && input.env.KXM_AUTH_TOKEN?.trim()) return "env:KXM_AUTH_TOKEN";
|
|
31963
|
+
if (ref?.env && input.env[ref.env]?.trim()) return `env:${ref.env}`;
|
|
31964
|
+
if (ref?.op) return `op:${ref.op}`;
|
|
31965
|
+
if (ref?.env) return `env:${ref.env}`;
|
|
31966
|
+
if (input.mode === "cloud") {
|
|
31967
|
+
if (input.binding?.tokenEnv) return `env:${input.binding.tokenEnv}`;
|
|
31968
|
+
if (input.binding?.tokenCommand) {
|
|
31969
|
+
const op = opReferenceFromTokenCommand(input.binding.tokenCommand);
|
|
31970
|
+
return op ? `op:${op}` : "command";
|
|
31971
|
+
}
|
|
31972
|
+
return "missing";
|
|
31973
|
+
}
|
|
31974
|
+
if (input.hasSavedProjectToken?.(input.project)) return "hub-env";
|
|
31975
|
+
return "missing";
|
|
31976
|
+
}
|
|
31977
|
+
function describeHubConnection(cwd, env = process.env, hooks = {}) {
|
|
31978
|
+
const settings = loadHubSettings(cwd, env);
|
|
31979
|
+
const binding = activeBinding(env);
|
|
31980
|
+
const mode = settings.mode ?? (binding?.cloud ? "cloud" : "local");
|
|
31981
|
+
const modeSource = settings.mode ? "config" : binding?.cloud ? "binding" : "default";
|
|
31982
|
+
const endpoint = endpointFor(mode, settings);
|
|
31983
|
+
const fromEnv = env.KXM_SERVER_URL?.trim();
|
|
31984
|
+
const fromConfig = endpoint?.url?.trim();
|
|
31985
|
+
const fromBinding = binding?.url;
|
|
31986
|
+
let url = "http://127.0.0.1:7331";
|
|
31987
|
+
let urlSource = "default";
|
|
31988
|
+
if (fromEnv) {
|
|
31989
|
+
url = fromEnv.replace(/\/$/, "");
|
|
31990
|
+
urlSource = "env";
|
|
31991
|
+
} else if (fromConfig) {
|
|
31992
|
+
url = fromConfig.replace(/\/$/, "");
|
|
31993
|
+
urlSource = "config";
|
|
31994
|
+
} else if (fromBinding) {
|
|
31995
|
+
url = fromBinding;
|
|
31996
|
+
urlSource = "binding";
|
|
31997
|
+
}
|
|
31998
|
+
const identity = resolveProjectIdentity(cwd, env, hooks.explicitProject);
|
|
31999
|
+
const configuredCloudUrl = settings.cloud?.url ?? (binding?.cloud ? binding.url : void 0);
|
|
32000
|
+
let scope;
|
|
32001
|
+
if (mode === "cloud") {
|
|
32002
|
+
const override = fromEnv ? normalizeUrl(fromEnv) : void 0;
|
|
32003
|
+
const named = configuredCloudUrl ? normalizeUrl(configuredCloudUrl) : void 0;
|
|
32004
|
+
scope = override && named && override !== named ? hubBindingScope(url) : "remote";
|
|
32005
|
+
} else {
|
|
32006
|
+
scope = hubBindingScope(url);
|
|
32007
|
+
}
|
|
32008
|
+
return {
|
|
32009
|
+
...identity,
|
|
32010
|
+
mode,
|
|
32011
|
+
modeSource,
|
|
32012
|
+
url,
|
|
32013
|
+
urlSource,
|
|
32014
|
+
scope,
|
|
32015
|
+
...endpoint ? { endpoint } : {},
|
|
32016
|
+
...binding ? { binding } : {},
|
|
32017
|
+
keySource: keySourceFor({
|
|
32018
|
+
mode,
|
|
32019
|
+
env,
|
|
32020
|
+
...endpoint ? { endpoint } : {},
|
|
32021
|
+
...binding ? { binding } : {},
|
|
32022
|
+
project: identity.project,
|
|
32023
|
+
...hooks.hasSavedProjectToken ? { hasSavedProjectToken: hooks.hasSavedProjectToken } : {}
|
|
32024
|
+
})
|
|
32025
|
+
};
|
|
32026
|
+
}
|
|
31525
32027
|
|
|
31526
32028
|
// plugins/kxm/src/hub-env.ts
|
|
31527
32029
|
var HUB_ENV_SCHEMA = "kxm.hub-env.v1";
|
|
@@ -31535,27 +32037,27 @@ function resolveUserStateRoot2(env) {
|
|
|
31535
32037
|
const explicit = env.KXM_STATE_HOME?.trim();
|
|
31536
32038
|
if (explicit) {
|
|
31537
32039
|
if (!isAbsolute7(explicit)) throw new HubEnvError("local_state_root_not_absolute");
|
|
31538
|
-
return
|
|
32040
|
+
return resolve12(explicit);
|
|
31539
32041
|
}
|
|
31540
32042
|
if (process.platform === "win32") {
|
|
31541
32043
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
31542
|
-
const base2 = localAppData && isAbsolute7(localAppData) ? localAppData :
|
|
31543
|
-
return
|
|
32044
|
+
const base2 = localAppData && isAbsolute7(localAppData) ? localAppData : join21(homedir4(), "AppData", "Local");
|
|
32045
|
+
return resolve12(base2, "KXM");
|
|
31544
32046
|
}
|
|
31545
|
-
if (process.platform === "darwin") return
|
|
32047
|
+
if (process.platform === "darwin") return resolve12(homedir4(), "Library", "Application Support", "KXM");
|
|
31546
32048
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
31547
|
-
const base = xdgState && isAbsolute7(xdgState) ? xdgState :
|
|
31548
|
-
return
|
|
32049
|
+
const base = xdgState && isAbsolute7(xdgState) ? xdgState : join21(homedir4(), ".local", "state");
|
|
32050
|
+
return resolve12(base, "kxm");
|
|
31549
32051
|
}
|
|
31550
32052
|
function hubEnvFile(env = process.env) {
|
|
31551
|
-
return
|
|
32053
|
+
return join21(resolveUserStateRoot2(env), "hub-env.json");
|
|
31552
32054
|
}
|
|
31553
32055
|
function readHubEnvRecord(env = process.env) {
|
|
31554
32056
|
const file = hubEnvFile(env);
|
|
31555
|
-
if (!
|
|
32057
|
+
if (!existsSync18(file)) return void 0;
|
|
31556
32058
|
let parsed;
|
|
31557
32059
|
try {
|
|
31558
|
-
parsed = JSON.parse(
|
|
32060
|
+
parsed = JSON.parse(readFileSync16(file, "utf8"));
|
|
31559
32061
|
} catch (error) {
|
|
31560
32062
|
throw new HubEnvError(`hub env file is malformed at ${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
31561
32063
|
}
|
|
@@ -31587,31 +32089,31 @@ function readHubEnvRecord(env = process.env) {
|
|
|
31587
32089
|
...record2.projectTokens !== void 0 ? { projectTokens: record2.projectTokens } : {}
|
|
31588
32090
|
};
|
|
31589
32091
|
}
|
|
31590
|
-
function
|
|
31591
|
-
|
|
31592
|
-
|
|
31593
|
-
|
|
31594
|
-
|
|
31595
|
-
|
|
31596
|
-
|
|
31597
|
-
|
|
31598
|
-
|
|
31599
|
-
|
|
31600
|
-
throw error;
|
|
31601
|
-
}
|
|
32092
|
+
function cloudModeToken(cwd, env, explicitProject, opRead) {
|
|
32093
|
+
const connection = describeHubConnection(cwd, env, explicitProject === void 0 ? {} : { explicitProject });
|
|
32094
|
+
if (connection.mode !== "cloud") return void 0;
|
|
32095
|
+
const fromConfig = resolveKeyReference(connection.endpoint?.key, env, opRead);
|
|
32096
|
+
if (fromConfig) return fromConfig.value;
|
|
32097
|
+
if (connection.binding?.cloud) return resolveCloudHubToken(connection.binding, env);
|
|
32098
|
+
throw new CloudTokenError(
|
|
32099
|
+
"cloud_token_missing",
|
|
32100
|
+
"cloud hub token is missing; the local hub-env token was not used"
|
|
32101
|
+
);
|
|
31602
32102
|
}
|
|
31603
|
-
function resolveClientHubAuthToken(env, project) {
|
|
31604
|
-
const cloud =
|
|
31605
|
-
if (cloud) return
|
|
32103
|
+
function resolveClientHubAuthToken(env, project, cwd = process.cwd(), opRead) {
|
|
32104
|
+
const cloud = cloudModeToken(cwd, env, void 0, opRead);
|
|
32105
|
+
if (cloud) return cloud;
|
|
31606
32106
|
const envToken = env.KXM_AUTH_TOKEN?.trim();
|
|
31607
32107
|
if (envToken) return envToken;
|
|
32108
|
+
const fromConfig = resolveKeyReference(describeHubConnection(cwd, env).endpoint?.key, env, opRead);
|
|
32109
|
+
if (fromConfig) return fromConfig.value;
|
|
31608
32110
|
const record2 = readHubEnvRecord(env);
|
|
31609
32111
|
return record2?.projectTokens?.[project]?.trim() || record2?.authToken?.trim() || void 0;
|
|
31610
32112
|
}
|
|
31611
32113
|
|
|
31612
32114
|
// plugins/kxm/src/logger.ts
|
|
31613
|
-
import { appendFileSync, existsSync as
|
|
31614
|
-
import { dirname as
|
|
32115
|
+
import { appendFileSync, existsSync as existsSync19, mkdirSync as mkdirSync9, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2 } from "node:fs";
|
|
32116
|
+
import { dirname as dirname12 } from "node:path";
|
|
31615
32117
|
var LOG_LEVEL_PRIORITY = {
|
|
31616
32118
|
debug: 10,
|
|
31617
32119
|
info: 20,
|
|
@@ -31648,7 +32150,7 @@ function redactLogValue(val, key) {
|
|
|
31648
32150
|
function rotateLogFiles(filePath, maxFiles) {
|
|
31649
32151
|
for (let i = maxFiles; i >= 1; i--) {
|
|
31650
32152
|
const current = `${filePath}.${i}`;
|
|
31651
|
-
if (
|
|
32153
|
+
if (existsSync19(current)) {
|
|
31652
32154
|
if (i >= maxFiles) {
|
|
31653
32155
|
try {
|
|
31654
32156
|
unlinkSync2(current);
|
|
@@ -31662,7 +32164,7 @@ function rotateLogFiles(filePath, maxFiles) {
|
|
|
31662
32164
|
}
|
|
31663
32165
|
}
|
|
31664
32166
|
}
|
|
31665
|
-
if (
|
|
32167
|
+
if (existsSync19(filePath)) {
|
|
31666
32168
|
try {
|
|
31667
32169
|
renameSync4(filePath, `${filePath}.1`);
|
|
31668
32170
|
} catch {
|
|
@@ -31679,7 +32181,7 @@ function createLogger(options) {
|
|
|
31679
32181
|
const shouldStdout = options.stdout ?? !isDaemon;
|
|
31680
32182
|
const correlationDefaults = options.correlation ?? {};
|
|
31681
32183
|
let currentSize = 0;
|
|
31682
|
-
if (filePath &&
|
|
32184
|
+
if (filePath && existsSync19(filePath)) {
|
|
31683
32185
|
try {
|
|
31684
32186
|
currentSize = statSync5(filePath).size;
|
|
31685
32187
|
} catch {
|
|
@@ -31717,7 +32219,7 @@ function createLogger(options) {
|
|
|
31717
32219
|
currentSize = 0;
|
|
31718
32220
|
}
|
|
31719
32221
|
try {
|
|
31720
|
-
|
|
32222
|
+
mkdirSync9(dirname12(filePath), { recursive: true });
|
|
31721
32223
|
appendFileSync(filePath, line, { encoding: "utf8", mode: 384 });
|
|
31722
32224
|
currentSize += lineBytes;
|
|
31723
32225
|
} catch {
|
|
@@ -31760,13 +32262,13 @@ function createLogger(options) {
|
|
|
31760
32262
|
|
|
31761
32263
|
// plugins/kxm/src/runtime-supervisor.ts
|
|
31762
32264
|
function kxmSupervisorTokenFile(paths) {
|
|
31763
|
-
return
|
|
32265
|
+
return join22(paths.runtimeDir, "supervisor.token");
|
|
31764
32266
|
}
|
|
31765
32267
|
function publishKxmSupervisorToken(paths, token) {
|
|
31766
32268
|
const file = kxmSupervisorTokenFile(paths);
|
|
31767
|
-
|
|
32269
|
+
mkdirSync10(dirname13(file), { recursive: true, mode: 448 });
|
|
31768
32270
|
const temp = `${file}.${process.pid}.tmp`;
|
|
31769
|
-
|
|
32271
|
+
writeFileSync10(temp, `${token}
|
|
31770
32272
|
`, { encoding: "utf8", mode: 384 });
|
|
31771
32273
|
try {
|
|
31772
32274
|
chmodSync2(temp, 384);
|
|
@@ -31788,7 +32290,7 @@ function readKxmSupervisorToken(paths) {
|
|
|
31788
32290
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
31789
32291
|
throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
|
|
31790
32292
|
}
|
|
31791
|
-
const token =
|
|
32293
|
+
const token = readFileSync17(file, "utf8").trim();
|
|
31792
32294
|
return token.length >= 32 ? token : void 0;
|
|
31793
32295
|
}
|
|
31794
32296
|
function processAlive(pid) {
|
|
@@ -31802,16 +32304,16 @@ function processAlive(pid) {
|
|
|
31802
32304
|
var HEARTBEAT_STALE_MS = 15e3;
|
|
31803
32305
|
var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
|
|
31804
32306
|
function supervisorErrorFile(paths) {
|
|
31805
|
-
return
|
|
32307
|
+
return join22(paths.runtimeDir, "supervisor.error");
|
|
31806
32308
|
}
|
|
31807
32309
|
function clearSupervisorError(paths) {
|
|
31808
32310
|
const file = supervisorErrorFile(paths);
|
|
31809
|
-
if (
|
|
32311
|
+
if (existsSync20(file)) rmSync4(file, { force: true });
|
|
31810
32312
|
}
|
|
31811
32313
|
function recordSupervisorError(paths, message) {
|
|
31812
32314
|
try {
|
|
31813
|
-
|
|
31814
|
-
|
|
32315
|
+
mkdirSync10(paths.runtimeDir, { recursive: true, mode: 448 });
|
|
32316
|
+
writeFileSync10(supervisorErrorFile(paths), `${message}
|
|
31815
32317
|
`, { encoding: "utf8", mode: 384 });
|
|
31816
32318
|
} catch {
|
|
31817
32319
|
}
|
|
@@ -31823,7 +32325,7 @@ function readRecentSupervisorError(paths) {
|
|
|
31823
32325
|
const ageMs = Date.now() - stat.mtimeMs;
|
|
31824
32326
|
if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
|
|
31825
32327
|
try {
|
|
31826
|
-
return
|
|
32328
|
+
return readFileSync17(file, "utf8").trim();
|
|
31827
32329
|
} catch {
|
|
31828
32330
|
return void 0;
|
|
31829
32331
|
}
|
|
@@ -31862,7 +32364,7 @@ function supervisorStatusOf(record2) {
|
|
|
31862
32364
|
};
|
|
31863
32365
|
}
|
|
31864
32366
|
function kxmSupervisorStatus(paths, options = {}) {
|
|
31865
|
-
if (!
|
|
32367
|
+
if (!existsSync20(paths.registryDb)) return { running: false };
|
|
31866
32368
|
if (options.readOnly) {
|
|
31867
32369
|
const database = openReadOnlyDatabase(paths.registryDb);
|
|
31868
32370
|
try {
|
|
@@ -31928,7 +32430,7 @@ async function ensureKxmSupervisor(options = {}) {
|
|
|
31928
32430
|
throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
|
|
31929
32431
|
}
|
|
31930
32432
|
clearSupervisorError(paths);
|
|
31931
|
-
const scriptPath =
|
|
32433
|
+
const scriptPath = join22(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
|
|
31932
32434
|
const spawnImpl = options.spawnImpl ?? ((script, env) => {
|
|
31933
32435
|
const child = spawn3(process.execPath, [script], {
|
|
31934
32436
|
detached: true,
|
|
@@ -32013,8 +32515,8 @@ async function waitForDriveSessions(settled, graceMs) {
|
|
|
32013
32515
|
try {
|
|
32014
32516
|
await Promise.race([
|
|
32015
32517
|
Promise.allSettled(settled),
|
|
32016
|
-
new Promise((
|
|
32017
|
-
timeout = setTimeout(
|
|
32518
|
+
new Promise((resolve13) => {
|
|
32519
|
+
timeout = setTimeout(resolve13, graceMs);
|
|
32018
32520
|
timeout.unref?.();
|
|
32019
32521
|
})
|
|
32020
32522
|
]);
|
|
@@ -32151,7 +32653,7 @@ function syncFailureText(error) {
|
|
|
32151
32653
|
return `${code ? `${code}: ` : ""}${message}`.replace(/(kxm_[A-Za-z0-9_]+|[A-Za-z0-9._-]{40,})/g, "[redacted]").slice(0, 300);
|
|
32152
32654
|
}
|
|
32153
32655
|
function runtimeSupervisorLogFile(paths) {
|
|
32154
|
-
return
|
|
32656
|
+
return join22(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
|
|
32155
32657
|
}
|
|
32156
32658
|
async function startKxmRuntimeSupervisor(options = {}) {
|
|
32157
32659
|
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -32167,8 +32669,8 @@ async function startKxmRuntimeSupervisor(options = {}) {
|
|
|
32167
32669
|
}
|
|
32168
32670
|
}
|
|
32169
32671
|
async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, env) {
|
|
32170
|
-
|
|
32171
|
-
|
|
32672
|
+
mkdirSync10(paths.runtimeDir, { recursive: true, mode: 448 });
|
|
32673
|
+
mkdirSync10(paths.projectsDir, { recursive: true, mode: 448 });
|
|
32172
32674
|
const logger = createLogger({
|
|
32173
32675
|
component: "runtime",
|
|
32174
32676
|
path: runtimeSupervisorLogFile(paths),
|
|
@@ -32280,8 +32782,8 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, e
|
|
|
32280
32782
|
openRunIds = unsettledRunIds(existing2);
|
|
32281
32783
|
} else {
|
|
32282
32784
|
const registration = registry.projectByRoot(projectRoot);
|
|
32283
|
-
const eventsPath =
|
|
32284
|
-
if (registration &&
|
|
32785
|
+
const eventsPath = join22(paths.projectsDir, registration?.projectKey ?? projectRuntimeKey(projectRoot), "run-events.db");
|
|
32786
|
+
if (registration && existsSync20(eventsPath)) {
|
|
32285
32787
|
const store = new KxmRunEventStore(eventsPath);
|
|
32286
32788
|
try {
|
|
32287
32789
|
openRunIds = store.runsForProject(registration.projectId, 1e4).filter((run) => !SETTLED_RUN_STATUS.has(run.status)).map((run) => run.runId);
|