aiexecode 1.0.66 → 1.0.69

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.

Potentially problematic release.


This version of aiexecode might be problematic. Click here for more details.

Files changed (87) hide show
  1. package/config_template/settings.json +1 -3
  2. package/index.js +46 -71
  3. package/package.json +1 -12
  4. package/payload_viewer/out/404/index.html +1 -1
  5. package/payload_viewer/out/404.html +1 -1
  6. package/payload_viewer/out/index.html +1 -1
  7. package/payload_viewer/out/index.txt +1 -1
  8. package/payload_viewer/web_server.js +0 -163
  9. package/prompts/completion_judge.txt +11 -7
  10. package/src/ai_based/completion_judge.js +97 -6
  11. package/src/ai_based/orchestrator.js +71 -3
  12. package/src/ai_based/pip_package_installer.js +14 -12
  13. package/src/ai_based/pip_package_lookup.js +13 -10
  14. package/src/commands/apikey.js +8 -34
  15. package/src/commands/help.js +3 -4
  16. package/src/commands/model.js +17 -74
  17. package/src/commands/reasoning_effort.js +1 -1
  18. package/src/config/feature_flags.js +0 -12
  19. package/src/{ui → frontend}/App.js +23 -25
  20. package/src/frontend/README.md +81 -0
  21. package/src/{ui/components/SuggestionsDisplay.js → frontend/components/AutocompleteMenu.js} +3 -3
  22. package/src/{ui/components/HistoryItemDisplay.js → frontend/components/ConversationItem.js} +37 -89
  23. package/src/{ui → frontend}/components/CurrentModelView.js +3 -5
  24. package/src/{ui → frontend}/components/Footer.js +4 -6
  25. package/src/{ui → frontend}/components/Header.js +2 -5
  26. package/src/{ui/components/InputPrompt.js → frontend/components/Input.js} +16 -54
  27. package/src/frontend/components/ModelListView.js +106 -0
  28. package/src/{ui → frontend}/components/ModelUpdatedView.js +3 -5
  29. package/src/{ui → frontend}/components/SessionSpinner.js +3 -3
  30. package/src/{ui → frontend}/components/SetupWizard.js +8 -101
  31. package/src/{ui → frontend}/components/ToolApprovalPrompt.js +16 -14
  32. package/src/frontend/design/themeColors.js +42 -0
  33. package/src/{ui → frontend}/index.js +7 -7
  34. package/src/frontend/utils/inputBuffer.js +441 -0
  35. package/src/{ui/utils/markdownRenderer.js → frontend/utils/markdownParser.js} +3 -3
  36. package/src/{ui/utils/ConsolePatcher.js → frontend/utils/outputRedirector.js} +9 -9
  37. package/src/{ui/utils/codeColorizer.js → frontend/utils/syntaxHighlighter.js} +2 -3
  38. package/src/system/ai_request.js +145 -595
  39. package/src/system/code_executer.js +111 -16
  40. package/src/system/file_integrity.js +5 -7
  41. package/src/system/log.js +3 -3
  42. package/src/system/mcp_integration.js +15 -13
  43. package/src/system/output_helper.js +0 -20
  44. package/src/system/session.js +97 -23
  45. package/src/system/session_memory.js +2 -82
  46. package/src/system/system_info.js +1 -1
  47. package/src/system/ui_events.js +0 -43
  48. package/src/tools/code_editor.js +17 -2
  49. package/src/tools/file_reader.js +17 -2
  50. package/src/tools/glob.js +9 -1
  51. package/src/tools/response_message.js +0 -2
  52. package/src/tools/ripgrep.js +9 -1
  53. package/src/tools/web_downloader.js +9 -1
  54. package/src/util/config.js +3 -8
  55. package/src/util/debug_log.js +4 -11
  56. package/src/util/mcp_config_manager.js +3 -5
  57. package/src/util/output_formatter.js +0 -47
  58. package/src/util/prompt_loader.js +3 -4
  59. package/src/util/safe_fs.js +60 -0
  60. package/src/util/setup_wizard.js +1 -3
  61. package/src/util/text_formatter.js +0 -86
  62. package/src/config/claude_models.js +0 -195
  63. package/src/ui/README.md +0 -208
  64. package/src/ui/api.js +0 -167
  65. package/src/ui/components/AgenticProgressDisplay.js +0 -126
  66. package/src/ui/components/Composer.js +0 -55
  67. package/src/ui/components/LoadingIndicator.js +0 -54
  68. package/src/ui/components/ModelListView.js +0 -214
  69. package/src/ui/components/Notifications.js +0 -55
  70. package/src/ui/components/StreamingIndicator.js +0 -36
  71. package/src/ui/contexts/AppContext.js +0 -25
  72. package/src/ui/contexts/StreamingContext.js +0 -20
  73. package/src/ui/contexts/UIStateContext.js +0 -117
  74. package/src/ui/example-usage.js +0 -180
  75. package/src/ui/hooks/useTerminalResize.js +0 -39
  76. package/src/ui/themes/semantic-tokens.js +0 -73
  77. package/src/ui/utils/text-buffer.js +0 -975
  78. /package/payload_viewer/out/_next/static/{t0WTsjXST7ISD1Boa6ifx → 7FgHZugvVp3pn1XStUYUJ}/_buildManifest.js +0 -0
  79. /package/payload_viewer/out/_next/static/{t0WTsjXST7ISD1Boa6ifx → 7FgHZugvVp3pn1XStUYUJ}/_clientMiddlewareManifest.json +0 -0
  80. /package/payload_viewer/out/_next/static/{t0WTsjXST7ISD1Boa6ifx → 7FgHZugvVp3pn1XStUYUJ}/_ssgManifest.js +0 -0
  81. /package/src/{ui → frontend}/components/BlankLine.js +0 -0
  82. /package/src/{ui → frontend}/components/FileDiffViewer.js +0 -0
  83. /package/src/{ui → frontend}/components/HelpView.js +0 -0
  84. /package/src/{ui → frontend}/hooks/useCompletion.js +0 -0
  85. /package/src/{ui → frontend}/hooks/useKeypress.js +0 -0
  86. /package/src/{ui → frontend}/utils/diffUtils.js +0 -0
  87. /package/src/{ui → frontend}/utils/renderInkComponent.js +0 -0
@@ -1,214 +0,0 @@
1
- /**
2
- * Model List View Component - Ink-based UI for displaying available models
3
- */
4
-
5
- import React from 'react';
6
- import { Box, Text } from 'ink';
7
- import { theme } from '../themes/semantic-tokens.js';
8
-
9
- export function ModelListView({ openaiModels, claudeModels }) {
10
- const sections = [
11
- // Header
12
- React.createElement(Box, {
13
- key: 'header',
14
- borderStyle: 'double',
15
- borderColor: 'gray',
16
- paddingX: 2,
17
- paddingY: 0,
18
- justifyContent: 'center'
19
- },
20
- React.createElement(Text, {
21
- bold: true,
22
- color: 'whiteBright'
23
- }, 'Available AI Models')
24
- ),
25
-
26
- React.createElement(Text, { key: 'spacer1' }, null),
27
-
28
- // OpenAI Section
29
- React.createElement(Box, {
30
- key: 'openai-section',
31
- flexDirection: 'column',
32
- borderStyle: 'round',
33
- borderColor: 'gray',
34
- paddingX: 2,
35
- paddingY: 1
36
- },
37
- React.createElement(Box, { flexDirection: 'column' },
38
- React.createElement(Text, {
39
- bold: true,
40
- color: 'cyan'
41
- }, '🤖 OpenAI Models'),
42
- React.createElement(Text, {
43
- dimColor: true,
44
- italic: true
45
- }, 'GPT-5 Series (Latest generation, recommended)'),
46
- React.createElement(Text, null)
47
- ),
48
-
49
- openaiModels.map((model, index) =>
50
- React.createElement(Box, {
51
- key: model.id,
52
- flexDirection: 'column',
53
- marginBottom: index < openaiModels.length - 1 ? 1 : 0
54
- },
55
- React.createElement(Box, { flexDirection: 'row', gap: 1 },
56
- React.createElement(Text, { color: 'green', bold: true }, '•'),
57
- React.createElement(Text, {
58
- color: 'white',
59
- bold: true
60
- }, model.id)
61
- ),
62
- React.createElement(Box, {
63
- flexDirection: 'column',
64
- marginLeft: 2,
65
- gap: 0
66
- },
67
- React.createElement(Text, {
68
- color: theme.text.secondary
69
- }, `${model.name} - ${model.description}`),
70
- React.createElement(Text, {
71
- dimColor: true,
72
- italic: true
73
- }, `💰 $${model.pricing.input}/$${model.pricing.output} (input/output per 1M tokens)`)
74
- )
75
- )
76
- )
77
- )
78
- ];
79
-
80
- // Anthropic 섹션들은 claudeModels가 있을 때만 추가
81
- if (claudeModels) {
82
- sections.push(
83
- React.createElement(Text, { key: 'spacer2' }, null),
84
-
85
- // Anthropic Claude 4.x Section
86
- React.createElement(Box, {
87
- key: 'claude4-section',
88
- flexDirection: 'column',
89
- borderStyle: 'round',
90
- borderColor: 'gray',
91
- paddingX: 2,
92
- paddingY: 1
93
- },
94
- React.createElement(Box, { flexDirection: 'column' },
95
- React.createElement(Text, {
96
- bold: true,
97
- color: 'magenta'
98
- }, '🧠 Anthropic Claude Models'),
99
- React.createElement(Text, {
100
- dimColor: true,
101
- italic: true
102
- }, 'Claude 4.x Series (Latest)'),
103
- React.createElement(Text, null)
104
- ),
105
-
106
- claudeModels.claude4.map((model, index) =>
107
- React.createElement(Box, {
108
- key: model.id,
109
- flexDirection: 'column',
110
- marginBottom: index < claudeModels.claude4.length - 1 ? 1 : 0
111
- },
112
- React.createElement(Box, { flexDirection: 'row', gap: 1 },
113
- React.createElement(Text, { color: 'green', bold: true }, '•'),
114
- React.createElement(Text, {
115
- color: 'white',
116
- bold: true
117
- }, model.id)
118
- ),
119
- React.createElement(Box, {
120
- flexDirection: 'column',
121
- marginLeft: 2,
122
- gap: 0
123
- },
124
- React.createElement(Text, {
125
- color: theme.text.secondary
126
- }, `${model.name} - ${model.description}`),
127
- React.createElement(Text, {
128
- dimColor: true,
129
- italic: true
130
- }, `💰 $${model.pricing.input}/$${model.pricing.output} (input/output per 1M tokens)`)
131
- )
132
- )
133
- )
134
- ),
135
-
136
- React.createElement(Text, { key: 'spacer3' }, null),
137
-
138
- // Claude 3.x Section
139
- React.createElement(Box, {
140
- key: 'claude3-section',
141
- flexDirection: 'column',
142
- borderStyle: 'round',
143
- borderColor: 'gray',
144
- paddingX: 2,
145
- paddingY: 1
146
- },
147
- React.createElement(Box, { flexDirection: 'column' },
148
- React.createElement(Text, {
149
- dimColor: true,
150
- italic: true
151
- }, 'Claude 3.x Series'),
152
- React.createElement(Text, null)
153
- ),
154
-
155
- claudeModels.claude3.map((model, index) =>
156
- React.createElement(Box, {
157
- key: model.id,
158
- flexDirection: 'column',
159
- marginBottom: index < claudeModels.claude3.length - 1 ? 1 : 0
160
- },
161
- React.createElement(Box, { flexDirection: 'row', gap: 1 },
162
- React.createElement(Text, { color: 'green', bold: true }, '•'),
163
- React.createElement(Text, {
164
- color: 'white',
165
- bold: true
166
- }, model.id)
167
- ),
168
- React.createElement(Box, {
169
- flexDirection: 'column',
170
- marginLeft: 2,
171
- gap: 0
172
- },
173
- React.createElement(Text, {
174
- color: theme.text.secondary
175
- }, `${model.name} - ${model.description}`),
176
- React.createElement(Text, {
177
- dimColor: true,
178
- italic: true
179
- }, `💰 $${model.pricing.input}/$${model.pricing.output} (input/output per 1M tokens)`)
180
- )
181
- )
182
- )
183
- )
184
- );
185
- }
186
-
187
- sections.push(
188
- React.createElement(Text, { key: 'spacer4' }, null),
189
-
190
- // Footer
191
- React.createElement(Box, {
192
- key: 'footer',
193
- flexDirection: 'column',
194
- borderStyle: 'single',
195
- borderColor: 'gray',
196
- paddingX: 2,
197
- paddingY: 1
198
- },
199
- React.createElement(Text, { bold: true }, '📖 Usage'),
200
- React.createElement(Text, null, ' /model <model-id>'),
201
- React.createElement(Text, { dimColor: true }, ' Example: /model gpt-5'),
202
- React.createElement(Text, null),
203
- React.createElement(Text, { bold: true }, '🔗 More Info'),
204
- React.createElement(Text, { color: theme.text.link }, ' OpenAI: https://platform.openai.com/docs/pricing'),
205
- claudeModels && React.createElement(Text, { color: theme.text.link }, ' Anthropic: https://docs.claude.com/en/docs/about-claude/models/overview')
206
- )
207
- );
208
-
209
- return React.createElement(Box, {
210
- flexDirection: 'column',
211
- paddingX: 2,
212
- paddingY: 1
213
- }, ...sections);
214
- }
@@ -1,55 +0,0 @@
1
- /**
2
- * Notifications - System notifications and warnings
3
- */
4
-
5
- import React from 'react';
6
- import { Box, Text } from 'ink';
7
- import { theme } from '../themes/semantic-tokens.js';
8
- import { useUIState, StreamingState } from '../contexts/UIStateContext.js';
9
-
10
- export function Notifications({ warnings = [], errors = [] }) {
11
- const uiState = useUIState();
12
-
13
- // Don't show notifications during streaming to avoid clutter
14
- if (uiState.streamingState === StreamingState.Responding) {
15
- return null;
16
- }
17
-
18
- if (warnings.length === 0 && errors.length === 0) {
19
- return null;
20
- }
21
-
22
- return React.createElement(Box, {
23
- flexDirection: "column",
24
- marginBottom: 1
25
- },
26
- warnings.length > 0 && React.createElement(Box, {
27
- borderStyle: "round",
28
- borderColor: theme.status.warning,
29
- paddingX: 1,
30
- marginBottom: errors.length > 0 ? 1 : 0,
31
- flexDirection: "column"
32
- },
33
- warnings.map((warning, index) =>
34
- React.createElement(Text, {
35
- key: index,
36
- color: theme.status.warning
37
- }, '⚠ ' + warning)
38
- )
39
- ),
40
-
41
- errors.length > 0 && React.createElement(Box, {
42
- borderStyle: "round",
43
- borderColor: theme.status.error,
44
- paddingX: 1,
45
- flexDirection: "column"
46
- },
47
- errors.map((error, index) =>
48
- React.createElement(Text, {
49
- key: index,
50
- color: theme.status.error
51
- }, '✗ ' + error)
52
- )
53
- )
54
- );
55
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * StreamingIndicator - Animated indicator for streaming/processing state
3
- * Isolated animation to prevent parent re-renders
4
- */
5
-
6
- import React, { useState, useEffect, memo } from 'react';
7
- import { Box, Text } from 'ink';
8
- import { theme } from '../themes/semantic-tokens.js';
9
-
10
- const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
11
- const DOTS_FRAMES = ['. ', '.. ', '...', ' '];
12
-
13
- // Isolated animation component
14
- const AnimatedFrame = memo(function AnimatedFrame({ type }) {
15
- const [frameIndex, setFrameIndex] = useState(0);
16
-
17
- useEffect(() => {
18
- const frames = type === 'spinner' ? SPINNER_FRAMES : DOTS_FRAMES;
19
- const interval = setInterval(() => {
20
- setFrameIndex(prev => (prev + 1) % frames.length);
21
- }, type === 'spinner' ? 80 : 400);
22
-
23
- return () => clearInterval(interval);
24
- }, [type]);
25
-
26
- const frames = type === 'spinner' ? SPINNER_FRAMES : DOTS_FRAMES;
27
- return React.createElement(Text, { color: theme.status.info }, frames[frameIndex] + ' ');
28
- });
29
-
30
- // Main component
31
- export const StreamingIndicator = memo(function StreamingIndicator({ message = 'Processing', type = 'spinner' }) {
32
- return React.createElement(Box, { marginLeft: 2, marginTop: 0 },
33
- React.createElement(AnimatedFrame, { type }),
34
- React.createElement(Text, { color: theme.text.secondary }, message)
35
- );
36
- });
@@ -1,25 +0,0 @@
1
- /**
2
- * AppContext - Global application state
3
- */
4
-
5
- import React, { createContext, useContext } from 'react';
6
- import { createDebugLogger } from '../../util/debug_log.js';
7
-
8
- const debugLog = createDebugLogger('ui_contexts.log', 'AppContext');
9
-
10
- const AppContext = createContext(null);
11
-
12
- export function AppProvider({ children, value }) {
13
- debugLog('AppProvider initialized');
14
- return React.createElement(AppContext.Provider, { value }, children);
15
- }
16
-
17
- export function useAppContext() {
18
- const context = useContext(AppContext);
19
- if (!context) {
20
- debugLog('ERROR: useAppContext called outside AppProvider');
21
- throw new Error('useAppContext must be used within AppProvider');
22
- }
23
- debugLog('useAppContext accessed successfully');
24
- return context;
25
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * StreamingContext - Real-time streaming state
3
- */
4
-
5
- import React, { createContext, useContext } from 'react';
6
- import { createDebugLogger } from '../../util/debug_log.js';
7
-
8
- const debugLog = createDebugLogger('ui_contexts.log', 'StreamingContext');
9
-
10
- const StreamingContext = createContext(null);
11
-
12
- export const StreamingContextProvider = StreamingContext.Provider;
13
-
14
- export function useStreaming() {
15
- const context = useContext(StreamingContext);
16
- debugLog('useStreaming accessed');
17
- return context;
18
- }
19
-
20
- export { StreamingContext };
@@ -1,117 +0,0 @@
1
- /**
2
- * UIStateContext - UI state management
3
- */
4
-
5
- import React, { createContext, useContext, useState, useRef } from 'react';
6
- import { createDebugLogger } from '../../util/debug_log.js';
7
-
8
- const debugLog = createDebugLogger('ui_contexts.log', 'UIStateContext');
9
-
10
- const UIStateContext = createContext(null);
11
-
12
- export const StreamingState = {
13
- Idle: 'idle',
14
- Responding: 'responding',
15
- WaitingForConfirmation: 'waiting_for_confirmation',
16
- Executing: 'executing',
17
- Completed: 'completed',
18
- Error: 'error'
19
- };
20
-
21
- export function UIStateProvider({ children, initialState = {} }) {
22
- debugLog(`UIStateProvider initializing - history items: ${(initialState.history || []).length}`);
23
-
24
- const [history, setHistory] = useState(initialState.history || []);
25
- const [pendingHistoryItems, setPendingHistoryItems] = useState([]);
26
- const [streamingState, setStreamingState] = useState(StreamingState.Idle);
27
- const [currentOperation, setCurrentOperation] = useState(null);
28
- const [progressMessage, setProgressMessage] = useState('');
29
- const [thought, setThought] = useState('');
30
- const [mainAreaWidth, setMainAreaWidth] = useState(process.stdout.columns || 80);
31
- const [terminalHeight, setTerminalHeight] = useState(process.stdout.rows || 24);
32
- const [elapsedTime, setElapsedTime] = useState(0);
33
- const [operations, setOperations] = useState([]);
34
- const [isSessionRunning, setIsSessionRunning] = useState(false);
35
- const [sessionMessage, setSessionMessage] = useState('Processing...');
36
- const [historyRemountKey, setHistoryRemountKey] = useState(0);
37
-
38
- const rootUiRef = useRef(null);
39
- const mainControlsRef = useRef(null);
40
-
41
- debugLog('UIStateProvider initialized with all state variables');
42
-
43
- const value = {
44
- // History
45
- history,
46
- setHistory,
47
- pendingHistoryItems,
48
- setPendingHistoryItems,
49
-
50
- // Streaming state
51
- streamingState,
52
- setStreamingState,
53
- currentOperation,
54
- setCurrentOperation,
55
- progressMessage,
56
- setProgressMessage,
57
- thought,
58
- setThought,
59
-
60
- // Operations tracking
61
- operations,
62
- setOperations,
63
- addOperation: (operation) => {
64
- debugLog(`addOperation: ${operation.type || 'unknown'} - ${operation.name || 'unnamed'}`);
65
- setOperations(prev => [...prev, {
66
- ...operation,
67
- id: Date.now(),
68
- startTime: Date.now(),
69
- status: 'running'
70
- }]);
71
- },
72
- updateOperation: (id, updates) => {
73
- debugLog(`updateOperation: id=${id}, updates=${JSON.stringify(updates)}`);
74
- setOperations(prev => prev.map(op =>
75
- op.id === id ? { ...op, ...updates } : op
76
- ));
77
- },
78
- completeOperation: (id) => {
79
- debugLog(`completeOperation: id=${id}`);
80
- setOperations(prev => prev.map(op =>
81
- op.id === id ? { ...op, status: 'completed', endTime: Date.now() } : op
82
- ));
83
- },
84
-
85
- // Layout
86
- mainAreaWidth,
87
- setMainAreaWidth,
88
- terminalHeight,
89
- setTerminalHeight,
90
- rootUiRef,
91
- mainControlsRef,
92
-
93
- // Timer
94
- elapsedTime,
95
- setElapsedTime,
96
-
97
- // Session state
98
- isSessionRunning,
99
- setIsSessionRunning,
100
- sessionMessage,
101
- setSessionMessage,
102
-
103
- // History remount key for Static component optimization
104
- historyRemountKey,
105
- setHistoryRemountKey,
106
- };
107
-
108
- return React.createElement(UIStateContext.Provider, { value }, children);
109
- }
110
-
111
- export function useUIState() {
112
- const context = useContext(UIStateContext);
113
- if (!context) {
114
- throw new Error('useUIState must be used within UIStateProvider');
115
- }
116
- return context;
117
- }
@@ -1,180 +0,0 @@
1
- /**
2
- * Example usage of the UI API
3
- *
4
- * This file demonstrates how to use the UI API to update the interface
5
- * during agentic coding operations.
6
- */
7
-
8
- import {
9
- StreamingState,
10
- addHistoryMessage,
11
- setStreamingState,
12
- setThought,
13
- setProgressMessage,
14
- startOperation,
15
- updateOperation,
16
- completeOperation,
17
- runOperation,
18
- batchUpdate
19
- } from './api.js';
20
-
21
- /**
22
- * Example: Simple progress update
23
- */
24
- export async function exampleSimpleProgress() {
25
- // Start responding
26
- setStreamingState(StreamingState.Responding);
27
- setThought('Analyzing the code structure...');
28
-
29
- // Simulate work
30
- await new Promise(resolve => setTimeout(resolve, 2000));
31
-
32
- // Update thought
33
- setThought('Planning the implementation...');
34
- await new Promise(resolve => setTimeout(resolve, 2000));
35
-
36
- // Complete
37
- setStreamingState(StreamingState.Completed);
38
- addHistoryMessage({
39
- type: 'assistant',
40
- text: 'Analysis complete! Here\'s what I found...'
41
- });
42
- }
43
-
44
- /**
45
- * Example: Multi-step operation with detailed progress
46
- */
47
- export async function exampleDetailedOperations() {
48
- setStreamingState(StreamingState.Executing);
49
-
50
- // Operation 1: Reading files
51
- const readOpId = startOperation({
52
- type: 'reading',
53
- name: 'Reading source files',
54
- description: 'Analyzing codebase structure'
55
- });
56
-
57
- await new Promise(resolve => setTimeout(resolve, 1000));
58
-
59
- updateOperation(readOpId, {
60
- progress: 50,
61
- detail: 'Processing src/components...'
62
- });
63
-
64
- await new Promise(resolve => setTimeout(resolve, 1000));
65
-
66
- completeOperation(readOpId);
67
-
68
- // Operation 2: Analyzing
69
- const analyzeOpId = startOperation({
70
- type: 'analyzing',
71
- name: 'Analyzing dependencies',
72
- description: 'Checking import relationships'
73
- });
74
-
75
- await new Promise(resolve => setTimeout(resolve, 1500));
76
- completeOperation(analyzeOpId);
77
-
78
- // Operation 3: Writing code
79
- const writeOpId = startOperation({
80
- type: 'writing',
81
- name: 'Writing new component',
82
- description: 'Creating Button.js'
83
- });
84
-
85
- await new Promise(resolve => setTimeout(resolve, 2000));
86
- completeOperation(writeOpId);
87
-
88
- setStreamingState(StreamingState.Completed);
89
- addHistoryMessage({
90
- type: 'assistant',
91
- text: 'Successfully created the new component!'
92
- });
93
- }
94
-
95
- /**
96
- * Example: Using runOperation helper
97
- */
98
- export async function exampleAutoOperation() {
99
- setStreamingState(StreamingState.Executing);
100
-
101
- await runOperation({
102
- type: 'building',
103
- name: 'Building project',
104
- description: 'Running npm run build'
105
- }, async (update) => {
106
- // Simulate build steps
107
- update({ progress: 25, detail: 'Compiling TypeScript...' });
108
- await new Promise(resolve => setTimeout(resolve, 1000));
109
-
110
- update({ progress: 50, detail: 'Bundling assets...' });
111
- await new Promise(resolve => setTimeout(resolve, 1000));
112
-
113
- update({ progress: 75, detail: 'Optimizing output...' });
114
- await new Promise(resolve => setTimeout(resolve, 1000));
115
-
116
- update({ progress: 100, detail: 'Build complete!' });
117
- });
118
-
119
- setStreamingState(StreamingState.Completed);
120
- addHistoryMessage({
121
- type: 'assistant',
122
- text: 'Build completed successfully!'
123
- });
124
- }
125
-
126
- /**
127
- * Example: Batch updates
128
- */
129
- export async function exampleBatchUpdate() {
130
- batchUpdate({
131
- streamingState: StreamingState.Responding,
132
- thought: 'Thinking about the best approach...',
133
- progressMessage: 'Analyzing requirements',
134
- addHistory: {
135
- type: 'system',
136
- text: 'Starting analysis...'
137
- }
138
- });
139
-
140
- await new Promise(resolve => setTimeout(resolve, 2000));
141
-
142
- batchUpdate({
143
- streamingState: StreamingState.Completed,
144
- thought: null,
145
- progressMessage: null,
146
- addHistory: {
147
- type: 'assistant',
148
- text: 'Analysis complete!'
149
- }
150
- });
151
- }
152
-
153
- /**
154
- * Example: Error handling
155
- */
156
- export async function exampleErrorHandling() {
157
- const opId = startOperation({
158
- type: 'testing',
159
- name: 'Running tests',
160
- description: 'npm test'
161
- });
162
-
163
- try {
164
- await new Promise((resolve, reject) => {
165
- setTimeout(() => reject(new Error('Test failed: timeout')), 1000);
166
- });
167
-
168
- completeOperation(opId);
169
- } catch (error) {
170
- updateOperation(opId, {
171
- status: 'error',
172
- detail: error.message
173
- });
174
-
175
- addHistoryMessage({
176
- type: 'error',
177
- text: `Test failed: ${error.message}`
178
- });
179
- }
180
- }
@@ -1,39 +0,0 @@
1
- /**
2
- * Hook to handle terminal resize events
3
- * Clears the screen on resize to prevent rendering artifacts
4
- */
5
-
6
- import { useEffect } from 'react';
7
- import { useStdout } from 'ink';
8
-
9
- export function useTerminalResize(onResize) {
10
- const { stdout } = useStdout();
11
-
12
- useEffect(() => {
13
- if (!stdout || typeof stdout.on !== 'function') {
14
- return;
15
- }
16
-
17
- const handleResize = () => {
18
- // Clear the screen to prevent artifacts
19
- if (stdout.write && typeof stdout.write === 'function') {
20
- // ANSI escape code to clear screen and reset cursor
21
- stdout.write('\x1Bc');
22
- }
23
-
24
- if (onResize) {
25
- onResize();
26
- }
27
- };
28
-
29
- stdout.on('resize', handleResize);
30
-
31
- return () => {
32
- if (stdout.off && typeof stdout.off === 'function') {
33
- stdout.off('resize', handleResize);
34
- } else if (stdout.removeListener && typeof stdout.removeListener === 'function') {
35
- stdout.removeListener('resize', handleResize);
36
- }
37
- };
38
- }, [stdout, onResize]);
39
- }