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/ui/Config.js
CHANGED
|
@@ -6,7 +6,7 @@ import { ComponentStatus } from '../types/components.js';
|
|
|
6
6
|
import { FeedbackType } from '../types/types.js';
|
|
7
7
|
import { Colors } from '../services/colors.js';
|
|
8
8
|
import { createFeedback } from '../services/components.js';
|
|
9
|
-
import { DebugLevel } from '../
|
|
9
|
+
import { DebugLevel } from '../configuration/types.js';
|
|
10
10
|
import { useInput } from '../services/keyboard.js';
|
|
11
11
|
/**
|
|
12
12
|
* Get postfix with debug brackets if debug is enabled
|
|
@@ -78,16 +78,52 @@ function SelectionStep({ options, selectedIndex, isCurrentStep, }) {
|
|
|
78
78
|
return (_jsx(Box, { marginRight: 2, children: _jsx(Text, { dimColor: !isSelected || !isCurrentStep, bold: isSelected, children: option.label }) }, option.value));
|
|
79
79
|
}) }));
|
|
80
80
|
}
|
|
81
|
+
export const ConfigView = ({ steps, state, status, debug = DebugLevel.None, onInputChange, onInputSubmit, }) => {
|
|
82
|
+
const isActive = status === ComponentStatus.Active;
|
|
83
|
+
const { values, completedStep, selectedIndex } = state;
|
|
84
|
+
const renderStepInput = (stepConfig, isCurrentStep) => {
|
|
85
|
+
const configKey = stepConfig.path || stepConfig.key;
|
|
86
|
+
const displayValue = values[configKey];
|
|
87
|
+
switch (stepConfig.type) {
|
|
88
|
+
case StepType.Text:
|
|
89
|
+
if (isCurrentStep && onInputChange && onInputSubmit) {
|
|
90
|
+
return (_jsx(TextStep, { value: values[configKey] || '', placeholder: stepConfig.value || undefined, validate: stepConfig.validate, onChange: onInputChange, onSubmit: onInputSubmit }));
|
|
91
|
+
}
|
|
92
|
+
return (_jsx(Text, { dimColor: true, wrap: "truncate-end", children: displayValue || '' }));
|
|
93
|
+
case StepType.Selection: {
|
|
94
|
+
if (!isCurrentStep) {
|
|
95
|
+
const option = stepConfig.options.find((opt) => opt.value === displayValue);
|
|
96
|
+
return _jsx(Text, { dimColor: true, children: option?.label || '' });
|
|
97
|
+
}
|
|
98
|
+
return (_jsx(SelectionStep, { options: stepConfig.options, selectedIndex: selectedIndex, isCurrentStep: true }));
|
|
99
|
+
}
|
|
100
|
+
default: {
|
|
101
|
+
const _exhaustiveCheck = stepConfig;
|
|
102
|
+
throw new Error('Unsupported step type');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return (_jsx(Box, { flexDirection: "column", marginLeft: 1, children: steps.map((stepConfig, index) => {
|
|
107
|
+
const isCurrentStep = index === completedStep && isActive;
|
|
108
|
+
const isCompleted = index < completedStep;
|
|
109
|
+
const wasAborted = index === completedStep && !isActive;
|
|
110
|
+
const shouldShow = isCompleted || isCurrentStep || wasAborted;
|
|
111
|
+
if (!shouldShow) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const postfix = getPostfix(stepConfig.path, debug);
|
|
115
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: index === 0 ? 0 : 1, children: [_jsxs(Box, { children: [_jsx(Text, { children: stepConfig.description }), _jsx(Text, { children: ": " }), postfix && _jsx(Text, { color: Colors.Type.Config, children: postfix })] }), _jsxs(Box, { children: [_jsx(Text, { children: " " }), _jsx(Text, { color: Colors.Action.Select, dimColor: !isCurrentStep, children: ">" }), _jsx(Text, { children: " " }), renderStepInput(stepConfig, isCurrentStep)] })] }, stepConfig.path || stepConfig.key));
|
|
116
|
+
}) }));
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Config controller: Multi-step wizard logic
|
|
120
|
+
*/
|
|
81
121
|
export function Config(props) {
|
|
82
|
-
const { steps,
|
|
122
|
+
const { steps, status, debug = DebugLevel.None, requestHandlers, lifecycleHandlers, onFinished, onAborted, } = props;
|
|
83
123
|
const isActive = status === ComponentStatus.Active;
|
|
84
|
-
const [step, setStep] = useState(
|
|
124
|
+
const [step, setStep] = useState(0);
|
|
85
125
|
const [values, setValues] = useState(() => {
|
|
86
|
-
//
|
|
87
|
-
if (!isActive && state?.values) {
|
|
88
|
-
return state.values;
|
|
89
|
-
}
|
|
90
|
-
// Otherwise initialize from step defaults
|
|
126
|
+
// Initialize from step defaults
|
|
91
127
|
const initial = {};
|
|
92
128
|
steps.forEach((stepConfig) => {
|
|
93
129
|
// Use full path if available, otherwise use key
|
|
@@ -112,26 +148,14 @@ export function Config(props) {
|
|
|
112
148
|
});
|
|
113
149
|
const [inputValue, setInputValue] = useState(() => {
|
|
114
150
|
// Initialize with the current step's value if available
|
|
115
|
-
if (
|
|
151
|
+
if (step < steps.length) {
|
|
116
152
|
const stepConfig = steps[step];
|
|
117
153
|
const configKey = stepConfig.path || stepConfig.key;
|
|
118
154
|
return values[configKey] || '';
|
|
119
155
|
}
|
|
120
156
|
return '';
|
|
121
157
|
});
|
|
122
|
-
const [selectedIndex, setSelectedIndex] = useState(
|
|
123
|
-
// If not active, use saved state
|
|
124
|
-
if (!isActive && state?.selectedIndex !== undefined) {
|
|
125
|
-
return state.selectedIndex;
|
|
126
|
-
}
|
|
127
|
-
// Initialize selectedIndex based on current step's defaultIndex
|
|
128
|
-
if (isActive &&
|
|
129
|
-
step < steps.length &&
|
|
130
|
-
steps[step].type === StepType.Selection) {
|
|
131
|
-
return steps[step].defaultIndex;
|
|
132
|
-
}
|
|
133
|
-
return 0;
|
|
134
|
-
});
|
|
158
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
135
159
|
const normalizeValue = (value) => {
|
|
136
160
|
if (value === null || value === undefined) {
|
|
137
161
|
return '';
|
|
@@ -167,20 +191,21 @@ export function Config(props) {
|
|
|
167
191
|
throw new Error('Unsupported step type');
|
|
168
192
|
}
|
|
169
193
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
values,
|
|
194
|
+
const finalValues = currentValue
|
|
195
|
+
? { ...values, [configKey]: currentValue }
|
|
196
|
+
: values;
|
|
197
|
+
// Expose final state
|
|
198
|
+
const finalState = {
|
|
199
|
+
values: finalValues,
|
|
176
200
|
completedStep: step,
|
|
177
201
|
selectedIndex,
|
|
178
|
-
}
|
|
202
|
+
};
|
|
203
|
+
requestHandlers.onCompleted(finalState);
|
|
179
204
|
if (onAborted) {
|
|
180
205
|
onAborted('configuration');
|
|
181
206
|
}
|
|
182
207
|
// Complete with abort feedback
|
|
183
|
-
lifecycleHandlers
|
|
208
|
+
lifecycleHandlers.completeActive(createFeedback(FeedbackType.Aborted, 'Configuration cancelled.'));
|
|
184
209
|
return;
|
|
185
210
|
}
|
|
186
211
|
// Handle selection step navigation
|
|
@@ -192,7 +217,7 @@ export function Config(props) {
|
|
|
192
217
|
handleSubmit(currentStepConfig.options[selectedIndex].value);
|
|
193
218
|
}
|
|
194
219
|
}
|
|
195
|
-
});
|
|
220
|
+
}, { isActive });
|
|
196
221
|
const handleSubmit = (value) => {
|
|
197
222
|
const currentStepConfig = steps[step];
|
|
198
223
|
let finalValue = '';
|
|
@@ -230,37 +255,29 @@ export function Config(props) {
|
|
|
230
255
|
setInputValue('');
|
|
231
256
|
if (step === steps.length - 1) {
|
|
232
257
|
// Last step completed
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
const stateUpdate = {
|
|
258
|
+
// Expose final state
|
|
259
|
+
const finalState = {
|
|
236
260
|
values: newValues,
|
|
237
261
|
completedStep: steps.length,
|
|
238
262
|
selectedIndex,
|
|
239
263
|
};
|
|
240
|
-
|
|
264
|
+
requestHandlers.onCompleted(finalState);
|
|
241
265
|
// Call onFinished callback and handle result
|
|
242
266
|
try {
|
|
243
267
|
if (onFinished) {
|
|
244
268
|
onFinished(newValues);
|
|
245
269
|
}
|
|
246
270
|
// Success - complete with success feedback
|
|
247
|
-
lifecycleHandlers
|
|
271
|
+
lifecycleHandlers.completeActive(createFeedback(FeedbackType.Succeeded, 'Configuration saved successfully.'));
|
|
248
272
|
}
|
|
249
273
|
catch (error) {
|
|
250
274
|
// Failure - complete with error feedback
|
|
251
275
|
const errorMessage = error instanceof Error ? error.message : 'Configuration failed';
|
|
252
|
-
lifecycleHandlers
|
|
276
|
+
lifecycleHandlers.completeActive(createFeedback(FeedbackType.Failed, errorMessage));
|
|
253
277
|
}
|
|
254
278
|
setStep(steps.length);
|
|
255
279
|
}
|
|
256
280
|
else {
|
|
257
|
-
// Save state after each step
|
|
258
|
-
const stateUpdate = {
|
|
259
|
-
values: newValues,
|
|
260
|
-
completedStep: step + 1,
|
|
261
|
-
selectedIndex,
|
|
262
|
-
};
|
|
263
|
-
stateHandlers?.updateState(stateUpdate);
|
|
264
281
|
const nextStep = step + 1;
|
|
265
282
|
setStep(nextStep);
|
|
266
283
|
// Reset selectedIndex for next step
|
|
@@ -270,39 +287,12 @@ export function Config(props) {
|
|
|
270
287
|
}
|
|
271
288
|
}
|
|
272
289
|
};
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (isCurrentStep) {
|
|
280
|
-
return (_jsx(TextStep, { value: inputValue, placeholder: stepConfig.value || undefined, validate: stepConfig.validate, onChange: setInputValue, onSubmit: handleSubmit }));
|
|
281
|
-
}
|
|
282
|
-
return (_jsx(Text, { dimColor: true, wrap: "truncate-end", children: displayValue || '' }));
|
|
283
|
-
case StepType.Selection: {
|
|
284
|
-
if (!isCurrentStep) {
|
|
285
|
-
// Find the option that matches the saved/current value
|
|
286
|
-
const option = stepConfig.options.find((opt) => opt.value === displayValue);
|
|
287
|
-
return _jsx(Text, { dimColor: true, children: option?.label || '' });
|
|
288
|
-
}
|
|
289
|
-
return (_jsx(SelectionStep, { options: stepConfig.options, selectedIndex: selectedIndex, isCurrentStep: true }));
|
|
290
|
-
}
|
|
291
|
-
default: {
|
|
292
|
-
const _exhaustiveCheck = stepConfig;
|
|
293
|
-
throw new Error('Unsupported step type');
|
|
294
|
-
}
|
|
295
|
-
}
|
|
290
|
+
// Build current state for View
|
|
291
|
+
// Controller always renders View, passing current state and callbacks
|
|
292
|
+
const state = {
|
|
293
|
+
values,
|
|
294
|
+
completedStep: step,
|
|
295
|
+
selectedIndex,
|
|
296
296
|
};
|
|
297
|
-
return (_jsx(
|
|
298
|
-
const isCurrentStep = index === step && isActive;
|
|
299
|
-
const isCompleted = index < step;
|
|
300
|
-
const wasAborted = index === step && !isActive;
|
|
301
|
-
const shouldShow = isCompleted || isCurrentStep || wasAborted;
|
|
302
|
-
if (!shouldShow) {
|
|
303
|
-
return null;
|
|
304
|
-
}
|
|
305
|
-
const postfix = getPostfix(stepConfig.path, debug);
|
|
306
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: index === 0 ? 0 : 1, children: [_jsxs(Box, { children: [_jsx(Text, { children: stepConfig.description }), _jsx(Text, { children: ": " }), postfix && _jsx(Text, { color: Colors.Type.Config, children: postfix })] }), _jsxs(Box, { children: [_jsx(Text, { children: " " }), _jsx(Text, { color: Colors.Action.Select, dimColor: !isCurrentStep, children: ">" }), _jsx(Text, { children: " " }), renderStepInput(stepConfig, isCurrentStep)] })] }, stepConfig.path || stepConfig.key));
|
|
307
|
-
}) }));
|
|
297
|
+
return (_jsx(ConfigView, { steps: steps, state: state, status: status, debug: debug, onInputChange: setInputValue, onInputSubmit: handleSubmit }));
|
|
308
298
|
}
|
package/dist/ui/Confirm.js
CHANGED
|
@@ -1,31 +1,53 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { 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, Palette } from '../services/colors.js';
|
|
6
6
|
import { useInput } from '../services/keyboard.js';
|
|
7
7
|
import { UserQuery } from './UserQuery.js';
|
|
8
|
-
export
|
|
8
|
+
export const ConfirmView = ({ message, state, status }) => {
|
|
9
9
|
const isActive = status === ComponentStatus.Active;
|
|
10
|
-
const
|
|
10
|
+
const { selectedIndex } = state;
|
|
11
|
+
const options = [
|
|
12
|
+
{ label: 'yes', value: 'yes', color: Palette.BrightGreen },
|
|
13
|
+
{ label: 'no', value: 'no', color: Colors.Status.Error },
|
|
14
|
+
];
|
|
15
|
+
// Timeline rendering (Done status)
|
|
16
|
+
if (status === ComponentStatus.Done) {
|
|
17
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, marginLeft: 1, children: _jsx(Text, { color: undefined, children: message }) }), _jsxs(UserQuery, { children: ["> ", options[selectedIndex].label] })] }));
|
|
18
|
+
}
|
|
19
|
+
// Active/Pending rendering
|
|
20
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, marginLeft: 1, children: _jsx(Text, { color: getTextColor(isActive), children: message }) }), _jsxs(Box, { marginLeft: 1, children: [_jsx(Text, { color: Colors.Action.Select, children: ">" }), _jsx(Text, { children: " " }), _jsx(Box, { children: options.map((option, index) => {
|
|
21
|
+
const isSelected = index === selectedIndex;
|
|
22
|
+
return (_jsx(Box, { marginRight: 2, children: _jsx(Text, { color: isSelected ? option.color : undefined, dimColor: !isSelected, children: option.label }) }, option.value));
|
|
23
|
+
}) })] })] }));
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Confirm controller: Manages yes/no selection
|
|
27
|
+
*/
|
|
28
|
+
export function Confirm({ message, status, requestHandlers, onConfirmed, onCancelled, }) {
|
|
29
|
+
const isActive = status === ComponentStatus.Active;
|
|
30
|
+
const [selectedIndex, setSelectedIndex] = useState(0); // 0 = Yes, 1 = No
|
|
11
31
|
useInput((input, key) => {
|
|
12
32
|
if (!isActive)
|
|
13
33
|
return;
|
|
14
34
|
if (key.escape) {
|
|
15
35
|
// Escape: highlight "No" and cancel
|
|
16
|
-
|
|
17
|
-
|
|
36
|
+
const finalState = { selectedIndex: 1, confirmed: false };
|
|
37
|
+
requestHandlers.onCompleted(finalState);
|
|
18
38
|
onCancelled();
|
|
19
39
|
}
|
|
20
40
|
else if (key.tab) {
|
|
21
41
|
// Toggle between Yes (0) and No (1)
|
|
22
|
-
|
|
23
|
-
setSelectedIndex(newIndex);
|
|
24
|
-
stateHandlers?.updateState({ selectedIndex: newIndex });
|
|
42
|
+
setSelectedIndex((prev) => (prev === 0 ? 1 : 0));
|
|
25
43
|
}
|
|
26
44
|
else if (key.return) {
|
|
27
45
|
// Confirm selection
|
|
28
|
-
|
|
46
|
+
const finalState = {
|
|
47
|
+
selectedIndex,
|
|
48
|
+
confirmed: true,
|
|
49
|
+
};
|
|
50
|
+
requestHandlers.onCompleted(finalState);
|
|
29
51
|
if (selectedIndex === 0) {
|
|
30
52
|
onConfirmed();
|
|
31
53
|
}
|
|
@@ -34,16 +56,7 @@ export function Confirm({ message, state, status, stateHandlers, onConfirmed, on
|
|
|
34
56
|
}
|
|
35
57
|
}
|
|
36
58
|
}, { isActive });
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
];
|
|
41
|
-
if (!isActive) {
|
|
42
|
-
// When done, show both the message and user's choice in timeline
|
|
43
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, marginLeft: 1, children: _jsx(Text, { color: undefined, children: message }) }), _jsxs(UserQuery, { children: ["> ", options[selectedIndex].label] })] }));
|
|
44
|
-
}
|
|
45
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, marginLeft: 1, children: _jsx(Text, { color: getTextColor(isActive), children: message }) }), _jsxs(Box, { marginLeft: 1, children: [_jsx(Text, { color: Colors.Action.Select, children: ">" }), _jsx(Text, { children: " " }), _jsx(Box, { children: options.map((option, index) => {
|
|
46
|
-
const isSelected = index === selectedIndex;
|
|
47
|
-
return (_jsx(Box, { marginRight: 2, children: _jsx(Text, { color: isSelected ? option.color : undefined, dimColor: !isSelected, children: option.label }) }, option.value));
|
|
48
|
-
}) })] })] }));
|
|
59
|
+
// Controller always renders View, passing current state
|
|
60
|
+
const state = { selectedIndex, confirmed: false };
|
|
61
|
+
return _jsx(ConfirmView, { message: message, state: state, status: status });
|
|
49
62
|
}
|