nexus-prime 6.0.0 → 6.0.2
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/dist/agents/adapters/ide-compat.d.ts +3 -0
- package/dist/agents/adapters/ide-compat.js +54 -1
- package/dist/agents/adapters/mcp/envelope.d.ts +50 -0
- package/dist/agents/adapters/mcp/envelope.js +45 -0
- package/dist/agents/adapters/mcp/handlers/discovery.js +4 -0
- package/dist/agents/adapters/mcp/handlers/governance.js +32 -0
- package/dist/agents/adapters/mcp/handlers/memory.js +8 -2
- package/dist/agents/adapters/mcp/handlers/orchestration.js +33 -8
- package/dist/agents/adapters/mcp/handlers/runtime.js +5 -1
- package/dist/agents/adapters/mcp/runHandler.d.ts +7 -34
- package/dist/agents/adapters/mcp/runHandler.js +46 -35
- package/dist/agents/adapters/mcp/util/detect-caller.d.ts +14 -6
- package/dist/agents/adapters/mcp/util/detect-caller.js +74 -11
- package/dist/agents/adapters/mcp/util/require-runtime.d.ts +24 -0
- package/dist/agents/adapters/mcp/util/require-runtime.js +28 -0
- package/dist/agents/adapters/mcp.js +60 -57
- package/dist/architects/db/schema.js +3 -0
- package/dist/architects/sentinel/patrol.d.ts +19 -0
- package/dist/architects/sentinel/patrol.js +22 -0
- package/dist/cli/install-wizard.d.ts +16 -0
- package/dist/cli/install-wizard.js +256 -15
- package/dist/cli/reset.d.ts +30 -0
- package/dist/cli/reset.js +132 -0
- package/dist/cli.js +102 -13
- package/dist/daemon/lock.d.ts +19 -0
- package/dist/daemon/lock.js +70 -1
- package/dist/daemon/preflight.d.ts +23 -0
- package/dist/daemon/preflight.js +121 -0
- package/dist/daemon/server.d.ts +1 -0
- package/dist/daemon/server.js +50 -1
- package/dist/dashboard/app/api.js +75 -23
- package/dist/dashboard/app/index.html +63 -0
- package/dist/dashboard/app/main.js +34 -4
- package/dist/dashboard/app/sse.js +6 -0
- package/dist/dashboard/app/state.js +6 -0
- package/dist/dashboard/app/styles/animation.css +10 -0
- package/dist/dashboard/app/styles/authoring.css +199 -0
- package/dist/dashboard/app/styles/governance.css +121 -0
- package/dist/dashboard/app/styles/tokens.css +62 -5
- package/dist/dashboard/app/styles/trust.css +356 -0
- package/dist/dashboard/app/views/authoring.js +295 -0
- package/dist/dashboard/app/views/federation.js +216 -0
- package/dist/dashboard/app/views/governance.js +317 -0
- package/dist/dashboard/app/views/knowledge.js +103 -2
- package/dist/dashboard/app/views/license.js +336 -0
- package/dist/dashboard/app/views/memory.js +30 -5
- package/dist/dashboard/app/views/repo.js +262 -0
- package/dist/dashboard/app/views/trust.js +296 -0
- package/dist/dashboard/app/views/workforce.js +191 -14
- package/dist/dashboard/app/widgets/error-banner.js +83 -0
- package/dist/dashboard/app/widgets/runtime-badge.js +46 -0
- package/dist/dashboard/routes/architects.d.ts +2 -0
- package/dist/dashboard/routes/architects.js +46 -0
- package/dist/dashboard/routes/authoring.d.ts +2 -0
- package/dist/dashboard/routes/authoring.js +193 -0
- package/dist/dashboard/routes/governance.js +93 -2
- package/dist/dashboard/routes/graph.d.ts +13 -0
- package/dist/dashboard/routes/graph.js +94 -0
- package/dist/dashboard/routes/runtime.js +24 -50
- package/dist/dashboard/server.d.ts +7 -3
- package/dist/dashboard/server.js +122 -81
- package/dist/dashboard/stream/sse-broker.js +11 -0
- package/dist/dashboard/types.d.ts +15 -2
- package/dist/engines/benchmark-extended.js +2 -2
- package/dist/engines/byzantine-consensus.js +22 -0
- package/dist/engines/client-registry.d.ts +2 -0
- package/dist/engines/client-registry.js +25 -5
- package/dist/engines/code-review-graph-client.d.ts +13 -0
- package/dist/engines/code-review-graph-client.js +60 -0
- package/dist/engines/event-bus.d.ts +75 -1
- package/dist/engines/instruction-gateway.js +14 -14
- package/dist/engines/knowledge-fabric.d.ts +1 -1
- package/dist/engines/knowledge-fabric.js +4 -4
- package/dist/engines/machine-efficiency/pressure-detector.js +10 -4
- package/dist/engines/memory/entropy-decay.d.ts +19 -0
- package/dist/engines/memory/entropy-decay.js +19 -0
- package/dist/engines/memory/recall.d.ts +8 -0
- package/dist/engines/memory/recall.js +36 -0
- package/dist/engines/memory/schema.d.ts +21 -0
- package/dist/engines/memory/schema.js +127 -0
- package/dist/engines/memory/store.d.ts +18 -0
- package/dist/engines/memory/store.js +86 -0
- package/dist/engines/memory/tier-promotion.d.ts +21 -0
- package/dist/engines/memory/tier-promotion.js +14 -0
- package/dist/engines/memory-bridge.d.ts +1 -1
- package/dist/engines/memory-bridge.js +2 -2
- package/dist/engines/memory.d.ts +10 -1
- package/dist/engines/memory.js +45 -194
- package/dist/engines/middleware-pipeline.d.ts +3 -0
- package/dist/engines/middleware-pipeline.js +20 -0
- package/dist/engines/nexus-layer.d.ts +1 -1
- package/dist/engines/orchestrator/funnel.d.ts +49 -0
- package/dist/engines/orchestrator/funnel.js +82 -0
- package/dist/engines/orchestrator.js +144 -61
- package/dist/engines/perf-history.d.ts +33 -0
- package/dist/engines/perf-history.js +93 -0
- package/dist/engines/runtime-backends.d.ts +3 -3
- package/dist/engines/runtime-backends.js +3 -3
- package/dist/engines/schema/integrity.d.ts +23 -0
- package/dist/engines/schema/integrity.js +111 -0
- package/dist/engines/schema/migrate.d.ts +27 -0
- package/dist/engines/schema/migrate.js +90 -0
- package/dist/engines/telemetry.d.ts +28 -0
- package/dist/engines/telemetry.js +79 -0
- package/dist/engines/token-supremacy.d.ts +6 -11
- package/dist/engines/token-supremacy.js +49 -53
- package/dist/index.d.ts +11 -3
- package/dist/index.js +23 -4
- package/dist/invokers/cursor.d.ts +27 -0
- package/dist/invokers/cursor.js +163 -0
- package/dist/invokers/registry.js +3 -0
- package/dist/invokers/types.d.ts +1 -1
- package/dist/migrations/architects/v001_baseline.sql +4 -0
- package/dist/migrations/memory/v001_baseline.sql +4 -0
- package/dist/migrations/synapse/v001_baseline.sql +4 -0
- package/dist/phantom/index.js +1 -1
- package/dist/phantom/runtime/diff-preview.d.ts +9 -0
- package/dist/phantom/runtime/diff-preview.js +72 -0
- package/dist/phantom/runtime/ghost-pass.d.ts +5 -0
- package/dist/phantom/runtime/ghost-pass.js +7 -0
- package/dist/phantom/runtime/index.d.ts +5 -0
- package/dist/phantom/runtime/index.js +5 -0
- package/dist/phantom/runtime/worker.d.ts +57 -0
- package/dist/phantom/runtime/worker.js +193 -0
- package/dist/phantom/runtime/worktree.d.ts +69 -0
- package/dist/phantom/runtime/worktree.js +227 -0
- package/dist/phantom/runtime.d.ts +10 -12
- package/dist/phantom/runtime.js +66 -536
- package/dist/postinstall/cleanup.d.ts +16 -0
- package/dist/postinstall/cleanup.js +85 -0
- package/dist/synapse/db/schema.js +3 -0
- package/dist/verify-token-scoring.js +1 -1
- package/package.json +6 -6
- 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 = [];
|
|
@@ -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
|
|
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 {
|
|
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
|
};
|
|
@@ -350,7 +371,9 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
350
371
|
const modifiedFiles = execution.workerResults.flatMap((w) => w.modifiedFiles);
|
|
351
372
|
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
373
|
}
|
|
353
|
-
catch {
|
|
374
|
+
catch (err) {
|
|
375
|
+
nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'auto-memory-store', error: err instanceof Error ? err.message : String(err) });
|
|
376
|
+
}
|
|
354
377
|
execution.activeSkills.forEach((skill) => hctx.sessionDNA.recordSkill(skill.name));
|
|
355
378
|
execution.workerResults.forEach((result) => {
|
|
356
379
|
result.modifiedFiles.forEach((file) => hctx.sessionDNA.recordFileModified(file));
|
|
@@ -509,7 +532,7 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
509
532
|
return { path: resolved, sizeBytes: 0 };
|
|
510
533
|
}
|
|
511
534
|
})));
|
|
512
|
-
const plan = getTokenEngine().plan(task, files);
|
|
535
|
+
const plan = await getTokenEngine().plan(task, files);
|
|
513
536
|
const formatted = formatReadingPlan(plan);
|
|
514
537
|
// Persist the decision
|
|
515
538
|
hctx.nexusRef.storeMemory(`Token plan for "${task.slice(0, 80)}": ` +
|
|
@@ -557,16 +580,16 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
557
580
|
const rawFiles = Array.isArray(request.params.arguments?.files)
|
|
558
581
|
? request.params.arguments.files.map(String)
|
|
559
582
|
: [];
|
|
560
|
-
const files = rawFiles.map(p => {
|
|
583
|
+
const files = await Promise.all(rawFiles.map(async (p) => {
|
|
561
584
|
const resolved = hctx.resolveToolPath(p, request.params.arguments ?? {});
|
|
562
585
|
try {
|
|
563
|
-
const stat =
|
|
586
|
+
const stat = await fsPromises.stat(resolved);
|
|
564
587
|
return { path: resolved, sizeBytes: stat.size, lastModified: stat.mtimeMs };
|
|
565
588
|
}
|
|
566
589
|
catch {
|
|
567
590
|
return { path: resolved, sizeBytes: 0 };
|
|
568
591
|
}
|
|
569
|
-
});
|
|
592
|
+
}));
|
|
570
593
|
const ghost = new GhostPass(hctx.getWorkspace(request.params.arguments ?? {}).repoRoot);
|
|
571
594
|
const report = await ghost.analyze(goal, files);
|
|
572
595
|
hctx.nexusRef.storeMemory(`Ghost pass for "${goal.slice(0, 80)}": ${report.riskAreas.length} risks identified.`, 0.6, ['#ghost-pass']);
|
|
@@ -650,7 +673,9 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
650
673
|
try {
|
|
651
674
|
storeToolSummary(hctx, 'nexus_spawn_workers', `Worker plan: "${goal.slice(0, 100)}" — ${workersCount} workers, ${rawFiles.length} files.`);
|
|
652
675
|
}
|
|
653
|
-
catch {
|
|
676
|
+
catch (err) {
|
|
677
|
+
nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'worker-plan-summary', error: err instanceof Error ? err.message : String(err) });
|
|
678
|
+
}
|
|
654
679
|
const execution = await hctx.getRuntime().run(applyExecutionPreset({
|
|
655
680
|
goal,
|
|
656
681
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
};
|
|
@@ -8,8 +8,13 @@
|
|
|
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
15
|
import { nexusEventBus } from '../../../engines/event-bus.js';
|
|
16
|
+
import { recordPerf } from '../../../engines/perf-history.js';
|
|
17
|
+
export { envelopeToMcpResponse } from './envelope.js';
|
|
13
18
|
// ─── Per-client timeout map ───────────────────────────────────────────────────
|
|
14
19
|
const CLIENT_TIMEOUTS = {
|
|
15
20
|
'codex': 90_000,
|
|
@@ -25,12 +30,7 @@ function resolveTimeout(opts) {
|
|
|
25
30
|
}
|
|
26
31
|
return DEFAULT_TIMEOUT;
|
|
27
32
|
}
|
|
28
|
-
// ───
|
|
29
|
-
const RETRIABLE_RE = /SQLITE_BUSY|SQLITE_LOCKED|synapse runtime not yet|runtime not yet ready/i;
|
|
30
|
-
function isRetriable(err) {
|
|
31
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
32
|
-
return RETRIABLE_RE.test(msg);
|
|
33
|
-
}
|
|
33
|
+
// ─── Error classification ─────────────────────────────────────────────────────
|
|
34
34
|
function classifyError(err) {
|
|
35
35
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36
36
|
if (/SQLITE_BUSY|SQLITE_LOCKED/i.test(msg))
|
|
@@ -41,6 +41,28 @@ function classifyError(err) {
|
|
|
41
41
|
return 'input-invalid';
|
|
42
42
|
return 'internal';
|
|
43
43
|
}
|
|
44
|
+
const RETRY_POLICIES = {
|
|
45
|
+
// SQLite lock: 3 retries with exponential backoff (100 → 300 → 900 ms).
|
|
46
|
+
'sqlite-busy': {
|
|
47
|
+
maxRetries: 3,
|
|
48
|
+
backoffMs: (attempt) => 100 * Math.pow(3, attempt - 1),
|
|
49
|
+
},
|
|
50
|
+
// Cold runtime: 1 immediate retry (the runtime may warm up in milliseconds).
|
|
51
|
+
'runtime-cold': {
|
|
52
|
+
maxRetries: 1,
|
|
53
|
+
backoffMs: () => 0,
|
|
54
|
+
},
|
|
55
|
+
// Bad input and timeouts are never retried — retrying won't fix them.
|
|
56
|
+
'input-invalid': { maxRetries: 0, backoffMs: () => 0 },
|
|
57
|
+
'timeout': { maxRetries: 0, backoffMs: () => 0 },
|
|
58
|
+
};
|
|
59
|
+
const DEFAULT_RETRY_POLICY = {
|
|
60
|
+
maxRetries: 1,
|
|
61
|
+
backoffMs: () => 200,
|
|
62
|
+
};
|
|
63
|
+
function getRetryPolicy(code) {
|
|
64
|
+
return RETRY_POLICIES[code] ?? DEFAULT_RETRY_POLICY;
|
|
65
|
+
}
|
|
44
66
|
// ─── Core wrapper ─────────────────────────────────────────────────────────────
|
|
45
67
|
/**
|
|
46
68
|
* Run a handler function with timeout, retry, and structured envelope.
|
|
@@ -53,7 +75,6 @@ function classifyError(err) {
|
|
|
53
75
|
*/
|
|
54
76
|
export async function runHandler(toolName, fn, opts = {}) {
|
|
55
77
|
const timeoutMs = resolveTimeout(opts);
|
|
56
|
-
const maxRetries = opts.retries ?? 1;
|
|
57
78
|
const startMs = Date.now();
|
|
58
79
|
let attempts = 0;
|
|
59
80
|
// eslint-disable-next-line no-constant-condition -- retry loop exits via return/break
|
|
@@ -77,22 +98,34 @@ export async function runHandler(toolName, fn, opts = {}) {
|
|
|
77
98
|
},
|
|
78
99
|
};
|
|
79
100
|
nexusEventBus.emit('mcp.handler.complete', { toolName, attempts, durationMs: envelope.meta.durationMs });
|
|
101
|
+
recordPerf(toolName, envelope.meta.durationMs);
|
|
80
102
|
return envelope;
|
|
81
103
|
}
|
|
82
104
|
catch (err) {
|
|
83
105
|
clearTimeout(timeoutHandle);
|
|
84
|
-
const isTimeout = err instanceof Error && err.message === '__nexus_timeout__'
|
|
85
|
-
|
|
106
|
+
const isTimeout = err instanceof Error && (err.message === '__nexus_timeout__' ||
|
|
107
|
+
err.message === '__nexus_pipeline_timeout__');
|
|
108
|
+
const code = isTimeout ? 'timeout' : classifyError(err);
|
|
109
|
+
const policy = getRetryPolicy(code);
|
|
110
|
+
// opts.retries overrides the policy maxRetries if provided explicitly.
|
|
111
|
+
const maxRetries = opts.retries !== undefined ? opts.retries : policy.maxRetries;
|
|
112
|
+
const canRetry = attempts <= maxRetries;
|
|
86
113
|
if (canRetry) {
|
|
87
|
-
|
|
88
|
-
|
|
114
|
+
const delay = policy.backoffMs(attempts);
|
|
115
|
+
nexusEventBus.emit('mcp.handler.retry', {
|
|
116
|
+
toolName,
|
|
117
|
+
code,
|
|
118
|
+
attempt: attempts,
|
|
119
|
+
delayMs: delay,
|
|
120
|
+
});
|
|
121
|
+
if (delay > 0)
|
|
122
|
+
await new Promise(r => setTimeout(r, delay));
|
|
89
123
|
continue;
|
|
90
124
|
}
|
|
91
|
-
const code = isTimeout ? 'timeout' : classifyError(err);
|
|
92
125
|
const message = isTimeout
|
|
93
126
|
? `Handler timed out after ${timeoutMs}ms`
|
|
94
127
|
: (err instanceof Error ? err.message : String(err));
|
|
95
|
-
const retriable =
|
|
128
|
+
const retriable = policy.maxRetries > 0 && !isTimeout;
|
|
96
129
|
const envelope = {
|
|
97
130
|
ok: false,
|
|
98
131
|
error: {
|
|
@@ -115,25 +148,3 @@ export async function runHandler(toolName, fn, opts = {}) {
|
|
|
115
148
|
}
|
|
116
149
|
}
|
|
117
150
|
}
|
|
118
|
-
/** Convert a HandlerEnvelope into the MCP tool-call response shape. */
|
|
119
|
-
export function envelopeToMcpResponse(envelope) {
|
|
120
|
-
if (envelope.ok) {
|
|
121
|
-
const text = typeof envelope.data === 'string'
|
|
122
|
-
? envelope.data
|
|
123
|
-
: JSON.stringify(envelope.data, null, 2);
|
|
124
|
-
return { content: [{ type: 'text', text }] };
|
|
125
|
-
}
|
|
126
|
-
return {
|
|
127
|
-
content: [{
|
|
128
|
-
type: 'text',
|
|
129
|
-
text: JSON.stringify({
|
|
130
|
-
status: 'error',
|
|
131
|
-
code: envelope.error.code,
|
|
132
|
-
message: envelope.error.message,
|
|
133
|
-
retriable: envelope.error.retriable,
|
|
134
|
-
hint: envelope.error.hint,
|
|
135
|
-
meta: envelope.meta,
|
|
136
|
-
}, null, 2),
|
|
137
|
-
}],
|
|
138
|
-
};
|
|
139
|
-
}
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Detect which MCP client is invoking nexus-prime.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1.
|
|
6
|
-
* 2.
|
|
4
|
+
* Three tiers (highest-priority first):
|
|
5
|
+
* 1. setMcpClientName() — from MCP initialize handshake clientInfo.name (most reliable)
|
|
6
|
+
* 2. detectCallerFromEnv() — sync env-var detection, covers ~99% of real clients
|
|
7
|
+
* 3. detectCallerAsync() — async ps(1) fallback for edge cases (no env vars)
|
|
7
8
|
*
|
|
8
|
-
* The MCP adapter constructor uses tier-
|
|
9
|
-
*
|
|
9
|
+
* The MCP adapter constructor uses tier-2 for immediate init, then the Server's
|
|
10
|
+
* oninitialized callback calls setMcpClientName() (tier-1) once the handshake
|
|
11
|
+
* completes. detectCallerAsync() falls through only when tier-1 and tier-2 miss.
|
|
10
12
|
*/
|
|
13
|
+
/**
|
|
14
|
+
* Store the caller identity obtained from the MCP `initialize` handshake
|
|
15
|
+
* `clientInfo.name` field. Pass an empty string to clear.
|
|
16
|
+
* Called by the MCP adapter's `oninitialized` callback.
|
|
17
|
+
*/
|
|
18
|
+
export declare function setMcpClientName(rawName: string): void;
|
|
11
19
|
/** Instant env-variable detection. Safe to call in a constructor. */
|
|
12
20
|
export declare function detectCallerFromEnv(): string;
|
|
13
|
-
/** Full detection
|
|
21
|
+
/** Full detection: MCP handshake name → env vars → ps(1) fallback. */
|
|
14
22
|
export declare function detectCallerAsync(): Promise<string>;
|