praxis-agent 0.46.0 → 0.46.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/cli/interactive.js
CHANGED
|
@@ -44,6 +44,7 @@ import { projectTuiCommandPalette, tuiCommandPaletteCommandId, } from './tui/com
|
|
|
44
44
|
import { runDoctor, } from '../maintenance/doctor.js';
|
|
45
45
|
import { canonicalClaudeCostModelName, formatCostSummary, } from './tui/cost-summary.js';
|
|
46
46
|
import { createComposerEditor, deleteComposerBackward, deleteComposerForward, insertComposerText, moveComposerCursor, } from './tui/composer-editor.js';
|
|
47
|
+
import { createComposerPromptHistory, navigateComposerPromptHistory, recordComposerPrompt, resetComposerPromptHistoryNavigation, seedComposerPromptHistory, } from './tui/composer-prompt-history.js';
|
|
47
48
|
import { routeComposerKey, } from './tui/composer-key-router.js';
|
|
48
49
|
import { routeTuiInteraction, } from './tui/tui-interaction-router.js';
|
|
49
50
|
import { currentTuiInteractionLayer, projectTuiFocusStack, } from './tui/tui-focus-stack.js';
|
|
@@ -239,6 +240,9 @@ const HIDDEN_TUI_SLASH_COMMANDS = new Set([
|
|
|
239
240
|
'update',
|
|
240
241
|
'usage',
|
|
241
242
|
]);
|
|
243
|
+
function transcriptPrompts(items) {
|
|
244
|
+
return items.flatMap((item) => (item.kind === 'user' ? [item.text] : []));
|
|
245
|
+
}
|
|
242
246
|
/** Advances the React-owned transcript plus its exact local mutation fact. */
|
|
243
247
|
export function advanceInteractiveHistoryState(current, items, changedFrom) {
|
|
244
248
|
if (!Number.isInteger(changedFrom) ||
|
|
@@ -372,9 +376,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
372
376
|
const [pendingFork, setPendingFork] = useState(resume?.forkSession === true);
|
|
373
377
|
const inputRef = useRef('');
|
|
374
378
|
const inputCursorRef = useRef(0);
|
|
375
|
-
const
|
|
376
|
-
const inputHistoryIndexRef = useRef(null);
|
|
377
|
-
const inputHistoryDraftRef = useRef('');
|
|
379
|
+
const promptHistoryRef = useRef(seedComposerPromptHistory(transcriptPrompts(initialHistory)));
|
|
378
380
|
const [pendingInputs, setPendingInputs] = useState([]);
|
|
379
381
|
const pendingInputsRef = useRef(pendingInputs);
|
|
380
382
|
pendingInputsRef.current = pendingInputs;
|
|
@@ -1466,6 +1468,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1466
1468
|
fileSelectionRef.current = 0;
|
|
1467
1469
|
};
|
|
1468
1470
|
const updateComposerEditor = (editor, recordUndo = true) => {
|
|
1471
|
+
promptHistoryRef.current = resetComposerPromptHistoryNavigation(promptHistoryRef.current);
|
|
1469
1472
|
if (recordUndo && editor.text !== inputRef.current) {
|
|
1470
1473
|
undoStackRef.current = [
|
|
1471
1474
|
...undoStackRef.current,
|
|
@@ -1474,7 +1477,10 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1474
1477
|
}
|
|
1475
1478
|
updateComposerInput(editor.text, editor.cursor);
|
|
1476
1479
|
};
|
|
1477
|
-
const clearComposerInput = () =>
|
|
1480
|
+
const clearComposerInput = () => {
|
|
1481
|
+
promptHistoryRef.current = resetComposerPromptHistoryNavigation(promptHistoryRef.current);
|
|
1482
|
+
updateComposerInput('');
|
|
1483
|
+
};
|
|
1478
1484
|
const promptImages = (prompt) => {
|
|
1479
1485
|
const seen = new Set();
|
|
1480
1486
|
return composerImageIds(prompt).flatMap((id) => {
|
|
@@ -1706,36 +1712,13 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1706
1712
|
return () => clearInterval(timer);
|
|
1707
1713
|
}, [menu?.kind]);
|
|
1708
1714
|
const appendPromptHistory = (prompt) => {
|
|
1709
|
-
|
|
1710
|
-
return;
|
|
1711
|
-
const history = inputHistoryRef.current.filter((item) => item !== prompt);
|
|
1712
|
-
inputHistoryRef.current = [prompt, ...history].slice(0, 100);
|
|
1713
|
-
inputHistoryIndexRef.current = null;
|
|
1714
|
-
inputHistoryDraftRef.current = '';
|
|
1715
|
+
promptHistoryRef.current = recordComposerPrompt(promptHistoryRef.current, prompt);
|
|
1715
1716
|
};
|
|
1716
1717
|
const restorePromptHistory = (direction) => {
|
|
1717
|
-
const
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
if (direction === 'previous') {
|
|
1722
|
-
if (currentIndex === null)
|
|
1723
|
-
inputHistoryDraftRef.current = inputRef.current;
|
|
1724
|
-
const nextIndex = Math.min(history.length - 1, (currentIndex ?? -1) + 1);
|
|
1725
|
-
inputHistoryIndexRef.current = nextIndex;
|
|
1726
|
-
updateComposerInput(history[nextIndex] ?? '');
|
|
1727
|
-
return;
|
|
1728
|
-
}
|
|
1729
|
-
if (currentIndex === null)
|
|
1730
|
-
return;
|
|
1731
|
-
const nextIndex = currentIndex - 1;
|
|
1732
|
-
if (nextIndex < 0) {
|
|
1733
|
-
inputHistoryIndexRef.current = null;
|
|
1734
|
-
updateComposerInput(inputHistoryDraftRef.current);
|
|
1735
|
-
return;
|
|
1736
|
-
}
|
|
1737
|
-
inputHistoryIndexRef.current = nextIndex;
|
|
1738
|
-
updateComposerInput(history[nextIndex] ?? '');
|
|
1718
|
+
const transition = navigateComposerPromptHistory(promptHistoryRef.current, direction, createComposerEditor(inputRef.current, inputCursorRef.current));
|
|
1719
|
+
promptHistoryRef.current = transition.state;
|
|
1720
|
+
if (transition.editor !== null)
|
|
1721
|
+
updateComposerInput(transition.editor.text, transition.editor.cursor);
|
|
1739
1722
|
};
|
|
1740
1723
|
const withdrawLatestPending = () => {
|
|
1741
1724
|
if (inputRef.current.trim().length !== 0)
|
|
@@ -2253,10 +2236,12 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
2253
2236
|
const loadId = sessionLoadRef.current + 1;
|
|
2254
2237
|
sessionLoadRef.current = loadId;
|
|
2255
2238
|
if (nextSessionId === null) {
|
|
2239
|
+
promptHistoryRef.current = createComposerPromptHistory();
|
|
2256
2240
|
setHistory([]);
|
|
2257
2241
|
setSessionColor(undefined);
|
|
2258
2242
|
return;
|
|
2259
2243
|
}
|
|
2244
|
+
promptHistoryRef.current = createComposerPromptHistory();
|
|
2260
2245
|
const loading = (async () => {
|
|
2261
2246
|
try {
|
|
2262
2247
|
const commands = await service();
|
|
@@ -2266,6 +2251,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
2266
2251
|
: await commands.agentColor(nextSessionId);
|
|
2267
2252
|
if (sessionLoadRef.current === loadId) {
|
|
2268
2253
|
setHistory(transcript ? [...transcript] : []);
|
|
2254
|
+
promptHistoryRef.current = seedComposerPromptHistory(transcriptPrompts(transcript ?? []));
|
|
2269
2255
|
setSessionColor(agentColor);
|
|
2270
2256
|
}
|
|
2271
2257
|
}
|
|
@@ -3249,6 +3235,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
3249
3235
|
setSessionId(restoredConversation.sessionId || null);
|
|
3250
3236
|
setPendingFork(false);
|
|
3251
3237
|
setHistory(restoredConversation.history);
|
|
3238
|
+
promptHistoryRef.current = seedComposerPromptHistory(transcriptPrompts(restoredConversation.history));
|
|
3252
3239
|
updateComposerInput(point.prompt);
|
|
3253
3240
|
}
|
|
3254
3241
|
append({
|
|
@@ -6285,9 +6272,6 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
6285
6272
|
streamingFrameRef.current?.flush();
|
|
6286
6273
|
setThinkingExpanded(false);
|
|
6287
6274
|
setStatus('ready');
|
|
6288
|
-
inputHistoryRef.current = [];
|
|
6289
|
-
inputHistoryIndexRef.current = null;
|
|
6290
|
-
inputHistoryDraftRef.current = '';
|
|
6291
6275
|
})().catch(warn);
|
|
6292
6276
|
}
|
|
6293
6277
|
else if (prompt === '/model') {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ComposerEditorState } from './composer-editor.js';
|
|
2
|
+
export declare const COMPOSER_PROMPT_HISTORY_LIMIT = 100;
|
|
3
|
+
export interface ComposerPromptHistoryState {
|
|
4
|
+
readonly entries: readonly string[];
|
|
5
|
+
readonly index: number | null;
|
|
6
|
+
readonly draft: ComposerEditorState | null;
|
|
7
|
+
}
|
|
8
|
+
export interface ComposerPromptHistoryTransition {
|
|
9
|
+
readonly state: ComposerPromptHistoryState;
|
|
10
|
+
readonly editor: ComposerEditorState | null;
|
|
11
|
+
}
|
|
12
|
+
export declare function createComposerPromptHistory(): ComposerPromptHistoryState;
|
|
13
|
+
export declare function seedComposerPromptHistory(prompts: readonly string[]): ComposerPromptHistoryState;
|
|
14
|
+
export declare function recordComposerPrompt(state: ComposerPromptHistoryState, prompt: string): ComposerPromptHistoryState;
|
|
15
|
+
export declare function navigateComposerPromptHistory(state: ComposerPromptHistoryState, direction: 'previous' | 'next', currentEditor: ComposerEditorState): ComposerPromptHistoryTransition;
|
|
16
|
+
export declare function resetComposerPromptHistoryNavigation(state: ComposerPromptHistoryState): ComposerPromptHistoryState;
|
|
17
|
+
//# sourceMappingURL=composer-prompt-history.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createComposerEditor, } from './composer-editor.js';
|
|
2
|
+
export const COMPOSER_PROMPT_HISTORY_LIMIT = 100;
|
|
3
|
+
export function createComposerPromptHistory() {
|
|
4
|
+
return { entries: [], index: null, draft: null };
|
|
5
|
+
}
|
|
6
|
+
function normalize(prompts) {
|
|
7
|
+
const entries = [];
|
|
8
|
+
for (const prompt of prompts) {
|
|
9
|
+
if (prompt.trim() === '')
|
|
10
|
+
continue;
|
|
11
|
+
if (entries.at(-1) === prompt)
|
|
12
|
+
continue;
|
|
13
|
+
entries.push(prompt);
|
|
14
|
+
}
|
|
15
|
+
return entries.slice(-COMPOSER_PROMPT_HISTORY_LIMIT);
|
|
16
|
+
}
|
|
17
|
+
export function seedComposerPromptHistory(prompts) {
|
|
18
|
+
return { entries: normalize(prompts), index: null, draft: null };
|
|
19
|
+
}
|
|
20
|
+
export function recordComposerPrompt(state, prompt) {
|
|
21
|
+
if (prompt.trim() === '')
|
|
22
|
+
return state;
|
|
23
|
+
return {
|
|
24
|
+
entries: normalize([...state.entries, prompt]),
|
|
25
|
+
index: null,
|
|
26
|
+
draft: null,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function navigateComposerPromptHistory(state, direction, currentEditor) {
|
|
30
|
+
if (state.entries.length === 0)
|
|
31
|
+
return { state, editor: null };
|
|
32
|
+
if (direction === 'previous') {
|
|
33
|
+
const index = state.index === null
|
|
34
|
+
? state.entries.length - 1
|
|
35
|
+
: Math.max(0, state.index - 1);
|
|
36
|
+
const draft = state.index === null
|
|
37
|
+
? createComposerEditor(currentEditor.text, currentEditor.cursor)
|
|
38
|
+
: state.draft;
|
|
39
|
+
const nextState = { ...state, index, draft };
|
|
40
|
+
return {
|
|
41
|
+
state: nextState,
|
|
42
|
+
editor: createComposerEditor(state.entries[index]),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (state.index === null)
|
|
46
|
+
return { state, editor: null };
|
|
47
|
+
if (state.index < state.entries.length - 1) {
|
|
48
|
+
const index = state.index + 1;
|
|
49
|
+
return {
|
|
50
|
+
state: { ...state, index },
|
|
51
|
+
editor: createComposerEditor(state.entries[index]),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const editor = state.draft;
|
|
55
|
+
return {
|
|
56
|
+
state: { ...state, index: null, draft: null },
|
|
57
|
+
editor,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function resetComposerPromptHistoryNavigation(state) {
|
|
61
|
+
return { ...state, index: null, draft: null };
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=composer-prompt-history.js.map
|
|
@@ -44,7 +44,8 @@ export function routeTuiInteraction(snapshot, input) {
|
|
|
44
44
|
if (snapshot.layer.kind === 'delegated')
|
|
45
45
|
return delegated(confirmationEffects);
|
|
46
46
|
const viewport = snapshot.viewport;
|
|
47
|
-
|
|
47
|
+
const scrollIsIncidental = input.action === undefined || input.action.startsWith('scroll:');
|
|
48
|
+
if (viewport.enabled && input.scrollIntent !== 'none' && scrollIsIncidental) {
|
|
48
49
|
const pageRows = finiteNonNegativeInteger(viewport.pageRows);
|
|
49
50
|
const offset = finiteNonNegativeInteger(viewport.offset);
|
|
50
51
|
const maxOffset = finiteNonNegativeInteger(viewport.maxOffset);
|