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.
@@ -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, queueHandlers, workflowHandlers, errorHandlers, hasDefineTask = false) {
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
- queueHandlers.addToQueue(message);
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
- queueHandlers.addToQueue(scheduleDefinition);
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
- workflowHandlers.completeActiveAndPending();
51
- executeTasksAfterConfirm(validTasks, service, userRequest, queueHandlers, errorHandlers);
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
- workflowHandlers.completeActiveAndPending();
57
+ lifecycleHandlers.completeActiveAndPending();
55
58
  const message = getCancellationMessage(operation);
56
- queueHandlers.addToQueue(createFeedback(FeedbackType.Aborted, message));
59
+ workflowHandlers.addToQueue(createFeedback(FeedbackType.Aborted, message));
57
60
  });
58
- queueHandlers.addToQueue(confirmDefinition);
61
+ workflowHandlers.addToQueue(confirmDefinition);
59
62
  });
60
- queueHandlers.addToQueue(scheduleDefinition);
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, queueHandlers, errorHandlers) {
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
- errorHandlers.onError(error instanceof Error ? error.message : String(error));
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, queueHandlers, errorHandlers);
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, queueHandlers, errorHandlers);
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, queueHandlers, errorHandlers) {
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
- queueHandlers.addToQueue(createAnswerDefinition(task.action, service));
155
+ workflowHandlers.addToQueue(createAnswerDefinition(task.action, service));
153
156
  }
154
157
  }
155
158
  else if (taskType === TaskType.Introspect) {
156
- queueHandlers.addToQueue(createIntrospectDefinition(typeTasks, service));
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
- queueHandlers.addToQueue(createConfigDefinitionWithKeys(configKeys, (config) => {
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
- errorHandlers.onAborted(operation);
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
- queueHandlers.addToQueue(createFeedback(FeedbackType.Failed, errorMessages.join('\n\n')));
211
+ workflowHandlers.addToQueue(createFeedback(FeedbackType.Failed, errorMessages.join('\n\n')));
196
212
  }
197
213
  else if (validation.missingConfig.length > 0) {
198
- queueHandlers.addToQueue(createValidateDefinition(validation.missingConfig, userRequest, service, (error) => {
199
- errorHandlers.onError(error);
214
+ workflowHandlers.addToQueue(createValidateDefinition(validation.missingConfig, userRequest, service, (error) => {
215
+ requestHandlers.onError(error);
200
216
  }, () => {
201
- queueHandlers.addToQueue(createExecuteDefinition(typeTasks, service));
217
+ workflowHandlers.addToQueue(createExecuteDefinition(typeTasks, service));
202
218
  }, (operation) => {
203
- errorHandlers.onAborted(operation);
219
+ requestHandlers.onAborted(operation);
204
220
  }));
205
221
  }
206
222
  else {
207
- queueHandlers.addToQueue(createExecuteDefinition(typeTasks, service));
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
- queueHandlers.addToQueue(message);
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 function Answer({ question, state, status, service, stateHandlers, lifecycleHandlers, errorHandlers, workflowHandlers, }) {
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(state?.answer ?? null);
23
+ const [answer, setAnswer] = useState(null);
15
24
  useInput((input, key) => {
16
25
  if (key.escape && isActive) {
17
- errorHandlers?.onAborted('answer');
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?.addToTimeline(...result.debug);
42
+ workflowHandlers.addToTimeline(...result.debug);
34
43
  }
35
44
  // Extract answer from result
36
45
  const answerText = result.answer || '';
37
46
  setAnswer(answerText);
38
- // Update component state so answer persists in timeline
39
- stateHandlers?.updateState({
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?.completeActive();
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
- stateHandlers?.updateState({
61
+ // Expose final state with error
62
+ const finalState = {
51
63
  error: errorMessage,
52
- });
53
- errorHandlers?.onError(errorMessage);
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
- }, [question, isActive, service]);
62
- const lines = answer ? answer.split('\n') : [];
63
- 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] }) }))] }));
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
  }
@@ -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 function Command({ command, state, status, service, stateHandlers, lifecycleHandlers, queueHandlers, errorHandlers, workflowHandlers, onAborted, }) {
16
+ export const CommandView = ({ command, state, status }) => {
17
17
  const isActive = status === ComponentStatus.Active;
18
- const [error, setError] = useState(state?.error ?? null);
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
- errorHandlers?.onAborted('request');
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?.addToTimeline(...debugComponents);
65
+ workflowHandlers.addToTimeline(...debugComponents);
56
66
  }
57
- // Save result to state for timeline display
58
- stateHandlers?.updateState({
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, queueHandlers, lifecycleHandlers, workflowHandlers, errorHandlers);
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
- queueHandlers.addToQueue(scheduleDefinition);
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, queueHandlers, workflowHandlers, errorHandlers, false);
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
- stateHandlers?.updateState({
103
+ // Expose final state with error
104
+ const finalState = {
96
105
  error: errorMessage,
97
- });
98
- errorHandlers?.onError(errorMessage);
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
- }, [command, isActive, service]);
107
- 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] }) }))] }));
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
  }
@@ -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
- export const Component = memo(function Component({ def, debug, }) {
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(Report, { ...def.props, status: def.status });
42
- case ComponentName.Answer:
43
- return _jsx(Answer, { ...def.props, state: def.state, status: def.status });
44
- case ComponentName.Execute:
45
- return _jsx(Execute, { ...def.props, state: def.state, status: def.status });
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
- return (_jsx(Validate, { ...def.props, state: def.state, status: def.status, debug: debug }));
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
+ };