orquesta-cli 0.2.111 → 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/core/commands/help.js +1 -0
- 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 +40 -8
- 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)) {
|
|
@@ -641,6 +641,32 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
641
641
|
setShowLogFiles(prev => !prev);
|
|
642
642
|
}
|
|
643
643
|
});
|
|
644
|
+
const handleCtrlS = useCallback((rawValue) => {
|
|
645
|
+
if (showSessionBrowser ||
|
|
646
|
+
showSettings ||
|
|
647
|
+
showSetupWizard ||
|
|
648
|
+
fileBrowserState.showFileBrowser ||
|
|
649
|
+
commandBrowserState.showCommandBrowser ||
|
|
650
|
+
planExecutionState.askUserRequest ||
|
|
651
|
+
pendingToolApproval) {
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
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
|
+
]);
|
|
644
670
|
const handleFileSelect = useCallback((filePaths) => {
|
|
645
671
|
logger.debug('File selected', { filePaths });
|
|
646
672
|
const newInput = fileBrowserState.handleFileSelect(filePaths, input);
|
|
@@ -1325,6 +1351,7 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1325
1351
|
: reason;
|
|
1326
1352
|
return (React.createElement(Box, { key: entry.id, flexDirection: "column", marginTop: 1 },
|
|
1327
1353
|
React.createElement(Box, null,
|
|
1354
|
+
React.createElement(Text, { color: "gray", dimColor: true }, "\u2502 "),
|
|
1328
1355
|
React.createElement(Text, { color: "cyan", bold: true },
|
|
1329
1356
|
icon,
|
|
1330
1357
|
" ",
|
|
@@ -1398,9 +1425,11 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1398
1425
|
". ",
|
|
1399
1426
|
item))))));
|
|
1400
1427
|
case 'todo_start':
|
|
1401
|
-
return (React.createElement(Box, { key: entry.id, marginTop: 1 },
|
|
1402
|
-
React.createElement(Text, { color: "
|
|
1403
|
-
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))));
|
|
1404
1433
|
case 'todo_complete':
|
|
1405
1434
|
return (React.createElement(Box, { key: entry.id, marginLeft: 2 },
|
|
1406
1435
|
React.createElement(Text, { color: "white" }, "\u23BF "),
|
|
@@ -1466,7 +1495,7 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1466
1495
|
React.createElement(ActivityIndicator, { activity: getCurrentActivityType(), startTime: activityStartTime, detail: activityDetail || currentToolName || '', subActivities: subActivities, modelName: currentModelInfo.model }),
|
|
1467
1496
|
streamingText && (React.createElement(StreamingOutput, { text: streamingText })))),
|
|
1468
1497
|
isDocsSearching && (React.createElement(DocsSearchProgress, { logs: docsSearchLogs, isSearching: isDocsSearching })),
|
|
1469
|
-
planExecutionState.todos.length > 0 && (React.createElement(Box, { marginTop:
|
|
1498
|
+
planExecutionState.todos.length > 0 && (React.createElement(Box, { marginTop: 1 },
|
|
1470
1499
|
React.createElement(TodoPanel, { todos: planExecutionState.todos, currentTodoId: planExecutionState.currentTodoId, isProcessing: isProcessing }))),
|
|
1471
1500
|
updatePhase === 'available' && (React.createElement(UpdateNotification, { currentVersion: VERSION, latestVersion: updateLatest })),
|
|
1472
1501
|
updatePhase === 'updating' && (React.createElement(UpdateNotification, { currentVersion: VERSION, latestVersion: updateLatest, isUpdating: true, updateProgress: updateProgress })),
|
|
@@ -1485,16 +1514,19 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
|
|
|
1485
1514
|
return;
|
|
1486
1515
|
}
|
|
1487
1516
|
setInput(value);
|
|
1488
|
-
}, onSubmit: handleSubmit, onHistoryPrev: isAnyPanelOpen ? undefined : handleHistoryPrev, onHistoryNext: isAnyPanelOpen ? undefined : handleHistoryNext, placeholder: isProcessing
|
|
1489
|
-
? "AI is working..."
|
|
1517
|
+
}, onSubmit: handleSubmit, onCtrlS: handleCtrlS, onHistoryPrev: isAnyPanelOpen ? undefined : handleHistoryPrev, onHistoryNext: isAnyPanelOpen ? undefined : handleHistoryNext, placeholder: isProcessing
|
|
1518
|
+
? "AI is working... (type + Ctrl+S to steer now)"
|
|
1490
1519
|
: showSessionBrowser
|
|
1491
1520
|
? "Select a session or press ESC..."
|
|
1492
1521
|
: showSettings
|
|
1493
1522
|
? "Press ESC to close settings..."
|
|
1494
1523
|
: showDocsBrowser
|
|
1495
1524
|
? "Select a doc source or press ESC..."
|
|
1496
|
-
: "Type your message... (@ files, / commands, Alt+Enter newline)", focus: !showSessionBrowser && !showSettings && !showDocsBrowser && !planExecutionState.askUserRequest && updatePhase === 'hidden' })),
|
|
1525
|
+
: "Type your message... (@ files, / commands, Alt+Enter newline, Ctrl+S send)", focus: !showSessionBrowser && !showSettings && !showDocsBrowser && !planExecutionState.askUserRequest && updatePhase === 'hidden' })),
|
|
1497
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"))),
|
|
1498
1530
|
fileBrowserState.showFileBrowser && !isProcessing && (React.createElement(Box, { marginTop: 0 }, fileBrowserState.isLoadingFiles ? (React.createElement(Box, { borderStyle: "single", borderColor: "yellow", paddingX: 1 },
|
|
1499
1531
|
React.createElement(Spinner, { type: "dots" }),
|
|
1500
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();
|