@kontextmind/kxm 0.7.60 → 0.7.61
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/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime-supervisor.js +15 -0
- package/plugins/kxm/dist/runtime.js +21 -0
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/engine.ts +23 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/pi-producer.ts +10 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "kxm",
|
|
4
4
|
"displayName": "KXM",
|
|
5
|
-
"version": "0.7.
|
|
5
|
+
"version": "0.7.61",
|
|
6
6
|
"description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "KontextMind",
|
|
@@ -17121,7 +17121,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
|
|
|
17121
17121
|
}
|
|
17122
17122
|
|
|
17123
17123
|
// plugins/kxm/src/mcp-server.ts
|
|
17124
|
-
var VERSION = "0.7.
|
|
17124
|
+
var VERSION = "0.7.61";
|
|
17125
17125
|
var inbox = /* @__PURE__ */ new Map();
|
|
17126
17126
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
|
17127
17127
|
var meshClient;
|
|
@@ -24883,6 +24883,21 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
24883
24883
|
const parsed = (0, import_yaml5.parse)(readFileSync7(agentFile, "utf8"));
|
|
24884
24884
|
if (typeof parsed?.model === "string") {
|
|
24885
24885
|
agentModel = parsed.model;
|
|
24886
|
+
} else if (parsed?.model && typeof parsed.model === "object" && !Array.isArray(parsed.model)) {
|
|
24887
|
+
const declared = parsed.model;
|
|
24888
|
+
const providerOk = typeof declared.provider === "string" && declared.provider.length > 0 && !declared.provider.includes("/");
|
|
24889
|
+
const modelOk = typeof declared.model === "string" && declared.model.length > 0 && !declared.model.startsWith("/") && !declared.model.endsWith("/");
|
|
24890
|
+
if (providerOk && modelOk) {
|
|
24891
|
+
agentModel = `${declared.provider}/${declared.model}`;
|
|
24892
|
+
} else {
|
|
24893
|
+
return {
|
|
24894
|
+
error: {
|
|
24895
|
+
reason: "step_unsupported",
|
|
24896
|
+
field: "model",
|
|
24897
|
+
detail: "producer_route_unsupported: invalid model declaration"
|
|
24898
|
+
}
|
|
24899
|
+
};
|
|
24900
|
+
}
|
|
24886
24901
|
}
|
|
24887
24902
|
} catch {
|
|
24888
24903
|
}
|
|
@@ -25395,6 +25395,21 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
25395
25395
|
const parsed = (0, import_yaml5.parse)(readFileSync7(agentFile, "utf8"));
|
|
25396
25396
|
if (typeof parsed?.model === "string") {
|
|
25397
25397
|
agentModel = parsed.model;
|
|
25398
|
+
} else if (parsed?.model && typeof parsed.model === "object" && !Array.isArray(parsed.model)) {
|
|
25399
|
+
const declared = parsed.model;
|
|
25400
|
+
const providerOk = typeof declared.provider === "string" && declared.provider.length > 0 && !declared.provider.includes("/");
|
|
25401
|
+
const modelOk = typeof declared.model === "string" && declared.model.length > 0 && !declared.model.startsWith("/") && !declared.model.endsWith("/");
|
|
25402
|
+
if (providerOk && modelOk) {
|
|
25403
|
+
agentModel = `${declared.provider}/${declared.model}`;
|
|
25404
|
+
} else {
|
|
25405
|
+
return {
|
|
25406
|
+
error: {
|
|
25407
|
+
reason: "step_unsupported",
|
|
25408
|
+
field: "model",
|
|
25409
|
+
detail: "producer_route_unsupported: invalid model declaration"
|
|
25410
|
+
}
|
|
25411
|
+
};
|
|
25412
|
+
}
|
|
25398
25413
|
}
|
|
25399
25414
|
} catch {
|
|
25400
25415
|
}
|
|
@@ -28212,6 +28227,9 @@ function createKxmPiProducer(options = {}) {
|
|
|
28212
28227
|
}
|
|
28213
28228
|
function resolveModelForRequest(request) {
|
|
28214
28229
|
if (request.model) {
|
|
28230
|
+
if (request.provider) {
|
|
28231
|
+
return { provider: request.provider.toLowerCase(), model: request.model, thinking: request.thinking };
|
|
28232
|
+
}
|
|
28215
28233
|
const parsed2 = parseModelString(request.model);
|
|
28216
28234
|
return {
|
|
28217
28235
|
provider: request.provider?.toLowerCase() ?? parsed2.provider,
|
|
@@ -28222,6 +28240,9 @@ function createKxmPiProducer(options = {}) {
|
|
|
28222
28240
|
if (options.resolveModel) {
|
|
28223
28241
|
const resolved = options.resolveModel(request.agentId, request.runId);
|
|
28224
28242
|
if (resolved && resolved.model) {
|
|
28243
|
+
if (resolved.provider) {
|
|
28244
|
+
return { provider: resolved.provider.toLowerCase(), model: resolved.model, thinking: resolved.thinking };
|
|
28245
|
+
}
|
|
28225
28246
|
const parsed2 = parseModelString(resolved.model);
|
|
28226
28247
|
return {
|
|
28227
28248
|
provider: resolved.provider?.toLowerCase() ?? parsed2.provider,
|
package/plugins/kxm/package.json
CHANGED
|
@@ -1284,6 +1284,29 @@ function resolveProducerRoute(
|
|
|
1284
1284
|
const parsed = parse(readFileSync(agentFile, "utf8")) as Record<string, unknown>;
|
|
1285
1285
|
if (typeof parsed?.model === "string") {
|
|
1286
1286
|
agentModel = parsed.model;
|
|
1287
|
+
} else if (parsed?.model && typeof parsed.model === "object" && !Array.isArray(parsed.model)) {
|
|
1288
|
+
// The agent schema requires the object form (`{provider, model}`); reading only the
|
|
1289
|
+
// string form left every agent without a route unless it was literally named
|
|
1290
|
+
// `implementer`, which alone hit the hard-coded fallback below. A declared model
|
|
1291
|
+
// must actually drive the producer route. Model ids may themselves be namespaced
|
|
1292
|
+
// (`qwen/qwen3-coder-plus` under `openrouter`) — the provider is the only field
|
|
1293
|
+
// that may not contain the separator, because it is what the selector splits on.
|
|
1294
|
+
// A malformed declaration is an error, not an absence: falling through to the
|
|
1295
|
+
// fallback would silently route an agent that declared `openrouter` to Grok.
|
|
1296
|
+
const declared = parsed.model as { provider?: unknown; model?: unknown };
|
|
1297
|
+
const providerOk = typeof declared.provider === "string" && declared.provider.length > 0 && !declared.provider.includes("/");
|
|
1298
|
+
const modelOk = typeof declared.model === "string" && declared.model.length > 0 && !declared.model.startsWith("/") && !declared.model.endsWith("/");
|
|
1299
|
+
if (providerOk && modelOk) {
|
|
1300
|
+
agentModel = `${declared.provider}/${declared.model}`;
|
|
1301
|
+
} else {
|
|
1302
|
+
return {
|
|
1303
|
+
error: {
|
|
1304
|
+
reason: "step_unsupported",
|
|
1305
|
+
field: "model",
|
|
1306
|
+
detail: "producer_route_unsupported: invalid model declaration",
|
|
1307
|
+
},
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1287
1310
|
}
|
|
1288
1311
|
} catch {
|
|
1289
1312
|
// ignore
|
|
@@ -8,7 +8,7 @@ import { AGENT_COMMANDS_MAP, enforceToolPolicy, getMcpTools, reconcileInbox } fr
|
|
|
8
8
|
import { deliverInboxNotification } from "./inbox.ts";
|
|
9
9
|
import type { HubEvent, MessageRecord } from "./protocol.ts";
|
|
10
10
|
|
|
11
|
-
const VERSION = "0.7.
|
|
11
|
+
const VERSION = "0.7.61";
|
|
12
12
|
const inbox = new Map<string, MessageRecord>();
|
|
13
13
|
const notifiedInbox = new Set<string>();
|
|
14
14
|
let meshClient: HubClient | undefined;
|
|
@@ -462,6 +462,13 @@ export function createKxmPiProducer(options: KxmPiProducerOptions = {}): KxmPiPr
|
|
|
462
462
|
|
|
463
463
|
function resolveModelForRequest(request: KxmProducerRequest): { provider: string; model: string; thinking?: string | undefined } {
|
|
464
464
|
if (request.model) {
|
|
465
|
+
// A separate provider field means the model id is bare and may itself be
|
|
466
|
+
// namespaced (`qwen/qwen3-coder-plus` under `openrouter`); reparsing it as a
|
|
467
|
+
// provider/model selector strips the namespace and sends the wrong model. Only
|
|
468
|
+
// parse when the provider must come from the string itself.
|
|
469
|
+
if (request.provider) {
|
|
470
|
+
return { provider: request.provider.toLowerCase(), model: request.model, thinking: request.thinking };
|
|
471
|
+
}
|
|
465
472
|
const parsed = parseModelString(request.model);
|
|
466
473
|
return {
|
|
467
474
|
provider: request.provider?.toLowerCase() ?? parsed.provider,
|
|
@@ -472,6 +479,9 @@ export function createKxmPiProducer(options: KxmPiProducerOptions = {}): KxmPiPr
|
|
|
472
479
|
if (options.resolveModel) {
|
|
473
480
|
const resolved = options.resolveModel(request.agentId, request.runId);
|
|
474
481
|
if (resolved && resolved.model) {
|
|
482
|
+
if (resolved.provider) {
|
|
483
|
+
return { provider: resolved.provider.toLowerCase(), model: resolved.model, thinking: resolved.thinking };
|
|
484
|
+
}
|
|
475
485
|
const parsed = parseModelString(resolved.model);
|
|
476
486
|
return {
|
|
477
487
|
provider: resolved.provider?.toLowerCase() ?? parsed.provider,
|