@kontextmind/kxm 0.7.5 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +421 -155
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime.js +267 -16
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli.ts +39 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/modes.ts +348 -0
- package/plugins/kxm/src/runtime.ts +1 -0
- package/schemas/vnext/modes.schema.json +56 -0
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -7263,7 +7263,7 @@ var require_public_api = __commonJS({
|
|
|
7263
7263
|
}
|
|
7264
7264
|
return doc;
|
|
7265
7265
|
}
|
|
7266
|
-
function
|
|
7266
|
+
function parse12(src, reviver, options) {
|
|
7267
7267
|
let _reviver = void 0;
|
|
7268
7268
|
if (typeof reviver === "function") {
|
|
7269
7269
|
_reviver = reviver;
|
|
@@ -7304,7 +7304,7 @@ var require_public_api = __commonJS({
|
|
|
7304
7304
|
return value.toString(options);
|
|
7305
7305
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
7306
7306
|
}
|
|
7307
|
-
exports.parse =
|
|
7307
|
+
exports.parse = parse12;
|
|
7308
7308
|
exports.parseAllDocuments = parseAllDocuments;
|
|
7309
7309
|
exports.parseDocument = parseDocument2;
|
|
7310
7310
|
exports.stringify = stringify11;
|
|
@@ -11162,7 +11162,7 @@ var require_fast_uri = __commonJS({
|
|
|
11162
11162
|
normalizeString(uri, options);
|
|
11163
11163
|
} else if (typeof uri === "object") {
|
|
11164
11164
|
uri = /** @type {T} */
|
|
11165
|
-
|
|
11165
|
+
parse12(serialize(uri, options), options);
|
|
11166
11166
|
}
|
|
11167
11167
|
return uri;
|
|
11168
11168
|
}
|
|
@@ -11202,8 +11202,8 @@ var require_fast_uri = __commonJS({
|
|
|
11202
11202
|
function resolveComponent(base, relative7, options, skipNormalization) {
|
|
11203
11203
|
const target = {};
|
|
11204
11204
|
if (!skipNormalization) {
|
|
11205
|
-
base =
|
|
11206
|
-
relative7 =
|
|
11205
|
+
base = parse12(serialize(base, options), options);
|
|
11206
|
+
relative7 = parse12(serialize(relative7, options), options);
|
|
11207
11207
|
}
|
|
11208
11208
|
options = options || {};
|
|
11209
11209
|
if (!options.tolerant && relative7.scheme) {
|
|
@@ -11495,7 +11495,7 @@ var require_fast_uri = __commonJS({
|
|
|
11495
11495
|
}
|
|
11496
11496
|
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
11497
11497
|
}
|
|
11498
|
-
function
|
|
11498
|
+
function parse12(uri, opts) {
|
|
11499
11499
|
return parseWithStatus(uri, opts).parsed;
|
|
11500
11500
|
}
|
|
11501
11501
|
function normalizeString(uri, opts) {
|
|
@@ -11532,7 +11532,7 @@ var require_fast_uri = __commonJS({
|
|
|
11532
11532
|
resolveComponent,
|
|
11533
11533
|
equal,
|
|
11534
11534
|
serialize,
|
|
11535
|
-
parse:
|
|
11535
|
+
parse: parse12
|
|
11536
11536
|
};
|
|
11537
11537
|
module.exports = fastUri;
|
|
11538
11538
|
module.exports.default = fastUri;
|
|
@@ -14778,9 +14778,9 @@ var require__ = __commonJS({
|
|
|
14778
14778
|
// plugins/kxm/src/cli.ts
|
|
14779
14779
|
import { spawn as spawn2, spawnSync as spawnSync8 } from "node:child_process";
|
|
14780
14780
|
import { createHash as createHash16, createHmac as createHmac3, randomUUID as randomUUID12 } from "node:crypto";
|
|
14781
|
-
import { existsSync as
|
|
14781
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync2, readFileSync as readFileSync29, readdirSync as readdirSync11, rmSync as rmSync10, writeFileSync as writeFileSync26 } from "node:fs";
|
|
14782
14782
|
import { homedir as homedir7, tmpdir as tmpdir2 } from "node:os";
|
|
14783
|
-
import { basename as basename7, dirname as dirname21, join as
|
|
14783
|
+
import { basename as basename7, dirname as dirname21, join as join37, relative as relative6, resolve as resolve22 } from "node:path";
|
|
14784
14784
|
|
|
14785
14785
|
// plugins/kxm/src/sqlite.ts
|
|
14786
14786
|
import { createRequire } from "node:module";
|
|
@@ -20364,8 +20364,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
20364
20364
|
const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
|
|
20365
20365
|
if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
|
|
20366
20366
|
}
|
|
20367
|
-
const
|
|
20368
|
-
const minimumPassed =
|
|
20367
|
+
const join38 = objectValue(step.join);
|
|
20368
|
+
const minimumPassed = join38 && typeof join38.minimumPassed === "number" ? join38.minimumPassed : void 0;
|
|
20369
20369
|
if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
|
|
20370
20370
|
const distinctBy = names(assignment?.distinctBy);
|
|
20371
20371
|
if (distinctBy.length > 0) {
|
|
@@ -39388,7 +39388,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
39388
39388
|
const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
|
|
39389
39389
|
const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
|
|
39390
39390
|
const assignments = compileAssignments(step, id, agent, sink);
|
|
39391
|
-
const
|
|
39391
|
+
const join38 = compileJoin(step, id, sink);
|
|
39392
39392
|
const requiredEvidence = compileEvidence(step, id, sink);
|
|
39393
39393
|
const transitions = compileTransitions(step, id, index, stepIndex, sink);
|
|
39394
39394
|
const outcomes = Object.keys(transitions).sort(compareCodeUnits6);
|
|
@@ -39416,7 +39416,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
39416
39416
|
transitions: orderedTransitions,
|
|
39417
39417
|
requiresPlanHash: requirePlanHash.includes(id),
|
|
39418
39418
|
assignments,
|
|
39419
|
-
join:
|
|
39419
|
+
join: join38
|
|
39420
39420
|
};
|
|
39421
39421
|
if (kind === "agent" || kind === "moa") {
|
|
39422
39422
|
if (!agent) return void 0;
|
|
@@ -39466,15 +39466,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
|
|
|
39466
39466
|
};
|
|
39467
39467
|
}
|
|
39468
39468
|
function compileJoin(step, stepId, sink) {
|
|
39469
|
-
const
|
|
39470
|
-
if (!
|
|
39471
|
-
const declared = stringValue3(
|
|
39469
|
+
const join38 = objectValue2(step.join);
|
|
39470
|
+
if (!join38) return { strategy: "all" };
|
|
39471
|
+
const declared = stringValue3(join38.strategy);
|
|
39472
39472
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
39473
|
-
const minimumPassed = compileOptionalCount(
|
|
39473
|
+
const minimumPassed = compileOptionalCount(join38.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
39474
39474
|
const compiled = {
|
|
39475
39475
|
strategy,
|
|
39476
39476
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
39477
|
-
...typeof
|
|
39477
|
+
...typeof join38.cancelRemaining === "boolean" ? { cancelRemaining: join38.cancelRemaining } : {}
|
|
39478
39478
|
};
|
|
39479
39479
|
return compiled;
|
|
39480
39480
|
}
|
|
@@ -41907,11 +41907,256 @@ function suggestWorkflowAndRoles(prompt, options = {}) {
|
|
|
41907
41907
|
};
|
|
41908
41908
|
}
|
|
41909
41909
|
|
|
41910
|
-
// plugins/kxm/src/
|
|
41910
|
+
// plugins/kxm/src/modes.ts
|
|
41911
41911
|
var import_yaml13 = __toESM(require_dist(), 1);
|
|
41912
|
+
import { existsSync as existsSync27, readFileSync as readFileSync25 } from "node:fs";
|
|
41913
|
+
import { join as join33 } from "node:path";
|
|
41914
|
+
var DEFAULT_MODES_CONFIG = Object.freeze({
|
|
41915
|
+
schema: "kxm.modes.v1",
|
|
41916
|
+
majorModes: {
|
|
41917
|
+
coder: {
|
|
41918
|
+
description: "First-pass implementation, bug fixing, and test authoring",
|
|
41919
|
+
baseTools: ["read", "edit", "write", "bash"],
|
|
41920
|
+
contextFiles: ["AGENTS.md"],
|
|
41921
|
+
thinkingLevel: "medium",
|
|
41922
|
+
model: "grok/grok-4.6"
|
|
41923
|
+
},
|
|
41924
|
+
planner: {
|
|
41925
|
+
description: "High-level architectural planning, scoping, and decomposition",
|
|
41926
|
+
baseTools: ["read", "grep", "find"],
|
|
41927
|
+
contextFiles: ["plans/implementation-plan.md"],
|
|
41928
|
+
thinkingLevel: "high",
|
|
41929
|
+
model: "claude/fable"
|
|
41930
|
+
},
|
|
41931
|
+
auditor: {
|
|
41932
|
+
description: "Security, compliance, and code quality verification",
|
|
41933
|
+
baseTools: ["read", "grep"],
|
|
41934
|
+
contextFiles: ["SECURITY.md"],
|
|
41935
|
+
thinkingLevel: "high",
|
|
41936
|
+
model: "codex/gpt-5.6-sol"
|
|
41937
|
+
},
|
|
41938
|
+
browser: {
|
|
41939
|
+
description: "Web application exploration, screenshotting, and UI testing",
|
|
41940
|
+
baseTools: ["read", "bash"],
|
|
41941
|
+
contextFiles: ["docs/browser-automation.md"],
|
|
41942
|
+
thinkingLevel: "medium",
|
|
41943
|
+
model: "grok/grok-4.6"
|
|
41944
|
+
}
|
|
41945
|
+
},
|
|
41946
|
+
domains: {
|
|
41947
|
+
git: {
|
|
41948
|
+
description: "Git version control operations",
|
|
41949
|
+
tools: ["git_status", "git_diff", "git_commit"],
|
|
41950
|
+
promptSnippet: "Follow git branch conventions; never commit directly to main."
|
|
41951
|
+
},
|
|
41952
|
+
k8s: {
|
|
41953
|
+
description: "Kubernetes cluster inspection and deployment",
|
|
41954
|
+
tools: ["kubectl_get", "kubectl_describe"],
|
|
41955
|
+
promptSnippet: "Target local dev cluster; verify namespaces before mutating."
|
|
41956
|
+
},
|
|
41957
|
+
database: {
|
|
41958
|
+
description: "Database queries and schema verification",
|
|
41959
|
+
tools: ["sqlite_query", "sqlite_schema"],
|
|
41960
|
+
promptSnippet: "Database is SQLite at .kxm/state/kxm.db; use read-only queries."
|
|
41961
|
+
},
|
|
41962
|
+
browser: {
|
|
41963
|
+
description: "Remote Steel browser sessions and visual testing",
|
|
41964
|
+
tools: ["steel_session", "steel_scrape", "steel_screenshot"],
|
|
41965
|
+
promptSnippet: "Use Steel on DOKS for browser automation; invoke takeover on MFA."
|
|
41966
|
+
}
|
|
41967
|
+
}
|
|
41968
|
+
});
|
|
41969
|
+
function estimateTokens(charCount) {
|
|
41970
|
+
return Math.ceil(charCount / 3.8);
|
|
41971
|
+
}
|
|
41972
|
+
function loadModesConfig(projectRoot) {
|
|
41973
|
+
if (!projectRoot) {
|
|
41974
|
+
return DEFAULT_MODES_CONFIG;
|
|
41975
|
+
}
|
|
41976
|
+
const modesPath = join33(projectRoot, ".kxm", "modes.yaml");
|
|
41977
|
+
if (!existsSync27(modesPath)) {
|
|
41978
|
+
return DEFAULT_MODES_CONFIG;
|
|
41979
|
+
}
|
|
41980
|
+
try {
|
|
41981
|
+
const raw = readFileSync25(modesPath, "utf8");
|
|
41982
|
+
const parsed = (0, import_yaml13.parse)(raw);
|
|
41983
|
+
if (parsed && parsed.schema === "kxm.modes.v1" && parsed.majorModes) {
|
|
41984
|
+
return {
|
|
41985
|
+
schema: "kxm.modes.v1",
|
|
41986
|
+
majorModes: { ...DEFAULT_MODES_CONFIG.majorModes, ...parsed.majorModes },
|
|
41987
|
+
domains: { ...DEFAULT_MODES_CONFIG.domains, ...parsed.domains }
|
|
41988
|
+
};
|
|
41989
|
+
}
|
|
41990
|
+
} catch {
|
|
41991
|
+
}
|
|
41992
|
+
return DEFAULT_MODES_CONFIG;
|
|
41993
|
+
}
|
|
41994
|
+
function resolveActiveMode(config, majorModeName = "coder", domainNames = []) {
|
|
41995
|
+
const major = config.majorModes[majorModeName] || config.majorModes["coder"] || DEFAULT_MODES_CONFIG.majorModes["coder"];
|
|
41996
|
+
const tools = new Set(major.baseTools);
|
|
41997
|
+
const contextFiles = new Set(major.contextFiles || []);
|
|
41998
|
+
const promptSnippets = [];
|
|
41999
|
+
const enabledDomains = [];
|
|
42000
|
+
if (config.domains) {
|
|
42001
|
+
for (const dName of domainNames) {
|
|
42002
|
+
const d2 = config.domains[dName.toLowerCase().trim()];
|
|
42003
|
+
if (d2) {
|
|
42004
|
+
enabledDomains.push(dName.toLowerCase().trim());
|
|
42005
|
+
d2.tools.forEach((t) => tools.add(t));
|
|
42006
|
+
(d2.contextFiles || []).forEach((f) => contextFiles.add(f));
|
|
42007
|
+
if (d2.promptSnippet) {
|
|
42008
|
+
promptSnippets.push(d2.promptSnippet);
|
|
42009
|
+
}
|
|
42010
|
+
}
|
|
42011
|
+
}
|
|
42012
|
+
}
|
|
42013
|
+
return {
|
|
42014
|
+
majorMode: majorModeName,
|
|
42015
|
+
enabledDomains,
|
|
42016
|
+
tools: Array.from(tools),
|
|
42017
|
+
contextFiles: Array.from(contextFiles),
|
|
42018
|
+
promptSnippets,
|
|
42019
|
+
thinkingLevel: major.thinkingLevel,
|
|
42020
|
+
model: major.model || "grok/grok-4.6"
|
|
42021
|
+
};
|
|
42022
|
+
}
|
|
42023
|
+
function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog) {
|
|
42024
|
+
const breakdown = [];
|
|
42025
|
+
const baseSystemPromptChars = 3200;
|
|
42026
|
+
breakdown.push({
|
|
42027
|
+
name: `Base System Prompt (${resolved.majorMode})`,
|
|
42028
|
+
chars: baseSystemPromptChars,
|
|
42029
|
+
estimatedTokens: estimateTokens(baseSystemPromptChars)
|
|
42030
|
+
});
|
|
42031
|
+
for (const relPath of resolved.contextFiles) {
|
|
42032
|
+
const fullPath = join33(projectRoot, relPath);
|
|
42033
|
+
let chars = 0;
|
|
42034
|
+
if (existsSync27(fullPath)) {
|
|
42035
|
+
try {
|
|
42036
|
+
chars = readFileSync25(fullPath, "utf8").length;
|
|
42037
|
+
} catch {
|
|
42038
|
+
chars = 0;
|
|
42039
|
+
}
|
|
42040
|
+
}
|
|
42041
|
+
if (chars === 0) {
|
|
42042
|
+
chars = 1500;
|
|
42043
|
+
}
|
|
42044
|
+
breakdown.push({
|
|
42045
|
+
name: `Context File: ${relPath}`,
|
|
42046
|
+
chars,
|
|
42047
|
+
estimatedTokens: estimateTokens(chars)
|
|
42048
|
+
});
|
|
42049
|
+
}
|
|
42050
|
+
if (resolved.promptSnippets.length > 0) {
|
|
42051
|
+
const snippetChars = resolved.promptSnippets.join("\n").length;
|
|
42052
|
+
breakdown.push({
|
|
42053
|
+
name: `Domain Prompts (${resolved.enabledDomains.join(", ")})`,
|
|
42054
|
+
chars: snippetChars,
|
|
42055
|
+
estimatedTokens: estimateTokens(snippetChars)
|
|
42056
|
+
});
|
|
42057
|
+
}
|
|
42058
|
+
const toolSchemaChars = resolved.tools.length * 650;
|
|
42059
|
+
breakdown.push({
|
|
42060
|
+
name: `Tool Schemas (${resolved.tools.length} active tools)`,
|
|
42061
|
+
chars: toolSchemaChars,
|
|
42062
|
+
estimatedTokens: estimateTokens(toolSchemaChars)
|
|
42063
|
+
});
|
|
42064
|
+
const totalChars = breakdown.reduce((sum, item) => sum + item.chars, 0);
|
|
42065
|
+
const totalTokens = breakdown.reduce((sum, item) => sum + item.estimatedTokens, 0);
|
|
42066
|
+
const maxContextWindow = 2e5;
|
|
42067
|
+
const contextWindowRatio = Math.round(totalTokens / maxContextWindow * 1e3) / 10;
|
|
42068
|
+
const cat = catalog || loadPriceCatalog(projectRoot);
|
|
42069
|
+
const rawModel = resolved.model || "grok/grok-4.6";
|
|
42070
|
+
const [prov, mod] = rawModel.includes("/") ? rawModel.split("/", 2) : [void 0, rawModel];
|
|
42071
|
+
const inputCost = cat ? calculateModelCost(cat, {
|
|
42072
|
+
model: mod || rawModel,
|
|
42073
|
+
...prov !== void 0 ? { provider: prov } : {},
|
|
42074
|
+
tokensIn: totalTokens,
|
|
42075
|
+
tokensOut: 0,
|
|
42076
|
+
cacheReadTokens: 0,
|
|
42077
|
+
cacheWriteTokens: 0
|
|
42078
|
+
}) : void 0;
|
|
42079
|
+
const cacheReadCost = cat ? calculateModelCost(cat, {
|
|
42080
|
+
model: mod || rawModel,
|
|
42081
|
+
...prov !== void 0 ? { provider: prov } : {},
|
|
42082
|
+
tokensIn: 0,
|
|
42083
|
+
tokensOut: 0,
|
|
42084
|
+
cacheReadTokens: totalTokens,
|
|
42085
|
+
cacheWriteTokens: 0
|
|
42086
|
+
}) : void 0;
|
|
42087
|
+
const outputEstimateCost = cat ? calculateModelCost(cat, {
|
|
42088
|
+
model: mod || rawModel,
|
|
42089
|
+
...prov !== void 0 ? { provider: prov } : {},
|
|
42090
|
+
tokensIn: 0,
|
|
42091
|
+
tokensOut: 1e3,
|
|
42092
|
+
cacheReadTokens: 0,
|
|
42093
|
+
cacheWriteTokens: 0
|
|
42094
|
+
}) : void 0;
|
|
42095
|
+
return {
|
|
42096
|
+
majorMode: resolved.majorMode,
|
|
42097
|
+
enabledDomains: resolved.enabledDomains,
|
|
42098
|
+
model: resolved.model || "grok/grok-4.6",
|
|
42099
|
+
breakdown,
|
|
42100
|
+
totalChars,
|
|
42101
|
+
totalTokens,
|
|
42102
|
+
contextWindowRatio,
|
|
42103
|
+
projectedCost: {
|
|
42104
|
+
inputCostUsd: inputCost?.costUsd ?? null,
|
|
42105
|
+
cacheReadCostUsd: cacheReadCost?.costUsd ?? null,
|
|
42106
|
+
outputCostEstimateUsd: outputEstimateCost?.costUsd ?? null
|
|
42107
|
+
}
|
|
42108
|
+
};
|
|
42109
|
+
}
|
|
42110
|
+
function formatModesExplainReport(footprint) {
|
|
42111
|
+
const divider = "\u2550".repeat(60);
|
|
42112
|
+
const subDivider = "\u2500".repeat(60);
|
|
42113
|
+
let out = `
|
|
42114
|
+
${divider}
|
|
42115
|
+
`;
|
|
42116
|
+
out += `KXM PRE-FLIGHT CONTEXT EXPLAIN
|
|
42117
|
+
`;
|
|
42118
|
+
out += `${divider}
|
|
42119
|
+
`;
|
|
42120
|
+
out += `Major Mode: ${footprint.majorMode}
|
|
42121
|
+
`;
|
|
42122
|
+
out += `Enabled Domains: ${footprint.enabledDomains.length > 0 ? footprint.enabledDomains.join(", ") : "(none)"}
|
|
42123
|
+
`;
|
|
42124
|
+
out += `Target Model: ${footprint.model}
|
|
42125
|
+
|
|
42126
|
+
`;
|
|
42127
|
+
out += `CONTEXT BREAKDOWN:
|
|
42128
|
+
`;
|
|
42129
|
+
for (const item of footprint.breakdown) {
|
|
42130
|
+
const padName = item.name.padEnd(38, " ");
|
|
42131
|
+
const tokenStr = `${item.estimatedTokens.toLocaleString()} tokens`.padStart(16, " ");
|
|
42132
|
+
out += ` \u2022 ${padName} ${tokenStr}
|
|
42133
|
+
`;
|
|
42134
|
+
}
|
|
42135
|
+
out += `${subDivider}
|
|
42136
|
+
`;
|
|
42137
|
+
const totalPad = `TOTAL PROMPT FOOTPRINT:`.padEnd(38, " ");
|
|
42138
|
+
const totalStr = `${footprint.totalTokens.toLocaleString()} tokens`.padStart(16, " ");
|
|
42139
|
+
out += ` ${totalPad} ${totalStr} (${footprint.contextWindowRatio}% of 200k window)
|
|
42140
|
+
|
|
42141
|
+
`;
|
|
42142
|
+
out += `PROJECTED COSTS (per turn):
|
|
42143
|
+
`;
|
|
42144
|
+
out += ` \u2022 Initial Turn Input Cost: ${footprint.projectedCost.inputCostUsd !== null ? `$${footprint.projectedCost.inputCostUsd.toFixed(4)}` : "unmetered/unknown"}
|
|
42145
|
+
`;
|
|
42146
|
+
out += ` \u2022 Subsequent Cache-Read Cost: ${footprint.projectedCost.cacheReadCostUsd !== null ? `$${footprint.projectedCost.cacheReadCostUsd.toFixed(4)} (approx 90% savings)` : "unmetered/unknown"}
|
|
42147
|
+
`;
|
|
42148
|
+
out += ` \u2022 Output Estimate (1k tokens): ${footprint.projectedCost.outputCostEstimateUsd !== null ? `$${footprint.projectedCost.outputCostEstimateUsd.toFixed(4)}` : "unmetered/unknown"}
|
|
42149
|
+
`;
|
|
42150
|
+
out += `${divider}
|
|
42151
|
+
`;
|
|
42152
|
+
return out;
|
|
42153
|
+
}
|
|
42154
|
+
|
|
42155
|
+
// plugins/kxm/src/task-manager.ts
|
|
42156
|
+
var import_yaml14 = __toESM(require_dist(), 1);
|
|
41912
42157
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
41913
|
-
import { existsSync as
|
|
41914
|
-
import { join as
|
|
42158
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync25, readFileSync as readFileSync26, readdirSync as readdirSync8, writeFileSync as writeFileSync23 } from "node:fs";
|
|
42159
|
+
import { join as join34, resolve as resolve19 } from "node:path";
|
|
41915
42160
|
var GOAL_SCHEMA = "kxm.goal.v1";
|
|
41916
42161
|
var TASK_SCHEMA = "kxm.task.v1";
|
|
41917
42162
|
function goalsDirectory(repoRoot3) {
|
|
@@ -41936,20 +42181,20 @@ function createGoal(repoRoot3, input) {
|
|
|
41936
42181
|
createdAt: now,
|
|
41937
42182
|
updatedAt: now
|
|
41938
42183
|
};
|
|
41939
|
-
const filePath =
|
|
41940
|
-
writeFileSync23(filePath, (0,
|
|
42184
|
+
const filePath = join34(dir, `${id}.yaml`);
|
|
42185
|
+
writeFileSync23(filePath, (0, import_yaml14.stringify)(record).trim() + "\n", "utf8");
|
|
41941
42186
|
return record;
|
|
41942
42187
|
}
|
|
41943
42188
|
function listGoals(repoRoot3) {
|
|
41944
42189
|
const dir = goalsDirectory(repoRoot3);
|
|
41945
|
-
if (!
|
|
42190
|
+
if (!existsSync28(dir)) return [];
|
|
41946
42191
|
const goals = [];
|
|
41947
42192
|
const entries = readdirSync8(dir, { withFileTypes: true });
|
|
41948
42193
|
for (const entry of entries) {
|
|
41949
42194
|
if (entry.isFile() && (entry.name.endsWith(".yaml") || entry.name.endsWith(".yml"))) {
|
|
41950
42195
|
try {
|
|
41951
|
-
const text =
|
|
41952
|
-
const doc = (0,
|
|
42196
|
+
const text = readFileSync26(join34(dir, entry.name), "utf8");
|
|
42197
|
+
const doc = (0, import_yaml14.parse)(text);
|
|
41953
42198
|
if (doc && doc.schema === GOAL_SCHEMA) goals.push(doc);
|
|
41954
42199
|
} catch {
|
|
41955
42200
|
}
|
|
@@ -41981,20 +42226,20 @@ function createTask(repoRoot3, input) {
|
|
|
41981
42226
|
createdAt: now,
|
|
41982
42227
|
updatedAt: now
|
|
41983
42228
|
};
|
|
41984
|
-
const filePath =
|
|
41985
|
-
writeFileSync23(filePath, (0,
|
|
42229
|
+
const filePath = join34(dir, `${id}.yaml`);
|
|
42230
|
+
writeFileSync23(filePath, (0, import_yaml14.stringify)(record).trim() + "\n", "utf8");
|
|
41986
42231
|
return record;
|
|
41987
42232
|
}
|
|
41988
42233
|
function listTasks(repoRoot3, options = {}) {
|
|
41989
42234
|
const dir = tasksDirectory(repoRoot3);
|
|
41990
|
-
if (!
|
|
42235
|
+
if (!existsSync28(dir)) return [];
|
|
41991
42236
|
const tasks = [];
|
|
41992
42237
|
const entries = readdirSync8(dir, { withFileTypes: true });
|
|
41993
42238
|
for (const entry of entries) {
|
|
41994
42239
|
if (entry.isFile() && (entry.name.endsWith(".yaml") || entry.name.endsWith(".yml"))) {
|
|
41995
42240
|
try {
|
|
41996
|
-
const text =
|
|
41997
|
-
const doc = (0,
|
|
42241
|
+
const text = readFileSync26(join34(dir, entry.name), "utf8");
|
|
42242
|
+
const doc = (0, import_yaml14.parse)(text);
|
|
41998
42243
|
if (doc && doc.schema === TASK_SCHEMA) {
|
|
41999
42244
|
if (options.goalId && doc.goalId !== options.goalId) continue;
|
|
42000
42245
|
if (options.status && doc.status !== options.status) continue;
|
|
@@ -42008,11 +42253,11 @@ function listTasks(repoRoot3, options = {}) {
|
|
|
42008
42253
|
}
|
|
42009
42254
|
function getTask(repoRoot3, taskId) {
|
|
42010
42255
|
const dir = tasksDirectory(repoRoot3);
|
|
42011
|
-
const filePath =
|
|
42012
|
-
if (!
|
|
42256
|
+
const filePath = join34(dir, `${taskId}.yaml`);
|
|
42257
|
+
if (!existsSync28(filePath)) return void 0;
|
|
42013
42258
|
try {
|
|
42014
|
-
const text =
|
|
42015
|
-
const doc = (0,
|
|
42259
|
+
const text = readFileSync26(filePath, "utf8");
|
|
42260
|
+
const doc = (0, import_yaml14.parse)(text);
|
|
42016
42261
|
return doc && doc.schema === TASK_SCHEMA ? doc : void 0;
|
|
42017
42262
|
} catch {
|
|
42018
42263
|
return void 0;
|
|
@@ -42026,8 +42271,8 @@ function updateTaskStatus(repoRoot3, taskId, status, options = {}) {
|
|
|
42026
42271
|
task.status = status;
|
|
42027
42272
|
if (options.workflowRunId) task.workflowRunId = options.workflowRunId;
|
|
42028
42273
|
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
42029
|
-
const filePath =
|
|
42030
|
-
writeFileSync23(filePath, (0,
|
|
42274
|
+
const filePath = join34(tasksDirectory(repoRoot3), `${taskId}.yaml`);
|
|
42275
|
+
writeFileSync23(filePath, (0, import_yaml14.stringify)(task).trim() + "\n", "utf8");
|
|
42031
42276
|
return task;
|
|
42032
42277
|
}
|
|
42033
42278
|
function syncTaskWithTracker(repoRoot3, taskId, options = {}) {
|
|
@@ -42042,13 +42287,13 @@ function syncTaskWithTracker(repoRoot3, taskId, options = {}) {
|
|
|
42042
42287
|
task.trackerSync.syncStatus = "synced";
|
|
42043
42288
|
task.trackerSync.lastSyncedAt = now;
|
|
42044
42289
|
task.updatedAt = now;
|
|
42045
|
-
const filePath =
|
|
42046
|
-
writeFileSync23(filePath, (0,
|
|
42290
|
+
const filePath = join34(tasksDirectory(repoRoot3), `${taskId}.yaml`);
|
|
42291
|
+
writeFileSync23(filePath, (0, import_yaml14.stringify)(task).trim() + "\n", "utf8");
|
|
42047
42292
|
return task;
|
|
42048
42293
|
}
|
|
42049
42294
|
|
|
42050
42295
|
// plugins/kxm/src/cli.ts
|
|
42051
|
-
var
|
|
42296
|
+
var import_yaml17 = __toESM(require_dist(), 1);
|
|
42052
42297
|
|
|
42053
42298
|
// plugins/kxm/src/studio-layout.ts
|
|
42054
42299
|
import { createServer } from "node:http";
|
|
@@ -42812,9 +43057,9 @@ function createStudioServer(options = {}) {
|
|
|
42812
43057
|
}
|
|
42813
43058
|
|
|
42814
43059
|
// plugins/kxm/src/role.ts
|
|
42815
|
-
var
|
|
42816
|
-
import { existsSync as
|
|
42817
|
-
import { join as
|
|
43060
|
+
var import_yaml15 = __toESM(require_dist(), 1);
|
|
43061
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync26, readdirSync as readdirSync9, readFileSync as readFileSync27, rmSync as rmSync8, writeFileSync as writeFileSync24 } from "node:fs";
|
|
43062
|
+
import { join as join35 } from "node:path";
|
|
42818
43063
|
var KXM_ROLE_SCHEMA = "kxm.role.v1";
|
|
42819
43064
|
var DEFAULT_ROLES = {
|
|
42820
43065
|
writer: {
|
|
@@ -42893,22 +43138,22 @@ var DEFAULT_ROLES = {
|
|
|
42893
43138
|
};
|
|
42894
43139
|
function rolesDirectory(scope, repoRoot3 = process.cwd(), userConfigDir) {
|
|
42895
43140
|
if (scope === "global") {
|
|
42896
|
-
return
|
|
43141
|
+
return join35(userConfigDirectory(userConfigDir), "roles");
|
|
42897
43142
|
}
|
|
42898
|
-
return
|
|
43143
|
+
return join35(repoConfigDirectory(repoRoot3), "roles");
|
|
42899
43144
|
}
|
|
42900
43145
|
function ensureRolesDirectory(scope, repoRoot3 = process.cwd(), userConfigDir) {
|
|
42901
43146
|
const dir = rolesDirectory(scope, repoRoot3, userConfigDir);
|
|
42902
|
-
if (!
|
|
43147
|
+
if (!existsSync29(dir)) {
|
|
42903
43148
|
mkdirSync26(dir, { recursive: true });
|
|
42904
43149
|
}
|
|
42905
43150
|
return dir;
|
|
42906
43151
|
}
|
|
42907
43152
|
function parseRoleFile(filePath) {
|
|
42908
|
-
if (!
|
|
43153
|
+
if (!existsSync29(filePath)) return void 0;
|
|
42909
43154
|
try {
|
|
42910
|
-
const raw =
|
|
42911
|
-
const parsed = (0,
|
|
43155
|
+
const raw = readFileSync27(filePath, "utf8");
|
|
43156
|
+
const parsed = (0, import_yaml15.parse)(raw);
|
|
42912
43157
|
if (!parsed || typeof parsed !== "object" || parsed.schema !== KXM_ROLE_SCHEMA) {
|
|
42913
43158
|
return void 0;
|
|
42914
43159
|
}
|
|
@@ -42934,10 +43179,10 @@ function listRoles(options = {}) {
|
|
|
42934
43179
|
const globalDir = rolesDirectory("global", repoRoot3, options.userConfigDir);
|
|
42935
43180
|
const localDir = rolesDirectory("local", repoRoot3, options.userConfigDir);
|
|
42936
43181
|
const localRoles = /* @__PURE__ */ new Map();
|
|
42937
|
-
if (scopeFilter !== "global" &&
|
|
43182
|
+
if (scopeFilter !== "global" && existsSync29(localDir)) {
|
|
42938
43183
|
for (const entry of readdirSync9(localDir)) {
|
|
42939
43184
|
if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
|
|
42940
|
-
const filePath =
|
|
43185
|
+
const filePath = join35(localDir, entry);
|
|
42941
43186
|
const parsed = parseRoleFile(filePath);
|
|
42942
43187
|
if (parsed) {
|
|
42943
43188
|
localRoles.set(parsed.id, { role: parsed, filePath });
|
|
@@ -42946,10 +43191,10 @@ function listRoles(options = {}) {
|
|
|
42946
43191
|
}
|
|
42947
43192
|
}
|
|
42948
43193
|
const globalRoles = /* @__PURE__ */ new Map();
|
|
42949
|
-
if (scopeFilter !== "local" &&
|
|
43194
|
+
if (scopeFilter !== "local" && existsSync29(globalDir)) {
|
|
42950
43195
|
for (const entry of readdirSync9(globalDir)) {
|
|
42951
43196
|
if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
|
|
42952
|
-
const filePath =
|
|
43197
|
+
const filePath = join35(globalDir, entry);
|
|
42953
43198
|
const parsed = parseRoleFile(filePath);
|
|
42954
43199
|
if (parsed) {
|
|
42955
43200
|
globalRoles.set(parsed.id, { role: parsed, filePath });
|
|
@@ -42997,13 +43242,13 @@ function getRole(roleId, options = {}) {
|
|
|
42997
43242
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
42998
43243
|
if (scope !== "global") {
|
|
42999
43244
|
const localDir = rolesDirectory("local", repoRoot3, options.userConfigDir);
|
|
43000
|
-
const localFile =
|
|
43245
|
+
const localFile = join35(localDir, `${roleId}.yaml`);
|
|
43001
43246
|
const parsed = parseRoleFile(localFile);
|
|
43002
43247
|
if (parsed) return { role: parsed, scope: "local", filePath: localFile };
|
|
43003
43248
|
}
|
|
43004
43249
|
if (scope !== "local") {
|
|
43005
43250
|
const globalDir = rolesDirectory("global", repoRoot3, options.userConfigDir);
|
|
43006
|
-
const globalFile =
|
|
43251
|
+
const globalFile = join35(globalDir, `${roleId}.yaml`);
|
|
43007
43252
|
const parsed = parseRoleFile(globalFile);
|
|
43008
43253
|
if (parsed) return { role: parsed, scope: "global", filePath: globalFile };
|
|
43009
43254
|
}
|
|
@@ -43013,19 +43258,19 @@ function addRole(role, options = {}) {
|
|
|
43013
43258
|
const scope = options.scope ?? "local";
|
|
43014
43259
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
43015
43260
|
const dir = ensureRolesDirectory(scope, repoRoot3, options.userConfigDir);
|
|
43016
|
-
const filePath =
|
|
43017
|
-
if (
|
|
43261
|
+
const filePath = join35(dir, `${role.id}.yaml`);
|
|
43262
|
+
if (existsSync29(filePath) && !options.overwrite) {
|
|
43018
43263
|
throw new Error(`role_already_exists: role '${role.id}' already exists at ${filePath}`);
|
|
43019
43264
|
}
|
|
43020
|
-
writeFileSync24(filePath, (0,
|
|
43265
|
+
writeFileSync24(filePath, (0, import_yaml15.stringify)(role), "utf8");
|
|
43021
43266
|
return { id: role.id, filePath, scope };
|
|
43022
43267
|
}
|
|
43023
43268
|
function removeRole(roleId, options = {}) {
|
|
43024
43269
|
const scope = options.scope ?? "local";
|
|
43025
43270
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
43026
43271
|
const dir = rolesDirectory(scope, repoRoot3, options.userConfigDir);
|
|
43027
|
-
const filePath =
|
|
43028
|
-
if (!
|
|
43272
|
+
const filePath = join35(dir, `${roleId}.yaml`);
|
|
43273
|
+
if (!existsSync29(filePath)) {
|
|
43029
43274
|
throw new Error(`role_not_found: role '${roleId}' not found in ${scope} directory (${filePath})`);
|
|
43030
43275
|
}
|
|
43031
43276
|
rmSync8(filePath);
|
|
@@ -43046,8 +43291,8 @@ function modifyRole(roleId, updates, options = {}) {
|
|
|
43046
43291
|
const scope = options.scope ?? target.scope;
|
|
43047
43292
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
43048
43293
|
const dir = ensureRolesDirectory(scope, repoRoot3, options.userConfigDir);
|
|
43049
|
-
const filePath =
|
|
43050
|
-
writeFileSync24(filePath, (0,
|
|
43294
|
+
const filePath = join35(dir, `${roleId}.yaml`);
|
|
43295
|
+
writeFileSync24(filePath, (0, import_yaml15.stringify)(updated), "utf8");
|
|
43051
43296
|
return { id: roleId, role: updated, filePath, scope };
|
|
43052
43297
|
}
|
|
43053
43298
|
var KXM_ROLE_HOSTS_SCHEMA = "kxm.role-hosts.v1";
|
|
@@ -43095,19 +43340,19 @@ var DEFAULT_ROLE_SEATS = {
|
|
|
43095
43340
|
};
|
|
43096
43341
|
function findExistingRoleHostsFile(scope, repoRoot3 = process.cwd(), userConfigDir) {
|
|
43097
43342
|
const dir = scope === "global" ? userConfigDirectory(userConfigDir) : repoConfigDirectory(repoRoot3);
|
|
43098
|
-
const yamlPath =
|
|
43099
|
-
const ymlPath =
|
|
43100
|
-
const jsonPath =
|
|
43101
|
-
if (
|
|
43102
|
-
if (
|
|
43103
|
-
if (
|
|
43343
|
+
const yamlPath = join35(dir, "role-hosts.yaml");
|
|
43344
|
+
const ymlPath = join35(dir, "role-hosts.yml");
|
|
43345
|
+
const jsonPath = join35(dir, "role-hosts.json");
|
|
43346
|
+
if (existsSync29(yamlPath)) return { filePath: yamlPath, exists: true, format: "yaml" };
|
|
43347
|
+
if (existsSync29(ymlPath)) return { filePath: ymlPath, exists: true, format: "yaml" };
|
|
43348
|
+
if (existsSync29(jsonPath)) return { filePath: jsonPath, exists: true, format: "json" };
|
|
43104
43349
|
return { filePath: yamlPath, exists: false, format: "yaml" };
|
|
43105
43350
|
}
|
|
43106
43351
|
function parseRoleHostsFile(filePath) {
|
|
43107
|
-
if (!
|
|
43352
|
+
if (!existsSync29(filePath)) return void 0;
|
|
43108
43353
|
try {
|
|
43109
|
-
const raw =
|
|
43110
|
-
const parsed = (0,
|
|
43354
|
+
const raw = readFileSync27(filePath, "utf8");
|
|
43355
|
+
const parsed = (0, import_yaml15.parse)(raw);
|
|
43111
43356
|
if (!parsed || typeof parsed !== "object") return void 0;
|
|
43112
43357
|
if (parsed.schema && parsed.schema !== KXM_ROLE_HOSTS_SCHEMA) return void 0;
|
|
43113
43358
|
return {
|
|
@@ -43178,17 +43423,17 @@ function saveRoleHostsConfig(config, options = {}) {
|
|
|
43178
43423
|
const scope = options.scope ?? "local";
|
|
43179
43424
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
43180
43425
|
const dir = scope === "global" ? userConfigDirectory(options.userConfigDir) : repoConfigDirectory(repoRoot3);
|
|
43181
|
-
if (!
|
|
43426
|
+
if (!existsSync29(dir)) {
|
|
43182
43427
|
mkdirSync26(dir, { recursive: true });
|
|
43183
43428
|
}
|
|
43184
43429
|
const format = options.format ?? "yaml";
|
|
43185
|
-
const filePath =
|
|
43430
|
+
const filePath = join35(dir, format === "json" ? "role-hosts.json" : "role-hosts.yaml");
|
|
43186
43431
|
const payload = {
|
|
43187
43432
|
schema: KXM_ROLE_HOSTS_SCHEMA,
|
|
43188
43433
|
seats: config.seats ?? {},
|
|
43189
43434
|
...config.hostProviders && Object.keys(config.hostProviders).length > 0 ? { hostProviders: config.hostProviders } : {}
|
|
43190
43435
|
};
|
|
43191
|
-
const content = format === "json" ? JSON.stringify(payload, null, 2) + "\n" : (0,
|
|
43436
|
+
const content = format === "json" ? JSON.stringify(payload, null, 2) + "\n" : (0, import_yaml15.stringify)(payload);
|
|
43192
43437
|
writeFileSync24(filePath, content, "utf8");
|
|
43193
43438
|
return { filePath, scope };
|
|
43194
43439
|
}
|
|
@@ -43273,9 +43518,9 @@ function resolveRoleSeat(seatId, options = {}) {
|
|
|
43273
43518
|
}
|
|
43274
43519
|
|
|
43275
43520
|
// plugins/kxm/src/workflow-manager.ts
|
|
43276
|
-
var
|
|
43277
|
-
import { existsSync as
|
|
43278
|
-
import { join as
|
|
43521
|
+
var import_yaml16 = __toESM(require_dist(), 1);
|
|
43522
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync27, readdirSync as readdirSync10, readFileSync as readFileSync28, rmSync as rmSync9, writeFileSync as writeFileSync25 } from "node:fs";
|
|
43523
|
+
import { join as join36 } from "node:path";
|
|
43279
43524
|
var WORKFLOW_TEMPLATES = {
|
|
43280
43525
|
"implement-and-verify": {
|
|
43281
43526
|
schema: "kxm.workflow.v1",
|
|
@@ -43426,22 +43671,22 @@ var WORKFLOW_TEMPLATES = {
|
|
|
43426
43671
|
var DEFAULT_WORKFLOW_TEMPLATE = WORKFLOW_TEMPLATES["implement-and-verify"];
|
|
43427
43672
|
function workflowsDirectory(scope, repoRoot3 = process.cwd(), userConfigDir) {
|
|
43428
43673
|
if (scope === "global") {
|
|
43429
|
-
return
|
|
43674
|
+
return join36(userConfigDirectory(userConfigDir), "workflows");
|
|
43430
43675
|
}
|
|
43431
|
-
return
|
|
43676
|
+
return join36(repoConfigDirectory(repoRoot3), "workflows");
|
|
43432
43677
|
}
|
|
43433
43678
|
function ensureWorkflowsDirectory(scope, repoRoot3 = process.cwd(), userConfigDir) {
|
|
43434
43679
|
const dir = workflowsDirectory(scope, repoRoot3, userConfigDir);
|
|
43435
|
-
if (!
|
|
43680
|
+
if (!existsSync30(dir)) {
|
|
43436
43681
|
mkdirSync27(dir, { recursive: true });
|
|
43437
43682
|
}
|
|
43438
43683
|
return dir;
|
|
43439
43684
|
}
|
|
43440
43685
|
function parseWorkflowFile(filePath) {
|
|
43441
|
-
if (!
|
|
43686
|
+
if (!existsSync30(filePath)) return void 0;
|
|
43442
43687
|
try {
|
|
43443
|
-
const raw =
|
|
43444
|
-
const parsed = (0,
|
|
43688
|
+
const raw = readFileSync28(filePath, "utf8");
|
|
43689
|
+
const parsed = (0, import_yaml16.parse)(raw);
|
|
43445
43690
|
if (!parsed || typeof parsed !== "object") return void 0;
|
|
43446
43691
|
return parsed;
|
|
43447
43692
|
} catch {
|
|
@@ -43454,10 +43699,10 @@ function listWorkflowDefinitions(options = {}) {
|
|
|
43454
43699
|
const globalDir = workflowsDirectory("global", repoRoot3, options.userConfigDir);
|
|
43455
43700
|
const localDir = workflowsDirectory("local", repoRoot3, options.userConfigDir);
|
|
43456
43701
|
const localDefs = /* @__PURE__ */ new Map();
|
|
43457
|
-
if (scopeFilter !== "global" &&
|
|
43702
|
+
if (scopeFilter !== "global" && existsSync30(localDir)) {
|
|
43458
43703
|
for (const entry of readdirSync10(localDir)) {
|
|
43459
43704
|
if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
|
|
43460
|
-
const filePath =
|
|
43705
|
+
const filePath = join36(localDir, entry);
|
|
43461
43706
|
const def = parseWorkflowFile(filePath);
|
|
43462
43707
|
if (def) {
|
|
43463
43708
|
const id = def.id || entry.replace(/\.ya?ml$/i, "");
|
|
@@ -43467,10 +43712,10 @@ function listWorkflowDefinitions(options = {}) {
|
|
|
43467
43712
|
}
|
|
43468
43713
|
}
|
|
43469
43714
|
const globalDefs = /* @__PURE__ */ new Map();
|
|
43470
|
-
if (scopeFilter !== "local" &&
|
|
43715
|
+
if (scopeFilter !== "local" && existsSync30(globalDir)) {
|
|
43471
43716
|
for (const entry of readdirSync10(globalDir)) {
|
|
43472
43717
|
if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
|
|
43473
|
-
const filePath =
|
|
43718
|
+
const filePath = join36(globalDir, entry);
|
|
43474
43719
|
const def = parseWorkflowFile(filePath);
|
|
43475
43720
|
if (def) {
|
|
43476
43721
|
const id = def.id || entry.replace(/\.ya?ml$/i, "");
|
|
@@ -43526,13 +43771,13 @@ function getWorkflowDefinition(workflowId, options = {}) {
|
|
|
43526
43771
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
43527
43772
|
if (scope !== "global") {
|
|
43528
43773
|
const localDir = workflowsDirectory("local", repoRoot3, options.userConfigDir);
|
|
43529
|
-
const localFile =
|
|
43774
|
+
const localFile = join36(localDir, `${workflowId}.yaml`);
|
|
43530
43775
|
const parsed = parseWorkflowFile(localFile);
|
|
43531
43776
|
if (parsed) return { workflow: parsed, scope: "local", filePath: localFile };
|
|
43532
43777
|
}
|
|
43533
43778
|
if (scope !== "local") {
|
|
43534
43779
|
const globalDir = workflowsDirectory("global", repoRoot3, options.userConfigDir);
|
|
43535
|
-
const globalFile =
|
|
43780
|
+
const globalFile = join36(globalDir, `${workflowId}.yaml`);
|
|
43536
43781
|
const parsed = parseWorkflowFile(globalFile);
|
|
43537
43782
|
if (parsed) return { workflow: parsed, scope: "global", filePath: globalFile };
|
|
43538
43783
|
}
|
|
@@ -43542,11 +43787,11 @@ function addWorkflowDefinition(workflowId, content = DEFAULT_WORKFLOW_TEMPLATE,
|
|
|
43542
43787
|
const scope = options.scope ?? "local";
|
|
43543
43788
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
43544
43789
|
const dir = ensureWorkflowsDirectory(scope, repoRoot3, options.userConfigDir);
|
|
43545
|
-
const filePath =
|
|
43546
|
-
if (
|
|
43790
|
+
const filePath = join36(dir, `${workflowId}.yaml`);
|
|
43791
|
+
if (existsSync30(filePath) && !options.overwrite) {
|
|
43547
43792
|
throw new Error(`workflow_already_exists: workflow '${workflowId}' already exists at ${filePath}`);
|
|
43548
43793
|
}
|
|
43549
|
-
const payload = typeof content === "string" ? content : (0,
|
|
43794
|
+
const payload = typeof content === "string" ? content : (0, import_yaml16.stringify)(content);
|
|
43550
43795
|
writeFileSync25(filePath, payload, "utf8");
|
|
43551
43796
|
return { id: workflowId, filePath, scope };
|
|
43552
43797
|
}
|
|
@@ -43554,8 +43799,8 @@ function removeWorkflowDefinition(workflowId, options = {}) {
|
|
|
43554
43799
|
const scope = options.scope ?? "local";
|
|
43555
43800
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
43556
43801
|
const dir = workflowsDirectory(scope, repoRoot3, options.userConfigDir);
|
|
43557
|
-
const filePath =
|
|
43558
|
-
if (!
|
|
43802
|
+
const filePath = join36(dir, `${workflowId}.yaml`);
|
|
43803
|
+
if (!existsSync30(filePath)) {
|
|
43559
43804
|
throw new Error(`workflow_not_found: workflow '${workflowId}' not found in ${scope} directory (${filePath})`);
|
|
43560
43805
|
}
|
|
43561
43806
|
rmSync9(filePath);
|
|
@@ -43573,8 +43818,8 @@ function modifyWorkflowDefinition(workflowId, updates, options = {}) {
|
|
|
43573
43818
|
const scope = options.scope ?? target.scope;
|
|
43574
43819
|
const repoRoot3 = options.repoRoot ?? process.cwd();
|
|
43575
43820
|
const dir = ensureWorkflowsDirectory(scope, repoRoot3, options.userConfigDir);
|
|
43576
|
-
const filePath =
|
|
43577
|
-
writeFileSync25(filePath, (0,
|
|
43821
|
+
const filePath = join36(dir, `${workflowId}.yaml`);
|
|
43822
|
+
writeFileSync25(filePath, (0, import_yaml16.stringify)(updated), "utf8");
|
|
43578
43823
|
return { id: workflowId, workflow: updated, filePath, scope };
|
|
43579
43824
|
}
|
|
43580
43825
|
|
|
@@ -43596,7 +43841,7 @@ var USAGE_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
|
43596
43841
|
]);
|
|
43597
43842
|
function spawnScript(scriptName, extraEnv = {}) {
|
|
43598
43843
|
return new Promise((resolveExit) => {
|
|
43599
|
-
const child = spawn2(process.execPath, [
|
|
43844
|
+
const child = spawn2(process.execPath, [join37(repoRoot2, "scripts", scriptName)], {
|
|
43600
43845
|
stdio: "inherit",
|
|
43601
43846
|
env: { ...process.env, ...extraEnv }
|
|
43602
43847
|
});
|
|
@@ -43686,10 +43931,10 @@ function workspaceDirs(cwd, workspaceFlag, env) {
|
|
|
43686
43931
|
return {
|
|
43687
43932
|
workdir,
|
|
43688
43933
|
workspace,
|
|
43689
|
-
config: derive ?
|
|
43690
|
-
logs: derive ?
|
|
43691
|
-
assets: derive ?
|
|
43692
|
-
state: derive ?
|
|
43934
|
+
config: derive ? join37(workspace, "config") : resolve22(workdir, env.KXM_CONFIG_DIR?.trim() || join37(workspace, "config")),
|
|
43935
|
+
logs: derive ? join37(workspace, "logs") : resolve22(workdir, env.KXM_LOGS_DIR?.trim() || join37(workspace, "logs")),
|
|
43936
|
+
assets: derive ? join37(workspace, "assets") : resolve22(workdir, env.KXM_ASSETS_DIR?.trim() || join37(workspace, "assets")),
|
|
43937
|
+
state: derive ? join37(workspace, "state") : resolve22(workdir, env.KXM_STATE_DIR?.trim() || join37(workspace, "state"))
|
|
43693
43938
|
};
|
|
43694
43939
|
}
|
|
43695
43940
|
function maskEnvName(name) {
|
|
@@ -43749,7 +43994,7 @@ async function hubGet(url, fetchImpl) {
|
|
|
43749
43994
|
}
|
|
43750
43995
|
}
|
|
43751
43996
|
function localWorkflowSnapshot(dataPath, runId) {
|
|
43752
|
-
if (!
|
|
43997
|
+
if (!existsSync31(dataPath)) throw new Error("state_database_not_found");
|
|
43753
43998
|
const database = new DatabaseSync(dataPath, { readOnly: true });
|
|
43754
43999
|
try {
|
|
43755
44000
|
const rows = runId ? database.prepare("SELECT record FROM workflow_runs WHERE id = ?").all(runId) : database.prepare("SELECT record FROM workflow_runs ORDER BY rowid DESC LIMIT 200").all();
|
|
@@ -43855,7 +44100,7 @@ function activeWorkflowDefinition(runtime, definitionId) {
|
|
|
43855
44100
|
let raw;
|
|
43856
44101
|
if (file) {
|
|
43857
44102
|
try {
|
|
43858
|
-
raw =
|
|
44103
|
+
raw = readFileSync29(resolve22(runtime.cwd, file), "utf8");
|
|
43859
44104
|
} catch {
|
|
43860
44105
|
throw new Error("workflow definition file is unavailable");
|
|
43861
44106
|
}
|
|
@@ -44138,7 +44383,7 @@ async function cmdBackup(runtime, options) {
|
|
|
44138
44383
|
const summary = [
|
|
44139
44384
|
`Created SQLite backup with ${manifest.stores.length} store(s):`,
|
|
44140
44385
|
...manifest.stores.map((s) => ` - ${s.storeId}: ${s.sourcePath} -> ${s.backupFile} (schema v${s.schemaVersion}, ${s.bytes} bytes, sha256 ${s.sha256.slice(0, 12)}...)`),
|
|
44141
|
-
`Manifest: ${
|
|
44386
|
+
`Manifest: ${join37(outDir, "manifest.json")}`
|
|
44142
44387
|
].join("\n");
|
|
44143
44388
|
print(runtime.io, runtime.json, payload, summary);
|
|
44144
44389
|
return 0;
|
|
@@ -44429,9 +44674,9 @@ function npmGlobalRootFn(runtime) {
|
|
|
44429
44674
|
};
|
|
44430
44675
|
}
|
|
44431
44676
|
function warnIgnoredProjectUpdateYaml(runtime) {
|
|
44432
|
-
const projectFile =
|
|
44433
|
-
if (!
|
|
44434
|
-
const userFile =
|
|
44677
|
+
const projectFile = join37(runtime.dirs.workspace, "update.yaml");
|
|
44678
|
+
if (!existsSync31(projectFile)) return;
|
|
44679
|
+
const userFile = join37(vnextUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
44435
44680
|
runtime.io.stderr(`kxm: ignoring .kxm/update.yaml in ${runtime.dirs.workdir}; update settings are read only from ${userFile}
|
|
44436
44681
|
`);
|
|
44437
44682
|
}
|
|
@@ -44460,7 +44705,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
44460
44705
|
detail: `release v${notice.latest} has no sha256 digest for ${name}; refusing to install`
|
|
44461
44706
|
};
|
|
44462
44707
|
}
|
|
44463
|
-
const releaseDir = mkdtempSync2(
|
|
44708
|
+
const releaseDir = mkdtempSync2(join37(tmpdir2(), "kxm-pkg-update-"));
|
|
44464
44709
|
try {
|
|
44465
44710
|
const planned = planKxmPackageUpdate(notice.source, notice.latest, releaseDir, notice.asset);
|
|
44466
44711
|
if (runtime.dryRun) {
|
|
@@ -44469,7 +44714,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
44469
44714
|
for (const step of planned) {
|
|
44470
44715
|
if (step.kind === "verify") {
|
|
44471
44716
|
if (!verifyReleaseAssetDigest(step.path, step.sha256)) {
|
|
44472
|
-
const actual =
|
|
44717
|
+
const actual = existsSync31(step.path) ? createHash16("sha256").update(readFileSync29(step.path)).digest("hex") : "missing";
|
|
44473
44718
|
return {
|
|
44474
44719
|
ok: false,
|
|
44475
44720
|
error: "release_digest_mismatch",
|
|
@@ -44555,6 +44800,22 @@ async function cmdModelInventoryRefresh(runtime) {
|
|
|
44555
44800
|
print(runtime.io, runtime.json, { ok: !failed, command: "models inventory refresh", output: ".kxm/models/inventory.yaml", ...inventory }, `wrote ${inventory.models.length} models to .kxm/models/inventory.yaml`);
|
|
44556
44801
|
return failed ? 1 : 0;
|
|
44557
44802
|
}
|
|
44803
|
+
async function cmdExplain(runtime, options) {
|
|
44804
|
+
const modesConfig = loadModesConfig(runtime.dirs.workdir);
|
|
44805
|
+
const majorMode = options.mode || "coder";
|
|
44806
|
+
const domains = options.domains ? options.domains.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
44807
|
+
const resolved = resolveActiveMode(modesConfig, majorMode, domains);
|
|
44808
|
+
if (options.model) {
|
|
44809
|
+
resolved.model = options.model;
|
|
44810
|
+
}
|
|
44811
|
+
const footprint = calculatePromptFootprint(resolved, runtime.dirs.workdir);
|
|
44812
|
+
if (runtime.json) {
|
|
44813
|
+
print(runtime.io, runtime.json, { ok: true, command: "explain", ...footprint }, "");
|
|
44814
|
+
} else {
|
|
44815
|
+
runtime.io.stdout(formatModesExplainReport(footprint) + "\n");
|
|
44816
|
+
}
|
|
44817
|
+
return 0;
|
|
44818
|
+
}
|
|
44558
44819
|
async function cmdUpdate(runtime, harness, options) {
|
|
44559
44820
|
if (options.check && (options.kxm || options.self || options.extensions || options.models || harness)) {
|
|
44560
44821
|
print(runtime.io, runtime.json, { ok: false, command: "update", error: "scope_conflict" }, "--check cannot be combined with other update flags");
|
|
@@ -44764,12 +45025,12 @@ async function cmdValidate(runtime, fileFlag) {
|
|
|
44764
45025
|
}
|
|
44765
45026
|
const selectedFile = explicitFile || configuredFile;
|
|
44766
45027
|
const file = selectedFile ? resolve22(runtime.cwd, selectedFile) : void 0;
|
|
44767
|
-
if (file && !
|
|
45028
|
+
if (file && !existsSync31(file)) {
|
|
44768
45029
|
printWorker(runtime, worker, { ok: false, command: "validate", error: "file_not_found", file }, `workflow file not found: ${file}`);
|
|
44769
45030
|
return 1;
|
|
44770
45031
|
}
|
|
44771
45032
|
try {
|
|
44772
|
-
const raw = file ?
|
|
45033
|
+
const raw = file ? readFileSync29(file, "utf8") : inline;
|
|
44773
45034
|
const warnings = [];
|
|
44774
45035
|
const definitions = parseWorkflowDefinitions(raw, runtime.env, (message) => warnings.push(message));
|
|
44775
45036
|
const secretEnvs = definitions.map((definition) => ({
|
|
@@ -44826,7 +45087,7 @@ async function cmdDash(runtime, options = {}) {
|
|
|
44826
45087
|
return 2;
|
|
44827
45088
|
}
|
|
44828
45089
|
const screen = requested;
|
|
44829
|
-
const dataPath = resolve22(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
45090
|
+
const dataPath = resolve22(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join37(runtime.dirs.state, "kxm.db"));
|
|
44830
45091
|
if (runtime.dryRun) {
|
|
44831
45092
|
print(runtime.io, runtime.json, {
|
|
44832
45093
|
ok: true,
|
|
@@ -44872,7 +45133,7 @@ async function cmdHub(runtime) {
|
|
|
44872
45133
|
config = loadKxmUpdateConfig(runtime.env);
|
|
44873
45134
|
} catch (error) {
|
|
44874
45135
|
if (error instanceof KxmUpdateConfigError) {
|
|
44875
|
-
const yamlPath =
|
|
45136
|
+
const yamlPath = join37(vnextUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
44876
45137
|
runtime.io.stderr(`kxm: ${error.message}; update check skipped; fix or remove ${yamlPath}
|
|
44877
45138
|
`);
|
|
44878
45139
|
} else {
|
|
@@ -45008,7 +45269,7 @@ async function cmdWorker(runtime, options) {
|
|
|
45008
45269
|
return await (runtime.io.spawnWorker ?? ((launchEnv) => spawnScript("kxm-worker.mjs", launchEnv)))(extraEnv);
|
|
45009
45270
|
}
|
|
45010
45271
|
async function cmdStop(runtime, waitMsFlag) {
|
|
45011
|
-
const pids =
|
|
45272
|
+
const pids = existsSync31(runtime.dirs.state) ? readdirSync11(runtime.dirs.state).filter((name) => name.endsWith(".pid")) : [];
|
|
45012
45273
|
if (runtime.dryRun) {
|
|
45013
45274
|
print(runtime.io, runtime.json, { ok: true, command: "stop", dryRun: true, pidFiles: pids }, "would signal pid files");
|
|
45014
45275
|
return 0;
|
|
@@ -45023,7 +45284,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45023
45284
|
const orphans = [];
|
|
45024
45285
|
for (const file of pids) {
|
|
45025
45286
|
try {
|
|
45026
|
-
const record = JSON.parse(
|
|
45287
|
+
const record = JSON.parse(readFileSync29(join37(runtime.dirs.state, file), "utf8"));
|
|
45027
45288
|
const expectedControl = file === "hub.pid" ? "hub.stop" : file.startsWith("worker-") ? `${file.slice(0, -4)}.stop` : void 0;
|
|
45028
45289
|
const expectedRole = file === "hub.pid" ? "hub" : file.startsWith("worker-") ? "worker" : void 0;
|
|
45029
45290
|
if (record.version !== 1 || !Number.isInteger(record.pid) || record.pid <= 0 || !record.startedAt || !expectedControl || record.controlFile !== expectedControl || record.role !== expectedRole) {
|
|
@@ -45043,7 +45304,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45043
45304
|
ignored.push(file);
|
|
45044
45305
|
continue;
|
|
45045
45306
|
}
|
|
45046
|
-
writeFileSync26(
|
|
45307
|
+
writeFileSync26(join37(runtime.dirs.state, record.controlFile), `${JSON.stringify({ startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {}, requestedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
45047
45308
|
`, { encoding: "utf8", mode: 384 });
|
|
45048
45309
|
requested.push(file);
|
|
45049
45310
|
records.set(file, { pid: record.pid, startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {} });
|
|
@@ -45061,7 +45322,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45061
45322
|
while (Date.now() <= deadline && stopped.size < requested.length) {
|
|
45062
45323
|
for (const [file, record] of records) {
|
|
45063
45324
|
try {
|
|
45064
|
-
const current = JSON.parse(
|
|
45325
|
+
const current = JSON.parse(readFileSync29(join37(runtime.dirs.state, file), "utf8"));
|
|
45065
45326
|
if (current.pid !== record.pid || current.startedAt !== record.startedAt || current.generation !== record.generation || !processExists2(record.pid)) stopped.add(file);
|
|
45066
45327
|
} catch {
|
|
45067
45328
|
stopped.add(file);
|
|
@@ -45074,7 +45335,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45074
45335
|
for (const file of orphans) {
|
|
45075
45336
|
while (Date.now() <= deadlineOrphans) {
|
|
45076
45337
|
try {
|
|
45077
|
-
const current = JSON.parse(
|
|
45338
|
+
const current = JSON.parse(readFileSync29(join37(runtime.dirs.state, file), "utf8"));
|
|
45078
45339
|
if (!Number.isInteger(current.serverPid) || !processExists2(current.serverPid)) break;
|
|
45079
45340
|
} catch {
|
|
45080
45341
|
break;
|
|
@@ -45082,14 +45343,14 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45082
45343
|
await (runtime.io.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms))))(100);
|
|
45083
45344
|
}
|
|
45084
45345
|
try {
|
|
45085
|
-
const current = JSON.parse(
|
|
45346
|
+
const current = JSON.parse(readFileSync29(join37(runtime.dirs.state, file), "utf8"));
|
|
45086
45347
|
if (Number.isInteger(current.serverPid) && processExists2(current.serverPid)) {
|
|
45087
45348
|
try {
|
|
45088
45349
|
process.kill(current.serverPid, "SIGKILL");
|
|
45089
45350
|
} catch {
|
|
45090
45351
|
}
|
|
45091
45352
|
}
|
|
45092
|
-
rmSync10(
|
|
45353
|
+
rmSync10(join37(runtime.dirs.state, file), { force: true });
|
|
45093
45354
|
} catch {
|
|
45094
45355
|
}
|
|
45095
45356
|
stopped.add(file);
|
|
@@ -45100,11 +45361,11 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
45100
45361
|
}
|
|
45101
45362
|
async function cmdSessionStatus(runtime) {
|
|
45102
45363
|
const stateDir = runtime.dirs.state;
|
|
45103
|
-
const names3 =
|
|
45364
|
+
const names3 = existsSync31(stateDir) ? readdirSync11(stateDir) : [];
|
|
45104
45365
|
const claims = [];
|
|
45105
45366
|
for (const file of names3.filter((name) => name.endsWith(".pid"))) {
|
|
45106
45367
|
try {
|
|
45107
|
-
const record = JSON.parse(
|
|
45368
|
+
const record = JSON.parse(readFileSync29(join37(stateDir, file), "utf8"));
|
|
45108
45369
|
claims.push({
|
|
45109
45370
|
file,
|
|
45110
45371
|
role: record.role,
|
|
@@ -45119,7 +45380,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
45119
45380
|
const recoveries = [];
|
|
45120
45381
|
for (const file of names3.filter((name) => name.startsWith("worker-recovery-") && name.endsWith(".json"))) {
|
|
45121
45382
|
try {
|
|
45122
|
-
const envelope = JSON.parse(
|
|
45383
|
+
const envelope = JSON.parse(readFileSync29(join37(stateDir, file), "utf8"));
|
|
45123
45384
|
recoveries.push({
|
|
45124
45385
|
file,
|
|
45125
45386
|
reason: envelope.reason,
|
|
@@ -45224,7 +45485,7 @@ async function cmdSessionBrief(runtime, options = {}) {
|
|
|
45224
45485
|
print(runtime.io, runtime.json, { ok: true, command: "session brief", sessionToken }, sessionToken);
|
|
45225
45486
|
return 0;
|
|
45226
45487
|
}
|
|
45227
|
-
const dataPath = resolve22(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
45488
|
+
const dataPath = resolve22(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join37(runtime.dirs.state, "kxm.db"));
|
|
45228
45489
|
const env = {
|
|
45229
45490
|
...runtime.env,
|
|
45230
45491
|
KXM_STATE_DIR: runtime.dirs.state,
|
|
@@ -45314,14 +45575,14 @@ async function cmdSessionStart(runtime, options) {
|
|
|
45314
45575
|
}
|
|
45315
45576
|
async function cmdImprove(runtime, options = {}) {
|
|
45316
45577
|
const file = options.file ? resolve22(runtime.cwd, options.file) : telemetryPath(runtime.dirs.logs);
|
|
45317
|
-
const routingRecords =
|
|
45318
|
-
const candidatesDir = options.outDir ? resolve22(runtime.cwd, options.outDir) :
|
|
45578
|
+
const routingRecords = existsSync31(file) ? readRoutingRecords(file).map((entry) => entry.routing) : [];
|
|
45579
|
+
const candidatesDir = options.outDir ? resolve22(runtime.cwd, options.outDir) : join37(runtime.cwd, ".kxm", "candidates");
|
|
45319
45580
|
const report2 = buildImprovementReport(routingRecords, {
|
|
45320
45581
|
candidatesDir,
|
|
45321
45582
|
projectRoot: runtime.cwd,
|
|
45322
45583
|
dryRun: runtime.dryRun
|
|
45323
45584
|
});
|
|
45324
|
-
const reportDir =
|
|
45585
|
+
const reportDir = join37(runtime.dirs.assets, "improvements");
|
|
45325
45586
|
const reportPath = writeImprovementReport(reportDir, report2, runtime.dryRun);
|
|
45326
45587
|
const text = formatImprovementReport(report2);
|
|
45327
45588
|
print(runtime.io, runtime.json, {
|
|
@@ -45480,7 +45741,7 @@ function skillStateFromFlag(value) {
|
|
|
45480
45741
|
throw new Error(`invalid skill state ${value}`);
|
|
45481
45742
|
}
|
|
45482
45743
|
function skillsRoot(runtime) {
|
|
45483
|
-
return
|
|
45744
|
+
return join37(runtime.dirs.workdir, ".kxm", "skills");
|
|
45484
45745
|
}
|
|
45485
45746
|
function csv(value) {
|
|
45486
45747
|
if (!value) return void 0;
|
|
@@ -45497,7 +45758,7 @@ async function cmdSkillsCreate(runtime, options) {
|
|
|
45497
45758
|
const metadata = lifecycle.create({
|
|
45498
45759
|
name: options.name,
|
|
45499
45760
|
description: options.description ?? "",
|
|
45500
|
-
content:
|
|
45761
|
+
content: readFileSync29(options.file, "utf8"),
|
|
45501
45762
|
createdBy: options.createdBy,
|
|
45502
45763
|
sources: {
|
|
45503
45764
|
runIds: csv(options.run) ?? [],
|
|
@@ -45767,9 +46028,9 @@ async function maybeOfferCompletionInstall(runtime) {
|
|
|
45767
46028
|
if (!pathNeeded) {
|
|
45768
46029
|
const scriptPath = completionScriptPath(shell, { env: runtime.env, configDir: runtime.env.KXM_USER_CONFIG_DIR });
|
|
45769
46030
|
const { rcFile } = completionRcTarget(shell, { env: runtime.env });
|
|
45770
|
-
if (rcFile &&
|
|
46031
|
+
if (rcFile && existsSync31(rcFile)) {
|
|
45771
46032
|
try {
|
|
45772
|
-
if (
|
|
46033
|
+
if (readFileSync29(rcFile, "utf8").includes(scriptPath)) return;
|
|
45773
46034
|
} catch {
|
|
45774
46035
|
}
|
|
45775
46036
|
}
|
|
@@ -46077,8 +46338,8 @@ async function cmdStudioLayout(runtime, workflowPath) {
|
|
|
46077
46338
|
}
|
|
46078
46339
|
let yamlContent;
|
|
46079
46340
|
let workflowId = "default";
|
|
46080
|
-
if (
|
|
46081
|
-
yamlContent =
|
|
46341
|
+
if (existsSync31(filePath)) {
|
|
46342
|
+
yamlContent = readFileSync29(filePath, "utf8");
|
|
46082
46343
|
} else {
|
|
46083
46344
|
yamlContent = `schema: kxm.workflow.v1
|
|
46084
46345
|
description: Feature implementation workflow
|
|
@@ -46118,7 +46379,7 @@ steps:
|
|
|
46118
46379
|
maxTransitions: 2
|
|
46119
46380
|
`;
|
|
46120
46381
|
}
|
|
46121
|
-
const parsedYaml = (0,
|
|
46382
|
+
const parsedYaml = (0, import_yaml17.parse)(yamlContent);
|
|
46122
46383
|
const plan = compileVnextWorkflow({ id: workflowId, value: parsedYaml });
|
|
46123
46384
|
const layout = generateStudioLayout(plan);
|
|
46124
46385
|
print(runtime.io, runtime.json, { ok: true, command: "studio layout", layout }, JSON.stringify(layout, null, 2));
|
|
@@ -46151,16 +46412,16 @@ async function cmdStudioServe(runtime, options) {
|
|
|
46151
46412
|
sessionToken,
|
|
46152
46413
|
planProvider: () => {
|
|
46153
46414
|
try {
|
|
46154
|
-
const wfDir =
|
|
46155
|
-
const defaultPath =
|
|
46156
|
-
let targetPath =
|
|
46157
|
-
if (!targetPath &&
|
|
46415
|
+
const wfDir = join37(runtime.cwd, ".kxm", "workflows");
|
|
46416
|
+
const defaultPath = join37(wfDir, "default.yaml");
|
|
46417
|
+
let targetPath = existsSync31(defaultPath) ? defaultPath : void 0;
|
|
46418
|
+
if (!targetPath && existsSync31(wfDir)) {
|
|
46158
46419
|
const yml = readdirSync11(wfDir).find((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
|
|
46159
|
-
if (yml) targetPath =
|
|
46420
|
+
if (yml) targetPath = join37(wfDir, yml);
|
|
46160
46421
|
}
|
|
46161
|
-
if (targetPath &&
|
|
46162
|
-
const raw =
|
|
46163
|
-
const parsed = (0,
|
|
46422
|
+
if (targetPath && existsSync31(targetPath)) {
|
|
46423
|
+
const raw = readFileSync29(targetPath, "utf8");
|
|
46424
|
+
const parsed = (0, import_yaml17.parse)(raw);
|
|
46164
46425
|
const wfId = basename7(targetPath).replace(/\.(yaml|yml)$/, "");
|
|
46165
46426
|
return compileVnextWorkflow({ id: wfId, value: parsed });
|
|
46166
46427
|
}
|
|
@@ -46246,7 +46507,7 @@ async function cmdRoleGet(runtime, roleId, options) {
|
|
|
46246
46507
|
runtime.io,
|
|
46247
46508
|
runtime.json,
|
|
46248
46509
|
{ ok: true, command: "role get", roleId, scope: result.scope, filePath: result.filePath, role: result.role },
|
|
46249
|
-
(0,
|
|
46510
|
+
(0, import_yaml17.stringify)(result.role)
|
|
46250
46511
|
);
|
|
46251
46512
|
return 0;
|
|
46252
46513
|
}
|
|
@@ -46358,8 +46619,8 @@ async function cmdRoleAdd(runtime, roleId, options) {
|
|
|
46358
46619
|
let roleDef;
|
|
46359
46620
|
if (options.file) {
|
|
46360
46621
|
const filePath = resolve22(runtime.cwd, options.file);
|
|
46361
|
-
const content =
|
|
46362
|
-
roleDef = (0,
|
|
46622
|
+
const content = readFileSync29(filePath, "utf8");
|
|
46623
|
+
roleDef = (0, import_yaml17.parse)(content);
|
|
46363
46624
|
roleDef.id = roleId;
|
|
46364
46625
|
} else {
|
|
46365
46626
|
const skills = options.skills ? options.skills.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
@@ -46657,8 +46918,8 @@ async function cmdRoleResume(runtime, runId, ruling) {
|
|
|
46657
46918
|
return 1;
|
|
46658
46919
|
}
|
|
46659
46920
|
}
|
|
46660
|
-
const dbPath =
|
|
46661
|
-
if (
|
|
46921
|
+
const dbPath = join37(runtime.cwd, ".kxm", "state", "kxm.db");
|
|
46922
|
+
if (existsSync31(dbPath)) {
|
|
46662
46923
|
try {
|
|
46663
46924
|
const database = new DatabaseSync(dbPath);
|
|
46664
46925
|
try {
|
|
@@ -46777,7 +47038,7 @@ async function cmdWorkflowAdd(runtime, workflowId, options) {
|
|
|
46777
47038
|
}
|
|
46778
47039
|
if (options.file) {
|
|
46779
47040
|
const filePath = resolve22(runtime.cwd, options.file);
|
|
46780
|
-
content =
|
|
47041
|
+
content = readFileSync29(filePath, "utf8");
|
|
46781
47042
|
} else if (!content) {
|
|
46782
47043
|
content = {
|
|
46783
47044
|
schema: "kxm.workflow.v1",
|
|
@@ -46921,7 +47182,7 @@ async function cmdRoutingReport(runtime, options) {
|
|
|
46921
47182
|
let catalog;
|
|
46922
47183
|
if (includeEquivalentListCost) {
|
|
46923
47184
|
try {
|
|
46924
|
-
const pricesPath = options.prices ? resolve22(runtime.cwd, options.prices) :
|
|
47185
|
+
const pricesPath = options.prices ? resolve22(runtime.cwd, options.prices) : join37(runtime.dirs.workspace, "prices.yaml");
|
|
46925
47186
|
catalog = loadPriceCatalog(pricesPath);
|
|
46926
47187
|
} catch {
|
|
46927
47188
|
}
|
|
@@ -47023,7 +47284,7 @@ async function cmdWorkflowStart(runtime, definitionIdArg, options) {
|
|
|
47023
47284
|
}
|
|
47024
47285
|
let payload;
|
|
47025
47286
|
try {
|
|
47026
|
-
const raw = payloadFlag.startsWith("@") ?
|
|
47287
|
+
const raw = payloadFlag.startsWith("@") ? readFileSync29(resolve22(runtime.cwd, payloadFlag.slice(1)), "utf8") : payloadFlag;
|
|
47027
47288
|
const value = JSON.parse(raw);
|
|
47028
47289
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("object required");
|
|
47029
47290
|
payload = value;
|
|
@@ -47090,7 +47351,7 @@ async function cmdWorkflowDegrade(runtime, runId, stageId, options) {
|
|
|
47090
47351
|
}
|
|
47091
47352
|
}
|
|
47092
47353
|
async function cmdWorkflowInspect(runtime, action, runId) {
|
|
47093
|
-
const dataPath = resolve22(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
47354
|
+
const dataPath = resolve22(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join37(runtime.dirs.state, "kxm.db"));
|
|
47094
47355
|
if (action === "get" && !runId) {
|
|
47095
47356
|
runtime.io.stderr(`Usage: ${CLI_NAME} workflow get <runId>
|
|
47096
47357
|
`);
|
|
@@ -47263,10 +47524,10 @@ async function cmdRetrospectiveExport(runtime, runId, options) {
|
|
|
47263
47524
|
let snapshot;
|
|
47264
47525
|
try {
|
|
47265
47526
|
if (snapshotPath) {
|
|
47266
|
-
if (!
|
|
47267
|
-
snapshot = JSON.parse(
|
|
47527
|
+
if (!existsSync31(snapshotPath)) throw new Error("snapshot_missing");
|
|
47528
|
+
snapshot = JSON.parse(readFileSync29(snapshotPath, "utf8"));
|
|
47268
47529
|
} else {
|
|
47269
|
-
const dataPath = resolve22(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
47530
|
+
const dataPath = resolve22(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join37(runtime.dirs.state, "kxm.db"));
|
|
47270
47531
|
const local = localWorkflowSnapshot(dataPath, runId);
|
|
47271
47532
|
if (!local.runs[0]) throw new Error("workflow_not_found");
|
|
47272
47533
|
snapshot = { run: local.runs[0], journal: local.journal };
|
|
@@ -47278,7 +47539,7 @@ async function cmdRetrospectiveExport(runtime, runId, options) {
|
|
|
47278
47539
|
return 1;
|
|
47279
47540
|
}
|
|
47280
47541
|
const doc = buildRetrospective(snapshot.run, snapshot.journal);
|
|
47281
|
-
const outDir = resolve22(runtime.cwd, String(options.outDir ||
|
|
47542
|
+
const outDir = resolve22(runtime.cwd, String(options.outDir || join37(runtime.dirs.assets, "retrospectives")));
|
|
47282
47543
|
const assetsRoot = resolve22(runtime.dirs.assets);
|
|
47283
47544
|
const assetsPrefix = `${assetsRoot}${process.platform === "win32" ? "\\" : "/"}`;
|
|
47284
47545
|
if (outDir !== assetsRoot && !outDir.startsWith(assetsPrefix)) {
|
|
@@ -47734,6 +47995,11 @@ function createProgram(ctx, result) {
|
|
|
47734
47995
|
addGlobalOptions(routing.command("benchmark").description("Dedicated offline benchmark for side-by-side model comparison (Decision Q12)")).option("--task <fixture>", "Task prompt or fixture path for benchmark comparison").option("--arms <models>", "Comma-separated model routes to benchmark (e.g. grok/grok-4.6,claude/fable)").option("--runs <count>", "Benchmark runs per arm", "1").action(async function routingBenchmarkAction(options) {
|
|
47735
47996
|
result.code = await cmdRoutingBenchmark(runtimeFrom(ctx, this), options);
|
|
47736
47997
|
});
|
|
47998
|
+
addGlobalOptions(
|
|
47999
|
+
program2.command("explain").description("Pre-flight context footprint and token cost inspection for workflow modes").option("--mode <name>", "Major mode (coder, planner, auditor, browser)", "coder").option("--domains <list>", "Comma-separated domain modules (git, k8s, database, browser)").option("--model <id>", "Target model identifier (e.g. grok/grok-4.6, claude/fable)")
|
|
48000
|
+
).action(async function explainAction(options) {
|
|
48001
|
+
result.code = await cmdExplain(runtimeFrom(ctx, this), options);
|
|
48002
|
+
});
|
|
47737
48003
|
const hub = addGlobalOptions(program2.command("hub").description("Start, inspect, and stop the local KXM hub"));
|
|
47738
48004
|
hub.helpCommand("help", "Show hub help");
|
|
47739
48005
|
addGlobalOptions(hub.command("view").description("Check hub /health and /ready")).action(bind(cmdStatus));
|