prompt-language-shell 0.8.2 → 0.8.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.
- package/dist/configuration/io.js +85 -0
- package/dist/configuration/messages.js +30 -0
- package/dist/configuration/schema.js +167 -0
- package/dist/configuration/transformation.js +55 -0
- package/dist/configuration/types.js +30 -0
- package/dist/configuration/validation.js +52 -0
- package/dist/execution/handlers.js +135 -0
- package/dist/execution/processing.js +35 -0
- package/dist/execution/reducer.js +148 -0
- package/dist/execution/types.js +12 -0
- package/dist/execution/validation.js +12 -0
- package/dist/index.js +1 -1
- package/dist/services/anthropic.js +43 -56
- package/dist/services/colors.js +2 -1
- package/dist/services/components.js +40 -24
- package/dist/services/config-labels.js +15 -15
- package/dist/services/filesystem.js +114 -0
- package/dist/services/loader.js +8 -5
- package/dist/services/logger.js +26 -1
- package/dist/services/messages.js +32 -1
- package/dist/services/parser.js +3 -1
- package/dist/services/refinement.js +10 -10
- package/dist/services/router.js +43 -27
- package/dist/services/skills.js +12 -11
- package/dist/services/validator.js +4 -3
- package/dist/types/guards.js +4 -6
- package/dist/types/handlers.js +1 -0
- package/dist/types/schemas.js +103 -0
- package/dist/types/types.js +1 -0
- package/dist/ui/Answer.js +38 -16
- package/dist/ui/Command.js +48 -22
- package/dist/ui/Component.js +147 -33
- package/dist/ui/Config.js +69 -78
- package/dist/ui/Confirm.js +34 -21
- package/dist/ui/Execute.js +151 -178
- package/dist/ui/Feedback.js +1 -0
- package/dist/ui/Introspect.js +54 -25
- package/dist/ui/Label.js +1 -1
- package/dist/ui/Main.js +10 -6
- package/dist/ui/Refinement.js +8 -1
- package/dist/ui/Schedule.js +76 -53
- package/dist/ui/Validate.js +77 -77
- package/dist/ui/Workflow.js +60 -61
- package/package.json +3 -2
- package/dist/services/configuration.js +0 -409
package/dist/ui/Execute.js
CHANGED
|
@@ -1,54 +1,65 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect,
|
|
2
|
+
import { useCallback, useEffect, useReducer } from 'react';
|
|
3
3
|
import { Box, Text } from 'ink';
|
|
4
4
|
import { ComponentStatus, } from '../types/components.js';
|
|
5
|
-
import {
|
|
6
|
-
import { addDebugToTimeline } from '../services/components.js';
|
|
5
|
+
import { getTextColor } from '../services/colors.js';
|
|
7
6
|
import { useInput } from '../services/keyboard.js';
|
|
8
|
-
import { loadUserConfig } from '../services/loader.js';
|
|
9
7
|
import { formatErrorMessage } from '../services/messages.js';
|
|
10
|
-
import { replacePlaceholders } from '../services/resolver.js';
|
|
11
8
|
import { ExecutionStatus } from '../services/shell.js';
|
|
12
9
|
import { ensureMinimumTime } from '../services/timing.js';
|
|
13
|
-
import {
|
|
10
|
+
import { buildAbortedState, handleTaskCompletion, handleTaskFailure, } from '../execution/handlers.js';
|
|
11
|
+
import { processTasks } from '../execution/processing.js';
|
|
12
|
+
import { executeReducer, initialState } from '../execution/reducer.js';
|
|
13
|
+
import { ExecuteActionType } from '../execution/types.js';
|
|
14
|
+
import { Message } from './Message.js';
|
|
14
15
|
import { Spinner } from './Spinner.js';
|
|
15
16
|
import { Task } from './Task.js';
|
|
16
17
|
const MINIMUM_PROCESSING_TIME = 400;
|
|
17
|
-
export
|
|
18
|
+
export const ExecuteView = ({ state, status, onTaskComplete, onTaskAbort, onTaskError, }) => {
|
|
18
19
|
const isActive = status === ComponentStatus.Active;
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
const { error, taskInfos, message, completed, completionMessage } = state;
|
|
21
|
+
const hasProcessed = taskInfos.length > 0;
|
|
22
|
+
// Derive loading state from current conditions
|
|
23
|
+
const isLoading = isActive && taskInfos.length === 0 && !error && !hasProcessed;
|
|
24
|
+
const isExecuting = completed < taskInfos.length;
|
|
25
|
+
// Return null only when loading completes with no commands
|
|
26
|
+
if (!isActive && taskInfos.length === 0 && !error) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
// Show completed steps when not active
|
|
30
|
+
const showTasks = !isActive && taskInfos.length > 0;
|
|
31
|
+
return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isLoading && (_jsxs(Box, { marginLeft: 1, children: [_jsx(Text, { color: getTextColor(isActive), children: "Preparing commands. " }), _jsx(Spinner, {})] })), (isExecuting || showTasks) && (_jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [message && (_jsxs(Box, { marginBottom: 1, gap: 1, children: [_jsx(Text, { color: getTextColor(isActive), children: message }), isExecuting && _jsx(Spinner, {})] })), taskInfos.map((taskInfo, index) => (_jsx(Box, { marginBottom: index < taskInfos.length - 1 ? 1 : 0, children: _jsx(Task, { label: taskInfo.label, command: taskInfo.command, isActive: isActive && index === completed, index: index, initialStatus: taskInfo.status, initialElapsed: taskInfo.elapsed, onComplete: onTaskComplete, onAbort: onTaskAbort, onError: onTaskError }) }, index)))] })), completionMessage && !isActive && (_jsx(Box, { marginTop: 1, marginLeft: 1, children: _jsx(Text, { color: getTextColor(false), children: completionMessage }) })), error && _jsx(Message, { text: error, status: status })] }));
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Execute controller: Runs tasks sequentially
|
|
35
|
+
*/
|
|
36
|
+
export function Execute({ tasks, status, service, requestHandlers, lifecycleHandlers, workflowHandlers, }) {
|
|
37
|
+
const isActive = status === ComponentStatus.Active;
|
|
38
|
+
const [localState, dispatch] = useReducer(executeReducer, initialState);
|
|
39
|
+
const { error, taskInfos, message, completed, hasProcessed, taskExecutionTimes, completionMessage, summary, } = localState;
|
|
27
40
|
// Derive loading state from current conditions
|
|
28
41
|
const isLoading = isActive && taskInfos.length === 0 && !error && !hasProcessed;
|
|
29
42
|
const isExecuting = completed < taskInfos.length;
|
|
30
43
|
// Handle cancel with useCallback to ensure we capture latest state
|
|
31
44
|
const handleCancel = useCallback(() => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
dispatch({
|
|
46
|
+
type: ExecuteActionType.CancelExecution,
|
|
47
|
+
payload: { completed },
|
|
48
|
+
});
|
|
49
|
+
// Get updated task infos after cancel
|
|
36
50
|
const updatedTaskInfos = taskInfos.map((task, taskIndex) => {
|
|
37
51
|
if (taskIndex < completed) {
|
|
38
|
-
// Tasks that completed before interruption
|
|
39
52
|
return { ...task, status: ExecutionStatus.Success };
|
|
40
53
|
}
|
|
41
54
|
else if (taskIndex === completed) {
|
|
42
|
-
// Task that was running when interrupted
|
|
43
55
|
return { ...task, status: ExecutionStatus.Aborted };
|
|
44
56
|
}
|
|
45
57
|
else {
|
|
46
|
-
// Tasks that haven't started yet
|
|
47
58
|
return { ...task, status: ExecutionStatus.Cancelled };
|
|
48
59
|
}
|
|
49
60
|
});
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
// Expose final state
|
|
62
|
+
const finalState = {
|
|
52
63
|
message,
|
|
53
64
|
summary,
|
|
54
65
|
taskInfos: updatedTaskInfos,
|
|
@@ -56,9 +67,17 @@ export function Execute({ tasks, state, status, service, handlers, }) {
|
|
|
56
67
|
taskExecutionTimes,
|
|
57
68
|
completionMessage: null,
|
|
58
69
|
error: null,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
};
|
|
71
|
+
requestHandlers.onCompleted(finalState);
|
|
72
|
+
requestHandlers.onAborted('execution');
|
|
73
|
+
}, [
|
|
74
|
+
message,
|
|
75
|
+
summary,
|
|
76
|
+
taskInfos,
|
|
77
|
+
completed,
|
|
78
|
+
taskExecutionTimes,
|
|
79
|
+
requestHandlers,
|
|
80
|
+
]);
|
|
62
81
|
useInput((_, key) => {
|
|
63
82
|
if (key.escape && (isLoading || isExecuting) && isActive) {
|
|
64
83
|
handleCancel();
|
|
@@ -73,28 +92,20 @@ export function Execute({ tasks, state, status, service, handlers, }) {
|
|
|
73
92
|
async function process(svc) {
|
|
74
93
|
const startTime = Date.now();
|
|
75
94
|
try {
|
|
76
|
-
|
|
77
|
-
const userConfig = loadUserConfig();
|
|
78
|
-
// Format tasks for the execute tool and resolve placeholders
|
|
79
|
-
const taskDescriptions = tasks
|
|
80
|
-
.map((task) => {
|
|
81
|
-
const resolvedAction = replacePlaceholders(task.action, userConfig);
|
|
82
|
-
const params = task.params
|
|
83
|
-
? ` (params: ${JSON.stringify(task.params)})`
|
|
84
|
-
: '';
|
|
85
|
-
return `- ${resolvedAction}${params}`;
|
|
86
|
-
})
|
|
87
|
-
.join('\n');
|
|
88
|
-
// Call execute tool to get commands
|
|
89
|
-
const result = await svc.processWithTool(taskDescriptions, 'execute');
|
|
95
|
+
const result = await processTasks(tasks, svc);
|
|
90
96
|
await ensureMinimumTime(startTime, MINIMUM_PROCESSING_TIME);
|
|
91
97
|
if (!mounted)
|
|
92
98
|
return;
|
|
93
99
|
// Add debug components to timeline if present
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
if (result.debug?.length) {
|
|
101
|
+
workflowHandlers.addToTimeline(...result.debug);
|
|
102
|
+
}
|
|
103
|
+
if (result.commands.length === 0) {
|
|
104
|
+
dispatch({
|
|
105
|
+
type: ExecuteActionType.ProcessingComplete,
|
|
106
|
+
payload: { message: result.message },
|
|
107
|
+
});
|
|
108
|
+
const finalState = {
|
|
98
109
|
message: result.message,
|
|
99
110
|
summary: '',
|
|
100
111
|
taskInfos: [],
|
|
@@ -102,44 +113,45 @@ export function Execute({ tasks, state, status, service, handlers, }) {
|
|
|
102
113
|
taskExecutionTimes: [],
|
|
103
114
|
completionMessage: null,
|
|
104
115
|
error: null,
|
|
105
|
-
}
|
|
106
|
-
|
|
116
|
+
};
|
|
117
|
+
requestHandlers.onCompleted(finalState);
|
|
118
|
+
lifecycleHandlers.completeActive();
|
|
107
119
|
return;
|
|
108
120
|
}
|
|
109
|
-
//
|
|
110
|
-
const
|
|
111
|
-
...cmd,
|
|
112
|
-
command: replacePlaceholders(cmd.command, userConfig),
|
|
113
|
-
}));
|
|
114
|
-
// Set message, summary, and create task infos
|
|
115
|
-
const newMessage = result.message;
|
|
116
|
-
const newSummary = result.summary || '';
|
|
117
|
-
const infos = resolvedCommands.map((cmd, index) => ({
|
|
121
|
+
// Create task infos from commands
|
|
122
|
+
const infos = result.commands.map((cmd, index) => ({
|
|
118
123
|
label: tasks[index]?.action,
|
|
119
124
|
command: cmd,
|
|
120
125
|
}));
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
dispatch({
|
|
127
|
+
type: ExecuteActionType.CommandsReady,
|
|
128
|
+
payload: {
|
|
129
|
+
message: result.message,
|
|
130
|
+
summary: result.summary,
|
|
131
|
+
taskInfos: infos,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
125
134
|
// Update state after AI processing
|
|
126
|
-
|
|
127
|
-
message:
|
|
128
|
-
summary:
|
|
135
|
+
const finalState = {
|
|
136
|
+
message: result.message,
|
|
137
|
+
summary: result.summary,
|
|
129
138
|
taskInfos: infos,
|
|
130
139
|
completed: 0,
|
|
131
140
|
taskExecutionTimes: [],
|
|
132
141
|
completionMessage: null,
|
|
133
142
|
error: null,
|
|
134
|
-
}
|
|
143
|
+
};
|
|
144
|
+
requestHandlers.onCompleted(finalState);
|
|
135
145
|
}
|
|
136
146
|
catch (err) {
|
|
137
147
|
await ensureMinimumTime(startTime, MINIMUM_PROCESSING_TIME);
|
|
138
148
|
if (mounted) {
|
|
139
149
|
const errorMessage = formatErrorMessage(err);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
dispatch({
|
|
151
|
+
type: ExecuteActionType.ProcessingError,
|
|
152
|
+
payload: { error: errorMessage },
|
|
153
|
+
});
|
|
154
|
+
const finalState = {
|
|
143
155
|
message: '',
|
|
144
156
|
summary: '',
|
|
145
157
|
taskInfos: [],
|
|
@@ -147,8 +159,9 @@ export function Execute({ tasks, state, status, service, handlers, }) {
|
|
|
147
159
|
taskExecutionTimes: [],
|
|
148
160
|
completionMessage: null,
|
|
149
161
|
error: errorMessage,
|
|
150
|
-
}
|
|
151
|
-
|
|
162
|
+
};
|
|
163
|
+
requestHandlers.onCompleted(finalState);
|
|
164
|
+
requestHandlers.onError(errorMessage);
|
|
152
165
|
}
|
|
153
166
|
}
|
|
154
167
|
}
|
|
@@ -156,122 +169,82 @@ export function Execute({ tasks, state, status, service, handlers, }) {
|
|
|
156
169
|
return () => {
|
|
157
170
|
mounted = false;
|
|
158
171
|
};
|
|
159
|
-
}, [
|
|
172
|
+
}, [
|
|
173
|
+
tasks,
|
|
174
|
+
isActive,
|
|
175
|
+
service,
|
|
176
|
+
requestHandlers,
|
|
177
|
+
lifecycleHandlers,
|
|
178
|
+
workflowHandlers,
|
|
179
|
+
taskInfos.length,
|
|
180
|
+
hasProcessed,
|
|
181
|
+
]);
|
|
160
182
|
// Handle task completion - move to next task
|
|
161
183
|
const handleTaskComplete = useCallback((index, _output, elapsed) => {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
handlers?.updateState({
|
|
173
|
-
message,
|
|
174
|
-
summary,
|
|
175
|
-
taskInfos: updatedTaskInfos,
|
|
176
|
-
completed: index + 1,
|
|
177
|
-
taskExecutionTimes: updatedTimes,
|
|
178
|
-
completionMessage: null,
|
|
179
|
-
error: null,
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
// All tasks complete
|
|
184
|
-
const totalElapsed = updatedTimes.reduce((sum, time) => sum + time, 0);
|
|
185
|
-
const summaryText = summary.trim() || 'Execution completed';
|
|
186
|
-
const completion = `${summaryText} in ${formatDuration(totalElapsed)}.`;
|
|
187
|
-
setCompletionMessage(completion);
|
|
188
|
-
handlers?.updateState({
|
|
189
|
-
message,
|
|
190
|
-
summary,
|
|
191
|
-
taskInfos: updatedTaskInfos,
|
|
192
|
-
completed: index + 1,
|
|
193
|
-
taskExecutionTimes: updatedTimes,
|
|
194
|
-
completionMessage: completion,
|
|
195
|
-
error: null,
|
|
196
|
-
});
|
|
197
|
-
handlers?.completeActive();
|
|
184
|
+
const result = handleTaskCompletion(index, elapsed, {
|
|
185
|
+
taskInfos,
|
|
186
|
+
message,
|
|
187
|
+
summary,
|
|
188
|
+
taskExecutionTimes,
|
|
189
|
+
});
|
|
190
|
+
dispatch(result.action);
|
|
191
|
+
requestHandlers.onCompleted(result.finalState);
|
|
192
|
+
if (result.shouldComplete) {
|
|
193
|
+
lifecycleHandlers.completeActive();
|
|
198
194
|
}
|
|
199
|
-
}, [
|
|
195
|
+
}, [
|
|
196
|
+
taskInfos,
|
|
197
|
+
message,
|
|
198
|
+
summary,
|
|
199
|
+
taskExecutionTimes,
|
|
200
|
+
requestHandlers,
|
|
201
|
+
lifecycleHandlers,
|
|
202
|
+
]);
|
|
200
203
|
const handleTaskError = useCallback((index, error, elapsed) => {
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
handlers?.updateState({
|
|
212
|
-
message,
|
|
213
|
-
summary,
|
|
214
|
-
taskInfos: updatedTaskInfos,
|
|
215
|
-
completed: index + 1,
|
|
216
|
-
taskExecutionTimes,
|
|
217
|
-
completionMessage: null,
|
|
218
|
-
error,
|
|
219
|
-
});
|
|
220
|
-
handlers?.onError(error);
|
|
204
|
+
const result = handleTaskFailure(index, error, elapsed, {
|
|
205
|
+
taskInfos,
|
|
206
|
+
message,
|
|
207
|
+
summary,
|
|
208
|
+
taskExecutionTimes,
|
|
209
|
+
});
|
|
210
|
+
dispatch(result.action);
|
|
211
|
+
requestHandlers.onCompleted(result.finalState);
|
|
212
|
+
if (result.shouldReportError) {
|
|
213
|
+
requestHandlers.onError(error);
|
|
221
214
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const updatedTimes = [...taskExecutionTimes, elapsed];
|
|
225
|
-
setTaskExecutionTimes(updatedTimes);
|
|
226
|
-
if (index < taskInfos.length - 1) {
|
|
227
|
-
setCompleted(index + 1);
|
|
228
|
-
handlers?.updateState({
|
|
229
|
-
message,
|
|
230
|
-
summary,
|
|
231
|
-
taskInfos: updatedTaskInfos,
|
|
232
|
-
completed: index + 1,
|
|
233
|
-
taskExecutionTimes: updatedTimes,
|
|
234
|
-
completionMessage: null,
|
|
235
|
-
error: null,
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
// Last task, complete execution
|
|
240
|
-
const totalElapsed = updatedTimes.reduce((sum, time) => sum + time, 0);
|
|
241
|
-
const summaryText = summary.trim() || 'Execution completed';
|
|
242
|
-
const completion = `${summaryText} in ${formatDuration(totalElapsed)}.`;
|
|
243
|
-
setCompletionMessage(completion);
|
|
244
|
-
handlers?.updateState({
|
|
245
|
-
message,
|
|
246
|
-
summary,
|
|
247
|
-
taskInfos: updatedTaskInfos,
|
|
248
|
-
completed: index + 1,
|
|
249
|
-
taskExecutionTimes: updatedTimes,
|
|
250
|
-
completionMessage: completion,
|
|
251
|
-
error: null,
|
|
252
|
-
});
|
|
253
|
-
handlers?.completeActive();
|
|
254
|
-
}
|
|
215
|
+
if (result.shouldComplete) {
|
|
216
|
+
lifecycleHandlers.completeActive();
|
|
255
217
|
}
|
|
256
|
-
}, [
|
|
218
|
+
}, [
|
|
219
|
+
taskInfos,
|
|
220
|
+
message,
|
|
221
|
+
summary,
|
|
222
|
+
taskExecutionTimes,
|
|
223
|
+
requestHandlers,
|
|
224
|
+
lifecycleHandlers,
|
|
225
|
+
]);
|
|
257
226
|
const handleTaskAbort = useCallback((_index) => {
|
|
258
227
|
// Task was aborted - execution already stopped by Escape handler
|
|
259
228
|
// Just update state, don't call onAborted (already called at Execute level)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
229
|
+
const finalState = buildAbortedState(taskInfos, message, summary, completed, taskExecutionTimes);
|
|
230
|
+
requestHandlers.onCompleted(finalState);
|
|
231
|
+
}, [
|
|
232
|
+
taskInfos,
|
|
233
|
+
message,
|
|
234
|
+
summary,
|
|
235
|
+
completed,
|
|
236
|
+
taskExecutionTimes,
|
|
237
|
+
requestHandlers,
|
|
238
|
+
]);
|
|
239
|
+
// Controller always renders View with current state
|
|
240
|
+
const viewState = {
|
|
241
|
+
error,
|
|
242
|
+
taskInfos,
|
|
243
|
+
message,
|
|
244
|
+
summary,
|
|
245
|
+
completed,
|
|
246
|
+
taskExecutionTimes,
|
|
247
|
+
completionMessage,
|
|
248
|
+
};
|
|
249
|
+
return (_jsx(ExecuteView, { tasks: tasks, state: viewState, status: status, onTaskComplete: handleTaskComplete, onTaskAbort: handleTaskAbort, onTaskError: handleTaskError }));
|
|
277
250
|
}
|
package/dist/ui/Feedback.js
CHANGED
package/dist/ui/Introspect.js
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { Box, Text } from 'ink';
|
|
4
|
-
import { ComponentStatus } from '../types/components.js';
|
|
4
|
+
import { ComponentStatus, } from '../types/components.js';
|
|
5
5
|
import { Colors, getTextColor } from '../services/colors.js';
|
|
6
|
-
import {
|
|
7
|
-
import { DebugLevel } from '../
|
|
6
|
+
import { createReportDefinition } from '../services/components.js';
|
|
7
|
+
import { DebugLevel } from '../configuration/types.js';
|
|
8
8
|
import { useInput } from '../services/keyboard.js';
|
|
9
9
|
import { formatErrorMessage } from '../services/messages.js';
|
|
10
10
|
import { ensureMinimumTime } from '../services/timing.js';
|
|
11
11
|
import { Spinner } from './Spinner.js';
|
|
12
12
|
const MIN_PROCESSING_TIME = 1000;
|
|
13
|
-
export
|
|
13
|
+
export const IntrospectView = ({ state, status, children, }) => {
|
|
14
|
+
const isActive = status === ComponentStatus.Active;
|
|
15
|
+
const { error } = state;
|
|
16
|
+
// Don't render wrapper when done and nothing to show
|
|
17
|
+
if (!isActive && !error && !children) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isActive && (_jsxs(Box, { marginLeft: 1, children: [_jsx(Text, { color: getTextColor(isActive), children: "Listing capabilities. " }), _jsx(Spinner, {})] })), error && (_jsx(Box, { marginTop: 1, marginLeft: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) })), children] }));
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Introspect controller: Lists capabilities via LLM
|
|
24
|
+
*/
|
|
25
|
+
export function Introspect({ tasks, status, service, children, debug = DebugLevel.None, requestHandlers, lifecycleHandlers, workflowHandlers, }) {
|
|
14
26
|
const isActive = status === ComponentStatus.Active;
|
|
15
|
-
// isActive passed as prop
|
|
16
27
|
const [error, setError] = useState(null);
|
|
28
|
+
const [capabilities, setCapabilities] = useState(null);
|
|
29
|
+
const [message, setMessage] = useState(null);
|
|
17
30
|
useInput((input, key) => {
|
|
18
31
|
if (key.escape && isActive) {
|
|
19
|
-
|
|
32
|
+
requestHandlers.onAborted('introspection');
|
|
20
33
|
}
|
|
21
34
|
}, { isActive });
|
|
22
35
|
useEffect(() => {
|
|
@@ -35,24 +48,29 @@ export function Introspect({ tasks, state: _state, status, service, children, de
|
|
|
35
48
|
await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
|
|
36
49
|
if (mounted) {
|
|
37
50
|
// Add debug components to timeline if present
|
|
38
|
-
|
|
51
|
+
if (result.debug?.length) {
|
|
52
|
+
workflowHandlers.addToTimeline(...result.debug);
|
|
53
|
+
}
|
|
39
54
|
// Capabilities come directly from result - no parsing needed
|
|
40
|
-
let
|
|
55
|
+
let caps = result.capabilities;
|
|
41
56
|
// Filter out internal capabilities when not in debug mode
|
|
42
57
|
if (debug === DebugLevel.None) {
|
|
43
|
-
|
|
58
|
+
caps = caps.filter((cap) => cap.name.toUpperCase() !== 'SCHEDULE' &&
|
|
44
59
|
cap.name.toUpperCase() !== 'VALIDATE' &&
|
|
45
60
|
cap.name.toUpperCase() !== 'REPORT');
|
|
46
61
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
setCapabilities(caps);
|
|
63
|
+
setMessage(result.message);
|
|
64
|
+
const finalState = {
|
|
65
|
+
error: null,
|
|
66
|
+
capabilities: caps,
|
|
50
67
|
message: result.message,
|
|
51
|
-
}
|
|
68
|
+
};
|
|
69
|
+
requestHandlers.onCompleted(finalState);
|
|
52
70
|
// Add Report component to queue
|
|
53
|
-
|
|
71
|
+
workflowHandlers.addToQueue(createReportDefinition(result.message, caps));
|
|
54
72
|
// Signal completion
|
|
55
|
-
|
|
73
|
+
lifecycleHandlers.completeActive();
|
|
56
74
|
}
|
|
57
75
|
}
|
|
58
76
|
catch (err) {
|
|
@@ -60,11 +78,13 @@ export function Introspect({ tasks, state: _state, status, service, children, de
|
|
|
60
78
|
if (mounted) {
|
|
61
79
|
const errorMessage = formatErrorMessage(err);
|
|
62
80
|
setError(errorMessage);
|
|
63
|
-
|
|
64
|
-
handlers?.updateState({
|
|
81
|
+
const finalState = {
|
|
65
82
|
error: errorMessage,
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
capabilities: [],
|
|
84
|
+
message: null,
|
|
85
|
+
};
|
|
86
|
+
requestHandlers.onCompleted(finalState);
|
|
87
|
+
requestHandlers.onError(errorMessage);
|
|
68
88
|
}
|
|
69
89
|
}
|
|
70
90
|
}
|
|
@@ -72,10 +92,19 @@ export function Introspect({ tasks, state: _state, status, service, children, de
|
|
|
72
92
|
return () => {
|
|
73
93
|
mounted = false;
|
|
74
94
|
};
|
|
75
|
-
}, [
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
95
|
+
}, [
|
|
96
|
+
tasks,
|
|
97
|
+
isActive,
|
|
98
|
+
service,
|
|
99
|
+
debug,
|
|
100
|
+
requestHandlers,
|
|
101
|
+
lifecycleHandlers,
|
|
102
|
+
workflowHandlers,
|
|
103
|
+
]);
|
|
104
|
+
const state = {
|
|
105
|
+
error,
|
|
106
|
+
capabilities: capabilities || [],
|
|
107
|
+
message,
|
|
108
|
+
};
|
|
109
|
+
return (_jsx(IntrospectView, { state: state, status: status, children: children }));
|
|
81
110
|
}
|
package/dist/ui/Label.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
3
|
import { getTaskColors, getTaskTypeLabel } from '../services/colors.js';
|
|
4
|
-
import { DebugLevel } from '../
|
|
4
|
+
import { DebugLevel } from '../configuration/types.js';
|
|
5
5
|
import { Separator } from './Separator.js';
|
|
6
6
|
export function Label({ description, taskType, showType = false, isCurrent = false, debug = DebugLevel.None, }) {
|
|
7
7
|
const colors = getTaskColors(taskType, isCurrent);
|
package/dist/ui/Main.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
|
+
import { DebugLevel } from '../configuration/types.js';
|
|
3
4
|
import { FeedbackType } from '../types/types.js';
|
|
4
|
-
import {
|
|
5
|
+
import { loadConfig, loadDebugSetting, saveConfig, saveDebugSetting, } from '../configuration/io.js';
|
|
6
|
+
import { getConfigurationRequiredMessage } from '../configuration/messages.js';
|
|
7
|
+
import { getMissingConfigKeys } from '../configuration/schema.js';
|
|
8
|
+
import { unflattenConfig } from '../configuration/transformation.js';
|
|
9
|
+
import { createAnthropicService } from '../services/anthropic.js';
|
|
5
10
|
import { createCommandDefinition, createConfigDefinitionWithKeys, createFeedback, createMessage, createWelcomeDefinition, } from '../services/components.js';
|
|
6
|
-
import { DebugLevel, getConfigurationRequiredMessage, getMissingConfigKeys, loadConfig, loadDebugSetting, saveConfig, saveDebugSetting, unflattenConfig, } from '../services/configuration.js';
|
|
7
11
|
import { registerGlobalShortcut } from '../services/keyboard.js';
|
|
8
12
|
import { initializeLogger, setDebugLevel } from '../services/logger.js';
|
|
9
13
|
import { Workflow } from './Workflow.js';
|
|
10
|
-
export const Main = ({ app, command }) => {
|
|
14
|
+
export const Main = ({ app, command, serviceFactory = createAnthropicService, }) => {
|
|
11
15
|
const [service, setService] = useState(null);
|
|
12
16
|
const [initialQueue, setInitialQueue] = useState(null);
|
|
13
17
|
const [debug, setDebugLevelState] = useState(() => loadDebugSetting());
|
|
@@ -44,7 +48,7 @@ export const Main = ({ app, command }) => {
|
|
|
44
48
|
// Config exists - create service immediately
|
|
45
49
|
try {
|
|
46
50
|
const config = loadConfig();
|
|
47
|
-
const newService =
|
|
51
|
+
const newService = serviceFactory(config.anthropic);
|
|
48
52
|
setService(newService);
|
|
49
53
|
}
|
|
50
54
|
catch (error) {
|
|
@@ -56,7 +60,7 @@ export const Main = ({ app, command }) => {
|
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
// If config is missing, service will be created after config completes
|
|
59
|
-
}, [service]);
|
|
63
|
+
}, [service, serviceFactory]);
|
|
60
64
|
// Initialize queue after service is ready
|
|
61
65
|
useEffect(() => {
|
|
62
66
|
// Only set initial queue once
|
|
@@ -75,7 +79,7 @@ export const Main = ({ app, command }) => {
|
|
|
75
79
|
}
|
|
76
80
|
// Load config and create service
|
|
77
81
|
const newConfig = loadConfig();
|
|
78
|
-
const newService =
|
|
82
|
+
const newService = serviceFactory(newConfig.anthropic);
|
|
79
83
|
setService(newService);
|
|
80
84
|
}
|
|
81
85
|
catch (error) {
|
package/dist/ui/Refinement.js
CHANGED
|
@@ -4,6 +4,13 @@ import { ComponentStatus } from '../types/components.js';
|
|
|
4
4
|
import { useInput } from '../services/keyboard.js';
|
|
5
5
|
import { Message } from './Message.js';
|
|
6
6
|
import { Spinner } from './Spinner.js';
|
|
7
|
+
export const RefinementView = ({ text, status }) => {
|
|
8
|
+
const isActive = status === ComponentStatus.Active;
|
|
9
|
+
return (_jsxs(Box, { gap: 1, children: [_jsx(Message, { text: text, status: status }), isActive && _jsx(Spinner, {})] }));
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Refinement controller: Handles abort input
|
|
13
|
+
*/
|
|
7
14
|
export const Refinement = ({ text, status, onAborted }) => {
|
|
8
15
|
const isActive = status === ComponentStatus.Active;
|
|
9
16
|
useInput((_, key) => {
|
|
@@ -12,5 +19,5 @@ export const Refinement = ({ text, status, onAborted }) => {
|
|
|
12
19
|
return;
|
|
13
20
|
}
|
|
14
21
|
}, { isActive });
|
|
15
|
-
return
|
|
22
|
+
return _jsx(RefinementView, { text: text, status: status });
|
|
16
23
|
};
|