prompt-language-shell 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -10
- package/dist/config/ANSWER.md +4 -0
- package/dist/config/INTROSPECT.md +4 -3
- package/dist/config/PLAN.md +23 -0
- package/dist/config/VALIDATE.md +12 -11
- package/dist/services/components.js +54 -64
- package/dist/services/configuration.js +84 -0
- package/dist/services/messages.js +22 -0
- package/dist/services/queue.js +2 -2
- package/dist/services/refinement.js +36 -0
- package/dist/services/task-router.js +135 -0
- package/dist/types/types.js +0 -1
- package/dist/ui/Answer.js +18 -27
- package/dist/ui/Command.js +45 -27
- package/dist/ui/Component.js +23 -50
- package/dist/ui/Config.js +49 -24
- package/dist/ui/Confirm.js +17 -11
- package/dist/ui/Execute.js +66 -45
- package/dist/ui/Feedback.js +1 -1
- package/dist/ui/Introspect.js +27 -23
- package/dist/ui/Main.js +71 -100
- package/dist/ui/Message.js +1 -1
- package/dist/ui/Plan.js +54 -32
- package/dist/ui/Refinement.js +6 -7
- package/dist/ui/Report.js +1 -1
- package/dist/ui/UserQuery.js +6 -0
- package/dist/ui/Validate.js +49 -19
- package/dist/ui/Welcome.js +12 -5
- package/dist/ui/Workflow.js +119 -0
- package/package.json +1 -1
- package/dist/handlers/answer.js +0 -21
- package/dist/handlers/command.js +0 -34
- package/dist/handlers/config.js +0 -88
- package/dist/handlers/execute.js +0 -46
- package/dist/handlers/execution.js +0 -140
- package/dist/handlers/introspect.js +0 -21
- package/dist/handlers/plan.js +0 -79
- package/dist/types/handlers.js +0 -1
- package/dist/ui/AnswerDisplay.js +0 -8
- package/dist/ui/Column.js +0 -7
|
@@ -43,6 +43,28 @@ export function getCancellationMessage(operation) {
|
|
|
43
43
|
];
|
|
44
44
|
return templates[Math.floor(Math.random() * templates.length)];
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Returns an error message when the request cannot be understood.
|
|
48
|
+
* Randomly selects from variations to sound natural.
|
|
49
|
+
*/
|
|
50
|
+
export function getUnknownRequestMessage() {
|
|
51
|
+
const messages = [
|
|
52
|
+
'I do not understand the request.',
|
|
53
|
+
'I cannot understand what you want me to do.',
|
|
54
|
+
"I'm not sure what you're asking for.",
|
|
55
|
+
'I cannot determine what action to take.',
|
|
56
|
+
'This request is unclear to me.',
|
|
57
|
+
'I do not recognize this command.',
|
|
58
|
+
];
|
|
59
|
+
return messages[Math.floor(Math.random() * messages.length)];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns an error message for mixed task types.
|
|
63
|
+
*/
|
|
64
|
+
export function getMixedTaskTypesError(types) {
|
|
65
|
+
const typeList = types.join(', ');
|
|
66
|
+
return `Mixed task types are not supported. Found: ${typeList}. All tasks in a plan must have the same type.`;
|
|
67
|
+
}
|
|
46
68
|
/**
|
|
47
69
|
* Feedback messages for various operations
|
|
48
70
|
*/
|
package/dist/services/queue.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FeedbackType } from '../types/types.js';
|
|
2
|
-
import { createFeedback
|
|
2
|
+
import { createFeedback } from './components.js';
|
|
3
3
|
import { FeedbackMessages } from './messages.js';
|
|
4
4
|
import { exitApp } from './process.js';
|
|
5
5
|
/**
|
|
@@ -37,7 +37,7 @@ export function withQueueHandler(componentName, callback, shouldExit = false, ex
|
|
|
37
37
|
*/
|
|
38
38
|
export function createErrorHandler(componentName, addToTimeline) {
|
|
39
39
|
return (error) => withQueueHandler(componentName, (first) => {
|
|
40
|
-
addToTimeline(
|
|
40
|
+
addToTimeline(first, createFeedback(FeedbackType.Failed, FeedbackMessages.UnexpectedError, error));
|
|
41
41
|
return undefined;
|
|
42
42
|
}, true, 1);
|
|
43
43
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createRefinement } from './components.js';
|
|
2
|
+
import { formatErrorMessage, getRefiningMessage } from './messages.js';
|
|
3
|
+
import { routeTasksWithConfirm } from './task-router.js';
|
|
4
|
+
/**
|
|
5
|
+
* Handle refinement flow for DEFINE tasks
|
|
6
|
+
* Called when user selects options from a plan with DEFINE tasks
|
|
7
|
+
*/
|
|
8
|
+
export async function handleRefinement(selectedTasks, service, originalCommand, handlers) {
|
|
9
|
+
// Create and add refinement component to queue
|
|
10
|
+
const refinementDef = createRefinement(getRefiningMessage(), (operation) => {
|
|
11
|
+
handlers.onAborted(operation);
|
|
12
|
+
});
|
|
13
|
+
handlers.addToQueue(refinementDef);
|
|
14
|
+
try {
|
|
15
|
+
// Build refined command from selected tasks
|
|
16
|
+
const refinedCommand = selectedTasks
|
|
17
|
+
.map((task) => {
|
|
18
|
+
const action = task.action.toLowerCase().replace(/,/g, ' -');
|
|
19
|
+
const type = task.type;
|
|
20
|
+
return `${action} (type: ${type})`;
|
|
21
|
+
})
|
|
22
|
+
.join(', ');
|
|
23
|
+
// Call LLM to refine plan with selected tasks
|
|
24
|
+
const refinedResult = await service.processWithTool(refinedCommand, 'plan');
|
|
25
|
+
// Complete the Refinement component
|
|
26
|
+
handlers.completeActive();
|
|
27
|
+
// Route refined tasks to appropriate components
|
|
28
|
+
routeTasksWithConfirm(refinedResult.tasks, refinedResult.message, service, originalCommand, handlers, false // No DEFINE tasks in refined result
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
handlers.completeActive();
|
|
33
|
+
const errorMessage = formatErrorMessage(err);
|
|
34
|
+
handlers.onError(errorMessage);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { TaskType } from '../types/types.js';
|
|
2
|
+
import { createAnswerDefinition, createConfigDefinitionWithKeys, createConfirmDefinition, createExecuteDefinition, createFeedback, createIntrospectDefinition, createMessage, createPlanDefinition, createValidateDefinition, } from './components.js';
|
|
3
|
+
import { saveConfig, unflattenConfig } from './configuration.js';
|
|
4
|
+
import { FeedbackType } from '../types/types.js';
|
|
5
|
+
import { validateExecuteTasks } from './execution-validator.js';
|
|
6
|
+
import { getMixedTaskTypesError, getUnknownRequestMessage, } from './messages.js';
|
|
7
|
+
/**
|
|
8
|
+
* Determine the operation name based on task types
|
|
9
|
+
*/
|
|
10
|
+
export function getOperationName(tasks) {
|
|
11
|
+
const allIntrospect = tasks.every((task) => task.type === TaskType.Introspect);
|
|
12
|
+
const allAnswer = tasks.every((task) => task.type === TaskType.Answer);
|
|
13
|
+
if (allIntrospect)
|
|
14
|
+
return 'introspection';
|
|
15
|
+
if (allAnswer)
|
|
16
|
+
return 'answer';
|
|
17
|
+
return 'execution';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Route tasks to appropriate components with Confirm flow
|
|
21
|
+
* Handles the complete flow: Plan → Confirm → Execute/Answer/Introspect
|
|
22
|
+
*/
|
|
23
|
+
export function routeTasksWithConfirm(tasks, message, service, userRequest, handlers, hasDefineTask = false) {
|
|
24
|
+
if (tasks.length === 0)
|
|
25
|
+
return;
|
|
26
|
+
// Filter out ignore and discard tasks early
|
|
27
|
+
const validTasks = tasks.filter((task) => task.type !== TaskType.Ignore && task.type !== TaskType.Discard);
|
|
28
|
+
// Check if no valid tasks remain after filtering
|
|
29
|
+
if (validTasks.length === 0) {
|
|
30
|
+
const message = createMessage(getUnknownRequestMessage());
|
|
31
|
+
handlers.addToQueue(message);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const operation = getOperationName(validTasks);
|
|
35
|
+
// Create plan definition with valid tasks only
|
|
36
|
+
const planDefinition = createPlanDefinition(message, validTasks);
|
|
37
|
+
if (hasDefineTask) {
|
|
38
|
+
// Has DEFINE tasks - add Plan to queue for user selection
|
|
39
|
+
// Refinement flow will call this function again with refined tasks
|
|
40
|
+
handlers.addToQueue(planDefinition);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// No DEFINE tasks - add Plan to timeline, create Confirm
|
|
44
|
+
const confirmDefinition = createConfirmDefinition(() => {
|
|
45
|
+
// User confirmed - route to appropriate component
|
|
46
|
+
handlers.completeActive();
|
|
47
|
+
executeTasksAfterConfirm(validTasks, service, userRequest, handlers);
|
|
48
|
+
}, () => {
|
|
49
|
+
// User cancelled
|
|
50
|
+
handlers.onAborted(operation);
|
|
51
|
+
});
|
|
52
|
+
handlers.addToTimeline(planDefinition);
|
|
53
|
+
handlers.addToQueue(confirmDefinition);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validate that all tasks have the same type
|
|
58
|
+
* Per FLOWS.md: "Mixed types → Error (not supported)"
|
|
59
|
+
*/
|
|
60
|
+
function validateTaskTypes(tasks) {
|
|
61
|
+
if (tasks.length === 0)
|
|
62
|
+
return;
|
|
63
|
+
const types = new Set(tasks.map((task) => task.type));
|
|
64
|
+
if (types.size > 1) {
|
|
65
|
+
throw new Error(getMixedTaskTypesError(Array.from(types)));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Execute tasks after confirmation (internal helper)
|
|
70
|
+
* Validates task types after user has seen and confirmed the plan
|
|
71
|
+
*/
|
|
72
|
+
function executeTasksAfterConfirm(tasks, service, userRequest, handlers) {
|
|
73
|
+
// Validate all tasks have the same type after user confirmation
|
|
74
|
+
// Per FLOWS.md: "Confirm component completes → Execution handler analyzes task types"
|
|
75
|
+
try {
|
|
76
|
+
validateTaskTypes(tasks);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
handlers.onError(error instanceof Error ? error.message : String(error));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const allIntrospect = tasks.every((task) => task.type === TaskType.Introspect);
|
|
83
|
+
const allAnswer = tasks.every((task) => task.type === TaskType.Answer);
|
|
84
|
+
const allConfig = tasks.every((task) => task.type === TaskType.Config);
|
|
85
|
+
if (allAnswer) {
|
|
86
|
+
const question = tasks[0].action;
|
|
87
|
+
handlers.addToQueue(createAnswerDefinition(question, service));
|
|
88
|
+
}
|
|
89
|
+
else if (allIntrospect) {
|
|
90
|
+
handlers.addToQueue(createIntrospectDefinition(tasks, service));
|
|
91
|
+
}
|
|
92
|
+
else if (allConfig) {
|
|
93
|
+
// Route to Config flow - extract keys from task params
|
|
94
|
+
const configKeys = tasks
|
|
95
|
+
.map((task) => task.params?.key)
|
|
96
|
+
.filter((key) => key !== undefined);
|
|
97
|
+
handlers.addToQueue(createConfigDefinitionWithKeys(configKeys, (config) => {
|
|
98
|
+
// Save config using the same pattern as Validate component
|
|
99
|
+
try {
|
|
100
|
+
// Convert flat dotted keys to nested structure grouped by section
|
|
101
|
+
const configBySection = unflattenConfig(config);
|
|
102
|
+
// Save each section
|
|
103
|
+
for (const [section, sectionConfig] of Object.entries(configBySection)) {
|
|
104
|
+
saveConfig(section, sectionConfig);
|
|
105
|
+
}
|
|
106
|
+
handlers.completeActive();
|
|
107
|
+
handlers.addToQueue(createFeedback(FeedbackType.Succeeded, 'Configuration updated successfully.'));
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
const errorMessage = error instanceof Error
|
|
111
|
+
? error.message
|
|
112
|
+
: 'Failed to save configuration';
|
|
113
|
+
handlers.onError(errorMessage);
|
|
114
|
+
}
|
|
115
|
+
}, (operation) => {
|
|
116
|
+
handlers.onAborted(operation);
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
// Execute tasks with validation
|
|
121
|
+
const missingConfig = validateExecuteTasks(tasks);
|
|
122
|
+
if (missingConfig.length > 0) {
|
|
123
|
+
handlers.addToQueue(createValidateDefinition(missingConfig, userRequest, service, (error) => {
|
|
124
|
+
handlers.onError(error);
|
|
125
|
+
}, () => {
|
|
126
|
+
handlers.addToQueue(createExecuteDefinition(tasks, service));
|
|
127
|
+
}, (operation) => {
|
|
128
|
+
handlers.onAborted(operation);
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
handlers.addToQueue(createExecuteDefinition(tasks, service));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
package/dist/types/types.js
CHANGED
|
@@ -11,7 +11,6 @@ export var ComponentName;
|
|
|
11
11
|
ComponentName["Introspect"] = "introspect";
|
|
12
12
|
ComponentName["Report"] = "report";
|
|
13
13
|
ComponentName["Answer"] = "answer";
|
|
14
|
-
ComponentName["AnswerDisplay"] = "answerDisplay";
|
|
15
14
|
ComponentName["Execute"] = "execute";
|
|
16
15
|
ComponentName["Validate"] = "validate";
|
|
17
16
|
})(ComponentName || (ComponentName = {}));
|
package/dist/ui/Answer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
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
4
|
import { Colors, getTextColor } from '../services/colors.js';
|
|
@@ -7,26 +7,22 @@ import { formatErrorMessage } from '../services/messages.js';
|
|
|
7
7
|
import { withMinimumTime } from '../services/timing.js';
|
|
8
8
|
import { Spinner } from './Spinner.js';
|
|
9
9
|
const MINIMUM_PROCESSING_TIME = 400;
|
|
10
|
-
export function Answer({ question, state,
|
|
11
|
-
const done = state?.done ?? false;
|
|
12
|
-
const isCurrent = done === false;
|
|
10
|
+
export function Answer({ question, state, isActive = true, service, handlers, }) {
|
|
13
11
|
const [error, setError] = useState(null);
|
|
14
|
-
const [
|
|
12
|
+
const [answer, setAnswer] = useState(state?.answer ?? null);
|
|
15
13
|
useInput((input, key) => {
|
|
16
|
-
if (key.escape &&
|
|
17
|
-
|
|
18
|
-
onAborted();
|
|
14
|
+
if (key.escape && isActive) {
|
|
15
|
+
handlers?.onAborted('answer');
|
|
19
16
|
}
|
|
20
|
-
}, { isActive
|
|
17
|
+
}, { isActive });
|
|
21
18
|
useEffect(() => {
|
|
22
19
|
// Skip processing if done
|
|
23
|
-
if (
|
|
20
|
+
if (!isActive) {
|
|
24
21
|
return;
|
|
25
22
|
}
|
|
26
23
|
// Skip processing if no service available
|
|
27
24
|
if (!service) {
|
|
28
25
|
setError('No service available');
|
|
29
|
-
setIsLoading(false);
|
|
30
26
|
return;
|
|
31
27
|
}
|
|
32
28
|
let mounted = true;
|
|
@@ -36,21 +32,19 @@ export function Answer({ question, state, service, onError, onComplete, onAborte
|
|
|
36
32
|
const result = await withMinimumTime(() => svc.processWithTool(question, 'answer'), MINIMUM_PROCESSING_TIME);
|
|
37
33
|
if (mounted) {
|
|
38
34
|
// Extract answer from result
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
const answerText = result.answer || '';
|
|
36
|
+
setAnswer(answerText);
|
|
37
|
+
// Update component state so answer persists in timeline
|
|
38
|
+
handlers?.updateState({ answer: answerText });
|
|
39
|
+
// Signal completion
|
|
40
|
+
handlers?.onComplete();
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
catch (err) {
|
|
45
44
|
if (mounted) {
|
|
46
45
|
const errorMessage = formatErrorMessage(err);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
onError(errorMessage);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
setError(errorMessage);
|
|
53
|
-
}
|
|
46
|
+
setError(errorMessage);
|
|
47
|
+
handlers?.onError(errorMessage);
|
|
54
48
|
}
|
|
55
49
|
}
|
|
56
50
|
}
|
|
@@ -58,10 +52,7 @@ export function Answer({ question, state, service, onError, onComplete, onAborte
|
|
|
58
52
|
return () => {
|
|
59
53
|
mounted = false;
|
|
60
54
|
};
|
|
61
|
-
}, [question,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isLoading && (_jsxs(Box, { children: [_jsx(Text, { color: getTextColor(isCurrent), children: "Finding answer. " }), _jsx(Spinner, {})] })), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) }))] }));
|
|
55
|
+
}, [question, isActive, service, handlers]);
|
|
56
|
+
const lines = answer ? answer.split('\n') : [];
|
|
57
|
+
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] }) }))] }));
|
|
67
58
|
}
|
package/dist/ui/Command.js
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx
|
|
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
4
|
import { TaskType } from '../types/types.js';
|
|
5
5
|
import { Colors } from '../services/colors.js';
|
|
6
|
-
import {
|
|
6
|
+
import { createPlanDefinition } from '../services/components.js';
|
|
7
7
|
import { formatErrorMessage } from '../services/messages.js';
|
|
8
|
+
import { useInput } from '../services/keyboard.js';
|
|
9
|
+
import { handleRefinement } from '../services/refinement.js';
|
|
10
|
+
import { routeTasksWithConfirm } from '../services/task-router.js';
|
|
8
11
|
import { ensureMinimumTime } from '../services/timing.js';
|
|
9
12
|
import { Spinner } from './Spinner.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const [error, setError] = useState(null);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
onAborted();
|
|
13
|
+
import { UserQuery } from './UserQuery.js';
|
|
14
|
+
const MIN_PROCESSING_TIME = 400; // purely for visual effect
|
|
15
|
+
export function Command({ command, state, isActive = true, service, handlers, onAborted, }) {
|
|
16
|
+
const [error, setError] = useState(state?.error ?? null);
|
|
17
|
+
useInput((_, key) => {
|
|
18
|
+
if (key.escape && isActive) {
|
|
19
|
+
handlers?.onAborted('request');
|
|
20
|
+
onAborted?.('request');
|
|
19
21
|
}
|
|
20
|
-
}, { isActive
|
|
22
|
+
}, { isActive });
|
|
21
23
|
useEffect(() => {
|
|
22
|
-
// Skip processing if
|
|
23
|
-
if (
|
|
24
|
+
// Skip processing if not active (showing historical/final state)
|
|
25
|
+
if (!isActive) {
|
|
24
26
|
return;
|
|
25
27
|
}
|
|
26
28
|
// Skip processing if no service available
|
|
27
29
|
if (!service) {
|
|
28
30
|
setError('No service available');
|
|
29
|
-
setIsLoading(false);
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
32
33
|
let mounted = true;
|
|
@@ -45,21 +46,39 @@ export function Command({ command, state, service, children, onError, onComplete
|
|
|
45
46
|
}
|
|
46
47
|
await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
|
|
47
48
|
if (mounted) {
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
// Save result to state for timeline display
|
|
50
|
+
handlers?.updateState({
|
|
51
|
+
message: result.message,
|
|
52
|
+
tasks: result.tasks,
|
|
53
|
+
});
|
|
54
|
+
// Check if tasks contain DEFINE type (variant selection needed)
|
|
55
|
+
const hasDefineTask = result.tasks.some((task) => task.type === TaskType.Define);
|
|
56
|
+
// Create Plan definition
|
|
57
|
+
const planDefinition = createPlanDefinition(result.message, result.tasks, hasDefineTask
|
|
58
|
+
? async (selectedTasks) => {
|
|
59
|
+
// Refinement flow for DEFINE tasks
|
|
60
|
+
await handleRefinement(selectedTasks, svc, command, handlers);
|
|
61
|
+
}
|
|
62
|
+
: undefined);
|
|
63
|
+
if (hasDefineTask) {
|
|
64
|
+
// Has DEFINE tasks: Add Plan to queue for selection
|
|
65
|
+
// The refinement callback will handle routing after user selects
|
|
66
|
+
handlers?.addToQueue(planDefinition);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// No DEFINE tasks: Use routing service for Confirm flow
|
|
70
|
+
routeTasksWithConfirm(result.tasks, result.message, svc, command, handlers, false);
|
|
71
|
+
}
|
|
72
|
+
// Move Command to timeline
|
|
73
|
+
handlers?.onComplete();
|
|
50
74
|
}
|
|
51
75
|
}
|
|
52
76
|
catch (err) {
|
|
53
77
|
await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
|
|
54
78
|
if (mounted) {
|
|
55
79
|
const errorMessage = formatErrorMessage(err);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
onError(errorMessage);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
setError(errorMessage);
|
|
62
|
-
}
|
|
80
|
+
setError(errorMessage);
|
|
81
|
+
handlers?.onError(errorMessage);
|
|
63
82
|
}
|
|
64
83
|
}
|
|
65
84
|
}
|
|
@@ -67,7 +86,6 @@ export function Command({ command, state, service, children, onError, onComplete
|
|
|
67
86
|
return () => {
|
|
68
87
|
mounted = false;
|
|
69
88
|
};
|
|
70
|
-
}, [command,
|
|
71
|
-
|
|
72
|
-
return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [_jsxs(Box, { paddingX: done ? 1 : 0, marginX: done ? -1 : 0, backgroundColor: done ? Colors.Background.UserQuery : undefined, children: [_jsxs(Text, { color: isCurrent ? Colors.Text.Active : Colors.Text.UserQuery, children: ["> pls ", command] }), isLoading && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Spinner, {})] }))] }), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) })), children] }));
|
|
89
|
+
}, [command, isActive, service, handlers]);
|
|
90
|
+
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] }) }))] }));
|
|
73
91
|
}
|
package/dist/ui/Component.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import { memo } from 'react';
|
|
3
3
|
import { ComponentName } from '../types/types.js';
|
|
4
4
|
import { Answer } from './Answer.js';
|
|
5
|
-
import { AnswerDisplay } from './AnswerDisplay.js';
|
|
6
5
|
import { Command } from './Command.js';
|
|
7
6
|
import { Confirm } from './Confirm.js';
|
|
8
7
|
import { Config } from './Config.js';
|
|
@@ -15,62 +14,36 @@ import { Refinement } from './Refinement.js';
|
|
|
15
14
|
import { Report } from './Report.js';
|
|
16
15
|
import { Validate } from './Validate.js';
|
|
17
16
|
import { Welcome } from './Welcome.js';
|
|
18
|
-
export const Component =
|
|
17
|
+
export const Component = memo(function Component({ def, isActive, debug, }) {
|
|
18
|
+
// For stateless components, always inactive
|
|
19
|
+
const isStatelessComponent = !('state' in def);
|
|
20
|
+
const componentIsActive = isStatelessComponent ? false : isActive;
|
|
19
21
|
switch (def.name) {
|
|
20
22
|
case ComponentName.Welcome:
|
|
21
23
|
return _jsx(Welcome, { ...def.props });
|
|
22
|
-
case ComponentName.Config:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return _jsx(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const props = def.props;
|
|
29
|
-
const state = def.state;
|
|
30
|
-
return _jsx(Command, { ...props, state: state });
|
|
31
|
-
}
|
|
32
|
-
case ComponentName.Plan: {
|
|
33
|
-
const props = def.props;
|
|
34
|
-
const state = def.state;
|
|
35
|
-
return _jsx(Plan, { ...props, state: state, debug: debug });
|
|
36
|
-
}
|
|
24
|
+
case ComponentName.Config:
|
|
25
|
+
return (_jsx(Config, { ...def.props, state: def.state, isActive: componentIsActive, debug: debug }));
|
|
26
|
+
case ComponentName.Command:
|
|
27
|
+
return _jsx(Command, { ...def.props, state: def.state, isActive: isActive });
|
|
28
|
+
case ComponentName.Plan:
|
|
29
|
+
return (_jsx(Plan, { ...def.props, state: def.state, isActive: componentIsActive, debug: debug }));
|
|
37
30
|
case ComponentName.Feedback:
|
|
38
31
|
return _jsx(Feedback, { ...def.props });
|
|
39
32
|
case ComponentName.Message:
|
|
40
33
|
return _jsx(Message, { ...def.props });
|
|
41
|
-
case ComponentName.Refinement:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return _jsx(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const props = def.props;
|
|
48
|
-
const state = def.state;
|
|
49
|
-
return _jsx(Confirm, { ...props, state: state });
|
|
50
|
-
}
|
|
51
|
-
case ComponentName.Introspect: {
|
|
52
|
-
const props = def.props;
|
|
53
|
-
const state = def.state;
|
|
54
|
-
return _jsx(Introspect, { ...props, state: state, debug: debug });
|
|
55
|
-
}
|
|
34
|
+
case ComponentName.Refinement:
|
|
35
|
+
return (_jsx(Refinement, { ...def.props, state: def.state, isActive: isActive }));
|
|
36
|
+
case ComponentName.Confirm:
|
|
37
|
+
return _jsx(Confirm, { ...def.props, state: def.state, isActive: isActive });
|
|
38
|
+
case ComponentName.Introspect:
|
|
39
|
+
return (_jsx(Introspect, { ...def.props, state: def.state, isActive: componentIsActive, debug: debug }));
|
|
56
40
|
case ComponentName.Report:
|
|
57
41
|
return _jsx(Report, { ...def.props });
|
|
58
|
-
case ComponentName.Answer:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return _jsx(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return _jsx(AnswerDisplay, { ...def.props });
|
|
65
|
-
case ComponentName.Execute: {
|
|
66
|
-
const props = def.props;
|
|
67
|
-
const state = def.state;
|
|
68
|
-
return _jsx(Execute, { ...props, state: state });
|
|
69
|
-
}
|
|
70
|
-
case ComponentName.Validate: {
|
|
71
|
-
const props = def.props;
|
|
72
|
-
const state = def.state;
|
|
73
|
-
return _jsx(Validate, { ...props, state: state });
|
|
74
|
-
}
|
|
42
|
+
case ComponentName.Answer:
|
|
43
|
+
return _jsx(Answer, { ...def.props, state: def.state, isActive: isActive });
|
|
44
|
+
case ComponentName.Execute:
|
|
45
|
+
return _jsx(Execute, { ...def.props, state: def.state, isActive: isActive });
|
|
46
|
+
case ComponentName.Validate:
|
|
47
|
+
return (_jsx(Validate, { ...def.props, state: def.state, isActive: isActive, debug: debug }));
|
|
75
48
|
}
|
|
76
49
|
});
|