nexus-prime 7.3.1 → 7.5.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.
- package/README.md +18 -0
- package/dist/adapters/hooks/context.d.ts +2 -2
- package/dist/adapters/hooks/index.d.ts +2 -2
- package/dist/agents/adapters/ide-compat.js +4 -1
- package/dist/agents/adapters/mcp/definitions.d.ts +3 -0
- package/dist/agents/adapters/mcp/definitions.js +83 -1
- package/dist/agents/adapters/mcp/handlers/governance.js +3 -2
- package/dist/agents/adapters/mcp/handlers/memory.js +8 -3
- package/dist/agents/adapters/mcp/handlers/orchestration.js +27 -11
- package/dist/agents/adapters/mcp/helpers.d.ts +0 -2
- package/dist/agents/adapters/mcp/helpers.js +0 -7
- package/dist/agents/adapters/mcp/util/token-engine.d.ts +2 -0
- package/dist/agents/adapters/mcp/util/token-engine.js +7 -0
- package/dist/agents/adapters/mcp.js +13 -12
- package/dist/cli/hook.d.ts +9 -1
- package/dist/cli/hook.js +11 -2
- package/dist/cli/install-wizard.js +4 -1
- package/dist/cli.js +8 -0
- package/dist/daemon/server.js +7 -8
- package/dist/dashboard/app/index.html +4 -1
- package/dist/dashboard/app/main.js +11 -0
- package/dist/dashboard/app/state.js +4 -0
- package/dist/dashboard/app/styles/tokens.css +5 -9
- package/dist/dashboard/app/views/board.js +65 -0
- package/dist/dashboard/app/views/knowledge.js +8 -4
- package/dist/dashboard/app/views/repo.js +113 -24
- package/dist/dashboard/routes/graph.js +218 -88
- package/dist/dashboard/server.js +6 -1
- package/dist/dashboard/stream/sse-broker.js +21 -15
- package/dist/engines/client-bootstrap.js +27 -3
- package/dist/engines/context-assembler.d.ts +1 -1
- package/dist/engines/context-assembler.js +12 -7
- package/dist/engines/event-bus.d.ts +29 -1
- package/dist/engines/generated-specialist-loader.js +25 -3
- package/dist/engines/instruction-gateway.js +9 -5
- package/dist/engines/machine-efficiency/types.js +5 -1
- package/dist/engines/memory.d.ts +6 -0
- package/dist/engines/memory.js +32 -16
- package/dist/engines/orchestrator.js +54 -25
- package/dist/engines/token-supremacy.d.ts +2 -2
- package/dist/engines/token-supremacy.js +4 -4
- package/dist/engines/workspace-resolver.js +6 -10
- package/dist/index.js +62 -35
- package/dist/kernel/context/service.d.ts +2 -2
- package/dist/kernel/index.d.ts +2 -2
- package/dist/phantom/runtime.d.ts +1 -1
- package/dist/phantom/runtime.js +83 -7
- package/package.json +4 -3
- package/dist/agents/adapters/mcp/util/auto-memory.d.ts +0 -15
- package/dist/agents/adapters/mcp/util/auto-memory.js +0 -23
package/README.md
CHANGED
|
@@ -49,8 +49,10 @@
|
|
|
49
49
|
- [The problem](#the-problem)
|
|
50
50
|
- [What changes when you install](#what-changes-when-you-install)
|
|
51
51
|
- [Quick start](#quick-start)
|
|
52
|
+
- [Docs and comparison](#docs-and-comparison)
|
|
52
53
|
- [Features](#features)
|
|
53
54
|
- [See it in action](#see-it-in-action)
|
|
55
|
+
- [Competitive position](#competitive-position)
|
|
54
56
|
- [Works with](#works-with)
|
|
55
57
|
- [What users see](#what-users-see)
|
|
56
58
|
- [Who it's for](#who-its-for)
|
|
@@ -62,6 +64,16 @@
|
|
|
62
64
|
|
|
63
65
|
---
|
|
64
66
|
|
|
67
|
+
## Docs and comparison
|
|
68
|
+
|
|
69
|
+
- Website: https://nexus-prime.cfd/
|
|
70
|
+
- Comparison: https://nexus-prime.cfd/comparison.html
|
|
71
|
+
- Knowledge base: https://nexus-prime.cfd/knowledge-base.html
|
|
72
|
+
|
|
73
|
+
Agents should start with `nexus_session_bootstrap`, then route the raw request through `nexus_orchestrate`. Auto-bootstrap runs on first non-bootstrap call for compatible clients, but the explicit bootstrap-first path remains the safest integration contract.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
65
77
|
## The problem
|
|
66
78
|
|
|
67
79
|
Every coding agent you use starts every session cold.
|
|
@@ -269,6 +281,12 @@ No benchmarks from a press release — this is what the dashboard shows you, on
|
|
|
269
281
|
|
|
270
282
|
---
|
|
271
283
|
|
|
284
|
+
## Competitive position
|
|
285
|
+
|
|
286
|
+
Nexus Prime is a local-first control plane for coding agents: persistent memory, workspace-scoped runtime state, dashboard observability, and MCP-native orchestration in one install. The public comparison page tracks where it differs from other agent frameworks and developer orchestrators: https://nexus-prime.cfd/comparison.html
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
272
290
|
## Who it's for
|
|
273
291
|
|
|
274
292
|
Nexus Prime is for people who take AI-assisted coding seriously:
|
|
@@ -12,11 +12,11 @@ export declare const ContextHooks: {
|
|
|
12
12
|
readonly hypertuneMax: (task: string, files: FileRef[], graphConnectivity?: (chunk: {
|
|
13
13
|
source: string;
|
|
14
14
|
label: string;
|
|
15
|
-
}) => number) => {
|
|
15
|
+
}) => number) => Promise<{
|
|
16
16
|
plan: ReadingPlan;
|
|
17
17
|
assembly: AssemblyResult;
|
|
18
18
|
budgetConfig: BudgetConfig;
|
|
19
|
-
}
|
|
19
|
+
}>;
|
|
20
20
|
readonly differential: (prev: SessionSummary, curr: FileRef[]) => ContextDelta;
|
|
21
21
|
readonly loadLatestSessionSummary: () => Promise<SessionSummary | null>;
|
|
22
22
|
readonly allocateBudget: (workers: Array<{
|
|
@@ -37,11 +37,11 @@ export declare const Hooks: {
|
|
|
37
37
|
readonly hypertuneMax: (task: string, files: FileRef[], graphConnectivity?: (chunk: {
|
|
38
38
|
source: string;
|
|
39
39
|
label: string;
|
|
40
|
-
}) => number) => {
|
|
40
|
+
}) => number) => Promise<{
|
|
41
41
|
plan: import("../../engines/token-supremacy.js").ReadingPlan;
|
|
42
42
|
assembly: import("../../engines/context-assembler.js").AssemblyResult;
|
|
43
43
|
budgetConfig: import("../../engines/context-assembler.js").BudgetConfig;
|
|
44
|
-
}
|
|
44
|
+
}>;
|
|
45
45
|
readonly differential: (prev: import("../../engines/token-supremacy.js").SessionSummary, curr: FileRef[]) => import("../../engines/token-supremacy.js").ContextDelta;
|
|
46
46
|
readonly loadLatestSessionSummary: () => Promise<import("../../engines/token-supremacy.js").SessionSummary | null>;
|
|
47
47
|
readonly allocateBudget: (workers: Array<{
|
|
@@ -13,7 +13,10 @@ function nexusMcpServerEntry(workspaceRoot) {
|
|
|
13
13
|
return {
|
|
14
14
|
command: 'node',
|
|
15
15
|
args: [join(workspaceRoot, 'node_modules', 'nexus-prime', 'dist', 'cli.js'), 'mcp'],
|
|
16
|
-
env: {
|
|
16
|
+
env: {
|
|
17
|
+
NEXUS_MCP_TOOL_PROFILE: 'autonomous',
|
|
18
|
+
NEXUS_WORKSPACE_ROOT: workspaceRoot,
|
|
19
|
+
},
|
|
17
20
|
};
|
|
18
21
|
}
|
|
19
22
|
function hasAnyEnvPrefix(prefix) {
|
|
@@ -2,5 +2,8 @@ export type McpToolDefinition = {
|
|
|
2
2
|
name: string;
|
|
3
3
|
description: string;
|
|
4
4
|
inputSchema: Record<string, unknown>;
|
|
5
|
+
deprecated?: true;
|
|
6
|
+
deprecatedReplacement?: string;
|
|
5
7
|
};
|
|
8
|
+
export declare const FIRST_CLASS_TOOLS: Set<string>;
|
|
6
9
|
export declare function buildMcpToolDefinitions(): McpToolDefinition[];
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { synapseToolDefinitions } from '../../../synapse/index.js';
|
|
2
2
|
import { architectsToolDefinitions } from '../../../architects/index.js';
|
|
3
3
|
import { getGstackBridge } from '../../../engines/gstack-bridge.js';
|
|
4
|
+
export const FIRST_CLASS_TOOLS = new Set([
|
|
5
|
+
'nexus_session_bootstrap',
|
|
6
|
+
'nexus_orchestrate',
|
|
7
|
+
'nexus_session_dna',
|
|
8
|
+
'nexus_store_memory',
|
|
9
|
+
'nexus_recall_memory',
|
|
10
|
+
'nexus_memory_stats',
|
|
11
|
+
'nexus_optimize_tokens',
|
|
12
|
+
'nexus_mindkit_check',
|
|
13
|
+
'nexus_ghost_pass',
|
|
14
|
+
'nexus_describe_tool',
|
|
15
|
+
'nexus_search',
|
|
16
|
+
'nexus_runtime_health',
|
|
17
|
+
'nexus_run_status',
|
|
18
|
+
'kernel_run_step',
|
|
19
|
+
'kernel_run_verify',
|
|
20
|
+
'kernel_run_merge',
|
|
21
|
+
]);
|
|
4
22
|
export function buildMcpToolDefinitions() {
|
|
5
|
-
|
|
23
|
+
const tools = [
|
|
6
24
|
// ── Memory ────────────────────────────────────────────────────────
|
|
7
25
|
{
|
|
8
26
|
name: 'nexus_store_memory',
|
|
@@ -1048,7 +1066,71 @@ export function buildMcpToolDefinitions() {
|
|
|
1048
1066
|
},
|
|
1049
1067
|
},
|
|
1050
1068
|
},
|
|
1069
|
+
{
|
|
1070
|
+
name: 'kernel_run_step',
|
|
1071
|
+
description: 'Run a mutation step inside an isolated git worktree and record it in the kernel ledger. Returns worktreeRef, commitSha, changedFiles. Merge requires a subsequent kernel_run_verify.',
|
|
1072
|
+
inputSchema: {
|
|
1073
|
+
type: 'object',
|
|
1074
|
+
properties: {
|
|
1075
|
+
runId: { type: 'string' },
|
|
1076
|
+
stepId: { type: 'string' },
|
|
1077
|
+
task: { type: 'string' },
|
|
1078
|
+
intent: { type: 'string' },
|
|
1079
|
+
baseRef: { type: 'string', description: 'Ref/branch/sha to branch off. Defaults to HEAD.' },
|
|
1080
|
+
worktreeHintRef: { type: 'string', description: 'Optional branch label override.' },
|
|
1081
|
+
mutations: {
|
|
1082
|
+
type: 'array',
|
|
1083
|
+
items: {
|
|
1084
|
+
type: 'object',
|
|
1085
|
+
properties: {
|
|
1086
|
+
kind: { type: 'string', enum: ['write_file', 'append_file', 'delete_file', 'run_command'] },
|
|
1087
|
+
path: { type: 'string' },
|
|
1088
|
+
content: { type: 'string' },
|
|
1089
|
+
command: { type: 'string' },
|
|
1090
|
+
cwd: { type: 'string' },
|
|
1091
|
+
},
|
|
1092
|
+
required: ['kind'],
|
|
1093
|
+
},
|
|
1094
|
+
},
|
|
1095
|
+
metadata: { type: 'object' },
|
|
1096
|
+
},
|
|
1097
|
+
required: ['runId', 'stepId', 'task'],
|
|
1098
|
+
},
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
name: 'kernel_run_verify',
|
|
1102
|
+
description: 'Hash the files changed by a kernel step and optionally run registered verifiers. Records the snapshot used to detect stale-verify at merge time.',
|
|
1103
|
+
inputSchema: {
|
|
1104
|
+
type: 'object',
|
|
1105
|
+
properties: {
|
|
1106
|
+
runId: { type: 'string' },
|
|
1107
|
+
stepId: { type: 'string' },
|
|
1108
|
+
verifierIds: { type: 'array', items: { type: 'string' } },
|
|
1109
|
+
metadata: { type: 'object' },
|
|
1110
|
+
},
|
|
1111
|
+
required: ['runId', 'stepId'],
|
|
1112
|
+
},
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
name: 'kernel_run_merge',
|
|
1116
|
+
description: 'Fast-forward targetRef to a verified kernel step. Rejects when verify is missing, failed, or stale.',
|
|
1117
|
+
inputSchema: {
|
|
1118
|
+
type: 'object',
|
|
1119
|
+
properties: {
|
|
1120
|
+
runId: { type: 'string' },
|
|
1121
|
+
stepId: { type: 'string' },
|
|
1122
|
+
verifyId: { type: 'string', description: 'Explicit verify pin. If omitted, latest passed verify is used.' },
|
|
1123
|
+
targetRef: { type: 'string' },
|
|
1124
|
+
reason: { type: 'string' },
|
|
1125
|
+
metadata: { type: 'object' },
|
|
1126
|
+
},
|
|
1127
|
+
required: ['runId', 'stepId', 'targetRef'],
|
|
1128
|
+
},
|
|
1129
|
+
},
|
|
1051
1130
|
// ── Embedded capabilities (auto-detected from installed skills) ──
|
|
1052
1131
|
...getGstackBridge().getToolDefinitions(),
|
|
1053
1132
|
];
|
|
1133
|
+
return tools.map((tool) => FIRST_CLASS_TOOLS.has(tool.name)
|
|
1134
|
+
? tool
|
|
1135
|
+
: { ...tool, deprecated: true, deprecatedReplacement: tool.deprecatedReplacement ?? 'nexus_orchestrate' });
|
|
1054
1136
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* graph_query, hypertune_max.
|
|
4
4
|
* Extracted from mcp.ts (Phase 3 split).
|
|
5
5
|
*/
|
|
6
|
-
import { formatBullets, formatJsonDetails,
|
|
6
|
+
import { formatBullets, formatJsonDetails, getGraphEngine, getTraversalEngine, getHybridRetriever, } from '../helpers.js';
|
|
7
|
+
import { getTokenEngine } from '../util/token-engine.js';
|
|
7
8
|
import { nexusEventBus } from '../../../../engines/event-bus.js';
|
|
8
9
|
import { formatBrandedResponse } from '../../../../engines/nexus-brand.js';
|
|
9
10
|
import { formatReadingPlan } from '../../../../engines/token-supremacy.js';
|
|
@@ -289,7 +290,7 @@ export async function handleGovernanceGroup(toolName, hctx, request, args, ctx)
|
|
|
289
290
|
return { path: resolved, sizeBytes: 0 };
|
|
290
291
|
}
|
|
291
292
|
})))).filter((f) => f.sizeBytes > 0);
|
|
292
|
-
const { plan, assembly, budgetConfig } = getTokenEngine().hypertuneMax(task, files);
|
|
293
|
+
const { plan, assembly, budgetConfig } = await getTokenEngine().hypertuneMax(task, files);
|
|
293
294
|
const planText = formatReadingPlan(plan);
|
|
294
295
|
const assemblyText = ContextAssembler.format(assembly, budgetConfig);
|
|
295
296
|
const savings = plan.savings;
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
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
|
-
import { storeToolSummary } from '../util/auto-memory.js';
|
|
11
10
|
import { requireRuntime } from '../util/require-runtime.js';
|
|
12
11
|
import { nxlResult } from '../../../../nxl/index.js';
|
|
13
12
|
import { consolidateMemory } from '../../../../engines/memory-consolidator.js';
|
|
@@ -368,9 +367,15 @@ export async function handleMemoryGroup(toolName, hctx, request, args, ctx) {
|
|
|
368
367
|
states,
|
|
369
368
|
auditLimit: limit,
|
|
370
369
|
});
|
|
371
|
-
//
|
|
370
|
+
// Surface hygiene-sweep on the SSE feed; do not persist as a memory.
|
|
372
371
|
try {
|
|
373
|
-
|
|
372
|
+
nexusEventBus.emit('memory.snapshot', {
|
|
373
|
+
kind: 'hygiene-sweep',
|
|
374
|
+
mode,
|
|
375
|
+
scanned: result.audit.scanned,
|
|
376
|
+
purgeEligible: result.health.purgeEligible,
|
|
377
|
+
quarantineBacklog: result.health.quarantineBacklog,
|
|
378
|
+
});
|
|
374
379
|
}
|
|
375
380
|
catch { /* best-effort */ }
|
|
376
381
|
return {
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* mindkit_check, ghost_pass, spawn_workers, session_dna, plan_execution.
|
|
4
4
|
* Extracted from mcp.ts (Phase 3 split).
|
|
5
5
|
*/
|
|
6
|
-
import { normalizeDetailLevel, normalizeBootstrapDepth, normalizeResponseIntent, normalizeResponseTopology, buildWorkspaceEnvelope, formatBullets, formatJsonDetails,
|
|
6
|
+
import { normalizeDetailLevel, normalizeBootstrapDepth, normalizeResponseIntent, normalizeResponseTopology, buildWorkspaceEnvelope, formatBullets, formatJsonDetails, getGuardrailEngine, truncateText, } from '../helpers.js';
|
|
7
|
+
import { getTokenEngine } from '../util/token-engine.js';
|
|
7
8
|
import { nexusEventBus } from '../../../../engines/event-bus.js';
|
|
8
9
|
import { formatBrandedResponse, getRandomQuote } from '../../../../engines/nexus-brand.js';
|
|
9
10
|
import { hasValidBootstrapReceipt } from '../../../../engines/bootstrap/index.js';
|
|
@@ -16,7 +17,6 @@ import { promises as fsPromises } from 'fs';
|
|
|
16
17
|
import { getSharedLicenseManager } from '../../../../licensing/index.js';
|
|
17
18
|
import { SessionDNAManager } from '../../../../engines/session-dna.js';
|
|
18
19
|
import { getSharedTelemetry } from '../../../../engines/telemetry-remote.js';
|
|
19
|
-
import { storeToolSummary } from '../util/auto-memory.js';
|
|
20
20
|
import { requireRuntime } from '../util/require-runtime.js';
|
|
21
21
|
import { ensureCrGraphBuilt } from '../../../../engines/code-review-graph-client.js';
|
|
22
22
|
import { recordFirstBootstrap } from '../../../../engines/telemetry.js';
|
|
@@ -136,10 +136,16 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
136
136
|
ctx.meta.repoRoot = workspace.repoRoot;
|
|
137
137
|
ctx.meta.repoName = workspace.repoName;
|
|
138
138
|
}
|
|
139
|
-
//
|
|
140
|
-
//
|
|
139
|
+
// Surface a session-bootstrap signal on the SSE feed without polluting persistent
|
|
140
|
+
// memory. Audit-log content like "Session bootstrap: ..." was previously stored as
|
|
141
|
+
// a real memory (priority 0.4) which dominated recall results and forced low-signal
|
|
142
|
+
// memories into hippocampus.
|
|
141
143
|
try {
|
|
142
|
-
|
|
144
|
+
nexusEventBus.emit('memory.snapshot', {
|
|
145
|
+
kind: 'session-bootstrap',
|
|
146
|
+
goal: bootstrapGoal || 'interactive session',
|
|
147
|
+
memoryStats: bootstrap.memoryStats,
|
|
148
|
+
});
|
|
143
149
|
}
|
|
144
150
|
catch (err) {
|
|
145
151
|
nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'persist-session-summary', error: err instanceof Error ? err.message : String(err) });
|
|
@@ -411,7 +417,10 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
411
417
|
result.modifiedFiles.forEach((file) => hctx.sessionDNA.recordFileModified(file));
|
|
412
418
|
});
|
|
413
419
|
const runtimeUsage = hctx.getRuntime().getUsageSnapshot();
|
|
414
|
-
hctx.sessionDNA.recordDecision('Orchestrated autonomous run completed', execution.result || summarizeExecution(execution), execution.state === 'merged' ? 0.95
|
|
420
|
+
hctx.sessionDNA.recordDecision('Orchestrated autonomous run completed', execution.result || summarizeExecution(execution), execution.state === 'merged' ? 0.95
|
|
421
|
+
: execution.state === 'inspected' ? 0.85
|
|
422
|
+
: execution.state === 'rolled_back' ? 0.55
|
|
423
|
+
: 0.3);
|
|
415
424
|
const timings = {
|
|
416
425
|
totalMs: Date.now() - callStartedAt,
|
|
417
426
|
};
|
|
@@ -738,10 +747,14 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
738
747
|
? String(request.params.arguments.executionPreset)
|
|
739
748
|
: undefined;
|
|
740
749
|
const preset = resolveExecutionPreset(executionPreset);
|
|
741
|
-
//
|
|
742
|
-
// shows something even if the run is still in progress.
|
|
750
|
+
// Surface worker-plan intent on the SSE feed without persisting it as a memory.
|
|
743
751
|
try {
|
|
744
|
-
|
|
752
|
+
nexusEventBus.emit('memory.snapshot', {
|
|
753
|
+
kind: 'worker-plan',
|
|
754
|
+
goal: goal.slice(0, 100),
|
|
755
|
+
workers: workersCount,
|
|
756
|
+
files: rawFiles.length,
|
|
757
|
+
});
|
|
745
758
|
}
|
|
746
759
|
catch (err) {
|
|
747
760
|
nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'worker-plan-summary', error: err instanceof Error ? err.message : String(err) });
|
|
@@ -775,7 +788,10 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
775
788
|
execution.workerResults.forEach(result => {
|
|
776
789
|
result.modifiedFiles.forEach(file => hctx.sessionDNA.recordFileModified(file));
|
|
777
790
|
});
|
|
778
|
-
hctx.sessionDNA.recordDecision('Runtime swarm execution completed', execution.result || summarizeExecution(execution), execution.state === 'merged' ? 0.94
|
|
791
|
+
hctx.sessionDNA.recordDecision('Runtime swarm execution completed', execution.result || summarizeExecution(execution), execution.state === 'merged' ? 0.94
|
|
792
|
+
: execution.state === 'inspected' ? 0.85
|
|
793
|
+
: execution.state === 'rolled_back' ? 0.45
|
|
794
|
+
: 0.3);
|
|
779
795
|
hctx.nexusRef.storeMemory(`Runtime swarm: state=${execution.state}, workers=${execution.workerResults.length}, verified=${verifiedWorkers}, decision=${execution.finalDecision?.action ?? 'none'}`, execution.state === 'merged' ? 0.92 : 0.72, ['#phantom', '#decision', execution.state]);
|
|
780
796
|
if (execution.finalDecision) {
|
|
781
797
|
nexusEventBus.emit('phantom.merge', {
|
|
@@ -789,7 +805,7 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
|
|
|
789
805
|
`Workers: ${execution.workerResults.length.toString().padEnd(5, ' ')} Verified: ${verifiedWorkers.toString().padEnd(10, ' ')} Files: ${String(modifiedFiles).padEnd(12, ' ')}`,
|
|
790
806
|
`${`Preset: ${preset?.name ?? 'manual'}`.padEnd(61, ' ')}`,
|
|
791
807
|
`Decision: ${(execution.finalDecision?.action ?? 'none').padEnd(52, ' ')}`
|
|
792
|
-
], execution.state === 'merged' ? '32' : execution.state === 'rolled_back' ? '33' : '31');
|
|
808
|
+
], execution.state === 'merged' || execution.state === 'inspected' ? '32' : execution.state === 'rolled_back' ? '33' : '31');
|
|
793
809
|
return {
|
|
794
810
|
content: [{
|
|
795
811
|
type: 'text',
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* These are pure functions and lazy-singleton getters shared by the
|
|
6
6
|
* handler files and by MCPAdapter itself.
|
|
7
7
|
*/
|
|
8
|
-
import { TokenSupremacyEngine } from '../../../engines/token-supremacy.js';
|
|
9
8
|
import { GuardrailEngine } from '../../../engines/guardrails-bridge.js';
|
|
10
9
|
import { ContinuousAttentionStream, createKVBridge, OrchestratorEngine } from '../../../engines/index.js';
|
|
11
10
|
import { FederationEngine } from '../../../engines/federation.js';
|
|
@@ -14,7 +13,6 @@ import { GraphTraversalEngine } from '../../../engines/graph-traversal.js';
|
|
|
14
13
|
import { HybridRetriever } from '../../../engines/hybrid-retriever.js';
|
|
15
14
|
import type { WorkspaceContext } from '../../../engines/workspace-resolver.js';
|
|
16
15
|
import type { SubAgentRuntime } from '../../../phantom/index.js';
|
|
17
|
-
export declare function getTokenEngine(): TokenSupremacyEngine;
|
|
18
16
|
export declare function getGuardrailEngine(): GuardrailEngine;
|
|
19
17
|
export declare function getCasEngine(): ContinuousAttentionStream;
|
|
20
18
|
export declare function getKvBridge(): ReturnType<typeof createKVBridge>;
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { statSync, readdirSync } from 'fs';
|
|
9
9
|
import * as path from 'path';
|
|
10
|
-
import { TokenSupremacyEngine } from '../../../engines/token-supremacy.js';
|
|
11
10
|
import { GuardrailEngine } from '../../../engines/guardrails-bridge.js';
|
|
12
11
|
import { ContinuousAttentionStream, createKVBridge, OrchestratorEngine, } from '../../../engines/index.js';
|
|
13
12
|
import { FederationEngine } from '../../../engines/federation.js';
|
|
@@ -16,7 +15,6 @@ import { GraphTraversalEngine } from '../../../engines/graph-traversal.js';
|
|
|
16
15
|
import { HybridRetriever } from '../../../engines/hybrid-retriever.js';
|
|
17
16
|
import { createSubAgentRuntime } from '../../../phantom/index.js';
|
|
18
17
|
// ─── Lazy-init engine singletons ─────────────────────────────────────────────
|
|
19
|
-
let _tokenEngine;
|
|
20
18
|
let _guardrailEngine;
|
|
21
19
|
let _casEngine;
|
|
22
20
|
let _kvBridge;
|
|
@@ -24,11 +22,6 @@ let _federation;
|
|
|
24
22
|
let _graphEngine = null;
|
|
25
23
|
let _traversalEngine = null;
|
|
26
24
|
let _hybridRetriever = null;
|
|
27
|
-
export function getTokenEngine() {
|
|
28
|
-
if (!_tokenEngine)
|
|
29
|
-
_tokenEngine = new TokenSupremacyEngine();
|
|
30
|
-
return _tokenEngine;
|
|
31
|
-
}
|
|
32
25
|
export function getGuardrailEngine() {
|
|
33
26
|
if (!_guardrailEngine)
|
|
34
27
|
_guardrailEngine = new GuardrailEngine();
|
|
@@ -830,21 +830,22 @@ export class MCPAdapter {
|
|
|
830
830
|
: { error: envelope.error.message }),
|
|
831
831
|
});
|
|
832
832
|
this.telemetry.observeSuccessfulToolCall(toolName, args);
|
|
833
|
-
//
|
|
834
|
-
//
|
|
835
|
-
//
|
|
836
|
-
//
|
|
837
|
-
// from the live SSE feed, so the dashboard event stream stays clean.
|
|
833
|
+
// Surface meaningful tool calls on the SSE feed without persisting them as memories.
|
|
834
|
+
// Previously a low-priority memory was auto-stored on every non-read-only tool call,
|
|
835
|
+
// which polluted recall with audit-log entries like "nexus_store_memory: priority=0.85,
|
|
836
|
+
// tags=...". Recall now stays focused on user-stored knowledge.
|
|
838
837
|
if (this.nexusRef && !isReadOnlyMcpTool(toolName)) {
|
|
839
838
|
const repoRoot = this.nexusRef.getWorkspaceContext?.()?.repoRoot ?? '';
|
|
840
839
|
const repoName = repoRoot ? path.basename(repoRoot) : '';
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
840
|
+
try {
|
|
841
|
+
nexusEventBus.emit('memory.snapshot', {
|
|
842
|
+
kind: 'tool-invocation',
|
|
843
|
+
toolName,
|
|
844
|
+
repo: repoName,
|
|
845
|
+
summary: buildAutoMemorySummary(toolName, args),
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
catch { /* best-effort */ }
|
|
848
849
|
}
|
|
849
850
|
const decorated = this.decorateLifecycleResponse(toolName, result);
|
|
850
851
|
return this.injectMemoryContext(toolName, args, decorated);
|
package/dist/cli/hook.d.ts
CHANGED
|
@@ -16,7 +16,15 @@
|
|
|
16
16
|
*/
|
|
17
17
|
/** UserPromptSubmit — call nexus_session_bootstrap so the model never has to. */
|
|
18
18
|
export declare function runHookBootstrap(): Promise<void>;
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* PostToolUse (Edit|Write|MultiEdit|Bash) — opt-in audit memory.
|
|
21
|
+
*
|
|
22
|
+
* Disabled by default because every Edit/Write/Bash was being stored as a
|
|
23
|
+
* low-priority memory, which polluted recall results with audit-log entries
|
|
24
|
+
* like "Edit: file_path=src/foo.ts". Real findings should be stored via
|
|
25
|
+
* nexus_store_memory by the agent itself. To opt back in, set
|
|
26
|
+
* NEXUS_HOOK_AUTO_MEMORY=1.
|
|
27
|
+
*/
|
|
20
28
|
export declare function runHookMemory(): Promise<void>;
|
|
21
29
|
/**
|
|
22
30
|
* PreToolUse (Edit|Write|MultiEdit) — governance check.
|
package/dist/cli/hook.js
CHANGED
|
@@ -149,8 +149,18 @@ export async function runHookBootstrap() {
|
|
|
149
149
|
goal: goal.slice(0, 500),
|
|
150
150
|
}, 10_000);
|
|
151
151
|
}
|
|
152
|
-
/**
|
|
152
|
+
/**
|
|
153
|
+
* PostToolUse (Edit|Write|MultiEdit|Bash) — opt-in audit memory.
|
|
154
|
+
*
|
|
155
|
+
* Disabled by default because every Edit/Write/Bash was being stored as a
|
|
156
|
+
* low-priority memory, which polluted recall results with audit-log entries
|
|
157
|
+
* like "Edit: file_path=src/foo.ts". Real findings should be stored via
|
|
158
|
+
* nexus_store_memory by the agent itself. To opt back in, set
|
|
159
|
+
* NEXUS_HOOK_AUTO_MEMORY=1.
|
|
160
|
+
*/
|
|
153
161
|
export async function runHookMemory() {
|
|
162
|
+
if (process.env.NEXUS_HOOK_AUTO_MEMORY !== '1')
|
|
163
|
+
return;
|
|
154
164
|
const data = await readStdinJson();
|
|
155
165
|
const cwd = String(data.cwd ?? process.cwd());
|
|
156
166
|
const toolName = String(data.tool_name ?? '');
|
|
@@ -163,7 +173,6 @@ export async function runHookMemory() {
|
|
|
163
173
|
if (!lock)
|
|
164
174
|
return;
|
|
165
175
|
const input = (data.tool_input ?? {});
|
|
166
|
-
// Summarize input without large content blobs
|
|
167
176
|
const inputSummary = Object.entries(input)
|
|
168
177
|
.filter(([k]) => !['content', 'new_string', 'old_string', 'result', 'command_result'].includes(k))
|
|
169
178
|
.map(([k, v]) => `${k}=${String(v).slice(0, 80)}`)
|
|
@@ -139,7 +139,10 @@ function _nexusMcpEntry(workspaceRoot) {
|
|
|
139
139
|
return {
|
|
140
140
|
command: 'node',
|
|
141
141
|
args: [join(workspaceRoot, 'node_modules', 'nexus-prime', 'dist', 'cli.js'), 'mcp'],
|
|
142
|
-
env: {
|
|
142
|
+
env: {
|
|
143
|
+
NEXUS_MCP_TOOL_PROFILE: 'autonomous',
|
|
144
|
+
NEXUS_WORKSPACE_ROOT: workspaceRoot,
|
|
145
|
+
},
|
|
143
146
|
};
|
|
144
147
|
}
|
|
145
148
|
/**
|
package/dist/cli.js
CHANGED
|
@@ -780,6 +780,14 @@ program
|
|
|
780
780
|
.addCommand(new Command('__serve')
|
|
781
781
|
.description('Internal: run the daemon server process (do not call directly)')
|
|
782
782
|
.action(async () => {
|
|
783
|
+
// Opt the daemon into the deferred-bootstrap fast-start path so the
|
|
784
|
+
// dashboard port listens before the (3+ second) workspace bootstrap
|
|
785
|
+
// file I/O completes. Tests that construct NexusPrime directly do not
|
|
786
|
+
// set this flag, so their synchronous workspace-file assertions still
|
|
787
|
+
// see a fully-initialized state by the time start() resolves.
|
|
788
|
+
if (process.env.NEXUS_DAEMON_FAST_START === undefined) {
|
|
789
|
+
process.env.NEXUS_DAEMON_FAST_START = '1';
|
|
790
|
+
}
|
|
783
791
|
const workspaceContext = resolveWorkspaceContext({ workspaceRoot: getWorkspaceRoot() });
|
|
784
792
|
const daemon = new NexusDaemonServer(workspaceContext);
|
|
785
793
|
const { started, record } = await daemon.start();
|
package/dist/daemon/server.js
CHANGED
|
@@ -185,14 +185,13 @@ export class NexusDaemonServer {
|
|
|
185
185
|
},
|
|
186
186
|
});
|
|
187
187
|
await this.nexus.start();
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
});
|
|
188
|
+
// Optional repo-search prewarm. It can be CPU-heavy in large workspaces, so
|
|
189
|
+
// keep daemon startup and dashboard responsiveness as the default behavior.
|
|
190
|
+
if (process.env.NEXUS_PREWARM_REPO_SEARCH === '1' && this.workspace.gitRoot) {
|
|
191
|
+
setImmediate(() => {
|
|
192
|
+
void this.nexus?.getOrchestrator().warmRepoSearchIndex().catch(() => { });
|
|
193
|
+
});
|
|
194
|
+
}
|
|
196
195
|
// Warm the invoker availability cache so /api/runtimes returns fast and
|
|
197
196
|
// the dashboard runtime badges render immediately on first load.
|
|
198
197
|
setImmediate(() => { invokerRegistry.warmCache(); });
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>Nexus Prime</title>
|
|
7
7
|
|
|
8
8
|
<!-- Design system -->
|
|
9
|
-
<link rel="stylesheet" href="./styles/tokens.css">
|
|
9
|
+
<link rel="stylesheet" href="./styles/tokens.css?v=4">
|
|
10
10
|
<link rel="stylesheet" href="./styles/shell.css">
|
|
11
11
|
<link rel="stylesheet" href="./styles/board.css">
|
|
12
12
|
<link rel="stylesheet" href="./styles/workforce.css">
|
|
@@ -113,6 +113,9 @@ if(location.protocol==='file:'){
|
|
|
113
113
|
<div><div class="kb-col-hd"><span class="kb-col-title">Done</span><span class="kb-count" id="kc-done">0</span></div><div class="kb-body" id="kb-done"></div></div>
|
|
114
114
|
</div>
|
|
115
115
|
|
|
116
|
+
<!-- Orchestration pipeline (live decomposition + completion) -->
|
|
117
|
+
<div id="orchestration-pipeline" class="card" style="margin-bottom:16px;display:none"></div>
|
|
118
|
+
|
|
116
119
|
<!-- Tool health strip -->
|
|
117
120
|
<div id="tool-health-card" class="card" style="margin-bottom:16px;display:none">
|
|
118
121
|
<div class="shd" style="margin-bottom:8px">Tool Health <span id="tool-health-stamp" style="font-size:11px;opacity:.5;font-weight:400"></span></div>
|
|
@@ -80,6 +80,17 @@ setOnEvent(evt => {
|
|
|
80
80
|
if (String(evt.type||'').startsWith('dispatch.')) {
|
|
81
81
|
Workforce.handleDispatchEvent(evt);
|
|
82
82
|
}
|
|
83
|
+
|
|
84
|
+
// Orchestration pipeline events — keep board fresh as decomposition / completion fires.
|
|
85
|
+
// The board's own SSE listener (board.js:loadOrchestrationPipeline) renders the detail card;
|
|
86
|
+
// here we just refresh the surface payload so kanban + KPIs reflect the new run.
|
|
87
|
+
if (String(evt.type||'').startsWith('orchestration.')) {
|
|
88
|
+
bustCache('/api/dashboard/surface/operate');
|
|
89
|
+
if (tab === 'board') {
|
|
90
|
+
Board.handleOrchestrationEvent?.(evt);
|
|
91
|
+
Board.render();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
83
94
|
// Workspace root promoted (e.g. from bootstrap hint) — refresh header immediately.
|
|
84
95
|
if (String(evt.type||'') === 'workspace.changed') {
|
|
85
96
|
bustCache('/api/workspace');
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* tokens.css — OKLCh design tokens, LATTICE typography scale, spacing, and reset.
|
|
3
3
|
* Lifted from index.html inline styles and kept as the single source of truth.
|
|
4
4
|
* Fonts: Instrument Serif (display/title), Geist (body/label), Geist Mono (data/caption).
|
|
5
|
-
*
|
|
5
|
+
* Local-first declarations avoid network/font 404s when optional subsets are absent.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/* ── @font-face declarations (local-first; graceful system fallback) ── */
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
font-style: normal;
|
|
12
12
|
font-weight: 400;
|
|
13
13
|
font-display: swap;
|
|
14
|
-
src: local('Instrument Serif')
|
|
15
|
-
url('../assets/fonts/InstrumentSerif-Regular.woff2') format('woff2');
|
|
14
|
+
src: local('Instrument Serif');
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
@font-face {
|
|
@@ -20,8 +19,7 @@
|
|
|
20
19
|
font-style: italic;
|
|
21
20
|
font-weight: 400;
|
|
22
21
|
font-display: swap;
|
|
23
|
-
src: local('Instrument Serif Italic')
|
|
24
|
-
url('../assets/fonts/InstrumentSerif-Italic.woff2') format('woff2');
|
|
22
|
+
src: local('Instrument Serif Italic');
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
@font-face {
|
|
@@ -29,8 +27,7 @@
|
|
|
29
27
|
font-style: normal;
|
|
30
28
|
font-weight: 400 600;
|
|
31
29
|
font-display: swap;
|
|
32
|
-
src: local('Geist')
|
|
33
|
-
url('../assets/fonts/Geist-Regular.woff2') format('woff2');
|
|
30
|
+
src: local('Geist');
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
@font-face {
|
|
@@ -38,8 +35,7 @@
|
|
|
38
35
|
font-style: normal;
|
|
39
36
|
font-weight: 400 600;
|
|
40
37
|
font-display: swap;
|
|
41
|
-
src: local('Geist Mono')
|
|
42
|
-
url('../assets/fonts/GeistMono-Regular.woff2') format('woff2');
|
|
38
|
+
src: local('Geist Mono');
|
|
43
39
|
}
|
|
44
40
|
|
|
45
41
|
:root {
|