@kontextmind/kxm 0.7.91 → 0.7.93

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 (92) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.kxm/workflows/default.yaml +1 -1
  3. package/CHANGELOG.md +212 -0
  4. package/README.md +3 -0
  5. package/docs/README.md +3 -0
  6. package/docs/agent-skills.md +123 -60
  7. package/docs/architecture.md +5 -2
  8. package/docs/cli-reference.md +3527 -0
  9. package/docs/config-reference.md +1943 -0
  10. package/docs/configuration.md +30 -4
  11. package/docs/continuous-improvement.md +122 -10
  12. package/docs/contracts/routing.md +95 -11
  13. package/docs/harness-routing.md +616 -0
  14. package/docs/kxm-handbook.md +106 -19
  15. package/docs/templates/README.md +1 -1
  16. package/docs/test-matrix.md +12 -6
  17. package/docs/troubleshooting.md +2 -2
  18. package/examples/project/.kxm/workflows/fix.yaml +1 -1
  19. package/examples/project/.kxm/workflows/improve.yaml +1 -1
  20. package/package.json +1 -1
  21. package/plugins/kxm/.claude-plugin/plugin.json +9 -10
  22. package/plugins/kxm/README.md +238 -56
  23. package/plugins/kxm/dist/claude-hook.js +10083 -0
  24. package/plugins/kxm/dist/cli.js +2487 -1848
  25. package/plugins/kxm/dist/client.js +64 -0
  26. package/plugins/kxm/dist/core.js +102 -9
  27. package/plugins/kxm/dist/extension.js +210 -68
  28. package/plugins/kxm/dist/mcp-server.js +217 -40
  29. package/plugins/kxm/dist/runtime-supervisor.js +1628 -157
  30. package/plugins/kxm/dist/runtime.js +1874 -298
  31. package/plugins/kxm/dist/server.js +416 -82
  32. package/plugins/kxm/package.json +1 -1
  33. package/plugins/kxm/skills/hints.json +1 -1
  34. package/plugins/kxm/skills/kxm/SKILL.md +48 -24
  35. package/plugins/kxm/skills/kxm/references/protocol.md +3 -3
  36. package/plugins/kxm/skills/kxm-context-memory/SKILL.md +67 -21
  37. package/plugins/kxm/skills/kxm-definitions/SKILL.md +9 -0
  38. package/plugins/kxm/skills/kxm-harness-auth/SKILL.md +82 -16
  39. package/plugins/kxm/skills/kxm-harvest/SKILL.md +1 -1
  40. package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +55 -27
  41. package/plugins/kxm/skills/kxm-insights/SKILL.md +1 -1
  42. package/plugins/kxm/skills/kxm-mind/SKILL.md +2 -2
  43. package/plugins/kxm/skills/{kxm-setup → kxm-mind-setup}/SKILL.md +4 -4
  44. package/plugins/kxm/skills/kxm-peer/SKILL.md +68 -93
  45. package/plugins/kxm/skills/kxm-project-setup/SKILL.md +156 -23
  46. package/plugins/kxm/skills/kxm-projects/SKILL.md +1 -1
  47. package/plugins/kxm/skills/kxm-protocol/SKILL.md +1 -1
  48. package/plugins/kxm/skills/kxm-query/SKILL.md +1 -1
  49. package/plugins/kxm/skills/kxm-routing-improve/SKILL.md +74 -15
  50. package/plugins/kxm/skills/kxm-runs/SKILL.md +46 -17
  51. package/plugins/kxm/skills/kxm-session/SKILL.md +64 -36
  52. package/plugins/kxm/skills/kxm-skill-lifecycle/SKILL.md +44 -15
  53. package/plugins/kxm/skills/kxm-tasks/SKILL.md +16 -4
  54. package/plugins/kxm/skills/kxm-triage/SKILL.md +1 -1
  55. package/plugins/kxm/skills/kxm-work/SKILL.md +1 -1
  56. package/plugins/kxm/skills/kxm-workflow/SKILL.md +60 -19
  57. package/plugins/kxm/src/arbiter.ts +67 -22
  58. package/plugins/kxm/src/autocomplete.ts +1 -1
  59. package/plugins/kxm/src/claude-hook.ts +192 -0
  60. package/plugins/kxm/src/cli/project.ts +11 -5
  61. package/plugins/kxm/src/cli/system.ts +85 -13
  62. package/plugins/kxm/src/cli/types.ts +4 -1
  63. package/plugins/kxm/src/cli/workflows.ts +18 -16
  64. package/plugins/kxm/src/cli.ts +23 -13
  65. package/plugins/kxm/src/client.ts +15 -4
  66. package/plugins/kxm/src/commands.ts +19 -9
  67. package/plugins/kxm/src/config.ts +42 -7
  68. package/plugins/kxm/src/context-packet.ts +14 -2
  69. package/plugins/kxm/src/context.ts +16 -5
  70. package/plugins/kxm/src/dispatch-context.ts +286 -0
  71. package/plugins/kxm/src/engine-plan.ts +40 -0
  72. package/plugins/kxm/src/engine.ts +138 -6
  73. package/plugins/kxm/src/hub-env.ts +17 -1
  74. package/plugins/kxm/src/hub.ts +92 -29
  75. package/plugins/kxm/src/improve-sources.ts +228 -0
  76. package/plugins/kxm/src/improve.ts +325 -140
  77. package/plugins/kxm/src/local-snapshot.ts +101 -42
  78. package/plugins/kxm/src/mcp-server.ts +129 -30
  79. package/plugins/kxm/src/memory.ts +43 -20
  80. package/plugins/kxm/src/project-config.ts +25 -0
  81. package/plugins/kxm/src/protocol.ts +11 -0
  82. package/plugins/kxm/src/relevance.ts +138 -0
  83. package/plugins/kxm/src/retrospective.ts +16 -10
  84. package/plugins/kxm/src/runtime-service.ts +8 -1
  85. package/plugins/kxm/src/runtime-supervisor.ts +16 -2
  86. package/plugins/kxm/src/session-token-hint.ts +17 -0
  87. package/plugins/kxm/src/suggest.ts +7 -7
  88. package/plugins/kxm/src/workflow-manager.ts +80 -78
  89. package/plugins/kxm/src/workflow.ts +202 -12
  90. package/scripts/build-runtime.mjs +7 -1
  91. package/scripts/check-generated.mjs +1 -0
  92. package/scripts/emit-codex-artifacts.mjs +1 -1
@@ -7187,6 +7187,10 @@ var require_dist = __commonJS({
7187
7187
  }
7188
7188
  });
7189
7189
 
7190
+ // plugins/kxm/src/mcp-server.ts
7191
+ import { statSync } from "node:fs";
7192
+ import { join as join4 } from "node:path";
7193
+
7190
7194
  // node_modules/zod/v4/core/core.js
7191
7195
  var _a;
7192
7196
  // @__NO_SIDE_EFFECTS__
@@ -15765,8 +15769,93 @@ var MAX_BODY_BYTES = 256 * 1024;
15765
15769
  var MAX_AGENT_HOST_CHARS = 64;
15766
15770
  var MAX_LEASE_TTL_MS = 10 * 6e4;
15767
15771
  var DEFAULT_LEASE_TTL_MS = 5 * 6e4;
15772
+ var IMPROVEMENT_AREAS = [
15773
+ "harness",
15774
+ "gates",
15775
+ "implementation",
15776
+ "workflow",
15777
+ "documentation",
15778
+ "security",
15779
+ "other"
15780
+ ];
15781
+
15782
+ // plugins/kxm/src/relevance.ts
15783
+ var RELEVANCE_STOPWORDS = Object.freeze(/* @__PURE__ */ new Set([
15784
+ "a",
15785
+ "an",
15786
+ "and",
15787
+ "are",
15788
+ "as",
15789
+ "at",
15790
+ "be",
15791
+ "been",
15792
+ "but",
15793
+ "by",
15794
+ "can",
15795
+ "could",
15796
+ "did",
15797
+ "do",
15798
+ "does",
15799
+ "for",
15800
+ "from",
15801
+ "had",
15802
+ "has",
15803
+ "have",
15804
+ "how",
15805
+ "if",
15806
+ "in",
15807
+ "into",
15808
+ "is",
15809
+ "it",
15810
+ "its",
15811
+ "of",
15812
+ "on",
15813
+ "or",
15814
+ "our",
15815
+ "should",
15816
+ "so",
15817
+ "than",
15818
+ "that",
15819
+ "the",
15820
+ "their",
15821
+ "them",
15822
+ "then",
15823
+ "there",
15824
+ "these",
15825
+ "they",
15826
+ "this",
15827
+ "those",
15828
+ "to",
15829
+ "was",
15830
+ "we",
15831
+ "were",
15832
+ "what",
15833
+ "when",
15834
+ "where",
15835
+ "which",
15836
+ "while",
15837
+ "who",
15838
+ "why",
15839
+ "will",
15840
+ "with",
15841
+ "would",
15842
+ "you",
15843
+ "your"
15844
+ ]));
15768
15845
 
15769
15846
  // plugins/kxm/src/workflow.ts
15847
+ var JOURNAL_CATEGORIES = [
15848
+ "plan",
15849
+ "decision",
15850
+ "contradiction",
15851
+ "error",
15852
+ "lesson",
15853
+ "observation",
15854
+ "hypothesis",
15855
+ "experiment",
15856
+ "state-change",
15857
+ "skill-candidate"
15858
+ ];
15770
15859
  function canonicalWorkflowEvidenceKey(value) {
15771
15860
  return value.trim().replace(/\s+/gu, " ").toLowerCase();
15772
15861
  }
@@ -16283,11 +16372,12 @@ function readHubEnvRecord(env = process.env) {
16283
16372
  ...record2.projectTokens !== void 0 ? { projectTokens: record2.projectTokens } : {}
16284
16373
  };
16285
16374
  }
16286
- function resolveClientHubAuthToken(env, project) {
16375
+ function resolveAgentHubAuthToken(env, project) {
16287
16376
  const envToken = env.KXM_AUTH_TOKEN?.trim();
16288
16377
  if (envToken) return envToken;
16289
- const record2 = readHubEnvRecord(env);
16290
- return record2?.projectTokens?.[project]?.trim() || record2?.authToken?.trim() || void 0;
16378
+ const tokens = readHubEnvRecord(env)?.projectTokens;
16379
+ if (!tokens || !Object.hasOwn(tokens, project)) return void 0;
16380
+ return tokens[project]?.trim() || void 0;
16291
16381
  }
16292
16382
 
16293
16383
  // plugins/kxm/src/project-name.ts
@@ -16655,7 +16745,7 @@ var AGENT_COMMANDS = [
16655
16745
  group: "workflow",
16656
16746
  verb: "run",
16657
16747
  label: "Get workflow run",
16658
- description: "Get a workflow's stages and journal of plans, decisions, contradictions, errors, and lessons.",
16748
+ description: "Get a workflow's stages and its learning journal (plans, decisions, contradictions, errors, lessons, and the other journal categories).",
16659
16749
  parameters: {
16660
16750
  type: "object",
16661
16751
  properties: {
@@ -16729,20 +16819,24 @@ var AGENT_COMMANDS = [
16729
16819
  group: "workflow",
16730
16820
  verb: "record",
16731
16821
  label: "Record workflow journal entry",
16732
- description: "Record a plan, decision, contradiction, error, or lesson for continuous improvement.",
16822
+ description: "Record a plan, decision, contradiction, error, lesson, observation, hypothesis, experiment, state-change, or skill-candidate for continuous improvement. Pass stageId to bind the entry to that stage: the hub derives the attempt, and area defaults to the stage's declared area. Lessons and skill-candidates require evidence.",
16733
16823
  parameters: {
16734
16824
  type: "object",
16735
16825
  properties: {
16736
16826
  runId: { type: "string", description: "Active durable workflow run ID" },
16737
16827
  category: {
16738
16828
  type: "string",
16739
- enum: ["plan", "decision", "contradiction", "error", "lesson"],
16829
+ enum: [...JOURNAL_CATEGORIES],
16740
16830
  description: "Category of journal entry"
16741
16831
  },
16742
16832
  area: {
16743
16833
  type: "string",
16744
- enum: ["harness", "gates", "implementation", "workflow", "documentation", "security", "other"],
16745
- description: "System area"
16834
+ enum: [...IMPROVEMENT_AREAS],
16835
+ description: "System area; required unless stageId names a stage that declares an area"
16836
+ },
16837
+ stageId: {
16838
+ type: "string",
16839
+ description: "Stage the entry belongs to; the hub binds the attempt from the stage's state"
16746
16840
  },
16747
16841
  severity: {
16748
16842
  type: "string",
@@ -16765,13 +16859,14 @@ var AGENT_COMMANDS = [
16765
16859
  description: "Related previous journal entry IDs"
16766
16860
  }
16767
16861
  },
16768
- required: ["runId", "category", "area", "summary"],
16862
+ required: ["runId", "category", "summary"],
16769
16863
  additionalProperties: false
16770
16864
  },
16771
16865
  async execute(client, args) {
16772
16866
  return await client.recordWorkflowEntry(requiredString(args.runId, "runId"), {
16773
16867
  category: requiredString(args.category, "category"),
16774
- area: requiredString(args.area, "area"),
16868
+ ...optionalString(args.area) ? { area: optionalString(args.area) } : {},
16869
+ ...optionalString(args.stageId) ? { stageId: optionalString(args.stageId) } : {},
16775
16870
  ...optionalString(args.severity) ? { severity: optionalString(args.severity) } : {},
16776
16871
  summary: requiredString(args.summary, "summary"),
16777
16872
  ...optionalString(args.details) ? { details: optionalString(args.details) } : {},
@@ -16848,7 +16943,7 @@ var AGENT_COMMANDS = [
16848
16943
  group: "workflow",
16849
16944
  verb: "improve-report",
16850
16945
  label: "Summarize improvement report",
16851
- description: "Summarize workflow errors, contradictions, and lessons by improvement area.",
16946
+ description: "Summarize workflow errors, contradictions, lessons, and skill candidates by improvement area, plus ranked cross-run signals: duplicates merged across runs and scored by frequency x severity x run-attempt cost x evidence confidence, security first, with redacted text.",
16852
16947
  parameters: {
16853
16948
  type: "object",
16854
16949
  properties: {},
@@ -16902,7 +16997,7 @@ var AGENT_COMMANDS = [
16902
16997
  group: "context",
16903
16998
  verb: "recall",
16904
16999
  label: "Recall context metadata",
16905
- description: "Search durable context records for a project by query; returns bounded metadata only.",
17000
+ description: "Search durable context records for a project by query. Ranks exact-phrase matches first, then token relevance, then id; returns bounded metadata with a numeric relevance per item, never summaries.",
16906
17001
  parameters: {
16907
17002
  type: "object",
16908
17003
  properties: {
@@ -17181,8 +17276,17 @@ async function deliverInboxNotification(messageId, delivered, notify) {
17181
17276
  return true;
17182
17277
  }
17183
17278
 
17279
+ // plugins/kxm/src/session-token-hint.ts
17280
+ var ENV_TEXT = "KXM_SESSION_TOKEN in the environment Claude Code was launched from is malformed or expired, so every kxm_* tool fails with tool_policy_denied. Ask the user to unset or replace KXM_SESSION_TOKEN in the environment Claude Code was launched from, then restart Claude Code.";
17281
+ var DISK_TEXT = "The KXM session token file on this machine is expired, malformed or unreadable, so every kxm_* tool fails with tool_policy_denied. Ask the user to run `kxm session token --clear` in their own terminal. `kxm session token --status` reports No active session token found for an expired file even though the file still blocks tools. The kxm plugin no longer refreshes that 24-hour token.";
17282
+ function sessionTokenFixHint(policy) {
17283
+ if (policy.error !== "session_token_invalid") return void 0;
17284
+ return policy.detail?.startsWith("KXM_SESSION_TOKEN") ? ENV_TEXT : DISK_TEXT;
17285
+ }
17286
+
17184
17287
  // plugins/kxm/src/mcp-server.ts
17185
- var VERSION = "0.7.91";
17288
+ var VERSION = "0.7.93";
17289
+ var CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
17186
17290
  var inbox = /* @__PURE__ */ new Map();
17187
17291
  var notifiedInbox = /* @__PURE__ */ new Set();
17188
17292
  var meshClient;
@@ -17195,11 +17299,11 @@ var mcp = new Server(
17195
17299
  tools: {}
17196
17300
  },
17197
17301
  instructions: [
17198
- 'KXM peer requests can arrive as <channel source="kxm" message_id="..."> events.',
17199
- "Handle the request using normal safety rules, then call kxm_reply with message_id and the final response.",
17200
- "Use kxm_inbox as a fallback when channel delivery is not enabled.",
17201
- "For durable workflow requests, call kxm_workflow_get, record material plans/decisions/contradictions/errors/lessons, and pass every checkpoint before replying.",
17202
- "If work is running in an external system, call kxm_workflow_wait and then kxm_reply so a signed callback can resume the workflow later."
17302
+ 'Peer requests arrive as <channel source="kxm" message_id="..."> events, or in kxm_inbox; handle each under normal safety rules, then call kxm_reply with message_id and the final response.',
17303
+ "For workflow requests, call kxm_workflow_get, record material knowledge with kxm_workflow_record in its ten categories (plan, decision, contradiction, error, lesson, observation, hypothesis, experiment, state-change, skill-candidate), pass the stageId each entry belongs to, and pass every checkpoint before replying.",
17304
+ "For external work, call kxm_workflow_wait, then kxm_reply; a signed callback resumes the run.",
17305
+ "In a KXM project, call kxm_context with your role and task before planning.",
17306
+ "If a KXM tool reports a problem with the hub or token, continue without KXM and tell the user the next step it names."
17203
17307
  ].join(" ")
17204
17308
  }
17205
17309
  );
@@ -17209,6 +17313,14 @@ function textResult(value) {
17209
17313
  function asRecord2(value) {
17210
17314
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
17211
17315
  }
17316
+ function sessionIdentity() {
17317
+ const projectDir = process.env.KXM_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd();
17318
+ return {
17319
+ projectDir,
17320
+ project: defaultProjectName(projectDir, process.env),
17321
+ serverUrl: process.env.KXM_SERVER_URL?.trim() || "http://127.0.0.1:7331"
17322
+ };
17323
+ }
17212
17324
  async function onHubEvent(event) {
17213
17325
  if (event.type === "cancelled" || event.type === "expired") {
17214
17326
  inbox.delete(event.message.id);
@@ -17242,28 +17354,44 @@ async function onHubEvent(event) {
17242
17354
  });
17243
17355
  });
17244
17356
  }
17357
+ async function startClient(project, serverUrl, name, authToken) {
17358
+ const candidate = new HubClient({
17359
+ serverUrl,
17360
+ name,
17361
+ purpose: process.env.KXM_AGENT_PURPOSE?.trim() || "Claude Code implementation and review agent",
17362
+ project,
17363
+ model: "claude-code",
17364
+ authToken
17365
+ });
17366
+ try {
17367
+ await candidate.start(onHubEvent);
17368
+ meshClient = candidate;
17369
+ return candidate;
17370
+ } catch (error2) {
17371
+ await candidate.stop();
17372
+ throw error2;
17373
+ }
17374
+ }
17245
17375
  async function ensureClient() {
17246
17376
  if (meshClient?.agent) return meshClient;
17247
17377
  if (starting) return starting;
17248
17378
  starting = (async () => {
17249
- const projectDir = process.env.KXM_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd();
17250
- const project = defaultProjectName(projectDir, process.env);
17251
- const authToken = resolveClientHubAuthToken(process.env, project);
17252
- const candidate = new HubClient({
17253
- serverUrl: process.env.KXM_SERVER_URL?.trim() || "http://127.0.0.1:7331",
17254
- name: process.env.KXM_AGENT_NAME?.trim() || `claude-${process.pid}`,
17255
- purpose: process.env.KXM_AGENT_PURPOSE?.trim() || "Claude Code implementation and review agent",
17256
- project,
17257
- model: "claude-code",
17258
- ...authToken ? { authToken } : {}
17259
- });
17379
+ const { project, serverUrl } = sessionIdentity();
17380
+ const authToken = resolveAgentHubAuthToken(process.env, project);
17381
+ if (!authToken) {
17382
+ throw new Error(
17383
+ `KXM has no project token for project ${project} on this machine. Ask the user to set the kxm plugin auth_token (${CONFIGURE_PLUGIN}) or to add ${project} to the hub KXM_PROJECT_TOKENS, listing every existing project too because that variable replaces the saved map.`
17384
+ );
17385
+ }
17386
+ const name = process.env.KXM_AGENT_NAME?.trim() || `claude-${process.pid}`;
17260
17387
  try {
17261
- await candidate.start(onHubEvent);
17262
- meshClient = candidate;
17263
- return candidate;
17388
+ return await startClient(project, serverUrl, name, authToken);
17264
17389
  } catch (error2) {
17265
- await candidate.stop();
17266
- throw error2;
17390
+ if (!(error2 instanceof HubHttpError && error2.code === "duplicate_agent_name")) throw error2;
17391
+ const substitute = `${name}-${process.pid}`;
17392
+ process.stderr.write(`kxm: agent name ${name} is already active in project ${project}; this session registers as ${substitute}
17393
+ `);
17394
+ return await startClient(project, serverUrl, substitute, authToken);
17267
17395
  }
17268
17396
  })();
17269
17397
  try {
@@ -17272,15 +17400,45 @@ async function ensureClient() {
17272
17400
  starting = void 0;
17273
17401
  }
17274
17402
  }
17403
+ function unreachableCause(error2) {
17404
+ if (!(error2 instanceof Error)) return void 0;
17405
+ if (error2.message.startsWith("request timed out after")) return error2.message;
17406
+ const cause = error2.cause;
17407
+ const causeCode = cause && typeof cause === "object" ? cause.code : void 0;
17408
+ if (error2.message === "fetch failed") {
17409
+ if (typeof causeCode === "string") return causeCode;
17410
+ return cause instanceof Error && cause.message ? cause.message : error2.message;
17411
+ }
17412
+ if (error2.code === "ECONNREFUSED" || error2.message.includes("ECONNREFUSED")) return "ECONNREFUSED";
17413
+ return void 0;
17414
+ }
17415
+ async function connectedClient() {
17416
+ try {
17417
+ return await ensureClient();
17418
+ } catch (error2) {
17419
+ const cause = unreachableCause(error2);
17420
+ if (!cause) throw error2;
17421
+ throw new Error(
17422
+ `KXM hub unreachable at ${sessionIdentity().serverUrl} (${cause}). Ask the user to start the hub (\`kxm hub start\`) or to correct the kxm plugin server_url with ${CONFIGURE_PLUGIN}.`
17423
+ );
17424
+ }
17425
+ }
17426
+ function toolErrorText(error2) {
17427
+ if (error2 instanceof HubHttpError && error2.code === "invalid_auth") {
17428
+ return `KXM hub rejected the project token for project ${sessionIdentity().project}. Ask the user to set the kxm plugin auth_token (${CONFIGURE_PLUGIN}) to that project's token from the hub KXM_PROJECT_TOKENS.`;
17429
+ }
17430
+ return error2 instanceof Error ? error2.message : String(error2);
17431
+ }
17275
17432
  var tools = getMcpTools();
17276
17433
  mcp.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
17277
17434
  mcp.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
17278
17435
  try {
17279
17436
  const policy = enforceToolPolicy(request.params.name);
17280
17437
  if (!policy.allowed) {
17281
- throw new Error(`tool_policy_denied: ${policy.detail ?? policy.error}`);
17438
+ const hint = sessionTokenFixHint(policy);
17439
+ throw new Error(hint ? `tool_policy_denied: ${policy.detail}. ${hint}` : `tool_policy_denied: ${policy.detail ?? policy.error}`);
17282
17440
  }
17283
- const client = await ensureClient();
17441
+ const client = await connectedClient();
17284
17442
  const cmd = AGENT_COMMANDS_MAP.get(request.params.name);
17285
17443
  if (!cmd) throw new Error(`unknown tool: ${request.params.name}`);
17286
17444
  const args = asRecord2(request.params.arguments);
@@ -17288,15 +17446,34 @@ mcp.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
17288
17446
  return textResult(result);
17289
17447
  } catch (error2) {
17290
17448
  return {
17291
- content: [{ type: "text", text: error2 instanceof Error ? error2.message : String(error2) }],
17449
+ content: [{ type: "text", text: toolErrorText(error2) }],
17292
17450
  isError: true
17293
17451
  };
17294
17452
  }
17295
17453
  });
17454
+ function registersAtStartup() {
17455
+ const { projectDir, project } = sessionIdentity();
17456
+ try {
17457
+ if (!statSync(join4(projectDir, ".kxm")).isDirectory()) return false;
17458
+ if (!resolveAgentHubAuthToken(process.env, project)) return false;
17459
+ } catch {
17460
+ return false;
17461
+ }
17462
+ return enforceToolPolicy("kxm_inbox").allowed && enforceToolPolicy("kxm_reply").allowed;
17463
+ }
17464
+ mcp.oninitialized = () => {
17465
+ if (registersAtStartup()) void ensureClient().catch(() => void 0);
17466
+ };
17296
17467
  await mcp.connect(new StdioServerTransport());
17297
- async function shutdown() {
17298
- await meshClient?.stop();
17299
- await mcp.close();
17468
+ var shuttingDown;
17469
+ function shutdown() {
17470
+ shuttingDown ??= (async () => {
17471
+ const client = meshClient ?? await starting?.catch(() => void 0);
17472
+ await client?.stop();
17473
+ await mcp.close();
17474
+ })();
17475
+ return shuttingDown;
17300
17476
  }
17301
17477
  process.once("SIGINT", () => void shutdown());
17302
17478
  process.once("SIGTERM", () => void shutdown());
17479
+ process.stdin.once("end", () => void shutdown());