orquesta-cli 0.2.112 → 0.2.115
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/ui/TodoPanel.js +1 -1
- package/dist/ui/components/ActivityIndicator.js +5 -5
- package/dist/ui/components/CustomTextInput.d.ts +1 -0
- package/dist/ui/components/CustomTextInput.js +7 -1
- package/dist/ui/components/PlanExecuteApp.js +37 -28
- package/dist/ui/components/StreamingOutput.d.ts +1 -0
- package/dist/ui/components/StreamingOutput.js +5 -3
- package/dist/ui/ink-entry.js +17 -0
- package/package.json +1 -1
package/dist/ui/TodoPanel.js
CHANGED
|
@@ -91,7 +91,7 @@ export const TodoPanel = React.memo(({ todos, currentTodoId, isProcessing = fals
|
|
|
91
91
|
React.createElement(Box, null,
|
|
92
92
|
React.createElement(Box, { width: 2 }, isInProgress && isProcessing ? (React.createElement(Text, { color: "blueBright" },
|
|
93
93
|
React.createElement(Spinner, { type: "dots2" }))) : (React.createElement(Text, { color: config.color }, config.icon))),
|
|
94
|
-
React.createElement(Text, { color: isCompleted ? 'gray' : isInProgress ? 'white' : 'gray', bold: isInProgress,
|
|
94
|
+
React.createElement(Text, { color: isCompleted ? 'gray' : isInProgress ? 'white' : 'gray', bold: isInProgress, strikethrough: isCompleted }, todo.title),
|
|
95
95
|
isInProgress && isProcessing && (React.createElement(Text, { color: "blueBright" }, " \u2190"))),
|
|
96
96
|
todo.error && (React.createElement(Box, { marginLeft: 2 },
|
|
97
97
|
React.createElement(Text, { color: "red", dimColor: true },
|
|
@@ -86,9 +86,9 @@ export const ActivityIndicator = ({ activity, startTime, detail, subActivities =
|
|
|
86
86
|
formatTime(elapsedSeconds)),
|
|
87
87
|
renderProgressBar()),
|
|
88
88
|
detail && (React.createElement(Box, { marginLeft: 2 },
|
|
89
|
-
React.createElement(Text, { color: "
|
|
89
|
+
React.createElement(Text, { color: "cyan" }, detail))),
|
|
90
90
|
stepName && (React.createElement(Box, { marginLeft: 2 },
|
|
91
|
-
React.createElement(Text, { color: "gray"
|
|
91
|
+
React.createElement(Text, { color: "gray" },
|
|
92
92
|
currentStep,
|
|
93
93
|
"/",
|
|
94
94
|
totalSteps,
|
|
@@ -98,15 +98,15 @@ export const ActivityIndicator = ({ activity, startTime, detail, subActivities =
|
|
|
98
98
|
const subInfo = ACTIVITY_INFO[sub.type];
|
|
99
99
|
return (React.createElement(Box, { key: idx },
|
|
100
100
|
getStatusIcon(sub.status),
|
|
101
|
-
React.createElement(Text, { color: "gray"
|
|
101
|
+
React.createElement(Text, { color: "gray" },
|
|
102
102
|
" ",
|
|
103
103
|
subInfo.label),
|
|
104
|
-
sub.detail && React.createElement(Text, { color: "
|
|
104
|
+
sub.detail && React.createElement(Text, { color: "white" },
|
|
105
105
|
": ",
|
|
106
106
|
sub.detail)));
|
|
107
107
|
}))),
|
|
108
108
|
tokenCount !== undefined && (React.createElement(Box, { marginLeft: 2 },
|
|
109
|
-
React.createElement(Text, { color: "gray"
|
|
109
|
+
React.createElement(Text, { color: "gray" },
|
|
110
110
|
formatTokens(tokenCount),
|
|
111
111
|
" tokens",
|
|
112
112
|
tokensPerSecond !== undefined && tokensPerSecond > 0 && ` · ${tokensPerSecond.toFixed(0)} tok/s`)))));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { Box, Text, useStdin } from 'ink';
|
|
3
3
|
const MULTILINE_COLLAPSE_THRESHOLD = 10;
|
|
4
|
-
export const CustomTextInput = ({ value, onChange, onSubmit, onHistoryPrev, onHistoryNext, placeholder = '', focus = true, }) => {
|
|
4
|
+
export const CustomTextInput = ({ value, onChange, onSubmit, onCtrlS, onHistoryPrev, onHistoryNext, placeholder = '', focus = true, }) => {
|
|
5
5
|
const { stdin, setRawMode } = useStdin();
|
|
6
6
|
const [cursorPosition, setCursorPosition] = useState(value.length);
|
|
7
7
|
const previousValueLength = useRef(value.length);
|
|
@@ -10,6 +10,7 @@ export const CustomTextInput = ({ value, onChange, onSubmit, onHistoryPrev, onHi
|
|
|
10
10
|
const cursorPositionRef = useRef(cursorPosition);
|
|
11
11
|
const onChangeRef = useRef(onChange);
|
|
12
12
|
const onSubmitRef = useRef(onSubmit);
|
|
13
|
+
const onCtrlSRef = useRef(onCtrlS);
|
|
13
14
|
const onHistoryPrevRef = useRef(onHistoryPrev);
|
|
14
15
|
const onHistoryNextRef = useRef(onHistoryNext);
|
|
15
16
|
const setIsCollapsedViewRef = useRef(setIsCollapsedView);
|
|
@@ -19,6 +20,7 @@ export const CustomTextInput = ({ value, onChange, onSubmit, onHistoryPrev, onHi
|
|
|
19
20
|
cursorPositionRef.current = cursorPosition;
|
|
20
21
|
onChangeRef.current = onChange;
|
|
21
22
|
onSubmitRef.current = onSubmit;
|
|
23
|
+
onCtrlSRef.current = onCtrlS;
|
|
22
24
|
onHistoryPrevRef.current = onHistoryPrev;
|
|
23
25
|
onHistoryNextRef.current = onHistoryNext;
|
|
24
26
|
setIsCollapsedViewRef.current = setIsCollapsedView;
|
|
@@ -49,6 +51,10 @@ export const CustomTextInput = ({ value, onChange, onSubmit, onHistoryPrev, onHi
|
|
|
49
51
|
const str = data.toString();
|
|
50
52
|
const currentValue = valueRef.current;
|
|
51
53
|
const currentCursor = cursorPositionRef.current;
|
|
54
|
+
if (str === '\x13') {
|
|
55
|
+
onCtrlSRef.current?.(currentValue);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
52
58
|
const deleteWordBeforeCursor = (value, cursor) => {
|
|
53
59
|
if (cursor > 0) {
|
|
54
60
|
const beforeCursor = value.slice(0, cursor);
|
|
@@ -50,7 +50,7 @@ const require = createRequire(import.meta.url);
|
|
|
50
50
|
const pkg = require('../../../package.json');
|
|
51
51
|
const VERSION = pkg.version;
|
|
52
52
|
const TOOLS_REQUIRING_APPROVAL = new Set(['create_file', 'edit_file', 'bash']);
|
|
53
|
-
const STARTUP_TIP = 'Type /help for
|
|
53
|
+
const STARTUP_TIP = 'Type /help for commands, /model to switch models. Press Ctrl+S to send now (or steer the AI mid-task).';
|
|
54
54
|
function shortenPath(fullPath) {
|
|
55
55
|
const homeDir = os.homedir();
|
|
56
56
|
if (fullPath.startsWith(homeDir)) {
|
|
@@ -640,30 +640,33 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
640
640
|
if (key.ctrl && inputChar === 'o') {
|
|
641
641
|
setShowLogFiles(prev => !prev);
|
|
642
642
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
}
|
|
653
|
-
const text = input.trim();
|
|
654
|
-
if (text) {
|
|
655
|
-
if (isProcessing) {
|
|
656
|
-
addLog({ type: 'user_input', content: `(⚡ steering now — picked up at next step) ${text}` });
|
|
657
|
-
setPendingUserMessage(text);
|
|
658
|
-
setInput('');
|
|
659
|
-
}
|
|
660
|
-
else {
|
|
661
|
-
handleSubmitRef.current?.(text);
|
|
662
|
-
}
|
|
663
|
-
}
|
|
643
|
+
});
|
|
644
|
+
const handleCtrlS = useCallback((rawValue) => {
|
|
645
|
+
if (showSessionBrowser ||
|
|
646
|
+
showSettings ||
|
|
647
|
+
showSetupWizard ||
|
|
648
|
+
fileBrowserState.showFileBrowser ||
|
|
649
|
+
commandBrowserState.showCommandBrowser ||
|
|
650
|
+
planExecutionState.askUserRequest ||
|
|
651
|
+
pendingToolApproval) {
|
|
664
652
|
return;
|
|
665
653
|
}
|
|
666
|
-
|
|
654
|
+
const text = (rawValue ?? '').trim();
|
|
655
|
+
if (!text)
|
|
656
|
+
return;
|
|
657
|
+
if (isProcessing) {
|
|
658
|
+
addLog({ type: 'user_input', content: `(⚡ Ctrl+S — steering now, picked up at next step) ${text}` });
|
|
659
|
+
setPendingUserMessage(text);
|
|
660
|
+
setInput('');
|
|
661
|
+
}
|
|
662
|
+
else {
|
|
663
|
+
handleSubmitRef.current?.(text);
|
|
664
|
+
}
|
|
665
|
+
}, [
|
|
666
|
+
showSessionBrowser, showSettings, showSetupWizard,
|
|
667
|
+
fileBrowserState.showFileBrowser, commandBrowserState.showCommandBrowser,
|
|
668
|
+
planExecutionState.askUserRequest, pendingToolApproval, isProcessing, addLog,
|
|
669
|
+
]);
|
|
667
670
|
const handleFileSelect = useCallback((filePaths) => {
|
|
668
671
|
logger.debug('File selected', { filePaths });
|
|
669
672
|
const newInput = fileBrowserState.handleFileSelect(filePaths, input);
|
|
@@ -1348,6 +1351,7 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1348
1351
|
: reason;
|
|
1349
1352
|
return (React.createElement(Box, { key: entry.id, flexDirection: "column", marginTop: 1 },
|
|
1350
1353
|
React.createElement(Box, null,
|
|
1354
|
+
React.createElement(Text, { color: "gray", dimColor: true }, "\u2502 "),
|
|
1351
1355
|
React.createElement(Text, { color: "cyan", bold: true },
|
|
1352
1356
|
icon,
|
|
1353
1357
|
" ",
|
|
@@ -1421,9 +1425,11 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1421
1425
|
". ",
|
|
1422
1426
|
item))))));
|
|
1423
1427
|
case 'todo_start':
|
|
1424
|
-
return (React.createElement(Box, { key: entry.id, marginTop: 1 },
|
|
1425
|
-
React.createElement(Text, { color: "
|
|
1426
|
-
React.createElement(
|
|
1428
|
+
return (React.createElement(Box, { key: entry.id, flexDirection: "column", marginTop: 1 },
|
|
1429
|
+
React.createElement(Text, { color: "gray", dimColor: true }, '─'.repeat(44)),
|
|
1430
|
+
React.createElement(Box, null,
|
|
1431
|
+
React.createElement(Text, { color: "blue", bold: true }, "\uD83C\uDFB5 \u25B6 "),
|
|
1432
|
+
React.createElement(Text, { bold: true }, entry.content))));
|
|
1427
1433
|
case 'todo_complete':
|
|
1428
1434
|
return (React.createElement(Box, { key: entry.id, marginLeft: 2 },
|
|
1429
1435
|
React.createElement(Text, { color: "white" }, "\u23BF "),
|
|
@@ -1489,7 +1495,7 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1489
1495
|
React.createElement(ActivityIndicator, { activity: getCurrentActivityType(), startTime: activityStartTime, detail: activityDetail || currentToolName || '', subActivities: subActivities, modelName: currentModelInfo.model }),
|
|
1490
1496
|
streamingText && (React.createElement(StreamingOutput, { text: streamingText })))),
|
|
1491
1497
|
isDocsSearching && (React.createElement(DocsSearchProgress, { logs: docsSearchLogs, isSearching: isDocsSearching })),
|
|
1492
|
-
planExecutionState.todos.length > 0 && (React.createElement(Box, { marginTop:
|
|
1498
|
+
planExecutionState.todos.length > 0 && (React.createElement(Box, { marginTop: 1 },
|
|
1493
1499
|
React.createElement(TodoPanel, { todos: planExecutionState.todos, currentTodoId: planExecutionState.currentTodoId, isProcessing: isProcessing }))),
|
|
1494
1500
|
updatePhase === 'available' && (React.createElement(UpdateNotification, { currentVersion: VERSION, latestVersion: updateLatest })),
|
|
1495
1501
|
updatePhase === 'updating' && (React.createElement(UpdateNotification, { currentVersion: VERSION, latestVersion: updateLatest, isUpdating: true, updateProgress: updateProgress })),
|
|
@@ -1508,7 +1514,7 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1508
1514
|
return;
|
|
1509
1515
|
}
|
|
1510
1516
|
setInput(value);
|
|
1511
|
-
}, onSubmit: handleSubmit, onHistoryPrev: isAnyPanelOpen ? undefined : handleHistoryPrev, onHistoryNext: isAnyPanelOpen ? undefined : handleHistoryNext, placeholder: isProcessing
|
|
1517
|
+
}, onSubmit: handleSubmit, onCtrlS: handleCtrlS, onHistoryPrev: isAnyPanelOpen ? undefined : handleHistoryPrev, onHistoryNext: isAnyPanelOpen ? undefined : handleHistoryNext, placeholder: isProcessing
|
|
1512
1518
|
? "AI is working... (type + Ctrl+S to steer now)"
|
|
1513
1519
|
: showSessionBrowser
|
|
1514
1520
|
? "Select a session or press ESC..."
|
|
@@ -1518,6 +1524,9 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1518
1524
|
? "Select a doc source or press ESC..."
|
|
1519
1525
|
: "Type your message... (@ files, / commands, Alt+Enter newline, Ctrl+S send)", focus: !showSessionBrowser && !showSettings && !showDocsBrowser && !planExecutionState.askUserRequest && updatePhase === 'hidden' })),
|
|
1520
1526
|
input.length > 0 && (React.createElement(Text, { color: input.length > 4000 ? 'red' : input.length > 2000 ? 'yellow' : 'gray', dimColor: true }, input.length.toLocaleString())))),
|
|
1527
|
+
isProcessing && input.trim().length > 0 && (React.createElement(Box, { paddingX: 1 },
|
|
1528
|
+
React.createElement(Text, { color: "yellow", bold: true }, "\u26A1 Ctrl+S"),
|
|
1529
|
+
React.createElement(Text, { color: "gray" }, " to send now, or Enter to queue for the next step"))),
|
|
1521
1530
|
fileBrowserState.showFileBrowser && !isProcessing && (React.createElement(Box, { marginTop: 0 }, fileBrowserState.isLoadingFiles ? (React.createElement(Box, { borderStyle: "single", borderColor: "yellow", paddingX: 1 },
|
|
1522
1531
|
React.createElement(Spinner, { type: "dots" }),
|
|
1523
1532
|
React.createElement(Text, { color: "yellow" }, " Loading files..."))) : (React.createElement(FileBrowser, { filter: fileBrowserState.filterText, onSelect: handleFileSelect, onCancel: fileBrowserState.handleFileBrowserCancel, cachedFiles: fileBrowserState.cachedFileList })))),
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
-
export const StreamingOutput = ({ text }) => {
|
|
3
|
+
export const StreamingOutput = ({ text, height = 3 }) => {
|
|
4
4
|
if (!text)
|
|
5
5
|
return null;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const tail = text.split('\n').slice(-height);
|
|
7
|
+
const pad = Array(Math.max(0, height - tail.length)).fill('');
|
|
8
|
+
const rows = [...pad, ...tail];
|
|
9
|
+
return (React.createElement(Box, { paddingX: 1, flexDirection: "column", height: height }, rows.map((line, i) => (React.createElement(Text, { key: i, wrap: "truncate-end" }, line || ' ')))));
|
|
8
10
|
};
|
|
9
11
|
//# sourceMappingURL=StreamingOutput.js.map
|
package/dist/ui/ink-entry.js
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
3
4
|
import { render } from 'ink';
|
|
4
5
|
import { PlanExecuteApp } from './components/PlanExecuteApp.js';
|
|
5
6
|
import { createLLMClient } from '../core/llm/llm-client.js';
|
|
6
7
|
import { configManager } from '../core/config/config-manager.js';
|
|
7
8
|
import { initializeOptionalTools } from '../tools/registry.js';
|
|
8
9
|
import { logger } from '../utils/logger.js';
|
|
10
|
+
function disableFlowControl() {
|
|
11
|
+
if (process.platform === 'win32' || !process.stdin.isTTY)
|
|
12
|
+
return;
|
|
13
|
+
try {
|
|
14
|
+
execSync('stty -ixon', { stdio: 'inherit' });
|
|
15
|
+
process.on('exit', () => {
|
|
16
|
+
try {
|
|
17
|
+
execSync('stty ixon', { stdio: 'inherit' });
|
|
18
|
+
}
|
|
19
|
+
catch { }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
}
|
|
24
|
+
}
|
|
9
25
|
(async () => {
|
|
10
26
|
try {
|
|
27
|
+
disableFlowControl();
|
|
11
28
|
await configManager.initialize();
|
|
12
29
|
await initializeOptionalTools();
|
|
13
30
|
const llmClient = createLLMClient();
|