@kontextmind/kxm 0.7.97 → 0.7.99

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.
Files changed (53) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.kxm/workflows/default.yaml +2 -0
  3. package/CHANGELOG.md +46 -2
  4. package/docs/concepts/architecture.md +1 -1
  5. package/docs/concepts/data-and-storage.md +1 -1
  6. package/docs/contracts/routing.md +1 -1
  7. package/docs/contributing/test-matrix.md +6 -5
  8. package/docs/guides/peer-messaging.md +2 -2
  9. package/docs/operations/backup-and-restore.md +43 -24
  10. package/docs/operations/deploy.md +1 -1
  11. package/docs/reference/cli-reference.md +65 -28
  12. package/docs/reference/config-reference.md +24 -13
  13. package/docs/reference/harness-routing.md +3 -3
  14. package/docs/reference/http-api.md +2 -1
  15. package/docs/reference/tools.md +3 -3
  16. package/docs/start/first-workflow.md +4 -4
  17. package/docs/start/quickstart-claude-code.md +2 -2
  18. package/package.json +1 -1
  19. package/plugins/kxm/.claude-plugin/plugin.json +1 -1
  20. package/plugins/kxm/dist/claude-hook.js +4 -1
  21. package/plugins/kxm/dist/cli.js +407 -156
  22. package/plugins/kxm/dist/client.js +9 -0
  23. package/plugins/kxm/dist/core.js +9 -3
  24. package/plugins/kxm/dist/extension.js +13 -1
  25. package/plugins/kxm/dist/mcp-server.js +14 -2
  26. package/plugins/kxm/dist/runtime-supervisor.js +231 -48
  27. package/plugins/kxm/dist/runtime.js +415 -92
  28. package/plugins/kxm/dist/server.js +19 -1
  29. package/plugins/kxm/package.json +1 -1
  30. package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +4 -3
  31. package/plugins/kxm/skills/kxm-peer/SKILL.md +5 -3
  32. package/plugins/kxm/skills/kxm-project-setup/SKILL.md +3 -2
  33. package/plugins/kxm/skills/kxm-routing-improve/SKILL.md +3 -0
  34. package/plugins/kxm/skills/kxm-runs/SKILL.md +8 -7
  35. package/plugins/kxm/src/cli/project.ts +22 -13
  36. package/plugins/kxm/src/cli/system.ts +22 -1
  37. package/plugins/kxm/src/cli.ts +14 -4
  38. package/plugins/kxm/src/client.ts +10 -0
  39. package/plugins/kxm/src/commands.ts +10 -1
  40. package/plugins/kxm/src/database.ts +210 -36
  41. package/plugins/kxm/src/engine.ts +117 -2
  42. package/plugins/kxm/src/extension.ts +1 -0
  43. package/plugins/kxm/src/harness.ts +29 -0
  44. package/plugins/kxm/src/hub.ts +12 -0
  45. package/plugins/kxm/src/init-guide-setup.ts +43 -28
  46. package/plugins/kxm/src/mcp-server.ts +1 -1
  47. package/plugins/kxm/src/oneshot-producer.ts +16 -8
  48. package/plugins/kxm/src/prices.ts +33 -2
  49. package/plugins/kxm/src/routing.ts +13 -7
  50. package/plugins/kxm/src/studio-layout.ts +5 -4
  51. package/plugins/kxm/src/template.ts +31 -0
  52. package/plugins/kxm/src/worktree-witness.ts +71 -0
  53. package/schemas/backup-manifest.schema.json +33 -0
@@ -262,6 +262,15 @@ var HubClient = class {
262
262
  }
263
263
  }));
264
264
  }
265
+ /** This agent's open inbound requests (queued or delivered), oldest first. A read: nothing
266
+ * is acknowledged. */
267
+ async listInbox() {
268
+ if (!this.agent) throw new Error("hub client is not registered");
269
+ const result = await this.request(
270
+ `/v1/agents/${encodeURIComponent(this.agent.id)}/inbox`
271
+ );
272
+ return result.messages;
273
+ }
265
274
  async getMessage(messageId) {
266
275
  const result = await this.request(`/v1/messages/${encodeURIComponent(messageId)}`);
267
276
  return result.message;
@@ -461,6 +461,8 @@ function compareRoutingRecords(records) {
461
461
  const blocked = settled.filter((record) => record.finalOutcome === "blocked").length;
462
462
  const failed = settled.filter((record) => record.finalOutcome === "failed").length;
463
463
  const reworked = records.filter((record) => record.retries > 0 || record.transitions > 0).length;
464
+ const missingCostRuns = records.filter((record) => typeof record.costUsd !== "number" || !Number.isFinite(record.costUsd)).length;
465
+ const summedCost = records.reduce((sum, record) => sum + (typeof record.costUsd === "number" && Number.isFinite(record.costUsd) ? record.costUsd : 0), 0);
464
466
  return {
465
467
  behavioralSha256,
466
468
  runs: records.length,
@@ -468,7 +470,8 @@ function compareRoutingRecords(records) {
468
470
  blocked,
469
471
  failed,
470
472
  reworkRate: records.length === 0 ? 0 : Math.round(reworked / records.length * 100) / 100,
471
- totalCostUsd: Math.round(records.reduce((sum, record) => sum + (record.costUsd ?? 0), 0) * 1e4) / 1e4,
473
+ totalCostUsd: missingCostRuns > 0 ? null : Math.round(summedCost * 1e4) / 1e4,
474
+ missingCostRuns,
472
475
  totalTokensIn: records.reduce((sum, record) => sum + (record.tokensIn ?? 0), 0),
473
476
  totalTokensOut: records.reduce((sum, record) => sum + (record.tokensOut ?? 0), 0),
474
477
  totalHumanInterventions: records.reduce((sum, record) => sum + record.humanInterventions, 0)
@@ -652,7 +655,7 @@ function generateRoutingReport(records, options = {}) {
652
655
  medianContextTokens = contextVals.length % 2 !== 0 ? contextVals[mid] : Math.round((contextVals[mid - 1] + contextVals[mid]) / 2);
653
656
  }
654
657
  const meteredCostUsd = Math.round(meteredCostTotal * 1e4) / 1e4;
655
- const costPerAcceptedUsd = acceptedCount > 0 ? meteredCostUsd > 0 || unmeteredAttempts > 0 ? Math.round(meteredCostUsd / acceptedCount * 1e4) / 1e4 : unknownCostAttempts === attempts ? null : 0 : null;
658
+ const costPerAcceptedUsd = acceptedCount > 0 ? unknownCostAttempts > 0 ? null : meteredCostUsd > 0 || unmeteredAttempts > 0 ? Math.round(meteredCostUsd / acceptedCount * 1e4) / 1e4 : 0 : null;
656
659
  const flagged = unknownCostAttempts > 0;
657
660
  let equivalentListCostUsd = void 0;
658
661
  if (options.includeEquivalentListCost && options.catalog) {
@@ -1281,7 +1284,10 @@ var AGENT_COMMANDS = [
1281
1284
  await reconcileInbox(client, context.inbox, context.notifiedInbox);
1282
1285
  return { messages: [...context.inbox.values()] };
1283
1286
  }
1284
- return { messages: [] };
1287
+ if (context?.hubInbox) return { messages: await client.listInbox() };
1288
+ throw new Error(
1289
+ "kxm_inbox is not available in this session: it activates each inbound request as a turn, and that turn's final response is the reply"
1290
+ );
1285
1291
  }
1286
1292
  },
1287
1293
  {
@@ -14842,6 +14842,15 @@ var HubClient = class {
14842
14842
  }
14843
14843
  }));
14844
14844
  }
14845
+ /** This agent's open inbound requests (queued or delivered), oldest first. A read: nothing
14846
+ * is acknowledged. */
14847
+ async listInbox() {
14848
+ if (!this.agent) throw new Error("hub client is not registered");
14849
+ const result2 = await this.request(
14850
+ `/v1/agents/${encodeURIComponent(this.agent.id)}/inbox`
14851
+ );
14852
+ return result2.messages;
14853
+ }
14845
14854
  async getMessage(messageId) {
14846
14855
  const result2 = await this.request(`/v1/messages/${encodeURIComponent(messageId)}`);
14847
14856
  return result2.message;
@@ -15408,7 +15417,10 @@ var AGENT_COMMANDS = [
15408
15417
  await reconcileInbox(client, context.inbox, context.notifiedInbox);
15409
15418
  return { messages: [...context.inbox.values()] };
15410
15419
  }
15411
- return { messages: [] };
15420
+ if (context?.hubInbox) return { messages: await client.listInbox() };
15421
+ throw new Error(
15422
+ "kxm_inbox is not available in this session: it activates each inbound request as a turn, and that turn's final response is the reply"
15423
+ );
15412
15424
  }
15413
15425
  },
15414
15426
  {
@@ -16042,6 +16042,15 @@ var HubClient = class {
16042
16042
  }
16043
16043
  }));
16044
16044
  }
16045
+ /** This agent's open inbound requests (queued or delivered), oldest first. A read: nothing
16046
+ * is acknowledged. */
16047
+ async listInbox() {
16048
+ if (!this.agent) throw new Error("hub client is not registered");
16049
+ const result = await this.request(
16050
+ `/v1/agents/${encodeURIComponent(this.agent.id)}/inbox`
16051
+ );
16052
+ return result.messages;
16053
+ }
16045
16054
  async getMessage(messageId) {
16046
16055
  const result = await this.request(`/v1/messages/${encodeURIComponent(messageId)}`);
16047
16056
  return result.message;
@@ -16700,7 +16709,10 @@ var AGENT_COMMANDS = [
16700
16709
  await reconcileInbox(client, context.inbox, context.notifiedInbox);
16701
16710
  return { messages: [...context.inbox.values()] };
16702
16711
  }
16703
- return { messages: [] };
16712
+ if (context?.hubInbox) return { messages: await client.listInbox() };
16713
+ throw new Error(
16714
+ "kxm_inbox is not available in this session: it activates each inbound request as a turn, and that turn's final response is the reply"
16715
+ );
16704
16716
  }
16705
16717
  },
16706
16718
  {
@@ -17296,7 +17308,7 @@ function sessionTokenFixHint(policy) {
17296
17308
  }
17297
17309
 
17298
17310
  // plugins/kxm/src/mcp-server.ts
17299
- var VERSION = "0.7.97";
17311
+ var VERSION = "0.7.99";
17300
17312
  var CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
17301
17313
  var inbox = /* @__PURE__ */ new Map();
17302
17314
  var notifiedInbox = /* @__PURE__ */ new Set();