prompt-language-shell 0.8.8 → 0.9.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.
Files changed (45) hide show
  1. package/README.md +0 -1
  2. package/dist/configuration/io.js +22 -1
  3. package/dist/{services/config-labels.js → configuration/labels.js} +1 -1
  4. package/dist/configuration/schema.js +2 -2
  5. package/dist/configuration/steps.js +171 -0
  6. package/dist/configuration/transformation.js +17 -0
  7. package/dist/configuration/types.js +3 -4
  8. package/dist/execution/handlers.js +20 -35
  9. package/dist/execution/hooks.js +291 -0
  10. package/dist/execution/processing.js +15 -2
  11. package/dist/execution/reducer.js +30 -48
  12. package/dist/execution/runner.js +81 -0
  13. package/dist/execution/types.js +1 -0
  14. package/dist/execution/utils.js +28 -0
  15. package/dist/services/components.js +109 -395
  16. package/dist/services/filesystem.js +21 -1
  17. package/dist/services/logger.js +3 -3
  18. package/dist/services/messages.js +10 -16
  19. package/dist/services/process.js +7 -2
  20. package/dist/services/refinement.js +5 -2
  21. package/dist/services/router.js +120 -67
  22. package/dist/services/shell.js +179 -10
  23. package/dist/services/skills.js +2 -1
  24. package/dist/skills/answer.md +14 -12
  25. package/dist/skills/execute.md +98 -39
  26. package/dist/skills/introspect.md +9 -9
  27. package/dist/skills/schedule.md +0 -6
  28. package/dist/types/errors.js +47 -0
  29. package/dist/types/result.js +40 -0
  30. package/dist/ui/Command.js +11 -7
  31. package/dist/ui/Component.js +6 -3
  32. package/dist/ui/Config.js +9 -3
  33. package/dist/ui/Execute.js +249 -163
  34. package/dist/ui/Introspect.js +13 -14
  35. package/dist/ui/List.js +2 -2
  36. package/dist/ui/Main.js +14 -7
  37. package/dist/ui/Output.js +54 -0
  38. package/dist/ui/Schedule.js +3 -1
  39. package/dist/ui/Subtask.js +6 -3
  40. package/dist/ui/Task.js +10 -85
  41. package/dist/ui/Validate.js +26 -21
  42. package/dist/ui/Workflow.js +21 -4
  43. package/package.json +1 -1
  44. package/dist/parser.js +0 -13
  45. package/dist/services/config-utils.js +0 -20
@@ -24,6 +24,12 @@ You will receive:
24
24
  - Tasks from user-defined skills include params.skill (skill name) and
25
25
  parameter values that were substituted into the action
26
26
 
27
+ **CRITICAL - Command Count Rule**: You MUST generate EXACTLY one command
28
+ per input task, no more, no less. The number of commands in your response
29
+ MUST match the number of tasks you received. Do NOT split a single task
30
+ into multiple commands or generate extra commands beyond what was
31
+ scheduled.
32
+
27
33
  ## Skill-Based Command Generation
28
34
 
29
35
  **CRITICAL**: The "Available Skills" section in the prompt defines the ONLY
@@ -133,9 +139,26 @@ Given tasks from this skill:
133
139
  Do NOT invent different commands - use exactly what the skill specifies,
134
140
  with parameter placeholders replaced by actual values.
135
141
 
136
- **CRITICAL**: Take the exact command from the ### Execution section. Do
137
- not modify, improve, or rewrite the command in any way. The user wrote
138
- these commands specifically for their environment and workflow.
142
+ **CRITICAL - VERBATIM EXECUTION**: Run shell commands EXACTLY as written in
143
+ the ### Execution section. Do NOT:
144
+ - Modify the command string in any way
145
+ - Optimize or improve the command
146
+ - Add flags or options
147
+ - Change paths or filenames
148
+ - Rewrite using different syntax
149
+ - "Fix" perceived issues in the command
150
+ - Expand aliases or shortcuts
151
+ - Strip or modify escape characters (backslashes, quotes)
152
+ - Convert `\"` to `"` or `\'` to `'`
153
+ - Remove or change any escaping sequences
154
+
155
+ The ONLY allowed change is replacing `{placeholder}` tokens with their
156
+ resolved values. Everything else must remain character-for-character
157
+ identical to what the user wrote in their skill definition.
158
+
159
+ **PRESERVE ALL CHARACTERS**: If the skill has `x=\"y\"`, output `x=\"y\"`.
160
+ If it has `path/to/file\ with\ spaces`, keep it exactly as written.
161
+ Escape sequences are intentional - do not "clean" or "simplify" them.
139
162
 
140
163
  ## Response Format
141
164
 
@@ -350,50 +373,86 @@ For complex multi-step operations:
350
373
  4. **Error handling**: For non-critical cleanup steps, set critical:
351
374
  false
352
375
 
376
+ ## Handling Config Placeholders
377
+
378
+ When substituting parameter placeholders in skill commands:
379
+
380
+ 1. **Known values**: Replace `{PARAM}` with the actual value from task params
381
+ 2. **Unknown values**: If a placeholder value is not available in task params,
382
+ **keep the original `{placeholder}` syntax** in the command. Do NOT replace
383
+ it with `<UNKNOWN>` or any other marker.
384
+
385
+ **CRITICAL**: Never use `<UNKNOWN>`, `<MISSING>`, `<undefined>`, or similar
386
+ markers in commands. The `<` and `>` characters break shell syntax. Always
387
+ preserve the original `{placeholder}` format for unresolved values - this
388
+ allows the system to detect and prompt for missing configuration.
389
+
390
+ Example:
391
+ - Command template: `process.py --output {settings.output}`
392
+ - If `settings.output` is NOT in task params:
393
+ - WRONG: `process.py --output <UNKNOWN>`
394
+ - CORRECT: `process.py --output {settings.output}`
395
+
353
396
  ## Common Mistakes to Avoid
354
397
 
355
- Generating commands that don't match the task description
356
- Using platform-specific commands without consideration
357
- Forgetting to quote paths with spaces
358
- Setting unrealistic timeouts for long operations
359
- Running destructive commands without safeguards
360
- Ignoring task parameters when generating commands
361
- **CRITICAL: Inventing commands instead of using skill's Execution
362
- section**
363
- **CRITICAL: Ignoring params.skill and making up your own commands**
364
- **CRITICAL: Generating commands when the skill doesn't exist in
365
- Available Skills**
366
- Not substituting parameter placeholders in skill commands
367
- **CRITICAL: Assuming what commands to run when skill is missing**
368
-
369
- Match commands precisely to task descriptions
370
- Use task params to fill in specific values
371
- ✅ Quote all file paths properly
372
- ✅ Set appropriate timeouts for each operation type
373
- Include safety checks for destructive operations
374
- Generate portable commands when possible
375
- **CRITICAL: Verify skill exists in Available Skills before generating
376
- commands**
377
- **CRITICAL: Return error response if skill not found, never invent
378
- commands**
379
- Always use skill's Execution section when params.skill is present
380
- ✅ Replace all {PARAM} placeholders with values from task params
398
+ **DO NOT:**
399
+ - Generate commands that don't match the task description
400
+ - Use platform-specific commands without consideration
401
+ - Forget to quote paths with spaces
402
+ - Set unrealistic timeouts for long operations
403
+ - Run destructive commands without safeguards
404
+ - Ignore task parameters when generating commands
405
+ - **CRITICAL: Invent commands instead of using skill's Execution
406
+ section**
407
+ - **CRITICAL: Ignore params.skill and make up your own commands**
408
+ - **CRITICAL: Generate commands when the skill doesn't exist in
409
+ Available Skills**
410
+ - Fail to substitute parameter placeholders in skill commands
411
+ - **CRITICAL: Assume what commands to run when skill is missing**
412
+ - **CRITICAL: Replace unknown placeholders with `<UNKNOWN>` - this breaks
413
+ shell syntax**
414
+
415
+ **DO:**
416
+ - Match commands precisely to task descriptions
417
+ - Use task params to fill in specific values
418
+ - Quote all file paths properly
419
+ - Set appropriate timeouts for each operation type
420
+ - Include safety checks for destructive operations
421
+ - Generate portable commands when possible
422
+ - **CRITICAL: Verify skill exists in Available Skills before generating
423
+ commands**
424
+ - **CRITICAL: Return error response if skill not found, never invent
425
+ commands**
426
+ - Always use skill's Execution section when params.skill is present
427
+ - Replace all {PARAM} placeholders with values from task params
381
428
 
382
429
  ## Final Validation
383
430
 
384
431
  Before returning commands:
385
432
 
386
- 1. **CRITICAL: If tasks have params.skill, verify Available Skills
433
+ 1. **CRITICAL: Verify command count matches input task count** - you must
434
+ have exactly one command per input task
435
+ 2. **CRITICAL: If tasks have params.skill, verify Available Skills
387
436
  section exists**
388
- 2. **CRITICAL: If tasks have params.skill, verify the skill exists in
437
+ 3. **CRITICAL: If tasks have params.skill, verify the skill exists in
389
438
  Available Skills section**
390
- 3. **CRITICAL: If tasks have params.skill, verify the skill has both
439
+ 4. **CRITICAL: If tasks have params.skill, verify the skill has both
391
440
  Steps and Execution sections**
392
- 4. **CRITICAL: If any validation fails, return error response with empty
441
+ 5. **CRITICAL: If any validation fails, return error response with empty
393
442
  commands array**
394
- 5. Verify each command matches its task description
395
- 6. Check that all task params are incorporated
396
- 7. Ensure paths are properly quoted
397
- 8. Confirm timeouts are reasonable for each operation
398
- 9. Validate that critical flags are set appropriately
399
- 10. Review for any safety concerns
443
+ 6. Verify each command matches its task description
444
+ 7. Check that all task params are incorporated
445
+ 8. Ensure paths are properly quoted
446
+ 9. Confirm timeouts are reasonable for each operation
447
+ 10. Validate that critical flags are set appropriately
448
+ 11. Review for any safety concerns
449
+
450
+ ## Confirmed Schedule
451
+
452
+ CRITICAL: The user message contains the confirmed schedule that the user
453
+ has reviewed and approved. You MUST generate exactly one command per task
454
+ listed in the confirmed schedule. The number of commands in your response
455
+ MUST equal the number of tasks below. DO NOT add extra commands, DO NOT
456
+ skip tasks, and DO NOT split tasks into multiple commands.
457
+
458
+ Your response MUST contain exactly N commands corresponding to these N tasks.
@@ -64,7 +64,7 @@ capability list.
64
64
 
65
65
  ## Capabilities Structure
66
66
 
67
- **⚠️ CRITICAL ORDERING REQUIREMENT ⚠️**
67
+ **CRITICAL ORDERING REQUIREMENT**
68
68
 
69
69
  You MUST present capabilities in the EXACT order specified below. This is
70
70
  NON-NEGOTIABLE and applies to EVERY response.
@@ -81,20 +81,20 @@ NON-NEGOTIABLE and applies to EVERY response.
81
81
 
82
82
  These MUST appear FIRST, in this EXACT sequence:
83
83
 
84
- 1. **Introspect** ← ALWAYS FIRST
85
- 2. **Configure** ← ALWAYS SECOND
86
- 3. **Answer** ← ALWAYS THIRD
87
- 4. **Execute** ← ALWAYS FOURTH
84
+ 1. **Introspect**
85
+ 2. **Configure**
86
+ 3. **Answer**
87
+ 4. **Execute**
88
88
 
89
89
  ### Position 5-7: meta workflow capabilities (origin: "meta")
90
90
 
91
91
  These MUST appear AFTER Execute and BEFORE user-provided skills:
92
92
 
93
- 5. **Schedule** ← NEVER FIRST, ALWAYS position 5 (after Execute)
94
- 6. **Validate** ← ALWAYS position 6 (after Schedule)
95
- 7. **Report** ← NEVER FIRST, ALWAYS position 7 (after Validate)
93
+ 5. **Schedule**
94
+ 6. **Validate**
95
+ 7. **Report**
96
96
 
97
- ### 3. user-provided skills (origin: "user")
97
+ ### Position 8+: user-provided skills (origin: "user")
98
98
 
99
99
  If skills are provided in the "Available Skills" section below, include
100
100
  them in the response. For each skill:
@@ -325,12 +325,6 @@ even if they use the same action verb.
325
325
  - Task 2: "Process data" (skill-based with subtasks)
326
326
  - Task 3: "Explain Kubernetes" (type: answer)
327
327
 
328
- - "explain tdd, process files, explain tbd" → THREE separate task
329
- groups:
330
- - Task 1: "Explain Test-Driven Development" (type: answer)
331
- - Task 2: "Process files" (skill-based with subtasks)
332
- - Task 3: "Explain TBD" (type: answer)
333
-
334
328
  - "process files and validate" where only "process" has a skill →
335
329
  - Task 1: "Process files" (skill-based with subtasks)
336
330
  - Task 2: type "ignore" for unmatched "validate"
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Error codes for categorization and programmatic handling
3
+ */
4
+ export var ErrorCode;
5
+ (function (ErrorCode) {
6
+ // User errors - display to user, usually recoverable
7
+ ErrorCode["InvalidInput"] = "INVALID_INPUT";
8
+ ErrorCode["MissingConfig"] = "MISSING_CONFIG";
9
+ ErrorCode["SkillNotFound"] = "SKILL_NOT_FOUND";
10
+ // System errors - log + display, may be recoverable
11
+ ErrorCode["FileReadError"] = "FILE_READ_ERROR";
12
+ ErrorCode["FileWriteError"] = "FILE_WRITE_ERROR";
13
+ ErrorCode["NetworkError"] = "NETWORK_ERROR";
14
+ ErrorCode["ApiError"] = "API_ERROR";
15
+ ErrorCode["ParseError"] = "PARSE_ERROR";
16
+ // Fatal errors - must abort
17
+ ErrorCode["CircularReference"] = "CIRCULAR_REFERENCE";
18
+ ErrorCode["InvalidState"] = "INVALID_STATE";
19
+ ErrorCode["ConfigCorruption"] = "CONFIG_CORRUPTION";
20
+ })(ErrorCode || (ErrorCode = {}));
21
+ /**
22
+ * Base error class with cause chain support
23
+ * Provides consistent error structure throughout the application
24
+ */
25
+ export class AppError extends Error {
26
+ code;
27
+ cause;
28
+ constructor(message, code, cause) {
29
+ super(message);
30
+ this.code = code;
31
+ this.cause = cause;
32
+ this.name = 'AppError';
33
+ }
34
+ }
35
+ /**
36
+ * Type guard for AppError
37
+ */
38
+ export function isAppError(error) {
39
+ return error instanceof AppError;
40
+ }
41
+ /**
42
+ * Helper to wrap unknown errors with context
43
+ */
44
+ export function wrapError(error, code, message) {
45
+ const cause = error instanceof Error ? error : undefined;
46
+ return new AppError(message, code, cause);
47
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Create a successful result
3
+ */
4
+ export function ok(value) {
5
+ return { ok: true, value };
6
+ }
7
+ /**
8
+ * Create a failed result
9
+ */
10
+ export function err(error) {
11
+ return { ok: false, error };
12
+ }
13
+ /**
14
+ * Unwrap a result, throwing if it's an error
15
+ */
16
+ export function unwrap(result) {
17
+ if (result.ok)
18
+ return result.value;
19
+ throw result.error;
20
+ }
21
+ /**
22
+ * Map the value of a successful result
23
+ */
24
+ export function mapResult(result, fn) {
25
+ if (result.ok)
26
+ return ok(fn(result.value));
27
+ return result;
28
+ }
29
+ /**
30
+ * Check if a result is successful
31
+ */
32
+ export function isOk(result) {
33
+ return result.ok;
34
+ }
35
+ /**
36
+ * Check if a result is an error
37
+ */
38
+ export function isErr(result) {
39
+ return !result.ok;
40
+ }
@@ -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 { createScheduleDefinition } from '../services/components.js';
7
+ import { createSchedule } from '../services/components.js';
8
8
  import { useInput } from '../services/keyboard.js';
9
9
  import { formatErrorMessage } from '../services/messages.js';
10
10
  import { handleRefinement } from '../services/refinement.js';
@@ -77,12 +77,16 @@ export function Command({ command, status, service, requestHandlers, lifecycleHa
77
77
  // Check if tasks contain DEFINE type (variant selection needed)
78
78
  const hasDefineTask = result.tasks.some((task) => task.type === TaskType.Define);
79
79
  // Create Schedule definition
80
- const scheduleDefinition = createScheduleDefinition(result.message, result.tasks, hasDefineTask
81
- ? async (selectedTasks) => {
82
- // Refinement flow for DEFINE tasks
83
- await handleRefinement(selectedTasks, svc, command, lifecycleHandlers, workflowHandlers, requestHandlers);
84
- }
85
- : undefined);
80
+ const scheduleDefinition = createSchedule({
81
+ message: result.message,
82
+ tasks: result.tasks,
83
+ onSelectionConfirmed: hasDefineTask
84
+ ? async (selectedTasks) => {
85
+ // Refinement flow for DEFINE tasks
86
+ await handleRefinement(selectedTasks, svc, command, lifecycleHandlers, workflowHandlers, requestHandlers);
87
+ }
88
+ : undefined,
89
+ });
86
90
  if (hasDefineTask) {
87
91
  // DEFINE tasks: Move Command to timeline, add Schedule to queue
88
92
  lifecycleHandlers.completeActive();
@@ -1,12 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { memo } from 'react';
3
+ import { ComponentStatus, } from '../types/components.js';
3
4
  import { ComponentName } from '../types/types.js';
4
5
  import { Answer, AnswerView } from './Answer.js';
5
6
  import { Command, CommandView } from './Command.js';
6
7
  import { Config, ConfigView } from './Config.js';
7
8
  import { Confirm, ConfirmView } from './Confirm.js';
8
9
  import { Debug } from './Debug.js';
9
- import { Execute, ExecuteView } from './Execute.js';
10
+ import { Execute, ExecuteView, mapStateToViewProps } from './Execute.js';
10
11
  import { Feedback } from './Feedback.js';
11
12
  import { Introspect, IntrospectView } from './Introspect.js';
12
13
  import { Message } from './Message.js';
@@ -107,8 +108,10 @@ export const ViewComponent = memo(function ViewComponent({ def, }) {
107
108
  return (_jsx(ScheduleView, { message: message, tasks: tasks, state: state, status: status }));
108
109
  }
109
110
  case ComponentName.Execute: {
110
- const { props: { tasks }, state, status, } = def;
111
- return _jsx(ExecuteView, { tasks: tasks, state: state, status: status });
111
+ const { state, status } = def;
112
+ const isActive = status === ComponentStatus.Active;
113
+ const viewProps = mapStateToViewProps(state, isActive);
114
+ return _jsx(ExecuteView, { ...viewProps });
112
115
  }
113
116
  case ComponentName.Answer: {
114
117
  const { props: { question }, state, status, } = def;
package/dist/ui/Config.js CHANGED
@@ -208,7 +208,10 @@ export function Config(props) {
208
208
  }
209
209
  else {
210
210
  // Fallback: complete with abort feedback directly
211
- lifecycleHandlers.completeActive(createFeedback(FeedbackType.Aborted, 'Configuration cancelled.'));
211
+ lifecycleHandlers.completeActive(createFeedback({
212
+ type: FeedbackType.Aborted,
213
+ message: 'Configuration cancelled.',
214
+ }));
212
215
  }
213
216
  return;
214
217
  }
@@ -272,12 +275,15 @@ export function Config(props) {
272
275
  onFinished(newValues);
273
276
  }
274
277
  // Success - complete with success feedback
275
- lifecycleHandlers.completeActive(createFeedback(FeedbackType.Succeeded, 'Configuration saved successfully.'));
278
+ lifecycleHandlers.completeActive(createFeedback({
279
+ type: FeedbackType.Succeeded,
280
+ message: 'Configuration saved successfully.',
281
+ }));
276
282
  }
277
283
  catch (error) {
278
284
  // Failure - complete with error feedback
279
285
  const errorMessage = error instanceof Error ? error.message : 'Configuration failed';
280
- lifecycleHandlers.completeActive(createFeedback(FeedbackType.Failed, errorMessage));
286
+ lifecycleHandlers.completeActive(createFeedback({ type: FeedbackType.Failed, message: errorMessage }));
281
287
  }
282
288
  setStep(steps.length);
283
289
  }