prompt-language-shell 0.3.0 → 0.3.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/config/PLAN.md +103 -54
- package/dist/index.js +2 -25
- package/dist/services/components.js +104 -0
- package/dist/services/config.js +63 -12
- package/dist/services/process.js +6 -0
- package/dist/types/components.js +11 -0
- package/dist/ui/Column.js +1 -1
- package/dist/ui/Command.js +2 -72
- package/dist/ui/Component.js +12 -5
- package/dist/ui/Config.js +169 -10
- package/dist/ui/Feedback.js +15 -4
- package/dist/ui/List.js +16 -2
- package/dist/ui/Main.js +145 -117
- package/dist/ui/Message.js +5 -0
- package/dist/ui/Plan.js +194 -0
- package/package.json +2 -1
package/dist/ui/Main.js
CHANGED
|
@@ -1,133 +1,161 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { ComponentName, TaskType, } from '../types/components.js';
|
|
4
|
+
import { createAnthropicService, } from '../services/anthropic.js';
|
|
3
5
|
import { FeedbackType } from '../types/components.js';
|
|
6
|
+
import { getConfigurationRequiredMessage, hasValidAnthropicKey, loadConfig, saveAnthropicConfig, } from '../services/config.js';
|
|
7
|
+
import { createCommandDefinition, createConfigDefinition, createFeedback, createMessage, createPlanDefinition, createWelcomeDefinition, isStateless, markAsDone, } from '../services/components.js';
|
|
8
|
+
import { exitApp } from '../services/process.js';
|
|
4
9
|
import { Column } from './Column.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function createWelcomeDefinition(app) {
|
|
12
|
-
return {
|
|
13
|
-
name: 'welcome',
|
|
14
|
-
props: { app },
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
function createConfigSteps() {
|
|
18
|
-
return [
|
|
19
|
-
{ description: 'Anthropic API key', key: 'key', value: null },
|
|
20
|
-
{
|
|
21
|
-
description: 'Model',
|
|
22
|
-
key: 'model',
|
|
23
|
-
value: 'claude-haiku-4-5-20251001',
|
|
24
|
-
},
|
|
25
|
-
];
|
|
26
|
-
}
|
|
27
|
-
function createConfigDefinition(onFinished, onAborted) {
|
|
28
|
-
return {
|
|
29
|
-
name: 'config',
|
|
30
|
-
state: { done: false },
|
|
31
|
-
props: {
|
|
32
|
-
steps: createConfigSteps(),
|
|
33
|
-
onFinished,
|
|
34
|
-
onAborted,
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function createCommandDefinition(command, service, onError, onComplete) {
|
|
39
|
-
return {
|
|
40
|
-
name: 'command',
|
|
41
|
-
state: {
|
|
42
|
-
done: false,
|
|
43
|
-
isLoading: true,
|
|
44
|
-
},
|
|
45
|
-
props: {
|
|
46
|
-
command,
|
|
47
|
-
service,
|
|
48
|
-
onError,
|
|
49
|
-
onComplete,
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function createFeedback(type, ...messages) {
|
|
54
|
-
return {
|
|
55
|
-
name: 'feedback',
|
|
56
|
-
props: {
|
|
57
|
-
type,
|
|
58
|
-
message: messages.join('\n\n'),
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
export const Main = ({ app, command, service: initialService, isReady, onConfigured, }) => {
|
|
63
|
-
const [history, setHistory] = React.useState([]);
|
|
64
|
-
const [current, setCurrent] = React.useState(null);
|
|
65
|
-
const [service, setService] = React.useState(initialService);
|
|
66
|
-
const addToHistory = React.useCallback((...items) => {
|
|
67
|
-
setHistory((history) => [...history, ...items]);
|
|
68
|
-
}, []);
|
|
69
|
-
const handleConfigFinished = React.useCallback((config) => {
|
|
70
|
-
const service = onConfigured?.(config);
|
|
71
|
-
if (service) {
|
|
72
|
-
setService(service);
|
|
10
|
+
export const Main = ({ app, command }) => {
|
|
11
|
+
// Initialize service from existing config if available
|
|
12
|
+
const [service, setService] = React.useState(() => {
|
|
13
|
+
if (hasValidAnthropicKey()) {
|
|
14
|
+
const config = loadConfig();
|
|
15
|
+
return createAnthropicService(config.anthropic);
|
|
73
16
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
17
|
+
return null;
|
|
18
|
+
});
|
|
19
|
+
const [timeline, setTimeline] = React.useState([]);
|
|
20
|
+
const [queue, setQueue] = React.useState([]);
|
|
21
|
+
const addToTimeline = React.useCallback((...items) => {
|
|
22
|
+
setTimeline((timeline) => [...timeline, ...items]);
|
|
23
|
+
}, []);
|
|
24
|
+
const processNextInQueue = React.useCallback(() => {
|
|
25
|
+
setQueue((currentQueue) => {
|
|
26
|
+
if (currentQueue.length === 0)
|
|
27
|
+
return currentQueue;
|
|
28
|
+
const [first, ...rest] = currentQueue;
|
|
29
|
+
// Stateless components auto-complete immediately
|
|
30
|
+
if (isStateless(first)) {
|
|
31
|
+
addToTimeline(first);
|
|
32
|
+
return rest;
|
|
33
|
+
}
|
|
34
|
+
return currentQueue;
|
|
89
35
|
});
|
|
90
|
-
}, [
|
|
36
|
+
}, [addToTimeline]);
|
|
91
37
|
const handleCommandError = React.useCallback((error) => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
38
|
+
setQueue((currentQueue) => {
|
|
39
|
+
if (currentQueue.length === 0)
|
|
40
|
+
return currentQueue;
|
|
41
|
+
const [first] = currentQueue;
|
|
42
|
+
if (first.name === ComponentName.Command) {
|
|
43
|
+
addToTimeline(markAsDone(first), createFeedback(FeedbackType.Failed, 'Unexpected error occurred:', error));
|
|
44
|
+
}
|
|
45
|
+
exitApp(1);
|
|
46
|
+
return [];
|
|
47
|
+
});
|
|
48
|
+
}, [addToTimeline]);
|
|
49
|
+
const handlePlanSelectionConfirmed = React.useCallback((selectedIndex, updatedTasks) => {
|
|
50
|
+
setQueue((currentQueue) => {
|
|
51
|
+
if (currentQueue.length === 0)
|
|
52
|
+
return currentQueue;
|
|
53
|
+
const [first] = currentQueue;
|
|
54
|
+
if (first.name === ComponentName.Plan) {
|
|
55
|
+
// Mark plan as done and add it to timeline
|
|
56
|
+
addToTimeline(markAsDone(first));
|
|
57
|
+
}
|
|
58
|
+
// Exit after selection is confirmed
|
|
59
|
+
exitApp(0);
|
|
60
|
+
return [];
|
|
98
61
|
});
|
|
99
|
-
}, [
|
|
100
|
-
const handleCommandComplete = React.useCallback(() => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
62
|
+
}, [addToTimeline]);
|
|
63
|
+
const handleCommandComplete = React.useCallback((message, tasks) => {
|
|
64
|
+
setQueue((currentQueue) => {
|
|
65
|
+
if (currentQueue.length === 0)
|
|
66
|
+
return currentQueue;
|
|
67
|
+
const [first] = currentQueue;
|
|
68
|
+
// Check if tasks contain a Define task that requires user interaction
|
|
69
|
+
const hasDefineTask = tasks.some((task) => task.type === TaskType.Define);
|
|
70
|
+
if (first.name === ComponentName.Command) {
|
|
71
|
+
const planDefinition = createPlanDefinition(message, tasks, hasDefineTask ? handlePlanSelectionConfirmed : undefined);
|
|
72
|
+
if (hasDefineTask) {
|
|
73
|
+
// Don't exit - keep the plan in the queue for interaction
|
|
74
|
+
addToTimeline(markAsDone(first));
|
|
75
|
+
return [planDefinition];
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// No define task - add plan to timeline and exit
|
|
79
|
+
addToTimeline(markAsDone(first), planDefinition);
|
|
80
|
+
exitApp(0);
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exitApp(0);
|
|
85
|
+
return [];
|
|
107
86
|
});
|
|
108
|
-
}, [
|
|
109
|
-
|
|
87
|
+
}, [addToTimeline, handlePlanSelectionConfirmed]);
|
|
88
|
+
const handleConfigFinished = React.useCallback((config) => {
|
|
89
|
+
const anthropicConfig = config;
|
|
90
|
+
saveAnthropicConfig(anthropicConfig);
|
|
91
|
+
const newService = createAnthropicService(anthropicConfig);
|
|
92
|
+
setService(newService);
|
|
93
|
+
// Complete config component and add command if present
|
|
94
|
+
setQueue((currentQueue) => {
|
|
95
|
+
if (currentQueue.length === 0)
|
|
96
|
+
return currentQueue;
|
|
97
|
+
const [first, ...rest] = currentQueue;
|
|
98
|
+
if (first.name === ComponentName.Config) {
|
|
99
|
+
addToTimeline(markAsDone(first), createFeedback(FeedbackType.Succeeded, 'Configuration complete'));
|
|
100
|
+
}
|
|
101
|
+
// Add command to queue if we have one
|
|
102
|
+
if (command) {
|
|
103
|
+
return [
|
|
104
|
+
...rest,
|
|
105
|
+
createCommandDefinition(command, newService, handleCommandError, handleCommandComplete),
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
// No command - exit after showing completion message
|
|
109
|
+
exitApp(0);
|
|
110
|
+
return rest;
|
|
111
|
+
});
|
|
112
|
+
}, [addToTimeline, command, handleCommandError, handleCommandComplete]);
|
|
113
|
+
const handleConfigAborted = React.useCallback(() => {
|
|
114
|
+
setQueue((currentQueue) => {
|
|
115
|
+
if (currentQueue.length === 0)
|
|
116
|
+
return currentQueue;
|
|
117
|
+
const [first] = currentQueue;
|
|
118
|
+
if (first.name === ComponentName.Config) {
|
|
119
|
+
addToTimeline(markAsDone(first), createFeedback(FeedbackType.Aborted, 'Configuration aborted by user'));
|
|
120
|
+
}
|
|
121
|
+
exitApp(0);
|
|
122
|
+
return [];
|
|
123
|
+
});
|
|
124
|
+
}, [addToTimeline]);
|
|
125
|
+
// Initialize queue on mount
|
|
110
126
|
React.useEffect(() => {
|
|
111
|
-
|
|
112
|
-
|
|
127
|
+
const hasConfig = !!service;
|
|
128
|
+
if (command && hasConfig) {
|
|
129
|
+
// With command + valid config: [Command]
|
|
130
|
+
setQueue([
|
|
131
|
+
createCommandDefinition(command, service, handleCommandError, handleCommandComplete),
|
|
132
|
+
]);
|
|
113
133
|
}
|
|
114
|
-
if (!
|
|
115
|
-
|
|
134
|
+
else if (command && !hasConfig) {
|
|
135
|
+
// With command + no config: [Message, Config] (Command added after config)
|
|
136
|
+
setQueue([
|
|
137
|
+
createMessage(getConfigurationRequiredMessage()),
|
|
138
|
+
createConfigDefinition(handleConfigFinished, handleConfigAborted),
|
|
139
|
+
]);
|
|
116
140
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
React.useEffect(() => {
|
|
121
|
-
if (command && service) {
|
|
122
|
-
setCurrent(createCommandDefinition(command, service, handleCommandError, handleCommandComplete));
|
|
141
|
+
else if (!command && hasConfig) {
|
|
142
|
+
// No command + valid config: [Welcome]
|
|
143
|
+
setQueue([createWelcomeDefinition(app)]);
|
|
123
144
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
145
|
+
else {
|
|
146
|
+
// No command + no config: [Welcome, Message, Config]
|
|
147
|
+
setQueue([
|
|
148
|
+
createWelcomeDefinition(app),
|
|
149
|
+
createMessage(getConfigurationRequiredMessage(true)),
|
|
150
|
+
createConfigDefinition(handleConfigFinished, handleConfigAborted),
|
|
151
|
+
]);
|
|
129
152
|
}
|
|
130
|
-
}, [
|
|
131
|
-
|
|
153
|
+
}, []); // Only run on mount
|
|
154
|
+
// Process queue whenever it changes
|
|
155
|
+
React.useEffect(() => {
|
|
156
|
+
processNextInQueue();
|
|
157
|
+
}, [queue, processNextInQueue]);
|
|
158
|
+
const current = queue.length > 0 ? queue[0] : null;
|
|
159
|
+
const items = [...timeline, ...(current ? [current] : [])];
|
|
132
160
|
return _jsx(Column, { items: items });
|
|
133
161
|
};
|
package/dist/ui/Plan.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { Box, useInput } from 'ink';
|
|
4
|
+
import { TaskType } from '../types/components.js';
|
|
5
|
+
import { Label } from './Label.js';
|
|
6
|
+
import { List } from './List.js';
|
|
7
|
+
const ColorPalette = {
|
|
8
|
+
[TaskType.Config]: {
|
|
9
|
+
description: '#ffffff', // white
|
|
10
|
+
type: '#5c9ccc', // cyan
|
|
11
|
+
},
|
|
12
|
+
[TaskType.Plan]: {
|
|
13
|
+
description: '#ffffff', // white
|
|
14
|
+
type: '#5ccccc', // magenta
|
|
15
|
+
},
|
|
16
|
+
[TaskType.Execute]: {
|
|
17
|
+
description: '#ffffff', // white
|
|
18
|
+
type: '#4a9a7a', // green
|
|
19
|
+
},
|
|
20
|
+
[TaskType.Answer]: {
|
|
21
|
+
description: '#ffffff', // white
|
|
22
|
+
type: '#9c5ccc', // purple
|
|
23
|
+
},
|
|
24
|
+
[TaskType.Report]: {
|
|
25
|
+
description: '#ffffff', // white
|
|
26
|
+
type: '#cc9c5c', // orange
|
|
27
|
+
},
|
|
28
|
+
[TaskType.Define]: {
|
|
29
|
+
description: '#ffffff', // white
|
|
30
|
+
type: '#cc9c5c', // amber
|
|
31
|
+
},
|
|
32
|
+
[TaskType.Ignore]: {
|
|
33
|
+
description: '#cccc5c', // yellow
|
|
34
|
+
type: '#cc7a5c', // orange
|
|
35
|
+
},
|
|
36
|
+
[TaskType.Select]: {
|
|
37
|
+
description: '#888888', // grey
|
|
38
|
+
type: '#5c8cbc', // steel blue
|
|
39
|
+
},
|
|
40
|
+
[TaskType.Discard]: {
|
|
41
|
+
description: '#666666', // dark grey
|
|
42
|
+
type: '#a85c3f', // dark orange
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
function taskToListItem(task, highlightedChildIndex = null, isDefineTaskWithoutSelection = false) {
|
|
46
|
+
const item = {
|
|
47
|
+
description: {
|
|
48
|
+
text: task.action,
|
|
49
|
+
color: ColorPalette[task.type].description,
|
|
50
|
+
},
|
|
51
|
+
type: { text: task.type, color: ColorPalette[task.type].type },
|
|
52
|
+
children: [],
|
|
53
|
+
};
|
|
54
|
+
// Mark define tasks with right arrow when no selection has been made
|
|
55
|
+
if (isDefineTaskWithoutSelection) {
|
|
56
|
+
item.marker = ' → ';
|
|
57
|
+
}
|
|
58
|
+
// Add children for Define tasks with options
|
|
59
|
+
if (task.type === TaskType.Define && Array.isArray(task.params?.options)) {
|
|
60
|
+
item.children = task.params.options.map((option, index) => {
|
|
61
|
+
// Determine the type based on selection state
|
|
62
|
+
let childType = TaskType.Select;
|
|
63
|
+
if (highlightedChildIndex !== null) {
|
|
64
|
+
// A selection was made - mark others as discarded
|
|
65
|
+
childType =
|
|
66
|
+
index === highlightedChildIndex ? TaskType.Execute : TaskType.Discard;
|
|
67
|
+
}
|
|
68
|
+
const colors = ColorPalette[childType];
|
|
69
|
+
return {
|
|
70
|
+
description: {
|
|
71
|
+
text: String(option),
|
|
72
|
+
color: colors.description,
|
|
73
|
+
highlightedColor: ColorPalette[TaskType.Plan].description,
|
|
74
|
+
},
|
|
75
|
+
type: {
|
|
76
|
+
text: childType,
|
|
77
|
+
color: colors.type,
|
|
78
|
+
highlightedColor: ColorPalette[TaskType.Plan].type,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return item;
|
|
84
|
+
}
|
|
85
|
+
export function Plan({ message, tasks, state, onSelectionConfirmed, }) {
|
|
86
|
+
const [highlightedIndex, setHighlightedIndex] = useState(state?.highlightedIndex ?? null);
|
|
87
|
+
const [currentDefineGroupIndex, setCurrentDefineGroupIndex] = useState(state?.currentDefineGroupIndex ?? 0);
|
|
88
|
+
const [completedSelections, setCompletedSelections] = useState(state?.completedSelections ?? []);
|
|
89
|
+
const [isDone, setIsDone] = useState(state?.done ?? false);
|
|
90
|
+
// Find all Define tasks
|
|
91
|
+
const defineTaskIndices = tasks
|
|
92
|
+
.map((t, idx) => (t.type === TaskType.Define ? idx : -1))
|
|
93
|
+
.filter((idx) => idx !== -1);
|
|
94
|
+
// Get the current active define task
|
|
95
|
+
const currentDefineTaskIndex = defineTaskIndices[currentDefineGroupIndex] ?? -1;
|
|
96
|
+
const defineTask = currentDefineTaskIndex >= 0 ? tasks[currentDefineTaskIndex] : null;
|
|
97
|
+
const optionsCount = Array.isArray(defineTask?.params?.options)
|
|
98
|
+
? defineTask.params.options.length
|
|
99
|
+
: 0;
|
|
100
|
+
const hasMoreGroups = currentDefineGroupIndex < defineTaskIndices.length - 1;
|
|
101
|
+
useInput((input, key) => {
|
|
102
|
+
// Don't handle input if already done or no define task
|
|
103
|
+
if (isDone || !defineTask) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (key.downArrow) {
|
|
107
|
+
setHighlightedIndex((prev) => {
|
|
108
|
+
if (prev === null) {
|
|
109
|
+
return 0; // Select first
|
|
110
|
+
}
|
|
111
|
+
return (prev + 1) % optionsCount; // Wrap around
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
else if (key.upArrow) {
|
|
115
|
+
setHighlightedIndex((prev) => {
|
|
116
|
+
if (prev === null) {
|
|
117
|
+
return optionsCount - 1; // Select last
|
|
118
|
+
}
|
|
119
|
+
return (prev - 1 + optionsCount) % optionsCount; // Wrap around
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
else if (key.return && highlightedIndex !== null) {
|
|
123
|
+
// Record the selection for this group
|
|
124
|
+
const newCompletedSelections = [...completedSelections];
|
|
125
|
+
newCompletedSelections[currentDefineGroupIndex] = highlightedIndex;
|
|
126
|
+
setCompletedSelections(newCompletedSelections);
|
|
127
|
+
if (hasMoreGroups) {
|
|
128
|
+
// Advance to next group
|
|
129
|
+
setCurrentDefineGroupIndex(currentDefineGroupIndex + 1);
|
|
130
|
+
setHighlightedIndex(null);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// Last group - mark as done to show the selection
|
|
134
|
+
setIsDone(true);
|
|
135
|
+
setHighlightedIndex(null); // Clear highlight to show Execute color
|
|
136
|
+
if (state) {
|
|
137
|
+
state.done = true;
|
|
138
|
+
}
|
|
139
|
+
// Update all tasks and notify parent
|
|
140
|
+
const updatedTasks = tasks.map((task, idx) => {
|
|
141
|
+
if (defineTaskIndices.includes(idx)) {
|
|
142
|
+
return { ...task, type: TaskType.Execute };
|
|
143
|
+
}
|
|
144
|
+
return task;
|
|
145
|
+
});
|
|
146
|
+
onSelectionConfirmed?.(highlightedIndex, updatedTasks);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}, { isActive: !isDone && defineTask !== null });
|
|
150
|
+
// Sync state back to state object
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (state) {
|
|
153
|
+
state.highlightedIndex = highlightedIndex;
|
|
154
|
+
state.currentDefineGroupIndex = currentDefineGroupIndex;
|
|
155
|
+
state.completedSelections = completedSelections;
|
|
156
|
+
state.done = isDone;
|
|
157
|
+
}
|
|
158
|
+
}, [
|
|
159
|
+
highlightedIndex,
|
|
160
|
+
currentDefineGroupIndex,
|
|
161
|
+
completedSelections,
|
|
162
|
+
isDone,
|
|
163
|
+
state,
|
|
164
|
+
]);
|
|
165
|
+
const listItems = tasks.map((task, idx) => {
|
|
166
|
+
// Find which define group this task belongs to (if any)
|
|
167
|
+
const defineGroupIndex = defineTaskIndices.indexOf(idx);
|
|
168
|
+
const isDefineTask = defineGroupIndex !== -1;
|
|
169
|
+
// Determine child selection state
|
|
170
|
+
let childIndex = null;
|
|
171
|
+
if (isDefineTask) {
|
|
172
|
+
if (defineGroupIndex < currentDefineGroupIndex) {
|
|
173
|
+
// Previously completed group - show the selection
|
|
174
|
+
childIndex = completedSelections[defineGroupIndex] ?? null;
|
|
175
|
+
}
|
|
176
|
+
else if (defineGroupIndex === currentDefineGroupIndex) {
|
|
177
|
+
// Current active group - show live navigation unless done
|
|
178
|
+
if (isDone) {
|
|
179
|
+
// If done, show the completed selection for this group too
|
|
180
|
+
childIndex = completedSelections[defineGroupIndex] ?? null;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
childIndex = null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Show arrow on current active define task when no child is highlighted
|
|
188
|
+
const isDefineWithoutSelection = isDefineTask &&
|
|
189
|
+
defineGroupIndex === currentDefineGroupIndex &&
|
|
190
|
+
highlightedIndex === null;
|
|
191
|
+
return taskToListItem(task, childIndex, isDefineWithoutSelection);
|
|
192
|
+
});
|
|
193
|
+
return (_jsxs(Box, { flexDirection: "column", children: [message && (_jsx(Box, { marginBottom: 1, children: _jsx(Label, { description: message, descriptionColor: ColorPalette[TaskType.Plan].description, type: TaskType.Plan, typeColor: ColorPalette[TaskType.Plan].type }) })), _jsx(List, { items: listItems, highlightedIndex: currentDefineTaskIndex >= 0 ? highlightedIndex : null, highlightedParentIndex: currentDefineTaskIndex })] }));
|
|
194
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prompt-language-shell",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Your personal command-line concierge. Ask politely, and it gets things done.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"@vitest/coverage-v8": "^4.0.8",
|
|
58
58
|
"eslint": "^9.17.0",
|
|
59
59
|
"husky": "^9.1.7",
|
|
60
|
+
"ink-testing-library": "^4.0.0",
|
|
60
61
|
"prettier": "^3.6.2",
|
|
61
62
|
"typescript": "^5.3.3",
|
|
62
63
|
"typescript-eslint": "^8.19.1",
|