prompt-language-shell 0.9.2 → 0.9.4
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/{ui/Main.js → Main.js} +12 -12
- package/dist/{ui → components}/Component.js +28 -26
- package/dist/{ui → components}/Workflow.js +2 -3
- package/dist/{ui → components/controllers}/Answer.js +18 -17
- package/dist/{ui → components/controllers}/Command.js +11 -18
- package/dist/{ui → components/controllers}/Config.js +8 -116
- package/dist/components/controllers/Confirm.js +42 -0
- package/dist/{ui → components/controllers}/Execute.js +75 -144
- package/dist/{ui → components/controllers}/Introspect.js +12 -28
- package/dist/components/controllers/Refinement.js +18 -0
- package/dist/components/controllers/Schedule.js +139 -0
- package/dist/{ui → components/controllers}/Validate.js +14 -32
- package/dist/components/views/Answer.js +28 -0
- package/dist/components/views/Command.js +11 -0
- package/dist/components/views/Config.js +115 -0
- package/dist/components/views/Confirm.js +24 -0
- package/dist/components/views/Execute.js +60 -0
- package/dist/{ui → components/views}/Feedback.js +3 -3
- package/dist/components/views/Introspect.js +17 -0
- package/dist/{ui → components/views}/Label.js +3 -3
- package/dist/{ui → components/views}/List.js +1 -1
- package/dist/{ui → components/views}/Output.js +2 -2
- package/dist/components/views/Refinement.js +9 -0
- package/dist/{ui → components/views}/Report.js +1 -1
- package/dist/components/views/Schedule.js +120 -0
- package/dist/{ui → components/views}/Separator.js +1 -1
- package/dist/{ui → components/views}/Spinner.js +1 -1
- package/dist/{ui → components/views}/Subtask.js +4 -4
- package/dist/components/views/Task.js +18 -0
- package/dist/components/views/Upcoming.js +30 -0
- package/dist/{ui → components/views}/UserQuery.js +1 -1
- package/dist/components/views/Validate.js +17 -0
- package/dist/{ui → components/views}/Welcome.js +1 -1
- package/dist/configuration/steps.js +1 -1
- package/dist/execution/handlers.js +19 -53
- package/dist/execution/reducer.js +26 -38
- package/dist/execution/runner.js +43 -25
- package/dist/execution/types.js +3 -4
- package/dist/execution/utils.js +1 -1
- package/dist/index.js +1 -1
- package/dist/services/messages.js +19 -0
- package/dist/services/router.js +69 -11
- package/dist/services/shell.js +26 -6
- package/dist/services/timing.js +1 -0
- package/dist/skills/execute.md +15 -7
- package/dist/tools/execute.tool.js +0 -4
- package/dist/types/schemas.js +0 -1
- package/package.json +1 -1
- package/dist/execution/hooks.js +0 -291
- package/dist/ui/Confirm.js +0 -62
- package/dist/ui/Refinement.js +0 -23
- package/dist/ui/Schedule.js +0 -257
- package/dist/ui/Task.js +0 -11
- /package/dist/{ui → components/views}/Debug.js +0 -0
- /package/dist/{ui → components/views}/Message.js +0 -0
- /package/dist/{ui → components/views}/Panel.js +0 -0
package/dist/skills/execute.md
CHANGED
|
@@ -139,6 +139,18 @@ Given tasks from this skill:
|
|
|
139
139
|
Do NOT invent different commands - use exactly what the skill specifies,
|
|
140
140
|
with parameter placeholders replaced by actual values.
|
|
141
141
|
|
|
142
|
+
### Handling Skipped Steps
|
|
143
|
+
|
|
144
|
+
**CRITICAL - STEP ORDER PRESERVATION**: When some steps from a skill are
|
|
145
|
+
omitted during scheduling, you MUST maintain alignment with the
|
|
146
|
+
original step positions in both the Steps and Execution sections. Each
|
|
147
|
+
task corresponds to a specific line number in the skill definition, NOT
|
|
148
|
+
to its sequential position in the task list. If you receive tasks for
|
|
149
|
+
steps 1 and 3 (with step 2 skipped), use Execution lines 1 and 3
|
|
150
|
+
(NOT lines 1 and 2). The step numbers in the task actions indicate
|
|
151
|
+
which Execution line to use - always match by original position, never
|
|
152
|
+
by sequential task index.
|
|
153
|
+
|
|
142
154
|
**CRITICAL - VERBATIM EXECUTION**: Run shell commands EXACTLY as written in
|
|
143
155
|
the ### Execution section. Do NOT:
|
|
144
156
|
- Modify the command string in any way
|
|
@@ -180,7 +192,6 @@ Return a structured response with commands to execute:
|
|
|
180
192
|
- **workdir**: Optional working directory for the command (defaults to
|
|
181
193
|
current)
|
|
182
194
|
- **timeout**: Optional timeout in milliseconds (defaults to 30000)
|
|
183
|
-
- **critical**: Whether failure should stop execution (defaults to true)
|
|
184
195
|
|
|
185
196
|
## Command Generation Guidelines
|
|
186
197
|
|
|
@@ -364,14 +375,12 @@ commands:
|
|
|
364
375
|
|
|
365
376
|
For complex multi-step operations:
|
|
366
377
|
|
|
367
|
-
1. **Sequential dependencies**:
|
|
368
|
-
|
|
378
|
+
1. **Sequential dependencies**: Commands execute in order; any failure stops
|
|
379
|
+
the chain
|
|
369
380
|
2. **Long-running processes**: Set appropriate timeouts (build processes
|
|
370
381
|
may need 10+ minutes)
|
|
371
382
|
3. **Working directories**: Use workdir to ensure commands run in the
|
|
372
383
|
right location
|
|
373
|
-
4. **Error handling**: For non-critical cleanup steps, set critical:
|
|
374
|
-
false
|
|
375
384
|
|
|
376
385
|
## Handling Config Placeholders
|
|
377
386
|
|
|
@@ -444,8 +453,7 @@ Before returning commands:
|
|
|
444
453
|
7. Check that all task params are incorporated
|
|
445
454
|
8. Ensure paths are properly quoted
|
|
446
455
|
9. Confirm timeouts are reasonable for each operation
|
|
447
|
-
10.
|
|
448
|
-
11. Review for any safety concerns
|
|
456
|
+
10. Review for any safety concerns
|
|
449
457
|
|
|
450
458
|
## Confirmed Schedule
|
|
451
459
|
|
|
@@ -34,10 +34,6 @@ export const executeTool = {
|
|
|
34
34
|
type: 'number',
|
|
35
35
|
description: 'Optional timeout in milliseconds. Defaults to 30000 (30 seconds).',
|
|
36
36
|
},
|
|
37
|
-
critical: {
|
|
38
|
-
type: 'boolean',
|
|
39
|
-
description: 'Whether failure should stop execution of subsequent commands. Defaults to true.',
|
|
40
|
-
},
|
|
41
37
|
},
|
|
42
38
|
required: ['description', 'command'],
|
|
43
39
|
},
|
package/dist/types/schemas.js
CHANGED
package/package.json
CHANGED
package/dist/execution/hooks.js
DELETED
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, useState, } from 'react';
|
|
2
|
-
import { ComponentStatus, } from '../types/components.js';
|
|
3
|
-
import { FeedbackType } from '../types/types.js';
|
|
4
|
-
import { createFeedback, createMessage } from '../services/components.js';
|
|
5
|
-
import { formatErrorMessage, getExecutionErrorMessage, } from '../services/messages.js';
|
|
6
|
-
import { ExecutionStatus } from '../services/shell.js';
|
|
7
|
-
import { ensureMinimumTime } from '../services/timing.js';
|
|
8
|
-
import { handleTaskCompletion, handleTaskFailure } from './handlers.js';
|
|
9
|
-
import { processTasks } from './processing.js';
|
|
10
|
-
import { executeTask } from './runner.js';
|
|
11
|
-
import { ExecuteActionType } from './types.js';
|
|
12
|
-
import { getCurrentTaskIndex } from './utils.js';
|
|
13
|
-
const ELAPSED_UPDATE_INTERVAL = 1000;
|
|
14
|
-
/**
|
|
15
|
-
* Track elapsed time from a start timestamp.
|
|
16
|
-
* Returns 0 when not active or no start time.
|
|
17
|
-
*/
|
|
18
|
-
export function useElapsedTimer(startTime, isActive) {
|
|
19
|
-
const [elapsed, setElapsed] = useState(0);
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (!startTime || !isActive)
|
|
22
|
-
return;
|
|
23
|
-
const interval = setInterval(() => {
|
|
24
|
-
setElapsed(Date.now() - startTime);
|
|
25
|
-
}, ELAPSED_UPDATE_INTERVAL);
|
|
26
|
-
return () => {
|
|
27
|
-
clearInterval(interval);
|
|
28
|
-
};
|
|
29
|
-
}, [startTime, isActive]);
|
|
30
|
-
return elapsed;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Manage live output and timing for the currently executing task.
|
|
34
|
-
* Groups related state for tracking a running task's output.
|
|
35
|
-
*/
|
|
36
|
-
export function useLiveTaskOutput() {
|
|
37
|
-
const [output, setOutput] = useState({
|
|
38
|
-
stdout: '',
|
|
39
|
-
stderr: '',
|
|
40
|
-
error: '',
|
|
41
|
-
});
|
|
42
|
-
const [startTime, setStartTime] = useState(null);
|
|
43
|
-
const start = useCallback(() => {
|
|
44
|
-
setOutput({ stdout: '', stderr: '', error: '' });
|
|
45
|
-
setStartTime(Date.now());
|
|
46
|
-
}, []);
|
|
47
|
-
const stop = useCallback(() => {
|
|
48
|
-
setStartTime(null);
|
|
49
|
-
}, []);
|
|
50
|
-
return {
|
|
51
|
-
output,
|
|
52
|
-
startTime,
|
|
53
|
-
setOutput,
|
|
54
|
-
start,
|
|
55
|
-
stop,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Handle execution cancellation with a ref-based flag.
|
|
60
|
-
* The ref is needed because callbacks check the current cancellation state.
|
|
61
|
-
*/
|
|
62
|
-
export function useCancellation() {
|
|
63
|
-
const cancelledRef = useRef(false);
|
|
64
|
-
const cancel = useCallback(() => {
|
|
65
|
-
cancelledRef.current = true;
|
|
66
|
-
}, []);
|
|
67
|
-
const reset = useCallback(() => {
|
|
68
|
-
cancelledRef.current = false;
|
|
69
|
-
}, []);
|
|
70
|
-
return {
|
|
71
|
-
cancelledRef,
|
|
72
|
-
cancel,
|
|
73
|
-
reset,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
const MINIMUM_PROCESSING_TIME = 400;
|
|
77
|
-
/**
|
|
78
|
-
* Helper to create ExecuteState with defaults
|
|
79
|
-
*/
|
|
80
|
-
function createExecuteState(overrides = {}) {
|
|
81
|
-
return {
|
|
82
|
-
message: '',
|
|
83
|
-
summary: '',
|
|
84
|
-
tasks: [],
|
|
85
|
-
completionMessage: null,
|
|
86
|
-
error: null,
|
|
87
|
-
...overrides,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Process input tasks through AI to generate executable commands.
|
|
92
|
-
* Handles the initial phase of task execution.
|
|
93
|
-
*/
|
|
94
|
-
export function useTaskProcessor(config) {
|
|
95
|
-
const { inputTasks, service, isActive, hasProcessed, tasksCount, dispatch, requestHandlers, lifecycleHandlers, workflowHandlers, } = config;
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
if (!isActive || tasksCount > 0 || hasProcessed) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
let mounted = true;
|
|
101
|
-
async function process(svc) {
|
|
102
|
-
const startTime = Date.now();
|
|
103
|
-
try {
|
|
104
|
-
const result = await processTasks(inputTasks, svc);
|
|
105
|
-
await ensureMinimumTime(startTime, MINIMUM_PROCESSING_TIME);
|
|
106
|
-
if (!mounted)
|
|
107
|
-
return;
|
|
108
|
-
// Add debug components to timeline if present
|
|
109
|
-
if (result.debug?.length) {
|
|
110
|
-
workflowHandlers.addToTimeline(...result.debug);
|
|
111
|
-
}
|
|
112
|
-
if (result.commands.length === 0) {
|
|
113
|
-
if (result.error) {
|
|
114
|
-
const errorMessage = getExecutionErrorMessage(result.error);
|
|
115
|
-
workflowHandlers.addToTimeline(createMessage({ text: errorMessage }, ComponentStatus.Done));
|
|
116
|
-
requestHandlers.onCompleted(createExecuteState({ message: result.message }));
|
|
117
|
-
lifecycleHandlers.completeActive();
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
dispatch({
|
|
121
|
-
type: ExecuteActionType.ProcessingComplete,
|
|
122
|
-
payload: { message: result.message },
|
|
123
|
-
});
|
|
124
|
-
requestHandlers.onCompleted(createExecuteState({ message: result.message }));
|
|
125
|
-
lifecycleHandlers.completeActive();
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
// Create task infos from commands
|
|
129
|
-
const taskInfos = result.commands.map((cmd, index) => ({
|
|
130
|
-
label: inputTasks[index]?.action ?? cmd.description,
|
|
131
|
-
command: cmd,
|
|
132
|
-
status: ExecutionStatus.Pending,
|
|
133
|
-
elapsed: 0,
|
|
134
|
-
}));
|
|
135
|
-
dispatch({
|
|
136
|
-
type: ExecuteActionType.CommandsReady,
|
|
137
|
-
payload: {
|
|
138
|
-
message: result.message,
|
|
139
|
-
summary: result.summary,
|
|
140
|
-
tasks: taskInfos,
|
|
141
|
-
},
|
|
142
|
-
});
|
|
143
|
-
requestHandlers.onCompleted(createExecuteState({
|
|
144
|
-
message: result.message,
|
|
145
|
-
summary: result.summary,
|
|
146
|
-
tasks: taskInfos,
|
|
147
|
-
}));
|
|
148
|
-
}
|
|
149
|
-
catch (err) {
|
|
150
|
-
await ensureMinimumTime(startTime, MINIMUM_PROCESSING_TIME);
|
|
151
|
-
if (mounted) {
|
|
152
|
-
const errorMessage = formatErrorMessage(err);
|
|
153
|
-
dispatch({
|
|
154
|
-
type: ExecuteActionType.ProcessingError,
|
|
155
|
-
payload: { error: errorMessage },
|
|
156
|
-
});
|
|
157
|
-
requestHandlers.onCompleted(createExecuteState({ error: errorMessage }));
|
|
158
|
-
requestHandlers.onError(errorMessage);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
void process(service);
|
|
163
|
-
return () => {
|
|
164
|
-
mounted = false;
|
|
165
|
-
};
|
|
166
|
-
}, [
|
|
167
|
-
inputTasks,
|
|
168
|
-
isActive,
|
|
169
|
-
service,
|
|
170
|
-
requestHandlers,
|
|
171
|
-
lifecycleHandlers,
|
|
172
|
-
workflowHandlers,
|
|
173
|
-
tasksCount,
|
|
174
|
-
hasProcessed,
|
|
175
|
-
dispatch,
|
|
176
|
-
]);
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Execute tasks sequentially, managing state and handling completion/errors.
|
|
180
|
-
*/
|
|
181
|
-
export function useTaskExecutor(config) {
|
|
182
|
-
const { isActive, tasks, message, summary, error, workdir, setWorkdir, cancelledRef, liveOutput, dispatch, requestHandlers, lifecycleHandlers, workflowHandlers, } = config;
|
|
183
|
-
const currentTaskIndex = getCurrentTaskIndex(tasks);
|
|
184
|
-
useEffect(() => {
|
|
185
|
-
if (!isActive ||
|
|
186
|
-
tasks.length === 0 ||
|
|
187
|
-
currentTaskIndex >= tasks.length ||
|
|
188
|
-
error) {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
const currentTask = tasks[currentTaskIndex];
|
|
192
|
-
if (currentTask.status !== ExecutionStatus.Pending) {
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
cancelledRef.current = false;
|
|
196
|
-
// Mark task as started (running)
|
|
197
|
-
dispatch({
|
|
198
|
-
type: ExecuteActionType.TaskStarted,
|
|
199
|
-
payload: { index: currentTaskIndex },
|
|
200
|
-
});
|
|
201
|
-
// Reset live state for new task
|
|
202
|
-
liveOutput.start();
|
|
203
|
-
// Merge workdir into command
|
|
204
|
-
const command = workdir
|
|
205
|
-
? { ...currentTask.command, workdir }
|
|
206
|
-
: currentTask.command;
|
|
207
|
-
void executeTask(command, currentTaskIndex, {
|
|
208
|
-
onOutputChange: (output) => {
|
|
209
|
-
if (!cancelledRef.current) {
|
|
210
|
-
liveOutput.setOutput(output);
|
|
211
|
-
}
|
|
212
|
-
},
|
|
213
|
-
onComplete: (elapsed, output) => {
|
|
214
|
-
if (cancelledRef.current)
|
|
215
|
-
return;
|
|
216
|
-
liveOutput.stop();
|
|
217
|
-
// Track working directory
|
|
218
|
-
if (output.workdir) {
|
|
219
|
-
setWorkdir(output.workdir);
|
|
220
|
-
}
|
|
221
|
-
const tasksWithOutput = tasks.map((task, i) => i === currentTaskIndex
|
|
222
|
-
? {
|
|
223
|
-
...task,
|
|
224
|
-
stdout: output.stdout,
|
|
225
|
-
stderr: output.stderr,
|
|
226
|
-
error: output.error,
|
|
227
|
-
}
|
|
228
|
-
: task);
|
|
229
|
-
const result = handleTaskCompletion(currentTaskIndex, elapsed, {
|
|
230
|
-
tasks: tasksWithOutput,
|
|
231
|
-
message,
|
|
232
|
-
summary,
|
|
233
|
-
});
|
|
234
|
-
dispatch(result.action);
|
|
235
|
-
requestHandlers.onCompleted(result.finalState);
|
|
236
|
-
if (result.shouldComplete) {
|
|
237
|
-
lifecycleHandlers.completeActive();
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
onError: (errorMsg, elapsed, output) => {
|
|
241
|
-
if (cancelledRef.current)
|
|
242
|
-
return;
|
|
243
|
-
liveOutput.stop();
|
|
244
|
-
// Track working directory
|
|
245
|
-
if (output.workdir) {
|
|
246
|
-
setWorkdir(output.workdir);
|
|
247
|
-
}
|
|
248
|
-
const tasksWithOutput = tasks.map((task, i) => i === currentTaskIndex
|
|
249
|
-
? {
|
|
250
|
-
...task,
|
|
251
|
-
stdout: output.stdout,
|
|
252
|
-
stderr: output.stderr,
|
|
253
|
-
error: output.error,
|
|
254
|
-
}
|
|
255
|
-
: task);
|
|
256
|
-
const result = handleTaskFailure(currentTaskIndex, errorMsg, elapsed, {
|
|
257
|
-
tasks: tasksWithOutput,
|
|
258
|
-
message,
|
|
259
|
-
summary,
|
|
260
|
-
});
|
|
261
|
-
dispatch(result.action);
|
|
262
|
-
requestHandlers.onCompleted(result.finalState);
|
|
263
|
-
if (result.action.type === ExecuteActionType.TaskErrorCritical) {
|
|
264
|
-
const criticalErrorMessage = getExecutionErrorMessage(errorMsg);
|
|
265
|
-
workflowHandlers.addToQueue(createFeedback({
|
|
266
|
-
type: FeedbackType.Failed,
|
|
267
|
-
message: criticalErrorMessage,
|
|
268
|
-
}));
|
|
269
|
-
}
|
|
270
|
-
if (result.shouldComplete) {
|
|
271
|
-
lifecycleHandlers.completeActive();
|
|
272
|
-
}
|
|
273
|
-
},
|
|
274
|
-
});
|
|
275
|
-
}, [
|
|
276
|
-
isActive,
|
|
277
|
-
tasks,
|
|
278
|
-
currentTaskIndex,
|
|
279
|
-
message,
|
|
280
|
-
summary,
|
|
281
|
-
error,
|
|
282
|
-
workdir,
|
|
283
|
-
setWorkdir,
|
|
284
|
-
cancelledRef,
|
|
285
|
-
liveOutput,
|
|
286
|
-
dispatch,
|
|
287
|
-
requestHandlers,
|
|
288
|
-
lifecycleHandlers,
|
|
289
|
-
workflowHandlers,
|
|
290
|
-
]);
|
|
291
|
-
}
|
package/dist/ui/Confirm.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { Box, Text } from 'ink';
|
|
4
|
-
import { ComponentStatus, } from '../types/components.js';
|
|
5
|
-
import { Colors, getTextColor, Palette } from '../services/colors.js';
|
|
6
|
-
import { useInput } from '../services/keyboard.js';
|
|
7
|
-
import { UserQuery } from './UserQuery.js';
|
|
8
|
-
export const ConfirmView = ({ message, state, status }) => {
|
|
9
|
-
const isActive = status === ComponentStatus.Active;
|
|
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
|
|
31
|
-
useInput((input, key) => {
|
|
32
|
-
if (!isActive)
|
|
33
|
-
return;
|
|
34
|
-
if (key.escape) {
|
|
35
|
-
// Escape: highlight "No" and cancel
|
|
36
|
-
const finalState = { selectedIndex: 1, confirmed: false };
|
|
37
|
-
requestHandlers.onCompleted(finalState);
|
|
38
|
-
onCancelled();
|
|
39
|
-
}
|
|
40
|
-
else if (key.tab) {
|
|
41
|
-
// Toggle between Yes (0) and No (1)
|
|
42
|
-
setSelectedIndex((prev) => (prev === 0 ? 1 : 0));
|
|
43
|
-
}
|
|
44
|
-
else if (key.return) {
|
|
45
|
-
// Confirm selection
|
|
46
|
-
const finalState = {
|
|
47
|
-
selectedIndex,
|
|
48
|
-
confirmed: true,
|
|
49
|
-
};
|
|
50
|
-
requestHandlers.onCompleted(finalState);
|
|
51
|
-
if (selectedIndex === 0) {
|
|
52
|
-
onConfirmed();
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
onCancelled();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}, { isActive });
|
|
59
|
-
// Controller always renders View, passing current state
|
|
60
|
-
const state = { selectedIndex, confirmed: false };
|
|
61
|
-
return _jsx(ConfirmView, { message: message, state: state, status: status });
|
|
62
|
-
}
|
package/dist/ui/Refinement.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box } from 'ink';
|
|
3
|
-
import { ComponentStatus } from '../types/components.js';
|
|
4
|
-
import { useInput } from '../services/keyboard.js';
|
|
5
|
-
import { Message } from './Message.js';
|
|
6
|
-
import { Spinner } from './Spinner.js';
|
|
7
|
-
export const RefinementView = ({ text, status }) => {
|
|
8
|
-
const isActive = status === ComponentStatus.Active;
|
|
9
|
-
return (_jsxs(Box, { gap: 1, children: [_jsx(Message, { text: text, status: status }), isActive && _jsx(Spinner, {})] }));
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Refinement controller: Handles abort input
|
|
13
|
-
*/
|
|
14
|
-
export const Refinement = ({ text, status, onAborted }) => {
|
|
15
|
-
const isActive = status === ComponentStatus.Active;
|
|
16
|
-
useInput((_, key) => {
|
|
17
|
-
if (key.escape && isActive) {
|
|
18
|
-
onAborted('plan refinement');
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
}, { isActive });
|
|
22
|
-
return _jsx(RefinementView, { text: text, status: status });
|
|
23
|
-
};
|