nexus-prime 7.9.14 → 7.9.16
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 +22 -21
- package/dist/agents/adapters/mcp/handlers/runtime.js +12 -0
- package/dist/agents/adapters/mcp.d.ts +2 -0
- package/dist/agents/adapters/mcp.js +58 -6
- package/dist/cli/install-wizard.js +19 -0
- package/dist/cli.js +37 -6
- package/dist/dashboard/app/index.html +8 -0
- package/dist/dashboard/app/main.js +7 -0
- package/dist/dashboard/app/state.js +5 -0
- package/dist/dashboard/app/styles/board.css +163 -2
- package/dist/dashboard/app/styles/context-log.css +167 -0
- package/dist/dashboard/app/styles/memory.css +63 -0
- package/dist/dashboard/app/styles/workforce.css +21 -0
- package/dist/dashboard/app/views/board.js +145 -7
- package/dist/dashboard/app/views/context-log.js +158 -0
- package/dist/dashboard/app/views/license.js +36 -0
- package/dist/dashboard/app/views/memory.js +87 -3
- package/dist/dashboard/app/views/workforce.js +22 -6
- package/dist/dashboard/routes/events.js +80 -3
- package/dist/dashboard/stream/sse-broker.js +25 -13
- package/dist/engines/client-bootstrap.js +66 -20
- package/dist/engines/code-review-graph-client.d.ts +11 -3
- package/dist/engines/code-review-graph-client.js +151 -24
- package/dist/engines/instruction-gateway.js +6 -0
- package/dist/engines/mcp-entrypoint.js +3 -1
- package/dist/engines/orchestrator/decision-spine.d.ts +170 -0
- package/dist/engines/orchestrator/decision-spine.js +424 -0
- package/dist/engines/orchestrator/selection-policy.d.ts +39 -0
- package/dist/engines/orchestrator/selection-policy.js +32 -0
- package/dist/engines/orchestrator.js +19 -33
- package/dist/licensing/enforcement.js +25 -5
- package/dist/licensing/index.d.ts +1 -1
- package/dist/licensing/license-manager.js +110 -4
- package/dist/licensing/license-sync.js +4 -3
- package/dist/licensing/types.d.ts +19 -3
- package/dist/licensing/upgrade-prompts.d.ts +2 -2
- package/dist/licensing/upgrade-prompts.js +30 -9
- package/dist/licensing/web-auth.d.ts +2 -2
- package/dist/licensing/web-auth.js +6 -6
- package/dist/phantom/runtime.d.ts +16 -0
- package/dist/phantom/runtime.js +158 -20
- package/dist/postinstall-bootstrap.js +6 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
<p>
|
|
17
17
|
<img src="https://img.shields.io/badge/Protocol-MCP-4285F4?style=for-the-badge" alt="MCP Protocol">
|
|
18
18
|
<img src="https://img.shields.io/badge/license-Commercial-6f42c1?style=for-the-badge" alt="Commercial License">
|
|
19
|
-
<a href="https://nexus-prime.cfd/pricing"><img src="https://img.shields.io/badge/
|
|
20
|
-
<img src="https://img.shields.io/badge/
|
|
19
|
+
<a href="https://nexus-prime.cfd/pricing"><img src="https://img.shields.io/badge/3--day-grace%20then%20license-00ff88?style=for-the-badge" alt="3-day grace then license"></a>
|
|
20
|
+
<img src="https://img.shields.io/badge/licenses-reviewed%20within%2024h-ff69b4?style=for-the-badge" alt="Licenses reviewed within 24 hours">
|
|
21
21
|
<img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-444?style=for-the-badge" alt="Cross-platform">
|
|
22
22
|
</p>
|
|
23
23
|
|
|
@@ -305,7 +305,7 @@ If any of that sounds like you — keep reading.
|
|
|
305
305
|
|
|
306
306
|
<div align="center">
|
|
307
307
|
|
|
308
|
-
**
|
|
308
|
+
**3-day no-license grace. Request a license before day 4. Manual approvals within 24 hours.**
|
|
309
309
|
|
|
310
310
|
</div>
|
|
311
311
|
|
|
@@ -317,16 +317,16 @@ If any of that sounds like you — keep reading.
|
|
|
317
317
|
<th>Caps</th>
|
|
318
318
|
</tr>
|
|
319
319
|
<tr>
|
|
320
|
-
<td><b>🎁
|
|
321
|
-
<td>Everyone —
|
|
322
|
-
<td>
|
|
323
|
-
<td>
|
|
320
|
+
<td><b>🎁 Local Grace</b></td>
|
|
321
|
+
<td>Everyone — install and verify locally</td>
|
|
322
|
+
<td>3 days without a license</td>
|
|
323
|
+
<td>Runtime available during grace; license required after day 3</td>
|
|
324
324
|
</tr>
|
|
325
325
|
<tr>
|
|
326
326
|
<td><b>💎 Independent Creators</b></td>
|
|
327
327
|
<td>Indie builders, solo engineers, students, OSS maintainers</td>
|
|
328
|
-
<td
|
|
329
|
-
<td>
|
|
328
|
+
<td>Request access</td>
|
|
329
|
+
<td>Manual creator licenses reviewed by the team</td>
|
|
330
330
|
</tr>
|
|
331
331
|
<tr>
|
|
332
332
|
<td><b>🚀 Pilot Program</b></td>
|
|
@@ -356,10 +356,10 @@ If any of that sounds like you — keep reading.
|
|
|
356
356
|
|
|
357
357
|
```bash
|
|
358
358
|
nexus-prime license status # check your plan
|
|
359
|
-
nexus-prime license activate <key> # activate
|
|
359
|
+
nexus-prime license activate <key> # activate the key shared by the team
|
|
360
360
|
```
|
|
361
361
|
|
|
362
|
-
→ **[nexus-prime.cfd/
|
|
362
|
+
→ **[nexus-prime.cfd/account](https://nexus-prime.cfd/account)** · **[Request by email](mailto:adarsh@nexus-prime.cfd?subject=Nexus%20Prime%20license%20request)**
|
|
363
363
|
|
|
364
364
|
---
|
|
365
365
|
|
|
@@ -380,19 +380,19 @@ No — it supercharges them. Keep the agents you already love. Nexus Prime adds
|
|
|
380
380
|
<details>
|
|
381
381
|
<summary><b>What happens after the 30-day trial ends?</b></summary>
|
|
382
382
|
<br>
|
|
383
|
-
|
|
383
|
+
The local trial window ends and paid-tier work requires an active license. Your local memory and data stay on your machine; activate a license or request renewal from the account page to continue.
|
|
384
384
|
</details>
|
|
385
385
|
|
|
386
386
|
<details>
|
|
387
387
|
<summary><b>Is it free for indie developers and creators?</b></summary>
|
|
388
388
|
<br>
|
|
389
|
-
|
|
389
|
+
Creator access is reviewed manually. If you build independently — solo founder, indie dev, content creator, student, OSS maintainer — request a creator license from the account page or email <a href="mailto:adarsh@nexus-prime.cfd?subject=Creator%20Program">adarsh@nexus-prime.cfd</a>.
|
|
390
390
|
</details>
|
|
391
391
|
|
|
392
392
|
<details>
|
|
393
393
|
<summary><b>My team wants to try this across the whole engineering org. What's the pilot?</b></summary>
|
|
394
394
|
<br>
|
|
395
|
-
We're taking <b>10 companies</b> into our pilot program —
|
|
395
|
+
We're taking <b>10 companies</b> into our pilot program — white-glove onboarding, direct access to the team building it, and team licenses issued after review. <a href="mailto:adarsh@nexus-prime.cfd?subject=Pilot%20Program">Reach out</a>.
|
|
396
396
|
</details>
|
|
397
397
|
|
|
398
398
|
<details>
|
|
@@ -416,7 +416,7 @@ Each engineer runs their own local instance — nothing is shared across machine
|
|
|
416
416
|
<details>
|
|
417
417
|
<summary><b>What if I hit my plan's cap?</b></summary>
|
|
418
418
|
<br>
|
|
419
|
-
|
|
419
|
+
The app shows an upgrade request path and keeps your local data intact. Features above your licensed tier require an approved upgrade.
|
|
420
420
|
</details>
|
|
421
421
|
|
|
422
422
|
<details>
|
|
@@ -433,7 +433,7 @@ Nexus Prime was designed privacy-first, because the code on your machine is your
|
|
|
433
433
|
|
|
434
434
|
- 🏠 **100% local.** All data lives on your disk, in your home directory.
|
|
435
435
|
- 🚫 **No cloud sync.** Your code, your memory, your logs — never uploaded.
|
|
436
|
-
- 🔐 **
|
|
436
|
+
- 🔐 **Short no-account grace.** You can run locally for 3 days without signing up; a license is required after that grace period.
|
|
437
437
|
- 📊 **Telemetry is opt-in.** Off by default. When on, only aggregate, anonymous event counts are sent — never source code, never memory contents.
|
|
438
438
|
- 🗑️ **Uninstall is clean.** Everything lives in one directory you can delete.
|
|
439
439
|
|
|
@@ -448,7 +448,8 @@ Nexus Prime was designed privacy-first, because the code on your machine is your
|
|
|
448
448
|
| 💬 [**Discord**](https://discord.gg/tByGZgk5gS) | Real-time help, show-and-tell, feature ideas |
|
|
449
449
|
| 🔴 [**Reddit — r/Nexus_Prime**](https://www.reddit.com/r/Nexus_Prime/) | Long-form posts, releases, community wins |
|
|
450
450
|
| 🐦 [**X / Twitter**](https://x.com/nexusprime_ai) | Launch announcements, tips, updates |
|
|
451
|
-
| 📧 [**
|
|
451
|
+
| 📧 [**adarsh@nexus-prime.cfd**](mailto:adarsh@nexus-prime.cfd) | License requests, upgrades, pilots, enterprise |
|
|
452
|
+
| 📧 [**hello@nexus-prime.cfd**](mailto:hello@nexus-prime.cfd) | General support, press, community |
|
|
452
453
|
| 🌐 [**nexus-prime.cfd**](https://nexus-prime.cfd) | Product site, demos, pricing, setup guides |
|
|
453
454
|
|
|
454
455
|
</div>
|
|
@@ -457,11 +458,11 @@ Nexus Prime was designed privacy-first, because the code on your machine is your
|
|
|
457
458
|
|
|
458
459
|
## License
|
|
459
460
|
|
|
460
|
-
Nexus Prime is a **commercial product** with
|
|
461
|
+
Nexus Prime is a **commercial product** with manual license issuance:
|
|
461
462
|
|
|
462
|
-
- ✅
|
|
463
|
-
- ✅
|
|
464
|
-
- ✅
|
|
463
|
+
- ✅ 3-day local no-license grace, for everyone
|
|
464
|
+
- ✅ Manual creator, pilot, team, and enterprise license review
|
|
465
|
+
- ✅ License and upgrade requests reviewed within 24 hours
|
|
465
466
|
- 💳 Paid plans for professional, team, and enterprise usage
|
|
466
467
|
|
|
467
468
|
Commercial use without a valid license is prohibited. See [nexus-prime.cfd/pricing](https://nexus-prime.cfd/pricing) for current plans and terms.
|
|
@@ -38,11 +38,21 @@ export async function handleRuntimeGroup(toolName, hctx, request, args, ctx) {
|
|
|
38
38
|
}
|
|
39
39
|
// summary (default)
|
|
40
40
|
const licStatus = getSharedLicenseManager().getStatus();
|
|
41
|
+
const trialLines = licStatus.trialPhase ? [
|
|
42
|
+
`- **Trial phase**: ${licStatus.trialPhase}`,
|
|
43
|
+
typeof licStatus.trialDaysRemaining === 'number'
|
|
44
|
+
? `- **Trial remaining**: ${licStatus.trialDaysRemaining} day${licStatus.trialDaysRemaining === 1 ? '' : 's'}`
|
|
45
|
+
: '',
|
|
46
|
+
licStatus.activationRequired
|
|
47
|
+
? `- **Agent motion**: Stop paid-tier work and ask the user to request or activate a Nexus Prime license now.`
|
|
48
|
+
: `- **Agent motion**: 3-day no-license grace is active; ask the user to request a license before day 4.`,
|
|
49
|
+
].filter((line) => Boolean(line)) : [];
|
|
41
50
|
const lines = [
|
|
42
51
|
`## License Status`,
|
|
43
52
|
`- **Plan**: ${pcu.tier.toUpperCase()}`,
|
|
44
53
|
`- **Status**: ${licStatus.valid ? 'Active' : licStatus.degradedReason ?? 'Inactive'}`,
|
|
45
54
|
licStatus.expiresAt ? `- **Expires**: ${new Date(licStatus.expiresAt).toISOString().split('T')[0]}` : '- **Expires**: Never',
|
|
55
|
+
...trialLines,
|
|
46
56
|
'',
|
|
47
57
|
`## Resource Usage`,
|
|
48
58
|
`- Memory: ${pcu.memory.current.toLocaleString()} / ${Number.isFinite(pcu.memory.limit) ? pcu.memory.limit.toLocaleString() : '∞'} (${pcu.memory.pct}%)`,
|
|
@@ -54,6 +64,8 @@ export async function handleRuntimeGroup(toolName, hctx, request, args, ctx) {
|
|
|
54
64
|
`## Upgrade`,
|
|
55
65
|
`- Dashboard: http://127.0.0.1:3377 → License tab`,
|
|
56
66
|
`- Web: https://nexus-prime.cfd/account`,
|
|
67
|
+
`- Email: adarsh@nexus-prime.cfd`,
|
|
68
|
+
`- SLA: team will share licenses within 24 hours`,
|
|
57
69
|
`- CLI: nexus-prime license sync`,
|
|
58
70
|
];
|
|
59
71
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
@@ -20,6 +20,7 @@ export declare class MCPAdapter implements Adapter {
|
|
|
20
20
|
private currentTask;
|
|
21
21
|
private middlewarePipeline;
|
|
22
22
|
private scanCache;
|
|
23
|
+
private sessionLifecycleFinalized;
|
|
23
24
|
private sciFiMatrixLog;
|
|
24
25
|
private classifyToolCategory;
|
|
25
26
|
private sciFiToolHeader;
|
|
@@ -83,6 +84,7 @@ export declare class MCPAdapter implements Adapter {
|
|
|
83
84
|
private extractFileRefsFromArgs;
|
|
84
85
|
scanSourceFiles(cwd: string): Promise<string[]>;
|
|
85
86
|
connect(): Promise<void>;
|
|
87
|
+
private finalizeSessionLifecycle;
|
|
86
88
|
disconnect(): Promise<void>;
|
|
87
89
|
send(message: NetworkMessage): Promise<void>;
|
|
88
90
|
receive(message: NetworkMessage): void;
|
|
@@ -160,6 +160,7 @@ export class MCPAdapter {
|
|
|
160
160
|
currentTask = '';
|
|
161
161
|
middlewarePipeline;
|
|
162
162
|
scanCache = new Map();
|
|
163
|
+
sessionLifecycleFinalized = false;
|
|
163
164
|
sciFiMatrixLog(title, metrics, intent) {
|
|
164
165
|
const width = 76;
|
|
165
166
|
console.error(`\n\x1b[36m╔═══ [ \x1b[37m\x1b[1mNEXUS PRIME · ORCHESTRATION MATRIX\x1b[0m\x1b[36m ] ${'═'.repeat(Math.max(0, width - 48))}╗\x1b[0m`);
|
|
@@ -876,6 +877,9 @@ export class MCPAdapter {
|
|
|
876
877
|
}
|
|
877
878
|
else {
|
|
878
879
|
this.telemetry.observeSuccessfulToolCall(toolName, args);
|
|
880
|
+
if (toolName === 'nexus_session_dna' && String(args.action ?? 'load') === 'generate') {
|
|
881
|
+
this.sessionLifecycleFinalized = true;
|
|
882
|
+
}
|
|
879
883
|
}
|
|
880
884
|
}
|
|
881
885
|
// Surface meaningful tool calls on the SSE feed; persist only high-signal outcomes.
|
|
@@ -1159,22 +1163,70 @@ export class MCPAdapter {
|
|
|
1159
1163
|
startWatchdog();
|
|
1160
1164
|
console.error('[MCP Adapter] Connected — runtime tools active');
|
|
1161
1165
|
}
|
|
1162
|
-
async
|
|
1163
|
-
|
|
1166
|
+
async finalizeSessionLifecycle(reason) {
|
|
1167
|
+
if (this.sessionLifecycleFinalized && reason !== 'explicit')
|
|
1168
|
+
return;
|
|
1169
|
+
const telemetry = this.telemetry.snapshot();
|
|
1170
|
+
try {
|
|
1171
|
+
const promoted = this.nexusRef?.runTierPromotion?.();
|
|
1172
|
+
if (promoted)
|
|
1173
|
+
nexusEventBus.emit('memory.tier.promoted', promoted);
|
|
1174
|
+
}
|
|
1175
|
+
catch (e) {
|
|
1176
|
+
nexusEventBus.emit('mcp.handler.failed', {
|
|
1177
|
+
toolName: 'nexus_session_dna.disconnect.tierPromotion',
|
|
1178
|
+
code: 'internal',
|
|
1179
|
+
attempts: 1,
|
|
1180
|
+
durationMs: 0,
|
|
1181
|
+
});
|
|
1182
|
+
console.error('[MCP Adapter] Failed to run Session DNA tier promotion:', e);
|
|
1183
|
+
}
|
|
1164
1184
|
try {
|
|
1165
|
-
const telemetry = this.telemetry.snapshot();
|
|
1166
1185
|
this.sessionDNA.syncFromTelemetry({
|
|
1167
1186
|
callCount: telemetry.callCount,
|
|
1168
1187
|
memoriesStored: telemetry.memoriesStored,
|
|
1169
1188
|
memoriesRecalled: telemetry.memoriesRecalled,
|
|
1170
1189
|
tokensOptimized: telemetry.tokensOptimized,
|
|
1171
1190
|
});
|
|
1172
|
-
this.sessionDNA.flush();
|
|
1173
|
-
|
|
1191
|
+
const dna = this.sessionDNA.flush();
|
|
1192
|
+
this.sessionLifecycleFinalized = true;
|
|
1193
|
+
try {
|
|
1194
|
+
const runtimeTokens = this.runtime?.getUsageSnapshot().tokens?.grossInputTokens ?? 0;
|
|
1195
|
+
this.getOrchestrator({}).persistSessionSummary(telemetry.tokensOptimized || runtimeTokens || 0);
|
|
1196
|
+
}
|
|
1197
|
+
catch (e) {
|
|
1198
|
+
nexusEventBus.emit('mcp.handler.failed', {
|
|
1199
|
+
toolName: 'nexus_session_dna.disconnect.persistSessionSummary',
|
|
1200
|
+
code: 'internal',
|
|
1201
|
+
attempts: 1,
|
|
1202
|
+
durationMs: 0,
|
|
1203
|
+
});
|
|
1204
|
+
console.error('[MCP Adapter] Failed to persist Session DNA summary:', e);
|
|
1205
|
+
}
|
|
1206
|
+
await getSharedTelemetry().trackSessionEnd(this.telemetry.elapsedMs(), {
|
|
1207
|
+
projectId: this.nexusRef?.getWorkspaceContext?.()?.repoRoot ?? '',
|
|
1208
|
+
tokensSaved: telemetry.tokensOptimized,
|
|
1209
|
+
memoriesCreated: telemetry.memoriesStored,
|
|
1210
|
+
memoriesRecalled: telemetry.memoriesRecalled,
|
|
1211
|
+
toolsUsed: telemetry.callCount,
|
|
1212
|
+
sessionId: dna.sessionId,
|
|
1213
|
+
}).catch((e) => {
|
|
1214
|
+
nexusEventBus.emit('mcp.handler.failed', {
|
|
1215
|
+
toolName: 'nexus_session_dna.disconnect.trackSessionEnd',
|
|
1216
|
+
code: 'internal',
|
|
1217
|
+
attempts: 1,
|
|
1218
|
+
durationMs: 0,
|
|
1219
|
+
});
|
|
1220
|
+
console.error('[MCP Adapter] Failed to track Session DNA session end:', e);
|
|
1221
|
+
});
|
|
1222
|
+
console.error(`[MCP Adapter] Session DNA finalized on ${reason}`);
|
|
1174
1223
|
}
|
|
1175
1224
|
catch (e) {
|
|
1176
|
-
console.error('[MCP Adapter] Failed to
|
|
1225
|
+
console.error('[MCP Adapter] Failed to finalize Session DNA:', e);
|
|
1177
1226
|
}
|
|
1227
|
+
}
|
|
1228
|
+
async disconnect() {
|
|
1229
|
+
await this.finalizeSessionLifecycle('disconnect');
|
|
1178
1230
|
await this.server.close();
|
|
1179
1231
|
this.connected = false;
|
|
1180
1232
|
console.error('[MCP Adapter] Disconnected');
|
|
@@ -159,6 +159,21 @@ function _writeClaudeCodeHooks(workspaceRoot) {
|
|
|
159
159
|
});
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
|
+
function _isManagedGraphPeer(server) {
|
|
163
|
+
if (!server || typeof server !== 'object' || Array.isArray(server))
|
|
164
|
+
return false;
|
|
165
|
+
const record = server;
|
|
166
|
+
const args = Array.isArray(record.args) ? record.args.map(String) : [];
|
|
167
|
+
return record.command === 'goatlas' && args.length === 1 && args[0] === 'mcp';
|
|
168
|
+
}
|
|
169
|
+
function _stripInternalGraphPeers(mcpServers) {
|
|
170
|
+
if (!mcpServers)
|
|
171
|
+
return;
|
|
172
|
+
delete mcpServers['code-review-graph'];
|
|
173
|
+
if (_isManagedGraphPeer(mcpServers['atlas'])) {
|
|
174
|
+
delete mcpServers['atlas'];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
162
177
|
/**
|
|
163
178
|
* Write workspace-local MCP config files for IDEs whose workspace directories
|
|
164
179
|
* already exist (`.vscode/`, `.cursor/`). Non-fatal; errors are swallowed.
|
|
@@ -181,6 +196,7 @@ function _writeWorkspaceLocalConfigs(callerIde, workspaceRoot) {
|
|
|
181
196
|
? settings.mcpServers
|
|
182
197
|
: {};
|
|
183
198
|
servers['nexus-prime'] = entry;
|
|
199
|
+
_stripInternalGraphPeers(servers);
|
|
184
200
|
settings.mcpServers = servers;
|
|
185
201
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
186
202
|
appendToManifest((m) => {
|
|
@@ -212,6 +228,7 @@ function _writeWorkspaceLocalConfigs(callerIde, workspaceRoot) {
|
|
|
212
228
|
? mcp.mcpServers
|
|
213
229
|
: {};
|
|
214
230
|
servers['nexus-prime'] = entry;
|
|
231
|
+
_stripInternalGraphPeers(servers);
|
|
215
232
|
mcp.mcpServers = servers;
|
|
216
233
|
writeFileSync(mcpPath, JSON.stringify(mcp, null, 2), 'utf8');
|
|
217
234
|
appendToManifest((m) => {
|
|
@@ -347,6 +364,7 @@ function mergeIntoExistingConfig(configPath, newContent, ide) {
|
|
|
347
364
|
...(existing.mcpServers ?? {}),
|
|
348
365
|
...(incoming.mcpServers ?? {}),
|
|
349
366
|
};
|
|
367
|
+
_stripInternalGraphPeers(existing.mcpServers);
|
|
350
368
|
return JSON.stringify(existing, null, 2);
|
|
351
369
|
}
|
|
352
370
|
if (ide === 'claude-code') {
|
|
@@ -362,6 +380,7 @@ function mergeIntoExistingConfig(configPath, newContent, ide) {
|
|
|
362
380
|
...(existing.mcpServers ?? {}),
|
|
363
381
|
...(incoming.mcpServers ?? {}),
|
|
364
382
|
};
|
|
383
|
+
_stripInternalGraphPeers(existing.mcpServers);
|
|
365
384
|
}
|
|
366
385
|
return JSON.stringify(existing, null, 2);
|
|
367
386
|
}
|
package/dist/cli.js
CHANGED
|
@@ -197,9 +197,25 @@ function writeStandardMcpConfig(targetPath, workspaceRoot) {
|
|
|
197
197
|
const existing = readJson(targetPath);
|
|
198
198
|
existing.mcpServers = existing.mcpServers ?? {};
|
|
199
199
|
existing.mcpServers['nexus-prime'] = buildStandardMcpServerConfig(workspaceRoot);
|
|
200
|
+
delete existing.mcpServers['code-review-graph'];
|
|
201
|
+
if (isNexusManagedGraphPeer(existing.mcpServers['atlas'])) {
|
|
202
|
+
delete existing.mcpServers['atlas'];
|
|
203
|
+
}
|
|
200
204
|
ensureParentDir(targetPath);
|
|
201
205
|
writeFileSync(targetPath, JSON.stringify(existing, null, 2));
|
|
202
206
|
}
|
|
207
|
+
function isNexusManagedGraphPeer(server) {
|
|
208
|
+
if (!server || typeof server !== 'object' || Array.isArray(server))
|
|
209
|
+
return false;
|
|
210
|
+
const record = server;
|
|
211
|
+
const args = Array.isArray(record['args']) ? record['args'].map(String) : [];
|
|
212
|
+
return record['command'] === 'goatlas' && args.length === 1 && args[0] === 'mcp';
|
|
213
|
+
}
|
|
214
|
+
function jsonExposesInternalGraphPeer(parsed) {
|
|
215
|
+
const servers = parsed?.mcpServers ?? parsed?.mcp ?? {};
|
|
216
|
+
return Boolean(servers?.['code-review-graph']
|
|
217
|
+
|| isNexusManagedGraphPeer(servers?.['atlas']));
|
|
218
|
+
}
|
|
203
219
|
function writeOpencodeConfig(targetPath, workspaceRoot) {
|
|
204
220
|
const existing = readJson(targetPath);
|
|
205
221
|
const mcpConfig = buildStandardMcpServerConfig(workspaceRoot);
|
|
@@ -428,6 +444,15 @@ function buildInstructionFiles(clientId) {
|
|
|
428
444
|
content: artifact.content,
|
|
429
445
|
}));
|
|
430
446
|
}
|
|
447
|
+
function resolveClaudeDesktopConfigPath() {
|
|
448
|
+
if (process.platform === 'darwin') {
|
|
449
|
+
return join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
450
|
+
}
|
|
451
|
+
if (process.platform === 'win32') {
|
|
452
|
+
return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
|
|
453
|
+
}
|
|
454
|
+
return join(homedir(), '.claude', 'claude_desktop_config.json');
|
|
455
|
+
}
|
|
431
456
|
function getSetupDefinition(clientId) {
|
|
432
457
|
const instructionFiles = buildInstructionFiles(clientId);
|
|
433
458
|
if (clientId === 'codex') {
|
|
@@ -458,7 +483,7 @@ function getSetupDefinition(clientId) {
|
|
|
458
483
|
return {
|
|
459
484
|
id: clientId,
|
|
460
485
|
label: 'Claude Desktop',
|
|
461
|
-
configPath:
|
|
486
|
+
configPath: resolveClaudeDesktopConfigPath(),
|
|
462
487
|
instructionFiles,
|
|
463
488
|
};
|
|
464
489
|
}
|
|
@@ -583,6 +608,8 @@ function hasExpectedConfig(definition) {
|
|
|
583
608
|
}
|
|
584
609
|
try {
|
|
585
610
|
const parsed = JSON.parse(readFileSync(definition.configPath, 'utf8'));
|
|
611
|
+
if (jsonExposesInternalGraphPeer(parsed))
|
|
612
|
+
return false;
|
|
586
613
|
if (definition.id === 'opencode') {
|
|
587
614
|
const server = parsed?.mcp?.['nexus-prime'];
|
|
588
615
|
return Boolean(server && isStableNexusMcpServerConfig(server, 'environment'));
|
|
@@ -1724,7 +1751,7 @@ program
|
|
|
1724
1751
|
.description('Manage your Nexus Prime license')
|
|
1725
1752
|
.addCommand(new Command('activate')
|
|
1726
1753
|
.description('Activate a license key')
|
|
1727
|
-
.argument('<key>', 'License key from
|
|
1754
|
+
.argument('<key>', 'License key from the Nexus account page or license team')
|
|
1728
1755
|
.action((key) => {
|
|
1729
1756
|
const mgr = getSharedLicenseManager();
|
|
1730
1757
|
const status = mgr.activate(key);
|
|
@@ -1737,7 +1764,8 @@ program
|
|
|
1737
1764
|
}
|
|
1738
1765
|
else {
|
|
1739
1766
|
console.error(`\u2717 License invalid: ${status.degradedReason ?? 'unknown'}`);
|
|
1740
|
-
console.error('
|
|
1767
|
+
console.error(' Request a valid key at https://nexus-prime.cfd/account');
|
|
1768
|
+
console.error(' Or email adarsh@nexus-prime.cfd — licenses are shared within 24 hours.');
|
|
1741
1769
|
process.exit(1);
|
|
1742
1770
|
}
|
|
1743
1771
|
}))
|
|
@@ -1765,7 +1793,8 @@ program
|
|
|
1765
1793
|
.action(() => {
|
|
1766
1794
|
getSharedLicenseManager().deactivate();
|
|
1767
1795
|
console.log('\u2713 License removed. Reverted to Free plan.');
|
|
1768
|
-
console.log('
|
|
1796
|
+
console.log(' Request a new key at https://nexus-prime.cfd/account');
|
|
1797
|
+
console.log(' Or email adarsh@nexus-prime.cfd — licenses are shared within 24 hours.');
|
|
1769
1798
|
}))
|
|
1770
1799
|
.addCommand(new Command('login')
|
|
1771
1800
|
.description('Login to nexus-prime.cfd for license sync')
|
|
@@ -1794,7 +1823,8 @@ program
|
|
|
1794
1823
|
}
|
|
1795
1824
|
catch {
|
|
1796
1825
|
console.log(' License sync skipped (no license found yet).');
|
|
1797
|
-
console.log('
|
|
1826
|
+
console.log(' Request a license at https://nexus-prime.cfd/account');
|
|
1827
|
+
console.log(' Or email adarsh@nexus-prime.cfd — licenses are shared within 24 hours.');
|
|
1798
1828
|
}
|
|
1799
1829
|
}
|
|
1800
1830
|
catch (err) {
|
|
@@ -1848,12 +1878,13 @@ program
|
|
|
1848
1878
|
try {
|
|
1849
1879
|
const result = await requestUpgrade(plan);
|
|
1850
1880
|
console.log(`\u2713 Upgrade request submitted (${result.status})`);
|
|
1851
|
-
console.log('
|
|
1881
|
+
console.log(' The Nexus Prime team will review it and share licenses within 24 hours.');
|
|
1852
1882
|
console.log(' Once approved, run: nexus-prime license sync');
|
|
1853
1883
|
}
|
|
1854
1884
|
catch (err) {
|
|
1855
1885
|
console.error(`\u2717 Request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1856
1886
|
console.log(' Visit https://nexus-prime.cfd/account to request an upgrade.');
|
|
1887
|
+
console.log(' Or email adarsh@nexus-prime.cfd with your account email and target plan.');
|
|
1857
1888
|
process.exit(1);
|
|
1858
1889
|
}
|
|
1859
1890
|
}));
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<link rel="stylesheet" href="./styles/board.css">
|
|
12
12
|
<link rel="stylesheet" href="./styles/workforce.css">
|
|
13
13
|
<link rel="stylesheet" href="./styles/memory.css">
|
|
14
|
+
<link rel="stylesheet" href="./styles/context-log.css">
|
|
14
15
|
<link rel="stylesheet" href="./styles/governance.css">
|
|
15
16
|
<link rel="stylesheet" href="./styles/trust.css">
|
|
16
17
|
<link rel="stylesheet" href="./styles/animation.css">
|
|
@@ -55,6 +56,7 @@ if(location.protocol==='file:'){
|
|
|
55
56
|
<a class="nav-item" data-nav="runtime" href="#runtime">⚡ Runtime</a>
|
|
56
57
|
<a class="nav-item" data-nav="workforce" href="#workforce">Workforce</a>
|
|
57
58
|
<a class="nav-item" data-nav="memory" href="#memory">Memory</a>
|
|
59
|
+
<a class="nav-item" data-nav="context-log" href="#context-log">Context Log</a>
|
|
58
60
|
<a class="nav-item" data-nav="repo" href="#repo">Repo</a>
|
|
59
61
|
<a class="nav-item" data-nav="knowledge" href="#knowledge">Knowledge</a>
|
|
60
62
|
<a class="nav-item" data-nav="governance" href="#governance">Governance</a>
|
|
@@ -214,12 +216,18 @@ if(location.protocol==='file:'){
|
|
|
214
216
|
<input id="mem-search" type="text" placeholder="Search memories…" aria-label="Search memories">
|
|
215
217
|
<button class="btn btn-sm" id="mem-list-browse-btn">Browse</button>
|
|
216
218
|
</div>
|
|
219
|
+
<div id="memory-selection-panel" class="memory-selection-panel"></div>
|
|
217
220
|
<div id="mem-list"></div>
|
|
218
221
|
</div>
|
|
219
222
|
<div class="card"><div id="mem-stats"></div></div>
|
|
220
223
|
</div>
|
|
221
224
|
</section>
|
|
222
225
|
|
|
226
|
+
<!-- CONTEXT LOG ────────────────────────────────────────────── -->
|
|
227
|
+
<section class="view-panel" data-view="context-log" aria-label="Context log">
|
|
228
|
+
<div id="context-log-view"></div>
|
|
229
|
+
</section>
|
|
230
|
+
|
|
223
231
|
<!-- REPO ───────────────────────────────────────────────────── -->
|
|
224
232
|
<section class="view-panel" data-view="repo" aria-label="Repo graph">
|
|
225
233
|
<div class="shd">Repo knowledge graph</div>
|
|
@@ -15,6 +15,7 @@ import { init as initCmdBar } from './widgets/command-bar.js';
|
|
|
15
15
|
import * as Board from './views/board.js';
|
|
16
16
|
import * as Workforce from './views/workforce.js';
|
|
17
17
|
import * as Memory from './views/memory.js';
|
|
18
|
+
import * as ContextLog from './views/context-log.js';
|
|
18
19
|
import * as Knowledge from './views/knowledge.js';
|
|
19
20
|
import * as Repo from './views/repo.js';
|
|
20
21
|
import * as Governance from './views/governance.js';
|
|
@@ -53,6 +54,7 @@ navRegister('board', Board.load);
|
|
|
53
54
|
navRegister('runtime', Runtime.load);
|
|
54
55
|
navRegister('workforce', Workforce.load);
|
|
55
56
|
navRegister('memory', Memory.load);
|
|
57
|
+
navRegister('context-log', ContextLog.load);
|
|
56
58
|
navRegister('repo', Repo.load);
|
|
57
59
|
navRegister('knowledge', Knowledge.load);
|
|
58
60
|
navRegister('governance', Governance.load);
|
|
@@ -113,10 +115,14 @@ setOnEvent(evt => {
|
|
|
113
115
|
// here we just refresh the surface payload so kanban + KPIs reflect the new run.
|
|
114
116
|
if (String(evt.type||'').startsWith('orchestration.')) {
|
|
115
117
|
bustCache('/api/dashboard/surface/operate');
|
|
118
|
+
bustCache('/api/runs');
|
|
116
119
|
if (tab === 'board') {
|
|
117
120
|
Board.handleOrchestrationEvent?.(evt);
|
|
118
121
|
Board.render();
|
|
119
122
|
}
|
|
123
|
+
if (tab === 'context-log') {
|
|
124
|
+
ContextLog.load();
|
|
125
|
+
}
|
|
120
126
|
}
|
|
121
127
|
// Workspace root promoted (e.g. from bootstrap hint) — refresh header immediately.
|
|
122
128
|
if (String(evt.type||'') === 'workspace.changed') {
|
|
@@ -300,6 +306,7 @@ function _reloadTab(tab) {
|
|
|
300
306
|
if (tab === 'board') Board.load();
|
|
301
307
|
if (tab === 'workforce') Workforce.load();
|
|
302
308
|
if (tab === 'memory') Memory.load();
|
|
309
|
+
if (tab === 'context-log') ContextLog.load();
|
|
303
310
|
if (tab === 'knowledge') Knowledge.load();
|
|
304
311
|
}
|
|
305
312
|
|
|
@@ -65,6 +65,7 @@ export const S = {
|
|
|
65
65
|
memQuery: '',
|
|
66
66
|
graphSim: null,
|
|
67
67
|
memLane: 'all',
|
|
68
|
+
selectedMemoryIds: [],
|
|
68
69
|
memorySurface: null,
|
|
69
70
|
topology: null,
|
|
70
71
|
|
|
@@ -81,6 +82,10 @@ export const S = {
|
|
|
81
82
|
// Orchestration pipeline (live decomposition + completion from SSE)
|
|
82
83
|
lastDecomposition: null,
|
|
83
84
|
lastCompletion: null,
|
|
85
|
+
lastDecisionSpine: null,
|
|
86
|
+
contextLogRuns: [],
|
|
87
|
+
contextLogSelectedRunId: null,
|
|
88
|
+
contextLogSpine: null,
|
|
84
89
|
|
|
85
90
|
// Neural Stream HUD ring buffer (latest SSE events, restored from v3.8.0)
|
|
86
91
|
neuralStream: [],
|