snow-ai 0.3.4 → 0.3.6

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 (37) 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 +226 -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/components/ToolResultPreview.js +21 -1
  15. package/dist/ui/pages/ChatScreen.js +29 -20
  16. package/dist/ui/pages/ConfigScreen.js +47 -46
  17. package/dist/ui/pages/ProxyConfigScreen.js +1 -1
  18. package/dist/ui/pages/SubAgentConfigScreen.d.ts +9 -0
  19. package/dist/ui/pages/SubAgentConfigScreen.js +352 -0
  20. package/dist/ui/pages/SubAgentListScreen.d.ts +9 -0
  21. package/dist/ui/pages/SubAgentListScreen.js +114 -0
  22. package/dist/ui/pages/WelcomeScreen.js +30 -2
  23. package/dist/utils/incrementalSnapshot.d.ts +7 -0
  24. package/dist/utils/incrementalSnapshot.js +34 -0
  25. package/dist/utils/mcpToolsManager.js +41 -1
  26. package/dist/utils/retryUtils.js +5 -0
  27. package/dist/utils/sessionConverter.d.ts +1 -0
  28. package/dist/utils/sessionConverter.js +192 -89
  29. package/dist/utils/subAgentConfig.d.ts +43 -0
  30. package/dist/utils/subAgentConfig.js +126 -0
  31. package/dist/utils/subAgentExecutor.d.ts +29 -0
  32. package/dist/utils/subAgentExecutor.js +272 -0
  33. package/dist/utils/toolExecutor.d.ts +10 -2
  34. package/dist/utils/toolExecutor.js +46 -5
  35. package/package.json +1 -1
  36. package/dist/ui/pages/ConfigProfileScreen.d.ts +0 -7
  37. package/dist/ui/pages/ConfigProfileScreen.js +0 -300
@@ -1,300 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { Box, Text, useInput } from 'ink';
3
- import Gradient from 'ink-gradient';
4
- import { Alert } from '@inkjs/ui';
5
- import TextInput from 'ink-text-input';
6
- import { getAllProfiles, switchProfile, createProfile, deleteProfile, renameProfile, } from '../../utils/configManager.js';
7
- import ConfigScreen from './ConfigScreen.js';
8
- const focusEventTokenRegex = /(?:\x1b)?\[[0-9;]*[IO]/g;
9
- const isFocusEventInput = (value) => {
10
- if (!value) {
11
- return false;
12
- }
13
- if (value === '\x1b[I' ||
14
- value === '\x1b[O' ||
15
- value === '[I' ||
16
- value === '[O') {
17
- return true;
18
- }
19
- const trimmed = value.trim();
20
- if (!trimmed) {
21
- return false;
22
- }
23
- const tokens = trimmed.match(focusEventTokenRegex);
24
- if (!tokens) {
25
- return false;
26
- }
27
- const normalized = trimmed.replace(/\s+/g, '');
28
- const tokensCombined = tokens.join('');
29
- return tokensCombined === normalized;
30
- };
31
- const stripFocusArtifacts = (value) => {
32
- if (!value) {
33
- return '';
34
- }
35
- return value
36
- .replace(/\x1b\[[0-9;]*[IO]/g, '')
37
- .replace(/\[[0-9;]*[IO]/g, '')
38
- .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
39
- };
40
- export default function ConfigProfileScreen({ onBack, onSelectProfile, }) {
41
- const [profiles, setProfiles] = useState([]);
42
- const [selectedIndex, setSelectedIndex] = useState(0);
43
- const [mode, setMode] = useState('list');
44
- const [inputValue, setInputValue] = useState('');
45
- const [error, setError] = useState('');
46
- // Load profiles on mount
47
- useEffect(() => {
48
- refreshProfiles();
49
- }, []);
50
- const refreshProfiles = () => {
51
- const loadedProfiles = getAllProfiles();
52
- setProfiles(loadedProfiles);
53
- // Find active profile and set selected index
54
- const activeIndex = loadedProfiles.findIndex(p => p.isActive);
55
- if (activeIndex !== -1) {
56
- setSelectedIndex(activeIndex);
57
- }
58
- };
59
- const handleCreateProfile = () => {
60
- const cleaned = stripFocusArtifacts(inputValue).trim();
61
- if (!cleaned) {
62
- setError('Profile name cannot be empty');
63
- return;
64
- }
65
- try {
66
- createProfile(cleaned);
67
- refreshProfiles();
68
- setMode('list');
69
- setInputValue('');
70
- setError('');
71
- }
72
- catch (err) {
73
- setError(err instanceof Error ? err.message : 'Failed to create profile');
74
- }
75
- };
76
- const handleRenameProfile = () => {
77
- const cleaned = stripFocusArtifacts(inputValue).trim();
78
- const currentProfile = profiles[selectedIndex];
79
- if (!currentProfile) {
80
- setError('No profile selected');
81
- return;
82
- }
83
- if (!cleaned) {
84
- setError('Profile name cannot be empty');
85
- return;
86
- }
87
- try {
88
- renameProfile(currentProfile.name, cleaned);
89
- refreshProfiles();
90
- setMode('list');
91
- setInputValue('');
92
- setError('');
93
- }
94
- catch (err) {
95
- setError(err instanceof Error ? err.message : 'Failed to rename profile');
96
- }
97
- };
98
- const handleDeleteProfile = () => {
99
- const currentProfile = profiles[selectedIndex];
100
- if (!currentProfile) {
101
- return;
102
- }
103
- try {
104
- deleteProfile(currentProfile.name);
105
- refreshProfiles();
106
- setMode('list');
107
- setError('');
108
- setSelectedIndex(Math.max(0, selectedIndex - 1));
109
- }
110
- catch (err) {
111
- setError(err instanceof Error ? err.message : 'Failed to delete profile');
112
- setMode('list');
113
- }
114
- };
115
- const handleSwitchProfile = () => {
116
- const currentProfile = profiles[selectedIndex];
117
- if (!currentProfile) {
118
- return;
119
- }
120
- try {
121
- switchProfile(currentProfile.name);
122
- onSelectProfile(currentProfile.name);
123
- }
124
- catch (err) {
125
- setError(err instanceof Error ? err.message : 'Failed to switch profile');
126
- }
127
- };
128
- const handleEditProfile = () => {
129
- const currentProfile = profiles[selectedIndex];
130
- if (!currentProfile) {
131
- return;
132
- }
133
- // Switch to this profile first to make it active for editing
134
- try {
135
- switchProfile(currentProfile.name);
136
- setMode('edit');
137
- setError('');
138
- }
139
- catch (err) {
140
- setError(err instanceof Error ? err.message : 'Failed to edit profile');
141
- }
142
- };
143
- const handleEditComplete = () => {
144
- // Refresh profiles to show updated config
145
- refreshProfiles();
146
- setMode('list');
147
- setError('');
148
- };
149
- useInput((rawInput, key) => {
150
- const input = stripFocusArtifacts(rawInput);
151
- if (!input && isFocusEventInput(rawInput)) {
152
- return;
153
- }
154
- if (isFocusEventInput(rawInput)) {
155
- return;
156
- }
157
- // Handle text input modes
158
- if (mode === 'create' || mode === 'rename') {
159
- if (key.return) {
160
- if (mode === 'create') {
161
- handleCreateProfile();
162
- }
163
- else if (mode === 'rename') {
164
- handleRenameProfile();
165
- }
166
- }
167
- else if (key.escape) {
168
- setMode('list');
169
- setInputValue('');
170
- setError('');
171
- }
172
- return;
173
- }
174
- // Handle edit mode - don't intercept input
175
- if (mode === 'edit') {
176
- // ConfigScreen handles all input
177
- return;
178
- }
179
- // Handle delete confirmation
180
- if (mode === 'delete-confirm') {
181
- if (input === 'y' || input === 'Y') {
182
- handleDeleteProfile();
183
- }
184
- else if (input === 'n' || input === 'N' || key.escape) {
185
- setMode('list');
186
- setError('');
187
- }
188
- return;
189
- }
190
- // Handle list mode
191
- if (mode === 'list') {
192
- if (key.escape) {
193
- onBack();
194
- }
195
- else if (key.upArrow) {
196
- setSelectedIndex(Math.max(0, selectedIndex - 1));
197
- setError('');
198
- }
199
- else if (key.downArrow) {
200
- setSelectedIndex(Math.min(profiles.length - 1, selectedIndex + 1));
201
- setError('');
202
- }
203
- else if (key.return) {
204
- handleSwitchProfile();
205
- }
206
- else if (input === 'n' || input === 'N') {
207
- setMode('create');
208
- setInputValue('');
209
- setError('');
210
- }
211
- else if (input === 'e' || input === 'E') {
212
- handleEditProfile();
213
- }
214
- else if (input === 'r' || input === 'R') {
215
- const currentProfile = profiles[selectedIndex];
216
- if (currentProfile) {
217
- setInputValue(currentProfile.name);
218
- setMode('rename');
219
- setError('');
220
- }
221
- }
222
- else if (input === 'd' || input === 'D') {
223
- const currentProfile = profiles[selectedIndex];
224
- if (currentProfile && currentProfile.name !== 'default') {
225
- setMode('delete-confirm');
226
- setError('');
227
- }
228
- else if (currentProfile?.name === 'default') {
229
- setError('Cannot delete the default profile');
230
- }
231
- }
232
- }
233
- });
234
- // Render input mode
235
- if (mode === 'create' || mode === 'rename') {
236
- return (React.createElement(Box, { flexDirection: "column", padding: 1 },
237
- React.createElement(Box, { marginBottom: 1, borderStyle: "double", borderColor: "cyan", paddingX: 2 },
238
- React.createElement(Box, { flexDirection: "column" },
239
- React.createElement(Gradient, { name: "rainbow" }, mode === 'create' ? 'Create New Profile' : 'Rename Profile'),
240
- React.createElement(Text, { color: "gray", dimColor: true }, mode === 'create'
241
- ? 'Enter a name for the new profile'
242
- : 'Enter a new name for the profile'))),
243
- React.createElement(Box, { flexDirection: "column" },
244
- React.createElement(Text, { color: "cyan" }, "Profile Name:"),
245
- React.createElement(Box, { marginLeft: 2 },
246
- React.createElement(TextInput, { value: inputValue, onChange: value => setInputValue(stripFocusArtifacts(value)), placeholder: "e.g., work, personal, test" }))),
247
- error && (React.createElement(Box, { marginTop: 1 },
248
- React.createElement(Text, { color: "red" },
249
- "Error: ",
250
- error))),
251
- React.createElement(Box, { marginTop: 1 },
252
- React.createElement(Alert, { variant: "info" }, "Press Enter to save, Esc to cancel"))));
253
- }
254
- // Render delete confirmation
255
- if (mode === 'delete-confirm') {
256
- const currentProfile = profiles[selectedIndex];
257
- return (React.createElement(Box, { flexDirection: "column", padding: 1 },
258
- React.createElement(Box, { marginBottom: 1, borderStyle: "double", borderColor: "cyan", paddingX: 2 },
259
- React.createElement(Box, { flexDirection: "column" },
260
- React.createElement(Gradient, { name: "rainbow" }, "Delete Profile"),
261
- React.createElement(Text, { color: "gray", dimColor: true }, "Confirm profile deletion"))),
262
- React.createElement(Box, { flexDirection: "column" },
263
- React.createElement(Text, { color: "yellow" },
264
- "Are you sure you want to delete the profile \"",
265
- currentProfile?.displayName,
266
- "\"?"),
267
- React.createElement(Text, { color: "gray", dimColor: true }, "This action cannot be undone.")),
268
- React.createElement(Box, { marginTop: 1 },
269
- React.createElement(Alert, { variant: "warning" }, "Press Y to confirm, N or Esc to cancel"))));
270
- }
271
- // Render edit mode
272
- if (mode === 'edit') {
273
- return (React.createElement(ConfigScreen, { onBack: handleEditComplete, onSave: handleEditComplete, inlineMode: false }));
274
- }
275
- // Render profile list
276
- return (React.createElement(Box, { flexDirection: "column", padding: 1 },
277
- React.createElement(Box, { marginBottom: 1, borderStyle: "double", borderColor: "cyan", paddingX: 2 },
278
- React.createElement(Box, { flexDirection: "column" },
279
- React.createElement(Gradient, { name: "rainbow" }, "Configuration Profiles"),
280
- React.createElement(Text, { color: "gray", dimColor: true }, "Manage multiple configuration profiles"))),
281
- React.createElement(Box, { flexDirection: "column" },
282
- React.createElement(Text, { color: "cyan", bold: true }, "Available Profiles:"),
283
- profiles.map((profile, index) => (React.createElement(Box, { key: profile.name, flexDirection: "column", marginLeft: 1 },
284
- React.createElement(Text, { color: index === selectedIndex ? 'green' : 'white', bold: profile.isActive },
285
- index === selectedIndex ? '❯ ' : ' ',
286
- profile.displayName,
287
- profile.isActive && (React.createElement(Text, { color: "cyan", dimColor: true },
288
- ' ',
289
- "(Active)"))),
290
- index === selectedIndex && (React.createElement(Box, { marginLeft: 3 },
291
- React.createElement(Text, { color: "gray", dimColor: true },
292
- "API: ",
293
- profile.config.snowcfg.baseUrl))))))),
294
- error && (React.createElement(Box, { marginTop: 1 },
295
- React.createElement(Text, { color: "red" },
296
- "Error: ",
297
- error))),
298
- React.createElement(Box, { flexDirection: "column", marginTop: 1 },
299
- React.createElement(Alert, { variant: "info" }, "\u2191\u2193: Navigate \u2022 Enter: Switch \u2022 E: Edit \u2022 N: New \u2022 R: Rename \u2022 D: Delete \u2022 Esc: Back"))));
300
- }