ideacode 1.3.1 → 1.3.2
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/repl.js +34 -1
- package/package.json +1 -1
package/dist/repl.js
CHANGED
|
@@ -50,6 +50,7 @@ const PARALLEL_SAFE_TOOLS = new Set([
|
|
|
50
50
|
]);
|
|
51
51
|
const LOADING_TICK_MS = 80;
|
|
52
52
|
const MAX_EMPTY_ASSISTANT_RETRIES = 3;
|
|
53
|
+
const TYPING_LAYOUT_FREEZE_MS = 180;
|
|
53
54
|
const TRUNCATE_NOTE = "\n\n(Output truncated to save context. Use read with offset/limit, grep with a specific pattern, or tail with fewer lines to get more.)";
|
|
54
55
|
function truncateToolResult(content) {
|
|
55
56
|
if (content.length <= MAX_TOOL_RESULT_CHARS)
|
|
@@ -403,12 +404,16 @@ export function Repl({ apiKey, cwd, onQuit }) {
|
|
|
403
404
|
const [showHelpModal, setShowHelpModal] = useState(false);
|
|
404
405
|
const [slashSuggestionIndex, setSlashSuggestionIndex] = useState(0);
|
|
405
406
|
const [inputCursor, setInputCursor] = useState(0);
|
|
407
|
+
const [isInputLayoutFrozen, setIsInputLayoutFrozen] = useState(false);
|
|
408
|
+
const [frozenFooterLines, setFrozenFooterLines] = useState(2);
|
|
406
409
|
const skipNextSubmitRef = useRef(false);
|
|
407
410
|
const queuedMessageRef = useRef(null);
|
|
408
411
|
const lastUserMessageRef = useRef("");
|
|
409
412
|
const [logScrollOffset, setLogScrollOffset] = useState(0);
|
|
410
413
|
const scrollBoundsRef = useRef({ maxLogScrollOffset: 0, logViewportHeight: 1 });
|
|
411
414
|
const prevEscRef = useRef(false);
|
|
415
|
+
const inputChangeMountedRef = useRef(false);
|
|
416
|
+
const typingFreezeTimerRef = useRef(null);
|
|
412
417
|
useEffect(() => {
|
|
413
418
|
// Enable SGR mouse + basic tracking so trackpad wheel scrolling works.
|
|
414
419
|
process.stdout.write("\x1b[?1006h\x1b[?1000h");
|
|
@@ -495,6 +500,28 @@ export function Repl({ apiKey, cwd, onQuit }) {
|
|
|
495
500
|
useEffect(() => {
|
|
496
501
|
setInputCursor((c) => Math.min(c, Math.max(0, inputValue.length)));
|
|
497
502
|
}, [inputValue.length]);
|
|
503
|
+
useEffect(() => {
|
|
504
|
+
if (!inputChangeMountedRef.current) {
|
|
505
|
+
inputChangeMountedRef.current = true;
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
setIsInputLayoutFrozen(true);
|
|
509
|
+
if (typingFreezeTimerRef.current) {
|
|
510
|
+
clearTimeout(typingFreezeTimerRef.current);
|
|
511
|
+
}
|
|
512
|
+
typingFreezeTimerRef.current = setTimeout(() => {
|
|
513
|
+
setIsInputLayoutFrozen(false);
|
|
514
|
+
typingFreezeTimerRef.current = null;
|
|
515
|
+
}, TYPING_LAYOUT_FREEZE_MS);
|
|
516
|
+
}, [inputValue, inputCursor]);
|
|
517
|
+
useEffect(() => {
|
|
518
|
+
return () => {
|
|
519
|
+
if (typingFreezeTimerRef.current) {
|
|
520
|
+
clearTimeout(typingFreezeTimerRef.current);
|
|
521
|
+
typingFreezeTimerRef.current = null;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
}, []);
|
|
498
525
|
useEffect(() => {
|
|
499
526
|
if (apiKey)
|
|
500
527
|
fetchModels(apiKey).then(setModelList);
|
|
@@ -1216,7 +1243,13 @@ export function Repl({ apiKey, cwd, onQuit }) {
|
|
|
1216
1243
|
const leftPad = Math.max(0, Math.floor((termColumns - paletteModalWidth) / 2));
|
|
1217
1244
|
return (_jsxs(Box, { flexDirection: "column", height: termRows, overflow: "hidden", children: [_jsx(Box, { height: topPad }), _jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: leftPad }), _jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: inkColors.primary, paddingX: 2, paddingY: 1, width: paletteModalWidth, minHeight: paletteModalHeight, children: [_jsx(Text, { bold: true, children: " Command palette " }), COMMANDS.map((c, i) => (_jsxs(Text, { color: i === paletteIndex ? inkColors.primary : undefined, children: [i === paletteIndex ? "› " : " ", c.cmd, _jsxs(Text, { color: inkColors.textSecondary, children: [" \u2014 ", c.desc] })] }, c.cmd))), _jsxs(Text, { color: paletteIndex === COMMANDS.length ? inkColors.primary : undefined, children: [paletteIndex === COMMANDS.length ? "› " : " ", "Cancel (Esc)"] }), _jsx(Text, { color: inkColors.textSecondary, children: " \u2191/\u2193 select, Enter confirm, Esc close " })] })] }), _jsx(Box, { flexGrow: 1 })] }));
|
|
1218
1245
|
}
|
|
1219
|
-
const
|
|
1246
|
+
const calculatedFooterLines = suggestionBoxLines + 1 + stableInputLineCount;
|
|
1247
|
+
useEffect(() => {
|
|
1248
|
+
if (!isInputLayoutFrozen) {
|
|
1249
|
+
setFrozenFooterLines(calculatedFooterLines);
|
|
1250
|
+
}
|
|
1251
|
+
}, [isInputLayoutFrozen, calculatedFooterLines]);
|
|
1252
|
+
const footerLines = isInputLayoutFrozen ? frozenFooterLines : calculatedFooterLines;
|
|
1220
1253
|
loadingFooterLinesRef.current = footerLines;
|
|
1221
1254
|
return (_jsxs(Box, { flexDirection: "column", height: termRows, overflow: "hidden", children: [_jsxs(Box, { flexDirection: "column", flexGrow: 1, minHeight: 0, overflow: "hidden", children: [_jsx(LogViewport, { lines: visibleLogLines, startIndex: logStartIndex, height: logViewportHeight }), _jsx(Box, { flexDirection: "row", marginTop: 1, marginBottom: 0, children: _jsx(Text, { color: inkColors.textSecondary, children: "\u00A0" }) })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, height: footerLines, children: [showSlashSuggestions && (_jsxs(Box, { flexDirection: "column", marginBottom: 0, paddingLeft: 2, borderStyle: "single", borderColor: inkColors.textDisabled, children: [filteredSlashCommands.length === 0 ? (_jsx(Text, { color: inkColors.textSecondary, children: " No match " })) : ([...filteredSlashCommands].reverse().map((c, rev) => {
|
|
1222
1255
|
const i = filteredSlashCommands.length - 1 - rev;
|