snow-ai 0.3.4 → 0.3.5

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.
Files changed (36) hide show
  1. package/dist/api/anthropic.js +38 -13
  2. package/dist/api/types.d.ts +1 -0
  3. package/dist/hooks/useConversation.js +212 -59
  4. package/dist/hooks/useSnapshotState.d.ts +2 -0
  5. package/dist/hooks/useToolConfirmation.js +1 -1
  6. package/dist/mcp/subagent.d.ts +35 -0
  7. package/dist/mcp/subagent.js +64 -0
  8. package/dist/ui/components/ChatInput.d.ts +1 -2
  9. package/dist/ui/components/ChatInput.js +47 -39
  10. package/dist/ui/components/FileRollbackConfirmation.d.ts +3 -2
  11. package/dist/ui/components/FileRollbackConfirmation.js +81 -22
  12. package/dist/ui/components/MessageList.d.ts +7 -1
  13. package/dist/ui/components/MessageList.js +16 -5
  14. package/dist/ui/pages/ChatScreen.js +29 -20
  15. package/dist/ui/pages/ConfigScreen.js +47 -46
  16. package/dist/ui/pages/ProxyConfigScreen.js +1 -1
  17. package/dist/ui/pages/SubAgentConfigScreen.d.ts +9 -0
  18. package/dist/ui/pages/SubAgentConfigScreen.js +352 -0
  19. package/dist/ui/pages/SubAgentListScreen.d.ts +9 -0
  20. package/dist/ui/pages/SubAgentListScreen.js +114 -0
  21. package/dist/ui/pages/WelcomeScreen.js +30 -2
  22. package/dist/utils/incrementalSnapshot.d.ts +7 -0
  23. package/dist/utils/incrementalSnapshot.js +34 -0
  24. package/dist/utils/mcpToolsManager.js +41 -1
  25. package/dist/utils/retryUtils.js +5 -0
  26. package/dist/utils/sessionConverter.d.ts +1 -0
  27. package/dist/utils/sessionConverter.js +192 -89
  28. package/dist/utils/subAgentConfig.d.ts +43 -0
  29. package/dist/utils/subAgentConfig.js +126 -0
  30. package/dist/utils/subAgentExecutor.d.ts +29 -0
  31. package/dist/utils/subAgentExecutor.js +272 -0
  32. package/dist/utils/toolExecutor.d.ts +10 -2
  33. package/dist/utils/toolExecutor.js +46 -5
  34. package/package.json +1 -1
  35. package/dist/ui/pages/ConfigProfileScreen.d.ts +0 -7
  36. package/dist/ui/pages/ConfigProfileScreen.js +0 -300
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
2
  type Props = {
3
3
  fileCount: number;
4
- onConfirm: (rollbackFiles: boolean) => void;
4
+ filePaths: string[];
5
+ onConfirm: (rollbackFiles: boolean | null) => void;
5
6
  };
6
- export default function FileRollbackConfirmation({ fileCount, onConfirm }: Props): React.JSX.Element;
7
+ export default function FileRollbackConfirmation({ fileCount, filePaths, onConfirm }: Props): React.JSX.Element;
7
8
  export {};
@@ -1,34 +1,71 @@
1
1
  import React, { useState } from 'react';
2
2
  import { Box, Text, useInput } from 'ink';
3
- export default function FileRollbackConfirmation({ fileCount, onConfirm }) {
3
+ export default function FileRollbackConfirmation({ fileCount, filePaths, onConfirm }) {
4
4
  const [selectedIndex, setSelectedIndex] = useState(0);
5
+ const [showFullList, setShowFullList] = useState(false);
6
+ const [fileScrollIndex, setFileScrollIndex] = useState(0);
5
7
  const options = [
6
8
  { label: 'Yes, rollback files and conversation', value: true },
7
9
  { label: 'No, rollback conversation only', value: false }
8
10
  ];
9
11
  useInput((_, key) => {
10
- // Up arrow
11
- if (key.upArrow) {
12
- setSelectedIndex(prev => Math.max(0, prev - 1));
12
+ // Tab - toggle full file list view
13
+ if (key.tab) {
14
+ setShowFullList(prev => !prev);
15
+ setFileScrollIndex(0); // Reset scroll when toggling
13
16
  return;
14
17
  }
15
- // Down arrow
16
- if (key.downArrow) {
17
- setSelectedIndex(prev => Math.min(options.length - 1, prev + 1));
18
- return;
18
+ // In full list mode, use up/down to scroll files
19
+ if (showFullList) {
20
+ const maxVisibleFiles = 10;
21
+ const maxScroll = Math.max(0, filePaths.length - maxVisibleFiles);
22
+ if (key.upArrow) {
23
+ setFileScrollIndex(prev => Math.max(0, prev - 1));
24
+ return;
25
+ }
26
+ if (key.downArrow) {
27
+ setFileScrollIndex(prev => Math.min(maxScroll, prev + 1));
28
+ return;
29
+ }
30
+ }
31
+ else {
32
+ // In compact mode, up/down navigate options
33
+ if (key.upArrow) {
34
+ setSelectedIndex(prev => Math.max(0, prev - 1));
35
+ return;
36
+ }
37
+ if (key.downArrow) {
38
+ setSelectedIndex(prev => Math.min(options.length - 1, prev + 1));
39
+ return;
40
+ }
19
41
  }
20
- // Enter - confirm selection
21
- if (key.return) {
42
+ // Enter - confirm selection (only when not in full list mode)
43
+ if (key.return && !showFullList) {
22
44
  onConfirm(options[selectedIndex]?.value ?? false);
23
45
  return;
24
46
  }
25
- // ESC - cancel rollback (select "No")
47
+ // ESC - exit full list mode or cancel rollback
26
48
  if (key.escape) {
27
- onConfirm(false);
49
+ if (showFullList) {
50
+ setShowFullList(false);
51
+ setFileScrollIndex(0);
52
+ }
53
+ else {
54
+ onConfirm(null); // null means cancel everything
55
+ }
28
56
  return;
29
57
  }
30
58
  });
31
- return (React.createElement(Box, { flexDirection: "column", marginX: 1, marginBottom: 1, borderStyle: "round", borderColor: "yellow", padding: 1 },
59
+ // Display logic for file list
60
+ const maxFilesToShowCompact = 5;
61
+ const maxFilesToShowFull = 10;
62
+ const displayFiles = showFullList
63
+ ? filePaths.slice(fileScrollIndex, fileScrollIndex + maxFilesToShowFull)
64
+ : filePaths.slice(0, maxFilesToShowCompact);
65
+ const remainingCountCompact = fileCount - maxFilesToShowCompact;
66
+ const hasMoreAbove = showFullList && fileScrollIndex > 0;
67
+ const hasMoreBelow = showFullList && (fileScrollIndex + maxFilesToShowFull) < filePaths.length;
68
+ return (React.createElement(Box, { flexDirection: "column", marginX: 1, marginBottom: 1, padding: 1 },
32
69
  React.createElement(Box, { marginBottom: 1 },
33
70
  React.createElement(Text, { color: "yellow", bold: true }, "\u26A0 File Rollback Confirmation")),
34
71
  React.createElement(Box, { marginBottom: 1 },
@@ -37,13 +74,35 @@ export default function FileRollbackConfirmation({ fileCount, onConfirm }) {
37
74
  fileCount,
38
75
  " file",
39
76
  fileCount > 1 ? 's' : '',
40
- " that will be rolled back.")),
41
- React.createElement(Box, { marginBottom: 1 },
42
- React.createElement(Text, { color: "gray", dimColor: true }, "Do you want to rollback the files as well?")),
43
- React.createElement(Box, { flexDirection: "column" }, options.map((option, index) => (React.createElement(Box, { key: index },
44
- React.createElement(Text, { color: index === selectedIndex ? 'green' : 'white', bold: index === selectedIndex },
45
- index === selectedIndex ? '❯ ' : ' ',
46
- option.label))))),
47
- React.createElement(Box, { marginTop: 1 },
48
- React.createElement(Text, { color: "gray", dimColor: true }, "Use \u2191\u2193 to select, Enter to confirm, ESC to cancel"))));
77
+ " that will be rolled back:")),
78
+ React.createElement(Box, { flexDirection: "column", marginBottom: 1, marginLeft: 2 },
79
+ hasMoreAbove && (React.createElement(Text, { color: "gray", dimColor: true },
80
+ "\u2191 ",
81
+ fileScrollIndex,
82
+ " more above...")),
83
+ displayFiles.map((file, index) => (React.createElement(Text, { key: index, color: "cyan", dimColor: true },
84
+ "\u2022 ",
85
+ file))),
86
+ hasMoreBelow && (React.createElement(Text, { color: "gray", dimColor: true },
87
+ "\u2193 ",
88
+ filePaths.length - (fileScrollIndex + maxFilesToShowFull),
89
+ " more below...")),
90
+ !showFullList && remainingCountCompact > 0 && (React.createElement(Text, { color: "gray", dimColor: true },
91
+ "... and ",
92
+ remainingCountCompact,
93
+ " more file",
94
+ remainingCountCompact > 1 ? 's' : ''))),
95
+ !showFullList && (React.createElement(React.Fragment, null,
96
+ React.createElement(Box, { marginBottom: 1 },
97
+ React.createElement(Text, { color: "gray", dimColor: true }, "Do you want to rollback the files as well?")),
98
+ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, options.map((option, index) => (React.createElement(Box, { key: index },
99
+ React.createElement(Text, { color: index === selectedIndex ? 'green' : 'white', bold: index === selectedIndex },
100
+ index === selectedIndex ? '❯ ' : ' ',
101
+ option.label))))))),
102
+ React.createElement(Box, null,
103
+ React.createElement(Text, { color: "gray", dimColor: true }, showFullList
104
+ ? '↑↓ scroll · Tab back · ESC close'
105
+ : fileCount > maxFilesToShowCompact
106
+ ? `↑↓ select · Tab view all (${fileCount} files) · Enter confirm · ESC cancel`
107
+ : '↑↓ select · Enter confirm · ESC cancel'))));
49
108
  }
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { SelectedFile } from '../../utils/fileUtils.js';
3
3
  export interface Message {
4
- role: 'user' | 'assistant' | 'command';
4
+ role: 'user' | 'assistant' | 'command' | 'subagent';
5
5
  content: string;
6
6
  streaming?: boolean;
7
7
  discontinued?: boolean;
@@ -39,6 +39,12 @@ export interface Message {
39
39
  exitCode?: number;
40
40
  command?: string;
41
41
  };
42
+ subAgent?: {
43
+ agentId: string;
44
+ agentName: string;
45
+ isComplete?: boolean;
46
+ };
47
+ subAgentInternal?: boolean;
42
48
  }
43
49
  interface Props {
44
50
  messages: Message[];
@@ -11,20 +11,31 @@ const MessageList = memo(({ messages, animationFrame, maxMessages = 6 }) => {
11
11
  ? 'green'
12
12
  : message.role === 'command'
13
13
  ? 'gray'
14
- : message.streaming
15
- ? STREAM_COLORS[animationFrame]
16
- : 'cyan';
14
+ : message.role === 'subagent'
15
+ ? 'magenta'
16
+ : message.streaming
17
+ ? STREAM_COLORS[animationFrame]
18
+ : 'cyan';
17
19
  return (React.createElement(Box, { key: index },
18
20
  React.createElement(Text, { color: iconColor, bold: true }, message.role === 'user'
19
21
  ? '⛇'
20
22
  : message.role === 'command'
21
23
  ? '⌘'
22
- : ''),
24
+ : message.role === 'subagent'
25
+ ? '◈'
26
+ : '❆'),
23
27
  React.createElement(Box, { marginLeft: 1, marginBottom: 1, flexDirection: "column" }, message.role === 'command' ? (React.createElement(Text, { color: "gray" },
24
28
  "\u2514\u2500 ",
25
- message.commandName)) : (React.createElement(React.Fragment, null,
29
+ message.commandName)) : message.role === 'subagent' ? (React.createElement(React.Fragment, null,
30
+ React.createElement(Text, { color: "magenta", dimColor: true },
31
+ "\u2514\u2500 Sub-Agent: ",
32
+ message.subAgent?.agentName,
33
+ message.subAgent?.isComplete ? ' ✓' : ' ...'),
34
+ React.createElement(Box, { marginLeft: 2 },
35
+ React.createElement(MarkdownRenderer, { content: message.content || ' ', color: "gray" })))) : (React.createElement(React.Fragment, null,
26
36
  React.createElement(MarkdownRenderer, { content: message.content || ' ', color: message.role === 'user' ? 'gray' : undefined }),
27
37
  (message.systemInfo ||
38
+ message.files ||
28
39
  message.files ||
29
40
  message.images) && (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
30
41
  message.systemInfo && (React.createElement(React.Fragment, null,
@@ -130,6 +130,20 @@ export default function ChatScreen({ skipWelcome }) {
130
130
  clearTimeout(handler);
131
131
  };
132
132
  }, [terminalWidth, stdout]);
133
+ // Reload messages from session when remountKey changes (to restore sub-agent messages)
134
+ useEffect(() => {
135
+ if (remountKey === 0)
136
+ return; // Skip initial render
137
+ const reloadMessages = async () => {
138
+ const currentSession = sessionManager.getCurrentSession();
139
+ if (currentSession && currentSession.messages.length > 0) {
140
+ // Convert session messages back to UI format
141
+ const uiMessages = convertSessionMessagesToUI(currentSession.messages);
142
+ setMessages(uiMessages);
143
+ }
144
+ };
145
+ reloadMessages();
146
+ }, [remountKey]);
133
147
  // Use tool confirmation hook
134
148
  const { pendingToolConfirmation, requestToolConfirmation, isToolAutoApproved, addMultipleToAlwaysApproved, } = useToolConfirmation();
135
149
  // Minimum terminal height required for proper rendering
@@ -249,9 +263,15 @@ export default function ChatScreen({ skipWelcome }) {
249
263
  }
250
264
  // Show confirmation dialog if there are files to rollback
251
265
  if (totalFileCount > 0) {
266
+ // Get list of files that will be rolled back
267
+ const currentSession = sessionManager.getCurrentSession();
268
+ const filePaths = currentSession
269
+ ? await incrementalSnapshotManager.getFilesToRollback(currentSession.id, selectedIndex)
270
+ : [];
252
271
  snapshotState.setPendingRollback({
253
272
  messageIndex: selectedIndex,
254
- fileCount: totalFileCount,
273
+ fileCount: filePaths.length, // Use actual unique file count
274
+ filePaths,
255
275
  });
256
276
  }
257
277
  else {
@@ -278,6 +298,11 @@ export default function ChatScreen({ skipWelcome }) {
278
298
  snapshotState.setPendingRollback(null);
279
299
  };
280
300
  const handleRollbackConfirm = (rollbackFiles) => {
301
+ if (rollbackFiles === null) {
302
+ // User cancelled - just close the dialog without doing anything
303
+ snapshotState.setPendingRollback(null);
304
+ return;
305
+ }
281
306
  if (snapshotState.pendingRollback) {
282
307
  performRollback(snapshotState.pendingRollback.messageIndex, rollbackFiles);
283
308
  }
@@ -527,7 +552,7 @@ export default function ChatScreen({ skipWelcome }) {
527
552
  "\u2022 Working directory: ",
528
553
  workingDirectory)))),
529
554
  ...messages
530
- .filter(m => !m.streaming && !m.toolPending)
555
+ .filter(m => !m.streaming)
531
556
  .map((message, index) => {
532
557
  // Determine tool message type and color
533
558
  let toolStatusColor = 'cyan';
@@ -670,22 +695,6 @@ export default function ChatScreen({ skipWelcome }) {
670
695
  message.discontinued && (React.createElement(Text, { color: "red", bold: true }, "\u2514\u2500 user discontinue"))))))));
671
696
  }),
672
697
  ] }, item => item),
673
- messages
674
- .filter(m => m.toolPending)
675
- .map((message, index) => (React.createElement(Box, { key: `pending-tool-${index}`, marginBottom: 1, paddingX: 1, width: terminalWidth },
676
- React.createElement(Text, { color: "yellowBright", bold: true }, "\u2746"),
677
- React.createElement(Box, { marginLeft: 1, marginBottom: 1, flexDirection: "column" },
678
- React.createElement(Box, { flexDirection: "row" },
679
- React.createElement(MarkdownRenderer, { content: message.content || ' ', color: "yellow" }),
680
- React.createElement(Box, { marginLeft: 1 },
681
- React.createElement(Text, { color: "yellow" },
682
- React.createElement(Spinner, { type: "dots" })))),
683
- message.toolDisplay && message.toolDisplay.args.length > 0 && (React.createElement(Box, { flexDirection: "column", marginTop: 1 }, message.toolDisplay.args.map((arg, argIndex) => (React.createElement(Text, { key: argIndex, color: "gray", dimColor: true },
684
- arg.isLast ? '└─' : '├─',
685
- " ",
686
- arg.key,
687
- ": ",
688
- arg.value))))))))),
689
698
  (streamingState.isStreaming || isSaving) && !pendingToolConfirmation && (React.createElement(Box, { marginBottom: 1, paddingX: 1, width: terminalWidth },
690
699
  React.createElement(Text, { color: ['#FF6EBF', 'green', 'blue', 'cyan', '#B588F8'][streamingState.animationFrame], bold: true }, "\u2746"),
691
700
  React.createElement(Box, { marginLeft: 1, marginBottom: 1, flexDirection: "column" }, streamingState.isStreaming ? (React.createElement(React.Fragment, null, streamingState.retryStatus &&
@@ -738,7 +747,7 @@ export default function ChatScreen({ skipWelcome }) {
738
747
  React.createElement(MCPInfoPanel, null),
739
748
  React.createElement(Box, { marginTop: 1 },
740
749
  React.createElement(Text, { color: "gray", dimColor: true }, "Press ESC to close")))),
741
- snapshotState.pendingRollback && (React.createElement(FileRollbackConfirmation, { fileCount: snapshotState.pendingRollback.fileCount, onConfirm: handleRollbackConfirm })),
750
+ snapshotState.pendingRollback && (React.createElement(FileRollbackConfirmation, { fileCount: snapshotState.pendingRollback.fileCount, filePaths: snapshotState.pendingRollback.filePaths || [], onConfirm: handleRollbackConfirm })),
742
751
  !pendingToolConfirmation &&
743
752
  !isCompressing &&
744
753
  !showSessionPanel &&
@@ -752,7 +761,7 @@ export default function ChatScreen({ skipWelcome }) {
752
761
  cacheReadTokens: streamingState.contextUsage.cache_read_input_tokens,
753
762
  cachedTokens: streamingState.contextUsage.cached_tokens,
754
763
  }
755
- : undefined, snapshotFileCount: snapshotState.snapshotFileCount }),
764
+ : undefined }),
756
765
  vscodeState.vscodeConnectionStatus !== 'disconnected' && (React.createElement(Box, { marginTop: 1 },
757
766
  React.createElement(Text, { color: vscodeState.vscodeConnectionStatus === 'connecting'
758
767
  ? 'yellow'
@@ -3,7 +3,6 @@ import { Box, Text, useInput } from 'ink';
3
3
  import Gradient from 'ink-gradient';
4
4
  import { Select, Alert, Spinner } from '@inkjs/ui';
5
5
  import TextInput from 'ink-text-input';
6
- import chalk from 'chalk';
7
6
  import { getOpenAiConfig, updateOpenAiConfig, validateApiConfig, } from '../../utils/apiConfig.js';
8
7
  import { fetchAvailableModels, filterModels, } from '../../api/models.js';
9
8
  import { getActiveProfileName, getAllProfiles, switchProfile, createProfile, deleteProfile, saveProfile, } from '../../utils/configManager.js';
@@ -158,34 +157,6 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
158
157
  return compactModelName;
159
158
  return '';
160
159
  };
161
- const handleProfileChange = (value) => {
162
- if (value === '__CREATE_NEW__') {
163
- setProfileMode('creating');
164
- setNewProfileName('');
165
- return;
166
- }
167
- if (value === '__DELETE__') {
168
- if (activeProfile === 'default') {
169
- setErrors(['Cannot delete the default profile']);
170
- setIsEditing(false); // Exit editing mode to prevent Select component error
171
- return;
172
- }
173
- setProfileMode('deleting');
174
- return;
175
- }
176
- // Switch profile
177
- try {
178
- switchProfile(value);
179
- loadProfilesAndConfig();
180
- setIsEditing(false);
181
- setErrors([]);
182
- }
183
- catch (err) {
184
- setErrors([
185
- err instanceof Error ? err.message : 'Failed to switch profile',
186
- ]);
187
- }
188
- };
189
160
  const handleCreateProfile = () => {
190
161
  const cleaned = stripFocusArtifacts(newProfileName).trim();
191
162
  if (!cleaned) {
@@ -204,7 +175,9 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
204
175
  basicModel,
205
176
  maxContextTokens,
206
177
  maxTokens,
207
- compactModel: compactModelName ? { modelName: compactModelName } : undefined,
178
+ compactModel: compactModelName
179
+ ? { modelName: compactModelName }
180
+ : undefined,
208
181
  },
209
182
  };
210
183
  createProfile(cleaned, currentConfig);
@@ -321,6 +294,25 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
321
294
  if (isFocusEventInput(rawInput)) {
322
295
  return;
323
296
  }
297
+ // Handle profile shortcuts (highest priority - works even in Select mode)
298
+ if (currentField === 'profile' && (input === 'n' || input === 'N')) {
299
+ // Handle profile creation (works in both normal and editing mode)
300
+ setProfileMode('creating');
301
+ setNewProfileName('');
302
+ setIsEditing(false); // Exit Select editing mode
303
+ return;
304
+ }
305
+ if (currentField === 'profile' && (input === 'd' || input === 'D')) {
306
+ // Handle profile deletion (works in both normal and editing mode)
307
+ if (activeProfile === 'default') {
308
+ setErrors(['Cannot delete the default profile']);
309
+ setIsEditing(false);
310
+ return;
311
+ }
312
+ setProfileMode('deleting');
313
+ setIsEditing(false); // Exit Select editing mode
314
+ return;
315
+ }
324
316
  // Handle profile creation mode
325
317
  if (profileMode === 'creating') {
326
318
  if (key.return) {
@@ -638,20 +630,24 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
638
630
  currentField === 'compactModelName' && 'Compact Model',
639
631
  ":"),
640
632
  React.createElement(Box, { marginLeft: 3, marginTop: 1 },
641
- currentField === 'profile' && (React.createElement(Select, { options: [
642
- ...profiles.map(p => ({
633
+ currentField === 'profile' && (React.createElement(Box, { flexDirection: "column" },
634
+ profiles.length > 1 && (React.createElement(Text, { color: "gray", dimColor: true }, "Scroll to see more profiles (\u2191\u2193)")),
635
+ React.createElement(Select, { options: profiles.map(p => ({
643
636
  label: `${p.displayName}${p.isActive ? ' (Active)' : ''}`,
644
637
  value: p.name,
645
- })),
646
- {
647
- label: chalk.green('+ New Profile'),
648
- value: '__CREATE_NEW__',
649
- },
650
- {
651
- label: chalk.red('🆇 Delete Profile'),
652
- value: '__DELETE__',
653
- },
654
- ], defaultValue: activeProfile, onChange: handleProfileChange })),
638
+ })), defaultValue: activeProfile, onChange: value => {
639
+ switchProfile(value);
640
+ loadProfilesAndConfig();
641
+ setIsEditing(false);
642
+ setErrors([]);
643
+ } }),
644
+ React.createElement(Box, { flexDirection: "row", marginTop: 1 },
645
+ React.createElement(Box, { marginRight: 2 },
646
+ React.createElement(Text, { color: "green" }, "+ New"),
647
+ React.createElement(Text, { color: "gray" }, " (n)")),
648
+ React.createElement(Box, null,
649
+ React.createElement(Text, { color: "red" }, "\uD83C\uDD87 Delete"),
650
+ React.createElement(Text, { color: "gray" }, " (d)"))))),
655
651
  currentField === 'requestMethod' && (React.createElement(Select, { options: requestMethodOptions, defaultValue: requestMethod, onChange: value => {
656
652
  setRequestMethod(value);
657
653
  setIsEditing(false);
@@ -669,7 +665,9 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
669
665
  currentField === 'basicModel' ||
670
666
  currentField === 'compactModelName') &&
671
667
  'Type to filter, ↑↓ to select, Enter to confirm, Esc to cancel',
672
- (currentField === 'profile' || currentField === 'requestMethod') &&
668
+ currentField === 'profile' &&
669
+ '↑↓ to select profile, N to create new, D to delete, Enter to confirm, Esc to cancel',
670
+ currentField === 'requestMethod' &&
673
671
  '↑↓ to select, Enter to confirm, Esc to cancel')))) : (React.createElement(Box, { flexDirection: "column" },
674
672
  React.createElement(Box, { flexDirection: "column" },
675
673
  React.createElement(Text, { color: currentField === 'profile' ? 'green' : 'white' },
@@ -707,7 +705,7 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
707
705
  "Anthropic Beta:"),
708
706
  React.createElement(Box, { marginLeft: 3 },
709
707
  React.createElement(Text, { color: "gray" },
710
- anthropicBeta ? ' Enabled' : '☐ Disabled',
708
+ anthropicBeta ? ' Enabled' : '☐ Disabled',
711
709
  " (Press Enter to toggle)"))),
712
710
  React.createElement(Box, { flexDirection: "column" },
713
711
  React.createElement(Text, { color: currentField === 'advancedModel' ? 'green' : 'white' },
@@ -760,7 +758,10 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
760
758
  currentField === 'compactModelName')) && (React.createElement(Box, { flexDirection: "column", marginTop: 1 }, isEditing ? (React.createElement(Alert, { variant: "info" },
761
759
  "Editing mode:",
762
760
  ' ',
763
- currentField === 'maxContextTokens' || currentField === 'maxTokens'
761
+ currentField === 'maxContextTokens' ||
762
+ currentField === 'maxTokens'
764
763
  ? 'Type to edit, Enter to save'
765
- : 'Press Enter to save and exit editing')) : (React.createElement(Alert, { variant: "info" }, "Use \u2191\u2193 to navigate, Enter to edit, M for manual input, Ctrl+S or Esc to save"))))));
764
+ : 'Press Enter to save and exit editing')) : (React.createElement(Alert, { variant: "info" }, currentField === 'profile'
765
+ ? 'Use ↑↓ to navigate, N to create new profile, D to delete profile, Ctrl+S or Esc to save'
766
+ : 'Use ↑↓ to navigate, Enter to edit, M for manual input, Ctrl+S or Esc to save'))))));
766
767
  }
@@ -98,7 +98,7 @@ export default function ProxyConfigScreen({ onBack, onSave, inlineMode = false }
98
98
  "Enable Proxy:"),
99
99
  React.createElement(Box, { marginLeft: 3 },
100
100
  React.createElement(Text, { color: "gray" },
101
- enabled ? ' Enabled' : '☐ Disabled',
101
+ enabled ? ' Enabled' : '☐ Disabled',
102
102
  " (Press Enter to toggle)")))),
103
103
  React.createElement(Box, { marginBottom: 1 },
104
104
  React.createElement(Box, { flexDirection: "column" },
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ type Props = {
3
+ onBack: () => void;
4
+ onSave: () => void;
5
+ inlineMode?: boolean;
6
+ agentId?: string;
7
+ };
8
+ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode, agentId, }: Props): React.JSX.Element;
9
+ export {};