@kontextmind/kxm 0.7.165 → 0.7.166
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +16 -0
- package/docs/concepts/trust-model.md +1 -1
- package/docs/glossary.md +2 -2
- package/docs/operations/troubleshooting.md +2 -2
- package/docs/operations.md +62 -8
- package/docs/reference/cli-reference.md +11 -11
- package/docs/reference/config-reference.md +36 -11
- package/docs/reference/configuration.md +2 -2
- package/docs/reference/tools.md +1 -1
- package/docs/start/quickstart-claude-code.md +2 -2
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/README.md +3 -3
- package/plugins/kxm/dist/claude-hook.js +417 -66
- package/plugins/kxm/dist/cli.js +1399 -900
- package/plugins/kxm/dist/extension.js +399 -64
- package/plugins/kxm/dist/mcp-server.js +622 -135
- package/plugins/kxm/dist/runtime-supervisor.js +668 -166
- package/plugins/kxm/dist/runtime.js +713 -211
- package/plugins/kxm/dist/server.js +466 -58
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +15 -7
- package/plugins/kxm/src/cli/hub.ts +80 -21
- package/plugins/kxm/src/cli/types.ts +8 -1
- package/plugins/kxm/src/cli.ts +41 -7
- package/plugins/kxm/src/config.ts +246 -3
- package/plugins/kxm/src/extension.ts +8 -7
- package/plugins/kxm/src/hub-autostart.ts +20 -0
- package/plugins/kxm/src/hub-env.ts +83 -31
- package/plugins/kxm/src/hub-identity.ts +337 -0
- package/plugins/kxm/src/mcp-server.ts +17 -15
- package/plugins/kxm/src/project-name.ts +6 -47
- package/plugins/kxm/src/server.ts +22 -4
- package/scripts/kxm-hub.mjs +5 -0
|
@@ -164,10 +164,10 @@ var require_code = __commonJS({
|
|
|
164
164
|
function interpolate(x) {
|
|
165
165
|
return typeof x == "number" || typeof x == "boolean" || x === null ? x : safeStringify(Array.isArray(x) ? x.join(",") : x);
|
|
166
166
|
}
|
|
167
|
-
function
|
|
167
|
+
function stringify4(x) {
|
|
168
168
|
return new _Code(safeStringify(x));
|
|
169
169
|
}
|
|
170
|
-
exports.stringify =
|
|
170
|
+
exports.stringify = stringify4;
|
|
171
171
|
function safeStringify(x) {
|
|
172
172
|
return JSON.stringify(x).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
173
173
|
}
|
|
@@ -2987,7 +2987,7 @@ var require_compile = __commonJS({
|
|
|
2987
2987
|
const schOrFunc = root.refs[ref];
|
|
2988
2988
|
if (schOrFunc)
|
|
2989
2989
|
return schOrFunc;
|
|
2990
|
-
let _sch =
|
|
2990
|
+
let _sch = resolve9.call(this, root, ref);
|
|
2991
2991
|
if (_sch === void 0) {
|
|
2992
2992
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2993
2993
|
const { schemaId } = this.opts;
|
|
@@ -3014,7 +3014,7 @@ var require_compile = __commonJS({
|
|
|
3014
3014
|
function sameSchemaEnv(s1, s2) {
|
|
3015
3015
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3016
3016
|
}
|
|
3017
|
-
function
|
|
3017
|
+
function resolve9(root, ref) {
|
|
3018
3018
|
let sch;
|
|
3019
3019
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3020
3020
|
ref = sch;
|
|
@@ -3835,11 +3835,11 @@ var require_fast_uri = __commonJS({
|
|
|
3835
3835
|
normalizeString(uri, options);
|
|
3836
3836
|
} else if (typeof uri === "object") {
|
|
3837
3837
|
uri = /** @type {T} */
|
|
3838
|
-
|
|
3838
|
+
parse4(serialize(uri, options), options);
|
|
3839
3839
|
}
|
|
3840
3840
|
return uri;
|
|
3841
3841
|
}
|
|
3842
|
-
function
|
|
3842
|
+
function resolve9(baseURI, relativeURI, options) {
|
|
3843
3843
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3844
3844
|
const {
|
|
3845
3845
|
parsed: baseParsed,
|
|
@@ -3875,8 +3875,8 @@ var require_fast_uri = __commonJS({
|
|
|
3875
3875
|
function resolveComponent(base, relative3, options, skipNormalization) {
|
|
3876
3876
|
const target = {};
|
|
3877
3877
|
if (!skipNormalization) {
|
|
3878
|
-
base =
|
|
3879
|
-
relative3 =
|
|
3878
|
+
base = parse4(serialize(base, options), options);
|
|
3879
|
+
relative3 = parse4(serialize(relative3, options), options);
|
|
3880
3880
|
}
|
|
3881
3881
|
options = options || {};
|
|
3882
3882
|
if (!options.tolerant && relative3.scheme) {
|
|
@@ -4168,7 +4168,7 @@ var require_fast_uri = __commonJS({
|
|
|
4168
4168
|
}
|
|
4169
4169
|
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
4170
4170
|
}
|
|
4171
|
-
function
|
|
4171
|
+
function parse4(uri, opts) {
|
|
4172
4172
|
return parseWithStatus(uri, opts).parsed;
|
|
4173
4173
|
}
|
|
4174
4174
|
function normalizeString(uri, opts) {
|
|
@@ -4201,11 +4201,11 @@ var require_fast_uri = __commonJS({
|
|
|
4201
4201
|
var fastUri = {
|
|
4202
4202
|
SCHEMES,
|
|
4203
4203
|
normalize,
|
|
4204
|
-
resolve:
|
|
4204
|
+
resolve: resolve9,
|
|
4205
4205
|
resolveComponent,
|
|
4206
4206
|
equal,
|
|
4207
4207
|
serialize,
|
|
4208
|
-
parse:
|
|
4208
|
+
parse: parse4
|
|
4209
4209
|
};
|
|
4210
4210
|
module.exports = fastUri;
|
|
4211
4211
|
module.exports.default = fastUri;
|
|
@@ -8918,7 +8918,7 @@ var require_stringify = __commonJS({
|
|
|
8918
8918
|
props.push(doc.directives.tagString(tag));
|
|
8919
8919
|
return props.join(" ");
|
|
8920
8920
|
}
|
|
8921
|
-
function
|
|
8921
|
+
function stringify4(item, ctx, onComment, onChompKeep) {
|
|
8922
8922
|
if (identity.isPair(item))
|
|
8923
8923
|
return item.toString(ctx, onComment, onChompKeep);
|
|
8924
8924
|
if (identity.isAlias(item)) {
|
|
@@ -8947,7 +8947,7 @@ var require_stringify = __commonJS({
|
|
|
8947
8947
|
${ctx.indent}${str}`;
|
|
8948
8948
|
}
|
|
8949
8949
|
exports.createStringifyContext = createStringifyContext;
|
|
8950
|
-
exports.stringify =
|
|
8950
|
+
exports.stringify = stringify4;
|
|
8951
8951
|
}
|
|
8952
8952
|
});
|
|
8953
8953
|
|
|
@@ -8957,7 +8957,7 @@ var require_stringifyPair = __commonJS({
|
|
|
8957
8957
|
"use strict";
|
|
8958
8958
|
var identity = require_identity();
|
|
8959
8959
|
var Scalar = require_Scalar();
|
|
8960
|
-
var
|
|
8960
|
+
var stringify4 = require_stringify();
|
|
8961
8961
|
var stringifyComment = require_stringifyComment();
|
|
8962
8962
|
function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
|
8963
8963
|
const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
|
|
@@ -8979,7 +8979,7 @@ var require_stringifyPair = __commonJS({
|
|
|
8979
8979
|
});
|
|
8980
8980
|
let keyCommentDone = false;
|
|
8981
8981
|
let chompKeep = false;
|
|
8982
|
-
let str =
|
|
8982
|
+
let str = stringify4.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
|
|
8983
8983
|
if (!explicitKey && !ctx.inFlow && str.length > 1024) {
|
|
8984
8984
|
if (simpleKeys)
|
|
8985
8985
|
throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
|
|
@@ -9031,7 +9031,7 @@ ${indent}:`;
|
|
|
9031
9031
|
ctx.indent = ctx.indent.substring(2);
|
|
9032
9032
|
}
|
|
9033
9033
|
let valueCommentDone = false;
|
|
9034
|
-
const valueStr =
|
|
9034
|
+
const valueStr = stringify4.stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
|
|
9035
9035
|
let ws = " ";
|
|
9036
9036
|
if (keyComment || vsb || vcb) {
|
|
9037
9037
|
ws = vsb ? "\n" : "";
|
|
@@ -9172,7 +9172,7 @@ var require_addPairToJSMap = __commonJS({
|
|
|
9172
9172
|
"use strict";
|
|
9173
9173
|
var log = require_log();
|
|
9174
9174
|
var merge = require_merge();
|
|
9175
|
-
var
|
|
9175
|
+
var stringify4 = require_stringify();
|
|
9176
9176
|
var identity = require_identity();
|
|
9177
9177
|
var toJS = require_toJS();
|
|
9178
9178
|
function addPairToJSMap(ctx, map, { key, value }) {
|
|
@@ -9208,7 +9208,7 @@ var require_addPairToJSMap = __commonJS({
|
|
|
9208
9208
|
if (typeof jsKey !== "object")
|
|
9209
9209
|
return String(jsKey);
|
|
9210
9210
|
if (identity.isNode(key) && ctx?.doc) {
|
|
9211
|
-
const strCtx =
|
|
9211
|
+
const strCtx = stringify4.createStringifyContext(ctx.doc, {});
|
|
9212
9212
|
strCtx.anchors = /* @__PURE__ */ new Set();
|
|
9213
9213
|
for (const node of ctx.anchors.keys())
|
|
9214
9214
|
strCtx.anchors.add(node.anchor);
|
|
@@ -9275,12 +9275,12 @@ var require_stringifyCollection = __commonJS({
|
|
|
9275
9275
|
"node_modules/yaml/dist/stringify/stringifyCollection.js"(exports) {
|
|
9276
9276
|
"use strict";
|
|
9277
9277
|
var identity = require_identity();
|
|
9278
|
-
var
|
|
9278
|
+
var stringify4 = require_stringify();
|
|
9279
9279
|
var stringifyComment = require_stringifyComment();
|
|
9280
9280
|
function stringifyCollection(collection, ctx, options) {
|
|
9281
9281
|
const flow = ctx.inFlow ?? collection.flow;
|
|
9282
|
-
const
|
|
9283
|
-
return
|
|
9282
|
+
const stringify5 = flow ? stringifyFlowCollection : stringifyBlockCollection;
|
|
9283
|
+
return stringify5(collection, ctx, options);
|
|
9284
9284
|
}
|
|
9285
9285
|
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
|
9286
9286
|
const { indent, options: { commentString } } = ctx;
|
|
@@ -9305,7 +9305,7 @@ var require_stringifyCollection = __commonJS({
|
|
|
9305
9305
|
}
|
|
9306
9306
|
}
|
|
9307
9307
|
chompKeep = false;
|
|
9308
|
-
let str2 =
|
|
9308
|
+
let str2 = stringify4.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
|
|
9309
9309
|
if (comment2)
|
|
9310
9310
|
str2 += stringifyComment.lineComment(str2, itemIndent, commentString(comment2));
|
|
9311
9311
|
if (chompKeep && comment2)
|
|
@@ -9372,7 +9372,7 @@ ${indent}${line}` : "\n";
|
|
|
9372
9372
|
}
|
|
9373
9373
|
if (comment)
|
|
9374
9374
|
reqNewline = true;
|
|
9375
|
-
let str =
|
|
9375
|
+
let str = stringify4.stringify(item, itemCtx, () => comment = null);
|
|
9376
9376
|
reqNewline || (reqNewline = lines.length > linesAtValue || str.includes("\n"));
|
|
9377
9377
|
if (i < items.length - 1) {
|
|
9378
9378
|
str += ",";
|
|
@@ -10733,7 +10733,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
10733
10733
|
"node_modules/yaml/dist/stringify/stringifyDocument.js"(exports) {
|
|
10734
10734
|
"use strict";
|
|
10735
10735
|
var identity = require_identity();
|
|
10736
|
-
var
|
|
10736
|
+
var stringify4 = require_stringify();
|
|
10737
10737
|
var stringifyComment = require_stringifyComment();
|
|
10738
10738
|
function stringifyDocument(doc, options) {
|
|
10739
10739
|
const lines = [];
|
|
@@ -10748,7 +10748,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
10748
10748
|
}
|
|
10749
10749
|
if (hasDirectives)
|
|
10750
10750
|
lines.push("---");
|
|
10751
|
-
const ctx =
|
|
10751
|
+
const ctx = stringify4.createStringifyContext(doc, options);
|
|
10752
10752
|
const { commentString } = ctx.options;
|
|
10753
10753
|
if (doc.commentBefore) {
|
|
10754
10754
|
if (lines.length !== 1)
|
|
@@ -10770,7 +10770,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
10770
10770
|
contentComment = doc.contents.comment;
|
|
10771
10771
|
}
|
|
10772
10772
|
const onChompKeep = contentComment ? void 0 : () => chompKeep = true;
|
|
10773
|
-
let body =
|
|
10773
|
+
let body = stringify4.stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
|
|
10774
10774
|
if (contentComment)
|
|
10775
10775
|
body += stringifyComment.lineComment(body, "", commentString(contentComment));
|
|
10776
10776
|
if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") {
|
|
@@ -10778,7 +10778,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
10778
10778
|
} else
|
|
10779
10779
|
lines.push(body);
|
|
10780
10780
|
} else {
|
|
10781
|
-
lines.push(
|
|
10781
|
+
lines.push(stringify4.stringify(doc.contents, ctx));
|
|
10782
10782
|
}
|
|
10783
10783
|
if (doc.directives?.docEnd) {
|
|
10784
10784
|
if (doc.comment) {
|
|
@@ -12914,7 +12914,7 @@ var require_cst_scalar = __commonJS({
|
|
|
12914
12914
|
var require_cst_stringify = __commonJS({
|
|
12915
12915
|
"node_modules/yaml/dist/parse/cst-stringify.js"(exports) {
|
|
12916
12916
|
"use strict";
|
|
12917
|
-
var
|
|
12917
|
+
var stringify4 = (cst) => "type" in cst ? stringifyToken(cst) : stringifyItem(cst);
|
|
12918
12918
|
function stringifyToken(token) {
|
|
12919
12919
|
switch (token.type) {
|
|
12920
12920
|
case "block-scalar": {
|
|
@@ -12967,7 +12967,7 @@ var require_cst_stringify = __commonJS({
|
|
|
12967
12967
|
res += stringifyToken(value);
|
|
12968
12968
|
return res;
|
|
12969
12969
|
}
|
|
12970
|
-
exports.stringify =
|
|
12970
|
+
exports.stringify = stringify4;
|
|
12971
12971
|
}
|
|
12972
12972
|
});
|
|
12973
12973
|
|
|
@@ -14678,7 +14678,7 @@ var require_public_api = __commonJS({
|
|
|
14678
14678
|
}
|
|
14679
14679
|
return doc;
|
|
14680
14680
|
}
|
|
14681
|
-
function
|
|
14681
|
+
function parse4(src, reviver, options) {
|
|
14682
14682
|
let _reviver = void 0;
|
|
14683
14683
|
if (typeof reviver === "function") {
|
|
14684
14684
|
_reviver = reviver;
|
|
@@ -14697,7 +14697,7 @@ var require_public_api = __commonJS({
|
|
|
14697
14697
|
}
|
|
14698
14698
|
return doc.toJS(Object.assign({ reviver: _reviver }, options));
|
|
14699
14699
|
}
|
|
14700
|
-
function
|
|
14700
|
+
function stringify4(value, replacer, options) {
|
|
14701
14701
|
let _replacer = null;
|
|
14702
14702
|
if (typeof replacer === "function" || Array.isArray(replacer)) {
|
|
14703
14703
|
_replacer = replacer;
|
|
@@ -14719,10 +14719,10 @@ var require_public_api = __commonJS({
|
|
|
14719
14719
|
return value.toString(options);
|
|
14720
14720
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
14721
14721
|
}
|
|
14722
|
-
exports.parse =
|
|
14722
|
+
exports.parse = parse4;
|
|
14723
14723
|
exports.parseAllDocuments = parseAllDocuments;
|
|
14724
14724
|
exports.parseDocument = parseDocument2;
|
|
14725
|
-
exports.stringify =
|
|
14725
|
+
exports.stringify = stringify4;
|
|
14726
14726
|
}
|
|
14727
14727
|
});
|
|
14728
14728
|
|
|
@@ -23105,11 +23105,11 @@ data: ${JSON.stringify({ agent: publicAgent(current, staleAfterMs) })}
|
|
|
23105
23105
|
state: { agents, messages, workflowRuns, journal, persistent: store.persistent },
|
|
23106
23106
|
async start() {
|
|
23107
23107
|
if (closed) throw new Error("hub is closed");
|
|
23108
|
-
await new Promise((
|
|
23108
|
+
await new Promise((resolve9, reject) => {
|
|
23109
23109
|
server.once("error", reject);
|
|
23110
23110
|
server.listen(port2, host2, () => {
|
|
23111
23111
|
server.off("error", reject);
|
|
23112
|
-
|
|
23112
|
+
resolve9();
|
|
23113
23113
|
});
|
|
23114
23114
|
});
|
|
23115
23115
|
cleanupTimer = setInterval(() => {
|
|
@@ -23139,7 +23139,7 @@ data: ${JSON.stringify({ agent: publicAgent(current, staleAfterMs) })}
|
|
|
23139
23139
|
if (closed) return;
|
|
23140
23140
|
closed = true;
|
|
23141
23141
|
if (cleanupTimer) clearInterval(cleanupTimer);
|
|
23142
|
-
const serverClosed = server.listening ? new Promise((
|
|
23142
|
+
const serverClosed = server.listening ? new Promise((resolve9, reject) => server.close((error) => error ? reject(error) : resolve9())) : Promise.resolve();
|
|
23143
23143
|
const forceClose = setTimeout(() => server.closeAllConnections(), shutdownGraceMs);
|
|
23144
23144
|
forceClose.unref();
|
|
23145
23145
|
for (const clients of streams.values()) {
|
|
@@ -23166,12 +23166,403 @@ data: ${JSON.stringify({ agent: publicAgent(current, staleAfterMs) })}
|
|
|
23166
23166
|
}
|
|
23167
23167
|
|
|
23168
23168
|
// plugins/kxm/src/server.ts
|
|
23169
|
-
import { mkdirSync as
|
|
23170
|
-
import { dirname as
|
|
23169
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync6 } from "node:fs";
|
|
23170
|
+
import { dirname as dirname9, join as join8, resolve as resolve8 } from "node:path";
|
|
23171
|
+
|
|
23172
|
+
// plugins/kxm/src/hub-identity.ts
|
|
23173
|
+
import { spawnSync } from "node:child_process";
|
|
23174
|
+
var import_yaml7 = __toESM(require_dist(), 1);
|
|
23175
|
+
|
|
23176
|
+
// plugins/kxm/src/config.ts
|
|
23177
|
+
var import_yaml6 = __toESM(require_dist(), 1);
|
|
23178
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
23179
|
+
import { tmpdir, homedir } from "node:os";
|
|
23180
|
+
import { dirname as dirname7, join as join7, resolve as resolve7 } from "node:path";
|
|
23181
|
+
var KXM_CONFIG_SCHEMA = "kxm.config.v1";
|
|
23182
|
+
var KxmHubConfigError = class extends Error {
|
|
23183
|
+
code = "hub_config_invalid";
|
|
23184
|
+
constructor(message) {
|
|
23185
|
+
super(message);
|
|
23186
|
+
this.name = "KxmHubConfigError";
|
|
23187
|
+
}
|
|
23188
|
+
};
|
|
23189
|
+
var HUB_ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
|
|
23190
|
+
var HUB_OP_REF = /^op:\/\/\S+\/\S+\/\S+$/;
|
|
23191
|
+
var LITERAL_SECRET_KEY = /^(token|secret|password|authToken|auth_token|apiKey|api_key|api_token|bearer|credential|access_token)$/i;
|
|
23192
|
+
function isHubKeyEnvName(value) {
|
|
23193
|
+
return HUB_ENV_NAME.test(value);
|
|
23194
|
+
}
|
|
23195
|
+
function isHubOpReference(value) {
|
|
23196
|
+
return HUB_OP_REF.test(value);
|
|
23197
|
+
}
|
|
23198
|
+
var IMPROVEMENT_PROMOTION_POLICIES = ["manual_pr", "critic_quorum", "auto_threshold"];
|
|
23199
|
+
var DEFAULT_KXM_CONFIG = {
|
|
23200
|
+
schema: KXM_CONFIG_SCHEMA,
|
|
23201
|
+
user: {
|
|
23202
|
+
theme: "dark",
|
|
23203
|
+
preferredCritics: ["reviewer-arch", "reviewer-cli"],
|
|
23204
|
+
tokenBudget: 16e3
|
|
23205
|
+
},
|
|
23206
|
+
defaults: {
|
|
23207
|
+
workflow: "software-engineering/feature-implementation",
|
|
23208
|
+
harness: "pi"
|
|
23209
|
+
},
|
|
23210
|
+
dash: {
|
|
23211
|
+
defaultScreen: "agents",
|
|
23212
|
+
refreshIntervalMs: 1e3,
|
|
23213
|
+
autoOpen: false
|
|
23214
|
+
},
|
|
23215
|
+
sync: {
|
|
23216
|
+
defaultTracker: "none"
|
|
23217
|
+
},
|
|
23218
|
+
hub: {
|
|
23219
|
+
autoStart: "background"
|
|
23220
|
+
},
|
|
23221
|
+
improvement: {
|
|
23222
|
+
promotionPolicy: "manual_pr",
|
|
23223
|
+
telemetryHalfLifeDays: 14,
|
|
23224
|
+
autoThreshold: {
|
|
23225
|
+
minRuns: 10,
|
|
23226
|
+
minPassRate: 0.95,
|
|
23227
|
+
minCostSavings: 0.5
|
|
23228
|
+
}
|
|
23229
|
+
},
|
|
23230
|
+
routing: {
|
|
23231
|
+
shadowExecution: {
|
|
23232
|
+
enabled: false,
|
|
23233
|
+
sampleRate: 0.05,
|
|
23234
|
+
candidateModels: []
|
|
23235
|
+
},
|
|
23236
|
+
circuitBreaker: {
|
|
23237
|
+
mode: "soft_demotion",
|
|
23238
|
+
failureThreshold: 3,
|
|
23239
|
+
windowSeconds: 3600,
|
|
23240
|
+
cooldownSeconds: 1800,
|
|
23241
|
+
penaltyMultiplier: 5
|
|
23242
|
+
}
|
|
23243
|
+
},
|
|
23244
|
+
telemetry: {
|
|
23245
|
+
federated: true,
|
|
23246
|
+
anonymize: true
|
|
23247
|
+
}
|
|
23248
|
+
};
|
|
23249
|
+
function userConfigDirectory(overrideDir) {
|
|
23250
|
+
if (overrideDir) return resolve7(overrideDir);
|
|
23251
|
+
return resolve7(process.env.KXM_USER_CONFIG_DIR?.trim() || join7(homedir(), ".config", "kxm"));
|
|
23252
|
+
}
|
|
23253
|
+
function repoConfigDirectory(repoRoot) {
|
|
23254
|
+
return resolve7(repoRoot, ".kxm");
|
|
23255
|
+
}
|
|
23256
|
+
function deepMerge(target, source) {
|
|
23257
|
+
const result = { ...target };
|
|
23258
|
+
for (const [key, val] of Object.entries(source)) {
|
|
23259
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
23260
|
+
const existing = result[key] && typeof result[key] === "object" && !Array.isArray(result[key]) ? result[key] : {};
|
|
23261
|
+
result[key] = deepMerge(existing, val);
|
|
23262
|
+
} else if (val !== void 0) {
|
|
23263
|
+
result[key] = val;
|
|
23264
|
+
}
|
|
23265
|
+
}
|
|
23266
|
+
return result;
|
|
23267
|
+
}
|
|
23268
|
+
function literalSecretMessage(path) {
|
|
23269
|
+
return `refusing literal hub token at ${path}: store an op:// reference (key.op) or an environment variable name (key.env), never the token`;
|
|
23270
|
+
}
|
|
23271
|
+
function rejectLiteralHubSecrets(value, path) {
|
|
23272
|
+
if (Array.isArray(value)) {
|
|
23273
|
+
value.forEach((item, index) => rejectLiteralHubSecrets(item, `${path}[${index}]`));
|
|
23274
|
+
return;
|
|
23275
|
+
}
|
|
23276
|
+
if (!value || typeof value !== "object") return;
|
|
23277
|
+
for (const [key, child] of Object.entries(value)) {
|
|
23278
|
+
const childPath = `${path}.${key}`;
|
|
23279
|
+
if (typeof child === "string" && (key === "key" || LITERAL_SECRET_KEY.test(key))) {
|
|
23280
|
+
throw new KxmHubConfigError(literalSecretMessage(childPath));
|
|
23281
|
+
}
|
|
23282
|
+
if (child && typeof child === "object") rejectLiteralHubSecrets(child, childPath);
|
|
23283
|
+
}
|
|
23284
|
+
}
|
|
23285
|
+
function parseKeyRef(raw, path) {
|
|
23286
|
+
if (raw === void 0) return void 0;
|
|
23287
|
+
if (typeof raw === "string") throw new KxmHubConfigError(literalSecretMessage(path));
|
|
23288
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
23289
|
+
throw new KxmHubConfigError(`${path} must be a key reference with op and/or env, never a token`);
|
|
23290
|
+
}
|
|
23291
|
+
const row = raw;
|
|
23292
|
+
for (const key of Object.keys(row)) {
|
|
23293
|
+
if (key !== "op" && key !== "env") {
|
|
23294
|
+
throw new KxmHubConfigError(literalSecretMessage(`${path}.${key}`));
|
|
23295
|
+
}
|
|
23296
|
+
}
|
|
23297
|
+
const ref = {};
|
|
23298
|
+
if (row.op !== void 0) {
|
|
23299
|
+
if (typeof row.op !== "string" || !isHubOpReference(row.op)) {
|
|
23300
|
+
throw new KxmHubConfigError(`${path}.op must be an op://vault/item/field reference, not a token`);
|
|
23301
|
+
}
|
|
23302
|
+
ref.op = row.op;
|
|
23303
|
+
}
|
|
23304
|
+
if (row.env !== void 0) {
|
|
23305
|
+
if (typeof row.env !== "string" || !isHubKeyEnvName(row.env)) {
|
|
23306
|
+
throw new KxmHubConfigError(`${path}.env must be an environment variable name, not a token`);
|
|
23307
|
+
}
|
|
23308
|
+
ref.env = row.env;
|
|
23309
|
+
}
|
|
23310
|
+
if (!ref.op && !ref.env) throw new KxmHubConfigError(`${path} needs key.op, key.env, or both`);
|
|
23311
|
+
return ref;
|
|
23312
|
+
}
|
|
23313
|
+
function parseEndpoint(raw, path) {
|
|
23314
|
+
if (raw === void 0) return void 0;
|
|
23315
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
23316
|
+
throw new KxmHubConfigError(`${path} must be an object with url, project, and key`);
|
|
23317
|
+
}
|
|
23318
|
+
const row = raw;
|
|
23319
|
+
const endpoint = {};
|
|
23320
|
+
if (row.url !== void 0) {
|
|
23321
|
+
if (typeof row.url !== "string" || !isHubUrl(row.url)) {
|
|
23322
|
+
throw new KxmHubConfigError(`${path}.url must be an http or https URL without credentials, query, or fragment`);
|
|
23323
|
+
}
|
|
23324
|
+
endpoint.url = row.url.replace(/\/$/, "");
|
|
23325
|
+
}
|
|
23326
|
+
if (row.project !== void 0) {
|
|
23327
|
+
if (typeof row.project !== "string" || !isHubProjectId(row.project)) {
|
|
23328
|
+
throw new KxmHubConfigError(`${path}.project must be a single-line project id, not a token`);
|
|
23329
|
+
}
|
|
23330
|
+
endpoint.project = row.project.trim();
|
|
23331
|
+
}
|
|
23332
|
+
const key = parseKeyRef(row.key, `${path}.key`);
|
|
23333
|
+
if (key) endpoint.key = key;
|
|
23334
|
+
for (const name of Object.keys(row)) {
|
|
23335
|
+
if (name !== "url" && name !== "project" && name !== "key") {
|
|
23336
|
+
if (typeof row[name] === "string") throw new KxmHubConfigError(literalSecretMessage(`${path}.${name}`));
|
|
23337
|
+
throw new KxmHubConfigError(`${path}.${name} is not a hub endpoint field`);
|
|
23338
|
+
}
|
|
23339
|
+
}
|
|
23340
|
+
return endpoint;
|
|
23341
|
+
}
|
|
23342
|
+
function isHubUrl(raw) {
|
|
23343
|
+
try {
|
|
23344
|
+
const parsed = new URL(raw);
|
|
23345
|
+
return (parsed.protocol === "http:" || parsed.protocol === "https:") && parsed.username === "" && parsed.password === "" && parsed.search === "" && parsed.hash === "" && !raw.includes("?") && !raw.includes("#");
|
|
23346
|
+
} catch {
|
|
23347
|
+
return false;
|
|
23348
|
+
}
|
|
23349
|
+
}
|
|
23350
|
+
function isHubProjectId(raw) {
|
|
23351
|
+
const value = raw.trim();
|
|
23352
|
+
return value.length > 0 && value.length <= 200 && !/[\s\r\n]/.test(value);
|
|
23353
|
+
}
|
|
23354
|
+
function parseProjectMap(raw) {
|
|
23355
|
+
if (raw === void 0) return void 0;
|
|
23356
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
23357
|
+
throw new KxmHubConfigError("hub.projects must be a map of project id to key reference, never a token");
|
|
23358
|
+
}
|
|
23359
|
+
const projects = {};
|
|
23360
|
+
for (const [project, value] of Object.entries(raw)) {
|
|
23361
|
+
if (!isHubProjectId(project)) {
|
|
23362
|
+
throw new KxmHubConfigError(`hub.projects key ${JSON.stringify(project)} must be a project id, not a token`);
|
|
23363
|
+
}
|
|
23364
|
+
const ref = parseKeyRef(value, `hub.projects.${project}`);
|
|
23365
|
+
if (!ref) throw new KxmHubConfigError(`hub.projects.${project} needs an op:// reference or an environment variable name`);
|
|
23366
|
+
projects[project.trim()] = ref;
|
|
23367
|
+
}
|
|
23368
|
+
return projects;
|
|
23369
|
+
}
|
|
23370
|
+
function normalizeHubConfig(raw) {
|
|
23371
|
+
const autoStart = raw?.autoStart;
|
|
23372
|
+
const hub2 = {
|
|
23373
|
+
autoStart: autoStart === "off" || autoStart === "background" ? autoStart : DEFAULT_KXM_CONFIG.hub.autoStart
|
|
23374
|
+
};
|
|
23375
|
+
if (raw === void 0) return hub2;
|
|
23376
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
23377
|
+
throw new KxmHubConfigError("hub must be an object");
|
|
23378
|
+
}
|
|
23379
|
+
rejectLiteralHubSecrets(raw, "hub");
|
|
23380
|
+
const row = raw;
|
|
23381
|
+
if (row.mode !== void 0) {
|
|
23382
|
+
if (row.mode !== "local" && row.mode !== "cloud") {
|
|
23383
|
+
throw new KxmHubConfigError("hub.mode must be local or cloud");
|
|
23384
|
+
}
|
|
23385
|
+
hub2.mode = row.mode;
|
|
23386
|
+
}
|
|
23387
|
+
const local = parseEndpoint(row.local, "hub.local");
|
|
23388
|
+
const cloud = parseEndpoint(row.cloud, "hub.cloud");
|
|
23389
|
+
const projects = parseProjectMap(row.projects);
|
|
23390
|
+
if (local) hub2.local = local;
|
|
23391
|
+
if (cloud) hub2.cloud = cloud;
|
|
23392
|
+
if (projects && Object.keys(projects).length > 0) hub2.projects = projects;
|
|
23393
|
+
return hub2;
|
|
23394
|
+
}
|
|
23395
|
+
function findConfigRoot(start) {
|
|
23396
|
+
let dir = resolve7(start);
|
|
23397
|
+
for (; ; ) {
|
|
23398
|
+
if (existsSync7(join7(dir, ".kxm", "project.yaml")) || existsSync7(join7(dir, ".kxm", "config.yaml"))) return dir;
|
|
23399
|
+
const parent = dirname7(dir);
|
|
23400
|
+
if (parent === dir) return resolve7(start);
|
|
23401
|
+
dir = parent;
|
|
23402
|
+
}
|
|
23403
|
+
}
|
|
23404
|
+
function userConfigDirForEnv(env) {
|
|
23405
|
+
const explicit = env.KXM_USER_CONFIG_DIR?.trim();
|
|
23406
|
+
if (explicit) return explicit;
|
|
23407
|
+
if (env === process.env) return void 0;
|
|
23408
|
+
return join7(tmpdir(), "kxm-no-user-config");
|
|
23409
|
+
}
|
|
23410
|
+
function loadHubSettings(start, env = process.env) {
|
|
23411
|
+
const userConfigDir = userConfigDirForEnv(env);
|
|
23412
|
+
return loadKxmConfig(findConfigRoot(start), userConfigDir === void 0 ? {} : { userConfigDir }).hub;
|
|
23413
|
+
}
|
|
23414
|
+
function recordOf(raw) {
|
|
23415
|
+
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
23416
|
+
}
|
|
23417
|
+
function finiteNumber(value) {
|
|
23418
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
23419
|
+
}
|
|
23420
|
+
function normalizeImprovementConfig(raw) {
|
|
23421
|
+
const value = recordOf(raw);
|
|
23422
|
+
const threshold = recordOf(value.autoThreshold);
|
|
23423
|
+
const policy = value.promotionPolicy;
|
|
23424
|
+
const halfLife = finiteNumber(value.telemetryHalfLifeDays);
|
|
23425
|
+
const minRuns = finiteNumber(threshold.minRuns);
|
|
23426
|
+
const minPassRate = finiteNumber(threshold.minPassRate);
|
|
23427
|
+
const minCostSavings = finiteNumber(threshold.minCostSavings);
|
|
23428
|
+
return {
|
|
23429
|
+
promotionPolicy: IMPROVEMENT_PROMOTION_POLICIES.includes(policy) ? policy : "manual_pr",
|
|
23430
|
+
telemetryHalfLifeDays: halfLife !== void 0 && halfLife > 0 && halfLife <= 3650 ? halfLife : 14,
|
|
23431
|
+
autoThreshold: {
|
|
23432
|
+
minRuns: minRuns !== void 0 && Number.isInteger(minRuns) && minRuns >= 1 && minRuns <= 1e6 ? minRuns : 10,
|
|
23433
|
+
minPassRate: minPassRate !== void 0 && minPassRate >= 0 && minPassRate <= 1 ? minPassRate : 0.95,
|
|
23434
|
+
minCostSavings: minCostSavings !== void 0 && minCostSavings >= 0 ? minCostSavings : 0.5
|
|
23435
|
+
}
|
|
23436
|
+
};
|
|
23437
|
+
}
|
|
23438
|
+
function loadKxmConfig(repoRoot = process.cwd(), options = {}) {
|
|
23439
|
+
const userDir = userConfigDirectory(options.userConfigDir);
|
|
23440
|
+
const userConfigFile = join7(userDir, "config.yaml");
|
|
23441
|
+
const repoDir = repoConfigDirectory(repoRoot);
|
|
23442
|
+
const repoConfigFile = join7(repoDir, "config.yaml");
|
|
23443
|
+
let userRaw = {};
|
|
23444
|
+
let userLoadedPath;
|
|
23445
|
+
if (existsSync7(userConfigFile)) {
|
|
23446
|
+
try {
|
|
23447
|
+
const text2 = readFileSync5(userConfigFile, "utf8");
|
|
23448
|
+
userRaw = (0, import_yaml6.parse)(text2) ?? {};
|
|
23449
|
+
userLoadedPath = userConfigFile;
|
|
23450
|
+
} catch (error) {
|
|
23451
|
+
throw new Error(`invalid user config YAML at ${userConfigFile}`, { cause: error });
|
|
23452
|
+
}
|
|
23453
|
+
}
|
|
23454
|
+
let repoRaw = {};
|
|
23455
|
+
let repoLoadedPath;
|
|
23456
|
+
if (existsSync7(repoConfigFile)) {
|
|
23457
|
+
try {
|
|
23458
|
+
const text2 = readFileSync5(repoConfigFile, "utf8");
|
|
23459
|
+
repoRaw = (0, import_yaml6.parse)(text2) ?? {};
|
|
23460
|
+
repoLoadedPath = repoConfigFile;
|
|
23461
|
+
} catch (error) {
|
|
23462
|
+
throw new Error(`invalid project config YAML at ${repoConfigFile}`, { cause: error });
|
|
23463
|
+
}
|
|
23464
|
+
}
|
|
23465
|
+
const baseCopy = JSON.parse(JSON.stringify(DEFAULT_KXM_CONFIG));
|
|
23466
|
+
const mergedUser = deepMerge(baseCopy, userRaw);
|
|
23467
|
+
const mergedAll = deepMerge(mergedUser, repoRaw);
|
|
23468
|
+
return {
|
|
23469
|
+
schema: KXM_CONFIG_SCHEMA,
|
|
23470
|
+
user: mergedAll.user ?? {},
|
|
23471
|
+
defaults: mergedAll.defaults ?? {},
|
|
23472
|
+
dash: mergedAll.dash ?? {},
|
|
23473
|
+
sync: mergedAll.sync ?? {},
|
|
23474
|
+
hub: normalizeHubConfig(mergedAll.hub),
|
|
23475
|
+
improvement: normalizeImprovementConfig(mergedAll.improvement),
|
|
23476
|
+
routing: mergedAll.routing ?? DEFAULT_KXM_CONFIG.routing,
|
|
23477
|
+
telemetry: mergedAll.telemetry ?? DEFAULT_KXM_CONFIG.telemetry,
|
|
23478
|
+
loadedFrom: {
|
|
23479
|
+
userConfigPath: userLoadedPath,
|
|
23480
|
+
repoConfigPath: repoLoadedPath
|
|
23481
|
+
}
|
|
23482
|
+
};
|
|
23483
|
+
}
|
|
23484
|
+
|
|
23485
|
+
// plugins/kxm/src/hub-binding.ts
|
|
23486
|
+
var CloudTokenError = class extends Error {
|
|
23487
|
+
code;
|
|
23488
|
+
constructor(code, message) {
|
|
23489
|
+
super(message);
|
|
23490
|
+
this.name = "CloudTokenError";
|
|
23491
|
+
this.code = code;
|
|
23492
|
+
}
|
|
23493
|
+
};
|
|
23494
|
+
|
|
23495
|
+
// plugins/kxm/src/hub-identity.ts
|
|
23496
|
+
var OP_TIMEOUT_MS = 15e3;
|
|
23497
|
+
var OP_MAX_BUFFER = 4096;
|
|
23498
|
+
function defaultOpRead(reference, env) {
|
|
23499
|
+
if (!isHubOpReference(reference)) {
|
|
23500
|
+
throw new CloudTokenError("cloud_token_command_invalid", `refusing to resolve ${reference}; an op:// reference is required`);
|
|
23501
|
+
}
|
|
23502
|
+
const result = spawnSync("op", ["read", reference], {
|
|
23503
|
+
encoding: "utf8",
|
|
23504
|
+
shell: false,
|
|
23505
|
+
timeout: OP_TIMEOUT_MS,
|
|
23506
|
+
maxBuffer: OP_MAX_BUFFER,
|
|
23507
|
+
env,
|
|
23508
|
+
windowsHide: true
|
|
23509
|
+
});
|
|
23510
|
+
if (result.error || result.status !== 0) {
|
|
23511
|
+
throw new CloudTokenError(
|
|
23512
|
+
"cloud_token_command_failed",
|
|
23513
|
+
`op read failed for ${reference}; the token was not saved`
|
|
23514
|
+
);
|
|
23515
|
+
}
|
|
23516
|
+
const line = (result.stdout ?? "").trim();
|
|
23517
|
+
if (!line || line.split(/\r?\n/).length !== 1) {
|
|
23518
|
+
throw new CloudTokenError(
|
|
23519
|
+
"cloud_token_command_failed",
|
|
23520
|
+
`op read did not print a single token for ${reference}; the token was not saved`
|
|
23521
|
+
);
|
|
23522
|
+
}
|
|
23523
|
+
return line;
|
|
23524
|
+
}
|
|
23525
|
+
function resolveKeyReference(ref, env, opRead = defaultOpRead) {
|
|
23526
|
+
if (!ref) return void 0;
|
|
23527
|
+
if (ref.env) {
|
|
23528
|
+
const value = env[ref.env]?.trim();
|
|
23529
|
+
if (value) return { value, source: `env:${ref.env}` };
|
|
23530
|
+
}
|
|
23531
|
+
if (ref.op) {
|
|
23532
|
+
const value = opRead(ref.op, env).trim();
|
|
23533
|
+
if (!value || value.split(/\r?\n/).length !== 1) {
|
|
23534
|
+
throw new CloudTokenError("cloud_token_command_failed", `op read did not print a single token for ${ref.op}`);
|
|
23535
|
+
}
|
|
23536
|
+
return { value, source: `op:${ref.op}` };
|
|
23537
|
+
}
|
|
23538
|
+
return void 0;
|
|
23539
|
+
}
|
|
23540
|
+
function selectHubProjectTokenMap(input) {
|
|
23541
|
+
if (input.explicit) return { tokens: input.explicit, source: "env" };
|
|
23542
|
+
if (input.configured && Object.keys(input.configured).length > 0) return { tokens: input.configured, source: "config" };
|
|
23543
|
+
if (input.file && Object.keys(input.file).length > 0) return { tokens: input.file, source: "file" };
|
|
23544
|
+
return { tokens: void 0, source: "none" };
|
|
23545
|
+
}
|
|
23546
|
+
function resolveConfiguredHubProjectTokens(cwd, env = process.env, opRead = defaultOpRead) {
|
|
23547
|
+
const projects = loadHubSettings(cwd, env).projects;
|
|
23548
|
+
if (!projects || Object.keys(projects).length === 0) return void 0;
|
|
23549
|
+
const tokens = {};
|
|
23550
|
+
for (const [project, ref] of Object.entries(projects)) {
|
|
23551
|
+
const resolved = resolveKeyReference(ref, env, opRead);
|
|
23552
|
+
if (!resolved?.value) {
|
|
23553
|
+
throw new CloudTokenError(
|
|
23554
|
+
"cloud_token_missing",
|
|
23555
|
+
`hub.projects.${project} did not resolve; set ${ref.env ?? "the named variable"} or fix the op:// reference. The token was not saved`
|
|
23556
|
+
);
|
|
23557
|
+
}
|
|
23558
|
+
tokens[project] = resolved.value;
|
|
23559
|
+
}
|
|
23560
|
+
return tokens;
|
|
23561
|
+
}
|
|
23171
23562
|
|
|
23172
23563
|
// plugins/kxm/src/logger.ts
|
|
23173
|
-
import { appendFileSync, existsSync as
|
|
23174
|
-
import { dirname as
|
|
23564
|
+
import { appendFileSync, existsSync as existsSync8, mkdirSync as mkdirSync6, renameSync as renameSync3, statSync as statSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
23565
|
+
import { dirname as dirname8 } from "node:path";
|
|
23175
23566
|
var LOG_LEVEL_PRIORITY = {
|
|
23176
23567
|
debug: 10,
|
|
23177
23568
|
info: 20,
|
|
@@ -23208,7 +23599,7 @@ function redactLogValue(val, key) {
|
|
|
23208
23599
|
function rotateLogFiles(filePath, maxFiles) {
|
|
23209
23600
|
for (let i = maxFiles; i >= 1; i--) {
|
|
23210
23601
|
const current = `${filePath}.${i}`;
|
|
23211
|
-
if (
|
|
23602
|
+
if (existsSync8(current)) {
|
|
23212
23603
|
if (i >= maxFiles) {
|
|
23213
23604
|
try {
|
|
23214
23605
|
unlinkSync2(current);
|
|
@@ -23222,7 +23613,7 @@ function rotateLogFiles(filePath, maxFiles) {
|
|
|
23222
23613
|
}
|
|
23223
23614
|
}
|
|
23224
23615
|
}
|
|
23225
|
-
if (
|
|
23616
|
+
if (existsSync8(filePath)) {
|
|
23226
23617
|
try {
|
|
23227
23618
|
renameSync3(filePath, `${filePath}.1`);
|
|
23228
23619
|
} catch {
|
|
@@ -23239,7 +23630,7 @@ function createLogger(options) {
|
|
|
23239
23630
|
const shouldStdout = options.stdout ?? !isDaemon;
|
|
23240
23631
|
const correlationDefaults = options.correlation ?? {};
|
|
23241
23632
|
let currentSize = 0;
|
|
23242
|
-
if (filePath &&
|
|
23633
|
+
if (filePath && existsSync8(filePath)) {
|
|
23243
23634
|
try {
|
|
23244
23635
|
currentSize = statSync2(filePath).size;
|
|
23245
23636
|
} catch {
|
|
@@ -23277,7 +23668,7 @@ function createLogger(options) {
|
|
|
23277
23668
|
currentSize = 0;
|
|
23278
23669
|
}
|
|
23279
23670
|
try {
|
|
23280
|
-
|
|
23671
|
+
mkdirSync6(dirname8(filePath), { recursive: true });
|
|
23281
23672
|
appendFileSync(filePath, line, { encoding: "utf8", mode: 384 });
|
|
23282
23673
|
currentSize += lineBytes;
|
|
23283
23674
|
} catch {
|
|
@@ -23322,14 +23713,14 @@ function createLogger(options) {
|
|
|
23322
23713
|
var host = process.env.KXM_HOST ?? "127.0.0.1";
|
|
23323
23714
|
var port = Number.parseInt(process.env.KXM_PORT ?? String(DEFAULT_PORT), 10);
|
|
23324
23715
|
var authToken = process.env.KXM_AUTH_TOKEN;
|
|
23325
|
-
var workspaceDir =
|
|
23326
|
-
var configDir =
|
|
23327
|
-
var logsDir =
|
|
23328
|
-
var assetsDir =
|
|
23329
|
-
var stateDir =
|
|
23716
|
+
var workspaceDir = resolve8(process.env.KXM_WORKSPACE_DIR?.trim() || ".kxm");
|
|
23717
|
+
var configDir = resolve8(process.env.KXM_CONFIG_DIR?.trim() || join8(workspaceDir, "config"));
|
|
23718
|
+
var logsDir = resolve8(process.env.KXM_LOGS_DIR?.trim() || join8(workspaceDir, "logs"));
|
|
23719
|
+
var assetsDir = resolve8(process.env.KXM_ASSETS_DIR?.trim() || join8(workspaceDir, "assets"));
|
|
23720
|
+
var stateDir = resolve8(process.env.KXM_STATE_DIR?.trim() || join8(workspaceDir, "state"));
|
|
23330
23721
|
var dataPathValue = process.env.KXM_DATA_PATH?.trim();
|
|
23331
|
-
var dataPath = dataPathValue === ":memory:" ? dataPathValue :
|
|
23332
|
-
var logPath =
|
|
23722
|
+
var dataPath = dataPathValue === ":memory:" ? dataPathValue : resolve8(dataPathValue || join8(stateDir, "kxm.db"));
|
|
23723
|
+
var logPath = resolve8(process.env.KXM_LOG_PATH?.trim() || join8(logsDir, "kxm-hub.jsonl"));
|
|
23333
23724
|
var messageTtlMs = Number.parseInt(process.env.KXM_MESSAGE_TTL_MS ?? String(DEFAULT_MESSAGE_TTL_MS), 10);
|
|
23334
23725
|
var messageRetentionMs = Number.parseInt(
|
|
23335
23726
|
process.env.KXM_MESSAGE_RETENTION_MS ?? String(DEFAULT_MESSAGE_RETENTION_MS),
|
|
@@ -23340,17 +23731,17 @@ var rateLimitWindowMs = Number.parseInt(
|
|
|
23340
23731
|
process.env.KXM_RATE_LIMIT_WINDOW_MS ?? String(DEFAULT_RATE_LIMIT_WINDOW_MS),
|
|
23341
23732
|
10
|
|
23342
23733
|
);
|
|
23343
|
-
for (const directory of [configDir, logsDir, assetsDir, stateDir,
|
|
23344
|
-
|
|
23734
|
+
for (const directory of [configDir, logsDir, assetsDir, stateDir, dirname9(logPath)]) {
|
|
23735
|
+
mkdirSync7(directory, { recursive: true });
|
|
23345
23736
|
}
|
|
23346
23737
|
var structuredLog = createLogger({
|
|
23347
23738
|
component: "hub",
|
|
23348
23739
|
path: logPath
|
|
23349
23740
|
});
|
|
23350
|
-
function
|
|
23351
|
-
const
|
|
23352
|
-
if (!
|
|
23353
|
-
const value = JSON.parse(
|
|
23741
|
+
function parseProjectTokenEnv(raw) {
|
|
23742
|
+
const trimmed = raw?.trim();
|
|
23743
|
+
if (!trimmed) return void 0;
|
|
23744
|
+
const value = JSON.parse(trimmed);
|
|
23354
23745
|
if (!value || Array.isArray(value) || typeof value !== "object") {
|
|
23355
23746
|
throw new Error("KXM_PROJECT_TOKENS must be a JSON object of project names to tokens");
|
|
23356
23747
|
}
|
|
@@ -23360,6 +23751,23 @@ function projectTokens() {
|
|
|
23360
23751
|
}
|
|
23361
23752
|
return Object.fromEntries(entries);
|
|
23362
23753
|
}
|
|
23754
|
+
function projectTokens() {
|
|
23755
|
+
const explicit = process.env.KXM_PROJECT_TOKENS_EXPLICIT === "1";
|
|
23756
|
+
const fromEnv = parseProjectTokenEnv(process.env.KXM_PROJECT_TOKENS);
|
|
23757
|
+
const workdir = resolve8(process.env.KXM_WORKDIR?.trim() || process.cwd());
|
|
23758
|
+
const configured = explicit ? void 0 : resolveConfiguredHubProjectTokens(workdir, process.env);
|
|
23759
|
+
const selected = selectHubProjectTokenMap({
|
|
23760
|
+
explicit: explicit ? fromEnv : void 0,
|
|
23761
|
+
configured,
|
|
23762
|
+
file: explicit ? void 0 : fromEnv
|
|
23763
|
+
});
|
|
23764
|
+
if (selected.source === "config") {
|
|
23765
|
+
const count = Object.keys(selected.tokens ?? {}).length;
|
|
23766
|
+
process.stderr.write(`kxm hub: project tokens from .kxm/config.yaml (${count} projects, key references resolved, values not saved)
|
|
23767
|
+
`);
|
|
23768
|
+
}
|
|
23769
|
+
return selected.tokens;
|
|
23770
|
+
}
|
|
23363
23771
|
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
23364
23772
|
throw new Error("KXM_PORT must be an integer between 0 and 65535");
|
|
23365
23773
|
}
|
|
@@ -23373,7 +23781,7 @@ if (inlineWorkflows && workflowFile) {
|
|
|
23373
23781
|
throw new Error("configure only one of KXM_WEBHOOK_WORKFLOWS or KXM_WEBHOOK_WORKFLOWS_FILE");
|
|
23374
23782
|
}
|
|
23375
23783
|
var webhookWorkflows = parseWorkflowDefinitions(
|
|
23376
|
-
workflowFile ?
|
|
23784
|
+
workflowFile ? readFileSync6(resolve8(workflowFile), "utf8") : inlineWorkflows
|
|
23377
23785
|
);
|
|
23378
23786
|
var hub = createMeshHub({
|
|
23379
23787
|
host,
|