helixmind 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/agent/loop.d.ts.map +1 -1
- package/dist/cli/agent/loop.js +18 -11
- package/dist/cli/agent/loop.js.map +1 -1
- package/dist/cli/agent/permissions.d.ts +16 -0
- package/dist/cli/agent/permissions.d.ts.map +1 -1
- package/dist/cli/agent/permissions.js +74 -5
- package/dist/cli/agent/permissions.js.map +1 -1
- package/dist/cli/agent/sandbox.d.ts.map +1 -1
- package/dist/cli/agent/sandbox.js +3 -0
- package/dist/cli/agent/sandbox.js.map +1 -1
- package/dist/cli/brain/archive.d.ts.map +1 -1
- package/dist/cli/brain/archive.js +48 -18
- package/dist/cli/brain/archive.js.map +1 -1
- package/dist/cli/brain/control-protocol.d.ts +17 -0
- package/dist/cli/brain/control-protocol.d.ts.map +1 -1
- package/dist/cli/brain/control-protocol.js +79 -0
- package/dist/cli/brain/control-protocol.js.map +1 -1
- package/dist/cli/brain/path-guard.d.ts +2 -0
- package/dist/cli/brain/path-guard.d.ts.map +1 -0
- package/dist/cli/brain/path-guard.js +94 -0
- package/dist/cli/brain/path-guard.js.map +1 -0
- package/dist/cli/brain/relay-client.d.ts +2 -0
- package/dist/cli/brain/relay-client.d.ts.map +1 -1
- package/dist/cli/brain/relay-client.js +58 -8
- package/dist/cli/brain/relay-client.js.map +1 -1
- package/dist/cli/brain/server.d.ts.map +1 -1
- package/dist/cli/brain/server.js +235 -23
- package/dist/cli/brain/server.js.map +1 -1
- package/dist/cli/brain/stdout-capture.d.ts +11 -0
- package/dist/cli/brain/stdout-capture.d.ts.map +1 -1
- package/dist/cli/brain/stdout-capture.js +42 -1
- package/dist/cli/brain/stdout-capture.js.map +1 -1
- package/dist/cli/brain/web-chat-handler.d.ts.map +1 -1
- package/dist/cli/brain/web-chat-handler.js +7 -0
- package/dist/cli/brain/web-chat-handler.js.map +1 -1
- package/dist/cli/checkpoints/revert.d.ts +5 -0
- package/dist/cli/checkpoints/revert.d.ts.map +1 -1
- package/dist/cli/checkpoints/revert.js +100 -11
- package/dist/cli/checkpoints/revert.js.map +1 -1
- package/dist/cli/checkpoints/store.d.ts +3 -0
- package/dist/cli/checkpoints/store.d.ts.map +1 -1
- package/dist/cli/checkpoints/store.js.map +1 -1
- package/dist/cli/commands/chat.d.ts.map +1 -1
- package/dist/cli/commands/chat.js +138 -73
- package/dist/cli/commands/chat.js.map +1 -1
- package/dist/cli/config/store.js +1 -1
- package/dist/cli/config/store.js.map +1 -1
- package/dist/cli/core/input.d.ts +0 -1
- package/dist/cli/core/input.d.ts.map +1 -1
- package/dist/cli/core/input.js +9 -17
- package/dist/cli/core/input.js.map +1 -1
- package/dist/cli/jarvis/autonomy.d.ts +13 -1
- package/dist/cli/jarvis/autonomy.d.ts.map +1 -1
- package/dist/cli/jarvis/autonomy.js +33 -1
- package/dist/cli/jarvis/autonomy.js.map +1 -1
- package/dist/cli/jarvis/core-ethics.d.ts +15 -0
- package/dist/cli/jarvis/core-ethics.d.ts.map +1 -1
- package/dist/cli/jarvis/core-ethics.js +110 -9
- package/dist/cli/jarvis/core-ethics.js.map +1 -1
- package/dist/cli/jarvis/daemon.d.ts.map +1 -1
- package/dist/cli/jarvis/daemon.js +8 -0
- package/dist/cli/jarvis/daemon.js.map +1 -1
- package/dist/cli/jarvis/instance-lock.d.ts.map +1 -1
- package/dist/cli/jarvis/instance-lock.js +132 -27
- package/dist/cli/jarvis/instance-lock.js.map +1 -1
- package/dist/cli/jarvis/learning.d.ts +6 -0
- package/dist/cli/jarvis/learning.d.ts.map +1 -1
- package/dist/cli/jarvis/learning.js +17 -3
- package/dist/cli/jarvis/learning.js.map +1 -1
- package/dist/cli/jarvis/notifications.d.ts.map +1 -1
- package/dist/cli/jarvis/notifications.js +75 -10
- package/dist/cli/jarvis/notifications.js.map +1 -1
- package/dist/cli/jarvis/onboarding.d.ts.map +1 -1
- package/dist/cli/jarvis/onboarding.js +32 -2
- package/dist/cli/jarvis/onboarding.js.map +1 -1
- package/dist/cli/jarvis/queue.d.ts +5 -0
- package/dist/cli/jarvis/queue.d.ts.map +1 -1
- package/dist/cli/jarvis/queue.js +23 -6
- package/dist/cli/jarvis/queue.js.map +1 -1
- package/dist/cli/jarvis/scheduler.d.ts +8 -0
- package/dist/cli/jarvis/scheduler.d.ts.map +1 -1
- package/dist/cli/jarvis/scheduler.js +32 -4
- package/dist/cli/jarvis/scheduler.js.map +1 -1
- package/dist/cli/jarvis/sentiment.d.ts +11 -0
- package/dist/cli/jarvis/sentiment.d.ts.map +1 -1
- package/dist/cli/jarvis/sentiment.js +40 -6
- package/dist/cli/jarvis/sentiment.js.map +1 -1
- package/dist/cli/jarvis/skills.d.ts +35 -0
- package/dist/cli/jarvis/skills.d.ts.map +1 -1
- package/dist/cli/jarvis/skills.js +144 -0
- package/dist/cli/jarvis/skills.js.map +1 -1
- package/dist/cli/jarvis/triggers.d.ts.map +1 -1
- package/dist/cli/jarvis/triggers.js +65 -9
- package/dist/cli/jarvis/triggers.js.map +1 -1
- package/dist/cli/jarvis/types.d.ts +10 -0
- package/dist/cli/jarvis/types.d.ts.map +1 -1
- package/dist/cli/jarvis/world-model.d.ts +4 -0
- package/dist/cli/jarvis/world-model.d.ts.map +1 -1
- package/dist/cli/jarvis/world-model.js +23 -1
- package/dist/cli/jarvis/world-model.js.map +1 -1
- package/dist/cli/providers/anthropic.d.ts +5 -1
- package/dist/cli/providers/anthropic.d.ts.map +1 -1
- package/dist/cli/providers/anthropic.js +133 -36
- package/dist/cli/providers/anthropic.js.map +1 -1
- package/dist/cli/providers/model-limits.d.ts +8 -0
- package/dist/cli/providers/model-limits.d.ts.map +1 -1
- package/dist/cli/providers/model-limits.js +42 -0
- package/dist/cli/providers/model-limits.js.map +1 -1
- package/dist/cli/providers/ollama.d.ts +2 -0
- package/dist/cli/providers/ollama.d.ts.map +1 -1
- package/dist/cli/providers/ollama.js +8 -0
- package/dist/cli/providers/ollama.js.map +1 -1
- package/dist/cli/providers/openai.d.ts +5 -1
- package/dist/cli/providers/openai.d.ts.map +1 -1
- package/dist/cli/providers/openai.js +66 -19
- package/dist/cli/providers/openai.js.map +1 -1
- package/dist/cli/providers/rate-limiter.d.ts +58 -20
- package/dist/cli/providers/rate-limiter.d.ts.map +1 -1
- package/dist/cli/providers/rate-limiter.js +212 -96
- package/dist/cli/providers/rate-limiter.js.map +1 -1
- package/dist/cli/providers/registry.d.ts.map +1 -1
- package/dist/cli/providers/registry.js +22 -13
- package/dist/cli/providers/registry.js.map +1 -1
- package/dist/cli/providers/types.d.ts +16 -5
- package/dist/cli/providers/types.d.ts.map +1 -1
- package/dist/spiral/cloud/content-extractor.d.ts.map +1 -1
- package/dist/spiral/cloud/content-extractor.js +6 -4
- package/dist/spiral/cloud/content-extractor.js.map +1 -1
- package/dist/spiral/cloud/search-provider.d.ts.map +1 -1
- package/dist/spiral/cloud/search-provider.js +7 -2
- package/dist/spiral/cloud/search-provider.js.map +1 -1
- package/dist/spiral/cloud/web-enricher.d.ts.map +1 -1
- package/dist/spiral/cloud/web-enricher.js +10 -2
- package/dist/spiral/cloud/web-enricher.js.map +1 -1
- package/dist/spiral/compression.d.ts +5 -2
- package/dist/spiral/compression.d.ts.map +1 -1
- package/dist/spiral/compression.js +23 -6
- package/dist/spiral/compression.js.map +1 -1
- package/dist/spiral/engine.d.ts +7 -1
- package/dist/spiral/engine.d.ts.map +1 -1
- package/dist/spiral/engine.js +83 -35
- package/dist/spiral/engine.js.map +1 -1
- package/dist/storage/database.d.ts.map +1 -1
- package/dist/storage/database.js +41 -0
- package/dist/storage/database.js.map +1 -1
- package/dist/storage/nodes.d.ts +6 -0
- package/dist/storage/nodes.d.ts.map +1 -1
- package/dist/storage/nodes.js +9 -0
- package/dist/storage/nodes.js.map +1 -1
- package/dist/storage/vectors.d.ts +1 -0
- package/dist/storage/vectors.d.ts.map +1 -1
- package/dist/storage/vectors.js +39 -7
- package/dist/storage/vectors.js.map +1 -1
- package/package.json +3 -3
|
@@ -2246,7 +2246,6 @@ export async function chatCommand(options) {
|
|
|
2246
2246
|
});
|
|
2247
2247
|
// Suggestion panel is now handled by InputManager (built-in arrow navigation, Tab/Enter/ESC)
|
|
2248
2248
|
// Legacy compat stubs:
|
|
2249
|
-
let panelJustClosed = false;
|
|
2250
2249
|
function replaceReadlineInput(text) {
|
|
2251
2250
|
inputMgr.setLine(text);
|
|
2252
2251
|
}
|
|
@@ -2531,15 +2530,11 @@ export async function chatCommand(options) {
|
|
|
2531
2530
|
// The panel opens/updates/closes automatically as the user types slash commands.
|
|
2532
2531
|
// === ESC detection (single ESC = stop for normal agents) ===
|
|
2533
2532
|
// Double-ESC (rewind browser) is handled by the raw data listener below.
|
|
2534
|
-
//
|
|
2535
|
-
//
|
|
2536
|
-
//
|
|
2533
|
+
// When the slash-suggestion panel is open, InputManager consumes ESC
|
|
2534
|
+
// internally before this handler fires, so no extra guard is needed.
|
|
2537
2535
|
// Special modes (Jarvis, autonomous): ESC is handled ENTIRELY by the raw
|
|
2538
2536
|
// data listener below — the keypress handler does NOTHING for them.
|
|
2539
|
-
|
|
2540
|
-
// from hint messages. See raw data listener for: quick double-ESC → Rewind,
|
|
2541
|
-
// deliberate double-ESC (>1s gap) → stop special mode.
|
|
2542
|
-
if (key.name === 'escape' && !fullScreenBrowserOpen && !panelJustClosed) {
|
|
2537
|
+
if (key.name === 'escape' && !fullScreenBrowserOpen && !inputMgr.isSuggestionOpen) {
|
|
2543
2538
|
const jarvisRunning = jarvisDaemonSession && jarvisDaemonSession.status === 'running';
|
|
2544
2539
|
const specialMode = jarvisRunning || autonomousMode;
|
|
2545
2540
|
const normalRunning = agentRunning || sessionMgr.hasBackgroundTasks;
|
|
@@ -2691,8 +2686,24 @@ export async function chatCommand(options) {
|
|
|
2691
2686
|
// because arrow key \x1b[A could arrive just after a real ESC press
|
|
2692
2687
|
});
|
|
2693
2688
|
async function openRewindBrowser() {
|
|
2694
|
-
if
|
|
2689
|
+
// Don't re-enter if already open
|
|
2690
|
+
if (fullScreenBrowserOpen)
|
|
2695
2691
|
return;
|
|
2692
|
+
// If an agent is running (main, swarm, or background), stop it first.
|
|
2693
|
+
// Previous behavior silently refused to open Rewind while agent was
|
|
2694
|
+
// running, which made coalesced ESC-ESC bursts feel broken.
|
|
2695
|
+
if (agentRunning || sessionMgr.hasBackgroundTasks) {
|
|
2696
|
+
activity.stop('Stopped');
|
|
2697
|
+
agentController.abort();
|
|
2698
|
+
sessionMgr.abortAll();
|
|
2699
|
+
if (activeSwarm) {
|
|
2700
|
+
activeSwarm.abort();
|
|
2701
|
+
activeSwarm = null;
|
|
2702
|
+
}
|
|
2703
|
+
typeAheadBuffer.length = 0;
|
|
2704
|
+
agentRunning = false;
|
|
2705
|
+
autonomousMode = false;
|
|
2706
|
+
}
|
|
2696
2707
|
const allCps = checkpointStore.getAll();
|
|
2697
2708
|
if (allCps.length === 0) {
|
|
2698
2709
|
renderInfo(chalk.dim('No checkpoints yet \u2014 start chatting to create rewind points.'));
|
|
@@ -2713,45 +2724,49 @@ export async function chatCommand(options) {
|
|
|
2713
2724
|
process.stdin.removeAllListeners('keypress');
|
|
2714
2725
|
let didRevertWithMessage = false;
|
|
2715
2726
|
try {
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2727
|
+
try {
|
|
2728
|
+
const browserResult = await runCheckpointBrowser({
|
|
2729
|
+
store: checkpointStore,
|
|
2730
|
+
agentHistory,
|
|
2731
|
+
simpleMessages: messages.map(m => ({ role: m.role, content: typeof m.content === 'string' ? m.content : '' })),
|
|
2732
|
+
isPaused: false,
|
|
2733
|
+
});
|
|
2734
|
+
if (browserResult.action === 'revert') {
|
|
2735
|
+
const r = browserResult.result;
|
|
2736
|
+
process.stdout.write('\n');
|
|
2737
|
+
if (r.messagesRemoved > 0)
|
|
2738
|
+
renderInfo(chalk.yellow(`${r.messagesRemoved} message(s) reverted`));
|
|
2739
|
+
if (r.filesReverted > 0)
|
|
2740
|
+
renderInfo(chalk.yellow(`${r.filesReverted} file(s) reverted`));
|
|
2741
|
+
if (browserResult.messageText) {
|
|
2742
|
+
inputMgr.setLine(browserResult.messageText);
|
|
2743
|
+
didRevertWithMessage = true;
|
|
2744
|
+
}
|
|
2732
2745
|
}
|
|
2733
2746
|
}
|
|
2747
|
+
catch (err) {
|
|
2748
|
+
// Surface the error instead of swallowing it silently (CHECK-CHATFLOW-009).
|
|
2749
|
+
renderError(`Rewind failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
2750
|
+
}
|
|
2734
2751
|
}
|
|
2735
|
-
|
|
2736
|
-
//
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2752
|
+
finally {
|
|
2753
|
+
// Guaranteed listener restore, even if the browser or revert threw.
|
|
2754
|
+
for (const listener of savedDataListeners) {
|
|
2755
|
+
process.stdin.on('data', listener);
|
|
2756
|
+
}
|
|
2757
|
+
for (const listener of savedKeypressListeners) {
|
|
2758
|
+
process.stdin.on('keypress', listener);
|
|
2759
|
+
}
|
|
2760
|
+
if (!didRevertWithMessage) {
|
|
2761
|
+
inputMgr.setLine('');
|
|
2762
|
+
}
|
|
2763
|
+
fullScreenBrowserOpen = false;
|
|
2764
|
+
chrome.activate();
|
|
2765
|
+
// Drain phantom line events for 500ms (sub-menu shared stdin)
|
|
2766
|
+
drainUntil = Date.now() + 500;
|
|
2767
|
+
rl.resume();
|
|
2768
|
+
showPrompt();
|
|
2748
2769
|
}
|
|
2749
|
-
fullScreenBrowserOpen = false;
|
|
2750
|
-
chrome.activate();
|
|
2751
|
-
// Drain phantom line events for 500ms (sub-menu shared stdin)
|
|
2752
|
-
drainUntil = Date.now() + 500;
|
|
2753
|
-
rl.resume();
|
|
2754
|
-
showPrompt();
|
|
2755
2770
|
}
|
|
2756
2771
|
}
|
|
2757
2772
|
// === Bracketed Paste helpers ===
|
|
@@ -3068,8 +3083,24 @@ export async function chatCommand(options) {
|
|
|
3068
3083
|
spiralEngine = await ensureSpiralEngine(newScope);
|
|
3069
3084
|
}, brainScope, (scope) => getSpiralEngine(scope ?? brainScope), async (action, goal) => {
|
|
3070
3085
|
if (action === 'stop') {
|
|
3071
|
-
//
|
|
3086
|
+
// FIX: CHATFLOW-003 — /stop must also interrupt a running main agent.
|
|
3087
|
+
// Previously only background sessions / autonomous mode were stopped,
|
|
3088
|
+
// and a /stop typed during main agent work sat in the type-ahead
|
|
3089
|
+
// queue and fired after the agent finished on its own.
|
|
3072
3090
|
const running = sessionMgr.running;
|
|
3091
|
+
let stoppedSomething = false;
|
|
3092
|
+
if (agentRunning) {
|
|
3093
|
+
activity.stop('Stopped');
|
|
3094
|
+
agentController.abort();
|
|
3095
|
+
if (activeSwarm) {
|
|
3096
|
+
activeSwarm.abort();
|
|
3097
|
+
activeSwarm = null;
|
|
3098
|
+
}
|
|
3099
|
+
agentRunning = false;
|
|
3100
|
+
typeAheadBuffer.length = 0;
|
|
3101
|
+
renderInfo(chalk.red('\u23F9 STOPPED') + chalk.dim(' \u2014 Main agent interrupted.'));
|
|
3102
|
+
stoppedSomething = true;
|
|
3103
|
+
}
|
|
3073
3104
|
if (running.length > 0) {
|
|
3074
3105
|
for (const s of running) {
|
|
3075
3106
|
s.abort();
|
|
@@ -3077,14 +3108,16 @@ export async function chatCommand(options) {
|
|
|
3077
3108
|
}
|
|
3078
3109
|
autonomousMode = false;
|
|
3079
3110
|
updateStatusBar();
|
|
3111
|
+
stoppedSomething = true;
|
|
3080
3112
|
}
|
|
3081
|
-
|
|
3113
|
+
if (autonomousMode) {
|
|
3082
3114
|
autonomousMode = false;
|
|
3083
3115
|
agentController.abort();
|
|
3084
3116
|
renderInfo('\u23F9 Stopping autonomous mode...');
|
|
3117
|
+
stoppedSomething = true;
|
|
3085
3118
|
}
|
|
3086
|
-
|
|
3087
|
-
renderInfo('
|
|
3119
|
+
if (!stoppedSomething) {
|
|
3120
|
+
renderInfo('Nothing running to stop.');
|
|
3088
3121
|
}
|
|
3089
3122
|
return;
|
|
3090
3123
|
}
|
|
@@ -3364,18 +3397,20 @@ export async function chatCommand(options) {
|
|
|
3364
3397
|
// Start Telegram bot alongside daemon (if configured)
|
|
3365
3398
|
startTelegramBot();
|
|
3366
3399
|
(async () => {
|
|
3367
|
-
//
|
|
3368
|
-
//
|
|
3369
|
-
//
|
|
3400
|
+
// FIX: JARVIS-CRITICAL-2 — no longer auto-enable YOLO/skip-permissions
|
|
3401
|
+
// based on autonomy level. Autonomy levels gate WHICH tools Jarvis may
|
|
3402
|
+
// attempt (enforced by core-ethics.assertCanExecute), not whether the
|
|
3403
|
+
// permission prompt fires. Silent auto-approval of writes and shell
|
|
3404
|
+
// commands was a structural safety defect. If a user wants unsupervised
|
|
3405
|
+
// operation, they must explicitly set --yolo / --skip-permissions at
|
|
3406
|
+
// CLI startup; those flags do propagate into daemon permissions below.
|
|
3370
3407
|
const daemonPermissions = new PermissionManager();
|
|
3371
3408
|
daemonPermissions.setReadline(rl);
|
|
3372
|
-
|
|
3373
|
-
if (
|
|
3409
|
+
// Inherit ONLY the user's explicit CLI flags, never the autonomy level.
|
|
3410
|
+
if (options.yolo)
|
|
3374
3411
|
daemonPermissions.setYolo(true);
|
|
3375
|
-
|
|
3376
|
-
else if (aLevel >= 3) {
|
|
3412
|
+
if (options.skipPermissions)
|
|
3377
3413
|
daemonPermissions.setSkipPermissions(true);
|
|
3378
|
-
}
|
|
3379
3414
|
try {
|
|
3380
3415
|
await runJarvisDaemon(jarvisQueue, {
|
|
3381
3416
|
sendMessage: async (prompt) => {
|
|
@@ -3744,8 +3779,31 @@ export async function chatCommand(options) {
|
|
|
3744
3779
|
}
|
|
3745
3780
|
}
|
|
3746
3781
|
agentRunning = false;
|
|
3747
|
-
// Keep simple message history for state persistence
|
|
3782
|
+
// Keep simple message history for state persistence.
|
|
3783
|
+
// FIX: CHATFLOW-001 — also persist the assistant's reply, otherwise
|
|
3784
|
+
// saveState() writes a user-only transcript and checkpoint browser shows
|
|
3785
|
+
// empty agent turns. Extract the last assistant text block from the
|
|
3786
|
+
// updated agentHistory.
|
|
3748
3787
|
messages.push({ role: 'user', content: input });
|
|
3788
|
+
for (let i = agentHistory.length - 1; i >= 0; i--) {
|
|
3789
|
+
const m = agentHistory[i];
|
|
3790
|
+
if (m.role !== 'assistant')
|
|
3791
|
+
continue;
|
|
3792
|
+
let assistantText = '';
|
|
3793
|
+
if (typeof m.content === 'string') {
|
|
3794
|
+
assistantText = m.content;
|
|
3795
|
+
}
|
|
3796
|
+
else if (Array.isArray(m.content)) {
|
|
3797
|
+
assistantText = m.content
|
|
3798
|
+
.filter((b) => b?.type === 'text' && typeof b.text === 'string')
|
|
3799
|
+
.map((b) => b.text)
|
|
3800
|
+
.join('');
|
|
3801
|
+
}
|
|
3802
|
+
if (assistantText.trim()) {
|
|
3803
|
+
messages.push({ role: 'assistant', content: assistantText });
|
|
3804
|
+
}
|
|
3805
|
+
break;
|
|
3806
|
+
}
|
|
3749
3807
|
// Process any type-ahead input that was buffered during agent work
|
|
3750
3808
|
// Skip if agent was aborted (ESC already cleared the buffer, but guard against race)
|
|
3751
3809
|
while (typeAheadBuffer.length > 0 && !agentController.isAborted) {
|
|
@@ -3869,26 +3927,32 @@ export async function chatCommand(options) {
|
|
|
3869
3927
|
}, PASTE_THRESHOLD_MS);
|
|
3870
3928
|
});
|
|
3871
3929
|
// Handle Esc to discard paste buffer
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
inputMgr.clearPasteBlock();
|
|
3884
|
-
showPrompt();
|
|
3930
|
+
// NOTE: paste-cancel is stored in a named const so rl.on('close') can
|
|
3931
|
+
// remove it cleanly. Without removal, re-entering the chat command in
|
|
3932
|
+
// the same process would stack this prependListener, causing duplicate
|
|
3933
|
+
// ESC handling and phantom paste-cancels.
|
|
3934
|
+
const pasteCancelListener = (_str, key) => {
|
|
3935
|
+
if (key?.name === 'escape' && (pasteBuffer.length > 0 || pendingPasteText || inputMgr.hasPasteBlock)) {
|
|
3936
|
+
pasteBuffer = [];
|
|
3937
|
+
pendingPasteText = null;
|
|
3938
|
+
if (pasteTimer) {
|
|
3939
|
+
clearTimeout(pasteTimer);
|
|
3940
|
+
pasteTimer = null;
|
|
3885
3941
|
}
|
|
3886
|
-
|
|
3942
|
+
inputMgr.clearPasteBlock();
|
|
3943
|
+
showPrompt();
|
|
3944
|
+
}
|
|
3945
|
+
};
|
|
3946
|
+
if (process.stdin.isTTY) {
|
|
3947
|
+
process.stdin.prependListener('keypress', pasteCancelListener);
|
|
3887
3948
|
}
|
|
3888
3949
|
// Type-ahead during LLM streaming is handled by InputManager._renderCurrentLine()
|
|
3889
3950
|
// (muted path renders dim text with proper cursor positioning via renderInput).
|
|
3890
3951
|
rl.on('close', async () => {
|
|
3891
3952
|
clearInterval(footerTimer);
|
|
3953
|
+
if (process.stdin.isTTY) {
|
|
3954
|
+
process.stdin.removeListener('keypress', pasteCancelListener);
|
|
3955
|
+
}
|
|
3892
3956
|
chrome.deactivate();
|
|
3893
3957
|
if (spiralEngine) {
|
|
3894
3958
|
// Persist session buffer (goals, entities, decisions) into spiral brain
|
|
@@ -4185,11 +4249,12 @@ async function sendAgentMessage(input, agentHistory, provider, project, spiralEn
|
|
|
4185
4249
|
renderError('Rate limit reached. Waiting and retrying automatically next time.');
|
|
4186
4250
|
renderInfo(chalk.dim(' Tip: Use /compact to reduce spiral nodes, or wait a moment before retrying.'));
|
|
4187
4251
|
}
|
|
4188
|
-
else if (
|
|
4252
|
+
else if (/authentication|401|invalid[^a-z]*key/i.test(errMsg)) {
|
|
4253
|
+
// FIX: CHATFLOW-004 — use real regex instead of literal "invalid.*key" substring.
|
|
4189
4254
|
renderError('Authentication failed. Your API key may be invalid or expired.');
|
|
4190
4255
|
renderInfo(chalk.dim(' Fix: /keys to update your API key.'));
|
|
4191
4256
|
}
|
|
4192
|
-
else if (
|
|
4257
|
+
else if (/ENOTFOUND|ECONNREFUSED|ETIMEDOUT|network|fetch failed|offline/i.test(errMsg)) {
|
|
4193
4258
|
renderError('Network error — cannot reach the API server.');
|
|
4194
4259
|
renderInfo(chalk.dim(' Check your internet connection and try again.'));
|
|
4195
4260
|
}
|