snow-ai 0.3.32 → 0.3.33

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/app.js CHANGED
@@ -69,9 +69,9 @@ export default function App({ version, skipWelcome, headlessPrompt }) {
69
69
  case 'mcp':
70
70
  return (React.createElement(MCPConfigScreen, { onBack: () => setCurrentView('welcome'), onSave: () => setCurrentView('welcome') }));
71
71
  case 'systemprompt':
72
- return (React.createElement(SystemPromptConfigScreen, { onBack: () => setCurrentView('welcome'), onSave: () => setCurrentView('welcome') }));
72
+ return (React.createElement(SystemPromptConfigScreen, { onBack: () => setCurrentView('welcome') }));
73
73
  case 'customheaders':
74
- return (React.createElement(CustomHeadersScreen, { onBack: () => setCurrentView('welcome'), onSave: () => setCurrentView('welcome') }));
74
+ return React.createElement(CustomHeadersScreen, { onBack: () => setCurrentView('welcome') });
75
75
  default:
76
76
  return (React.createElement(WelcomeScreen, { version: version, onMenuSelect: handleMenuSelect }));
77
77
  }
@@ -1,6 +1,6 @@
1
+ import React from 'react';
1
2
  type Props = {
2
3
  onBack: () => void;
3
- onSave: () => void;
4
4
  };
5
- export default function CustomHeadersScreen({ onBack }: Props): null;
5
+ export default function CustomHeadersScreen({ onBack }: Props): React.JSX.Element | null;
6
6
  export {};
@@ -1,104 +1,494 @@
1
- import { useEffect } from 'react';
2
- import { useApp } from 'ink';
3
- import { spawn } from 'child_process';
4
- import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';
5
- import { join } from 'path';
6
- import { homedir, platform } from 'os';
7
- const CONFIG_DIR = join(homedir(), '.snow');
8
- const CUSTOM_HEADERS_FILE = join(CONFIG_DIR, 'custom-headers.json');
9
- function getSystemEditor() {
10
- if (platform() === 'win32') {
11
- return 'notepad';
12
- }
13
- return process.env['EDITOR'] || 'vim';
14
- }
15
- function ensureConfigDirectory() {
16
- if (!existsSync(CONFIG_DIR)) {
17
- mkdirSync(CONFIG_DIR, { recursive: true });
18
- }
19
- }
20
- const DEFAULT_HEADERS_TEMPLATE = `{
21
- "X-Custom-Header": "custom-value",
22
- "User-Agent": "MyApp/1.0"
23
- }`;
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 { getCustomHeadersConfig, saveCustomHeadersConfig, } from '../../utils/apiConfig.js';
24
7
  export default function CustomHeadersScreen({ onBack }) {
25
- const { exit } = useApp();
8
+ const [config, setConfig] = useState(() => {
9
+ return (getCustomHeadersConfig() || {
10
+ active: '',
11
+ schemes: [],
12
+ });
13
+ });
14
+ const [view, setView] = useState('list');
15
+ const [selectedIndex, setSelectedIndex] = useState(0);
16
+ const [currentAction, setCurrentAction] = useState('activate');
17
+ const [isEditing, setIsEditing] = useState(false);
18
+ const [editName, setEditName] = useState('');
19
+ const [editHeaders, setEditHeaders] = useState({});
20
+ const [editingField, setEditingField] = useState('name');
21
+ const [error, setError] = useState('');
22
+ // Headers editing state
23
+ const [headerKeys, setHeaderKeys] = useState([]);
24
+ const [headerSelectedIndex, setHeaderSelectedIndex] = useState(0);
25
+ const [headerEditingIndex, setHeaderEditingIndex] = useState(-1);
26
+ const [headerEditingField, setHeaderEditingField] = useState('key');
27
+ const [headerEditKey, setHeaderEditKey] = useState('');
28
+ const [headerEditValue, setHeaderEditValue] = useState('');
29
+ const actions = config.schemes.length > 0
30
+ ? config.active
31
+ ? ['activate', 'deactivate', 'edit', 'delete', 'add', 'back']
32
+ : ['activate', 'edit', 'delete', 'add', 'back']
33
+ : ['add', 'back'];
26
34
  useEffect(() => {
27
- const openEditor = async () => {
28
- ensureConfigDirectory();
29
- // Read existing custom headers, or use template if not exists
30
- let currentHeaders = DEFAULT_HEADERS_TEMPLATE;
31
- if (existsSync(CUSTOM_HEADERS_FILE)) {
32
- try {
33
- currentHeaders = readFileSync(CUSTOM_HEADERS_FILE, 'utf8');
35
+ const savedConfig = getCustomHeadersConfig();
36
+ if (savedConfig) {
37
+ setConfig(savedConfig);
38
+ }
39
+ }, [view]);
40
+ const saveAndRefresh = (newConfig) => {
41
+ try {
42
+ saveCustomHeadersConfig(newConfig);
43
+ setConfig(newConfig);
44
+ setError('');
45
+ return true;
46
+ }
47
+ catch (err) {
48
+ setError(err instanceof Error ? err.message : 'Failed to save');
49
+ return false;
50
+ }
51
+ };
52
+ const handleActivate = () => {
53
+ if (config.schemes.length === 0 || selectedIndex >= config.schemes.length)
54
+ return;
55
+ const scheme = config.schemes[selectedIndex];
56
+ const newConfig = {
57
+ ...config,
58
+ active: scheme.id,
59
+ };
60
+ if (saveAndRefresh(newConfig)) {
61
+ setError('');
62
+ }
63
+ };
64
+ const handleDeactivate = () => {
65
+ const newConfig = {
66
+ ...config,
67
+ active: '',
68
+ };
69
+ if (saveAndRefresh(newConfig)) {
70
+ setError('');
71
+ }
72
+ };
73
+ const handleEdit = () => {
74
+ if (config.schemes.length === 0 || selectedIndex >= config.schemes.length)
75
+ return;
76
+ const scheme = config.schemes[selectedIndex];
77
+ setEditName(scheme.name);
78
+ setEditHeaders(scheme.headers);
79
+ setEditingField('name');
80
+ setView('edit');
81
+ };
82
+ const handleDelete = () => {
83
+ setView('confirmDelete');
84
+ };
85
+ const confirmDelete = () => {
86
+ if (config.schemes.length === 0 || selectedIndex >= config.schemes.length)
87
+ return;
88
+ const schemeToDelete = config.schemes[selectedIndex];
89
+ const newSchemes = config.schemes.filter((_, i) => i !== selectedIndex);
90
+ const newActive = config.active === schemeToDelete.id && newSchemes.length > 0
91
+ ? newSchemes[0].id
92
+ : config.active === schemeToDelete.id
93
+ ? ''
94
+ : config.active;
95
+ const newConfig = {
96
+ active: newActive,
97
+ schemes: newSchemes,
98
+ };
99
+ if (saveAndRefresh(newConfig)) {
100
+ setSelectedIndex(Math.max(0, selectedIndex - 1));
101
+ setView('list');
102
+ }
103
+ };
104
+ const handleAdd = () => {
105
+ setEditName('');
106
+ setEditHeaders({});
107
+ setEditingField('name');
108
+ setView('add');
109
+ };
110
+ const saveNewScheme = () => {
111
+ const newScheme = {
112
+ id: Date.now().toString(),
113
+ name: editName.trim() || 'Unnamed Scheme',
114
+ headers: editHeaders,
115
+ createdAt: new Date().toISOString(),
116
+ };
117
+ const newConfig = {
118
+ ...config,
119
+ schemes: [...config.schemes, newScheme],
120
+ active: config.schemes.length === 0 ? newScheme.id : config.active,
121
+ };
122
+ if (saveAndRefresh(newConfig)) {
123
+ setView('list');
124
+ setSelectedIndex(config.schemes.length);
125
+ }
126
+ };
127
+ const saveEditedScheme = () => {
128
+ if (config.schemes.length === 0 || selectedIndex >= config.schemes.length)
129
+ return;
130
+ const newConfig = {
131
+ ...config,
132
+ schemes: config.schemes.map((s, i) => i === selectedIndex
133
+ ? {
134
+ ...s,
135
+ name: editName.trim() || 'Unnamed Scheme',
136
+ headers: editHeaders,
34
137
  }
35
- catch {
36
- // Read failed, use template
37
- currentHeaders = DEFAULT_HEADERS_TEMPLATE;
138
+ : s),
139
+ };
140
+ if (saveAndRefresh(newConfig)) {
141
+ setView('list');
142
+ }
143
+ };
144
+ // Headers editing functions
145
+ const enterHeadersEditMode = () => {
146
+ setHeaderKeys(Object.keys(editHeaders));
147
+ setHeaderSelectedIndex(0);
148
+ setHeaderEditingIndex(-1);
149
+ setView('editHeaders');
150
+ };
151
+ const exitHeadersEditMode = () => {
152
+ setView(view === 'add' ? 'add' : 'edit');
153
+ };
154
+ const addNewHeader = () => {
155
+ setHeaderEditKey('');
156
+ setHeaderEditValue('');
157
+ setHeaderEditingIndex(headerKeys.length);
158
+ setHeaderEditingField('key');
159
+ };
160
+ const editHeaderAtIndex = (index) => {
161
+ const key = headerKeys[index];
162
+ setHeaderEditKey(key);
163
+ setHeaderEditValue(editHeaders[key] || '');
164
+ setHeaderEditingIndex(index);
165
+ setHeaderEditingField('key');
166
+ };
167
+ const saveHeaderEdit = () => {
168
+ const trimmedKey = headerEditKey.trim();
169
+ const trimmedValue = headerEditValue.trim();
170
+ if (!trimmedKey) {
171
+ setHeaderEditingIndex(-1);
172
+ return;
173
+ }
174
+ const newHeaders = { ...editHeaders };
175
+ if (headerEditingIndex < headerKeys.length) {
176
+ const oldKey = headerKeys[headerEditingIndex];
177
+ if (oldKey !== trimmedKey) {
178
+ delete newHeaders[oldKey];
179
+ }
180
+ }
181
+ newHeaders[trimmedKey] = trimmedValue;
182
+ setEditHeaders(newHeaders);
183
+ setHeaderKeys(Object.keys(newHeaders));
184
+ setHeaderEditingIndex(-1);
185
+ };
186
+ const deleteHeaderAtIndex = (index) => {
187
+ const key = headerKeys[index];
188
+ const newHeaders = { ...editHeaders };
189
+ delete newHeaders[key];
190
+ setEditHeaders(newHeaders);
191
+ setHeaderKeys(Object.keys(newHeaders));
192
+ setHeaderSelectedIndex(Math.max(0, Math.min(index, headerKeys.length - 2)));
193
+ };
194
+ // List view input handling
195
+ useInput((_input, key) => {
196
+ if (view !== 'list')
197
+ return;
198
+ if (key.escape) {
199
+ onBack();
200
+ }
201
+ else if (key.upArrow) {
202
+ if (config.schemes.length > 0) {
203
+ setSelectedIndex(prev => prev > 0 ? prev - 1 : config.schemes.length - 1);
204
+ }
205
+ }
206
+ else if (key.downArrow) {
207
+ if (config.schemes.length > 0) {
208
+ setSelectedIndex(prev => prev < config.schemes.length - 1 ? prev + 1 : 0);
209
+ }
210
+ }
211
+ else if (key.leftArrow) {
212
+ const currentIdx = actions.indexOf(currentAction);
213
+ setCurrentAction(actions[currentIdx > 0 ? currentIdx - 1 : actions.length - 1]);
214
+ }
215
+ else if (key.rightArrow) {
216
+ const currentIdx = actions.indexOf(currentAction);
217
+ setCurrentAction(actions[currentIdx < actions.length - 1 ? currentIdx + 1 : 0]);
218
+ }
219
+ else if (key.return) {
220
+ if (currentAction === 'activate') {
221
+ handleActivate();
222
+ }
223
+ else if (currentAction === 'deactivate') {
224
+ handleDeactivate();
225
+ }
226
+ else if (currentAction === 'edit') {
227
+ handleEdit();
228
+ }
229
+ else if (currentAction === 'delete') {
230
+ handleDelete();
231
+ }
232
+ else if (currentAction === 'add') {
233
+ handleAdd();
234
+ }
235
+ else if (currentAction === 'back') {
236
+ onBack();
237
+ }
238
+ }
239
+ }, { isActive: view === 'list' });
240
+ // Add/Edit view input handling
241
+ useInput((input, key) => {
242
+ if (view !== 'add' && view !== 'edit')
243
+ return;
244
+ if (key.escape) {
245
+ setView('list');
246
+ setError('');
247
+ }
248
+ else if (!isEditing && key.upArrow) {
249
+ setEditingField('name');
250
+ }
251
+ else if (!isEditing && key.downArrow) {
252
+ setEditingField('headers');
253
+ }
254
+ else if (key.return) {
255
+ if (editingField === 'headers' && !isEditing) {
256
+ enterHeadersEditMode();
257
+ }
258
+ else if (isEditing) {
259
+ setIsEditing(false);
260
+ }
261
+ else {
262
+ setIsEditing(true);
263
+ }
264
+ }
265
+ else if (input === 's' && (key.ctrl || key.meta)) {
266
+ if (view === 'add') {
267
+ saveNewScheme();
268
+ }
269
+ else {
270
+ saveEditedScheme();
271
+ }
272
+ }
273
+ }, { isActive: view === 'add' || view === 'edit' });
274
+ // Headers edit view input handling
275
+ useInput((input, key) => {
276
+ if (view !== 'editHeaders')
277
+ return;
278
+ if (headerEditingIndex === -1) {
279
+ // 列表浏览模式
280
+ if (key.escape) {
281
+ exitHeadersEditMode();
282
+ }
283
+ else if (key.upArrow) {
284
+ setHeaderSelectedIndex(prev => prev > 0 ? prev - 1 : headerKeys.length);
285
+ }
286
+ else if (key.downArrow) {
287
+ setHeaderSelectedIndex(prev => prev < headerKeys.length ? prev + 1 : 0);
288
+ }
289
+ else if (key.return) {
290
+ if (headerSelectedIndex < headerKeys.length) {
291
+ editHeaderAtIndex(headerSelectedIndex);
292
+ }
293
+ else {
294
+ addNewHeader();
38
295
  }
39
296
  }
40
- // Write to file for editing
41
- writeFileSync(CUSTOM_HEADERS_FILE, currentHeaders, 'utf8');
42
- const editor = getSystemEditor();
43
- exit();
44
- const child = spawn(editor, [CUSTOM_HEADERS_FILE], {
45
- stdio: 'inherit'
46
- });
47
- child.on('close', () => {
48
- // Read edited content
49
- if (existsSync(CUSTOM_HEADERS_FILE)) {
50
- try {
51
- const editedContent = readFileSync(CUSTOM_HEADERS_FILE, 'utf8');
52
- const trimmedContent = editedContent.trim();
53
- // Validate JSON format
54
- if (trimmedContent === '' || trimmedContent === '{}') {
55
- // Empty or empty object, delete file to reset
56
- try {
57
- const fs = require('fs');
58
- fs.unlinkSync(CUSTOM_HEADERS_FILE);
59
- console.log('Custom headers cleared. Please use `snow` to restart!');
60
- }
61
- catch {
62
- // Delete failed, save empty object
63
- writeFileSync(CUSTOM_HEADERS_FILE, '{}', 'utf8');
64
- console.log('Custom headers cleared. Please use `snow` to restart!');
65
- }
66
- }
67
- else {
68
- // Validate JSON
69
- try {
70
- const headers = JSON.parse(trimmedContent);
71
- if (typeof headers !== 'object' || headers === null || Array.isArray(headers)) {
72
- throw new Error('Headers must be a JSON object');
73
- }
74
- // Validate all values are strings
75
- for (const [key, value] of Object.entries(headers)) {
76
- if (typeof value !== 'string') {
77
- throw new Error(`Header value for "${key}" must be a string`);
78
- }
79
- }
80
- // Save valid headers
81
- writeFileSync(CUSTOM_HEADERS_FILE, JSON.stringify(headers, null, 2), 'utf8');
82
- console.log('Custom headers saved successfully! Please use `snow` to restart!');
83
- }
84
- catch (error) {
85
- console.error('Invalid JSON format:', error instanceof Error ? error.message : 'Unknown error');
86
- console.error('Custom headers were NOT saved. Please fix the JSON format and try again.');
87
- }
88
- }
89
- }
90
- catch (error) {
91
- console.error('Failed to save custom headers:', error instanceof Error ? error.message : 'Unknown error');
92
- }
297
+ else if (key.delete || input === 'd') {
298
+ if (headerSelectedIndex < headerKeys.length) {
299
+ deleteHeaderAtIndex(headerSelectedIndex);
93
300
  }
94
- process.exit(0);
95
- });
96
- child.on('error', (error) => {
97
- console.error('Failed to open editor:', error.message);
98
- process.exit(1);
99
- });
100
- };
101
- openEditor();
102
- }, [exit, onBack]);
301
+ }
302
+ }
303
+ else {
304
+ // 编辑模式
305
+ if (key.escape) {
306
+ setHeaderEditingIndex(-1);
307
+ }
308
+ else if (key.upArrow && !isEditing) {
309
+ setHeaderEditingField('key');
310
+ }
311
+ else if (key.downArrow && !isEditing) {
312
+ setHeaderEditingField('value');
313
+ }
314
+ else if (key.return) {
315
+ if (isEditing) {
316
+ setIsEditing(false);
317
+ }
318
+ else {
319
+ setIsEditing(true);
320
+ }
321
+ }
322
+ else if (input === 's' && (key.ctrl || key.meta)) {
323
+ saveHeaderEdit();
324
+ }
325
+ }
326
+ }, { isActive: view === 'editHeaders' });
327
+ // Delete confirmation input handling
328
+ useInput((input, key) => {
329
+ if (view !== 'confirmDelete')
330
+ return;
331
+ if (key.escape || input === 'n' || input === 'N') {
332
+ setView('list');
333
+ }
334
+ else if (input === 'y' || input === 'Y' || key.return) {
335
+ confirmDelete();
336
+ }
337
+ }, { isActive: view === 'confirmDelete' });
338
+ // Render list view
339
+ if (view === 'list') {
340
+ const activeScheme = config.schemes.find(s => s.id === config.active);
341
+ return (React.createElement(Box, { flexDirection: "column", padding: 1 },
342
+ React.createElement(Box, { marginBottom: 1, borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 },
343
+ React.createElement(Box, { flexDirection: "column" },
344
+ React.createElement(Gradient, { name: "rainbow" }, "Custom Headers Management"),
345
+ React.createElement(Text, { color: "gray", dimColor: true }, "Manage multiple header schemes and switch between them"))),
346
+ error && (React.createElement(Box, { marginBottom: 1 },
347
+ React.createElement(Alert, { variant: "error" }, error))),
348
+ React.createElement(Box, { marginBottom: 1 },
349
+ React.createElement(Text, { bold: true },
350
+ "Active Scheme:",
351
+ ' ',
352
+ React.createElement(Text, { color: "green" }, activeScheme?.name || 'None'))),
353
+ config.schemes.length === 0 ? (React.createElement(Box, { marginBottom: 1 },
354
+ React.createElement(Text, { color: "yellow" }, "No header schemes configured. Press Enter to add one."))) : (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
355
+ React.createElement(Text, { bold: true, color: "cyan" }, "Available Schemes:"),
356
+ config.schemes.map((scheme, index) => {
357
+ const headerCount = Object.keys(scheme.headers).length;
358
+ const headerPreview = headerCount > 0
359
+ ? Object.entries(scheme.headers)
360
+ .slice(0, 2)
361
+ .map(([k, v]) => `${k}: ${v}`)
362
+ .join(', ')
363
+ : '';
364
+ return (React.createElement(Box, { key: scheme.id, marginLeft: 2 },
365
+ React.createElement(Text, { color: index === selectedIndex
366
+ ? 'green'
367
+ : scheme.id === config.active
368
+ ? 'cyan'
369
+ : 'white' },
370
+ index === selectedIndex ? '❯ ' : ' ',
371
+ scheme.id === config.active ? '✓ ' : ' ',
372
+ scheme.name,
373
+ headerPreview && (React.createElement(Text, { dimColor: true },
374
+ ' ',
375
+ "- ",
376
+ headerPreview.substring(0, 50),
377
+ headerPreview.length > 50 ? '...' : '')))));
378
+ }))),
379
+ React.createElement(Box, { marginBottom: 1 },
380
+ React.createElement(Text, { bold: true, color: "cyan" }, "Actions:")),
381
+ React.createElement(Box, { flexDirection: "column", marginBottom: 1, marginLeft: 2 }, actions.map(action => (React.createElement(Text, { key: action, color: currentAction === action ? 'green' : 'gray', bold: currentAction === action },
382
+ currentAction === action ? '❯ ' : ' ',
383
+ action === 'activate' && 'Activate',
384
+ action === 'deactivate' && 'Deactivate',
385
+ action === 'edit' && 'Edit',
386
+ action === 'delete' && 'Delete',
387
+ action === 'add' && 'Add New',
388
+ action === 'back' && '[ESC] Back')))),
389
+ React.createElement(Box, { marginTop: 1 },
390
+ React.createElement(Text, { color: "gray", dimColor: true }, "Use \u2191\u2193 to select scheme, \u2190\u2192 to select action, Enter to confirm"))));
391
+ }
392
+ // Render add/edit view
393
+ if (view === 'add' || view === 'edit') {
394
+ const headerCount = Object.keys(editHeaders).length;
395
+ const headerPreview = headerCount > 0
396
+ ? Object.entries(editHeaders)
397
+ .slice(0, 3)
398
+ .map(([k, v]) => `${k}: ${v}`)
399
+ .join(', ')
400
+ : 'Not set';
401
+ return (React.createElement(Box, { flexDirection: "column", padding: 1 },
402
+ React.createElement(Box, { marginBottom: 1, borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 },
403
+ React.createElement(Gradient, { name: "rainbow" }, view === 'add' ? 'Add New Header Scheme' : 'Edit Header Scheme')),
404
+ error && (React.createElement(Box, { marginBottom: 1 },
405
+ React.createElement(Alert, { variant: "error" }, error))),
406
+ React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
407
+ React.createElement(Box, { marginBottom: 1 },
408
+ React.createElement(Box, { flexDirection: "column" },
409
+ React.createElement(Text, { color: editingField === 'name' ? 'green' : 'white' },
410
+ editingField === 'name' ? '❯ ' : ' ',
411
+ "Name:"),
412
+ editingField === 'name' && isEditing && (React.createElement(Box, { marginLeft: 3 },
413
+ React.createElement(TextInput, { value: editName, onChange: setEditName, placeholder: "Enter scheme name" }))),
414
+ (!isEditing || editingField !== 'name') && (React.createElement(Box, { marginLeft: 3 },
415
+ React.createElement(Text, { color: "gray" }, editName || 'Not set'))))),
416
+ React.createElement(Box, { marginBottom: 1 },
417
+ React.createElement(Box, { flexDirection: "column" },
418
+ React.createElement(Text, { color: editingField === 'headers' ? 'green' : 'white' },
419
+ editingField === 'headers' ? '❯ ' : ' ',
420
+ "Headers (",
421
+ headerCount,
422
+ ' ',
423
+ "configured):"),
424
+ editingField === 'headers' && !isEditing ? (React.createElement(Box, { marginLeft: 3 },
425
+ React.createElement(Text, { color: "cyan", dimColor: true }, "Press Enter to edit headers \u2192"))) : (React.createElement(Box, { marginLeft: 3 },
426
+ React.createElement(Text, { color: "gray" },
427
+ headerPreview.substring(0, 100),
428
+ headerPreview.length > 100 ? '...' : '')))))),
429
+ React.createElement(Box, { marginTop: 1 },
430
+ React.createElement(Text, { color: "gray", dimColor: true }, "\u2191\u2193: Navigate fields | Enter: Edit | Ctrl+S: Save | ESC: Cancel"))));
431
+ }
432
+ // Render headers edit view
433
+ if (view === 'editHeaders') {
434
+ return (React.createElement(Box, { flexDirection: "column", padding: 1 },
435
+ React.createElement(Box, { marginBottom: 1, borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 },
436
+ React.createElement(Gradient, { name: "rainbow" },
437
+ "Edit Headers - ",
438
+ editName)),
439
+ headerEditingIndex === -1 ? (React.createElement(React.Fragment, null,
440
+ React.createElement(Box, { marginBottom: 1 },
441
+ React.createElement(Text, { bold: true, color: "cyan" }, "Header List:")),
442
+ headerKeys.length === 0 ? (React.createElement(Box, { marginBottom: 1 },
443
+ React.createElement(Text, { color: "yellow" }, "No headers configured. Press Enter to add one."))) : (React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, headerKeys.map((key, index) => {
444
+ const isSelected = index === headerSelectedIndex;
445
+ return (React.createElement(Box, { key: index, marginLeft: 2 },
446
+ React.createElement(Text, { color: isSelected ? 'green' : 'white', bold: isSelected },
447
+ isSelected ? '❯ ' : ' ',
448
+ key,
449
+ ": ",
450
+ editHeaders[key])));
451
+ }))),
452
+ React.createElement(Box, { marginLeft: 2, marginBottom: 1 },
453
+ React.createElement(Text, { color: headerSelectedIndex === headerKeys.length ? 'green' : 'gray', bold: headerSelectedIndex === headerKeys.length },
454
+ headerSelectedIndex === headerKeys.length ? '❯ ' : ' ',
455
+ "[+] Add new header")),
456
+ React.createElement(Box, { marginTop: 1 },
457
+ React.createElement(Text, { color: "gray", dimColor: true }, "\u2191\u2193: Navigate | Enter: Edit/Add | D: Delete | ESC: Finish")))) : (React.createElement(React.Fragment, null,
458
+ React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
459
+ React.createElement(Box, { marginBottom: 1 },
460
+ React.createElement(Box, { flexDirection: "column" },
461
+ React.createElement(Text, { color: headerEditingField === 'key' ? 'green' : 'white' },
462
+ headerEditingField === 'key' ? '❯ ' : ' ',
463
+ "Key:"),
464
+ headerEditingField === 'key' && isEditing && (React.createElement(Box, { marginLeft: 3 },
465
+ React.createElement(TextInput, { value: headerEditKey, onChange: setHeaderEditKey, placeholder: "Header key (e.g., X-API-Key)" }))),
466
+ (!isEditing || headerEditingField !== 'key') && (React.createElement(Box, { marginLeft: 3 },
467
+ React.createElement(Text, { color: "gray" }, headerEditKey || 'Not set'))))),
468
+ React.createElement(Box, { marginBottom: 1 },
469
+ React.createElement(Box, { flexDirection: "column" },
470
+ React.createElement(Text, { color: headerEditingField === 'value' ? 'green' : 'white' },
471
+ headerEditingField === 'value' ? '❯ ' : ' ',
472
+ "Value:"),
473
+ headerEditingField === 'value' && isEditing && (React.createElement(Box, { marginLeft: 3 },
474
+ React.createElement(TextInput, { value: headerEditValue, onChange: setHeaderEditValue, placeholder: "Header value" }))),
475
+ (!isEditing || headerEditingField !== 'value') && (React.createElement(Box, { marginLeft: 3 },
476
+ React.createElement(Text, { color: "gray" }, headerEditValue || 'Not set')))))),
477
+ React.createElement(Box, { marginTop: 1 },
478
+ React.createElement(Text, { color: "gray", dimColor: true }, "\u2191\u2193: Navigate fields | Enter: Edit | Ctrl+S: Save | ESC: Cancel"))))));
479
+ }
480
+ // Render delete confirmation
481
+ if (view === 'confirmDelete') {
482
+ const schemeToDelete = config.schemes.length > 0 ? config.schemes[selectedIndex] : null;
483
+ return (React.createElement(Box, { flexDirection: "column", padding: 1 },
484
+ React.createElement(Alert, { variant: "warning" }, "Confirm Delete"),
485
+ React.createElement(Box, { marginBottom: 1 },
486
+ React.createElement(Text, null,
487
+ "Are you sure you want to delete \"",
488
+ React.createElement(Text, { bold: true, color: "yellow" }, schemeToDelete?.name),
489
+ "\"?")),
490
+ React.createElement(Box, { marginTop: 1 },
491
+ React.createElement(Text, { color: "gray", dimColor: true }, "Press Y to confirm, N or ESC to cancel"))));
492
+ }
103
493
  return null;
104
494
  }
@@ -1,6 +1,6 @@
1
+ import React from 'react';
1
2
  type Props = {
2
3
  onBack: () => void;
3
- onSave: () => void;
4
4
  };
5
- export default function SystemPromptConfigScreen({ onBack }: Props): null;
5
+ export default function SystemPromptConfigScreen({ onBack }: Props): React.JSX.Element | null;
6
6
  export {};