prompt-language-shell 0.9.0 → 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.
Files changed (64) hide show
  1. package/dist/{ui/Main.js → Main.js} +24 -17
  2. package/dist/{ui → components}/Component.js +31 -26
  3. package/dist/{ui → components}/Workflow.js +23 -7
  4. package/dist/{ui → components/controllers}/Answer.js +18 -17
  5. package/dist/{ui → components/controllers}/Command.js +21 -24
  6. package/dist/{ui → components/controllers}/Config.js +17 -119
  7. package/dist/components/controllers/Confirm.js +42 -0
  8. package/dist/components/controllers/Execute.js +288 -0
  9. package/dist/{ui → components/controllers}/Introspect.js +22 -39
  10. package/dist/components/controllers/Refinement.js +18 -0
  11. package/dist/{ui → components/controllers}/Schedule.js +8 -124
  12. package/dist/{ui → components/controllers}/Validate.js +37 -50
  13. package/dist/components/views/Answer.js +28 -0
  14. package/dist/components/views/Command.js +11 -0
  15. package/dist/components/views/Config.js +115 -0
  16. package/dist/components/views/Confirm.js +24 -0
  17. package/dist/components/views/Execute.js +60 -0
  18. package/dist/{ui → components/views}/Feedback.js +3 -3
  19. package/dist/components/views/Introspect.js +17 -0
  20. package/dist/{ui → components/views}/Label.js +3 -3
  21. package/dist/{ui → components/views}/List.js +3 -3
  22. package/dist/{ui → components/views}/Output.js +2 -2
  23. package/dist/components/views/Refinement.js +9 -0
  24. package/dist/{ui → components/views}/Report.js +1 -1
  25. package/dist/components/views/Schedule.js +120 -0
  26. package/dist/{ui → components/views}/Separator.js +1 -1
  27. package/dist/{ui → components/views}/Spinner.js +1 -1
  28. package/dist/{ui → components/views}/Subtask.js +10 -7
  29. package/dist/components/views/Task.js +18 -0
  30. package/dist/components/views/Upcoming.js +30 -0
  31. package/dist/{ui → components/views}/UserQuery.js +1 -1
  32. package/dist/components/views/Validate.js +17 -0
  33. package/dist/{ui → components/views}/Welcome.js +1 -1
  34. package/dist/{services/config-labels.js → configuration/labels.js} +1 -1
  35. package/dist/configuration/schema.js +2 -2
  36. package/dist/configuration/steps.js +171 -0
  37. package/dist/configuration/transformation.js +17 -0
  38. package/dist/execution/handlers.js +20 -60
  39. package/dist/execution/processing.js +3 -1
  40. package/dist/execution/reducer.js +34 -44
  41. package/dist/execution/runner.js +99 -0
  42. package/dist/execution/types.js +4 -4
  43. package/dist/execution/utils.js +23 -1
  44. package/dist/index.js +1 -1
  45. package/dist/services/components.js +109 -394
  46. package/dist/services/logger.js +3 -3
  47. package/dist/services/messages.js +19 -0
  48. package/dist/services/refinement.js +5 -2
  49. package/dist/services/router.js +136 -55
  50. package/dist/services/shell.js +26 -6
  51. package/dist/services/timing.js +1 -0
  52. package/dist/skills/execute.md +40 -14
  53. package/dist/tools/execute.tool.js +0 -4
  54. package/dist/types/schemas.js +0 -1
  55. package/package.json +1 -1
  56. package/dist/parser.js +0 -13
  57. package/dist/services/config-utils.js +0 -20
  58. package/dist/ui/Confirm.js +0 -62
  59. package/dist/ui/Execute.js +0 -294
  60. package/dist/ui/Refinement.js +0 -23
  61. package/dist/ui/Task.js +0 -175
  62. /package/dist/{ui → components/views}/Debug.js +0 -0
  63. /package/dist/{ui → components/views}/Message.js +0 -0
  64. /package/dist/{ui → components/views}/Panel.js +0 -0
@@ -1,294 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useReducer, useRef } from 'react';
3
- import { Box, Text } from 'ink';
4
- import { ComponentStatus, } from '../types/components.js';
5
- import { getTextColor } from '../services/colors.js';
6
- import { useInput } from '../services/keyboard.js';
7
- import { formatErrorMessage, getExecutionErrorMessage, } from '../services/messages.js';
8
- import { ExecutionStatus } from '../services/shell.js';
9
- import { ensureMinimumTime } from '../services/timing.js';
10
- import { buildAbortedState, handleTaskCompletion, handleTaskFailure, } from '../execution/handlers.js';
11
- import { processTasks } from '../execution/processing.js';
12
- import { executeReducer, initialState } from '../execution/reducer.js';
13
- import { ExecuteActionType } from '../execution/types.js';
14
- import { createFeedback, createMessage, markAsDone, } from '../services/components.js';
15
- import { FeedbackType } from '../types/types.js';
16
- import { Message } from './Message.js';
17
- import { Spinner } from './Spinner.js';
18
- import { Task } from './Task.js';
19
- const MINIMUM_PROCESSING_TIME = 400;
20
- /**
21
- * Create an ExecuteState with defaults
22
- */
23
- function createExecuteState(overrides = {}) {
24
- return {
25
- message: '',
26
- summary: '',
27
- tasks: [],
28
- completed: 0,
29
- completionMessage: null,
30
- error: null,
31
- ...overrides,
32
- };
33
- }
34
- export const ExecuteView = ({ state, status, workdir, onOutputChange, onTaskComplete, onTaskAbort, onTaskError, }) => {
35
- const isActive = status === ComponentStatus.Active;
36
- const { error, tasks, message, completed, completionMessage } = state;
37
- const hasProcessed = tasks.length > 0;
38
- // Derive loading state from current conditions
39
- const isLoading = isActive && tasks.length === 0 && !error && !hasProcessed;
40
- const isExecuting = completed < tasks.length;
41
- // Return null only when loading completes with no commands
42
- if (!isActive && tasks.length === 0 && !error) {
43
- return null;
44
- }
45
- // Show completed steps when not active
46
- const showTasks = !isActive && tasks.length > 0;
47
- return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isLoading && (_jsxs(Box, { marginLeft: 1, children: [_jsx(Text, { color: getTextColor(isActive), children: "Preparing commands. " }), _jsx(Spinner, {})] })), (isExecuting || showTasks) && (_jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [message && (_jsxs(Box, { marginBottom: 1, gap: 1, children: [_jsx(Text, { color: getTextColor(isActive), children: message }), isExecuting && _jsx(Spinner, {})] })), tasks.map((taskInfo, index) => {
48
- // Merge workdir into active task's command
49
- const taskCommand = isActive && index === completed && workdir
50
- ? { ...taskInfo.command, workdir }
51
- : taskInfo.command;
52
- return (_jsx(Box, { marginBottom: index < tasks.length - 1 ? 1 : 0, children: _jsx(Task, { label: taskInfo.label, command: taskCommand, isActive: isActive && index === completed, isFinished: index < completed, index: index, initialStatus: taskInfo.status, initialElapsed: taskInfo.elapsed, initialOutput: taskInfo.stdout || taskInfo.stderr || taskInfo.error
53
- ? {
54
- stdout: taskInfo.stdout ?? '',
55
- stderr: taskInfo.stderr ?? '',
56
- error: taskInfo.error ?? '',
57
- }
58
- : undefined, onOutputChange: onOutputChange, onComplete: onTaskComplete, onAbort: onTaskAbort, onError: onTaskError }) }, index));
59
- })] })), completionMessage && !isActive && (_jsx(Box, { marginTop: 1, marginLeft: 1, children: _jsx(Text, { color: getTextColor(false), children: completionMessage }) })), error && _jsx(Message, { text: error, status: status })] }));
60
- };
61
- /**
62
- * Execute controller: Runs tasks sequentially
63
- */
64
- export function Execute({ tasks: inputTasks, status, service, requestHandlers, lifecycleHandlers, workflowHandlers, }) {
65
- const isActive = status === ComponentStatus.Active;
66
- const [localState, dispatch] = useReducer(executeReducer, initialState);
67
- // Ref to store current output for each task (avoids re-renders)
68
- const taskOutputRef = useRef(new Map());
69
- // Track working directory across commands (persists cd changes)
70
- const workdirRef = useRef(undefined);
71
- const { error, tasks, message, completed, hasProcessed, completionMessage, summary, } = localState;
72
- // Derive loading state from current conditions
73
- const isLoading = isActive && tasks.length === 0 && !error && !hasProcessed;
74
- const isExecuting = completed < tasks.length;
75
- // Handle output changes from Task - store in ref (no re-render)
76
- const handleOutputChange = useCallback((index, taskOutput) => {
77
- taskOutputRef.current.set(index, taskOutput);
78
- }, []);
79
- // Handle cancel with useCallback to ensure we capture latest state
80
- const handleCancel = useCallback(() => {
81
- dispatch({
82
- type: ExecuteActionType.CancelExecution,
83
- payload: { completed },
84
- });
85
- // Get updated task infos after cancel, merging output from ref
86
- const updatedTaskInfos = tasks.map((task, taskIndex) => {
87
- const output = taskOutputRef.current.get(taskIndex);
88
- const baseTask = output
89
- ? {
90
- ...task,
91
- stdout: output.stdout,
92
- stderr: output.stderr,
93
- error: output.error,
94
- }
95
- : task;
96
- if (taskIndex < completed) {
97
- return { ...baseTask, status: ExecutionStatus.Success };
98
- }
99
- else if (taskIndex === completed) {
100
- return { ...baseTask, status: ExecutionStatus.Aborted };
101
- }
102
- else {
103
- return { ...baseTask, status: ExecutionStatus.Cancelled };
104
- }
105
- });
106
- // Expose final state
107
- const finalState = createExecuteState({
108
- message,
109
- summary,
110
- tasks: updatedTaskInfos,
111
- completed,
112
- });
113
- requestHandlers.onCompleted(finalState);
114
- requestHandlers.onAborted('execution');
115
- }, [message, summary, tasks, completed, requestHandlers]);
116
- useInput((_, key) => {
117
- if (key.escape && (isLoading || isExecuting) && isActive) {
118
- handleCancel();
119
- }
120
- }, { isActive: (isLoading || isExecuting) && isActive });
121
- // Process tasks to get commands from AI
122
- useEffect(() => {
123
- if (!isActive || tasks.length > 0 || hasProcessed) {
124
- return;
125
- }
126
- let mounted = true;
127
- async function process(svc) {
128
- const startTime = Date.now();
129
- try {
130
- const result = await processTasks(inputTasks, svc);
131
- await ensureMinimumTime(startTime, MINIMUM_PROCESSING_TIME);
132
- if (!mounted)
133
- return;
134
- // Add debug components to timeline if present
135
- if (result.debug?.length) {
136
- workflowHandlers.addToTimeline(...result.debug);
137
- }
138
- if (result.commands.length === 0) {
139
- // Check if this is an error response (has error field)
140
- if (result.error) {
141
- // Add error message to timeline
142
- const errorMessage = getExecutionErrorMessage(result.error);
143
- workflowHandlers.addToTimeline(markAsDone(createMessage(errorMessage)));
144
- // Complete without error in state (message already in timeline)
145
- requestHandlers.onCompleted(createExecuteState({ message: result.message }));
146
- lifecycleHandlers.completeActive();
147
- return;
148
- }
149
- // No commands and no error - just complete
150
- dispatch({
151
- type: ExecuteActionType.ProcessingComplete,
152
- payload: { message: result.message },
153
- });
154
- requestHandlers.onCompleted(createExecuteState({ message: result.message }));
155
- lifecycleHandlers.completeActive();
156
- return;
157
- }
158
- // Create task infos from commands
159
- const tasks = result.commands.map((cmd, index) => ({
160
- label: inputTasks[index]?.action ?? cmd.description,
161
- command: cmd,
162
- status: ExecutionStatus.Pending,
163
- elapsed: 0,
164
- }));
165
- dispatch({
166
- type: ExecuteActionType.CommandsReady,
167
- payload: {
168
- message: result.message,
169
- summary: result.summary,
170
- tasks,
171
- },
172
- });
173
- // Update state after AI processing
174
- requestHandlers.onCompleted(createExecuteState({
175
- message: result.message,
176
- summary: result.summary,
177
- tasks,
178
- }));
179
- }
180
- catch (err) {
181
- await ensureMinimumTime(startTime, MINIMUM_PROCESSING_TIME);
182
- if (mounted) {
183
- const errorMessage = formatErrorMessage(err);
184
- dispatch({
185
- type: ExecuteActionType.ProcessingError,
186
- payload: { error: errorMessage },
187
- });
188
- requestHandlers.onCompleted(createExecuteState({ error: errorMessage }));
189
- requestHandlers.onError(errorMessage);
190
- }
191
- }
192
- }
193
- void process(service);
194
- return () => {
195
- mounted = false;
196
- };
197
- }, [
198
- inputTasks,
199
- isActive,
200
- service,
201
- requestHandlers,
202
- lifecycleHandlers,
203
- workflowHandlers,
204
- tasks.length,
205
- hasProcessed,
206
- ]);
207
- // Handle task completion - move to next task
208
- const handleTaskComplete = useCallback((index, elapsed, taskOutput) => {
209
- // Track working directory for subsequent commands
210
- if (taskOutput.workdir) {
211
- workdirRef.current = taskOutput.workdir;
212
- }
213
- // Update tasks with output before calling handler
214
- const tasksWithOutput = tasks.map((task, i) => i === index
215
- ? {
216
- ...task,
217
- stdout: taskOutput.stdout,
218
- stderr: taskOutput.stderr,
219
- error: taskOutput.error,
220
- }
221
- : task);
222
- const result = handleTaskCompletion(index, elapsed, {
223
- tasks: tasksWithOutput,
224
- message,
225
- summary,
226
- });
227
- dispatch(result.action);
228
- requestHandlers.onCompleted(result.finalState);
229
- if (result.shouldComplete) {
230
- lifecycleHandlers.completeActive();
231
- }
232
- }, [tasks, message, summary, requestHandlers, lifecycleHandlers]);
233
- const handleTaskError = useCallback((index, error, elapsed, taskOutput) => {
234
- // Track working directory for subsequent commands (even on error)
235
- if (taskOutput.workdir) {
236
- workdirRef.current = taskOutput.workdir;
237
- }
238
- // Update tasks with output before calling handler
239
- const tasksWithOutput = tasks.map((task, i) => i === index
240
- ? {
241
- ...task,
242
- stdout: taskOutput.stdout,
243
- stderr: taskOutput.stderr,
244
- error: taskOutput.error,
245
- }
246
- : task);
247
- const result = handleTaskFailure(index, error, elapsed, {
248
- tasks: tasksWithOutput,
249
- message,
250
- summary,
251
- });
252
- dispatch(result.action);
253
- requestHandlers.onCompleted(result.finalState);
254
- // Add error feedback to queue for critical failures
255
- if (result.action.type === ExecuteActionType.TaskErrorCritical) {
256
- const errorMessage = getExecutionErrorMessage(error);
257
- workflowHandlers.addToQueue(createFeedback(FeedbackType.Failed, errorMessage));
258
- }
259
- if (result.shouldComplete) {
260
- lifecycleHandlers.completeActive();
261
- }
262
- }, [
263
- tasks,
264
- message,
265
- summary,
266
- requestHandlers,
267
- lifecycleHandlers,
268
- workflowHandlers,
269
- ]);
270
- const handleTaskAbort = useCallback((index, taskOutput) => {
271
- // Task was aborted - execution already stopped by Escape handler
272
- // Update tasks with output before building state
273
- const tasksWithOutput = tasks.map((task, i) => i === index
274
- ? {
275
- ...task,
276
- stdout: taskOutput.stdout,
277
- stderr: taskOutput.stderr,
278
- error: taskOutput.error,
279
- }
280
- : task);
281
- const finalState = buildAbortedState(tasksWithOutput, message, summary, completed);
282
- requestHandlers.onCompleted(finalState);
283
- }, [tasks, message, summary, completed, requestHandlers]);
284
- // Controller always renders View with current state
285
- const viewState = createExecuteState({
286
- error,
287
- tasks,
288
- message,
289
- summary,
290
- completed,
291
- completionMessage,
292
- });
293
- return (_jsx(ExecuteView, { state: viewState, status: status, workdir: workdirRef.current, onOutputChange: handleOutputChange, onTaskComplete: handleTaskComplete, onTaskAbort: handleTaskAbort, onTaskError: handleTaskError }));
294
- }
@@ -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
- };
package/dist/ui/Task.js DELETED
@@ -1,175 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from 'react';
3
- import { Box } from 'ink';
4
- import { ExecutionResult, ExecutionStatus, executeCommand, setOutputCallback, } from '../services/shell.js';
5
- import { calculateElapsed } from '../services/utils.js';
6
- import { Output } from './Output.js';
7
- import { Subtask } from './Subtask.js';
8
- export function Task({ label, command, isActive, isFinished, index, initialStatus, initialElapsed, initialOutput, onOutputChange, onComplete, onAbort, onError, }) {
9
- const [status, setStatus] = useState(initialStatus ?? ExecutionStatus.Pending);
10
- const [startTime, setStartTime] = useState();
11
- const [endTime, setEndTime] = useState();
12
- const [elapsed, setElapsed] = useState(initialElapsed);
13
- const [currentElapsed, setCurrentElapsed] = useState(0);
14
- const [stdout, setStdout] = useState(initialOutput?.stdout ?? '');
15
- const [stderr, setStderr] = useState(initialOutput?.stderr ?? '');
16
- const [error, setError] = useState(initialOutput?.error ?? '');
17
- // Refs to track current output for callbacks (avoid stale closure)
18
- const stdoutRef = useRef(stdout);
19
- const stderrRef = useRef(stderr);
20
- const errorRef = useRef(error);
21
- stdoutRef.current = stdout;
22
- stderrRef.current = stderr;
23
- errorRef.current = error;
24
- // Refs for callbacks to avoid stale closures in async effects
25
- const onOutputChangeRef = useRef(onOutputChange);
26
- const onCompleteRef = useRef(onComplete);
27
- const onErrorRef = useRef(onError);
28
- const onAbortRef = useRef(onAbort);
29
- onOutputChangeRef.current = onOutputChange;
30
- onCompleteRef.current = onComplete;
31
- onErrorRef.current = onError;
32
- onAbortRef.current = onAbort;
33
- // Update elapsed time while running
34
- useEffect(() => {
35
- if (status !== ExecutionStatus.Running || !startTime)
36
- return;
37
- const interval = setInterval(() => {
38
- setCurrentElapsed((prev) => {
39
- const next = Date.now() - startTime;
40
- return next !== prev ? next : prev;
41
- });
42
- }, 1000);
43
- return () => {
44
- clearInterval(interval);
45
- };
46
- }, [status, startTime]);
47
- // Execute command when becoming active
48
- useEffect(() => {
49
- // Don't execute if task is cancelled or if not active
50
- if (!isActive ||
51
- status === ExecutionStatus.Cancelled ||
52
- status !== ExecutionStatus.Pending) {
53
- return;
54
- }
55
- let mounted = true;
56
- async function execute() {
57
- const start = Date.now();
58
- setStatus(ExecutionStatus.Running);
59
- setStartTime(start);
60
- setCurrentElapsed(0);
61
- setStdout('');
62
- setStderr('');
63
- setError('');
64
- // Set up output callback to capture real-time output
65
- setOutputCallback((data, stream) => {
66
- if (!mounted)
67
- return;
68
- if (stream === 'stdout') {
69
- setStdout((prev) => {
70
- const newStdout = prev + data;
71
- stdoutRef.current = newStdout;
72
- // Report output change to parent using refs for current values
73
- onOutputChangeRef.current?.(index, {
74
- stdout: newStdout,
75
- stderr: stderrRef.current,
76
- error: errorRef.current,
77
- });
78
- return newStdout;
79
- });
80
- }
81
- else {
82
- setStderr((prev) => {
83
- const newStderr = prev + data;
84
- stderrRef.current = newStderr;
85
- // Report output change to parent using refs for current values
86
- onOutputChangeRef.current?.(index, {
87
- stdout: stdoutRef.current,
88
- stderr: newStderr,
89
- error: errorRef.current,
90
- });
91
- return newStderr;
92
- });
93
- }
94
- });
95
- try {
96
- const output = await executeCommand(command, undefined, index);
97
- setOutputCallback(undefined); // Clear callback
98
- if (!mounted)
99
- return;
100
- const end = Date.now();
101
- setEndTime(end);
102
- const taskDuration = calculateElapsed(start);
103
- setElapsed(taskDuration);
104
- setStatus(output.result === ExecutionResult.Success
105
- ? ExecutionStatus.Success
106
- : ExecutionStatus.Failed);
107
- if (output.result === ExecutionResult.Success) {
108
- const taskOutput = {
109
- stdout: output.output,
110
- stderr: output.errors,
111
- error: '',
112
- workdir: output.workdir,
113
- };
114
- onCompleteRef.current?.(index, taskDuration, taskOutput);
115
- }
116
- else {
117
- const errorMsg = output.errors || output.error || 'Command failed';
118
- setError(errorMsg);
119
- const taskOutput = {
120
- stdout: output.output,
121
- stderr: output.errors,
122
- error: errorMsg,
123
- workdir: output.workdir,
124
- };
125
- onErrorRef.current?.(index, errorMsg, taskDuration, taskOutput);
126
- }
127
- }
128
- catch (err) {
129
- setOutputCallback(undefined); // Clear callback
130
- if (!mounted)
131
- return;
132
- const end = Date.now();
133
- setEndTime(end);
134
- const errorDuration = calculateElapsed(start);
135
- setElapsed(errorDuration);
136
- setStatus(ExecutionStatus.Failed);
137
- const errorMsg = err instanceof Error ? err.message : 'Unknown error';
138
- setError(errorMsg);
139
- const taskOutput = {
140
- stdout: stdoutRef.current,
141
- stderr: stderrRef.current,
142
- error: errorMsg,
143
- };
144
- // Use try/catch to prevent callback errors from propagating
145
- try {
146
- onErrorRef.current?.(index, errorMsg, errorDuration, taskOutput);
147
- }
148
- catch {
149
- // Callback error - already set error state above
150
- }
151
- }
152
- }
153
- void execute();
154
- return () => {
155
- mounted = false;
156
- };
157
- }, [isActive]);
158
- // Handle abort when task becomes inactive while running
159
- useEffect(() => {
160
- if (!isActive && status === ExecutionStatus.Running && startTime) {
161
- // Task was aborted mid-execution
162
- const end = Date.now();
163
- setEndTime(end);
164
- setElapsed(calculateElapsed(startTime));
165
- setStatus(ExecutionStatus.Aborted);
166
- const taskOutput = {
167
- stdout: stdoutRef.current,
168
- stderr: stderrRef.current,
169
- error: errorRef.current,
170
- };
171
- onAbortRef.current?.(index, taskOutput);
172
- }
173
- }, [isActive, status, startTime, index]);
174
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Subtask, { label: label, command: command, status: status, isActive: isActive, startTime: startTime, endTime: endTime, elapsed: status === ExecutionStatus.Running ? currentElapsed : elapsed }), _jsx(Output, { stdout: stdout, stderr: stderr, isFinished: isFinished, status: status }, `${stdout.length}-${stderr.length}`)] }));
175
- }
File without changes
File without changes
File without changes