@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
|
@@ -2986,7 +2986,7 @@ var require_compile = __commonJS({
|
|
|
2986
2986
|
const schOrFunc = root.refs[ref];
|
|
2987
2987
|
if (schOrFunc)
|
|
2988
2988
|
return schOrFunc;
|
|
2989
|
-
let _sch =
|
|
2989
|
+
let _sch = resolve8.call(this, root, ref);
|
|
2990
2990
|
if (_sch === void 0) {
|
|
2991
2991
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2992
2992
|
const { schemaId } = this.opts;
|
|
@@ -3013,7 +3013,7 @@ var require_compile = __commonJS({
|
|
|
3013
3013
|
function sameSchemaEnv(s1, s2) {
|
|
3014
3014
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3015
3015
|
}
|
|
3016
|
-
function
|
|
3016
|
+
function resolve8(root, ref) {
|
|
3017
3017
|
let sch;
|
|
3018
3018
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3019
3019
|
ref = sch;
|
|
@@ -3838,7 +3838,7 @@ var require_fast_uri = __commonJS({
|
|
|
3838
3838
|
}
|
|
3839
3839
|
return uri;
|
|
3840
3840
|
}
|
|
3841
|
-
function
|
|
3841
|
+
function resolve8(baseURI, relativeURI, options) {
|
|
3842
3842
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3843
3843
|
const {
|
|
3844
3844
|
parsed: baseParsed,
|
|
@@ -4200,7 +4200,7 @@ var require_fast_uri = __commonJS({
|
|
|
4200
4200
|
var fastUri = {
|
|
4201
4201
|
SCHEMES,
|
|
4202
4202
|
normalize,
|
|
4203
|
-
resolve:
|
|
4203
|
+
resolve: resolve8,
|
|
4204
4204
|
resolveComponent,
|
|
4205
4205
|
equal,
|
|
4206
4206
|
serialize,
|
|
@@ -14779,16 +14779,15 @@ var require_dist = __commonJS({
|
|
|
14779
14779
|
|
|
14780
14780
|
// plugins/kxm/src/vnext-runtime.ts
|
|
14781
14781
|
import { createHash as createHash6 } from "node:crypto";
|
|
14782
|
-
import { existsSync as
|
|
14783
|
-
import { join as
|
|
14782
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync4 } from "node:fs";
|
|
14783
|
+
import { join as join6 } from "node:path";
|
|
14784
14784
|
|
|
14785
14785
|
// plugins/kxm/src/vnext-config.ts
|
|
14786
14786
|
var import__ = __toESM(require__(), 1);
|
|
14787
14787
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
14788
14788
|
import { createHash as createHash2 } from "node:crypto";
|
|
14789
|
-
import { existsSync as
|
|
14790
|
-
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
14791
|
-
import { fileURLToPath } from "node:url";
|
|
14789
|
+
import { existsSync as existsSync3, lstatSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
14790
|
+
import { basename, dirname as dirname2, extname, isAbsolute, join as join2, relative, resolve, sep } from "node:path";
|
|
14792
14791
|
|
|
14793
14792
|
// plugins/kxm/src/restricted-yaml.mjs
|
|
14794
14793
|
var import_yaml = __toESM(require_dist(), 1);
|
|
@@ -15114,9 +15113,28 @@ function resolveVnextTemplateBaseline(value) {
|
|
|
15114
15113
|
return void 0;
|
|
15115
15114
|
}
|
|
15116
15115
|
|
|
15116
|
+
// plugins/kxm/src/repo-root.ts
|
|
15117
|
+
import { existsSync } from "node:fs";
|
|
15118
|
+
import { dirname, join } from "node:path";
|
|
15119
|
+
import { fileURLToPath } from "node:url";
|
|
15120
|
+
var ROOT_MARKERS = ["scripts/kxm-hub.mjs", "scripts/kxm.mjs"];
|
|
15121
|
+
var MAX_WALK_DEPTH = 10;
|
|
15122
|
+
function findKxmRepoRoot(fromUrl = import.meta.url) {
|
|
15123
|
+
let dir = dirname(fileURLToPath(fromUrl));
|
|
15124
|
+
for (let depth = 0; depth < MAX_WALK_DEPTH; depth += 1) {
|
|
15125
|
+
if (ROOT_MARKERS.some((marker) => existsSync(join(dir, marker)))) return dir;
|
|
15126
|
+
const parent = dirname(dir);
|
|
15127
|
+
if (parent === dir) break;
|
|
15128
|
+
dir = parent;
|
|
15129
|
+
}
|
|
15130
|
+
throw new Error(
|
|
15131
|
+
`kxm: cannot locate the KXM repo root from ${fileURLToPath(fromUrl)} (walked ${MAX_WALK_DEPTH} levels looking for ${ROOT_MARKERS[0]})`
|
|
15132
|
+
);
|
|
15133
|
+
}
|
|
15134
|
+
|
|
15117
15135
|
// plugins/kxm/src/vnext-harness.ts
|
|
15118
15136
|
import { spawnSync } from "node:child_process";
|
|
15119
|
-
import { existsSync } from "node:fs";
|
|
15137
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
15120
15138
|
import { win32 as win32Path } from "node:path";
|
|
15121
15139
|
|
|
15122
15140
|
// plugins/kxm/src/vnext-oneshot-process.ts
|
|
@@ -15142,7 +15160,7 @@ function defaultSpawn(command, args, options) {
|
|
|
15142
15160
|
if (options.signal?.aborted) {
|
|
15143
15161
|
return Promise.resolve({ stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") });
|
|
15144
15162
|
}
|
|
15145
|
-
return new Promise((
|
|
15163
|
+
return new Promise((resolve8) => {
|
|
15146
15164
|
const stdout = [];
|
|
15147
15165
|
const stderr = [];
|
|
15148
15166
|
let outputBytes = 0;
|
|
@@ -15173,7 +15191,7 @@ function defaultSpawn(command, args, options) {
|
|
|
15173
15191
|
const started = Boolean(child?.pid);
|
|
15174
15192
|
if (started && !observedChildExit) error ??= new Error("process_exit_unobserved");
|
|
15175
15193
|
const unverifiedDescendants = stopping || started && !observedChildExit;
|
|
15176
|
-
|
|
15194
|
+
resolve8({
|
|
15177
15195
|
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
15178
15196
|
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
15179
15197
|
code,
|
|
@@ -15665,7 +15683,7 @@ function findWinNpmInnerExe(cliId, options = {}) {
|
|
|
15665
15683
|
if ((options.platform ?? process.platform) !== "win32") return void 0;
|
|
15666
15684
|
const segments = WIN_NPM_INNER_EXE[cliId];
|
|
15667
15685
|
if (!segments) return void 0;
|
|
15668
|
-
const exists = options.existsSync ??
|
|
15686
|
+
const exists = options.existsSync ?? existsSync2;
|
|
15669
15687
|
const pathEnv = options.pathEnv ?? process.env.PATH ?? "";
|
|
15670
15688
|
for (const dir of pathEnv.split(";").filter(Boolean)) {
|
|
15671
15689
|
if (!exists(win32Path.join(dir, `${cliId}.cmd`))) continue;
|
|
@@ -16348,8 +16366,10 @@ var VnextConfigError = class extends Error {
|
|
|
16348
16366
|
this.issues = sorted;
|
|
16349
16367
|
}
|
|
16350
16368
|
};
|
|
16351
|
-
|
|
16352
|
-
|
|
16369
|
+
function defaultVnextSchemaDir() {
|
|
16370
|
+
return join2(findKxmRepoRoot(import.meta.url), "schemas", "vnext");
|
|
16371
|
+
}
|
|
16372
|
+
var DEFAULT_SCHEMA_DIR = defaultVnextSchemaDir();
|
|
16353
16373
|
var RESOURCE_SCHEMA = Object.freeze({
|
|
16354
16374
|
project: { identity: "kxm.project.v1", file: "project.schema.json" },
|
|
16355
16375
|
repository: { identity: "kxm.repository.v1", file: "repository.schema.json" },
|
|
@@ -16414,10 +16434,10 @@ var VnextSchemaRegistry = class {
|
|
|
16414
16434
|
constructor(schemasDir = DEFAULT_SCHEMA_DIR) {
|
|
16415
16435
|
this.schemasDir = resolve(schemasDir);
|
|
16416
16436
|
this.ajv = new import__.Ajv2020({ allErrors: true, strict: true, strictRequired: false });
|
|
16417
|
-
const common = readJsonObject(
|
|
16437
|
+
const common = readJsonObject(join2(this.schemasDir, "common.schema.json"));
|
|
16418
16438
|
this.ajv.addSchema(common);
|
|
16419
16439
|
for (const definition of Object.values(RESOURCE_SCHEMA)) {
|
|
16420
|
-
this.ajv.addSchema(readJsonObject(
|
|
16440
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, definition.file)));
|
|
16421
16441
|
}
|
|
16422
16442
|
const localBindingsFile = "local-repository-bindings.schema.json";
|
|
16423
16443
|
const templateProvenanceFile = "template-provenance.schema.json";
|
|
@@ -16427,14 +16447,14 @@ var VnextSchemaRegistry = class {
|
|
|
16427
16447
|
const migrationReceiptFile = "migration-receipt.schema.json";
|
|
16428
16448
|
const permissionDiffFile = "permission-diff.schema.json";
|
|
16429
16449
|
const runEventFile = "run-event.schema.json";
|
|
16430
|
-
this.ajv.addSchema(readJsonObject(
|
|
16431
|
-
this.ajv.addSchema(readJsonObject(
|
|
16432
|
-
this.ajv.addSchema(readJsonObject(
|
|
16433
|
-
this.ajv.addSchema(readJsonObject(
|
|
16434
|
-
this.ajv.addSchema(readJsonObject(
|
|
16435
|
-
this.ajv.addSchema(readJsonObject(
|
|
16436
|
-
this.ajv.addSchema(readJsonObject(
|
|
16437
|
-
this.ajv.addSchema(readJsonObject(
|
|
16450
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, localBindingsFile)));
|
|
16451
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, templateProvenanceFile)));
|
|
16452
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, initOperationFile)));
|
|
16453
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationPlanFile)));
|
|
16454
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationDecisionFile)));
|
|
16455
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationReceiptFile)));
|
|
16456
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, permissionDiffFile)));
|
|
16457
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, runEventFile)));
|
|
16438
16458
|
for (const [kind, definition] of Object.entries(RESOURCE_SCHEMA)) {
|
|
16439
16459
|
const validator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${definition.file}`);
|
|
16440
16460
|
if (!validator) throw new Error(`schema did not compile: ${definition.file}`);
|
|
@@ -16541,15 +16561,15 @@ function containedHostPath(root, candidate) {
|
|
|
16541
16561
|
function portableBindingIssue(root, pathHint, repositoryId) {
|
|
16542
16562
|
let current = root;
|
|
16543
16563
|
for (const segment of pathHint === "." ? [] : pathHint.split("/")) {
|
|
16544
|
-
current =
|
|
16545
|
-
if (!
|
|
16564
|
+
current = join2(current, segment);
|
|
16565
|
+
if (!existsSync3(current)) break;
|
|
16546
16566
|
const stat = lstatSync(current);
|
|
16547
16567
|
if (stat.isSymbolicLink()) {
|
|
16548
16568
|
return issue2("path", "repository_binding_path_link", ".kxm/project.yaml", `portable pathHint for ${repositoryId} traverses a symbolic link or junction`);
|
|
16549
16569
|
}
|
|
16550
16570
|
}
|
|
16551
16571
|
const binding = resolve(root, ...pathHint.split("/"));
|
|
16552
|
-
if (
|
|
16572
|
+
if (existsSync3(binding)) {
|
|
16553
16573
|
const realRoot = canonicalHostPath(root);
|
|
16554
16574
|
const realBinding = canonicalHostPath(binding);
|
|
16555
16575
|
if (!containedHostPath(realRoot, realBinding)) {
|
|
@@ -16587,9 +16607,9 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
|
|
|
16587
16607
|
}
|
|
16588
16608
|
if (stat.isSymbolicLink()) fail2("path", "resource_symlink", label, "configuration resources must not be symbolic links");
|
|
16589
16609
|
const boundary = resolve(containmentRoot);
|
|
16590
|
-
let parent =
|
|
16610
|
+
let parent = dirname2(file);
|
|
16591
16611
|
while (parent !== boundary) {
|
|
16592
|
-
if (parent ===
|
|
16612
|
+
if (parent === dirname2(parent)) fail2("path", "resource_outside_project", label, "resource escapes the project root");
|
|
16593
16613
|
let parentStat;
|
|
16594
16614
|
try {
|
|
16595
16615
|
parentStat = lstatSync(parent);
|
|
@@ -16597,7 +16617,7 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
|
|
|
16597
16617
|
fail2("discovery", "resource_parent_missing", label, "resource parent does not exist");
|
|
16598
16618
|
}
|
|
16599
16619
|
if (parentStat.isSymbolicLink()) fail2("path", "resource_parent_symlink", label, "configuration resource parents must not be symbolic links");
|
|
16600
|
-
parent =
|
|
16620
|
+
parent = dirname2(parent);
|
|
16601
16621
|
}
|
|
16602
16622
|
if (!stat.isFile()) fail2("path", "resource_not_file", label, "configuration resource must be a regular file");
|
|
16603
16623
|
const value = parseRestrictedYaml2(readFileSync(file), label);
|
|
@@ -16606,22 +16626,22 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
|
|
|
16606
16626
|
return { kind, ...id === void 0 ? {} : { id }, file, logicalPath, value };
|
|
16607
16627
|
}
|
|
16608
16628
|
function readTemplateProvenance(registry, root) {
|
|
16609
|
-
const file =
|
|
16610
|
-
if (!
|
|
16629
|
+
const file = join2(root, ".kxm", "template-provenance.yaml");
|
|
16630
|
+
if (!existsSync3(file)) return void 0;
|
|
16611
16631
|
const label = ".kxm/template-provenance.yaml";
|
|
16612
16632
|
const stat = lstatSync(file);
|
|
16613
16633
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
16614
16634
|
fail2("path", "resource_not_file", label, "template provenance must be a regular file, not a link or directory");
|
|
16615
16635
|
}
|
|
16616
|
-
const configRoot =
|
|
16617
|
-
let parent =
|
|
16636
|
+
const configRoot = join2(root, ".kxm");
|
|
16637
|
+
let parent = dirname2(file);
|
|
16618
16638
|
while (parent !== root) {
|
|
16619
16639
|
const parentStat = lstatSync(parent);
|
|
16620
16640
|
if (parentStat.isSymbolicLink() || !parentStat.isDirectory()) {
|
|
16621
16641
|
fail2("path", "resource_parent_symlink", label, "template provenance parents must be regular directories");
|
|
16622
16642
|
}
|
|
16623
16643
|
if (parent === configRoot) break;
|
|
16624
|
-
parent =
|
|
16644
|
+
parent = dirname2(parent);
|
|
16625
16645
|
}
|
|
16626
16646
|
const value = parseRestrictedYaml2(readFileSync(file), label);
|
|
16627
16647
|
const issues = registry.validateTemplateProvenance(value, label);
|
|
@@ -16654,7 +16674,7 @@ function readTemplateProvenance(registry, root) {
|
|
|
16654
16674
|
}
|
|
16655
16675
|
function listNamedResources(registry, root, directory, logicalDirectory, kind) {
|
|
16656
16676
|
const resources = /* @__PURE__ */ new Map();
|
|
16657
|
-
if (!
|
|
16677
|
+
if (!existsSync3(directory)) return resources;
|
|
16658
16678
|
const stat = lstatSync(directory);
|
|
16659
16679
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
16660
16680
|
fail2("path", "resource_directory_invalid", displayPath(root, directory), "resource directory must be a regular directory");
|
|
@@ -16663,27 +16683,27 @@ function listNamedResources(registry, root, directory, logicalDirectory, kind) {
|
|
|
16663
16683
|
const entries = readdirSync(directory, { withFileTypes: true }).sort((left, right) => compareCodeUnits3(left.name, right.name));
|
|
16664
16684
|
for (const entry of entries) {
|
|
16665
16685
|
if (entry.isDirectory()) {
|
|
16666
|
-
issues.push(issue2("path", "nested_resource_directory", displayPath(root,
|
|
16686
|
+
issues.push(issue2("path", "nested_resource_directory", displayPath(root, join2(directory, entry.name)), "nested resource directories are not allowed"));
|
|
16667
16687
|
continue;
|
|
16668
16688
|
}
|
|
16669
16689
|
if (!entry.name.toLowerCase().endsWith(".yaml") && !entry.name.toLowerCase().endsWith(".yml")) continue;
|
|
16670
16690
|
if (!entry.isFile() || extname(entry.name) !== ".yaml") {
|
|
16671
|
-
issues.push(issue2("path", "resource_filename_invalid", displayPath(root,
|
|
16691
|
+
issues.push(issue2("path", "resource_filename_invalid", displayPath(root, join2(directory, entry.name)), "resource must be a regular file with the exact .yaml extension"));
|
|
16672
16692
|
continue;
|
|
16673
16693
|
}
|
|
16674
16694
|
const id = basename(entry.name, ".yaml");
|
|
16675
16695
|
if (kind === "model" && id === "inventory") continue;
|
|
16676
16696
|
if (!resourceIdentifier(id)) {
|
|
16677
|
-
issues.push(issue2("path", "resource_id_invalid", displayPath(root,
|
|
16697
|
+
issues.push(issue2("path", "resource_id_invalid", displayPath(root, join2(directory, entry.name)), `filename-derived identity ${id} is invalid or platform-reserved`));
|
|
16678
16698
|
continue;
|
|
16679
16699
|
}
|
|
16680
16700
|
const collision = [...resources.keys()].find((candidate) => candidate.toLocaleLowerCase("en-US") === id.toLocaleLowerCase("en-US"));
|
|
16681
16701
|
if (collision) {
|
|
16682
|
-
issues.push(issue2("path", "resource_id_collision", displayPath(root,
|
|
16702
|
+
issues.push(issue2("path", "resource_id_collision", displayPath(root, join2(directory, entry.name)), `${id} case-folds to existing ${collision}`));
|
|
16683
16703
|
continue;
|
|
16684
16704
|
}
|
|
16685
16705
|
try {
|
|
16686
|
-
const resource = readResource(registry, root,
|
|
16706
|
+
const resource = readResource(registry, root, join2(directory, entry.name), `${logicalDirectory}/${id}.yaml`, kind, id);
|
|
16687
16707
|
resources.set(id, resource);
|
|
16688
16708
|
} catch (error) {
|
|
16689
16709
|
if (error instanceof VnextConfigError) issues.push(...error.issues);
|
|
@@ -16975,8 +16995,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
16975
16995
|
const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
|
|
16976
16996
|
if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
|
|
16977
16997
|
}
|
|
16978
|
-
const
|
|
16979
|
-
const minimumPassed =
|
|
16998
|
+
const join18 = objectValue(step.join);
|
|
16999
|
+
const minimumPassed = join18 && typeof join18.minimumPassed === "number" ? join18.minimumPassed : void 0;
|
|
16980
17000
|
if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
|
|
16981
17001
|
const distinctBy = names(assignment?.distinctBy);
|
|
16982
17002
|
if (distinctBy.length > 0) {
|
|
@@ -17190,9 +17210,9 @@ function validateBundle(project, repositories, agents, models, workflows, enviro
|
|
|
17190
17210
|
if (!workflows.has(defaultWorkflow)) issues.push(issue2("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
|
|
17191
17211
|
for (const workflow of workflows.values()) validateWorkflow(workflow, agents, models, repositoryIds, gates, issues);
|
|
17192
17212
|
if (projectRoot) {
|
|
17193
|
-
const writerRolePath =
|
|
17213
|
+
const writerRolePath = join2(projectRoot, ".kxm", "roles", "writer.yaml");
|
|
17194
17214
|
const implementerAgent = agents.get("implementer") ?? agents.get("writer");
|
|
17195
|
-
if (
|
|
17215
|
+
if (existsSync3(writerRolePath) && implementerAgent) {
|
|
17196
17216
|
try {
|
|
17197
17217
|
const rawRole = parseRestrictedYaml2(readFileSync(writerRolePath, "utf8"));
|
|
17198
17218
|
const roleObj = objectValue(rawRole);
|
|
@@ -17241,7 +17261,7 @@ function gitEnvironment() {
|
|
|
17241
17261
|
}
|
|
17242
17262
|
function discoverGitRoot(start = process.cwd()) {
|
|
17243
17263
|
let current = resolve(start);
|
|
17244
|
-
if (
|
|
17264
|
+
if (existsSync3(current) && !lstatSync(current).isDirectory()) current = dirname2(current);
|
|
17245
17265
|
const result = spawnSync2("git", ["-C", current, "rev-parse", "--show-toplevel"], {
|
|
17246
17266
|
encoding: "utf8",
|
|
17247
17267
|
env: gitEnvironment(),
|
|
@@ -17250,7 +17270,7 @@ function discoverGitRoot(start = process.cwd()) {
|
|
|
17250
17270
|
});
|
|
17251
17271
|
if (result.status !== 0 || result.error || !result.stdout.trim()) return void 0;
|
|
17252
17272
|
const root = resolve(result.stdout.trim());
|
|
17253
|
-
return
|
|
17273
|
+
return existsSync3(root) && lstatSync(root).isDirectory() ? root : void 0;
|
|
17254
17274
|
}
|
|
17255
17275
|
function assertNoRegisteredGates(options) {
|
|
17256
17276
|
if ("registeredGates" in options) {
|
|
@@ -17267,7 +17287,7 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17267
17287
|
migrationReceipt = receiptCheck.receipt;
|
|
17268
17288
|
}
|
|
17269
17289
|
const registry = new VnextSchemaRegistry(options.schemasDir);
|
|
17270
|
-
const project = readResource(registry, root,
|
|
17290
|
+
const project = readResource(registry, root, join2(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
|
|
17271
17291
|
const earlyIssues = [];
|
|
17272
17292
|
validatePortablePaths(project, earlyIssues);
|
|
17273
17293
|
const templateProvenance = readTemplateProvenance(registry, root);
|
|
@@ -17289,16 +17309,16 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17289
17309
|
}
|
|
17290
17310
|
}
|
|
17291
17311
|
if (earlyIssues.length > 0) throw new VnextConfigError(earlyIssues);
|
|
17292
|
-
const agents = listNamedResources(registry, root,
|
|
17293
|
-
const models = listNamedResources(registry, root,
|
|
17294
|
-
const workflows = listNamedResources(registry, root,
|
|
17295
|
-
const gatePath =
|
|
17296
|
-
const gateRegistry =
|
|
17312
|
+
const agents = listNamedResources(registry, root, join2(root, ".kxm", "agents"), ".kxm/agents", "agent");
|
|
17313
|
+
const models = listNamedResources(registry, root, join2(root, ".kxm", "models"), ".kxm/models", "model");
|
|
17314
|
+
const workflows = listNamedResources(registry, root, join2(root, ".kxm", "workflows"), ".kxm/workflows", "workflow");
|
|
17315
|
+
const gatePath = join2(root, ".kxm", "gates.yaml");
|
|
17316
|
+
const gateRegistry = existsSync3(gatePath) ? readResource(registry, root, gatePath, ".kxm/gates.yaml", "gate-registry") : void 0;
|
|
17297
17317
|
const environments = [];
|
|
17298
17318
|
const repositories = /* @__PURE__ */ new Map();
|
|
17299
17319
|
const loadIssues = [];
|
|
17300
|
-
const projectEnvironment =
|
|
17301
|
-
if (
|
|
17320
|
+
const projectEnvironment = join2(root, ".kxm", "project", "env.yaml");
|
|
17321
|
+
if (existsSync3(projectEnvironment)) {
|
|
17302
17322
|
try {
|
|
17303
17323
|
environments.push(readResource(registry, root, projectEnvironment, ".kxm/project/env.yaml", "environment"));
|
|
17304
17324
|
} catch (error) {
|
|
@@ -17340,7 +17360,7 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17340
17360
|
if (required) loadIssues.push(issue2("discovery", "repository_binding_missing", ".kxm/project.yaml", `required repository ${repositoryId} has no portable pathHint or host-local binding`));
|
|
17341
17361
|
continue;
|
|
17342
17362
|
}
|
|
17343
|
-
if (!
|
|
17363
|
+
if (!existsSync3(binding)) {
|
|
17344
17364
|
if (required || hasLocalBinding) loadIssues.push(issue2("discovery", "repository_binding_unavailable", ".kxm/project.yaml", `${hasLocalBinding ? "explicit" : "required"} repository binding ${repositoryId} is unavailable`));
|
|
17345
17365
|
continue;
|
|
17346
17366
|
}
|
|
@@ -17363,9 +17383,9 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17363
17383
|
continue;
|
|
17364
17384
|
}
|
|
17365
17385
|
seenBindings.set(foldedBinding, repositoryId);
|
|
17366
|
-
const repositoryFile =
|
|
17386
|
+
const repositoryFile = join2(binding, ".kxm", "repo", "repo.yaml");
|
|
17367
17387
|
let definitionValidated = false;
|
|
17368
|
-
if (
|
|
17388
|
+
if (existsSync3(repositoryFile)) {
|
|
17369
17389
|
try {
|
|
17370
17390
|
const resource = readResource(registry, root, repositoryFile, `.kxm/repositories/${repositoryId}/repo.yaml`, "repository", repositoryId, binding);
|
|
17371
17391
|
if (resource.value.repositoryId !== repositoryId) {
|
|
@@ -17381,8 +17401,8 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17381
17401
|
} else if (required || hasLocalBinding) {
|
|
17382
17402
|
loadIssues.push(issue2("discovery", "repository_definition_missing", `.kxm/repositories/${repositoryId}/repo.yaml`, `${hasLocalBinding ? "explicit" : "required"} repository ${repositoryId} has no repo.yaml`));
|
|
17383
17403
|
}
|
|
17384
|
-
const environmentFile =
|
|
17385
|
-
if (
|
|
17404
|
+
const environmentFile = join2(binding, ".kxm", "repo", "env.yaml");
|
|
17405
|
+
if (existsSync3(environmentFile)) {
|
|
17386
17406
|
if (!definitionValidated) {
|
|
17387
17407
|
loadIssues.push(issue2("reference", "repository_environment_without_definition", `.kxm/repositories/${repositoryId}/env.yaml`, `repository ${repositoryId} environment requires a validated matching repo.yaml`));
|
|
17388
17408
|
} else {
|
|
@@ -17419,14 +17439,14 @@ var LEGACY_CONFIG_FILES = [".kxm/config/agents.json", ".kxm/config/gates.json"];
|
|
|
17419
17439
|
function legacyConfigFilesAt(root) {
|
|
17420
17440
|
const files = [];
|
|
17421
17441
|
for (const component of [".kxm", ".kxm/config"]) {
|
|
17422
|
-
const absolute =
|
|
17423
|
-
if (
|
|
17442
|
+
const absolute = join2(root, ...component.split("/"));
|
|
17443
|
+
if (existsSync3(absolute) && lstatSync(absolute).isSymbolicLink()) return [component];
|
|
17424
17444
|
}
|
|
17425
17445
|
for (const candidate of LEGACY_CONFIG_FILES) {
|
|
17426
|
-
if (
|
|
17446
|
+
if (existsSync3(join2(root, ...candidate.split("/")))) files.push(candidate);
|
|
17427
17447
|
}
|
|
17428
|
-
const workflowsDir =
|
|
17429
|
-
if (
|
|
17448
|
+
const workflowsDir = join2(root, ".kxm", "config", "workflows");
|
|
17449
|
+
if (existsSync3(workflowsDir)) {
|
|
17430
17450
|
const stat = lstatSync(workflowsDir);
|
|
17431
17451
|
if (stat.isSymbolicLink()) {
|
|
17432
17452
|
files.push(".kxm/config/workflows");
|
|
@@ -17441,8 +17461,8 @@ function legacyConfigFilesAt(root) {
|
|
|
17441
17461
|
return files;
|
|
17442
17462
|
}
|
|
17443
17463
|
function hashFileRecord(root, relativePath) {
|
|
17444
|
-
const absolute =
|
|
17445
|
-
if (!
|
|
17464
|
+
const absolute = join2(root, ...relativePath.split("/"));
|
|
17465
|
+
if (!existsSync3(absolute)) return void 0;
|
|
17446
17466
|
const bytes = readFileSync(absolute);
|
|
17447
17467
|
return {
|
|
17448
17468
|
path: relativePath,
|
|
@@ -17455,9 +17475,9 @@ function migrationReceiptSelfHash(receipt) {
|
|
|
17455
17475
|
return `sha256:${createHash2("sha256").update(vnextCanonicalJson(unsigned), "utf8").digest("hex")}`;
|
|
17456
17476
|
}
|
|
17457
17477
|
function readVnextMigrationReceipt(root, options = {}) {
|
|
17458
|
-
const receiptPath =
|
|
17478
|
+
const receiptPath = join2(root, ...VNEXT_MIGRATION_RECEIPT_PATH.split("/"));
|
|
17459
17479
|
const legacyFiles = legacyConfigFilesAt(root);
|
|
17460
|
-
if (!
|
|
17480
|
+
if (!existsSync3(receiptPath)) {
|
|
17461
17481
|
return {
|
|
17462
17482
|
issues: legacyFiles.map((file) => issue2("semantic", "legacy_vnext_conflict", file, "legacy and vNext configuration cannot coexist before an accepted migration receipt"))
|
|
17463
17483
|
};
|
|
@@ -17503,8 +17523,8 @@ function readVnextMigrationReceipt(root, options = {}) {
|
|
|
17503
17523
|
|
|
17504
17524
|
// plugins/kxm/src/vnext-runtime-store.ts
|
|
17505
17525
|
import { createHash as createHash4, randomUUID } from "node:crypto";
|
|
17506
|
-
import { existsSync as
|
|
17507
|
-
import { dirname as
|
|
17526
|
+
import { existsSync as existsSync5, lstatSync as lstatSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
17527
|
+
import { dirname as dirname5, join as join5, resolve as resolve4 } from "node:path";
|
|
17508
17528
|
|
|
17509
17529
|
// plugins/kxm/src/vnext-bindings.ts
|
|
17510
17530
|
import { homedir } from "node:os";
|
|
@@ -17549,7 +17569,7 @@ var DatabaseSync = class {
|
|
|
17549
17569
|
};
|
|
17550
17570
|
|
|
17551
17571
|
// plugins/kxm/src/vnext-bindings.ts
|
|
17552
|
-
import { dirname as
|
|
17572
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, parse, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
17553
17573
|
var MAX_BINDING_RECORD_BYTES = 256 * 1024;
|
|
17554
17574
|
var BINDING_LABEL = "Runtime-local repository bindings";
|
|
17555
17575
|
function bindingIssue(phase, code, message) {
|
|
@@ -17569,12 +17589,12 @@ function vnextUserStateRoot(options = {}) {
|
|
|
17569
17589
|
}
|
|
17570
17590
|
if (platform === "win32") {
|
|
17571
17591
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
17572
|
-
const base2 = localAppData && isAbsolute2(localAppData) ? localAppData :
|
|
17592
|
+
const base2 = localAppData && isAbsolute2(localAppData) ? localAppData : join3(home, "AppData", "Local");
|
|
17573
17593
|
return resolve2(base2, "KXM");
|
|
17574
17594
|
}
|
|
17575
17595
|
if (platform === "darwin") return resolve2(home, "Library", "Application Support", "KXM");
|
|
17576
17596
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
17577
|
-
const base = xdgState && isAbsolute2(xdgState) ? xdgState :
|
|
17597
|
+
const base = xdgState && isAbsolute2(xdgState) ? xdgState : join3(home, ".local", "state");
|
|
17578
17598
|
return resolve2(base, "kxm");
|
|
17579
17599
|
}
|
|
17580
17600
|
|
|
@@ -17583,7 +17603,7 @@ import { createHash as createHash3, randomBytes } from "node:crypto";
|
|
|
17583
17603
|
import {
|
|
17584
17604
|
chmodSync,
|
|
17585
17605
|
copyFileSync,
|
|
17586
|
-
existsSync as
|
|
17606
|
+
existsSync as existsSync4,
|
|
17587
17607
|
lstatSync as lstatSync2,
|
|
17588
17608
|
mkdirSync,
|
|
17589
17609
|
readdirSync as readdirSync2,
|
|
@@ -17591,14 +17611,14 @@ import {
|
|
|
17591
17611
|
unlinkSync,
|
|
17592
17612
|
writeFileSync
|
|
17593
17613
|
} from "node:fs";
|
|
17594
|
-
import { basename as basename2, dirname as
|
|
17614
|
+
import { basename as basename2, dirname as dirname4, join as join4, resolve as resolve3 } from "node:path";
|
|
17595
17615
|
function databaseError(code, file, message) {
|
|
17596
17616
|
const issue3 = { phase: "semantic", code, file, message };
|
|
17597
17617
|
return new VnextConfigError([issue3]);
|
|
17598
17618
|
}
|
|
17599
17619
|
function checkedParent(path, description) {
|
|
17600
|
-
const parent =
|
|
17601
|
-
if (!
|
|
17620
|
+
const parent = dirname4(path);
|
|
17621
|
+
if (!existsSync4(parent)) mkdirSync(parent, { recursive: true, mode: 448 });
|
|
17602
17622
|
const stat = lstatSync2(parent, { throwIfNoEntry: false });
|
|
17603
17623
|
if (!stat || stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
17604
17624
|
throw databaseError("runtime_path_invalid", description, `${description} parent must be a regular directory, not a link`);
|
|
@@ -17772,7 +17792,7 @@ function backupDatabaseFile(sourcePath, targetPath, storeId) {
|
|
|
17772
17792
|
throw databaseError("runtime_path_invalid", resolvedSource, `source database ${resolvedSource} must be a regular file, not a link or directory`);
|
|
17773
17793
|
}
|
|
17774
17794
|
checkedParent(resolvedTarget, "backup target");
|
|
17775
|
-
if (
|
|
17795
|
+
if (existsSync4(resolvedTarget)) {
|
|
17776
17796
|
unlinkSync(resolvedTarget);
|
|
17777
17797
|
}
|
|
17778
17798
|
const sourceDb = new DatabaseSync(resolvedSource);
|
|
@@ -17850,7 +17870,7 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
|
|
|
17850
17870
|
}
|
|
17851
17871
|
checkedParent(resolvedTarget, "restore target");
|
|
17852
17872
|
for (const file of [resolvedTarget, `${resolvedTarget}-wal`, `${resolvedTarget}-shm`]) {
|
|
17853
|
-
if (
|
|
17873
|
+
if (existsSync4(file)) {
|
|
17854
17874
|
try {
|
|
17855
17875
|
unlinkSync(file);
|
|
17856
17876
|
} catch {
|
|
@@ -17882,27 +17902,27 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
|
|
|
17882
17902
|
function discoverProjectStores(projectRoot, options = {}) {
|
|
17883
17903
|
const root = resolve3(projectRoot);
|
|
17884
17904
|
const stores = [];
|
|
17885
|
-
const hubPath = options.hubDataPath ? resolve3(options.hubDataPath) :
|
|
17886
|
-
if (
|
|
17905
|
+
const hubPath = options.hubDataPath ? resolve3(options.hubDataPath) : join4(root, ".kxm", "state", "kxm.db");
|
|
17906
|
+
if (existsSync4(hubPath)) {
|
|
17887
17907
|
stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: 3 });
|
|
17888
17908
|
}
|
|
17889
|
-
const registryPath =
|
|
17890
|
-
if (
|
|
17909
|
+
const registryPath = join4(root, ".kxm", "runtime", "registry.db");
|
|
17910
|
+
if (existsSync4(registryPath)) {
|
|
17891
17911
|
stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: 1 });
|
|
17892
17912
|
}
|
|
17893
|
-
const bindingsPath =
|
|
17894
|
-
if (
|
|
17913
|
+
const bindingsPath = join4(root, ".kxm", "runtime", "bindings.db");
|
|
17914
|
+
if (existsSync4(bindingsPath)) {
|
|
17895
17915
|
stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: 1 });
|
|
17896
17916
|
}
|
|
17897
|
-
const eventsDir =
|
|
17898
|
-
if (
|
|
17917
|
+
const eventsDir = join4(root, ".kxm", "runtime", "events");
|
|
17918
|
+
if (existsSync4(eventsDir)) {
|
|
17899
17919
|
const entries = readdirSync2(eventsDir, { withFileTypes: true });
|
|
17900
17920
|
for (const entry of entries) {
|
|
17901
17921
|
if (entry.isFile() && entry.name.endsWith(".db")) {
|
|
17902
17922
|
const key = entry.name.replace(/\.db$/, "");
|
|
17903
17923
|
stores.push({
|
|
17904
17924
|
storeId: `events:${key}`,
|
|
17905
|
-
sourcePath:
|
|
17925
|
+
sourcePath: join4(eventsDir, entry.name),
|
|
17906
17926
|
maxSupportedVersion: 3
|
|
17907
17927
|
});
|
|
17908
17928
|
}
|
|
@@ -17921,8 +17941,8 @@ function createBackup(options = {}) {
|
|
|
17921
17941
|
const now = /* @__PURE__ */ new Date();
|
|
17922
17942
|
const timestamp = now.toISOString().replace(/[:.]/g, "-");
|
|
17923
17943
|
const backupId = `bk_${randomBytes(8).toString("hex")}`;
|
|
17924
|
-
const outDir = options.outDir ? resolve3(options.outDir) :
|
|
17925
|
-
if (!
|
|
17944
|
+
const outDir = options.outDir ? resolve3(options.outDir) : join4(projectRoot, ".kxm", "backups", `backup-${timestamp}`);
|
|
17945
|
+
if (!existsSync4(outDir)) {
|
|
17926
17946
|
mkdirSync(outDir, { recursive: true, mode: 448 });
|
|
17927
17947
|
}
|
|
17928
17948
|
const backedUpStores = [];
|
|
@@ -17934,7 +17954,7 @@ function createBackup(options = {}) {
|
|
|
17934
17954
|
filename = `${sanitizedId}-${filename}`;
|
|
17935
17955
|
}
|
|
17936
17956
|
usedFilenames.add(filename);
|
|
17937
|
-
const targetFile =
|
|
17957
|
+
const targetFile = join4(outDir, filename);
|
|
17938
17958
|
const record2 = backupDatabaseFile(store.sourcePath, targetFile, store.storeId);
|
|
17939
17959
|
backedUpStores.push(record2);
|
|
17940
17960
|
}
|
|
@@ -17949,7 +17969,7 @@ function createBackup(options = {}) {
|
|
|
17949
17969
|
const manifestSha256 = `sha256:${createHash3("sha256").update(manifestJson, "utf8").digest("hex")}`;
|
|
17950
17970
|
manifest.manifestSha256 = manifestSha256;
|
|
17951
17971
|
const finalJson = JSON.stringify(manifest, null, 2) + "\n";
|
|
17952
|
-
const manifestPath =
|
|
17972
|
+
const manifestPath = join4(outDir, "manifest.json");
|
|
17953
17973
|
writeFileSync(manifestPath, finalJson, "utf8");
|
|
17954
17974
|
return { manifest, outDir };
|
|
17955
17975
|
}
|
|
@@ -17960,12 +17980,12 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
17960
17980
|
throw databaseError("runtime_path_invalid", manifestPath, `manifest path ${manifestPath} does not exist`);
|
|
17961
17981
|
}
|
|
17962
17982
|
if (stat.isDirectory()) {
|
|
17963
|
-
manifestPath =
|
|
17983
|
+
manifestPath = join4(manifestPath, "manifest.json");
|
|
17964
17984
|
}
|
|
17965
|
-
if (!
|
|
17985
|
+
if (!existsSync4(manifestPath)) {
|
|
17966
17986
|
throw databaseError("runtime_path_invalid", manifestPath, `backup manifest ${manifestPath} not found`);
|
|
17967
17987
|
}
|
|
17968
|
-
const manifestDir =
|
|
17988
|
+
const manifestDir = dirname4(manifestPath);
|
|
17969
17989
|
const rawText = readFileSync2(manifestPath, "utf8");
|
|
17970
17990
|
let manifest;
|
|
17971
17991
|
try {
|
|
@@ -17978,8 +17998,8 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
17978
17998
|
}
|
|
17979
17999
|
const restoredStores = [];
|
|
17980
18000
|
for (const store of manifest.stores) {
|
|
17981
|
-
const backupFilePath =
|
|
17982
|
-
if (!
|
|
18001
|
+
const backupFilePath = join4(manifestDir, store.backupFile);
|
|
18002
|
+
if (!existsSync4(backupFilePath)) {
|
|
17983
18003
|
throw databaseError("restore_file_missing", backupFilePath, `backup file ${store.backupFile} missing from ${manifestDir}`);
|
|
17984
18004
|
}
|
|
17985
18005
|
const actualSha256 = fileSha256(backupFilePath);
|
|
@@ -17997,7 +18017,7 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
17997
18017
|
let targetPath = store.sourcePath;
|
|
17998
18018
|
if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
|
|
17999
18019
|
const rel = targetPath.slice(manifest.projectRoot.length).replace(/^[\\/]+/, "");
|
|
18000
|
-
targetPath =
|
|
18020
|
+
targetPath = join4(resolve3(options.projectRoot), rel);
|
|
18001
18021
|
}
|
|
18002
18022
|
const result = restoreDatabaseFile(
|
|
18003
18023
|
backupFilePath,
|
|
@@ -18018,12 +18038,12 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
18018
18038
|
// plugins/kxm/src/vnext-runtime-store.ts
|
|
18019
18039
|
function vnextRuntimePaths(options = {}) {
|
|
18020
18040
|
const stateRoot = options.stateRoot ? resolve4(options.stateRoot) : vnextUserStateRoot({ ...options.env ? { env: options.env } : {}, ...options.homeDir ? { homeDir: options.homeDir } : {} });
|
|
18021
|
-
const runtimeDir =
|
|
18041
|
+
const runtimeDir = join5(stateRoot, "runtime");
|
|
18022
18042
|
return {
|
|
18023
18043
|
stateRoot,
|
|
18024
18044
|
runtimeDir,
|
|
18025
|
-
registryDb:
|
|
18026
|
-
projectsDir:
|
|
18045
|
+
registryDb: join5(runtimeDir, "registry.db"),
|
|
18046
|
+
projectsDir: join5(runtimeDir, "projects")
|
|
18027
18047
|
};
|
|
18028
18048
|
}
|
|
18029
18049
|
function runtimeIssue(phase, code, file, message) {
|
|
@@ -18486,7 +18506,7 @@ var VnextRunEventStore = class {
|
|
|
18486
18506
|
}
|
|
18487
18507
|
readRunPrompts() {
|
|
18488
18508
|
const sidecar = this.runPromptSidecarPath();
|
|
18489
|
-
if (!
|
|
18509
|
+
if (!existsSync5(sidecar)) return {};
|
|
18490
18510
|
try {
|
|
18491
18511
|
const parsed = JSON.parse(readFileSync3(sidecar, "utf8"));
|
|
18492
18512
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
@@ -20504,7 +20524,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
20504
20524
|
const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
|
|
20505
20525
|
const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
|
|
20506
20526
|
const assignments = compileAssignments(step, id, agent, sink);
|
|
20507
|
-
const
|
|
20527
|
+
const join18 = compileJoin(step, id, sink);
|
|
20508
20528
|
const requiredEvidence = compileEvidence(step, id, sink);
|
|
20509
20529
|
const transitions = compileTransitions(step, id, index, stepIndex, sink);
|
|
20510
20530
|
const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
|
|
@@ -20532,7 +20552,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
20532
20552
|
transitions: orderedTransitions,
|
|
20533
20553
|
requiresPlanHash: requirePlanHash.includes(id),
|
|
20534
20554
|
assignments,
|
|
20535
|
-
join:
|
|
20555
|
+
join: join18
|
|
20536
20556
|
};
|
|
20537
20557
|
if (kind === "agent" || kind === "moa") {
|
|
20538
20558
|
if (!agent) return void 0;
|
|
@@ -20582,15 +20602,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
|
|
|
20582
20602
|
};
|
|
20583
20603
|
}
|
|
20584
20604
|
function compileJoin(step, stepId, sink) {
|
|
20585
|
-
const
|
|
20586
|
-
if (!
|
|
20587
|
-
const declared = stringValue2(
|
|
20605
|
+
const join18 = objectValue2(step.join);
|
|
20606
|
+
if (!join18) return { strategy: "all" };
|
|
20607
|
+
const declared = stringValue2(join18.strategy);
|
|
20588
20608
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
20589
|
-
const minimumPassed = compileOptionalCount(
|
|
20609
|
+
const minimumPassed = compileOptionalCount(join18.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
20590
20610
|
const compiled = {
|
|
20591
20611
|
strategy,
|
|
20592
20612
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
20593
|
-
...typeof
|
|
20613
|
+
...typeof join18.cancelRemaining === "boolean" ? { cancelRemaining: join18.cancelRemaining } : {}
|
|
20594
20614
|
};
|
|
20595
20615
|
return compiled;
|
|
20596
20616
|
}
|
|
@@ -21911,12 +21931,12 @@ function enqueueVnextScheduledRun(storePath, runId, configRevision, bound, start
|
|
|
21911
21931
|
if (owner.admitted.has(runId) || owner.queue.some((item) => item.runId === runId)) {
|
|
21912
21932
|
return Promise.reject(runtimeError("run_busy", runId, `run ${runId} is already admitted or queued`));
|
|
21913
21933
|
}
|
|
21914
|
-
return new Promise((
|
|
21934
|
+
return new Promise((resolve8, reject) => {
|
|
21915
21935
|
owner.queue.push({
|
|
21916
21936
|
runId,
|
|
21917
21937
|
configRevision,
|
|
21918
21938
|
bound,
|
|
21919
|
-
start: (token) => start(token).then(
|
|
21939
|
+
start: (token) => start(token).then(resolve8, reject),
|
|
21920
21940
|
fail: (error) => reject(error)
|
|
21921
21941
|
});
|
|
21922
21942
|
pump(storePath, owner);
|
|
@@ -21977,11 +21997,11 @@ function vnextToolPolicyRevision(bundle) {
|
|
|
21977
21997
|
return sha256Of(vnextCanonicalJson({ policies, gateRegistry: bundle.gateRegistry?.value ?? null }));
|
|
21978
21998
|
}
|
|
21979
21999
|
function collectMemoryFiles(dir, baseDir, ignoreSubdirs = /* @__PURE__ */ new Set()) {
|
|
21980
|
-
if (!
|
|
22000
|
+
if (!existsSync6(dir)) return [];
|
|
21981
22001
|
const entries = readdirSync3(dir, { withFileTypes: true });
|
|
21982
22002
|
const results = [];
|
|
21983
22003
|
for (const entry of entries) {
|
|
21984
|
-
const fullPath =
|
|
22004
|
+
const fullPath = join6(dir, entry.name);
|
|
21985
22005
|
if (entry.isDirectory()) {
|
|
21986
22006
|
if (ignoreSubdirs.has(entry.name)) continue;
|
|
21987
22007
|
results.push(...collectMemoryFiles(fullPath, baseDir, ignoreSubdirs));
|
|
@@ -21994,15 +22014,15 @@ function collectMemoryFiles(dir, baseDir, ignoreSubdirs = /* @__PURE__ */ new Se
|
|
|
21994
22014
|
}
|
|
21995
22015
|
function computeVnextMemoryRevision(bundle, options = {}) {
|
|
21996
22016
|
const hash = createHash6("sha256");
|
|
21997
|
-
const memoryDir = options.memoryDir ??
|
|
22017
|
+
const memoryDir = options.memoryDir ?? join6(bundle.projectRoot, ".kxm", "memory");
|
|
21998
22018
|
const memoryFiles = collectMemoryFiles(memoryDir, memoryDir, /* @__PURE__ */ new Set(["candidates"])).sort((left, right) => compareCodeUnits5(left.relPath, right.relPath));
|
|
21999
22019
|
for (const file of memoryFiles) {
|
|
22000
22020
|
hash.update(`memory:${file.relPath}\0`, "utf8");
|
|
22001
22021
|
hash.update(readFileSync4(file.fullPath));
|
|
22002
22022
|
hash.update("\0", "utf8");
|
|
22003
22023
|
}
|
|
22004
|
-
const skillsDir = options.skillsDir ??
|
|
22005
|
-
const promotedSkillsDir =
|
|
22024
|
+
const skillsDir = options.skillsDir ?? join6(bundle.projectRoot, ".kxm", "skills");
|
|
22025
|
+
const promotedSkillsDir = join6(skillsDir, "promoted");
|
|
22006
22026
|
const skillFiles = collectMemoryFiles(promotedSkillsDir, promotedSkillsDir).sort((left, right) => compareCodeUnits5(left.relPath, right.relPath));
|
|
22007
22027
|
for (const file of skillFiles) {
|
|
22008
22028
|
hash.update(`skill:${file.relPath}\0`, "utf8");
|
|
@@ -22086,7 +22106,7 @@ function openVnextRuntimeContext(projectRoot, options) {
|
|
|
22086
22106
|
configRevision: bundle.configRevision,
|
|
22087
22107
|
now: options.now ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
22088
22108
|
});
|
|
22089
|
-
const eventStore = new VnextRunEventStore(
|
|
22109
|
+
const eventStore = new VnextRunEventStore(join6(paths.projectsDir, registration.projectKey, "run-events.db"));
|
|
22090
22110
|
registerVnextRuntimeHandle(eventStore.path);
|
|
22091
22111
|
return {
|
|
22092
22112
|
registry,
|
|
@@ -22416,18 +22436,17 @@ function assertVnextConfigError(error) {
|
|
|
22416
22436
|
// plugins/kxm/src/vnext-runtime-supervisor.ts
|
|
22417
22437
|
import { spawn as spawn3 } from "node:child_process";
|
|
22418
22438
|
import { createHash as createHash12, createHmac, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
22419
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
22439
|
+
import { chmodSync as chmodSync2, existsSync as existsSync10, lstatSync as lstatSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync8, renameSync, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
22420
22440
|
import { createServer } from "node:http";
|
|
22421
|
-
import { dirname as
|
|
22422
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
22441
|
+
import { dirname as dirname6, isAbsolute as isAbsolute4, join as join13 } from "node:path";
|
|
22423
22442
|
|
|
22424
22443
|
// plugins/kxm/src/vnext-oneshot-producer.ts
|
|
22425
|
-
import { join as
|
|
22444
|
+
import { join as join12 } from "node:path";
|
|
22426
22445
|
|
|
22427
22446
|
// plugins/kxm/src/vnext-oneshot-evidence.ts
|
|
22428
22447
|
import { createHash as createHash7, randomUUID as randomUUID3 } from "node:crypto";
|
|
22429
22448
|
import { lstat, mkdir, open, rename } from "node:fs/promises";
|
|
22430
|
-
import { join as
|
|
22449
|
+
import { join as join7 } from "node:path";
|
|
22431
22450
|
var ONESHOT_EVIDENCE_SCHEMA = "kxm.oneshot-evidence.v2";
|
|
22432
22451
|
var RETIRED_ONESHOT_EVIDENCE_SCHEMAS = /* @__PURE__ */ new Set(["kxm.oneshot-evidence.v1"]);
|
|
22433
22452
|
var TEXT_LIMIT = 4 * 1024 * 1024;
|
|
@@ -22457,7 +22476,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
22457
22476
|
throw new Error("oneshot_evidence_root_not_private");
|
|
22458
22477
|
}
|
|
22459
22478
|
const id = `evd_${randomUUID3().replaceAll("-", "")}`;
|
|
22460
|
-
const dir =
|
|
22479
|
+
const dir = join7(root, id);
|
|
22461
22480
|
await mkdir(dir, { mode: 448 });
|
|
22462
22481
|
const secrets = [...new Set(sensitive.filter((value) => value.length >= 8))].sort((a, b) => b.length - a.length);
|
|
22463
22482
|
const redact = (value) => {
|
|
@@ -22477,7 +22496,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
22477
22496
|
const bytes = JSON.stringify(value);
|
|
22478
22497
|
if (Buffer.byteLength(bytes) > RECORD_LIMIT) throw new Error("oneshot_evidence_record_limit");
|
|
22479
22498
|
parseOneShotEvidenceRecord(bytes);
|
|
22480
|
-
const target =
|
|
22499
|
+
const target = join7(dir, name);
|
|
22481
22500
|
const partial = `${target}.partial`;
|
|
22482
22501
|
const file = await open(partial, "wx", 384);
|
|
22483
22502
|
try {
|
|
@@ -22544,8 +22563,8 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
22544
22563
|
// plugins/kxm/src/prices.ts
|
|
22545
22564
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
22546
22565
|
import { createHash as createHash8 } from "node:crypto";
|
|
22547
|
-
import { existsSync as
|
|
22548
|
-
import { join as
|
|
22566
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, statSync } from "node:fs";
|
|
22567
|
+
import { join as join8 } from "node:path";
|
|
22549
22568
|
|
|
22550
22569
|
// plugins/kxm/src/price-calc.ts
|
|
22551
22570
|
var PRICES_SCHEMA = "kxm.prices.v1";
|
|
@@ -22697,8 +22716,8 @@ function parsePriceCatalog(text) {
|
|
|
22697
22716
|
return catalog;
|
|
22698
22717
|
}
|
|
22699
22718
|
function loadPriceCatalog(rootOrPath) {
|
|
22700
|
-
const candidatePath =
|
|
22701
|
-
if (!candidatePath || !
|
|
22719
|
+
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;
|
|
22720
|
+
if (!candidatePath || !existsSync7(candidatePath)) {
|
|
22702
22721
|
return void 0;
|
|
22703
22722
|
}
|
|
22704
22723
|
const content = readFileSync5(candidatePath, "utf8");
|
|
@@ -22720,28 +22739,28 @@ function loadPriceCatalogForEstimate(options) {
|
|
|
22720
22739
|
// plugins/kxm/src/vnext-engine.ts
|
|
22721
22740
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
22722
22741
|
import { createHash as createHash11, randomBytes as randomBytes2, timingSafeEqual } from "node:crypto";
|
|
22723
|
-
import { existsSync as
|
|
22724
|
-
import { join as
|
|
22742
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
|
|
22743
|
+
import { join as join11 } from "node:path";
|
|
22725
22744
|
|
|
22726
22745
|
// plugins/kxm/src/producers.ts
|
|
22727
22746
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
22728
|
-
import { existsSync as
|
|
22729
|
-
import { join as
|
|
22747
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, readdirSync as readdirSync4 } from "node:fs";
|
|
22748
|
+
import { join as join9 } from "node:path";
|
|
22730
22749
|
var empty = () => ({ schema: "kxm.producers.v1", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), promoted: [], demoted: [], enabled: [], disabled: [], roles: {} });
|
|
22731
22750
|
function loadProducerPolicy(root) {
|
|
22732
|
-
const path =
|
|
22733
|
-
if (!
|
|
22751
|
+
const path = join9(root, ".kxm", "producers.yaml");
|
|
22752
|
+
if (!existsSync8(path)) return empty();
|
|
22734
22753
|
const value = (0, import_yaml4.parse)(readFileSync6(path, "utf8"));
|
|
22735
22754
|
if (value?.schema !== "kxm.producers.v1" || !Array.isArray(value.promoted) || !Array.isArray(value.demoted)) throw new Error("invalid .kxm/producers.yaml");
|
|
22736
22755
|
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")])) : {} };
|
|
22737
22756
|
}
|
|
22738
22757
|
function listRoleBindings(root) {
|
|
22739
|
-
const dir =
|
|
22758
|
+
const dir = join9(root, ".kxm", "roles");
|
|
22740
22759
|
const result = {};
|
|
22741
|
-
if (!
|
|
22760
|
+
if (!existsSync8(dir)) return result;
|
|
22742
22761
|
for (const file of readdirSync4(dir).filter((name) => name.endsWith(".yaml"))) {
|
|
22743
22762
|
const role = file.slice(0, -5);
|
|
22744
|
-
const value = (0, import_yaml4.parse)(readFileSync6(
|
|
22763
|
+
const value = (0, import_yaml4.parse)(readFileSync6(join9(dir, file), "utf8"));
|
|
22745
22764
|
result[role] = (value.roster ?? []).map((entry) => entry.model).filter((model) => typeof model === "string");
|
|
22746
22765
|
}
|
|
22747
22766
|
return result;
|
|
@@ -23012,7 +23031,7 @@ function pruneContextPacket(packet, tokenBudget) {
|
|
|
23012
23031
|
}
|
|
23013
23032
|
|
|
23014
23033
|
// plugins/kxm/src/vnext-engine-artifacts.ts
|
|
23015
|
-
import { join as
|
|
23034
|
+
import { join as join10 } from "node:path";
|
|
23016
23035
|
|
|
23017
23036
|
// plugins/kxm/src/artifacts-exist.ts
|
|
23018
23037
|
import { lstatSync as lstatSync4, realpathSync as realpathSync3, statSync as statSync2 } from "node:fs";
|
|
@@ -23059,14 +23078,14 @@ function verifyArtifactExists(rootInput, pathInput) {
|
|
|
23059
23078
|
// plugins/kxm/src/vnext-engine-artifacts.ts
|
|
23060
23079
|
var vnextArtifactsGateSeams = {};
|
|
23061
23080
|
function evaluateArtifactsGate(context, definition) {
|
|
23062
|
-
const root =
|
|
23081
|
+
const root = join10(context.projectRoot, ".kxm", "assets");
|
|
23063
23082
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23064
23083
|
const startTime = process.hrtime.bigint();
|
|
23065
23084
|
let checkedCount = 0;
|
|
23066
23085
|
let failedCount = 0;
|
|
23067
23086
|
for (const [index, path] of definition.paths.entries()) {
|
|
23068
23087
|
checkedCount += 1;
|
|
23069
|
-
const result = verifyArtifactExists(root,
|
|
23088
|
+
const result = verifyArtifactExists(root, join10(root, path));
|
|
23070
23089
|
if (!result.ok) failedCount += 1;
|
|
23071
23090
|
vnextArtifactsGateSeams.afterPathChecked?.({ path, index, checkedCount, failedCount });
|
|
23072
23091
|
}
|
|
@@ -23222,8 +23241,8 @@ var CommandObserver = class {
|
|
|
23222
23241
|
this.requestStop("error", "lost-close");
|
|
23223
23242
|
}
|
|
23224
23243
|
run() {
|
|
23225
|
-
return new Promise((
|
|
23226
|
-
this.resolveOutcome =
|
|
23244
|
+
return new Promise((resolve8) => {
|
|
23245
|
+
this.resolveOutcome = resolve8;
|
|
23227
23246
|
try {
|
|
23228
23247
|
this.start();
|
|
23229
23248
|
} catch (error) {
|
|
@@ -24424,8 +24443,8 @@ var VnextRunScheduler = class _VnextRunScheduler {
|
|
|
24424
24443
|
resolve: (_value) => void 0,
|
|
24425
24444
|
reject: (_error) => void 0
|
|
24426
24445
|
};
|
|
24427
|
-
const settled = new Promise((
|
|
24428
|
-
pending.resolve =
|
|
24446
|
+
const settled = new Promise((resolve8, reject) => {
|
|
24447
|
+
pending.resolve = resolve8;
|
|
24429
24448
|
pending.reject = reject;
|
|
24430
24449
|
});
|
|
24431
24450
|
void settled.then(void 0, () => void 0);
|
|
@@ -24760,8 +24779,8 @@ function unreconciledPanelAttemptId(state) {
|
|
|
24760
24779
|
}
|
|
24761
24780
|
function resolveProducerRoute(projectRoot, step, agentId) {
|
|
24762
24781
|
let agentModel;
|
|
24763
|
-
const agentFile =
|
|
24764
|
-
if (
|
|
24782
|
+
const agentFile = join11(projectRoot, ".kxm", "agents", `${agentId}.yaml`);
|
|
24783
|
+
if (existsSync9(agentFile)) {
|
|
24765
24784
|
try {
|
|
24766
24785
|
const parsed = (0, import_yaml5.parse)(readFileSync7(agentFile, "utf8"));
|
|
24767
24786
|
if (typeof parsed?.model === "string") {
|
|
@@ -26344,7 +26363,7 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
|
|
|
26344
26363
|
}
|
|
26345
26364
|
const spawnFn = options.spawnProcess ?? defaultSpawn;
|
|
26346
26365
|
const cwd = options.projectRoot ?? process.cwd();
|
|
26347
|
-
const evidence = await beginOneShotEvidence(options.evidenceRoot ??
|
|
26366
|
+
const evidence = await beginOneShotEvidence(options.evidenceRoot ?? join12(vnextUserStateRoot(), "runtime", "oneshot-evidence"), {
|
|
26348
26367
|
runId: request.runId,
|
|
26349
26368
|
stepId: request.stepId,
|
|
26350
26369
|
attemptId: request.attemptId,
|
|
@@ -26488,13 +26507,12 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
|
|
|
26488
26507
|
}
|
|
26489
26508
|
|
|
26490
26509
|
// plugins/kxm/src/vnext-runtime-supervisor.ts
|
|
26491
|
-
var repoRoot = resolve6(fileURLToPath2(new URL("../../../", import.meta.url)));
|
|
26492
26510
|
function vnextSupervisorTokenFile(paths) {
|
|
26493
|
-
return
|
|
26511
|
+
return join13(paths.runtimeDir, "supervisor.token");
|
|
26494
26512
|
}
|
|
26495
26513
|
function publishVnextSupervisorToken(paths, token) {
|
|
26496
26514
|
const file = vnextSupervisorTokenFile(paths);
|
|
26497
|
-
mkdirSync4(
|
|
26515
|
+
mkdirSync4(dirname6(file), { recursive: true, mode: 448 });
|
|
26498
26516
|
const temp = `${file}.${process.pid}.tmp`;
|
|
26499
26517
|
writeFileSync4(temp, `${token}
|
|
26500
26518
|
`, { encoding: "utf8", mode: 384 });
|
|
@@ -26532,11 +26550,11 @@ function processAlive(pid) {
|
|
|
26532
26550
|
var HEARTBEAT_STALE_MS = 15e3;
|
|
26533
26551
|
var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
|
|
26534
26552
|
function supervisorErrorFile(paths) {
|
|
26535
|
-
return
|
|
26553
|
+
return join13(paths.runtimeDir, "supervisor.error");
|
|
26536
26554
|
}
|
|
26537
26555
|
function clearSupervisorError(paths) {
|
|
26538
26556
|
const file = supervisorErrorFile(paths);
|
|
26539
|
-
if (
|
|
26557
|
+
if (existsSync10(file)) rmSync(file, { force: true });
|
|
26540
26558
|
}
|
|
26541
26559
|
function recordSupervisorError(paths, message) {
|
|
26542
26560
|
try {
|
|
@@ -26559,7 +26577,7 @@ function readRecentSupervisorError(paths) {
|
|
|
26559
26577
|
}
|
|
26560
26578
|
}
|
|
26561
26579
|
function vnextSupervisorStatus(paths) {
|
|
26562
|
-
if (!
|
|
26580
|
+
if (!existsSync10(paths.registryDb)) return { running: false };
|
|
26563
26581
|
const registry = new VnextRuntimeRegistry(paths.registryDb);
|
|
26564
26582
|
try {
|
|
26565
26583
|
const record2 = registry.supervisor();
|
|
@@ -26620,7 +26638,7 @@ async function ensureVnextSupervisor(options = {}) {
|
|
|
26620
26638
|
throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
|
|
26621
26639
|
}
|
|
26622
26640
|
clearSupervisorError(paths);
|
|
26623
|
-
const scriptPath =
|
|
26641
|
+
const scriptPath = join13(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
|
|
26624
26642
|
const spawnImpl = options.spawnImpl ?? ((script, env) => {
|
|
26625
26643
|
const child = spawn3(process.execPath, [script], {
|
|
26626
26644
|
detached: true,
|
|
@@ -26705,8 +26723,8 @@ async function waitForDriveSessions(settled, graceMs) {
|
|
|
26705
26723
|
try {
|
|
26706
26724
|
await Promise.race([
|
|
26707
26725
|
Promise.allSettled(settled),
|
|
26708
|
-
new Promise((
|
|
26709
|
-
timeout = setTimeout(
|
|
26726
|
+
new Promise((resolve8) => {
|
|
26727
|
+
timeout = setTimeout(resolve8, graceMs);
|
|
26710
26728
|
timeout.unref?.();
|
|
26711
26729
|
})
|
|
26712
26730
|
]);
|
|
@@ -27073,7 +27091,7 @@ async function vnextRuntimeRequest(handle, method, path, body) {
|
|
|
27073
27091
|
|
|
27074
27092
|
// plugins/kxm/src/vnext-pi-producer.ts
|
|
27075
27093
|
import { spawn as spawn4 } from "node:child_process";
|
|
27076
|
-
import { join as
|
|
27094
|
+
import { join as join14 } from "node:path";
|
|
27077
27095
|
import { StringDecoder } from "node:string_decoder";
|
|
27078
27096
|
function formatPiSessionKey(params) {
|
|
27079
27097
|
if (params.agentId === "coordinator") {
|
|
@@ -27272,8 +27290,8 @@ var PiSession = class {
|
|
|
27272
27290
|
}
|
|
27273
27291
|
const id = `cmd_${++this.commandCounter}`;
|
|
27274
27292
|
const payload = { ...command, id };
|
|
27275
|
-
return new Promise((
|
|
27276
|
-
this.pendingCommands.set(id, { resolve:
|
|
27293
|
+
return new Promise((resolve8, reject) => {
|
|
27294
|
+
this.pendingCommands.set(id, { resolve: resolve8, reject });
|
|
27277
27295
|
try {
|
|
27278
27296
|
this.process.stdin.write(JSON.stringify(payload) + "\n");
|
|
27279
27297
|
} catch (err) {
|
|
@@ -27294,7 +27312,7 @@ var PiSession = class {
|
|
|
27294
27312
|
return { outcome, text: "aborted", usage: {} };
|
|
27295
27313
|
}
|
|
27296
27314
|
this.status = "busy";
|
|
27297
|
-
return new Promise((
|
|
27315
|
+
return new Promise((resolve8, reject) => {
|
|
27298
27316
|
let signalCleanup;
|
|
27299
27317
|
if (signal) {
|
|
27300
27318
|
const onAbort = () => {
|
|
@@ -27308,7 +27326,7 @@ var PiSession = class {
|
|
|
27308
27326
|
signalCleanup = () => signal.removeEventListener("abort", onAbort);
|
|
27309
27327
|
}
|
|
27310
27328
|
this.activePrompt = {
|
|
27311
|
-
resolve:
|
|
27329
|
+
resolve: resolve8,
|
|
27312
27330
|
reject,
|
|
27313
27331
|
allowedOutcomes,
|
|
27314
27332
|
text: "",
|
|
@@ -27425,7 +27443,7 @@ function createVnextPiProducer(options = {}) {
|
|
|
27425
27443
|
const args = ["--mode", "rpc", "--name", displayName];
|
|
27426
27444
|
if (options.sessionDir) {
|
|
27427
27445
|
const safeDirName = key.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
27428
|
-
args.push("--session-dir",
|
|
27446
|
+
args.push("--session-dir", join14(options.sessionDir, request.runId, safeDirName));
|
|
27429
27447
|
}
|
|
27430
27448
|
if (model) {
|
|
27431
27449
|
args.push("--model", model);
|
|
@@ -27553,8 +27571,8 @@ function createVnextPiProducer(options = {}) {
|
|
|
27553
27571
|
}
|
|
27554
27572
|
|
|
27555
27573
|
// plugins/kxm/src/logger.ts
|
|
27556
|
-
import { appendFileSync, existsSync as
|
|
27557
|
-
import { dirname as
|
|
27574
|
+
import { appendFileSync, existsSync as existsSync11, mkdirSync as mkdirSync5, renameSync as renameSync2, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
27575
|
+
import { dirname as dirname7 } from "node:path";
|
|
27558
27576
|
|
|
27559
27577
|
// plugins/kxm/src/redact.ts
|
|
27560
27578
|
var SECRET_PATTERNS = [
|
|
@@ -27617,7 +27635,7 @@ function redactLogValue(val, key) {
|
|
|
27617
27635
|
function rotateLogFiles(filePath, maxFiles) {
|
|
27618
27636
|
for (let i = maxFiles; i >= 1; i--) {
|
|
27619
27637
|
const current = `${filePath}.${i}`;
|
|
27620
|
-
if (
|
|
27638
|
+
if (existsSync11(current)) {
|
|
27621
27639
|
if (i >= maxFiles) {
|
|
27622
27640
|
try {
|
|
27623
27641
|
unlinkSync2(current);
|
|
@@ -27631,7 +27649,7 @@ function rotateLogFiles(filePath, maxFiles) {
|
|
|
27631
27649
|
}
|
|
27632
27650
|
}
|
|
27633
27651
|
}
|
|
27634
|
-
if (
|
|
27652
|
+
if (existsSync11(filePath)) {
|
|
27635
27653
|
try {
|
|
27636
27654
|
renameSync2(filePath, `${filePath}.1`);
|
|
27637
27655
|
} catch {
|
|
@@ -27648,7 +27666,7 @@ function createLogger(options) {
|
|
|
27648
27666
|
const shouldStdout = options.stdout ?? !isDaemon;
|
|
27649
27667
|
const correlationDefaults = options.correlation ?? {};
|
|
27650
27668
|
let currentSize = 0;
|
|
27651
|
-
if (filePath &&
|
|
27669
|
+
if (filePath && existsSync11(filePath)) {
|
|
27652
27670
|
try {
|
|
27653
27671
|
currentSize = statSync3(filePath).size;
|
|
27654
27672
|
} catch {
|
|
@@ -27686,7 +27704,7 @@ function createLogger(options) {
|
|
|
27686
27704
|
currentSize = 0;
|
|
27687
27705
|
}
|
|
27688
27706
|
try {
|
|
27689
|
-
mkdirSync5(
|
|
27707
|
+
mkdirSync5(dirname7(filePath), { recursive: true });
|
|
27690
27708
|
appendFileSync(filePath, line, { encoding: "utf8", mode: 384 });
|
|
27691
27709
|
currentSize += lineBytes;
|
|
27692
27710
|
} catch {
|
|
@@ -27729,8 +27747,8 @@ function createLogger(options) {
|
|
|
27729
27747
|
|
|
27730
27748
|
// plugins/kxm/src/improve.ts
|
|
27731
27749
|
import { createHash as createHash13 } from "node:crypto";
|
|
27732
|
-
import { existsSync as
|
|
27733
|
-
import { join as
|
|
27750
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
27751
|
+
import { join as join15, relative as relative4, resolve as resolve6 } from "node:path";
|
|
27734
27752
|
|
|
27735
27753
|
// plugins/kxm/src/protocol.ts
|
|
27736
27754
|
var DEFAULT_MESSAGE_TTL_MS = 24 * 60 * 6e4;
|
|
@@ -27913,8 +27931,8 @@ function groupRoutingRecords(records, options = {}) {
|
|
|
27913
27931
|
});
|
|
27914
27932
|
}
|
|
27915
27933
|
function buildImprovementReport(records, options = {}) {
|
|
27916
|
-
const projectRoot = options.projectRoot ?
|
|
27917
|
-
const candidatesDir = options.candidatesDir ?
|
|
27934
|
+
const projectRoot = options.projectRoot ? resolve6(options.projectRoot) : process.cwd();
|
|
27935
|
+
const candidatesDir = options.candidatesDir ? resolve6(options.candidatesDir) : join15(projectRoot, ".kxm", "candidates");
|
|
27918
27936
|
const groups = groupRoutingRecords(records, options);
|
|
27919
27937
|
const candidates = [];
|
|
27920
27938
|
for (const group of groups) {
|
|
@@ -27926,7 +27944,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
27926
27944
|
group.workflowHash
|
|
27927
27945
|
);
|
|
27928
27946
|
const diffFileName = `${group.candidateId}.diff`;
|
|
27929
|
-
const diffFilePath =
|
|
27947
|
+
const diffFilePath = join15(candidatesDir, diffFileName);
|
|
27930
27948
|
const relDiffPath = relative4(projectRoot, diffFilePath).replace(/\\/g, "/");
|
|
27931
27949
|
const candidate = {
|
|
27932
27950
|
schema: CANDIDATE_SCHEMA,
|
|
@@ -27948,11 +27966,11 @@ function buildImprovementReport(records, options = {}) {
|
|
|
27948
27966
|
createdAt: nowIso()
|
|
27949
27967
|
};
|
|
27950
27968
|
if (!options.dryRun) {
|
|
27951
|
-
if (!
|
|
27969
|
+
if (!existsSync12(candidatesDir)) {
|
|
27952
27970
|
mkdirSync6(candidatesDir, { recursive: true });
|
|
27953
27971
|
}
|
|
27954
27972
|
writeFileSync5(diffFilePath, diff, "utf8");
|
|
27955
|
-
const jsonFilePath =
|
|
27973
|
+
const jsonFilePath = join15(candidatesDir, `${group.candidateId}.json`);
|
|
27956
27974
|
writeFileSync5(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
|
|
27957
27975
|
}
|
|
27958
27976
|
candidates.push(candidate);
|
|
@@ -27968,7 +27986,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
27968
27986
|
}
|
|
27969
27987
|
function writeImprovementReport(improvementsDir, report, dryRun = false) {
|
|
27970
27988
|
const stamp = report.createdAt.replace(/[:.]/g, "-");
|
|
27971
|
-
const path =
|
|
27989
|
+
const path = join15(improvementsDir, `${stamp}.json`);
|
|
27972
27990
|
if (!dryRun) {
|
|
27973
27991
|
mkdirSync6(improvementsDir, { recursive: true });
|
|
27974
27992
|
writeFileSync5(path, `${JSON.stringify(report, null, 2)}
|
|
@@ -28472,8 +28490,8 @@ Instructions for Operator:
|
|
|
28472
28490
|
|
|
28473
28491
|
// plugins/kxm/src/modes.ts
|
|
28474
28492
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
28475
|
-
import { existsSync as
|
|
28476
|
-
import { join as
|
|
28493
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "node:fs";
|
|
28494
|
+
import { join as join16 } from "node:path";
|
|
28477
28495
|
var DEFAULT_MODES_CONFIG = Object.freeze({
|
|
28478
28496
|
schema: "kxm.modes.v1",
|
|
28479
28497
|
majorModes: {
|
|
@@ -28536,8 +28554,8 @@ function loadModesConfig(projectRoot) {
|
|
|
28536
28554
|
if (!projectRoot) {
|
|
28537
28555
|
return DEFAULT_MODES_CONFIG;
|
|
28538
28556
|
}
|
|
28539
|
-
const modesPath =
|
|
28540
|
-
if (!
|
|
28557
|
+
const modesPath = join16(projectRoot, ".kxm", "modes.yaml");
|
|
28558
|
+
if (!existsSync13(modesPath)) {
|
|
28541
28559
|
return DEFAULT_MODES_CONFIG;
|
|
28542
28560
|
}
|
|
28543
28561
|
try {
|
|
@@ -28627,9 +28645,9 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
|
|
|
28627
28645
|
estimatedTokens: estimateTokens(baseSystemPromptChars)
|
|
28628
28646
|
});
|
|
28629
28647
|
for (const relPath of resolved.contextFiles) {
|
|
28630
|
-
const fullPath =
|
|
28648
|
+
const fullPath = join16(projectRoot, relPath);
|
|
28631
28649
|
let chars = 0;
|
|
28632
|
-
if (
|
|
28650
|
+
if (existsSync13(fullPath)) {
|
|
28633
28651
|
try {
|
|
28634
28652
|
chars = readFileSync10(fullPath, "utf8").length;
|
|
28635
28653
|
} catch {
|
|
@@ -28763,9 +28781,9 @@ ${divider}
|
|
|
28763
28781
|
|
|
28764
28782
|
// plugins/kxm/src/ssh-remote.ts
|
|
28765
28783
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
28766
|
-
import { existsSync as
|
|
28784
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync11, readdirSync as readdirSync5, rmSync as rmSync2, statSync as statSync4 } from "node:fs";
|
|
28767
28785
|
import { homedir as homedir2 } from "node:os";
|
|
28768
|
-
import { join as
|
|
28786
|
+
import { join as join17, resolve as resolve7 } from "node:path";
|
|
28769
28787
|
var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
|
|
28770
28788
|
var MAX_SSH_OUTPUT_LINES = 2e3;
|
|
28771
28789
|
var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
|
|
@@ -28791,8 +28809,8 @@ function truncateSshOutput(raw) {
|
|
|
28791
28809
|
return { text, truncated };
|
|
28792
28810
|
}
|
|
28793
28811
|
function parseSshConfig(configPath) {
|
|
28794
|
-
const targetPath = configPath ??
|
|
28795
|
-
if (!
|
|
28812
|
+
const targetPath = configPath ?? join17(homedir2(), ".ssh", "config");
|
|
28813
|
+
if (!existsSync14(targetPath)) {
|
|
28796
28814
|
return [];
|
|
28797
28815
|
}
|
|
28798
28816
|
try {
|
|
@@ -28873,15 +28891,15 @@ function resolveSshHostG(host, execFn = spawnSync3) {
|
|
|
28873
28891
|
}
|
|
28874
28892
|
}
|
|
28875
28893
|
function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
|
|
28876
|
-
const resolved =
|
|
28877
|
-
if (!
|
|
28894
|
+
const resolved = resolve7(socketDir);
|
|
28895
|
+
if (!existsSync14(resolved)) {
|
|
28878
28896
|
mkdirSync7(resolved, { recursive: true, mode: 448 });
|
|
28879
28897
|
}
|
|
28880
28898
|
return resolved;
|
|
28881
28899
|
}
|
|
28882
28900
|
function buildSshArgs(options) {
|
|
28883
28901
|
const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
|
|
28884
|
-
const controlPath =
|
|
28902
|
+
const controlPath = join17(socketDir, "%C");
|
|
28885
28903
|
const persist2 = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
|
|
28886
28904
|
const args = [
|
|
28887
28905
|
"-o",
|
|
@@ -28906,7 +28924,7 @@ function buildSshArgs(options) {
|
|
|
28906
28924
|
}
|
|
28907
28925
|
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync3) {
|
|
28908
28926
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
28909
|
-
const controlPath =
|
|
28927
|
+
const controlPath = join17(resolvedDir, "%C");
|
|
28910
28928
|
try {
|
|
28911
28929
|
const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
|
|
28912
28930
|
encoding: "utf-8"
|
|
@@ -28918,7 +28936,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
28918
28936
|
}
|
|
28919
28937
|
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync3) {
|
|
28920
28938
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
28921
|
-
const controlPath =
|
|
28939
|
+
const controlPath = join17(resolvedDir, "%C");
|
|
28922
28940
|
try {
|
|
28923
28941
|
const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
|
|
28924
28942
|
encoding: "utf-8"
|
|
@@ -28934,7 +28952,7 @@ function pruneSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
|
|
|
28934
28952
|
try {
|
|
28935
28953
|
const entries = readdirSync5(resolvedDir);
|
|
28936
28954
|
for (const entry of entries) {
|
|
28937
|
-
const fullPath =
|
|
28955
|
+
const fullPath = join17(resolvedDir, entry);
|
|
28938
28956
|
try {
|
|
28939
28957
|
const stat = statSync4(fullPath);
|
|
28940
28958
|
if (stat.isSocket()) {
|