prompt-language-shell 0.7.0 → 0.7.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.
@@ -4,7 +4,7 @@ import { Box, Text } from 'ink';
4
4
  import { ComponentStatus, } from '../types/components.js';
5
5
  import { TaskType } from '../types/types.js';
6
6
  import { Colors } from '../services/colors.js';
7
- import { createPlanDefinition } from '../services/components.js';
7
+ import { createScheduleDefinition } from '../services/components.js';
8
8
  import { formatErrorMessage } from '../services/messages.js';
9
9
  import { useInput } from '../services/keyboard.js';
10
10
  import { handleRefinement } from '../services/refinement.js';
@@ -36,21 +36,28 @@ export function Command({ command, state, status, service, handlers, onAborted,
36
36
  async function process(svc) {
37
37
  const startTime = Date.now();
38
38
  try {
39
- let result = await svc.processWithTool(command, 'plan');
40
- // If all tasks are config type, delegate to CONFIG tool
39
+ let result = await svc.processWithTool(command, 'schedule');
40
+ // Save schedule debug output before potentially delegating
41
+ const scheduleDebug = result.debug || [];
42
+ // If all tasks are configure type, delegate to CONFIGURE tool
41
43
  const allConfig = result.tasks.length > 0 &&
42
44
  result.tasks.every((task) => task.type === TaskType.Config);
43
45
  if (allConfig) {
44
46
  // Extract query from first config task params, default to 'app'
45
47
  const query = result.tasks[0].params?.query || 'app';
46
- // Call CONFIG tool to get specific config keys
47
- result = await svc.processWithTool(query, 'config');
48
+ // Call CONFIGURE tool to get specific config keys
49
+ result = await svc.processWithTool(query, 'configure');
48
50
  }
49
51
  await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
50
52
  if (mounted) {
51
53
  // Add debug components to timeline if present
52
- if (result.debug && result.debug.length > 0) {
53
- handlers?.addToTimeline(...result.debug);
54
+ // If we delegated to configure, include both schedule and configure debug
55
+ // If not, only include schedule debug (result.debug is same as scheduleDebug)
56
+ const allDebug = allConfig
57
+ ? [...scheduleDebug, ...(result.debug || [])]
58
+ : scheduleDebug;
59
+ if (allDebug.length > 0) {
60
+ handlers?.addToTimeline(...allDebug);
54
61
  }
55
62
  // Save result to state for timeline display
56
63
  handlers?.updateState({
@@ -59,17 +66,17 @@ export function Command({ command, state, status, service, handlers, onAborted,
59
66
  });
60
67
  // Check if tasks contain DEFINE type (variant selection needed)
61
68
  const hasDefineTask = result.tasks.some((task) => task.type === TaskType.Define);
62
- // Create Plan definition
63
- const planDefinition = createPlanDefinition(result.message, result.tasks, hasDefineTask
69
+ // Create Schedule definition
70
+ const scheduleDefinition = createScheduleDefinition(result.message, result.tasks, hasDefineTask
64
71
  ? async (selectedTasks) => {
65
72
  // Refinement flow for DEFINE tasks
66
73
  await handleRefinement(selectedTasks, svc, command, handlers);
67
74
  }
68
75
  : undefined);
69
76
  if (hasDefineTask) {
70
- // DEFINE tasks: Move Command to timeline, add Plan to queue
77
+ // DEFINE tasks: Move Command to timeline, add Schedule to queue
71
78
  handlers?.completeActive();
72
- handlers?.addToQueue(planDefinition);
79
+ handlers?.addToQueue(scheduleDefinition);
73
80
  }
74
81
  else {
75
82
  // No DEFINE tasks: Complete Command, then route to Confirm flow
@@ -10,7 +10,7 @@ import { Execute } from './Execute.js';
10
10
  import { Feedback } from './Feedback.js';
11
11
  import { Introspect } from './Introspect.js';
12
12
  import { Message } from './Message.js';
13
- import { Plan } from './Plan.js';
13
+ import { Schedule } from './Schedule.js';
14
14
  import { Refinement } from './Refinement.js';
15
15
  import { Report } from './Report.js';
16
16
  import { Validate } from './Validate.js';
@@ -23,8 +23,8 @@ export const Component = memo(function Component({ def, debug, }) {
23
23
  return (_jsx(Config, { ...def.props, state: def.state, status: def.status, debug: debug }));
24
24
  case ComponentName.Command:
25
25
  return _jsx(Command, { ...def.props, state: def.state, status: def.status });
26
- case ComponentName.Plan:
27
- return (_jsx(Plan, { ...def.props, state: def.state, status: def.status, debug: debug }));
26
+ case ComponentName.Schedule:
27
+ return (_jsx(Schedule, { ...def.props, state: def.state, status: def.status, debug: debug }));
28
28
  case ComponentName.Feedback:
29
29
  return _jsx(Feedback, { ...def.props, status: def.status });
30
30
  case ComponentName.Message:
package/dist/ui/Config.js CHANGED
@@ -3,7 +3,9 @@ import { useState } from 'react';
3
3
  import { Box, Text, useFocus } from 'ink';
4
4
  import TextInput from 'ink-text-input';
5
5
  import { ComponentStatus } from '../types/components.js';
6
+ import { FeedbackType } from '../types/types.js';
6
7
  import { Colors } from '../services/colors.js';
8
+ import { createFeedback } from '../services/components.js';
7
9
  import { DebugLevel } from '../services/configuration.js';
8
10
  import { useInput } from '../services/keyboard.js';
9
11
  export var StepType;
@@ -131,9 +133,16 @@ export function Config({ steps, state, status, debug = DebugLevel.None, handlers
131
133
  setValues({ ...values, [configKey]: currentValue });
132
134
  }
133
135
  }
136
+ // Save state before aborting
137
+ handlers?.updateState({
138
+ values,
139
+ completedStep: step,
140
+ });
134
141
  if (onAborted) {
135
142
  onAborted('configuration');
136
143
  }
144
+ // Complete with abort feedback
145
+ handlers?.completeActive(createFeedback(FeedbackType.Aborted, 'Configuration cancelled.'));
137
146
  return;
138
147
  }
139
148
  // Handle selection step navigation
@@ -190,9 +199,18 @@ export function Config({ steps, state, status, debug = DebugLevel.None, handlers
190
199
  completedStep: steps.length,
191
200
  };
192
201
  handlers?.updateState(stateUpdate);
193
- // Now call onFinished - this may trigger completeActive()
194
- if (onFinished) {
195
- onFinished(newValues);
202
+ // Call onFinished callback and handle result
203
+ try {
204
+ if (onFinished) {
205
+ onFinished(newValues);
206
+ }
207
+ // Success - complete with success feedback
208
+ handlers?.completeActive(createFeedback(FeedbackType.Succeeded, 'Configuration saved successfully.'));
209
+ }
210
+ catch (error) {
211
+ // Failure - complete with error feedback
212
+ const errorMessage = error instanceof Error ? error.message : 'Configuration failed';
213
+ handlers?.completeActive(createFeedback(FeedbackType.Failed, errorMessage));
196
214
  }
197
215
  setStep(steps.length);
198
216
  }
package/dist/ui/Debug.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text } from 'ink';
3
- const MIN_CONTENT_WIDTH = 80;
3
+ const CONTENT_WIDTH = 80;
4
4
  const HORIZONTAL_PADDING = 2;
5
- const BORDER_WIDTH = 1;
6
5
  export const Debug = ({ title, content, color }) => {
7
- return (_jsxs(Box, { flexDirection: "column", paddingX: HORIZONTAL_PADDING, paddingY: 1, borderStyle: "single", borderColor: color, alignSelf: "flex-start", minWidth: MIN_CONTENT_WIDTH + 2 * HORIZONTAL_PADDING + 2 * BORDER_WIDTH, children: [_jsx(Text, { color: color, children: title }), _jsx(Text, { color: color, children: content })] }));
6
+ return (_jsxs(Box, { flexDirection: "column", paddingX: HORIZONTAL_PADDING, paddingY: 1, borderStyle: "single", borderColor: color, width: CONTENT_WIDTH, children: [_jsx(Text, { color: color, wrap: "wrap", children: title }), _jsx(Text, { color: color, wrap: "wrap", children: content })] }));
8
7
  };
@@ -12,14 +12,14 @@ import { Spinner } from './Spinner.js';
12
12
  const MIN_PROCESSING_TIME = 1000;
13
13
  const BUILT_IN_CAPABILITIES = new Set([
14
14
  'CONFIG',
15
- 'PLAN',
15
+ 'SCHEDULE',
16
16
  'INTROSPECT',
17
17
  'ANSWER',
18
18
  'EXECUTE',
19
19
  'VALIDATE',
20
20
  'REPORT',
21
21
  ]);
22
- const INDIRECT_CAPABILITIES = new Set(['PLAN', 'VALIDATE', 'REPORT']);
22
+ const INDIRECT_CAPABILITIES = new Set(['SCHEDULE', 'VALIDATE', 'REPORT']);
23
23
  function parseCapabilityFromTask(task) {
24
24
  // Parse "NAME: Description" format from task.action
25
25
  const colonIndex = task.action.indexOf(':');
@@ -85,7 +85,7 @@ export function Introspect({ tasks, state, status, service, children, debug = De
85
85
  let capabilities = result.tasks.map(parseCapabilityFromTask);
86
86
  // Filter out internal capabilities when not in debug mode
87
87
  if (debug === DebugLevel.None) {
88
- capabilities = capabilities.filter((cap) => cap.name.toUpperCase() !== 'PLAN' &&
88
+ capabilities = capabilities.filter((cap) => cap.name.toUpperCase() !== 'SCHEDULE' &&
89
89
  cap.name.toUpperCase() !== 'VALIDATE' &&
90
90
  cap.name.toUpperCase() !== 'REPORT');
91
91
  }
package/dist/ui/Label.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text } from 'ink';
3
- import { getTaskColors } from '../services/colors.js';
3
+ import { DebugLevel } from '../services/configuration.js';
4
+ import { getTaskColors, getTaskTypeLabel } from '../services/colors.js';
4
5
  import { Separator } from './Separator.js';
5
- export function Label({ description, taskType, showType = false, isCurrent = false, }) {
6
+ export function Label({ description, taskType, showType = false, isCurrent = false, debug = DebugLevel.None, }) {
6
7
  const colors = getTaskColors(taskType, isCurrent);
7
- return (_jsxs(Box, { children: [_jsx(Text, { color: colors.description, children: description }), showType && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx(Text, { color: colors.type, children: taskType })] }))] }));
8
+ return (_jsxs(Box, { children: [_jsx(Text, { color: colors.description, children: description }), showType && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx(Text, { color: colors.type, children: getTaskTypeLabel(taskType, debug) })] }))] }));
8
9
  }
package/dist/ui/List.js CHANGED
@@ -2,13 +2,14 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  import { Box, Text } from 'ink';
3
3
  import { Separator } from './Separator.js';
4
4
  export const List = ({ items, level = 0, highlightedIndex = null, highlightedParentIndex = null, showType = false, }) => {
5
- const marginLeft = level > 0 ? 4 : 0;
5
+ const marginLeft = level > 0 ? 2 : 0;
6
6
  return (_jsx(Box, { flexDirection: "column", marginLeft: marginLeft, children: items.map((item, index) => {
7
7
  // At level 0, track which parent is active for child highlighting
8
8
  // At level > 0, only highlight if this parent is the active one
9
9
  const shouldHighlightChildren = level === 0 ? highlightedParentIndex === index : false;
10
10
  const isHighlighted = item.highlighted || (level > 0 && index === highlightedIndex);
11
- const marker = item.marker || (isHighlighted ? ' ' : ' - ');
11
+ const defaultMarker = level > 0 ? ' · ' : ' - ';
12
+ const marker = item.marker || (isHighlighted ? ' → ' : defaultMarker);
12
13
  // Use highlighted colors if available and item is highlighted
13
14
  const descriptionColor = isHighlighted && item.description.highlightedColor
14
15
  ? item.description.highlightedColor
package/dist/ui/Main.js CHANGED
@@ -3,7 +3,7 @@ import { useEffect, useState } from 'react';
3
3
  import { FeedbackType } from '../types/types.js';
4
4
  import { createAnthropicService, } from '../services/anthropic.js';
5
5
  import { createCommandDefinition, createConfigDefinitionWithKeys, createFeedback, createMessage, createWelcomeDefinition, } from '../services/components.js';
6
- import { DebugLevel, getConfigurationRequiredMessage, getMissingConfigKeys, loadConfig, loadDebugSetting, saveAnthropicConfig, saveDebugSetting, } from '../services/configuration.js';
6
+ import { DebugLevel, getConfigurationRequiredMessage, getMissingConfigKeys, loadConfig, loadDebugSetting, saveConfig, saveDebugSetting, unflattenConfig, } from '../services/configuration.js';
7
7
  import { registerGlobalShortcut } from '../services/keyboard.js';
8
8
  import { initializeLogger, setDebugLevel } from '../services/logger.js';
9
9
  import { Workflow } from './Workflow.js';
@@ -69,20 +69,25 @@ export const Main = ({ app, command }) => {
69
69
  const handleConfigFinished = (config) => {
70
70
  // Save config and create service
71
71
  try {
72
- const newConfig = saveAnthropicConfig(config);
72
+ const configBySection = unflattenConfig(config);
73
+ for (const [section, sectionConfig] of Object.entries(configBySection)) {
74
+ saveConfig(section, sectionConfig);
75
+ }
76
+ // Load config and create service
77
+ const newConfig = loadConfig();
73
78
  const newService = createAnthropicService(newConfig.anthropic);
74
79
  setService(newService);
75
80
  }
76
81
  catch (error) {
77
- // Config creation failed - show error
82
+ // Config save failed
78
83
  const errorMessage = error instanceof Error
79
84
  ? error.message
80
85
  : 'Failed to save configuration';
81
- setInitialQueue([createFeedback(FeedbackType.Failed, errorMessage)]);
86
+ throw new Error(errorMessage);
82
87
  }
83
88
  };
84
89
  const handleConfigAborted = (operation) => {
85
- // Config was cancelled - just exit
90
+ // Config was cancelled
86
91
  };
87
92
  setInitialQueue([
88
93
  createWelcomeDefinition(app),
@@ -4,24 +4,24 @@ import { Box } from 'ink';
4
4
  import { ComponentStatus } from '../types/components.js';
5
5
  import { TaskType } from '../types/types.js';
6
6
  import { DebugLevel } from '../services/configuration.js';
7
- import { getTaskColors } from '../services/colors.js';
7
+ import { getTaskColors, getTaskTypeLabel } from '../services/colors.js';
8
8
  import { useInput } from '../services/keyboard.js';
9
9
  import { Label } from './Label.js';
10
10
  import { List } from './List.js';
11
- function taskToListItem(task, highlightedChildIndex = null, isDefineTaskWithoutSelection = false, isCurrent = false) {
11
+ function taskToListItem(task, highlightedChildIndex = null, isDefineTaskWithoutSelection = false, isCurrent = false, debug = DebugLevel.None) {
12
12
  const taskColors = getTaskColors(task.type, isCurrent);
13
13
  const item = {
14
14
  description: {
15
15
  text: task.action,
16
16
  color: taskColors.description,
17
17
  },
18
- type: { text: task.type, color: taskColors.type },
18
+ type: { text: getTaskTypeLabel(task.type, debug), color: taskColors.type },
19
19
  children: [],
20
20
  };
21
21
  // Mark define tasks with right arrow when no selection has been made
22
22
  if (isDefineTaskWithoutSelection) {
23
23
  item.marker = ' → ';
24
- item.markerColor = getTaskColors(TaskType.Plan, isCurrent).type;
24
+ item.markerColor = getTaskColors(TaskType.Schedule, isCurrent).type;
25
25
  }
26
26
  // Add children for Define tasks with options
27
27
  if (task.type === TaskType.Define && Array.isArray(task.params?.options)) {
@@ -34,7 +34,7 @@ function taskToListItem(task, highlightedChildIndex = null, isDefineTaskWithoutS
34
34
  index === highlightedChildIndex ? TaskType.Execute : TaskType.Discard;
35
35
  }
36
36
  const colors = getTaskColors(childType, isCurrent);
37
- const planColors = getTaskColors(TaskType.Plan, isCurrent);
37
+ const planColors = getTaskColors(TaskType.Schedule, isCurrent);
38
38
  return {
39
39
  description: {
40
40
  text: String(option),
@@ -42,16 +42,36 @@ function taskToListItem(task, highlightedChildIndex = null, isDefineTaskWithoutS
42
42
  highlightedColor: planColors.description,
43
43
  },
44
44
  type: {
45
- text: childType,
45
+ text: getTaskTypeLabel(childType, debug),
46
46
  color: colors.type,
47
47
  highlightedColor: planColors.type,
48
48
  },
49
49
  };
50
50
  });
51
51
  }
52
+ // Add children for Group tasks with subtasks
53
+ const scheduledTask = task;
54
+ if (task.type === TaskType.Group &&
55
+ scheduledTask.subtasks &&
56
+ Array.isArray(scheduledTask.subtasks) &&
57
+ scheduledTask.subtasks.length > 0) {
58
+ item.children = scheduledTask.subtasks.map((subtask) => {
59
+ const subtaskColors = getTaskColors(subtask.type, isCurrent);
60
+ return {
61
+ description: {
62
+ text: subtask.action,
63
+ color: subtaskColors.description,
64
+ },
65
+ type: {
66
+ text: getTaskTypeLabel(subtask.type, debug),
67
+ color: subtaskColors.type,
68
+ },
69
+ };
70
+ });
71
+ }
52
72
  return item;
53
73
  }
54
- export function Plan({ message, tasks, state, status, debug = DebugLevel.None, handlers, onSelectionConfirmed, }) {
74
+ export function Schedule({ message, tasks, state, status, debug = DebugLevel.None, handlers, onSelectionConfirmed, }) {
55
75
  const isActive = status === ComponentStatus.Active;
56
76
  // isActive passed as prop
57
77
  const [highlightedIndex, setHighlightedIndex] = useState(state?.highlightedIndex ?? null);
@@ -138,6 +158,7 @@ export function Plan({ message, tasks, state, status, debug = DebugLevel.None, h
138
158
  refinedTasks.push({
139
159
  action: selectedOption,
140
160
  type: TaskType.Execute,
161
+ config: [],
141
162
  });
142
163
  }
143
164
  else if (task.type !== TaskType.Ignore &&
@@ -200,7 +221,7 @@ export function Plan({ message, tasks, state, status, debug = DebugLevel.None, h
200
221
  defineGroupIndex === currentDefineGroupIndex &&
201
222
  highlightedIndex === null &&
202
223
  isActive;
203
- return taskToListItem(task, childIndex, isDefineWithoutSelection, isActive);
224
+ return taskToListItem(task, childIndex, isDefineWithoutSelection, isActive, debug);
204
225
  });
205
- return (_jsxs(Box, { flexDirection: "column", children: [message && (_jsx(Box, { marginBottom: 1, marginLeft: 1, children: _jsx(Label, { description: message, taskType: TaskType.Plan, showType: debug !== DebugLevel.None, isCurrent: isActive }) })), _jsx(Box, { marginLeft: 1, children: _jsx(List, { items: listItems, highlightedIndex: currentDefineTaskIndex >= 0 ? highlightedIndex : null, highlightedParentIndex: currentDefineTaskIndex, showType: debug !== DebugLevel.None }) })] }));
226
+ return (_jsxs(Box, { flexDirection: "column", children: [message && (_jsx(Box, { marginBottom: 1, marginLeft: 1, children: _jsx(Label, { description: message, taskType: TaskType.Schedule, showType: debug !== DebugLevel.None, isCurrent: isActive, debug: debug }) })), _jsx(Box, { marginLeft: 1, children: _jsx(List, { items: listItems, highlightedIndex: currentDefineTaskIndex >= 0 ? highlightedIndex : null, highlightedParentIndex: currentDefineTaskIndex, showType: debug !== DebugLevel.None }) })] }));
206
227
  }
@@ -139,7 +139,7 @@ export function Validate({ missingConfig, userRequest, state, status, service, c
139
139
  handlers?.completeActive();
140
140
  onAborted(operation);
141
141
  };
142
- return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isActive && !completionMessage && !error && (_jsxs(Box, { marginLeft: 1, children: [_jsxs(Text, { color: getTextColor(isActive), children: ["Validating configuration requirements.", ' '] }), _jsx(Spinner, {})] })), completionMessage && (_jsx(Box, { marginLeft: 1, children: _jsx(Text, { color: getTextColor(isActive), children: completionMessage }) })), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) })), configSteps && !error && (_jsx(Box, { marginTop: 1, children: _jsx(Config, { steps: configSteps, status: status, debug: debug, onFinished: handleConfigFinished, onAborted: handleConfigAborted, handlers: handlers }) })), children] }));
142
+ return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isActive && !completionMessage && !error && (_jsxs(Box, { marginLeft: 1, children: [_jsxs(Text, { color: getTextColor(isActive), children: ["Validating configuration requirements.", ' '] }), _jsx(Spinner, {})] })), completionMessage && (_jsx(Box, { marginLeft: 1, children: _jsx(Text, { color: getTextColor(isActive), children: completionMessage }) })), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) })), configSteps && configSteps.length > 0 && !error && (_jsx(Box, { marginTop: 1, children: _jsx(Config, { steps: configSteps, status: status, debug: debug, onFinished: handleConfigFinished, onAborted: handleConfigAborted, handlers: handlers }) })), configSteps && configSteps.length === 0 && !error && (_jsx(Box, { marginTop: 1, marginLeft: 1, children: _jsx(Text, { color: Colors.Status.Error, children: "Error: No configuration steps generated. Please try again." }) })), children] }));
143
143
  }
144
144
  /**
145
145
  * Build prompt for VALIDATE tool
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prompt-language-shell",
3
- "version": "0.7.0",
3
+ "version": "0.7.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",