praxis-agent 0.3.0 → 0.5.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.
Files changed (42) hide show
  1. package/README.md +4 -2
  2. package/dist/application/session-service.d.ts +29 -0
  3. package/dist/application/session-service.d.ts.map +1 -1
  4. package/dist/application/session-service.js +431 -31
  5. package/dist/application/session-service.js.map +1 -1
  6. package/dist/application/top-level-agent-manager.d.ts +15 -1
  7. package/dist/application/top-level-agent-manager.d.ts.map +1 -1
  8. package/dist/application/top-level-agent-manager.js +101 -34
  9. package/dist/application/top-level-agent-manager.js.map +1 -1
  10. package/dist/cli/agents-dashboard.d.ts.map +1 -1
  11. package/dist/cli/agents-dashboard.js +22 -6
  12. package/dist/cli/agents-dashboard.js.map +1 -1
  13. package/dist/cli/interactive.d.ts +22 -2
  14. package/dist/cli/interactive.d.ts.map +1 -1
  15. package/dist/cli/interactive.js +311 -5
  16. package/dist/cli/interactive.js.map +1 -1
  17. package/dist/cli/tui/claude-style.d.ts +15 -0
  18. package/dist/cli/tui/claude-style.d.ts.map +1 -1
  19. package/dist/cli/tui/claude-style.js +26 -0
  20. package/dist/cli/tui/claude-style.js.map +1 -1
  21. package/dist/cli/tui/clipboard.d.ts +3 -0
  22. package/dist/cli/tui/clipboard.d.ts.map +1 -1
  23. package/dist/cli/tui/clipboard.js +12 -0
  24. package/dist/cli/tui/clipboard.js.map +1 -1
  25. package/dist/cli/tui/slash-commands.d.ts.map +1 -1
  26. package/dist/cli/tui/slash-commands.js +10 -0
  27. package/dist/cli/tui/slash-commands.js.map +1 -1
  28. package/dist/cli.d.ts +11 -1
  29. package/dist/cli.d.ts.map +1 -1
  30. package/dist/cli.js +25 -1
  31. package/dist/cli.js.map +1 -1
  32. package/dist/compatibility/claude/schema.d.ts.map +1 -1
  33. package/dist/compatibility/claude/schema.js +11 -1
  34. package/dist/compatibility/claude/schema.js.map +1 -1
  35. package/dist/persistence/claude-job-store.d.ts +11 -1
  36. package/dist/persistence/claude-job-store.d.ts.map +1 -1
  37. package/dist/persistence/claude-job-store.js +23 -2
  38. package/dist/persistence/claude-job-store.js.map +1 -1
  39. package/dist/persistence/claude-transcript-store.d.ts.map +1 -1
  40. package/dist/persistence/claude-transcript-store.js +8 -2
  41. package/dist/persistence/claude-transcript-store.js.map +1 -1
  42. package/package.json +2 -1
@@ -1,4 +1,4 @@
1
- import type { ForkResult, ManualCompactResult, ManualCompactSelection, RewindPoint, SessionRunResult, SessionSummary } from '../application/session-service.js';
1
+ import type { ForkResult, ManualCompactResult, ManualCompactSelection, RewindPoint, SessionForkCheckpoint, SessionRunResult, SessionSummary, SideQuestionForkResult, SideQuestionResult } from '../application/session-service.js';
2
2
  import type { ModelImage, ModelToolCall, RuntimeEventSink } from '../core/runtime.js';
3
3
  import type { CliElicitationRequest, CliElicitationResult, CliRuntimeInfo } from './protocol.js';
4
4
  import type { ClaudeInteractiveToolCallbacks } from '../tools/claude-interactive-tools.js';
@@ -26,6 +26,11 @@ interface InteractiveSessionCommands {
26
26
  rewindPoints?(sessionId: string): Promise<RewindPoint[]>;
27
27
  changeCwd?(sessionId: string | undefined, cwd: string): Promise<string>;
28
28
  recordCdUsage?(sessionId: string): Promise<void>;
29
+ answerSideQuestion?(sessionId: string | undefined, question: string, signal?: AbortSignal, onDelta?: (delta: string) => void, permissionMode?: ClaudePermissionMode): Promise<SideQuestionResult>;
30
+ recordBtwUsage?(sessionId: string | undefined, permissionMode?: ClaudePermissionMode): Promise<string>;
31
+ recordBackgroundUsage?(sessionId: string | undefined, permissionMode?: ClaudePermissionMode): Promise<string>;
32
+ recordBackgroundLaunch?(sessionId: string): Promise<SessionForkCheckpoint>;
33
+ forkSideQuestion?(sessionId: string, question: string, signal?: AbortSignal): Promise<SideQuestionForkResult>;
29
34
  rename?(sessionId: string, name: string): Promise<void>;
30
35
  sessionNameSuggestion?(sessionId: string, signal?: AbortSignal): Promise<string | null>;
31
36
  workflows?(): readonly Record<string, unknown>[];
@@ -66,6 +71,17 @@ export interface InteractiveResumeOptions {
66
71
  forkSessionId?: string;
67
72
  retryInterruptedTools?: boolean;
68
73
  }
74
+ export interface InteractiveBackgroundRequest {
75
+ sourceSessionId: string;
76
+ sourceCheckpoint: SessionForkCheckpoint;
77
+ prompt: string;
78
+ detail: string;
79
+ cwd: string;
80
+ }
81
+ export interface InteractiveBackgroundResult {
82
+ id: string;
83
+ sessionId: string;
84
+ }
69
85
  interface InteractiveAppProps {
70
86
  factory: InteractiveServiceFactory;
71
87
  initialSessions: readonly SessionSummary[];
@@ -75,6 +91,7 @@ interface InteractiveAppProps {
75
91
  onCancel?: () => void;
76
92
  onTurnChange?: (turn: Promise<void> | null) => void;
77
93
  onCleanup?: (closing: Promise<void>) => void;
94
+ onBackground?: (request: InteractiveBackgroundRequest) => Promise<InteractiveBackgroundResult>;
78
95
  axScreenReader?: boolean;
79
96
  allowNewSession?: boolean;
80
97
  resume?: InteractiveResumeOptions;
@@ -96,6 +113,7 @@ interface InteractiveAppProps {
96
113
  suspendProcess?: () => void | Promise<void>;
97
114
  clipboardReader?: () => Promise<TuiClipboardContent>;
98
115
  clipboardWriter?: (text: string) => Promise<void>;
116
+ sideQuestionClipboardWriter?: (text: string) => Promise<void>;
99
117
  exportWriter?: (path: string, text: string) => Promise<void>;
100
118
  permissionRuleStore?: {
101
119
  load(): Promise<readonly TuiPermissionRule[]>;
@@ -109,7 +127,7 @@ interface InteractiveAppProps {
109
127
  workspaceDirectoryResolver?: typeof resolveTuiWorkspaceDirectory;
110
128
  workspaceDirectoryCompleter?: typeof completeTuiWorkspaceDirectory;
111
129
  }
112
- export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, signal, onCancel, onTurnChange, onCleanup, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, suspendProcess, clipboardReader, clipboardWriter, exportWriter, permissionRuleStore, workspaceDirectoryResolver, workspaceDirectoryCompleter, }: InteractiveAppProps): import("react").JSX.Element;
130
+ export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, signal, onCancel, onTurnChange, onCleanup, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, workspaceDirectoryResolver, workspaceDirectoryCompleter, }: InteractiveAppProps): import("react").JSX.Element;
113
131
  export declare function runInteractive(options: {
114
132
  factory: InteractiveServiceFactory;
115
133
  initialPrompt?: string;
@@ -122,6 +140,8 @@ export declare function runInteractive(options: {
122
140
  requireSession?: boolean;
123
141
  missingSessionMessage?: string;
124
142
  resume?: InteractiveResumeOptions;
143
+ onBackground?: (request: InteractiveBackgroundRequest) => Promise<InteractiveBackgroundResult>;
144
+ onBackgrounded?: (result: InteractiveBackgroundResult) => void;
125
145
  }): Promise<number>;
126
146
  export {};
127
147
  //# sourceMappingURL=interactive.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/cli/interactive.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/cli/interactive.tsx"],"names":[],"mappings":"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"}
@@ -3,8 +3,9 @@ import { homedir } from 'node:os';
3
3
  import { resolve } from 'node:path';
4
4
  import { useEffect, useMemo, useRef, useState } from 'react';
5
5
  import { Box, Text, render, useApp, useInput } from 'ink';
6
+ import { AgentRunCancelledError } from '../core/runtime.js';
6
7
  import { redactSensitiveText, sensitiveEnvironmentValues, } from '../platform/sensitive-data.js';
7
- import { CommandPalette, Composer, DiffDashboard, DialogFrame, ExternalEditorWait, HelpMenu, ListDashboard, MentionPicker, PermissionDashboard, SelectionMenu, SessionPicker, StatusDashboard, Transcript, WelcomePanel, useTerminalWidth, } from './tui/claude-style.js';
8
+ import { CommandPalette, BtwPanel, Composer, DiffDashboard, DialogFrame, ExternalEditorWait, HelpMenu, ListDashboard, MentionPicker, PermissionDashboard, SelectionMenu, SessionPicker, StatusDashboard, Transcript, WelcomePanel, useTerminalWidth, } from './tui/claude-style.js';
8
9
  import { loadGitDiff, visiblePatchLines, } from './tui/git-diff.js';
9
10
  import { addTuiPermissionRule, loadTuiPermissionRules, removeTuiPermissionRule, } from './tui/permission-settings.js';
10
11
  import { filterTuiSlashCommands, mergeTuiSlashCommands, slashCommandQuery, } from './tui/slash-commands.js';
@@ -12,7 +13,7 @@ import { createComposerEditor, deleteComposerToEnd, deleteComposerToStart, delet
12
13
  import { applyMentionReference, fileReferenceAtCursor, filterTuiMentionEntries, loadTuiFileEntries, } from './tui/file-picker.js';
13
14
  import { editTuiPrompt, openTuiEditorFile, } from './tui/external-editor.js';
14
15
  import { suspendTuiProcess } from './tui/terminal-suspend.js';
15
- import { readTuiClipboard, writeTuiClipboard, } from './tui/clipboard.js';
16
+ import { readTuiClipboard, writeTuiClipboard, writeTuiOsc52Clipboard, } from './tui/clipboard.js';
16
17
  import { composerImageIds, deleteComposerImageBackward, deleteComposerImageForward, insertComposerImageMarker, moveComposerCursorAcrossImages, } from './tui/composer-images.js';
17
18
  import { defaultTuiKeybindings, ensureTuiKeybindingsFile, hasTuiKeybindingPrefix, loadTuiKeybindings, resolveTuiKeybinding, tuiKeyChord, } from './tui/keybindings.js';
18
19
  import { completeTuiWorkspaceDirectory, resolveTuiWorkspaceDirectory, } from './tui/workspace-directories.js';
@@ -185,7 +186,7 @@ function ordinal(value) {
185
186
  return `${value}th`;
186
187
  }
187
188
  }
188
- export function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory = [], signal, onCancel, onTurnChange, onCleanup, axScreenReader = false, allowNewSession = true, resume, display = { version: 'dev', cwd: process.cwd() }, terminalWidth, slashCommands = EMPTY_SLASH_COMMANDS, agents = EMPTY_AGENTS, allowDangerouslySkipPermissions = false, additionalDirectories = [], diffLoader, fileLoader, externalEditor = editTuiPrompt, keybindingsConfigRoot, keybindingsFile = ensureTuiKeybindingsFile, keybindingsLoader = loadTuiKeybindings, keybindingsEditor = openTuiEditorFile, suspendProcess = suspendTuiProcess, clipboardReader = readTuiClipboard, clipboardWriter = writeTuiClipboard, exportWriter = writeConversationExport, permissionRuleStore, workspaceDirectoryResolver = resolveTuiWorkspaceDirectory, workspaceDirectoryCompleter = completeTuiWorkspaceDirectory, }) {
189
+ export function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory = [], signal, onCancel, onTurnChange, onCleanup, onBackground, axScreenReader = false, allowNewSession = true, resume, display = { version: 'dev', cwd: process.cwd() }, terminalWidth, slashCommands = EMPTY_SLASH_COMMANDS, agents = EMPTY_AGENTS, allowDangerouslySkipPermissions = false, additionalDirectories = [], diffLoader, fileLoader, externalEditor = editTuiPrompt, keybindingsConfigRoot, keybindingsFile = ensureTuiKeybindingsFile, keybindingsLoader = loadTuiKeybindings, keybindingsEditor = openTuiEditorFile, suspendProcess = suspendTuiProcess, clipboardReader = readTuiClipboard, clipboardWriter = writeTuiClipboard, sideQuestionClipboardWriter = writeTuiOsc52Clipboard, exportWriter = writeConversationExport, permissionRuleStore, workspaceDirectoryResolver = resolveTuiWorkspaceDirectory, workspaceDirectoryCompleter = completeTuiWorkspaceDirectory, }) {
189
190
  const { exit, suspendTerminal, waitUntilRenderFlush } = useApp();
190
191
  const width = useTerminalWidth(terminalWidth);
191
192
  const keybindingsRoot = useMemo(() => resolve(keybindingsConfigRoot ??
@@ -246,6 +247,12 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
246
247
  const [editorFooterMessage, setEditorFooterMessage] = useState();
247
248
  const [availableSlashCommands, setAvailableSlashCommands] = useState(slashCommands);
248
249
  const [availableAgents, setAvailableAgents] = useState(agents);
250
+ const [btwHistory, setBtwHistory] = useState([]);
251
+ const btwHistoryRef = useRef([]);
252
+ const btwIdRef = useRef(0);
253
+ const btwControllerRef = useRef(null);
254
+ const [btwCopied, setBtwCopied] = useState(false);
255
+ const btwCopiedTimerRef = useRef(null);
249
256
  const [menu, setMenu] = useState(null);
250
257
  const menuRef = useRef(null);
251
258
  const [busy, setBusy] = useState(false);
@@ -427,8 +434,11 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
427
434
  planApprovalRef.current?.resolve(false);
428
435
  if (exitConfirmationTimerRef.current)
429
436
  clearTimeout(exitConfirmationTimerRef.current);
437
+ if (btwCopiedTimerRef.current)
438
+ clearTimeout(btwCopiedTimerRef.current);
430
439
  scheduledWaitRef.current?.abort();
431
440
  turnControllerRef.current?.abort();
441
+ btwControllerRef.current?.abort();
432
442
  const closing = serviceRef.current?.close?.() ?? Promise.resolve();
433
443
  if (onCleanupRef.current)
434
444
  onCleanupRef.current(closing);
@@ -619,6 +629,11 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
619
629
  menuRef.current = next;
620
630
  setMenu(next);
621
631
  };
632
+ const updateBtwHistory = (updater) => {
633
+ const next = updater(btwHistoryRef.current);
634
+ btwHistoryRef.current = next;
635
+ setBtwHistory(next);
636
+ };
622
637
  useEffect(() => {
623
638
  if (menu?.kind !== 'compact-progress')
624
639
  return;
@@ -1015,6 +1030,27 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
1015
1030
  }
1016
1031
  }
1017
1032
  };
1033
+ const withLocalCommands = async (operation) => {
1034
+ if (serviceRef.current)
1035
+ return operation(serviceRef.current);
1036
+ const preferences = runtimePreferencesRef.current;
1037
+ const commands = await factory.createService({
1038
+ eventSink: handleEvent,
1039
+ requireProvider: false,
1040
+ ...(preferences.model === undefined ? {} : { model: preferences.model }),
1041
+ effort: preferences.effort,
1042
+ permissionMode: preferences.permissionMode,
1043
+ additionalDirectories: preferences.additionalDirectories,
1044
+ cwd: runtimeCwdRef.current,
1045
+ ...(signal ? { signal } : {}),
1046
+ });
1047
+ try {
1048
+ return await operation(commands);
1049
+ }
1050
+ finally {
1051
+ await commands.close?.();
1052
+ }
1053
+ };
1018
1054
  const openSession = (nextSessionId) => {
1019
1055
  setSessionId(nextSessionId);
1020
1056
  const loadId = sessionLoadRef.current + 1;
@@ -1288,6 +1324,189 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
1288
1324
  onTurnChange?.(showing);
1289
1325
  void showing.finally(() => onTurnChange?.(null));
1290
1326
  };
1327
+ const showBtwUsage = () => {
1328
+ appendPromptHistory('/btw');
1329
+ const showing = (async () => {
1330
+ try {
1331
+ const activeSessionId = await (await service()).recordBtwUsage?.(sessionId ?? undefined, runtimePreferencesRef.current.permissionMode);
1332
+ if (activeSessionId)
1333
+ setSessionId(activeSessionId);
1334
+ append({ kind: 'user', text: '/btw' });
1335
+ append({ kind: 'local-result', text: 'Usage: /btw <your question>' });
1336
+ }
1337
+ catch (error) {
1338
+ warn(error);
1339
+ }
1340
+ })();
1341
+ onTurnChange?.(showing);
1342
+ void showing.finally(() => onTurnChange?.(null));
1343
+ };
1344
+ const backgroundSession = () => {
1345
+ appendPromptHistory('/background');
1346
+ const backgrounding = (async () => {
1347
+ setBusy(true);
1348
+ try {
1349
+ const hasModelTurn = history.some((item) => item.kind === 'assistant');
1350
+ if (!sessionId || !hasModelTurn) {
1351
+ const activeSessionId = await withLocalCommands(async (commands) => {
1352
+ if (!commands.recordBackgroundUsage) {
1353
+ throw new Error('Background sessions are unavailable.');
1354
+ }
1355
+ return commands.recordBackgroundUsage(sessionId ?? undefined, runtimePreferencesRef.current.permissionMode);
1356
+ });
1357
+ setSessionId(activeSessionId);
1358
+ append({
1359
+ kind: 'local-result',
1360
+ text: 'Nothing to background yet — send a message first.',
1361
+ });
1362
+ return;
1363
+ }
1364
+ if (!onBackground) {
1365
+ throw new Error('Background sessions are unavailable.');
1366
+ }
1367
+ const prompt = [...history]
1368
+ .reverse()
1369
+ .find((item) => item.kind === 'user');
1370
+ const detail = [...history]
1371
+ .reverse()
1372
+ .find((item) => item.kind === 'assistant' || item.kind === 'thinking');
1373
+ const sourceCheckpoint = await withLocalCommands(async (commands) => {
1374
+ if (!commands.recordBackgroundLaunch) {
1375
+ throw new Error('Background sessions are unavailable.');
1376
+ }
1377
+ return commands.recordBackgroundLaunch(sessionId);
1378
+ });
1379
+ setStatus('Backgrounding…');
1380
+ append({ kind: 'notice', text: 'Backgrounding…' });
1381
+ await waitUntilRenderFlush();
1382
+ await onBackground({
1383
+ sourceSessionId: sessionId,
1384
+ sourceCheckpoint,
1385
+ prompt: prompt && 'text' in prompt
1386
+ ? prompt.text
1387
+ : 'empty-background-command',
1388
+ detail: detail && 'text' in detail ? detail.text : '',
1389
+ cwd: runtimeCwdRef.current,
1390
+ });
1391
+ await retireService();
1392
+ exit();
1393
+ }
1394
+ catch (error) {
1395
+ warn(error);
1396
+ }
1397
+ finally {
1398
+ if (componentMountedRef.current) {
1399
+ setBusy(false);
1400
+ setStatus('ready');
1401
+ }
1402
+ }
1403
+ })();
1404
+ onTurnChange?.(backgrounding);
1405
+ void backgrounding.finally(() => onTurnChange?.(null));
1406
+ };
1407
+ const askSideQuestion = (question) => {
1408
+ const id = btwIdRef.current + 1;
1409
+ btwIdRef.current = id;
1410
+ appendPromptHistory(`/btw ${question}`);
1411
+ const entry = {
1412
+ id,
1413
+ question,
1414
+ answer: '',
1415
+ status: 'answering',
1416
+ };
1417
+ updateBtwHistory((entries) => [...entries, entry]);
1418
+ updateMenu({
1419
+ kind: 'btw',
1420
+ selectedIndex: btwHistoryRef.current.length - 1,
1421
+ scrollOffset: 0,
1422
+ });
1423
+ setBtwCopied(false);
1424
+ const controller = new AbortController();
1425
+ btwControllerRef.current?.abort();
1426
+ btwControllerRef.current = controller;
1427
+ const sideSignal = signal
1428
+ ? AbortSignal.any([signal, controller.signal])
1429
+ : controller.signal;
1430
+ const answering = (async () => {
1431
+ try {
1432
+ const commands = await service();
1433
+ if (!commands.answerSideQuestion) {
1434
+ throw new Error('Side questions are unavailable.');
1435
+ }
1436
+ const result = await commands.answerSideQuestion(sessionId ?? undefined, question, sideSignal, (delta) => updateBtwHistory((entries) => entries.map((item) => item.id === id
1437
+ ? { ...item, answer: item.answer + delta }
1438
+ : item)), runtimePreferencesRef.current.permissionMode);
1439
+ if (result.sessionId)
1440
+ setSessionId(result.sessionId);
1441
+ updateBtwHistory((entries) => entries.map((item) => item.id === id ? { ...item, status: 'complete' } : item));
1442
+ if (sideSignal.aborted)
1443
+ throw new AgentRunCancelledError();
1444
+ setUsage((current) => ({
1445
+ inputTokens: (current?.inputTokens ?? 0) + result.usage.inputTokens,
1446
+ outputTokens: (current?.outputTokens ?? 0) + result.usage.outputTokens,
1447
+ cacheReadInputTokens: (current?.cacheReadInputTokens ?? 0) +
1448
+ (result.usage.cacheReadInputTokens ?? 0),
1449
+ cacheCreationInputTokens: (current?.cacheCreationInputTokens ?? 0) +
1450
+ (result.usage.cacheCreationInputTokens ?? 0),
1451
+ }));
1452
+ if (result.costUsd !== undefined) {
1453
+ const sideCostUsd = result.costUsd;
1454
+ setCostUsd((current) => (current ?? 0) + sideCostUsd);
1455
+ }
1456
+ }
1457
+ catch (error) {
1458
+ updateBtwHistory((entries) => entries.map((item) => item.id === id
1459
+ ? {
1460
+ ...item,
1461
+ status: 'error',
1462
+ error: sideSignal.aborted
1463
+ ? 'Cancelled'
1464
+ : error instanceof Error
1465
+ ? error.message
1466
+ : String(error),
1467
+ }
1468
+ : item));
1469
+ }
1470
+ finally {
1471
+ if (btwControllerRef.current === controller) {
1472
+ btwControllerRef.current = null;
1473
+ }
1474
+ }
1475
+ })();
1476
+ onTurnChange?.(answering);
1477
+ void answering.finally(() => onTurnChange?.(null));
1478
+ };
1479
+ const forkSideQuestion = (entry) => {
1480
+ updateBtwHistory((entries) => entries.map((item) => item.id === entry.id ? { ...item, status: 'forking' } : item));
1481
+ const forking = (async () => {
1482
+ try {
1483
+ if (!sessionId) {
1484
+ throw new Error('Start a conversation before forking a side question.');
1485
+ }
1486
+ const commands = await service();
1487
+ if (!commands.forkSideQuestion) {
1488
+ throw new Error('Side-question forking is unavailable.');
1489
+ }
1490
+ const result = await commands.forkSideQuestion(sessionId, entry.question);
1491
+ updateMenu(null);
1492
+ append({
1493
+ kind: 'local-result',
1494
+ text: `⑂ forked ${result.name} (${result.agentId.slice(-4)})`,
1495
+ });
1496
+ }
1497
+ catch (error) {
1498
+ updateBtwHistory((entries) => entries.map((item) => item.id === entry.id
1499
+ ? {
1500
+ ...item,
1501
+ status: 'error',
1502
+ error: error instanceof Error ? error.message : String(error),
1503
+ }
1504
+ : item));
1505
+ }
1506
+ })();
1507
+ onTurnChange?.(forking);
1508
+ void forking.finally(() => onTurnChange?.(null));
1509
+ };
1291
1510
  const renameSession = (requestedName) => {
1292
1511
  const renaming = (async () => {
1293
1512
  if (!sessionId) {
@@ -2019,6 +2238,69 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
2019
2238
  }
2020
2239
  const activeMenu = menuRef.current;
2021
2240
  if (activeMenu) {
2241
+ if (activeMenu.kind === 'btw') {
2242
+ const selected = btwHistoryRef.current[activeMenu.selectedIndex];
2243
+ if (key.escape || value === '\u001B') {
2244
+ btwControllerRef.current?.abort();
2245
+ btwControllerRef.current = null;
2246
+ updateMenu(null);
2247
+ return;
2248
+ }
2249
+ if (key.leftArrow || key.rightArrow) {
2250
+ updateMenu({
2251
+ ...activeMenu,
2252
+ selectedIndex: Math.max(0, Math.min(btwHistoryRef.current.length - 1, activeMenu.selectedIndex + (key.leftArrow ? -1 : 1))),
2253
+ scrollOffset: 0,
2254
+ });
2255
+ setBtwCopied(false);
2256
+ return;
2257
+ }
2258
+ if (key.upArrow || key.downArrow) {
2259
+ const maxOffset = Math.max(0, (selected?.answer.split('\n').length ?? 0) - 16);
2260
+ updateMenu({
2261
+ ...activeMenu,
2262
+ scrollOffset: Math.max(0, Math.min(maxOffset, activeMenu.scrollOffset + (key.upArrow ? -1 : 1))),
2263
+ });
2264
+ return;
2265
+ }
2266
+ if (lower === 'x' && btwHistoryRef.current.length > 1 && selected) {
2267
+ updateBtwHistory(() => [selected]);
2268
+ updateMenu({ kind: 'btw', selectedIndex: 0, scrollOffset: 0 });
2269
+ setBtwCopied(false);
2270
+ return;
2271
+ }
2272
+ if (lower === 'c' && selected?.status === 'complete') {
2273
+ const copying = sideQuestionClipboardWriter(selected.answer).then(() => {
2274
+ if (!componentMountedRef.current)
2275
+ return;
2276
+ setBtwCopied(true);
2277
+ if (btwCopiedTimerRef.current) {
2278
+ clearTimeout(btwCopiedTimerRef.current);
2279
+ }
2280
+ btwCopiedTimerRef.current = setTimeout(() => {
2281
+ if (componentMountedRef.current)
2282
+ setBtwCopied(false);
2283
+ btwCopiedTimerRef.current = null;
2284
+ }, 1500);
2285
+ btwCopiedTimerRef.current.unref?.();
2286
+ }, (error) => updateBtwHistory((entries) => entries.map((item) => item.id === selected.id
2287
+ ? {
2288
+ ...item,
2289
+ status: 'error',
2290
+ error: error instanceof Error
2291
+ ? error.message
2292
+ : String(error),
2293
+ }
2294
+ : item)));
2295
+ onTurnChange?.(copying);
2296
+ void copying.finally(() => onTurnChange?.(null));
2297
+ return;
2298
+ }
2299
+ if (lower === 'f' && selected?.status === 'complete') {
2300
+ forkSideQuestion(selected);
2301
+ }
2302
+ return;
2303
+ }
2022
2304
  if (activeMenu.kind === 'help') {
2023
2305
  if (key.escape) {
2024
2306
  updateMenu(null);
@@ -2790,6 +3072,7 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
2790
3072
  const copyCommand = /^\/copy(?:\s+(\d+))?$/u.exec(prompt);
2791
3073
  const renameCommand = /^\/rename(?:\s+(.+))?$/u.exec(prompt);
2792
3074
  const cdCommand = /^\/cd(?:\s+(.+))?$/u.exec(prompt);
3075
+ const btwCommand = /^\/btw(?:\s+([\s\S]+))?$/u.exec(prompt);
2793
3076
  if (prompt === '/exit') {
2794
3077
  exit();
2795
3078
  }
@@ -2830,6 +3113,16 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
2830
3113
  else if (prompt === '/add-dir') {
2831
3114
  openWorkspaceDirectoryInput();
2832
3115
  }
3116
+ else if (btwCommand) {
3117
+ const sideQuestion = btwCommand[1]?.trim();
3118
+ if (sideQuestion)
3119
+ askSideQuestion(sideQuestion);
3120
+ else
3121
+ showBtwUsage();
3122
+ }
3123
+ else if (prompt === '/background') {
3124
+ backgroundSession();
3125
+ }
2833
3126
  else if (cdCommand) {
2834
3127
  append({ kind: 'user', text: prompt });
2835
3128
  const requestedCwd = cdCommand[1]?.trim();
@@ -3017,7 +3310,7 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
3017
3310
  ? `Retry interrupted ${permission.call.name}?`
3018
3311
  : `Allow ${permission.call.name}?`, screenReader: axScreenReader, children: [_jsx(Text, { bold: true, children: describeTool(permission.call, sensitiveValues) }), _jsx(Text, { children: "\u276F 1. Yes" }), _jsx(Text, { children: " 2. No" }), _jsx(Text, { dimColor: true, children: "Enter/Esc declines \u00B7 y/n quick response" })] })) : planApproval ? (_jsxs(DialogFrame, { title: "Approve this plan and begin implementation?", screenReader: axScreenReader, children: [_jsx(Text, { dimColor: true, children: planApproval.request.planPath }), planApproval.request.plan ? (_jsx(Box, { marginY: 1, children: _jsx(Text, { children: planApproval.request.plan }) })) : null, _jsx(Text, { children: "\u276F 1. Yes, implement the plan" }), _jsx(Text, { children: " 2. No, keep planning" })] })) : question ? (_jsxs(DialogFrame, { title: `${question.questions[question.index]?.header}: ${question.questions[question.index]?.question}`, screenReader: axScreenReader, children: [question.questions[question.index]?.options.map((option, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [index === 0 ? '❯ ' : ' ', index + 1, ". ", option.label, " \u2014 ", option.description] }), option.preview ? (_jsx(Text, { dimColor: true, children: option.preview })) : null] }, `${index}-${option.label}`))), _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: question.questions[question.index]?.multiSelect
3019
3312
  ? 'Enter comma-separated option numbers or custom text · Esc cancels'
3020
- : 'Enter one option number or custom text · Esc cancels' })] })) : elicitation ? (_jsxs(DialogFrame, { title: `MCP elicitation (${elicitation.request.serverName})`, screenReader: axScreenReader, children: [_jsx(Text, { children: elicitation.request.message }), elicitation.request.url ? (_jsx(Text, { children: elicitation.request.url })) : null, elicitation.request.requestedSchema ? (_jsx(Text, { dimColor: true, children: JSON.stringify(elicitation.request.requestedSchema) })) : null, _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: "Enter JSON object to accept \u00B7 Esc to cancel" })] })) : menu?.kind === 'model-input' ? (_jsxs(DialogFrame, { title: "Enter model ID", screenReader: axScreenReader, children: [_jsx(Text, { dimColor: true, children: "Enter a model ID supported by the configured provider." }), _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: "Enter confirms \u00B7 Esc cancels" })] })) : menu?.kind === 'export-filename' ? (_jsxs(DialogFrame, { title: "Enter filename:", screenReader: axScreenReader, children: [_jsxs(Text, { children: ["> ", input] }), _jsx(Text, { dimColor: true, children: "Enter to save \u00B7 Esc to go back" })] })) : menu?.kind === 'compact-progress' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "\u273B Compacting conversation\u2026" }), _jsxs(Text, { children: ['▰'.repeat(Math.floor(compactProgress / 2)), '▱'.repeat(50 - Math.floor(compactProgress / 2)), ' ', compactProgress, "%"] })] })) : menu?.kind === 'rewind' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: " Rewind" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', "Restore the code and/or conversation to the point before\u2026"] }), _jsx(Text, { children: " " }), (() => {
3313
+ : 'Enter one option number or custom text · Esc cancels' })] })) : elicitation ? (_jsxs(DialogFrame, { title: `MCP elicitation (${elicitation.request.serverName})`, screenReader: axScreenReader, children: [_jsx(Text, { children: elicitation.request.message }), elicitation.request.url ? (_jsx(Text, { children: elicitation.request.url })) : null, elicitation.request.requestedSchema ? (_jsx(Text, { dimColor: true, children: JSON.stringify(elicitation.request.requestedSchema) })) : null, _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: "Enter JSON object to accept \u00B7 Esc to cancel" })] })) : menu?.kind === 'model-input' ? (_jsxs(DialogFrame, { title: "Enter model ID", screenReader: axScreenReader, children: [_jsx(Text, { dimColor: true, children: "Enter a model ID supported by the configured provider." }), _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: "Enter confirms \u00B7 Esc cancels" })] })) : menu?.kind === 'export-filename' ? (_jsxs(DialogFrame, { title: "Enter filename:", screenReader: axScreenReader, children: [_jsxs(Text, { children: ["> ", input] }), _jsx(Text, { dimColor: true, children: "Enter to save \u00B7 Esc to go back" })] })) : menu?.kind === 'compact-progress' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "\u273B Compacting conversation\u2026" }), _jsxs(Text, { children: ['▰'.repeat(Math.floor(compactProgress / 2)), '▱'.repeat(50 - Math.floor(compactProgress / 2)), ' ', compactProgress, "%"] })] })) : menu?.kind === 'btw' ? (_jsx(BtwPanel, { entries: btwHistory, selectedIndex: menu.selectedIndex, scrollOffset: menu.scrollOffset, copied: btwCopied, width: width, screenReader: axScreenReader })) : menu?.kind === 'rewind' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: " Rewind" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', "Restore the code and/or conversation to the point before\u2026"] }), _jsx(Text, { children: " " }), (() => {
3021
3314
  const window = rewindPointWindow(menu.points, menu.selectedIndex);
3022
3315
  return (_jsxs(_Fragment, { children: [window.start > 0 ? (_jsxs(Text, { dimColor: true, children: [" \u2191 ", window.start, " more above"] })) : null, menu.points
3023
3316
  .slice(window.start, window.end)
@@ -3133,13 +3426,24 @@ export async function runInteractive(options) {
3133
3426
  await listing.close?.();
3134
3427
  let activeTurn = null;
3135
3428
  let cleanup = null;
3429
+ let backgrounded;
3136
3430
  const instance = render(_jsx(InteractiveApp, { factory: options.factory, initialSessions: initialSessions, slashCommands: initialSlashCommands, agents: initialAgents, initialHistory: initialHistory, ...(options.initialPrompt === undefined
3137
3431
  ? {}
3138
3432
  : { initialPrompt: options.initialPrompt }), signal: signal, onCancel: () => controller.abort(), onTurnChange: (turn) => {
3139
3433
  activeTurn = turn;
3140
3434
  }, onCleanup: (closing) => {
3141
3435
  cleanup = closing;
3142
- }, allowNewSession: !options.requireSession, ...(options.additionalDirectories === undefined
3436
+ }, ...(options.onBackground === undefined
3437
+ ? {}
3438
+ : {
3439
+ onBackground: async (request) => {
3440
+ const result = await options.onBackground?.(request);
3441
+ if (!result)
3442
+ throw new Error('Background launch returned no job');
3443
+ backgrounded = result;
3444
+ return result;
3445
+ },
3446
+ }), allowNewSession: !options.requireSession, ...(options.additionalDirectories === undefined
3143
3447
  ? {}
3144
3448
  : { additionalDirectories: options.additionalDirectories }), ...(resume === undefined ? {} : { resume }), ...(options.display === undefined ? {} : { display: options.display }), ...(options.axScreenReader ? { axScreenReader: true } : {}), ...(options.allowDangerouslySkipPermissions
3145
3449
  ? { allowDangerouslySkipPermissions: true }
@@ -3153,6 +3457,8 @@ export async function runInteractive(options) {
3153
3457
  await activeTurn;
3154
3458
  if (cleanup)
3155
3459
  await cleanup;
3460
+ if (backgrounded)
3461
+ options.onBackgrounded?.(backgrounded);
3156
3462
  return signal.aborted ? 130 : 0;
3157
3463
  }
3158
3464
  //# sourceMappingURL=interactive.js.map