prompt-language-shell 0.8.4 → 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 +1 -1
- package/dist/services/colors.js +1 -1
- package/dist/services/components.js +35 -11
- package/dist/services/config-labels.js +15 -15
- package/dist/services/logger.js +2 -1
- package/dist/services/messages.js +32 -1
- package/dist/services/refinement.js +6 -6
- package/dist/services/router.js +43 -27
- package/dist/ui/Answer.js +36 -15
- package/dist/ui/Command.js +43 -23
- package/dist/ui/Component.js +147 -33
- package/dist/ui/Config.js +68 -78
- package/dist/ui/Confirm.js +34 -21
- package/dist/ui/Execute.js +107 -328
- package/dist/ui/Introspect.js +51 -24
- package/dist/ui/Label.js +1 -1
- package/dist/ui/Main.js +5 -1
- package/dist/ui/Refinement.js +8 -1
- package/dist/ui/Schedule.js +75 -52
- package/dist/ui/Validate.js +75 -77
- package/dist/ui/Workflow.js +50 -123
- package/package.json +1 -1
- package/dist/services/configuration.js +0 -409
package/dist/services/router.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { asScheduledTasks } from '../types/guards.js';
|
|
2
2
|
import { FeedbackType, TaskType } from '../types/types.js';
|
|
3
|
+
import { saveConfig } from '../configuration/io.js';
|
|
4
|
+
import { getConfigSchema } from '../configuration/schema.js';
|
|
5
|
+
import { unflattenConfig } from '../configuration/transformation.js';
|
|
6
|
+
import { saveConfigLabels } from './config-labels.js';
|
|
3
7
|
import { createAnswerDefinition, createConfigDefinitionWithKeys, createConfirmDefinition, createExecuteDefinition, createFeedback, createIntrospectDefinition, createMessage, createScheduleDefinition, createValidateDefinition, } from './components.js';
|
|
4
|
-
import { saveConfig, unflattenConfig } from './configuration.js';
|
|
5
8
|
import { getCancellationMessage, getMixedTaskTypesError, getUnknownRequestMessage, } from './messages.js';
|
|
6
9
|
import { validateExecuteTasks } from './validator.js';
|
|
7
10
|
/**
|
|
@@ -20,7 +23,7 @@ export function getOperationName(tasks) {
|
|
|
20
23
|
* Route tasks to appropriate components with Confirm flow
|
|
21
24
|
* Handles the complete flow: Plan → Confirm → Execute/Answer/Introspect
|
|
22
25
|
*/
|
|
23
|
-
export function routeTasksWithConfirm(tasks, message, service, userRequest,
|
|
26
|
+
export function routeTasksWithConfirm(tasks, message, service, userRequest, lifecycleHandlers, workflowHandlers, requestHandlers, hasDefineTask = false) {
|
|
24
27
|
if (tasks.length === 0)
|
|
25
28
|
return;
|
|
26
29
|
// Filter out ignore and discard tasks early
|
|
@@ -28,7 +31,7 @@ export function routeTasksWithConfirm(tasks, message, service, userRequest, queu
|
|
|
28
31
|
// Check if no valid tasks remain after filtering
|
|
29
32
|
if (validTasks.length === 0) {
|
|
30
33
|
const message = createMessage(getUnknownRequestMessage());
|
|
31
|
-
|
|
34
|
+
workflowHandlers.addToQueue(message);
|
|
32
35
|
return;
|
|
33
36
|
}
|
|
34
37
|
const operation = getOperationName(validTasks);
|
|
@@ -36,7 +39,7 @@ export function routeTasksWithConfirm(tasks, message, service, userRequest, queu
|
|
|
36
39
|
// Has DEFINE tasks - add Schedule to queue for user selection
|
|
37
40
|
// Refinement flow will call this function again with refined tasks
|
|
38
41
|
const scheduleDefinition = createScheduleDefinition(message, validTasks);
|
|
39
|
-
|
|
42
|
+
workflowHandlers.addToQueue(scheduleDefinition);
|
|
40
43
|
}
|
|
41
44
|
else {
|
|
42
45
|
// No DEFINE tasks - Schedule auto-completes and adds Confirm to queue
|
|
@@ -47,17 +50,17 @@ export function routeTasksWithConfirm(tasks, message, service, userRequest, queu
|
|
|
47
50
|
// Schedule completed - add Confirm to queue
|
|
48
51
|
const confirmDefinition = createConfirmDefinition(() => {
|
|
49
52
|
// User confirmed - complete both Confirm and Schedule, then route to appropriate component
|
|
50
|
-
|
|
51
|
-
executeTasksAfterConfirm(validTasks, service, userRequest,
|
|
53
|
+
lifecycleHandlers.completeActiveAndPending();
|
|
54
|
+
executeTasksAfterConfirm(validTasks, service, userRequest, workflowHandlers, requestHandlers);
|
|
52
55
|
}, () => {
|
|
53
56
|
// User cancelled - complete both Confirm and Schedule, then show cancellation
|
|
54
|
-
|
|
57
|
+
lifecycleHandlers.completeActiveAndPending();
|
|
55
58
|
const message = getCancellationMessage(operation);
|
|
56
|
-
|
|
59
|
+
workflowHandlers.addToQueue(createFeedback(FeedbackType.Aborted, message));
|
|
57
60
|
});
|
|
58
|
-
|
|
61
|
+
workflowHandlers.addToQueue(confirmDefinition);
|
|
59
62
|
});
|
|
60
|
-
|
|
63
|
+
workflowHandlers.addToQueue(scheduleDefinition);
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
/**
|
|
@@ -88,13 +91,13 @@ function validateTaskTypes(tasks) {
|
|
|
88
91
|
* Validates task types and routes each type appropriately
|
|
89
92
|
* Supports mixed types at top level with Groups
|
|
90
93
|
*/
|
|
91
|
-
function executeTasksAfterConfirm(tasks, service, userRequest,
|
|
94
|
+
function executeTasksAfterConfirm(tasks, service, userRequest, workflowHandlers, requestHandlers) {
|
|
92
95
|
// Validate task types (Groups must have uniform subtasks)
|
|
93
96
|
try {
|
|
94
97
|
validateTaskTypes(tasks);
|
|
95
98
|
}
|
|
96
99
|
catch (error) {
|
|
97
|
-
|
|
100
|
+
requestHandlers.onError(error instanceof Error ? error.message : String(error));
|
|
98
101
|
return;
|
|
99
102
|
}
|
|
100
103
|
const scheduledTasks = asScheduledTasks(tasks);
|
|
@@ -117,7 +120,7 @@ function executeTasksAfterConfirm(tasks, service, userRequest, queueHandlers, er
|
|
|
117
120
|
const taskType = type;
|
|
118
121
|
if (typeTasks.length === 0)
|
|
119
122
|
continue;
|
|
120
|
-
routeTasksByType(taskType, typeTasks, service, userRequest,
|
|
123
|
+
routeTasksByType(taskType, typeTasks, service, userRequest, workflowHandlers, requestHandlers);
|
|
121
124
|
}
|
|
122
125
|
consecutiveStandaloneTasks = [];
|
|
123
126
|
};
|
|
@@ -130,7 +133,7 @@ function executeTasksAfterConfirm(tasks, service, userRequest, queueHandlers, er
|
|
|
130
133
|
if (task.subtasks.length > 0) {
|
|
131
134
|
const subtasks = task.subtasks;
|
|
132
135
|
const taskType = subtasks[0].type;
|
|
133
|
-
routeTasksByType(taskType, subtasks, service, userRequest,
|
|
136
|
+
routeTasksByType(taskType, subtasks, service, userRequest, workflowHandlers, requestHandlers);
|
|
134
137
|
}
|
|
135
138
|
}
|
|
136
139
|
else {
|
|
@@ -145,22 +148,35 @@ function executeTasksAfterConfirm(tasks, service, userRequest, queueHandlers, er
|
|
|
145
148
|
* Route tasks by type to appropriate components
|
|
146
149
|
* Extracted to allow reuse for both Groups and standalone tasks
|
|
147
150
|
*/
|
|
148
|
-
function routeTasksByType(taskType, typeTasks, service, userRequest,
|
|
151
|
+
function routeTasksByType(taskType, typeTasks, service, userRequest, workflowHandlers, requestHandlers) {
|
|
149
152
|
if (taskType === TaskType.Answer) {
|
|
150
153
|
// Create separate Answer component for each question
|
|
151
154
|
for (const task of typeTasks) {
|
|
152
|
-
|
|
155
|
+
workflowHandlers.addToQueue(createAnswerDefinition(task.action, service));
|
|
153
156
|
}
|
|
154
157
|
}
|
|
155
158
|
else if (taskType === TaskType.Introspect) {
|
|
156
|
-
|
|
159
|
+
workflowHandlers.addToQueue(createIntrospectDefinition(typeTasks, service));
|
|
157
160
|
}
|
|
158
161
|
else if (taskType === TaskType.Config) {
|
|
159
|
-
// Route to Config flow - extract keys from task params
|
|
162
|
+
// Route to Config flow - extract keys and descriptions from task params
|
|
160
163
|
const configKeys = typeTasks
|
|
161
164
|
.map((task) => task.params?.key)
|
|
162
165
|
.filter((key) => key !== undefined);
|
|
163
|
-
|
|
166
|
+
// Extract and cache labels from task descriptions
|
|
167
|
+
// Only cache labels for dynamically discovered keys (not in schema)
|
|
168
|
+
const schema = getConfigSchema();
|
|
169
|
+
const labels = {};
|
|
170
|
+
for (const task of typeTasks) {
|
|
171
|
+
const key = task.params?.key;
|
|
172
|
+
if (key && task.action && !(key in schema)) {
|
|
173
|
+
labels[key] = task.action;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (Object.keys(labels).length > 0) {
|
|
177
|
+
saveConfigLabels(labels);
|
|
178
|
+
}
|
|
179
|
+
workflowHandlers.addToQueue(createConfigDefinitionWithKeys(configKeys, (config) => {
|
|
164
180
|
// Save config - Config component will handle completion and feedback
|
|
165
181
|
try {
|
|
166
182
|
// Convert flat dotted keys to nested structure grouped by section
|
|
@@ -177,7 +193,7 @@ function routeTasksByType(taskType, typeTasks, service, userRequest, queueHandle
|
|
|
177
193
|
throw new Error(errorMessage);
|
|
178
194
|
}
|
|
179
195
|
}, (operation) => {
|
|
180
|
-
|
|
196
|
+
requestHandlers.onAborted(operation);
|
|
181
197
|
}));
|
|
182
198
|
}
|
|
183
199
|
else if (taskType === TaskType.Execute) {
|
|
@@ -192,26 +208,26 @@ function routeTasksByType(taskType, typeTasks, service, userRequest, queueHandle
|
|
|
192
208
|
.join('\n');
|
|
193
209
|
return `Invalid skill definition "${error.skill}":\n\n${issuesList}`;
|
|
194
210
|
});
|
|
195
|
-
|
|
211
|
+
workflowHandlers.addToQueue(createFeedback(FeedbackType.Failed, errorMessages.join('\n\n')));
|
|
196
212
|
}
|
|
197
213
|
else if (validation.missingConfig.length > 0) {
|
|
198
|
-
|
|
199
|
-
|
|
214
|
+
workflowHandlers.addToQueue(createValidateDefinition(validation.missingConfig, userRequest, service, (error) => {
|
|
215
|
+
requestHandlers.onError(error);
|
|
200
216
|
}, () => {
|
|
201
|
-
|
|
217
|
+
workflowHandlers.addToQueue(createExecuteDefinition(typeTasks, service));
|
|
202
218
|
}, (operation) => {
|
|
203
|
-
|
|
219
|
+
requestHandlers.onAborted(operation);
|
|
204
220
|
}));
|
|
205
221
|
}
|
|
206
222
|
else {
|
|
207
|
-
|
|
223
|
+
workflowHandlers.addToQueue(createExecuteDefinition(typeTasks, service));
|
|
208
224
|
}
|
|
209
225
|
}
|
|
210
226
|
catch (error) {
|
|
211
227
|
// Handle skill reference errors (e.g., unknown skills)
|
|
212
228
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
213
229
|
const message = createMessage(errorMessage);
|
|
214
|
-
|
|
230
|
+
workflowHandlers.addToQueue(message);
|
|
215
231
|
}
|
|
216
232
|
}
|
|
217
233
|
}
|
package/dist/ui/Answer.js
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } 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
6
|
import { useInput } from '../services/keyboard.js';
|
|
7
7
|
import { formatErrorMessage } from '../services/messages.js';
|
|
8
8
|
import { withMinimumTime } from '../services/timing.js';
|
|
9
9
|
import { Spinner } from './Spinner.js';
|
|
10
10
|
const MINIMUM_PROCESSING_TIME = 400;
|
|
11
|
-
export
|
|
11
|
+
export const AnswerView = ({ question, state, status }) => {
|
|
12
|
+
const isActive = status === ComponentStatus.Active;
|
|
13
|
+
const { error, answer } = state;
|
|
14
|
+
const lines = answer ? answer.split('\n') : [];
|
|
15
|
+
return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isActive && !answer && !error && (_jsxs(Box, { marginLeft: 1, children: [_jsx(Text, { color: getTextColor(isActive), children: "Finding answer. " }), _jsx(Spinner, {})] })), answer && (_jsxs(_Fragment, { children: [_jsx(Box, { marginLeft: 1, marginBottom: 1, children: _jsx(Text, { color: getTextColor(isActive), children: question }) }), _jsx(Box, { flexDirection: "column", paddingLeft: 3, children: lines.map((line, index) => (_jsx(Text, { color: getTextColor(isActive), children: line }, index))) })] })), error && (_jsx(Box, { marginTop: 1, marginLeft: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) }))] }));
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Answer controller: Fetches answer from LLM
|
|
19
|
+
*/
|
|
20
|
+
export function Answer({ question, status, service, requestHandlers, lifecycleHandlers, workflowHandlers, }) {
|
|
12
21
|
const isActive = status === ComponentStatus.Active;
|
|
13
22
|
const [error, setError] = useState(null);
|
|
14
|
-
const [answer, setAnswer] = useState(
|
|
23
|
+
const [answer, setAnswer] = useState(null);
|
|
15
24
|
useInput((input, key) => {
|
|
16
25
|
if (key.escape && isActive) {
|
|
17
|
-
|
|
26
|
+
requestHandlers.onAborted('answer');
|
|
18
27
|
}
|
|
19
28
|
}, { isActive });
|
|
20
29
|
useEffect(() => {
|
|
@@ -30,27 +39,32 @@ export function Answer({ question, state, status, service, stateHandlers, lifecy
|
|
|
30
39
|
if (mounted) {
|
|
31
40
|
// Add debug components to timeline if present
|
|
32
41
|
if (result.debug?.length) {
|
|
33
|
-
workflowHandlers
|
|
42
|
+
workflowHandlers.addToTimeline(...result.debug);
|
|
34
43
|
}
|
|
35
44
|
// Extract answer from result
|
|
36
45
|
const answerText = result.answer || '';
|
|
37
46
|
setAnswer(answerText);
|
|
38
|
-
//
|
|
39
|
-
|
|
47
|
+
// Expose final state
|
|
48
|
+
const finalState = {
|
|
40
49
|
answer: answerText,
|
|
41
|
-
|
|
50
|
+
error: null,
|
|
51
|
+
};
|
|
52
|
+
requestHandlers.onCompleted(finalState);
|
|
42
53
|
// Signal completion
|
|
43
|
-
lifecycleHandlers
|
|
54
|
+
lifecycleHandlers.completeActive();
|
|
44
55
|
}
|
|
45
56
|
}
|
|
46
57
|
catch (err) {
|
|
47
58
|
if (mounted) {
|
|
48
59
|
const errorMessage = formatErrorMessage(err);
|
|
49
60
|
setError(errorMessage);
|
|
50
|
-
|
|
61
|
+
// Expose final state with error
|
|
62
|
+
const finalState = {
|
|
51
63
|
error: errorMessage,
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
answer: null,
|
|
65
|
+
};
|
|
66
|
+
requestHandlers.onCompleted(finalState);
|
|
67
|
+
requestHandlers.onError(errorMessage);
|
|
54
68
|
}
|
|
55
69
|
}
|
|
56
70
|
}
|
|
@@ -58,7 +72,14 @@ export function Answer({ question, state, status, service, stateHandlers, lifecy
|
|
|
58
72
|
return () => {
|
|
59
73
|
mounted = false;
|
|
60
74
|
};
|
|
61
|
-
}, [
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
}, [
|
|
76
|
+
question,
|
|
77
|
+
isActive,
|
|
78
|
+
service,
|
|
79
|
+
requestHandlers,
|
|
80
|
+
lifecycleHandlers,
|
|
81
|
+
workflowHandlers,
|
|
82
|
+
]);
|
|
83
|
+
const state = { error, answer };
|
|
84
|
+
return _jsx(AnswerView, { question: question, state: state, status: status });
|
|
64
85
|
}
|
package/dist/ui/Command.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } 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 { TaskType } from '../types/types.js';
|
|
6
6
|
import { Colors } from '../services/colors.js';
|
|
7
7
|
import { createScheduleDefinition } from '../services/components.js';
|
|
@@ -13,12 +13,22 @@ import { ensureMinimumTime } from '../services/timing.js';
|
|
|
13
13
|
import { Spinner } from './Spinner.js';
|
|
14
14
|
import { UserQuery } from './UserQuery.js';
|
|
15
15
|
const MIN_PROCESSING_TIME = 400; // purely for visual effect
|
|
16
|
-
export
|
|
16
|
+
export const CommandView = ({ command, state, status }) => {
|
|
17
17
|
const isActive = status === ComponentStatus.Active;
|
|
18
|
-
const
|
|
18
|
+
const { error } = state;
|
|
19
|
+
return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [!isActive ? (_jsxs(UserQuery, { children: ["> pls ", command] })) : (_jsxs(Box, { marginLeft: 1, children: [_jsxs(Text, { color: Colors.Text.Active, children: ["> pls ", command] }), _jsx(Text, { children: " " }), _jsx(Spinner, {})] })), error && (_jsx(Box, { marginTop: 1, marginLeft: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) }))] }));
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Command controller: Processes and routes command
|
|
23
|
+
*/
|
|
24
|
+
export function Command({ command, status, service, requestHandlers, lifecycleHandlers, workflowHandlers, onAborted, }) {
|
|
25
|
+
const isActive = status === ComponentStatus.Active;
|
|
26
|
+
const [error, setError] = useState(null);
|
|
27
|
+
const [message, setMessage] = useState(null);
|
|
28
|
+
const [tasks, setTasks] = useState([]);
|
|
19
29
|
useInput((_, key) => {
|
|
20
30
|
if (key.escape && isActive) {
|
|
21
|
-
|
|
31
|
+
requestHandlers.onAborted('request');
|
|
22
32
|
onAborted?.('request');
|
|
23
33
|
}
|
|
24
34
|
}, { isActive });
|
|
@@ -52,38 +62,36 @@ export function Command({ command, state, status, service, stateHandlers, lifecy
|
|
|
52
62
|
? [...scheduleDebug, ...(result.debug || [])]
|
|
53
63
|
: scheduleDebug;
|
|
54
64
|
if (debugComponents.length > 0) {
|
|
55
|
-
workflowHandlers
|
|
65
|
+
workflowHandlers.addToTimeline(...debugComponents);
|
|
56
66
|
}
|
|
57
|
-
//
|
|
58
|
-
|
|
67
|
+
// Update local state
|
|
68
|
+
setMessage(result.message);
|
|
69
|
+
setTasks(result.tasks);
|
|
70
|
+
// Expose final state
|
|
71
|
+
const finalState = {
|
|
72
|
+
error: null,
|
|
59
73
|
message: result.message,
|
|
60
74
|
tasks: result.tasks,
|
|
61
|
-
}
|
|
75
|
+
};
|
|
76
|
+
requestHandlers.onCompleted(finalState);
|
|
62
77
|
// Check if tasks contain DEFINE type (variant selection needed)
|
|
63
78
|
const hasDefineTask = result.tasks.some((task) => task.type === TaskType.Define);
|
|
64
|
-
// Guard: ensure all required handlers are present
|
|
65
|
-
if (!queueHandlers ||
|
|
66
|
-
!lifecycleHandlers ||
|
|
67
|
-
!workflowHandlers ||
|
|
68
|
-
!errorHandlers) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
79
|
// Create Schedule definition
|
|
72
80
|
const scheduleDefinition = createScheduleDefinition(result.message, result.tasks, hasDefineTask
|
|
73
81
|
? async (selectedTasks) => {
|
|
74
82
|
// Refinement flow for DEFINE tasks
|
|
75
|
-
await handleRefinement(selectedTasks, svc, command,
|
|
83
|
+
await handleRefinement(selectedTasks, svc, command, lifecycleHandlers, workflowHandlers, requestHandlers);
|
|
76
84
|
}
|
|
77
85
|
: undefined);
|
|
78
86
|
if (hasDefineTask) {
|
|
79
87
|
// DEFINE tasks: Move Command to timeline, add Schedule to queue
|
|
80
88
|
lifecycleHandlers.completeActive();
|
|
81
|
-
|
|
89
|
+
workflowHandlers.addToQueue(scheduleDefinition);
|
|
82
90
|
}
|
|
83
91
|
else {
|
|
84
92
|
// No DEFINE tasks: Complete Command, then route to Confirm flow
|
|
85
93
|
lifecycleHandlers.completeActive();
|
|
86
|
-
routeTasksWithConfirm(result.tasks, result.message, svc, command,
|
|
94
|
+
routeTasksWithConfirm(result.tasks, result.message, svc, command, lifecycleHandlers, workflowHandlers, requestHandlers, false);
|
|
87
95
|
}
|
|
88
96
|
}
|
|
89
97
|
}
|
|
@@ -92,10 +100,14 @@ export function Command({ command, state, status, service, stateHandlers, lifecy
|
|
|
92
100
|
if (mounted) {
|
|
93
101
|
const errorMessage = formatErrorMessage(err);
|
|
94
102
|
setError(errorMessage);
|
|
95
|
-
|
|
103
|
+
// Expose final state with error
|
|
104
|
+
const finalState = {
|
|
96
105
|
error: errorMessage,
|
|
97
|
-
|
|
98
|
-
|
|
106
|
+
message: null,
|
|
107
|
+
tasks: [],
|
|
108
|
+
};
|
|
109
|
+
requestHandlers.onCompleted(finalState);
|
|
110
|
+
requestHandlers.onError(errorMessage);
|
|
99
111
|
}
|
|
100
112
|
}
|
|
101
113
|
}
|
|
@@ -103,6 +115,14 @@ export function Command({ command, state, status, service, stateHandlers, lifecy
|
|
|
103
115
|
return () => {
|
|
104
116
|
mounted = false;
|
|
105
117
|
};
|
|
106
|
-
}, [
|
|
107
|
-
|
|
118
|
+
}, [
|
|
119
|
+
command,
|
|
120
|
+
isActive,
|
|
121
|
+
service,
|
|
122
|
+
requestHandlers,
|
|
123
|
+
lifecycleHandlers,
|
|
124
|
+
workflowHandlers,
|
|
125
|
+
]);
|
|
126
|
+
const state = { error, message, tasks };
|
|
127
|
+
return _jsx(CommandView, { command: command, state: state, status: status });
|
|
108
128
|
}
|
package/dist/ui/Component.js
CHANGED
|
@@ -1,49 +1,163 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
import { ComponentName } from '../types/types.js';
|
|
4
|
-
import { Answer } from './Answer.js';
|
|
5
|
-
import { Command } from './Command.js';
|
|
6
|
-
import { Config } from './Config.js';
|
|
7
|
-
import { Confirm } from './Confirm.js';
|
|
4
|
+
import { Answer, AnswerView } from './Answer.js';
|
|
5
|
+
import { Command, CommandView } from './Command.js';
|
|
6
|
+
import { Config, ConfigView } from './Config.js';
|
|
7
|
+
import { Confirm, ConfirmView } from './Confirm.js';
|
|
8
8
|
import { Debug } from './Debug.js';
|
|
9
|
-
import { Execute } from './Execute.js';
|
|
9
|
+
import { Execute, ExecuteView } from './Execute.js';
|
|
10
10
|
import { Feedback } from './Feedback.js';
|
|
11
|
-
import { Introspect } from './Introspect.js';
|
|
11
|
+
import { Introspect, IntrospectView } from './Introspect.js';
|
|
12
12
|
import { Message } from './Message.js';
|
|
13
|
-
import { Refinement } from './Refinement.js';
|
|
13
|
+
import { Refinement, RefinementView } from './Refinement.js';
|
|
14
14
|
import { Report } from './Report.js';
|
|
15
|
-
import { Schedule } from './Schedule.js';
|
|
16
|
-
import { Validate } from './Validate.js';
|
|
15
|
+
import { Schedule, ScheduleView } from './Schedule.js';
|
|
16
|
+
import { Validate, ValidateView } from './Validate.js';
|
|
17
17
|
import { Welcome } from './Welcome.js';
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Render a simple component (no lifecycle management)
|
|
20
|
+
*/
|
|
21
|
+
export const SimpleComponent = memo(function SimpleComponent({ def, }) {
|
|
19
22
|
switch (def.name) {
|
|
23
|
+
case ComponentName.Welcome: {
|
|
24
|
+
const { props, status } = def;
|
|
25
|
+
return _jsx(Welcome, { ...props, status: status });
|
|
26
|
+
}
|
|
27
|
+
case ComponentName.Feedback: {
|
|
28
|
+
const { props, status } = def;
|
|
29
|
+
return _jsx(Feedback, { ...props, status: status });
|
|
30
|
+
}
|
|
31
|
+
case ComponentName.Message: {
|
|
32
|
+
const { props, status } = def;
|
|
33
|
+
return _jsx(Message, { ...props, status: status });
|
|
34
|
+
}
|
|
35
|
+
case ComponentName.Debug: {
|
|
36
|
+
const { props, status } = def;
|
|
37
|
+
return _jsx(Debug, { ...props, status: status });
|
|
38
|
+
}
|
|
39
|
+
case ComponentName.Report: {
|
|
40
|
+
const { props, status } = def;
|
|
41
|
+
return _jsx(Report, { ...props, status: status });
|
|
42
|
+
}
|
|
43
|
+
default:
|
|
44
|
+
throw new Error(`Unknown simple component: ${def.name}`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Render a managed component (controller with lifecycle management)
|
|
49
|
+
*/
|
|
50
|
+
export const ControllerComponent = memo(function ControllerComponent({ def, debug, requestHandlers, lifecycleHandlers, workflowHandlers, }) {
|
|
51
|
+
switch (def.name) {
|
|
52
|
+
case ComponentName.Config: {
|
|
53
|
+
const { props: { steps, onFinished, onAborted }, status, } = def;
|
|
54
|
+
return (_jsx(Config, { steps: steps, onFinished: onFinished, onAborted: onAborted, requestHandlers: requestHandlers, lifecycleHandlers: lifecycleHandlers, status: status, debug: debug }));
|
|
55
|
+
}
|
|
56
|
+
case ComponentName.Command: {
|
|
57
|
+
const { props: { command, service, onAborted }, status, } = def;
|
|
58
|
+
return (_jsx(Command, { command: command, service: service, onAborted: onAborted, requestHandlers: requestHandlers, lifecycleHandlers: lifecycleHandlers, workflowHandlers: workflowHandlers, status: status }));
|
|
59
|
+
}
|
|
60
|
+
case ComponentName.Schedule: {
|
|
61
|
+
const { props: { message, tasks, onSelectionConfirmed }, status, } = def;
|
|
62
|
+
return (_jsx(Schedule, { message: message, tasks: tasks, onSelectionConfirmed: onSelectionConfirmed, requestHandlers: requestHandlers, lifecycleHandlers: lifecycleHandlers, status: status, debug: debug }));
|
|
63
|
+
}
|
|
64
|
+
case ComponentName.Refinement: {
|
|
65
|
+
const { props: { text, onAborted }, status, } = def;
|
|
66
|
+
return (_jsx(Refinement, { text: text, onAborted: onAborted, requestHandlers: requestHandlers, status: status }));
|
|
67
|
+
}
|
|
68
|
+
case ComponentName.Confirm: {
|
|
69
|
+
const { props: { message, onConfirmed, onCancelled }, status, } = def;
|
|
70
|
+
return (_jsx(Confirm, { message: message, onConfirmed: onConfirmed, onCancelled: onCancelled, requestHandlers: requestHandlers, status: status }));
|
|
71
|
+
}
|
|
72
|
+
case ComponentName.Introspect: {
|
|
73
|
+
const { props: { tasks, service, children }, status, } = def;
|
|
74
|
+
return (_jsx(Introspect, { tasks: tasks, service: service, children: children, requestHandlers: requestHandlers, lifecycleHandlers: lifecycleHandlers, workflowHandlers: workflowHandlers, status: status, debug: debug }));
|
|
75
|
+
}
|
|
76
|
+
case ComponentName.Answer: {
|
|
77
|
+
const { props: { question, service }, status, } = def;
|
|
78
|
+
return (_jsx(Answer, { question: question, service: service, requestHandlers: requestHandlers, lifecycleHandlers: lifecycleHandlers, workflowHandlers: workflowHandlers, status: status }));
|
|
79
|
+
}
|
|
80
|
+
case ComponentName.Validate: {
|
|
81
|
+
const { props: { missingConfig, userRequest, service, onError, onValidationComplete, onAborted, }, status, } = def;
|
|
82
|
+
return (_jsx(Validate, { missingConfig: missingConfig, userRequest: userRequest, service: service, onError: onError, onValidationComplete: onValidationComplete, onAborted: onAborted, requestHandlers: requestHandlers, lifecycleHandlers: lifecycleHandlers, workflowHandlers: workflowHandlers, status: status }));
|
|
83
|
+
}
|
|
84
|
+
case ComponentName.Execute: {
|
|
85
|
+
const { props: { tasks, service }, status, } = def;
|
|
86
|
+
return (_jsx(Execute, { tasks: tasks, service: service, requestHandlers: requestHandlers, lifecycleHandlers: lifecycleHandlers, workflowHandlers: workflowHandlers, status: status }));
|
|
87
|
+
}
|
|
88
|
+
default:
|
|
89
|
+
throw new Error(`Unknown managed component: ${def.name}`);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
/**
|
|
93
|
+
* Render a managed component as View only (no Controller logic)
|
|
94
|
+
*/
|
|
95
|
+
export const ViewComponent = memo(function ViewComponent({ def, }) {
|
|
96
|
+
switch (def.name) {
|
|
97
|
+
case ComponentName.Confirm: {
|
|
98
|
+
const { props: { message }, state, status, } = def;
|
|
99
|
+
return _jsx(ConfirmView, { message: message, state: state, status: status });
|
|
100
|
+
}
|
|
101
|
+
case ComponentName.Config: {
|
|
102
|
+
const { props: { steps }, state, status, } = def;
|
|
103
|
+
return _jsx(ConfigView, { steps: steps, state: state, status: status });
|
|
104
|
+
}
|
|
105
|
+
case ComponentName.Schedule: {
|
|
106
|
+
const { props: { message, tasks }, state, status, } = def;
|
|
107
|
+
return (_jsx(ScheduleView, { message: message, tasks: tasks, state: state, status: status }));
|
|
108
|
+
}
|
|
109
|
+
case ComponentName.Execute: {
|
|
110
|
+
const { props: { tasks }, state, status, } = def;
|
|
111
|
+
return _jsx(ExecuteView, { tasks: tasks, state: state, status: status });
|
|
112
|
+
}
|
|
113
|
+
case ComponentName.Answer: {
|
|
114
|
+
const { props: { question }, state, status, } = def;
|
|
115
|
+
return _jsx(AnswerView, { question: question, state: state, status: status });
|
|
116
|
+
}
|
|
117
|
+
case ComponentName.Command: {
|
|
118
|
+
const { props: { command }, state, status, } = def;
|
|
119
|
+
return _jsx(CommandView, { command: command, state: state, status: status });
|
|
120
|
+
}
|
|
121
|
+
case ComponentName.Introspect: {
|
|
122
|
+
const { props: { children }, state, status, } = def;
|
|
123
|
+
return (_jsx(IntrospectView, { state: state, status: status, children: children }));
|
|
124
|
+
}
|
|
125
|
+
case ComponentName.Validate: {
|
|
126
|
+
const { state, status } = def;
|
|
127
|
+
return _jsx(ValidateView, { state: state, status: status });
|
|
128
|
+
}
|
|
129
|
+
case ComponentName.Refinement: {
|
|
130
|
+
const { props: { text }, status, } = def;
|
|
131
|
+
return _jsx(RefinementView, { text: text, status: status });
|
|
132
|
+
}
|
|
133
|
+
default:
|
|
134
|
+
throw new Error(`Unknown managed component: ${def.name}`);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
/**
|
|
138
|
+
* Render a component in the timeline (Views only for managed, as-is for simple)
|
|
139
|
+
*/
|
|
140
|
+
export const TimelineComponent = ({ def, }) => {
|
|
141
|
+
switch (def.name) {
|
|
142
|
+
// Simple components render as-is
|
|
20
143
|
case ComponentName.Welcome:
|
|
21
|
-
return _jsx(Welcome, { ...def.props, status: def.status });
|
|
22
|
-
case ComponentName.Config:
|
|
23
|
-
return (_jsx(Config, { ...def.props, state: def.state, status: def.status, debug: debug }));
|
|
24
|
-
case ComponentName.Command:
|
|
25
|
-
return _jsx(Command, { ...def.props, state: def.state, status: def.status });
|
|
26
|
-
case ComponentName.Schedule:
|
|
27
|
-
return (_jsx(Schedule, { ...def.props, state: def.state, status: def.status, debug: debug }));
|
|
28
144
|
case ComponentName.Feedback:
|
|
29
|
-
return _jsx(Feedback, { ...def.props, status: def.status });
|
|
30
145
|
case ComponentName.Message:
|
|
31
|
-
return _jsx(Message, { ...def.props, status: def.status });
|
|
32
146
|
case ComponentName.Debug:
|
|
33
|
-
return _jsx(Debug, { ...def.props, status: def.status });
|
|
34
|
-
case ComponentName.Refinement:
|
|
35
|
-
return (_jsx(Refinement, { ...def.props, state: def.state, status: def.status }));
|
|
36
|
-
case ComponentName.Confirm:
|
|
37
|
-
return _jsx(Confirm, { ...def.props, state: def.state, status: def.status });
|
|
38
|
-
case ComponentName.Introspect:
|
|
39
|
-
return (_jsx(Introspect, { ...def.props, state: def.state, status: def.status, debug: debug }));
|
|
40
147
|
case ComponentName.Report:
|
|
41
|
-
return _jsx(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
case ComponentName.
|
|
45
|
-
|
|
148
|
+
return _jsx(SimpleComponent, { def: def });
|
|
149
|
+
// Managed components render as Views
|
|
150
|
+
case ComponentName.Config:
|
|
151
|
+
case ComponentName.Command:
|
|
152
|
+
case ComponentName.Confirm:
|
|
153
|
+
case ComponentName.Schedule:
|
|
154
|
+
case ComponentName.Refinement:
|
|
46
155
|
case ComponentName.Validate:
|
|
47
|
-
|
|
156
|
+
case ComponentName.Execute:
|
|
157
|
+
case ComponentName.Answer:
|
|
158
|
+
case ComponentName.Introspect:
|
|
159
|
+
return _jsx(ViewComponent, { def: def });
|
|
160
|
+
default:
|
|
161
|
+
throw new Error('Unknown component type');
|
|
48
162
|
}
|
|
49
|
-
}
|
|
163
|
+
};
|