nexus-prime 7.9.15 → 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/cli.js +9 -5
- package/dist/dashboard/app/views/license.js +36 -0
- 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/postinstall-bootstrap.js +6 -4
- package/package.json +1 -1
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') }] };
|
package/dist/cli.js
CHANGED
|
@@ -1751,7 +1751,7 @@ program
|
|
|
1751
1751
|
.description('Manage your Nexus Prime license')
|
|
1752
1752
|
.addCommand(new Command('activate')
|
|
1753
1753
|
.description('Activate a license key')
|
|
1754
|
-
.argument('<key>', 'License key from
|
|
1754
|
+
.argument('<key>', 'License key from the Nexus account page or license team')
|
|
1755
1755
|
.action((key) => {
|
|
1756
1756
|
const mgr = getSharedLicenseManager();
|
|
1757
1757
|
const status = mgr.activate(key);
|
|
@@ -1764,7 +1764,8 @@ program
|
|
|
1764
1764
|
}
|
|
1765
1765
|
else {
|
|
1766
1766
|
console.error(`\u2717 License invalid: ${status.degradedReason ?? 'unknown'}`);
|
|
1767
|
-
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.');
|
|
1768
1769
|
process.exit(1);
|
|
1769
1770
|
}
|
|
1770
1771
|
}))
|
|
@@ -1792,7 +1793,8 @@ program
|
|
|
1792
1793
|
.action(() => {
|
|
1793
1794
|
getSharedLicenseManager().deactivate();
|
|
1794
1795
|
console.log('\u2713 License removed. Reverted to Free plan.');
|
|
1795
|
-
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.');
|
|
1796
1798
|
}))
|
|
1797
1799
|
.addCommand(new Command('login')
|
|
1798
1800
|
.description('Login to nexus-prime.cfd for license sync')
|
|
@@ -1821,7 +1823,8 @@ program
|
|
|
1821
1823
|
}
|
|
1822
1824
|
catch {
|
|
1823
1825
|
console.log(' License sync skipped (no license found yet).');
|
|
1824
|
-
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.');
|
|
1825
1828
|
}
|
|
1826
1829
|
}
|
|
1827
1830
|
catch (err) {
|
|
@@ -1875,12 +1878,13 @@ program
|
|
|
1875
1878
|
try {
|
|
1876
1879
|
const result = await requestUpgrade(plan);
|
|
1877
1880
|
console.log(`\u2713 Upgrade request submitted (${result.status})`);
|
|
1878
|
-
console.log('
|
|
1881
|
+
console.log(' The Nexus Prime team will review it and share licenses within 24 hours.');
|
|
1879
1882
|
console.log(' Once approved, run: nexus-prime license sync');
|
|
1880
1883
|
}
|
|
1881
1884
|
catch (err) {
|
|
1882
1885
|
console.error(`\u2717 Request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1883
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.');
|
|
1884
1888
|
process.exit(1);
|
|
1885
1889
|
}
|
|
1886
1890
|
}));
|
|
@@ -158,12 +158,41 @@ function _renewalNagBanner(status) {
|
|
|
158
158
|
</div>`;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
function _trialActivationBanner(status) {
|
|
162
|
+
if (!status?.trialPhase) return '';
|
|
163
|
+
const motion = status.activationMotion ?? {};
|
|
164
|
+
const required = status.activationRequired === true || status.trialPhase === 'activation' || status.trialPhase === 'expired';
|
|
165
|
+
const days = typeof status.trialDaysRemaining === 'number' ? status.trialDaysRemaining : null;
|
|
166
|
+
const color = status.trialPhase === 'expired' ? 'var(--bad)' : required ? 'var(--warn)' : 'var(--accent)';
|
|
167
|
+
const bg = status.trialPhase === 'expired'
|
|
168
|
+
? 'oklch(65% 0.22 25 / 8%)'
|
|
169
|
+
: required ? 'oklch(80% 0.16 80 / 8%)' : 'oklch(70% 0.16 250 / 8%)';
|
|
170
|
+
const title = motion.title ?? (required ? 'License required' : '3-day no-license grace');
|
|
171
|
+
const message = motion.message ?? (required
|
|
172
|
+
? 'The no-license grace period is over. Request a license from the account page or email adarsh@nexus-prime.cfd; the team will share licenses within 24 hours.'
|
|
173
|
+
: 'First 3 days run without a license. Request a license before day 4; the team will share licenses within 24 hours.');
|
|
174
|
+
const remaining = days == null ? '' : `<div style="font-size:11px;color:var(--text-muted);margin-top:4px">${days} day${days === 1 ? '' : 's'} remaining</div>`;
|
|
175
|
+
return `
|
|
176
|
+
<div style="background:${bg};border:1px solid ${color};border-radius:8px;padding:12px 16px;margin-bottom:16px;display:flex;align-items:center;gap:12px;flex-wrap:wrap">
|
|
177
|
+
<div style="flex:1;min-width:220px">
|
|
178
|
+
<div style="font:600 13px ui-sans-serif;color:${color};margin-bottom:3px">${esc(title)}</div>
|
|
179
|
+
<div style="font-size:12px;color:var(--text-muted);line-height:1.45">${esc(message)}</div>
|
|
180
|
+
${remaining}
|
|
181
|
+
</div>
|
|
182
|
+
<button class="btn btn-primary btn-sm" id="lic-trial-account-btn" style="flex-shrink:0;white-space:nowrap">Request license</button>
|
|
183
|
+
<button class="btn btn-sm" id="lic-trial-activate-btn" style="flex-shrink:0;white-space:nowrap">Activate key</button>
|
|
184
|
+
<button class="btn btn-sm" id="lic-trial-email-btn" style="flex-shrink:0;white-space:nowrap">Email team</button>
|
|
185
|
+
</div>`;
|
|
186
|
+
}
|
|
187
|
+
|
|
161
188
|
function _renderStep1(tier, status, pcu, formatted) {
|
|
162
189
|
const plan = PLANS.find(p => p.id === tier) ?? PLANS[0];
|
|
163
190
|
const valid = status.valid !== false;
|
|
164
191
|
|
|
165
192
|
return `
|
|
166
193
|
<div class="license-card card">
|
|
194
|
+
${_trialActivationBanner(status)}
|
|
195
|
+
|
|
167
196
|
<!-- Renewal nag (shown when expiry < 14 days) -->
|
|
168
197
|
${_renewalNagBanner(status)}
|
|
169
198
|
|
|
@@ -300,6 +329,13 @@ function _attachHandlers() {
|
|
|
300
329
|
$('lic-upgrade-btn')?.addEventListener('click', () => { _step = 2; render(); });
|
|
301
330
|
$('lic-sync-btn')?.addEventListener('click', _doSync);
|
|
302
331
|
$('lic-deactivate-btn')?.addEventListener('click', _doDeactivate);
|
|
332
|
+
$('lic-trial-activate-btn')?.addEventListener('click', () => { _step = 3; render(); });
|
|
333
|
+
$('lic-trial-account-btn')?.addEventListener('click', () => {
|
|
334
|
+
window.open('https://nexus-prime.cfd/account', '_blank', 'noopener');
|
|
335
|
+
});
|
|
336
|
+
$('lic-trial-email-btn')?.addEventListener('click', () => {
|
|
337
|
+
window.open('mailto:adarsh@nexus-prime.cfd?subject=Nexus%20Prime%20license%20request', '_blank', 'noopener');
|
|
338
|
+
});
|
|
303
339
|
$('lic-renew-nag-btn')?.addEventListener('click', () => {
|
|
304
340
|
window.open('https://nexus-prime.cfd/license', '_blank', 'noopener');
|
|
305
341
|
});
|
|
@@ -21,6 +21,12 @@ function getMode() {
|
|
|
21
21
|
// Tools that create resources subject to quantity caps
|
|
22
22
|
const MEMORY_CREATION_TOOLS = new Set(['nexus_store_memory']);
|
|
23
23
|
const OPERATIVE_CREATION_TOOLS = new Set(['nexus_synapse_hire', 'nexus_synapse_mandate']);
|
|
24
|
+
const LICENSE_SAFE_TOOLS = new Set([
|
|
25
|
+
'nexus_license_usage',
|
|
26
|
+
'nexus_runtime_health',
|
|
27
|
+
'nexus_describe_tool',
|
|
28
|
+
'nexus_session_dna',
|
|
29
|
+
]);
|
|
24
30
|
/**
|
|
25
31
|
* LicenseEnforcementMiddleware — priority 5 (runs first in the pipeline).
|
|
26
32
|
*
|
|
@@ -35,8 +41,8 @@ export const LicenseEnforcementMiddleware = {
|
|
|
35
41
|
const status = lm.getStatus();
|
|
36
42
|
const mode = getMode();
|
|
37
43
|
const toolName = ctx.toolName;
|
|
38
|
-
//
|
|
39
|
-
if (toolName
|
|
44
|
+
// Keep activation/status paths available even when the trial gate is closed.
|
|
45
|
+
if (LICENSE_SAFE_TOOLS.has(toolName))
|
|
40
46
|
return;
|
|
41
47
|
// ── No license check ──────────────────────────────────────────────
|
|
42
48
|
if (status.degradedReason === 'not-activated') {
|
|
@@ -46,17 +52,31 @@ export const LicenseEnforcementMiddleware = {
|
|
|
46
52
|
// In all modes: let the tool execute (soft gate during ramp)
|
|
47
53
|
return;
|
|
48
54
|
}
|
|
55
|
+
if (status.degradedReason === 'activation-required') {
|
|
56
|
+
const msg = trialActiveMessage(status);
|
|
57
|
+
if (mode !== 'audit') {
|
|
58
|
+
ctx.meta.shortCircuitResult = {
|
|
59
|
+
content: [{ type: 'text', text: msg }],
|
|
60
|
+
};
|
|
61
|
+
ctx.meta.shortCircuitedBy = 'license-enforcement';
|
|
62
|
+
}
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
49
65
|
if (status.degradedReason === 'trial-expired') {
|
|
66
|
+
const msg = trialExpiredMessage();
|
|
50
67
|
if (mode !== 'audit') {
|
|
51
|
-
ctx.meta.
|
|
68
|
+
ctx.meta.shortCircuitResult = {
|
|
69
|
+
content: [{ type: 'text', text: msg }],
|
|
70
|
+
};
|
|
71
|
+
ctx.meta.shortCircuitedBy = 'license-enforcement';
|
|
52
72
|
}
|
|
53
|
-
|
|
73
|
+
return;
|
|
54
74
|
}
|
|
55
75
|
if (status.trial && mode !== 'audit') {
|
|
56
76
|
// Soft footer so users know the runtime is being kept alive by the
|
|
57
77
|
// auto-issued local trial. Doesn't gate execution — paid tiers behave
|
|
58
78
|
// exactly like a real license while the trial is active.
|
|
59
|
-
ctx.meta.licenseUpgradeHint = trialActiveMessage(status
|
|
79
|
+
ctx.meta.licenseUpgradeHint = trialActiveMessage(status);
|
|
60
80
|
}
|
|
61
81
|
// ── Tool tier check ───────────────────────────────────────────────
|
|
62
82
|
if (!isToolAllowed(toolName, status.tier)) {
|
|
@@ -6,4 +6,4 @@ export { snapshotPCU, formatPCUStatus, type PCUSnapshot } from './pcu-meter.js';
|
|
|
6
6
|
export { capWarningMessage, capExceededMessage, toolGateMessage, noLicenseMessage, trialActiveMessage, trialExpiredMessage, } from './upgrade-prompts.js';
|
|
7
7
|
export { syncLicense, requestUpgrade } from './license-sync.js';
|
|
8
8
|
export { loginFromCLI, readAuthToken, readAuthInfo, isLoggedIn, logout } from './web-auth.js';
|
|
9
|
-
export type { PlanTier, PlanCaps, LicenseClaims, LicenseStatus, CapType, CapCheckResult, SkillProfile, DarwinScope, } from './types.js';
|
|
9
|
+
export type { PlanTier, TrialPhase, PlanCaps, LicenseClaims, LicenseStatus, CapType, CapCheckResult, SkillProfile, DarwinScope, } from './types.js';
|
|
@@ -28,6 +28,8 @@ async function emitLicenseEvent(eventType, payload) {
|
|
|
28
28
|
// The matching private key is stored securely on the Nexus Prime licensing backend.
|
|
29
29
|
const NEXUS_PUBLIC_KEY_B64 = 'MCowBQYDK2VwAyEAbrBiMBqzIyatM/Q/plA0Dn2Y/TAu2UVmWG8guGI0ElQ=';
|
|
30
30
|
const UPGRADE_URL = 'https://nexus-prime.cfd/pricing';
|
|
31
|
+
const ACCOUNT_URL = 'https://nexus-prime.cfd/account';
|
|
32
|
+
const LICENSE_TEAM_EMAIL = 'adarsh@nexus-prime.cfd';
|
|
31
33
|
// Warn at this fraction of the cap (e.g. 0.8 = 80%)
|
|
32
34
|
const WARN_THRESHOLD = 0.8;
|
|
33
35
|
// Trial configuration. Every install gets a 30-day full-tier trial the first
|
|
@@ -35,7 +37,9 @@ const WARN_THRESHOLD = 0.8;
|
|
|
35
37
|
// paid tools available — so users can actually evaluate the product. The
|
|
36
38
|
// trial marker (stateDir/trial.json) records issue + expiry, so subsequent
|
|
37
39
|
// loads stay deterministic offline. NEXUS_DISABLE_TRIAL=1 opts out (tests).
|
|
38
|
-
const
|
|
40
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
41
|
+
const TRIAL_DURATION_MS = 30 * DAY_MS;
|
|
42
|
+
const TRIAL_GRACE_MS = 3 * DAY_MS;
|
|
39
43
|
const TRIAL_TIER = 'enterprise';
|
|
40
44
|
const TRIAL_MARKER_FILENAME = 'trial.json';
|
|
41
45
|
function readTrialMarker(markerPath) {
|
|
@@ -69,6 +73,64 @@ function writeTrialMarker(markerPath, marker) {
|
|
|
69
73
|
// best-effort: trial still applies in memory even if we can't persist it.
|
|
70
74
|
}
|
|
71
75
|
}
|
|
76
|
+
function clampTrialMarker(marker, now) {
|
|
77
|
+
const issuedAt = Number.isFinite(marker.issuedAt) && marker.issuedAt <= now + DAY_MS
|
|
78
|
+
? marker.issuedAt
|
|
79
|
+
: now;
|
|
80
|
+
const maxExpiresAt = issuedAt + TRIAL_DURATION_MS;
|
|
81
|
+
const expiresAt = Number.isFinite(marker.expiresAt) && marker.expiresAt >= issuedAt
|
|
82
|
+
? Math.min(marker.expiresAt, maxExpiresAt)
|
|
83
|
+
: maxExpiresAt;
|
|
84
|
+
const normalized = {
|
|
85
|
+
issuedAt,
|
|
86
|
+
expiresAt,
|
|
87
|
+
tier: TRIAL_TIER,
|
|
88
|
+
orgId: marker.orgId ?? null,
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
marker: normalized,
|
|
92
|
+
changed: normalized.issuedAt !== marker.issuedAt
|
|
93
|
+
|| normalized.expiresAt !== marker.expiresAt
|
|
94
|
+
|| normalized.tier !== marker.tier
|
|
95
|
+
|| normalized.orgId !== marker.orgId,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function daysUntil(timestamp, now) {
|
|
99
|
+
return Math.max(0, Math.ceil((timestamp - now) / DAY_MS));
|
|
100
|
+
}
|
|
101
|
+
function buildActivationMotion(phase, daysRemaining) {
|
|
102
|
+
if (phase === 'expired') {
|
|
103
|
+
return {
|
|
104
|
+
phase: 'expired',
|
|
105
|
+
required: true,
|
|
106
|
+
title: 'Trial expired',
|
|
107
|
+
message: `The trial window is over. Request a license in the Nexus account page or email ${LICENSE_TEAM_EMAIL}. The team will share licenses within 24 hours.`,
|
|
108
|
+
action: 'Request license',
|
|
109
|
+
url: ACCOUNT_URL,
|
|
110
|
+
command: 'nexus-prime license activate <token>',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (phase === 'activation') {
|
|
114
|
+
return {
|
|
115
|
+
phase: 'activation',
|
|
116
|
+
required: true,
|
|
117
|
+
title: 'License required',
|
|
118
|
+
message: `The 3-day no-license grace period is over. Nexus Prime requires an activated license now; ${daysRemaining} day${daysRemaining === 1 ? '' : 's'} remain in the trial window after activation. Request one in the Nexus account page or email ${LICENSE_TEAM_EMAIL}; the team will share licenses within 24 hours.`,
|
|
119
|
+
action: 'Request license',
|
|
120
|
+
url: ACCOUNT_URL,
|
|
121
|
+
command: 'nexus-prime license activate <token>',
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
phase: 'grace',
|
|
126
|
+
required: false,
|
|
127
|
+
title: '3-day no-license grace',
|
|
128
|
+
message: `Nexus Prime is in the first 3-day no-license grace period. Request a license before day 4; approvals are shared within 24 hours by the Nexus Prime team.`,
|
|
129
|
+
action: 'Request license',
|
|
130
|
+
url: ACCOUNT_URL,
|
|
131
|
+
command: 'nexus-prime license activate <token>',
|
|
132
|
+
};
|
|
133
|
+
}
|
|
72
134
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
73
135
|
function base64urlDecode(s) {
|
|
74
136
|
return Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/'), 'base64');
|
|
@@ -101,7 +163,24 @@ function buildFreeStatus(degradedReason) {
|
|
|
101
163
|
degradedReason,
|
|
102
164
|
};
|
|
103
165
|
}
|
|
104
|
-
function buildTrialStatus(marker) {
|
|
166
|
+
function buildTrialStatus(marker, now = Date.now()) {
|
|
167
|
+
const graceEndsAt = marker.issuedAt + TRIAL_GRACE_MS;
|
|
168
|
+
const daysRemaining = daysUntil(marker.expiresAt, now);
|
|
169
|
+
const trialPhase = now >= graceEndsAt ? 'activation' : 'grace';
|
|
170
|
+
const trialDaysElapsed = Math.max(0, Math.floor((now - marker.issuedAt) / DAY_MS));
|
|
171
|
+
if (trialPhase === 'activation') {
|
|
172
|
+
return {
|
|
173
|
+
...buildFreeStatus('activation-required'),
|
|
174
|
+
trial: true,
|
|
175
|
+
trialPhase,
|
|
176
|
+
trialIssuedAt: marker.issuedAt,
|
|
177
|
+
trialGraceEndsAt: graceEndsAt,
|
|
178
|
+
trialDaysElapsed,
|
|
179
|
+
trialDaysRemaining: daysRemaining,
|
|
180
|
+
activationRequired: true,
|
|
181
|
+
activationMotion: buildActivationMotion(trialPhase, daysRemaining),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
105
184
|
return {
|
|
106
185
|
valid: true,
|
|
107
186
|
tier: marker.tier,
|
|
@@ -109,6 +188,26 @@ function buildTrialStatus(marker) {
|
|
|
109
188
|
expiresAt: marker.expiresAt,
|
|
110
189
|
orgId: marker.orgId,
|
|
111
190
|
trial: true,
|
|
191
|
+
trialPhase,
|
|
192
|
+
trialIssuedAt: marker.issuedAt,
|
|
193
|
+
trialGraceEndsAt: graceEndsAt,
|
|
194
|
+
trialDaysElapsed,
|
|
195
|
+
trialDaysRemaining: daysRemaining,
|
|
196
|
+
activationRequired: false,
|
|
197
|
+
activationMotion: buildActivationMotion(trialPhase, daysRemaining),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function buildTrialExpiredStatus(marker, now = Date.now()) {
|
|
201
|
+
return {
|
|
202
|
+
...buildFreeStatus('trial-expired'),
|
|
203
|
+
trial: false,
|
|
204
|
+
trialPhase: 'expired',
|
|
205
|
+
trialIssuedAt: marker.issuedAt,
|
|
206
|
+
trialGraceEndsAt: marker.issuedAt + TRIAL_GRACE_MS,
|
|
207
|
+
trialDaysElapsed: Math.max(0, Math.floor((now - marker.issuedAt) / DAY_MS)),
|
|
208
|
+
trialDaysRemaining: 0,
|
|
209
|
+
activationRequired: true,
|
|
210
|
+
activationMotion: buildActivationMotion('expired', 0),
|
|
112
211
|
};
|
|
113
212
|
}
|
|
114
213
|
function validateClaims(claims) {
|
|
@@ -240,10 +339,17 @@ export class LicenseManager {
|
|
|
240
339
|
};
|
|
241
340
|
writeTrialMarker(this.trialPath, marker);
|
|
242
341
|
}
|
|
342
|
+
else {
|
|
343
|
+
const normalized = clampTrialMarker(marker, now);
|
|
344
|
+
marker = normalized.marker;
|
|
345
|
+
if (normalized.changed) {
|
|
346
|
+
writeTrialMarker(this.trialPath, marker);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
243
349
|
if (marker.expiresAt <= now) {
|
|
244
|
-
return
|
|
350
|
+
return buildTrialExpiredStatus(marker, now);
|
|
245
351
|
}
|
|
246
|
-
return buildTrialStatus(marker);
|
|
352
|
+
return buildTrialStatus(marker, now);
|
|
247
353
|
}
|
|
248
354
|
/** Returns the path of the trial marker (for tests + status surfaces). */
|
|
249
355
|
getTrialMarkerPath() {
|
|
@@ -22,7 +22,8 @@ export async function syncLicense() {
|
|
|
22
22
|
const authToken = readAuthToken();
|
|
23
23
|
if (!authToken) {
|
|
24
24
|
throw new Error('Not logged in. Run: nexus-prime license login\n' +
|
|
25
|
-
'Or
|
|
25
|
+
'Or request a license: https://nexus-prime.cfd/account\n' +
|
|
26
|
+
'Email fallback: adarsh@nexus-prime.cfd');
|
|
26
27
|
}
|
|
27
28
|
const res = await fetch(`${API_BASE}/api/license/current`, {
|
|
28
29
|
headers: { Authorization: `Bearer ${authToken}` },
|
|
@@ -37,7 +38,7 @@ export async function syncLicense() {
|
|
|
37
38
|
}
|
|
38
39
|
const data = await res.json();
|
|
39
40
|
if (!data.signed_key) {
|
|
40
|
-
throw new Error('No license key found.
|
|
41
|
+
throw new Error('No license key found. Request one at https://nexus-prime.cfd/account or email adarsh@nexus-prime.cfd. Licenses are reviewed within 24 hours.');
|
|
41
42
|
}
|
|
42
43
|
const lm = getSharedLicenseManager();
|
|
43
44
|
return lm.activate(data.signed_key);
|
|
@@ -49,7 +50,7 @@ export async function syncLicense() {
|
|
|
49
50
|
export async function requestUpgrade(requestedPlan) {
|
|
50
51
|
const authToken = readAuthToken();
|
|
51
52
|
if (!authToken) {
|
|
52
|
-
throw new Error('Not logged in. Run: nexus-prime license login');
|
|
53
|
+
throw new Error('Not logged in. Run: nexus-prime license login, or use https://nexus-prime.cfd/account / adarsh@nexus-prime.cfd.');
|
|
53
54
|
}
|
|
54
55
|
const res = await fetch(`${API_BASE}/api/license/request-upgrade`, {
|
|
55
56
|
method: 'POST',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type PlanTier = 'free' | 'pro' | 'team' | 'enterprise';
|
|
2
2
|
export type SkillProfile = 'foundation' | 'all-builtin' | 'all-custom' | 'all-registry';
|
|
3
3
|
export type DarwinScope = 'off' | 'solo' | 'team' | 'fleet';
|
|
4
|
+
export type TrialPhase = 'grace' | 'activation' | 'expired';
|
|
4
5
|
export interface PlanCaps {
|
|
5
6
|
maxProjects: number;
|
|
6
7
|
maxMemoryEntries: number;
|
|
@@ -27,9 +28,24 @@ export interface LicenseStatus {
|
|
|
27
28
|
orgId: string | null;
|
|
28
29
|
/** True when the active status is the auto-issued local trial. */
|
|
29
30
|
trial?: boolean;
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/** Trial phase for PLG surfaces. First three days are grace, then activation prompts become direct. */
|
|
32
|
+
trialPhase?: TrialPhase;
|
|
33
|
+
trialIssuedAt?: number;
|
|
34
|
+
trialGraceEndsAt?: number;
|
|
35
|
+
trialDaysElapsed?: number;
|
|
36
|
+
trialDaysRemaining?: number;
|
|
37
|
+
activationRequired?: boolean;
|
|
38
|
+
activationMotion?: {
|
|
39
|
+
phase: TrialPhase;
|
|
40
|
+
required: boolean;
|
|
41
|
+
title: string;
|
|
42
|
+
message: string;
|
|
43
|
+
action: string;
|
|
44
|
+
url: string;
|
|
45
|
+
command: string;
|
|
46
|
+
};
|
|
47
|
+
/** Reason a license is degraded; absent when status is valid. */
|
|
48
|
+
degradedReason?: 'expired' | 'signature-invalid' | 'malformed' | 'not-activated' | 'activation-required' | 'trial-expired';
|
|
33
49
|
}
|
|
34
50
|
export type CapType = 'memory_entries' | 'projects' | 'operatives';
|
|
35
51
|
export interface CapCheckResult {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PlanTier, CapCheckResult } from './types.js';
|
|
1
|
+
import type { PlanTier, CapCheckResult, LicenseStatus } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Soft nudge at 80% of cap — single line appended to tool response.
|
|
4
4
|
*/
|
|
@@ -19,7 +19,7 @@ export declare function noLicenseMessage(): string;
|
|
|
19
19
|
* Trial is active. Soft hint that surfaces alongside paid tools so users
|
|
20
20
|
* know the auto-issued window is what's keeping their runtime alive.
|
|
21
21
|
*/
|
|
22
|
-
export declare function trialActiveMessage(
|
|
22
|
+
export declare function trialActiveMessage(statusOrExpiresAt: LicenseStatus | number | null): string;
|
|
23
23
|
/**
|
|
24
24
|
* Trial has expired — runtime drops to free caps. Tell the user clearly so
|
|
25
25
|
* the gap between trial-expired and a real license is obvious.
|
|
@@ -14,6 +14,7 @@ async function emitUpgradeNudge(currentTier, feature, message, ctaUrl) {
|
|
|
14
14
|
}
|
|
15
15
|
const UPGRADE_URL = 'https://nexus-prime.cfd/account';
|
|
16
16
|
const SIGNUP_URL = 'https://nexus-prime.cfd/signup';
|
|
17
|
+
const LICENSE_TEAM_EMAIL = 'adarsh@nexus-prime.cfd';
|
|
17
18
|
const CAP_LABELS = {
|
|
18
19
|
memory_entries: 'memory entries',
|
|
19
20
|
projects: 'projects',
|
|
@@ -55,21 +56,39 @@ export function toolGateMessage(toolName, requiredTier, currentTier) {
|
|
|
55
56
|
*/
|
|
56
57
|
export function noLicenseMessage() {
|
|
57
58
|
return [
|
|
58
|
-
`[Nexus Prime] No license activated.
|
|
59
|
+
`[Nexus Prime] No license activated. Request a license before paid-tier work runs:`,
|
|
59
60
|
` → ${SIGNUP_URL}`,
|
|
60
|
-
`
|
|
61
|
+
` Account: ${UPGRADE_URL}`,
|
|
62
|
+
` Email: ${LICENSE_TEAM_EMAIL}`,
|
|
63
|
+
` Licenses are reviewed and shared by the team within 24 hours.`,
|
|
64
|
+
` Then activate: nexus-prime license activate <your-token>`,
|
|
61
65
|
].join('\n');
|
|
62
66
|
}
|
|
63
67
|
/**
|
|
64
68
|
* Trial is active. Soft hint that surfaces alongside paid tools so users
|
|
65
69
|
* know the auto-issued window is what's keeping their runtime alive.
|
|
66
70
|
*/
|
|
67
|
-
export function trialActiveMessage(
|
|
68
|
-
const
|
|
71
|
+
export function trialActiveMessage(statusOrExpiresAt) {
|
|
72
|
+
const status = typeof statusOrExpiresAt === 'object' ? statusOrExpiresAt : null;
|
|
73
|
+
const expiresAt = status ? status.expiresAt : typeof statusOrExpiresAt === 'number' ? statusOrExpiresAt : null;
|
|
74
|
+
const daysLeft = status?.trialDaysRemaining
|
|
75
|
+
?? (expiresAt ? Math.max(0, Math.ceil((expiresAt - Date.now()) / (24 * 60 * 60 * 1000))) : 0);
|
|
76
|
+
if (status?.activationRequired) {
|
|
77
|
+
return [
|
|
78
|
+
`[Nexus Prime] License required — the 3-day no-license grace period is over.`,
|
|
79
|
+
` Agent motion: ask the user to request or activate a Nexus Prime license now before continuing.`,
|
|
80
|
+
` Trial window after activation: ${daysLeft} day${daysLeft === 1 ? '' : 's'} remaining.`,
|
|
81
|
+
` Request: ${UPGRADE_URL}`,
|
|
82
|
+
` Email: ${LICENSE_TEAM_EMAIL}`,
|
|
83
|
+
` The Nexus Prime team will share licenses within 24 hours.`,
|
|
84
|
+
` Activate: nexus-prime license activate <token>`,
|
|
85
|
+
].join('\n');
|
|
86
|
+
}
|
|
69
87
|
return [
|
|
70
|
-
`[Nexus Prime]
|
|
71
|
-
`
|
|
72
|
-
`
|
|
88
|
+
`[Nexus Prime] 3-day no-license grace active (${daysLeft} day${daysLeft === 1 ? '' : 's'} in the trial window).`,
|
|
89
|
+
` Request a license before day 4: ${UPGRADE_URL}`,
|
|
90
|
+
` Email fallback: ${LICENSE_TEAM_EMAIL}`,
|
|
91
|
+
` Licenses are reviewed and shared within 24 hours.`,
|
|
73
92
|
].join('\n');
|
|
74
93
|
}
|
|
75
94
|
/**
|
|
@@ -78,8 +97,10 @@ export function trialActiveMessage(expiresAt) {
|
|
|
78
97
|
*/
|
|
79
98
|
export function trialExpiredMessage() {
|
|
80
99
|
return [
|
|
81
|
-
`[Nexus Prime] Trial expired —
|
|
100
|
+
`[Nexus Prime] Trial expired — license required for paid-tier work.`,
|
|
101
|
+
` Request: ${UPGRADE_URL}`,
|
|
102
|
+
` Email: ${LICENSE_TEAM_EMAIL}`,
|
|
103
|
+
` Licenses are reviewed and shared within 24 hours.`,
|
|
82
104
|
` Activate: nexus-prime license activate <token>`,
|
|
83
|
-
` Pricing: ${UPGRADE_URL}`,
|
|
84
105
|
].join('\n');
|
|
85
106
|
}
|
|
@@ -7,8 +7,8 @@ interface AuthTokens {
|
|
|
7
7
|
/**
|
|
8
8
|
* Login to nexus-prime.cfd and store auth tokens locally. Errors are
|
|
9
9
|
* normalised so signup/signin failures don't surface raw HTTP codes —
|
|
10
|
-
* users get something actionable, plus a reminder that the local
|
|
11
|
-
*
|
|
10
|
+
* users get something actionable, plus a reminder that the local no-license
|
|
11
|
+
* grace period is intentionally short and licenses are reviewed manually.
|
|
12
12
|
*/
|
|
13
13
|
export declare function loginFromCLI(email: string, password: string): Promise<{
|
|
14
14
|
email: string;
|
|
@@ -12,8 +12,8 @@ const API_BASE = process.env.NEXUS_WEB_API_URL ?? 'https://nexus-prime.cfd';
|
|
|
12
12
|
/**
|
|
13
13
|
* Login to nexus-prime.cfd and store auth tokens locally. Errors are
|
|
14
14
|
* normalised so signup/signin failures don't surface raw HTTP codes —
|
|
15
|
-
* users get something actionable, plus a reminder that the local
|
|
16
|
-
*
|
|
15
|
+
* users get something actionable, plus a reminder that the local no-license
|
|
16
|
+
* grace period is intentionally short and licenses are reviewed manually.
|
|
17
17
|
*/
|
|
18
18
|
export async function loginFromCLI(email, password) {
|
|
19
19
|
let res;
|
|
@@ -28,8 +28,8 @@ export async function loginFromCLI(email, password) {
|
|
|
28
28
|
catch (err) {
|
|
29
29
|
const reason = err instanceof Error ? err.message : String(err);
|
|
30
30
|
throw new Error(`Could not reach ${API_BASE}: ${reason}. `
|
|
31
|
-
+ `
|
|
32
|
-
+ `
|
|
31
|
+
+ `If your 3-day no-license grace is over, request a license at ${API_BASE}/account `
|
|
32
|
+
+ `or email adarsh@nexus-prime.cfd. Licenses are shared within 24 hours.`);
|
|
33
33
|
}
|
|
34
34
|
if (!res.ok) {
|
|
35
35
|
const body = await res.json().catch(() => ({}));
|
|
@@ -41,10 +41,10 @@ export async function loginFromCLI(email, password) {
|
|
|
41
41
|
}
|
|
42
42
|
if (res.status === 404) {
|
|
43
43
|
throw new Error(`No account for ${email}. Sign up at ${API_BASE}/signup, then retry. `
|
|
44
|
-
+ `
|
|
44
|
+
+ `If you need manual help, email adarsh@nexus-prime.cfd. Licenses are shared within 24 hours.`);
|
|
45
45
|
}
|
|
46
46
|
if (res.status >= 500) {
|
|
47
|
-
throw new Error(`Server error (${res.status}) at ${API_BASE}.
|
|
47
|
+
throw new Error(`Server error (${res.status}) at ${API_BASE}. Try again shortly, or email adarsh@nexus-prime.cfd for a manual license review within 24 hours.`);
|
|
48
48
|
}
|
|
49
49
|
throw new Error(detail ?? `Login failed (HTTP ${res.status})`);
|
|
50
50
|
}
|
|
@@ -122,17 +122,19 @@ async function runWithRetry(maxRetries = 3, delayMs = 1000) {
|
|
|
122
122
|
registerInstall(installId || 'unknown', version);
|
|
123
123
|
}
|
|
124
124
|
catch { /* non-fatal — install tracking is best-effort */ }
|
|
125
|
-
// Show license
|
|
125
|
+
// Show license request prompt
|
|
126
126
|
if (shouldShowInstallBanner()) {
|
|
127
127
|
try {
|
|
128
128
|
const licenseKeyPath = path.join(os.homedir(), '.nexus-prime', 'license.key');
|
|
129
129
|
if (!fs.existsSync(licenseKeyPath)) {
|
|
130
130
|
console.log('');
|
|
131
131
|
console.log('\u2554' + '\u2550'.repeat(50) + '\u2557');
|
|
132
|
-
console.log('\u2551
|
|
133
|
-
console.log('\u2551
|
|
132
|
+
console.log('\u2551 3-day no-license grace is active. \u2551');
|
|
133
|
+
console.log('\u2551 Request a license before day 4: \u2551');
|
|
134
|
+
console.log('\u2551 \u2192 https://nexus-prime.cfd/account \u2551');
|
|
135
|
+
console.log('\u2551 \u2192 adarsh@nexus-prime.cfd \u2551');
|
|
134
136
|
console.log('\u2551 \u2551');
|
|
135
|
-
console.log('\u2551
|
|
137
|
+
console.log('\u2551 Team shares licenses within 24 hours. \u2551');
|
|
136
138
|
console.log('\u2551 nexus-prime license activate <your-token> \u2551');
|
|
137
139
|
console.log('\u255A' + '\u2550'.repeat(50) + '\u255D');
|
|
138
140
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexus-prime",
|
|
3
|
-
"version": "7.9.
|
|
3
|
+
"version": "7.9.16",
|
|
4
4
|
"description": "Local-first MCP control plane for coding agents with bootstrap-orchestrate execution, memory fabric, token budgeting, and worktree-backed swarms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|