@kontextmind/kxm 0.7.18 → 0.7.20
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/docs/configuration.md +17 -1
- package/docs/getting-started.md +4 -1
- package/docs/kxm-handbook.md +6 -2
- package/docs/troubleshooting.md +4 -0
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +441 -419
- package/plugins/kxm/dist/extension.js +13981 -13557
- package/plugins/kxm/dist/mcp-server.js +21 -10
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/hub.ts +3 -2
- package/plugins/kxm/src/cli.ts +3 -2
- package/plugins/kxm/src/config.ts +20 -0
- package/plugins/kxm/src/extension.ts +37 -3
- package/plugins/kxm/src/hub-autostart.ts +214 -0
- package/plugins/kxm/src/mcp-server.ts +3 -3
- package/plugins/kxm/src/project-name.ts +20 -0
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -14779,7 +14779,7 @@ var require_dist = __commonJS({
|
|
|
14779
14779
|
});
|
|
14780
14780
|
|
|
14781
14781
|
// plugins/kxm/src/cli.ts
|
|
14782
|
-
import {
|
|
14782
|
+
import { resolve as resolve30 } from "node:path";
|
|
14783
14783
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
14784
14784
|
|
|
14785
14785
|
// node_modules/commander/lib/error.js
|
|
@@ -19571,11 +19571,25 @@ var HubClient = class {
|
|
|
19571
19571
|
}
|
|
19572
19572
|
};
|
|
19573
19573
|
|
|
19574
|
+
// plugins/kxm/src/project-name.ts
|
|
19575
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
19576
|
+
import { basename, join as join2 } from "node:path";
|
|
19577
|
+
function defaultProjectName(cwd, env = process.env) {
|
|
19578
|
+
const fromEnv = env.KXM_PROJECT?.trim();
|
|
19579
|
+
if (fromEnv) return fromEnv;
|
|
19580
|
+
try {
|
|
19581
|
+
const pkg = JSON.parse(readFileSync2(join2(cwd, "package.json"), "utf8"));
|
|
19582
|
+
if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
|
|
19583
|
+
} catch {
|
|
19584
|
+
}
|
|
19585
|
+
return basename(cwd);
|
|
19586
|
+
}
|
|
19587
|
+
|
|
19574
19588
|
// plugins/kxm/src/commands.ts
|
|
19575
19589
|
import { createHash as createHash4, randomUUID as randomUUID2, timingSafeEqual } from "node:crypto";
|
|
19576
|
-
import { chmodSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as
|
|
19590
|
+
import { chmodSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
19577
19591
|
import { homedir } from "node:os";
|
|
19578
|
-
import { dirname, join as
|
|
19592
|
+
import { dirname, join as join3, resolve } from "node:path";
|
|
19579
19593
|
function requiredString(value, name) {
|
|
19580
19594
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`${name} is required`);
|
|
19581
19595
|
return value.trim();
|
|
@@ -20324,10 +20338,10 @@ function parseSessionToken(token) {
|
|
|
20324
20338
|
}
|
|
20325
20339
|
function resolveUserConfigDirectory(overrideDir) {
|
|
20326
20340
|
if (overrideDir) return resolve(overrideDir);
|
|
20327
|
-
return resolve(process.env.KXM_USER_CONFIG_DIR?.trim() ||
|
|
20341
|
+
return resolve(process.env.KXM_USER_CONFIG_DIR?.trim() || join3(homedir(), ".config", "kxm"));
|
|
20328
20342
|
}
|
|
20329
20343
|
function sessionTokenPath(userConfigDir) {
|
|
20330
|
-
return
|
|
20344
|
+
return join3(resolveUserConfigDirectory(userConfigDir), "session.token");
|
|
20331
20345
|
}
|
|
20332
20346
|
function persistSessionTokenToDisk(token, options) {
|
|
20333
20347
|
const filePath = sessionTokenPath(options?.userConfigDir);
|
|
@@ -20346,7 +20360,7 @@ function readSessionTokenFromDisk(options) {
|
|
|
20346
20360
|
const filePath = sessionTokenPath(options?.userConfigDir);
|
|
20347
20361
|
if (!existsSync2(filePath)) return void 0;
|
|
20348
20362
|
try {
|
|
20349
|
-
const token =
|
|
20363
|
+
const token = readFileSync3(filePath, "utf8").trim();
|
|
20350
20364
|
if (!token) return void 0;
|
|
20351
20365
|
const payload = parseSessionToken(token);
|
|
20352
20366
|
if (!payload) return void 0;
|
|
@@ -20459,7 +20473,7 @@ function enforceToolPolicy(commandName, env = process.env, options) {
|
|
|
20459
20473
|
if (existsSync2(tokenFile)) {
|
|
20460
20474
|
let tokenRaw;
|
|
20461
20475
|
try {
|
|
20462
|
-
tokenRaw =
|
|
20476
|
+
tokenRaw = readFileSync3(tokenFile, "utf8").trim();
|
|
20463
20477
|
} catch {
|
|
20464
20478
|
return { allowed: false, error: "session_token_invalid", detail: "Session token file on disk could not be read" };
|
|
20465
20479
|
}
|
|
@@ -20483,8 +20497,8 @@ function enforceToolPolicy(commandName, env = process.env, options) {
|
|
|
20483
20497
|
var import__ = __toESM(require__(), 1);
|
|
20484
20498
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
20485
20499
|
import { createHash as createHash6 } from "node:crypto";
|
|
20486
|
-
import { existsSync as existsSync4, lstatSync, readFileSync as
|
|
20487
|
-
import { basename, dirname as dirname2, extname, isAbsolute, join as
|
|
20500
|
+
import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync4, readdirSync, realpathSync } from "node:fs";
|
|
20501
|
+
import { basename as basename2, dirname as dirname2, extname, isAbsolute, join as join4, relative, resolve as resolve2, sep } from "node:path";
|
|
20488
20502
|
import { fileURLToPath } from "node:url";
|
|
20489
20503
|
|
|
20490
20504
|
// plugins/kxm/src/restricted-yaml.mjs
|
|
@@ -21880,7 +21894,7 @@ var VnextConfigError = class extends Error {
|
|
|
21880
21894
|
}
|
|
21881
21895
|
};
|
|
21882
21896
|
var PACKAGE_ROOT = resolve2(dirname2(fileURLToPath(import.meta.url)), "../../..");
|
|
21883
|
-
var DEFAULT_SCHEMA_DIR =
|
|
21897
|
+
var DEFAULT_SCHEMA_DIR = join4(PACKAGE_ROOT, "schemas", "vnext");
|
|
21884
21898
|
var RESOURCE_SCHEMA = Object.freeze({
|
|
21885
21899
|
project: { identity: "kxm.project.v1", file: "project.schema.json" },
|
|
21886
21900
|
repository: { identity: "kxm.repository.v1", file: "repository.schema.json" },
|
|
@@ -21926,7 +21940,7 @@ function parseRestrictedYaml2(input, label = "<yaml>", limits = VNEXT_YAML_LIMIT
|
|
|
21926
21940
|
}
|
|
21927
21941
|
}
|
|
21928
21942
|
function readJsonObject(file) {
|
|
21929
|
-
const parsed = JSON.parse(
|
|
21943
|
+
const parsed = JSON.parse(readFileSync4(file, "utf8"));
|
|
21930
21944
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`${file} is not a JSON object`);
|
|
21931
21945
|
return parsed;
|
|
21932
21946
|
}
|
|
@@ -21945,10 +21959,10 @@ var VnextSchemaRegistry = class {
|
|
|
21945
21959
|
constructor(schemasDir = DEFAULT_SCHEMA_DIR) {
|
|
21946
21960
|
this.schemasDir = resolve2(schemasDir);
|
|
21947
21961
|
this.ajv = new import__.Ajv2020({ allErrors: true, strict: true, strictRequired: false });
|
|
21948
|
-
const common = readJsonObject(
|
|
21962
|
+
const common = readJsonObject(join4(this.schemasDir, "common.schema.json"));
|
|
21949
21963
|
this.ajv.addSchema(common);
|
|
21950
21964
|
for (const definition of Object.values(RESOURCE_SCHEMA)) {
|
|
21951
|
-
this.ajv.addSchema(readJsonObject(
|
|
21965
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, definition.file)));
|
|
21952
21966
|
}
|
|
21953
21967
|
const localBindingsFile = "local-repository-bindings.schema.json";
|
|
21954
21968
|
const templateProvenanceFile = "template-provenance.schema.json";
|
|
@@ -21958,14 +21972,14 @@ var VnextSchemaRegistry = class {
|
|
|
21958
21972
|
const migrationReceiptFile = "migration-receipt.schema.json";
|
|
21959
21973
|
const permissionDiffFile = "permission-diff.schema.json";
|
|
21960
21974
|
const runEventFile = "run-event.schema.json";
|
|
21961
|
-
this.ajv.addSchema(readJsonObject(
|
|
21962
|
-
this.ajv.addSchema(readJsonObject(
|
|
21963
|
-
this.ajv.addSchema(readJsonObject(
|
|
21964
|
-
this.ajv.addSchema(readJsonObject(
|
|
21965
|
-
this.ajv.addSchema(readJsonObject(
|
|
21966
|
-
this.ajv.addSchema(readJsonObject(
|
|
21967
|
-
this.ajv.addSchema(readJsonObject(
|
|
21968
|
-
this.ajv.addSchema(readJsonObject(
|
|
21975
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, localBindingsFile)));
|
|
21976
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, templateProvenanceFile)));
|
|
21977
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, initOperationFile)));
|
|
21978
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, migrationPlanFile)));
|
|
21979
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, migrationDecisionFile)));
|
|
21980
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, migrationReceiptFile)));
|
|
21981
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, permissionDiffFile)));
|
|
21982
|
+
this.ajv.addSchema(readJsonObject(join4(this.schemasDir, runEventFile)));
|
|
21969
21983
|
for (const [kind, definition] of Object.entries(RESOURCE_SCHEMA)) {
|
|
21970
21984
|
const validator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${definition.file}`);
|
|
21971
21985
|
if (!validator) throw new Error(`schema did not compile: ${definition.file}`);
|
|
@@ -22060,7 +22074,7 @@ function containedHostPath(root, candidate) {
|
|
|
22060
22074
|
function portableBindingIssue(root, pathHint, repositoryId) {
|
|
22061
22075
|
let current = root;
|
|
22062
22076
|
for (const segment of pathHint === "." ? [] : pathHint.split("/")) {
|
|
22063
|
-
current =
|
|
22077
|
+
current = join4(current, segment);
|
|
22064
22078
|
if (!existsSync4(current)) break;
|
|
22065
22079
|
const stat = lstatSync(current);
|
|
22066
22080
|
if (stat.isSymbolicLink()) {
|
|
@@ -22119,20 +22133,20 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
|
|
|
22119
22133
|
parent = dirname2(parent);
|
|
22120
22134
|
}
|
|
22121
22135
|
if (!stat.isFile()) fail2("path", "resource_not_file", label, "configuration resource must be a regular file");
|
|
22122
|
-
const value = parseRestrictedYaml2(
|
|
22136
|
+
const value = parseRestrictedYaml2(readFileSync4(file), label);
|
|
22123
22137
|
const issues = registry.validate(kind, value, label);
|
|
22124
22138
|
if (issues.length > 0) throw new VnextConfigError(issues);
|
|
22125
22139
|
return { kind, ...id === void 0 ? {} : { id }, file, logicalPath, value };
|
|
22126
22140
|
}
|
|
22127
22141
|
function readTemplateProvenance(registry, root) {
|
|
22128
|
-
const file =
|
|
22142
|
+
const file = join4(root, ".kxm", "template-provenance.yaml");
|
|
22129
22143
|
if (!existsSync4(file)) return void 0;
|
|
22130
22144
|
const label = ".kxm/template-provenance.yaml";
|
|
22131
22145
|
const stat = lstatSync(file);
|
|
22132
22146
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
22133
22147
|
fail2("path", "resource_not_file", label, "template provenance must be a regular file, not a link or directory");
|
|
22134
22148
|
}
|
|
22135
|
-
const configRoot =
|
|
22149
|
+
const configRoot = join4(root, ".kxm");
|
|
22136
22150
|
let parent = dirname2(file);
|
|
22137
22151
|
while (parent !== root) {
|
|
22138
22152
|
const parentStat = lstatSync(parent);
|
|
@@ -22142,7 +22156,7 @@ function readTemplateProvenance(registry, root) {
|
|
|
22142
22156
|
if (parent === configRoot) break;
|
|
22143
22157
|
parent = dirname2(parent);
|
|
22144
22158
|
}
|
|
22145
|
-
const value = parseRestrictedYaml2(
|
|
22159
|
+
const value = parseRestrictedYaml2(readFileSync4(file), label);
|
|
22146
22160
|
const issues = registry.validateTemplateProvenance(value, label);
|
|
22147
22161
|
if (issues.length > 0) throw new VnextConfigError(issues);
|
|
22148
22162
|
if (!resolveVnextTemplateBaseline(value)) {
|
|
@@ -22182,27 +22196,27 @@ function listNamedResources(registry, root, directory, logicalDirectory, kind) {
|
|
|
22182
22196
|
const entries = readdirSync(directory, { withFileTypes: true }).sort((left, right) => compareCodeUnits3(left.name, right.name));
|
|
22183
22197
|
for (const entry of entries) {
|
|
22184
22198
|
if (entry.isDirectory()) {
|
|
22185
|
-
issues.push(issue2("path", "nested_resource_directory", displayPath(root,
|
|
22199
|
+
issues.push(issue2("path", "nested_resource_directory", displayPath(root, join4(directory, entry.name)), "nested resource directories are not allowed"));
|
|
22186
22200
|
continue;
|
|
22187
22201
|
}
|
|
22188
22202
|
if (!entry.name.toLowerCase().endsWith(".yaml") && !entry.name.toLowerCase().endsWith(".yml")) continue;
|
|
22189
22203
|
if (!entry.isFile() || extname(entry.name) !== ".yaml") {
|
|
22190
|
-
issues.push(issue2("path", "resource_filename_invalid", displayPath(root,
|
|
22204
|
+
issues.push(issue2("path", "resource_filename_invalid", displayPath(root, join4(directory, entry.name)), "resource must be a regular file with the exact .yaml extension"));
|
|
22191
22205
|
continue;
|
|
22192
22206
|
}
|
|
22193
|
-
const id =
|
|
22207
|
+
const id = basename2(entry.name, ".yaml");
|
|
22194
22208
|
if (kind === "model" && id === "inventory") continue;
|
|
22195
22209
|
if (!resourceIdentifier(id)) {
|
|
22196
|
-
issues.push(issue2("path", "resource_id_invalid", displayPath(root,
|
|
22210
|
+
issues.push(issue2("path", "resource_id_invalid", displayPath(root, join4(directory, entry.name)), `filename-derived identity ${id} is invalid or platform-reserved`));
|
|
22197
22211
|
continue;
|
|
22198
22212
|
}
|
|
22199
22213
|
const collision = [...resources.keys()].find((candidate) => candidate.toLocaleLowerCase("en-US") === id.toLocaleLowerCase("en-US"));
|
|
22200
22214
|
if (collision) {
|
|
22201
|
-
issues.push(issue2("path", "resource_id_collision", displayPath(root,
|
|
22215
|
+
issues.push(issue2("path", "resource_id_collision", displayPath(root, join4(directory, entry.name)), `${id} case-folds to existing ${collision}`));
|
|
22202
22216
|
continue;
|
|
22203
22217
|
}
|
|
22204
22218
|
try {
|
|
22205
|
-
const resource = readResource(registry, root,
|
|
22219
|
+
const resource = readResource(registry, root, join4(directory, entry.name), `${logicalDirectory}/${id}.yaml`, kind, id);
|
|
22206
22220
|
resources.set(id, resource);
|
|
22207
22221
|
} catch (error) {
|
|
22208
22222
|
if (error instanceof VnextConfigError) issues.push(...error.issues);
|
|
@@ -22523,8 +22537,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
22523
22537
|
const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
|
|
22524
22538
|
if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
|
|
22525
22539
|
}
|
|
22526
|
-
const
|
|
22527
|
-
const minimumPassed =
|
|
22540
|
+
const join48 = objectValue(step.join);
|
|
22541
|
+
const minimumPassed = join48 && typeof join48.minimumPassed === "number" ? join48.minimumPassed : void 0;
|
|
22528
22542
|
if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
|
|
22529
22543
|
const distinctBy = names(assignment?.distinctBy);
|
|
22530
22544
|
if (distinctBy.length > 0) {
|
|
@@ -22738,11 +22752,11 @@ function validateBundle(project, repositories, agents, models, workflows, enviro
|
|
|
22738
22752
|
if (!workflows.has(defaultWorkflow)) issues.push(issue2("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
|
|
22739
22753
|
for (const workflow of workflows.values()) validateWorkflow(workflow, agents, models, repositoryIds, gates, issues);
|
|
22740
22754
|
if (projectRoot) {
|
|
22741
|
-
const writerRolePath =
|
|
22755
|
+
const writerRolePath = join4(projectRoot, ".kxm", "roles", "writer.yaml");
|
|
22742
22756
|
const implementerAgent = agents.get("implementer") ?? agents.get("writer");
|
|
22743
22757
|
if (existsSync4(writerRolePath) && implementerAgent) {
|
|
22744
22758
|
try {
|
|
22745
|
-
const rawRole = parseRestrictedYaml2(
|
|
22759
|
+
const rawRole = parseRestrictedYaml2(readFileSync4(writerRolePath, "utf8"));
|
|
22746
22760
|
const roleObj = objectValue(rawRole);
|
|
22747
22761
|
const rosterEntries = valuesOf(roleObj ?? {}, "roster").map((candidate) => objectValue(candidate)).filter((entry) => Boolean(entry));
|
|
22748
22762
|
const enabledRosterModels = rosterEntries.filter((entry) => entry.enabled !== false).map((entry) => stringValue(entry.model)).filter((m2) => Boolean(m2));
|
|
@@ -22802,7 +22816,7 @@ function discoverGitRoot(start = process.cwd()) {
|
|
|
22802
22816
|
}
|
|
22803
22817
|
function discoverVnextProjectRoot(start = process.cwd()) {
|
|
22804
22818
|
const gitRoot = discoverGitRoot(start);
|
|
22805
|
-
return gitRoot && existsSync4(
|
|
22819
|
+
return gitRoot && existsSync4(join4(gitRoot, ".kxm", "project.yaml")) ? gitRoot : void 0;
|
|
22806
22820
|
}
|
|
22807
22821
|
function assertNoRegisteredGates(options) {
|
|
22808
22822
|
if ("registeredGates" in options) {
|
|
@@ -22819,7 +22833,7 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
22819
22833
|
migrationReceipt = receiptCheck.receipt;
|
|
22820
22834
|
}
|
|
22821
22835
|
const registry = new VnextSchemaRegistry(options.schemasDir);
|
|
22822
|
-
const project = readResource(registry, root,
|
|
22836
|
+
const project = readResource(registry, root, join4(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
|
|
22823
22837
|
const earlyIssues = [];
|
|
22824
22838
|
validatePortablePaths(project, earlyIssues);
|
|
22825
22839
|
const templateProvenance = readTemplateProvenance(registry, root);
|
|
@@ -22841,15 +22855,15 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
22841
22855
|
}
|
|
22842
22856
|
}
|
|
22843
22857
|
if (earlyIssues.length > 0) throw new VnextConfigError(earlyIssues);
|
|
22844
|
-
const agents = listNamedResources(registry, root,
|
|
22845
|
-
const models = listNamedResources(registry, root,
|
|
22846
|
-
const workflows = listNamedResources(registry, root,
|
|
22847
|
-
const gatePath =
|
|
22858
|
+
const agents = listNamedResources(registry, root, join4(root, ".kxm", "agents"), ".kxm/agents", "agent");
|
|
22859
|
+
const models = listNamedResources(registry, root, join4(root, ".kxm", "models"), ".kxm/models", "model");
|
|
22860
|
+
const workflows = listNamedResources(registry, root, join4(root, ".kxm", "workflows"), ".kxm/workflows", "workflow");
|
|
22861
|
+
const gatePath = join4(root, ".kxm", "gates.yaml");
|
|
22848
22862
|
const gateRegistry = existsSync4(gatePath) ? readResource(registry, root, gatePath, ".kxm/gates.yaml", "gate-registry") : void 0;
|
|
22849
22863
|
const environments = [];
|
|
22850
22864
|
const repositories = /* @__PURE__ */ new Map();
|
|
22851
22865
|
const loadIssues = [];
|
|
22852
|
-
const projectEnvironment =
|
|
22866
|
+
const projectEnvironment = join4(root, ".kxm", "project", "env.yaml");
|
|
22853
22867
|
if (existsSync4(projectEnvironment)) {
|
|
22854
22868
|
try {
|
|
22855
22869
|
environments.push(readResource(registry, root, projectEnvironment, ".kxm/project/env.yaml", "environment"));
|
|
@@ -22915,7 +22929,7 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
22915
22929
|
continue;
|
|
22916
22930
|
}
|
|
22917
22931
|
seenBindings.set(foldedBinding, repositoryId);
|
|
22918
|
-
const repositoryFile =
|
|
22932
|
+
const repositoryFile = join4(binding, ".kxm", "repo", "repo.yaml");
|
|
22919
22933
|
let definitionValidated = false;
|
|
22920
22934
|
if (existsSync4(repositoryFile)) {
|
|
22921
22935
|
try {
|
|
@@ -22933,7 +22947,7 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
22933
22947
|
} else if (required || hasLocalBinding) {
|
|
22934
22948
|
loadIssues.push(issue2("discovery", "repository_definition_missing", `.kxm/repositories/${repositoryId}/repo.yaml`, `${hasLocalBinding ? "explicit" : "required"} repository ${repositoryId} has no repo.yaml`));
|
|
22935
22949
|
}
|
|
22936
|
-
const environmentFile =
|
|
22950
|
+
const environmentFile = join4(binding, ".kxm", "repo", "env.yaml");
|
|
22937
22951
|
if (existsSync4(environmentFile)) {
|
|
22938
22952
|
if (!definitionValidated) {
|
|
22939
22953
|
loadIssues.push(issue2("reference", "repository_environment_without_definition", `.kxm/repositories/${repositoryId}/env.yaml`, `repository ${repositoryId} environment requires a validated matching repo.yaml`));
|
|
@@ -23012,20 +23026,20 @@ function legacyInputsAt(root) {
|
|
|
23012
23026
|
".kxm/config/workflows",
|
|
23013
23027
|
".kxm/state/kxm.db"
|
|
23014
23028
|
];
|
|
23015
|
-
return candidates.filter((candidate) => existsSync4(
|
|
23029
|
+
return candidates.filter((candidate) => existsSync4(join4(root, ...candidate.split("/"))));
|
|
23016
23030
|
}
|
|
23017
23031
|
var VNEXT_MIGRATION_RECEIPT_PATH = ".kxm/migration-receipt.yaml";
|
|
23018
23032
|
var LEGACY_CONFIG_FILES = [".kxm/config/agents.json", ".kxm/config/gates.json"];
|
|
23019
23033
|
function legacyConfigFilesAt(root) {
|
|
23020
23034
|
const files = [];
|
|
23021
23035
|
for (const component of [".kxm", ".kxm/config"]) {
|
|
23022
|
-
const absolute =
|
|
23036
|
+
const absolute = join4(root, ...component.split("/"));
|
|
23023
23037
|
if (existsSync4(absolute) && lstatSync(absolute).isSymbolicLink()) return [component];
|
|
23024
23038
|
}
|
|
23025
23039
|
for (const candidate of LEGACY_CONFIG_FILES) {
|
|
23026
|
-
if (existsSync4(
|
|
23040
|
+
if (existsSync4(join4(root, ...candidate.split("/")))) files.push(candidate);
|
|
23027
23041
|
}
|
|
23028
|
-
const workflowsDir =
|
|
23042
|
+
const workflowsDir = join4(root, ".kxm", "config", "workflows");
|
|
23029
23043
|
if (existsSync4(workflowsDir)) {
|
|
23030
23044
|
const stat = lstatSync(workflowsDir);
|
|
23031
23045
|
if (stat.isSymbolicLink()) {
|
|
@@ -23041,9 +23055,9 @@ function legacyConfigFilesAt(root) {
|
|
|
23041
23055
|
return files;
|
|
23042
23056
|
}
|
|
23043
23057
|
function hashFileRecord(root, relativePath) {
|
|
23044
|
-
const absolute =
|
|
23058
|
+
const absolute = join4(root, ...relativePath.split("/"));
|
|
23045
23059
|
if (!existsSync4(absolute)) return void 0;
|
|
23046
|
-
const bytes =
|
|
23060
|
+
const bytes = readFileSync4(absolute);
|
|
23047
23061
|
return {
|
|
23048
23062
|
path: relativePath,
|
|
23049
23063
|
sha256: `sha256:${createHash6("sha256").update(bytes).digest("hex")}`,
|
|
@@ -23055,7 +23069,7 @@ function migrationReceiptSelfHash(receipt) {
|
|
|
23055
23069
|
return `sha256:${createHash6("sha256").update(vnextCanonicalJson(unsigned), "utf8").digest("hex")}`;
|
|
23056
23070
|
}
|
|
23057
23071
|
function readVnextMigrationReceipt(root, options = {}) {
|
|
23058
|
-
const receiptPath =
|
|
23072
|
+
const receiptPath = join4(root, ...VNEXT_MIGRATION_RECEIPT_PATH.split("/"));
|
|
23059
23073
|
const legacyFiles = legacyConfigFilesAt(root);
|
|
23060
23074
|
if (!existsSync4(receiptPath)) {
|
|
23061
23075
|
return {
|
|
@@ -23068,7 +23082,7 @@ function readVnextMigrationReceipt(root, options = {}) {
|
|
|
23068
23082
|
}
|
|
23069
23083
|
let receipt;
|
|
23070
23084
|
try {
|
|
23071
|
-
receipt = parseRestrictedYaml2(
|
|
23085
|
+
receipt = parseRestrictedYaml2(readFileSync4(receiptPath), VNEXT_MIGRATION_RECEIPT_PATH);
|
|
23072
23086
|
} catch (error) {
|
|
23073
23087
|
if (error instanceof VnextConfigError) return { issues: [...error.issues] };
|
|
23074
23088
|
throw error;
|
|
@@ -23129,7 +23143,7 @@ function planVnextInitialization(start = process.cwd(), options = {}) {
|
|
|
23129
23143
|
}
|
|
23130
23144
|
const gitRoot = discoverGitRoot(inspectedFrom);
|
|
23131
23145
|
const candidateRoot = gitRoot ?? inspectedFrom;
|
|
23132
|
-
if (existsSync4(
|
|
23146
|
+
if (existsSync4(join4(candidateRoot, ".kxm"))) {
|
|
23133
23147
|
return {
|
|
23134
23148
|
mode: "repair",
|
|
23135
23149
|
inspectedFrom,
|
|
@@ -23145,14 +23159,14 @@ function planVnextInitialization(start = process.cwd(), options = {}) {
|
|
|
23145
23159
|
// plugins/kxm/src/vnext-runtime-supervisor.ts
|
|
23146
23160
|
import { spawn as spawn2 } from "node:child_process";
|
|
23147
23161
|
import { createHash as createHash11, createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
23148
|
-
import { chmodSync as chmodSync4, existsSync as existsSync10, lstatSync as lstatSync6, mkdirSync as mkdirSync7, readFileSync as
|
|
23149
|
-
import { dirname as dirname6, isAbsolute as isAbsolute4, join as
|
|
23162
|
+
import { chmodSync as chmodSync4, existsSync as existsSync10, lstatSync as lstatSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync10, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
23163
|
+
import { dirname as dirname6, isAbsolute as isAbsolute4, join as join10, resolve as resolve7 } from "node:path";
|
|
23150
23164
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
23151
23165
|
|
|
23152
23166
|
// plugins/kxm/src/vnext-runtime-store.ts
|
|
23153
23167
|
import { createHash as createHash9, randomUUID as randomUUID4 } from "node:crypto";
|
|
23154
|
-
import { existsSync as existsSync7, lstatSync as lstatSync4, mkdirSync as mkdirSync5, readFileSync as
|
|
23155
|
-
import { dirname as dirname5, join as
|
|
23168
|
+
import { existsSync as existsSync7, lstatSync as lstatSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync7, realpathSync as realpathSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
23169
|
+
import { dirname as dirname5, join as join7, resolve as resolve5 } from "node:path";
|
|
23156
23170
|
|
|
23157
23171
|
// plugins/kxm/src/vnext-bindings.ts
|
|
23158
23172
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
@@ -23165,7 +23179,7 @@ import {
|
|
|
23165
23179
|
lstatSync as lstatSync2,
|
|
23166
23180
|
mkdirSync as mkdirSync3,
|
|
23167
23181
|
openSync,
|
|
23168
|
-
readFileSync as
|
|
23182
|
+
readFileSync as readFileSync5,
|
|
23169
23183
|
realpathSync as realpathSync2,
|
|
23170
23184
|
renameSync,
|
|
23171
23185
|
rmSync,
|
|
@@ -23213,7 +23227,7 @@ var DatabaseSync = class {
|
|
|
23213
23227
|
};
|
|
23214
23228
|
|
|
23215
23229
|
// plugins/kxm/src/vnext-bindings.ts
|
|
23216
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, join as
|
|
23230
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join5, parse, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
|
|
23217
23231
|
var MAX_BINDING_RECORD_BYTES = 256 * 1024;
|
|
23218
23232
|
var BINDING_LABEL = "Runtime-local repository bindings";
|
|
23219
23233
|
var activeLocks = /* @__PURE__ */ new WeakSet();
|
|
@@ -23247,12 +23261,12 @@ function vnextUserStateRoot(options = {}) {
|
|
|
23247
23261
|
}
|
|
23248
23262
|
if (platform === "win32") {
|
|
23249
23263
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
23250
|
-
const base2 = localAppData && isAbsolute2(localAppData) ? localAppData :
|
|
23264
|
+
const base2 = localAppData && isAbsolute2(localAppData) ? localAppData : join5(home, "AppData", "Local");
|
|
23251
23265
|
return resolve3(base2, "KXM");
|
|
23252
23266
|
}
|
|
23253
23267
|
if (platform === "darwin") return resolve3(home, "Library", "Application Support", "KXM");
|
|
23254
23268
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
23255
|
-
const base = xdgState && isAbsolute2(xdgState) ? xdgState :
|
|
23269
|
+
const base = xdgState && isAbsolute2(xdgState) ? xdgState : join5(home, ".local", "state");
|
|
23256
23270
|
return resolve3(base, "kxm");
|
|
23257
23271
|
}
|
|
23258
23272
|
function projectBindingKey(projectRoot, platform = process.platform) {
|
|
@@ -23262,7 +23276,7 @@ function projectBindingKey(projectRoot, platform = process.platform) {
|
|
|
23262
23276
|
}
|
|
23263
23277
|
function vnextLocalBindingFile(projectRoot, options = {}) {
|
|
23264
23278
|
const stateRoot = vnextUserStateRoot(options);
|
|
23265
|
-
return
|
|
23279
|
+
return join5(stateRoot, "projects", projectBindingKey(projectRoot, options.platform), "repository-bindings.json");
|
|
23266
23280
|
}
|
|
23267
23281
|
function checkedDirectory(path4, description) {
|
|
23268
23282
|
if (!existsSync5(path4)) return false;
|
|
@@ -23273,7 +23287,7 @@ function checkedDirectory(path4, description) {
|
|
|
23273
23287
|
return true;
|
|
23274
23288
|
}
|
|
23275
23289
|
function existingBindingDirectory(file, stateRoot) {
|
|
23276
|
-
const projects =
|
|
23290
|
+
const projects = join5(stateRoot, "projects");
|
|
23277
23291
|
const project = dirname3(file);
|
|
23278
23292
|
if (!checkedDirectory(stateRoot, "local state root")) return false;
|
|
23279
23293
|
if (!checkedDirectory(projects, "local projects directory")) return false;
|
|
@@ -23308,7 +23322,7 @@ function readVnextLocalBindings(projectRoot, options = {}) {
|
|
|
23308
23322
|
if (stat.size > MAX_BINDING_RECORD_BYTES) {
|
|
23309
23323
|
bindingError("parse", "local_binding_file_too_large", `binding record exceeds ${MAX_BINDING_RECORD_BYTES} bytes`);
|
|
23310
23324
|
}
|
|
23311
|
-
const parsed = parseRestrictedYaml2(
|
|
23325
|
+
const parsed = parseRestrictedYaml2(readFileSync5(file), BINDING_LABEL);
|
|
23312
23326
|
return asRecord2(parsed, file, root, options.schemasDir);
|
|
23313
23327
|
}
|
|
23314
23328
|
function normalizedRecord(projectRoot, projectId, repositories, schemasDir) {
|
|
@@ -23376,7 +23390,7 @@ function ensureBindingDirectory(file, stateRoot) {
|
|
|
23376
23390
|
ensureDurableDirectory(stateRoot, "local state root");
|
|
23377
23391
|
checkedDirectory(stateRoot, "local state root");
|
|
23378
23392
|
syncDirectory(stateRoot);
|
|
23379
|
-
const projects =
|
|
23393
|
+
const projects = join5(stateRoot, "projects");
|
|
23380
23394
|
createDirectoryIfMissing(projects);
|
|
23381
23395
|
checkedDirectory(projects, "local projects directory");
|
|
23382
23396
|
const project = dirname3(file);
|
|
@@ -23389,7 +23403,7 @@ function assertNoLinkedDirectoryComponents(path4, description) {
|
|
|
23389
23403
|
let current = filesystemRoot;
|
|
23390
23404
|
const remainder = relative2(filesystemRoot, absolute);
|
|
23391
23405
|
for (const segment of remainder.split(sep2).filter(Boolean)) {
|
|
23392
|
-
current =
|
|
23406
|
+
current = join5(current, segment);
|
|
23393
23407
|
const stat = lstatSync2(current);
|
|
23394
23408
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
23395
23409
|
bindingError("path", "project_operation_lock_parent_invalid", `${description} contains a linked or non-directory component`);
|
|
@@ -23416,7 +23430,7 @@ function projectOperationLockFile(projectRoot) {
|
|
|
23416
23430
|
if (gitStat.isSymbolicLink() || !gitStat.isDirectory()) {
|
|
23417
23431
|
bindingError("path", "project_operation_lock_parent_invalid", "authoritative Git metadata must resolve to a regular directory");
|
|
23418
23432
|
}
|
|
23419
|
-
const lockDirectory =
|
|
23433
|
+
const lockDirectory = join5(gitDirectory, "kxm");
|
|
23420
23434
|
if (existsSync5(lockDirectory)) {
|
|
23421
23435
|
const stat = lstatSync2(lockDirectory);
|
|
23422
23436
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
@@ -23426,7 +23440,7 @@ function projectOperationLockFile(projectRoot) {
|
|
|
23426
23440
|
mkdirSync3(lockDirectory, { mode: 448 });
|
|
23427
23441
|
syncDirectory(gitDirectory);
|
|
23428
23442
|
}
|
|
23429
|
-
return
|
|
23443
|
+
return join5(lockDirectory, "project-operation-lock.sqlite");
|
|
23430
23444
|
}
|
|
23431
23445
|
function withVnextLocalBindingLock(projectRoot, options, callback) {
|
|
23432
23446
|
const root = resolve3(projectRoot);
|
|
@@ -23485,7 +23499,7 @@ function writeVnextLocalBindings(projectRoot, projectId, repositories, options =
|
|
|
23485
23499
|
const { file, record } = planned;
|
|
23486
23500
|
if (!planned.written) return planned;
|
|
23487
23501
|
ensureBindingDirectory(file, vnextUserStateRoot(options));
|
|
23488
|
-
const temporary =
|
|
23502
|
+
const temporary = join5(dirname3(file), `.repository-bindings-${process.pid}-${randomUUID3()}.tmp`);
|
|
23489
23503
|
let descriptor;
|
|
23490
23504
|
try {
|
|
23491
23505
|
descriptor = openSync(temporary, "wx", 384);
|
|
@@ -23516,11 +23530,11 @@ import {
|
|
|
23516
23530
|
lstatSync as lstatSync3,
|
|
23517
23531
|
mkdirSync as mkdirSync4,
|
|
23518
23532
|
readdirSync as readdirSync2,
|
|
23519
|
-
readFileSync as
|
|
23533
|
+
readFileSync as readFileSync6,
|
|
23520
23534
|
unlinkSync as unlinkSync2,
|
|
23521
23535
|
writeFileSync as writeFileSync4
|
|
23522
23536
|
} from "node:fs";
|
|
23523
|
-
import { basename as
|
|
23537
|
+
import { basename as basename3, dirname as dirname4, join as join6, resolve as resolve4 } from "node:path";
|
|
23524
23538
|
function databaseError(code, file, message) {
|
|
23525
23539
|
const issue3 = { phase: "semantic", code, file, message };
|
|
23526
23540
|
return new VnextConfigError([issue3]);
|
|
@@ -23669,7 +23683,7 @@ function checkIntegrity(database) {
|
|
|
23669
23683
|
return rows.length === 1 && rows[0]?.integrity_check === "ok";
|
|
23670
23684
|
}
|
|
23671
23685
|
function fileSha256(filePath) {
|
|
23672
|
-
const bytes =
|
|
23686
|
+
const bytes = readFileSync6(filePath);
|
|
23673
23687
|
return `sha256:${createHash8("sha256").update(bytes).digest("hex")}`;
|
|
23674
23688
|
}
|
|
23675
23689
|
function backupDatabaseFile(sourcePath, targetPath, storeId) {
|
|
@@ -23716,7 +23730,7 @@ function backupDatabaseFile(sourcePath, targetPath, storeId) {
|
|
|
23716
23730
|
return {
|
|
23717
23731
|
storeId,
|
|
23718
23732
|
sourcePath: resolvedSource,
|
|
23719
|
-
backupFile:
|
|
23733
|
+
backupFile: basename3(resolvedTarget),
|
|
23720
23734
|
schemaVersion,
|
|
23721
23735
|
sha256,
|
|
23722
23736
|
bytes,
|
|
@@ -23782,7 +23796,7 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
|
|
|
23782
23796
|
return {
|
|
23783
23797
|
storeId,
|
|
23784
23798
|
sourcePath: resolvedTarget,
|
|
23785
|
-
backupFile:
|
|
23799
|
+
backupFile: basename3(resolvedBackup),
|
|
23786
23800
|
schemaVersion,
|
|
23787
23801
|
integrity: "ok"
|
|
23788
23802
|
};
|
|
@@ -23790,19 +23804,19 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
|
|
|
23790
23804
|
function discoverProjectStores(projectRoot, options = {}) {
|
|
23791
23805
|
const root = resolve4(projectRoot);
|
|
23792
23806
|
const stores = [];
|
|
23793
|
-
const hubPath = options.hubDataPath ? resolve4(options.hubDataPath) :
|
|
23807
|
+
const hubPath = options.hubDataPath ? resolve4(options.hubDataPath) : join6(root, ".kxm", "state", "kxm.db");
|
|
23794
23808
|
if (existsSync6(hubPath)) {
|
|
23795
23809
|
stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: 3 });
|
|
23796
23810
|
}
|
|
23797
|
-
const registryPath =
|
|
23811
|
+
const registryPath = join6(root, ".kxm", "runtime", "registry.db");
|
|
23798
23812
|
if (existsSync6(registryPath)) {
|
|
23799
23813
|
stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: 1 });
|
|
23800
23814
|
}
|
|
23801
|
-
const bindingsPath =
|
|
23815
|
+
const bindingsPath = join6(root, ".kxm", "runtime", "bindings.db");
|
|
23802
23816
|
if (existsSync6(bindingsPath)) {
|
|
23803
23817
|
stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: 1 });
|
|
23804
23818
|
}
|
|
23805
|
-
const eventsDir =
|
|
23819
|
+
const eventsDir = join6(root, ".kxm", "runtime", "events");
|
|
23806
23820
|
if (existsSync6(eventsDir)) {
|
|
23807
23821
|
const entries = readdirSync2(eventsDir, { withFileTypes: true });
|
|
23808
23822
|
for (const entry of entries) {
|
|
@@ -23810,7 +23824,7 @@ function discoverProjectStores(projectRoot, options = {}) {
|
|
|
23810
23824
|
const key = entry.name.replace(/\.db$/, "");
|
|
23811
23825
|
stores.push({
|
|
23812
23826
|
storeId: `events:${key}`,
|
|
23813
|
-
sourcePath:
|
|
23827
|
+
sourcePath: join6(eventsDir, entry.name),
|
|
23814
23828
|
maxSupportedVersion: 3
|
|
23815
23829
|
});
|
|
23816
23830
|
}
|
|
@@ -23829,20 +23843,20 @@ function createBackup(options = {}) {
|
|
|
23829
23843
|
const now = /* @__PURE__ */ new Date();
|
|
23830
23844
|
const timestamp = now.toISOString().replace(/[:.]/g, "-");
|
|
23831
23845
|
const backupId = `bk_${randomBytes(8).toString("hex")}`;
|
|
23832
|
-
const outDir = options.outDir ? resolve4(options.outDir) :
|
|
23846
|
+
const outDir = options.outDir ? resolve4(options.outDir) : join6(projectRoot, ".kxm", "backups", `backup-${timestamp}`);
|
|
23833
23847
|
if (!existsSync6(outDir)) {
|
|
23834
23848
|
mkdirSync4(outDir, { recursive: true, mode: 448 });
|
|
23835
23849
|
}
|
|
23836
23850
|
const backedUpStores = [];
|
|
23837
23851
|
const usedFilenames = /* @__PURE__ */ new Set();
|
|
23838
23852
|
for (const store of stores) {
|
|
23839
|
-
let filename =
|
|
23853
|
+
let filename = basename3(store.sourcePath);
|
|
23840
23854
|
if (usedFilenames.has(filename)) {
|
|
23841
23855
|
const sanitizedId = store.storeId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
23842
23856
|
filename = `${sanitizedId}-${filename}`;
|
|
23843
23857
|
}
|
|
23844
23858
|
usedFilenames.add(filename);
|
|
23845
|
-
const targetFile2 =
|
|
23859
|
+
const targetFile2 = join6(outDir, filename);
|
|
23846
23860
|
const record = backupDatabaseFile(store.sourcePath, targetFile2, store.storeId);
|
|
23847
23861
|
backedUpStores.push(record);
|
|
23848
23862
|
}
|
|
@@ -23857,7 +23871,7 @@ function createBackup(options = {}) {
|
|
|
23857
23871
|
const manifestSha256 = `sha256:${createHash8("sha256").update(manifestJson, "utf8").digest("hex")}`;
|
|
23858
23872
|
manifest.manifestSha256 = manifestSha256;
|
|
23859
23873
|
const finalJson = JSON.stringify(manifest, null, 2) + "\n";
|
|
23860
|
-
const manifestPath =
|
|
23874
|
+
const manifestPath = join6(outDir, "manifest.json");
|
|
23861
23875
|
writeFileSync4(manifestPath, finalJson, "utf8");
|
|
23862
23876
|
return { manifest, outDir };
|
|
23863
23877
|
}
|
|
@@ -23868,13 +23882,13 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
23868
23882
|
throw databaseError("runtime_path_invalid", manifestPath, `manifest path ${manifestPath} does not exist`);
|
|
23869
23883
|
}
|
|
23870
23884
|
if (stat.isDirectory()) {
|
|
23871
|
-
manifestPath =
|
|
23885
|
+
manifestPath = join6(manifestPath, "manifest.json");
|
|
23872
23886
|
}
|
|
23873
23887
|
if (!existsSync6(manifestPath)) {
|
|
23874
23888
|
throw databaseError("runtime_path_invalid", manifestPath, `backup manifest ${manifestPath} not found`);
|
|
23875
23889
|
}
|
|
23876
23890
|
const manifestDir = dirname4(manifestPath);
|
|
23877
|
-
const rawText =
|
|
23891
|
+
const rawText = readFileSync6(manifestPath, "utf8");
|
|
23878
23892
|
let manifest;
|
|
23879
23893
|
try {
|
|
23880
23894
|
manifest = JSON.parse(rawText);
|
|
@@ -23886,7 +23900,7 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
23886
23900
|
}
|
|
23887
23901
|
const restoredStores = [];
|
|
23888
23902
|
for (const store of manifest.stores) {
|
|
23889
|
-
const backupFilePath =
|
|
23903
|
+
const backupFilePath = join6(manifestDir, store.backupFile);
|
|
23890
23904
|
if (!existsSync6(backupFilePath)) {
|
|
23891
23905
|
throw databaseError("restore_file_missing", backupFilePath, `backup file ${store.backupFile} missing from ${manifestDir}`);
|
|
23892
23906
|
}
|
|
@@ -23905,7 +23919,7 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
23905
23919
|
let targetPath = store.sourcePath;
|
|
23906
23920
|
if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
|
|
23907
23921
|
const rel = targetPath.slice(manifest.projectRoot.length).replace(/^[\\/]+/, "");
|
|
23908
|
-
targetPath =
|
|
23922
|
+
targetPath = join6(resolve4(options.projectRoot), rel);
|
|
23909
23923
|
}
|
|
23910
23924
|
const result = restoreDatabaseFile(
|
|
23911
23925
|
backupFilePath,
|
|
@@ -23926,12 +23940,12 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
23926
23940
|
// plugins/kxm/src/vnext-runtime-store.ts
|
|
23927
23941
|
function vnextRuntimePaths(options = {}) {
|
|
23928
23942
|
const stateRoot = options.stateRoot ? resolve5(options.stateRoot) : vnextUserStateRoot({ ...options.env ? { env: options.env } : {}, ...options.homeDir ? { homeDir: options.homeDir } : {} });
|
|
23929
|
-
const runtimeDir =
|
|
23943
|
+
const runtimeDir = join7(stateRoot, "runtime");
|
|
23930
23944
|
return {
|
|
23931
23945
|
stateRoot,
|
|
23932
23946
|
runtimeDir,
|
|
23933
|
-
registryDb:
|
|
23934
|
-
projectsDir:
|
|
23947
|
+
registryDb: join7(runtimeDir, "registry.db"),
|
|
23948
|
+
projectsDir: join7(runtimeDir, "projects")
|
|
23935
23949
|
};
|
|
23936
23950
|
}
|
|
23937
23951
|
function runtimeIssue(phase, code, file, message) {
|
|
@@ -24290,7 +24304,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
24290
24304
|
const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
|
|
24291
24305
|
const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
|
|
24292
24306
|
const assignments = compileAssignments(step, id, agent, sink);
|
|
24293
|
-
const
|
|
24307
|
+
const join48 = compileJoin(step, id, sink);
|
|
24294
24308
|
const requiredEvidence = compileEvidence(step, id, sink);
|
|
24295
24309
|
const transitions = compileTransitions(step, id, index, stepIndex, sink);
|
|
24296
24310
|
const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
|
|
@@ -24318,7 +24332,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
24318
24332
|
transitions: orderedTransitions,
|
|
24319
24333
|
requiresPlanHash: requirePlanHash.includes(id),
|
|
24320
24334
|
assignments,
|
|
24321
|
-
join:
|
|
24335
|
+
join: join48
|
|
24322
24336
|
};
|
|
24323
24337
|
if (kind === "agent" || kind === "moa") {
|
|
24324
24338
|
if (!agent) return void 0;
|
|
@@ -24368,15 +24382,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
|
|
|
24368
24382
|
};
|
|
24369
24383
|
}
|
|
24370
24384
|
function compileJoin(step, stepId, sink) {
|
|
24371
|
-
const
|
|
24372
|
-
if (!
|
|
24373
|
-
const declared = stringValue2(
|
|
24385
|
+
const join48 = objectValue2(step.join);
|
|
24386
|
+
if (!join48) return { strategy: "all" };
|
|
24387
|
+
const declared = stringValue2(join48.strategy);
|
|
24374
24388
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
24375
|
-
const minimumPassed = compileOptionalCount(
|
|
24389
|
+
const minimumPassed = compileOptionalCount(join48.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
24376
24390
|
const compiled = {
|
|
24377
24391
|
strategy,
|
|
24378
24392
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
24379
|
-
...typeof
|
|
24393
|
+
...typeof join48.cancelRemaining === "boolean" ? { cancelRemaining: join48.cancelRemaining } : {}
|
|
24380
24394
|
};
|
|
24381
24395
|
return compiled;
|
|
24382
24396
|
}
|
|
@@ -24656,8 +24670,8 @@ var RECORD_LIMIT = 16 * 1024 * 1024;
|
|
|
24656
24670
|
// plugins/kxm/src/prices.ts
|
|
24657
24671
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
24658
24672
|
import { createHash as createHash10 } from "node:crypto";
|
|
24659
|
-
import { existsSync as existsSync8, readFileSync as
|
|
24660
|
-
import { join as
|
|
24673
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8, statSync } from "node:fs";
|
|
24674
|
+
import { join as join8 } from "node:path";
|
|
24661
24675
|
|
|
24662
24676
|
// plugins/kxm/src/price-calc.ts
|
|
24663
24677
|
var PRICES_SCHEMA = "kxm.prices.v1";
|
|
@@ -24809,11 +24823,11 @@ function parsePriceCatalog(text) {
|
|
|
24809
24823
|
return catalog;
|
|
24810
24824
|
}
|
|
24811
24825
|
function loadPriceCatalog(rootOrPath) {
|
|
24812
|
-
const candidatePath = existsSync8(
|
|
24826
|
+
const candidatePath = existsSync8(join8(rootOrPath, ".kxm", "prices.yaml")) ? join8(rootOrPath, ".kxm", "prices.yaml") : existsSync8(join8(rootOrPath, "prices.yaml")) ? join8(rootOrPath, "prices.yaml") : existsSync8(rootOrPath) && statSync(rootOrPath).isFile() ? rootOrPath : void 0;
|
|
24813
24827
|
if (!candidatePath || !existsSync8(candidatePath)) {
|
|
24814
24828
|
return void 0;
|
|
24815
24829
|
}
|
|
24816
|
-
const content =
|
|
24830
|
+
const content = readFileSync8(candidatePath, "utf8");
|
|
24817
24831
|
return parsePriceCatalog(content);
|
|
24818
24832
|
}
|
|
24819
24833
|
function loadPriceCatalogForEstimate(options) {
|
|
@@ -24834,13 +24848,13 @@ var import_yaml5 = __toESM(require_dist(), 1);
|
|
|
24834
24848
|
|
|
24835
24849
|
// plugins/kxm/src/producers.ts
|
|
24836
24850
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
24837
|
-
import { existsSync as existsSync9, readFileSync as
|
|
24838
|
-
import { join as
|
|
24851
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, readdirSync as readdirSync3 } from "node:fs";
|
|
24852
|
+
import { join as join9 } from "node:path";
|
|
24839
24853
|
var empty = () => ({ schema: "kxm.producers.v1", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), promoted: [], demoted: [], enabled: [], disabled: [], roles: {} });
|
|
24840
24854
|
function loadProducerPolicy(root) {
|
|
24841
|
-
const path4 =
|
|
24855
|
+
const path4 = join9(root, ".kxm", "producers.yaml");
|
|
24842
24856
|
if (!existsSync9(path4)) return empty();
|
|
24843
|
-
const value = (0, import_yaml4.parse)(
|
|
24857
|
+
const value = (0, import_yaml4.parse)(readFileSync9(path4, "utf8"));
|
|
24844
24858
|
if (value?.schema !== "kxm.producers.v1" || !Array.isArray(value.promoted) || !Array.isArray(value.demoted)) throw new Error("invalid .kxm/producers.yaml");
|
|
24845
24859
|
return { schema: "kxm.producers.v1", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), promoted: value.promoted.filter((x2) => typeof x2 === "string"), demoted: value.demoted.filter((x2) => typeof x2 === "string"), enabled: Array.isArray(value.enabled) ? value.enabled.filter((x2) => typeof x2 === "string") : [], disabled: Array.isArray(value.disabled) ? value.disabled.filter((x2) => typeof x2 === "string") : [], roles: value.roles && typeof value.roles === "object" ? Object.fromEntries(Object.entries(value.roles).filter(([, v2]) => Array.isArray(v2)).map(([k, v2]) => [k, v2.filter((x2) => typeof x2 === "string")])) : {} };
|
|
24846
24860
|
}
|
|
@@ -24850,8 +24864,8 @@ function updateProducer(root, model, status) {
|
|
|
24850
24864
|
policy.demoted = policy.demoted.filter((x2) => x2 !== model);
|
|
24851
24865
|
policy[status].push(model);
|
|
24852
24866
|
policy.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
24853
|
-
mkdirSync6(
|
|
24854
|
-
writeFileSync6(
|
|
24867
|
+
mkdirSync6(join9(root, ".kxm"), { recursive: true });
|
|
24868
|
+
writeFileSync6(join9(root, ".kxm", "producers.yaml"), (0, import_yaml4.stringify)(policy), "utf8");
|
|
24855
24869
|
return policy;
|
|
24856
24870
|
}
|
|
24857
24871
|
function setModelState(root, model, state, role, removeRole2 = false) {
|
|
@@ -24861,10 +24875,10 @@ function setModelState(root, model, state, role, removeRole2 = false) {
|
|
|
24861
24875
|
policy[state].push(model);
|
|
24862
24876
|
if (role) {
|
|
24863
24877
|
if (!/^[a-z][a-z0-9_-]{0,63}$/i.test(role)) throw new Error("invalid role id");
|
|
24864
|
-
const rolePath =
|
|
24878
|
+
const rolePath = join9(root, ".kxm", "roles", `${role}.yaml`);
|
|
24865
24879
|
let roleFile = {};
|
|
24866
24880
|
if (existsSync9(rolePath)) {
|
|
24867
|
-
const parsed = (0, import_yaml4.parse)(
|
|
24881
|
+
const parsed = (0, import_yaml4.parse)(readFileSync9(rolePath, "utf8"));
|
|
24868
24882
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) roleFile = parsed;
|
|
24869
24883
|
}
|
|
24870
24884
|
const roster = Array.isArray(roleFile.roster) ? roleFile.roster.filter((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry)) : [];
|
|
@@ -24875,29 +24889,29 @@ function setModelState(root, model, state, role, removeRole2 = false) {
|
|
|
24875
24889
|
roleFile.schema ??= "kxm.role.v1";
|
|
24876
24890
|
roleFile.id ??= role;
|
|
24877
24891
|
roleFile.roster = roster;
|
|
24878
|
-
mkdirSync6(
|
|
24892
|
+
mkdirSync6(join9(root, ".kxm", "roles"), { recursive: true });
|
|
24879
24893
|
writeFileSync6(rolePath, (0, import_yaml4.stringify)(roleFile), "utf8");
|
|
24880
24894
|
}
|
|
24881
24895
|
policy.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
24882
|
-
mkdirSync6(
|
|
24883
|
-
writeFileSync6(
|
|
24896
|
+
mkdirSync6(join9(root, ".kxm"), { recursive: true });
|
|
24897
|
+
writeFileSync6(join9(root, ".kxm", "producers.yaml"), (0, import_yaml4.stringify)(policy), "utf8");
|
|
24884
24898
|
return policy;
|
|
24885
24899
|
}
|
|
24886
24900
|
function listRoleBindings(root) {
|
|
24887
|
-
const dir =
|
|
24901
|
+
const dir = join9(root, ".kxm", "roles");
|
|
24888
24902
|
const result = {};
|
|
24889
24903
|
if (!existsSync9(dir)) return result;
|
|
24890
24904
|
for (const file of readdirSync3(dir).filter((name) => name.endsWith(".yaml"))) {
|
|
24891
24905
|
const role = file.slice(0, -5);
|
|
24892
|
-
const value = (0, import_yaml4.parse)(
|
|
24906
|
+
const value = (0, import_yaml4.parse)(readFileSync9(join9(dir, file), "utf8"));
|
|
24893
24907
|
result[role] = (value.roster ?? []).map((entry) => entry.model).filter((model) => typeof model === "string");
|
|
24894
24908
|
}
|
|
24895
24909
|
return result;
|
|
24896
24910
|
}
|
|
24897
24911
|
function listInventoryModels(root) {
|
|
24898
|
-
const path4 =
|
|
24912
|
+
const path4 = join9(root, ".kxm", "models", "inventory.yaml");
|
|
24899
24913
|
if (!existsSync9(path4)) return [];
|
|
24900
|
-
const value = (0, import_yaml4.parse)(
|
|
24914
|
+
const value = (0, import_yaml4.parse)(readFileSync9(path4, "utf8"));
|
|
24901
24915
|
return (value.models ?? []).map((m2) => m2.id).filter((id) => typeof id === "string");
|
|
24902
24916
|
}
|
|
24903
24917
|
|
|
@@ -25531,7 +25545,7 @@ function formatRoutingReport(report2, options = {}) {
|
|
|
25531
25545
|
// plugins/kxm/src/vnext-runtime-supervisor.ts
|
|
25532
25546
|
var repoRoot = resolve7(fileURLToPath2(new URL("../../../", import.meta.url)));
|
|
25533
25547
|
function vnextSupervisorTokenFile(paths) {
|
|
25534
|
-
return
|
|
25548
|
+
return join10(paths.runtimeDir, "supervisor.token");
|
|
25535
25549
|
}
|
|
25536
25550
|
function readVnextSupervisorToken(paths) {
|
|
25537
25551
|
const file = vnextSupervisorTokenFile(paths);
|
|
@@ -25540,7 +25554,7 @@ function readVnextSupervisorToken(paths) {
|
|
|
25540
25554
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
25541
25555
|
throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
|
|
25542
25556
|
}
|
|
25543
|
-
const token =
|
|
25557
|
+
const token = readFileSync10(file, "utf8").trim();
|
|
25544
25558
|
return token.length >= 32 ? token : void 0;
|
|
25545
25559
|
}
|
|
25546
25560
|
function processAlive(pid) {
|
|
@@ -25554,7 +25568,7 @@ function processAlive(pid) {
|
|
|
25554
25568
|
var HEARTBEAT_STALE_MS = 15e3;
|
|
25555
25569
|
var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
|
|
25556
25570
|
function supervisorErrorFile(paths) {
|
|
25557
|
-
return
|
|
25571
|
+
return join10(paths.runtimeDir, "supervisor.error");
|
|
25558
25572
|
}
|
|
25559
25573
|
function clearSupervisorError(paths) {
|
|
25560
25574
|
const file = supervisorErrorFile(paths);
|
|
@@ -25567,7 +25581,7 @@ function readRecentSupervisorError(paths) {
|
|
|
25567
25581
|
const ageMs = Date.now() - stat.mtimeMs;
|
|
25568
25582
|
if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
|
|
25569
25583
|
try {
|
|
25570
|
-
return
|
|
25584
|
+
return readFileSync10(file, "utf8").trim();
|
|
25571
25585
|
} catch {
|
|
25572
25586
|
return void 0;
|
|
25573
25587
|
}
|
|
@@ -25634,7 +25648,7 @@ async function ensureVnextSupervisor(options = {}) {
|
|
|
25634
25648
|
throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
|
|
25635
25649
|
}
|
|
25636
25650
|
clearSupervisorError(paths);
|
|
25637
|
-
const scriptPath =
|
|
25651
|
+
const scriptPath = join10(repoRoot, "scripts", "kxm-runtime-supervisor.mjs");
|
|
25638
25652
|
const spawnImpl = options.spawnImpl ?? ((script, env) => {
|
|
25639
25653
|
const child = spawn2(process.execPath, [script], {
|
|
25640
25654
|
detached: true,
|
|
@@ -25687,7 +25701,7 @@ async function vnextRuntimeRequest(handle, method, path4, body) {
|
|
|
25687
25701
|
|
|
25688
25702
|
// plugins/kxm/src/cli/types.ts
|
|
25689
25703
|
import { spawn as spawn3 } from "node:child_process";
|
|
25690
|
-
import { join as
|
|
25704
|
+
import { join as join13, resolve as resolve9 } from "node:path";
|
|
25691
25705
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
25692
25706
|
|
|
25693
25707
|
// plugins/kxm/src/redact.ts
|
|
@@ -25718,8 +25732,8 @@ function redactStringList(values, maxItems = 32) {
|
|
|
25718
25732
|
}
|
|
25719
25733
|
|
|
25720
25734
|
// plugins/kxm/src/telemetry.ts
|
|
25721
|
-
import { appendFileSync, mkdirSync as mkdirSync8, readFileSync as
|
|
25722
|
-
import { dirname as dirname7, join as
|
|
25735
|
+
import { appendFileSync, mkdirSync as mkdirSync8, readFileSync as readFileSync11 } from "node:fs";
|
|
25736
|
+
import { dirname as dirname7, join as join11 } from "node:path";
|
|
25723
25737
|
var TELEMETRY_SCHEMA = "kxm.telemetry.v1";
|
|
25724
25738
|
function inferImprovementTarget(input) {
|
|
25725
25739
|
const explicit = input.env?.KXM_IMPROVE_TARGET?.trim();
|
|
@@ -25734,7 +25748,7 @@ function appendTelemetry(path4, event) {
|
|
|
25734
25748
|
`, { encoding: "utf8", mode: 384 });
|
|
25735
25749
|
}
|
|
25736
25750
|
function telemetryPath(logsDir) {
|
|
25737
|
-
return
|
|
25751
|
+
return join11(logsDir, "telemetry.jsonl");
|
|
25738
25752
|
}
|
|
25739
25753
|
function makeTelemetryEvent(input) {
|
|
25740
25754
|
return {
|
|
@@ -25749,7 +25763,7 @@ function makeTelemetryEvent(input) {
|
|
|
25749
25763
|
function readRoutingRecords(path4) {
|
|
25750
25764
|
const records = [];
|
|
25751
25765
|
try {
|
|
25752
|
-
const raw =
|
|
25766
|
+
const raw = readFileSync11(path4, "utf8");
|
|
25753
25767
|
for (const line of raw.split(/\r?\n/)) {
|
|
25754
25768
|
if (!line.trim()) continue;
|
|
25755
25769
|
try {
|
|
@@ -25826,9 +25840,9 @@ function workerResult(worker, payload) {
|
|
|
25826
25840
|
}
|
|
25827
25841
|
|
|
25828
25842
|
// plugins/kxm/src/hub-binding.ts
|
|
25829
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as
|
|
25843
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync12, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
25830
25844
|
import { homedir as homedir3 } from "node:os";
|
|
25831
|
-
import { dirname as dirname8, isAbsolute as isAbsolute5, join as
|
|
25845
|
+
import { dirname as dirname8, isAbsolute as isAbsolute5, join as join12, resolve as resolve8 } from "node:path";
|
|
25832
25846
|
var HUB_BINDING_SCHEMA = "kxm.hub-binding.v1";
|
|
25833
25847
|
var HUB_HEALTH_PROBE_MS = 300;
|
|
25834
25848
|
var HubBindingError = class extends Error {
|
|
@@ -25845,16 +25859,16 @@ function resolveUserStateRoot(env) {
|
|
|
25845
25859
|
}
|
|
25846
25860
|
if (process.platform === "win32") {
|
|
25847
25861
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
25848
|
-
const base2 = localAppData && isAbsolute5(localAppData) ? localAppData :
|
|
25862
|
+
const base2 = localAppData && isAbsolute5(localAppData) ? localAppData : join12(homedir3(), "AppData", "Local");
|
|
25849
25863
|
return resolve8(base2, "KXM");
|
|
25850
25864
|
}
|
|
25851
25865
|
if (process.platform === "darwin") return resolve8(homedir3(), "Library", "Application Support", "KXM");
|
|
25852
25866
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
25853
|
-
const base = xdgState && isAbsolute5(xdgState) ? xdgState :
|
|
25867
|
+
const base = xdgState && isAbsolute5(xdgState) ? xdgState : join12(homedir3(), ".local", "state");
|
|
25854
25868
|
return resolve8(base, "kxm");
|
|
25855
25869
|
}
|
|
25856
25870
|
function hubBindingFile(env = process.env) {
|
|
25857
|
-
return
|
|
25871
|
+
return join12(resolveUserStateRoot(env), "hub-binding.json");
|
|
25858
25872
|
}
|
|
25859
25873
|
function validateHubUrl(raw) {
|
|
25860
25874
|
let parsed;
|
|
@@ -25882,7 +25896,7 @@ function readHubBinding(env = process.env) {
|
|
|
25882
25896
|
if (!existsSync11(file)) return void 0;
|
|
25883
25897
|
let parsed;
|
|
25884
25898
|
try {
|
|
25885
|
-
parsed = JSON.parse(
|
|
25899
|
+
parsed = JSON.parse(readFileSync12(file, "utf8"));
|
|
25886
25900
|
} catch {
|
|
25887
25901
|
throw new HubBindingError(`malformed hub binding at ${file}`);
|
|
25888
25902
|
}
|
|
@@ -25905,7 +25919,7 @@ function readHubBinding(env = process.env) {
|
|
|
25905
25919
|
function writeHubBinding(record, env = process.env) {
|
|
25906
25920
|
const file = hubBindingFile(env);
|
|
25907
25921
|
mkdirSync9(dirname8(file), { recursive: true, mode: 448 });
|
|
25908
|
-
const temporary =
|
|
25922
|
+
const temporary = join12(dirname8(file), `.hub-binding-${process.pid}.tmp`);
|
|
25909
25923
|
try {
|
|
25910
25924
|
writeFileSync8(temporary, `${JSON.stringify(record, null, 2)}
|
|
25911
25925
|
`, { encoding: "utf8", mode: 384 });
|
|
@@ -25953,7 +25967,7 @@ async function probeHubHealth(url, fetchImpl, timeoutMs = HUB_HEALTH_PROBE_MS) {
|
|
|
25953
25967
|
var repoRoot2 = resolve9(fileURLToPath3(new URL("../../../../", import.meta.url)));
|
|
25954
25968
|
function spawnScript(scriptName, extraEnv = {}) {
|
|
25955
25969
|
return new Promise((resolveExit) => {
|
|
25956
|
-
const child = spawn3(process.execPath, [
|
|
25970
|
+
const child = spawn3(process.execPath, [join13(repoRoot2, "scripts", scriptName)], {
|
|
25957
25971
|
stdio: "inherit",
|
|
25958
25972
|
env: { ...process.env, ...extraEnv }
|
|
25959
25973
|
});
|
|
@@ -26043,10 +26057,10 @@ function workspaceDirs(cwd, workspaceFlag, env) {
|
|
|
26043
26057
|
return {
|
|
26044
26058
|
workdir,
|
|
26045
26059
|
workspace,
|
|
26046
|
-
config: derive ?
|
|
26047
|
-
logs: derive ?
|
|
26048
|
-
assets: derive ?
|
|
26049
|
-
state: derive ?
|
|
26060
|
+
config: derive ? join13(workspace, "config") : resolve9(workdir, env.KXM_CONFIG_DIR?.trim() || join13(workspace, "config")),
|
|
26061
|
+
logs: derive ? join13(workspace, "logs") : resolve9(workdir, env.KXM_LOGS_DIR?.trim() || join13(workspace, "logs")),
|
|
26062
|
+
assets: derive ? join13(workspace, "assets") : resolve9(workdir, env.KXM_ASSETS_DIR?.trim() || join13(workspace, "assets")),
|
|
26063
|
+
state: derive ? join13(workspace, "state") : resolve9(workdir, env.KXM_STATE_DIR?.trim() || join13(workspace, "state"))
|
|
26050
26064
|
};
|
|
26051
26065
|
}
|
|
26052
26066
|
function maskEnvName(name) {
|
|
@@ -26114,20 +26128,20 @@ function workspaceEnv(runtime) {
|
|
|
26114
26128
|
// plugins/kxm/src/cli/roles.ts
|
|
26115
26129
|
var import_yaml8 = __toESM(require_dist(), 1);
|
|
26116
26130
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
26117
|
-
import { existsSync as existsSync14, readFileSync as
|
|
26118
|
-
import { join as
|
|
26131
|
+
import { existsSync as existsSync14, readFileSync as readFileSync15 } from "node:fs";
|
|
26132
|
+
import { join as join16, resolve as resolve12 } from "node:path";
|
|
26119
26133
|
import { createInterface } from "node:readline";
|
|
26120
26134
|
|
|
26121
26135
|
// plugins/kxm/src/role.ts
|
|
26122
26136
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
26123
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync11, readdirSync as readdirSync4, readFileSync as
|
|
26124
|
-
import { join as
|
|
26137
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync11, readdirSync as readdirSync4, readFileSync as readFileSync14, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
|
|
26138
|
+
import { join as join15 } from "node:path";
|
|
26125
26139
|
|
|
26126
26140
|
// plugins/kxm/src/config.ts
|
|
26127
26141
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
26128
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as
|
|
26142
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
|
|
26129
26143
|
import { homedir as homedir4 } from "node:os";
|
|
26130
|
-
import { dirname as dirname9, join as
|
|
26144
|
+
import { dirname as dirname9, join as join14, resolve as resolve10 } from "node:path";
|
|
26131
26145
|
var KXM_CONFIG_SCHEMA = "kxm.config.v1";
|
|
26132
26146
|
var DEFAULT_KXM_CONFIG = {
|
|
26133
26147
|
schema: KXM_CONFIG_SCHEMA,
|
|
@@ -26148,6 +26162,9 @@ var DEFAULT_KXM_CONFIG = {
|
|
|
26148
26162
|
sync: {
|
|
26149
26163
|
defaultTracker: "none"
|
|
26150
26164
|
},
|
|
26165
|
+
hub: {
|
|
26166
|
+
autoStart: "background"
|
|
26167
|
+
},
|
|
26151
26168
|
improvement: {
|
|
26152
26169
|
promotionPolicy: "manual_pr",
|
|
26153
26170
|
telemetryHalfLifeDays: 14,
|
|
@@ -26178,7 +26195,7 @@ var DEFAULT_KXM_CONFIG = {
|
|
|
26178
26195
|
};
|
|
26179
26196
|
function userConfigDirectory(overrideDir) {
|
|
26180
26197
|
if (overrideDir) return resolve10(overrideDir);
|
|
26181
|
-
return resolve10(process.env.KXM_USER_CONFIG_DIR?.trim() ||
|
|
26198
|
+
return resolve10(process.env.KXM_USER_CONFIG_DIR?.trim() || join14(homedir4(), ".config", "kxm"));
|
|
26182
26199
|
}
|
|
26183
26200
|
function repoConfigDirectory(repoRoot6) {
|
|
26184
26201
|
return resolve10(repoRoot6, ".kxm");
|
|
@@ -26195,16 +26212,20 @@ function deepMerge(target, source) {
|
|
|
26195
26212
|
}
|
|
26196
26213
|
return result;
|
|
26197
26214
|
}
|
|
26215
|
+
function normalizeHubConfig(raw) {
|
|
26216
|
+
const autoStart = raw?.autoStart;
|
|
26217
|
+
return { autoStart: autoStart === "off" || autoStart === "background" ? autoStart : DEFAULT_KXM_CONFIG.hub.autoStart };
|
|
26218
|
+
}
|
|
26198
26219
|
function loadKxmConfig(repoRoot6 = process.cwd(), options = {}) {
|
|
26199
26220
|
const userDir = userConfigDirectory(options.userConfigDir);
|
|
26200
|
-
const userConfigFile =
|
|
26221
|
+
const userConfigFile = join14(userDir, "config.yaml");
|
|
26201
26222
|
const repoDir = repoConfigDirectory(repoRoot6);
|
|
26202
|
-
const repoConfigFile =
|
|
26223
|
+
const repoConfigFile = join14(repoDir, "config.yaml");
|
|
26203
26224
|
let userRaw = {};
|
|
26204
26225
|
let userLoadedPath;
|
|
26205
26226
|
if (existsSync12(userConfigFile)) {
|
|
26206
26227
|
try {
|
|
26207
|
-
const text =
|
|
26228
|
+
const text = readFileSync13(userConfigFile, "utf8");
|
|
26208
26229
|
userRaw = (0, import_yaml6.parse)(text) ?? {};
|
|
26209
26230
|
userLoadedPath = userConfigFile;
|
|
26210
26231
|
} catch (error) {
|
|
@@ -26215,7 +26236,7 @@ function loadKxmConfig(repoRoot6 = process.cwd(), options = {}) {
|
|
|
26215
26236
|
let repoLoadedPath;
|
|
26216
26237
|
if (existsSync12(repoConfigFile)) {
|
|
26217
26238
|
try {
|
|
26218
|
-
const text =
|
|
26239
|
+
const text = readFileSync13(repoConfigFile, "utf8");
|
|
26219
26240
|
repoRaw = (0, import_yaml6.parse)(text) ?? {};
|
|
26220
26241
|
repoLoadedPath = repoConfigFile;
|
|
26221
26242
|
} catch (error) {
|
|
@@ -26231,6 +26252,7 @@ function loadKxmConfig(repoRoot6 = process.cwd(), options = {}) {
|
|
|
26231
26252
|
defaults: mergedAll.defaults ?? {},
|
|
26232
26253
|
dash: mergedAll.dash ?? {},
|
|
26233
26254
|
sync: mergedAll.sync ?? {},
|
|
26255
|
+
hub: normalizeHubConfig(mergedAll.hub),
|
|
26234
26256
|
improvement: mergedAll.improvement ?? DEFAULT_KXM_CONFIG.improvement,
|
|
26235
26257
|
routing: mergedAll.routing ?? DEFAULT_KXM_CONFIG.routing,
|
|
26236
26258
|
telemetry: mergedAll.telemetry ?? DEFAULT_KXM_CONFIG.telemetry,
|
|
@@ -26251,12 +26273,12 @@ function getKxmConfigValue(config, keyPath) {
|
|
|
26251
26273
|
}
|
|
26252
26274
|
function setKxmConfigValue(repoRoot6, keyPath, value, options = {}) {
|
|
26253
26275
|
const scope = options.scope ?? "project";
|
|
26254
|
-
const targetFile2 = scope === "user" ?
|
|
26276
|
+
const targetFile2 = scope === "user" ? join14(userConfigDirectory(options.userConfigDir), "config.yaml") : join14(repoConfigDirectory(repoRoot6), "config.yaml");
|
|
26255
26277
|
mkdirSync10(dirname9(targetFile2), { recursive: true });
|
|
26256
26278
|
let existing = {};
|
|
26257
26279
|
if (existsSync12(targetFile2)) {
|
|
26258
26280
|
try {
|
|
26259
|
-
existing = (0, import_yaml6.parse)(
|
|
26281
|
+
existing = (0, import_yaml6.parse)(readFileSync13(targetFile2, "utf8")) ?? {};
|
|
26260
26282
|
} catch {
|
|
26261
26283
|
existing = {};
|
|
26262
26284
|
}
|
|
@@ -26367,9 +26389,9 @@ var DEFAULT_ROLES = {
|
|
|
26367
26389
|
};
|
|
26368
26390
|
function rolesDirectory(scope, repoRoot6 = process.cwd(), userConfigDir) {
|
|
26369
26391
|
if (scope === "global") {
|
|
26370
|
-
return
|
|
26392
|
+
return join15(userConfigDirectory(userConfigDir), "roles");
|
|
26371
26393
|
}
|
|
26372
|
-
return
|
|
26394
|
+
return join15(repoConfigDirectory(repoRoot6), "roles");
|
|
26373
26395
|
}
|
|
26374
26396
|
function ensureRolesDirectory(scope, repoRoot6 = process.cwd(), userConfigDir) {
|
|
26375
26397
|
const dir = rolesDirectory(scope, repoRoot6, userConfigDir);
|
|
@@ -26381,7 +26403,7 @@ function ensureRolesDirectory(scope, repoRoot6 = process.cwd(), userConfigDir) {
|
|
|
26381
26403
|
function parseRoleFile(filePath) {
|
|
26382
26404
|
if (!existsSync13(filePath)) return void 0;
|
|
26383
26405
|
try {
|
|
26384
|
-
const raw =
|
|
26406
|
+
const raw = readFileSync14(filePath, "utf8");
|
|
26385
26407
|
const parsed = (0, import_yaml7.parse)(raw);
|
|
26386
26408
|
if (!parsed || typeof parsed !== "object" || parsed.schema !== KXM_ROLE_SCHEMA) {
|
|
26387
26409
|
return void 0;
|
|
@@ -26411,7 +26433,7 @@ function listRoles(options = {}) {
|
|
|
26411
26433
|
if (scopeFilter !== "global" && existsSync13(localDir)) {
|
|
26412
26434
|
for (const entry of readdirSync4(localDir)) {
|
|
26413
26435
|
if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
|
|
26414
|
-
const filePath =
|
|
26436
|
+
const filePath = join15(localDir, entry);
|
|
26415
26437
|
const parsed = parseRoleFile(filePath);
|
|
26416
26438
|
if (parsed) {
|
|
26417
26439
|
localRoles.set(parsed.id, { role: parsed, filePath });
|
|
@@ -26423,7 +26445,7 @@ function listRoles(options = {}) {
|
|
|
26423
26445
|
if (scopeFilter !== "local" && existsSync13(globalDir)) {
|
|
26424
26446
|
for (const entry of readdirSync4(globalDir)) {
|
|
26425
26447
|
if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
|
|
26426
|
-
const filePath =
|
|
26448
|
+
const filePath = join15(globalDir, entry);
|
|
26427
26449
|
const parsed = parseRoleFile(filePath);
|
|
26428
26450
|
if (parsed) {
|
|
26429
26451
|
globalRoles.set(parsed.id, { role: parsed, filePath });
|
|
@@ -26471,13 +26493,13 @@ function getRole(roleId, options = {}) {
|
|
|
26471
26493
|
const repoRoot6 = options.repoRoot ?? process.cwd();
|
|
26472
26494
|
if (scope !== "global") {
|
|
26473
26495
|
const localDir = rolesDirectory("local", repoRoot6, options.userConfigDir);
|
|
26474
|
-
const localFile =
|
|
26496
|
+
const localFile = join15(localDir, `${roleId}.yaml`);
|
|
26475
26497
|
const parsed = parseRoleFile(localFile);
|
|
26476
26498
|
if (parsed) return { role: parsed, scope: "local", filePath: localFile };
|
|
26477
26499
|
}
|
|
26478
26500
|
if (scope !== "local") {
|
|
26479
26501
|
const globalDir = rolesDirectory("global", repoRoot6, options.userConfigDir);
|
|
26480
|
-
const globalFile =
|
|
26502
|
+
const globalFile = join15(globalDir, `${roleId}.yaml`);
|
|
26481
26503
|
const parsed = parseRoleFile(globalFile);
|
|
26482
26504
|
if (parsed) return { role: parsed, scope: "global", filePath: globalFile };
|
|
26483
26505
|
}
|
|
@@ -26487,7 +26509,7 @@ function addRole(role, options = {}) {
|
|
|
26487
26509
|
const scope = options.scope ?? "local";
|
|
26488
26510
|
const repoRoot6 = options.repoRoot ?? process.cwd();
|
|
26489
26511
|
const dir = ensureRolesDirectory(scope, repoRoot6, options.userConfigDir);
|
|
26490
|
-
const filePath =
|
|
26512
|
+
const filePath = join15(dir, `${role.id}.yaml`);
|
|
26491
26513
|
if (existsSync13(filePath) && !options.overwrite) {
|
|
26492
26514
|
throw new Error(`role_already_exists: role '${role.id}' already exists at ${filePath}`);
|
|
26493
26515
|
}
|
|
@@ -26498,7 +26520,7 @@ function removeRole(roleId, options = {}) {
|
|
|
26498
26520
|
const scope = options.scope ?? "local";
|
|
26499
26521
|
const repoRoot6 = options.repoRoot ?? process.cwd();
|
|
26500
26522
|
const dir = rolesDirectory(scope, repoRoot6, options.userConfigDir);
|
|
26501
|
-
const filePath =
|
|
26523
|
+
const filePath = join15(dir, `${roleId}.yaml`);
|
|
26502
26524
|
if (!existsSync13(filePath)) {
|
|
26503
26525
|
throw new Error(`role_not_found: role '${roleId}' not found in ${scope} directory (${filePath})`);
|
|
26504
26526
|
}
|
|
@@ -26520,7 +26542,7 @@ function modifyRole(roleId, updates, options = {}) {
|
|
|
26520
26542
|
const scope = options.scope ?? target.scope;
|
|
26521
26543
|
const repoRoot6 = options.repoRoot ?? process.cwd();
|
|
26522
26544
|
const dir = ensureRolesDirectory(scope, repoRoot6, options.userConfigDir);
|
|
26523
|
-
const filePath =
|
|
26545
|
+
const filePath = join15(dir, `${roleId}.yaml`);
|
|
26524
26546
|
writeFileSync10(filePath, (0, import_yaml7.stringify)(updated), "utf8");
|
|
26525
26547
|
return { id: roleId, role: updated, filePath, scope };
|
|
26526
26548
|
}
|
|
@@ -26569,9 +26591,9 @@ var DEFAULT_ROLE_SEATS = {
|
|
|
26569
26591
|
};
|
|
26570
26592
|
function findExistingRoleHostsFile(scope, repoRoot6 = process.cwd(), userConfigDir) {
|
|
26571
26593
|
const dir = scope === "global" ? userConfigDirectory(userConfigDir) : repoConfigDirectory(repoRoot6);
|
|
26572
|
-
const yamlPath =
|
|
26573
|
-
const ymlPath =
|
|
26574
|
-
const jsonPath =
|
|
26594
|
+
const yamlPath = join15(dir, "role-hosts.yaml");
|
|
26595
|
+
const ymlPath = join15(dir, "role-hosts.yml");
|
|
26596
|
+
const jsonPath = join15(dir, "role-hosts.json");
|
|
26575
26597
|
if (existsSync13(yamlPath)) return { filePath: yamlPath, exists: true, format: "yaml" };
|
|
26576
26598
|
if (existsSync13(ymlPath)) return { filePath: ymlPath, exists: true, format: "yaml" };
|
|
26577
26599
|
if (existsSync13(jsonPath)) return { filePath: jsonPath, exists: true, format: "json" };
|
|
@@ -26580,7 +26602,7 @@ function findExistingRoleHostsFile(scope, repoRoot6 = process.cwd(), userConfigD
|
|
|
26580
26602
|
function parseRoleHostsFile(filePath) {
|
|
26581
26603
|
if (!existsSync13(filePath)) return void 0;
|
|
26582
26604
|
try {
|
|
26583
|
-
const raw =
|
|
26605
|
+
const raw = readFileSync14(filePath, "utf8");
|
|
26584
26606
|
const parsed = (0, import_yaml7.parse)(raw);
|
|
26585
26607
|
if (!parsed || typeof parsed !== "object") return void 0;
|
|
26586
26608
|
if (parsed.schema && parsed.schema !== KXM_ROLE_HOSTS_SCHEMA) return void 0;
|
|
@@ -26656,7 +26678,7 @@ function saveRoleHostsConfig(config, options = {}) {
|
|
|
26656
26678
|
mkdirSync11(dir, { recursive: true });
|
|
26657
26679
|
}
|
|
26658
26680
|
const format = options.format ?? "yaml";
|
|
26659
|
-
const filePath =
|
|
26681
|
+
const filePath = join15(dir, format === "json" ? "role-hosts.json" : "role-hosts.yaml");
|
|
26660
26682
|
const payload = {
|
|
26661
26683
|
schema: KXM_ROLE_HOSTS_SCHEMA,
|
|
26662
26684
|
seats: config.seats ?? {},
|
|
@@ -26898,7 +26920,7 @@ async function cmdRoleAdd(runtime, roleId, options) {
|
|
|
26898
26920
|
let roleDef;
|
|
26899
26921
|
if (options.file) {
|
|
26900
26922
|
const filePath = resolve12(runtime.cwd, options.file);
|
|
26901
|
-
const content =
|
|
26923
|
+
const content = readFileSync15(filePath, "utf8");
|
|
26902
26924
|
roleDef = (0, import_yaml8.parse)(content);
|
|
26903
26925
|
roleDef.id = roleId;
|
|
26904
26926
|
} else {
|
|
@@ -27197,7 +27219,7 @@ async function cmdRoleResume(runtime, runId, ruling) {
|
|
|
27197
27219
|
return 1;
|
|
27198
27220
|
}
|
|
27199
27221
|
}
|
|
27200
|
-
const dbPath =
|
|
27222
|
+
const dbPath = join16(runtime.cwd, ".kxm", "state", "kxm.db");
|
|
27201
27223
|
if (existsSync14(dbPath)) {
|
|
27202
27224
|
try {
|
|
27203
27225
|
const database = new DatabaseSync(dbPath);
|
|
@@ -27260,8 +27282,8 @@ async function cmdRoleResume(runtime, runId, ruling) {
|
|
|
27260
27282
|
|
|
27261
27283
|
// plugins/kxm/src/cli/workflows.ts
|
|
27262
27284
|
import { createHmac as createHmac3, randomUUID as randomUUID7 } from "node:crypto";
|
|
27263
|
-
import { existsSync as existsSync16, readFileSync as
|
|
27264
|
-
import { join as
|
|
27285
|
+
import { existsSync as existsSync16, readFileSync as readFileSync17 } from "node:fs";
|
|
27286
|
+
import { join as join18, resolve as resolve15 } from "node:path";
|
|
27265
27287
|
|
|
27266
27288
|
// plugins/kxm/src/retrospective.ts
|
|
27267
27289
|
import { mkdirSync as mkdirSync12, renameSync as renameSync4, writeFileSync as writeFileSync11 } from "node:fs";
|
|
@@ -27679,8 +27701,8 @@ async function watchGithubChecks(input) {
|
|
|
27679
27701
|
|
|
27680
27702
|
// plugins/kxm/src/workflow-manager.ts
|
|
27681
27703
|
var import_yaml9 = __toESM(require_dist(), 1);
|
|
27682
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync13, readdirSync as readdirSync5, readFileSync as
|
|
27683
|
-
import { join as
|
|
27704
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync13, readdirSync as readdirSync5, readFileSync as readFileSync16, rmSync as rmSync5, writeFileSync as writeFileSync12 } from "node:fs";
|
|
27705
|
+
import { join as join17 } from "node:path";
|
|
27684
27706
|
var WORKFLOW_TEMPLATES = {
|
|
27685
27707
|
"implement-and-verify": {
|
|
27686
27708
|
schema: "kxm.workflow.v1",
|
|
@@ -27831,9 +27853,9 @@ var WORKFLOW_TEMPLATES = {
|
|
|
27831
27853
|
var DEFAULT_WORKFLOW_TEMPLATE = WORKFLOW_TEMPLATES["implement-and-verify"];
|
|
27832
27854
|
function workflowsDirectory(scope, repoRoot6 = process.cwd(), userConfigDir) {
|
|
27833
27855
|
if (scope === "global") {
|
|
27834
|
-
return
|
|
27856
|
+
return join17(userConfigDirectory(userConfigDir), "workflows");
|
|
27835
27857
|
}
|
|
27836
|
-
return
|
|
27858
|
+
return join17(repoConfigDirectory(repoRoot6), "workflows");
|
|
27837
27859
|
}
|
|
27838
27860
|
function ensureWorkflowsDirectory(scope, repoRoot6 = process.cwd(), userConfigDir) {
|
|
27839
27861
|
const dir = workflowsDirectory(scope, repoRoot6, userConfigDir);
|
|
@@ -27845,7 +27867,7 @@ function ensureWorkflowsDirectory(scope, repoRoot6 = process.cwd(), userConfigDi
|
|
|
27845
27867
|
function parseWorkflowFile(filePath) {
|
|
27846
27868
|
if (!existsSync15(filePath)) return void 0;
|
|
27847
27869
|
try {
|
|
27848
|
-
const raw =
|
|
27870
|
+
const raw = readFileSync16(filePath, "utf8");
|
|
27849
27871
|
const parsed = (0, import_yaml9.parse)(raw);
|
|
27850
27872
|
if (!parsed || typeof parsed !== "object") return void 0;
|
|
27851
27873
|
return parsed;
|
|
@@ -27862,7 +27884,7 @@ function listWorkflowDefinitions(options = {}) {
|
|
|
27862
27884
|
if (scopeFilter !== "global" && existsSync15(localDir)) {
|
|
27863
27885
|
for (const entry of readdirSync5(localDir)) {
|
|
27864
27886
|
if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
|
|
27865
|
-
const filePath =
|
|
27887
|
+
const filePath = join17(localDir, entry);
|
|
27866
27888
|
const def = parseWorkflowFile(filePath);
|
|
27867
27889
|
if (def) {
|
|
27868
27890
|
const id = def.id || entry.replace(/\.ya?ml$/i, "");
|
|
@@ -27875,7 +27897,7 @@ function listWorkflowDefinitions(options = {}) {
|
|
|
27875
27897
|
if (scopeFilter !== "local" && existsSync15(globalDir)) {
|
|
27876
27898
|
for (const entry of readdirSync5(globalDir)) {
|
|
27877
27899
|
if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
|
|
27878
|
-
const filePath =
|
|
27900
|
+
const filePath = join17(globalDir, entry);
|
|
27879
27901
|
const def = parseWorkflowFile(filePath);
|
|
27880
27902
|
if (def) {
|
|
27881
27903
|
const id = def.id || entry.replace(/\.ya?ml$/i, "");
|
|
@@ -27931,13 +27953,13 @@ function getWorkflowDefinition(workflowId, options = {}) {
|
|
|
27931
27953
|
const repoRoot6 = options.repoRoot ?? process.cwd();
|
|
27932
27954
|
if (scope !== "global") {
|
|
27933
27955
|
const localDir = workflowsDirectory("local", repoRoot6, options.userConfigDir);
|
|
27934
|
-
const localFile =
|
|
27956
|
+
const localFile = join17(localDir, `${workflowId}.yaml`);
|
|
27935
27957
|
const parsed = parseWorkflowFile(localFile);
|
|
27936
27958
|
if (parsed) return { workflow: parsed, scope: "local", filePath: localFile };
|
|
27937
27959
|
}
|
|
27938
27960
|
if (scope !== "local") {
|
|
27939
27961
|
const globalDir = workflowsDirectory("global", repoRoot6, options.userConfigDir);
|
|
27940
|
-
const globalFile =
|
|
27962
|
+
const globalFile = join17(globalDir, `${workflowId}.yaml`);
|
|
27941
27963
|
const parsed = parseWorkflowFile(globalFile);
|
|
27942
27964
|
if (parsed) return { workflow: parsed, scope: "global", filePath: globalFile };
|
|
27943
27965
|
}
|
|
@@ -27947,7 +27969,7 @@ function addWorkflowDefinition(workflowId, content = DEFAULT_WORKFLOW_TEMPLATE,
|
|
|
27947
27969
|
const scope = options.scope ?? "local";
|
|
27948
27970
|
const repoRoot6 = options.repoRoot ?? process.cwd();
|
|
27949
27971
|
const dir = ensureWorkflowsDirectory(scope, repoRoot6, options.userConfigDir);
|
|
27950
|
-
const filePath =
|
|
27972
|
+
const filePath = join17(dir, `${workflowId}.yaml`);
|
|
27951
27973
|
if (existsSync15(filePath) && !options.overwrite) {
|
|
27952
27974
|
throw new Error(`workflow_already_exists: workflow '${workflowId}' already exists at ${filePath}`);
|
|
27953
27975
|
}
|
|
@@ -27959,7 +27981,7 @@ function removeWorkflowDefinition(workflowId, options = {}) {
|
|
|
27959
27981
|
const scope = options.scope ?? "local";
|
|
27960
27982
|
const repoRoot6 = options.repoRoot ?? process.cwd();
|
|
27961
27983
|
const dir = workflowsDirectory(scope, repoRoot6, options.userConfigDir);
|
|
27962
|
-
const filePath =
|
|
27984
|
+
const filePath = join17(dir, `${workflowId}.yaml`);
|
|
27963
27985
|
if (!existsSync15(filePath)) {
|
|
27964
27986
|
throw new Error(`workflow_not_found: workflow '${workflowId}' not found in ${scope} directory (${filePath})`);
|
|
27965
27987
|
}
|
|
@@ -27978,7 +28000,7 @@ function modifyWorkflowDefinition(workflowId, updates, options = {}) {
|
|
|
27978
28000
|
const scope = options.scope ?? target.scope;
|
|
27979
28001
|
const repoRoot6 = options.repoRoot ?? process.cwd();
|
|
27980
28002
|
const dir = ensureWorkflowsDirectory(scope, repoRoot6, options.userConfigDir);
|
|
27981
|
-
const filePath =
|
|
28003
|
+
const filePath = join17(dir, `${workflowId}.yaml`);
|
|
27982
28004
|
writeFileSync12(filePath, (0, import_yaml9.stringify)(updated), "utf8");
|
|
27983
28005
|
return { id: workflowId, workflow: updated, filePath, scope };
|
|
27984
28006
|
}
|
|
@@ -28063,7 +28085,7 @@ function activeWorkflowDefinition(runtime, definitionId) {
|
|
|
28063
28085
|
let raw;
|
|
28064
28086
|
if (file) {
|
|
28065
28087
|
try {
|
|
28066
|
-
raw =
|
|
28088
|
+
raw = readFileSync17(resolve15(runtime.cwd, file), "utf8");
|
|
28067
28089
|
} catch {
|
|
28068
28090
|
throw new Error("workflow definition file is unavailable");
|
|
28069
28091
|
}
|
|
@@ -28145,7 +28167,7 @@ async function cmdWorkflowAdd(runtime, workflowId, options) {
|
|
|
28145
28167
|
}
|
|
28146
28168
|
if (options.file) {
|
|
28147
28169
|
const filePath = resolve15(runtime.cwd, options.file);
|
|
28148
|
-
content =
|
|
28170
|
+
content = readFileSync17(filePath, "utf8");
|
|
28149
28171
|
} else if (!content) {
|
|
28150
28172
|
content = {
|
|
28151
28173
|
schema: "kxm.workflow.v1",
|
|
@@ -28303,7 +28325,7 @@ async function cmdWorkflowStart(runtime, definitionIdArg, options) {
|
|
|
28303
28325
|
}
|
|
28304
28326
|
let payload;
|
|
28305
28327
|
try {
|
|
28306
|
-
const raw = payloadFlag.startsWith("@") ?
|
|
28328
|
+
const raw = payloadFlag.startsWith("@") ? readFileSync17(resolve15(runtime.cwd, payloadFlag.slice(1)), "utf8") : payloadFlag;
|
|
28307
28329
|
const value = JSON.parse(raw);
|
|
28308
28330
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("object required");
|
|
28309
28331
|
payload = value;
|
|
@@ -28370,7 +28392,7 @@ async function cmdWorkflowDegrade(runtime, runId, stageId, options) {
|
|
|
28370
28392
|
}
|
|
28371
28393
|
}
|
|
28372
28394
|
async function cmdWorkflowInspect(runtime, action, runId) {
|
|
28373
|
-
const dataPath = resolve15(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
28395
|
+
const dataPath = resolve15(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join18(runtime.dirs.state, "kxm.db"));
|
|
28374
28396
|
if (action === "get" && !runId) {
|
|
28375
28397
|
runtime.io.stderr(`Usage: ${CLI_NAME} workflow get <runId>
|
|
28376
28398
|
`);
|
|
@@ -28544,9 +28566,9 @@ async function cmdRetrospectiveExport(runtime, runId, options) {
|
|
|
28544
28566
|
try {
|
|
28545
28567
|
if (snapshotPath) {
|
|
28546
28568
|
if (!existsSync16(snapshotPath)) throw new Error("snapshot_missing");
|
|
28547
|
-
snapshot = JSON.parse(
|
|
28569
|
+
snapshot = JSON.parse(readFileSync17(snapshotPath, "utf8"));
|
|
28548
28570
|
} else {
|
|
28549
|
-
const dataPath = resolve15(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
28571
|
+
const dataPath = resolve15(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join18(runtime.dirs.state, "kxm.db"));
|
|
28550
28572
|
const local = localWorkflowSnapshot(dataPath, runId);
|
|
28551
28573
|
if (!local.runs[0]) throw new Error("workflow_not_found");
|
|
28552
28574
|
snapshot = { run: local.runs[0], journal: local.journal };
|
|
@@ -28558,7 +28580,7 @@ async function cmdRetrospectiveExport(runtime, runId, options) {
|
|
|
28558
28580
|
return 1;
|
|
28559
28581
|
}
|
|
28560
28582
|
const doc = buildRetrospective(snapshot.run, snapshot.journal);
|
|
28561
|
-
const outDir = resolve15(runtime.cwd, String(options.outDir ||
|
|
28583
|
+
const outDir = resolve15(runtime.cwd, String(options.outDir || join18(runtime.dirs.assets, "retrospectives")));
|
|
28562
28584
|
const assetsRoot = resolve15(runtime.dirs.assets);
|
|
28563
28585
|
const assetsPrefix = `${assetsRoot}${process.platform === "win32" ? "\\" : "/"}`;
|
|
28564
28586
|
if (outDir !== assetsRoot && !outDir.startsWith(assetsPrefix)) {
|
|
@@ -28576,8 +28598,8 @@ async function cmdRetrospectiveExport(runtime, runId, options) {
|
|
|
28576
28598
|
|
|
28577
28599
|
// plugins/kxm/src/cli/tasks.ts
|
|
28578
28600
|
var import_yaml13 = __toESM(require_dist(), 1);
|
|
28579
|
-
import { existsSync as existsSync22, readFileSync as
|
|
28580
|
-
import { basename as
|
|
28601
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22, readdirSync as readdirSync8 } from "node:fs";
|
|
28602
|
+
import { basename as basename6, join as join26, resolve as resolve21 } from "node:path";
|
|
28581
28603
|
|
|
28582
28604
|
// plugins/kxm/src/suggest.ts
|
|
28583
28605
|
var WORKFLOW_PATTERNS = [
|
|
@@ -28688,8 +28710,8 @@ function suggestWorkflowAndRoles(prompt, options = {}) {
|
|
|
28688
28710
|
// plugins/kxm/src/task-manager.ts
|
|
28689
28711
|
var import_yaml10 = __toESM(require_dist(), 1);
|
|
28690
28712
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
28691
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync14, readFileSync as
|
|
28692
|
-
import { join as
|
|
28713
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync14, readFileSync as readFileSync18, readdirSync as readdirSync6, writeFileSync as writeFileSync13 } from "node:fs";
|
|
28714
|
+
import { join as join19, resolve as resolve16 } from "node:path";
|
|
28693
28715
|
var GOAL_SCHEMA = "kxm.goal.v1";
|
|
28694
28716
|
var TASK_SCHEMA = "kxm.task.v1";
|
|
28695
28717
|
function goalsDirectory(repoRoot6) {
|
|
@@ -28714,7 +28736,7 @@ function createGoal(repoRoot6, input) {
|
|
|
28714
28736
|
createdAt: now,
|
|
28715
28737
|
updatedAt: now
|
|
28716
28738
|
};
|
|
28717
|
-
const filePath =
|
|
28739
|
+
const filePath = join19(dir, `${id}.yaml`);
|
|
28718
28740
|
writeFileSync13(filePath, (0, import_yaml10.stringify)(record).trim() + "\n", "utf8");
|
|
28719
28741
|
return record;
|
|
28720
28742
|
}
|
|
@@ -28726,7 +28748,7 @@ function listGoals(repoRoot6) {
|
|
|
28726
28748
|
for (const entry of entries) {
|
|
28727
28749
|
if (entry.isFile() && (entry.name.endsWith(".yaml") || entry.name.endsWith(".yml"))) {
|
|
28728
28750
|
try {
|
|
28729
|
-
const text =
|
|
28751
|
+
const text = readFileSync18(join19(dir, entry.name), "utf8");
|
|
28730
28752
|
const doc = (0, import_yaml10.parse)(text);
|
|
28731
28753
|
if (doc && doc.schema === GOAL_SCHEMA) goals.push(doc);
|
|
28732
28754
|
} catch {
|
|
@@ -28759,7 +28781,7 @@ function createTask(repoRoot6, input) {
|
|
|
28759
28781
|
createdAt: now,
|
|
28760
28782
|
updatedAt: now
|
|
28761
28783
|
};
|
|
28762
|
-
const filePath =
|
|
28784
|
+
const filePath = join19(dir, `${id}.yaml`);
|
|
28763
28785
|
writeFileSync13(filePath, (0, import_yaml10.stringify)(record).trim() + "\n", "utf8");
|
|
28764
28786
|
return record;
|
|
28765
28787
|
}
|
|
@@ -28771,7 +28793,7 @@ function listTasks(repoRoot6, options = {}) {
|
|
|
28771
28793
|
for (const entry of entries) {
|
|
28772
28794
|
if (entry.isFile() && (entry.name.endsWith(".yaml") || entry.name.endsWith(".yml"))) {
|
|
28773
28795
|
try {
|
|
28774
|
-
const text =
|
|
28796
|
+
const text = readFileSync18(join19(dir, entry.name), "utf8");
|
|
28775
28797
|
const doc = (0, import_yaml10.parse)(text);
|
|
28776
28798
|
if (doc && doc.schema === TASK_SCHEMA) {
|
|
28777
28799
|
if (options.goalId && doc.goalId !== options.goalId) continue;
|
|
@@ -28786,10 +28808,10 @@ function listTasks(repoRoot6, options = {}) {
|
|
|
28786
28808
|
}
|
|
28787
28809
|
function getTask(repoRoot6, taskId) {
|
|
28788
28810
|
const dir = tasksDirectory(repoRoot6);
|
|
28789
|
-
const filePath =
|
|
28811
|
+
const filePath = join19(dir, `${taskId}.yaml`);
|
|
28790
28812
|
if (!existsSync17(filePath)) return void 0;
|
|
28791
28813
|
try {
|
|
28792
|
-
const text =
|
|
28814
|
+
const text = readFileSync18(filePath, "utf8");
|
|
28793
28815
|
const doc = (0, import_yaml10.parse)(text);
|
|
28794
28816
|
return doc && doc.schema === TASK_SCHEMA ? doc : void 0;
|
|
28795
28817
|
} catch {
|
|
@@ -28804,7 +28826,7 @@ function updateTaskStatus(repoRoot6, taskId, status, options = {}) {
|
|
|
28804
28826
|
task.status = status;
|
|
28805
28827
|
if (options.workflowRunId) task.workflowRunId = options.workflowRunId;
|
|
28806
28828
|
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
28807
|
-
const filePath =
|
|
28829
|
+
const filePath = join19(tasksDirectory(repoRoot6), `${taskId}.yaml`);
|
|
28808
28830
|
writeFileSync13(filePath, (0, import_yaml10.stringify)(task).trim() + "\n", "utf8");
|
|
28809
28831
|
return task;
|
|
28810
28832
|
}
|
|
@@ -28820,7 +28842,7 @@ function syncTaskWithTracker(repoRoot6, taskId, options = {}) {
|
|
|
28820
28842
|
task.trackerSync.syncStatus = "synced";
|
|
28821
28843
|
task.trackerSync.lastSyncedAt = now;
|
|
28822
28844
|
task.updatedAt = now;
|
|
28823
|
-
const filePath =
|
|
28845
|
+
const filePath = join19(tasksDirectory(repoRoot6), `${taskId}.yaml`);
|
|
28824
28846
|
writeFileSync13(filePath, (0, import_yaml10.stringify)(task).trim() + "\n", "utf8");
|
|
28825
28847
|
return task;
|
|
28826
28848
|
}
|
|
@@ -29587,14 +29609,14 @@ function createStudioServer(options = {}) {
|
|
|
29587
29609
|
}
|
|
29588
29610
|
|
|
29589
29611
|
// plugins/kxm/src/cli/vnext.ts
|
|
29590
|
-
import { join as
|
|
29612
|
+
import { join as join25, resolve as resolve20 } from "node:path";
|
|
29591
29613
|
import { createInterface as createInterface2 } from "node:readline";
|
|
29592
29614
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
29593
29615
|
|
|
29594
29616
|
// plugins/kxm/src/model-inventory.ts
|
|
29595
29617
|
var import_yaml11 = __toESM(require_dist(), 1);
|
|
29596
29618
|
import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync14 } from "node:fs";
|
|
29597
|
-
import { join as
|
|
29619
|
+
import { join as join20 } from "node:path";
|
|
29598
29620
|
var OR_URL = "https://openrouter.ai/api/v1/models";
|
|
29599
29621
|
var NOUS_URL = "https://inference-api.nousresearch.com/v1/models";
|
|
29600
29622
|
function price(value) {
|
|
@@ -29680,15 +29702,15 @@ async function refreshModelInventory(options) {
|
|
|
29680
29702
|
sources.nous = { url: nousUrl, ok: !nous.error, ...nous.error ? { error: nous.error } : {} };
|
|
29681
29703
|
for (const item of nous.data) add(item, "nous", "discount");
|
|
29682
29704
|
const inventory = { schema: "kxm.model-inventory.v1", fetchedAt, currency: "USD", sources, models: [...byId.values()].sort((a, b2) => a.id.localeCompare(b2.id)) };
|
|
29683
|
-
mkdirSync15(
|
|
29684
|
-
writeFileSync14(
|
|
29705
|
+
mkdirSync15(join20(options.outputRoot, ".kxm", "models"), { recursive: true });
|
|
29706
|
+
writeFileSync14(join20(options.outputRoot, ".kxm", "models", "inventory.yaml"), (0, import_yaml11.stringify)(inventory), "utf8");
|
|
29685
29707
|
return inventory;
|
|
29686
29708
|
}
|
|
29687
29709
|
|
|
29688
29710
|
// plugins/kxm/src/vnext-init.ts
|
|
29689
29711
|
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
29690
29712
|
import { existsSync as existsSync20 } from "node:fs";
|
|
29691
|
-
import { basename as
|
|
29713
|
+
import { basename as basename5, join as join23 } from "node:path";
|
|
29692
29714
|
|
|
29693
29715
|
// plugins/kxm/src/vnext-repair.ts
|
|
29694
29716
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
@@ -29701,20 +29723,20 @@ import {
|
|
|
29701
29723
|
lstatSync as lstatSync7,
|
|
29702
29724
|
mkdirSync as mkdirSync17,
|
|
29703
29725
|
openSync as openSync2,
|
|
29704
|
-
readFileSync as
|
|
29726
|
+
readFileSync as readFileSync20,
|
|
29705
29727
|
readdirSync as readdirSync7,
|
|
29706
29728
|
renameSync as renameSync5,
|
|
29707
29729
|
rmSync as rmSync7,
|
|
29708
29730
|
writeFileSync as writeFileSync16
|
|
29709
29731
|
} from "node:fs";
|
|
29710
|
-
import { dirname as dirname13, isAbsolute as isAbsolute6, join as
|
|
29732
|
+
import { dirname as dirname13, isAbsolute as isAbsolute6, join as join22, relative as relative4, resolve as resolve18 } from "node:path";
|
|
29711
29733
|
|
|
29712
29734
|
// plugins/kxm/src/vnext-permission.ts
|
|
29713
29735
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
29714
29736
|
import { createHash as createHash12 } from "node:crypto";
|
|
29715
|
-
import { existsSync as existsSync18, mkdtempSync, mkdirSync as mkdirSync16, readFileSync as
|
|
29737
|
+
import { existsSync as existsSync18, mkdtempSync, mkdirSync as mkdirSync16, readFileSync as readFileSync19, rmSync as rmSync6, writeFileSync as writeFileSync15 } from "node:fs";
|
|
29716
29738
|
import { tmpdir } from "node:os";
|
|
29717
|
-
import { dirname as dirname12, join as
|
|
29739
|
+
import { dirname as dirname12, join as join21, resolve as resolve17, sep as sep3 } from "node:path";
|
|
29718
29740
|
var PROSE_FIELDS = {
|
|
29719
29741
|
project: /* @__PURE__ */ new Set(["name", "description"]),
|
|
29720
29742
|
repository: /* @__PURE__ */ new Set(["description"]),
|
|
@@ -30235,7 +30257,7 @@ function loadVnextProjectAtRevision(root, revision, options = {}) {
|
|
|
30235
30257
|
const tree = resolveTreeRevision(root, revision);
|
|
30236
30258
|
const listing = gitBuffer(root, ["ls-tree", "-r", "-z", "--name-only", tree]).toString("utf8");
|
|
30237
30259
|
const paths = listing.split("\0").filter((line) => line.length > 0 && (line.startsWith(".kxm/") || line.includes("/.kxm/")));
|
|
30238
|
-
const shadow = mkdtempSync(
|
|
30260
|
+
const shadow = mkdtempSync(join21(tmpdir(), "kxm-permission-base-"));
|
|
30239
30261
|
const shadowResolved = resolve17(shadow);
|
|
30240
30262
|
const shadowMembersDir = `.kxm-shadow-members-${createHash12("sha256").update(shadowResolved, "utf8").digest("hex").slice(0, 8)}`;
|
|
30241
30263
|
try {
|
|
@@ -30249,7 +30271,7 @@ function loadVnextProjectAtRevision(root, revision, options = {}) {
|
|
|
30249
30271
|
message: "Git tree entry contains a traversal or non-portable segment"
|
|
30250
30272
|
}]);
|
|
30251
30273
|
}
|
|
30252
|
-
const absolute =
|
|
30274
|
+
const absolute = join21(shadowResolved, ...segments);
|
|
30253
30275
|
const resolved = resolve17(absolute);
|
|
30254
30276
|
if (!resolved.startsWith(`${shadowResolved}${sep3}`)) {
|
|
30255
30277
|
throw new VnextConfigError([{
|
|
@@ -30264,7 +30286,7 @@ function loadVnextProjectAtRevision(root, revision, options = {}) {
|
|
|
30264
30286
|
writeFileSync15(absolute, content);
|
|
30265
30287
|
}
|
|
30266
30288
|
initShadowGitRoot(shadowResolved);
|
|
30267
|
-
const baseProjectFile =
|
|
30289
|
+
const baseProjectFile = join21(shadowResolved, ".kxm", "project.yaml");
|
|
30268
30290
|
let baseProject;
|
|
30269
30291
|
try {
|
|
30270
30292
|
baseProject = loadBaseProjectDeclarations(baseProjectFile);
|
|
@@ -30342,7 +30364,7 @@ function loadVnextProjectAtRevision(root, revision, options = {}) {
|
|
|
30342
30364
|
const memberTree = git(memberWorktree, ["rev-parse", "--verify", "--quiet", `${pinnedCommit}^{tree}`]).trim();
|
|
30343
30365
|
const memberListing = gitBuffer(memberWorktree, ["ls-tree", "-r", "-z", "--name-only", memberTree]).toString("utf8");
|
|
30344
30366
|
const memberPaths = memberListing.split("\0").filter((line) => line.length > 0 && (line.startsWith(".kxm/") || line.includes("/.kxm/")));
|
|
30345
|
-
const memberShadowRoot =
|
|
30367
|
+
const memberShadowRoot = join21(shadowResolved, shadowMembersDir, member.repositoryId);
|
|
30346
30368
|
if (!resolve17(memberShadowRoot).startsWith(`${resolve17(shadowResolved, shadowMembersDir)}${sep3}`)) {
|
|
30347
30369
|
throw new VnextConfigError([{
|
|
30348
30370
|
phase: "path",
|
|
@@ -30356,7 +30378,7 @@ function loadVnextProjectAtRevision(root, revision, options = {}) {
|
|
|
30356
30378
|
if (segments.some((segment) => segment === "" || segment === "." || segment === ".." || /[\\:]/.test(segment))) {
|
|
30357
30379
|
throw new VnextConfigError([{ phase: "path", code: "git_tree_path_invalid", file: path4, message: "member Git tree entry contains a traversal or non-portable segment" }]);
|
|
30358
30380
|
}
|
|
30359
|
-
const absolute =
|
|
30381
|
+
const absolute = join21(memberShadowRoot, ...segments);
|
|
30360
30382
|
const resolved = resolve17(absolute);
|
|
30361
30383
|
if (!resolved.startsWith(`${resolve17(memberShadowRoot)}${sep3}`)) {
|
|
30362
30384
|
throw new VnextConfigError([{ phase: "path", code: "git_tree_path_invalid", file: path4, message: "member Git tree entry escapes the shadow root" }]);
|
|
@@ -30385,7 +30407,7 @@ function portableMemberPathHint(pathHint) {
|
|
|
30385
30407
|
}
|
|
30386
30408
|
function loadBaseProjectDeclarations(projectFile) {
|
|
30387
30409
|
if (!existsSync18(projectFile)) return [];
|
|
30388
|
-
const value = parseRestrictedYaml2(
|
|
30410
|
+
const value = parseRestrictedYaml2(readFileSync19(projectFile, "utf8"), ".kxm/project.yaml");
|
|
30389
30411
|
const repositories = Array.isArray(value?.repositories) ? value.repositories : [];
|
|
30390
30412
|
const members = [];
|
|
30391
30413
|
for (const entry of repositories) {
|
|
@@ -30513,19 +30535,19 @@ function sameHostPath3(left, right) {
|
|
|
30513
30535
|
return process.platform === "win32" ? first.toLocaleLowerCase("en-US") === second.toLocaleLowerCase("en-US") : first === second;
|
|
30514
30536
|
}
|
|
30515
30537
|
function transactionRoot(projectRoot) {
|
|
30516
|
-
return
|
|
30538
|
+
return join22(resolve18(projectRoot), TRANSACTION_NAME);
|
|
30517
30539
|
}
|
|
30518
30540
|
function operationFile(projectRoot) {
|
|
30519
|
-
return
|
|
30541
|
+
return join22(transactionRoot(projectRoot), OPERATION_FILE);
|
|
30520
30542
|
}
|
|
30521
30543
|
function targetFile(projectRoot, portablePath2) {
|
|
30522
|
-
return
|
|
30544
|
+
return join22(transactionRoot(projectRoot), "targets", ...portablePath2.split("/"));
|
|
30523
30545
|
}
|
|
30524
30546
|
function shadowRoot(projectRoot) {
|
|
30525
|
-
return
|
|
30547
|
+
return join22(transactionRoot(projectRoot), "shadow");
|
|
30526
30548
|
}
|
|
30527
30549
|
function backupFile(projectRoot, portablePath2) {
|
|
30528
|
-
return
|
|
30550
|
+
return join22(transactionRoot(projectRoot), "backups", ...portablePath2.split("/"));
|
|
30529
30551
|
}
|
|
30530
30552
|
function portableManagedPath(path4) {
|
|
30531
30553
|
return path4.startsWith(".kxm/") && path4 !== VNEXT_TEMPLATE_PROVENANCE_PATH && path4.length <= 1024 && !path4.includes("\\") && !isAbsolute6(path4) && PORTABLE_PATH.test(path4) && !/[<>:"|?*]/.test(path4);
|
|
@@ -30534,10 +30556,10 @@ function readRegularBounded(file, label) {
|
|
|
30534
30556
|
const stat = lstatSync7(file);
|
|
30535
30557
|
if (stat.isSymbolicLink() || !stat.isFile()) fail3("repair_file_invalid", label, "managed file must be a regular file, not a link or directory", "path");
|
|
30536
30558
|
if (stat.size > MAX_MANAGED_FILE_BYTES) fail3("repair_file_too_large", label, `managed file exceeds ${MAX_MANAGED_FILE_BYTES} bytes`, "parse");
|
|
30537
|
-
return
|
|
30559
|
+
return readFileSync20(file);
|
|
30538
30560
|
}
|
|
30539
30561
|
function readOptionalManaged(projectRoot, path4) {
|
|
30540
|
-
const file =
|
|
30562
|
+
const file = join22(projectRoot, ...path4.split("/"));
|
|
30541
30563
|
if (!existsSync19(file)) return void 0;
|
|
30542
30564
|
let parent = dirname13(file);
|
|
30543
30565
|
const boundary = resolve18(projectRoot);
|
|
@@ -30549,8 +30571,8 @@ function readOptionalManaged(projectRoot, path4) {
|
|
|
30549
30571
|
return readRegularBounded(file, path4);
|
|
30550
30572
|
}
|
|
30551
30573
|
function readProjectAndProvenance(projectRoot, schemasDir) {
|
|
30552
|
-
const projectFile =
|
|
30553
|
-
const provenanceFile =
|
|
30574
|
+
const projectFile = join22(projectRoot, ".kxm", "project.yaml");
|
|
30575
|
+
const provenanceFile = join22(projectRoot, ...VNEXT_TEMPLATE_PROVENANCE_PATH.split("/"));
|
|
30554
30576
|
if (!existsSync19(projectFile) || !existsSync19(provenanceFile)) return void 0;
|
|
30555
30577
|
const projectBytes = readOptionalManaged(projectRoot, ".kxm/project.yaml");
|
|
30556
30578
|
const provenanceBytes = readOptionalManaged(projectRoot, VNEXT_TEMPLATE_PROVENANCE_PATH);
|
|
@@ -30715,7 +30737,7 @@ function operationPlanSha(operation) {
|
|
|
30715
30737
|
function writeOperation(projectRoot, operation) {
|
|
30716
30738
|
const root = transactionRoot(projectRoot);
|
|
30717
30739
|
const file = operationFile(projectRoot);
|
|
30718
|
-
const temporary =
|
|
30740
|
+
const temporary = join22(root, `.operation-${operation.operationId}-${randomUUID10()}.tmp`);
|
|
30719
30741
|
try {
|
|
30720
30742
|
writeDurableNew(temporary, Buffer.from(`${JSON.stringify(operation, null, 2)}
|
|
30721
30743
|
`, "utf8"), 384);
|
|
@@ -30767,7 +30789,7 @@ function hasVnextInitTransaction(projectRoot) {
|
|
|
30767
30789
|
return existsSync19(transactionRoot(projectRoot));
|
|
30768
30790
|
}
|
|
30769
30791
|
function readTarget(projectRoot, path4) {
|
|
30770
|
-
return readOptionalManaged(
|
|
30792
|
+
return readOptionalManaged(join22(transactionRoot(projectRoot), "targets"), path4);
|
|
30771
30793
|
}
|
|
30772
30794
|
function writeTarget(projectRoot, path4, bytes) {
|
|
30773
30795
|
if (bytes.byteLength > MAX_MANAGED_FILE_BYTES) fail3("template_target_too_large", path4, `target exceeds ${MAX_MANAGED_FILE_BYTES} bytes`);
|
|
@@ -30807,7 +30829,7 @@ function verifyBackups(projectRoot, operation) {
|
|
|
30807
30829
|
if (operation.kind !== "repair") return;
|
|
30808
30830
|
for (const entry of operation.files) {
|
|
30809
30831
|
if (entry.observedSha256 === null) continue;
|
|
30810
|
-
const bytes = readOptionalManaged(
|
|
30832
|
+
const bytes = readOptionalManaged(join22(transactionRoot(projectRoot), "backups"), entry.path);
|
|
30811
30833
|
if (!bytes || vnextContentSha256(bytes) !== entry.observedSha256) {
|
|
30812
30834
|
fail3("init_transaction_backup_invalid", entry.path, "pinned preimage backup is missing or corrupt");
|
|
30813
30835
|
}
|
|
@@ -30841,9 +30863,9 @@ function sourceConfigFiles(projectRoot) {
|
|
|
30841
30863
|
".kxm/repo/repo.yaml",
|
|
30842
30864
|
".kxm/repo/env.yaml"
|
|
30843
30865
|
];
|
|
30844
|
-
const files = fixed.filter((path4) => existsSync19(
|
|
30866
|
+
const files = fixed.filter((path4) => existsSync19(join22(projectRoot, ...path4.split("/"))));
|
|
30845
30867
|
for (const directory of ["agents", "models", "workflows"]) {
|
|
30846
|
-
const absolute =
|
|
30868
|
+
const absolute = join22(projectRoot, ".kxm", directory);
|
|
30847
30869
|
if (!existsSync19(absolute)) continue;
|
|
30848
30870
|
const stat = lstatSync7(absolute);
|
|
30849
30871
|
if (stat.isSymbolicLink() || !stat.isDirectory()) fail3("repair_directory_invalid", `.kxm/${directory}`, "configuration directory must be regular", "path");
|
|
@@ -30880,8 +30902,8 @@ function prepareShadow(projectRoot, operation, options) {
|
|
|
30880
30902
|
const bytes = readOptionalManaged(projectRoot, path4);
|
|
30881
30903
|
if (!bytes) fail3("repair_snapshot_file_missing", path4, "configuration changed during shadow preparation");
|
|
30882
30904
|
total += bytes.byteLength;
|
|
30883
|
-
const source =
|
|
30884
|
-
const destination =
|
|
30905
|
+
const source = join22(projectRoot, ...path4.split("/"));
|
|
30906
|
+
const destination = join22(shadow, ...path4.split("/"));
|
|
30885
30907
|
mkdirSync17(dirname13(destination), { recursive: true, mode: 448 });
|
|
30886
30908
|
writeDurableNew(destination, bytes, lstatSync7(source).mode & 511);
|
|
30887
30909
|
if (total > MAX_MANAGED_TOTAL_BYTES) fail3("repair_snapshot_too_large", ".kxm", `configuration snapshot exceeds ${MAX_MANAGED_TOTAL_BYTES} bytes`, "parse");
|
|
@@ -30890,12 +30912,12 @@ function prepareShadow(projectRoot, operation, options) {
|
|
|
30890
30912
|
for (const entry of operation.files) {
|
|
30891
30913
|
const bytes = readTarget(projectRoot, entry.path);
|
|
30892
30914
|
if (!bytes) fail3("init_transaction_target_missing", entry.path, "pinned target artifact is missing");
|
|
30893
|
-
const destination =
|
|
30915
|
+
const destination = join22(shadow, ...entry.path.split("/"));
|
|
30894
30916
|
mkdirSync17(dirname13(destination), { recursive: true, mode: 448 });
|
|
30895
30917
|
const mode = existsSync19(destination) ? lstatSync7(destination).mode & 511 : 420;
|
|
30896
30918
|
writeDurable(destination, bytes, mode);
|
|
30897
30919
|
}
|
|
30898
|
-
const project = parseRestrictedYaml2(
|
|
30920
|
+
const project = parseRestrictedYaml2(readFileSync20(join22(shadow, ".kxm", "project.yaml")), ".kxm/project.yaml");
|
|
30899
30921
|
const bound = absoluteMemberBindings(projectRoot, project, options.repositoryBindings);
|
|
30900
30922
|
loadVnextProject(shadow, { ...loaderOptions(options), repositoryBindings: bound });
|
|
30901
30923
|
const provenance = readProjectAndProvenance(shadow, options.schemasDir)?.provenance;
|
|
@@ -30959,21 +30981,21 @@ function ensureDestinationParents(projectRoot, path4) {
|
|
|
30959
30981
|
const segments = path4.split("/").slice(0, -1);
|
|
30960
30982
|
let current = boundary;
|
|
30961
30983
|
for (const segment of segments) {
|
|
30962
|
-
current =
|
|
30984
|
+
current = join22(current, segment);
|
|
30963
30985
|
if (!existsSync19(current)) mkdirSync17(current, { mode: 448 });
|
|
30964
30986
|
const stat = lstatSync7(current);
|
|
30965
30987
|
if (stat.isSymbolicLink() || !stat.isDirectory()) fail3("repair_destination_parent_invalid", path4, "destination parent must be a regular directory", "path");
|
|
30966
30988
|
}
|
|
30967
30989
|
}
|
|
30968
30990
|
function destinationSha(projectRoot, path4) {
|
|
30969
|
-
const file =
|
|
30991
|
+
const file = join22(projectRoot, ...path4.split("/"));
|
|
30970
30992
|
if (!existsSync19(file)) return void 0;
|
|
30971
30993
|
return vnextContentSha256(readRegularBounded(file, path4));
|
|
30972
30994
|
}
|
|
30973
30995
|
function requireConditionalLinkSupport(directory, operationId, path4) {
|
|
30974
30996
|
const nonce = randomUUID10();
|
|
30975
|
-
const source =
|
|
30976
|
-
const target =
|
|
30997
|
+
const source = join22(directory, `.kxm-repair-${operationId}-${nonce}.link-source`);
|
|
30998
|
+
const target = join22(directory, `.kxm-repair-${operationId}-${nonce}.link-target`);
|
|
30977
30999
|
try {
|
|
30978
31000
|
writeDurableNew(source, Buffer.from("kxm-link-probe\n", "utf8"), 384);
|
|
30979
31001
|
try {
|
|
@@ -30988,16 +31010,16 @@ function requireConditionalLinkSupport(directory, operationId, path4) {
|
|
|
30988
31010
|
}
|
|
30989
31011
|
}
|
|
30990
31012
|
function atomicInstallTarget(projectRoot, operation, entry) {
|
|
30991
|
-
const destination =
|
|
31013
|
+
const destination = join22(projectRoot, ...entry.path.split("/"));
|
|
30992
31014
|
ensureDestinationParents(projectRoot, entry.path);
|
|
30993
31015
|
const directory = dirname13(destination);
|
|
30994
31016
|
const temporaryPrefix = `.kxm-repair-${operation.operationId}-`;
|
|
30995
31017
|
const pathKey = vnextContentSha256(entry.path).slice("sha256:".length, "sha256:".length + 16);
|
|
30996
|
-
const displaced =
|
|
31018
|
+
const displaced = join22(directory, `${temporaryPrefix}${pathKey}.preimage`);
|
|
30997
31019
|
if (existsSync19(displaced)) {
|
|
30998
31020
|
const stat = lstatSync7(displaced);
|
|
30999
31021
|
if (stat.isSymbolicLink() || !stat.isFile()) fail3("repair_preimage_temporary_invalid", entry.path, "stale displaced preimage is not a regular file", "path");
|
|
31000
|
-
if (entry.observedSha256 === null || vnextContentSha256(
|
|
31022
|
+
if (entry.observedSha256 === null || vnextContentSha256(readFileSync20(displaced)) !== entry.observedSha256) {
|
|
31001
31023
|
fail3("repair_preimage_temporary_mismatch", entry.path, "stale displaced preimage does not match the pinned operation");
|
|
31002
31024
|
}
|
|
31003
31025
|
if (!existsSync19(destination)) {
|
|
@@ -31015,7 +31037,7 @@ function atomicInstallTarget(projectRoot, operation, entry) {
|
|
|
31015
31037
|
const owned = candidate.name.startsWith(temporaryPrefix) && (candidate.name.endsWith(".tmp") || candidate.name.endsWith(".link-source") || candidate.name.endsWith(".link-target"));
|
|
31016
31038
|
if (!owned) continue;
|
|
31017
31039
|
if (!candidate.isFile()) fail3("repair_temporary_invalid", entry.path, "stale operation temporary is not a regular file", "path");
|
|
31018
|
-
rmSync7(
|
|
31040
|
+
rmSync7(join22(directory, candidate.name), { force: true });
|
|
31019
31041
|
}
|
|
31020
31042
|
const current = destinationSha(projectRoot, entry.path);
|
|
31021
31043
|
if (current === entry.targetSha256) return;
|
|
@@ -31025,14 +31047,14 @@ function atomicInstallTarget(projectRoot, operation, entry) {
|
|
|
31025
31047
|
requireConditionalLinkSupport(directory, operation.operationId, entry.path);
|
|
31026
31048
|
const bytes = readTarget(projectRoot, entry.path);
|
|
31027
31049
|
if (!bytes) fail3("init_transaction_target_missing", entry.path, "pinned target artifact is missing");
|
|
31028
|
-
const temporary =
|
|
31050
|
+
const temporary = join22(directory, `${temporaryPrefix}${randomUUID10()}.tmp`);
|
|
31029
31051
|
const mode = existsSync19(destination) ? lstatSync7(destination).mode & 511 : 420;
|
|
31030
31052
|
try {
|
|
31031
31053
|
writeDurableNew(temporary, bytes, mode);
|
|
31032
31054
|
if (entry.observedSha256 !== null) {
|
|
31033
31055
|
renameSync5(destination, displaced);
|
|
31034
31056
|
syncDirectory2(directory);
|
|
31035
|
-
if (vnextContentSha256(
|
|
31057
|
+
if (vnextContentSha256(readFileSync20(displaced)) !== entry.observedSha256) {
|
|
31036
31058
|
if (!existsSync19(destination)) {
|
|
31037
31059
|
try {
|
|
31038
31060
|
linkSync(displaced, destination);
|
|
@@ -31071,12 +31093,12 @@ function atomicInstallTarget(projectRoot, operation, entry) {
|
|
|
31071
31093
|
if (destinationSha(projectRoot, entry.path) !== entry.targetSha256) fail3("repair_install_verification_failed", entry.path, "installed target hash does not match the pinned operation");
|
|
31072
31094
|
}
|
|
31073
31095
|
function installedCreateMatches(projectRoot, operation) {
|
|
31074
|
-
const configRoot =
|
|
31096
|
+
const configRoot = join22(projectRoot, ".kxm");
|
|
31075
31097
|
if (!existsSync19(configRoot)) return false;
|
|
31076
31098
|
const actual = [];
|
|
31077
31099
|
const visit2 = (directory) => {
|
|
31078
31100
|
for (const entry of readdirSync7(directory, { withFileTypes: true })) {
|
|
31079
|
-
const absolute =
|
|
31101
|
+
const absolute = join22(directory, entry.name);
|
|
31080
31102
|
if (entry.isSymbolicLink()) fail3("create_resume_link", relativeConfigPath(projectRoot, absolute), "created configuration must not contain links", "path");
|
|
31081
31103
|
if (entry.isDirectory()) visit2(absolute);
|
|
31082
31104
|
else if (entry.isFile()) actual.push(relativeConfigPath(projectRoot, absolute));
|
|
@@ -31097,7 +31119,7 @@ function syncTreeDirectories(root) {
|
|
|
31097
31119
|
const visit2 = (directory) => {
|
|
31098
31120
|
directories.push(directory);
|
|
31099
31121
|
for (const entry of readdirSync7(directory, { withFileTypes: true })) {
|
|
31100
|
-
if (entry.isDirectory()) visit2(
|
|
31122
|
+
if (entry.isDirectory()) visit2(join22(directory, entry.name));
|
|
31101
31123
|
}
|
|
31102
31124
|
};
|
|
31103
31125
|
visit2(root);
|
|
@@ -31111,7 +31133,7 @@ function rebuildCreateShadow(projectRoot, operation, options) {
|
|
|
31111
31133
|
if (stat.isSymbolicLink() || !stat.isDirectory() || !installedCreateMatches(shadow, operation)) {
|
|
31112
31134
|
fail3("create_shadow_invalid", TRANSACTION_NAME, "reconstructed create shadow does not exactly match pinned target files", "path");
|
|
31113
31135
|
}
|
|
31114
|
-
syncTreeDirectories(
|
|
31136
|
+
syncTreeDirectories(join22(shadow, ".kxm"));
|
|
31115
31137
|
}
|
|
31116
31138
|
function applyOperation(projectRoot, original, options, resumed) {
|
|
31117
31139
|
assertNoRegisteredGates(options);
|
|
@@ -31121,10 +31143,10 @@ function applyOperation(projectRoot, original, options, resumed) {
|
|
|
31121
31143
|
verifyBackups(projectRoot, operation);
|
|
31122
31144
|
operation = updatePhase(projectRoot, operation, "applying");
|
|
31123
31145
|
if (operation.kind === "create") {
|
|
31124
|
-
const destination =
|
|
31146
|
+
const destination = join22(projectRoot, ".kxm");
|
|
31125
31147
|
if (!existsSync19(destination)) {
|
|
31126
31148
|
rebuildCreateShadow(projectRoot, operation, effectiveOptions);
|
|
31127
|
-
renameSync5(
|
|
31149
|
+
renameSync5(join22(shadowRoot(projectRoot), ".kxm"), destination);
|
|
31128
31150
|
syncDirectory2(projectRoot);
|
|
31129
31151
|
} else if (!installedCreateMatches(projectRoot, operation)) {
|
|
31130
31152
|
fail3("create_resume_conflict", ".kxm", "existing project configuration does not match the pinned create operation");
|
|
@@ -31151,7 +31173,7 @@ function applyOperation(projectRoot, original, options, resumed) {
|
|
|
31151
31173
|
operation = updatePhase(projectRoot, operation, "verified");
|
|
31152
31174
|
if (options.testFaultAt === "verified") throw new Error("injected init fault after verification");
|
|
31153
31175
|
const files = operation.files.map((entry) => entry.path);
|
|
31154
|
-
syncTreeDirectories(
|
|
31176
|
+
syncTreeDirectories(join22(projectRoot, ".kxm"));
|
|
31155
31177
|
return { kind: operation.kind, resumed, bundle, files };
|
|
31156
31178
|
}
|
|
31157
31179
|
function prepareAndApplyVnextCreate(projectRoot, rendered, options = {}) {
|
|
@@ -31266,7 +31288,7 @@ function finishPreparingOperation(projectRoot, operation, options) {
|
|
|
31266
31288
|
const rendered = rendererForOperation(operation);
|
|
31267
31289
|
if (!rendered) fail3("init_transaction_renderer_unavailable", TRANSACTION_NAME, "this binary cannot reproduce the pinned pre-application target");
|
|
31268
31290
|
for (const directory of ["targets", "backups", "shadow"]) {
|
|
31269
|
-
rmSync7(
|
|
31291
|
+
rmSync7(join22(transactionRoot(projectRoot), directory), { recursive: true, force: true });
|
|
31270
31292
|
}
|
|
31271
31293
|
for (const entry of operation.files) {
|
|
31272
31294
|
const bytes = rendered.files.get(entry.path);
|
|
@@ -31301,7 +31323,7 @@ function commitVnextInitTransaction(projectRoot, schemasDir) {
|
|
|
31301
31323
|
fail3("init_transaction_not_verified", TRANSACTION_NAME, "initialization transaction cannot commit before installed state is verified");
|
|
31302
31324
|
}
|
|
31303
31325
|
const transaction = transactionRoot(projectRoot);
|
|
31304
|
-
const retired =
|
|
31326
|
+
const retired = join22(projectRoot, `${TRANSACTION_NAME}-cleanup-${operation.operationId}-${randomUUID10()}`);
|
|
31305
31327
|
renameSync5(transaction, retired);
|
|
31306
31328
|
syncDirectory2(projectRoot);
|
|
31307
31329
|
rmSync7(retired, { recursive: true, force: true });
|
|
@@ -31322,7 +31344,7 @@ function initIssue(code, file, message) {
|
|
|
31322
31344
|
return { phase: "discovery", code, file, message };
|
|
31323
31345
|
}
|
|
31324
31346
|
function normalizedProjectName(root, requested) {
|
|
31325
|
-
const name = (requested ??
|
|
31347
|
+
const name = (requested ?? basename5(root) ?? "KXM Project").trim();
|
|
31326
31348
|
if (name.length < 1 || name.length > 120 || /[\u0000\r\n]/.test(name)) {
|
|
31327
31349
|
throw new VnextConfigError([initIssue("project_name_invalid", ".kxm/project.yaml", "project name must contain 1-120 characters on one line")]);
|
|
31328
31350
|
}
|
|
@@ -31410,7 +31432,7 @@ function validateBindingIdentities(bundle, persisted, explicit) {
|
|
|
31410
31432
|
}
|
|
31411
31433
|
function initializeVnextProjectAtGitRoot(start, gitRoot, options, mutationLock) {
|
|
31412
31434
|
const storeOptions = bindingStoreOptions(options);
|
|
31413
|
-
const persisted = existsSync20(
|
|
31435
|
+
const persisted = existsSync20(join23(gitRoot, ".kxm", "project.yaml")) ? readVnextLocalBindings(gitRoot, storeOptions) : void 0;
|
|
31414
31436
|
const repositoryBindings = Object.fromEntries([
|
|
31415
31437
|
...Object.entries(persisted?.repositories ?? {}),
|
|
31416
31438
|
...Object.entries(options.repositoryBindings ?? {})
|
|
@@ -31599,7 +31621,7 @@ function initializeVnextProjectAtGitRoot(start, gitRoot, options, mutationLock)
|
|
|
31599
31621
|
const files = [...rendered.files.keys()];
|
|
31600
31622
|
if (options.dryRun) return { action: "planned", plan, projectRoot: gitRoot, files };
|
|
31601
31623
|
if (!mutationLock) throw new Error("project mutation lock is required to create configuration");
|
|
31602
|
-
if (existsSync20(
|
|
31624
|
+
if (existsSync20(join23(gitRoot, ".kxm"))) {
|
|
31603
31625
|
throw new VnextConfigError([initIssue("workspace_changed", ".kxm", "workspace changed after planning; existing .kxm state was not overwritten")]);
|
|
31604
31626
|
}
|
|
31605
31627
|
const created = prepareAndApplyVnextCreate(gitRoot, rendered, transactionOptions);
|
|
@@ -31631,8 +31653,8 @@ function initializeVnextProject(start = process.cwd(), options = {}) {
|
|
|
31631
31653
|
// plugins/kxm/src/vnext-migrate.ts
|
|
31632
31654
|
var import_yaml12 = __toESM(require_dist(), 1);
|
|
31633
31655
|
import { createHash as createHash13 } from "node:crypto";
|
|
31634
|
-
import { chmodSync as chmodSync6, closeSync as closeSync3, existsSync as existsSync21, fsyncSync as fsyncSync3, lstatSync as lstatSync8, mkdirSync as mkdirSync18, openSync as openSync3, readFileSync as
|
|
31635
|
-
import { join as
|
|
31656
|
+
import { chmodSync as chmodSync6, closeSync as closeSync3, existsSync as existsSync21, fsyncSync as fsyncSync3, lstatSync as lstatSync8, mkdirSync as mkdirSync18, openSync as openSync3, readFileSync as readFileSync21, renameSync as renameSync6, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "node:fs";
|
|
31657
|
+
import { join as join24 } from "node:path";
|
|
31636
31658
|
var MAX_LEGACY_JSON_BYTES = 1024 * 1024;
|
|
31637
31659
|
var MAX_LEGACY_JSON_DEPTH = 32;
|
|
31638
31660
|
var MAX_LEGACY_JSON_NODES = 32768;
|
|
@@ -31801,12 +31823,12 @@ function readVnextLegacySources(root) {
|
|
|
31801
31823
|
throw new VnextConfigError([migrateIssue("discovery", "legacy_source_limit", ".kxm/config", `legacy configuration exceeds ${MAX_LEGACY_SOURCES} files`)]);
|
|
31802
31824
|
}
|
|
31803
31825
|
return files.map((path4) => {
|
|
31804
|
-
const absolute =
|
|
31826
|
+
const absolute = join24(root, ...path4.split("/"));
|
|
31805
31827
|
const stat = lstatSync8(absolute);
|
|
31806
31828
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
31807
31829
|
throw new VnextConfigError([migrateIssue("path", "legacy_source_invalid", path4, "legacy configuration must be a regular file, not a link")]);
|
|
31808
31830
|
}
|
|
31809
|
-
const buffer =
|
|
31831
|
+
const buffer = readFileSync21(absolute);
|
|
31810
31832
|
let text;
|
|
31811
31833
|
try {
|
|
31812
31834
|
text = new TextDecoder("utf-8", { fatal: true }).decode(buffer);
|
|
@@ -32883,7 +32905,7 @@ function readVnextMigrationDecisions(path4, schemasDir) {
|
|
|
32883
32905
|
throw new VnextConfigError([migrateIssue("discovery", "decisions_missing", path4, "migration decisions file does not exist")]);
|
|
32884
32906
|
}
|
|
32885
32907
|
const registry = new VnextSchemaRegistry(schemasDir);
|
|
32886
|
-
const value = parseRestrictedYaml2(
|
|
32908
|
+
const value = parseRestrictedYaml2(readFileSync21(path4), path4);
|
|
32887
32909
|
const issues = registry.validateMigrationDecision(value, path4);
|
|
32888
32910
|
if (issues.length > 0) throw new VnextConfigError(issues);
|
|
32889
32911
|
return value;
|
|
@@ -32922,7 +32944,7 @@ function writeDurable2(path4, content) {
|
|
|
32922
32944
|
chmodSync6(path4, 384);
|
|
32923
32945
|
} catch {
|
|
32924
32946
|
}
|
|
32925
|
-
syncDirectory3(
|
|
32947
|
+
syncDirectory3(join24(path4, ".."));
|
|
32926
32948
|
} finally {
|
|
32927
32949
|
if (created && existsSync21(temp)) rmSync8(temp, { force: true });
|
|
32928
32950
|
}
|
|
@@ -32934,7 +32956,7 @@ function applyVnextMigration(projectRoot, options = {}) {
|
|
|
32934
32956
|
...options.schemasDir === void 0 ? {} : { schemasDir: options.schemasDir }
|
|
32935
32957
|
};
|
|
32936
32958
|
const execute = (lock) => {
|
|
32937
|
-
const receiptAbsolute =
|
|
32959
|
+
const receiptAbsolute = join24(root, ...VNEXT_MIGRATION_RECEIPT_PATH.split("/"));
|
|
32938
32960
|
if (existsSync21(receiptAbsolute)) {
|
|
32939
32961
|
const stat = lstatSync8(receiptAbsolute);
|
|
32940
32962
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
@@ -32988,7 +33010,7 @@ function applyVnextMigration(projectRoot, options = {}) {
|
|
|
32988
33010
|
return { action: "planned", projectRoot: root, files: [], plan: first.plan };
|
|
32989
33011
|
}
|
|
32990
33012
|
const files = [...first.resources.entries()].sort(([left], [right]) => compareCodeUnits6(left, right)).map(([path4, value]) => ({ path: path4, bytes: Buffer.from((0, import_yaml12.stringify)(value, { lineWidth: 0 }), "utf8") }));
|
|
32991
|
-
const collisions = files.filter((file) => existsSync21(
|
|
33013
|
+
const collisions = files.filter((file) => existsSync21(join24(root, ...file.path.split("/"))));
|
|
32992
33014
|
if (collisions.length > 0) {
|
|
32993
33015
|
throw new VnextConfigError(collisions.map((file) => migrateIssue("semantic", "migration_target_exists", file.path, "target resource already exists; refusing to overwrite")));
|
|
32994
33016
|
}
|
|
@@ -32997,7 +33019,7 @@ function applyVnextMigration(projectRoot, options = {}) {
|
|
|
32997
33019
|
const segments = file.path.split("/");
|
|
32998
33020
|
let current = root;
|
|
32999
33021
|
for (const segment of segments.slice(0, -1)) {
|
|
33000
|
-
current =
|
|
33022
|
+
current = join24(current, segment);
|
|
33001
33023
|
if (!existsSync21(current)) continue;
|
|
33002
33024
|
const stat = lstatSync8(current);
|
|
33003
33025
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
@@ -33014,8 +33036,8 @@ function applyVnextMigration(projectRoot, options = {}) {
|
|
|
33014
33036
|
const written = [];
|
|
33015
33037
|
try {
|
|
33016
33038
|
for (const file of files) {
|
|
33017
|
-
const absolute =
|
|
33018
|
-
mkdirSync18(
|
|
33039
|
+
const absolute = join24(root, ...file.path.split("/"));
|
|
33040
|
+
mkdirSync18(join24(absolute, ".."), { recursive: true });
|
|
33019
33041
|
written.push(absolute);
|
|
33020
33042
|
writeDurable2(absolute, file.bytes);
|
|
33021
33043
|
}
|
|
@@ -33061,7 +33083,7 @@ ${bundle.configRevision}`).slice(7, 39)}`,
|
|
|
33061
33083
|
}
|
|
33062
33084
|
function verifyVnextMigration(projectRoot, options = {}) {
|
|
33063
33085
|
const root = migrationGitRoot(projectRoot);
|
|
33064
|
-
const receiptAbsolute =
|
|
33086
|
+
const receiptAbsolute = join24(root, ...VNEXT_MIGRATION_RECEIPT_PATH.split("/"));
|
|
33065
33087
|
if (!existsSync21(receiptAbsolute)) {
|
|
33066
33088
|
return {
|
|
33067
33089
|
ok: false,
|
|
@@ -33372,7 +33394,7 @@ async function cmdBackup(runtime, options) {
|
|
|
33372
33394
|
const summary = [
|
|
33373
33395
|
`Created SQLite backup with ${manifest.stores.length} store(s):`,
|
|
33374
33396
|
...manifest.stores.map((s) => ` - ${s.storeId}: ${s.sourcePath} -> ${s.backupFile} (schema v${s.schemaVersion}, ${s.bytes} bytes, sha256 ${s.sha256.slice(0, 12)}...)`),
|
|
33375
|
-
`Manifest: ${
|
|
33397
|
+
`Manifest: ${join25(outDir, "manifest.json")}`
|
|
33376
33398
|
].join("\n");
|
|
33377
33399
|
print(runtime.io, runtime.json, payload, summary);
|
|
33378
33400
|
return 0;
|
|
@@ -33942,7 +33964,7 @@ async function cmdStudioLayout(runtime, workflowPath) {
|
|
|
33942
33964
|
let yamlContent;
|
|
33943
33965
|
let workflowId = "default";
|
|
33944
33966
|
if (existsSync22(filePath)) {
|
|
33945
|
-
yamlContent =
|
|
33967
|
+
yamlContent = readFileSync22(filePath, "utf8");
|
|
33946
33968
|
} else {
|
|
33947
33969
|
yamlContent = `schema: kxm.workflow.v1
|
|
33948
33970
|
description: Feature implementation workflow
|
|
@@ -34015,17 +34037,17 @@ async function cmdStudioServe(runtime, options) {
|
|
|
34015
34037
|
sessionToken,
|
|
34016
34038
|
planProvider: () => {
|
|
34017
34039
|
try {
|
|
34018
|
-
const wfDir =
|
|
34019
|
-
const defaultPath =
|
|
34040
|
+
const wfDir = join26(runtime.cwd, ".kxm", "workflows");
|
|
34041
|
+
const defaultPath = join26(wfDir, "default.yaml");
|
|
34020
34042
|
let targetPath = existsSync22(defaultPath) ? defaultPath : void 0;
|
|
34021
34043
|
if (!targetPath && existsSync22(wfDir)) {
|
|
34022
34044
|
const yml = readdirSync8(wfDir).find((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
|
|
34023
|
-
if (yml) targetPath =
|
|
34045
|
+
if (yml) targetPath = join26(wfDir, yml);
|
|
34024
34046
|
}
|
|
34025
34047
|
if (targetPath && existsSync22(targetPath)) {
|
|
34026
|
-
const raw =
|
|
34048
|
+
const raw = readFileSync22(targetPath, "utf8");
|
|
34027
34049
|
const parsed = (0, import_yaml13.parse)(raw);
|
|
34028
|
-
const wfId =
|
|
34050
|
+
const wfId = basename6(targetPath).replace(/\.(yaml|yml)$/, "");
|
|
34029
34051
|
return compileVnextWorkflow({ id: wfId, value: parsed });
|
|
34030
34052
|
}
|
|
34031
34053
|
} catch {
|
|
@@ -34073,14 +34095,14 @@ Press Ctrl+C to stop.
|
|
|
34073
34095
|
}
|
|
34074
34096
|
|
|
34075
34097
|
// plugins/kxm/src/cli/context-skills.ts
|
|
34076
|
-
import { readFileSync as
|
|
34077
|
-
import { join as
|
|
34098
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
34099
|
+
import { join as join30, relative as relative5 } from "node:path";
|
|
34078
34100
|
|
|
34079
34101
|
// plugins/kxm/src/memory.ts
|
|
34080
34102
|
var import_yaml14 = __toESM(require_dist(), 1);
|
|
34081
34103
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
34082
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync19, readdirSync as readdirSync9, readFileSync as
|
|
34083
|
-
import { extname as extname2, join as
|
|
34104
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync19, readdirSync as readdirSync9, readFileSync as readFileSync23, writeFileSync as writeFileSync18 } from "node:fs";
|
|
34105
|
+
import { extname as extname2, join as join27, resolve as resolve22 } from "node:path";
|
|
34084
34106
|
var MEMORY_SCHEMA = "kxm.memory.v1";
|
|
34085
34107
|
var MEMORY_BRIEF_SCHEMA = "kxm.memory-brief.v1";
|
|
34086
34108
|
var MEMORY_MARKER_START = "<!-- kxm:memory:start -->";
|
|
@@ -34207,8 +34229,8 @@ ${yamlText}
|
|
|
34207
34229
|
}
|
|
34208
34230
|
function memoryDirectories(repoRoot6) {
|
|
34209
34231
|
const root = resolve22(repoRoot6);
|
|
34210
|
-
const memoryDir =
|
|
34211
|
-
const candidatesDir =
|
|
34232
|
+
const memoryDir = join27(root, ".kxm", "memory");
|
|
34233
|
+
const candidatesDir = join27(memoryDir, "candidates");
|
|
34212
34234
|
return { memoryDir, candidatesDir };
|
|
34213
34235
|
}
|
|
34214
34236
|
function loadAuthoredMemory(repoRoot6) {
|
|
@@ -34218,9 +34240,9 @@ function loadAuthoredMemory(repoRoot6) {
|
|
|
34218
34240
|
const entries = readdirSync9(memoryDir, { withFileTypes: true });
|
|
34219
34241
|
for (const entry of entries) {
|
|
34220
34242
|
if (entry.isFile() && extname2(entry.name) === ".md") {
|
|
34221
|
-
const fullPath =
|
|
34243
|
+
const fullPath = join27(memoryDir, entry.name);
|
|
34222
34244
|
try {
|
|
34223
|
-
const text =
|
|
34245
|
+
const text = readFileSync23(fullPath, "utf8");
|
|
34224
34246
|
const record = parseMemoryRecord(text, entry.name);
|
|
34225
34247
|
if (record.lifecycle === "active") {
|
|
34226
34248
|
records.push(record);
|
|
@@ -34259,7 +34281,7 @@ function createMemoryNote(repoRoot6, summary, options = {}) {
|
|
|
34259
34281
|
evidenceRefs: [],
|
|
34260
34282
|
...options.body ? { body: options.body.trim() } : {}
|
|
34261
34283
|
};
|
|
34262
|
-
const targetPath =
|
|
34284
|
+
const targetPath = join27(candidatesDir, `${id}.md`);
|
|
34263
34285
|
writeFileSync18(targetPath, formatMemoryRecord(record), "utf8");
|
|
34264
34286
|
return { record, path: targetPath };
|
|
34265
34287
|
}
|
|
@@ -34297,7 +34319,7 @@ function formatHarnessMemoryBlock(records) {
|
|
|
34297
34319
|
function updateHarnessDocument(filePath, block, defaultHeader) {
|
|
34298
34320
|
let original = "";
|
|
34299
34321
|
if (existsSync23(filePath)) {
|
|
34300
|
-
original =
|
|
34322
|
+
original = readFileSync23(filePath, "utf8");
|
|
34301
34323
|
}
|
|
34302
34324
|
let updated = "";
|
|
34303
34325
|
if (original.includes(MEMORY_MARKER_START) && original.includes(MEMORY_MARKER_END)) {
|
|
@@ -34336,14 +34358,14 @@ function syncHarnessMemory(repoRoot6) {
|
|
|
34336
34358
|
const block = formatHarnessMemoryBlock(records);
|
|
34337
34359
|
const updated = [];
|
|
34338
34360
|
const created = [];
|
|
34339
|
-
const agentsPath =
|
|
34361
|
+
const agentsPath = join27(root, "AGENTS.md");
|
|
34340
34362
|
const agentsHeader = "# AGENTS\n\nFollow project instructions.\n";
|
|
34341
34363
|
const agentsExisted = existsSync23(agentsPath);
|
|
34342
34364
|
if (updateHarnessDocument(agentsPath, block, agentsHeader)) {
|
|
34343
34365
|
if (agentsExisted) updated.push("AGENTS.md");
|
|
34344
34366
|
else created.push("AGENTS.md");
|
|
34345
34367
|
}
|
|
34346
|
-
const claudePath =
|
|
34368
|
+
const claudePath = join27(root, "CLAUDE.md");
|
|
34347
34369
|
const claudeHeader = `# KXM (Claude)
|
|
34348
34370
|
|
|
34349
34371
|
Follow [\`AGENTS.md\`](AGENTS.md). Official phase tracking:
|
|
@@ -34359,7 +34381,7 @@ artifacts, not hub \`peer-reply\` evidence.
|
|
|
34359
34381
|
if (claudeExisted) updated.push("CLAUDE.md");
|
|
34360
34382
|
else created.push("CLAUDE.md");
|
|
34361
34383
|
}
|
|
34362
|
-
const geminiPath =
|
|
34384
|
+
const geminiPath = join27(root, "GEMINI.md");
|
|
34363
34385
|
const geminiHeader = `# KXM (Gemini / Antigravity)
|
|
34364
34386
|
|
|
34365
34387
|
Follow [\`AGENTS.md\`](AGENTS.md). Official phase tracking:
|
|
@@ -34379,8 +34401,8 @@ for Gemini models. Starting rotation remains Grok.
|
|
|
34379
34401
|
// plugins/kxm/src/skills.ts
|
|
34380
34402
|
var import_yaml15 = __toESM(require_dist(), 1);
|
|
34381
34403
|
import { createHash as createHash14 } from "node:crypto";
|
|
34382
|
-
import { existsSync as existsSync24, mkdirSync as mkdirSync20, readdirSync as readdirSync10, readFileSync as
|
|
34383
|
-
import { join as
|
|
34404
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync20, readdirSync as readdirSync10, readFileSync as readFileSync24, renameSync as renameSync7, rmSync as rmSync9, statSync as statSync3, writeFileSync as writeFileSync19 } from "node:fs";
|
|
34405
|
+
import { join as join28 } from "node:path";
|
|
34384
34406
|
var SKILL_CANDIDATE_SCHEMA = "kxm.skill-candidate.v1";
|
|
34385
34407
|
var SKILL_EVALUATION_SCHEMA = "kxm.skill-evaluation.v1";
|
|
34386
34408
|
var SKILL_DECISION_SCHEMA = "kxm.skill-decision.v1";
|
|
@@ -34474,21 +34496,21 @@ var SkillLifecycle = class {
|
|
|
34474
34496
|
this.allowOptimizationEvals = options.allowOptimizationEvals === true;
|
|
34475
34497
|
}
|
|
34476
34498
|
dir(state) {
|
|
34477
|
-
return
|
|
34499
|
+
return join28(this.root, state === "candidate" ? "candidates" : `${state}s`.replace("rejecteds", "rejected").replace("promoteds", "promoted"));
|
|
34478
34500
|
}
|
|
34479
34501
|
historyFile(id) {
|
|
34480
|
-
return
|
|
34502
|
+
return join28(this.root, "history", `${id}.jsonl`);
|
|
34481
34503
|
}
|
|
34482
34504
|
paths(state, id) {
|
|
34483
|
-
const dir =
|
|
34484
|
-
return { dir, metadata:
|
|
34505
|
+
const dir = join28(this.dir(state), id);
|
|
34506
|
+
return { dir, metadata: join28(dir, "metadata.json"), skill: join28(dir, "SKILL.md") };
|
|
34485
34507
|
}
|
|
34486
34508
|
appendHistory(id, record) {
|
|
34487
|
-
mkdirSync20(
|
|
34509
|
+
mkdirSync20(join28(this.root, "history"), { recursive: true });
|
|
34488
34510
|
const line = `${JSON.stringify(record)}
|
|
34489
34511
|
`;
|
|
34490
34512
|
if (existsSync24(this.historyFile(id))) {
|
|
34491
|
-
const existing =
|
|
34513
|
+
const existing = readFileSync24(this.historyFile(id), "utf8");
|
|
34492
34514
|
const lines = existing.split("\n").filter((entry) => entry.trim());
|
|
34493
34515
|
writeFileSync19(this.historyFile(id), [...lines.slice(-499), line.trim()].join("\n") + "\n");
|
|
34494
34516
|
} else {
|
|
@@ -34498,18 +34520,18 @@ var SkillLifecycle = class {
|
|
|
34498
34520
|
history(id) {
|
|
34499
34521
|
const file = this.historyFile(id);
|
|
34500
34522
|
if (!existsSync24(file)) return [];
|
|
34501
|
-
return
|
|
34523
|
+
return readFileSync24(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
|
|
34502
34524
|
}
|
|
34503
34525
|
readMetadata(state, id) {
|
|
34504
34526
|
const { metadata } = this.paths(state, id);
|
|
34505
34527
|
if (!existsSync24(metadata)) {
|
|
34506
34528
|
throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${state}`);
|
|
34507
34529
|
}
|
|
34508
|
-
return JSON.parse(
|
|
34530
|
+
return JSON.parse(readFileSync24(metadata, "utf8"));
|
|
34509
34531
|
}
|
|
34510
34532
|
move(from, to, id) {
|
|
34511
|
-
const fromDir =
|
|
34512
|
-
const toDir =
|
|
34533
|
+
const fromDir = join28(this.dir(from), id);
|
|
34534
|
+
const toDir = join28(this.dir(to), id);
|
|
34513
34535
|
if (!existsSync24(fromDir)) {
|
|
34514
34536
|
throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${from}`);
|
|
34515
34537
|
}
|
|
@@ -34668,13 +34690,13 @@ var SkillLifecycle = class {
|
|
|
34668
34690
|
const candidatePaths = this.paths("candidate", candidateId);
|
|
34669
34691
|
const promotedPaths = this.paths("promoted", candidateId);
|
|
34670
34692
|
mkdirSync20(promotedPaths.dir, { recursive: true });
|
|
34671
|
-
const skillContent =
|
|
34672
|
-
const metadataContent =
|
|
34693
|
+
const skillContent = readFileSync24(candidatePaths.skill, "utf8");
|
|
34694
|
+
const metadataContent = readFileSync24(candidatePaths.metadata, "utf8");
|
|
34673
34695
|
writeFileSync19(promotedPaths.skill, skillContent);
|
|
34674
34696
|
writeFileSync19(promotedPaths.metadata, metadataContent);
|
|
34675
|
-
const patchesDir =
|
|
34697
|
+
const patchesDir = join28(this.root, "patches");
|
|
34676
34698
|
mkdirSync20(patchesDir, { recursive: true });
|
|
34677
|
-
const patchPath =
|
|
34699
|
+
const patchPath = join28(patchesDir, `${candidateId}.patch`);
|
|
34678
34700
|
const relSkillPath = `.kxm/skills/promoted/${candidateId}/SKILL.md`;
|
|
34679
34701
|
const relMetaPath = `.kxm/skills/promoted/${candidateId}/metadata.json`;
|
|
34680
34702
|
const patch = `${createUnifiedPatch(relSkillPath, skillContent)}${createUnifiedPatch(relMetaPath, metadataContent)}`;
|
|
@@ -34702,7 +34724,7 @@ var SkillLifecycle = class {
|
|
|
34702
34724
|
verify(state, id) {
|
|
34703
34725
|
const metadata = this.readMetadata(state, id);
|
|
34704
34726
|
const { skill } = this.paths(state, id);
|
|
34705
|
-
const content =
|
|
34727
|
+
const content = readFileSync24(skill, "utf8");
|
|
34706
34728
|
if (skillContentSha256(content) !== metadata.contentSha256) {
|
|
34707
34729
|
throw new SkillLifecycleError(
|
|
34708
34730
|
"skill_integrity_violation",
|
|
@@ -34733,7 +34755,7 @@ var SkillLifecycle = class {
|
|
|
34733
34755
|
read(state, id) {
|
|
34734
34756
|
const metadata = this.readMetadata(state, id);
|
|
34735
34757
|
const { skill } = this.paths(state, id);
|
|
34736
|
-
return { metadata, content:
|
|
34758
|
+
return { metadata, content: readFileSync24(skill, "utf8") };
|
|
34737
34759
|
}
|
|
34738
34760
|
};
|
|
34739
34761
|
function boundedList(value, field) {
|
|
@@ -34748,16 +34770,16 @@ function boundedList(value, field) {
|
|
|
34748
34770
|
return [...new Set(refs)];
|
|
34749
34771
|
}
|
|
34750
34772
|
function readdirSorted(dir) {
|
|
34751
|
-
return readdirSync10(dir).filter((entry) => statSync3(
|
|
34773
|
+
return readdirSync10(dir).filter((entry) => statSync3(join28(dir, entry)).isDirectory()).sort();
|
|
34752
34774
|
}
|
|
34753
34775
|
|
|
34754
34776
|
// plugins/kxm/src/wiki.ts
|
|
34755
34777
|
import { mkdirSync as mkdirSync21, writeFileSync as writeFileSync20 } from "node:fs";
|
|
34756
|
-
import { join as
|
|
34778
|
+
import { join as join29 } from "node:path";
|
|
34757
34779
|
function writeCompiledWiki(root, wiki) {
|
|
34758
34780
|
const written = [];
|
|
34759
34781
|
for (const [relativePath, content] of [...wiki.pages].sort(([left], [right]) => left.localeCompare(right))) {
|
|
34760
|
-
const absolute =
|
|
34782
|
+
const absolute = join29(root, relativePath);
|
|
34761
34783
|
mkdirSync21(absolute.slice(0, absolute.lastIndexOf("/")), { recursive: true });
|
|
34762
34784
|
writeFileSync20(absolute, content);
|
|
34763
34785
|
written.push(relativePath);
|
|
@@ -34925,7 +34947,7 @@ function skillStateFromFlag(value) {
|
|
|
34925
34947
|
throw new Error(`invalid skill state ${value}`);
|
|
34926
34948
|
}
|
|
34927
34949
|
function skillsRoot(runtime) {
|
|
34928
|
-
return
|
|
34950
|
+
return join30(runtime.dirs.workdir, ".kxm", "skills");
|
|
34929
34951
|
}
|
|
34930
34952
|
function csv(value) {
|
|
34931
34953
|
if (!value) return void 0;
|
|
@@ -34942,7 +34964,7 @@ async function cmdSkillsCreate(runtime, options) {
|
|
|
34942
34964
|
const metadata = lifecycle.create({
|
|
34943
34965
|
name: options.name,
|
|
34944
34966
|
description: options.description ?? "",
|
|
34945
|
-
content:
|
|
34967
|
+
content: readFileSync25(options.file, "utf8"),
|
|
34946
34968
|
createdBy: options.createdBy,
|
|
34947
34969
|
sources: {
|
|
34948
34970
|
runIds: csv(options.run) ?? [],
|
|
@@ -35100,8 +35122,8 @@ async function cmdMemorySync(runtime) {
|
|
|
35100
35122
|
|
|
35101
35123
|
// plugins/kxm/src/cli/hub.ts
|
|
35102
35124
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
35103
|
-
import { existsSync as existsSync30, mkdirSync as mkdirSync25, readFileSync as
|
|
35104
|
-
import {
|
|
35125
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync25, readFileSync as readFileSync31, readdirSync as readdirSync12, rmSync as rmSync10, writeFileSync as writeFileSync23 } from "node:fs";
|
|
35126
|
+
import { join as join40, resolve as resolve25 } from "node:path";
|
|
35105
35127
|
|
|
35106
35128
|
// node_modules/marked/lib/marked.esm.js
|
|
35107
35129
|
function M() {
|
|
@@ -41034,7 +41056,7 @@ import * as path2 from "node:path";
|
|
|
41034
41056
|
|
|
41035
41057
|
// node_modules/@earendil-works/pi-tui/dist/native-module-path.js
|
|
41036
41058
|
import { createRequire as createRequire2 } from "node:module";
|
|
41037
|
-
import { dirname as dirname16, join as
|
|
41059
|
+
import { dirname as dirname16, join as join31 } from "node:path";
|
|
41038
41060
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
41039
41061
|
var moduleRequire = createRequire2(import.meta.url);
|
|
41040
41062
|
var TUI_PACKAGE_NAME = "@earendil-works/pi-tui";
|
|
@@ -41043,10 +41065,10 @@ function getNativeModuleCandidates(nativePath, options = {}) {
|
|
|
41043
41065
|
const candidates = [];
|
|
41044
41066
|
try {
|
|
41045
41067
|
const packageEntry = (options.resolvePackage ?? moduleRequire.resolve)(TUI_PACKAGE_NAME);
|
|
41046
|
-
candidates.push(
|
|
41068
|
+
candidates.push(join31(dirname16(packageEntry), "..", nativePath));
|
|
41047
41069
|
} catch {
|
|
41048
41070
|
}
|
|
41049
|
-
candidates.push(
|
|
41071
|
+
candidates.push(join31(moduleDir, "..", nativePath), join31(moduleDir, nativePath), join31(dirname16(options.execPath ?? process.execPath), nativePath));
|
|
41050
41072
|
return Array.from(new Set(candidates));
|
|
41051
41073
|
}
|
|
41052
41074
|
|
|
@@ -43503,7 +43525,7 @@ var MAX_RENDER_WRITE_CHARS = 1024 * 1024;
|
|
|
43503
43525
|
|
|
43504
43526
|
// plugins/kxm/src/tui.ts
|
|
43505
43527
|
import { mkdirSync as mkdirSync22 } from "node:fs";
|
|
43506
|
-
import { join as
|
|
43528
|
+
import { join as join35, resolve as resolve24, dirname as dirname17 } from "node:path";
|
|
43507
43529
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
43508
43530
|
|
|
43509
43531
|
// plugins/kxm/src/external-effects.ts
|
|
@@ -43514,9 +43536,9 @@ function slugifyBranchPart(text, maxLength = 40) {
|
|
|
43514
43536
|
}
|
|
43515
43537
|
|
|
43516
43538
|
// plugins/kxm/src/local-snapshot.ts
|
|
43517
|
-
import { existsSync as existsSync25, readdirSync as readdirSync11, readFileSync as
|
|
43539
|
+
import { existsSync as existsSync25, readdirSync as readdirSync11, readFileSync as readFileSync26 } from "node:fs";
|
|
43518
43540
|
import { homedir as homedir5 } from "node:os";
|
|
43519
|
-
import { isAbsolute as isAbsolute7, join as
|
|
43541
|
+
import { isAbsolute as isAbsolute7, join as join34, resolve as resolve23 } from "node:path";
|
|
43520
43542
|
function processExists2(pid) {
|
|
43521
43543
|
try {
|
|
43522
43544
|
process.kill(pid, 0);
|
|
@@ -43636,16 +43658,16 @@ function readOpenMessageMetadata(database) {
|
|
|
43636
43658
|
return messages;
|
|
43637
43659
|
}
|
|
43638
43660
|
function resolveKxmSnapshotPaths(cwd, env = process.env) {
|
|
43639
|
-
const stateDir = env.KXM_STATE_DIR?.trim() ||
|
|
43661
|
+
const stateDir = env.KXM_STATE_DIR?.trim() || join34(cwd, ".kxm", "state");
|
|
43640
43662
|
const configured = env.KXM_DATA_PATH?.trim();
|
|
43641
|
-
const dataPath = configured ? resolve23(cwd, configured) :
|
|
43663
|
+
const dataPath = configured ? resolve23(cwd, configured) : join34(stateDir, "kxm.db");
|
|
43642
43664
|
return { dataPath, stateDir };
|
|
43643
43665
|
}
|
|
43644
43666
|
function resolveVnextStateRoot(stateDir, options) {
|
|
43645
43667
|
if (options?.vnextStateRoot && existsSync25(options.vnextStateRoot)) {
|
|
43646
43668
|
return resolve23(options.vnextStateRoot);
|
|
43647
43669
|
}
|
|
43648
|
-
if (existsSync25(
|
|
43670
|
+
if (existsSync25(join34(stateDir, "runtime", "registry.db")) || existsSync25(join34(stateDir, "runtime", "projects"))) {
|
|
43649
43671
|
return stateDir;
|
|
43650
43672
|
}
|
|
43651
43673
|
const env = options?.env ?? process.env;
|
|
@@ -43656,13 +43678,13 @@ function resolveVnextStateRoot(stateDir, options) {
|
|
|
43656
43678
|
let base;
|
|
43657
43679
|
if (process.platform === "win32") {
|
|
43658
43680
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
43659
|
-
base = localAppData && isAbsolute7(localAppData) ? localAppData :
|
|
43681
|
+
base = localAppData && isAbsolute7(localAppData) ? localAppData : join34(homedir5(), "AppData", "Local");
|
|
43660
43682
|
base = resolve23(base, "KXM");
|
|
43661
43683
|
} else if (process.platform === "darwin") {
|
|
43662
43684
|
base = resolve23(homedir5(), "Library", "Application Support", "KXM");
|
|
43663
43685
|
} else {
|
|
43664
43686
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
43665
|
-
base = xdgState && isAbsolute7(xdgState) ? xdgState :
|
|
43687
|
+
base = xdgState && isAbsolute7(xdgState) ? xdgState : join34(homedir5(), ".local", "state");
|
|
43666
43688
|
base = resolve23(base, "kxm");
|
|
43667
43689
|
}
|
|
43668
43690
|
if (existsSync25(base)) return base;
|
|
@@ -43696,9 +43718,9 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
43696
43718
|
let vnextRunTotal = 0;
|
|
43697
43719
|
const vnextStateRoot = resolveVnextStateRoot(stateDir, options);
|
|
43698
43720
|
if (vnextStateRoot) {
|
|
43699
|
-
const runtimeDir =
|
|
43700
|
-
const registryDbPath =
|
|
43701
|
-
const projectsDir =
|
|
43721
|
+
const runtimeDir = join34(vnextStateRoot, "runtime");
|
|
43722
|
+
const registryDbPath = join34(runtimeDir, "registry.db");
|
|
43723
|
+
const projectsDir = join34(runtimeDir, "projects");
|
|
43702
43724
|
const projectKeys = /* @__PURE__ */ new Set();
|
|
43703
43725
|
if (existsSync25(registryDbPath)) {
|
|
43704
43726
|
hasVnext = true;
|
|
@@ -43727,7 +43749,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
43727
43749
|
}
|
|
43728
43750
|
}
|
|
43729
43751
|
for (const key of projectKeys) {
|
|
43730
|
-
const eventDbPath =
|
|
43752
|
+
const eventDbPath = join34(projectsDir, key, "run-events.db");
|
|
43731
43753
|
if (existsSync25(eventDbPath)) {
|
|
43732
43754
|
hasVnext = true;
|
|
43733
43755
|
try {
|
|
@@ -43761,7 +43783,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
43761
43783
|
if (existsSync25(stateDir)) {
|
|
43762
43784
|
for (const file of readdirSync11(stateDir).filter((name) => name.endsWith(".pid"))) {
|
|
43763
43785
|
try {
|
|
43764
|
-
const record = JSON.parse(
|
|
43786
|
+
const record = JSON.parse(readFileSync26(join34(stateDir, file), "utf8"));
|
|
43765
43787
|
pids.push({
|
|
43766
43788
|
file,
|
|
43767
43789
|
...record.role ? { role: record.role } : {},
|
|
@@ -43800,7 +43822,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
43800
43822
|
} else {
|
|
43801
43823
|
source = "legacy";
|
|
43802
43824
|
}
|
|
43803
|
-
const telemetryFile =
|
|
43825
|
+
const telemetryFile = join34(stateDir, "telemetry.jsonl");
|
|
43804
43826
|
const spend = existsSync25(telemetryFile) ? readRoutingRecords(telemetryFile) : [];
|
|
43805
43827
|
return {
|
|
43806
43828
|
source,
|
|
@@ -43935,7 +43957,7 @@ function spawnDegradeWorktree(repoRoot6, runId, options) {
|
|
|
43935
43957
|
const cleanRunId = runId.replace(/^run_/, "");
|
|
43936
43958
|
const desc = options?.description ? slugifyBranchPart(options.description, 30) : "degrade";
|
|
43937
43959
|
const branchName = `kxm/run-${cleanRunId}-${desc}`;
|
|
43938
|
-
const relativeWtPath =
|
|
43960
|
+
const relativeWtPath = join35(".kxm", "worktrees", `run-${cleanRunId}-${desc}`);
|
|
43939
43961
|
const absoluteWtPath = resolve24(repoRoot6, relativeWtPath);
|
|
43940
43962
|
const jumpCommand = `cd "${absoluteWtPath}"`;
|
|
43941
43963
|
try {
|
|
@@ -44705,8 +44727,8 @@ async function runMeshTui(input) {
|
|
|
44705
44727
|
// plugins/kxm/src/session-work.ts
|
|
44706
44728
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
44707
44729
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
44708
|
-
import { existsSync as existsSync26, mkdirSync as mkdirSync23, readFileSync as
|
|
44709
|
-
import { join as
|
|
44730
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync23, readFileSync as readFileSync27, renameSync as renameSync8, writeFileSync as writeFileSync21 } from "node:fs";
|
|
44731
|
+
import { join as join36 } from "node:path";
|
|
44710
44732
|
var MAX_SESSION_BRIEF_TASKS = 5;
|
|
44711
44733
|
var MAX_SESSION_BRIEF_PLANS = 5;
|
|
44712
44734
|
var SESSION_BRIEF_SCHEMA = "kxm.session-brief.v1";
|
|
@@ -44862,10 +44884,10 @@ function buildSessionBrief(snapshot, current, hub, ship, updateLatest, cost, ses
|
|
|
44862
44884
|
};
|
|
44863
44885
|
}
|
|
44864
44886
|
function readCachedSessionBrief(stateDir) {
|
|
44865
|
-
const file =
|
|
44887
|
+
const file = join36(stateDir, "session-brief.json");
|
|
44866
44888
|
try {
|
|
44867
44889
|
if (!existsSync26(file)) return void 0;
|
|
44868
|
-
const raw =
|
|
44890
|
+
const raw = readFileSync27(file, "utf8");
|
|
44869
44891
|
const parsed = JSON.parse(raw);
|
|
44870
44892
|
if (parsed && parsed.schema === "kxm.session-brief.v1" && typeof parsed.generatedAt === "string") {
|
|
44871
44893
|
const ageMs = Date.now() - Date.parse(parsed.generatedAt);
|
|
@@ -44881,7 +44903,7 @@ function readCachedSessionBrief(stateDir) {
|
|
|
44881
44903
|
function writeCachedSessionBrief(stateDir, brief) {
|
|
44882
44904
|
try {
|
|
44883
44905
|
mkdirSync23(stateDir, { recursive: true, mode: 448 });
|
|
44884
|
-
const file =
|
|
44906
|
+
const file = join36(stateDir, "session-brief.json");
|
|
44885
44907
|
const tmp = `${file}.tmp.${randomUUID13().slice(0, 8)}`;
|
|
44886
44908
|
writeFileSync21(tmp, JSON.stringify(brief, null, 2), { encoding: "utf8", mode: 384 });
|
|
44887
44909
|
renameSync8(tmp, file);
|
|
@@ -44890,7 +44912,7 @@ function writeCachedSessionBrief(stateDir, brief) {
|
|
|
44890
44912
|
}
|
|
44891
44913
|
function estimateSessionCost(stateDir) {
|
|
44892
44914
|
try {
|
|
44893
|
-
const telemetryFile =
|
|
44915
|
+
const telemetryFile = join36(stateDir, "telemetry.jsonl");
|
|
44894
44916
|
if (!existsSync26(telemetryFile)) return void 0;
|
|
44895
44917
|
const records = readRoutingRecords(telemetryFile);
|
|
44896
44918
|
if (records.length === 0) return void 0;
|
|
@@ -45059,11 +45081,11 @@ function formatSessionBriefText(brief) {
|
|
|
45059
45081
|
}
|
|
45060
45082
|
|
|
45061
45083
|
// plugins/kxm/src/kxm-install-kind.ts
|
|
45062
|
-
import { existsSync as existsSync27, readFileSync as
|
|
45063
|
-
import { dirname as dirname18, join as
|
|
45084
|
+
import { existsSync as existsSync27, readFileSync as readFileSync28 } from "node:fs";
|
|
45085
|
+
import { dirname as dirname18, join as join37 } from "node:path";
|
|
45064
45086
|
function packageIsKxm(root) {
|
|
45065
45087
|
try {
|
|
45066
|
-
const pkg = JSON.parse(
|
|
45088
|
+
const pkg = JSON.parse(readFileSync28(join37(root, "package.json"), "utf8"));
|
|
45067
45089
|
return pkg.name === "@kontextmind/kxm";
|
|
45068
45090
|
} catch {
|
|
45069
45091
|
return false;
|
|
@@ -45112,12 +45134,12 @@ function report(kind, root) {
|
|
|
45112
45134
|
return { kind, root, instruction: installKindInstruction(kind, root) };
|
|
45113
45135
|
}
|
|
45114
45136
|
function classifyInstallRoot(probe) {
|
|
45115
|
-
const piGitRoot =
|
|
45137
|
+
const piGitRoot = join37(probe.homeDir, ".pi", "agent", "git");
|
|
45116
45138
|
if (isUnder(probe.repoRoot, piGitRoot, probe.platform)) return report("pi-git", probe.repoRoot);
|
|
45117
|
-
const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() ||
|
|
45118
|
-
const pluginsRoot =
|
|
45139
|
+
const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() || join37(probe.homeDir, ".claude");
|
|
45140
|
+
const pluginsRoot = join37(claudeHome, "plugins");
|
|
45119
45141
|
if (isUnder(probe.moduleDir, pluginsRoot, probe.platform)) return report("claude-marketplace", probe.moduleDir);
|
|
45120
|
-
const hasGit = existsSync27(
|
|
45142
|
+
const hasGit = existsSync27(join37(probe.repoRoot, ".git"));
|
|
45121
45143
|
if (hasGit && packageIsKxm(probe.repoRoot)) return report("source", probe.repoRoot);
|
|
45122
45144
|
if (isNpmPackageLayout(probe.repoRoot, probe.platform) && packageIsKxm(probe.repoRoot) && !hasGit) {
|
|
45123
45145
|
return report("npm-package", probe.repoRoot);
|
|
@@ -45138,14 +45160,14 @@ function resolveInstallKind(probe, npmGlobalRoot) {
|
|
|
45138
45160
|
|
|
45139
45161
|
// plugins/kxm/src/kxm-update-config.ts
|
|
45140
45162
|
var import_yaml16 = __toESM(require_dist(), 1);
|
|
45141
|
-
import { existsSync as existsSync28, readFileSync as
|
|
45142
|
-
import { join as
|
|
45163
|
+
import { existsSync as existsSync28, readFileSync as readFileSync29 } from "node:fs";
|
|
45164
|
+
import { join as join38 } from "node:path";
|
|
45143
45165
|
function loadKxmUpdateConfig(env = process.env) {
|
|
45144
|
-
const path4 =
|
|
45166
|
+
const path4 = join38(vnextUserStateRoot({ env }), "update.yaml");
|
|
45145
45167
|
if (!existsSync28(path4)) return { schema: KXM_UPDATE_SCHEMA, auto: false, source: "github" };
|
|
45146
45168
|
let parsed;
|
|
45147
45169
|
try {
|
|
45148
|
-
parsed = (0, import_yaml16.parse)(
|
|
45170
|
+
parsed = (0, import_yaml16.parse)(readFileSync29(path4, "utf8"));
|
|
45149
45171
|
} catch {
|
|
45150
45172
|
throw new KxmUpdateConfigError("update.yaml is not valid YAML");
|
|
45151
45173
|
}
|
|
@@ -45171,8 +45193,8 @@ function loadKxmUpdateConfig(env = process.env) {
|
|
|
45171
45193
|
}
|
|
45172
45194
|
|
|
45173
45195
|
// plugins/kxm/src/session.ts
|
|
45174
|
-
import { existsSync as existsSync29, mkdirSync as mkdirSync24, readFileSync as
|
|
45175
|
-
import { join as
|
|
45196
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync24, readFileSync as readFileSync30, writeFileSync as writeFileSync22 } from "node:fs";
|
|
45197
|
+
import { join as join39 } from "node:path";
|
|
45176
45198
|
var SESSION_SCHEMA = "kxm.session.v1";
|
|
45177
45199
|
var SessionConfigError = class extends Error {
|
|
45178
45200
|
code = "session_config_invalid";
|
|
@@ -45182,12 +45204,12 @@ var SessionConfigError = class extends Error {
|
|
|
45182
45204
|
}
|
|
45183
45205
|
};
|
|
45184
45206
|
function workflowAssetDirs(assetsDir, workflowId) {
|
|
45185
|
-
const root =
|
|
45186
|
-
return [root,
|
|
45207
|
+
const root = join39(assetsDir, "workflows", workflowId);
|
|
45208
|
+
return [root, join39(root, "inputs"), join39(root, "outputs"), join39(root, "generated")];
|
|
45187
45209
|
}
|
|
45188
45210
|
function sessionAssetDirs(assetsDir, sessionId) {
|
|
45189
|
-
const root =
|
|
45190
|
-
return [root,
|
|
45211
|
+
const root = join39(assetsDir, "sessions", sessionId);
|
|
45212
|
+
return [root, join39(root, "inputs"), join39(root, "outputs")];
|
|
45191
45213
|
}
|
|
45192
45214
|
function rosterNames(configDir) {
|
|
45193
45215
|
return [...loadRosterMap(configDir).values()].map((row) => String(row.name));
|
|
@@ -45237,7 +45259,7 @@ function workerFromRosterRow(name, row, project) {
|
|
|
45237
45259
|
function loadRosterMap(configDir) {
|
|
45238
45260
|
const byName = /* @__PURE__ */ new Map();
|
|
45239
45261
|
for (const [file, key] of [["agents.json", "agents"], ["gates.json", "gates"]]) {
|
|
45240
|
-
const path4 =
|
|
45262
|
+
const path4 = join39(configDir, file);
|
|
45241
45263
|
for (const row of loadRoster(path4, key)) {
|
|
45242
45264
|
const name = String(row.name).trim();
|
|
45243
45265
|
const lowered = name.toLowerCase();
|
|
@@ -45254,7 +45276,7 @@ function loadRoster(path4, key) {
|
|
|
45254
45276
|
if (!existsSync29(path4)) return [];
|
|
45255
45277
|
let parsed;
|
|
45256
45278
|
try {
|
|
45257
|
-
parsed = JSON.parse(
|
|
45279
|
+
parsed = JSON.parse(readFileSync30(path4, "utf8"));
|
|
45258
45280
|
} catch (error) {
|
|
45259
45281
|
throw new SessionConfigError(
|
|
45260
45282
|
`${key} roster at ${path4} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -45279,7 +45301,7 @@ function loadRoster(path4, key) {
|
|
|
45279
45301
|
});
|
|
45280
45302
|
}
|
|
45281
45303
|
function createSession(input) {
|
|
45282
|
-
const assetDir = input.mode === "workflow" && input.workflowId ?
|
|
45304
|
+
const assetDir = input.mode === "workflow" && input.workflowId ? join39("assets", "workflows", input.workflowId) : join39("assets", "sessions", input.id);
|
|
45283
45305
|
return {
|
|
45284
45306
|
schema: SESSION_SCHEMA,
|
|
45285
45307
|
id: input.id,
|
|
@@ -45292,8 +45314,8 @@ function createSession(input) {
|
|
|
45292
45314
|
};
|
|
45293
45315
|
}
|
|
45294
45316
|
function writeSession(assetsDir, session, dryRun = false) {
|
|
45295
|
-
const dir =
|
|
45296
|
-
const path4 =
|
|
45317
|
+
const dir = join39(assetsDir, "sessions", session.id);
|
|
45318
|
+
const path4 = join39(dir, "session.json");
|
|
45297
45319
|
if (!dryRun) {
|
|
45298
45320
|
mkdirSync24(dir, { recursive: true });
|
|
45299
45321
|
writeFileSync22(path4, `${JSON.stringify(session, null, 2)}
|
|
@@ -45331,9 +45353,9 @@ function installProbeFrom(runtime) {
|
|
|
45331
45353
|
};
|
|
45332
45354
|
}
|
|
45333
45355
|
function warnIgnoredProjectUpdateYaml(runtime) {
|
|
45334
|
-
const projectFile =
|
|
45356
|
+
const projectFile = join40(runtime.dirs.workspace, "update.yaml");
|
|
45335
45357
|
if (!existsSync30(projectFile)) return;
|
|
45336
|
-
const userFile =
|
|
45358
|
+
const userFile = join40(vnextUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
45337
45359
|
runtime.io.stderr(`kxm: ignoring .kxm/update.yaml in ${runtime.dirs.workdir}; update settings are read only from ${userFile}
|
|
45338
45360
|
`);
|
|
45339
45361
|
}
|
|
@@ -45359,7 +45381,7 @@ async function cmdDash(runtime, options = {}) {
|
|
|
45359
45381
|
return 2;
|
|
45360
45382
|
}
|
|
45361
45383
|
const screen = requested;
|
|
45362
|
-
const dataPath = resolve25(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
45384
|
+
const dataPath = resolve25(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join40(runtime.dirs.state, "kxm.db"));
|
|
45363
45385
|
if (runtime.dryRun) {
|
|
45364
45386
|
print(runtime.io, runtime.json, {
|
|
45365
45387
|
ok: true,
|
|
@@ -45375,7 +45397,7 @@ async function cmdDash(runtime, options = {}) {
|
|
|
45375
45397
|
runtime.io.stderr("kxm dash does not support --json; use kxm hub view\n");
|
|
45376
45398
|
return 2;
|
|
45377
45399
|
}
|
|
45378
|
-
const project = runtime.
|
|
45400
|
+
const project = defaultProjectName(runtime.dirs.workdir, runtime.env) || "project";
|
|
45379
45401
|
const authToken = runtime.env.KXM_AUTH_TOKEN?.trim();
|
|
45380
45402
|
return await runMeshTui({
|
|
45381
45403
|
serverUrl: runtime.serverUrl,
|
|
@@ -45405,7 +45427,7 @@ async function cmdHub(runtime) {
|
|
|
45405
45427
|
config = loadKxmUpdateConfig(runtime.env);
|
|
45406
45428
|
} catch (error) {
|
|
45407
45429
|
if (error instanceof KxmUpdateConfigError) {
|
|
45408
|
-
const yamlPath =
|
|
45430
|
+
const yamlPath = join40(vnextUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
45409
45431
|
runtime.io.stderr(`kxm: ${error.message}; update check skipped; fix or remove ${yamlPath}
|
|
45410
45432
|
`);
|
|
45411
45433
|
} else {
|
|
@@ -45556,7 +45578,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45556
45578
|
const orphans = [];
|
|
45557
45579
|
for (const file of pids) {
|
|
45558
45580
|
try {
|
|
45559
|
-
const record = JSON.parse(
|
|
45581
|
+
const record = JSON.parse(readFileSync31(join40(runtime.dirs.state, file), "utf8"));
|
|
45560
45582
|
const expectedControl = file === "hub.pid" ? "hub.stop" : file.startsWith("worker-") ? `${file.slice(0, -4)}.stop` : void 0;
|
|
45561
45583
|
const expectedRole = file === "hub.pid" ? "hub" : file.startsWith("worker-") ? "worker" : void 0;
|
|
45562
45584
|
if (record.version !== 1 || !Number.isInteger(record.pid) || record.pid <= 0 || !record.startedAt || !expectedControl || record.controlFile !== expectedControl || record.role !== expectedRole) {
|
|
@@ -45576,7 +45598,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45576
45598
|
ignored.push(file);
|
|
45577
45599
|
continue;
|
|
45578
45600
|
}
|
|
45579
|
-
writeFileSync23(
|
|
45601
|
+
writeFileSync23(join40(runtime.dirs.state, record.controlFile), `${JSON.stringify({ startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {}, requestedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
45580
45602
|
`, { encoding: "utf8", mode: 384 });
|
|
45581
45603
|
requested.push(file);
|
|
45582
45604
|
records.set(file, { pid: record.pid, startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {} });
|
|
@@ -45594,7 +45616,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45594
45616
|
while (Date.now() <= deadline && stopped.size < requested.length) {
|
|
45595
45617
|
for (const [file, record] of records) {
|
|
45596
45618
|
try {
|
|
45597
|
-
const current = JSON.parse(
|
|
45619
|
+
const current = JSON.parse(readFileSync31(join40(runtime.dirs.state, file), "utf8"));
|
|
45598
45620
|
if (current.pid !== record.pid || current.startedAt !== record.startedAt || current.generation !== record.generation || !processExists(record.pid)) stopped.add(file);
|
|
45599
45621
|
} catch {
|
|
45600
45622
|
stopped.add(file);
|
|
@@ -45607,7 +45629,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45607
45629
|
for (const file of orphans) {
|
|
45608
45630
|
while (Date.now() <= deadlineOrphans) {
|
|
45609
45631
|
try {
|
|
45610
|
-
const current = JSON.parse(
|
|
45632
|
+
const current = JSON.parse(readFileSync31(join40(runtime.dirs.state, file), "utf8"));
|
|
45611
45633
|
if (!Number.isInteger(current.serverPid) || !processExists(current.serverPid)) break;
|
|
45612
45634
|
} catch {
|
|
45613
45635
|
break;
|
|
@@ -45615,14 +45637,14 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45615
45637
|
await (runtime.io.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms))))(100);
|
|
45616
45638
|
}
|
|
45617
45639
|
try {
|
|
45618
|
-
const current = JSON.parse(
|
|
45640
|
+
const current = JSON.parse(readFileSync31(join40(runtime.dirs.state, file), "utf8"));
|
|
45619
45641
|
if (Number.isInteger(current.serverPid) && processExists(current.serverPid)) {
|
|
45620
45642
|
try {
|
|
45621
45643
|
process.kill(current.serverPid, "SIGKILL");
|
|
45622
45644
|
} catch {
|
|
45623
45645
|
}
|
|
45624
45646
|
}
|
|
45625
|
-
rmSync10(
|
|
45647
|
+
rmSync10(join40(runtime.dirs.state, file), { force: true });
|
|
45626
45648
|
} catch {
|
|
45627
45649
|
}
|
|
45628
45650
|
stopped.add(file);
|
|
@@ -45637,7 +45659,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
45637
45659
|
const claims = [];
|
|
45638
45660
|
for (const file of names3.filter((name) => name.endsWith(".pid"))) {
|
|
45639
45661
|
try {
|
|
45640
|
-
const record = JSON.parse(
|
|
45662
|
+
const record = JSON.parse(readFileSync31(join40(stateDir, file), "utf8"));
|
|
45641
45663
|
claims.push({
|
|
45642
45664
|
file,
|
|
45643
45665
|
role: record.role,
|
|
@@ -45652,7 +45674,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
45652
45674
|
const recoveries = [];
|
|
45653
45675
|
for (const file of names3.filter((name) => name.startsWith("worker-recovery-") && name.endsWith(".json"))) {
|
|
45654
45676
|
try {
|
|
45655
|
-
const envelope = JSON.parse(
|
|
45677
|
+
const envelope = JSON.parse(readFileSync31(join40(stateDir, file), "utf8"));
|
|
45656
45678
|
recoveries.push({
|
|
45657
45679
|
file,
|
|
45658
45680
|
reason: envelope.reason,
|
|
@@ -45757,7 +45779,7 @@ async function cmdSessionBrief(runtime, options = {}) {
|
|
|
45757
45779
|
print(runtime.io, runtime.json, { ok: true, command: "session brief", sessionToken }, sessionToken);
|
|
45758
45780
|
return 0;
|
|
45759
45781
|
}
|
|
45760
|
-
const dataPath = resolve25(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
45782
|
+
const dataPath = resolve25(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join40(runtime.dirs.state, "kxm.db"));
|
|
45761
45783
|
const env = {
|
|
45762
45784
|
...runtime.env,
|
|
45763
45785
|
KXM_STATE_DIR: runtime.dirs.state,
|
|
@@ -45849,16 +45871,16 @@ async function cmdSessionStart(runtime, options) {
|
|
|
45849
45871
|
// plugins/kxm/src/cli/system.ts
|
|
45850
45872
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
45851
45873
|
import { createHash as createHash16 } from "node:crypto";
|
|
45852
|
-
import { existsSync as existsSync36, mkdtempSync as mkdtempSync2, readFileSync as
|
|
45874
|
+
import { existsSync as existsSync36, mkdtempSync as mkdtempSync2, readFileSync as readFileSync36, rmSync as rmSync12 } from "node:fs";
|
|
45853
45875
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
45854
|
-
import { join as
|
|
45876
|
+
import { join as join46, resolve as resolve29 } from "node:path";
|
|
45855
45877
|
import { createInterface as createInterface3 } from "node:readline";
|
|
45856
45878
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
45857
45879
|
|
|
45858
45880
|
// plugins/kxm/src/improve.ts
|
|
45859
45881
|
import { createHash as createHash15 } from "node:crypto";
|
|
45860
45882
|
import { existsSync as existsSync31, mkdirSync as mkdirSync26, writeFileSync as writeFileSync24 } from "node:fs";
|
|
45861
|
-
import { join as
|
|
45883
|
+
import { join as join41, relative as relative6, resolve as resolve26 } from "node:path";
|
|
45862
45884
|
var CANDIDATE_SCHEMA = "kxm.candidate.v1";
|
|
45863
45885
|
var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
|
|
45864
45886
|
function classifyCandidateKind(stepId, agentRole) {
|
|
@@ -46030,7 +46052,7 @@ function groupRoutingRecords(records, options = {}) {
|
|
|
46030
46052
|
}
|
|
46031
46053
|
function buildImprovementReport(records, options = {}) {
|
|
46032
46054
|
const projectRoot = options.projectRoot ? resolve26(options.projectRoot) : process.cwd();
|
|
46033
|
-
const candidatesDir = options.candidatesDir ? resolve26(options.candidatesDir) :
|
|
46055
|
+
const candidatesDir = options.candidatesDir ? resolve26(options.candidatesDir) : join41(projectRoot, ".kxm", "candidates");
|
|
46034
46056
|
const groups = groupRoutingRecords(records, options);
|
|
46035
46057
|
const candidates = [];
|
|
46036
46058
|
for (const group of groups) {
|
|
@@ -46042,7 +46064,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
46042
46064
|
group.workflowHash
|
|
46043
46065
|
);
|
|
46044
46066
|
const diffFileName = `${group.candidateId}.diff`;
|
|
46045
|
-
const diffFilePath =
|
|
46067
|
+
const diffFilePath = join41(candidatesDir, diffFileName);
|
|
46046
46068
|
const relDiffPath = relative6(projectRoot, diffFilePath).replace(/\\/g, "/");
|
|
46047
46069
|
const candidate = {
|
|
46048
46070
|
schema: CANDIDATE_SCHEMA,
|
|
@@ -46068,7 +46090,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
46068
46090
|
mkdirSync26(candidatesDir, { recursive: true });
|
|
46069
46091
|
}
|
|
46070
46092
|
writeFileSync24(diffFilePath, diff, "utf8");
|
|
46071
|
-
const jsonFilePath =
|
|
46093
|
+
const jsonFilePath = join41(candidatesDir, `${group.candidateId}.json`);
|
|
46072
46094
|
writeFileSync24(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
|
|
46073
46095
|
}
|
|
46074
46096
|
candidates.push(candidate);
|
|
@@ -46084,7 +46106,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
46084
46106
|
}
|
|
46085
46107
|
function writeImprovementReport(improvementsDir, report2, dryRun = false) {
|
|
46086
46108
|
const stamp = report2.createdAt.replace(/[:.]/g, "-");
|
|
46087
|
-
const path4 =
|
|
46109
|
+
const path4 = join41(improvementsDir, `${stamp}.json`);
|
|
46088
46110
|
if (!dryRun) {
|
|
46089
46111
|
mkdirSync26(improvementsDir, { recursive: true });
|
|
46090
46112
|
writeFileSync24(path4, `${JSON.stringify(report2, null, 2)}
|
|
@@ -46127,8 +46149,8 @@ function formatImprovementReport(report2) {
|
|
|
46127
46149
|
|
|
46128
46150
|
// plugins/kxm/src/modes.ts
|
|
46129
46151
|
var import_yaml17 = __toESM(require_dist(), 1);
|
|
46130
|
-
import { existsSync as existsSync32, readFileSync as
|
|
46131
|
-
import { join as
|
|
46152
|
+
import { existsSync as existsSync32, readFileSync as readFileSync33 } from "node:fs";
|
|
46153
|
+
import { join as join42 } from "node:path";
|
|
46132
46154
|
var DEFAULT_MODES_CONFIG = Object.freeze({
|
|
46133
46155
|
schema: "kxm.modes.v1",
|
|
46134
46156
|
majorModes: {
|
|
@@ -46191,12 +46213,12 @@ function loadModesConfig(projectRoot) {
|
|
|
46191
46213
|
if (!projectRoot) {
|
|
46192
46214
|
return DEFAULT_MODES_CONFIG;
|
|
46193
46215
|
}
|
|
46194
|
-
const modesPath =
|
|
46216
|
+
const modesPath = join42(projectRoot, ".kxm", "modes.yaml");
|
|
46195
46217
|
if (!existsSync32(modesPath)) {
|
|
46196
46218
|
return DEFAULT_MODES_CONFIG;
|
|
46197
46219
|
}
|
|
46198
46220
|
try {
|
|
46199
|
-
const raw =
|
|
46221
|
+
const raw = readFileSync33(modesPath, "utf8");
|
|
46200
46222
|
const parsed = (0, import_yaml17.parse)(raw);
|
|
46201
46223
|
if (parsed && parsed.schema === "kxm.modes.v1" && parsed.majorModes) {
|
|
46202
46224
|
return {
|
|
@@ -46282,11 +46304,11 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
|
|
|
46282
46304
|
estimatedTokens: estimateTokens(baseSystemPromptChars)
|
|
46283
46305
|
});
|
|
46284
46306
|
for (const relPath of resolved.contextFiles) {
|
|
46285
|
-
const fullPath =
|
|
46307
|
+
const fullPath = join42(projectRoot, relPath);
|
|
46286
46308
|
let chars = 0;
|
|
46287
46309
|
if (existsSync32(fullPath)) {
|
|
46288
46310
|
try {
|
|
46289
|
-
chars =
|
|
46311
|
+
chars = readFileSync33(fullPath, "utf8").length;
|
|
46290
46312
|
} catch {
|
|
46291
46313
|
chars = 0;
|
|
46292
46314
|
}
|
|
@@ -46418,9 +46440,9 @@ ${divider}
|
|
|
46418
46440
|
|
|
46419
46441
|
// plugins/kxm/src/ssh-remote.ts
|
|
46420
46442
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
46421
|
-
import { existsSync as existsSync33, mkdirSync as mkdirSync27, readFileSync as
|
|
46443
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync27, readFileSync as readFileSync34, readdirSync as readdirSync13, rmSync as rmSync11, statSync as statSync5 } from "node:fs";
|
|
46422
46444
|
import { homedir as homedir7 } from "node:os";
|
|
46423
|
-
import { join as
|
|
46445
|
+
import { join as join43, resolve as resolve27 } from "node:path";
|
|
46424
46446
|
var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
|
|
46425
46447
|
var MAX_SSH_OUTPUT_LINES = 2e3;
|
|
46426
46448
|
var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
|
|
@@ -46446,12 +46468,12 @@ function truncateSshOutput(raw) {
|
|
|
46446
46468
|
return { text, truncated };
|
|
46447
46469
|
}
|
|
46448
46470
|
function parseSshConfig(configPath) {
|
|
46449
|
-
const targetPath = configPath ??
|
|
46471
|
+
const targetPath = configPath ?? join43(homedir7(), ".ssh", "config");
|
|
46450
46472
|
if (!existsSync33(targetPath)) {
|
|
46451
46473
|
return [];
|
|
46452
46474
|
}
|
|
46453
46475
|
try {
|
|
46454
|
-
const content =
|
|
46476
|
+
const content = readFileSync34(targetPath, "utf-8");
|
|
46455
46477
|
const lines = content.split("\n");
|
|
46456
46478
|
const hosts = [];
|
|
46457
46479
|
let currentHosts = [];
|
|
@@ -46536,7 +46558,7 @@ function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
|
|
|
46536
46558
|
}
|
|
46537
46559
|
function buildSshArgs(options) {
|
|
46538
46560
|
const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
|
|
46539
|
-
const controlPath =
|
|
46561
|
+
const controlPath = join43(socketDir, "%C");
|
|
46540
46562
|
const persist = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
|
|
46541
46563
|
const args = [
|
|
46542
46564
|
"-o",
|
|
@@ -46561,7 +46583,7 @@ function buildSshArgs(options) {
|
|
|
46561
46583
|
}
|
|
46562
46584
|
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync7) {
|
|
46563
46585
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
46564
|
-
const controlPath =
|
|
46586
|
+
const controlPath = join43(resolvedDir, "%C");
|
|
46565
46587
|
try {
|
|
46566
46588
|
const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
|
|
46567
46589
|
encoding: "utf-8"
|
|
@@ -46573,7 +46595,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
46573
46595
|
}
|
|
46574
46596
|
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync7) {
|
|
46575
46597
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
46576
|
-
const controlPath =
|
|
46598
|
+
const controlPath = join43(resolvedDir, "%C");
|
|
46577
46599
|
try {
|
|
46578
46600
|
const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
|
|
46579
46601
|
encoding: "utf-8"
|
|
@@ -47019,9 +47041,9 @@ complete -c kxm -n "__fish_seen_subcommand_from goal" -a "create list get"
|
|
|
47019
47041
|
}
|
|
47020
47042
|
|
|
47021
47043
|
// plugins/kxm/src/completion-install.ts
|
|
47022
|
-
import { existsSync as existsSync34, mkdirSync as mkdirSync28, readFileSync as
|
|
47044
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync28, readFileSync as readFileSync35, writeFileSync as writeFileSync25 } from "node:fs";
|
|
47023
47045
|
import { homedir as homedir8 } from "node:os";
|
|
47024
|
-
import { basename as basename9, delimiter, dirname as dirname21, isAbsolute as isAbsolute8, join as
|
|
47046
|
+
import { basename as basename9, delimiter, dirname as dirname21, isAbsolute as isAbsolute8, join as join44, resolve as resolve28 } from "node:path";
|
|
47025
47047
|
var COMPLETION_MARKER = "# kxm completion";
|
|
47026
47048
|
var PATH_MARKER = "# kxm path";
|
|
47027
47049
|
function detectShell(env = process.env, platform = process.platform) {
|
|
@@ -47043,25 +47065,25 @@ function completionScriptPath(shell, options = {}) {
|
|
|
47043
47065
|
const env = options.env ?? process.env;
|
|
47044
47066
|
const explicit = options.configDir ?? env.KXM_USER_CONFIG_DIR?.trim();
|
|
47045
47067
|
const base = explicit && explicit.length > 0 ? resolve28(explicit) : resolve28(effectiveHome(options), ".config", "kxm");
|
|
47046
|
-
return
|
|
47068
|
+
return join44(base, "completions", `kxm.${shell}`);
|
|
47047
47069
|
}
|
|
47048
47070
|
function bashRcCandidate(options) {
|
|
47049
47071
|
const home = effectiveHome(options);
|
|
47050
|
-
const candidates = [
|
|
47072
|
+
const candidates = [join44(home, ".bashrc"), join44(home, ".bash_profile")];
|
|
47051
47073
|
const existing = candidates.find((candidate) => existsSync34(candidate));
|
|
47052
47074
|
return existing ?? candidates[0];
|
|
47053
47075
|
}
|
|
47054
47076
|
function zshRcCandidate(options) {
|
|
47055
47077
|
const env = options.env ?? process.env;
|
|
47056
47078
|
const home = effectiveHome(options);
|
|
47057
|
-
if (env.ZDOTDIR?.trim()) return
|
|
47058
|
-
return
|
|
47079
|
+
if (env.ZDOTDIR?.trim()) return join44(resolve28(env.ZDOTDIR.trim()), ".zshrc");
|
|
47080
|
+
return join44(home, ".zshrc");
|
|
47059
47081
|
}
|
|
47060
47082
|
function fishCompletionTarget(shell, options) {
|
|
47061
47083
|
const env = options.env ?? process.env;
|
|
47062
47084
|
const home = effectiveHome(options);
|
|
47063
|
-
if (env.XDG_CONFIG_HOME?.trim()) return
|
|
47064
|
-
return
|
|
47085
|
+
if (env.XDG_CONFIG_HOME?.trim()) return join44(resolve28(env.XDG_CONFIG_HOME.trim()), "fish", "completions", "kxm.fish");
|
|
47086
|
+
return join44(home, ".config", "fish", "completions", "kxm.fish");
|
|
47065
47087
|
}
|
|
47066
47088
|
function completionRcTarget(shell, options = {}) {
|
|
47067
47089
|
if (shell === "fish") {
|
|
@@ -47094,12 +47116,12 @@ function installShellCompletion(shellInput, options = {}) {
|
|
|
47094
47116
|
const { rcFile } = completionRcTarget(shell, options);
|
|
47095
47117
|
const script = generateShellCompletion(shell);
|
|
47096
47118
|
const existingScript = existsSync34(scriptPath);
|
|
47097
|
-
const existingScriptMatches = existingScript &&
|
|
47119
|
+
const existingScriptMatches = existingScript && readFileSync35(scriptPath, "utf8") === script;
|
|
47098
47120
|
let rcModified = false;
|
|
47099
47121
|
let alreadyInstalled = false;
|
|
47100
47122
|
if (shell === "fish") {
|
|
47101
47123
|
const fishTarget = fishCompletionTarget(shell, options);
|
|
47102
|
-
const fishInstalled = existsSync34(fishTarget) &&
|
|
47124
|
+
const fishInstalled = existsSync34(fishTarget) && readFileSync35(fishTarget, "utf8") === script;
|
|
47103
47125
|
alreadyInstalled = fishInstalled;
|
|
47104
47126
|
if (!options.dryRun && (!fishInstalled || options.overwrite)) {
|
|
47105
47127
|
mkdirSync28(resolve28(fishTarget, ".."), { recursive: true });
|
|
@@ -47116,7 +47138,7 @@ function installShellCompletion(shellInput, options = {}) {
|
|
|
47116
47138
|
}
|
|
47117
47139
|
if (rcFile) {
|
|
47118
47140
|
const line = sourceLine(shell, scriptPath);
|
|
47119
|
-
const rcContent = existsSync34(rcFile) ?
|
|
47141
|
+
const rcContent = existsSync34(rcFile) ? readFileSync35(rcFile, "utf8") : "";
|
|
47120
47142
|
alreadyInstalled = rcContent.includes(line) || rcContent.includes(`${COMPLETION_MARKER}`);
|
|
47121
47143
|
}
|
|
47122
47144
|
if (!options.dryRun) {
|
|
@@ -47132,7 +47154,7 @@ ${marker}
|
|
|
47132
47154
|
${line}
|
|
47133
47155
|
`;
|
|
47134
47156
|
mkdirSync28(resolve28(rcFile, ".."), { recursive: true });
|
|
47135
|
-
writeFileSync25(rcFile, (existsSync34(rcFile) ?
|
|
47157
|
+
writeFileSync25(rcFile, (existsSync34(rcFile) ? readFileSync35(rcFile, "utf8") : "") + stanza, { encoding: "utf8" });
|
|
47136
47158
|
rcModified = true;
|
|
47137
47159
|
}
|
|
47138
47160
|
}
|
|
@@ -47149,7 +47171,7 @@ function kxmBinDir(env = process.env) {
|
|
|
47149
47171
|
const argv1 = env.KXM_ENTRY ?? process.argv[1];
|
|
47150
47172
|
if (argv1 && isAbsolute8(argv1)) {
|
|
47151
47173
|
const dir = dirname21(argv1);
|
|
47152
|
-
if (existsSync34(
|
|
47174
|
+
if (existsSync34(join44(dir, process.platform === "win32" ? "kxm.cmd" : "kxm"))) return dir;
|
|
47153
47175
|
}
|
|
47154
47176
|
const pathEnv = env.PATH ?? "";
|
|
47155
47177
|
for (const part of pathEnv.split(delimiter)) {
|
|
@@ -47173,7 +47195,7 @@ function installPathEntry(shellInput, options = {}) {
|
|
|
47173
47195
|
}
|
|
47174
47196
|
const { rcFile } = completionRcTarget(shell, options);
|
|
47175
47197
|
const line = pathLine(binDir);
|
|
47176
|
-
const rcContent = existsSync34(rcFile ?? "") ?
|
|
47198
|
+
const rcContent = existsSync34(rcFile ?? "") ? readFileSync35(rcFile, "utf8") : "";
|
|
47177
47199
|
const alreadyInstalled = rcContent.includes(binDir) || (options.env?.PATH ?? process.env.PATH ?? "").split(delimiter).includes(binDir);
|
|
47178
47200
|
if (!options.dryRun && rcFile && !alreadyInstalled) {
|
|
47179
47201
|
mkdirSync28(dirname21(rcFile), { recursive: true });
|
|
@@ -47188,7 +47210,7 @@ ${line}
|
|
|
47188
47210
|
// plugins/kxm/src/init-guide-setup.ts
|
|
47189
47211
|
var import_yaml18 = __toESM(require_dist(), 1);
|
|
47190
47212
|
import { existsSync as existsSync35, mkdirSync as mkdirSync29, writeFileSync as writeFileSync26 } from "node:fs";
|
|
47191
|
-
import { dirname as dirname22, join as
|
|
47213
|
+
import { dirname as dirname22, join as join45 } from "node:path";
|
|
47192
47214
|
var NATIVE_VENDOR_HARNESS = Object.freeze({
|
|
47193
47215
|
anthropic: "claude",
|
|
47194
47216
|
openai: "codex",
|
|
@@ -47587,13 +47609,13 @@ function renderGuideSetupFiles(projectRoot, plan) {
|
|
|
47587
47609
|
const stage = roleStages.get(role);
|
|
47588
47610
|
if (!stage) continue;
|
|
47589
47611
|
files.push({
|
|
47590
|
-
path:
|
|
47612
|
+
path: join45(projectRoot, ".kxm", "agents", `${role}.yaml`),
|
|
47591
47613
|
content: (0, import_yaml18.stringify)(agentDocument(role, stage, binding))
|
|
47592
47614
|
});
|
|
47593
47615
|
}
|
|
47594
47616
|
for (const workflow of plan.workflows) {
|
|
47595
47617
|
files.push({
|
|
47596
|
-
path:
|
|
47618
|
+
path: join45(projectRoot, ".kxm", "workflows", `${workflow.slug}.yaml`),
|
|
47597
47619
|
content: (0, import_yaml18.stringify)(workflowDocument(workflow))
|
|
47598
47620
|
});
|
|
47599
47621
|
}
|
|
@@ -47672,7 +47694,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
47672
47694
|
detail: `release v${notice.latest} has no sha256 digest for ${name}; refusing to install`
|
|
47673
47695
|
};
|
|
47674
47696
|
}
|
|
47675
|
-
const releaseDir = mkdtempSync2(
|
|
47697
|
+
const releaseDir = mkdtempSync2(join46(tmpdir2(), "kxm-pkg-update-"));
|
|
47676
47698
|
try {
|
|
47677
47699
|
const planned = planKxmPackageUpdate(notice.source, notice.latest, releaseDir, notice.asset);
|
|
47678
47700
|
if (runtime.dryRun) {
|
|
@@ -47681,7 +47703,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
47681
47703
|
for (const step of planned) {
|
|
47682
47704
|
if (step.kind === "verify") {
|
|
47683
47705
|
if (!verifyReleaseAssetDigest(step.path, step.sha256)) {
|
|
47684
|
-
const actual = existsSync36(step.path) ? createHash16("sha256").update(
|
|
47706
|
+
const actual = existsSync36(step.path) ? createHash16("sha256").update(readFileSync36(step.path)).digest("hex") : "missing";
|
|
47685
47707
|
return {
|
|
47686
47708
|
ok: false,
|
|
47687
47709
|
error: "release_digest_mismatch",
|
|
@@ -47952,7 +47974,7 @@ async function cmdValidate(runtime, fileFlag) {
|
|
|
47952
47974
|
return 1;
|
|
47953
47975
|
}
|
|
47954
47976
|
try {
|
|
47955
|
-
const raw = file ?
|
|
47977
|
+
const raw = file ? readFileSync36(file, "utf8") : inline;
|
|
47956
47978
|
const warnings = [];
|
|
47957
47979
|
const definitions = parseWorkflowDefinitions(raw, runtime.env, (message) => warnings.push(message));
|
|
47958
47980
|
const secretEnvs = definitions.map((definition) => ({
|
|
@@ -47998,13 +48020,13 @@ async function cmdArtifactsExist(runtime, pathFlag) {
|
|
|
47998
48020
|
async function cmdImprove(runtime, options = {}) {
|
|
47999
48021
|
const file = options.file ? resolve29(runtime.cwd, options.file) : telemetryPath(runtime.dirs.logs);
|
|
48000
48022
|
const routingRecords = existsSync36(file) ? readRoutingRecords(file).map((entry) => entry.routing) : [];
|
|
48001
|
-
const candidatesDir = options.outDir ? resolve29(runtime.cwd, options.outDir) :
|
|
48023
|
+
const candidatesDir = options.outDir ? resolve29(runtime.cwd, options.outDir) : join46(runtime.cwd, ".kxm", "candidates");
|
|
48002
48024
|
const report2 = buildImprovementReport(routingRecords, {
|
|
48003
48025
|
candidatesDir,
|
|
48004
48026
|
projectRoot: runtime.cwd,
|
|
48005
48027
|
dryRun: runtime.dryRun
|
|
48006
48028
|
});
|
|
48007
|
-
const reportDir =
|
|
48029
|
+
const reportDir = join46(runtime.dirs.assets, "improvements");
|
|
48008
48030
|
const reportPath = writeImprovementReport(reportDir, report2, runtime.dryRun);
|
|
48009
48031
|
const text = formatImprovementReport(report2);
|
|
48010
48032
|
print(runtime.io, runtime.json, {
|
|
@@ -48138,7 +48160,7 @@ async function maybeOfferCompletionInstall(runtime) {
|
|
|
48138
48160
|
const { rcFile } = completionRcTarget(shell, { env: runtime.env });
|
|
48139
48161
|
if (rcFile && existsSync36(rcFile)) {
|
|
48140
48162
|
try {
|
|
48141
|
-
if (
|
|
48163
|
+
if (readFileSync36(rcFile, "utf8").includes(scriptPath)) return;
|
|
48142
48164
|
} catch {
|
|
48143
48165
|
}
|
|
48144
48166
|
}
|
|
@@ -48270,7 +48292,7 @@ async function cmdRoutingReport(runtime, options) {
|
|
|
48270
48292
|
let catalog;
|
|
48271
48293
|
if (includeEquivalentListCost) {
|
|
48272
48294
|
try {
|
|
48273
|
-
const pricesPath = options.prices ? resolve29(runtime.cwd, options.prices) :
|
|
48295
|
+
const pricesPath = options.prices ? resolve29(runtime.cwd, options.prices) : join46(runtime.dirs.workspace, "prices.yaml");
|
|
48274
48296
|
catalog = loadPriceCatalog(pricesPath);
|
|
48275
48297
|
} catch {
|
|
48276
48298
|
}
|
|
@@ -48373,7 +48395,7 @@ function addGlobalOptions(command) {
|
|
|
48373
48395
|
}
|
|
48374
48396
|
async function ensureCliClient(runtime) {
|
|
48375
48397
|
const serverUrl = runtime.serverUrl;
|
|
48376
|
-
const project =
|
|
48398
|
+
const project = defaultProjectName(runtime.cwd, runtime.env);
|
|
48377
48399
|
const name = runtime.env.KXM_AGENT_NAME?.trim() || `cli-${process.pid}`;
|
|
48378
48400
|
const purpose = runtime.env.KXM_AGENT_PURPOSE?.trim() || "CLI agent client";
|
|
48379
48401
|
const authToken = runtime.env.KXM_AUTH_TOKEN?.trim();
|