@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.
@@ -11,7 +11,7 @@
11
11
  "name": "kxm",
12
12
  "source": "./plugins/kxm",
13
13
  "description": "Durable workflows, peer agents, and kxm tui",
14
- "version": "0.7.60",
14
+ "version": "0.7.61",
15
15
  "category": "development",
16
16
  "tags": ["kxm", "multi-agent", "workflows", "mcp"]
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextmind/kxm",
3
- "version": "0.7.60",
3
+ "version": "0.7.61",
4
4
  "description": "KXM local-first multi-agent orchestration and operator dashboard",
5
5
  "type": "module",
6
6
  "author": "KontextMind",
@@ -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.60",
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.60";
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,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-plugin",
3
- "version": "0.7.60",
3
+ "version": "0.7.61",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "engines": {
@@ -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.60";
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,