nyxora 26.7.22 → 26.7.23
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/CHANGELOG.md +18 -0
- package/bin/nyxora.mjs +7 -1
- package/dist/launcher.js +2 -2
- package/dist/packages/core/src/agent/osAgent.js +16 -45
- package/dist/packages/core/src/agent/web3Agent.js +9 -4
- package/dist/packages/core/src/gateway/server.js +44 -1
- package/dist/packages/core/src/system/skills/executeShell.js +4 -0
- package/dist/packages/core/src/system/skills/executeShellPTY.js +2 -1
- package/dist/packages/core/src/utils/dynamicTokenUpdater.js +14 -1
- package/dist/packages/core/src/utils/historySanitizer.js +17 -2
- package/dist/packages/core/src/web3/skills/checkPortfolio.js +41 -38
- package/launcher.ts +2 -2
- package/package.json +2 -9
- package/packages/core/package.json +1 -1
- package/packages/core/src/agent/osAgent.ts +18 -45
- package/packages/core/src/agent/web3Agent.ts +9 -4
- package/packages/core/src/gateway/server.ts +46 -1
- package/packages/core/src/system/skills/executeShell.ts +5 -0
- package/packages/core/src/system/skills/executeShellPTY.ts +2 -1
- package/packages/core/src/utils/dynamicTokenUpdater.ts +16 -2
- package/packages/core/src/utils/historySanitizer.ts +16 -2
- package/packages/core/src/web3/skills/checkPortfolio.ts +45 -41
- package/packages/dashboard/dist/assets/index-Cxh73Rml.js +87 -0
- package/packages/dashboard/dist/assets/index-DLBxY6G0.css +1 -0
- package/packages/dashboard/dist/index.html +2 -2
- package/packages/dashboard/package.json +1 -1
- package/packages/mcp-server/package.json +1 -1
- package/packages/policy/package.json +1 -1
- package/packages/signer/package.json +1 -1
- package/packages/tui/dist/app/App.js +28 -0
- package/packages/tui/dist/components/MainArea.js +110 -0
- package/packages/tui/dist/components/Sidebar.js +5 -0
- package/packages/tui/dist/components/logo.js +50 -0
- package/packages/tui/dist/index.js +11 -53
- package/packages/tui/package.json +9 -20
- package/packages/dashboard/dist/assets/index-AGu4iXxs.css +0 -1
- package/packages/dashboard/dist/assets/index-C-jQzkzL.js +0 -87
- package/packages/nyxora-ink/ambient.d.ts +0 -92
- package/packages/nyxora-ink/dist/entry-exports.js +0 -14294
- package/packages/nyxora-ink/index.d.ts +0 -41
- package/packages/nyxora-ink/index.js +0 -1
- package/packages/nyxora-ink/package.json +0 -59
- package/packages/nyxora-ink/text-input.d.ts +0 -2
- package/packages/nyxora-ink/text-input.js +0 -1
- package/packages/tui/dist/app/createGatewayEventHandler.js +0 -728
- package/packages/tui/dist/app/createSlashHandler.js +0 -114
- package/packages/tui/dist/app/delegationStore.js +0 -47
- package/packages/tui/dist/app/gatewayContext.js +0 -13
- package/packages/tui/dist/app/gatewayRecovery.js +0 -19
- package/packages/tui/dist/app/inputSelectionStore.js +0 -4
- package/packages/tui/dist/app/interfaces.js +0 -6
- package/packages/tui/dist/app/overlayStore.js +0 -56
- package/packages/tui/dist/app/petFlashStore.js +0 -16
- package/packages/tui/dist/app/scroll.js +0 -44
- package/packages/tui/dist/app/setupHandoff.js +0 -28
- package/packages/tui/dist/app/slash/commands/billing.js +0 -248
- package/packages/tui/dist/app/slash/commands/core.js +0 -534
- package/packages/tui/dist/app/slash/commands/credits.js +0 -44
- package/packages/tui/dist/app/slash/commands/debug.js +0 -40
- package/packages/tui/dist/app/slash/commands/ops.js +0 -531
- package/packages/tui/dist/app/slash/commands/session.js +0 -481
- package/packages/tui/dist/app/slash/commands/setup.js +0 -16
- package/packages/tui/dist/app/slash/registry.js +0 -18
- package/packages/tui/dist/app/slash/types.js +0 -1
- package/packages/tui/dist/app/spawnHistoryStore.js +0 -117
- package/packages/tui/dist/app/submissionCore.js +0 -80
- package/packages/tui/dist/app/turnController.js +0 -802
- package/packages/tui/dist/app/turnStore.js +0 -44
- package/packages/tui/dist/app/uiStore.js +0 -36
- package/packages/tui/dist/app/useComposerState.js +0 -264
- package/packages/tui/dist/app/useConfigSync.js +0 -203
- package/packages/tui/dist/app/useInputHandlers.js +0 -483
- package/packages/tui/dist/app/useLongRunToolCharms.js +0 -46
- package/packages/tui/dist/app/useMainApp.js +0 -851
- package/packages/tui/dist/app/usePet.js +0 -219
- package/packages/tui/dist/app/useSessionLifecycle.js +0 -268
- package/packages/tui/dist/app/useSubmission.js +0 -238
- package/packages/tui/dist/app.js +0 -11
- package/packages/tui/dist/banner.js +0 -55
- package/packages/tui/dist/components/activeSessionSwitcher.js +0 -503
- package/packages/tui/dist/components/agentsOverlay.js +0 -443
- package/packages/tui/dist/components/appChrome.js +0 -425
- package/packages/tui/dist/components/appLayout.js +0 -189
- package/packages/tui/dist/components/appOverlays.js +0 -76
- package/packages/tui/dist/components/billingOverlay.js +0 -375
- package/packages/tui/dist/components/branding.js +0 -143
- package/packages/tui/dist/components/fpsOverlay.js +0 -18
- package/packages/tui/dist/components/helpHint.js +0 -17
- package/packages/tui/dist/components/journey.js +0 -286
- package/packages/tui/dist/components/markdown.js +0 -722
- package/packages/tui/dist/components/maskedPrompt.js +0 -8
- package/packages/tui/dist/components/messageLine.js +0 -98
- package/packages/tui/dist/components/modelPicker.js +0 -368
- package/packages/tui/dist/components/overlayControls.js +0 -26
- package/packages/tui/dist/components/overlayScrollbar.js +0 -41
- package/packages/tui/dist/components/petPicker.js +0 -97
- package/packages/tui/dist/components/petSprite.js +0 -49
- package/packages/tui/dist/components/pluginsHub.js +0 -127
- package/packages/tui/dist/components/prompts.js +0 -133
- package/packages/tui/dist/components/queuedMessages.js +0 -20
- package/packages/tui/dist/components/skillsHub.js +0 -161
- package/packages/tui/dist/components/streamingAssistant.js +0 -59
- package/packages/tui/dist/components/streamingMarkdown.js +0 -140
- package/packages/tui/dist/components/textInput.js +0 -1080
- package/packages/tui/dist/components/themed.js +0 -8
- package/packages/tui/dist/components/thinking.js +0 -501
- package/packages/tui/dist/components/todoPanel.js +0 -36
- package/packages/tui/dist/config/env.js +0 -56
- package/packages/tui/dist/config/limits.js +0 -22
- package/packages/tui/dist/config/timing.js +0 -13
- package/packages/tui/dist/content/charms.js +0 -1
- package/packages/tui/dist/content/faces.js +0 -17
- package/packages/tui/dist/content/fortunes.js +0 -25
- package/packages/tui/dist/content/hotkeys.js +0 -34
- package/packages/tui/dist/content/placeholders.js +0 -11
- package/packages/tui/dist/content/setup.js +0 -14
- package/packages/tui/dist/content/verbs.js +0 -37
- package/packages/tui/dist/domain/blockLayout.js +0 -95
- package/packages/tui/dist/domain/details.js +0 -53
- package/packages/tui/dist/domain/messages.js +0 -59
- package/packages/tui/dist/domain/paths.js +0 -27
- package/packages/tui/dist/domain/providers.js +0 -7
- package/packages/tui/dist/domain/roles.js +0 -6
- package/packages/tui/dist/domain/slash.js +0 -43
- package/packages/tui/dist/domain/usage.js +0 -1
- package/packages/tui/dist/domain/viewport.js +0 -33
- package/packages/tui/dist/entry.js +0 -124
- package/packages/tui/dist/gatewayClient.js +0 -634
- package/packages/tui/dist/gatewayTypes.js +0 -1
- package/packages/tui/dist/hooks/useCompletion.js +0 -82
- package/packages/tui/dist/hooks/useGitBranch.js +0 -54
- package/packages/tui/dist/hooks/useInputHistory.js +0 -8
- package/packages/tui/dist/hooks/useQueue.js +0 -53
- package/packages/tui/dist/hooks/useVirtualHistory.js +0 -416
- package/packages/tui/dist/lib/circularBuffer.js +0 -39
- package/packages/tui/dist/lib/clipboard.js +0 -137
- package/packages/tui/dist/lib/editor.js +0 -57
- package/packages/tui/dist/lib/editor.test.js +0 -54
- package/packages/tui/dist/lib/emoji.js +0 -45
- package/packages/tui/dist/lib/externalCli.js +0 -7
- package/packages/tui/dist/lib/externalLink.js +0 -335
- package/packages/tui/dist/lib/forceTruecolor.js +0 -46
- package/packages/tui/dist/lib/fpsStore.js +0 -32
- package/packages/tui/dist/lib/fuzzy.js +0 -129
- package/packages/tui/dist/lib/fuzzy.test.js +0 -88
- package/packages/tui/dist/lib/gracefulExit.js +0 -36
- package/packages/tui/dist/lib/history.js +0 -65
- package/packages/tui/dist/lib/inputMetrics.js +0 -158
- package/packages/tui/dist/lib/liveProgress.js +0 -51
- package/packages/tui/dist/lib/liveProgress.test.js +0 -85
- package/packages/tui/dist/lib/mathUnicode.js +0 -685
- package/packages/tui/dist/lib/memory.js +0 -159
- package/packages/tui/dist/lib/memory.test.js +0 -135
- package/packages/tui/dist/lib/memoryMonitor.js +0 -130
- package/packages/tui/dist/lib/messages.js +0 -3
- package/packages/tui/dist/lib/messages.test.js +0 -21
- package/packages/tui/dist/lib/openExternalUrl.js +0 -133
- package/packages/tui/dist/lib/openExternalUrl.test.js +0 -162
- package/packages/tui/dist/lib/osc52.js +0 -49
- package/packages/tui/dist/lib/parentLog.js +0 -53
- package/packages/tui/dist/lib/perfPane.js +0 -90
- package/packages/tui/dist/lib/platform.js +0 -309
- package/packages/tui/dist/lib/precisionWheel.js +0 -21
- package/packages/tui/dist/lib/prompt.js +0 -23
- package/packages/tui/dist/lib/reasoning.js +0 -40
- package/packages/tui/dist/lib/resizeCoalescer.js +0 -46
- package/packages/tui/dist/lib/resizeCoalescer.test.js +0 -65
- package/packages/tui/dist/lib/rpc.js +0 -33
- package/packages/tui/dist/lib/starmapPalette.js +0 -104
- package/packages/tui/dist/lib/subagentTree.js +0 -284
- package/packages/tui/dist/lib/syntax.js +0 -89
- package/packages/tui/dist/lib/terminalModes.js +0 -42
- package/packages/tui/dist/lib/terminalParity.js +0 -44
- package/packages/tui/dist/lib/terminalSetup.js +0 -317
- package/packages/tui/dist/lib/termux.js +0 -24
- package/packages/tui/dist/lib/text.js +0 -258
- package/packages/tui/dist/lib/text.test.js +0 -39
- package/packages/tui/dist/lib/todo.js +0 -2
- package/packages/tui/dist/lib/todo.test.js +0 -18
- package/packages/tui/dist/lib/viewportStore.js +0 -82
- package/packages/tui/dist/lib/virtualHeights.js +0 -113
- package/packages/tui/dist/lib/wheelAccel.js +0 -139
- package/packages/tui/dist/protocol/interpolation.js +0 -2
- package/packages/tui/dist/protocol/paste.js +0 -1
- package/packages/tui/dist/theme.js +0 -396
- package/packages/tui/dist/types.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## [26.7.23]
|
|
8
|
+
### Dashboard Features & UI
|
|
9
|
+
- **System & Maintenance Module**: Engineered the `System.tsx` component from scratch. The interface now features a sleek, edge-to-edge stacked row list design, completely abandoning the legacy card-based layout for a more professional, native application feel.
|
|
10
|
+
- **Native System Operations**: Implemented deep integration between the React frontend and the Node.js daemon. Users can now natively trigger **Restart Server**, **Shutdown Server**, and **Clear System Cache** directly from the UI without touching the CLI.
|
|
11
|
+
- **OS Autostart Controller**: Introduced a cross-platform Auto-Start toggle in the dashboard. The system dynamically queries and manages `.desktop` (Linux) and `.plist` (macOS) configurations via `GET/POST /api/system/autostart`.
|
|
12
|
+
- **Wallet Balances Fix**: Resolved a data mapping issue in `Wallets.tsx`. The component now correctly utilizes `viem`'s `formatUnits` combined with backend `decimals` and `priceUsd` to flawlessly compute and render real-time fiat values for multi-chain assets. Added a functional Refresh button to sync the latest portfolio states.
|
|
13
|
+
- **Minimalist Aesthetic**: Purged redundant icons/emojis across the System settings to achieve a clean, text-heavy minimalist aesthetic, reserving visual icons strictly for the page header and footer.
|
|
14
|
+
|
|
15
|
+
### Bug Fixes & Agent Enhancements
|
|
16
|
+
- **Windows CLI Spawn Fix (Critical)**: Resolved a major UX issue for global Windows users where running `nyxora start` would rapidly spawn multiple visible `cmd.exe` and `node.exe` console windows. Implemented `windowsHide: true` across all detached daemon spawns and Cloudflared sub-processes in `nyxora.mjs` and `launcher.ts`, ensuring Nyxora boots perfectly in headless mode on Windows without spamming the user's desktop.
|
|
17
|
+
- **Windows CLI Stop/Restart Fix**: Fixed a critical crash where `nyxora stop` and `nyxora restart` failed on Windows systems. Switched process termination from POSIX-only `-pid` (Process Group Signal) to native Windows `taskkill /pid <PID> /t /f` via `spawnSync`, ensuring all daemon and microservice child processes (like Python ML Engine) are cleanly forcefully terminated without leaving zombie processes.
|
|
18
|
+
- **Smart Anti-Loop Breaker V2.0**: Completely overhauled the agent's anti-loop safety mechanism. Removed rigid hard-limits on specific tool usage (e.g. `write_local_file`) to allow unconstrained complex coding sessions. Replaced it with an intelligent "Soft Warning" system that injects a self-reflection prompt into the LLM's context every 5 repetitions, allowing the AI to organically realize if it's hallucinating and ask the user for help. Also increased global `MAX_TURNS` from 30 to 50 for extended autonomous workflows.
|
|
19
|
+
- **Auto-Scroll Chat Snap Fix**: Resolved a Dashboard UI glitch where LLM text streaming would scroll the container to the top instead of the bottom. Fixed ResizeObserver spacer calculation timing and exact layout recalculation bounds, ensuring smooth and flawless chat autoscrolling identical to the Desktop app.
|
|
20
|
+
## [26.7.22]
|
|
21
|
+
### Bug Fixes & Monorepo Enhancements
|
|
22
|
+
- **Global `npm install` Crash Fix (Critical Fix)**: Resolved a severe issue where `nyxora start` would crash immediately after global installation (`npm install -g nyxora`) due to missing dependencies. All required workspace dependencies (e.g., `systeminformation`, messaging bot SDKs) have now been synced and hoisted to the root `package.json`, ensuring the background daemon can boot properly for global users without throwing `Cannot find module` errors.
|
|
23
|
+
- **Dependency Overrides Synchronization**: Fixed dependency conflict warnings during installation by aligning `lodash-es` and `undici` versions with the root workspace `overrides`.
|
|
24
|
+
|
|
7
25
|
## [26.7.21]
|
|
8
26
|
### Dashboard Features & UI
|
|
9
27
|
- **Control Panel Expansion**: Engineered 4 brand new native dashboard menus (`Memory`, `Security`, `Wallets`, `Workflows`) transforming the dashboard into a full-fledged agent control panel.
|
package/bin/nyxora.mjs
CHANGED
|
@@ -73,6 +73,7 @@ async function start() {
|
|
|
73
73
|
const child = spawn(cmd, args, {
|
|
74
74
|
cwd: projectRoot,
|
|
75
75
|
detached: true,
|
|
76
|
+
windowsHide: true,
|
|
76
77
|
stdio: ['ignore', out, err],
|
|
77
78
|
env: { ...process.env, TS_NODE_CACHE: 'false' }
|
|
78
79
|
});
|
|
@@ -91,7 +92,12 @@ async function stop(preserveTracker = false) {
|
|
|
91
92
|
if (pid) {
|
|
92
93
|
console.log(`Stopping Nyxora daemon (PID: ${pid})...`);
|
|
93
94
|
try {
|
|
94
|
-
process.
|
|
95
|
+
if (process.platform === 'win32') {
|
|
96
|
+
const { spawnSync } = await import('child_process');
|
|
97
|
+
spawnSync('taskkill', ['/pid', pid.toString(), '/t', '/f']);
|
|
98
|
+
} else {
|
|
99
|
+
process.kill(-pid, 'SIGTERM');
|
|
100
|
+
}
|
|
95
101
|
let attempts = 0;
|
|
96
102
|
while (isDaemonRunning(pid.toString()) && attempts < 20) {
|
|
97
103
|
await new Promise(r => setTimeout(r, 100));
|
package/dist/launcher.js
CHANGED
|
@@ -35,7 +35,7 @@ const spawnService = (name, command, args, env, inheritStdio = false, cwd) => {
|
|
|
35
35
|
let crashWindowStart = Date.now();
|
|
36
36
|
let isShuttingDown = false;
|
|
37
37
|
const startProcess = () => {
|
|
38
|
-
const spawnOpts = { env, stdio: inheritStdio ? 'inherit' : 'pipe' };
|
|
38
|
+
const spawnOpts = { env, stdio: inheritStdio ? 'inherit' : 'pipe', windowsHide: true };
|
|
39
39
|
if (cwd)
|
|
40
40
|
spawnOpts.cwd = cwd;
|
|
41
41
|
child = (0, child_process_1.spawn)(command, args, spawnOpts);
|
|
@@ -190,7 +190,7 @@ setTimeout(() => {
|
|
|
190
190
|
catch (e) { }
|
|
191
191
|
if (cfEnabled) {
|
|
192
192
|
console.log('[Launcher] Starting Auto-Tunnel (Cloudflare) on port 3000...');
|
|
193
|
-
const cf = (0, child_process_1.spawn)('npx', ['cloudflared', 'tunnel', '--url', 'http://localhost:3000'], { env, shell: true });
|
|
193
|
+
const cf = (0, child_process_1.spawn)('npx', ['cloudflared', 'tunnel', '--url', 'http://localhost:3000'], { env, shell: true, windowsHide: true });
|
|
194
194
|
children.push({
|
|
195
195
|
kill: () => { try {
|
|
196
196
|
process.kill(cf.pid, 'SIGTERM');
|
|
@@ -190,7 +190,7 @@ The user explicitly stated your previous response was WRONG, STALE, or INACCURAT
|
|
|
190
190
|
const cachedSystemPrompt = await getSystemPrompt('os', input, sessionId);
|
|
191
191
|
try {
|
|
192
192
|
let turnCount = 0;
|
|
193
|
-
const MAX_TURNS =
|
|
193
|
+
const MAX_TURNS = 50; // Increased to 50 to allow limitless tool usage without hard crashing
|
|
194
194
|
let consecutiveToolErrors = 0;
|
|
195
195
|
let criticHasFired = false; // Critic Pass hanya aktif 1x per request
|
|
196
196
|
// Anti-loop: track (toolName+argsHash) pairs from the PREVIOUS turn to
|
|
@@ -199,15 +199,7 @@ The user explicitly stated your previous response was WRONG, STALE, or INACCURAT
|
|
|
199
199
|
// ── Per-tool-name call count tracker ──────────────────────────────────────────────
|
|
200
200
|
// Catches loops where args differ per turn (e.g. search_web different query each time).
|
|
201
201
|
const osToolCallCounts = new Map();
|
|
202
|
-
|
|
203
|
-
'search_web': 5,
|
|
204
|
-
'search_files': 8,
|
|
205
|
-
'read_local_file': 10,
|
|
206
|
-
'run_terminal_command': 8,
|
|
207
|
-
'edit_local_file': 6,
|
|
208
|
-
'write_local_file': 6,
|
|
209
|
-
'__default__': 12,
|
|
210
|
-
};
|
|
202
|
+
// OS_TOOL_CALL_LIMITS removed: We now use soft-warnings (self-reflection) instead of hard limits.
|
|
211
203
|
// P6: Compress history ONCE before loop starts (not per iteration)
|
|
212
204
|
const rawHistory = exports.logger.getHistory(sessionId);
|
|
213
205
|
const initialHistory = (0, historySanitizer_1.pruneLoopedHistory)(rawHistory); // Collapse any failed loop runs
|
|
@@ -523,19 +515,15 @@ The user explicitly stated your previous response was WRONG, STALE, or INACCURAT
|
|
|
523
515
|
}, sessionId);
|
|
524
516
|
console.log(picocolors_1.default.red('[Anti-Loop] Repeat tool call signature detected across turns. Injecting block.'));
|
|
525
517
|
}
|
|
526
|
-
// Fix B: Per-tool-name count
|
|
518
|
+
// Fix B: Per-tool-name count soft-warning (prevents hallucination)
|
|
527
519
|
for (const tc of responseMessage.tool_calls) {
|
|
528
520
|
const tn = tc.function.name;
|
|
529
521
|
const count = osToolCallCounts.get(tn) || 0;
|
|
530
|
-
|
|
531
|
-
if (count
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
const forceStop = `⚠️ Loop breaker: '${tn}' called ${count}x (limit ${limit}). Stopping.`;
|
|
536
|
-
exports.logger.addEntry({ role: 'assistant', content: forceStop }, sessionId);
|
|
537
|
-
triggerBackgroundReview(sessionId);
|
|
538
|
-
return forceStop;
|
|
522
|
+
// Soft Warning every 5 times a tool is used
|
|
523
|
+
if (count > 0 && count % 5 === 0) {
|
|
524
|
+
const warningMsg = `[SYSTEM WARNING] You have used the tool '${tn}' ${count} times in this session. Are you making progress? If you are stuck in a loop of errors or hallucinating fixes without success, STOP using this tool and ask the user for clarification.`;
|
|
525
|
+
exports.logger.addEntry({ role: 'system', content: warningMsg }, sessionId);
|
|
526
|
+
console.warn(picocolors_1.default.yellow(`[OsAgent] ⚠️ ANTI-LOOP SOFT WARNING: '${tn}' called ${count}x. Injected self-reflection prompt.`));
|
|
539
527
|
}
|
|
540
528
|
}
|
|
541
529
|
// ── Partition into parallel (read-only) and serial (write) batches ───
|
|
@@ -706,7 +694,7 @@ The user explicitly stated your previous response was WRONG, STALE, or INACCURAT
|
|
|
706
694
|
try {
|
|
707
695
|
let turnCount = 0;
|
|
708
696
|
let nudgeCount = 0;
|
|
709
|
-
const MAX_TURNS =
|
|
697
|
+
const MAX_TURNS = 50; // Increased to 50 to allow limitless tool usage without hard crashing
|
|
710
698
|
let thinkingPrefillRetries = 0; // Prefill-continuation retries for think-only silent stops
|
|
711
699
|
let antiLoopStrikes = 0;
|
|
712
700
|
let fullResponse = '';
|
|
@@ -715,18 +703,7 @@ The user explicitly stated your previous response was WRONG, STALE, or INACCURAT
|
|
|
715
703
|
// ── Per-tool-name call count tracker (stream) ─────────────────────────────────────
|
|
716
704
|
// Catches loops where args differ per turn (e.g. search_web with different queries).
|
|
717
705
|
const osToolCallCountsStream = new Map();
|
|
718
|
-
|
|
719
|
-
'search_web': 5,
|
|
720
|
-
'search_files': 8,
|
|
721
|
-
'read_local_file': 10,
|
|
722
|
-
'run_terminal_command': 8,
|
|
723
|
-
'edit_local_file': 6,
|
|
724
|
-
'write_local_file': 6,
|
|
725
|
-
'search_playbook': 2,
|
|
726
|
-
'read_gmail_inbox': 3,
|
|
727
|
-
'search_gmail': 3,
|
|
728
|
-
'__default__': 12,
|
|
729
|
-
};
|
|
706
|
+
// OS_TOOL_CALL_LIMITS_STREAM removed: We now use soft-warnings (self-reflection) instead of hard limits.
|
|
730
707
|
// P6: Compress history ONCE before loop starts (not per iteration)
|
|
731
708
|
const rawHistoryStream = exports.logger.getHistory(sessionId);
|
|
732
709
|
const initialHistoryStream = (0, historySanitizer_1.pruneLoopedHistory)(rawHistoryStream); // Collapse any failed loop runs
|
|
@@ -886,20 +863,14 @@ Do NOT output filler text like "Wait, I will check". Act now.`;
|
|
|
886
863
|
for (const tc of responseMessage.tool_calls) {
|
|
887
864
|
const normalizedArgs = normalizeArgs(tc.function.arguments);
|
|
888
865
|
const sig = `${tc.function.name}:${normalizedArgs}`;
|
|
889
|
-
// Per-tool-name count
|
|
866
|
+
// Per-tool-name count soft warning (prevents hallucination)
|
|
890
867
|
const tnS = tc.function.name;
|
|
891
868
|
const countS = osToolCallCountsStream.get(tnS) || 0;
|
|
892
|
-
|
|
893
|
-
if (countS
|
|
894
|
-
console.warn(`[OsAgentStream] ⚠️ ANTI-LOOP: '${tnS}' called ${countS}x
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
exports.logger.addEntry({ role: 'system', content: stopMsg }, sessionId);
|
|
898
|
-
const forceMsg = `⚠️ Loop breaker: '${tnS}' called ${countS}x (limit ${limitS}). Stopping.`;
|
|
899
|
-
exports.logger.addEntry({ role: 'assistant', content: forceMsg }, sessionId);
|
|
900
|
-
await onChunk(forceMsg);
|
|
901
|
-
triggerBackgroundReview(sessionId);
|
|
902
|
-
return forceMsg;
|
|
869
|
+
// Soft Warning every 5 times a tool is used
|
|
870
|
+
if (countS > 0 && countS % 5 === 0) {
|
|
871
|
+
console.warn(`[OsAgentStream] ⚠️ ANTI-LOOP SOFT WARNING: '${tnS}' called ${countS}x. Injected self-reflection prompt.`);
|
|
872
|
+
const warningMsg = `[SYSTEM WARNING] You have used the tool '${tnS}' ${countS} times in this session. Are you making progress? If you are stuck in a loop of errors or hallucinating fixes without success, STOP using this tool and ask the user for clarification.`;
|
|
873
|
+
exports.logger.addEntry({ role: 'system', content: warningMsg }, sessionId);
|
|
903
874
|
}
|
|
904
875
|
if (historicalToolCallSigs.has(sig)) {
|
|
905
876
|
// Exact-sig repeat across turns
|
|
@@ -749,10 +749,15 @@ Do NOT output filler text like "Wait, I will check". Act now.`;
|
|
|
749
749
|
fullResponse = cleanNarrative;
|
|
750
750
|
}
|
|
751
751
|
catch {
|
|
752
|
-
// Fallback to raw data if summary call fails
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
752
|
+
// Fallback to raw data if summary call fails — clean it first
|
|
753
|
+
const cleanRawData = rawData
|
|
754
|
+
.replace(/\[SILENT_FAST_RETURN\] /g, '')
|
|
755
|
+
.replace(/\[System Error\][^\n]*/g, '')
|
|
756
|
+
.trim();
|
|
757
|
+
onChunk('[CLEAR_STREAM]');
|
|
758
|
+
await onChunk(cleanRawData);
|
|
759
|
+
exports.logger.addEntry({ role: 'assistant', content: cleanRawData }, sessionId);
|
|
760
|
+
fullResponse = cleanRawData;
|
|
756
761
|
}
|
|
757
762
|
// ────────────────────────────────────────────────────────────────
|
|
758
763
|
break;
|
|
@@ -91,7 +91,7 @@ app.use((0, helmet_1.default)({
|
|
|
91
91
|
contentSecurityPolicy: {
|
|
92
92
|
directives: {
|
|
93
93
|
defaultSrc: ["'self'"],
|
|
94
|
-
imgSrc: ["'self'", 'data:', 'https://raw.githubusercontent.com', 'https://logos.covalenthq.com'],
|
|
94
|
+
imgSrc: ["'self'", 'data:', 'https://raw.githubusercontent.com', 'https://logos.covalenthq.com', 'https://cdn.simpleicons.org'],
|
|
95
95
|
scriptSrc: ["'self'", "'unsafe-inline'"],
|
|
96
96
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
97
97
|
connectSrc: ["'self'", 'https://*']
|
|
@@ -379,6 +379,49 @@ app.get('/api/system/pick-folder', (req, res) => {
|
|
|
379
379
|
res.status(400).json({ error: 'Canceled' });
|
|
380
380
|
}
|
|
381
381
|
});
|
|
382
|
+
app.post('/api/system/restart', (req, res) => {
|
|
383
|
+
res.json({ success: true, message: 'Restarting daemon...' });
|
|
384
|
+
const childProcess = require('child_process');
|
|
385
|
+
setTimeout(() => {
|
|
386
|
+
childProcess.spawn('node', ['./bin/nyxora.mjs', 'restart'], { cwd: process.cwd(), detached: true, stdio: 'ignore' }).unref();
|
|
387
|
+
}, 500);
|
|
388
|
+
});
|
|
389
|
+
app.post('/api/system/shutdown', (req, res) => {
|
|
390
|
+
res.json({ success: true, message: 'Shutting down daemon...' });
|
|
391
|
+
const childProcess = require('child_process');
|
|
392
|
+
setTimeout(() => {
|
|
393
|
+
childProcess.spawn('node', ['./bin/nyxora.mjs', 'stop'], { cwd: process.cwd(), detached: true, stdio: 'ignore' }).unref();
|
|
394
|
+
}, 500);
|
|
395
|
+
});
|
|
396
|
+
app.post('/api/system/clear-cache', (req, res) => {
|
|
397
|
+
const childProcess = require('child_process');
|
|
398
|
+
childProcess.exec('node ./bin/nyxora.mjs clean-logs', { cwd: process.cwd() }, (err) => {
|
|
399
|
+
if (err)
|
|
400
|
+
return res.status(500).json({ error: 'Failed to clear cache' });
|
|
401
|
+
res.json({ success: true });
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
app.get('/api/system/autostart', (req, res) => {
|
|
405
|
+
const isLinux = process.platform === 'linux';
|
|
406
|
+
const isMac = process.platform === 'darwin';
|
|
407
|
+
let enabled = false;
|
|
408
|
+
if (isLinux) {
|
|
409
|
+
enabled = require('fs').existsSync(require('path').join(require('os').homedir(), '.config', 'autostart', 'nyxora.desktop'));
|
|
410
|
+
}
|
|
411
|
+
else if (isMac) {
|
|
412
|
+
enabled = require('fs').existsSync(require('path').join(require('os').homedir(), 'Library', 'LaunchAgents', 'com.nyxora.gateway.plist'));
|
|
413
|
+
}
|
|
414
|
+
res.json({ enabled });
|
|
415
|
+
});
|
|
416
|
+
app.post('/api/system/autostart', (req, res) => {
|
|
417
|
+
const action = req.body.enabled ? 'enable' : 'disable';
|
|
418
|
+
const childProcess = require('child_process');
|
|
419
|
+
childProcess.exec(`node ./bin/nyxora.mjs autostart ${action}`, { cwd: process.cwd() }, (err) => {
|
|
420
|
+
if (err)
|
|
421
|
+
return res.status(500).json({ error: 'Failed to configure autostart' });
|
|
422
|
+
res.json({ success: true });
|
|
423
|
+
});
|
|
424
|
+
});
|
|
382
425
|
app.put('/api/sessions/:id', (req, res) => {
|
|
383
426
|
try {
|
|
384
427
|
const { title } = req.body;
|
|
@@ -89,6 +89,10 @@ async function runTerminalCommand(command, cwd, envType = 'local', dockerImage =
|
|
|
89
89
|
output += `ERROR:\n${error.message}\n`;
|
|
90
90
|
if (!output)
|
|
91
91
|
output = "Command executed successfully with no output.";
|
|
92
|
+
// Clean ANSI escape codes and control characters for LLM readability
|
|
93
|
+
output = output
|
|
94
|
+
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '')
|
|
95
|
+
.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, '');
|
|
92
96
|
// If sudo failed due to missing password, give a helpful hint
|
|
93
97
|
if (needsSudo && (output.includes('sudo: a password is required') || output.includes('no password supplied'))) {
|
|
94
98
|
output += `\n[NYXORA HINT] To allow Nyxora to run sudo commands automatically, add the following to your ~/.nyxora/config.yaml:\n security:\n sudo_password: YOUR_SUDO_PASSWORD\nAlternatively, run this command yourself in a terminal: ${command}`;
|
|
@@ -105,7 +105,8 @@ async function runTerminalCommandPTY(command, autoSudoPassword, cwd) {
|
|
|
105
105
|
ptyProcess.onExit(({ exitCode }) => {
|
|
106
106
|
// Clean ANSI escape codes for LLM readability
|
|
107
107
|
const cleanOutput = output
|
|
108
|
-
.replace(/\x1b\[[0-9;]*
|
|
108
|
+
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '') // Remove ALL ANSI escape sequences (colors, cursor movements, etc.)
|
|
109
|
+
.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, '') // Remove all non-printable control characters except \n, \r, \t
|
|
109
110
|
.replace(/\r\n/g, '\n') // Normalize line endings
|
|
110
111
|
.trim();
|
|
111
112
|
if (exitCode === 0) {
|
|
@@ -17,6 +17,14 @@ const TOKEN_LIST_URLS = {
|
|
|
17
17
|
optimism: 'https://static.optimism.io/optimism.tokenlist.json',
|
|
18
18
|
bsc: 'https://tokens.pancakeswap.finance/pancakeswap-extended.json'
|
|
19
19
|
};
|
|
20
|
+
// Numeric chainId for each chain so we can filter token lists by chainId field
|
|
21
|
+
const CHAIN_ID_MAP = {
|
|
22
|
+
ethereum: 1,
|
|
23
|
+
base: 8453,
|
|
24
|
+
arbitrum: 42161,
|
|
25
|
+
optimism: 10,
|
|
26
|
+
bsc: 56,
|
|
27
|
+
};
|
|
20
28
|
async function fetchDynamicTokens() {
|
|
21
29
|
// Check cache first
|
|
22
30
|
try {
|
|
@@ -35,9 +43,14 @@ async function fetchDynamicTokens() {
|
|
|
35
43
|
const res = await fetch(url);
|
|
36
44
|
const data = await res.json();
|
|
37
45
|
let tokens = [];
|
|
46
|
+
const targetChainId = CHAIN_ID_MAP[chain];
|
|
38
47
|
if (data && data.tokens && Array.isArray(data.tokens)) {
|
|
48
|
+
// Filter strictly by chainId to prevent cross-chain token bleed
|
|
49
|
+
const filtered = targetChainId
|
|
50
|
+
? data.tokens.filter((t) => t.chainId === targetChainId)
|
|
51
|
+
: data.tokens;
|
|
39
52
|
// Limit to top 50 to avoid massive multicall
|
|
40
|
-
const topTokens =
|
|
53
|
+
const topTokens = filtered.slice(0, 50);
|
|
41
54
|
tokens = topTokens.map((t) => ({
|
|
42
55
|
symbol: t.symbol,
|
|
43
56
|
address: t.address
|
|
@@ -29,8 +29,23 @@ function sanitizeHistoryForLLM(history, activeTools, provider = 'openai') {
|
|
|
29
29
|
// If it IS a summary, keep role as 'system'.
|
|
30
30
|
}
|
|
31
31
|
let content = m.content || "";
|
|
32
|
-
if (
|
|
33
|
-
|
|
32
|
+
if (typeof content === 'string') {
|
|
33
|
+
if (role === 'assistant') {
|
|
34
|
+
content = content.replace(/No response generated\.\s*(---)?\s*/g, '').trim();
|
|
35
|
+
}
|
|
36
|
+
// Scrub ANSI escape codes and control characters to prevent LLM JSON parser crashes from old corrupted history
|
|
37
|
+
content = content
|
|
38
|
+
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '')
|
|
39
|
+
.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, '');
|
|
40
|
+
}
|
|
41
|
+
else if (Array.isArray(content)) {
|
|
42
|
+
for (const block of content) {
|
|
43
|
+
if (block.type === 'text' && typeof block.text === 'string') {
|
|
44
|
+
block.text = block.text
|
|
45
|
+
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '')
|
|
46
|
+
.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, '');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
34
49
|
}
|
|
35
50
|
let msg = { ...m, role, content };
|
|
36
51
|
if (m.tool_calls && m.tool_calls.length > 0) {
|
|
@@ -42,9 +42,11 @@ const tokens_1 = require("../utils/tokens");
|
|
|
42
42
|
const httpClient_1 = require("../../utils/httpClient");
|
|
43
43
|
const portfolioCache = {};
|
|
44
44
|
const CACHE_TTL = 5000; // 5 seconds TTL
|
|
45
|
+
const TESTNET_CHAINS = new Set(['sepolia', 'base_sepolia', 'arbitrum_sepolia', 'optimism_sepolia', 'robinhood_testnet']);
|
|
45
46
|
async function checkPortfolio(chainName, address) {
|
|
46
47
|
try {
|
|
47
48
|
chainName = (0, chains_1.normalizeChainName)(chainName);
|
|
49
|
+
const isTestnet = TESTNET_CHAINS.has(chainName);
|
|
48
50
|
const client = (0, config_1.getPublicClient)(chainName);
|
|
49
51
|
let targetAddress = address;
|
|
50
52
|
if (!targetAddress) {
|
|
@@ -86,30 +88,34 @@ async function checkPortfolio(chainName, address) {
|
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
// Merge Dynamic Trending Whitelist (CoinGecko lists)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
// ⚠️ Skip on testnets: token lists are mainnet-only and would cause false positives
|
|
92
|
+
if (!isTestnet) {
|
|
93
|
+
const { getDynamicTokensForChain } = await Promise.resolve().then(() => __importStar(require('../../utils/dynamicTokenUpdater')));
|
|
94
|
+
const dynamicTokens = await getDynamicTokensForChain(chainName);
|
|
95
|
+
for (const dToken of dynamicTokens) {
|
|
96
|
+
if (!tokensToScan.find(t => String(t.address).toLowerCase() === String(dToken.address).toLowerCase())) {
|
|
97
|
+
tokensToScan.push({ symbol: dToken.symbol, address: dToken.address, isNative: false });
|
|
98
|
+
}
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
|
-
|
|
101
|
+
const testnetWarning = isTestnet
|
|
102
|
+
? `\n> ⚠️ **Testnet Mode** — USD prices are not available for testnet tokens. Only native ETH balances are real.\n`
|
|
103
|
+
: '';
|
|
104
|
+
let report = `📊 **Portfolio for ${targetAddress} on ${chainName.toUpperCase()}**${testnetWarning}\n\n`;
|
|
97
105
|
let totalUsdValue = 0;
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
// 1. Fetch Native Balance directly (works on all chains even without Multicall3)
|
|
107
|
+
let nativeBalanceNum = 0;
|
|
108
|
+
try {
|
|
109
|
+
const nativeRaw = await client.getBalance({ address: targetAddress });
|
|
110
|
+
nativeBalanceNum = parseFloat((0, viem_1.formatEther)(nativeRaw));
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
console.error(`Failed to get native balance for ${chainName}:`, e);
|
|
114
|
+
}
|
|
115
|
+
// 2. Prepare Multicall for ERC20s only
|
|
107
116
|
const contracts = [];
|
|
108
117
|
for (const t of tokensToScan) {
|
|
109
|
-
if (t.isNative) {
|
|
110
|
-
contracts.push({ address: MULTICALL3_ADDRESS, abi: MULTICALL3_ABI, functionName: 'getEthBalance', args: [targetAddress] });
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
118
|
+
if (!t.isNative) {
|
|
113
119
|
contracts.push({ address: t.address, abi: tokens_1.ERC20_ABI, functionName: 'balanceOf', args: [targetAddress] });
|
|
114
120
|
contracts.push({ address: t.address, abi: tokens_1.ERC20_ABI, functionName: 'decimals' });
|
|
115
121
|
}
|
|
@@ -117,29 +123,28 @@ async function checkPortfolio(chainName, address) {
|
|
|
117
123
|
const CHUNK_SIZE = 60; // 30 tokens (2 calls per token)
|
|
118
124
|
const multicallResults = [];
|
|
119
125
|
try {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
if (contracts.length > 0) {
|
|
127
|
+
// Create a timeout promise for 5 seconds (more tolerant for large portfolios)
|
|
128
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('RPC request timed out')), 5000));
|
|
129
|
+
const executionPromise = (async () => {
|
|
130
|
+
for (let i = 0; i < contracts.length; i += CHUNK_SIZE) {
|
|
131
|
+
const chunk = contracts.slice(i, i + CHUNK_SIZE);
|
|
132
|
+
const res = await client.multicall({ contracts: chunk, allowFailure: true });
|
|
133
|
+
multicallResults.push(...res);
|
|
134
|
+
}
|
|
135
|
+
})();
|
|
136
|
+
await Promise.race([executionPromise, timeoutPromise]);
|
|
137
|
+
}
|
|
130
138
|
}
|
|
131
139
|
catch (e) {
|
|
132
|
-
|
|
140
|
+
console.warn(`[checkPortfolio] Multicall timeout or fail on ${chainName}, proceeding with native balance only.`);
|
|
133
141
|
}
|
|
134
142
|
// Map results back to tokens
|
|
135
143
|
let resultIndex = 0;
|
|
136
144
|
const balances = tokensToScan.map((t) => {
|
|
137
145
|
let balanceNum = 0;
|
|
138
146
|
if (t.isNative) {
|
|
139
|
-
|
|
140
|
-
if (balResult?.status === 'success' && balResult.result) {
|
|
141
|
-
balanceNum = parseFloat((0, viem_1.formatEther)(balResult.result));
|
|
142
|
-
}
|
|
147
|
+
balanceNum = nativeBalanceNum;
|
|
143
148
|
}
|
|
144
149
|
else {
|
|
145
150
|
const balResult = multicallResults[resultIndex++];
|
|
@@ -196,10 +201,8 @@ async function checkPortfolio(chainName, address) {
|
|
|
196
201
|
const usdValue = b.balanceNum * price;
|
|
197
202
|
totalUsdValue += usdValue;
|
|
198
203
|
const formattedUsd = usdValue > 0 && usdValue < 0.01 ? usdValue.toFixed(4) : usdValue.toFixed(2);
|
|
199
|
-
const pnlIndicator = usdValue > 0 ? '🟢' : '⚪';
|
|
200
|
-
report += `${pnlIndicator} **$${b.symbol}** | ${b.balanceNum.toFixed(4)} ${b.symbol} ($${formattedUsd})\n`;
|
|
201
|
-
report += `📈 **PnL:** +0.00% ($0.00) _(Simulation)_\n`;
|
|
202
|
-
report += `🤖 *Analysis:* Asset tracking active. Awaiting historical entry price data.\n\n`;
|
|
204
|
+
const pnlIndicator = usdValue > 0 ? '🟢' : (b.isNative ? '🔵' : '⚪');
|
|
205
|
+
report += `${pnlIndicator} **$${b.symbol}** | ${b.balanceNum.toFixed(4)} ${b.symbol}${!isTestnet && usdValue > 0 ? ` ($${formattedUsd})` : ''}\n`;
|
|
203
206
|
}
|
|
204
207
|
report += `\n💰 **Estimated Net Worth: $${totalUsdValue.toFixed(2)}**`;
|
|
205
208
|
portfolioCache[cacheKey] = { data: report, timestamp: Date.now() };
|
package/launcher.ts
CHANGED
|
@@ -36,7 +36,7 @@ const spawnService = (name: string, command: string, args: string[], env: any, i
|
|
|
36
36
|
let isShuttingDown = false;
|
|
37
37
|
|
|
38
38
|
const startProcess = () => {
|
|
39
|
-
const spawnOpts: any = { env, stdio: inheritStdio ? 'inherit' : 'pipe' };
|
|
39
|
+
const spawnOpts: any = { env, stdio: inheritStdio ? 'inherit' : 'pipe', windowsHide: true };
|
|
40
40
|
if (cwd) spawnOpts.cwd = cwd;
|
|
41
41
|
child = spawn(command, args, spawnOpts);
|
|
42
42
|
child.on('error', (err) => {
|
|
@@ -199,7 +199,7 @@ setTimeout(() => {
|
|
|
199
199
|
|
|
200
200
|
if (cfEnabled) {
|
|
201
201
|
console.log('[Launcher] Starting Auto-Tunnel (Cloudflare) on port 3000...');
|
|
202
|
-
const cf = spawn('npx', ['cloudflared', 'tunnel', '--url', 'http://localhost:3000'], { env, shell: true });
|
|
202
|
+
const cf = spawn('npx', ['cloudflared', 'tunnel', '--url', 'http://localhost:3000'], { env, shell: true, windowsHide: true });
|
|
203
203
|
|
|
204
204
|
children.push({
|
|
205
205
|
kill: () => { try { process.kill(cf.pid!, 'SIGTERM'); } catch(e){} },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nyxora",
|
|
3
|
-
"version": "26.7.
|
|
3
|
+
"version": "26.7.23",
|
|
4
4
|
"description": "Your Personal Web3 Assistant",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web3",
|
|
@@ -37,13 +37,6 @@
|
|
|
37
37
|
"packages/ml-engine",
|
|
38
38
|
"packages/tui/dist",
|
|
39
39
|
"packages/tui/package.json",
|
|
40
|
-
"packages/nyxora-ink/dist",
|
|
41
|
-
"packages/nyxora-ink/index.js",
|
|
42
|
-
"packages/nyxora-ink/index.d.ts",
|
|
43
|
-
"packages/nyxora-ink/text-input.js",
|
|
44
|
-
"packages/nyxora-ink/text-input.d.ts",
|
|
45
|
-
"packages/nyxora-ink/ambient.d.ts",
|
|
46
|
-
"packages/nyxora-ink/package.json",
|
|
47
40
|
"scripts"
|
|
48
41
|
],
|
|
49
42
|
"bin": {
|
|
@@ -63,7 +56,7 @@
|
|
|
63
56
|
"tui": "node ./bin/nyxora.mjs tui",
|
|
64
57
|
"set-key": "node ./bin/nyxora.mjs set-key",
|
|
65
58
|
"doctor": "node ./bin/nyxora.mjs doctor",
|
|
66
|
-
"build": "tsc && npm run build --workspace=@nyxora/
|
|
59
|
+
"build": "tsc && npm run build --workspace=@nyxora/tui && npm run build --workspace=nyxora-mcp-server && npm run build --workspace=nyxora-dashboard",
|
|
67
60
|
"test": "npm run test --workspace=packages/core",
|
|
68
61
|
"docs:dev": "vitepress dev docs",
|
|
69
62
|
"docs:build": "vitepress build docs",
|