helixmind 0.2.28 → 0.2.30
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.
Potentially problematic release.
This version of helixmind might be problematic. Click here for more details.
- package/dist/cli/brain/control-protocol.d.ts +118 -1
- package/dist/cli/brain/control-protocol.d.ts.map +1 -1
- package/dist/cli/brain/control-protocol.js +21 -0
- package/dist/cli/brain/control-protocol.js.map +1 -1
- package/dist/cli/brain/generator.d.ts +7 -1
- package/dist/cli/brain/generator.d.ts.map +1 -1
- package/dist/cli/brain/generator.js +31 -0
- package/dist/cli/brain/generator.js.map +1 -1
- package/dist/cli/brain/server.d.ts.map +1 -1
- package/dist/cli/brain/server.js +36 -0
- package/dist/cli/brain/server.js.map +1 -1
- package/dist/cli/brain/template.d.ts.map +1 -1
- package/dist/cli/brain/template.js +98 -285
- package/dist/cli/brain/template.js.map +1 -1
- package/dist/cli/commands/chat.d.ts.map +1 -1
- package/dist/cli/commands/chat.js +315 -5
- package/dist/cli/commands/chat.js.map +1 -1
- package/dist/cli/jarvis/daemon.d.ts +14 -0
- package/dist/cli/jarvis/daemon.d.ts.map +1 -0
- package/dist/cli/jarvis/daemon.js +170 -0
- package/dist/cli/jarvis/daemon.js.map +1 -0
- package/dist/cli/jarvis/index.d.ts +5 -0
- package/dist/cli/jarvis/index.d.ts.map +1 -0
- package/dist/cli/jarvis/index.js +3 -0
- package/dist/cli/jarvis/index.js.map +1 -0
- package/package.json +1 -1
|
@@ -34,6 +34,8 @@ import { getSuggestions, writeSuggestions, clearSuggestions } from '../ui/comman
|
|
|
34
34
|
import { selectMenu } from '../ui/select-menu.js';
|
|
35
35
|
import { BugJournal } from '../bugs/journal.js';
|
|
36
36
|
import { detectBugReport } from '../bugs/detector.js';
|
|
37
|
+
import { JarvisQueue } from '../jarvis/queue.js';
|
|
38
|
+
import { runJarvisDaemon } from '../jarvis/daemon.js';
|
|
37
39
|
import { BrowserController } from '../browser/controller.js';
|
|
38
40
|
import { VisionProcessor } from '../browser/vision.js';
|
|
39
41
|
import { classifyTask } from '../validation/classifier.js';
|
|
@@ -87,6 +89,19 @@ const HELP_CATEGORIES = [
|
|
|
87
89
|
{ cmd: '/local', label: '/local', description: 'Local LLM setup (Ollama)' },
|
|
88
90
|
],
|
|
89
91
|
},
|
|
92
|
+
{
|
|
93
|
+
category: 'Jarvis', color: '#ff00ff',
|
|
94
|
+
items: [
|
|
95
|
+
{ cmd: '/jarvis', label: '/jarvis', description: 'Start Jarvis daemon' },
|
|
96
|
+
{ cmd: '/jarvis task', label: '/jarvis task "..."', description: 'Add task to queue' },
|
|
97
|
+
{ cmd: '/jarvis tasks', label: '/jarvis tasks', description: 'List all tasks' },
|
|
98
|
+
{ cmd: '/jarvis status', label: '/jarvis status [id]', description: 'Show task/daemon status' },
|
|
99
|
+
{ cmd: '/jarvis stop', label: '/jarvis stop', description: 'Stop Jarvis daemon' },
|
|
100
|
+
{ cmd: '/jarvis pause', label: '/jarvis pause', description: 'Pause daemon' },
|
|
101
|
+
{ cmd: '/jarvis resume', label: '/jarvis resume', description: 'Resume daemon' },
|
|
102
|
+
{ cmd: '/jarvis clear', label: '/jarvis clear', description: 'Clear completed tasks' },
|
|
103
|
+
],
|
|
104
|
+
},
|
|
90
105
|
{
|
|
91
106
|
category: 'Validation Matrix', color: '#00cc66',
|
|
92
107
|
items: [
|
|
@@ -274,6 +289,10 @@ export async function chatCommand(options) {
|
|
|
274
289
|
const sessionBuffer = new SessionBuffer();
|
|
275
290
|
// Bug journal (persistent bug tracking)
|
|
276
291
|
const bugJournal = new BugJournal(process.cwd());
|
|
292
|
+
// Jarvis task queue (persistent task orchestration)
|
|
293
|
+
const jarvisQueue = new JarvisQueue(process.cwd());
|
|
294
|
+
let jarvisDaemonSession = null;
|
|
295
|
+
let jarvisPaused = false;
|
|
277
296
|
// Browser controller (lazy — instantiated on /browser or agent tool use)
|
|
278
297
|
let browserController;
|
|
279
298
|
let visionProcessor;
|
|
@@ -441,8 +460,8 @@ export async function chatCommand(options) {
|
|
|
441
460
|
// === Register CLI ↔ Web control protocol ===
|
|
442
461
|
if (brainUrl) {
|
|
443
462
|
try {
|
|
444
|
-
const { registerControlHandlers, setInstanceMeta, getBrainToken, pushSessionCreated, pushSessionUpdate, pushSessionRemoved, pushOutputLine, pushBugCreated, pushBugUpdated, pushBrowserScreenshot, pushControlEvent, startRelayClient, } = await import('../brain/generator.js');
|
|
445
|
-
const { serializeSession, buildInstanceMeta, resetInstanceStartTime } = await import('../brain/control-protocol.js');
|
|
463
|
+
const { registerControlHandlers, setInstanceMeta, getBrainToken, pushSessionCreated, pushSessionUpdate, pushSessionRemoved, pushOutputLine, pushBugCreated, pushBugUpdated, pushBrowserScreenshot, pushControlEvent, startRelayClient, pushJarvisTaskCreated, pushJarvisTaskUpdated, pushJarvisStatusChanged, } = await import('../brain/generator.js');
|
|
464
|
+
const { serializeSession, buildInstanceMeta, resetInstanceStartTime, serializeJarvisTask } = await import('../brain/control-protocol.js');
|
|
446
465
|
resetInstanceStartTime();
|
|
447
466
|
// Collected findings for getFindings() handler
|
|
448
467
|
const collectedFindings = [];
|
|
@@ -696,6 +715,79 @@ export async function chatCommand(options) {
|
|
|
696
715
|
fixedAt: b.fixedAt,
|
|
697
716
|
fixDescription: b.fixDescription,
|
|
698
717
|
})),
|
|
718
|
+
startJarvis: () => {
|
|
719
|
+
if (jarvisDaemonSession && jarvisDaemonSession.status === 'running')
|
|
720
|
+
return jarvisDaemonSession.id;
|
|
721
|
+
const bgSession = sessionMgr.create('\u{1F916} Jarvis', '\u{1F916}', agentHistory);
|
|
722
|
+
bgSession.start();
|
|
723
|
+
wireSessionOutput(bgSession);
|
|
724
|
+
pushSessionCreated(serializeSession(bgSession));
|
|
725
|
+
jarvisDaemonSession = bgSession;
|
|
726
|
+
jarvisPaused = false;
|
|
727
|
+
(async () => {
|
|
728
|
+
try {
|
|
729
|
+
await runJarvisDaemon(jarvisQueue, {
|
|
730
|
+
sendMessage: async (prompt) => {
|
|
731
|
+
bgSession.controller.reset();
|
|
732
|
+
const rth = { text: '' };
|
|
733
|
+
const orig = bgSession.buffer.addAssistantSummary.bind(bgSession.buffer);
|
|
734
|
+
bgSession.buffer.addAssistantSummary = (t) => { rth.text = t; orig(t); };
|
|
735
|
+
await sendAgentMessage(prompt, bgSession.history, provider, project, spiralEngine, config, permissions, bgSession.undoStack, checkpointStore, bgSession.controller, new ActivityIndicator(), bgSession.buffer, (inp, out) => { sessionTokensInput += inp; sessionTokensOutput += out; }, () => { sessionToolCalls++; }, undefined, { enabled: false, verbose: false, strict: false });
|
|
736
|
+
bgSession.buffer.addAssistantSummary = orig;
|
|
737
|
+
return rth.text;
|
|
738
|
+
},
|
|
739
|
+
isAborted: () => bgSession.controller.isAborted,
|
|
740
|
+
isPaused: () => jarvisPaused,
|
|
741
|
+
onTaskStart: (task) => { bgSession.capture(`\u25B6 Task #${task.id}: ${task.title}`); pushSessionUpdate(serializeSession(bgSession)); },
|
|
742
|
+
onTaskComplete: (task, result) => { bgSession.capture(`\u2713 Task #${task.id} done: ${result.slice(0, 100)}`); pushSessionUpdate(serializeSession(bgSession)); },
|
|
743
|
+
onTaskFailed: (task, error) => { bgSession.capture(`\u2717 Task #${task.id} failed: ${error.slice(0, 100)}`); pushSessionUpdate(serializeSession(bgSession)); },
|
|
744
|
+
updateStatus: () => updateStatusBar(),
|
|
745
|
+
storeInSpiral: spiralEngine ? async (content, type, tags) => {
|
|
746
|
+
try {
|
|
747
|
+
await spiralEngine.add(content, { type: type, tags });
|
|
748
|
+
}
|
|
749
|
+
catch { }
|
|
750
|
+
} : undefined,
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
catch (err) {
|
|
754
|
+
if (!(err instanceof AgentAbortError))
|
|
755
|
+
bgSession.capture(`Jarvis error: ${err}`);
|
|
756
|
+
}
|
|
757
|
+
sessionMgr.complete(bgSession.id, { text: 'Jarvis stopped', steps: [], errors: bgSession.controller.isAborted ? ['Stopped'] : [], durationMs: bgSession.elapsed });
|
|
758
|
+
pushSessionUpdate(serializeSession(bgSession));
|
|
759
|
+
jarvisDaemonSession = null;
|
|
760
|
+
})();
|
|
761
|
+
return bgSession.id;
|
|
762
|
+
},
|
|
763
|
+
stopJarvis: () => {
|
|
764
|
+
if (!jarvisDaemonSession)
|
|
765
|
+
return false;
|
|
766
|
+
jarvisDaemonSession.abort();
|
|
767
|
+
pushSessionUpdate(serializeSession(jarvisDaemonSession));
|
|
768
|
+
jarvisDaemonSession = null;
|
|
769
|
+
return true;
|
|
770
|
+
},
|
|
771
|
+
pauseJarvis: () => {
|
|
772
|
+
if (!jarvisDaemonSession || jarvisPaused)
|
|
773
|
+
return false;
|
|
774
|
+
jarvisPaused = true;
|
|
775
|
+
jarvisQueue.setDaemonState('paused');
|
|
776
|
+
return true;
|
|
777
|
+
},
|
|
778
|
+
resumeJarvis: () => {
|
|
779
|
+
if (!jarvisDaemonSession || !jarvisPaused)
|
|
780
|
+
return false;
|
|
781
|
+
jarvisPaused = false;
|
|
782
|
+
jarvisQueue.setDaemonState('running');
|
|
783
|
+
return true;
|
|
784
|
+
},
|
|
785
|
+
addJarvisTask: (title, description, opts) => {
|
|
786
|
+
const task = jarvisQueue.addTask(title, description, opts);
|
|
787
|
+
return serializeJarvisTask(task);
|
|
788
|
+
},
|
|
789
|
+
listJarvisTasks: () => jarvisQueue.getAllTasks().map(serializeJarvisTask),
|
|
790
|
+
getJarvisStatus: () => jarvisQueue.getStatus(),
|
|
699
791
|
});
|
|
700
792
|
// Wire bug journal change events to brain server
|
|
701
793
|
bugJournal.setOnChange((event, bug) => {
|
|
@@ -717,6 +809,16 @@ export async function chatCommand(options) {
|
|
|
717
809
|
pushBugUpdated(bugInfo);
|
|
718
810
|
}
|
|
719
811
|
});
|
|
812
|
+
// Wire Jarvis queue change events to brain server
|
|
813
|
+
jarvisQueue.setOnChange((event, task) => {
|
|
814
|
+
const info = serializeJarvisTask(task);
|
|
815
|
+
if (event === 'task_created') {
|
|
816
|
+
pushJarvisTaskCreated(info);
|
|
817
|
+
}
|
|
818
|
+
else {
|
|
819
|
+
pushJarvisTaskUpdated(info);
|
|
820
|
+
}
|
|
821
|
+
});
|
|
720
822
|
// Wire browser screenshots to brain server
|
|
721
823
|
pushScreenshotToBrainFn = (info) => {
|
|
722
824
|
pushBrowserScreenshot({
|
|
@@ -797,6 +899,13 @@ export async function chatCommand(options) {
|
|
|
797
899
|
status: b.status, createdAt: b.createdAt, updatedAt: b.updatedAt,
|
|
798
900
|
fixedAt: b.fixedAt, fixDescription: b.fixDescription,
|
|
799
901
|
})),
|
|
902
|
+
startJarvis: () => '',
|
|
903
|
+
stopJarvis: () => false,
|
|
904
|
+
pauseJarvis: () => false,
|
|
905
|
+
resumeJarvis: () => false,
|
|
906
|
+
addJarvisTask: () => ({ id: 0, title: '', description: '', status: 'pending', priority: 'medium', createdAt: Date.now(), updatedAt: Date.now(), retries: 0, maxRetries: 3, tags: [] }),
|
|
907
|
+
listJarvisTasks: () => [],
|
|
908
|
+
getJarvisStatus: () => ({ daemonState: 'stopped', currentTaskId: null, pendingCount: 0, completedCount: 0, failedCount: 0, totalCount: 0, uptimeMs: 0 }),
|
|
800
909
|
}, updateMeta).catch(() => { });
|
|
801
910
|
}
|
|
802
911
|
}
|
|
@@ -1682,7 +1791,64 @@ export async function chatCommand(options) {
|
|
|
1682
1791
|
default:
|
|
1683
1792
|
renderInfo(`Validation Matrix: ${validationEnabled ? 'ON' : 'OFF'} | Verbose: ${validationVerbose ? 'ON' : 'OFF'} | Strict: ${validationStrict ? 'ON' : 'OFF'}`);
|
|
1684
1793
|
}
|
|
1685
|
-
}, sessionMgr, registerBrainHandlers, (active) => { isAtPrompt = active; }, bugJournal
|
|
1794
|
+
}, sessionMgr, registerBrainHandlers, (active) => { isAtPrompt = active; }, bugJournal, {
|
|
1795
|
+
queue: jarvisQueue,
|
|
1796
|
+
getSession: () => jarvisDaemonSession,
|
|
1797
|
+
setSession: (s) => { jarvisDaemonSession = s; },
|
|
1798
|
+
isPaused: () => jarvisPaused,
|
|
1799
|
+
setPaused: (v) => { jarvisPaused = v; },
|
|
1800
|
+
startDaemon: () => {
|
|
1801
|
+
const bgSession = sessionMgr.create('\u{1F916} Jarvis', '\u{1F916}', agentHistory);
|
|
1802
|
+
bgSession.start();
|
|
1803
|
+
jarvisDaemonSession = bgSession;
|
|
1804
|
+
jarvisPaused = false;
|
|
1805
|
+
renderInfo(chalk.hex('#ff00ff').bold('\u{1F916} Jarvis daemon started'));
|
|
1806
|
+
renderInfo(chalk.dim('Add tasks with /jarvis task "description"'));
|
|
1807
|
+
(async () => {
|
|
1808
|
+
try {
|
|
1809
|
+
await runJarvisDaemon(jarvisQueue, {
|
|
1810
|
+
sendMessage: async (prompt) => {
|
|
1811
|
+
bgSession.controller.reset();
|
|
1812
|
+
const rth = { text: '' };
|
|
1813
|
+
const orig = bgSession.buffer.addAssistantSummary.bind(bgSession.buffer);
|
|
1814
|
+
bgSession.buffer.addAssistantSummary = (t) => { rth.text = t; orig(t); };
|
|
1815
|
+
await sendAgentMessage(prompt, bgSession.history, provider, project, spiralEngine, config, permissions, bgSession.undoStack, checkpointStore, bgSession.controller, new ActivityIndicator(), bgSession.buffer, (inp, out) => { sessionTokensInput += inp; sessionTokensOutput += out; }, () => { sessionToolCalls++; }, undefined, { enabled: false, verbose: false, strict: false });
|
|
1816
|
+
bgSession.buffer.addAssistantSummary = orig;
|
|
1817
|
+
return rth.text;
|
|
1818
|
+
},
|
|
1819
|
+
isAborted: () => bgSession.controller.isAborted,
|
|
1820
|
+
isPaused: () => jarvisPaused,
|
|
1821
|
+
onTaskStart: (task) => {
|
|
1822
|
+
bgSession.capture(`\u25B6 Task #${task.id}: ${task.title}`);
|
|
1823
|
+
renderInfo(chalk.hex('#ff00ff')(`\u25B6 Jarvis: Starting task #${task.id} \u2014 ${task.title}`));
|
|
1824
|
+
},
|
|
1825
|
+
onTaskComplete: (task, result) => {
|
|
1826
|
+
bgSession.capture(`\u2713 Task #${task.id} done: ${result.slice(0, 100)}`);
|
|
1827
|
+
renderInfo(chalk.hex('#ff00ff')(`\u2713 Jarvis: Task #${task.id} completed`));
|
|
1828
|
+
},
|
|
1829
|
+
onTaskFailed: (task, error) => {
|
|
1830
|
+
bgSession.capture(`\u2717 Task #${task.id} failed: ${error.slice(0, 100)}`);
|
|
1831
|
+
renderInfo(chalk.hex('#ff00ff')(`\u2717 Jarvis: Task #${task.id} failed \u2014 ${error.slice(0, 60)}`));
|
|
1832
|
+
},
|
|
1833
|
+
updateStatus: () => updateStatusBar(),
|
|
1834
|
+
storeInSpiral: spiralEngine ? async (content, type, tags) => {
|
|
1835
|
+
try {
|
|
1836
|
+
await spiralEngine.add(content, { type: type, tags });
|
|
1837
|
+
}
|
|
1838
|
+
catch { }
|
|
1839
|
+
} : undefined,
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
catch (err) {
|
|
1843
|
+
if (!(err instanceof AgentAbortError))
|
|
1844
|
+
bgSession.capture(`Jarvis error: ${err}`);
|
|
1845
|
+
}
|
|
1846
|
+
sessionMgr.complete(bgSession.id, { text: 'Jarvis stopped', steps: [], errors: bgSession.controller.isAborted ? ['Stopped'] : [], durationMs: bgSession.elapsed });
|
|
1847
|
+
jarvisDaemonSession = null;
|
|
1848
|
+
renderInfo(chalk.hex('#ff00ff')('\u{1F916} Jarvis daemon stopped'));
|
|
1849
|
+
})();
|
|
1850
|
+
},
|
|
1851
|
+
});
|
|
1686
1852
|
if (handled === 'exit') {
|
|
1687
1853
|
spiralEngine?.close();
|
|
1688
1854
|
rl.close();
|
|
@@ -2256,7 +2422,7 @@ function showFullAutonomousWarning() {
|
|
|
2256
2422
|
process.stdout.write(d('\u2502 ') + d('ESC = stop agent if needed.') + d(' \u2502') + '\n');
|
|
2257
2423
|
process.stdout.write(d('\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F') + '\n\n');
|
|
2258
2424
|
}
|
|
2259
|
-
async function handleSlashCommand(input, messages, agentHistory, config, spiralEngine, store, rl, permissions, undoStack, checkpointStore, sessionBuffer, sessionTokens, sessionToolCalls, onProviderSwitch, onBrainSwitch, currentBrainScope, onAutonomous, onValidation, sessionManager, onRegisterBrainHandlers, onSubPrompt, bugJournal) {
|
|
2425
|
+
async function handleSlashCommand(input, messages, agentHistory, config, spiralEngine, store, rl, permissions, undoStack, checkpointStore, sessionBuffer, sessionTokens, sessionToolCalls, onProviderSwitch, onBrainSwitch, currentBrainScope, onAutonomous, onValidation, sessionManager, onRegisterBrainHandlers, onSubPrompt, bugJournal, jarvisCtx) {
|
|
2260
2426
|
const parts = input.split(/\s+/);
|
|
2261
2427
|
const cmd = parts[0].toLowerCase();
|
|
2262
2428
|
switch (cmd) {
|
|
@@ -2279,7 +2445,7 @@ async function handleSlashCommand(input, messages, agentHistory, config, spiralE
|
|
|
2279
2445
|
rl.resume();
|
|
2280
2446
|
if (helpIdx >= 0 && helpCmds[helpIdx]) {
|
|
2281
2447
|
// Execute the selected command
|
|
2282
|
-
return handleSlashCommand(helpCmds[helpIdx], messages, agentHistory, config, spiralEngine, store, rl, permissions, undoStack, checkpointStore, sessionBuffer, sessionTokens, sessionToolCalls, onProviderSwitch, onBrainSwitch, currentBrainScope, onAutonomous, onValidation, sessionManager, onRegisterBrainHandlers, onSubPrompt, bugJournal);
|
|
2448
|
+
return handleSlashCommand(helpCmds[helpIdx], messages, agentHistory, config, spiralEngine, store, rl, permissions, undoStack, checkpointStore, sessionBuffer, sessionTokens, sessionToolCalls, onProviderSwitch, onBrainSwitch, currentBrainScope, onAutonomous, onValidation, sessionManager, onRegisterBrainHandlers, onSubPrompt, bugJournal, jarvisCtx);
|
|
2283
2449
|
}
|
|
2284
2450
|
break;
|
|
2285
2451
|
}
|
|
@@ -2835,6 +3001,150 @@ async function handleSlashCommand(input, messages, agentHistory, config, spiralE
|
|
|
2835
3001
|
await onAutonomous('security');
|
|
2836
3002
|
}
|
|
2837
3003
|
break;
|
|
3004
|
+
case '/jarvis': {
|
|
3005
|
+
if (!jarvisCtx) {
|
|
3006
|
+
renderInfo('Jarvis not available.');
|
|
3007
|
+
break;
|
|
3008
|
+
}
|
|
3009
|
+
const sub = parts[1]?.toLowerCase();
|
|
3010
|
+
const jq = jarvisCtx.queue;
|
|
3011
|
+
if (!sub || sub === 'start') {
|
|
3012
|
+
const existing = jarvisCtx.getSession();
|
|
3013
|
+
if (existing && existing.status === 'running') {
|
|
3014
|
+
renderInfo(chalk.hex('#ff00ff')('Jarvis is already running.'));
|
|
3015
|
+
const sl = jq.getStatusLine();
|
|
3016
|
+
if (sl)
|
|
3017
|
+
renderInfo(sl);
|
|
3018
|
+
break;
|
|
3019
|
+
}
|
|
3020
|
+
jarvisCtx.startDaemon();
|
|
3021
|
+
}
|
|
3022
|
+
else if (sub === 'task') {
|
|
3023
|
+
const taskText = input.replace(/^\/jarvis\s+task\s*/i, '').trim();
|
|
3024
|
+
if (!taskText) {
|
|
3025
|
+
renderInfo('Usage: /jarvis task "Do something"');
|
|
3026
|
+
break;
|
|
3027
|
+
}
|
|
3028
|
+
let title = taskText;
|
|
3029
|
+
let description = '';
|
|
3030
|
+
const quoteMatch = taskText.match(/^["'](.+?)["']\s*(.*)/s);
|
|
3031
|
+
if (quoteMatch) {
|
|
3032
|
+
title = quoteMatch[1];
|
|
3033
|
+
description = quoteMatch[2] || title;
|
|
3034
|
+
}
|
|
3035
|
+
else if (taskText.includes('\u2014') || taskText.includes('--')) {
|
|
3036
|
+
const sep = taskText.includes('\u2014') ? '\u2014' : '--';
|
|
3037
|
+
const sepIdx = taskText.indexOf(sep);
|
|
3038
|
+
title = taskText.slice(0, sepIdx).trim();
|
|
3039
|
+
description = taskText.slice(sepIdx + sep.length).trim() || title;
|
|
3040
|
+
}
|
|
3041
|
+
else {
|
|
3042
|
+
description = title;
|
|
3043
|
+
}
|
|
3044
|
+
const task = jq.addTask(title, description);
|
|
3045
|
+
renderInfo(chalk.hex('#ff00ff')(`\u2714 Task #${task.id} added: ${task.title}`));
|
|
3046
|
+
}
|
|
3047
|
+
else if (sub === 'tasks') {
|
|
3048
|
+
const tasks = jq.getAllTasks();
|
|
3049
|
+
if (tasks.length === 0) {
|
|
3050
|
+
renderInfo('No tasks in queue. Add with /jarvis task "..."');
|
|
3051
|
+
break;
|
|
3052
|
+
}
|
|
3053
|
+
const statusIcons = {
|
|
3054
|
+
pending: chalk.yellow('\u25CB'), running: chalk.hex('#ff00ff')('\u25CF'),
|
|
3055
|
+
completed: chalk.green('\u2713'), failed: chalk.red('\u2717'), paused: chalk.dim('\u25CB'),
|
|
3056
|
+
};
|
|
3057
|
+
process.stdout.write('\n');
|
|
3058
|
+
for (const t of tasks) {
|
|
3059
|
+
const icon = statusIcons[t.status] || '\u25CB';
|
|
3060
|
+
const priColor = t.priority === 'high' ? '#ff3333' : t.priority === 'medium' ? '#ffaa00' : '#888888';
|
|
3061
|
+
process.stdout.write(` ${icon} ${chalk.bold('#' + t.id)} ${chalk.hex(priColor)(`[${t.priority}]`)} ${t.title}\n`);
|
|
3062
|
+
if (t.result)
|
|
3063
|
+
process.stdout.write(chalk.dim(` Result: ${t.result.slice(0, 80)}\n`));
|
|
3064
|
+
if (t.error)
|
|
3065
|
+
process.stdout.write(chalk.red(` Error: ${t.error.slice(0, 80)}\n`));
|
|
3066
|
+
}
|
|
3067
|
+
process.stdout.write('\n');
|
|
3068
|
+
const sl = jq.getStatusLine();
|
|
3069
|
+
if (sl)
|
|
3070
|
+
renderInfo(sl);
|
|
3071
|
+
}
|
|
3072
|
+
else if (sub === 'status') {
|
|
3073
|
+
const taskId = parts[2] ? parseInt(parts[2], 10) : NaN;
|
|
3074
|
+
if (!isNaN(taskId)) {
|
|
3075
|
+
const task = jq.getAllTasks().find((t) => t.id === taskId);
|
|
3076
|
+
if (!task) {
|
|
3077
|
+
renderInfo(`Task #${taskId} not found.`);
|
|
3078
|
+
}
|
|
3079
|
+
else {
|
|
3080
|
+
process.stdout.write('\n');
|
|
3081
|
+
process.stdout.write(chalk.hex('#ff00ff').bold(` Task #${task.id}: ${task.title}\n`));
|
|
3082
|
+
process.stdout.write(` Status: ${task.status} | Priority: ${task.priority}\n`);
|
|
3083
|
+
process.stdout.write(` Created: ${new Date(task.createdAt).toLocaleString()}\n`);
|
|
3084
|
+
if (task.startedAt)
|
|
3085
|
+
process.stdout.write(` Started: ${new Date(task.startedAt).toLocaleString()}\n`);
|
|
3086
|
+
if (task.completedAt)
|
|
3087
|
+
process.stdout.write(` Completed: ${new Date(task.completedAt).toLocaleString()}\n`);
|
|
3088
|
+
if (task.description !== task.title)
|
|
3089
|
+
process.stdout.write(chalk.dim(` Description: ${task.description}\n`));
|
|
3090
|
+
if (task.result)
|
|
3091
|
+
process.stdout.write(chalk.green(` Result: ${task.result}\n`));
|
|
3092
|
+
if (task.error)
|
|
3093
|
+
process.stdout.write(chalk.red(` Error: ${task.error}\n`));
|
|
3094
|
+
process.stdout.write('\n');
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
else {
|
|
3098
|
+
const status = jq.getStatus();
|
|
3099
|
+
process.stdout.write('\n');
|
|
3100
|
+
process.stdout.write(chalk.hex('#ff00ff').bold(' \u{1F916} Jarvis Status\n'));
|
|
3101
|
+
process.stdout.write(` Daemon: ${status.daemonState}`);
|
|
3102
|
+
if (status.currentTaskId)
|
|
3103
|
+
process.stdout.write(` (task #${status.currentTaskId})`);
|
|
3104
|
+
process.stdout.write('\n');
|
|
3105
|
+
process.stdout.write(` Pending: ${status.pendingCount} | Completed: ${status.completedCount} | Failed: ${status.failedCount}\n`);
|
|
3106
|
+
if (status.uptimeMs > 0)
|
|
3107
|
+
process.stdout.write(` Uptime: ${Math.floor(status.uptimeMs / 1000)}s\n`);
|
|
3108
|
+
process.stdout.write('\n');
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
else if (sub === 'stop') {
|
|
3112
|
+
const s = jarvisCtx.getSession();
|
|
3113
|
+
if (!s) {
|
|
3114
|
+
renderInfo('Jarvis is not running.');
|
|
3115
|
+
break;
|
|
3116
|
+
}
|
|
3117
|
+
s.abort();
|
|
3118
|
+
jarvisCtx.setSession(null);
|
|
3119
|
+
renderInfo(chalk.hex('#ff00ff')('\u{1F916} Jarvis daemon stopped'));
|
|
3120
|
+
}
|
|
3121
|
+
else if (sub === 'pause') {
|
|
3122
|
+
if (!jarvisCtx.getSession() || jarvisCtx.isPaused()) {
|
|
3123
|
+
renderInfo(jarvisCtx.isPaused() ? 'Jarvis is already paused.' : 'Jarvis is not running.');
|
|
3124
|
+
break;
|
|
3125
|
+
}
|
|
3126
|
+
jarvisCtx.setPaused(true);
|
|
3127
|
+
jq.setDaemonState('paused');
|
|
3128
|
+
renderInfo(chalk.hex('#ff00ff')('\u23F8 Jarvis paused'));
|
|
3129
|
+
}
|
|
3130
|
+
else if (sub === 'resume') {
|
|
3131
|
+
if (!jarvisCtx.getSession() || !jarvisCtx.isPaused()) {
|
|
3132
|
+
renderInfo(!jarvisCtx.isPaused() ? 'Jarvis is not paused.' : 'Jarvis is not running.');
|
|
3133
|
+
break;
|
|
3134
|
+
}
|
|
3135
|
+
jarvisCtx.setPaused(false);
|
|
3136
|
+
jq.setDaemonState('running');
|
|
3137
|
+
renderInfo(chalk.hex('#ff00ff')('\u25B6 Jarvis resumed'));
|
|
3138
|
+
}
|
|
3139
|
+
else if (sub === 'clear') {
|
|
3140
|
+
const removed = jq.clearCompleted();
|
|
3141
|
+
renderInfo(`Cleared ${removed} completed task(s).`);
|
|
3142
|
+
}
|
|
3143
|
+
else {
|
|
3144
|
+
renderInfo('Usage: /jarvis [start|task|tasks|status|stop|pause|resume|clear]');
|
|
3145
|
+
}
|
|
3146
|
+
break;
|
|
3147
|
+
}
|
|
2838
3148
|
case '/monitor': {
|
|
2839
3149
|
if (!onAutonomous)
|
|
2840
3150
|
break;
|