praxis-agent 0.35.0 → 0.36.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/README.md +5 -1
- package/dist/application/background-agent-manager.d.ts +16 -6
- package/dist/application/background-agent-manager.js +139 -97
- package/dist/application/context-engine.d.ts +56 -0
- package/dist/application/context-engine.js +129 -0
- package/dist/application/session-service.d.ts +8 -4
- package/dist/application/session-service.js +528 -434
- package/dist/application/subagent-service.js +358 -177
- package/dist/application/top-level-agent-manager.d.ts +1 -0
- package/dist/application/top-level-agent-manager.js +1025 -403
- package/dist/application/transcript-projection.d.ts +33 -0
- package/dist/application/transcript-projection.js +110 -0
- package/dist/application/turn-lifecycle.d.ts +2 -0
- package/dist/application/turn-memory-coordinator.d.ts +43 -0
- package/dist/application/turn-memory-coordinator.js +98 -0
- package/dist/cli/agents-dashboard.js +10 -5
- package/dist/cli/interactive.js +264 -204
- package/dist/cli/tui/claude-style.js +154 -130
- package/dist/cli/tui/task-panel.js +10 -1
- package/dist/cli/tui/theme.d.ts +46 -3
- package/dist/cli/tui/theme.js +414 -56
- package/dist/cli/tui/tool-permission.js +9 -5
- package/dist/cli/tui/tui-interaction-router.d.ts +78 -0
- package/dist/cli/tui/tui-interaction-router.js +127 -0
- package/dist/cli-runtime.d.ts +2 -2
- package/dist/core/agent-orchestration.d.ts +31 -0
- package/dist/core/agent-orchestration.js +235 -0
- package/dist/core/runtime.d.ts +5 -0
- package/dist/core/runtime.js +15 -1
- package/dist/persistence/claude-job-store.d.ts +58 -0
- package/dist/persistence/claude-job-store.js +483 -1
- package/dist/persistence/native-transcript-reader.d.ts +53 -0
- package/dist/persistence/native-transcript-reader.js +283 -0
- package/dist/persistence/subagent-lifecycle-store.d.ts +41 -8
- package/dist/persistence/subagent-lifecycle-store.js +373 -146
- package/dist/platform/exclusive-file-lease.d.ts +3 -0
- package/dist/platform/exclusive-file-lease.js +3 -0
- package/package.json +1 -1
package/dist/cli/interactive.js
CHANGED
|
@@ -26,18 +26,19 @@ import { agentColorMessage, parseAgentColorInput, } from '../compatibility/claud
|
|
|
26
26
|
import { filterTuiSlashCommands, mergeTuiSlashCommands, slashCommandQuery, } from './tui/slash-commands.js';
|
|
27
27
|
import { runDoctor, } from '../maintenance/doctor.js';
|
|
28
28
|
import { canonicalClaudeCostModelName, formatCostSummary, } from './tui/cost-summary.js';
|
|
29
|
-
import { createComposerEditor, deleteComposerBackward, deleteComposerForward,
|
|
29
|
+
import { createComposerEditor, deleteComposerBackward, deleteComposerForward, insertComposerText, moveComposerCursor, } from './tui/composer-editor.js';
|
|
30
30
|
import { routeComposerKey, } from './tui/composer-key-router.js';
|
|
31
|
+
import { routeTuiInteraction, } from './tui/tui-interaction-router.js';
|
|
31
32
|
import { applyMentionReference, fileReferenceAtCursor, filterTuiMentionEntries, loadTuiFileEntries, } from './tui/file-picker.js';
|
|
32
33
|
import { editTuiPrompt, openTuiEditorFile, } from './tui/external-editor.js';
|
|
33
34
|
import { suspendTuiProcess } from './tui/terminal-suspend.js';
|
|
34
35
|
import { readTuiClipboard, writeTuiClipboard, writeTuiOsc52Clipboard, } from './tui/clipboard.js';
|
|
35
|
-
import { composerImageIds,
|
|
36
|
+
import { composerImageIds, insertComposerImageMarker, } from './tui/composer-images.js';
|
|
36
37
|
import { defaultTuiKeybindings, ensureTuiKeybindingsFile, hasTuiKeybindingPrefix, loadTuiKeybindings, resolveTuiKeybinding, tuiKeyChord, } from './tui/keybindings.js';
|
|
37
38
|
import { completeTuiWorkspaceDirectory, resolveTuiWorkspaceDirectory, } from './tui/workspace-directories.js';
|
|
38
39
|
import { conversationExportPath, conversationExportText, defaultConversationExportFilename, writeConversationExport, } from './tui/conversation-export.js';
|
|
39
40
|
import { loadTuiThemeSettings, saveTuiThemeSettings, themeSettingsWithCustomTheme, } from './tui/theme-settings.js';
|
|
40
|
-
import { DEFAULT_TUI_THEME_SETTINGS, TUI_THEMES, TuiThemeProvider,
|
|
41
|
+
import { DEFAULT_TUI_THEME_SETTINGS, TUI_THEMES, TuiThemeProvider, useTuiTheme, } from './tui/theme.js';
|
|
41
42
|
import { CUSTOM_THEME_TOKENS, createTuiCustomTheme, deleteTuiCustomTheme, loadTuiCustomThemes, updateTuiCustomTheme, } from './tui/custom-themes.js';
|
|
42
43
|
import { setupTuiTerminal, terminalSetupTuiSlashCommand, } from './tui/terminal-setup.js';
|
|
43
44
|
import { commitElicitationText, createTuiElicitationForm, elicitationFormIsValid, elicitationTextValue, expandElicitationOptions, focusedElicitationField, McpElicitationForm, McpElicitationUrl, moveElicitationFocus, moveElicitationOption, selectElicitationOption, toggleElicitationBoolean, typeaheadElicitationOption, unsetElicitationField, validateTuiElicitationForm, } from './tui/mcp-elicitation.js';
|
|
@@ -111,11 +112,6 @@ const ZERO_COST_SUMMARY = {
|
|
|
111
112
|
hasUnknownModelCost: false,
|
|
112
113
|
modelUsage: [],
|
|
113
114
|
};
|
|
114
|
-
function selectionPrefix(selected, screenReader) {
|
|
115
|
-
if (selected)
|
|
116
|
-
return screenReader ? 'Selected: ' : '❯ ';
|
|
117
|
-
return screenReader ? '' : ' ';
|
|
118
|
-
}
|
|
119
115
|
function rewindActions(point) {
|
|
120
116
|
const shared = [
|
|
121
117
|
{ action: 'summarize-from', label: 'Summarize from here' },
|
|
@@ -266,6 +262,25 @@ const HIDDEN_TUI_SLASH_COMMANDS = new Set([
|
|
|
266
262
|
'update',
|
|
267
263
|
'usage',
|
|
268
264
|
]);
|
|
265
|
+
function RewindWarning() {
|
|
266
|
+
const theme = useTuiTheme();
|
|
267
|
+
return (_jsx(Text, { ...theme.text.warning, children: "\u26A0 Rewinding does not affect files edited manually or via bash." }));
|
|
268
|
+
}
|
|
269
|
+
function ExitWarning() {
|
|
270
|
+
const theme = useTuiTheme();
|
|
271
|
+
return _jsx(Text, { ...theme.text.warning, children: "Press Ctrl-C again to exit" });
|
|
272
|
+
}
|
|
273
|
+
function DecisionOption({ selected, screenReader, children, selectedPrefix = '❯ ', unselectedPrefix = ' ', }) {
|
|
274
|
+
const theme = useTuiTheme();
|
|
275
|
+
const accessible = screenReader || theme.noColor;
|
|
276
|
+
return (_jsxs(Text, { ...(selected ? theme.text.selectedRow : {}), children: [selected
|
|
277
|
+
? accessible
|
|
278
|
+
? 'Selected: '
|
|
279
|
+
: selectedPrefix
|
|
280
|
+
: accessible
|
|
281
|
+
? ''
|
|
282
|
+
: unselectedPrefix, children] }));
|
|
283
|
+
}
|
|
269
284
|
export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: suppliedConfigRoot, statePath: suppliedStatePath, factory, initialSessions, initialPrompt, initialHistory = [], initialSessionColor, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader = false, allowNewSession = true, resume, display = { version: 'dev', cwd: process.cwd() }, terminalWidth, slashCommands = EMPTY_SLASH_COMMANDS, agents = EMPTY_AGENTS, allowDangerouslySkipPermissions = false, additionalDirectories = [], diffLoader, doctorLoader, fileLoader, externalEditor = editTuiPrompt, keybindingsConfigRoot, keybindingsFile = ensureTuiKeybindingsFile, keybindingsLoader = loadTuiKeybindings, keybindingsEditor = openTuiEditorFile, memoryFilesLoader, memoryEditor = openTuiEditorFile, memoryFolderOpener = openTuiMemoryFolder, suspendProcess = suspendTuiProcess, clipboardReader = readTuiClipboard, clipboardWriter = writeTuiClipboard, sideQuestionClipboardWriter = writeTuiOsc52Clipboard, exportWriter = writeConversationExport, permissionRuleStore, sandboxStore: suppliedSandboxStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver = resolveTuiWorkspaceDirectory, workspaceDirectoryCompleter = completeTuiWorkspaceDirectory, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, notificationDelayMs = 6_000, elicitationUrlOpener = openTuiUrl, releaseNotesLoader = (configRoot) => loadClaudeReleaseNotes({ configRoot }), settingSources, }) {
|
|
270
285
|
const { exit, suspendTerminal, waitUntilRenderFlush } = useApp();
|
|
271
286
|
const width = useTerminalWidth(terminalWidth);
|
|
@@ -345,9 +360,6 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
345
360
|
runtimeSettingsRef.current = runtimeSettings;
|
|
346
361
|
runtimeGitignoreRef.current = runtimeSettings.gitignore;
|
|
347
362
|
const [vimInsertMode, setVimInsertMode] = useState(true);
|
|
348
|
-
const activePalette = tuiPalette(TUI_THEMES.includes(themeSettings.theme)
|
|
349
|
-
? themeSettings.theme
|
|
350
|
-
: 'dark', themeSettings.syntaxHighlightingDisabled, process.env, themeSettings.customTheme);
|
|
351
363
|
const choices = useMemo(() => allowNewSession ? [null, ...initialSessions] : initialSessions, [allowNewSession, initialSessions]);
|
|
352
364
|
const [pickerIncludesNewSession, setPickerIncludesNewSession] = useState(allowNewSession);
|
|
353
365
|
const pickerIncludesNewSessionRef = useRef(allowNewSession);
|
|
@@ -449,7 +461,12 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
449
461
|
const [contextWindowTokens, setContextWindowTokens] = useState(display.contextWindowTokens);
|
|
450
462
|
const [history, setHistory] = useState([...initialHistory]);
|
|
451
463
|
const activeAttemptThinkingItemsRef = useRef([]);
|
|
452
|
-
const [transcriptScrollOffset,
|
|
464
|
+
const [transcriptScrollOffset, setTranscriptScrollOffsetState] = useState(0);
|
|
465
|
+
const transcriptScrollOffsetRef = useRef(0);
|
|
466
|
+
const setTranscriptScrollOffset = (offset) => {
|
|
467
|
+
transcriptScrollOffsetRef.current = offset;
|
|
468
|
+
setTranscriptScrollOffsetState(offset);
|
|
469
|
+
};
|
|
453
470
|
// The pure TUI view model classifies the session identity (fresh/resumed/
|
|
454
471
|
// started) and projects the rendered transcript. Startup diagnostics are
|
|
455
472
|
// useful before the first prompt, but they are not conversation history and
|
|
@@ -1152,25 +1169,6 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1152
1169
|
exitConfirmationTimerRef.current = null;
|
|
1153
1170
|
setExitConfirmation(false);
|
|
1154
1171
|
};
|
|
1155
|
-
const armExitConfirmation = () => {
|
|
1156
|
-
if (exitConfirmation) {
|
|
1157
|
-
permissionRef.current?.resolve(false);
|
|
1158
|
-
elicitationRef.current?.resolve({ action: 'cancel' });
|
|
1159
|
-
questionRef.current?.resolve(null);
|
|
1160
|
-
planApprovalRef.current?.resolve({ behavior: 'deny' });
|
|
1161
|
-
onCancel?.();
|
|
1162
|
-
exit();
|
|
1163
|
-
return;
|
|
1164
|
-
}
|
|
1165
|
-
clearComposerInput();
|
|
1166
|
-
setExitConfirmation(true);
|
|
1167
|
-
if (exitConfirmationTimerRef.current)
|
|
1168
|
-
clearTimeout(exitConfirmationTimerRef.current);
|
|
1169
|
-
exitConfirmationTimerRef.current = setTimeout(() => {
|
|
1170
|
-
exitConfirmationTimerRef.current = null;
|
|
1171
|
-
setExitConfirmation(false);
|
|
1172
|
-
}, 1_500);
|
|
1173
|
-
};
|
|
1174
1172
|
useEffect(() => {
|
|
1175
1173
|
setCommandSelection((current) => Math.min(current, Math.max(0, matchingSlashCommands.length - 1)));
|
|
1176
1174
|
}, [matchingSlashCommands.length]);
|
|
@@ -2872,74 +2870,150 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
2872
2870
|
const codePoint = character.codePointAt(0) ?? 0;
|
|
2873
2871
|
return codePoint >= 32 && codePoint !== 127;
|
|
2874
2872
|
});
|
|
2873
|
+
const composerKey = {
|
|
2874
|
+
value,
|
|
2875
|
+
left: key.leftArrow,
|
|
2876
|
+
right: key.rightArrow,
|
|
2877
|
+
backspace: key.backspace,
|
|
2878
|
+
delete: key.delete,
|
|
2879
|
+
ctrl: key.ctrl,
|
|
2880
|
+
meta: key.meta,
|
|
2881
|
+
escape: key.escape || value === '\u001B',
|
|
2882
|
+
};
|
|
2875
2883
|
const editor = () => createComposerEditor(inputRef.current, inputCursorRef.current);
|
|
2876
2884
|
const editComposer = () => {
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
: moveComposerCursorAcrossImages(editor(), -1));
|
|
2881
|
-
return true;
|
|
2882
|
-
}
|
|
2883
|
-
if (key.rightArrow) {
|
|
2884
|
-
updateComposerEditor(key.meta
|
|
2885
|
-
? moveComposerCursorByWord(editor(), 'forward')
|
|
2886
|
-
: moveComposerCursorAcrossImages(editor(), 1));
|
|
2887
|
-
return true;
|
|
2888
|
-
}
|
|
2889
|
-
if (controlKey('a')) {
|
|
2890
|
-
updateComposerEditor(createComposerEditor(inputRef.current, 0));
|
|
2891
|
-
return true;
|
|
2892
|
-
}
|
|
2893
|
-
if (controlKey('e')) {
|
|
2894
|
-
updateComposerEditor(createComposerEditor(inputRef.current));
|
|
2895
|
-
return true;
|
|
2896
|
-
}
|
|
2897
|
-
if (controlKey('b')) {
|
|
2898
|
-
updateComposerEditor(moveComposerCursorAcrossImages(editor(), -1));
|
|
2899
|
-
return true;
|
|
2900
|
-
}
|
|
2901
|
-
if (controlKey('f')) {
|
|
2902
|
-
updateComposerEditor(moveComposerCursorAcrossImages(editor(), 1));
|
|
2903
|
-
return true;
|
|
2904
|
-
}
|
|
2905
|
-
if (controlKey('w')) {
|
|
2906
|
-
updateComposerEditor(deleteComposerWordBackward(editor()));
|
|
2907
|
-
return true;
|
|
2908
|
-
}
|
|
2909
|
-
if (controlKey('u')) {
|
|
2910
|
-
updateComposerEditor(deleteComposerToStart(editor()));
|
|
2911
|
-
return true;
|
|
2912
|
-
}
|
|
2913
|
-
if (controlKey('k')) {
|
|
2914
|
-
updateComposerEditor(deleteComposerToEnd(editor()));
|
|
2915
|
-
return true;
|
|
2916
|
-
}
|
|
2917
|
-
if (key.backspace) {
|
|
2918
|
-
updateComposerEditor(deleteComposerImageBackward(editor()));
|
|
2885
|
+
const transition = routeComposerKey(editor(), composerKey);
|
|
2886
|
+
if (transition.kind === 'edit') {
|
|
2887
|
+
updateComposerEditor(transition.editor);
|
|
2919
2888
|
return true;
|
|
2920
2889
|
}
|
|
2921
|
-
if (
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
}
|
|
2925
|
-
if (!key.ctrl && !key.meta && value && printable) {
|
|
2926
|
-
updateComposerEditor(insertComposerText(editor(), value));
|
|
2927
|
-
return true;
|
|
2928
|
-
}
|
|
2929
|
-
return false;
|
|
2890
|
+
if (transition.kind === 'cancel')
|
|
2891
|
+
clearComposerInput();
|
|
2892
|
+
return transition.kind === 'cancel';
|
|
2930
2893
|
};
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2894
|
+
const interactionComposer = () => ({
|
|
2895
|
+
mode: runtimeSettingsRef.current.editor === 'vim'
|
|
2896
|
+
? vimInsertMode
|
|
2897
|
+
? 'vim-insert'
|
|
2898
|
+
: 'vim-normal'
|
|
2899
|
+
: 'readline',
|
|
2900
|
+
editor: editor(),
|
|
2901
|
+
lastCancelAtMs: lastEscapeAtRef.current,
|
|
2902
|
+
});
|
|
2903
|
+
const applyInteractionEffects = (effects) => {
|
|
2904
|
+
for (const effect of effects) {
|
|
2905
|
+
if (effect.kind === 'request-process-suspension') {
|
|
2906
|
+
processSuspendRequestedRef.current = true;
|
|
2907
|
+
setProcessSuspendRequested(true);
|
|
2908
|
+
}
|
|
2909
|
+
else if (effect.kind === 'set-transcript-scroll-offset') {
|
|
2910
|
+
setTranscriptScrollOffset(effect.offset);
|
|
2911
|
+
}
|
|
2912
|
+
else if (effect.kind === 'interrupt-turn') {
|
|
2913
|
+
turnControllerRef.current?.abort();
|
|
2914
|
+
}
|
|
2915
|
+
else if (effect.kind === 'arm-exit-confirmation') {
|
|
2916
|
+
setExitConfirmation(true);
|
|
2917
|
+
if (exitConfirmationTimerRef.current)
|
|
2918
|
+
clearTimeout(exitConfirmationTimerRef.current);
|
|
2919
|
+
exitConfirmationTimerRef.current = setTimeout(() => {
|
|
2920
|
+
exitConfirmationTimerRef.current = null;
|
|
2921
|
+
setExitConfirmation(false);
|
|
2922
|
+
}, 1_500);
|
|
2923
|
+
}
|
|
2924
|
+
else if (effect.kind === 'dismiss-exit-confirmation') {
|
|
2925
|
+
dismissExitConfirmation();
|
|
2926
|
+
}
|
|
2927
|
+
else if (effect.kind === 'exit-application') {
|
|
2928
|
+
permissionRef.current?.resolve(false);
|
|
2929
|
+
elicitationRef.current?.resolve({ action: 'cancel' });
|
|
2930
|
+
questionRef.current?.resolve(null);
|
|
2931
|
+
planApprovalRef.current?.resolve({ behavior: 'deny' });
|
|
2932
|
+
onCancel?.();
|
|
2933
|
+
exit();
|
|
2934
|
+
}
|
|
2935
|
+
else if (effect.kind === 'set-vim-insert-mode') {
|
|
2936
|
+
setVimInsertMode(effect.insert);
|
|
2937
|
+
}
|
|
2938
|
+
else if (effect.kind === 'set-composer-editor') {
|
|
2939
|
+
updateComposerEditor(effect.editor);
|
|
2940
|
+
}
|
|
2941
|
+
else if (effect.kind === 'clear-composer') {
|
|
2942
|
+
clearComposerInput();
|
|
2943
|
+
}
|
|
2944
|
+
else if (effect.kind === 'record-composer-cancel') {
|
|
2945
|
+
lastEscapeAtRef.current = effect.timestamp;
|
|
2946
|
+
}
|
|
2947
|
+
else if (effect.kind === 'cancel-tui-layer') {
|
|
2948
|
+
switch (effect.target) {
|
|
2949
|
+
case 'permission':
|
|
2950
|
+
permissionRef.current?.resolve(false);
|
|
2951
|
+
break;
|
|
2952
|
+
case 'plan-approval':
|
|
2953
|
+
planApprovalRef.current?.resolve({ behavior: 'deny' });
|
|
2954
|
+
break;
|
|
2955
|
+
case 'question':
|
|
2956
|
+
questionRef.current?.resolve(null);
|
|
2957
|
+
break;
|
|
2958
|
+
case 'elicitation-url-waiting':
|
|
2959
|
+
if (elicitationUrlWaitingRef.current) {
|
|
2960
|
+
elicitationUrlWaitingRef.current = null;
|
|
2961
|
+
setElicitationUrlWaiting(false);
|
|
2962
|
+
setElicitation(null);
|
|
2963
|
+
setElicitationForm(null);
|
|
2964
|
+
clearComposerInput();
|
|
2965
|
+
}
|
|
2966
|
+
break;
|
|
2967
|
+
case 'elicitation-options':
|
|
2968
|
+
setElicitationForm((current) => current?.expandedField
|
|
2969
|
+
? { ...current, expandedField: undefined }
|
|
2970
|
+
: current);
|
|
2971
|
+
break;
|
|
2972
|
+
case 'elicitation':
|
|
2973
|
+
elicitationRef.current?.resolve({ action: 'cancel' });
|
|
2974
|
+
break;
|
|
2975
|
+
case 'file-picker':
|
|
2976
|
+
setFilePickerOpen(false);
|
|
2977
|
+
break;
|
|
2978
|
+
case 'command-palette':
|
|
2979
|
+
setCommandPaletteOpen(false);
|
|
2980
|
+
break;
|
|
2981
|
+
default: {
|
|
2982
|
+
const unhandledTarget = effect.target;
|
|
2983
|
+
return unhandledTarget;
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
else {
|
|
2988
|
+
const unhandledEffect = effect;
|
|
2989
|
+
return unhandledEffect;
|
|
2990
|
+
}
|
|
2939
2991
|
}
|
|
2992
|
+
};
|
|
2993
|
+
if (controlKey('c') || controlKey('z')) {
|
|
2994
|
+
const globalInteraction = routeTuiInteraction({
|
|
2995
|
+
suspensionPending: processSuspendRequestedRef.current,
|
|
2996
|
+
exitConfirmationArmed: exitConfirmation,
|
|
2997
|
+
layer: { kind: 'none' },
|
|
2998
|
+
busy,
|
|
2999
|
+
viewport: {
|
|
3000
|
+
enabled: false,
|
|
3001
|
+
offset: 0,
|
|
3002
|
+
maxOffset: 0,
|
|
3003
|
+
pageRows: 0,
|
|
3004
|
+
},
|
|
3005
|
+
composer: interactionComposer(),
|
|
3006
|
+
}, {
|
|
3007
|
+
globalIntent: controlKey('c') ? 'exit' : 'suspend',
|
|
3008
|
+
scrollIntent: 'none',
|
|
3009
|
+
action: undefined,
|
|
3010
|
+
composerKey,
|
|
3011
|
+
timestamp: Date.now(),
|
|
3012
|
+
callerIntent: 'none',
|
|
3013
|
+
});
|
|
3014
|
+
applyInteractionEffects(globalInteraction.effects);
|
|
2940
3015
|
return;
|
|
2941
3016
|
}
|
|
2942
|
-
dismissExitConfirmation();
|
|
2943
3017
|
const keybindingContexts = menuRef.current
|
|
2944
3018
|
? menuRef.current.kind === 'diff'
|
|
2945
3019
|
? ['DiffDialog']
|
|
@@ -2976,57 +3050,90 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
2976
3050
|
if (!keybindingAction) {
|
|
2977
3051
|
keybindingAction = resolveTuiKeybinding(keybindings, keybindingContexts, inputChord);
|
|
2978
3052
|
}
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
3053
|
+
const scrollIntent = key.pageUp
|
|
3054
|
+
? 'page-older'
|
|
3055
|
+
: key.pageDown
|
|
3056
|
+
? 'page-newer'
|
|
3057
|
+
: controlKey('u') || controlKey('b')
|
|
3058
|
+
? 'half-page-older'
|
|
3059
|
+
: controlKey('f') || controlKey('n')
|
|
3060
|
+
? 'half-page-newer'
|
|
3061
|
+
: inputRef.current.length === 0 && key.upArrow
|
|
3062
|
+
? 'line-older'
|
|
3063
|
+
: inputRef.current.length === 0 && key.downArrow
|
|
3064
|
+
? 'line-newer'
|
|
3065
|
+
: 'none';
|
|
3066
|
+
const hasPendingPrefix = !keybindingAction &&
|
|
3067
|
+
inputChord !== null &&
|
|
3068
|
+
hasTuiKeybindingPrefix(keybindings, keybindingContexts, inputChord);
|
|
3069
|
+
if (hasPendingPrefix) {
|
|
2982
3070
|
keySequenceRef.current = { chord: inputChord, at: Date.now() };
|
|
3071
|
+
}
|
|
3072
|
+
const layer = hasPendingPrefix
|
|
3073
|
+
? { kind: 'pending-prefix' }
|
|
3074
|
+
: permission
|
|
3075
|
+
? { kind: 'cancelable', target: 'permission' }
|
|
3076
|
+
: planApproval
|
|
3077
|
+
? { kind: 'cancelable', target: 'plan-approval' }
|
|
3078
|
+
: question
|
|
3079
|
+
? { kind: 'cancelable', target: 'question' }
|
|
3080
|
+
: elicitation
|
|
3081
|
+
? {
|
|
3082
|
+
kind: 'cancelable',
|
|
3083
|
+
target: elicitationUrlWaiting
|
|
3084
|
+
? 'elicitation-url-waiting'
|
|
3085
|
+
: elicitationForm?.expandedField
|
|
3086
|
+
? 'elicitation-options'
|
|
3087
|
+
: 'elicitation',
|
|
3088
|
+
}
|
|
3089
|
+
: selectingSession
|
|
3090
|
+
? { kind: 'delegated', target: 'session-picker' }
|
|
3091
|
+
: menuRef.current
|
|
3092
|
+
? { kind: 'delegated', target: 'menu' }
|
|
3093
|
+
: filePickerVisible
|
|
3094
|
+
? { kind: 'cancelable', target: 'file-picker' }
|
|
3095
|
+
: commandPaletteVisible
|
|
3096
|
+
? { kind: 'cancelable', target: 'command-palette' }
|
|
3097
|
+
: { kind: 'none' };
|
|
3098
|
+
const callerIntent = !busy && value === '?' && inputRef.current.length === 0
|
|
3099
|
+
? 'toggle-shortcuts'
|
|
3100
|
+
: runtimeSettingsRef.current.leftArrowOpensAgents &&
|
|
3101
|
+
key.leftArrow &&
|
|
3102
|
+
inputRef.current.length === 0 &&
|
|
3103
|
+
availableAgents.length > 0
|
|
3104
|
+
? 'open-agents'
|
|
3105
|
+
: key.return &&
|
|
3106
|
+
(key.shift || key.meta) &&
|
|
3107
|
+
keybindingAction === undefined
|
|
3108
|
+
? 'implicit-newline'
|
|
3109
|
+
: 'none';
|
|
3110
|
+
const interaction = routeTuiInteraction({
|
|
3111
|
+
suspensionPending: processSuspendRequestedRef.current,
|
|
3112
|
+
exitConfirmationArmed: exitConfirmation,
|
|
3113
|
+
layer,
|
|
3114
|
+
busy,
|
|
3115
|
+
viewport: {
|
|
3116
|
+
enabled: fixedViewport,
|
|
3117
|
+
offset: transcriptScrollOffsetRef.current,
|
|
3118
|
+
maxOffset: maxTranscriptScrollOffset,
|
|
3119
|
+
pageRows: transcriptPageRows,
|
|
3120
|
+
},
|
|
3121
|
+
composer: interactionComposer(),
|
|
3122
|
+
}, {
|
|
3123
|
+
globalIntent: 'none',
|
|
3124
|
+
scrollIntent,
|
|
3125
|
+
action: keybindingAction,
|
|
3126
|
+
composerKey,
|
|
3127
|
+
timestamp: Date.now(),
|
|
3128
|
+
callerIntent,
|
|
3129
|
+
});
|
|
3130
|
+
applyInteractionEffects(interaction.effects);
|
|
3131
|
+
if (interaction.disposition === 'handled') {
|
|
2983
3132
|
return;
|
|
2984
3133
|
}
|
|
2985
3134
|
const isKeybinding = (action) => keybindingAction === action;
|
|
2986
|
-
if (
|
|
2987
|
-
|
|
2988
|
-
!permission &&
|
|
2989
|
-
!planApproval &&
|
|
2990
|
-
!question &&
|
|
2991
|
-
!elicitation &&
|
|
2992
|
-
!selectingSession) {
|
|
2993
|
-
const page = transcriptPageRows;
|
|
2994
|
-
const scrollDelta = key.pageUp
|
|
2995
|
-
? page
|
|
2996
|
-
: key.pageDown
|
|
2997
|
-
? -page
|
|
2998
|
-
: controlKey('u') || controlKey('b')
|
|
2999
|
-
? page / 2
|
|
3000
|
-
: controlKey('f') || controlKey('n')
|
|
3001
|
-
? -page / 2
|
|
3002
|
-
: inputRef.current.length === 0 && key.upArrow
|
|
3003
|
-
? 1
|
|
3004
|
-
: inputRef.current.length === 0 && key.downArrow
|
|
3005
|
-
? -1
|
|
3006
|
-
: 0;
|
|
3007
|
-
if (scrollDelta !== 0) {
|
|
3008
|
-
setTranscriptScrollOffset((current) => Math.min(Math.max(0, maxTranscriptScrollOffset), Math.max(0, current + Math.trunc(scrollDelta))));
|
|
3009
|
-
return;
|
|
3010
|
-
}
|
|
3011
|
-
}
|
|
3012
|
-
if (runtimeSettingsRef.current.editor === 'vim' &&
|
|
3013
|
-
!permission &&
|
|
3014
|
-
!planApproval &&
|
|
3015
|
-
!question &&
|
|
3016
|
-
!elicitation &&
|
|
3017
|
-
menuRef.current === null) {
|
|
3018
|
-
if (!vimInsertMode) {
|
|
3019
|
-
if (value === 'i' || value === 'a')
|
|
3020
|
-
setVimInsertMode(true);
|
|
3021
|
-
else if (key.leftArrow || key.rightArrow)
|
|
3022
|
-
editComposer();
|
|
3023
|
-
return;
|
|
3024
|
-
}
|
|
3025
|
-
if (key.escape || value === '\u001B') {
|
|
3026
|
-
setVimInsertMode(false);
|
|
3027
|
-
return;
|
|
3028
|
-
}
|
|
3029
|
-
}
|
|
3135
|
+
if (hasPendingPrefix)
|
|
3136
|
+
return;
|
|
3030
3137
|
if (permission) {
|
|
3031
3138
|
const options = permission.kind === 'tool' && toolPermissionModel
|
|
3032
3139
|
? toolPermissionModel.options
|
|
@@ -3172,10 +3279,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
3172
3279
|
}
|
|
3173
3280
|
permission.resolve(feedback ? { behavior: 'deny', message: feedback } : false);
|
|
3174
3281
|
};
|
|
3175
|
-
if (
|
|
3176
|
-
permission.resolve(false);
|
|
3177
|
-
}
|
|
3178
|
-
else if (permissionFeedbackMode) {
|
|
3282
|
+
if (permissionFeedbackMode) {
|
|
3179
3283
|
if (key.tab) {
|
|
3180
3284
|
clearComposerInput();
|
|
3181
3285
|
setPermissionFeedbackMode(false);
|
|
@@ -3256,10 +3360,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
3256
3360
|
...(feedback ? { feedback } : {}),
|
|
3257
3361
|
});
|
|
3258
3362
|
};
|
|
3259
|
-
if (
|
|
3260
|
-
planApproval.resolve({ behavior: 'deny' });
|
|
3261
|
-
}
|
|
3262
|
-
else if (planApprovalFeedbackMode) {
|
|
3363
|
+
if (planApprovalFeedbackMode) {
|
|
3263
3364
|
if (key.tab) {
|
|
3264
3365
|
clearComposerInput();
|
|
3265
3366
|
setPlanApprovalFeedbackMode(false);
|
|
@@ -3296,10 +3397,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
3296
3397
|
return;
|
|
3297
3398
|
}
|
|
3298
3399
|
if (question) {
|
|
3299
|
-
if (key.
|
|
3300
|
-
question.resolve(null);
|
|
3301
|
-
}
|
|
3302
|
-
else if (key.return) {
|
|
3400
|
+
if (key.return) {
|
|
3303
3401
|
try {
|
|
3304
3402
|
const current = question.questions[question.index];
|
|
3305
3403
|
if (!current)
|
|
@@ -3353,13 +3451,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
3353
3451
|
setElicitationForm(null);
|
|
3354
3452
|
clearComposerInput();
|
|
3355
3453
|
};
|
|
3356
|
-
if (key.
|
|
3357
|
-
if (elicitationUrlWaiting)
|
|
3358
|
-
dismissUrlDialog();
|
|
3359
|
-
else
|
|
3360
|
-
elicitation.resolve({ action: 'cancel' });
|
|
3361
|
-
}
|
|
3362
|
-
else if (key.leftArrow || key.rightArrow) {
|
|
3454
|
+
if (key.leftArrow || key.rightArrow) {
|
|
3363
3455
|
setElicitationForm({
|
|
3364
3456
|
...form,
|
|
3365
3457
|
focusIndex: form.focusIndex === 0 ? 1 : 0,
|
|
@@ -3385,7 +3477,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
3385
3477
|
return;
|
|
3386
3478
|
}
|
|
3387
3479
|
if (form.expandedField && currentField) {
|
|
3388
|
-
if (key.
|
|
3480
|
+
if (key.leftArrow) {
|
|
3389
3481
|
setElicitationForm({ ...form, expandedField: undefined });
|
|
3390
3482
|
}
|
|
3391
3483
|
else if (key.upArrow) {
|
|
@@ -3404,9 +3496,6 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
3404
3496
|
setElicitationForm(typeaheadElicitationOption(form, value));
|
|
3405
3497
|
}
|
|
3406
3498
|
}
|
|
3407
|
-
else if (key.escape) {
|
|
3408
|
-
elicitation.resolve({ action: 'cancel' });
|
|
3409
|
-
}
|
|
3410
3499
|
else if (key.upArrow) {
|
|
3411
3500
|
move(-1);
|
|
3412
3501
|
}
|
|
@@ -5175,8 +5264,6 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5175
5264
|
void backgrounding;
|
|
5176
5265
|
return;
|
|
5177
5266
|
}
|
|
5178
|
-
if (isKeybinding('chat:cancel'))
|
|
5179
|
-
turnControllerRef.current?.abort();
|
|
5180
5267
|
return;
|
|
5181
5268
|
}
|
|
5182
5269
|
if (isKeybinding('chat:imagePaste')) {
|
|
@@ -5192,10 +5279,6 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5192
5279
|
return;
|
|
5193
5280
|
}
|
|
5194
5281
|
if (filePickerVisible) {
|
|
5195
|
-
if (key.escape || value === '\u001B') {
|
|
5196
|
-
setFilePickerOpen(false);
|
|
5197
|
-
return;
|
|
5198
|
-
}
|
|
5199
5282
|
if (key.upArrow) {
|
|
5200
5283
|
setFileSelection((current) => Math.max(0, current - 1));
|
|
5201
5284
|
return;
|
|
@@ -5220,13 +5303,6 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5220
5303
|
updateMenu({ kind: 'agents', agents: availableAgents, selectedIndex: 0 });
|
|
5221
5304
|
return;
|
|
5222
5305
|
}
|
|
5223
|
-
if (isKeybinding('chat:cancel')) {
|
|
5224
|
-
const now = Date.now();
|
|
5225
|
-
if (now - lastEscapeAtRef.current <= 500)
|
|
5226
|
-
clearComposerInput();
|
|
5227
|
-
lastEscapeAtRef.current = now;
|
|
5228
|
-
return;
|
|
5229
|
-
}
|
|
5230
5306
|
if (isKeybinding('chat:cycleMode')) {
|
|
5231
5307
|
const currentIndex = permissionOptions.findIndex((option) => option.mode === runtimePreferences.permissionMode);
|
|
5232
5308
|
const next = permissionOptions[(currentIndex + 1) % permissionOptions.length];
|
|
@@ -5235,10 +5311,6 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5235
5311
|
return;
|
|
5236
5312
|
}
|
|
5237
5313
|
if (commandPaletteVisible) {
|
|
5238
|
-
if (key.escape) {
|
|
5239
|
-
setCommandPaletteOpen(false);
|
|
5240
|
-
return;
|
|
5241
|
-
}
|
|
5242
5314
|
if (key.upArrow) {
|
|
5243
5315
|
if (matchingSlashCommands.length > 0) {
|
|
5244
5316
|
setCommandSelection((current) => Math.max(0, current - 1));
|
|
@@ -5842,24 +5914,12 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5842
5914
|
clearComposerInput();
|
|
5843
5915
|
return;
|
|
5844
5916
|
}
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
right: key.rightArrow,
|
|
5849
|
-
backspace: key.backspace,
|
|
5850
|
-
delete: key.delete,
|
|
5851
|
-
ctrl: key.ctrl,
|
|
5852
|
-
meta: key.meta,
|
|
5853
|
-
escape: key.escape || value === '\u001B',
|
|
5854
|
-
});
|
|
5855
|
-
if (transition.kind === 'cancel') {
|
|
5856
|
-
clearComposerInput();
|
|
5857
|
-
}
|
|
5858
|
-
else if (transition.kind === 'edit') {
|
|
5859
|
-
updateComposerEditor(transition.editor);
|
|
5917
|
+
if (filePickerVisible || commandPaletteVisible) {
|
|
5918
|
+
editComposer();
|
|
5919
|
+
return;
|
|
5860
5920
|
}
|
|
5861
5921
|
});
|
|
5862
|
-
return (_jsx(TuiThemeProvider, { settings: themeSettings, children: _jsx(Box, { flexDirection: "column", ...(!fixedViewport
|
|
5922
|
+
return (_jsx(TuiThemeProvider, { settings: themeSettings, screenReader: axScreenReader, children: _jsx(Box, { flexDirection: "column", ...(!fixedViewport
|
|
5863
5923
|
? {}
|
|
5864
5924
|
: { height: rows, overflowY: 'hidden' }), children: selectingSession ? (_jsx(SessionPicker, { sessions: filteredPickerChoices, selectedIndex: selectedIndex, screenReader: axScreenReader, query: sessionSearch })) : (_jsxs(_Fragment, { children: [!axScreenReader && freshSession ? (_jsx(WelcomePanel, { display: runtimeDisplay, width: width, showTips: runtimeSettings.tips, dataPlane: dataPlane })) : null, sessionId ? (_jsxs(Text, { dimColor: true, children: ["Session ", sessionId.slice(0, 8)] })) : null, !axScreenReader && !resumed && hasConversationHistory ? (_jsx(SessionIdentity, { display: runtimeDisplay, width: width })) : null, _jsx(Box, { ...(fixedViewport
|
|
5865
5925
|
? {
|
|
@@ -5869,16 +5929,16 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5869
5929
|
}
|
|
5870
5930
|
: {}), children: _jsx(Transcript, { entries: transcriptEntries, activeText: activeText, activeThinking: activeThinking, activeStreamVisible: transcriptScrollOffset === 0, thinkingExpanded: thinkingExpanded, detailedTranscript: thinkingExpanded || runtimeSettings.verbose, screenReader: axScreenReader }) }), externalEditorRequest !== null ||
|
|
5871
5931
|
keybindingsEditing ||
|
|
5872
|
-
memoryEditorRequest !== null ? (_jsx(ExternalEditorWait, { screenReader: axScreenReader })) : permission ? (permission.kind === 'tool' && toolPermissionModel ? (_jsx(ToolPermissionDialog, { model: toolPermissionModel, selection: permissionSelection, feedbackMode: permissionFeedbackMode, feedback: input, ruleEditor: permissionRuleEditor, screenReader: axScreenReader })) : (_jsxs(DialogFrame, { title: `Retry interrupted ${permission.call.name}?`, screenReader: axScreenReader, children: [_jsx(Box, { flexDirection: "column", paddingX: 1, paddingY: 1, children: _jsx(Text, { bold: true, children: describeTool(permission.call, sensitiveValues) }) }), _jsx(Text, { children: "Do you want to proceed?" }),
|
|
5932
|
+
memoryEditorRequest !== null ? (_jsx(ExternalEditorWait, { screenReader: axScreenReader })) : permission ? (permission.kind === 'tool' && toolPermissionModel ? (_jsx(ToolPermissionDialog, { model: toolPermissionModel, selection: permissionSelection, feedbackMode: permissionFeedbackMode, feedback: input, ruleEditor: permissionRuleEditor, screenReader: axScreenReader })) : (_jsxs(DialogFrame, { title: `Retry interrupted ${permission.call.name}?`, screenReader: axScreenReader, children: [_jsx(Box, { flexDirection: "column", paddingX: 1, paddingY: 1, children: _jsx(Text, { bold: true, children: describeTool(permission.call, sensitiveValues) }) }), _jsx(Text, { children: "Do you want to proceed?" }), _jsx(DecisionOption, { selected: permissionSelection === 0, screenReader: axScreenReader, children: "1. Yes" }), _jsx(DecisionOption, { selected: permissionSelection === 1, screenReader: axScreenReader, children: "2. No" }), permissionFeedbackMode ? (_jsxs(Text, { children: ["\u203A", ' ', input ||
|
|
5873
5933
|
(permissionSelection === 0
|
|
5874
5934
|
? 'tell Praxis what to do next'
|
|
5875
5935
|
: 'tell Praxis what to do differently')] })) : null, _jsx(Text, { dimColor: true, children: permissionFeedbackMode
|
|
5876
5936
|
? 'Enter to submit · Tab to collapse · Esc to cancel'
|
|
5877
|
-
: 'Enter to confirm · Tab to add feedback · Esc to cancel' })] }))) : planApproval ? (_jsxs(DialogFrame, { title: "Ready to code?", screenReader: axScreenReader, children: [_jsx(Text, { children: "Here is Praxis's plan:" }), planApproval.request.plan ? (_jsx(Box, { borderStyle: axScreenReader ? undefined : 'classic', borderLeft: false, borderRight: false, paddingX: axScreenReader ? 0 : 1, marginY: 1, children: _jsx(Text, { children: planApproval.request.plan }) })) : null, _jsx(Text, { dimColor: true, children: "Praxis has written up a plan and is ready to execute. Would you like to proceed?" }), _jsxs(
|
|
5937
|
+
: 'Enter to confirm · Tab to add feedback · Esc to cancel' })] }))) : planApproval ? (_jsxs(DialogFrame, { title: "Ready to code?", screenReader: axScreenReader, children: [_jsx(Text, { children: "Here is Praxis's plan:" }), planApproval.request.plan ? (_jsx(Box, { borderStyle: axScreenReader ? undefined : 'classic', borderLeft: false, borderRight: false, paddingX: axScreenReader ? 0 : 1, marginY: 1, children: _jsx(Text, { children: planApproval.request.plan }) })) : null, _jsx(Text, { dimColor: true, children: "Praxis has written up a plan and is ready to execute. Would you like to proceed?" }), _jsxs(DecisionOption, { selected: planApprovalSelection === 0, screenReader: axScreenReader, children: ["1.", ' ', runtimeSettings.useAutoModeDuringPlan
|
|
5878
5938
|
? 'Yes, and use auto mode'
|
|
5879
5939
|
: allowDangerouslySkipPermissions
|
|
5880
5940
|
? 'Yes, and bypass permissions'
|
|
5881
|
-
: 'Yes, auto-accept edits'] }),
|
|
5941
|
+
: 'Yes, auto-accept edits'] }), _jsx(DecisionOption, { selected: planApprovalSelection === 1, screenReader: axScreenReader, children: "2. Yes, manually approve edits" }), _jsx(DecisionOption, { selected: planApprovalSelection === 2, screenReader: axScreenReader, children: "3. No, keep planning" }), planApprovalFeedbackMode ? (_jsxs(Text, { children: ["\u203A", ' ', input ||
|
|
5882
5942
|
(planApprovalSelection === 2
|
|
5883
5943
|
? 'Tell Praxis what to change'
|
|
5884
5944
|
: 'Add feedback for implementation')] })) : null, _jsx(Text, { dimColor: true, children: planApproval.request.planPath }), _jsx(Text, { dimColor: true, children: planApprovalFeedbackMode
|
|
@@ -5894,9 +5954,9 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5894
5954
|
.slice(window.start, window.end)
|
|
5895
5955
|
.map((point, offset) => {
|
|
5896
5956
|
const index = window.start + offset;
|
|
5897
|
-
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
5898
|
-
|
|
5899
|
-
|
|
5957
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(DecisionOption, { selected: menu.selectedIndex === index, screenReader: axScreenReader, selectedPrefix: " \u276F ", unselectedPrefix: " ", children: point.prompt
|
|
5958
|
+
.replace(/\s+/gu, ' ')
|
|
5959
|
+
.slice(0, 72) }), _jsxs(Text, { dimColor: true, children: [' ', point.fileChanges.length > 0
|
|
5900
5960
|
? point.fileChanges
|
|
5901
5961
|
.map((path) => path.startsWith(`${runtimeCwd}/`)
|
|
5902
5962
|
? path.slice(runtimeCwd.length + 1)
|
|
@@ -5906,11 +5966,11 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5906
5966
|
? 'No code changes'
|
|
5907
5967
|
: '⚠ No code restore'] })] }, point.messageId));
|
|
5908
5968
|
}), window.end < menu.points.length ? (_jsxs(Text, { dimColor: true, children: [' ', "\u2193 ", menu.points.length - window.end, " more below"] })) : null] }));
|
|
5909
|
-
})(),
|
|
5969
|
+
})(), _jsx(DecisionOption, { selected: menu.selectedIndex === menu.points.length, screenReader: axScreenReader, selectedPrefix: " \u276F ", unselectedPrefix: " ", children: "(current)" }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: " Enter to continue \u00B7 Esc to cancel" })] })) : menu?.kind === 'rewind-confirm' ? (_jsxs(DialogFrame, { title: "Confirm restore point", screenReader: axScreenReader, children: [_jsxs(Text, { children: ["\u2502 ", menu.point.prompt] }), _jsx(Text, { children: " " }), _jsx(Text, { children: "The conversation will be forked." }), _jsxs(Text, { children: ["The code will", ' ', menu.point.fileChanges.length > 0
|
|
5910
5970
|
? `restore ${menu.point.fileChanges.join(', ')}.`
|
|
5911
|
-
: 'be unchanged.'] }), _jsx(Text, { children: " " }), rewindActions(menu.point).map((option, index) => (_jsxs(
|
|
5971
|
+
: 'be unchanged.'] }), _jsx(Text, { children: " " }), rewindActions(menu.point).map((option, index) => (_jsxs(DecisionOption, { selected: menu.selectedIndex === index, screenReader: axScreenReader, children: [index + 1, ". ", option.label] }, option.action))), _jsx(Text, { children: " " }), _jsx(RewindWarning, {})] })) : menu?.kind === 'rewind-context' ? (_jsxs(DialogFrame, { title: `Summarize ${menu.direction === 'from' ? 'from' : 'up to'} here`, screenReader: axScreenReader, children: [_jsx(Text, { children: menu.direction === 'from'
|
|
5912
5972
|
? 'Messages after this point will be summarized.'
|
|
5913
|
-
: 'Messages up to this point will be summarized.' }), _jsx(Text, { children: " " }), _jsxs(Text, { children: ["add context (optional): ", input] }), _jsx(Text, { dimColor: true, children: "Enter to summarize \u00B7 Esc to go back" })] })) : menu?.kind === 'permission-rule-input' ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { bold: true, children: ["Add ", menu.behavior, " permission rule"] }), _jsx(Text, { children: "Permission rules are a tool name, optionally followed by a specifier in parentheses." }), _jsx(Text, { children: "e.g., WebFetch or Bash(ls *)" }), _jsx(Text, { children: " " }), _jsx(Box, { borderStyle: axScreenReader ? undefined : 'round', paddingX: axScreenReader ? 0 : 1, children: _jsx(Text, { ...(input ? {} : { dimColor: true }), children: input || 'Enter permission rule…' }) }), _jsx(Text, { dimColor: true, children: "Enter to submit \u00B7 Esc to cancel" })] })) : menu?.kind === 'workspace-directory-input' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Add directory to workspace" }), _jsx(Text, { children: "Praxis Code will be able to read files in this directory and make edits when auto-accept edits is on." }), _jsx(Text, { children: " " }), _jsx(Text, { children: "Enter the path to the directory:" }), _jsx(Box, { borderStyle: axScreenReader ? undefined : 'round', paddingX: axScreenReader ? 0 : 1, children: _jsx(Text, { ...(input ? {} : { dimColor: true }), children: input || 'Directory path…' }) }), _jsx(Text, { dimColor: true, children: "Tab to complete \u00B7 Enter to add \u00B7 Esc to cancel" })] })) : menu?.kind === 'permission-delete' ? (_jsxs(DialogFrame, { title: permissionDeleteTitle(menu.rule.behavior), screenReader: axScreenReader, children: [_jsx(Text, { children: menu.rule.rule }), permissionRuleDescription(menu.rule.rule) ? (_jsx(Text, { dimColor: true, children: permissionRuleDescription(menu.rule.rule) })) : null, _jsx(Text, { dimColor: true, children: permissionScopeLabel(menu.rule.scope) }), _jsx(Text, { children: " " }), _jsx(Text, { children: "Are you sure you want to delete this permission rule?" }), _jsx(Text, { children: " " }),
|
|
5973
|
+
: 'Messages up to this point will be summarized.' }), _jsx(Text, { children: " " }), _jsxs(Text, { children: ["add context (optional): ", input] }), _jsx(Text, { dimColor: true, children: "Enter to summarize \u00B7 Esc to go back" })] })) : menu?.kind === 'permission-rule-input' ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { bold: true, children: ["Add ", menu.behavior, " permission rule"] }), _jsx(Text, { children: "Permission rules are a tool name, optionally followed by a specifier in parentheses." }), _jsx(Text, { children: "e.g., WebFetch or Bash(ls *)" }), _jsx(Text, { children: " " }), _jsx(Box, { borderStyle: axScreenReader ? undefined : 'round', paddingX: axScreenReader ? 0 : 1, children: _jsx(Text, { ...(input ? {} : { dimColor: true }), children: input || 'Enter permission rule…' }) }), _jsx(Text, { dimColor: true, children: "Enter to submit \u00B7 Esc to cancel" })] })) : menu?.kind === 'workspace-directory-input' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Add directory to workspace" }), _jsx(Text, { children: "Praxis Code will be able to read files in this directory and make edits when auto-accept edits is on." }), _jsx(Text, { children: " " }), _jsx(Text, { children: "Enter the path to the directory:" }), _jsx(Box, { borderStyle: axScreenReader ? undefined : 'round', paddingX: axScreenReader ? 0 : 1, children: _jsx(Text, { ...(input ? {} : { dimColor: true }), children: input || 'Directory path…' }) }), _jsx(Text, { dimColor: true, children: "Tab to complete \u00B7 Enter to add \u00B7 Esc to cancel" })] })) : menu?.kind === 'permission-delete' ? (_jsxs(DialogFrame, { title: permissionDeleteTitle(menu.rule.behavior), screenReader: axScreenReader, children: [_jsx(Text, { children: menu.rule.rule }), permissionRuleDescription(menu.rule.rule) ? (_jsx(Text, { dimColor: true, children: permissionRuleDescription(menu.rule.rule) })) : null, _jsx(Text, { dimColor: true, children: permissionScopeLabel(menu.rule.scope) }), _jsx(Text, { children: " " }), _jsx(Text, { children: "Are you sure you want to delete this permission rule?" }), _jsx(Text, { children: " " }), _jsx(DecisionOption, { selected: menu.selectedIndex === 0, screenReader: axScreenReader, children: "1. Yes" }), _jsx(DecisionOption, { selected: menu.selectedIndex === 1, screenReader: axScreenReader, children: "2. No" }), _jsx(Text, { dimColor: true, children: "Esc to cancel" })] })) : menu?.kind === 'workspace-directory-delete' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Remove directory from workspace?" }), _jsxs(Text, { children: [" ", menu.path] }), _jsx(Text, { children: " " }), _jsx(Text, { children: "Praxis Code will no longer have access to files in this directory." }), _jsx(Text, { children: " " }), _jsx(DecisionOption, { selected: menu.selectedIndex === 0, screenReader: axScreenReader, children: "1. Yes" }), _jsx(DecisionOption, { selected: menu.selectedIndex === 1, screenReader: axScreenReader, children: "2. No" }), _jsx(Text, { dimColor: true, children: "Enter to confirm \u00B7 Esc to cancel" })] })) : menu ? (menu.kind === 'help' ? (_jsx(HelpMenu, { tabIndex: menu.tabIndex, selectedIndex: menu.selectedIndex, builtinCommands: builtinSlashCommands, customCommands: customSlashCommands, width: width, screenReader: axScreenReader })) : menu.kind === 'diff' ? (_jsx(DiffDashboard, { snapshots: menu.snapshots, sourceIndex: menu.sourceIndex, selectedIndex: menu.selectedIndex, viewingFile: menu.viewingFile, scrollOffset: menu.scrollOffset, width: width, screenReader: axScreenReader })) : menu.kind === 'permission-dashboard' ? (_jsx(PermissionDashboard, { tabIndex: menu.tabIndex, selectedIndex: menu.selectedIndex, query: menu.query, rules: menu.rules, recentDenied: recentDenied, retryingDeniedId: retryingDeniedId, workspaceDirectories: workspaceDirectories, width: width, screenReader: axScreenReader })) : menu.kind === 'sandbox' ? (_jsx(SandboxDashboard, { snapshot: menu.snapshot, tab: menu.tab, selectedIndex: menu.selectedIndex, width: width, screenReader: axScreenReader })) : menu.kind === 'permission-scope' ? (_jsx(SelectionMenu, { title: "Where should this rule be saved?", description: `${menu.rule}${permissionRuleDescription(menu.rule)
|
|
5914
5974
|
? ` · ${permissionRuleDescription(menu.rule)}`
|
|
5915
5975
|
: ''}`, options: [
|
|
5916
5976
|
{
|
|
@@ -5957,7 +6017,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
5957
6017
|
label: 'Save to file',
|
|
5958
6018
|
description: 'Save the conversation to a file in the current directory',
|
|
5959
6019
|
},
|
|
5960
|
-
], selectedIndex: menu.selectedIndex, footer: "Esc to cancel", width: width, screenReader: axScreenReader })) : menu.kind === 'copy' ? (_jsx(SelectionMenu, { title: "Copy", description: "Select content to copy:", options: menu.candidates, selectedIndex: menu.selectedIndex, footer: "Enter to copy \u00B7 w to write to /tmp/claude \u00B7 Esc to cancel", width: width, screenReader: axScreenReader })) : null) : (_jsxs(_Fragment, { children: [commandPaletteVisible ? (_jsx(CommandPalette, { commands: matchingSlashCommands, selectedIndex: selectedSlashCommandIndex, width: width, screenReader: axScreenReader })) : null, filePickerVisible ? (_jsx(MentionPicker, { entries: matchingMentionEntries, selectedIndex: selectedFileIndex, width: width, screenReader: axScreenReader })) : null, exitConfirmation ?
|
|
6020
|
+
], selectedIndex: menu.selectedIndex, footer: "Esc to cancel", width: width, screenReader: axScreenReader })) : menu.kind === 'copy' ? (_jsx(SelectionMenu, { title: "Copy", description: "Select content to copy:", options: menu.candidates, selectedIndex: menu.selectedIndex, footer: "Enter to copy \u00B7 w to write to /tmp/claude \u00B7 Esc to cancel", width: width, screenReader: axScreenReader })) : null) : (_jsxs(_Fragment, { children: [commandPaletteVisible ? (_jsx(CommandPalette, { commands: matchingSlashCommands, selectedIndex: selectedSlashCommandIndex, width: width, screenReader: axScreenReader })) : null, filePickerVisible ? (_jsx(MentionPicker, { entries: matchingMentionEntries, selectedIndex: selectedFileIndex, width: width, screenReader: axScreenReader })) : null, exitConfirmation ? _jsx(ExitWarning, {}) : null, fixedViewport ? _jsx(Box, { flexGrow: 1 }) : null, _jsx(Composer, { input: shellMode ? input.slice(1) : input, cursor: shellMode ? Math.max(0, inputCursor - 1) : inputCursor, shellMode: shellMode, ...(sessionColor === undefined ? {} : { sessionColor }), ...(commandArgumentHint === undefined
|
|
5961
6021
|
? {}
|
|
5962
6022
|
: { commandArgumentHint }), busy: busy, clipboardBusy: clipboardBusy, status: status, display: runtimeDisplay, ...(usage === undefined ? {} : { usage }), ...(costUsd === undefined ? {} : { costUsd }), width: width, screenReader: axScreenReader, hasThinking: hasDetailedTranscript, thinkingExpanded: thinkingExpanded, reduceMotion: runtimeSettings.reduceMotion, progressBar: runtimeSettings.progressBar, ...(runtimeSettings.turnDuration
|
|
5963
6023
|
? (() => {
|