@kontextmind/kxm 0.7.20 → 0.7.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +958 -872
- package/plugins/kxm/dist/client.js +2 -2
- package/plugins/kxm/dist/extension.js +85 -67
- package/plugins/kxm/dist/mcp-server.js +3 -3
- package/plugins/kxm/dist/runtime.js +212 -194
- package/plugins/kxm/dist/server.js +46 -26
- package/plugins/kxm/dist/vnext-runtime-supervisor.js +155 -137
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/system.ts +3 -4
- package/plugins/kxm/src/cli/types.ts +2 -4
- package/plugins/kxm/src/cli/vnext.ts +1 -4
- package/plugins/kxm/src/cli.ts +15 -3
- package/plugins/kxm/src/client.ts +4 -2
- package/plugins/kxm/src/hub-autostart.ts +4 -4
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/repo-root.ts +29 -0
- package/plugins/kxm/src/vnext-config.ts +5 -3
- package/plugins/kxm/src/vnext-runtime-supervisor.ts +3 -4
|
@@ -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 = resolve6.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 resolve6(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 resolve6(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: resolve6,
|
|
4205
4205
|
resolveComponent,
|
|
4206
4206
|
equal,
|
|
4207
4207
|
serialize,
|
|
@@ -14781,18 +14781,35 @@ var require_dist = __commonJS({
|
|
|
14781
14781
|
// plugins/kxm/src/vnext-runtime-supervisor.ts
|
|
14782
14782
|
import { spawn as spawn3 } from "node:child_process";
|
|
14783
14783
|
import { createHash as createHash11, createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
14784
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
14784
|
+
import { chmodSync as chmodSync2, existsSync as existsSync10, lstatSync as lstatSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync8, renameSync, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
14785
14785
|
import { createServer } from "node:http";
|
|
14786
|
-
import { dirname as
|
|
14787
|
-
|
|
14786
|
+
import { dirname as dirname6, isAbsolute as isAbsolute4, join as join13 } from "node:path";
|
|
14787
|
+
|
|
14788
|
+
// plugins/kxm/src/repo-root.ts
|
|
14789
|
+
import { existsSync } from "node:fs";
|
|
14790
|
+
import { dirname, join } from "node:path";
|
|
14791
|
+
import { fileURLToPath } from "node:url";
|
|
14792
|
+
var ROOT_MARKERS = ["scripts/kxm-hub.mjs", "scripts/kxm.mjs"];
|
|
14793
|
+
var MAX_WALK_DEPTH = 10;
|
|
14794
|
+
function findKxmRepoRoot(fromUrl = import.meta.url) {
|
|
14795
|
+
let dir = dirname(fileURLToPath(fromUrl));
|
|
14796
|
+
for (let depth = 0; depth < MAX_WALK_DEPTH; depth += 1) {
|
|
14797
|
+
if (ROOT_MARKERS.some((marker) => existsSync(join(dir, marker)))) return dir;
|
|
14798
|
+
const parent = dirname(dir);
|
|
14799
|
+
if (parent === dir) break;
|
|
14800
|
+
dir = parent;
|
|
14801
|
+
}
|
|
14802
|
+
throw new Error(
|
|
14803
|
+
`kxm: cannot locate the KXM repo root from ${fileURLToPath(fromUrl)} (walked ${MAX_WALK_DEPTH} levels looking for ${ROOT_MARKERS[0]})`
|
|
14804
|
+
);
|
|
14805
|
+
}
|
|
14788
14806
|
|
|
14789
14807
|
// plugins/kxm/src/vnext-config.ts
|
|
14790
14808
|
var import__ = __toESM(require__(), 1);
|
|
14791
14809
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
14792
14810
|
import { createHash as createHash2 } from "node:crypto";
|
|
14793
|
-
import { existsSync as
|
|
14794
|
-
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
14795
|
-
import { fileURLToPath } from "node:url";
|
|
14811
|
+
import { existsSync as existsSync3, lstatSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
14812
|
+
import { basename, dirname as dirname2, extname, isAbsolute, join as join2, relative, resolve, sep } from "node:path";
|
|
14796
14813
|
|
|
14797
14814
|
// plugins/kxm/src/restricted-yaml.mjs
|
|
14798
14815
|
var import_yaml = __toESM(require_dist(), 1);
|
|
@@ -15120,7 +15137,7 @@ function resolveVnextTemplateBaseline(value) {
|
|
|
15120
15137
|
|
|
15121
15138
|
// plugins/kxm/src/vnext-harness.ts
|
|
15122
15139
|
import { spawnSync } from "node:child_process";
|
|
15123
|
-
import { existsSync } from "node:fs";
|
|
15140
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
15124
15141
|
import { win32 as win32Path } from "node:path";
|
|
15125
15142
|
|
|
15126
15143
|
// plugins/kxm/src/vnext-oneshot-process.ts
|
|
@@ -15146,7 +15163,7 @@ function defaultSpawn(command, args, options) {
|
|
|
15146
15163
|
if (options.signal?.aborted) {
|
|
15147
15164
|
return Promise.resolve({ stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") });
|
|
15148
15165
|
}
|
|
15149
|
-
return new Promise((
|
|
15166
|
+
return new Promise((resolve6) => {
|
|
15150
15167
|
const stdout = [];
|
|
15151
15168
|
const stderr = [];
|
|
15152
15169
|
let outputBytes = 0;
|
|
@@ -15177,7 +15194,7 @@ function defaultSpawn(command, args, options) {
|
|
|
15177
15194
|
const started = Boolean(child?.pid);
|
|
15178
15195
|
if (started && !observedChildExit) error ??= new Error("process_exit_unobserved");
|
|
15179
15196
|
const unverifiedDescendants = stopping || started && !observedChildExit;
|
|
15180
|
-
|
|
15197
|
+
resolve6({
|
|
15181
15198
|
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
15182
15199
|
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
15183
15200
|
code,
|
|
@@ -15669,7 +15686,7 @@ function findWinNpmInnerExe(cliId, options = {}) {
|
|
|
15669
15686
|
if ((options.platform ?? process.platform) !== "win32") return void 0;
|
|
15670
15687
|
const segments = WIN_NPM_INNER_EXE[cliId];
|
|
15671
15688
|
if (!segments) return void 0;
|
|
15672
|
-
const exists = options.existsSync ??
|
|
15689
|
+
const exists = options.existsSync ?? existsSync2;
|
|
15673
15690
|
const pathEnv = options.pathEnv ?? process.env.PATH ?? "";
|
|
15674
15691
|
for (const dir of pathEnv.split(";").filter(Boolean)) {
|
|
15675
15692
|
if (!exists(win32Path.join(dir, `${cliId}.cmd`))) continue;
|
|
@@ -16179,8 +16196,10 @@ var VnextConfigError = class extends Error {
|
|
|
16179
16196
|
this.issues = sorted;
|
|
16180
16197
|
}
|
|
16181
16198
|
};
|
|
16182
|
-
|
|
16183
|
-
|
|
16199
|
+
function defaultVnextSchemaDir() {
|
|
16200
|
+
return join2(findKxmRepoRoot(import.meta.url), "schemas", "vnext");
|
|
16201
|
+
}
|
|
16202
|
+
var DEFAULT_SCHEMA_DIR = defaultVnextSchemaDir();
|
|
16184
16203
|
var RESOURCE_SCHEMA = Object.freeze({
|
|
16185
16204
|
project: { identity: "kxm.project.v1", file: "project.schema.json" },
|
|
16186
16205
|
repository: { identity: "kxm.repository.v1", file: "repository.schema.json" },
|
|
@@ -16245,10 +16264,10 @@ var VnextSchemaRegistry = class {
|
|
|
16245
16264
|
constructor(schemasDir = DEFAULT_SCHEMA_DIR) {
|
|
16246
16265
|
this.schemasDir = resolve(schemasDir);
|
|
16247
16266
|
this.ajv = new import__.Ajv2020({ allErrors: true, strict: true, strictRequired: false });
|
|
16248
|
-
const common = readJsonObject(
|
|
16267
|
+
const common = readJsonObject(join2(this.schemasDir, "common.schema.json"));
|
|
16249
16268
|
this.ajv.addSchema(common);
|
|
16250
16269
|
for (const definition of Object.values(RESOURCE_SCHEMA)) {
|
|
16251
|
-
this.ajv.addSchema(readJsonObject(
|
|
16270
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, definition.file)));
|
|
16252
16271
|
}
|
|
16253
16272
|
const localBindingsFile = "local-repository-bindings.schema.json";
|
|
16254
16273
|
const templateProvenanceFile = "template-provenance.schema.json";
|
|
@@ -16258,14 +16277,14 @@ var VnextSchemaRegistry = class {
|
|
|
16258
16277
|
const migrationReceiptFile = "migration-receipt.schema.json";
|
|
16259
16278
|
const permissionDiffFile = "permission-diff.schema.json";
|
|
16260
16279
|
const runEventFile = "run-event.schema.json";
|
|
16261
|
-
this.ajv.addSchema(readJsonObject(
|
|
16262
|
-
this.ajv.addSchema(readJsonObject(
|
|
16263
|
-
this.ajv.addSchema(readJsonObject(
|
|
16264
|
-
this.ajv.addSchema(readJsonObject(
|
|
16265
|
-
this.ajv.addSchema(readJsonObject(
|
|
16266
|
-
this.ajv.addSchema(readJsonObject(
|
|
16267
|
-
this.ajv.addSchema(readJsonObject(
|
|
16268
|
-
this.ajv.addSchema(readJsonObject(
|
|
16280
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, localBindingsFile)));
|
|
16281
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, templateProvenanceFile)));
|
|
16282
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, initOperationFile)));
|
|
16283
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationPlanFile)));
|
|
16284
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationDecisionFile)));
|
|
16285
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationReceiptFile)));
|
|
16286
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, permissionDiffFile)));
|
|
16287
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, runEventFile)));
|
|
16269
16288
|
for (const [kind, definition] of Object.entries(RESOURCE_SCHEMA)) {
|
|
16270
16289
|
const validator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${definition.file}`);
|
|
16271
16290
|
if (!validator) throw new Error(`schema did not compile: ${definition.file}`);
|
|
@@ -16372,15 +16391,15 @@ function containedHostPath(root, candidate) {
|
|
|
16372
16391
|
function portableBindingIssue(root, pathHint, repositoryId) {
|
|
16373
16392
|
let current = root;
|
|
16374
16393
|
for (const segment of pathHint === "." ? [] : pathHint.split("/")) {
|
|
16375
|
-
current =
|
|
16376
|
-
if (!
|
|
16394
|
+
current = join2(current, segment);
|
|
16395
|
+
if (!existsSync3(current)) break;
|
|
16377
16396
|
const stat = lstatSync(current);
|
|
16378
16397
|
if (stat.isSymbolicLink()) {
|
|
16379
16398
|
return issue2("path", "repository_binding_path_link", ".kxm/project.yaml", `portable pathHint for ${repositoryId} traverses a symbolic link or junction`);
|
|
16380
16399
|
}
|
|
16381
16400
|
}
|
|
16382
16401
|
const binding = resolve(root, ...pathHint.split("/"));
|
|
16383
|
-
if (
|
|
16402
|
+
if (existsSync3(binding)) {
|
|
16384
16403
|
const realRoot = canonicalHostPath(root);
|
|
16385
16404
|
const realBinding = canonicalHostPath(binding);
|
|
16386
16405
|
if (!containedHostPath(realRoot, realBinding)) {
|
|
@@ -16418,9 +16437,9 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
|
|
|
16418
16437
|
}
|
|
16419
16438
|
if (stat.isSymbolicLink()) fail2("path", "resource_symlink", label, "configuration resources must not be symbolic links");
|
|
16420
16439
|
const boundary = resolve(containmentRoot);
|
|
16421
|
-
let parent =
|
|
16440
|
+
let parent = dirname2(file);
|
|
16422
16441
|
while (parent !== boundary) {
|
|
16423
|
-
if (parent ===
|
|
16442
|
+
if (parent === dirname2(parent)) fail2("path", "resource_outside_project", label, "resource escapes the project root");
|
|
16424
16443
|
let parentStat;
|
|
16425
16444
|
try {
|
|
16426
16445
|
parentStat = lstatSync(parent);
|
|
@@ -16428,7 +16447,7 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
|
|
|
16428
16447
|
fail2("discovery", "resource_parent_missing", label, "resource parent does not exist");
|
|
16429
16448
|
}
|
|
16430
16449
|
if (parentStat.isSymbolicLink()) fail2("path", "resource_parent_symlink", label, "configuration resource parents must not be symbolic links");
|
|
16431
|
-
parent =
|
|
16450
|
+
parent = dirname2(parent);
|
|
16432
16451
|
}
|
|
16433
16452
|
if (!stat.isFile()) fail2("path", "resource_not_file", label, "configuration resource must be a regular file");
|
|
16434
16453
|
const value = parseRestrictedYaml2(readFileSync(file), label);
|
|
@@ -16437,22 +16456,22 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
|
|
|
16437
16456
|
return { kind, ...id === void 0 ? {} : { id }, file, logicalPath, value };
|
|
16438
16457
|
}
|
|
16439
16458
|
function readTemplateProvenance(registry, root) {
|
|
16440
|
-
const file =
|
|
16441
|
-
if (!
|
|
16459
|
+
const file = join2(root, ".kxm", "template-provenance.yaml");
|
|
16460
|
+
if (!existsSync3(file)) return void 0;
|
|
16442
16461
|
const label = ".kxm/template-provenance.yaml";
|
|
16443
16462
|
const stat = lstatSync(file);
|
|
16444
16463
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
16445
16464
|
fail2("path", "resource_not_file", label, "template provenance must be a regular file, not a link or directory");
|
|
16446
16465
|
}
|
|
16447
|
-
const configRoot =
|
|
16448
|
-
let parent =
|
|
16466
|
+
const configRoot = join2(root, ".kxm");
|
|
16467
|
+
let parent = dirname2(file);
|
|
16449
16468
|
while (parent !== root) {
|
|
16450
16469
|
const parentStat = lstatSync(parent);
|
|
16451
16470
|
if (parentStat.isSymbolicLink() || !parentStat.isDirectory()) {
|
|
16452
16471
|
fail2("path", "resource_parent_symlink", label, "template provenance parents must be regular directories");
|
|
16453
16472
|
}
|
|
16454
16473
|
if (parent === configRoot) break;
|
|
16455
|
-
parent =
|
|
16474
|
+
parent = dirname2(parent);
|
|
16456
16475
|
}
|
|
16457
16476
|
const value = parseRestrictedYaml2(readFileSync(file), label);
|
|
16458
16477
|
const issues = registry.validateTemplateProvenance(value, label);
|
|
@@ -16485,7 +16504,7 @@ function readTemplateProvenance(registry, root) {
|
|
|
16485
16504
|
}
|
|
16486
16505
|
function listNamedResources(registry, root, directory, logicalDirectory, kind) {
|
|
16487
16506
|
const resources = /* @__PURE__ */ new Map();
|
|
16488
|
-
if (!
|
|
16507
|
+
if (!existsSync3(directory)) return resources;
|
|
16489
16508
|
const stat = lstatSync(directory);
|
|
16490
16509
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
16491
16510
|
fail2("path", "resource_directory_invalid", displayPath(root, directory), "resource directory must be a regular directory");
|
|
@@ -16494,27 +16513,27 @@ function listNamedResources(registry, root, directory, logicalDirectory, kind) {
|
|
|
16494
16513
|
const entries = readdirSync(directory, { withFileTypes: true }).sort((left, right) => compareCodeUnits3(left.name, right.name));
|
|
16495
16514
|
for (const entry of entries) {
|
|
16496
16515
|
if (entry.isDirectory()) {
|
|
16497
|
-
issues.push(issue2("path", "nested_resource_directory", displayPath(root,
|
|
16516
|
+
issues.push(issue2("path", "nested_resource_directory", displayPath(root, join2(directory, entry.name)), "nested resource directories are not allowed"));
|
|
16498
16517
|
continue;
|
|
16499
16518
|
}
|
|
16500
16519
|
if (!entry.name.toLowerCase().endsWith(".yaml") && !entry.name.toLowerCase().endsWith(".yml")) continue;
|
|
16501
16520
|
if (!entry.isFile() || extname(entry.name) !== ".yaml") {
|
|
16502
|
-
issues.push(issue2("path", "resource_filename_invalid", displayPath(root,
|
|
16521
|
+
issues.push(issue2("path", "resource_filename_invalid", displayPath(root, join2(directory, entry.name)), "resource must be a regular file with the exact .yaml extension"));
|
|
16503
16522
|
continue;
|
|
16504
16523
|
}
|
|
16505
16524
|
const id = basename(entry.name, ".yaml");
|
|
16506
16525
|
if (kind === "model" && id === "inventory") continue;
|
|
16507
16526
|
if (!resourceIdentifier(id)) {
|
|
16508
|
-
issues.push(issue2("path", "resource_id_invalid", displayPath(root,
|
|
16527
|
+
issues.push(issue2("path", "resource_id_invalid", displayPath(root, join2(directory, entry.name)), `filename-derived identity ${id} is invalid or platform-reserved`));
|
|
16509
16528
|
continue;
|
|
16510
16529
|
}
|
|
16511
16530
|
const collision = [...resources.keys()].find((candidate) => candidate.toLocaleLowerCase("en-US") === id.toLocaleLowerCase("en-US"));
|
|
16512
16531
|
if (collision) {
|
|
16513
|
-
issues.push(issue2("path", "resource_id_collision", displayPath(root,
|
|
16532
|
+
issues.push(issue2("path", "resource_id_collision", displayPath(root, join2(directory, entry.name)), `${id} case-folds to existing ${collision}`));
|
|
16514
16533
|
continue;
|
|
16515
16534
|
}
|
|
16516
16535
|
try {
|
|
16517
|
-
const resource = readResource(registry, root,
|
|
16536
|
+
const resource = readResource(registry, root, join2(directory, entry.name), `${logicalDirectory}/${id}.yaml`, kind, id);
|
|
16518
16537
|
resources.set(id, resource);
|
|
16519
16538
|
} catch (error) {
|
|
16520
16539
|
if (error instanceof VnextConfigError) issues.push(...error.issues);
|
|
@@ -16806,8 +16825,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
16806
16825
|
const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
|
|
16807
16826
|
if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
|
|
16808
16827
|
}
|
|
16809
|
-
const
|
|
16810
|
-
const minimumPassed =
|
|
16828
|
+
const join14 = objectValue(step.join);
|
|
16829
|
+
const minimumPassed = join14 && typeof join14.minimumPassed === "number" ? join14.minimumPassed : void 0;
|
|
16811
16830
|
if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
|
|
16812
16831
|
const distinctBy = names(assignment?.distinctBy);
|
|
16813
16832
|
if (distinctBy.length > 0) {
|
|
@@ -17021,9 +17040,9 @@ function validateBundle(project, repositories, agents, models, workflows, enviro
|
|
|
17021
17040
|
if (!workflows.has(defaultWorkflow)) issues.push(issue2("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
|
|
17022
17041
|
for (const workflow of workflows.values()) validateWorkflow(workflow, agents, models, repositoryIds, gates, issues);
|
|
17023
17042
|
if (projectRoot) {
|
|
17024
|
-
const writerRolePath =
|
|
17043
|
+
const writerRolePath = join2(projectRoot, ".kxm", "roles", "writer.yaml");
|
|
17025
17044
|
const implementerAgent = agents.get("implementer") ?? agents.get("writer");
|
|
17026
|
-
if (
|
|
17045
|
+
if (existsSync3(writerRolePath) && implementerAgent) {
|
|
17027
17046
|
try {
|
|
17028
17047
|
const rawRole = parseRestrictedYaml2(readFileSync(writerRolePath, "utf8"));
|
|
17029
17048
|
const roleObj = objectValue(rawRole);
|
|
@@ -17072,7 +17091,7 @@ function gitEnvironment() {
|
|
|
17072
17091
|
}
|
|
17073
17092
|
function discoverGitRoot(start = process.cwd()) {
|
|
17074
17093
|
let current = resolve(start);
|
|
17075
|
-
if (
|
|
17094
|
+
if (existsSync3(current) && !lstatSync(current).isDirectory()) current = dirname2(current);
|
|
17076
17095
|
const result = spawnSync2("git", ["-C", current, "rev-parse", "--show-toplevel"], {
|
|
17077
17096
|
encoding: "utf8",
|
|
17078
17097
|
env: gitEnvironment(),
|
|
@@ -17081,7 +17100,7 @@ function discoverGitRoot(start = process.cwd()) {
|
|
|
17081
17100
|
});
|
|
17082
17101
|
if (result.status !== 0 || result.error || !result.stdout.trim()) return void 0;
|
|
17083
17102
|
const root = resolve(result.stdout.trim());
|
|
17084
|
-
return
|
|
17103
|
+
return existsSync3(root) && lstatSync(root).isDirectory() ? root : void 0;
|
|
17085
17104
|
}
|
|
17086
17105
|
function assertNoRegisteredGates(options) {
|
|
17087
17106
|
if ("registeredGates" in options) {
|
|
@@ -17098,7 +17117,7 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17098
17117
|
migrationReceipt = receiptCheck.receipt;
|
|
17099
17118
|
}
|
|
17100
17119
|
const registry = new VnextSchemaRegistry(options.schemasDir);
|
|
17101
|
-
const project = readResource(registry, root,
|
|
17120
|
+
const project = readResource(registry, root, join2(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
|
|
17102
17121
|
const earlyIssues = [];
|
|
17103
17122
|
validatePortablePaths(project, earlyIssues);
|
|
17104
17123
|
const templateProvenance = readTemplateProvenance(registry, root);
|
|
@@ -17120,16 +17139,16 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17120
17139
|
}
|
|
17121
17140
|
}
|
|
17122
17141
|
if (earlyIssues.length > 0) throw new VnextConfigError(earlyIssues);
|
|
17123
|
-
const agents = listNamedResources(registry, root,
|
|
17124
|
-
const models = listNamedResources(registry, root,
|
|
17125
|
-
const workflows = listNamedResources(registry, root,
|
|
17126
|
-
const gatePath =
|
|
17127
|
-
const gateRegistry =
|
|
17142
|
+
const agents = listNamedResources(registry, root, join2(root, ".kxm", "agents"), ".kxm/agents", "agent");
|
|
17143
|
+
const models = listNamedResources(registry, root, join2(root, ".kxm", "models"), ".kxm/models", "model");
|
|
17144
|
+
const workflows = listNamedResources(registry, root, join2(root, ".kxm", "workflows"), ".kxm/workflows", "workflow");
|
|
17145
|
+
const gatePath = join2(root, ".kxm", "gates.yaml");
|
|
17146
|
+
const gateRegistry = existsSync3(gatePath) ? readResource(registry, root, gatePath, ".kxm/gates.yaml", "gate-registry") : void 0;
|
|
17128
17147
|
const environments = [];
|
|
17129
17148
|
const repositories = /* @__PURE__ */ new Map();
|
|
17130
17149
|
const loadIssues = [];
|
|
17131
|
-
const projectEnvironment =
|
|
17132
|
-
if (
|
|
17150
|
+
const projectEnvironment = join2(root, ".kxm", "project", "env.yaml");
|
|
17151
|
+
if (existsSync3(projectEnvironment)) {
|
|
17133
17152
|
try {
|
|
17134
17153
|
environments.push(readResource(registry, root, projectEnvironment, ".kxm/project/env.yaml", "environment"));
|
|
17135
17154
|
} catch (error) {
|
|
@@ -17171,7 +17190,7 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17171
17190
|
if (required) loadIssues.push(issue2("discovery", "repository_binding_missing", ".kxm/project.yaml", `required repository ${repositoryId} has no portable pathHint or host-local binding`));
|
|
17172
17191
|
continue;
|
|
17173
17192
|
}
|
|
17174
|
-
if (!
|
|
17193
|
+
if (!existsSync3(binding)) {
|
|
17175
17194
|
if (required || hasLocalBinding) loadIssues.push(issue2("discovery", "repository_binding_unavailable", ".kxm/project.yaml", `${hasLocalBinding ? "explicit" : "required"} repository binding ${repositoryId} is unavailable`));
|
|
17176
17195
|
continue;
|
|
17177
17196
|
}
|
|
@@ -17194,9 +17213,9 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17194
17213
|
continue;
|
|
17195
17214
|
}
|
|
17196
17215
|
seenBindings.set(foldedBinding, repositoryId);
|
|
17197
|
-
const repositoryFile =
|
|
17216
|
+
const repositoryFile = join2(binding, ".kxm", "repo", "repo.yaml");
|
|
17198
17217
|
let definitionValidated = false;
|
|
17199
|
-
if (
|
|
17218
|
+
if (existsSync3(repositoryFile)) {
|
|
17200
17219
|
try {
|
|
17201
17220
|
const resource = readResource(registry, root, repositoryFile, `.kxm/repositories/${repositoryId}/repo.yaml`, "repository", repositoryId, binding);
|
|
17202
17221
|
if (resource.value.repositoryId !== repositoryId) {
|
|
@@ -17212,8 +17231,8 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17212
17231
|
} else if (required || hasLocalBinding) {
|
|
17213
17232
|
loadIssues.push(issue2("discovery", "repository_definition_missing", `.kxm/repositories/${repositoryId}/repo.yaml`, `${hasLocalBinding ? "explicit" : "required"} repository ${repositoryId} has no repo.yaml`));
|
|
17214
17233
|
}
|
|
17215
|
-
const environmentFile =
|
|
17216
|
-
if (
|
|
17234
|
+
const environmentFile = join2(binding, ".kxm", "repo", "env.yaml");
|
|
17235
|
+
if (existsSync3(environmentFile)) {
|
|
17217
17236
|
if (!definitionValidated) {
|
|
17218
17237
|
loadIssues.push(issue2("reference", "repository_environment_without_definition", `.kxm/repositories/${repositoryId}/env.yaml`, `repository ${repositoryId} environment requires a validated matching repo.yaml`));
|
|
17219
17238
|
} else {
|
|
@@ -17250,14 +17269,14 @@ var LEGACY_CONFIG_FILES = [".kxm/config/agents.json", ".kxm/config/gates.json"];
|
|
|
17250
17269
|
function legacyConfigFilesAt(root) {
|
|
17251
17270
|
const files = [];
|
|
17252
17271
|
for (const component of [".kxm", ".kxm/config"]) {
|
|
17253
|
-
const absolute =
|
|
17254
|
-
if (
|
|
17272
|
+
const absolute = join2(root, ...component.split("/"));
|
|
17273
|
+
if (existsSync3(absolute) && lstatSync(absolute).isSymbolicLink()) return [component];
|
|
17255
17274
|
}
|
|
17256
17275
|
for (const candidate of LEGACY_CONFIG_FILES) {
|
|
17257
|
-
if (
|
|
17276
|
+
if (existsSync3(join2(root, ...candidate.split("/")))) files.push(candidate);
|
|
17258
17277
|
}
|
|
17259
|
-
const workflowsDir =
|
|
17260
|
-
if (
|
|
17278
|
+
const workflowsDir = join2(root, ".kxm", "config", "workflows");
|
|
17279
|
+
if (existsSync3(workflowsDir)) {
|
|
17261
17280
|
const stat = lstatSync(workflowsDir);
|
|
17262
17281
|
if (stat.isSymbolicLink()) {
|
|
17263
17282
|
files.push(".kxm/config/workflows");
|
|
@@ -17272,8 +17291,8 @@ function legacyConfigFilesAt(root) {
|
|
|
17272
17291
|
return files;
|
|
17273
17292
|
}
|
|
17274
17293
|
function hashFileRecord(root, relativePath) {
|
|
17275
|
-
const absolute =
|
|
17276
|
-
if (!
|
|
17294
|
+
const absolute = join2(root, ...relativePath.split("/"));
|
|
17295
|
+
if (!existsSync3(absolute)) return void 0;
|
|
17277
17296
|
const bytes = readFileSync(absolute);
|
|
17278
17297
|
return {
|
|
17279
17298
|
path: relativePath,
|
|
@@ -17286,9 +17305,9 @@ function migrationReceiptSelfHash(receipt) {
|
|
|
17286
17305
|
return `sha256:${createHash2("sha256").update(vnextCanonicalJson(unsigned), "utf8").digest("hex")}`;
|
|
17287
17306
|
}
|
|
17288
17307
|
function readVnextMigrationReceipt(root, options = {}) {
|
|
17289
|
-
const receiptPath =
|
|
17308
|
+
const receiptPath = join2(root, ...VNEXT_MIGRATION_RECEIPT_PATH.split("/"));
|
|
17290
17309
|
const legacyFiles = legacyConfigFilesAt(root);
|
|
17291
|
-
if (!
|
|
17310
|
+
if (!existsSync3(receiptPath)) {
|
|
17292
17311
|
return {
|
|
17293
17312
|
issues: legacyFiles.map((file) => issue2("semantic", "legacy_vnext_conflict", file, "legacy and vNext configuration cannot coexist before an accepted migration receipt"))
|
|
17294
17313
|
};
|
|
@@ -17334,8 +17353,8 @@ function readVnextMigrationReceipt(root, options = {}) {
|
|
|
17334
17353
|
|
|
17335
17354
|
// plugins/kxm/src/vnext-runtime-store.ts
|
|
17336
17355
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
17337
|
-
import { existsSync as
|
|
17338
|
-
import { dirname as
|
|
17356
|
+
import { existsSync as existsSync5, lstatSync as lstatSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
17357
|
+
import { dirname as dirname5, join as join5, resolve as resolve4 } from "node:path";
|
|
17339
17358
|
|
|
17340
17359
|
// plugins/kxm/src/vnext-bindings.ts
|
|
17341
17360
|
import { homedir } from "node:os";
|
|
@@ -17380,7 +17399,7 @@ var DatabaseSync = class {
|
|
|
17380
17399
|
};
|
|
17381
17400
|
|
|
17382
17401
|
// plugins/kxm/src/vnext-bindings.ts
|
|
17383
|
-
import { dirname as
|
|
17402
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, parse, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
17384
17403
|
var MAX_BINDING_RECORD_BYTES = 256 * 1024;
|
|
17385
17404
|
var BINDING_LABEL = "Runtime-local repository bindings";
|
|
17386
17405
|
function bindingIssue(phase, code, message) {
|
|
@@ -17400,12 +17419,12 @@ function vnextUserStateRoot(options = {}) {
|
|
|
17400
17419
|
}
|
|
17401
17420
|
if (platform === "win32") {
|
|
17402
17421
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
17403
|
-
const base2 = localAppData && isAbsolute2(localAppData) ? localAppData :
|
|
17422
|
+
const base2 = localAppData && isAbsolute2(localAppData) ? localAppData : join3(home, "AppData", "Local");
|
|
17404
17423
|
return resolve2(base2, "KXM");
|
|
17405
17424
|
}
|
|
17406
17425
|
if (platform === "darwin") return resolve2(home, "Library", "Application Support", "KXM");
|
|
17407
17426
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
17408
|
-
const base = xdgState && isAbsolute2(xdgState) ? xdgState :
|
|
17427
|
+
const base = xdgState && isAbsolute2(xdgState) ? xdgState : join3(home, ".local", "state");
|
|
17409
17428
|
return resolve2(base, "kxm");
|
|
17410
17429
|
}
|
|
17411
17430
|
|
|
@@ -17413,7 +17432,7 @@ function vnextUserStateRoot(options = {}) {
|
|
|
17413
17432
|
import {
|
|
17414
17433
|
chmodSync,
|
|
17415
17434
|
copyFileSync,
|
|
17416
|
-
existsSync as
|
|
17435
|
+
existsSync as existsSync4,
|
|
17417
17436
|
lstatSync as lstatSync2,
|
|
17418
17437
|
mkdirSync,
|
|
17419
17438
|
readdirSync as readdirSync2,
|
|
@@ -17421,14 +17440,14 @@ import {
|
|
|
17421
17440
|
unlinkSync,
|
|
17422
17441
|
writeFileSync
|
|
17423
17442
|
} from "node:fs";
|
|
17424
|
-
import { basename as basename2, dirname as
|
|
17443
|
+
import { basename as basename2, dirname as dirname4, join as join4, resolve as resolve3 } from "node:path";
|
|
17425
17444
|
function databaseError(code, file, message) {
|
|
17426
17445
|
const issue3 = { phase: "semantic", code, file, message };
|
|
17427
17446
|
return new VnextConfigError([issue3]);
|
|
17428
17447
|
}
|
|
17429
17448
|
function checkedParent(path, description) {
|
|
17430
|
-
const parent =
|
|
17431
|
-
if (!
|
|
17449
|
+
const parent = dirname4(path);
|
|
17450
|
+
if (!existsSync4(parent)) mkdirSync(parent, { recursive: true, mode: 448 });
|
|
17432
17451
|
const stat = lstatSync2(parent, { throwIfNoEntry: false });
|
|
17433
17452
|
if (!stat || stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
17434
17453
|
throw databaseError("runtime_path_invalid", description, `${description} parent must be a regular directory, not a link`);
|
|
@@ -17582,12 +17601,12 @@ function withDatabaseTransaction(database, work, mode = "IMMEDIATE") {
|
|
|
17582
17601
|
// plugins/kxm/src/vnext-runtime-store.ts
|
|
17583
17602
|
function vnextRuntimePaths(options = {}) {
|
|
17584
17603
|
const stateRoot = options.stateRoot ? resolve4(options.stateRoot) : vnextUserStateRoot({ ...options.env ? { env: options.env } : {}, ...options.homeDir ? { homeDir: options.homeDir } : {} });
|
|
17585
|
-
const runtimeDir =
|
|
17604
|
+
const runtimeDir = join5(stateRoot, "runtime");
|
|
17586
17605
|
return {
|
|
17587
17606
|
stateRoot,
|
|
17588
17607
|
runtimeDir,
|
|
17589
|
-
registryDb:
|
|
17590
|
-
projectsDir:
|
|
17608
|
+
registryDb: join5(runtimeDir, "registry.db"),
|
|
17609
|
+
projectsDir: join5(runtimeDir, "projects")
|
|
17591
17610
|
};
|
|
17592
17611
|
}
|
|
17593
17612
|
function runtimeIssue(phase, code, file, message) {
|
|
@@ -18049,7 +18068,7 @@ var VnextRunEventStore = class {
|
|
|
18049
18068
|
}
|
|
18050
18069
|
readRunPrompts() {
|
|
18051
18070
|
const sidecar = this.runPromptSidecarPath();
|
|
18052
|
-
if (!
|
|
18071
|
+
if (!existsSync5(sidecar)) return {};
|
|
18053
18072
|
try {
|
|
18054
18073
|
const parsed = JSON.parse(readFileSync3(sidecar, "utf8"));
|
|
18055
18074
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
@@ -18772,8 +18791,8 @@ function capabilityFromRow(row) {
|
|
|
18772
18791
|
|
|
18773
18792
|
// plugins/kxm/src/vnext-runtime.ts
|
|
18774
18793
|
import { createHash as createHash5 } from "node:crypto";
|
|
18775
|
-
import { existsSync as
|
|
18776
|
-
import { join as
|
|
18794
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync4 } from "node:fs";
|
|
18795
|
+
import { join as join6 } from "node:path";
|
|
18777
18796
|
|
|
18778
18797
|
// plugins/kxm/src/vnext-engine-fold.ts
|
|
18779
18798
|
var VNEXT_RUN_STATE_SCHEMA = "kxm.run-state.v2";
|
|
@@ -20072,7 +20091,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
20072
20091
|
const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
|
|
20073
20092
|
const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
|
|
20074
20093
|
const assignments = compileAssignments(step, id, agent, sink);
|
|
20075
|
-
const
|
|
20094
|
+
const join14 = compileJoin(step, id, sink);
|
|
20076
20095
|
const requiredEvidence = compileEvidence(step, id, sink);
|
|
20077
20096
|
const transitions = compileTransitions(step, id, index, stepIndex, sink);
|
|
20078
20097
|
const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
|
|
@@ -20100,7 +20119,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
20100
20119
|
transitions: orderedTransitions,
|
|
20101
20120
|
requiresPlanHash: requirePlanHash.includes(id),
|
|
20102
20121
|
assignments,
|
|
20103
|
-
join:
|
|
20122
|
+
join: join14
|
|
20104
20123
|
};
|
|
20105
20124
|
if (kind === "agent" || kind === "moa") {
|
|
20106
20125
|
if (!agent) return void 0;
|
|
@@ -20150,15 +20169,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
|
|
|
20150
20169
|
};
|
|
20151
20170
|
}
|
|
20152
20171
|
function compileJoin(step, stepId, sink) {
|
|
20153
|
-
const
|
|
20154
|
-
if (!
|
|
20155
|
-
const declared = stringValue2(
|
|
20172
|
+
const join14 = objectValue2(step.join);
|
|
20173
|
+
if (!join14) return { strategy: "all" };
|
|
20174
|
+
const declared = stringValue2(join14.strategy);
|
|
20156
20175
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
20157
|
-
const minimumPassed = compileOptionalCount(
|
|
20176
|
+
const minimumPassed = compileOptionalCount(join14.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
20158
20177
|
const compiled = {
|
|
20159
20178
|
strategy,
|
|
20160
20179
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
20161
|
-
...typeof
|
|
20180
|
+
...typeof join14.cancelRemaining === "boolean" ? { cancelRemaining: join14.cancelRemaining } : {}
|
|
20162
20181
|
};
|
|
20163
20182
|
return compiled;
|
|
20164
20183
|
}
|
|
@@ -21479,12 +21498,12 @@ function enqueueVnextScheduledRun(storePath, runId, configRevision, bound, start
|
|
|
21479
21498
|
if (owner.admitted.has(runId) || owner.queue.some((item) => item.runId === runId)) {
|
|
21480
21499
|
return Promise.reject(runtimeError("run_busy", runId, `run ${runId} is already admitted or queued`));
|
|
21481
21500
|
}
|
|
21482
|
-
return new Promise((
|
|
21501
|
+
return new Promise((resolve6, reject) => {
|
|
21483
21502
|
owner.queue.push({
|
|
21484
21503
|
runId,
|
|
21485
21504
|
configRevision,
|
|
21486
21505
|
bound,
|
|
21487
|
-
start: (token) => start(token).then(
|
|
21506
|
+
start: (token) => start(token).then(resolve6, reject),
|
|
21488
21507
|
fail: (error) => reject(error)
|
|
21489
21508
|
});
|
|
21490
21509
|
pump(storePath, owner);
|
|
@@ -21545,11 +21564,11 @@ function vnextToolPolicyRevision(bundle) {
|
|
|
21545
21564
|
return sha256Of(vnextCanonicalJson({ policies, gateRegistry: bundle.gateRegistry?.value ?? null }));
|
|
21546
21565
|
}
|
|
21547
21566
|
function collectMemoryFiles(dir, baseDir, ignoreSubdirs = /* @__PURE__ */ new Set()) {
|
|
21548
|
-
if (!
|
|
21567
|
+
if (!existsSync6(dir)) return [];
|
|
21549
21568
|
const entries = readdirSync3(dir, { withFileTypes: true });
|
|
21550
21569
|
const results = [];
|
|
21551
21570
|
for (const entry of entries) {
|
|
21552
|
-
const fullPath =
|
|
21571
|
+
const fullPath = join6(dir, entry.name);
|
|
21553
21572
|
if (entry.isDirectory()) {
|
|
21554
21573
|
if (ignoreSubdirs.has(entry.name)) continue;
|
|
21555
21574
|
results.push(...collectMemoryFiles(fullPath, baseDir, ignoreSubdirs));
|
|
@@ -21562,15 +21581,15 @@ function collectMemoryFiles(dir, baseDir, ignoreSubdirs = /* @__PURE__ */ new Se
|
|
|
21562
21581
|
}
|
|
21563
21582
|
function computeVnextMemoryRevision(bundle, options = {}) {
|
|
21564
21583
|
const hash = createHash5("sha256");
|
|
21565
|
-
const memoryDir = options.memoryDir ??
|
|
21584
|
+
const memoryDir = options.memoryDir ?? join6(bundle.projectRoot, ".kxm", "memory");
|
|
21566
21585
|
const memoryFiles = collectMemoryFiles(memoryDir, memoryDir, /* @__PURE__ */ new Set(["candidates"])).sort((left, right) => compareCodeUnits5(left.relPath, right.relPath));
|
|
21567
21586
|
for (const file of memoryFiles) {
|
|
21568
21587
|
hash.update(`memory:${file.relPath}\0`, "utf8");
|
|
21569
21588
|
hash.update(readFileSync4(file.fullPath));
|
|
21570
21589
|
hash.update("\0", "utf8");
|
|
21571
21590
|
}
|
|
21572
|
-
const skillsDir = options.skillsDir ??
|
|
21573
|
-
const promotedSkillsDir =
|
|
21591
|
+
const skillsDir = options.skillsDir ?? join6(bundle.projectRoot, ".kxm", "skills");
|
|
21592
|
+
const promotedSkillsDir = join6(skillsDir, "promoted");
|
|
21574
21593
|
const skillFiles = collectMemoryFiles(promotedSkillsDir, promotedSkillsDir).sort((left, right) => compareCodeUnits5(left.relPath, right.relPath));
|
|
21575
21594
|
for (const file of skillFiles) {
|
|
21576
21595
|
hash.update(`skill:${file.relPath}\0`, "utf8");
|
|
@@ -21646,7 +21665,7 @@ function openVnextRuntimeContext(projectRoot, options) {
|
|
|
21646
21665
|
configRevision: bundle.configRevision,
|
|
21647
21666
|
now: options.now ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
21648
21667
|
});
|
|
21649
|
-
const eventStore = new VnextRunEventStore(
|
|
21668
|
+
const eventStore = new VnextRunEventStore(join6(paths.projectsDir, registration.projectKey, "run-events.db"));
|
|
21650
21669
|
registerVnextRuntimeHandle(eventStore.path);
|
|
21651
21670
|
return {
|
|
21652
21671
|
registry,
|
|
@@ -21961,12 +21980,12 @@ function cancelVnextRun(context, runId, options = {}) {
|
|
|
21961
21980
|
}
|
|
21962
21981
|
|
|
21963
21982
|
// plugins/kxm/src/vnext-oneshot-producer.ts
|
|
21964
|
-
import { join as
|
|
21983
|
+
import { join as join12 } from "node:path";
|
|
21965
21984
|
|
|
21966
21985
|
// plugins/kxm/src/vnext-oneshot-evidence.ts
|
|
21967
21986
|
import { createHash as createHash6, randomUUID as randomUUID3 } from "node:crypto";
|
|
21968
21987
|
import { lstat, mkdir, open, rename } from "node:fs/promises";
|
|
21969
|
-
import { join as
|
|
21988
|
+
import { join as join7 } from "node:path";
|
|
21970
21989
|
var ONESHOT_EVIDENCE_SCHEMA = "kxm.oneshot-evidence.v2";
|
|
21971
21990
|
var RETIRED_ONESHOT_EVIDENCE_SCHEMAS = /* @__PURE__ */ new Set(["kxm.oneshot-evidence.v1"]);
|
|
21972
21991
|
var TEXT_LIMIT = 4 * 1024 * 1024;
|
|
@@ -21996,7 +22015,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
21996
22015
|
throw new Error("oneshot_evidence_root_not_private");
|
|
21997
22016
|
}
|
|
21998
22017
|
const id = `evd_${randomUUID3().replaceAll("-", "")}`;
|
|
21999
|
-
const dir =
|
|
22018
|
+
const dir = join7(root, id);
|
|
22000
22019
|
await mkdir(dir, { mode: 448 });
|
|
22001
22020
|
const secrets = [...new Set(sensitive.filter((value) => value.length >= 8))].sort((a, b) => b.length - a.length);
|
|
22002
22021
|
const redact = (value) => {
|
|
@@ -22016,7 +22035,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
22016
22035
|
const bytes = JSON.stringify(value);
|
|
22017
22036
|
if (Buffer.byteLength(bytes) > RECORD_LIMIT) throw new Error("oneshot_evidence_record_limit");
|
|
22018
22037
|
parseOneShotEvidenceRecord(bytes);
|
|
22019
|
-
const target =
|
|
22038
|
+
const target = join7(dir, name);
|
|
22020
22039
|
const partial = `${target}.partial`;
|
|
22021
22040
|
const file = await open(partial, "wx", 384);
|
|
22022
22041
|
try {
|
|
@@ -22083,8 +22102,8 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
22083
22102
|
// plugins/kxm/src/prices.ts
|
|
22084
22103
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
22085
22104
|
import { createHash as createHash7 } from "node:crypto";
|
|
22086
|
-
import { existsSync as
|
|
22087
|
-
import { join as
|
|
22105
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, statSync } from "node:fs";
|
|
22106
|
+
import { join as join8 } from "node:path";
|
|
22088
22107
|
|
|
22089
22108
|
// plugins/kxm/src/price-calc.ts
|
|
22090
22109
|
var PRICES_SCHEMA = "kxm.prices.v1";
|
|
@@ -22236,8 +22255,8 @@ function parsePriceCatalog(text) {
|
|
|
22236
22255
|
return catalog;
|
|
22237
22256
|
}
|
|
22238
22257
|
function loadPriceCatalog(rootOrPath) {
|
|
22239
|
-
const candidatePath =
|
|
22240
|
-
if (!candidatePath || !
|
|
22258
|
+
const candidatePath = existsSync7(join8(rootOrPath, ".kxm", "prices.yaml")) ? join8(rootOrPath, ".kxm", "prices.yaml") : existsSync7(join8(rootOrPath, "prices.yaml")) ? join8(rootOrPath, "prices.yaml") : existsSync7(rootOrPath) && statSync(rootOrPath).isFile() ? rootOrPath : void 0;
|
|
22259
|
+
if (!candidatePath || !existsSync7(candidatePath)) {
|
|
22241
22260
|
return void 0;
|
|
22242
22261
|
}
|
|
22243
22262
|
const content = readFileSync5(candidatePath, "utf8");
|
|
@@ -22247,28 +22266,28 @@ function loadPriceCatalog(rootOrPath) {
|
|
|
22247
22266
|
// plugins/kxm/src/vnext-engine.ts
|
|
22248
22267
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
22249
22268
|
import { createHash as createHash10, randomBytes, timingSafeEqual } from "node:crypto";
|
|
22250
|
-
import { existsSync as
|
|
22251
|
-
import { join as
|
|
22269
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
|
|
22270
|
+
import { join as join11 } from "node:path";
|
|
22252
22271
|
|
|
22253
22272
|
// plugins/kxm/src/producers.ts
|
|
22254
22273
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
22255
|
-
import { existsSync as
|
|
22256
|
-
import { join as
|
|
22274
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, readdirSync as readdirSync4 } from "node:fs";
|
|
22275
|
+
import { join as join9 } from "node:path";
|
|
22257
22276
|
var empty = () => ({ schema: "kxm.producers.v1", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), promoted: [], demoted: [], enabled: [], disabled: [], roles: {} });
|
|
22258
22277
|
function loadProducerPolicy(root) {
|
|
22259
|
-
const path =
|
|
22260
|
-
if (!
|
|
22278
|
+
const path = join9(root, ".kxm", "producers.yaml");
|
|
22279
|
+
if (!existsSync8(path)) return empty();
|
|
22261
22280
|
const value = (0, import_yaml4.parse)(readFileSync6(path, "utf8"));
|
|
22262
22281
|
if (value?.schema !== "kxm.producers.v1" || !Array.isArray(value.promoted) || !Array.isArray(value.demoted)) throw new Error("invalid .kxm/producers.yaml");
|
|
22263
22282
|
return { schema: "kxm.producers.v1", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), promoted: value.promoted.filter((x) => typeof x === "string"), demoted: value.demoted.filter((x) => typeof x === "string"), enabled: Array.isArray(value.enabled) ? value.enabled.filter((x) => typeof x === "string") : [], disabled: Array.isArray(value.disabled) ? value.disabled.filter((x) => typeof x === "string") : [], roles: value.roles && typeof value.roles === "object" ? Object.fromEntries(Object.entries(value.roles).filter(([, v]) => Array.isArray(v)).map(([k, v]) => [k, v.filter((x) => typeof x === "string")])) : {} };
|
|
22264
22283
|
}
|
|
22265
22284
|
function listRoleBindings(root) {
|
|
22266
|
-
const dir =
|
|
22285
|
+
const dir = join9(root, ".kxm", "roles");
|
|
22267
22286
|
const result = {};
|
|
22268
|
-
if (!
|
|
22287
|
+
if (!existsSync8(dir)) return result;
|
|
22269
22288
|
for (const file of readdirSync4(dir).filter((name) => name.endsWith(".yaml"))) {
|
|
22270
22289
|
const role = file.slice(0, -5);
|
|
22271
|
-
const value = (0, import_yaml4.parse)(readFileSync6(
|
|
22290
|
+
const value = (0, import_yaml4.parse)(readFileSync6(join9(dir, file), "utf8"));
|
|
22272
22291
|
result[role] = (value.roster ?? []).map((entry) => entry.model).filter((model) => typeof model === "string");
|
|
22273
22292
|
}
|
|
22274
22293
|
return result;
|
|
@@ -22539,7 +22558,7 @@ function pruneContextPacket(packet, tokenBudget) {
|
|
|
22539
22558
|
}
|
|
22540
22559
|
|
|
22541
22560
|
// plugins/kxm/src/vnext-engine-artifacts.ts
|
|
22542
|
-
import { join as
|
|
22561
|
+
import { join as join10 } from "node:path";
|
|
22543
22562
|
|
|
22544
22563
|
// plugins/kxm/src/artifacts-exist.ts
|
|
22545
22564
|
import { lstatSync as lstatSync4, realpathSync as realpathSync3, statSync as statSync2 } from "node:fs";
|
|
@@ -22586,14 +22605,14 @@ function verifyArtifactExists(rootInput, pathInput) {
|
|
|
22586
22605
|
// plugins/kxm/src/vnext-engine-artifacts.ts
|
|
22587
22606
|
var vnextArtifactsGateSeams = {};
|
|
22588
22607
|
function evaluateArtifactsGate(context, definition) {
|
|
22589
|
-
const root =
|
|
22608
|
+
const root = join10(context.projectRoot, ".kxm", "assets");
|
|
22590
22609
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22591
22610
|
const startTime = process.hrtime.bigint();
|
|
22592
22611
|
let checkedCount = 0;
|
|
22593
22612
|
let failedCount = 0;
|
|
22594
22613
|
for (const [index, path] of definition.paths.entries()) {
|
|
22595
22614
|
checkedCount += 1;
|
|
22596
|
-
const result = verifyArtifactExists(root,
|
|
22615
|
+
const result = verifyArtifactExists(root, join10(root, path));
|
|
22597
22616
|
if (!result.ok) failedCount += 1;
|
|
22598
22617
|
vnextArtifactsGateSeams.afterPathChecked?.({ path, index, checkedCount, failedCount });
|
|
22599
22618
|
}
|
|
@@ -22738,8 +22757,8 @@ var CommandObserver = class {
|
|
|
22738
22757
|
this.requestStop("error", "lost-close");
|
|
22739
22758
|
}
|
|
22740
22759
|
run() {
|
|
22741
|
-
return new Promise((
|
|
22742
|
-
this.resolveOutcome =
|
|
22760
|
+
return new Promise((resolve6) => {
|
|
22761
|
+
this.resolveOutcome = resolve6;
|
|
22743
22762
|
try {
|
|
22744
22763
|
this.start();
|
|
22745
22764
|
} catch (error) {
|
|
@@ -23940,8 +23959,8 @@ var VnextRunScheduler = class _VnextRunScheduler {
|
|
|
23940
23959
|
resolve: (_value) => void 0,
|
|
23941
23960
|
reject: (_error) => void 0
|
|
23942
23961
|
};
|
|
23943
|
-
const settled = new Promise((
|
|
23944
|
-
pending.resolve =
|
|
23962
|
+
const settled = new Promise((resolve6, reject) => {
|
|
23963
|
+
pending.resolve = resolve6;
|
|
23945
23964
|
pending.reject = reject;
|
|
23946
23965
|
});
|
|
23947
23966
|
void settled.then(void 0, () => void 0);
|
|
@@ -24276,8 +24295,8 @@ function unreconciledPanelAttemptId(state) {
|
|
|
24276
24295
|
}
|
|
24277
24296
|
function resolveProducerRoute(projectRoot, step, agentId) {
|
|
24278
24297
|
let agentModel;
|
|
24279
|
-
const agentFile =
|
|
24280
|
-
if (
|
|
24298
|
+
const agentFile = join11(projectRoot, ".kxm", "agents", `${agentId}.yaml`);
|
|
24299
|
+
if (existsSync9(agentFile)) {
|
|
24281
24300
|
try {
|
|
24282
24301
|
const parsed = (0, import_yaml5.parse)(readFileSync7(agentFile, "utf8"));
|
|
24283
24302
|
if (typeof parsed?.model === "string") {
|
|
@@ -25860,7 +25879,7 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
|
|
|
25860
25879
|
}
|
|
25861
25880
|
const spawnFn = options.spawnProcess ?? defaultSpawn;
|
|
25862
25881
|
const cwd = options.projectRoot ?? process.cwd();
|
|
25863
|
-
const evidence = await beginOneShotEvidence(options.evidenceRoot ??
|
|
25882
|
+
const evidence = await beginOneShotEvidence(options.evidenceRoot ?? join12(vnextUserStateRoot(), "runtime", "oneshot-evidence"), {
|
|
25864
25883
|
runId: request.runId,
|
|
25865
25884
|
stepId: request.stepId,
|
|
25866
25885
|
attemptId: request.attemptId,
|
|
@@ -26004,13 +26023,12 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
|
|
|
26004
26023
|
}
|
|
26005
26024
|
|
|
26006
26025
|
// plugins/kxm/src/vnext-runtime-supervisor.ts
|
|
26007
|
-
var repoRoot = resolve6(fileURLToPath2(new URL("../../../", import.meta.url)));
|
|
26008
26026
|
function vnextSupervisorTokenFile(paths) {
|
|
26009
|
-
return
|
|
26027
|
+
return join13(paths.runtimeDir, "supervisor.token");
|
|
26010
26028
|
}
|
|
26011
26029
|
function publishVnextSupervisorToken(paths, token) {
|
|
26012
26030
|
const file = vnextSupervisorTokenFile(paths);
|
|
26013
|
-
mkdirSync4(
|
|
26031
|
+
mkdirSync4(dirname6(file), { recursive: true, mode: 448 });
|
|
26014
26032
|
const temp = `${file}.${process.pid}.tmp`;
|
|
26015
26033
|
writeFileSync4(temp, `${token}
|
|
26016
26034
|
`, { encoding: "utf8", mode: 384 });
|
|
@@ -26048,11 +26066,11 @@ function processAlive(pid) {
|
|
|
26048
26066
|
var HEARTBEAT_STALE_MS = 15e3;
|
|
26049
26067
|
var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
|
|
26050
26068
|
function supervisorErrorFile(paths) {
|
|
26051
|
-
return
|
|
26069
|
+
return join13(paths.runtimeDir, "supervisor.error");
|
|
26052
26070
|
}
|
|
26053
26071
|
function clearSupervisorError(paths) {
|
|
26054
26072
|
const file = supervisorErrorFile(paths);
|
|
26055
|
-
if (
|
|
26073
|
+
if (existsSync10(file)) rmSync(file, { force: true });
|
|
26056
26074
|
}
|
|
26057
26075
|
function recordSupervisorError(paths, message) {
|
|
26058
26076
|
try {
|
|
@@ -26075,7 +26093,7 @@ function readRecentSupervisorError(paths) {
|
|
|
26075
26093
|
}
|
|
26076
26094
|
}
|
|
26077
26095
|
function vnextSupervisorStatus(paths) {
|
|
26078
|
-
if (!
|
|
26096
|
+
if (!existsSync10(paths.registryDb)) return { running: false };
|
|
26079
26097
|
const registry = new VnextRuntimeRegistry(paths.registryDb);
|
|
26080
26098
|
try {
|
|
26081
26099
|
const record2 = registry.supervisor();
|
|
@@ -26136,7 +26154,7 @@ async function ensureVnextSupervisor(options = {}) {
|
|
|
26136
26154
|
throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
|
|
26137
26155
|
}
|
|
26138
26156
|
clearSupervisorError(paths);
|
|
26139
|
-
const scriptPath =
|
|
26157
|
+
const scriptPath = join13(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
|
|
26140
26158
|
const spawnImpl = options.spawnImpl ?? ((script, env) => {
|
|
26141
26159
|
const child = spawn3(process.execPath, [script], {
|
|
26142
26160
|
detached: true,
|
|
@@ -26221,8 +26239,8 @@ async function waitForDriveSessions(settled, graceMs) {
|
|
|
26221
26239
|
try {
|
|
26222
26240
|
await Promise.race([
|
|
26223
26241
|
Promise.allSettled(settled),
|
|
26224
|
-
new Promise((
|
|
26225
|
-
timeout = setTimeout(
|
|
26242
|
+
new Promise((resolve6) => {
|
|
26243
|
+
timeout = setTimeout(resolve6, graceMs);
|
|
26226
26244
|
timeout.unref?.();
|
|
26227
26245
|
})
|
|
26228
26246
|
]);
|