@robota-sdk/agent-transport 3.0.0-beta.64 → 3.0.0-beta.66
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/README.md +97 -0
- package/dist/node/chunk-Bmb41Sf3.cjs +1 -0
- package/dist/node/headless/index.cjs +1 -1
- package/dist/node/headless/index.d.ts +2 -2
- package/dist/node/headless/index.js +1 -1
- package/dist/node/headless-B8yWkXW_.js +15 -0
- package/dist/node/headless-B8yWkXW_.js.map +1 -0
- package/dist/node/headless-Dp3kQVmo.cjs +14 -0
- package/dist/node/http/index.cjs +1 -1
- package/dist/node/http/index.d.ts +1 -1
- package/dist/node/http/index.js +1 -1
- package/dist/node/{http-DwO1AHG-.js → http-Br10Ps8m.js} +1 -1
- package/dist/node/http-Br10Ps8m.js.map +1 -0
- package/dist/node/http-Da6Kw4oy.cjs +1 -0
- package/dist/node/{index-Y0zHb1Bz.d.ts → index-C5KNEBO9.d.ts} +1 -1
- package/dist/node/{index-B_rcr14p.d.ts.map → index-C5KNEBO9.d.ts.map} +1 -1
- package/dist/node/{index-B_rcr14p.d.ts → index-C7DvsmEg.d.ts} +2 -2
- package/dist/node/{index-Y0zHb1Bz.d.ts.map → index-C7DvsmEg.d.ts.map} +1 -1
- package/dist/node/index-C9LWCL4l.d.ts.map +1 -1
- package/dist/node/{index-D34WUfFH.d.ts → index-CP7kaYMg.d.ts} +17 -2
- package/dist/node/index-CP7kaYMg.d.ts.map +1 -0
- package/dist/node/{index-CAr3ioVh.d.ts → index-CQsMNXAh.d.ts} +19 -16
- package/dist/node/index-CQsMNXAh.d.ts.map +1 -0
- package/dist/node/{index-nBlMTFkZ.d.ts → index-DOA2KIYt.d.ts} +2 -2
- package/dist/node/{index-nBlMTFkZ.d.ts.map → index-DOA2KIYt.d.ts.map} +1 -1
- package/dist/node/{index-k3TUjA-T.d.ts → index-Gby9H4q2.d.ts} +17 -2
- package/dist/node/index-Gby9H4q2.d.ts.map +1 -0
- package/dist/node/{index-CEs25wVk.d.ts → index-X2Zg8FEY.d.ts} +2 -2
- package/dist/node/{index-CEs25wVk.d.ts.map → index-X2Zg8FEY.d.ts.map} +1 -1
- package/dist/node/{index--Ti9NzQX.d.ts → index-rGmGTQ9o.d.ts} +19 -16
- package/dist/node/index-rGmGTQ9o.d.ts.map +1 -0
- package/dist/node/{index-CvXLpjJO.d.ts → index-yvGShbDx.d.ts} +2 -2
- package/dist/node/{index-CvXLpjJO.d.ts.map → index-yvGShbDx.d.ts.map} +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.ts +28 -6
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +2 -1
- package/dist/node/index.js.map +1 -0
- package/dist/node/mcp/index.cjs +1 -1
- package/dist/node/mcp/index.d.ts +1 -1
- package/dist/node/mcp/index.js +1 -1
- package/dist/node/{mcp-BXBwF6Wu.js → mcp-BAujHOMr.js} +1 -1
- package/dist/node/mcp-BAujHOMr.js.map +1 -0
- package/dist/node/mcp-Bl8jUfev.cjs +1 -0
- package/dist/node/tui/index.cjs +1 -1
- package/dist/node/tui/index.d.ts +2 -2
- package/dist/node/tui/index.js +1 -1
- package/dist/node/tui-B8G3yHrL.cjs +24 -0
- package/dist/node/tui-DUIfVw3G.js +25 -0
- package/dist/node/tui-DUIfVw3G.js.map +1 -0
- package/dist/node/ws/index.cjs +1 -1
- package/dist/node/ws/index.d.ts +1 -1
- package/dist/node/ws/index.js +1 -1
- package/dist/node/{ws-B-oRccFl.js → ws-BWel8nzl.js} +1 -1
- package/dist/node/ws-BWel8nzl.js.map +1 -0
- package/dist/node/ws-tCjj2gPu.cjs +1 -0
- package/package.json +19 -18
- package/src/headless/cli-input.ts +50 -0
- package/src/headless/headless-runner.ts +2 -1
- package/src/headless/headless-stream-json.ts +1 -0
- package/src/headless/headless-transport.ts +3 -2
- package/src/headless/index.ts +2 -0
- package/src/headless/print-terminal.ts +57 -0
- package/src/http/http-transport.ts +3 -3
- package/src/http/routes.ts +2 -1
- package/src/index.ts +2 -1
- package/src/mcp/mcp-server.ts +1 -0
- package/src/mcp/mcp-transport.ts +3 -2
- package/src/transport-registry.ts +100 -0
- package/src/tui/App.tsx +52 -31
- package/src/tui/BackgroundTaskPanel.tsx +4 -2
- package/src/tui/CjkTextInput.tsx +3 -2
- package/src/tui/ConfirmPrompt.tsx +2 -1
- package/src/tui/ExecutionWorkspaceDetailPane.tsx +7 -5
- package/src/tui/ExecutionWorkspaceSwitcher.tsx +8 -6
- package/src/tui/InputArea.tsx +72 -12
- package/src/tui/InteractivePrompt.tsx +5 -3
- package/src/tui/ListPicker.tsx +2 -1
- package/src/tui/MenuSelect.tsx +2 -1
- package/src/tui/MessageList.tsx +8 -6
- package/src/tui/PermissionPrompt.tsx +5 -3
- package/src/tui/PluginTUI.tsx +5 -3
- package/src/tui/SessionPicker.tsx +4 -2
- package/src/tui/SessionStatusBar.tsx +7 -3
- package/src/tui/SlashAutocomplete.tsx +6 -6
- package/src/tui/StatusBar.tsx +5 -3
- package/src/tui/StreamingIndicator.tsx +4 -2
- package/src/tui/TextPrompt.tsx +2 -1
- package/src/tui/ToolCommandOutput.tsx +4 -2
- package/src/tui/ToolDiffBlock.tsx +4 -2
- package/src/tui/TransportTUI.tsx +3 -2
- package/src/tui/UpdateNotice.tsx +1 -1
- package/src/tui/UsageSummaryEntry.tsx +3 -2
- package/src/tui/WaveText.tsx +1 -1
- package/src/tui/__tests__/fixtures/provider-setup-prompt-driver.tsx +7 -4
- package/src/tui/__tests__/input-area-flow.test.ts +19 -0
- package/src/tui/background-task-row-format.ts +2 -1
- package/src/tui/command-interaction-registry.ts +66 -0
- package/src/tui/command-interaction.ts +9 -0
- package/src/tui/create-default-tui-cli-adapter.ts +42 -0
- package/src/tui/flows/input-area-flow.ts +10 -2
- package/src/tui/hooks/command-effect-handler.ts +4 -3
- package/src/tui/hooks/side-effects-types.ts +1 -1
- package/src/tui/hooks/use-interactive-session-init.ts +4 -2
- package/src/tui/hooks/useAutocomplete.ts +1 -0
- package/src/tui/hooks/useInteractiveSession.ts +22 -19
- package/src/tui/hooks/usePermissionQueue.ts +2 -1
- package/src/tui/hooks/usePluginCallbacks.ts +1 -0
- package/src/tui/hooks/usePluginScreenData.ts +2 -1
- package/src/tui/hooks/useSideEffects.ts +8 -6
- package/src/tui/hooks/useSlashRouting.ts +4 -3
- package/src/tui/hooks/useStatusLineSettings.ts +4 -2
- package/src/tui/index.ts +11 -1
- package/src/tui/interactions/CommandConfirm.tsx +36 -0
- package/src/tui/interactions/CommandPicker.tsx +77 -0
- package/src/tui/render-markdown.ts +2 -1
- package/src/tui/render.tsx +12 -26
- package/src/tui/tui-cli-adapter-context.tsx +1 -0
- package/src/tui/tui-cli-adapter.ts +1 -1
- package/src/tui/tui-transport.ts +5 -4
- package/src/tui/utils/edit-diff.ts +1 -0
- package/src/tui/utils/tool-call-extractor.ts +1 -0
- package/src/ws/ws-background-messages.ts +1 -1
- package/src/ws/ws-handler.ts +6 -5
- package/src/ws/ws-transport-configurable.ts +6 -3
- package/src/ws/ws-transport.ts +3 -2
- package/dist/node/headless-CWEpJXFK.js +0 -7
- package/dist/node/headless-CWEpJXFK.js.map +0 -1
- package/dist/node/headless-CsZFelG9.cjs +0 -6
- package/dist/node/http-CM3TJhrF.cjs +0 -1
- package/dist/node/http-DwO1AHG-.js.map +0 -1
- package/dist/node/index--Ti9NzQX.d.ts.map +0 -1
- package/dist/node/index-CAr3ioVh.d.ts.map +0 -1
- package/dist/node/index-D34WUfFH.d.ts.map +0 -1
- package/dist/node/index-k3TUjA-T.d.ts.map +0 -1
- package/dist/node/mcp-BXBwF6Wu.js.map +0 -1
- package/dist/node/mcp-DcHuGokt.cjs +0 -1
- package/dist/node/tui-CeD_6rSo.cjs +0 -24
- package/dist/node/tui-zmDTPk4b.js +0 -25
- package/dist/node/tui-zmDTPk4b.js.map +0 -1
- package/dist/node/ws-B-oRccFl.js.map +0 -1
- package/dist/node/ws-COnIgnmn.cjs +0 -1
package/src/tui/CjkTextInput.tsx
CHANGED
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
* Drop-in replacement: same props as ink-text-input.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import React, { useRef, useState } from 'react';
|
|
15
|
-
import { Text, useInput, usePaste } from 'ink';
|
|
16
14
|
import chalk from 'chalk';
|
|
15
|
+
import { Text, useInput, usePaste } from 'ink';
|
|
16
|
+
import React, { useRef, useState } from 'react';
|
|
17
|
+
|
|
17
18
|
import {
|
|
18
19
|
applyCjkTextInput,
|
|
19
20
|
applyCjkTextPaste,
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* Used by model change, permission prompts, and other yes/no confirmations.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React, { useState, useRef, useCallback } from 'react';
|
|
7
6
|
import { Box, Text, useInput } from 'ink';
|
|
7
|
+
import React, { useState, useRef, useCallback } from 'react';
|
|
8
|
+
|
|
8
9
|
import {
|
|
9
10
|
applyConfirmPromptInput,
|
|
10
11
|
getConfirmPromptInputAction,
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { Box, Text } from 'ink';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
formatExecutionDetailRecord,
|
|
6
|
+
formatExecutionWorkspaceEntryRow,
|
|
7
|
+
} from './execution-workspace-view-model.js';
|
|
8
|
+
|
|
3
9
|
import type {
|
|
4
10
|
IExecutionDetailPage,
|
|
5
11
|
IExecutionWorkspaceEntry,
|
|
6
12
|
TExecutionDetailRecordKind,
|
|
7
13
|
} from '@robota-sdk/agent-framework';
|
|
8
|
-
import {
|
|
9
|
-
formatExecutionDetailRecord,
|
|
10
|
-
formatExecutionWorkspaceEntryRow,
|
|
11
|
-
} from './execution-workspace-view-model.js';
|
|
12
14
|
|
|
13
15
|
const MAX_VISIBLE_DETAIL_RECORDS = 12;
|
|
14
16
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
2
1
|
import { Box, Text, useInput } from 'ink';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from '@robota-sdk/agent-framework';
|
|
2
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { formatExecutionWorkspaceEntryRow } from './execution-workspace-view-model.js';
|
|
7
5
|
import {
|
|
8
6
|
applySelectionInput,
|
|
9
7
|
createSelectionFlowState,
|
|
@@ -12,7 +10,11 @@ import {
|
|
|
12
10
|
type ISelectionFlowState,
|
|
13
11
|
type TSelectionInputAction,
|
|
14
12
|
} from './flows/selection-flow.js';
|
|
15
|
-
|
|
13
|
+
|
|
14
|
+
import type {
|
|
15
|
+
IExecutionWorkspaceEntry,
|
|
16
|
+
IExecutionWorkspaceSnapshot,
|
|
17
|
+
} from '@robota-sdk/agent-framework';
|
|
16
18
|
|
|
17
19
|
const MAX_VISIBLE_WORKSPACE_ENTRIES = 8;
|
|
18
20
|
|
package/src/tui/InputArea.tsx
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { Box, Text, useInput, useWindowSize } from 'ink';
|
|
1
2
|
import React, { useState, useCallback, useRef, useMemo } from 'react';
|
|
2
3
|
|
|
3
4
|
const PENDING_PROMPT_DISPLAY_MAX = 50;
|
|
4
5
|
const PENDING_PROMPT_TAIL_KEEP = 47;
|
|
5
|
-
|
|
6
|
-
import type { IHistoryEntry } from '@robota-sdk/agent-core';
|
|
7
|
-
import type { CommandRegistry, ICommand } from '@robota-sdk/agent-framework';
|
|
6
|
+
|
|
8
7
|
import CjkTextInput from './CjkTextInput.js';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
import { resolveCommandInteraction } from './command-interaction-registry.js';
|
|
9
|
+
import {
|
|
10
|
+
isPickerInteraction,
|
|
11
|
+
isConfirmInteraction,
|
|
12
|
+
type ITuiCommandInteraction,
|
|
13
|
+
type ITuiPickerItem,
|
|
14
|
+
} from './command-interaction.js';
|
|
13
15
|
import {
|
|
14
16
|
appendPromptHistory,
|
|
15
17
|
createPasteLabelChange,
|
|
@@ -24,6 +26,20 @@ import {
|
|
|
24
26
|
resolveTabCompletion,
|
|
25
27
|
shouldSubmitInput,
|
|
26
28
|
} from './flows/input-area-flow.js';
|
|
29
|
+
import { useAutocomplete } from './hooks/useAutocomplete.js';
|
|
30
|
+
import CommandConfirm from './interactions/CommandConfirm.js';
|
|
31
|
+
import CommandPicker from './interactions/CommandPicker.js';
|
|
32
|
+
import SlashAutocomplete from './SlashAutocomplete.js';
|
|
33
|
+
import { expandPasteLabels } from './utils/paste-labels.js';
|
|
34
|
+
import WaveText from './WaveText.js';
|
|
35
|
+
|
|
36
|
+
import type { IHistoryEntry } from '@robota-sdk/agent-core';
|
|
37
|
+
import type { CommandRegistry, ICommand } from '@robota-sdk/agent-framework';
|
|
38
|
+
|
|
39
|
+
interface IActiveInteraction {
|
|
40
|
+
commandName: string;
|
|
41
|
+
interaction: ITuiCommandInteraction;
|
|
42
|
+
}
|
|
27
43
|
|
|
28
44
|
interface IProps {
|
|
29
45
|
onSubmit: (value: string) => void;
|
|
@@ -68,6 +84,7 @@ export default function InputArea({
|
|
|
68
84
|
}: IProps): React.ReactElement {
|
|
69
85
|
const [value, setValue] = useState('');
|
|
70
86
|
const [cursorHint, setCursorHint] = useState<number | null>(null);
|
|
87
|
+
const [activeInteraction, setActiveInteraction] = useState<IActiveInteraction | null>(null);
|
|
71
88
|
const [historyState, setHistoryState] = useState(createPromptHistoryNavigationState);
|
|
72
89
|
const [localPromptHistory, setLocalPromptHistory] = useState<string[]>([]);
|
|
73
90
|
const restoredPromptHistory = useMemo(() => extractPromptHistory(history ?? []), [history]);
|
|
@@ -139,7 +156,8 @@ export default function InputArea({
|
|
|
139
156
|
/** Enter: insert and execute command immediately */
|
|
140
157
|
const enterSelectCommand = useCallback(
|
|
141
158
|
(cmd: ICommand): void => {
|
|
142
|
-
const
|
|
159
|
+
const interaction = resolveCommandInteraction(cmd.name);
|
|
160
|
+
const result = resolveEnterCommandSelection(value, cmd, interaction);
|
|
143
161
|
if (result.type === 'insert') {
|
|
144
162
|
setValue(result.value);
|
|
145
163
|
if (result.selectedIndex !== undefined) {
|
|
@@ -147,10 +165,17 @@ export default function InputArea({
|
|
|
147
165
|
}
|
|
148
166
|
return;
|
|
149
167
|
}
|
|
150
|
-
|
|
151
|
-
|
|
168
|
+
if (result.type === 'open-interaction' && interaction?.onMissingArgs) {
|
|
169
|
+
setShowPopup(false);
|
|
170
|
+
setActiveInteraction({ commandName: result.commandName, interaction });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (result.type === 'submit') {
|
|
174
|
+
setValue('');
|
|
175
|
+
submitPrompt(result.value);
|
|
176
|
+
}
|
|
152
177
|
},
|
|
153
|
-
[value, submitPrompt, setSelectedIndex],
|
|
178
|
+
[value, submitPrompt, setSelectedIndex, setShowPopup],
|
|
154
179
|
);
|
|
155
180
|
|
|
156
181
|
const handleSubmit = useCallback(
|
|
@@ -238,9 +263,44 @@ export default function InputArea({
|
|
|
238
263
|
return { left: '┌' + '─'.repeat(innerWidth), label: '', right: '┐' };
|
|
239
264
|
})();
|
|
240
265
|
|
|
266
|
+
const handlePickerSelect = useCallback(
|
|
267
|
+
(item: ITuiPickerItem): void => {
|
|
268
|
+
if (!activeInteraction) return;
|
|
269
|
+
setActiveInteraction(null);
|
|
270
|
+
submitPrompt(`/${activeInteraction.commandName} ${item.value}`);
|
|
271
|
+
},
|
|
272
|
+
[activeInteraction, submitPrompt],
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
const handleConfirm = useCallback((): void => {
|
|
276
|
+
if (!activeInteraction) return;
|
|
277
|
+
setActiveInteraction(null);
|
|
278
|
+
submitPrompt(`/${activeInteraction.commandName}`);
|
|
279
|
+
}, [activeInteraction, submitPrompt]);
|
|
280
|
+
|
|
281
|
+
const handleInteractionCancel = useCallback((): void => {
|
|
282
|
+
setActiveInteraction(null);
|
|
283
|
+
}, []);
|
|
284
|
+
|
|
241
285
|
return (
|
|
242
286
|
<Box flexDirection="column">
|
|
243
|
-
{
|
|
287
|
+
{activeInteraction && isPickerInteraction(activeInteraction.interaction) && (
|
|
288
|
+
<CommandPicker
|
|
289
|
+
commandName={activeInteraction.commandName}
|
|
290
|
+
interaction={activeInteraction.interaction}
|
|
291
|
+
onSelect={handlePickerSelect}
|
|
292
|
+
onCancel={handleInteractionCancel}
|
|
293
|
+
/>
|
|
294
|
+
)}
|
|
295
|
+
{activeInteraction && isConfirmInteraction(activeInteraction.interaction) && (
|
|
296
|
+
<CommandConfirm
|
|
297
|
+
commandName={activeInteraction.commandName}
|
|
298
|
+
interaction={activeInteraction.interaction}
|
|
299
|
+
onConfirm={handleConfirm}
|
|
300
|
+
onCancel={handleInteractionCancel}
|
|
301
|
+
/>
|
|
302
|
+
)}
|
|
303
|
+
{!activeInteraction && showPopup && (
|
|
244
304
|
<SlashAutocomplete
|
|
245
305
|
commands={filteredCommands}
|
|
246
306
|
selectedIndex={selectedIndex}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { Box, Text } from 'ink';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import ListPicker from './ListPicker.js';
|
|
5
|
+
import TextPrompt from './TextPrompt.js';
|
|
6
|
+
|
|
3
7
|
import type {
|
|
4
8
|
TCommandInteractionPrompt as TInteractivePrompt,
|
|
5
9
|
ICommandChoicePromptOption as IChoicePromptOption,
|
|
6
10
|
} from '@robota-sdk/agent-framework';
|
|
7
|
-
import ListPicker from './ListPicker.js';
|
|
8
|
-
import TextPrompt from './TextPrompt.js';
|
|
9
11
|
|
|
10
12
|
interface IInteractivePromptProps {
|
|
11
13
|
prompt: TInteractivePrompt;
|
package/src/tui/ListPicker.tsx
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Shows a limited number of items at a time; scrolls as the cursor moves.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React, { useState, useRef, useCallback } from 'react';
|
|
8
7
|
import { Box, Text, useInput } from 'ink';
|
|
8
|
+
import React, { useState, useRef, useCallback } from 'react';
|
|
9
|
+
|
|
9
10
|
import {
|
|
10
11
|
applySelectionInput,
|
|
11
12
|
createSelectionFlowState,
|
package/src/tui/MenuSelect.tsx
CHANGED
package/src/tui/MessageList.tsx
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
import type { IHistoryEntry, TUniversalMessage, TUniversalValue } from '@robota-sdk/agent-core';
|
|
4
1
|
import { isToolMessage, isAssistantMessage } from '@robota-sdk/agent-core';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import { formatCommandOutputSummary } from './command-output-summary.js';
|
|
5
6
|
import { renderMarkdown } from './render-markdown.js';
|
|
6
|
-
import
|
|
7
|
+
import ToolCommandOutput from './ToolCommandOutput.js';
|
|
7
8
|
import ToolDiffBlock from './ToolDiffBlock.js';
|
|
8
9
|
import UsageSummaryEntry from './UsageSummaryEntry.js';
|
|
9
|
-
|
|
10
|
-
import
|
|
10
|
+
|
|
11
|
+
import type { IToolCallSummary } from './utils/tool-call-extractor.js';
|
|
12
|
+
import type { IHistoryEntry, TUniversalMessage, TUniversalValue } from '@robota-sdk/agent-core';
|
|
11
13
|
|
|
12
14
|
interface IProps {
|
|
13
15
|
history: IHistoryEntry[];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { Box, Text, useInput } from 'ink';
|
|
3
|
-
import
|
|
4
|
-
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
5
4
|
import {
|
|
6
5
|
applyPermissionPromptInput,
|
|
7
6
|
getPermissionPromptInputAction,
|
|
@@ -10,6 +9,9 @@ import {
|
|
|
10
9
|
} from './flows/permission-prompt-flow.js';
|
|
11
10
|
import { createSelectionFlowState, type ISelectionFlowState } from './flows/selection-flow.js';
|
|
12
11
|
|
|
12
|
+
import type { IPermissionRequest } from './types.js';
|
|
13
|
+
import type { TToolArgs } from '@robota-sdk/agent-core';
|
|
14
|
+
|
|
13
15
|
interface IProps {
|
|
14
16
|
request: IPermissionRequest;
|
|
15
17
|
}
|
package/src/tui/PluginTUI.tsx
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { useState, useCallback } from 'react';
|
|
7
|
-
|
|
8
|
-
import TextPrompt from './TextPrompt.js';
|
|
7
|
+
|
|
9
8
|
import ConfirmPrompt from './ConfirmPrompt.js';
|
|
9
|
+
import { usePluginScreenData } from './hooks/usePluginScreenData.js';
|
|
10
|
+
import MenuSelect from './MenuSelect.js';
|
|
10
11
|
import {
|
|
11
12
|
handleMainSelect,
|
|
12
13
|
handleMarketplaceListSelect,
|
|
@@ -16,9 +17,10 @@ import {
|
|
|
16
17
|
handleInstalledListSelect,
|
|
17
18
|
handleInstalledActionSelect,
|
|
18
19
|
} from './plugin-tui-handlers.js';
|
|
20
|
+
import TextPrompt from './TextPrompt.js';
|
|
21
|
+
|
|
19
22
|
import type { IMenuSelectItem } from './MenuSelect.js';
|
|
20
23
|
import type { ICommandPluginAdapter } from '@robota-sdk/agent-framework';
|
|
21
|
-
import { usePluginScreenData } from './hooks/usePluginScreenData.js';
|
|
22
24
|
|
|
23
25
|
type TScreenId =
|
|
24
26
|
| 'main'
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
* Shows a list of sessions for the current cwd.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from 'react';
|
|
7
6
|
import { Box, Text } from 'ink';
|
|
8
|
-
import
|
|
7
|
+
import React from 'react';
|
|
8
|
+
|
|
9
9
|
import ListPicker from './ListPicker.js';
|
|
10
10
|
|
|
11
|
+
import type { IResumableSessionSummary } from '@robota-sdk/agent-framework';
|
|
12
|
+
|
|
11
13
|
const SESSION_ID_DISPLAY_LENGTH = 8;
|
|
12
14
|
const SESSION_PREVIEW_DISPLAY_LENGTH = 60;
|
|
13
15
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import StatusBar from './StatusBar.js';
|
|
4
|
+
import { useTuiCliAdapter } from './tui-cli-adapter-context.js';
|
|
5
|
+
|
|
2
6
|
import type { TPermissionMode } from '@robota-sdk/agent-core';
|
|
3
7
|
import type { IStatusLineCommandSettings } from '@robota-sdk/agent-framework';
|
|
4
|
-
import { useTuiCliAdapter } from './tui-cli-adapter-context.js';
|
|
5
|
-
import StatusBar from './StatusBar.js';
|
|
6
8
|
|
|
7
9
|
interface IProps {
|
|
8
10
|
cwd: string;
|
|
@@ -18,6 +20,7 @@ interface IProps {
|
|
|
18
20
|
sessionName?: string;
|
|
19
21
|
settings: IStatusLineCommandSettings;
|
|
20
22
|
activeAgentLabel?: string;
|
|
23
|
+
gitRefreshToken?: number;
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
export default function SessionStatusBar({
|
|
@@ -34,9 +37,10 @@ export default function SessionStatusBar({
|
|
|
34
37
|
sessionName,
|
|
35
38
|
settings,
|
|
36
39
|
activeAgentLabel,
|
|
40
|
+
gitRefreshToken,
|
|
37
41
|
}: IProps): React.ReactElement | null {
|
|
38
42
|
const cliAdapter = useTuiCliAdapter();
|
|
39
|
-
const gitBranch = useMemo(() => cliAdapter.getGitBranch(cwd), [cliAdapter, cwd]);
|
|
43
|
+
const gitBranch = useMemo(() => cliAdapter.getGitBranch(cwd), [cliAdapter, cwd, gitRefreshToken]);
|
|
40
44
|
const providerDisplayName = useMemo(
|
|
41
45
|
() =>
|
|
42
46
|
providerType !== undefined ? cliAdapter.getProviderDisplayName(providerType) : undefined,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
1
|
import { Box, Text, useStdout } from 'ink';
|
|
2
|
+
import React, { useState, useEffect } from 'react';
|
|
3
|
+
|
|
3
4
|
import type { ICommand } from '@robota-sdk/agent-framework';
|
|
4
5
|
|
|
5
6
|
interface IProps {
|
|
@@ -21,11 +22,11 @@ const NAME_COL_MAX = 20;
|
|
|
21
22
|
|
|
22
23
|
function useRowWidth(): number {
|
|
23
24
|
const { stdout } = useStdout();
|
|
24
|
-
const measure = () => Math.max(MIN_ROW_WIDTH, (stdout.columns ?? 80) - OUTER_CHROME);
|
|
25
|
+
const measure = (): number => Math.max(MIN_ROW_WIDTH, (stdout.columns ?? 80) - OUTER_CHROME);
|
|
25
26
|
const [width, setWidth] = useState(measure);
|
|
26
27
|
|
|
27
28
|
useEffect(() => {
|
|
28
|
-
const onResize = () => setWidth(measure());
|
|
29
|
+
const onResize = (): void => setWidth(measure());
|
|
29
30
|
stdout.on('resize', onResize);
|
|
30
31
|
return () => {
|
|
31
32
|
stdout.off('resize', onResize);
|
|
@@ -51,8 +52,7 @@ function CommandRow(props: {
|
|
|
51
52
|
const indicator = isSelected ? '▸ ' : ' ';
|
|
52
53
|
const nameColor = isSelected ? 'cyan' : undefined;
|
|
53
54
|
const dimmed = !isSelected;
|
|
54
|
-
const
|
|
55
|
-
const namePart = capName(displayLabel, nameColWidth);
|
|
55
|
+
const namePart = capName(cmd.name, nameColWidth);
|
|
56
56
|
const text = showSlash
|
|
57
57
|
? `${indicator}/${namePart} ${cmd.description ?? ''}`
|
|
58
58
|
: `${indicator}${namePart} ${cmd.description ?? ''}`;
|
|
@@ -82,7 +82,7 @@ export default function SlashAutocomplete({
|
|
|
82
82
|
|
|
83
83
|
const nameColWidth = Math.min(
|
|
84
84
|
NAME_COL_MAX,
|
|
85
|
-
Math.max(...visibleCommands.map((c) =>
|
|
85
|
+
Math.max(...visibleCommands.map((c) => c.name.length)),
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
return (
|
package/src/tui/StatusBar.tsx
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
import type { TPermissionMode } from '@robota-sdk/agent-core';
|
|
4
1
|
import { formatTokenCount } from '@robota-sdk/agent-core';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
5
|
import { formatStatusActivity } from './status-activity.js';
|
|
6
6
|
|
|
7
|
+
import type { TPermissionMode } from '@robota-sdk/agent-core';
|
|
8
|
+
|
|
7
9
|
/** Threshold boundaries for context percentage color coding */
|
|
8
10
|
const CONTEXT_YELLOW_THRESHOLD = 70;
|
|
9
11
|
const CONTEXT_RED_THRESHOLD = 90;
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* Displayed during session.run() execution.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from 'react';
|
|
7
6
|
import { Box, Text } from 'ink';
|
|
8
|
-
import
|
|
7
|
+
import React from 'react';
|
|
8
|
+
|
|
9
9
|
import { renderMarkdown } from './render-markdown.js';
|
|
10
10
|
import ToolDiffBlock from './ToolDiffBlock.js';
|
|
11
11
|
|
|
12
|
+
import type { IToolState } from '@robota-sdk/agent-framework';
|
|
13
|
+
|
|
12
14
|
function getToolStyle(t: IToolState): {
|
|
13
15
|
color: string;
|
|
14
16
|
icon: string;
|
package/src/tui/TextPrompt.tsx
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { Box, Text } from 'ink';
|
|
3
|
-
import
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
4
|
import { formatCommandOutputSummary } from './command-output-summary.js';
|
|
5
5
|
|
|
6
|
+
import type { ICommandOutputInput } from './command-output-summary.js';
|
|
7
|
+
|
|
6
8
|
interface IProps {
|
|
7
9
|
tool: ICommandOutputInput;
|
|
8
10
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { Box, Text } from 'ink';
|
|
3
|
-
import
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
4
|
import { renderMarkdown } from './render-markdown.js';
|
|
5
|
+
import { buildToolDiffSummary } from './utils/tool-diff-summary.js';
|
|
6
|
+
|
|
5
7
|
import type { IDiffLine } from './utils/edit-diff.js';
|
|
6
8
|
|
|
7
9
|
interface IProps {
|
package/src/tui/TransportTUI.tsx
CHANGED
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
* Arrow keys navigate the list, space toggles enabled/disabled, enter/esc closes.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React, { useState, useCallback } from 'react';
|
|
8
7
|
import { Box, Text, useInput } from 'ink';
|
|
8
|
+
import React, { useState, useCallback } from 'react';
|
|
9
|
+
|
|
10
|
+
import type { IInteractiveSession } from '@robota-sdk/agent-framework';
|
|
9
11
|
import type {
|
|
10
12
|
ITransportEntry,
|
|
11
13
|
ITransportRegistryView,
|
|
12
14
|
} from '@robota-sdk/agent-interface-transport';
|
|
13
|
-
import type { IInteractiveSession } from '@robota-sdk/agent-framework';
|
|
14
15
|
|
|
15
16
|
const TRANSPORT_NAME_WIDTH = 18;
|
|
16
17
|
|
package/src/tui/UpdateNotice.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { formatTokenCount } from '@robota-sdk/agent-core';
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
3
5
|
import type { IHistoryEntry } from '@robota-sdk/agent-core';
|
|
4
|
-
import { formatTokenCount } from '@robota-sdk/agent-core';
|
|
5
6
|
import type { IUsageSnapshot } from '@robota-sdk/agent-framework';
|
|
6
7
|
|
|
7
8
|
const TOKEN_COMPACT_THRESHOLD = 1000;
|
package/src/tui/WaveText.tsx
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Colors stay in a narrow range (dim grays) to avoid harsh contrast.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React, { useState, useEffect } from 'react';
|
|
8
7
|
import { Text } from 'ink';
|
|
8
|
+
import React, { useState, useEffect } from 'react';
|
|
9
9
|
|
|
10
10
|
// Subtle gray tones — minimal contrast, soft wave
|
|
11
11
|
const WAVE_COLORS = ['#666666', '#888888', '#aaaaaa', '#888888'] as const;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { writeFileSync } from 'node:fs';
|
|
3
|
-
|
|
4
|
-
import InteractivePrompt from '../../InteractivePrompt.js';
|
|
5
|
-
import type { TCommandInteractionPrompt as TInteractivePrompt } from '@robota-sdk/agent-framework';
|
|
2
|
+
|
|
6
3
|
import {
|
|
7
4
|
createProviderSetupFlow,
|
|
8
5
|
formatProviderSetupHelpLinks,
|
|
@@ -12,7 +9,13 @@ import {
|
|
|
12
9
|
type IProviderSetupFlowState,
|
|
13
10
|
type TProviderSetupType,
|
|
14
11
|
} from '@robota-sdk/agent-command';
|
|
12
|
+
import { render, useApp } from 'ink';
|
|
13
|
+
import React from 'react';
|
|
14
|
+
|
|
15
|
+
import InteractivePrompt from '../../InteractivePrompt.js';
|
|
16
|
+
|
|
15
17
|
import type { IAIProvider, IProviderDefinition } from '@robota-sdk/agent-core';
|
|
18
|
+
import type { TCommandInteractionPrompt as TInteractivePrompt } from '@robota-sdk/agent-framework';
|
|
16
19
|
|
|
17
20
|
const openaiDefaults = {
|
|
18
21
|
apiKey: '$ENV:OPENAI_API_KEY',
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
shouldSubmitInput,
|
|
15
15
|
} from '../flows/input-area-flow.js';
|
|
16
16
|
import type { ICommand } from '@robota-sdk/agent-framework';
|
|
17
|
+
import type { ITuiPickerInteraction } from '../command-interaction.js';
|
|
17
18
|
import {
|
|
18
19
|
createAssistantMessage,
|
|
19
20
|
createSystemMessage,
|
|
@@ -66,6 +67,24 @@ describe('input area flow', () => {
|
|
|
66
67
|
expect(result).toEqual({ type: 'submit', value: '/help' });
|
|
67
68
|
});
|
|
68
69
|
|
|
70
|
+
it('Given interaction declared and no args When enter selects command Then open-interaction is returned', () => {
|
|
71
|
+
const result = resolveEnterCommandSelection('/ex', command('exit'), {
|
|
72
|
+
onMissingArgs: 'confirm',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
expect(result).toEqual({ type: 'open-interaction', commandName: 'exit' });
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('Given interaction declared but subcommand selected (args present) When enter selects Then submits', () => {
|
|
79
|
+
const pickerInteraction: ITuiPickerInteraction = {
|
|
80
|
+
onMissingArgs: 'picker',
|
|
81
|
+
getItems: () => [],
|
|
82
|
+
};
|
|
83
|
+
const result = resolveEnterCommandSelection('/mode plan', command('plan'), pickerInteraction);
|
|
84
|
+
|
|
85
|
+
expect(result).toEqual({ type: 'submit', value: '/mode plan' });
|
|
86
|
+
});
|
|
87
|
+
|
|
69
88
|
it('Given multiline paste When label change is created Then label is inserted at cursor', () => {
|
|
70
89
|
const result = createPasteLabelChange('abef', 2, 7, 'c\nd\ne');
|
|
71
90
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { IExecutionWorkspaceEntry } from '@robota-sdk/agent-framework';
|
|
2
1
|
import { formatExecutionWorkspaceEntryRow } from './execution-workspace-view-model.js';
|
|
3
2
|
|
|
3
|
+
import type { IExecutionWorkspaceEntry } from '@robota-sdk/agent-framework';
|
|
4
|
+
|
|
4
5
|
export interface IBackgroundTaskRow {
|
|
5
6
|
connector: '├' | '└';
|
|
6
7
|
marker: '□' | '■';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ITuiPickerItem, TAnyTuiCommandInteraction } from './command-interaction.js';
|
|
2
|
+
|
|
3
|
+
function getModeItems(): ITuiPickerItem[] {
|
|
4
|
+
return [
|
|
5
|
+
{ label: 'plan', value: 'plan', description: 'Plan only, no execution' },
|
|
6
|
+
{ label: 'default', value: 'default', description: 'Ask before risky actions' },
|
|
7
|
+
{ label: 'acceptEdits', value: 'acceptEdits', description: 'Auto-approve file edits' },
|
|
8
|
+
{
|
|
9
|
+
label: 'bypassPermissions',
|
|
10
|
+
value: 'bypassPermissions',
|
|
11
|
+
description: 'Skip all permission checks',
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getLanguageItems(): ITuiPickerItem[] {
|
|
17
|
+
return [
|
|
18
|
+
{ label: 'ko Korean', value: 'ko', description: '한국어' },
|
|
19
|
+
{ label: 'en English', value: 'en', description: 'English' },
|
|
20
|
+
{ label: 'ja Japanese', value: 'ja', description: '日本語' },
|
|
21
|
+
{ label: 'zh Chinese', value: 'zh', description: '中文' },
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getProviderSubcommandItems(): ITuiPickerItem[] {
|
|
26
|
+
return [
|
|
27
|
+
{ label: 'current', value: 'current', description: 'Show current provider' },
|
|
28
|
+
{ label: 'list', value: 'list', description: 'List available providers' },
|
|
29
|
+
{ label: 'use', value: 'use', description: 'Switch to a provider' },
|
|
30
|
+
{ label: 'add', value: 'add', description: 'Add a new provider' },
|
|
31
|
+
{ label: 'test', value: 'test', description: 'Test provider connection' },
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const BUILT_IN_INTERACTIONS: Record<string, TAnyTuiCommandInteraction | undefined> = {
|
|
36
|
+
agent: undefined,
|
|
37
|
+
background: undefined,
|
|
38
|
+
clear: { onMissingArgs: 'confirm', message: 'Clear conversation history?' },
|
|
39
|
+
compact: undefined,
|
|
40
|
+
context: undefined,
|
|
41
|
+
cost: undefined,
|
|
42
|
+
exit: { onMissingArgs: 'confirm', message: 'Exit the session?' },
|
|
43
|
+
help: undefined,
|
|
44
|
+
language: { onMissingArgs: 'picker', getItems: getLanguageItems },
|
|
45
|
+
memory: undefined,
|
|
46
|
+
mode: { onMissingArgs: 'picker', getItems: getModeItems },
|
|
47
|
+
model: undefined,
|
|
48
|
+
permissions: undefined,
|
|
49
|
+
plugin: undefined,
|
|
50
|
+
provider: { onMissingArgs: 'picker', getItems: getProviderSubcommandItems },
|
|
51
|
+
rename: undefined,
|
|
52
|
+
reset: undefined,
|
|
53
|
+
resume: undefined,
|
|
54
|
+
rewind: undefined,
|
|
55
|
+
settings: undefined,
|
|
56
|
+
skills: undefined,
|
|
57
|
+
statusline: undefined,
|
|
58
|
+
'user-local': undefined,
|
|
59
|
+
'validate-session': undefined,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export function resolveCommandInteraction(
|
|
63
|
+
commandName: string,
|
|
64
|
+
): TAnyTuiCommandInteraction | undefined {
|
|
65
|
+
return BUILT_IN_INTERACTIONS[commandName];
|
|
66
|
+
}
|