nexus-prime 6.0.0 → 6.1.0

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 (144) hide show
  1. package/dist/agents/adapters/ide-compat.d.ts +3 -0
  2. package/dist/agents/adapters/ide-compat.js +54 -1
  3. package/dist/agents/adapters/mcp/dispatch.js +22 -7
  4. package/dist/agents/adapters/mcp/envelope.d.ts +50 -0
  5. package/dist/agents/adapters/mcp/envelope.js +45 -0
  6. package/dist/agents/adapters/mcp/handlers/discovery.js +4 -0
  7. package/dist/agents/adapters/mcp/handlers/governance.js +32 -0
  8. package/dist/agents/adapters/mcp/handlers/memory.js +8 -2
  9. package/dist/agents/adapters/mcp/handlers/orchestration.js +66 -37
  10. package/dist/agents/adapters/mcp/handlers/runtime.js +5 -1
  11. package/dist/agents/adapters/mcp/runHandler.d.ts +7 -34
  12. package/dist/agents/adapters/mcp/runHandler.js +46 -35
  13. package/dist/agents/adapters/mcp/tool-health.d.ts +17 -0
  14. package/dist/agents/adapters/mcp/tool-health.js +57 -0
  15. package/dist/agents/adapters/mcp/util/detect-caller.d.ts +14 -6
  16. package/dist/agents/adapters/mcp/util/detect-caller.js +74 -11
  17. package/dist/agents/adapters/mcp/util/require-runtime.d.ts +24 -0
  18. package/dist/agents/adapters/mcp/util/require-runtime.js +28 -0
  19. package/dist/agents/adapters/mcp/util/walk.d.ts +9 -2
  20. package/dist/agents/adapters/mcp/util/walk.js +27 -5
  21. package/dist/agents/adapters/mcp.js +60 -57
  22. package/dist/architects/db/schema.js +3 -0
  23. package/dist/architects/sentinel/patrol.d.ts +19 -0
  24. package/dist/architects/sentinel/patrol.js +22 -0
  25. package/dist/cli/hook.js +34 -2
  26. package/dist/cli/install-wizard.d.ts +16 -0
  27. package/dist/cli/install-wizard.js +260 -15
  28. package/dist/cli/reset.d.ts +30 -0
  29. package/dist/cli/reset.js +132 -0
  30. package/dist/cli.js +102 -13
  31. package/dist/daemon/lock.d.ts +19 -0
  32. package/dist/daemon/lock.js +70 -1
  33. package/dist/daemon/preflight.d.ts +23 -0
  34. package/dist/daemon/preflight.js +121 -0
  35. package/dist/daemon/server.d.ts +1 -0
  36. package/dist/daemon/server.js +50 -1
  37. package/dist/dashboard/app/api.js +75 -23
  38. package/dist/dashboard/app/index.html +74 -0
  39. package/dist/dashboard/app/main.js +38 -4
  40. package/dist/dashboard/app/sse.js +6 -0
  41. package/dist/dashboard/app/state.js +6 -0
  42. package/dist/dashboard/app/styles/animation.css +10 -0
  43. package/dist/dashboard/app/styles/authoring.css +199 -0
  44. package/dist/dashboard/app/styles/governance.css +121 -0
  45. package/dist/dashboard/app/styles/tokens.css +62 -5
  46. package/dist/dashboard/app/styles/trust.css +356 -0
  47. package/dist/dashboard/app/styles/workforce.css +4 -0
  48. package/dist/dashboard/app/views/authoring.js +295 -0
  49. package/dist/dashboard/app/views/board.js +37 -0
  50. package/dist/dashboard/app/views/federation.js +216 -0
  51. package/dist/dashboard/app/views/governance.js +317 -0
  52. package/dist/dashboard/app/views/knowledge.js +103 -2
  53. package/dist/dashboard/app/views/license.js +336 -0
  54. package/dist/dashboard/app/views/memory.js +30 -5
  55. package/dist/dashboard/app/views/repo.js +262 -0
  56. package/dist/dashboard/app/views/trust.js +296 -0
  57. package/dist/dashboard/app/views/workforce.js +259 -35
  58. package/dist/dashboard/app/widgets/error-banner.js +83 -0
  59. package/dist/dashboard/app/widgets/runtime-badge.js +46 -0
  60. package/dist/dashboard/routes/architects.d.ts +2 -0
  61. package/dist/dashboard/routes/architects.js +46 -0
  62. package/dist/dashboard/routes/authoring.d.ts +2 -0
  63. package/dist/dashboard/routes/authoring.js +193 -0
  64. package/dist/dashboard/routes/governance.js +104 -7
  65. package/dist/dashboard/routes/graph.d.ts +13 -0
  66. package/dist/dashboard/routes/graph.js +94 -0
  67. package/dist/dashboard/routes/health.js +5 -0
  68. package/dist/dashboard/routes/runtime.js +24 -50
  69. package/dist/dashboard/server.d.ts +7 -3
  70. package/dist/dashboard/server.js +133 -81
  71. package/dist/dashboard/stream/sse-broker.js +13 -0
  72. package/dist/dashboard/types.d.ts +15 -2
  73. package/dist/engines/benchmark-extended.js +2 -2
  74. package/dist/engines/byzantine-consensus.js +22 -0
  75. package/dist/engines/client-registry.d.ts +2 -0
  76. package/dist/engines/client-registry.js +25 -5
  77. package/dist/engines/code-review-graph-client.d.ts +13 -0
  78. package/dist/engines/code-review-graph-client.js +60 -0
  79. package/dist/engines/event-bus.d.ts +80 -1
  80. package/dist/engines/instruction-gateway.js +14 -14
  81. package/dist/engines/knowledge-fabric.d.ts +1 -1
  82. package/dist/engines/knowledge-fabric.js +4 -4
  83. package/dist/engines/machine-efficiency/pressure-detector.js +10 -4
  84. package/dist/engines/memory/entropy-decay.d.ts +19 -0
  85. package/dist/engines/memory/entropy-decay.js +19 -0
  86. package/dist/engines/memory/recall.d.ts +8 -0
  87. package/dist/engines/memory/recall.js +36 -0
  88. package/dist/engines/memory/schema.d.ts +21 -0
  89. package/dist/engines/memory/schema.js +127 -0
  90. package/dist/engines/memory/store.d.ts +18 -0
  91. package/dist/engines/memory/store.js +86 -0
  92. package/dist/engines/memory/tier-promotion.d.ts +21 -0
  93. package/dist/engines/memory/tier-promotion.js +14 -0
  94. package/dist/engines/memory-bridge.d.ts +1 -1
  95. package/dist/engines/memory-bridge.js +2 -2
  96. package/dist/engines/memory.d.ts +10 -1
  97. package/dist/engines/memory.js +45 -194
  98. package/dist/engines/middleware-pipeline.d.ts +3 -0
  99. package/dist/engines/middleware-pipeline.js +20 -0
  100. package/dist/engines/nexus-layer.d.ts +1 -1
  101. package/dist/engines/orchestrator/funnel.d.ts +49 -0
  102. package/dist/engines/orchestrator/funnel.js +82 -0
  103. package/dist/engines/orchestrator.js +144 -61
  104. package/dist/engines/perf-history.d.ts +33 -0
  105. package/dist/engines/perf-history.js +93 -0
  106. package/dist/engines/runtime-backends.d.ts +3 -3
  107. package/dist/engines/runtime-backends.js +3 -3
  108. package/dist/engines/schema/integrity.d.ts +23 -0
  109. package/dist/engines/schema/integrity.js +111 -0
  110. package/dist/engines/schema/migrate.d.ts +27 -0
  111. package/dist/engines/schema/migrate.js +90 -0
  112. package/dist/engines/telemetry.d.ts +28 -0
  113. package/dist/engines/telemetry.js +79 -0
  114. package/dist/engines/token-supremacy.d.ts +6 -11
  115. package/dist/engines/token-supremacy.js +49 -53
  116. package/dist/index.d.ts +11 -3
  117. package/dist/index.js +23 -4
  118. package/dist/invokers/cursor.d.ts +27 -0
  119. package/dist/invokers/cursor.js +163 -0
  120. package/dist/invokers/registry.js +3 -0
  121. package/dist/invokers/types.d.ts +1 -1
  122. package/dist/migrations/architects/v001_baseline.sql +4 -0
  123. package/dist/migrations/memory/v001_baseline.sql +4 -0
  124. package/dist/migrations/synapse/v001_baseline.sql +4 -0
  125. package/dist/phantom/index.js +1 -1
  126. package/dist/phantom/runtime/diff-preview.d.ts +9 -0
  127. package/dist/phantom/runtime/diff-preview.js +72 -0
  128. package/dist/phantom/runtime/ghost-pass.d.ts +5 -0
  129. package/dist/phantom/runtime/ghost-pass.js +7 -0
  130. package/dist/phantom/runtime/index.d.ts +5 -0
  131. package/dist/phantom/runtime/index.js +5 -0
  132. package/dist/phantom/runtime/worker.d.ts +57 -0
  133. package/dist/phantom/runtime/worker.js +193 -0
  134. package/dist/phantom/runtime/worktree.d.ts +69 -0
  135. package/dist/phantom/runtime/worktree.js +227 -0
  136. package/dist/phantom/runtime.d.ts +10 -12
  137. package/dist/phantom/runtime.js +66 -536
  138. package/dist/postinstall/cleanup.d.ts +16 -0
  139. package/dist/postinstall/cleanup.js +85 -0
  140. package/dist/synapse/db/schema.js +3 -0
  141. package/dist/synapse/mandate/pipeline.js +5 -0
  142. package/dist/verify-token-scoring.js +1 -1
  143. package/package.json +6 -6
  144. package/dist/dashboard/index.html +0 -3678
@@ -5,6 +5,7 @@
5
5
  * Supported: VS Code (Claude Code ext), JetBrains, Cursor, Windsurf, Zed, Continue.dev, Aider, Cline, Codex
6
6
  */
7
7
  export type IDEId = 'claude-code' | 'cursor' | 'windsurf' | 'continue' | 'cline' | 'zed' | 'codex';
8
+ export type CallerIDEId = 'claude-code' | 'cursor' | 'windsurf' | 'continue' | 'zed' | 'codex';
8
9
  export interface McpConfigOutput {
9
10
  /** Absolute path where the config should be written */
10
11
  configPath: string | null;
@@ -13,6 +14,8 @@ export interface McpConfigOutput {
13
14
  /** If true, attempt to merge into existing file rather than overwrite */
14
15
  merge: boolean;
15
16
  }
17
+ export declare function resetDetectedCallerIDECache(): void;
18
+ export declare function detectCallerIDE(): CallerIDEId | null;
16
19
  /** Detect which IDEs are present in the workspace or home directory. */
17
20
  export declare function detectInstalledIDEs(workspaceRoot: string): IDEId[];
18
21
  /** Get the MCP config content and target path for a given IDE. */
@@ -6,7 +6,8 @@
6
6
  */
7
7
  import { existsSync } from 'fs';
8
8
  import { homedir } from 'os';
9
- import { join } from 'path';
9
+ import { dirname, join, resolve } from 'path';
10
+ let callerIDECache;
10
11
  /** Nexus Prime MCP server entry (stdio transport). */
11
12
  function nexusMcpServerEntry(workspaceRoot) {
12
13
  return {
@@ -15,6 +16,58 @@ function nexusMcpServerEntry(workspaceRoot) {
15
16
  env: {},
16
17
  };
17
18
  }
19
+ function hasAnyEnvPrefix(prefix) {
20
+ return Object.keys(process.env).some((key) => key.startsWith(prefix));
21
+ }
22
+ function detectCallerIDEFromEnv() {
23
+ if (process.env.CLAUDECODE || process.env.CLAUDE_CODE || process.env.CLAUDE_SESSION_ID || process.env.CLAUDE_PROJECT_DIR) {
24
+ return 'claude-code';
25
+ }
26
+ if (process.env.CURSOR_TRACE_ID || hasAnyEnvPrefix('CURSOR_')) {
27
+ return 'cursor';
28
+ }
29
+ if (process.env.CODEX_HOME || hasAnyEnvPrefix('CODEX_')) {
30
+ return 'codex';
31
+ }
32
+ if (hasAnyEnvPrefix('WINDSURF_')) {
33
+ return 'windsurf';
34
+ }
35
+ if (hasAnyEnvPrefix('CONTINUE_')) {
36
+ return 'continue';
37
+ }
38
+ if (hasAnyEnvPrefix('ZED_')) {
39
+ return 'zed';
40
+ }
41
+ return null;
42
+ }
43
+ function detectCallerIDEFromFilesystem(startDir) {
44
+ let current = resolve(startDir);
45
+ for (;;) {
46
+ if (existsSync(join(current, '.cursor')))
47
+ return 'cursor';
48
+ if (existsSync(join(current, '.continue')))
49
+ return 'continue';
50
+ if (existsSync(join(current, '.windsurf')))
51
+ return 'windsurf';
52
+ if (existsSync(join(current, '.zed')))
53
+ return 'zed';
54
+ const parent = dirname(current);
55
+ if (parent === current) {
56
+ return null;
57
+ }
58
+ current = parent;
59
+ }
60
+ }
61
+ export function resetDetectedCallerIDECache() {
62
+ callerIDECache = undefined;
63
+ }
64
+ export function detectCallerIDE() {
65
+ if (callerIDECache !== undefined) {
66
+ return callerIDECache;
67
+ }
68
+ callerIDECache = detectCallerIDEFromEnv() ?? detectCallerIDEFromFilesystem(process.cwd());
69
+ return callerIDECache;
70
+ }
18
71
  /** Detect which IDEs are present in the workspace or home directory. */
19
72
  export function detectInstalledIDEs(workspaceRoot) {
20
73
  const detected = [];
@@ -13,6 +13,8 @@ import { handleGovernanceGroup } from './handlers/governance.js';
13
13
  import { handleRuntimeGroup } from './handlers/runtime.js';
14
14
  import { handleDiscoveryGroup } from './handlers/discovery.js';
15
15
  import { handleMiscGroup } from './handlers/misc.js';
16
+ import { nexusEventBus } from '../../../engines/event-bus.js';
17
+ import { recordToolInvocation } from './tool-health.js';
16
18
  /**
17
19
  * Route a tool call to the appropriate handler group.
18
20
  *
@@ -22,11 +24,24 @@ import { handleMiscGroup } from './handlers/misc.js';
22
24
  */
23
25
  export async function dispatchMcpToolCall(hctx, request, args, ctx) {
24
26
  const toolName = String(request.params?.name ?? '');
25
- // Try each group in priority order. Groups return undefined for unknown tools.
26
- return (await handleOrchestrationGroup(toolName, hctx, request, args, ctx) ??
27
- await handleMemoryGroup(toolName, hctx, request, args, ctx) ??
28
- await handleGovernanceGroup(toolName, hctx, request, args, ctx) ??
29
- await handleRuntimeGroup(toolName, hctx, request, args, ctx) ??
30
- await handleDiscoveryGroup(toolName, hctx, request, args, ctx) ??
31
- await handleMiscGroup(toolName, hctx, request, args, ctx));
27
+ const startedAt = Date.now();
28
+ try {
29
+ // Try each group in priority order. Groups return undefined for unknown tools.
30
+ const result = (await handleOrchestrationGroup(toolName, hctx, request, args, ctx) ??
31
+ await handleMemoryGroup(toolName, hctx, request, args, ctx) ??
32
+ await handleGovernanceGroup(toolName, hctx, request, args, ctx) ??
33
+ await handleRuntimeGroup(toolName, hctx, request, args, ctx) ??
34
+ await handleDiscoveryGroup(toolName, hctx, request, args, ctx) ??
35
+ await handleMiscGroup(toolName, hctx, request, args, ctx));
36
+ const durationMs = Date.now() - startedAt;
37
+ recordToolInvocation(toolName, durationMs, 'ok');
38
+ nexusEventBus.emit('tool.invocation', { toolName, durationMs, status: 'ok' });
39
+ return result;
40
+ }
41
+ catch (err) {
42
+ const durationMs = Date.now() - startedAt;
43
+ recordToolInvocation(toolName, durationMs, 'error');
44
+ nexusEventBus.emit('tool.invocation', { toolName, durationMs, status: 'error' });
45
+ throw err;
46
+ }
32
47
  }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * HandlerEnvelope — unified success/error shape for all MCP tool handlers.
3
+ *
4
+ * Lifted out of runHandler.ts so any module (middleware, handlers, tests,
5
+ * dashboard routes) can import the type without pulling in the full
6
+ * runHandler runtime. runHandler.ts re-exports these for back-compat.
7
+ */
8
+ export type HandlerErrorCode = 'timeout' | 'sqlite-busy' | 'runtime-cold' | 'input-invalid' | 'nested-dispatch-refused' | 'internal';
9
+ export interface HandlerEnvelope<T = unknown> {
10
+ ok: boolean;
11
+ data?: T;
12
+ error?: {
13
+ code: HandlerErrorCode;
14
+ message: string;
15
+ retriable: boolean;
16
+ hint?: string;
17
+ };
18
+ meta: {
19
+ toolName: string;
20
+ durationMs: number;
21
+ attempts: number;
22
+ runtimeHotAt: number | null;
23
+ };
24
+ }
25
+ export interface RunHandlerOptions {
26
+ /** Override the per-client default timeout. */
27
+ timeoutMs?: number;
28
+ /** Max retries for transient errors (SQLite-busy, runtime-cold). Default 1. */
29
+ retries?: number;
30
+ /** Caller name for per-client timeout selection. */
31
+ callerName?: string;
32
+ /** Timestamp (ms) when the runtime became hot. Passed through into meta. */
33
+ runtimeHotAt?: number | null;
34
+ }
35
+ /**
36
+ * Convert a HandlerEnvelope into the MCP tool-call response shape.
37
+ *
38
+ * On success, if `envelope.data` is already a ToolResult
39
+ * (`{ content: Array<...> }`), it is returned directly so we never
40
+ * double-wrap handler output. Any other value is JSON-stringified into a
41
+ * single text content block.
42
+ *
43
+ * On error, a structured JSON error block is produced.
44
+ */
45
+ export declare function envelopeToMcpResponse<T>(envelope: HandlerEnvelope<T>): {
46
+ content: Array<{
47
+ type: 'text';
48
+ text: string;
49
+ }>;
50
+ };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * HandlerEnvelope — unified success/error shape for all MCP tool handlers.
3
+ *
4
+ * Lifted out of runHandler.ts so any module (middleware, handlers, tests,
5
+ * dashboard routes) can import the type without pulling in the full
6
+ * runHandler runtime. runHandler.ts re-exports these for back-compat.
7
+ */
8
+ // ─── Serialisation helper ─────────────────────────────────────────────────────
9
+ /**
10
+ * Convert a HandlerEnvelope into the MCP tool-call response shape.
11
+ *
12
+ * On success, if `envelope.data` is already a ToolResult
13
+ * (`{ content: Array<...> }`), it is returned directly so we never
14
+ * double-wrap handler output. Any other value is JSON-stringified into a
15
+ * single text content block.
16
+ *
17
+ * On error, a structured JSON error block is produced.
18
+ */
19
+ export function envelopeToMcpResponse(envelope) {
20
+ if (envelope.ok) {
21
+ const data = envelope.data;
22
+ // Pass-through: handler already returned a ToolResult-shaped object.
23
+ if (data !== null &&
24
+ data !== undefined &&
25
+ typeof data === 'object' &&
26
+ Array.isArray(data.content)) {
27
+ return data;
28
+ }
29
+ const text = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
30
+ return { content: [{ type: 'text', text }] };
31
+ }
32
+ return {
33
+ content: [{
34
+ type: 'text',
35
+ text: JSON.stringify({
36
+ status: 'error',
37
+ code: envelope.error.code,
38
+ message: envelope.error.message,
39
+ retriable: envelope.error.retriable,
40
+ hint: envelope.error.hint,
41
+ meta: envelope.meta,
42
+ }, null, 2),
43
+ }],
44
+ };
45
+ }
@@ -5,8 +5,12 @@
5
5
  */
6
6
  import { formatBullets, formatJsonDetails, collectFolderFiles, } from '../helpers.js';
7
7
  import { listExecutionPresets } from '../../../../engines/execution-presets.js';
8
+ import { requireRuntime } from '../util/require-runtime.js';
8
9
  import * as path from 'path';
9
10
  export async function handleDiscoveryGroup(toolName, hctx, request, args, ctx) {
11
+ const runtimeError = requireRuntime(hctx);
12
+ if (runtimeError)
13
+ return runtimeError;
10
14
  switch (toolName) {
11
15
  case 'nexus_list_execution_presets': {
12
16
  const presets = listExecutionPresets();
@@ -17,9 +17,15 @@ import { ensureBootstrap } from '../../../../engines/client-bootstrap.js';
17
17
  import { HybridRetriever } from '../../../../engines/hybrid-retriever.js';
18
18
  import { GraphTraversalEngine } from '../../../../engines/graph-traversal.js';
19
19
  import { fileURLToPath } from 'url';
20
+ import { requireRuntime } from '../util/require-runtime.js';
21
+ import { getAllPerfStats } from '../../../../engines/perf-history.js';
22
+ import { getTTVSnapshot } from '../../../../engines/telemetry.js';
20
23
  const _gfile = fileURLToPath(import.meta.url);
21
24
  const PROJECT_ROOT = path.resolve(path.dirname(_gfile), '..', '..', '..', '..', '..');
22
25
  export async function handleGovernanceGroup(toolName, hctx, request, args, ctx) {
26
+ const runtimeError = requireRuntime(hctx);
27
+ if (runtimeError)
28
+ return runtimeError;
23
29
  switch (toolName) {
24
30
  case 'nexus_runtime_health': {
25
31
  const envelope = hctx.nexusRef.getRuntimeHealthEnvelope();
@@ -78,6 +84,30 @@ export async function handleGovernanceGroup(toolName, hctx, request, args, ctx)
78
84
  : []),
79
85
  ];
80
86
  const allLive = deadSubsystems.length === 0;
87
+ // ── perfProfile: p50/p90/p99 per tool + TTV snapshot ─────────
88
+ const [perfStats, ttvSnap] = await Promise.all([
89
+ getAllPerfStats().catch(() => []),
90
+ Promise.resolve(getTTVSnapshot()),
91
+ ]);
92
+ const perfProfile = {
93
+ tools: perfStats.map((s) => ({
94
+ tool: s.tool,
95
+ count: s.count,
96
+ p50ms: s.p50,
97
+ p90ms: s.p90,
98
+ p99ms: s.p99,
99
+ budget: s.budget ?? null,
100
+ slow: s.budget ? s.p99 > s.budget.fail : false,
101
+ })),
102
+ ttv: {
103
+ daemonStartAt: ttvSnap.daemonStartAt,
104
+ firstBootstrapMs: ttvSnap.firstBootstrapAt != null ? ttvSnap.firstBootstrapAt - ttvSnap.daemonStartAt : null,
105
+ firstMemoryMs: ttvSnap.firstMemoryAt != null ? ttvSnap.firstMemoryAt - ttvSnap.daemonStartAt : null,
106
+ firstInteractionMs: ttvSnap.firstInteractionAt != null ? ttvSnap.firstInteractionAt - ttvSnap.daemonStartAt : null,
107
+ firstMissionMs: ttvSnap.firstMissionCompleteAt != null ? ttvSnap.firstMissionCompleteAt - ttvSnap.daemonStartAt : null,
108
+ },
109
+ };
110
+ const slowTools = perfProfile.tools.filter((t) => t.slow).map((t) => t.tool);
81
111
  return {
82
112
  content: [{
83
113
  type: 'text',
@@ -94,6 +124,7 @@ export async function handleGovernanceGroup(toolName, hctx, request, args, ctx)
94
124
  `Workspace: ${envelope.workspace.source}`,
95
125
  `Issues: ${issues.length}`,
96
126
  `Ngram index: ${ngramOversized ? 'oversized' : 'ok'} (${Math.round(ngramSizeBytes / 1024 / 1024)}MB)`,
127
+ ...(slowTools.length > 0 ? [`\u26A0\uFE0F Slow tools (p99 > budget): ${slowTools.join(', ')}`] : []),
97
128
  ]),
98
129
  issues.length > 0 ? formatBullets(issues.map((issue) => `\u26A0\uFE0F ${issue}`)) : '',
99
130
  (() => {
@@ -115,6 +146,7 @@ export async function handleGovernanceGroup(toolName, hctx, request, args, ctx)
115
146
  oversized: ngramOversized,
116
147
  },
117
148
  securityAudit: getSharedAuditLog().getSummary(),
149
+ perfProfile,
118
150
  }),
119
151
  ].filter(Boolean).join('\n\n'),
120
152
  }],
@@ -8,7 +8,12 @@ import { formatBullets, formatJsonDetails } from '../helpers.js';
8
8
  import { nexusEventBus } from '../../../../engines/event-bus.js';
9
9
  import { getOperativeJournal } from '../../../../engines/operative-journal.js';
10
10
  import { storeToolSummary } from '../util/auto-memory.js';
11
+ import { requireRuntime } from '../util/require-runtime.js';
12
+ import { recordFirstMemory } from '../../../../engines/telemetry.js';
11
13
  export async function handleMemoryGroup(toolName, hctx, request, args, ctx) {
14
+ const runtimeError = requireRuntime(hctx);
15
+ if (runtimeError)
16
+ return runtimeError;
12
17
  switch (toolName) {
13
18
  case 'nexus_store_memory': {
14
19
  const content = String(request.params.arguments?.content ?? '');
@@ -19,6 +24,7 @@ export async function handleMemoryGroup(toolName, hctx, request, args, ctx) {
19
24
  const verbatim = Boolean(request.params.arguments?.verbatim ?? false);
20
25
  const id = hctx.nexusRef.storeMemory(content, priority, tags, undefined, undefined, { verbatim });
21
26
  hctx.telemetry.recordStore();
27
+ void recordFirstMemory().catch(() => { });
22
28
  hctx.sessionDNA.recordMemoryStore();
23
29
  const nudge = hctx.telemetry.planningNudge('store', { priority });
24
30
  if (ctx) {
@@ -170,7 +176,7 @@ export async function handleMemoryGroup(toolName, hctx, request, args, ctx) {
170
176
  };
171
177
  }
172
178
  case 'nexus_memory_import': {
173
- const result = hctx.nexusRef.importMemoryBundle({
179
+ const result = await hctx.nexusRef.importMemoryBundle({
174
180
  path: request.params.arguments?.path ? String(request.params.arguments.path) : undefined,
175
181
  bundle: request.params.arguments?.bundle,
176
182
  });
@@ -232,7 +238,7 @@ export async function handleMemoryGroup(toolName, hctx, request, args, ctx) {
232
238
  ]);
233
239
  }
234
240
  else if (action === 'syncFrom') {
235
- const result = bridge.syncFrom(sourceDir || bridge.getBridgeDir());
241
+ const result = await bridge.syncFrom(sourceDir || bridge.getBridgeDir());
236
242
  detail = formatBullets([
237
243
  `Success: ${result.success}`,
238
244
  `Imported: ${result.imported}`,
@@ -12,12 +12,18 @@ import { formatReadingPlan } from '../../../../engines/token-supremacy.js';
12
12
  import { GhostPass, summarizeExecution } from '../../../../phantom/index.js';
13
13
  import { applyExecutionPreset, resolveExecutionPreset } from '../../../../engines/execution-presets.js';
14
14
  import { pLimit } from '../../../../engines/util/p-limit.js';
15
- import { promises as fsPromises, statSync } from 'fs';
15
+ import { promises as fsPromises } from 'fs';
16
16
  import { getSharedLicenseManager } from '../../../../licensing/index.js';
17
17
  import { SessionDNAManager } from '../../../../engines/session-dna.js';
18
18
  import { getSharedTelemetry } from '../../../../engines/telemetry-remote.js';
19
19
  import { storeToolSummary } from '../util/auto-memory.js';
20
+ import { requireRuntime } from '../util/require-runtime.js';
21
+ import { ensureCrGraphBuilt } from '../../../../engines/code-review-graph-client.js';
22
+ import { recordFirstBootstrap } from '../../../../engines/telemetry.js';
20
23
  export async function handleOrchestrationGroup(toolName, hctx, request, args, ctx) {
24
+ const runtimeError = requireRuntime(hctx);
25
+ if (runtimeError)
26
+ return runtimeError;
21
27
  // Variables computed in the original handleToolCall preamble and used by these cases
22
28
  const detailLevel = normalizeDetailLevel(args.detailLevel);
23
29
  const requestedIntent = normalizeResponseIntent(args.intent);
@@ -117,7 +123,9 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
117
123
  remoteTelemetry.trackTokenSavings(Number(bootstrap.tokenOptimization.planMetrics.savings));
118
124
  }
119
125
  }
120
- catch { /* best-effort telemetry */ }
126
+ catch (err) {
127
+ nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'track-session-start', error: err instanceof Error ? err.message : String(err) });
128
+ }
121
129
  if (ctx) {
122
130
  ctx.meta.tokenSavings = Number(bootstrap.tokenOptimization?.planMetrics?.savings ?? 0);
123
131
  ctx.meta.projectMemoryBootstrapCount = Number(bootstrap.projectMemoryBootstrap?.count ?? 0);
@@ -133,7 +141,20 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
133
141
  try {
134
142
  storeToolSummary(hctx, 'nexus_session_bootstrap', `Session bootstrap: ${bootstrapGoal || 'interactive session'}. Memory: prefrontal=${bootstrap.memoryStats?.prefrontal ?? 0}, hippocampus=${bootstrap.memoryStats?.hippocampus ?? 0}, cortex=${bootstrap.memoryStats?.cortex ?? 0}.`);
135
143
  }
144
+ catch (err) {
145
+ nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'persist-session-summary', error: err instanceof Error ? err.message : String(err) });
146
+ }
147
+ // Non-blocking: ensure cr-graph is fresh after bootstrap. Fires after the handler
148
+ // returns so the response is not delayed. Any failure is silently swallowed.
149
+ try {
150
+ const crRepoRoot = hctx.nexusRef.getWorkspaceContext().repoRoot;
151
+ if (crRepoRoot) {
152
+ setImmediate(() => { void ensureCrGraphBuilt(crRepoRoot); });
153
+ }
154
+ }
136
155
  catch { /* best-effort */ }
156
+ // TTV telemetry: record first successful bootstrap (fire-and-forget).
157
+ void recordFirstBootstrap().catch(() => { });
137
158
  const timings = {
138
159
  totalMs: Date.now() - callStartedAt,
139
160
  };
@@ -232,28 +253,11 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
232
253
  formatBullets([
233
254
  `Workspace: ${workspace.repoName} (${workspace.workspaceSource})`,
234
255
  `Client: ${bootstrap.client?.displayName || bootstrap.client?.clientId || 'unknown'} (${bootstrap.client?.state || 'unknown'})`,
235
- `Bootstrap depth: ${bootstrap.depth || bootstrapDepth}`,
236
256
  `Memory recall: ${bootstrap.memoryRecall?.count ?? 0} result(s)`,
237
257
  `Memory stats: prefrontal ${bootstrap.memoryStats?.prefrontal ?? 0} · hippocampus ${bootstrap.memoryStats?.hippocampus ?? 0} · cortex ${bootstrap.memoryStats?.cortex ?? 0}`,
238
258
  `Recommended next step: ${bootstrap.recommendedNextStep || 'nexus_orchestrate'}`,
239
- `Execution mode: ${bootstrap.recommendedExecutionMode || 'autonomous'}`,
240
259
  `Token optimization: ${bootstrap.tokenOptimization?.autoApplied ? `auto-applied — saved ${Number(bootstrap.tokenOptimization?.planMetrics?.savings ?? 0).toLocaleString()} tokens (${bootstrap.tokenOptimization?.planMetrics?.pct ?? 0}% reduction)` : (bootstrap.tokenOptimization?.required ? 'required before broad reading' : 'not required yet')}`,
241
260
  `Catalog health: ${bootstrap.catalogHealth?.overall || 'unknown'} · selected ${bootstrap.artifactSelectionAudit?.selected?.length || 0}`,
242
- `Shortlist: ${bootstrap.shortlist?.skills?.slice(0, 3).join(', ') || 'none'} (skills), ${bootstrap.shortlist?.specialists?.slice(0, 3).join(', ') || 'none'} (specialists)`,
243
- `Knowledge fabric: ${bootstrap.sourceMixRecommendation?.dominantSource || bootstrap.knowledgeFabric?.dominantSource || 'awaiting source mix'}`,
244
- `RAG: ${bootstrap.ragCandidateStatus?.attachedCollections || 0} attached · ${bootstrap.ragCandidateStatus?.retrievedChunks || 0} retrieved`,
245
- `Task graph: ${bootstrap.taskGraphPreview?.phases?.length || 0} phases · ${bootstrap.taskGraphPreview?.independentBranches || 0} branches`,
246
- `Worker plan: ${bootstrap.workerPlanPreview?.totalWorkers || 0} workers planned`,
247
- bootstrap.needsDeepBootstrap ? 'Deep preparation: still recommended before risky or cross-file work' : 'Deep preparation: not currently required',
248
- `Payload ref: ${workspace.stateKey} · ${detailLevel}`,
249
- `Session summary: ${bootstrap.sessionSummaryBootstrap?.savedTokens ? `reused ${Number(bootstrap.sessionSummaryBootstrap.savedTokens || 0).toLocaleString()} tokens from the previous visit` : 'none available yet'}`,
250
- bootstrap.projectMemoryBootstrap?.count
251
- ? `Project memory: recovered ${bootstrap.projectMemoryBootstrap.count} prior project memories`
252
- : 'Project memory: no prior project memories recovered',
253
- bootstrap.autoGhostPass?.applied
254
- ? `Auto ghost-pass: ${bootstrap.autoGhostPass.riskAreas.length} risk area(s) · ${bootstrap.autoGhostPass.workerApproaches} approach(es)`
255
- : `Auto ghost-pass: skipped`,
256
- `Bootstrap status: ${bootstrap.clientBootstrapStatus?.clients?.length || 0} client manifests tracked`,
257
261
  (() => {
258
262
  try {
259
263
  const _lic = getSharedLicenseManager().getStatus();
@@ -266,11 +270,30 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
266
270
  return '';
267
271
  }
268
272
  })(),
273
+ ...(detailLevel === 'debug' ? [
274
+ `Bootstrap depth: ${bootstrap.depth || bootstrapDepth}`,
275
+ `Execution mode: ${bootstrap.recommendedExecutionMode || 'autonomous'}`,
276
+ `Shortlist: ${bootstrap.shortlist?.skills?.slice(0, 3).join(', ') || 'none'} (skills), ${bootstrap.shortlist?.specialists?.slice(0, 3).join(', ') || 'none'} (specialists)`,
277
+ `Knowledge fabric: ${bootstrap.sourceMixRecommendation?.dominantSource || bootstrap.knowledgeFabric?.dominantSource || 'awaiting source mix'}`,
278
+ `RAG: ${bootstrap.ragCandidateStatus?.attachedCollections || 0} attached · ${bootstrap.ragCandidateStatus?.retrievedChunks || 0} retrieved`,
279
+ `Task graph: ${bootstrap.taskGraphPreview?.phases?.length || 0} phases · ${bootstrap.taskGraphPreview?.independentBranches || 0} branches`,
280
+ `Worker plan: ${bootstrap.workerPlanPreview?.totalWorkers || 0} workers planned`,
281
+ bootstrap.needsDeepBootstrap ? 'Deep preparation: still recommended before risky or cross-file work' : 'Deep preparation: not currently required',
282
+ `Payload ref: ${workspace.stateKey} · ${detailLevel}`,
283
+ `Session summary: ${bootstrap.sessionSummaryBootstrap?.savedTokens ? `reused ${Number(bootstrap.sessionSummaryBootstrap.savedTokens || 0).toLocaleString()} tokens from the previous visit` : 'none available yet'}`,
284
+ bootstrap.projectMemoryBootstrap?.count
285
+ ? `Project memory: recovered ${bootstrap.projectMemoryBootstrap.count} prior project memories`
286
+ : 'Project memory: no prior project memories recovered',
287
+ bootstrap.autoGhostPass?.applied
288
+ ? `Auto ghost-pass: ${bootstrap.autoGhostPass.riskAreas.length} risk area(s) · ${bootstrap.autoGhostPass.workerApproaches} approach(es)`
289
+ : `Auto ghost-pass: skipped`,
290
+ `Bootstrap status: ${bootstrap.clientBootstrapStatus?.clients?.length || 0} client manifests tracked`,
291
+ ] : []),
269
292
  ]),
270
293
  detailLevel === 'debug' && bootstrap.tokenOptimization?.autoApplied && bootstrap.tokenOptimization?.plan
271
294
  ? `Auto token plan\n\`\`\`txt\n${bootstrap.tokenOptimization.plan}\n\`\`\``
272
295
  : '',
273
- formatJsonDetails('Structured details', payload),
296
+ detailLevel === 'debug' ? formatJsonDetails('Structured details', payload) : '',
274
297
  hctx.formatProtocolChecklist(),
275
298
  ].filter(Boolean).join('\n\n'),
276
299
  }],
@@ -350,7 +373,9 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
350
373
  const modifiedFiles = execution.workerResults.flatMap((w) => w.modifiedFiles);
351
374
  hctx.nexusRef.storeMemory(`Run ${execution.runId} ${execution.state}: ${summarizeExecution(execution)}. Workers: ${verifiedWorkers}/${execution.workerResults.length} verified. Files modified: ${modifiedFiles.slice(0, 5).join(', ') || 'none'}.`, 0.34, ['#run-summary', '#auto', '#system-hidden']);
352
375
  }
353
- catch { /* best-effort */ }
376
+ catch (err) {
377
+ nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'auto-memory-store', error: err instanceof Error ? err.message : String(err) });
378
+ }
354
379
  execution.activeSkills.forEach((skill) => hctx.sessionDNA.recordSkill(skill.name));
355
380
  execution.workerResults.forEach((result) => {
356
381
  result.modifiedFiles.forEach((file) => hctx.sessionDNA.recordFileModified(file));
@@ -440,21 +465,23 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
440
465
  `Run ID: ${execution.runId}`,
441
466
  `Summary: ${summarizeExecution(execution)}`,
442
467
  `Crew: ${execution.plannerState?.selectedCrew?.name || 'baseline path'}`,
443
- `Specialists: ${execution.plannerState?.selectedSpecialists.map((specialist) => specialist.name).slice(0, 4).join(', ') || 'none selected'}`,
444
- `Assets: ${(execution.activeSkills || []).length} skills · ${(execution.activeWorkflows || []).length} workflows · ${(runtimeUsage.artifactSelectionAudit?.selected?.length || 0)} audited selections`,
445
- `Task graph: ${runtimeUsage.taskGraph?.phases?.length || execution.taskGraph?.phases?.length || 0} phases · ${runtimeUsage.workerPlan?.totalWorkers || execution.workerPlan?.totalWorkers || 0} workers`,
446
- `Catalog health: ${runtimeUsage.catalogHealth?.overall || 'unknown'}`,
447
- preset ? `Preset: ${preset.name} (${preset.id})` : null,
448
468
  `Verification: ${verifiedWorkers}/${execution.workerResults.length} worker(s) verified`,
449
- `Worktrees: ${runtimeUsage.worktreeHealth?.overall || 'unknown'} · repaired ${runtimeUsage.worktreeHealth?.repairedEntries || 0} · broken ${runtimeUsage.worktreeHealth?.brokenEntries || 0}`,
450
- `Tokens: saved ${Number(execution.tokenTelemetry?.savedTokens || 0).toLocaleString()} · compression ${Number(execution.tokenTelemetry?.compressionPct || 0)}% · dominant ${runtimeUsage.sourceAwareTokenBudget?.dominantSource || execution.knowledgeFabric?.sourceMix?.dominantSource || 'repo'}`,
469
+ `Tokens: saved ${Number(execution.tokenTelemetry?.savedTokens || 0).toLocaleString()} · compression ${Number(execution.tokenTelemetry?.compressionPct || 0)}%`,
451
470
  autoTokenApplyNote || null,
452
- `RAG: ${(runtimeUsage.ragUsageSummary?.attachedCollections || execution.knowledgeFabric?.rag.attachedCollections.length || 0)} attached · ${(runtimeUsage.ragUsageSummary?.retrievedChunks || execution.knowledgeFabric?.rag.hits.length || 0)} retrieved`,
453
- `Memory scopes: ${Object.entries(runtimeUsage.memoryScopeUsage?.byScope || execution.memoryScopeUsage?.byScope || {}).map(([scope, count]) => `${scope}:${count}`).join(' · ') || 'awaiting shared/session reads'}`,
454
- `Payload ref: ${workspace.stateKey} · ${detailLevel}`,
471
+ ...(detailLevel === 'debug' ? [
472
+ `Specialists: ${execution.plannerState?.selectedSpecialists.map((specialist) => specialist.name).slice(0, 4).join(', ') || 'none selected'}`,
473
+ `Assets: ${(execution.activeSkills || []).length} skills · ${(execution.activeWorkflows || []).length} workflows · ${(runtimeUsage.artifactSelectionAudit?.selected?.length || 0)} audited selections`,
474
+ `Task graph: ${runtimeUsage.taskGraph?.phases?.length || execution.taskGraph?.phases?.length || 0} phases · ${runtimeUsage.workerPlan?.totalWorkers || execution.workerPlan?.totalWorkers || 0} workers`,
475
+ `Catalog health: ${runtimeUsage.catalogHealth?.overall || 'unknown'}`,
476
+ preset ? `Preset: ${preset.name} (${preset.id})` : null,
477
+ `Worktrees: ${runtimeUsage.worktreeHealth?.overall || 'unknown'} · repaired ${runtimeUsage.worktreeHealth?.repairedEntries || 0} · broken ${runtimeUsage.worktreeHealth?.brokenEntries || 0}`,
478
+ `RAG: ${(runtimeUsage.ragUsageSummary?.attachedCollections || execution.knowledgeFabric?.rag.attachedCollections.length || 0)} attached · ${(runtimeUsage.ragUsageSummary?.retrievedChunks || execution.knowledgeFabric?.rag.hits.length || 0)} retrieved`,
479
+ `Memory scopes: ${Object.entries(runtimeUsage.memoryScopeUsage?.byScope || execution.memoryScopeUsage?.byScope || {}).map(([scope, count]) => `${scope}:${count}`).join(' · ') || 'awaiting shared/session reads'}`,
480
+ `Payload ref: ${workspace.stateKey} · ${detailLevel}`,
481
+ ] : []),
455
482
  ]),
456
483
  detailLevel === 'debug' && execution.result ? `Result\n\`\`\`\n${execution.result}\n\`\`\`` : `Result preview\n\`\`\`\n${truncateText(execution.result || summarizeExecution(execution), 900)}\n\`\`\``,
457
- formatJsonDetails('Structured details', payload),
484
+ detailLevel === 'debug' ? formatJsonDetails('Structured details', payload) : '',
458
485
  hctx.formatRemainingProtocolSteps(),
459
486
  ].filter(Boolean).join('\n\n'),
460
487
  }],
@@ -509,7 +536,7 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
509
536
  return { path: resolved, sizeBytes: 0 };
510
537
  }
511
538
  })));
512
- const plan = getTokenEngine().plan(task, files);
539
+ const plan = await getTokenEngine().plan(task, files);
513
540
  const formatted = formatReadingPlan(plan);
514
541
  // Persist the decision
515
542
  hctx.nexusRef.storeMemory(`Token plan for "${task.slice(0, 80)}": ` +
@@ -557,16 +584,16 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
557
584
  const rawFiles = Array.isArray(request.params.arguments?.files)
558
585
  ? request.params.arguments.files.map(String)
559
586
  : [];
560
- const files = rawFiles.map(p => {
587
+ const files = await Promise.all(rawFiles.map(async (p) => {
561
588
  const resolved = hctx.resolveToolPath(p, request.params.arguments ?? {});
562
589
  try {
563
- const stat = statSync(resolved);
590
+ const stat = await fsPromises.stat(resolved);
564
591
  return { path: resolved, sizeBytes: stat.size, lastModified: stat.mtimeMs };
565
592
  }
566
593
  catch {
567
594
  return { path: resolved, sizeBytes: 0 };
568
595
  }
569
- });
596
+ }));
570
597
  const ghost = new GhostPass(hctx.getWorkspace(request.params.arguments ?? {}).repoRoot);
571
598
  const report = await ghost.analyze(goal, files);
572
599
  hctx.nexusRef.storeMemory(`Ghost pass for "${goal.slice(0, 80)}": ${report.riskAreas.length} risks identified.`, 0.6, ['#ghost-pass']);
@@ -650,7 +677,9 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
650
677
  try {
651
678
  storeToolSummary(hctx, 'nexus_spawn_workers', `Worker plan: "${goal.slice(0, 100)}" — ${workersCount} workers, ${rawFiles.length} files.`);
652
679
  }
653
- catch { /* best-effort */ }
680
+ catch (err) {
681
+ nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'worker-plan-summary', error: err instanceof Error ? err.message : String(err) });
682
+ }
654
683
  const execution = await hctx.getRuntime().run(applyExecutionPreset({
655
684
  goal,
656
685
  files: rawFiles,
@@ -8,7 +8,11 @@ import { formatBullets, formatJsonDetails, } from '../helpers.js';
8
8
  import { nexusEventBus } from '../../../../engines/event-bus.js';
9
9
  import { getSharedLicenseManager, snapshotPCU, formatPCUStatus } from '../../../../licensing/index.js';
10
10
  import { TokenAnalyticsEngine } from '../../../../engines/token-analytics.js';
11
+ import { requireRuntime } from '../util/require-runtime.js';
11
12
  export async function handleRuntimeGroup(toolName, hctx, request, args, ctx) {
13
+ const runtimeError = requireRuntime(hctx);
14
+ if (runtimeError)
15
+ return runtimeError;
12
16
  switch (toolName) {
13
17
  case 'nexus_license_usage': {
14
18
  const fmt = String(request.params.arguments?.format ?? 'summary');
@@ -220,7 +224,7 @@ export async function handleRuntimeGroup(toolName, hctx, request, args, ctx) {
220
224
  }
221
225
  case 'nexus_run_status': {
222
226
  const runId = String(request.params.arguments?.runId ?? '');
223
- const run = hctx.getRuntime().getRun(runId);
227
+ const run = await hctx.getRuntime().getRun(runId);
224
228
  if (!run) {
225
229
  return { content: [{ type: 'text', text: `❌ Run not found: ${runId}` }] };
226
230
  }
@@ -8,34 +8,14 @@
8
8
  *
9
9
  * Per-client timeouts (AI Lead refinement):
10
10
  * Codex 90 s · Claude Code 60 s · Cursor 30 s · default 25 s
11
+ *
12
+ * Types and `envelopeToMcpResponse` are canonical in ./envelope.ts;
13
+ * re-exported from here for backward compatibility.
11
14
  */
12
- export type HandlerErrorCode = 'timeout' | 'sqlite-busy' | 'runtime-cold' | 'input-invalid' | 'nested-dispatch-refused' | 'internal';
13
- export interface HandlerEnvelope<T = unknown> {
14
- ok: boolean;
15
- data?: T;
16
- error?: {
17
- code: HandlerErrorCode;
18
- message: string;
19
- retriable: boolean;
20
- hint?: string;
21
- };
22
- meta: {
23
- toolName: string;
24
- durationMs: number;
25
- attempts: number;
26
- runtimeHotAt: number | null;
27
- };
28
- }
29
- export interface RunHandlerOptions {
30
- /** Override the per-client default timeout. */
31
- timeoutMs?: number;
32
- /** Max retries for transient errors (SQLite-busy, runtime-cold). Default 1. */
33
- retries?: number;
34
- /** Caller name for per-client timeout selection. */
35
- callerName?: string;
36
- /** Timestamp (ms) when the runtime became hot. Passed through into meta. */
37
- runtimeHotAt?: number | null;
38
- }
15
+ import type { RunHandlerOptions } from './envelope.js';
16
+ import type { HandlerEnvelope } from './envelope.js';
17
+ export type { HandlerErrorCode, HandlerEnvelope, RunHandlerOptions } from './envelope.js';
18
+ export { envelopeToMcpResponse } from './envelope.js';
39
19
  /**
40
20
  * Run a handler function with timeout, retry, and structured envelope.
41
21
  *
@@ -46,10 +26,3 @@ export interface RunHandlerOptions {
46
26
  * }, { callerName: hctx.adapterName });
47
27
  */
48
28
  export declare function runHandler<T>(toolName: string, fn: () => Promise<T>, opts?: RunHandlerOptions): Promise<HandlerEnvelope<T>>;
49
- /** Convert a HandlerEnvelope into the MCP tool-call response shape. */
50
- export declare function envelopeToMcpResponse<T>(envelope: HandlerEnvelope<T>): {
51
- content: Array<{
52
- type: 'text';
53
- text: string;
54
- }>;
55
- };