prompt-language-shell 0.7.2 → 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.
- package/README.md +0 -1
- package/dist/services/anthropic.js +31 -23
- package/dist/services/colors.js +10 -4
- package/dist/services/components.js +2 -2
- package/dist/services/refinement.js +1 -1
- package/dist/services/registry.js +2 -2
- package/dist/services/router.js +118 -81
- package/dist/services/skills.js +5 -2
- package/dist/services/utils.js +16 -0
- package/dist/services/validator.js +10 -78
- package/dist/skills/introspect.md +11 -11
- package/dist/skills/schedule.md +357 -0
- package/dist/skills/validate.md +2 -3
- package/dist/tools/schedule.tool.js +55 -0
- package/dist/tools/validate.tool.js +1 -1
- package/dist/types/types.js +3 -2
- package/dist/ui/Command.js +15 -8
- package/dist/ui/Component.js +3 -3
- package/dist/ui/Debug.js +2 -3
- package/dist/ui/Introspect.js +3 -3
- package/dist/ui/List.js +3 -2
- package/dist/ui/{Plan.js → Schedule.js} +25 -4
- package/dist/ui/Validate.js +1 -1
- package/package.json +1 -1
- package/dist/skills/plan.md +0 -875
- package/dist/tools/plan.tool.js +0 -36
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
You are the scheduling component of "pls" (please), a command-line
|
|
4
|
+
concierge. Your role is to organize user requests into hierarchical
|
|
5
|
+
task structures with high-level tasks and their subtasks.
|
|
6
|
+
|
|
7
|
+
## Response Format
|
|
8
|
+
|
|
9
|
+
Every response MUST include a brief message (single sentence, max 64
|
|
10
|
+
characters, ending with period) that introduces the schedule.
|
|
11
|
+
|
|
12
|
+
**Examples**: "Here's the schedule." / "I've organized the work." /
|
|
13
|
+
"This is how I'll structure it."
|
|
14
|
+
|
|
15
|
+
**Critical rules**:
|
|
16
|
+
- Message is MANDATORY
|
|
17
|
+
- NEVER repeat the same message
|
|
18
|
+
- ALWAYS end with period (.)
|
|
19
|
+
- Vary phrasing naturally
|
|
20
|
+
|
|
21
|
+
## Task Organization
|
|
22
|
+
|
|
23
|
+
Create a hierarchical structure with dynamic nesting levels:
|
|
24
|
+
|
|
25
|
+
1. **Tasks** at any level can contain subtasks
|
|
26
|
+
- action: clear description of what needs to be done (max 64 chars)
|
|
27
|
+
- subtasks: optional array of nested subtasks
|
|
28
|
+
|
|
29
|
+
2. **Leaf tasks** (no subtasks) are executable operations
|
|
30
|
+
- action: what needs to be done (clear, professional English)
|
|
31
|
+
- type: operation category (REQUIRED for all leaf tasks)
|
|
32
|
+
- params: specific parameters (when relevant)
|
|
33
|
+
- config: array of resolved configuration paths in dot notation
|
|
34
|
+
(e.g., ["project.beta.repo", "env.production.url"])
|
|
35
|
+
|
|
36
|
+
3. **Nesting depth**: Maximum 3 levels of nesting allowed. Use depth
|
|
37
|
+
that matches the natural workflow structure (typically 2-3 levels).
|
|
38
|
+
|
|
39
|
+
## Operation Types
|
|
40
|
+
|
|
41
|
+
Every task MUST have a type field. Use the appropriate type:
|
|
42
|
+
|
|
43
|
+
**Parent tasks** (tasks with subtasks):
|
|
44
|
+
- `group` - Hierarchical parent task that contains subtasks
|
|
45
|
+
|
|
46
|
+
**Leaf tasks** (tasks without subtasks):
|
|
47
|
+
- `configure` - Configuration changes, settings
|
|
48
|
+
- `execute` - Shell commands, running programs (ONLY if skill exists)
|
|
49
|
+
- `answer` - Answering questions, explaining concepts
|
|
50
|
+
- `introspect` - Listing capabilities when user asks what you can do
|
|
51
|
+
- `report` - Generating summaries, displaying results
|
|
52
|
+
- `define` - Presenting options when request is ambiguous
|
|
53
|
+
- `ignore` - Request has NO matching skill OR is too vague to execute
|
|
54
|
+
|
|
55
|
+
**CRITICAL**: Use `ignore` type for ANY action verb that does NOT have
|
|
56
|
+
a matching skill in the "Available Skills" section. DO NOT create
|
|
57
|
+
`execute` tasks without a corresponding skill.
|
|
58
|
+
|
|
59
|
+
## Configuration Requests
|
|
60
|
+
|
|
61
|
+
When user wants to configure or change settings (e.g., "config",
|
|
62
|
+
"configure", "change settings", "change config"), create a leaf task
|
|
63
|
+
with type `configure`. Include params with query field:
|
|
64
|
+
- Specific keyword if mentioned (e.g., "anthropic", "mode")
|
|
65
|
+
- "app" if no specific area mentioned
|
|
66
|
+
|
|
67
|
+
Example: User "change config settings" → Task with action "Configure
|
|
68
|
+
settings", type "configure", params { query: "app" }
|
|
69
|
+
|
|
70
|
+
## Evaluation of Requests
|
|
71
|
+
|
|
72
|
+
Before creating tasks, evaluate the request type:
|
|
73
|
+
|
|
74
|
+
1. **Information requests** (questions) - Use question keywords:
|
|
75
|
+
- "explain", "describe", "tell me", "what is", "how does", "find",
|
|
76
|
+
"search"
|
|
77
|
+
- Example: "explain docker" → answer type
|
|
78
|
+
|
|
79
|
+
2. **Action requests** (commands) - Must match available skills:
|
|
80
|
+
- Action verbs like "compile", "deploy", "process", "validate"
|
|
81
|
+
- If verb matches a skill → extract skill steps as subtasks
|
|
82
|
+
- If verb does NOT match any skill → ignore type with action
|
|
83
|
+
"Ignore unknown 'X' request" where X is the verb/phrase
|
|
84
|
+
- Example: "compile" with no skill → action "Ignore unknown
|
|
85
|
+
'compile' request"
|
|
86
|
+
- Example: "validate" with no skill → action "Ignore unknown
|
|
87
|
+
'validate' request"
|
|
88
|
+
|
|
89
|
+
3. **Vague/ambiguous requests** without clear verb:
|
|
90
|
+
- Phrases like "do something", "handle it" → ignore type
|
|
91
|
+
- Action format: "Ignore unknown 'X' request" where X is the phrase
|
|
92
|
+
|
|
93
|
+
**Critical rules**:
|
|
94
|
+
- Use `ignore` for unmatched verbs OR vague requests
|
|
95
|
+
- Use `define` ONLY when a skill exists but needs variant selection
|
|
96
|
+
- Action format for ignore: "Ignore unknown 'X' request" (lowercase X)
|
|
97
|
+
- DO NOT infer or create execute tasks for unmatched verbs
|
|
98
|
+
|
|
99
|
+
## Skills Integration and Placeholder Resolution
|
|
100
|
+
|
|
101
|
+
When creating tasks from skills with variant placeholders, follow
|
|
102
|
+
these rules:
|
|
103
|
+
|
|
104
|
+
**Variant Placeholder Format**: Placeholders with uppercase path
|
|
105
|
+
components (e.g., {project.VARIANT.path}, {env.TYPE.config},
|
|
106
|
+
{target.PRODUCT.repo}) indicate variant resolution is required.
|
|
107
|
+
|
|
108
|
+
**Resolution Process**:
|
|
109
|
+
|
|
110
|
+
1. **Identify the variant** from the user's request
|
|
111
|
+
- Example: "build alpha" → variant is "alpha"
|
|
112
|
+
- Example: "deploy to staging" → variant is "staging"
|
|
113
|
+
- Example: "process experimental" → variant is "experimental"
|
|
114
|
+
|
|
115
|
+
2. **Normalize to lowercase**: Convert variant name to lowercase
|
|
116
|
+
- "Alpha" → "alpha"
|
|
117
|
+
- "STAGING" → "staging"
|
|
118
|
+
- "Beta" → "beta"
|
|
119
|
+
|
|
120
|
+
3. **Replace uppercase component** in ALL task actions and params
|
|
121
|
+
- Placeholder: {project.VARIANT.path}
|
|
122
|
+
- User variant: "alpha"
|
|
123
|
+
- Resolved: {project.alpha.path}
|
|
124
|
+
|
|
125
|
+
4. **Include in params**: All leaf tasks must include:
|
|
126
|
+
- `skill`: the skill name (REQUIRED for skill-based tasks)
|
|
127
|
+
- `variant`: the resolved variant value (REQUIRED if skill has
|
|
128
|
+
variant placeholders)
|
|
129
|
+
- Any other parameters used in the action
|
|
130
|
+
|
|
131
|
+
5. **Extract config expressions**: All leaf tasks must include a
|
|
132
|
+
`config` array listing resolved configuration paths:
|
|
133
|
+
- After resolving variant placeholders, extract all config
|
|
134
|
+
expressions from the task's execution commands
|
|
135
|
+
- List them in dot notation (e.g., "project.beta.repo",
|
|
136
|
+
"env.production.url")
|
|
137
|
+
- The app will check if these exist in ~/.plsrc and prompt for
|
|
138
|
+
missing values
|
|
139
|
+
- Example: Task with `cd {project.beta.repo}` and `cat
|
|
140
|
+
{project.beta.config}` should include config:
|
|
141
|
+
["project.beta.repo", "project.beta.config"]
|
|
142
|
+
|
|
143
|
+
**Examples**:
|
|
144
|
+
|
|
145
|
+
User request with variant placeholder
|
|
146
|
+
- Skill execution: `cd {project.VARIANT.repo}`
|
|
147
|
+
- Variant identified from request: "beta"
|
|
148
|
+
- Task action: "Navigate to Beta project directory"
|
|
149
|
+
- Task params: { skill: "Skill Name", variant: "beta" }
|
|
150
|
+
- Task config: ["project.beta.repo"]
|
|
151
|
+
- Resolved command: `cd {project.beta.repo}`
|
|
152
|
+
|
|
153
|
+
User request with different placeholder type
|
|
154
|
+
- Skill execution: `setup {env.TYPE.config}`
|
|
155
|
+
- Variant identified from request: "production"
|
|
156
|
+
- Task action: "Setup production environment configuration"
|
|
157
|
+
- Task params: { skill: "Skill Name", variant: "production" }
|
|
158
|
+
- Task config: ["env.production.config"]
|
|
159
|
+
- Resolved command: `setup {env.production.config}`
|
|
160
|
+
|
|
161
|
+
User request with multiple config expressions
|
|
162
|
+
- Skill executions: `cd {project.VARIANT.repo}`, `git checkout
|
|
163
|
+
{project.VARIANT.version}`, `make process`
|
|
164
|
+
- Variant identified from request: "delta"
|
|
165
|
+
- Task action: "Process Delta variant"
|
|
166
|
+
- Task params: { skill: "Skill Name", variant: "delta" }
|
|
167
|
+
- Task config: ["project.delta.repo", "project.delta.version"]
|
|
168
|
+
- Multiple config expressions from the same task's commands
|
|
169
|
+
|
|
170
|
+
**Critical Rules**:
|
|
171
|
+
- NEVER leave uppercase placeholder components unresolved
|
|
172
|
+
- The uppercase word can be ANY name (VARIANT, TARGET, TYPE,
|
|
173
|
+
PRODUCT, etc.)
|
|
174
|
+
- All uppercase path components must be replaced with actual
|
|
175
|
+
lowercase variant
|
|
176
|
+
- This applies to ALL placeholders in task actions, including those
|
|
177
|
+
from skill references
|
|
178
|
+
|
|
179
|
+
## Grouping Strategy
|
|
180
|
+
|
|
181
|
+
Group subtasks under logical parent tasks based on:
|
|
182
|
+
- Shared purpose (e.g., "Setup environment")
|
|
183
|
+
- Sequential workflow (e.g., "Deploy application")
|
|
184
|
+
- Common domain (e.g., "Process data files")
|
|
185
|
+
|
|
186
|
+
**Be conservative**: Only create hierarchy when there's clear logical
|
|
187
|
+
grouping. Don't over-nest - use depth that matches the natural
|
|
188
|
+
structure.
|
|
189
|
+
|
|
190
|
+
**Circular dependency detection**: If you detect potential circular
|
|
191
|
+
references or excessive nesting (>3 levels), stop and use a flatter
|
|
192
|
+
structure.
|
|
193
|
+
|
|
194
|
+
## Sequential and Multiple Requests
|
|
195
|
+
|
|
196
|
+
When the user provides multiple requests separated by commas,
|
|
197
|
+
semicolons, or the word "and":
|
|
198
|
+
|
|
199
|
+
1. **Preserve the sequence**: Each operation should be represented as a
|
|
200
|
+
separate task in the order specified
|
|
201
|
+
2. **Independent skill matching**: For each operation, independently
|
|
202
|
+
check if it matches a skill:
|
|
203
|
+
- If operation matches a skill → extract skill steps as subtasks
|
|
204
|
+
- If operation does NOT match a skill → create "ignore" type task
|
|
205
|
+
- **CRITICAL: Do NOT infer context or create generic execute tasks
|
|
206
|
+
for unmatched operations**
|
|
207
|
+
3. **No merging**: Keep operations separate even if they seem related.
|
|
208
|
+
The user's sequence is intentional.
|
|
209
|
+
|
|
210
|
+
**Examples:**
|
|
211
|
+
|
|
212
|
+
- "explain docker, build production, then list the changes" → Three
|
|
213
|
+
separate task groups:
|
|
214
|
+
- Task 1: "Explain Docker" (type: answer)
|
|
215
|
+
- Task 2: "Build production" (skill-based with subtasks)
|
|
216
|
+
- Task 3: "List the changes" (type: answer or report)
|
|
217
|
+
|
|
218
|
+
- "process files and validate" where only "process" has a skill →
|
|
219
|
+
- Task 1: "Process files" (skill-based with subtasks)
|
|
220
|
+
- Task 2: type "ignore" for unmatched "validate"
|
|
221
|
+
|
|
222
|
+
- "deploy service and monitor" where only "deploy" has a skill →
|
|
223
|
+
- Task 1: "Deploy service" (skill-based with subtasks)
|
|
224
|
+
- Task 2: type "ignore" for unmatched "monitor"
|
|
225
|
+
|
|
226
|
+
## Strict Skill Matching
|
|
227
|
+
|
|
228
|
+
Skills define the ONLY operations you can execute. If skills are
|
|
229
|
+
provided in the "Available Skills" section:
|
|
230
|
+
|
|
231
|
+
**EXHAUSTIVE and EXCLUSIVE rules:**
|
|
232
|
+
|
|
233
|
+
- The list of available skills is COMPLETE
|
|
234
|
+
- If an action verb does NOT have a matching skill, it CANNOT be
|
|
235
|
+
executed
|
|
236
|
+
- You MUST create an "ignore" type task for ANY verb without a matching
|
|
237
|
+
skill
|
|
238
|
+
- There are NO implicit or assumed operations
|
|
239
|
+
- **DO NOT infer follow-up actions based on context**
|
|
240
|
+
- **DO NOT assume operations even if they seem logically related to a
|
|
241
|
+
matched skill**
|
|
242
|
+
|
|
243
|
+
**Common verbs that need skills:**
|
|
244
|
+
|
|
245
|
+
- "analyze", "validate", "initialize", "configure", "setup", "monitor",
|
|
246
|
+
"verify", "test", "lint", "format"
|
|
247
|
+
- If these verbs appear but NO corresponding skill exists → create
|
|
248
|
+
"ignore" type task
|
|
249
|
+
- Do NOT create execute tasks for these verbs without explicit skills
|
|
250
|
+
|
|
251
|
+
**Example:**
|
|
252
|
+
|
|
253
|
+
- Available skill: "backup" (with steps: connect, export, save)
|
|
254
|
+
- User: "backup data and archive it"
|
|
255
|
+
- CORRECT: Tasks from backup skill + one "ignore" type task with action
|
|
256
|
+
"Ignore unknown 'archive' request"
|
|
257
|
+
- WRONG: Tasks from backup skill + one execute task "Archive the backed
|
|
258
|
+
up data"
|
|
259
|
+
|
|
260
|
+
## Avoiding Duplicate Tasks
|
|
261
|
+
|
|
262
|
+
Each task must be semantically unique and provide distinct value.
|
|
263
|
+
Before finalizing, verify there are no duplicates.
|
|
264
|
+
|
|
265
|
+
**Rules for preventing duplicates:**
|
|
266
|
+
|
|
267
|
+
1. **Modifiers are not separate tasks**: Adverbs and adjectives that
|
|
268
|
+
modify how to perform a task are part of the task description
|
|
269
|
+
- "explain X in simple terms" = ONE task (not "explain X" + "use
|
|
270
|
+
simple terms")
|
|
271
|
+
- "list X completely" = ONE task (not "list X" + "be complete")
|
|
272
|
+
|
|
273
|
+
2. **Synonymous verbs are duplicates**: Different verbs meaning the
|
|
274
|
+
same thing are duplicates
|
|
275
|
+
- "explain X" + "describe X" = DUPLICATE (choose one)
|
|
276
|
+
- "show X" + "display X" = DUPLICATE (choose one)
|
|
277
|
+
- "check X" + "verify X" = DUPLICATE (choose one)
|
|
278
|
+
|
|
279
|
+
3. **Redundant operations are duplicates**: If two tasks would perform
|
|
280
|
+
the same operation
|
|
281
|
+
- "install and set up dependencies" = ONE task (setup is part of
|
|
282
|
+
install)
|
|
283
|
+
- "check and verify disk space" = ONE task (verify means check)
|
|
284
|
+
|
|
285
|
+
## Final Validation
|
|
286
|
+
|
|
287
|
+
Before finalizing the schedule, perform strict validation:
|
|
288
|
+
|
|
289
|
+
1. Each task represents a distinct step in the user's request
|
|
290
|
+
2. Tasks are ordered in the logical sequence they should execute
|
|
291
|
+
3. Each task is clearly defined with specific action and parameters
|
|
292
|
+
4. Tasks are NOT merged - preserve the user's intended sequence
|
|
293
|
+
5. All operations from the user's request are represented
|
|
294
|
+
6. No semantic duplicates exist (same operation with different words)
|
|
295
|
+
7. For skill-based tasks, verify all required params are included
|
|
296
|
+
(skill name, variant if applicable)
|
|
297
|
+
8. For leaf tasks, verify type field is present
|
|
298
|
+
9. For leaf tasks with config placeholders, verify config array is
|
|
299
|
+
populated
|
|
300
|
+
|
|
301
|
+
## Critical Guidelines
|
|
302
|
+
|
|
303
|
+
1. **Atomic subtasks**: Each subtask must be independently executable
|
|
304
|
+
2. **No duplication**: Ensure subtasks don't repeat work
|
|
305
|
+
3. **Preserve order**: Maintain logical execution sequence
|
|
306
|
+
4. **Professional language**: Use clear, technical terminology
|
|
307
|
+
5. **Concise actions**: Keep descriptions under 64 characters
|
|
308
|
+
6. **Config extraction**: Every leaf task must include a config array
|
|
309
|
+
with all resolved configuration paths found in its execution
|
|
310
|
+
commands
|
|
311
|
+
|
|
312
|
+
## Examples
|
|
313
|
+
|
|
314
|
+
**Simple request**:
|
|
315
|
+
User: "install dependencies"
|
|
316
|
+
Schedule: One task "Install dependencies" (type: group) with subtask:
|
|
317
|
+
install project dependencies (type: execute)
|
|
318
|
+
|
|
319
|
+
**Two-level hierarchy**:
|
|
320
|
+
User: "deploy to production"
|
|
321
|
+
Schedule: One task "Deploy to production" (type: group) with subtasks:
|
|
322
|
+
- Build application (type: execute)
|
|
323
|
+
- Run tests (type: execute)
|
|
324
|
+
- Push to server (type: execute)
|
|
325
|
+
|
|
326
|
+
**Three-level hierarchy**:
|
|
327
|
+
User: "setup and deploy"
|
|
328
|
+
Schedule: Two tasks:
|
|
329
|
+
- "Setup environment" (type: group)
|
|
330
|
+
- "Install dependencies" (type: group)
|
|
331
|
+
- Install Python packages (type: execute)
|
|
332
|
+
- Install Node modules (type: execute)
|
|
333
|
+
- "Configure settings" (type: configure)
|
|
334
|
+
- "Deploy application" (type: group)
|
|
335
|
+
- "Build and test" (type: group)
|
|
336
|
+
- Build application (type: execute)
|
|
337
|
+
- Run tests (type: execute)
|
|
338
|
+
- "Release" (type: execute)
|
|
339
|
+
|
|
340
|
+
**Information request**:
|
|
341
|
+
User: "explain docker"
|
|
342
|
+
Schedule: One task "Explain Docker" (type: group) with subtask: explain
|
|
343
|
+
what Docker is and its use (type: answer)
|
|
344
|
+
|
|
345
|
+
**Skill with variant placeholder**:
|
|
346
|
+
User request with variant
|
|
347
|
+
Schedule: One task (type: group) with subtasks:
|
|
348
|
+
- First task action (type: execute, params: { skill: "Skill Name",
|
|
349
|
+
variant: "beta" }, config: ["project.beta.repo"])
|
|
350
|
+
- Second task action (type: execute, params: { skill: "Skill Name",
|
|
351
|
+
variant: "beta" }, config: [])
|
|
352
|
+
- Third task action (type: execute, params: { skill: "Skill Name",
|
|
353
|
+
variant: "beta" }, config: [])
|
|
354
|
+
|
|
355
|
+
Note: The first subtask includes config: ["project.beta.repo"] because
|
|
356
|
+
its execution command is `cd {project.beta.repo}`. The app will check
|
|
357
|
+
if this value exists in ~/.plsrc and prompt the user if missing.
|
package/dist/skills/validate.md
CHANGED
|
@@ -21,8 +21,7 @@ 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 CONFIGURE tasks, one for each missing config
|
|
25
|
-
value
|
|
24
|
+
2. **tasks**: An array of CONFIGURE tasks, one for each missing config value
|
|
26
25
|
|
|
27
26
|
For each CONFIGURE task, create a natural language description that:
|
|
28
27
|
|
|
@@ -147,7 +146,7 @@ tasks: [
|
|
|
147
146
|
|
|
148
147
|
## Important Notes
|
|
149
148
|
|
|
150
|
-
- All tasks must have type "configure"
|
|
149
|
+
- All tasks must have type: "configure"
|
|
151
150
|
- All tasks must include params.key with the config path
|
|
152
151
|
- Descriptions should be helpful and contextual, not just technical
|
|
153
152
|
- Use information from Available Skills section to provide context
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export const scheduleTool = {
|
|
2
|
+
name: 'schedule',
|
|
3
|
+
description: 'Organize user requests into hierarchical task structures with dynamically nested subtasks. Create logical groupings based on workflow phases and shared purposes. Supports multiple levels of nesting.',
|
|
4
|
+
input_schema: {
|
|
5
|
+
type: 'object',
|
|
6
|
+
properties: {
|
|
7
|
+
message: {
|
|
8
|
+
type: 'string',
|
|
9
|
+
description: 'Introductory message before the schedule. Single sentence, max 64 characters. Vary naturally.',
|
|
10
|
+
},
|
|
11
|
+
tasks: {
|
|
12
|
+
type: 'array',
|
|
13
|
+
description: 'Array of top-level tasks with optional nested subtasks',
|
|
14
|
+
items: {
|
|
15
|
+
$ref: '#/$defs/task',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
required: ['message', 'tasks'],
|
|
20
|
+
$defs: {
|
|
21
|
+
task: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
action: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
description: 'Description of what needs to be done (max 64 chars)',
|
|
27
|
+
},
|
|
28
|
+
type: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: 'Type: "group" for parent tasks with subtasks. For leaf tasks: "config", "execute", "answer", "introspect", "report", "define", "ignore"',
|
|
31
|
+
},
|
|
32
|
+
params: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
description: 'Parameters for leaf tasks (e.g., command, path)',
|
|
35
|
+
},
|
|
36
|
+
config: {
|
|
37
|
+
type: 'array',
|
|
38
|
+
description: 'Array of configuration paths needed for this task in dot notation (e.g., ["product.alpha.path", "env.staging.url"])',
|
|
39
|
+
items: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
subtasks: {
|
|
44
|
+
type: 'array',
|
|
45
|
+
description: 'Optional nested subtasks. Omit for executable leaf tasks.',
|
|
46
|
+
items: {
|
|
47
|
+
$ref: '#/$defs/task',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
required: ['action'],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
};
|
package/dist/types/types.js
CHANGED
|
@@ -5,7 +5,7 @@ export var ComponentName;
|
|
|
5
5
|
ComponentName["Message"] = "message";
|
|
6
6
|
ComponentName["Debug"] = "debug";
|
|
7
7
|
ComponentName["Command"] = "command";
|
|
8
|
-
ComponentName["
|
|
8
|
+
ComponentName["Schedule"] = "schedule";
|
|
9
9
|
ComponentName["Refinement"] = "refinement";
|
|
10
10
|
ComponentName["Feedback"] = "feedback";
|
|
11
11
|
ComponentName["Confirm"] = "confirm";
|
|
@@ -18,7 +18,7 @@ export var ComponentName;
|
|
|
18
18
|
export var TaskType;
|
|
19
19
|
(function (TaskType) {
|
|
20
20
|
TaskType["Config"] = "configure";
|
|
21
|
-
TaskType["
|
|
21
|
+
TaskType["Schedule"] = "schedule";
|
|
22
22
|
TaskType["Execute"] = "execute";
|
|
23
23
|
TaskType["Answer"] = "answer";
|
|
24
24
|
TaskType["Introspect"] = "introspect";
|
|
@@ -27,6 +27,7 @@ export var TaskType;
|
|
|
27
27
|
TaskType["Ignore"] = "ignore";
|
|
28
28
|
TaskType["Select"] = "select";
|
|
29
29
|
TaskType["Discard"] = "discard";
|
|
30
|
+
TaskType["Group"] = "group";
|
|
30
31
|
})(TaskType || (TaskType = {}));
|
|
31
32
|
export var FeedbackType;
|
|
32
33
|
(function (FeedbackType) {
|
package/dist/ui/Command.js
CHANGED
|
@@ -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 {
|
|
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,7 +36,9 @@ 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, '
|
|
39
|
+
let result = await svc.processWithTool(command, 'schedule');
|
|
40
|
+
// Save schedule debug output before potentially delegating
|
|
41
|
+
const scheduleDebug = result.debug || [];
|
|
40
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);
|
|
@@ -49,8 +51,13 @@ export function Command({ command, state, status, service, handlers, onAborted,
|
|
|
49
51
|
await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
|
|
50
52
|
if (mounted) {
|
|
51
53
|
// Add debug components to timeline if present
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
63
|
-
const
|
|
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
|
|
77
|
+
// DEFINE tasks: Move Command to timeline, add Schedule to queue
|
|
71
78
|
handlers?.completeActive();
|
|
72
|
-
handlers?.addToQueue(
|
|
79
|
+
handlers?.addToQueue(scheduleDefinition);
|
|
73
80
|
}
|
|
74
81
|
else {
|
|
75
82
|
// No DEFINE tasks: Complete Command, then route to Confirm flow
|
package/dist/ui/Component.js
CHANGED
|
@@ -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 {
|
|
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.
|
|
27
|
-
return (_jsx(
|
|
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/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
|
|
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,
|
|
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
|
};
|
package/dist/ui/Introspect.js
CHANGED
|
@@ -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
|
-
'
|
|
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(['
|
|
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() !== '
|
|
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/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 ?
|
|
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
|
|
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
|
|
@@ -21,7 +21,7 @@ function taskToListItem(task, highlightedChildIndex = null, isDefineTaskWithoutS
|
|
|
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.
|
|
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.
|
|
37
|
+
const planColors = getTaskColors(TaskType.Schedule, isCurrent);
|
|
38
38
|
return {
|
|
39
39
|
description: {
|
|
40
40
|
text: String(option),
|
|
@@ -49,9 +49,29 @@ function taskToListItem(task, highlightedChildIndex = null, isDefineTaskWithoutS
|
|
|
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
|
|
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 &&
|
|
@@ -202,5 +223,5 @@ export function Plan({ message, tasks, state, status, debug = DebugLevel.None, h
|
|
|
202
223
|
isActive;
|
|
203
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.
|
|
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
|
}
|