ideacode 1.3.0 → 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 +41 -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);
|
|
@@ -703,6 +730,13 @@ export function Repl({ apiKey, cwd, onQuit }) {
|
|
|
703
730
|
const runParallelBatch = async (batch) => {
|
|
704
731
|
if (batch.length === 0)
|
|
705
732
|
return;
|
|
733
|
+
if (batch.length === 1) {
|
|
734
|
+
const planned = batch[0];
|
|
735
|
+
setLoadingLabel(`Running ${planned.toolName}…`);
|
|
736
|
+
const result = await runTool(planned.toolName, planned.toolArgs);
|
|
737
|
+
renderToolOutcome(planned, result);
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
706
740
|
setLoadingLabel(`Running ${batch.length} tools in parallel…`);
|
|
707
741
|
const started = Date.now();
|
|
708
742
|
const groupedTools = Array.from(batch.reduce((acc, planned) => {
|
|
@@ -1209,7 +1243,13 @@ export function Repl({ apiKey, cwd, onQuit }) {
|
|
|
1209
1243
|
const leftPad = Math.max(0, Math.floor((termColumns - paletteModalWidth) / 2));
|
|
1210
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 })] }));
|
|
1211
1245
|
}
|
|
1212
|
-
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;
|
|
1213
1253
|
loadingFooterLinesRef.current = footerLines;
|
|
1214
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) => {
|
|
1215
1255
|
const i = filteredSlashCommands.length - 1 - rev;
|