prompt-language-shell 0.6.6 → 0.7.0

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 (33) hide show
  1. package/dist/index.js +2 -1
  2. package/dist/services/anthropic.js +21 -2
  3. package/dist/services/components.js +11 -0
  4. package/dist/services/configuration.js +23 -5
  5. package/dist/services/logger.js +64 -0
  6. package/dist/services/messages.js +17 -2
  7. package/dist/services/{skill-parser.js → parser.js} +34 -15
  8. package/dist/services/refinement.js +5 -1
  9. package/dist/services/{tool-registry.js → registry.js} +14 -24
  10. package/dist/services/{task-router.js → router.js} +29 -21
  11. package/dist/services/skills.js +165 -17
  12. package/dist/services/{execution-validator.js → validator.js} +6 -8
  13. package/dist/{config/ANSWER.md → skills/answer.md} +10 -9
  14. package/dist/{config/CONFIG.md → skills/config.md} +16 -9
  15. package/dist/{config/EXECUTE.md → skills/execute.md} +91 -53
  16. package/dist/{config/INTROSPECT.md → skills/introspect.md} +63 -47
  17. package/dist/{config/PLAN.md → skills/plan.md} +419 -337
  18. package/dist/{config/VALIDATE.md → skills/validate.md} +26 -12
  19. package/dist/types/types.js +1 -0
  20. package/dist/ui/Command.js +5 -1
  21. package/dist/ui/Component.js +3 -0
  22. package/dist/ui/Config.js +3 -2
  23. package/dist/ui/Debug.js +8 -0
  24. package/dist/ui/Execute.js +2 -2
  25. package/dist/ui/Introspect.js +3 -2
  26. package/dist/ui/Main.js +19 -5
  27. package/dist/ui/Plan.js +3 -2
  28. package/dist/ui/Validate.js +8 -2
  29. package/dist/ui/Workflow.js +2 -1
  30. package/package.json +2 -2
  31. package/dist/services/skill-expander.js +0 -87
  32. /package/dist/services/{config-loader.js → loader.js} +0 -0
  33. /package/dist/services/{placeholder-resolver.js → resolver.js} +0 -0
@@ -1,7 +1,42 @@
1
1
  import { existsSync, readdirSync, readFileSync } from 'fs';
2
2
  import { homedir } from 'os';
3
3
  import { join } from 'path';
4
- import { parseSkillMarkdown } from './skill-parser.js';
4
+ import { getUnknownSkillMessage } from './messages.js';
5
+ import { parseSkillMarkdown, displayNameToKey } from './parser.js';
6
+ /**
7
+ * Built-in skill names that user skills cannot override
8
+ */
9
+ const BUILT_IN_SKILLS = new Set([
10
+ 'plan',
11
+ 'execute',
12
+ 'answer',
13
+ 'config',
14
+ 'validate',
15
+ 'introspect',
16
+ ]);
17
+ /**
18
+ * Validate filename follows kebab-case pattern
19
+ * Valid: deploy-app.md, build-project-2.md, copy-files.md
20
+ * Invalid: Deploy_App.md, buildProject.md, DEPLOY.md, file name.md
21
+ */
22
+ export function isValidSkillFilename(filename) {
23
+ // Must end with .md or .MD extension
24
+ if (!filename.endsWith('.md') && !filename.endsWith('.MD')) {
25
+ return false;
26
+ }
27
+ // Extract name without extension
28
+ const name = filename.slice(0, -3);
29
+ // Must match kebab-case pattern: lowercase letters, numbers, and hyphens only
30
+ // Must start with a letter, and not start or end with a hyphen
31
+ const kebabCasePattern = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
32
+ return kebabCasePattern.test(name);
33
+ }
34
+ /**
35
+ * Check if skill key conflicts with built-in skills
36
+ */
37
+ export function conflictsWithBuiltIn(key) {
38
+ return BUILT_IN_SKILLS.has(key);
39
+ }
5
40
  /**
6
41
  * Get the path to the skills directory
7
42
  */
@@ -10,7 +45,8 @@ export function getSkillsDirectory() {
10
45
  }
11
46
  /**
12
47
  * Load all skill markdown files from the skills directory
13
- * Returns an array of skill file contents
48
+ * Returns an array of objects with filename (key) and content
49
+ * Filters out invalid filenames and conflicts with built-in skills
14
50
  */
15
51
  export function loadSkills() {
16
52
  const skillsDir = getSkillsDirectory();
@@ -20,12 +56,27 @@ export function loadSkills() {
20
56
  }
21
57
  try {
22
58
  const files = readdirSync(skillsDir);
23
- // Filter for markdown files
24
- const skillFiles = files.filter((file) => file.endsWith('.md') || file.endsWith('.MD'));
25
- // Read and return contents of each skill file
26
- return skillFiles.map((file) => {
59
+ // Filter and map valid skill files
60
+ return files
61
+ .filter((file) => {
62
+ // Must follow kebab-case naming convention
63
+ if (!isValidSkillFilename(file)) {
64
+ return false;
65
+ }
66
+ // Extract key (filename without extension, handles both .md and .MD)
67
+ const key = file.slice(0, -3);
68
+ // Must not conflict with built-in skills
69
+ if (conflictsWithBuiltIn(key)) {
70
+ return false;
71
+ }
72
+ return true;
73
+ })
74
+ .map((file) => {
75
+ // Extract key (filename without extension, handles both .md and .MD)
76
+ const key = file.slice(0, -3);
27
77
  const filePath = join(skillsDir, file);
28
- return readFileSync(filePath, 'utf-8');
78
+ const content = readFileSync(filePath, 'utf-8');
79
+ return { key, content };
29
80
  });
30
81
  }
31
82
  catch {
@@ -38,17 +89,17 @@ export function loadSkills() {
38
89
  * Returns structured skill definitions (including invalid skills)
39
90
  */
40
91
  export function loadSkillDefinitions() {
41
- const skillContents = loadSkills();
42
- return skillContents.map((content) => parseSkillMarkdown(content));
92
+ const skills = loadSkills();
93
+ return skills.map(({ key, content }) => parseSkillMarkdown(key, content));
43
94
  }
44
95
  /**
45
96
  * Load skills and mark incomplete ones in their markdown
46
97
  * Returns array of skill markdown with status markers
47
98
  */
48
99
  export function loadSkillsWithValidation() {
49
- const skillContents = loadSkills();
50
- return skillContents.map((content) => {
51
- const parsed = parseSkillMarkdown(content);
100
+ const skills = loadSkills();
101
+ return skills.map(({ key, content }) => {
102
+ const parsed = parseSkillMarkdown(key, content);
52
103
  // If skill is incomplete (either validation failed or needs more documentation), append (INCOMPLETE) to the name
53
104
  if (parsed.isIncomplete) {
54
105
  return content.replace(/^(#{1,6}\s+Name\s*\n+)(.+?)(\n|$)/im, `$1$2 (INCOMPLETE)$3`);
@@ -58,13 +109,19 @@ export function loadSkillsWithValidation() {
58
109
  }
59
110
  /**
60
111
  * Create skill lookup function from definitions
112
+ * Lookup by key (display name is converted to kebab-case for matching)
113
+ * Example: "Deploy App" -> "deploy-app" -> matches skill with key "deploy-app"
61
114
  */
62
115
  export function createSkillLookup(definitions) {
63
- const map = new Map();
116
+ const keyMap = new Map();
64
117
  for (const definition of definitions) {
65
- map.set(definition.name, definition);
118
+ keyMap.set(definition.key, definition);
66
119
  }
67
- return (name) => map.get(name) || null;
120
+ return (name) => {
121
+ // Convert display name to kebab-case key for lookup
122
+ const key = displayNameToKey(name);
123
+ return keyMap.get(key) || null;
124
+ };
68
125
  }
69
126
  /**
70
127
  * Format skills for inclusion in the planning prompt
@@ -74,7 +131,6 @@ export function formatSkillsForPrompt(skills) {
74
131
  return '';
75
132
  }
76
133
  const header = `
77
-
78
134
  ## Available Skills
79
135
 
80
136
  The following skills define domain-specific workflows. When the user's
@@ -90,6 +146,98 @@ brackets for additional information. Use commas instead. For example:
90
146
  - WRONG: "Build project Alpha (the legacy version)"
91
147
 
92
148
  `;
93
- const skillsContent = skills.join('\n\n');
149
+ const skillsContent = skills.map((s) => s.trim()).join('\n\n');
94
150
  return header + skillsContent;
95
151
  }
152
+ /**
153
+ * Parse skill reference from execution line
154
+ * Format: [ Display Name ] with mandatory spaces
155
+ * Returns display name if line matches format, otherwise null
156
+ * Example: "[ My Skill ]" -> "My Skill"
157
+ */
158
+ export function parseSkillReference(line) {
159
+ // Must match format: [ content ] with at least one space before and after
160
+ const match = line.trim().match(/^\[\s+(.+?)\s+\]$/);
161
+ return match ? match[1] : null;
162
+ }
163
+ /**
164
+ * Check if execution line is a skill reference
165
+ * Must have format: [ content ] with spaces
166
+ */
167
+ export function isSkillReference(line) {
168
+ return /^\[\s+.+?\s+\]$/.test(line.trim());
169
+ }
170
+ /**
171
+ * Expand skill references in execution commands
172
+ * Returns expanded execution lines with references replaced
173
+ * Throws error if circular reference detected or skill not found
174
+ * Reference format: [ Skill Name ]
175
+ */
176
+ export function expandSkillReferences(execution, skillLookup, visited = new Set()) {
177
+ const expanded = [];
178
+ for (const line of execution) {
179
+ // First: Detect if line matches [ XXX ] format
180
+ const skillName = parseSkillReference(line);
181
+ if (!skillName) {
182
+ // Not a reference, keep command as-is
183
+ expanded.push(line);
184
+ continue;
185
+ }
186
+ // Check for circular reference
187
+ if (visited.has(skillName)) {
188
+ throw new Error(`Circular skill reference detected: ${Array.from(visited).join(' → ')} → ${skillName}`);
189
+ }
190
+ // Second: Match against skill name
191
+ const skill = skillLookup(skillName);
192
+ if (!skill) {
193
+ // Referenced skill not found - throw error to break execution
194
+ throw new Error(getUnknownSkillMessage(skillName));
195
+ }
196
+ // Recursively expand referenced skill's execution
197
+ const newVisited = new Set(visited);
198
+ newVisited.add(skillName);
199
+ const referencedExecution = expandSkillReferences(skill.execution, skillLookup, newVisited);
200
+ expanded.push(...referencedExecution);
201
+ }
202
+ return expanded;
203
+ }
204
+ /**
205
+ * Get all skill names referenced in execution (including nested)
206
+ * Returns unique set of skill names
207
+ */
208
+ export function getReferencedSkills(execution, skillLookup, visited = new Set()) {
209
+ const referenced = new Set();
210
+ for (const line of execution) {
211
+ const skillName = parseSkillReference(line);
212
+ if (!skillName || visited.has(skillName)) {
213
+ continue;
214
+ }
215
+ referenced.add(skillName);
216
+ const skill = skillLookup(skillName);
217
+ if (skill) {
218
+ const newVisited = new Set(visited);
219
+ newVisited.add(skillName);
220
+ const nested = getReferencedSkills(skill.execution, skillLookup, newVisited);
221
+ for (const name of nested) {
222
+ referenced.add(name);
223
+ }
224
+ }
225
+ }
226
+ return referenced;
227
+ }
228
+ /**
229
+ * Validate skill references don't form cycles
230
+ * Returns true if valid, false if circular reference detected
231
+ */
232
+ export function validateNoCycles(execution, skillLookup, visited = new Set()) {
233
+ try {
234
+ expandSkillReferences(execution, skillLookup, visited);
235
+ return true;
236
+ }
237
+ catch (error) {
238
+ if (error instanceof Error && error.message.includes('Circular')) {
239
+ return false;
240
+ }
241
+ throw error;
242
+ }
243
+ }
@@ -1,8 +1,7 @@
1
- import { extractPlaceholders, pathToString, resolveVariant, } from './placeholder-resolver.js';
2
- import { loadUserConfig, hasConfigPath } from './config-loader.js';
3
- import { loadSkills } from './skills.js';
4
- import { expandSkillReferences } from './skill-expander.js';
5
- import { getConfigType, parseSkillMarkdown } from './skill-parser.js';
1
+ import { extractPlaceholders, pathToString, resolveVariant, } from './resolver.js';
2
+ import { loadUserConfig, hasConfigPath } from './loader.js';
3
+ import { loadSkillDefinitions, createSkillLookup, expandSkillReferences, } from './skills.js';
4
+ import { getConfigType } from './parser.js';
6
5
  /**
7
6
  * Validate config requirements for execute tasks
8
7
  * Returns validation result with missing config and validation errors
@@ -14,9 +13,8 @@ export function validateExecuteTasks(tasks) {
14
13
  const validationErrors = [];
15
14
  const seenSkills = new Set();
16
15
  // Load all skills (including invalid ones for validation)
17
- const skillContents = loadSkills();
18
- const parsedSkills = skillContents.map((content) => parseSkillMarkdown(content));
19
- const skillLookup = (name) => parsedSkills.find((s) => s.name === name) || null;
16
+ const parsedSkills = loadSkillDefinitions();
17
+ const skillLookup = createSkillLookup(parsedSkills);
20
18
  // Check for invalid skills being used in tasks
21
19
  for (const task of tasks) {
22
20
  const skillName = typeof task.params?.skill === 'string' ? task.params.skill : null;
@@ -5,9 +5,9 @@ command-line concierge. Your role is to **answer questions** and provide
5
5
  up-to-date information when a task with type "answer" has been planned and
6
6
  confirmed.
7
7
 
8
- **IMPORTANT**: Use web search to find current, accurate information. This tool
9
- is designed for quick answers from the terminal without needing to open a web
10
- browser. Always search for the latest data rather than relying solely on
8
+ **IMPORTANT**: Use web search to find current, accurate information. This
9
+ tool is designed for quick answers from the terminal without needing to open a
10
+ web browser. Always search for the latest data rather than relying solely on
11
11
  training data.
12
12
 
13
13
  ## Execution Flow
@@ -60,11 +60,11 @@ TypeScript code compiles to JavaScript and runs anywhere JavaScript runs.
60
60
 
61
61
  Bad answer (too verbose):
62
62
  ```
63
- TypeScript is a strongly typed programming language that builds on JavaScript,
64
- giving you better tooling at any scale. TypeScript adds additional syntax to
65
- JavaScript to support a tighter integration with your editor. It catches errors
66
- early in development by checking types. TypeScript code converts to JavaScript
67
- which runs anywhere.
63
+ TypeScript is a strongly typed programming language that builds on
64
+ JavaScript, giving you better tooling at any scale. TypeScript adds
65
+ additional syntax to JavaScript to support a tighter integration with your
66
+ editor. It catches errors early in development by checking types. TypeScript
67
+ code converts to JavaScript which runs anywhere.
68
68
  ```
69
69
 
70
70
  ### Example 2: Technical explanation
@@ -101,7 +101,8 @@ They enable cleaner, more reusable component logic.
101
101
 
102
102
  ## Guidelines
103
103
 
104
- 1. **Be direct**: Answer the question immediately, don't introduce your answer
104
+ 1. **Be direct**: Answer the question immediately, don't introduce your
105
+ answer
105
106
  2. **Be accurate**: Provide correct, factual information
106
107
  3. **Be concise**: Respect the 4-line, 80-character constraints strictly
107
108
  4. **Be helpful**: Focus on what the user needs to know
@@ -1,33 +1,40 @@
1
1
  ## Overview
2
2
 
3
- You are the CONFIG tool for "pls" (please), a professional command-line concierge.
4
- Your role is to determine which configuration settings the user wants to configure
5
- based on their query.
3
+ You are the CONFIG tool for "pls" (please), a professional command-line
4
+ concierge. Your role is to determine which configuration settings the user
5
+ wants to configure based on their query.
6
6
 
7
7
  ## Input
8
8
 
9
9
  You will receive:
10
- - `configStructure`: Object mapping config keys to descriptions (e.g., {"anthropic.key": "Anthropic API key", "settings.debug": "Debug mode (optional)"})
11
- - `configuredKeys`: Array of keys that exist in the user's config file (e.g., ["anthropic.key", "anthropic.model", "settings.debug"])
10
+ - `configStructure`: Object mapping config keys to descriptions (e.g.,
11
+ {"anthropic.key": "Anthropic API key", "settings.debug": "Debug mode
12
+ (optional)"})
13
+ - `configuredKeys`: Array of keys that exist in the user's config file
14
+ (e.g., ["anthropic.key", "anthropic.model", "settings.debug"])
12
15
  - `query`: User's request (e.g., "app", "mode", "anthropic", or empty)
13
16
 
14
17
  ## Task
15
18
 
16
- Determine which config keys the user wants to configure and return them as tasks.
19
+ Determine which config keys the user wants to configure and return them
20
+ as tasks.
17
21
 
18
22
  ## Mapping Rules
19
23
 
20
24
  ### Query: "app" or empty/unclear
21
25
  - Return all **required** config keys (those needed for the app to work)
22
- - Also include any keys marked as "(optional)" that appear in `configuredKeys` (optional settings that exist in user's config file)
23
- - Also include any keys marked as "(discovered)" (they exist in user's config file but aren't in schema)
26
+ - Also include any keys marked as "(optional)" that appear in
27
+ `configuredKeys` (optional settings that exist in user's config file)
28
+ - Also include any keys marked as "(discovered)" (they exist in user's
29
+ config file but aren't in schema)
24
30
  - Required keys: `anthropic.key`, `anthropic.model`
25
31
 
26
32
  ### Query: "mode"
27
33
  - Return only: `settings.debug`
28
34
 
29
35
  ### Query: "anthropic"
30
- - Return all keys starting with `anthropic.` (usually `anthropic.key` and `anthropic.model`)
36
+ - Return all keys starting with `anthropic.` (usually `anthropic.key` and
37
+ `anthropic.model`)
31
38
 
32
39
  ### Other queries
33
40
  - Match the query against config key names and descriptions
@@ -1,8 +1,8 @@
1
1
  ## Overview
2
2
 
3
- You are the execution component of "pls" (please), a professional command-line
4
- concierge. Your role is to **execute shell commands** and operations when tasks
5
- with type "execute" have been planned and confirmed.
3
+ You are the execution component of "pls" (please), a professional
4
+ command-line concierge. Your role is to **execute shell commands** and
5
+ operations when tasks with type "execute" have been planned and confirmed.
6
6
 
7
7
  ## Execution Flow
8
8
 
@@ -11,23 +11,23 @@ This tool is invoked AFTER:
11
11
  2. User reviewed and confirmed the plan
12
12
  3. The execute tasks are now being executed
13
13
 
14
- Your task is to translate the planned actions into specific shell commands that
15
- can be run in the terminal.
14
+ Your task is to translate the planned actions into specific shell commands
15
+ that can be run in the terminal.
16
16
 
17
17
  ## Input
18
18
 
19
19
  You will receive:
20
20
  - An array of tasks with their actions and parameters
21
- - Each task describes what needs to be done (e.g., "Create a new file called
22
- test.txt", "List files in the current directory")
21
+ - Each task describes what needs to be done (e.g., "Create a new file
22
+ called test.txt", "List files in the current directory")
23
23
  - Tasks may include params with specific values (paths, filenames, etc.)
24
- - Tasks from user-defined skills include params.skill (skill name) and parameter
25
- values that were substituted into the action
24
+ - Tasks from user-defined skills include params.skill (skill name) and
25
+ parameter values that were substituted into the action
26
26
 
27
27
  ## Skill-Based Command Generation
28
28
 
29
- **CRITICAL**: When tasks originate from a user-defined skill, you MUST use the
30
- skill's **Execution** section to generate commands, NOT invent your own.
29
+ **CRITICAL**: When tasks originate from a user-defined skill, you MUST use
30
+ the skill's **Execution** section to generate commands, NOT invent your own.
31
31
 
32
32
  ### Understanding Skill Structure
33
33
 
@@ -35,16 +35,18 @@ User-defined skills have two key sections:
35
35
  - **Steps**: Describes WHAT to do (shown to user as task actions)
36
36
  - **Execution**: Describes HOW to do it (actual shell commands)
37
37
 
38
- Each line in Steps corresponds to a line in Execution at the same position.
38
+ Each line in Steps corresponds to a line in Execution at the same
39
+ position.
39
40
 
40
41
  ### How to Generate Commands from Skills
41
42
 
42
43
  1. **Identify skill tasks**: Check if tasks have params.skill
43
- 2. **Find the skill**: Look up the skill in "Available Skills" section below
44
+ 2. **Find the skill**: Look up the skill in "Available Skills" section
45
+ below
44
46
  3. **Match tasks to Execution**: Each task action came from a Steps line;
45
47
  use the corresponding Execution line for the command
46
- 4. **Substitute parameters**: Replace {PARAM} placeholders with actual values
47
- from task params
48
+ 4. **Substitute parameters**: Replace {PARAM} placeholders with actual
49
+ values from task params
48
50
 
49
51
  ### Example Skill
50
52
 
@@ -59,8 +61,8 @@ Process Data
59
61
 
60
62
  ### Execution
61
63
  - curl -O https://data.example.com/{SOURCE}.csv
62
- - python3 transform.py --input {SOURCE}.csv --output processed.csv
63
- - csvtool col 1-3 processed.csv > output.{FORMAT}
64
+ - python3 transform.py --input {SOURCE}.csv --output data.csv
65
+ - csvtool col 1-3 data.csv > output.{FORMAT}
64
66
  ```
65
67
 
66
68
  ### Matching Process
@@ -77,9 +79,9 @@ Given tasks from this skill:
77
79
  Do NOT invent different commands - use exactly what the skill specifies,
78
80
  with parameter placeholders replaced by actual values.
79
81
 
80
- **CRITICAL**: Take the exact command from the ### Execution section. Do not
81
- modify, improve, or rewrite the command in any way. The user wrote these
82
- commands specifically for their environment and workflow.
82
+ **CRITICAL**: Take the exact command from the ### Execution section. Do
83
+ not modify, improve, or rewrite the command in any way. The user wrote
84
+ these commands specifically for their environment and workflow.
83
85
 
84
86
  ## Response Format
85
87
 
@@ -90,9 +92,11 @@ Return a structured response with commands to execute:
90
92
  - **commands**: Array of command objects to execute sequentially
91
93
 
92
94
  **Command object structure:**
93
- - **description**: Brief description of what this command does (max 64 chars)
95
+ - **description**: Brief description of what this command does (max 64
96
+ chars)
94
97
  - **command**: The exact shell command to run
95
- - **workdir**: Optional working directory for the command (defaults to current)
98
+ - **workdir**: Optional working directory for the command (defaults to
99
+ current)
96
100
  - **timeout**: Optional timeout in milliseconds (defaults to 30000)
97
101
  - **critical**: Whether failure should stop execution (defaults to true)
98
102
 
@@ -101,24 +105,31 @@ Return a structured response with commands to execute:
101
105
  When generating commands:
102
106
 
103
107
  1. **Be precise**: Generate exact, runnable shell commands
104
- 2. **Be safe**: Never generate destructive commands without explicit user intent
105
- 3. **Use parameters**: Extract values from task params and incorporate them
108
+ 2. **Be safe**: Never generate destructive commands without explicit user
109
+ intent
110
+ 3. **Use parameters**: Extract values from task params and incorporate
111
+ them
106
112
  4. **Handle paths**: Use proper quoting for paths with spaces
107
113
  5. **Be portable**: Prefer POSIX-compatible commands when possible
108
114
 
109
115
  **Safety rules:**
110
116
  - NEVER run `rm -rf /` or any command that could delete system files
111
- - NEVER run commands that modify system configuration without explicit request
117
+ - NEVER run commands that modify system configuration without explicit
118
+ request
112
119
  - NEVER expose sensitive information in command output
113
- - Always use safe defaults (e.g., prefer `rm -i` over `rm -f` for deletions)
120
+ - Always use safe defaults (e.g., prefer `rm -i` over `rm -f` for
121
+ deletions)
114
122
  - For file deletions, prefer moving to trash over permanent deletion
115
123
 
116
124
  ## Examples
117
125
 
118
126
  ### Example 1: Simple file creation
119
127
 
120
- Task: { action: "Create a new file called test.txt", type: "execute",
121
- params: { filename: "test.txt" } }
128
+ Task: {
129
+ action: "Create a new file called test.txt",
130
+ type: "execute",
131
+ params: { filename: "test.txt" }
132
+ }
122
133
 
123
134
  Response:
124
135
  ```
@@ -130,7 +141,10 @@ commands:
130
141
 
131
142
  ### Example 2: Directory listing
132
143
 
133
- Task: { action: "Show files in the current directory", type: "execute" }
144
+ Task: {
145
+ action: "Show files in the current directory",
146
+ type: "execute"
147
+ }
134
148
 
135
149
  Response:
136
150
  ```
@@ -143,8 +157,11 @@ commands:
143
157
  ### Example 3: Multiple sequential commands
144
158
 
145
159
  Tasks:
146
- - { action: "Create project directory", type: "execute",
147
- params: { path: "my-project" } }
160
+ - {
161
+ action: "Create project directory",
162
+ type: "execute",
163
+ params: { path: "my-project" }
164
+ }
148
165
  - { action: "Initialize git repository", type: "execute" }
149
166
  - { action: "Create README file", type: "execute" }
150
167
 
@@ -164,7 +181,10 @@ commands:
164
181
 
165
182
  ### Example 4: Install dependencies
166
183
 
167
- Task: { action: "Install dependencies", type: "execute" }
184
+ Task: {
185
+ action: "Install dependencies",
186
+ type: "execute"
187
+ }
168
188
 
169
189
  Response:
170
190
  ```
@@ -177,20 +197,30 @@ commands:
177
197
 
178
198
  ### Example 5: Skill-based execution
179
199
 
180
- When executing from a skill like "Process Data", tasks include params.skill:
200
+ When executing from a skill like "Process Data", tasks include
201
+ params.skill:
181
202
 
182
203
  Tasks:
183
- - { action: "Load the sales dataset", type: "execute",
184
- params: { skill: "Process Data", source: "sales", format: "json" } }
185
- - { action: "Transform the sales data", type: "execute",
186
- params: { skill: "Process Data", source: "sales", format: "json" } }
187
- - { action: "Export the results to json", type: "execute",
188
- params: { skill: "Process Data", source: "sales", format: "json" } }
204
+ - {
205
+ action: "Load the sales dataset",
206
+ type: "execute",
207
+ params: { skill: "Process Data", source: "sales", format: "json" }
208
+ }
209
+ - {
210
+ action: "Transform the sales data",
211
+ type: "execute",
212
+ params: { skill: "Process Data", source: "sales", format: "json" }
213
+ }
214
+ - {
215
+ action: "Export the results to json",
216
+ type: "execute",
217
+ params: { skill: "Process Data", source: "sales", format: "json" }
218
+ }
189
219
 
190
220
  The "Process Data" skill's Execution section specifies:
191
221
  - Line 1: curl -O https://data.example.com/{SOURCE}.csv
192
- - Line 2: python3 transform.py --input {SOURCE}.csv --output processed.csv
193
- - Line 3: csvtool col 1-3 processed.csv > output.{FORMAT}
222
+ - Line 2: python3 transform.py --input {SOURCE}.csv --output data.csv
223
+ - Line 3: csvtool col 1-3 data.csv > output.{FORMAT}
194
224
 
195
225
  Response (using skill's Execution commands):
196
226
  ```
@@ -200,19 +230,23 @@ commands:
200
230
  command: "curl -O https://data.example.com/sales.csv"
201
231
  timeout: 60000
202
232
  - description: "Transform the sales data"
203
- command: "python3 transform.py --input sales.csv --output processed.csv"
233
+ command: "python3 transform.py --input sales.csv --output data.csv"
204
234
  timeout: 120000
205
235
  - description: "Export the results to json"
206
- command: "csvtool col 1-3 processed.csv > output.json"
236
+ command: "csvtool col 1-3 data.csv > output.json"
207
237
  ```
208
238
 
209
- Note: Commands come directly from the skill's Execution section, with {SOURCE}
210
- replaced by "sales" and {FORMAT} replaced by "json" from task params.
239
+ Note: Commands come directly from the skill's Execution section, with
240
+ {SOURCE} replaced by "sales" and {FORMAT} replaced by "json" from task
241
+ params.
211
242
 
212
243
  ### Example 6: File operations with paths
213
244
 
214
- Task: { action: "Copy config to backup", type: "execute",
215
- params: { source: "~/.config/app", destination: "~/.config/app.backup" } }
245
+ Task: {
246
+ action: "Copy config to backup",
247
+ type: "execute",
248
+ params: { source: "~/.config/app", destination: "~/.config/app.backup" }
249
+ }
216
250
 
217
251
  Response:
218
252
  ```
@@ -224,7 +258,10 @@ commands:
224
258
 
225
259
  ### Example 7: Checking system information
226
260
 
227
- Task: { action: "Check disk space", type: "execute" }
261
+ Task: {
262
+ action: "Check disk space",
263
+ type: "execute"
264
+ }
228
265
 
229
266
  Response:
230
267
  ```
@@ -240,11 +277,12 @@ For complex multi-step operations:
240
277
 
241
278
  1. **Sequential dependencies**: Mark early commands as critical so failure
242
279
  stops the chain
243
- 2. **Long-running processes**: Set appropriate timeouts (build processes may
244
- need 10+ minutes)
245
- 3. **Working directories**: Use workdir to ensure commands run in the right
246
- location
247
- 4. **Error handling**: For non-critical cleanup steps, set critical: false
280
+ 2. **Long-running processes**: Set appropriate timeouts (build processes
281
+ may need 10+ minutes)
282
+ 3. **Working directories**: Use workdir to ensure commands run in the
283
+ right location
284
+ 4. **Error handling**: For non-critical cleanup steps, set critical:
285
+ false
248
286
 
249
287
  ## Common Mistakes to Avoid
250
288