@kontextmind/kxm 0.7.17 → 0.7.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/docs/configuration.md +17 -1
- package/docs/getting-started.md +4 -1
- package/docs/kxm-handbook.md +6 -2
- package/package.json +8 -6
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +484 -458
- package/plugins/kxm/dist/core.js +3 -2
- package/plugins/kxm/dist/extension.js +28841 -5273
- package/plugins/kxm/dist/mcp-server.js +21 -10
- package/plugins/kxm/dist/runtime.js +43 -39
- package/plugins/kxm/dist/server.js +43 -39
- package/plugins/kxm/dist/vnext-runtime-supervisor.js +40 -37
- package/plugins/kxm/package.json +4 -1
- package/plugins/kxm/src/cli/hub.ts +3 -2
- package/plugins/kxm/src/cli.ts +3 -2
- package/plugins/kxm/src/config.ts +20 -0
- package/plugins/kxm/src/extension.ts +46 -3
- package/plugins/kxm/src/hub-autostart.ts +214 -0
- package/plugins/kxm/src/mcp-server.ts +3 -3
- package/plugins/kxm/src/project-name.ts +20 -0
- package/plugins/kxm/src/providers/claude-bridge/LICENSE +21 -0
- package/plugins/kxm/src/providers/claude-bridge/README.md +18 -0
- package/plugins/kxm/src/providers/claude-bridge/config.ts +53 -0
- package/plugins/kxm/src/providers/claude-bridge/convert.ts +180 -0
- package/plugins/kxm/src/providers/claude-bridge/index.ts +28 -0
- package/plugins/kxm/src/providers/claude-bridge/mcp-server.ts +59 -0
- package/plugins/kxm/src/providers/claude-bridge/models.ts +166 -0
- package/plugins/kxm/src/providers/claude-bridge/pi-compat.ts +215 -0
- package/plugins/kxm/src/providers/claude-bridge/prompt-stream.ts +89 -0
- package/plugins/kxm/src/providers/claude-bridge/provider.ts +286 -0
- package/plugins/kxm/src/providers/claude-bridge/query-state.ts +72 -0
- package/plugins/kxm/src/providers/claude-bridge/redact.ts +26 -0
- package/plugins/kxm/src/providers/claude-bridge/register.ts +124 -0
- package/plugins/kxm/src/providers/claude-bridge/stream.ts +390 -0
- package/plugins/kxm/src/providers/claude-bridge/tools.ts +140 -0
- package/plugins/kxm/src/redact.ts +3 -2
- package/scripts/build-runtime.mjs +5 -1
|
@@ -7187,9 +7187,6 @@ var require_dist = __commonJS({
|
|
|
7187
7187
|
}
|
|
7188
7188
|
});
|
|
7189
7189
|
|
|
7190
|
-
// plugins/kxm/src/mcp-server.ts
|
|
7191
|
-
import { basename } from "node:path";
|
|
7192
|
-
|
|
7193
7190
|
// node_modules/zod/v4/core/core.js
|
|
7194
7191
|
var _a;
|
|
7195
7192
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -16169,10 +16166,24 @@ var HubClient = class {
|
|
|
16169
16166
|
}
|
|
16170
16167
|
};
|
|
16171
16168
|
|
|
16169
|
+
// plugins/kxm/src/project-name.ts
|
|
16170
|
+
import { readFileSync } from "node:fs";
|
|
16171
|
+
import { basename, join } from "node:path";
|
|
16172
|
+
function defaultProjectName(cwd, env = process.env) {
|
|
16173
|
+
const fromEnv = env.KXM_PROJECT?.trim();
|
|
16174
|
+
if (fromEnv) return fromEnv;
|
|
16175
|
+
try {
|
|
16176
|
+
const pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf8"));
|
|
16177
|
+
if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
|
|
16178
|
+
} catch {
|
|
16179
|
+
}
|
|
16180
|
+
return basename(cwd);
|
|
16181
|
+
}
|
|
16182
|
+
|
|
16172
16183
|
// plugins/kxm/src/commands.ts
|
|
16173
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
16184
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync as readFileSync2, unlinkSync, writeFileSync } from "node:fs";
|
|
16174
16185
|
import { homedir } from "node:os";
|
|
16175
|
-
import { dirname, join, resolve } from "node:path";
|
|
16186
|
+
import { dirname, join as join2, resolve } from "node:path";
|
|
16176
16187
|
function requiredString(value, name) {
|
|
16177
16188
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`${name} is required`);
|
|
16178
16189
|
return value.trim();
|
|
@@ -16908,10 +16919,10 @@ function parseSessionToken(token) {
|
|
|
16908
16919
|
}
|
|
16909
16920
|
function resolveUserConfigDirectory(overrideDir) {
|
|
16910
16921
|
if (overrideDir) return resolve(overrideDir);
|
|
16911
|
-
return resolve(process.env.KXM_USER_CONFIG_DIR?.trim() ||
|
|
16922
|
+
return resolve(process.env.KXM_USER_CONFIG_DIR?.trim() || join2(homedir(), ".config", "kxm"));
|
|
16912
16923
|
}
|
|
16913
16924
|
function sessionTokenPath(userConfigDir) {
|
|
16914
|
-
return
|
|
16925
|
+
return join2(resolveUserConfigDirectory(userConfigDir), "session.token");
|
|
16915
16926
|
}
|
|
16916
16927
|
function matchToolPattern(pattern, toolName) {
|
|
16917
16928
|
if (pattern === "*" || pattern === toolName) return true;
|
|
@@ -17007,7 +17018,7 @@ function enforceToolPolicy(commandName, env = process.env, options) {
|
|
|
17007
17018
|
if (existsSync(tokenFile)) {
|
|
17008
17019
|
let tokenRaw;
|
|
17009
17020
|
try {
|
|
17010
|
-
tokenRaw =
|
|
17021
|
+
tokenRaw = readFileSync2(tokenFile, "utf8").trim();
|
|
17011
17022
|
} catch {
|
|
17012
17023
|
return { allowed: false, error: "session_token_invalid", detail: "Session token file on disk could not be read" };
|
|
17013
17024
|
}
|
|
@@ -17036,7 +17047,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
|
|
|
17036
17047
|
}
|
|
17037
17048
|
|
|
17038
17049
|
// plugins/kxm/src/mcp-server.ts
|
|
17039
|
-
var VERSION = "0.7.
|
|
17050
|
+
var VERSION = "0.7.19";
|
|
17040
17051
|
var inbox = /* @__PURE__ */ new Map();
|
|
17041
17052
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
|
17042
17053
|
var meshClient;
|
|
@@ -17109,7 +17120,7 @@ async function ensureClient() {
|
|
|
17109
17120
|
serverUrl: process.env.KXM_SERVER_URL?.trim() || "http://127.0.0.1:7331",
|
|
17110
17121
|
name: process.env.KXM_AGENT_NAME?.trim() || `claude-${process.pid}`,
|
|
17111
17122
|
purpose: process.env.KXM_AGENT_PURPOSE?.trim() || "Claude Code implementation and review agent",
|
|
17112
|
-
project: process.env
|
|
17123
|
+
project: defaultProjectName(projectDir, process.env),
|
|
17113
17124
|
model: "claude-code",
|
|
17114
17125
|
...authToken ? { authToken } : {}
|
|
17115
17126
|
});
|
|
@@ -8071,36 +8071,38 @@ var require_Alias = __commonJS({
|
|
|
8071
8071
|
if (node.anchor === this.source)
|
|
8072
8072
|
found = node;
|
|
8073
8073
|
}
|
|
8074
|
+
if (found && ctx) {
|
|
8075
|
+
const { anchors: anchors2, doc: doc2, maxAliasCount } = ctx;
|
|
8076
|
+
let data = anchors2.get(found);
|
|
8077
|
+
if (!data) {
|
|
8078
|
+
toJS.toJS(found, null, ctx);
|
|
8079
|
+
data = anchors2.get(found);
|
|
8080
|
+
}
|
|
8081
|
+
if (data?.res === void 0) {
|
|
8082
|
+
const msg = "This should not happen: Alias anchor was not resolved?";
|
|
8083
|
+
throw new ReferenceError(msg);
|
|
8084
|
+
}
|
|
8085
|
+
if (maxAliasCount >= 0) {
|
|
8086
|
+
data.count += 1;
|
|
8087
|
+
if (data.aliasCount === 0)
|
|
8088
|
+
data.aliasCount = getAliasCount(doc2, found, anchors2);
|
|
8089
|
+
if (data.count * data.aliasCount > maxAliasCount) {
|
|
8090
|
+
const msg = "Excessive alias count indicates a resource exhaustion attack";
|
|
8091
|
+
throw new ReferenceError(msg);
|
|
8092
|
+
}
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8074
8095
|
return found;
|
|
8075
8096
|
}
|
|
8076
8097
|
toJSON(_arg, ctx) {
|
|
8077
8098
|
if (!ctx)
|
|
8078
8099
|
return { source: this.source };
|
|
8079
|
-
const
|
|
8080
|
-
const source = this.resolve(doc, ctx);
|
|
8100
|
+
const source = this.resolve(ctx.doc, ctx);
|
|
8081
8101
|
if (!source) {
|
|
8082
8102
|
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
8083
8103
|
throw new ReferenceError(msg);
|
|
8084
8104
|
}
|
|
8085
|
-
|
|
8086
|
-
if (!data) {
|
|
8087
|
-
toJS.toJS(source, null, ctx);
|
|
8088
|
-
data = anchors2.get(source);
|
|
8089
|
-
}
|
|
8090
|
-
if (data?.res === void 0) {
|
|
8091
|
-
const msg = "This should not happen: Alias anchor was not resolved?";
|
|
8092
|
-
throw new ReferenceError(msg);
|
|
8093
|
-
}
|
|
8094
|
-
if (maxAliasCount >= 0) {
|
|
8095
|
-
data.count += 1;
|
|
8096
|
-
if (data.aliasCount === 0)
|
|
8097
|
-
data.aliasCount = getAliasCount(doc, source, anchors2);
|
|
8098
|
-
if (data.count * data.aliasCount > maxAliasCount) {
|
|
8099
|
-
const msg = "Excessive alias count indicates a resource exhaustion attack";
|
|
8100
|
-
throw new ReferenceError(msg);
|
|
8101
|
-
}
|
|
8102
|
-
}
|
|
8103
|
-
return data.res;
|
|
8105
|
+
return ctx.anchors.get(source).res;
|
|
8104
8106
|
}
|
|
8105
8107
|
toString(ctx, _onComment, _onChompKeep) {
|
|
8106
8108
|
const src = `*${this.source}`;
|
|
@@ -12102,37 +12104,38 @@ var require_resolve_flow_scalar = __commonJS({
|
|
|
12102
12104
|
}
|
|
12103
12105
|
if (badChar)
|
|
12104
12106
|
onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
|
|
12105
|
-
return
|
|
12107
|
+
return unfoldLines(source);
|
|
12106
12108
|
}
|
|
12107
12109
|
function singleQuotedValue(source, onError) {
|
|
12108
12110
|
if (source[source.length - 1] !== "'" || source.length === 1)
|
|
12109
12111
|
onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
|
|
12110
|
-
return
|
|
12112
|
+
return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
|
|
12111
12113
|
}
|
|
12112
|
-
function
|
|
12113
|
-
|
|
12114
|
+
function unfoldLines(source) {
|
|
12115
|
+
const line = /(.*?)\r?\n/sy;
|
|
12116
|
+
let match = line.exec(source);
|
|
12117
|
+
if (!match)
|
|
12118
|
+
return source;
|
|
12119
|
+
let trimEnd, trimBoth;
|
|
12114
12120
|
try {
|
|
12115
|
-
|
|
12116
|
-
|
|
12121
|
+
trimEnd = new RegExp("(?<![ ])[ ]+$");
|
|
12122
|
+
trimBoth = new RegExp("^[ ]+|(?<![ ])[ ]+$", "g");
|
|
12117
12123
|
} catch {
|
|
12118
|
-
|
|
12119
|
-
|
|
12124
|
+
trimEnd = /[ \t]+$/;
|
|
12125
|
+
trimBoth = /^[ \t]+|[ \t]+$/g;
|
|
12120
12126
|
}
|
|
12121
|
-
let
|
|
12122
|
-
if (!match)
|
|
12123
|
-
return source;
|
|
12124
|
-
let res = match[1];
|
|
12127
|
+
let res = match[1].replace(trimEnd, "");
|
|
12125
12128
|
let sep3 = " ";
|
|
12126
|
-
let pos =
|
|
12127
|
-
line.lastIndex = pos;
|
|
12129
|
+
let pos = line.lastIndex;
|
|
12128
12130
|
while (match = line.exec(source)) {
|
|
12129
|
-
|
|
12131
|
+
const lm = match[1].replace(trimBoth, "");
|
|
12132
|
+
if (lm === "") {
|
|
12130
12133
|
if (sep3 === "\n")
|
|
12131
12134
|
res += sep3;
|
|
12132
12135
|
else
|
|
12133
12136
|
sep3 = "\n";
|
|
12134
12137
|
} else {
|
|
12135
|
-
res += sep3 +
|
|
12138
|
+
res += sep3 + lm;
|
|
12136
12139
|
sep3 = " ";
|
|
12137
12140
|
}
|
|
12138
12141
|
pos = line.lastIndex;
|
|
@@ -27556,6 +27559,7 @@ import { dirname as dirname6 } from "node:path";
|
|
|
27556
27559
|
// plugins/kxm/src/redact.ts
|
|
27557
27560
|
var SECRET_PATTERNS = [
|
|
27558
27561
|
/\bsk-[A-Za-z0-9_-]{8,}\b/g,
|
|
27562
|
+
/\bsk-ant-[A-Za-z0-9_-]{8,}\b/g,
|
|
27559
27563
|
/\bghp_[A-Za-z0-9_]{20,}\b/g,
|
|
27560
27564
|
/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
|
|
27561
27565
|
/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/gi,
|
|
@@ -27563,9 +27567,9 @@ var SECRET_PATTERNS = [
|
|
|
27563
27567
|
/\bya29\.[A-Za-z0-9._~+/-]+=*/g,
|
|
27564
27568
|
/\b1\/\/[A-Za-z0-9_-]+/g,
|
|
27565
27569
|
/\b1\/[A-Za-z0-9_-]{20,}/g,
|
|
27566
|
-
/("?(?:access_token|refresh_token|id_token)"?\s*[:=]\s*")[^"]*(")/gi,
|
|
27570
|
+
/("?(?:access_token|refresh_token|id_token|sessionKey|session_key|claude_oauth_token|anthropicApiKey)"?\s*[:=]\s*")[^"]*(")/gi,
|
|
27567
27571
|
/\bKXM_[A-Z0-9_]*(TOKEN|SECRET|KEY)[A-Z0-9_]*=\S+/gi,
|
|
27568
|
-
/\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET)=\S+/gi,
|
|
27572
|
+
/\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET|ANTHROPIC_API_KEY|ANTHROPIC_AUTH_TOKEN|CLAUDE_API_KEY)=\S+/gi,
|
|
27569
27573
|
/\b[A-Fa-f0-9]{64}\b/g
|
|
27570
27574
|
];
|
|
27571
27575
|
function redactSecrets(value) {
|
|
@@ -660,36 +660,38 @@ var require_Alias = __commonJS({
|
|
|
660
660
|
if (node.anchor === this.source)
|
|
661
661
|
found = node;
|
|
662
662
|
}
|
|
663
|
+
if (found && ctx) {
|
|
664
|
+
const { anchors: anchors2, doc: doc2, maxAliasCount } = ctx;
|
|
665
|
+
let data = anchors2.get(found);
|
|
666
|
+
if (!data) {
|
|
667
|
+
toJS.toJS(found, null, ctx);
|
|
668
|
+
data = anchors2.get(found);
|
|
669
|
+
}
|
|
670
|
+
if (data?.res === void 0) {
|
|
671
|
+
const msg = "This should not happen: Alias anchor was not resolved?";
|
|
672
|
+
throw new ReferenceError(msg);
|
|
673
|
+
}
|
|
674
|
+
if (maxAliasCount >= 0) {
|
|
675
|
+
data.count += 1;
|
|
676
|
+
if (data.aliasCount === 0)
|
|
677
|
+
data.aliasCount = getAliasCount(doc2, found, anchors2);
|
|
678
|
+
if (data.count * data.aliasCount > maxAliasCount) {
|
|
679
|
+
const msg = "Excessive alias count indicates a resource exhaustion attack";
|
|
680
|
+
throw new ReferenceError(msg);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
663
684
|
return found;
|
|
664
685
|
}
|
|
665
686
|
toJSON(_arg, ctx) {
|
|
666
687
|
if (!ctx)
|
|
667
688
|
return { source: this.source };
|
|
668
|
-
const
|
|
669
|
-
const source = this.resolve(doc, ctx);
|
|
689
|
+
const source = this.resolve(ctx.doc, ctx);
|
|
670
690
|
if (!source) {
|
|
671
691
|
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
672
692
|
throw new ReferenceError(msg);
|
|
673
693
|
}
|
|
674
|
-
|
|
675
|
-
if (!data) {
|
|
676
|
-
toJS.toJS(source, null, ctx);
|
|
677
|
-
data = anchors2.get(source);
|
|
678
|
-
}
|
|
679
|
-
if (data?.res === void 0) {
|
|
680
|
-
const msg = "This should not happen: Alias anchor was not resolved?";
|
|
681
|
-
throw new ReferenceError(msg);
|
|
682
|
-
}
|
|
683
|
-
if (maxAliasCount >= 0) {
|
|
684
|
-
data.count += 1;
|
|
685
|
-
if (data.aliasCount === 0)
|
|
686
|
-
data.aliasCount = getAliasCount(doc, source, anchors2);
|
|
687
|
-
if (data.count * data.aliasCount > maxAliasCount) {
|
|
688
|
-
const msg = "Excessive alias count indicates a resource exhaustion attack";
|
|
689
|
-
throw new ReferenceError(msg);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
return data.res;
|
|
694
|
+
return ctx.anchors.get(source).res;
|
|
693
695
|
}
|
|
694
696
|
toString(ctx, _onComment, _onChompKeep) {
|
|
695
697
|
const src = `*${this.source}`;
|
|
@@ -4691,37 +4693,38 @@ var require_resolve_flow_scalar = __commonJS({
|
|
|
4691
4693
|
}
|
|
4692
4694
|
if (badChar)
|
|
4693
4695
|
onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
|
|
4694
|
-
return
|
|
4696
|
+
return unfoldLines(source);
|
|
4695
4697
|
}
|
|
4696
4698
|
function singleQuotedValue(source, onError) {
|
|
4697
4699
|
if (source[source.length - 1] !== "'" || source.length === 1)
|
|
4698
4700
|
onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
|
|
4699
|
-
return
|
|
4701
|
+
return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
|
|
4700
4702
|
}
|
|
4701
|
-
function
|
|
4702
|
-
|
|
4703
|
+
function unfoldLines(source) {
|
|
4704
|
+
const line = /(.*?)\r?\n/sy;
|
|
4705
|
+
let match = line.exec(source);
|
|
4706
|
+
if (!match)
|
|
4707
|
+
return source;
|
|
4708
|
+
let trimEnd, trimBoth;
|
|
4703
4709
|
try {
|
|
4704
|
-
|
|
4705
|
-
|
|
4710
|
+
trimEnd = new RegExp("(?<![ ])[ ]+$");
|
|
4711
|
+
trimBoth = new RegExp("^[ ]+|(?<![ ])[ ]+$", "g");
|
|
4706
4712
|
} catch {
|
|
4707
|
-
|
|
4708
|
-
|
|
4713
|
+
trimEnd = /[ \t]+$/;
|
|
4714
|
+
trimBoth = /^[ \t]+|[ \t]+$/g;
|
|
4709
4715
|
}
|
|
4710
|
-
let
|
|
4711
|
-
if (!match)
|
|
4712
|
-
return source;
|
|
4713
|
-
let res = match[1];
|
|
4716
|
+
let res = match[1].replace(trimEnd, "");
|
|
4714
4717
|
let sep2 = " ";
|
|
4715
|
-
let pos =
|
|
4716
|
-
line.lastIndex = pos;
|
|
4718
|
+
let pos = line.lastIndex;
|
|
4717
4719
|
while (match = line.exec(source)) {
|
|
4718
|
-
|
|
4720
|
+
const lm = match[1].replace(trimBoth, "");
|
|
4721
|
+
if (lm === "") {
|
|
4719
4722
|
if (sep2 === "\n")
|
|
4720
4723
|
res += sep2;
|
|
4721
4724
|
else
|
|
4722
4725
|
sep2 = "\n";
|
|
4723
4726
|
} else {
|
|
4724
|
-
res += sep2 +
|
|
4727
|
+
res += sep2 + lm;
|
|
4725
4728
|
sep2 = " ";
|
|
4726
4729
|
}
|
|
4727
4730
|
pos = line.lastIndex;
|
|
@@ -9211,6 +9214,7 @@ function timingSafeStringCompare(a, b) {
|
|
|
9211
9214
|
// plugins/kxm/src/redact.ts
|
|
9212
9215
|
var SECRET_PATTERNS = [
|
|
9213
9216
|
/\bsk-[A-Za-z0-9_-]{8,}\b/g,
|
|
9217
|
+
/\bsk-ant-[A-Za-z0-9_-]{8,}\b/g,
|
|
9214
9218
|
/\bghp_[A-Za-z0-9_]{20,}\b/g,
|
|
9215
9219
|
/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
|
|
9216
9220
|
/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/gi,
|
|
@@ -9218,9 +9222,9 @@ var SECRET_PATTERNS = [
|
|
|
9218
9222
|
/\bya29\.[A-Za-z0-9._~+/-]+=*/g,
|
|
9219
9223
|
/\b1\/\/[A-Za-z0-9_-]+/g,
|
|
9220
9224
|
/\b1\/[A-Za-z0-9_-]{20,}/g,
|
|
9221
|
-
/("?(?:access_token|refresh_token|id_token)"?\s*[:=]\s*")[^"]*(")/gi,
|
|
9225
|
+
/("?(?:access_token|refresh_token|id_token|sessionKey|session_key|claude_oauth_token|anthropicApiKey)"?\s*[:=]\s*")[^"]*(")/gi,
|
|
9222
9226
|
/\bKXM_[A-Z0-9_]*(TOKEN|SECRET|KEY)[A-Z0-9_]*=\S+/gi,
|
|
9223
|
-
/\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET)=\S+/gi,
|
|
9227
|
+
/\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET|ANTHROPIC_API_KEY|ANTHROPIC_AUTH_TOKEN|CLAUDE_API_KEY)=\S+/gi,
|
|
9224
9228
|
/\b[A-Fa-f0-9]{64}\b/g
|
|
9225
9229
|
];
|
|
9226
9230
|
function redactSecrets(value) {
|
|
@@ -8072,36 +8072,38 @@ var require_Alias = __commonJS({
|
|
|
8072
8072
|
if (node.anchor === this.source)
|
|
8073
8073
|
found = node;
|
|
8074
8074
|
}
|
|
8075
|
+
if (found && ctx) {
|
|
8076
|
+
const { anchors: anchors2, doc: doc2, maxAliasCount } = ctx;
|
|
8077
|
+
let data = anchors2.get(found);
|
|
8078
|
+
if (!data) {
|
|
8079
|
+
toJS.toJS(found, null, ctx);
|
|
8080
|
+
data = anchors2.get(found);
|
|
8081
|
+
}
|
|
8082
|
+
if (data?.res === void 0) {
|
|
8083
|
+
const msg = "This should not happen: Alias anchor was not resolved?";
|
|
8084
|
+
throw new ReferenceError(msg);
|
|
8085
|
+
}
|
|
8086
|
+
if (maxAliasCount >= 0) {
|
|
8087
|
+
data.count += 1;
|
|
8088
|
+
if (data.aliasCount === 0)
|
|
8089
|
+
data.aliasCount = getAliasCount(doc2, found, anchors2);
|
|
8090
|
+
if (data.count * data.aliasCount > maxAliasCount) {
|
|
8091
|
+
const msg = "Excessive alias count indicates a resource exhaustion attack";
|
|
8092
|
+
throw new ReferenceError(msg);
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
}
|
|
8075
8096
|
return found;
|
|
8076
8097
|
}
|
|
8077
8098
|
toJSON(_arg, ctx) {
|
|
8078
8099
|
if (!ctx)
|
|
8079
8100
|
return { source: this.source };
|
|
8080
|
-
const
|
|
8081
|
-
const source = this.resolve(doc, ctx);
|
|
8101
|
+
const source = this.resolve(ctx.doc, ctx);
|
|
8082
8102
|
if (!source) {
|
|
8083
8103
|
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
8084
8104
|
throw new ReferenceError(msg);
|
|
8085
8105
|
}
|
|
8086
|
-
|
|
8087
|
-
if (!data) {
|
|
8088
|
-
toJS.toJS(source, null, ctx);
|
|
8089
|
-
data = anchors2.get(source);
|
|
8090
|
-
}
|
|
8091
|
-
if (data?.res === void 0) {
|
|
8092
|
-
const msg = "This should not happen: Alias anchor was not resolved?";
|
|
8093
|
-
throw new ReferenceError(msg);
|
|
8094
|
-
}
|
|
8095
|
-
if (maxAliasCount >= 0) {
|
|
8096
|
-
data.count += 1;
|
|
8097
|
-
if (data.aliasCount === 0)
|
|
8098
|
-
data.aliasCount = getAliasCount(doc, source, anchors2);
|
|
8099
|
-
if (data.count * data.aliasCount > maxAliasCount) {
|
|
8100
|
-
const msg = "Excessive alias count indicates a resource exhaustion attack";
|
|
8101
|
-
throw new ReferenceError(msg);
|
|
8102
|
-
}
|
|
8103
|
-
}
|
|
8104
|
-
return data.res;
|
|
8106
|
+
return ctx.anchors.get(source).res;
|
|
8105
8107
|
}
|
|
8106
8108
|
toString(ctx, _onComment, _onChompKeep) {
|
|
8107
8109
|
const src = `*${this.source}`;
|
|
@@ -12103,37 +12105,38 @@ var require_resolve_flow_scalar = __commonJS({
|
|
|
12103
12105
|
}
|
|
12104
12106
|
if (badChar)
|
|
12105
12107
|
onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
|
|
12106
|
-
return
|
|
12108
|
+
return unfoldLines(source);
|
|
12107
12109
|
}
|
|
12108
12110
|
function singleQuotedValue(source, onError) {
|
|
12109
12111
|
if (source[source.length - 1] !== "'" || source.length === 1)
|
|
12110
12112
|
onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
|
|
12111
|
-
return
|
|
12113
|
+
return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
|
|
12112
12114
|
}
|
|
12113
|
-
function
|
|
12114
|
-
|
|
12115
|
+
function unfoldLines(source) {
|
|
12116
|
+
const line = /(.*?)\r?\n/sy;
|
|
12117
|
+
let match = line.exec(source);
|
|
12118
|
+
if (!match)
|
|
12119
|
+
return source;
|
|
12120
|
+
let trimEnd, trimBoth;
|
|
12115
12121
|
try {
|
|
12116
|
-
|
|
12117
|
-
|
|
12122
|
+
trimEnd = new RegExp("(?<![ ])[ ]+$");
|
|
12123
|
+
trimBoth = new RegExp("^[ ]+|(?<![ ])[ ]+$", "g");
|
|
12118
12124
|
} catch {
|
|
12119
|
-
|
|
12120
|
-
|
|
12125
|
+
trimEnd = /[ \t]+$/;
|
|
12126
|
+
trimBoth = /^[ \t]+|[ \t]+$/g;
|
|
12121
12127
|
}
|
|
12122
|
-
let
|
|
12123
|
-
if (!match)
|
|
12124
|
-
return source;
|
|
12125
|
-
let res = match[1];
|
|
12128
|
+
let res = match[1].replace(trimEnd, "");
|
|
12126
12129
|
let sep3 = " ";
|
|
12127
|
-
let pos =
|
|
12128
|
-
line.lastIndex = pos;
|
|
12130
|
+
let pos = line.lastIndex;
|
|
12129
12131
|
while (match = line.exec(source)) {
|
|
12130
|
-
|
|
12132
|
+
const lm = match[1].replace(trimBoth, "");
|
|
12133
|
+
if (lm === "") {
|
|
12131
12134
|
if (sep3 === "\n")
|
|
12132
12135
|
res += sep3;
|
|
12133
12136
|
else
|
|
12134
12137
|
sep3 = "\n";
|
|
12135
12138
|
} else {
|
|
12136
|
-
res += sep3 +
|
|
12139
|
+
res += sep3 + lm;
|
|
12137
12140
|
sep3 = " ";
|
|
12138
12141
|
}
|
|
12139
12142
|
pos = line.lastIndex;
|
package/plugins/kxm/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kxm-claude-plugin",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.19",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
8
8
|
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@anthropic-ai/claude-agent-sdk": "0.2.141"
|
|
11
|
+
},
|
|
9
12
|
"devDependencies": {
|
|
10
13
|
"@modelcontextprotocol/sdk": "1.30.0"
|
|
11
14
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import {
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
4
|
import { redactSecrets } from "../redact.ts";
|
|
5
|
+
import { defaultProjectName } from "../project-name.ts";
|
|
5
6
|
import { agentWorker, type Worker } from "../envelope.ts";
|
|
6
7
|
import { MESH_TUI_PANELS, runMeshTui, type MeshTuiPanel } from "../tui.ts";
|
|
7
8
|
import { formatSessionBriefText, loadSessionBriefAsync, type SessionHubStatus } from "../session-work.ts";
|
|
@@ -130,7 +131,7 @@ export async function cmdDash(runtime: Runtime, options: { screen?: string | und
|
|
|
130
131
|
runtime.io.stderr("kxm dash does not support --json; use kxm hub view\n");
|
|
131
132
|
return 2;
|
|
132
133
|
}
|
|
133
|
-
const project = runtime.
|
|
134
|
+
const project = defaultProjectName(runtime.dirs.workdir, runtime.env) || "project";
|
|
134
135
|
const authToken = runtime.env.KXM_AUTH_TOKEN?.trim();
|
|
135
136
|
return await runMeshTui({
|
|
136
137
|
serverUrl: runtime.serverUrl,
|
package/plugins/kxm/src/cli.ts
CHANGED
|
@@ -12,11 +12,12 @@
|
|
|
12
12
|
* - System, update, and configuration (`kxm update`, `kxm config`, `kxm completion`, `kxm improve`)
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import { dirname, join, resolve } from "node:path";
|
|
16
16
|
import { fileURLToPath } from "node:url";
|
|
17
17
|
import { Command, CommanderError } from "commander";
|
|
18
18
|
import { readInstalledKxmVersion } from "./kxm-update.ts";
|
|
19
19
|
import { HubClient } from "./client.ts";
|
|
20
|
+
import { defaultProjectName } from "./project-name.ts";
|
|
20
21
|
import {
|
|
21
22
|
AGENT_COMMANDS_MAP,
|
|
22
23
|
enforceToolPolicy,
|
|
@@ -179,7 +180,7 @@ function addGlobalOptions(command: Command): Command {
|
|
|
179
180
|
|
|
180
181
|
async function ensureCliClient(runtime: Runtime): Promise<HubClient> {
|
|
181
182
|
const serverUrl = runtime.serverUrl;
|
|
182
|
-
const project =
|
|
183
|
+
const project = defaultProjectName(runtime.cwd, runtime.env);
|
|
183
184
|
const name = runtime.env.KXM_AGENT_NAME?.trim() || `cli-${process.pid}`;
|
|
184
185
|
const purpose = runtime.env.KXM_AGENT_PURPOSE?.trim() || "CLI agent client";
|
|
185
186
|
const authToken = runtime.env.KXM_AUTH_TOKEN?.trim();
|
|
@@ -45,6 +45,14 @@ export interface KxmSyncTrackerConfig {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
export type KxmHubAutoStart = "off" | "background";
|
|
49
|
+
|
|
50
|
+
export interface KxmHubConfig {
|
|
51
|
+
/** Pi extension hub startup: `background` starts a detached hub when no
|
|
52
|
+
* healthy bound hub or live local claim exists; `off` never starts one. */
|
|
53
|
+
autoStart: KxmHubAutoStart;
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
export type ImprovementPromotionPolicy = "manual_pr" | "critic_quorum" | "auto_threshold";
|
|
49
57
|
|
|
50
58
|
export interface KxmImprovementConfig {
|
|
@@ -90,6 +98,7 @@ export interface KxmResolvedConfig {
|
|
|
90
98
|
defaults: KxmProjectDefaults;
|
|
91
99
|
dash: KxmDashConfig;
|
|
92
100
|
sync: KxmSyncTrackerConfig;
|
|
101
|
+
hub: KxmHubConfig;
|
|
93
102
|
improvement: KxmImprovementConfig;
|
|
94
103
|
routing: KxmRoutingConfig;
|
|
95
104
|
telemetry: KxmTelemetryConfig;
|
|
@@ -118,6 +127,9 @@ export const DEFAULT_KXM_CONFIG: Omit<KxmResolvedConfig, "loadedFrom"> = {
|
|
|
118
127
|
sync: {
|
|
119
128
|
defaultTracker: "none",
|
|
120
129
|
},
|
|
130
|
+
hub: {
|
|
131
|
+
autoStart: "background",
|
|
132
|
+
},
|
|
121
133
|
improvement: {
|
|
122
134
|
promotionPolicy: "manual_pr",
|
|
123
135
|
telemetryHalfLifeDays: 14,
|
|
@@ -176,6 +188,13 @@ function deepMerge<T extends Record<string, unknown>>(target: T, source: Record<
|
|
|
176
188
|
return result as T;
|
|
177
189
|
}
|
|
178
190
|
|
|
191
|
+
/** Unknown `hub.autoStart` values fail closed to the default so a config typo
|
|
192
|
+
* never silently changes hub startup behavior. */
|
|
193
|
+
function normalizeHubConfig(raw: unknown): KxmHubConfig {
|
|
194
|
+
const autoStart = (raw as { autoStart?: unknown } | undefined)?.autoStart;
|
|
195
|
+
return { autoStart: autoStart === "off" || autoStart === "background" ? autoStart : DEFAULT_KXM_CONFIG.hub.autoStart };
|
|
196
|
+
}
|
|
197
|
+
|
|
179
198
|
export function loadKxmConfig(
|
|
180
199
|
repoRoot = process.cwd(),
|
|
181
200
|
options: { userConfigDir?: string } = {},
|
|
@@ -221,6 +240,7 @@ export function loadKxmConfig(
|
|
|
221
240
|
defaults: (mergedAll.defaults as KxmProjectDefaults) ?? {},
|
|
222
241
|
dash: (mergedAll.dash as KxmDashConfig) ?? {},
|
|
223
242
|
sync: (mergedAll.sync as KxmSyncTrackerConfig) ?? {},
|
|
243
|
+
hub: normalizeHubConfig(mergedAll.hub),
|
|
224
244
|
improvement: (mergedAll.improvement as KxmImprovementConfig) ?? DEFAULT_KXM_CONFIG.improvement,
|
|
225
245
|
routing: (mergedAll.routing as KxmRoutingConfig) ?? DEFAULT_KXM_CONFIG.routing,
|
|
226
246
|
telemetry: (mergedAll.telemetry as KxmTelemetryConfig) ?? DEFAULT_KXM_CONFIG.telemetry,
|