@visorcraft/idlehands 1.1.17 → 1.2.1
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/agent/formatting.js +30 -13
- package/dist/agent/formatting.js.map +1 -1
- package/dist/agent/review-artifact.js +12 -8
- package/dist/agent/review-artifact.js.map +1 -1
- package/dist/agent/tool-calls.js +57 -20
- package/dist/agent/tool-calls.js.map +1 -1
- package/dist/agent/tool-loop-detection.js +310 -0
- package/dist/agent/tool-loop-detection.js.map +1 -0
- package/dist/agent/tool-loop-guard.js +251 -0
- package/dist/agent/tool-loop-guard.js.map +1 -0
- package/dist/agent.js +460 -144
- package/dist/agent.js.map +1 -1
- package/dist/anton/controller.js +46 -30
- package/dist/anton/controller.js.map +1 -1
- package/dist/anton/lock.js +5 -1
- package/dist/anton/lock.js.map +1 -1
- package/dist/anton/parser.js +18 -19
- package/dist/anton/parser.js.map +1 -1
- package/dist/anton/prompt.js +42 -11
- package/dist/anton/prompt.js.map +1 -1
- package/dist/anton/reporter.js.map +1 -1
- package/dist/anton/session.js.map +1 -1
- package/dist/anton/verifier.js +3 -5
- package/dist/anton/verifier.js.map +1 -1
- package/dist/bench/compare.js +53 -20
- package/dist/bench/compare.js.map +1 -1
- package/dist/bench/openclaw.js +4 -4
- package/dist/bench/openclaw.js.map +1 -1
- package/dist/bench/report.js +11 -3
- package/dist/bench/report.js.map +1 -1
- package/dist/bench/runner.js +20 -14
- package/dist/bench/runner.js.map +1 -1
- package/dist/bot/commands.js +65 -31
- package/dist/bot/commands.js.map +1 -1
- package/dist/bot/confirm-discord.js +32 -9
- package/dist/bot/confirm-discord.js.map +1 -1
- package/dist/bot/confirm-telegram.js +26 -10
- package/dist/bot/confirm-telegram.js.map +1 -1
- package/dist/bot/dir-guard.js +18 -3
- package/dist/bot/dir-guard.js.map +1 -1
- package/dist/bot/discord-routing.js +28 -4
- package/dist/bot/discord-routing.js.map +1 -1
- package/dist/bot/discord-streaming.js +3 -3
- package/dist/bot/discord-streaming.js.map +1 -1
- package/dist/bot/discord.js +82 -37
- package/dist/bot/discord.js.map +1 -1
- package/dist/bot/escalation.js +124 -0
- package/dist/bot/escalation.js.map +1 -0
- package/dist/bot/format.js +2 -5
- package/dist/bot/format.js.map +1 -1
- package/dist/bot/session-manager.js +17 -6
- package/dist/bot/session-manager.js.map +1 -1
- package/dist/bot/telegram.js +88 -28
- package/dist/bot/telegram.js.map +1 -1
- package/dist/cli/agent-turn.js +10 -4
- package/dist/cli/agent-turn.js.map +1 -1
- package/dist/cli/args.js +51 -9
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/bot.js +19 -9
- package/dist/cli/bot.js.map +1 -1
- package/dist/cli/build-repl-context.js +60 -26
- package/dist/cli/build-repl-context.js.map +1 -1
- package/dist/cli/command-registry.js.map +1 -1
- package/dist/cli/commands/anton.js +5 -3
- package/dist/cli/commands/anton.js.map +1 -1
- package/dist/cli/commands/editing.js +27 -12
- package/dist/cli/commands/editing.js.map +1 -1
- package/dist/cli/commands/model.js +16 -7
- package/dist/cli/commands/model.js.map +1 -1
- package/dist/cli/commands/project.js +52 -17
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/runtime.js +1 -1
- package/dist/cli/commands/runtime.js.map +1 -1
- package/dist/cli/commands/secrets.js +279 -0
- package/dist/cli/commands/secrets.js.map +1 -0
- package/dist/cli/commands/session.js +49 -1
- package/dist/cli/commands/session.js.map +1 -1
- package/dist/cli/commands/tools.js +3 -1
- package/dist/cli/commands/tools.js.map +1 -1
- package/dist/cli/commands/trifecta.js +1 -1
- package/dist/cli/commands/trifecta.js.map +1 -1
- package/dist/cli/commands/tui.js.map +1 -1
- package/dist/cli/init.js +50 -16
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/input.js +25 -7
- package/dist/cli/input.js.map +1 -1
- package/dist/cli/oneshot.js +31 -19
- package/dist/cli/oneshot.js.map +1 -1
- package/dist/cli/repl-dispatch.js +10 -6
- package/dist/cli/repl-dispatch.js.map +1 -1
- package/dist/cli/runtime-cmds.js +110 -46
- package/dist/cli/runtime-cmds.js.map +1 -1
- package/dist/cli/service.js +3 -3
- package/dist/cli/service.js.map +1 -1
- package/dist/cli/session-state.js +12 -5
- package/dist/cli/session-state.js.map +1 -1
- package/dist/cli/setup.js +86 -33
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/shell.js +4 -4
- package/dist/cli/shell.js.map +1 -1
- package/dist/cli/status.js +56 -12
- package/dist/cli/status.js.map +1 -1
- package/dist/client.js +40 -21
- package/dist/client.js.map +1 -1
- package/dist/commands.js +1 -1
- package/dist/commands.js.map +1 -1
- package/dist/config.js +171 -15
- package/dist/config.js.map +1 -1
- package/dist/confirm/auto.js.map +1 -1
- package/dist/confirm/headless.js +13 -2
- package/dist/confirm/headless.js.map +1 -1
- package/dist/confirm/terminal.js +1 -5
- package/dist/confirm/terminal.js.map +1 -1
- package/dist/context.js +9 -3
- package/dist/context.js.map +1 -1
- package/dist/git.js +56 -61
- package/dist/git.js.map +1 -1
- package/dist/harnesses.js +137 -37
- package/dist/harnesses.js.map +1 -1
- package/dist/history.js +12 -4
- package/dist/history.js.map +1 -1
- package/dist/hooks/index.js +2 -2
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/loader.js +6 -5
- package/dist/hooks/loader.js.map +1 -1
- package/dist/hooks/manager.js.map +1 -1
- package/dist/hooks/plugins/example-console.js.map +1 -1
- package/dist/hooks/scaffold.js +8 -6
- package/dist/hooks/scaffold.js.map +1 -1
- package/dist/index.js +120 -66
- package/dist/index.js.map +1 -1
- package/dist/indexer.js +6 -18
- package/dist/indexer.js.map +1 -1
- package/dist/jsonrpc.js.map +1 -1
- package/dist/lens.js +38 -16
- package/dist/lens.js.map +1 -1
- package/dist/lsp.js +60 -24
- package/dist/lsp.js.map +1 -1
- package/dist/markdown.js +6 -6
- package/dist/markdown.js.map +1 -1
- package/dist/mcp.js +15 -6
- package/dist/mcp.js.map +1 -1
- package/dist/model-customization.js +7 -3
- package/dist/model-customization.js.map +1 -1
- package/dist/progress/message-edit-scheduler.js +15 -3
- package/dist/progress/message-edit-scheduler.js.map +1 -1
- package/dist/progress/progress-message-renderer.js.map +1 -1
- package/dist/progress/progress-presenter.js +3 -3
- package/dist/progress/progress-presenter.js.map +1 -1
- package/dist/progress/serialize-telegram.js.map +1 -1
- package/dist/progress/tool-summary.js +3 -1
- package/dist/progress/tool-summary.js.map +1 -1
- package/dist/progress/turn-progress.js +3 -1
- package/dist/progress/turn-progress.js.map +1 -1
- package/dist/recovery.js +11 -3
- package/dist/recovery.js.map +1 -1
- package/dist/replay.js +9 -3
- package/dist/replay.js.map +1 -1
- package/dist/replay_cli.js +5 -3
- package/dist/replay_cli.js.map +1 -1
- package/dist/runtime/executor.js +66 -20
- package/dist/runtime/executor.js.map +1 -1
- package/dist/runtime/health.js.map +1 -1
- package/dist/runtime/host-runner.js +103 -0
- package/dist/runtime/host-runner.js.map +1 -0
- package/dist/runtime/planner.js +3 -1
- package/dist/runtime/planner.js.map +1 -1
- package/dist/runtime/secrets.js +102 -0
- package/dist/runtime/secrets.js.map +1 -0
- package/dist/runtime/store.js +95 -19
- package/dist/runtime/store.js.map +1 -1
- package/dist/safety.js +38 -21
- package/dist/safety.js.map +1 -1
- package/dist/spinner.js +7 -8
- package/dist/spinner.js.map +1 -1
- package/dist/sys/context.js +3 -3
- package/dist/sys/context.js.map +1 -1
- package/dist/term.js +1 -1
- package/dist/term.js.map +1 -1
- package/dist/themes.js +11 -5
- package/dist/themes.js.map +1 -1
- package/dist/tools/tool-error.js +2 -5
- package/dist/tools/tool-error.js.map +1 -1
- package/dist/tools.js +69 -34
- package/dist/tools.js.map +1 -1
- package/dist/tui/branch-picker.js +9 -3
- package/dist/tui/branch-picker.js.map +1 -1
- package/dist/tui/command-handler.js +88 -36
- package/dist/tui/command-handler.js.map +1 -1
- package/dist/tui/confirm.js.map +1 -1
- package/dist/tui/controller.js +234 -117
- package/dist/tui/controller.js.map +1 -1
- package/dist/tui/event-bridge.js.map +1 -1
- package/dist/tui/keymap.js +93 -71
- package/dist/tui/keymap.js.map +1 -1
- package/dist/tui/layout.js +9 -1
- package/dist/tui/layout.js.map +1 -1
- package/dist/tui/render.js +17 -5
- package/dist/tui/render.js.map +1 -1
- package/dist/tui/screen.js.map +1 -1
- package/dist/tui/state.js +129 -63
- package/dist/tui/state.js.map +1 -1
- package/dist/tui/theme.js +12 -3
- package/dist/tui/theme.js.map +1 -1
- package/dist/upgrade.js +28 -15
- package/dist/upgrade.js.map +1 -1
- package/dist/utils.js +8 -5
- package/dist/utils.js.map +1 -1
- package/dist/vault.js +48 -12
- package/dist/vault.js.map +1 -1
- package/dist/vim.js.map +1 -1
- package/package.json +11 -2
package/dist/tui/controller.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { createSession } from
|
|
2
|
-
import { decodeRawInput, resolveAction } from "./keymap.js";
|
|
3
|
-
import { createInitialTuiState, reduceTuiState } from "./state.js";
|
|
4
|
-
import { renderTui, setRenderTheme } from "./render.js";
|
|
5
|
-
import { calculateLayout } from "./layout.js";
|
|
6
|
-
import { enterFullScreen, leaveFullScreen } from "./screen.js";
|
|
7
|
-
import { saveSessionFile, lastSessionPath, projectSessionPath } from "../cli/session-state.js";
|
|
8
|
-
import { loadBranches, executeBranchSelect } from "./branch-picker.js";
|
|
9
|
-
import { ensureCommandsRegistered, allCommandNames, runShellCommand, runSlashCommand } from "./command-handler.js";
|
|
10
|
-
import { projectDir } from "../utils.js";
|
|
11
|
-
import { formatWatchdogCancelMessage, resolveWatchdogSettings } from "../watchdog.js";
|
|
12
|
-
import { TuiConfirmProvider } from "./confirm.js";
|
|
1
|
+
import { createSession } from '../agent.js';
|
|
13
2
|
import { splitTokens } from '../cli/command-utils.js';
|
|
3
|
+
import { saveSessionFile, lastSessionPath, projectSessionPath } from '../cli/session-state.js';
|
|
14
4
|
import { chainAgentHooks } from '../progress/agent-hooks.js';
|
|
15
|
-
import { formatToolCallSummary } from '../progress/tool-summary.js';
|
|
16
5
|
import { ProgressPresenter } from '../progress/progress-presenter.js';
|
|
6
|
+
import { formatToolCallSummary } from '../progress/tool-summary.js';
|
|
7
|
+
import { projectDir } from '../utils.js';
|
|
8
|
+
import { formatWatchdogCancelMessage, resolveWatchdogSettings } from '../watchdog.js';
|
|
9
|
+
import { loadBranches, executeBranchSelect } from './branch-picker.js';
|
|
10
|
+
import { ensureCommandsRegistered, allCommandNames, runShellCommand, runSlashCommand, } from './command-handler.js';
|
|
11
|
+
import { TuiConfirmProvider } from './confirm.js';
|
|
12
|
+
import { decodeRawInput, resolveAction } from './keymap.js';
|
|
13
|
+
import { calculateLayout } from './layout.js';
|
|
14
|
+
import { renderTui, setRenderTheme } from './render.js';
|
|
15
|
+
import { enterFullScreen, leaveFullScreen } from './screen.js';
|
|
16
|
+
import { createInitialTuiState, reduceTuiState } from './state.js';
|
|
17
17
|
const THEME_OPTIONS = ['default', 'dark', 'light', 'minimal', 'hacker'];
|
|
18
18
|
const APPROVAL_OPTIONS = ['plan', 'default', 'auto-edit', 'yolo'];
|
|
19
19
|
export class TuiController {
|
|
@@ -59,9 +59,19 @@ export class TuiController {
|
|
|
59
59
|
this.tabIndex = -1;
|
|
60
60
|
const names = allCommandNames();
|
|
61
61
|
// Add TUI-specific commands that aren't in the registry
|
|
62
|
-
const extra = [
|
|
62
|
+
const extra = [
|
|
63
|
+
'/quit',
|
|
64
|
+
'/exit',
|
|
65
|
+
'/clear',
|
|
66
|
+
'/cancel',
|
|
67
|
+
'/help',
|
|
68
|
+
'/branches',
|
|
69
|
+
'/steps',
|
|
70
|
+
'/settings',
|
|
71
|
+
'/hooks',
|
|
72
|
+
];
|
|
63
73
|
const all = [...new Set([...names, ...extra])];
|
|
64
|
-
this.tabCandidates = all.filter(n => n.toLowerCase().startsWith(prefix)).sort();
|
|
74
|
+
this.tabCandidates = all.filter((n) => n.toLowerCase().startsWith(prefix)).sort();
|
|
65
75
|
}
|
|
66
76
|
if (!this.tabCandidates.length)
|
|
67
77
|
return;
|
|
@@ -101,7 +111,12 @@ export class TuiController {
|
|
|
101
111
|
if (result.ok)
|
|
102
112
|
this.pushSystemMessage(result.message);
|
|
103
113
|
else
|
|
104
|
-
this.dispatch({
|
|
114
|
+
this.dispatch({
|
|
115
|
+
type: 'ALERT_PUSH',
|
|
116
|
+
id: `br_${Date.now()}`,
|
|
117
|
+
level: result.level ?? 'error',
|
|
118
|
+
text: result.message,
|
|
119
|
+
});
|
|
105
120
|
}
|
|
106
121
|
}
|
|
107
122
|
transcriptLineStarts() {
|
|
@@ -118,7 +133,9 @@ export class TuiController {
|
|
|
118
133
|
const q = (query ?? '').trim().toLowerCase();
|
|
119
134
|
const starts = this.transcriptLineStarts();
|
|
120
135
|
const items = this.state.transcript.map((item, idx) => {
|
|
121
|
-
const preview = String(item.text ?? '')
|
|
136
|
+
const preview = String(item.text ?? '')
|
|
137
|
+
.split(/\r?\n/)[0]
|
|
138
|
+
?.trim() ?? '';
|
|
122
139
|
return {
|
|
123
140
|
id: item.id,
|
|
124
141
|
ts: item.ts,
|
|
@@ -129,7 +146,7 @@ export class TuiController {
|
|
|
129
146
|
});
|
|
130
147
|
if (!q)
|
|
131
148
|
return items;
|
|
132
|
-
return items.filter((it) =>
|
|
149
|
+
return items.filter((it) => `${it.role} ${it.preview}`.toLowerCase().includes(q));
|
|
133
150
|
}
|
|
134
151
|
openStepNavigator(query = '') {
|
|
135
152
|
const items = this.buildStepNavigatorItems(query);
|
|
@@ -160,13 +177,19 @@ export class TuiController {
|
|
|
160
177
|
const starts = this.transcriptLineStarts();
|
|
161
178
|
const totalLines = starts.length
|
|
162
179
|
? (starts[starts.length - 1] ?? 0) +
|
|
163
|
-
Math.max(1, String(this.state.transcript[this.state.transcript.length - 1]?.text ?? '').split('\n')
|
|
180
|
+
Math.max(1, String(this.state.transcript[this.state.transcript.length - 1]?.text ?? '').split('\n')
|
|
181
|
+
.length)
|
|
164
182
|
: 0;
|
|
165
183
|
const desiredStart = Math.max(0, Math.min(selected.lineStart, Math.max(0, totalLines - layout.transcriptRows)));
|
|
166
184
|
const scrollBack = Math.max(0, totalLines - (desiredStart + layout.transcriptRows));
|
|
167
185
|
this.dispatch({ type: 'SCROLL_SET', panel: 'transcript', value: scrollBack });
|
|
168
186
|
this.dispatch({ type: 'STEP_NAV_CLOSE' });
|
|
169
|
-
this.dispatch({
|
|
187
|
+
this.dispatch({
|
|
188
|
+
type: 'ALERT_PUSH',
|
|
189
|
+
id: `step_${Date.now()}`,
|
|
190
|
+
level: 'info',
|
|
191
|
+
text: `Jumped to ${selected.role}: ${selected.preview || '(no preview)'}`,
|
|
192
|
+
});
|
|
170
193
|
}
|
|
171
194
|
buildSettingsItems() {
|
|
172
195
|
const watchdog = resolveWatchdogSettings(undefined, this.config);
|
|
@@ -234,7 +257,8 @@ export class TuiController {
|
|
|
234
257
|
break;
|
|
235
258
|
}
|
|
236
259
|
case 'approval': {
|
|
237
|
-
const current = (this.config.approval_mode ||
|
|
260
|
+
const current = (this.config.approval_mode ||
|
|
261
|
+
'default');
|
|
238
262
|
const idx = Math.max(0, APPROVAL_OPTIONS.indexOf(current));
|
|
239
263
|
const next = APPROVAL_OPTIONS[(idx + (delta >= 0 ? 1 : -1) + APPROVAL_OPTIONS.length) % APPROVAL_OPTIONS.length];
|
|
240
264
|
this.config.approval_mode = next;
|
|
@@ -314,7 +338,7 @@ export class TuiController {
|
|
|
314
338
|
}
|
|
315
339
|
/** Push a system-role transcript item and re-render. */
|
|
316
340
|
pushSystemMessage(text) {
|
|
317
|
-
const item = { id: `sys_${Date.now()}`, role:
|
|
341
|
+
const item = { id: `sys_${Date.now()}`, role: 'system', text, ts: Date.now() };
|
|
318
342
|
this.state = { ...this.state, transcript: [...this.state.transcript, item] };
|
|
319
343
|
renderTui(this.state);
|
|
320
344
|
}
|
|
@@ -322,28 +346,46 @@ export class TuiController {
|
|
|
322
346
|
async handleShellCommand(line) {
|
|
323
347
|
const result = await runShellCommand(line, this.config);
|
|
324
348
|
if (!result.command) {
|
|
325
|
-
this.dispatch({
|
|
349
|
+
this.dispatch({
|
|
350
|
+
type: 'ALERT_PUSH',
|
|
351
|
+
id: `sh_${Date.now()}`,
|
|
352
|
+
level: 'info',
|
|
353
|
+
text: 'Usage: !<command> or !!<command> to inject output',
|
|
354
|
+
});
|
|
326
355
|
return;
|
|
327
356
|
}
|
|
328
357
|
this.pushSystemMessage(`$ ${result.command}`);
|
|
329
358
|
if (result.output.trim())
|
|
330
359
|
this.pushSystemMessage(result.output);
|
|
331
360
|
if (result.rc !== 0)
|
|
332
|
-
this.dispatch({
|
|
361
|
+
this.dispatch({
|
|
362
|
+
type: 'ALERT_PUSH',
|
|
363
|
+
id: `sh_${Date.now()}`,
|
|
364
|
+
level: 'warn',
|
|
365
|
+
text: `Shell exited rc=${result.rc}`,
|
|
366
|
+
});
|
|
333
367
|
if (result.inject && this.session) {
|
|
334
|
-
this.session.messages.push({
|
|
335
|
-
|
|
368
|
+
this.session.messages.push({
|
|
369
|
+
role: 'user',
|
|
370
|
+
content: `[Shell output]\n$ ${result.command}\n${result.output}`,
|
|
371
|
+
});
|
|
372
|
+
this.dispatch({
|
|
373
|
+
type: 'ALERT_PUSH',
|
|
374
|
+
id: `sh_${Date.now()}`,
|
|
375
|
+
level: 'info',
|
|
376
|
+
text: 'Output injected into context',
|
|
377
|
+
});
|
|
336
378
|
}
|
|
337
379
|
}
|
|
338
380
|
/** Handle a slash command. Returns true if handled. */
|
|
339
381
|
async handleSlashCommand(line) {
|
|
340
382
|
const parts = splitTokens(line);
|
|
341
|
-
const head = (parts[0] ||
|
|
342
|
-
if (!head.startsWith(
|
|
383
|
+
const head = (parts[0] || '').toLowerCase();
|
|
384
|
+
if (!head.startsWith('/'))
|
|
343
385
|
return false;
|
|
344
386
|
ensureCommandsRegistered();
|
|
345
387
|
// TUI-specific overrides
|
|
346
|
-
if (head ===
|
|
388
|
+
if (head === '/quit' || head === '/exit') {
|
|
347
389
|
if (this.cleanupFn)
|
|
348
390
|
await this.cleanupFn();
|
|
349
391
|
return true;
|
|
@@ -358,29 +400,43 @@ export class TuiController {
|
|
|
358
400
|
this.session?.cancel();
|
|
359
401
|
}
|
|
360
402
|
catch { }
|
|
361
|
-
this.dispatch({
|
|
403
|
+
this.dispatch({
|
|
404
|
+
type: 'ALERT_PUSH',
|
|
405
|
+
id: `cancel_${Date.now()}`,
|
|
406
|
+
level: 'warn',
|
|
407
|
+
text: '⏹ Cancel requested.',
|
|
408
|
+
});
|
|
362
409
|
}
|
|
363
410
|
else {
|
|
364
|
-
this.dispatch({
|
|
411
|
+
this.dispatch({
|
|
412
|
+
type: 'ALERT_PUSH',
|
|
413
|
+
id: `cancel_${Date.now()}`,
|
|
414
|
+
level: 'info',
|
|
415
|
+
text: 'Nothing to cancel.',
|
|
416
|
+
});
|
|
365
417
|
}
|
|
366
418
|
return true;
|
|
367
419
|
}
|
|
368
|
-
if (head ===
|
|
420
|
+
if (head === '/clear') {
|
|
369
421
|
this.state = { ...this.state, transcript: [], toolEvents: [], alerts: [] };
|
|
370
422
|
renderTui(this.state);
|
|
371
423
|
return true;
|
|
372
424
|
}
|
|
373
|
-
if (head ===
|
|
374
|
-
const cmds = allCommandNames().join(
|
|
425
|
+
if (head === '/help') {
|
|
426
|
+
const cmds = allCommandNames().join(' ');
|
|
375
427
|
this.pushSystemMessage(`Commands: ${cmds}\n` +
|
|
376
428
|
`Shell: !<cmd> to run, !! to inject output\n` +
|
|
377
|
-
`TUI: /cancel (stop active run), /branches [browse|checkout|merge], /steps, /settings, /hooks [status|errors|slow|plugins]\n` +
|
|
429
|
+
`TUI: /cancel (stop active run), /branches [browse|checkout|merge], /steps, /settings, /hooks [status|errors|slow|plugins], /version\n` +
|
|
378
430
|
`Hotkeys: Ctrl+C cancel in-flight run, Ctrl+G step navigator, Ctrl+O quick settings`);
|
|
379
431
|
return true;
|
|
380
432
|
}
|
|
381
|
-
if (head ===
|
|
433
|
+
if (head === '/branches') {
|
|
382
434
|
const sub = (parts[1] || '').toLowerCase();
|
|
383
|
-
const action = sub === 'checkout'
|
|
435
|
+
const action = sub === 'checkout'
|
|
436
|
+
? 'checkout'
|
|
437
|
+
: sub === 'merge'
|
|
438
|
+
? 'merge'
|
|
439
|
+
: 'browse';
|
|
384
440
|
await this.openBranchPicker(action);
|
|
385
441
|
return true;
|
|
386
442
|
}
|
|
@@ -394,10 +450,18 @@ export class TuiController {
|
|
|
394
450
|
return true;
|
|
395
451
|
}
|
|
396
452
|
if (head === '/hooks') {
|
|
397
|
-
const modeRaw = line
|
|
453
|
+
const modeRaw = line
|
|
454
|
+
.replace(/^\/hooks\s*/i, '')
|
|
455
|
+
.trim()
|
|
456
|
+
.toLowerCase();
|
|
398
457
|
const mode = (modeRaw || 'status');
|
|
399
458
|
if (!['status', 'errors', 'slow', 'plugins'].includes(mode)) {
|
|
400
|
-
this.dispatch({
|
|
459
|
+
this.dispatch({
|
|
460
|
+
type: 'ALERT_PUSH',
|
|
461
|
+
id: `hooks_${Date.now()}`,
|
|
462
|
+
level: 'warn',
|
|
463
|
+
text: 'Usage: /hooks [status|errors|slow|plugins]',
|
|
464
|
+
});
|
|
401
465
|
return true;
|
|
402
466
|
}
|
|
403
467
|
this.openHooksInspector(mode);
|
|
@@ -405,7 +469,12 @@ export class TuiController {
|
|
|
405
469
|
}
|
|
406
470
|
const result = await runSlashCommand(line, this.session, this.config, this.cleanupFn, () => this.saveTuiSessionSnapshot());
|
|
407
471
|
if (!result.found) {
|
|
408
|
-
this.dispatch({
|
|
472
|
+
this.dispatch({
|
|
473
|
+
type: 'ALERT_PUSH',
|
|
474
|
+
id: `cmd_${Date.now()}`,
|
|
475
|
+
level: 'warn',
|
|
476
|
+
text: `Unknown command: ${head}`,
|
|
477
|
+
});
|
|
409
478
|
}
|
|
410
479
|
else if (result.output) {
|
|
411
480
|
this.pushSystemMessage(result.output);
|
|
@@ -421,7 +490,7 @@ export class TuiController {
|
|
|
421
490
|
harness: this.session.harness,
|
|
422
491
|
contextWindow: this.session.contextWindow,
|
|
423
492
|
messages: this.session.messages,
|
|
424
|
-
mode:
|
|
493
|
+
mode: 'tui',
|
|
425
494
|
};
|
|
426
495
|
const cwd = projectDir(this.config);
|
|
427
496
|
const targets = new Set([lastSessionPath(), projectSessionPath(cwd)]);
|
|
@@ -436,33 +505,43 @@ export class TuiController {
|
|
|
436
505
|
return;
|
|
437
506
|
// Slash commands: route through registry instead of agent.
|
|
438
507
|
// While a generation is in-flight, only /cancel is accepted immediately.
|
|
439
|
-
if (trimmed.startsWith(
|
|
508
|
+
if (trimmed.startsWith('/')) {
|
|
440
509
|
const head = (splitTokens(trimmed)[0] || '').toLowerCase();
|
|
441
510
|
if (this.inFlight && head !== '/cancel') {
|
|
442
|
-
this.dispatch({
|
|
511
|
+
this.dispatch({
|
|
512
|
+
type: 'ALERT_PUSH',
|
|
513
|
+
id: `busy_${Date.now()}`,
|
|
514
|
+
level: 'warn',
|
|
515
|
+
text: 'Generation in progress. Use /cancel first.',
|
|
516
|
+
});
|
|
443
517
|
return;
|
|
444
518
|
}
|
|
445
|
-
this.dispatch({ type:
|
|
519
|
+
this.dispatch({ type: 'USER_INPUT_SUBMIT', text: trimmed });
|
|
446
520
|
await this.handleSlashCommand(trimmed);
|
|
447
521
|
return;
|
|
448
522
|
}
|
|
449
523
|
if (this.inFlight) {
|
|
450
|
-
this.dispatch({
|
|
524
|
+
this.dispatch({
|
|
525
|
+
type: 'ALERT_PUSH',
|
|
526
|
+
id: `busy_${Date.now()}`,
|
|
527
|
+
level: 'warn',
|
|
528
|
+
text: 'Generation in progress. Use /cancel first.',
|
|
529
|
+
});
|
|
451
530
|
return;
|
|
452
531
|
}
|
|
453
532
|
// Shell commands: !cmd or !!cmd
|
|
454
533
|
if (/^!{1,2}\s*\S/.test(trimmed)) {
|
|
455
|
-
this.dispatch({ type:
|
|
534
|
+
this.dispatch({ type: 'USER_INPUT_SUBMIT', text: trimmed });
|
|
456
535
|
await this.handleShellCommand(trimmed);
|
|
457
536
|
return;
|
|
458
537
|
}
|
|
459
|
-
this.dispatch({ type:
|
|
538
|
+
this.dispatch({ type: 'USER_INPUT_SUBMIT', text: trimmed });
|
|
460
539
|
const id = `a_${Date.now()}`;
|
|
461
540
|
this.inFlight = true;
|
|
462
541
|
this.aborter = new AbortController();
|
|
463
542
|
this.lastProgressAt = Date.now();
|
|
464
543
|
this.watchdogCompactAttempts = 0;
|
|
465
|
-
this.dispatch({ type:
|
|
544
|
+
this.dispatch({ type: 'AGENT_STREAM_START', id });
|
|
466
545
|
const watchdogSettings = resolveWatchdogSettings(undefined, this.config);
|
|
467
546
|
const watchdogMs = watchdogSettings.timeoutMs;
|
|
468
547
|
const maxWatchdogCompacts = watchdogSettings.maxCompactions;
|
|
@@ -501,10 +580,10 @@ export class TuiController {
|
|
|
501
580
|
presenter.setBanner('⏳ Still working... model is taking longer than usual.');
|
|
502
581
|
console.error(`[tui] watchdog inactivity — applying grace period (${watchdogGraceUsed}/${watchdogIdleGraceTimeouts})`);
|
|
503
582
|
this.dispatch({
|
|
504
|
-
type:
|
|
583
|
+
type: 'ALERT_PUSH',
|
|
505
584
|
id: `watchdog_grace_${Date.now()}`,
|
|
506
|
-
level:
|
|
507
|
-
text:
|
|
585
|
+
level: 'info',
|
|
586
|
+
text: 'Still working... model is taking longer than usual.',
|
|
508
587
|
});
|
|
509
588
|
return;
|
|
510
589
|
}
|
|
@@ -517,12 +596,14 @@ export class TuiController {
|
|
|
517
596
|
this.aborter?.abort();
|
|
518
597
|
}
|
|
519
598
|
catch { }
|
|
520
|
-
this.session.compactHistory({ force: true })
|
|
599
|
+
this.session.compactHistory({ force: true })
|
|
600
|
+
.then((result) => {
|
|
521
601
|
console.error(`[tui] watchdog compaction: freed ${result.freedTokens} tokens, dropped ${result.droppedMessages} messages`);
|
|
522
602
|
presenter.setBanner(null);
|
|
523
603
|
this.lastProgressAt = Date.now();
|
|
524
604
|
watchdogCompactPending = false;
|
|
525
|
-
})
|
|
605
|
+
})
|
|
606
|
+
.catch((e) => {
|
|
526
607
|
console.error(`[tui] watchdog compaction failed: ${e?.message ?? e}`);
|
|
527
608
|
presenter.setBanner(null);
|
|
528
609
|
watchdogCompactPending = false;
|
|
@@ -597,7 +678,12 @@ export class TuiController {
|
|
|
597
678
|
presenterHooks.onToolResult?.(r);
|
|
598
679
|
if (activeToolId === r.id)
|
|
599
680
|
activeToolId = null;
|
|
600
|
-
this.dispatch({
|
|
681
|
+
this.dispatch({
|
|
682
|
+
type: r.success ? 'TOOL_END' : 'TOOL_ERROR',
|
|
683
|
+
id: r.id,
|
|
684
|
+
name: r.name,
|
|
685
|
+
detail: r.summary,
|
|
686
|
+
});
|
|
601
687
|
},
|
|
602
688
|
onTurnEnd: (stats) => {
|
|
603
689
|
this.lastProgressAt = Date.now();
|
|
@@ -614,7 +700,12 @@ export class TuiController {
|
|
|
614
700
|
const msg = e?.message ?? String(e);
|
|
615
701
|
const isAbort = msg.includes('AbortError') || msg.toLowerCase().includes('aborted');
|
|
616
702
|
if (isAbort && watchdogCompactPending) {
|
|
617
|
-
this.dispatch({
|
|
703
|
+
this.dispatch({
|
|
704
|
+
type: 'ALERT_PUSH',
|
|
705
|
+
id: `compact_${Date.now()}`,
|
|
706
|
+
level: 'info',
|
|
707
|
+
text: `Context too large — compacting and retrying (attempt ${this.watchdogCompactAttempts}/${maxWatchdogCompacts})...`,
|
|
708
|
+
});
|
|
618
709
|
while (watchdogCompactPending) {
|
|
619
710
|
await new Promise((r) => setTimeout(r, 500));
|
|
620
711
|
}
|
|
@@ -632,7 +723,12 @@ export class TuiController {
|
|
|
632
723
|
this.dispatch({ type: 'ALERT_PUSH', id: `err_${Date.now()}`, level: 'error', text });
|
|
633
724
|
}
|
|
634
725
|
else {
|
|
635
|
-
this.dispatch({
|
|
726
|
+
this.dispatch({
|
|
727
|
+
type: 'ALERT_PUSH',
|
|
728
|
+
id: `err_${Date.now()}`,
|
|
729
|
+
level: 'error',
|
|
730
|
+
text: msg,
|
|
731
|
+
});
|
|
636
732
|
}
|
|
637
733
|
}
|
|
638
734
|
}
|
|
@@ -655,25 +751,36 @@ export class TuiController {
|
|
|
655
751
|
confirm: async (prompt) => {
|
|
656
752
|
// Legacy confirm fallback — route through the TUI confirm provider
|
|
657
753
|
return this.confirmProvider.confirm({
|
|
658
|
-
tool: 'unknown',
|
|
754
|
+
tool: 'unknown',
|
|
755
|
+
args: {},
|
|
756
|
+
summary: prompt,
|
|
757
|
+
mode: this.config.approval_mode ?? 'suggest',
|
|
659
758
|
});
|
|
660
759
|
},
|
|
661
760
|
});
|
|
662
|
-
this.dispatch({
|
|
761
|
+
this.dispatch({
|
|
762
|
+
type: 'RUNTIME_STATE_UPDATE',
|
|
763
|
+
runtime: { modelId: this.session.model, endpoint: this.session.endpoint, healthy: true },
|
|
764
|
+
});
|
|
663
765
|
enterFullScreen();
|
|
664
766
|
renderTui(this.state);
|
|
665
767
|
this.dispatch({
|
|
666
|
-
type:
|
|
768
|
+
type: 'ALERT_PUSH',
|
|
667
769
|
id: `info_${Date.now()}`,
|
|
668
|
-
level:
|
|
669
|
-
text:
|
|
770
|
+
level: 'info',
|
|
771
|
+
text: 'Input: Enter=send, Ctrl+J/Alt+Enter=newline, Up/Down=history, Ctrl+G=steps, Ctrl+O=settings, /hooks inspector.',
|
|
670
772
|
});
|
|
671
773
|
const onSigwinch = () => {
|
|
672
774
|
renderTui(this.state);
|
|
673
775
|
};
|
|
674
776
|
const onFatal = async (err, source) => {
|
|
675
777
|
const text = err instanceof Error ? err.message : String(err);
|
|
676
|
-
this.dispatch({
|
|
778
|
+
this.dispatch({
|
|
779
|
+
type: 'ALERT_PUSH',
|
|
780
|
+
id: `fatal_${Date.now()}`,
|
|
781
|
+
level: 'error',
|
|
782
|
+
text: `${source}: ${text}`,
|
|
783
|
+
});
|
|
677
784
|
try {
|
|
678
785
|
await this.saveTuiSessionSnapshot();
|
|
679
786
|
}
|
|
@@ -682,25 +789,25 @@ export class TuiController {
|
|
|
682
789
|
await cleanup();
|
|
683
790
|
};
|
|
684
791
|
const onData = (buf) => {
|
|
685
|
-
const keys = decodeRawInput(buf.toString(
|
|
792
|
+
const keys = decodeRawInput(buf.toString('utf8'));
|
|
686
793
|
for (const key of keys) {
|
|
687
794
|
// Confirmation mode: route y/n/d to confirm provider
|
|
688
795
|
if (this.state.confirmPending) {
|
|
689
|
-
if (key ===
|
|
796
|
+
if (key === 'text:y' || key === 'text:Y') {
|
|
690
797
|
this.confirmProvider.resolve(true);
|
|
691
798
|
continue;
|
|
692
799
|
}
|
|
693
|
-
if (key ===
|
|
800
|
+
if (key === 'text:n' || key === 'text:N') {
|
|
694
801
|
this.confirmProvider.resolve(false);
|
|
695
802
|
continue;
|
|
696
803
|
}
|
|
697
|
-
if (key ===
|
|
804
|
+
if (key === 'text:d' || key === 'text:D') {
|
|
698
805
|
this.confirmProvider.toggleDiff();
|
|
699
806
|
continue;
|
|
700
807
|
}
|
|
701
808
|
// Ctrl+C rejects during confirm
|
|
702
809
|
const cAction = resolveAction(key);
|
|
703
|
-
if (cAction ===
|
|
810
|
+
if (cAction === 'cancel') {
|
|
704
811
|
this.confirmProvider.resolve(false);
|
|
705
812
|
continue;
|
|
706
813
|
}
|
|
@@ -709,20 +816,20 @@ export class TuiController {
|
|
|
709
816
|
// Branch picker mode: arrow keys navigate, Enter selects, Esc/q closes
|
|
710
817
|
if (this.state.branchPicker) {
|
|
711
818
|
const bAction = resolveAction(key);
|
|
712
|
-
if (bAction ===
|
|
713
|
-
this.dispatch({ type:
|
|
819
|
+
if (bAction === 'history_prev' || key === 'up') {
|
|
820
|
+
this.dispatch({ type: 'BRANCH_PICKER_MOVE', delta: -1 });
|
|
714
821
|
continue;
|
|
715
822
|
}
|
|
716
|
-
if (bAction ===
|
|
717
|
-
this.dispatch({ type:
|
|
823
|
+
if (bAction === 'history_next' || key === 'down') {
|
|
824
|
+
this.dispatch({ type: 'BRANCH_PICKER_MOVE', delta: 1 });
|
|
718
825
|
continue;
|
|
719
826
|
}
|
|
720
|
-
if (bAction ===
|
|
827
|
+
if (bAction === 'send') {
|
|
721
828
|
void this.handleBranchSelect();
|
|
722
829
|
continue;
|
|
723
830
|
}
|
|
724
|
-
if (bAction ===
|
|
725
|
-
this.dispatch({ type:
|
|
831
|
+
if (bAction === 'cancel' || bAction === 'quit' || key === 'text:q') {
|
|
832
|
+
this.dispatch({ type: 'BRANCH_PICKER_CLOSE' });
|
|
726
833
|
continue;
|
|
727
834
|
}
|
|
728
835
|
continue; // swallow all other input during picker
|
|
@@ -805,22 +912,25 @@ export class TuiController {
|
|
|
805
912
|
this.dispatch({ type: 'HOOKS_INSPECTOR_MOVE', delta: 1 });
|
|
806
913
|
continue;
|
|
807
914
|
}
|
|
808
|
-
if (hAction === 'cancel' ||
|
|
915
|
+
if (hAction === 'cancel' ||
|
|
916
|
+
hAction === 'quit' ||
|
|
917
|
+
key === 'text:q' ||
|
|
918
|
+
hAction === 'send') {
|
|
809
919
|
this.dispatch({ type: 'HOOKS_INSPECTOR_CLOSE' });
|
|
810
920
|
continue;
|
|
811
921
|
}
|
|
812
922
|
continue;
|
|
813
923
|
}
|
|
814
|
-
if (key.startsWith(
|
|
924
|
+
if (key.startsWith('text:')) {
|
|
815
925
|
this.resetTab();
|
|
816
|
-
this.dispatch({ type:
|
|
926
|
+
this.dispatch({ type: 'USER_INPUT_INSERT', text: key.slice(5) });
|
|
817
927
|
continue;
|
|
818
928
|
}
|
|
819
929
|
const action = resolveAction(key);
|
|
820
930
|
if (!action)
|
|
821
931
|
continue;
|
|
822
932
|
// Tab completion doesn't reset tab state
|
|
823
|
-
if (action ===
|
|
933
|
+
if (action === 'tab_complete') {
|
|
824
934
|
this.handleTabComplete();
|
|
825
935
|
continue;
|
|
826
936
|
}
|
|
@@ -834,11 +944,11 @@ export class TuiController {
|
|
|
834
944
|
this.openSettingsMenu();
|
|
835
945
|
continue;
|
|
836
946
|
}
|
|
837
|
-
if (action ===
|
|
947
|
+
if (action === 'quit') {
|
|
838
948
|
void cleanup();
|
|
839
949
|
continue;
|
|
840
950
|
}
|
|
841
|
-
if (action ===
|
|
951
|
+
if (action === 'cancel') {
|
|
842
952
|
if (this.inFlight && this.aborter) {
|
|
843
953
|
this.aborter.abort();
|
|
844
954
|
this.session?.cancel();
|
|
@@ -850,55 +960,60 @@ export class TuiController {
|
|
|
850
960
|
continue;
|
|
851
961
|
}
|
|
852
962
|
this.ctrlCAt = now;
|
|
853
|
-
this.dispatch({
|
|
963
|
+
this.dispatch({
|
|
964
|
+
type: 'ALERT_PUSH',
|
|
965
|
+
id: `warn_${now}`,
|
|
966
|
+
level: 'warn',
|
|
967
|
+
text: 'Press Ctrl+C again to quit',
|
|
968
|
+
});
|
|
854
969
|
continue;
|
|
855
970
|
}
|
|
856
|
-
if (action ===
|
|
971
|
+
if (action === 'send') {
|
|
857
972
|
void this.submitInput(this.state.inputBuffer);
|
|
858
973
|
continue;
|
|
859
974
|
}
|
|
860
|
-
if (action ===
|
|
861
|
-
this.dispatch({ type:
|
|
975
|
+
if (action === 'insert_newline') {
|
|
976
|
+
this.dispatch({ type: 'USER_INPUT_INSERT', text: '\n' });
|
|
862
977
|
continue;
|
|
863
978
|
}
|
|
864
|
-
if (action ===
|
|
865
|
-
this.dispatch({ type:
|
|
979
|
+
if (action === 'backspace') {
|
|
980
|
+
this.dispatch({ type: 'USER_INPUT_BACKSPACE' });
|
|
866
981
|
continue;
|
|
867
982
|
}
|
|
868
|
-
if (action ===
|
|
869
|
-
this.dispatch({ type:
|
|
983
|
+
if (action === 'delete_forward') {
|
|
984
|
+
this.dispatch({ type: 'USER_INPUT_DELETE_FORWARD' });
|
|
870
985
|
continue;
|
|
871
986
|
}
|
|
872
|
-
if (action ===
|
|
873
|
-
this.dispatch({ type:
|
|
987
|
+
if (action === 'cursor_left') {
|
|
988
|
+
this.dispatch({ type: 'USER_INPUT_CURSOR_MOVE', delta: -1 });
|
|
874
989
|
continue;
|
|
875
990
|
}
|
|
876
|
-
if (action ===
|
|
877
|
-
this.dispatch({ type:
|
|
991
|
+
if (action === 'cursor_right') {
|
|
992
|
+
this.dispatch({ type: 'USER_INPUT_CURSOR_MOVE', delta: 1 });
|
|
878
993
|
continue;
|
|
879
994
|
}
|
|
880
|
-
if (action ===
|
|
881
|
-
this.dispatch({ type:
|
|
995
|
+
if (action === 'cursor_home') {
|
|
996
|
+
this.dispatch({ type: 'USER_INPUT_CURSOR_HOME' });
|
|
882
997
|
continue;
|
|
883
998
|
}
|
|
884
|
-
if (action ===
|
|
885
|
-
this.dispatch({ type:
|
|
999
|
+
if (action === 'cursor_end') {
|
|
1000
|
+
this.dispatch({ type: 'USER_INPUT_CURSOR_END' });
|
|
886
1001
|
continue;
|
|
887
1002
|
}
|
|
888
|
-
if (action ===
|
|
889
|
-
this.dispatch({ type:
|
|
1003
|
+
if (action === 'history_prev') {
|
|
1004
|
+
this.dispatch({ type: 'USER_INPUT_HISTORY_PREV' });
|
|
890
1005
|
continue;
|
|
891
1006
|
}
|
|
892
|
-
if (action ===
|
|
893
|
-
this.dispatch({ type:
|
|
1007
|
+
if (action === 'history_next') {
|
|
1008
|
+
this.dispatch({ type: 'USER_INPUT_HISTORY_NEXT' });
|
|
894
1009
|
continue;
|
|
895
1010
|
}
|
|
896
|
-
if (action ===
|
|
897
|
-
this.dispatch({ type:
|
|
1011
|
+
if (action === 'scroll_up') {
|
|
1012
|
+
this.dispatch({ type: 'SCROLL', panel: 'transcript', delta: -5 });
|
|
898
1013
|
continue;
|
|
899
1014
|
}
|
|
900
|
-
if (action ===
|
|
901
|
-
this.dispatch({ type:
|
|
1015
|
+
if (action === 'scroll_down') {
|
|
1016
|
+
this.dispatch({ type: 'SCROLL', panel: 'transcript', delta: 5 });
|
|
902
1017
|
}
|
|
903
1018
|
}
|
|
904
1019
|
};
|
|
@@ -909,19 +1024,19 @@ export class TuiController {
|
|
|
909
1024
|
cleaned = true;
|
|
910
1025
|
this.cleanupFn = null;
|
|
911
1026
|
try {
|
|
912
|
-
process.stdin.off(
|
|
1027
|
+
process.stdin.off('data', onData);
|
|
913
1028
|
}
|
|
914
1029
|
catch { }
|
|
915
1030
|
try {
|
|
916
|
-
process.off(
|
|
1031
|
+
process.off('SIGWINCH', onSigwinch);
|
|
917
1032
|
}
|
|
918
1033
|
catch { }
|
|
919
1034
|
try {
|
|
920
|
-
process.off(
|
|
1035
|
+
process.off('uncaughtException', onFatal);
|
|
921
1036
|
}
|
|
922
1037
|
catch { }
|
|
923
1038
|
try {
|
|
924
|
-
process.off(
|
|
1039
|
+
process.off('unhandledRejection', onFatal);
|
|
925
1040
|
}
|
|
926
1041
|
catch { }
|
|
927
1042
|
try {
|
|
@@ -945,33 +1060,35 @@ export class TuiController {
|
|
|
945
1060
|
resolveDone();
|
|
946
1061
|
};
|
|
947
1062
|
let resolveDone;
|
|
948
|
-
const done = new Promise((resolve) => {
|
|
1063
|
+
const done = new Promise((resolve) => {
|
|
1064
|
+
resolveDone = resolve;
|
|
1065
|
+
});
|
|
949
1066
|
this.cleanupFn = cleanup;
|
|
950
1067
|
try {
|
|
951
1068
|
if (process.stdin.isTTY)
|
|
952
1069
|
process.stdin.setRawMode(true);
|
|
953
1070
|
process.stdin.resume();
|
|
954
|
-
process.stdin.on(
|
|
955
|
-
process.on(
|
|
956
|
-
process.on(
|
|
957
|
-
process.on(
|
|
1071
|
+
process.stdin.on('data', onData);
|
|
1072
|
+
process.on('SIGWINCH', onSigwinch);
|
|
1073
|
+
process.on('uncaughtException', onFatal);
|
|
1074
|
+
process.on('unhandledRejection', onFatal);
|
|
958
1075
|
await done;
|
|
959
1076
|
}
|
|
960
1077
|
finally {
|
|
961
1078
|
try {
|
|
962
|
-
process.stdin.off(
|
|
1079
|
+
process.stdin.off('data', onData);
|
|
963
1080
|
}
|
|
964
1081
|
catch { }
|
|
965
1082
|
try {
|
|
966
|
-
process.off(
|
|
1083
|
+
process.off('SIGWINCH', onSigwinch);
|
|
967
1084
|
}
|
|
968
1085
|
catch { }
|
|
969
1086
|
try {
|
|
970
|
-
process.off(
|
|
1087
|
+
process.off('uncaughtException', onFatal);
|
|
971
1088
|
}
|
|
972
1089
|
catch { }
|
|
973
1090
|
try {
|
|
974
|
-
process.off(
|
|
1091
|
+
process.off('unhandledRejection', onFatal);
|
|
975
1092
|
}
|
|
976
1093
|
catch { }
|
|
977
1094
|
try {
|