snow-ai 0.3.36 → 0.4.0

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 (97) hide show
  1. package/dist/agents/codebaseIndexAgent.js +1 -0
  2. package/dist/agents/codebaseReviewAgent.d.ts +61 -0
  3. package/dist/agents/codebaseReviewAgent.js +301 -0
  4. package/dist/agents/promptOptimizeAgent.d.ts +54 -0
  5. package/dist/agents/promptOptimizeAgent.js +268 -0
  6. package/dist/api/anthropic.js +1 -0
  7. package/dist/api/chat.js +1 -0
  8. package/dist/api/embedding.js +1 -0
  9. package/dist/api/gemini.js +2 -1
  10. package/dist/api/responses.js +1 -0
  11. package/dist/api/systemPrompt.d.ts +1 -5
  12. package/dist/api/systemPrompt.js +168 -100
  13. package/dist/app.js +14 -6
  14. package/dist/cli.js +1 -1
  15. package/dist/hooks/useCommandPanel.js +48 -46
  16. package/dist/hooks/useConversation.d.ts +2 -1
  17. package/dist/hooks/useConversation.js +116 -30
  18. package/dist/hooks/useGlobalExit.js +4 -2
  19. package/dist/hooks/useStreamingState.d.ts +9 -0
  20. package/dist/hooks/useStreamingState.js +3 -0
  21. package/dist/i18n/I18nContext.d.ts +14 -0
  22. package/dist/i18n/I18nContext.js +24 -0
  23. package/dist/i18n/index.d.ts +3 -0
  24. package/dist/i18n/index.js +2 -0
  25. package/dist/i18n/lang/en.d.ts +2 -0
  26. package/dist/i18n/lang/en.js +483 -0
  27. package/dist/i18n/lang/es.d.ts +2 -0
  28. package/dist/i18n/lang/es.js +483 -0
  29. package/dist/i18n/lang/ja.d.ts +2 -0
  30. package/dist/i18n/lang/ja.js +483 -0
  31. package/dist/i18n/lang/ko.d.ts +2 -0
  32. package/dist/i18n/lang/ko.js +483 -0
  33. package/dist/i18n/lang/zh-TW.d.ts +2 -0
  34. package/dist/i18n/lang/zh-TW.js +483 -0
  35. package/dist/i18n/lang/zh.d.ts +2 -0
  36. package/dist/i18n/lang/zh.js +483 -0
  37. package/dist/i18n/translations.d.ts +2 -0
  38. package/dist/i18n/translations.js +14 -0
  39. package/dist/i18n/types.d.ts +459 -0
  40. package/dist/i18n/types.js +1 -0
  41. package/dist/mcp/aceCodeSearch.d.ts +17 -48
  42. package/dist/mcp/aceCodeSearch.js +24 -56
  43. package/dist/mcp/bash.js +8 -1
  44. package/dist/mcp/codebaseSearch.d.ts +1 -1
  45. package/dist/mcp/codebaseSearch.js +159 -30
  46. package/dist/mcp/filesystem.d.ts +3 -80
  47. package/dist/mcp/filesystem.js +23 -103
  48. package/dist/mcp/subagent.d.ts +2 -1
  49. package/dist/mcp/subagent.js +54 -5
  50. package/dist/ui/components/ChatInput.js +22 -25
  51. package/dist/ui/components/CommandPanel.d.ts +1 -1
  52. package/dist/ui/components/CommandPanel.js +20 -13
  53. package/dist/ui/components/DiffViewer.d.ts +1 -1
  54. package/dist/ui/components/DiffViewer.js +101 -91
  55. package/dist/ui/components/FileList.js +22 -11
  56. package/dist/ui/components/HelpPanel.js +47 -21
  57. package/dist/ui/components/Menu.js +6 -2
  58. package/dist/ui/components/MessageList.d.ts +6 -0
  59. package/dist/ui/components/MessageList.js +1 -1
  60. package/dist/ui/components/ToolConfirmation.d.ts +4 -1
  61. package/dist/ui/components/ToolConfirmation.js +28 -2
  62. package/dist/ui/components/ToolResultPreview.d.ts +2 -1
  63. package/dist/ui/components/ToolResultPreview.js +41 -25
  64. package/dist/ui/pages/ChatScreen.js +177 -56
  65. package/dist/ui/pages/CodeBaseConfigScreen.js +54 -30
  66. package/dist/ui/pages/ConfigScreen.js +138 -98
  67. package/dist/ui/pages/CustomHeadersScreen.js +75 -69
  68. package/dist/ui/pages/LanguageSettingsScreen.d.ts +7 -0
  69. package/dist/ui/pages/LanguageSettingsScreen.js +89 -0
  70. package/dist/ui/pages/ProxyConfigScreen.js +27 -23
  71. package/dist/ui/pages/SensitiveCommandConfigScreen.js +32 -25
  72. package/dist/ui/pages/SubAgentConfigScreen.js +88 -75
  73. package/dist/ui/pages/SystemPromptConfigScreen.js +31 -26
  74. package/dist/ui/pages/WelcomeScreen.js +40 -26
  75. package/dist/utils/apiConfig.d.ts +2 -0
  76. package/dist/utils/codebaseConfig.d.ts +1 -5
  77. package/dist/utils/codebaseConfig.js +2 -10
  78. package/dist/utils/codebaseSearchEvents.d.ts +16 -0
  79. package/dist/utils/codebaseSearchEvents.js +13 -0
  80. package/dist/utils/commands/agent.js +2 -2
  81. package/dist/utils/commands/init.js +1 -1
  82. package/dist/utils/configManager.js +26 -5
  83. package/dist/utils/contextCompressor.js +1 -1
  84. package/dist/utils/languageConfig.d.ts +21 -0
  85. package/dist/utils/languageConfig.js +61 -0
  86. package/dist/utils/mcpToolsManager.js +0 -9
  87. package/dist/utils/notebookManager.js +11 -4
  88. package/dist/utils/sessionConverter.js +13 -3
  89. package/dist/utils/sessionManager.d.ts +1 -0
  90. package/dist/utils/subAgentConfig.d.ts +10 -5
  91. package/dist/utils/subAgentConfig.js +112 -19
  92. package/dist/utils/subAgentExecutor.d.ts +9 -1
  93. package/dist/utils/subAgentExecutor.js +122 -9
  94. package/dist/utils/toolExecutor.d.ts +2 -1
  95. package/dist/utils/toolExecutor.js +1 -2
  96. package/dist/utils/usageLogger.js +18 -3
  97. package/package.json +2 -1
@@ -6,6 +6,7 @@ import TextInput from 'ink-text-input';
6
6
  import { getOpenAiConfig, updateOpenAiConfig, validateApiConfig, } from '../../utils/apiConfig.js';
7
7
  import { fetchAvailableModels, filterModels, } from '../../api/models.js';
8
8
  import { getActiveProfileName, getAllProfiles, switchProfile, createProfile, deleteProfile, saveProfile, } from '../../utils/configManager.js';
9
+ import { useI18n } from '../../i18n/index.js';
9
10
  const focusEventTokenRegex = /(?:\x1b)?\[[0-9;]*[IO]/g;
10
11
  const isFocusEventInput = (value) => {
11
12
  if (!value) {
@@ -39,6 +40,7 @@ const stripFocusArtifacts = (value) => {
39
40
  .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
40
41
  };
41
42
  export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
43
+ const { t } = useI18n();
42
44
  // Profile management
43
45
  const [profiles, setProfiles] = useState([]);
44
46
  const [activeProfile, setActiveProfile] = useState('');
@@ -49,6 +51,8 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
49
51
  const [apiKey, setApiKey] = useState('');
50
52
  const [requestMethod, setRequestMethod] = useState('chat');
51
53
  const [anthropicBeta, setAnthropicBeta] = useState(false);
54
+ const [enablePromptOptimization, setEnablePromptOptimization] = useState(true);
55
+ const [enableAutoCompress, setEnableAutoCompress] = useState(true);
52
56
  const [thinkingEnabled, setThinkingEnabled] = useState(false);
53
57
  const [thinkingBudgetTokens, setThinkingBudgetTokens] = useState(10000);
54
58
  const [geminiThinkingEnabled, setGeminiThinkingEnabled] = useState(false);
@@ -76,19 +80,19 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
76
80
  const MAX_VISIBLE_FIELDS = 8;
77
81
  const requestMethodOptions = [
78
82
  {
79
- label: 'Chat Completions - Modern chat API (GPT-4, GPT-3.5-turbo)',
83
+ label: t.configScreen.requestMethodChat,
80
84
  value: 'chat',
81
85
  },
82
86
  {
83
- label: 'Responses - New responses API (2025, with built-in tools)',
87
+ label: t.configScreen.requestMethodResponses,
84
88
  value: 'responses',
85
89
  },
86
90
  {
87
- label: 'Gemini - Google Gemini API',
91
+ label: t.configScreen.requestMethodGemini,
88
92
  value: 'gemini',
89
93
  },
90
94
  {
91
- label: 'Anthropic - Claude API',
95
+ label: t.configScreen.requestMethodAnthropic,
92
96
  value: 'anthropic',
93
97
  },
94
98
  ];
@@ -99,6 +103,8 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
99
103
  'baseUrl',
100
104
  'apiKey',
101
105
  'requestMethod',
106
+ 'enablePromptOptimization',
107
+ 'enableAutoCompress',
102
108
  ...(requestMethod === 'anthropic'
103
109
  ? [
104
110
  'anthropicBeta',
@@ -165,6 +171,8 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
165
171
  setApiKey(config.apiKey);
166
172
  setRequestMethod(config.requestMethod || 'chat');
167
173
  setAnthropicBeta(config.anthropicBeta || false);
174
+ setEnablePromptOptimization(config.enablePromptOptimization !== false); // Default to true
175
+ setEnableAutoCompress(config.enableAutoCompress !== false); // Default to true
168
176
  setThinkingEnabled(config.thinking?.type === 'enabled' || false);
169
177
  setThinkingBudgetTokens(config.thinking?.budget_tokens || 10000);
170
178
  setGeminiThinkingEnabled(config.geminiThinking?.enabled || false);
@@ -208,7 +216,7 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
208
216
  value: model.id,
209
217
  }));
210
218
  return [
211
- { label: 'Manual Input (Enter model name)', value: '__MANUAL_INPUT__' },
219
+ { label: t.configScreen.manualInputOption, value: '__MANUAL_INPUT__' },
212
220
  ...modelOptions,
213
221
  ];
214
222
  };
@@ -240,7 +248,7 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
240
248
  const handleCreateProfile = () => {
241
249
  const cleaned = stripFocusArtifacts(newProfileName).trim();
242
250
  if (!cleaned) {
243
- setErrors(['Profile name cannot be empty']);
251
+ setErrors([t.configScreen.profileNameEmpty]);
244
252
  return;
245
253
  }
246
254
  try {
@@ -326,6 +334,8 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
326
334
  apiKey,
327
335
  requestMethod,
328
336
  anthropicBeta,
337
+ enablePromptOptimization,
338
+ enableAutoCompress,
329
339
  advancedModel,
330
340
  basicModel,
331
341
  maxContextTokens,
@@ -378,6 +388,8 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
378
388
  apiKey,
379
389
  requestMethod,
380
390
  anthropicBeta,
391
+ enablePromptOptimization,
392
+ enableAutoCompress,
381
393
  thinking: thinkingEnabled
382
394
  ? { type: 'enabled', budget_tokens: thinkingBudgetTokens }
383
395
  : undefined,
@@ -418,7 +430,7 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
418
430
  return (React.createElement(Box, { key: field, flexDirection: "column" },
419
431
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
420
432
  isActive ? '❯ ' : ' ',
421
- "Profile:"),
433
+ t.configScreen.profile),
422
434
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
423
435
  React.createElement(Text, { color: "gray" }, profiles.find(p => p.name === activeProfile)?.displayName ||
424
436
  activeProfile)))));
@@ -426,54 +438,77 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
426
438
  return (React.createElement(Box, { key: field, flexDirection: "column" },
427
439
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
428
440
  isActive ? '❯ ' : ' ',
429
- "Base URL:"),
441
+ t.configScreen.baseUrl),
430
442
  isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
431
443
  React.createElement(TextInput, { value: baseUrl, onChange: value => setBaseUrl(stripFocusArtifacts(value)), placeholder: "https://api.openai.com/v1" }))),
432
444
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
433
- React.createElement(Text, { color: "gray" }, baseUrl || 'Not set')))));
445
+ React.createElement(Text, { color: "gray" }, baseUrl || t.configScreen.notSet)))));
434
446
  case 'apiKey':
435
447
  return (React.createElement(Box, { key: field, flexDirection: "column" },
436
448
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
437
449
  isActive ? '❯ ' : ' ',
438
- "API Key:"),
450
+ t.configScreen.apiKey),
439
451
  isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
440
452
  React.createElement(TextInput, { value: apiKey, onChange: value => setApiKey(stripFocusArtifacts(value)), placeholder: "sk-...", mask: "*" }))),
441
453
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
442
- React.createElement(Text, { color: "gray" }, apiKey ? '*'.repeat(Math.min(apiKey.length, 20)) : 'Not set')))));
454
+ React.createElement(Text, { color: "gray" }, apiKey ? '*'.repeat(Math.min(apiKey.length, 20)) : t.configScreen.notSet)))));
443
455
  case 'requestMethod':
444
456
  return (React.createElement(Box, { key: field, flexDirection: "column" },
445
457
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
446
458
  isActive ? '❯ ' : ' ',
447
- "Request Method:"),
459
+ t.configScreen.requestMethod),
448
460
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
449
461
  React.createElement(Text, { color: "gray" }, requestMethodOptions.find(opt => opt.value === requestMethod)
450
- ?.label || 'Not set')))));
462
+ ?.label || t.configScreen.notSet)))));
451
463
  case 'anthropicBeta':
452
464
  return (React.createElement(Box, { key: field, flexDirection: "column" },
453
465
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
454
466
  isActive ? '❯ ' : ' ',
455
- "Anthropic Beta:"),
467
+ t.configScreen.anthropicBeta),
456
468
  React.createElement(Box, { marginLeft: 3 },
457
469
  React.createElement(Text, { color: "gray" },
458
- anthropicBeta ? '[✓] Enabled' : '[ ] Disabled',
459
- " (Press Enter to toggle)"))));
470
+ anthropicBeta ? t.configScreen.enabled : t.configScreen.disabled,
471
+ " ",
472
+ t.configScreen.toggleHint))));
473
+ case 'enablePromptOptimization':
474
+ return (React.createElement(Box, { key: field, flexDirection: "column" },
475
+ React.createElement(Text, { color: isActive ? 'green' : 'white' },
476
+ isActive ? '❯ ' : ' ',
477
+ t.configScreen.enablePromptOptimization),
478
+ React.createElement(Box, { marginLeft: 3 },
479
+ React.createElement(Text, { color: "gray" },
480
+ enablePromptOptimization ? t.configScreen.enabled : t.configScreen.disabled,
481
+ " ",
482
+ t.configScreen.toggleHint))));
483
+ case 'enableAutoCompress':
484
+ return (React.createElement(Box, { key: field, flexDirection: "column" },
485
+ React.createElement(Text, { color: isActive ? 'green' : 'white' },
486
+ isActive ? '❯ ' : ' ',
487
+ t.configScreen.enableAutoCompress),
488
+ React.createElement(Box, { marginLeft: 3 },
489
+ React.createElement(Text, { color: "gray" },
490
+ enableAutoCompress ? t.configScreen.enabled : t.configScreen.disabled,
491
+ " ",
492
+ t.configScreen.toggleHint))));
460
493
  case 'thinkingEnabled':
461
494
  return (React.createElement(Box, { key: field, flexDirection: "column" },
462
495
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
463
496
  isActive ? '❯ ' : ' ',
464
- "Thinking Enabled:"),
497
+ t.configScreen.thinkingEnabled),
465
498
  React.createElement(Box, { marginLeft: 3 },
466
499
  React.createElement(Text, { color: "gray" },
467
- thinkingEnabled ? '[✓] Enabled' : '[ ] Disabled',
468
- " (Press Enter to toggle)"))));
500
+ thinkingEnabled ? t.configScreen.enabled : t.configScreen.disabled,
501
+ " ",
502
+ t.configScreen.toggleHint))));
469
503
  case 'thinkingBudgetTokens':
470
504
  return (React.createElement(Box, { key: field, flexDirection: "column" },
471
505
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
472
506
  isActive ? '❯ ' : ' ',
473
- "Thinking Budget Tokens:"),
507
+ t.configScreen.thinkingBudgetTokens),
474
508
  isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
475
509
  React.createElement(Text, { color: "cyan" },
476
- "Enter value: ",
510
+ t.configScreen.enterValue,
511
+ " ",
477
512
  thinkingBudgetTokens))),
478
513
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
479
514
  React.createElement(Text, { color: "gray" }, thinkingBudgetTokens)))));
@@ -481,19 +516,21 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
481
516
  return (React.createElement(Box, { key: field, flexDirection: "column" },
482
517
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
483
518
  isActive ? '❯ ' : ' ',
484
- "Gemini Thinking Enabled:"),
519
+ t.configScreen.geminiThinkingEnabled),
485
520
  React.createElement(Box, { marginLeft: 3 },
486
521
  React.createElement(Text, { color: "gray" },
487
- geminiThinkingEnabled ? '[✓] Enabled' : '[ ] Disabled',
488
- " (Press Enter to toggle)"))));
522
+ geminiThinkingEnabled ? t.configScreen.enabled : t.configScreen.disabled,
523
+ " ",
524
+ t.configScreen.toggleHint))));
489
525
  case 'geminiThinkingBudget':
490
526
  return (React.createElement(Box, { key: field, flexDirection: "column" },
491
527
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
492
528
  isActive ? '❯ ' : ' ',
493
- "Gemini Thinking Budget:"),
529
+ t.configScreen.geminiThinkingBudget),
494
530
  isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
495
531
  React.createElement(Text, { color: "cyan" },
496
- "Enter value: ",
532
+ t.configScreen.enterValue,
533
+ " ",
497
534
  geminiThinkingBudget))),
498
535
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
499
536
  React.createElement(Text, { color: "gray" }, geminiThinkingBudget)))));
@@ -501,24 +538,24 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
501
538
  return (React.createElement(Box, { key: field, flexDirection: "column" },
502
539
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
503
540
  isActive ? '❯ ' : ' ',
504
- "Responses Reasoning Enabled:"),
541
+ t.configScreen.responsesReasoningEnabled),
505
542
  React.createElement(Box, { marginLeft: 3 },
506
543
  React.createElement(Text, { color: "gray" },
507
- responsesReasoningEnabled ? '[✓] Enabled' : '[ ] Disabled',
544
+ responsesReasoningEnabled ? t.configScreen.enabled : t.configScreen.disabled,
508
545
  ' ',
509
- "(Press Enter to toggle)"))));
546
+ t.configScreen.toggleHint))));
510
547
  case 'responsesReasoningEffort':
511
548
  return (React.createElement(Box, { key: field, flexDirection: "column" },
512
549
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
513
550
  isActive ? '❯ ' : ' ',
514
- "Responses Reasoning Effort:"),
551
+ t.configScreen.responsesReasoningEffort),
515
552
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
516
553
  React.createElement(Text, { color: "gray" }, responsesReasoningEffort.toUpperCase()))),
517
554
  isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
518
555
  React.createElement(Select, { options: [
519
- { label: 'Low', value: 'low' },
520
- { label: 'Medium', value: 'medium' },
521
- { label: 'High', value: 'high' },
556
+ { label: t.configScreen.low, value: 'low' },
557
+ { label: t.configScreen.medium, value: 'medium' },
558
+ { label: t.configScreen.high, value: 'high' },
522
559
  ], defaultValue: responsesReasoningEffort, onChange: value => {
523
560
  setResponsesReasoningEffort(value);
524
561
  setIsEditing(false);
@@ -527,31 +564,32 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
527
564
  return (React.createElement(Box, { key: field, flexDirection: "column" },
528
565
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
529
566
  isActive ? '❯ ' : ' ',
530
- "Advanced Model:"),
567
+ t.configScreen.advancedModel),
531
568
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
532
- React.createElement(Text, { color: "gray" }, advancedModel || 'Not set')))));
569
+ React.createElement(Text, { color: "gray" }, advancedModel || t.configScreen.notSet)))));
533
570
  case 'basicModel':
534
571
  return (React.createElement(Box, { key: field, flexDirection: "column" },
535
572
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
536
573
  isActive ? '❯ ' : ' ',
537
- "Basic Model:"),
574
+ t.configScreen.basicModel),
538
575
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
539
- React.createElement(Text, { color: "gray" }, basicModel || 'Not set')))));
576
+ React.createElement(Text, { color: "gray" }, basicModel || t.configScreen.notSet)))));
540
577
  case 'compactModelName':
541
578
  return (React.createElement(Box, { key: field, flexDirection: "column" },
542
579
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
543
580
  isActive ? '❯ ' : ' ',
544
- "Compact Model:"),
581
+ t.configScreen.compactModel),
545
582
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
546
- React.createElement(Text, { color: "gray" }, compactModelName || 'Not set')))));
583
+ React.createElement(Text, { color: "gray" }, compactModelName || t.configScreen.notSet)))));
547
584
  case 'maxContextTokens':
548
585
  return (React.createElement(Box, { key: field, flexDirection: "column" },
549
586
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
550
587
  isActive ? '❯ ' : ' ',
551
- "Max Context Tokens:"),
588
+ t.configScreen.maxContextTokens),
552
589
  isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
553
590
  React.createElement(Text, { color: "cyan" },
554
- "Enter value: ",
591
+ t.configScreen.enterValue,
592
+ " ",
555
593
  maxContextTokens))),
556
594
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
557
595
  React.createElement(Text, { color: "gray" }, maxContextTokens)))));
@@ -559,10 +597,11 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
559
597
  return (React.createElement(Box, { key: field, flexDirection: "column" },
560
598
  React.createElement(Text, { color: isActive ? 'green' : 'white' },
561
599
  isActive ? '❯ ' : ' ',
562
- "Max Tokens:"),
600
+ t.configScreen.maxTokens),
563
601
  isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
564
602
  React.createElement(Text, { color: "cyan" },
565
- "Enter value: ",
603
+ t.configScreen.enterValue,
604
+ " ",
566
605
  maxTokens))),
567
606
  !isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
568
607
  React.createElement(Text, { color: "gray" }, maxTokens)))));
@@ -616,7 +655,7 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
616
655
  (input === 'd' || input === 'D')) {
617
656
  // Handle profile deletion (works in both normal and editing mode)
618
657
  if (activeProfile === 'default') {
619
- setErrors(['Cannot delete the default profile']);
658
+ setErrors([t.configScreen.cannotDeleteDefault]);
620
659
  setIsEditing(false);
621
660
  return;
622
661
  }
@@ -800,6 +839,12 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
800
839
  if (currentField === 'anthropicBeta') {
801
840
  setAnthropicBeta(!anthropicBeta);
802
841
  }
842
+ else if (currentField === 'enablePromptOptimization') {
843
+ setEnablePromptOptimization(!enablePromptOptimization);
844
+ }
845
+ else if (currentField === 'enableAutoCompress') {
846
+ setEnableAutoCompress(!enableAutoCompress);
847
+ }
803
848
  else if (currentField === 'thinkingEnabled') {
804
849
  setThinkingEnabled(!thinkingEnabled);
805
850
  }
@@ -867,90 +912,91 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
867
912
  return (React.createElement(Box, { flexDirection: "column", padding: 1 },
868
913
  !inlineMode && (React.createElement(Box, { marginBottom: 1, borderStyle: "double", borderColor: 'cyan', paddingX: 2 },
869
914
  React.createElement(Box, { flexDirection: "column" },
870
- React.createElement(Gradient, { name: "rainbow" }, "Create New Profile"),
871
- React.createElement(Text, { color: "gray", dimColor: true }, "Enter a name for the new configuration profile")))),
915
+ React.createElement(Gradient, { name: "rainbow" }, t.configScreen.createNewProfile),
916
+ React.createElement(Text, { color: "gray", dimColor: true }, t.configScreen.enterProfileName)))),
872
917
  React.createElement(Box, { flexDirection: "column" },
873
918
  React.createElement(Text, { color: "cyan" }, "Profile Name:"),
874
919
  React.createElement(Box, { marginLeft: 2 },
875
- React.createElement(TextInput, { value: newProfileName, onChange: value => setNewProfileName(stripFocusArtifacts(value)), placeholder: "e.g., work, personal, test" }))),
920
+ React.createElement(TextInput, { value: newProfileName, onChange: value => setNewProfileName(stripFocusArtifacts(value)), placeholder: t.configScreen.profileNamePlaceholder }))),
876
921
  errors.length > 0 && (React.createElement(Box, { marginTop: 1 },
877
922
  React.createElement(Text, { color: "red" }, errors[0]))),
878
923
  React.createElement(Box, { marginTop: 1 },
879
- React.createElement(Alert, { variant: "info" }, "Press Enter to create, Esc to cancel"))));
924
+ React.createElement(Alert, { variant: "info" }, t.configScreen.createHint))));
880
925
  }
881
926
  // Render profile deletion confirmation
882
927
  if (profileMode === 'deleting') {
883
928
  return (React.createElement(Box, { flexDirection: "column", padding: 1 },
884
929
  !inlineMode && (React.createElement(Box, { marginBottom: 1, borderStyle: "double", borderColor: 'cyan', paddingX: 2 },
885
930
  React.createElement(Box, { flexDirection: "column" },
886
- React.createElement(Gradient, { name: "rainbow" }, "Delete Profile"),
887
- React.createElement(Text, { color: "gray", dimColor: true }, "Confirm profile deletion")))),
931
+ React.createElement(Gradient, { name: "rainbow" }, t.configScreen.deleteProfile),
932
+ React.createElement(Text, { color: "gray", dimColor: true }, t.configScreen.confirmDelete)))),
888
933
  React.createElement(Box, { flexDirection: "column" },
889
934
  React.createElement(Text, { color: "yellow" },
890
935
  "Are you sure you want to delete the profile \"",
891
936
  activeProfile,
892
937
  "\"?"),
893
- React.createElement(Text, { color: "gray", dimColor: true }, "This action cannot be undone. You will be switched to the default profile.")),
938
+ React.createElement(Text, { color: "gray", dimColor: true }, t.configScreen.deleteWarning)),
894
939
  errors.length > 0 && (React.createElement(Box, { marginTop: 1 },
895
940
  React.createElement(Text, { color: "red" }, errors[0]))),
896
941
  React.createElement(Box, { marginTop: 1 },
897
- React.createElement(Alert, { variant: "warning" }, "Press Y to confirm, N or Esc to cancel"))));
942
+ React.createElement(Alert, { variant: "warning" }, t.configScreen.confirmHint))));
898
943
  }
899
944
  if (loading) {
900
945
  return (React.createElement(Box, { flexDirection: "column", padding: 1 },
901
946
  !inlineMode && (React.createElement(Box, { marginBottom: 1, borderStyle: "double", borderColor: 'cyan', paddingX: 2 },
902
947
  React.createElement(Box, { flexDirection: "column" },
903
- React.createElement(Gradient, { name: "rainbow" }, "API & Model Configuration"),
904
- React.createElement(Text, { color: "gray", dimColor: true }, "Loading available models...")))),
948
+ React.createElement(Gradient, { name: "rainbow" }, t.configScreen.title),
949
+ React.createElement(Text, { color: "gray", dimColor: true }, t.configScreen.loadingMessage)))),
905
950
  React.createElement(Box, { flexDirection: "column" },
906
951
  React.createElement(Box, null,
907
952
  React.createElement(Spinner, { type: "dots" }),
908
- React.createElement(Text, { color: "cyan" }, " Fetching models from API...")),
953
+ React.createElement(Text, { color: "cyan" },
954
+ " ",
955
+ t.configScreen.fetchingModels)),
909
956
  React.createElement(Box, { marginLeft: 2 },
910
- React.createElement(Text, { color: "gray", dimColor: true }, "This may take a few seconds depending on your network connection"))),
957
+ React.createElement(Text, { color: "gray", dimColor: true }, t.configScreen.fetchingHint))),
911
958
  React.createElement(Box, { flexDirection: "column", marginTop: 1 },
912
- React.createElement(Alert, { variant: "info" }, "Press Esc to cancel and return to configuration"))));
959
+ React.createElement(Alert, { variant: "info" }, t.configScreen.loadingCancelHint))));
913
960
  }
914
961
  if (manualInputMode) {
915
962
  return (React.createElement(Box, { flexDirection: "column", padding: 1 },
916
963
  !inlineMode && (React.createElement(Box, { marginBottom: 1, borderStyle: "double", borderColor: 'cyan', paddingX: 2 },
917
964
  React.createElement(Box, { flexDirection: "column" },
918
- React.createElement(Gradient, { name: "rainbow" }, "Manual Input Model"),
919
- React.createElement(Text, { color: "gray", dimColor: true }, "Enter model name manually")))),
965
+ React.createElement(Gradient, { name: "rainbow" }, t.configScreen.manualInputTitle),
966
+ React.createElement(Text, { color: "gray", dimColor: true }, t.configScreen.manualInputSubtitle)))),
920
967
  loadError && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
921
- React.createElement(Text, { color: "yellow" }, "\u26A0 Failed to load models from API"),
968
+ React.createElement(Text, { color: "yellow" }, t.configScreen.loadingError),
922
969
  React.createElement(Text, { color: "gray", dimColor: true }, loadError))),
923
970
  React.createElement(Box, { flexDirection: "column" },
924
971
  React.createElement(Text, { color: "cyan" },
925
- currentField === 'advancedModel' && 'Advanced Model',
926
- currentField === 'basicModel' && 'Basic Model',
927
- currentField === 'compactModelName' && 'Compact Model',
928
- ":"),
972
+ currentField === 'advancedModel' && t.configScreen.advancedModel,
973
+ currentField === 'basicModel' && t.configScreen.basicModel,
974
+ currentField === 'compactModelName' && t.configScreen.compactModel),
929
975
  React.createElement(Box, { marginLeft: 2 },
930
976
  React.createElement(Text, { color: "green" },
931
977
  `> ${manualInputValue}`,
932
978
  React.createElement(Text, { color: "white" }, "_")))),
933
979
  React.createElement(Box, { flexDirection: "column", marginTop: 1 },
934
- React.createElement(Alert, { variant: "info" }, "Press Enter to confirm, Esc to cancel"))));
980
+ React.createElement(Alert, { variant: "info" }, t.configScreen.manualInputHint))));
935
981
  }
936
982
  return (React.createElement(Box, { flexDirection: "column", padding: 1 },
937
983
  !inlineMode && (React.createElement(Box, { marginBottom: 1, borderStyle: "double", borderColor: 'cyan', paddingX: 2 },
938
984
  React.createElement(Box, { flexDirection: "column" },
939
- React.createElement(Gradient, { name: "rainbow" }, "API & Model Configuration"),
940
- React.createElement(Text, { color: "gray", dimColor: true }, "Configure your API settings and AI models"),
985
+ React.createElement(Gradient, { name: "rainbow" }, t.configScreen.title),
986
+ React.createElement(Text, { color: "gray", dimColor: true }, t.configScreen.subtitle),
941
987
  activeProfile && (React.createElement(Text, { color: "cyan", dimColor: true },
942
- "Active Profile: ",
988
+ t.configScreen.activeProfile,
989
+ " ",
943
990
  activeProfile))))),
944
991
  React.createElement(Box, { marginBottom: 1 },
945
992
  React.createElement(Text, { color: "yellow", bold: true },
946
- "Settings (",
993
+ t.configScreen.settingsPosition,
994
+ " (",
947
995
  currentFieldIndex + 1,
948
996
  "/",
949
997
  totalFields,
950
998
  ")"),
951
- totalFields > MAX_VISIBLE_FIELDS && (React.createElement(Text, { color: "gray", dimColor: true },
952
- ' ',
953
- "\u00B7 \u2191\u2193 to scroll"))),
999
+ totalFields > MAX_VISIBLE_FIELDS && (React.createElement(Text, { color: "gray", dimColor: true }, t.configScreen.scrollHint))),
954
1000
  isEditing &&
955
1001
  (currentField === 'profile' ||
956
1002
  currentField === 'requestMethod' ||
@@ -960,14 +1006,13 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
960
1006
  currentField === 'responsesReasoningEffort') ? (React.createElement(Box, { flexDirection: "column" },
961
1007
  React.createElement(Text, { color: "green" },
962
1008
  "\u276F ",
963
- currentField === 'profile' && 'Profile',
964
- currentField === 'requestMethod' && 'Request Method',
965
- currentField === 'advancedModel' && 'Advanced Model',
966
- currentField === 'basicModel' && 'Basic Model',
967
- currentField === 'compactModelName' && 'Compact Model',
1009
+ currentField === 'profile' && t.configScreen.profile.replace(':', ''),
1010
+ currentField === 'requestMethod' && t.configScreen.requestMethod.replace(':', ''),
1011
+ currentField === 'advancedModel' && t.configScreen.advancedModel.replace(':', ''),
1012
+ currentField === 'basicModel' && t.configScreen.basicModel.replace(':', ''),
1013
+ currentField === 'compactModelName' && t.configScreen.compactModel.replace(':', ''),
968
1014
  currentField === 'responsesReasoningEffort' &&
969
- 'Responses Reasoning Effort',
970
- ":"),
1015
+ t.configScreen.responsesReasoningEffort.replace(':', '')),
971
1016
  React.createElement(Box, { marginLeft: 3, marginTop: 1 },
972
1017
  currentField === 'profile' && (React.createElement(Box, { flexDirection: "column" },
973
1018
  profiles.length > 1 && (React.createElement(Text, { color: "gray", dimColor: true }, "Scroll to see more profiles (\u2191\u2193)")),
@@ -982,10 +1027,10 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
982
1027
  } }),
983
1028
  React.createElement(Box, { flexDirection: "row", marginTop: 1 },
984
1029
  React.createElement(Box, { marginRight: 2 },
985
- React.createElement(Text, { color: "green" }, "+ New"),
1030
+ React.createElement(Text, { color: "green" }, t.configScreen.newProfile),
986
1031
  React.createElement(Text, { color: "gray" }, " (n)")),
987
1032
  React.createElement(Box, null,
988
- React.createElement(Text, { color: "red" }, "\uD83C\uDD87 Delete"),
1033
+ React.createElement(Text, { color: "red" }, t.configScreen.deleteProfileShort),
989
1034
  React.createElement(Text, { color: "gray" }, " (d)"))))),
990
1035
  currentField === 'requestMethod' && (React.createElement(Select, { options: requestMethodOptions, defaultValue: requestMethod, onChange: value => {
991
1036
  setRequestMethod(value);
@@ -999,9 +1044,9 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
999
1044
  searchTerm),
1000
1045
  React.createElement(Select, { options: getCurrentOptions(), defaultValue: getCurrentValue(), onChange: handleModelChange }))),
1001
1046
  currentField === 'responsesReasoningEffort' && (React.createElement(Select, { options: [
1002
- { label: 'Low', value: 'low' },
1003
- { label: 'Medium', value: 'medium' },
1004
- { label: 'High', value: 'high' },
1047
+ { label: t.configScreen.low, value: 'low' },
1048
+ { label: t.configScreen.medium, value: 'medium' },
1049
+ { label: t.configScreen.high, value: 'high' },
1005
1050
  ], defaultValue: responsesReasoningEffort, onChange: value => {
1006
1051
  setResponsesReasoningEffort(value);
1007
1052
  setIsEditing(false);
@@ -1011,13 +1056,13 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
1011
1056
  (currentField === 'advancedModel' ||
1012
1057
  currentField === 'basicModel' ||
1013
1058
  currentField === 'compactModelName') &&
1014
- 'Type to filter, ↑↓ to select, Enter to confirm, Esc to cancel',
1059
+ t.configScreen.modelFilterHint,
1015
1060
  currentField === 'responsesReasoningEffort' &&
1016
- '↑↓ to select, Enter to confirm, Esc to cancel',
1061
+ t.configScreen.effortSelectHint,
1017
1062
  currentField === 'profile' &&
1018
- '↑↓ to select profile, N to create new, D to delete, Enter to confirm, Esc to cancel',
1063
+ t.configScreen.profileSelectHint,
1019
1064
  currentField === 'requestMethod' &&
1020
- '↑↓ to select, Enter to confirm, Esc to cancel')))) : (React.createElement(Box, { flexDirection: "column" }, (() => {
1065
+ t.configScreen.requestMethodSelectHint)))) : (React.createElement(Box, { flexDirection: "column" }, (() => {
1021
1066
  // Calculate visible window
1022
1067
  if (allFields.length <= MAX_VISIBLE_FIELDS) {
1023
1068
  // Show all fields if less than max
@@ -1035,7 +1080,7 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
1035
1080
  return visibleFields.map(field => renderField(field));
1036
1081
  })())),
1037
1082
  errors.length > 0 && (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
1038
- React.createElement(Text, { color: "red", bold: true }, "Errors:"),
1083
+ React.createElement(Text, { color: "red", bold: true }, t.configScreen.errors),
1039
1084
  errors.map((error, index) => (React.createElement(Text, { key: index, color: "red" },
1040
1085
  "\u2022 ",
1041
1086
  error))))),
@@ -1045,13 +1090,8 @@ export default function ConfigScreen({ onBack, onSave, inlineMode = false, }) {
1045
1090
  currentField === 'advancedModel' ||
1046
1091
  currentField === 'basicModel' ||
1047
1092
  currentField === 'compactModelName' ||
1048
- currentField === 'responsesReasoningEffort')) && (React.createElement(Box, { flexDirection: "column", marginTop: 1 }, isEditing ? (React.createElement(Alert, { variant: "info" },
1049
- "Editing mode:",
1050
- ' ',
1051
- currentField === 'maxContextTokens' ||
1052
- currentField === 'maxTokens'
1053
- ? 'Type to edit, Enter to save'
1054
- : 'Press Enter to save and exit editing')) : (React.createElement(Alert, { variant: "info" }, currentField === 'profile'
1055
- ? 'Use ↑↓ to navigate, N to create new profile, D to delete profile, Ctrl+S or Esc to save'
1056
- : 'Use ↑↓ to navigate, Enter to edit, M for manual input, Ctrl+S or Esc to save'))))));
1093
+ currentField === 'responsesReasoningEffort')) && (React.createElement(Box, { flexDirection: "column", marginTop: 1 }, isEditing ? (React.createElement(Alert, { variant: "info" }, currentField === 'maxContextTokens' ||
1094
+ currentField === 'maxTokens'
1095
+ ? t.configScreen.editingHintNumeric
1096
+ : t.configScreen.editingHintGeneral)) : (React.createElement(Alert, { variant: "info" }, t.configScreen.navigationHint))))));
1057
1097
  }