prompt-language-shell 0.7.0 → 0.7.2

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.
@@ -68,7 +68,7 @@ export class AnthropicService {
68
68
  systemPrompt += skillsSection;
69
69
  }
70
70
  // Add config structure for config tool only
71
- if (toolName === 'config') {
71
+ if (toolName === 'configure') {
72
72
  const configStructure = getAvailableConfigStructure();
73
73
  const configuredKeys = getConfiguredKeys();
74
74
  const configSection = '\n## Available Configuration\n\n' +
@@ -1,4 +1,5 @@
1
1
  import { FeedbackType, TaskType } from '../types/types.js';
2
+ import { DebugLevel } from './configuration.js';
2
3
  /**
3
4
  * Base color palette - raw color values with descriptive names.
4
5
  * All colors used in the interface are defined here.
@@ -174,3 +175,32 @@ export function getFeedbackColor(type, isCurrent) {
174
175
  export function getTextColor(isCurrent) {
175
176
  return isCurrent ? Colors.Text.Active : Colors.Text.Inactive;
176
177
  }
178
+ /**
179
+ * Verbose task type labels - two-word descriptions that start with the same
180
+ * keyword as the short version
181
+ */
182
+ const verboseTaskTypeLabels = {
183
+ [TaskType.Config]: 'configure option',
184
+ [TaskType.Plan]: 'plan tasks',
185
+ [TaskType.Execute]: 'execute command',
186
+ [TaskType.Answer]: 'answer question',
187
+ [TaskType.Introspect]: 'introspect capabilities',
188
+ [TaskType.Report]: 'report results',
189
+ [TaskType.Define]: 'define options',
190
+ [TaskType.Ignore]: 'ignore request',
191
+ [TaskType.Select]: 'select option',
192
+ [TaskType.Discard]: 'discard option',
193
+ };
194
+ /**
195
+ * Get task type label based on debug level.
196
+ *
197
+ * Returns:
198
+ * - Verbose label (2 words) in verbose mode
199
+ * - Short label (1 word) in info mode or when debug is off
200
+ */
201
+ export function getTaskTypeLabel(type, debug) {
202
+ if (debug === DebugLevel.Verbose) {
203
+ return verboseTaskTypeLabels[type];
204
+ }
205
+ return type;
206
+ }
@@ -34,14 +34,14 @@ class ToolRegistry {
34
34
  export const toolRegistry = new ToolRegistry();
35
35
  // Register built-in tools
36
36
  import { answerTool } from '../tools/answer.tool.js';
37
- import { configTool } from '../tools/config.tool.js';
37
+ import { configureTool } from '../tools/configure.tool.js';
38
38
  import { executeTool } from '../tools/execute.tool.js';
39
39
  import { introspectTool } from '../tools/introspect.tool.js';
40
40
  import { planTool } from '../tools/plan.tool.js';
41
41
  import { validateTool } from '../tools/validate.tool.js';
42
42
  const tools = {
43
43
  answer: answerTool,
44
- config: configTool,
44
+ configure: configureTool,
45
45
  execute: executeTool,
46
46
  introspect: introspectTool,
47
47
  plan: planTool,
@@ -102,7 +102,7 @@ function executeTasksAfterConfirm(tasks, service, userRequest, handlers) {
102
102
  .map((task) => task.params?.key)
103
103
  .filter((key) => key !== undefined);
104
104
  handlers.addToQueue(createConfigDefinitionWithKeys(configKeys, (config) => {
105
- // Save config using the same pattern as Validate component
105
+ // Save config - Config component will handle completion and feedback
106
106
  try {
107
107
  // Convert flat dotted keys to nested structure grouped by section
108
108
  const configBySection = unflattenConfig(config);
@@ -110,14 +110,12 @@ function executeTasksAfterConfirm(tasks, service, userRequest, handlers) {
110
110
  for (const [section, sectionConfig] of Object.entries(configBySection)) {
111
111
  saveConfig(section, sectionConfig);
112
112
  }
113
- handlers.completeActive();
114
- handlers.addToQueue(createFeedback(FeedbackType.Succeeded, 'Configuration updated successfully.'));
115
113
  }
116
114
  catch (error) {
117
115
  const errorMessage = error instanceof Error
118
116
  ? error.message
119
117
  : 'Failed to save configuration';
120
- handlers.onError(errorMessage);
118
+ throw new Error(errorMessage);
121
119
  }
122
120
  }, (operation) => {
123
121
  handlers.onAborted(operation);
@@ -49,14 +49,14 @@ as tasks.
49
49
  "tasks": [
50
50
  {
51
51
  "action": "Anthropic API key",
52
- "type": "config",
52
+ "type": "configure",
53
53
  "params": {
54
54
  "key": "anthropic.key"
55
55
  }
56
56
  },
57
57
  {
58
58
  "action": "Model",
59
- "type": "config",
59
+ "type": "configure",
60
60
  "params": {
61
61
  "key": "anthropic.model"
62
62
  }
@@ -69,7 +69,7 @@ as tasks.
69
69
 
70
70
  - Use the exact config keys from `configStructure`
71
71
  - Use the descriptions from `configStructure` as the action text
72
- - Always use type "config"
72
+ - Always use type "configure"
73
73
  - Always include the key in params
74
74
  - Keep message concise (≤64 characters)
75
75
  - Return at least one task (required keys if unsure)
@@ -516,7 +516,7 @@ When creating task definitions, focus on:
516
516
  characters.**
517
517
 
518
518
  - **Type**: Categorize the operation using one of these supported types:
519
- - `config` - Configuration changes, settings updates
519
+ - `configure` - Configuration changes, settings updates
520
520
  - `plan` - Planning or breaking down tasks
521
521
  - `execute` - Shell commands, running programs, scripts, processing
522
522
  operations
@@ -551,33 +551,38 @@ unambiguous and executable.
551
551
  ## Configuration Requests
552
552
 
553
553
  When the user wants to configure or change settings (e.g., "pls config",
554
- "pls configure", "pls change settings", "pls run settings", "pls config
555
- anthropic", "pls config mode"), create a SINGLE task with type "config".
554
+ "pls cfg", "pls configure", "pls change settings", "pls run settings",
555
+ "pls config anthropic", "pls config mode"), create a SINGLE task with type
556
+ "configure".
556
557
 
557
558
  **Task format:**
558
559
  - **action**: "Configure settings" (or similar natural description)
559
- - **type**: "config"
560
+ - **type**: "configure"
560
561
  - **params**: Include `{ "query": "filter" }` where filter specifies
561
562
  which settings to configure:
562
563
  - If command contains specific keywords like "anthropic", "mode",
563
564
  "debug" → use that keyword
564
- - If command is just "config" or "configure" or "settings" with no
565
- specific area → use "app"
565
+ - If command is just "config" or "cfg" or "configure" or "settings"
566
+ with no specific area → use "app"
566
567
  - Extract the relevant context, not the full command
567
568
 
568
569
  **Examples:**
569
- - User: "pls config anthropic" → `{ "action": "Configure settings",
570
- "type": "config", "params": { "query": "anthropic" } }`
570
+ - User: "pls config" → `{ "action": "Configure settings", "type":
571
+ "configure", "params": { "query": "app" } }`
572
+ - User: "pls cfg" → `{ "action": "Configure settings", "type":
573
+ "configure", "params": { "query": "app" } }`
571
574
  - User: "pls configure" → `{ "action": "Configure settings", "type":
572
- "config", "params": { "query": "app" } }`
575
+ "configure", "params": { "query": "app" } }`
573
576
  - User: "pls run settings" → `{ "action": "Configure settings", "type":
574
- "config", "params": { "query": "app" } }`
577
+ "configure", "params": { "query": "app" } }`
578
+ - User: "pls config anthropic" → `{ "action": "Configure settings",
579
+ "type": "configure", "params": { "query": "anthropic" } }`
575
580
  - User: "pls config mode" → `{ "action": "Configure settings", "type":
576
- "config", "params": { "query": "mode" } }`
581
+ "configure", "params": { "query": "mode" } }`
577
582
  - User: "pls change debug settings" → `{ "action": "Configure settings",
578
- "type": "config", "params": { "query": "mode" } }`
583
+ "type": "configure", "params": { "query": "mode" } }`
579
584
 
580
- The CONFIG tool will handle determining which specific config keys to
585
+ The CONFIGURE tool will handle determining which specific config keys to
581
586
  show based on the query.
582
587
 
583
588
  ## Multiple Tasks
@@ -21,9 +21,10 @@ You will receive information about missing configuration values:
21
21
  Generate a response with two required fields:
22
22
 
23
23
  1. **message**: An empty string `""`
24
- 2. **tasks**: An array of CONFIG tasks, one for each missing config value
24
+ 2. **tasks**: An array of CONFIGURE tasks, one for each missing config
25
+ value
25
26
 
26
- For each CONFIG task, create a natural language description that:
27
+ For each CONFIGURE task, create a natural language description that:
27
28
 
28
29
  1. **Explains what the value is for** using context from the skill's
29
30
  description
@@ -59,7 +60,7 @@ message: ""
59
60
  tasks: [
60
61
  {
61
62
  action: "Path to Alpha repository",
62
- type: "config",
63
+ type: "configure",
63
64
  params: { key: "project.alpha.repo" }
64
65
  }
65
66
  ]
@@ -78,7 +79,7 @@ message: ""
78
79
  tasks: [
79
80
  {
80
81
  action: "Staging environment URL",
81
- type: "config",
82
+ type: "configure",
82
83
  params: { key: "env.staging.url" }
83
84
  }
84
85
  ]
@@ -97,7 +98,7 @@ message: ""
97
98
  tasks: [
98
99
  {
99
100
  action: "Path to Beta workspace",
100
- type: "config",
101
+ type: "configure",
101
102
  params: { key: "workspace.beta.path" }
102
103
  }
103
104
  ]
@@ -129,14 +130,15 @@ tasks: [
129
130
 
130
131
  ## Response Format
131
132
 
132
- Return a message field (can be empty string) and an array of CONFIG tasks:
133
+ Return a message field (can be empty string) and an array of CONFIGURE
134
+ tasks:
133
135
 
134
136
  ```
135
137
  message: ""
136
138
  tasks: [
137
139
  {
138
140
  action: "Natural description without config path",
139
- type: "config",
141
+ type: "configure",
140
142
  params: { key: "config.path" }
141
143
  },
142
144
  // ... more tasks
@@ -145,7 +147,7 @@ tasks: [
145
147
 
146
148
  ## Important Notes
147
149
 
148
- - All tasks must have type "config"
150
+ - All tasks must have type "configure"
149
151
  - All tasks must include params.key with the config path
150
152
  - Descriptions should be helpful and contextual, not just technical
151
153
  - Use information from Available Skills section to provide context
@@ -1,5 +1,5 @@
1
- export const configTool = {
2
- name: 'config',
1
+ export const configureTool = {
2
+ name: 'configure',
3
3
  description: 'Determine which configuration settings to show based on user query. Receives available config keys with descriptions and returns which keys the user wants to configure.',
4
4
  input_schema: {
5
5
  type: 'object',
@@ -10,25 +10,25 @@ export const configTool = {
10
10
  },
11
11
  tasks: {
12
12
  type: 'array',
13
- description: 'Array of config settings to configure. Each task has type "config" and params with the config key.',
13
+ description: 'Settings the user wants to configure. Each task specifies which setting to configure.',
14
14
  items: {
15
15
  type: 'object',
16
16
  properties: {
17
17
  action: {
18
18
  type: 'string',
19
- description: 'Description of the config setting (from the provided descriptions). Maximum 64 characters.',
19
+ description: 'Description of the setting (from the provided descriptions). Maximum 64 characters.',
20
20
  },
21
21
  type: {
22
22
  type: 'string',
23
- description: 'Always "config" for configuration tasks.',
23
+ description: 'Task type. Always "configure" for settings.',
24
24
  },
25
25
  params: {
26
26
  type: 'object',
27
- description: 'Parameters for the config task.',
27
+ description: 'Task parameters.',
28
28
  properties: {
29
29
  key: {
30
30
  type: 'string',
31
- description: 'The config key to configure (e.g., "anthropic.key", "settings.debug").',
31
+ description: 'The setting key to configure (e.g., "anthropic.key", "settings.debug").',
32
32
  },
33
33
  },
34
34
  required: ['key'],
@@ -17,7 +17,7 @@ export var ComponentName;
17
17
  })(ComponentName || (ComponentName = {}));
18
18
  export var TaskType;
19
19
  (function (TaskType) {
20
- TaskType["Config"] = "config";
20
+ TaskType["Config"] = "configure";
21
21
  TaskType["Plan"] = "plan";
22
22
  TaskType["Execute"] = "execute";
23
23
  TaskType["Answer"] = "answer";
@@ -37,14 +37,14 @@ export function Command({ command, state, status, service, handlers, onAborted,
37
37
  const startTime = Date.now();
38
38
  try {
39
39
  let result = await svc.processWithTool(command, 'plan');
40
- // If all tasks are config type, delegate to CONFIG tool
40
+ // If all tasks are configure type, delegate to CONFIGURE tool
41
41
  const allConfig = result.tasks.length > 0 &&
42
42
  result.tasks.every((task) => task.type === TaskType.Config);
43
43
  if (allConfig) {
44
44
  // Extract query from first config task params, default to 'app'
45
45
  const query = result.tasks[0].params?.query || 'app';
46
- // Call CONFIG tool to get specific config keys
47
- result = await svc.processWithTool(query, 'config');
46
+ // Call CONFIGURE tool to get specific config keys
47
+ result = await svc.processWithTool(query, 'configure');
48
48
  }
49
49
  await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
50
50
  if (mounted) {
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/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/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),
package/dist/ui/Plan.js CHANGED
@@ -4,18 +4,18 @@ 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
@@ -42,7 +42,7 @@ 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
  },
@@ -200,7 +200,7 @@ export function Plan({ message, tasks, state, status, debug = DebugLevel.None, h
200
200
  defineGroupIndex === currentDefineGroupIndex &&
201
201
  highlightedIndex === null &&
202
202
  isActive;
203
- return taskToListItem(task, childIndex, isDefineWithoutSelection, isActive);
203
+ return taskToListItem(task, childIndex, isDefineWithoutSelection, isActive, debug);
204
204
  });
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 }) })] }));
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, debug: debug }) })), _jsx(Box, { marginLeft: 1, children: _jsx(List, { items: listItems, highlightedIndex: currentDefineTaskIndex >= 0 ? highlightedIndex : null, highlightedParentIndex: currentDefineTaskIndex, showType: debug !== DebugLevel.None }) })] }));
206
206
  }
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.2",
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",