prompt-language-shell 0.8.0 → 0.8.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/dist/services/anthropic.js +50 -37
- package/dist/services/colors.js +21 -1
- package/dist/services/components.js +6 -14
- package/dist/services/config-labels.js +75 -0
- package/dist/services/config-utils.js +20 -0
- package/dist/services/configuration.js +38 -59
- package/dist/services/filesystem.js +114 -0
- package/dist/services/loader.js +8 -5
- package/dist/services/logger.js +24 -0
- package/dist/services/parser.js +3 -1
- package/dist/services/refinement.js +9 -9
- package/dist/services/registry.js +1 -1
- package/dist/services/router.js +29 -28
- package/dist/services/skills.js +15 -14
- package/dist/services/validator.js +4 -3
- package/dist/skills/introspect.md +52 -43
- package/dist/skills/schedule.md +8 -3
- package/dist/tools/introspect.tool.js +18 -9
- package/dist/types/guards.js +23 -0
- package/dist/types/handlers.js +1 -0
- package/dist/types/schemas.js +103 -0
- package/dist/types/types.js +7 -0
- package/dist/ui/Answer.js +11 -15
- package/dist/ui/Command.js +24 -20
- package/dist/ui/Config.js +44 -32
- package/dist/ui/Confirm.js +9 -9
- package/dist/ui/Execute.js +265 -75
- package/dist/ui/Feedback.js +1 -0
- package/dist/ui/Introspect.js +16 -61
- package/dist/ui/Main.js +6 -6
- package/dist/ui/Report.js +4 -8
- package/dist/ui/Schedule.js +12 -12
- package/dist/ui/Spinner.js +3 -1
- package/dist/ui/Subtask.js +1 -1
- package/dist/ui/Task.js +7 -6
- package/dist/ui/Validate.js +28 -21
- package/dist/ui/Workflow.js +102 -30
- package/package.json +3 -2
package/dist/services/logger.js
CHANGED
|
@@ -6,6 +6,10 @@ import { Palette } from './colors.js';
|
|
|
6
6
|
* Logs information based on the current debug level setting
|
|
7
7
|
*/
|
|
8
8
|
let currentDebugLevel = DebugLevel.None;
|
|
9
|
+
/**
|
|
10
|
+
* Accumulated warnings to be displayed in the timeline
|
|
11
|
+
*/
|
|
12
|
+
const warnings = [];
|
|
9
13
|
/**
|
|
10
14
|
* Initialize the logger with the current debug level from config
|
|
11
15
|
*/
|
|
@@ -24,6 +28,26 @@ export function setDebugLevel(debug) {
|
|
|
24
28
|
export function getDebugLevel() {
|
|
25
29
|
return currentDebugLevel;
|
|
26
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Store a warning message to be displayed in the timeline
|
|
33
|
+
* Only stores warnings at Info or Verbose debug levels
|
|
34
|
+
*/
|
|
35
|
+
export function displayWarning(message, error) {
|
|
36
|
+
if (currentDebugLevel === DebugLevel.None) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const errorDetails = error instanceof Error ? `: ${error.message}` : '';
|
|
40
|
+
warnings.push(`${message}${errorDetails}`);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get all accumulated warnings and clear the list
|
|
44
|
+
* Returns array of warning messages
|
|
45
|
+
*/
|
|
46
|
+
export function getWarnings() {
|
|
47
|
+
const result = [...warnings];
|
|
48
|
+
warnings.length = 0;
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
27
51
|
/**
|
|
28
52
|
* Create debug component for system prompts sent to the LLM
|
|
29
53
|
* Only creates at Verbose level
|
package/dist/services/parser.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import YAML from 'yaml';
|
|
2
|
+
import { displayWarning } from './logger.js';
|
|
2
3
|
/**
|
|
3
4
|
* Validate a skill without parsing it fully
|
|
4
5
|
* Returns validation error if skill is invalid, null if valid
|
|
@@ -188,7 +189,8 @@ function parseConfigSchema(content) {
|
|
|
188
189
|
}
|
|
189
190
|
return parsed;
|
|
190
191
|
}
|
|
191
|
-
catch {
|
|
192
|
+
catch (error) {
|
|
193
|
+
displayWarning('Failed to parse config schema in skill', error);
|
|
192
194
|
return undefined;
|
|
193
195
|
}
|
|
194
196
|
}
|
|
@@ -5,12 +5,12 @@ import { routeTasksWithConfirm } from './router.js';
|
|
|
5
5
|
* Handle refinement flow for DEFINE tasks
|
|
6
6
|
* Called when user selects options from a plan with DEFINE tasks
|
|
7
7
|
*/
|
|
8
|
-
export async function handleRefinement(selectedTasks, service, originalCommand,
|
|
8
|
+
export async function handleRefinement(selectedTasks, service, originalCommand, queueHandlers, lifecycleHandlers, workflowHandlers, errorHandlers) {
|
|
9
9
|
// Create and add refinement component to queue
|
|
10
10
|
const refinementDef = createRefinement(getRefiningMessage(), (operation) => {
|
|
11
|
-
|
|
11
|
+
errorHandlers.onAborted(operation);
|
|
12
12
|
});
|
|
13
|
-
|
|
13
|
+
queueHandlers.addToQueue(refinementDef);
|
|
14
14
|
try {
|
|
15
15
|
// Build refined command from selected tasks
|
|
16
16
|
const refinedCommand = selectedTasks
|
|
@@ -23,18 +23,18 @@ export async function handleRefinement(selectedTasks, service, originalCommand,
|
|
|
23
23
|
// Call LLM to refine plan with selected tasks
|
|
24
24
|
const refinedResult = await service.processWithTool(refinedCommand, 'schedule');
|
|
25
25
|
// Complete the Refinement component
|
|
26
|
-
|
|
26
|
+
lifecycleHandlers.completeActive();
|
|
27
27
|
// Add debug components to timeline if present
|
|
28
|
-
if (refinedResult.debug
|
|
29
|
-
|
|
28
|
+
if (refinedResult.debug?.length) {
|
|
29
|
+
workflowHandlers.addToTimeline(...refinedResult.debug);
|
|
30
30
|
}
|
|
31
31
|
// Route refined tasks to appropriate components
|
|
32
|
-
routeTasksWithConfirm(refinedResult.tasks, refinedResult.message, service, originalCommand,
|
|
32
|
+
routeTasksWithConfirm(refinedResult.tasks, refinedResult.message, service, originalCommand, queueHandlers, workflowHandlers, errorHandlers, false // No DEFINE tasks in refined result
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
catch (err) {
|
|
36
|
-
|
|
36
|
+
lifecycleHandlers.completeActive();
|
|
37
37
|
const errorMessage = formatErrorMessage(err);
|
|
38
|
-
|
|
38
|
+
errorHandlers.onError(errorMessage);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -32,7 +32,7 @@ class ToolRegistry {
|
|
|
32
32
|
}
|
|
33
33
|
// Create singleton instance
|
|
34
34
|
export const toolRegistry = new ToolRegistry();
|
|
35
|
-
// Register
|
|
35
|
+
// Register system tools
|
|
36
36
|
import { answerTool } from '../tools/answer.tool.js';
|
|
37
37
|
import { configureTool } from '../tools/configure.tool.js';
|
|
38
38
|
import { executeTool } from '../tools/execute.tool.js';
|
package/dist/services/router.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asScheduledTasks } from '../types/guards.js';
|
|
1
2
|
import { FeedbackType, TaskType } from '../types/types.js';
|
|
2
3
|
import { createAnswerDefinition, createConfigDefinitionWithKeys, createConfirmDefinition, createExecuteDefinition, createFeedback, createIntrospectDefinition, createMessage, createScheduleDefinition, createValidateDefinition, } from './components.js';
|
|
3
4
|
import { saveConfig, unflattenConfig } from './configuration.js';
|
|
@@ -19,7 +20,7 @@ export function getOperationName(tasks) {
|
|
|
19
20
|
* Route tasks to appropriate components with Confirm flow
|
|
20
21
|
* Handles the complete flow: Plan → Confirm → Execute/Answer/Introspect
|
|
21
22
|
*/
|
|
22
|
-
export function routeTasksWithConfirm(tasks, message, service, userRequest,
|
|
23
|
+
export function routeTasksWithConfirm(tasks, message, service, userRequest, queueHandlers, workflowHandlers, errorHandlers, hasDefineTask = false) {
|
|
23
24
|
if (tasks.length === 0)
|
|
24
25
|
return;
|
|
25
26
|
// Filter out ignore and discard tasks early
|
|
@@ -27,7 +28,7 @@ export function routeTasksWithConfirm(tasks, message, service, userRequest, hand
|
|
|
27
28
|
// Check if no valid tasks remain after filtering
|
|
28
29
|
if (validTasks.length === 0) {
|
|
29
30
|
const message = createMessage(getUnknownRequestMessage());
|
|
30
|
-
|
|
31
|
+
queueHandlers.addToQueue(message);
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
34
|
const operation = getOperationName(validTasks);
|
|
@@ -35,7 +36,7 @@ export function routeTasksWithConfirm(tasks, message, service, userRequest, hand
|
|
|
35
36
|
// Has DEFINE tasks - add Schedule to queue for user selection
|
|
36
37
|
// Refinement flow will call this function again with refined tasks
|
|
37
38
|
const scheduleDefinition = createScheduleDefinition(message, validTasks);
|
|
38
|
-
|
|
39
|
+
queueHandlers.addToQueue(scheduleDefinition);
|
|
39
40
|
}
|
|
40
41
|
else {
|
|
41
42
|
// No DEFINE tasks - Schedule auto-completes and adds Confirm to queue
|
|
@@ -46,17 +47,17 @@ export function routeTasksWithConfirm(tasks, message, service, userRequest, hand
|
|
|
46
47
|
// Schedule completed - add Confirm to queue
|
|
47
48
|
const confirmDefinition = createConfirmDefinition(() => {
|
|
48
49
|
// User confirmed - complete both Confirm and Schedule, then route to appropriate component
|
|
49
|
-
|
|
50
|
-
executeTasksAfterConfirm(validTasks, service, userRequest,
|
|
50
|
+
workflowHandlers.completeActiveAndPending();
|
|
51
|
+
executeTasksAfterConfirm(validTasks, service, userRequest, queueHandlers, errorHandlers);
|
|
51
52
|
}, () => {
|
|
52
53
|
// User cancelled - complete both Confirm and Schedule, then show cancellation
|
|
53
|
-
|
|
54
|
+
workflowHandlers.completeActiveAndPending();
|
|
54
55
|
const message = getCancellationMessage(operation);
|
|
55
|
-
|
|
56
|
+
queueHandlers.addToQueue(createFeedback(FeedbackType.Aborted, message));
|
|
56
57
|
});
|
|
57
|
-
|
|
58
|
+
queueHandlers.addToQueue(confirmDefinition);
|
|
58
59
|
});
|
|
59
|
-
|
|
60
|
+
queueHandlers.addToQueue(scheduleDefinition);
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
/**
|
|
@@ -66,8 +67,8 @@ export function routeTasksWithConfirm(tasks, message, service, userRequest, hand
|
|
|
66
67
|
function validateTaskTypes(tasks) {
|
|
67
68
|
if (tasks.length === 0)
|
|
68
69
|
return;
|
|
69
|
-
//
|
|
70
|
-
const scheduledTasks = tasks;
|
|
70
|
+
// Convert to ScheduledTask to access subtasks property
|
|
71
|
+
const scheduledTasks = asScheduledTasks(tasks);
|
|
71
72
|
// Check each Group task's subtasks for uniform types
|
|
72
73
|
for (const task of scheduledTasks) {
|
|
73
74
|
if (task.type === TaskType.Group &&
|
|
@@ -87,16 +88,16 @@ function validateTaskTypes(tasks) {
|
|
|
87
88
|
* Validates task types and routes each type appropriately
|
|
88
89
|
* Supports mixed types at top level with Groups
|
|
89
90
|
*/
|
|
90
|
-
function executeTasksAfterConfirm(tasks, service, userRequest,
|
|
91
|
+
function executeTasksAfterConfirm(tasks, service, userRequest, queueHandlers, errorHandlers) {
|
|
91
92
|
// Validate task types (Groups must have uniform subtasks)
|
|
92
93
|
try {
|
|
93
94
|
validateTaskTypes(tasks);
|
|
94
95
|
}
|
|
95
96
|
catch (error) {
|
|
96
|
-
|
|
97
|
+
errorHandlers.onError(error instanceof Error ? error.message : String(error));
|
|
97
98
|
return;
|
|
98
99
|
}
|
|
99
|
-
const scheduledTasks = tasks;
|
|
100
|
+
const scheduledTasks = asScheduledTasks(tasks);
|
|
100
101
|
// Process tasks in order, preserving Group boundaries
|
|
101
102
|
// Track consecutive standalone tasks to group them by type
|
|
102
103
|
let consecutiveStandaloneTasks = [];
|
|
@@ -116,7 +117,7 @@ function executeTasksAfterConfirm(tasks, service, userRequest, handlers) {
|
|
|
116
117
|
const taskType = type;
|
|
117
118
|
if (typeTasks.length === 0)
|
|
118
119
|
continue;
|
|
119
|
-
routeTasksByType(taskType, typeTasks, service, userRequest,
|
|
120
|
+
routeTasksByType(taskType, typeTasks, service, userRequest, queueHandlers, errorHandlers);
|
|
120
121
|
}
|
|
121
122
|
consecutiveStandaloneTasks = [];
|
|
122
123
|
};
|
|
@@ -129,7 +130,7 @@ function executeTasksAfterConfirm(tasks, service, userRequest, handlers) {
|
|
|
129
130
|
if (task.subtasks.length > 0) {
|
|
130
131
|
const subtasks = task.subtasks;
|
|
131
132
|
const taskType = subtasks[0].type;
|
|
132
|
-
routeTasksByType(taskType, subtasks, service, userRequest,
|
|
133
|
+
routeTasksByType(taskType, subtasks, service, userRequest, queueHandlers, errorHandlers);
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
else {
|
|
@@ -144,22 +145,22 @@ function executeTasksAfterConfirm(tasks, service, userRequest, handlers) {
|
|
|
144
145
|
* Route tasks by type to appropriate components
|
|
145
146
|
* Extracted to allow reuse for both Groups and standalone tasks
|
|
146
147
|
*/
|
|
147
|
-
function routeTasksByType(taskType, typeTasks, service, userRequest,
|
|
148
|
+
function routeTasksByType(taskType, typeTasks, service, userRequest, queueHandlers, errorHandlers) {
|
|
148
149
|
if (taskType === TaskType.Answer) {
|
|
149
150
|
// Create separate Answer component for each question
|
|
150
151
|
for (const task of typeTasks) {
|
|
151
|
-
|
|
152
|
+
queueHandlers.addToQueue(createAnswerDefinition(task.action, service));
|
|
152
153
|
}
|
|
153
154
|
}
|
|
154
155
|
else if (taskType === TaskType.Introspect) {
|
|
155
|
-
|
|
156
|
+
queueHandlers.addToQueue(createIntrospectDefinition(typeTasks, service));
|
|
156
157
|
}
|
|
157
158
|
else if (taskType === TaskType.Config) {
|
|
158
159
|
// Route to Config flow - extract keys from task params
|
|
159
160
|
const configKeys = typeTasks
|
|
160
161
|
.map((task) => task.params?.key)
|
|
161
162
|
.filter((key) => key !== undefined);
|
|
162
|
-
|
|
163
|
+
queueHandlers.addToQueue(createConfigDefinitionWithKeys(configKeys, (config) => {
|
|
163
164
|
// Save config - Config component will handle completion and feedback
|
|
164
165
|
try {
|
|
165
166
|
// Convert flat dotted keys to nested structure grouped by section
|
|
@@ -176,7 +177,7 @@ function routeTasksByType(taskType, typeTasks, service, userRequest, handlers) {
|
|
|
176
177
|
throw new Error(errorMessage);
|
|
177
178
|
}
|
|
178
179
|
}, (operation) => {
|
|
179
|
-
|
|
180
|
+
errorHandlers.onAborted(operation);
|
|
180
181
|
}));
|
|
181
182
|
}
|
|
182
183
|
else if (taskType === TaskType.Execute) {
|
|
@@ -191,26 +192,26 @@ function routeTasksByType(taskType, typeTasks, service, userRequest, handlers) {
|
|
|
191
192
|
.join('\n');
|
|
192
193
|
return `Invalid skill definition "${error.skill}":\n\n${issuesList}`;
|
|
193
194
|
});
|
|
194
|
-
|
|
195
|
+
queueHandlers.addToQueue(createFeedback(FeedbackType.Failed, errorMessages.join('\n\n')));
|
|
195
196
|
}
|
|
196
197
|
else if (validation.missingConfig.length > 0) {
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
queueHandlers.addToQueue(createValidateDefinition(validation.missingConfig, userRequest, service, (error) => {
|
|
199
|
+
errorHandlers.onError(error);
|
|
199
200
|
}, () => {
|
|
200
|
-
|
|
201
|
+
queueHandlers.addToQueue(createExecuteDefinition(typeTasks, service));
|
|
201
202
|
}, (operation) => {
|
|
202
|
-
|
|
203
|
+
errorHandlers.onAborted(operation);
|
|
203
204
|
}));
|
|
204
205
|
}
|
|
205
206
|
else {
|
|
206
|
-
|
|
207
|
+
queueHandlers.addToQueue(createExecuteDefinition(typeTasks, service));
|
|
207
208
|
}
|
|
208
209
|
}
|
|
209
210
|
catch (error) {
|
|
210
211
|
// Handle skill reference errors (e.g., unknown skills)
|
|
211
212
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
212
213
|
const message = createMessage(errorMessage);
|
|
213
|
-
|
|
214
|
+
queueHandlers.addToQueue(message);
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
217
|
}
|
package/dist/services/skills.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync } from 'fs';
|
|
2
1
|
import { homedir } from 'os';
|
|
3
2
|
import { join } from 'path';
|
|
3
|
+
import { defaultFileSystem } from './filesystem.js';
|
|
4
|
+
import { displayWarning } from './logger.js';
|
|
4
5
|
import { getUnknownSkillMessage } from './messages.js';
|
|
5
6
|
import { parseSkillMarkdown, displayNameToKey } from './parser.js';
|
|
6
7
|
/**
|
|
@@ -32,7 +33,7 @@ export function isValidSkillFilename(filename) {
|
|
|
32
33
|
return kebabCasePattern.test(name);
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
|
-
* Check if skill key conflicts with
|
|
36
|
+
* Check if skill key conflicts with system skills
|
|
36
37
|
*/
|
|
37
38
|
export function conflictsWithBuiltIn(key) {
|
|
38
39
|
return BUILT_IN_SKILLS.has(key);
|
|
@@ -46,16 +47,16 @@ export function getSkillsDirectory() {
|
|
|
46
47
|
/**
|
|
47
48
|
* Load all skill markdown files from the skills directory
|
|
48
49
|
* Returns an array of objects with filename (key) and content
|
|
49
|
-
* Filters out invalid filenames and conflicts with
|
|
50
|
+
* Filters out invalid filenames and conflicts with system skills
|
|
50
51
|
*/
|
|
51
|
-
export function loadSkills() {
|
|
52
|
+
export function loadSkills(fs = defaultFileSystem) {
|
|
52
53
|
const skillsDir = getSkillsDirectory();
|
|
53
54
|
// Return empty array if directory doesn't exist
|
|
54
|
-
if (!
|
|
55
|
+
if (!fs.exists(skillsDir)) {
|
|
55
56
|
return [];
|
|
56
57
|
}
|
|
57
58
|
try {
|
|
58
|
-
const files =
|
|
59
|
+
const files = fs.readDirectory(skillsDir);
|
|
59
60
|
// Filter and map valid skill files
|
|
60
61
|
return files
|
|
61
62
|
.filter((file) => {
|
|
@@ -65,7 +66,7 @@ export function loadSkills() {
|
|
|
65
66
|
}
|
|
66
67
|
// Extract key (filename without extension, handles both .md and .MD)
|
|
67
68
|
const key = file.slice(0, -3);
|
|
68
|
-
// Must not conflict with
|
|
69
|
+
// Must not conflict with system skills
|
|
69
70
|
if (conflictsWithBuiltIn(key)) {
|
|
70
71
|
return false;
|
|
71
72
|
}
|
|
@@ -75,12 +76,12 @@ export function loadSkills() {
|
|
|
75
76
|
// Extract key (filename without extension, handles both .md and .MD)
|
|
76
77
|
const key = file.slice(0, -3);
|
|
77
78
|
const filePath = join(skillsDir, file);
|
|
78
|
-
const content =
|
|
79
|
+
const content = fs.readFile(filePath, 'utf-8');
|
|
79
80
|
return { key, content };
|
|
80
81
|
});
|
|
81
82
|
}
|
|
82
|
-
catch {
|
|
83
|
-
|
|
83
|
+
catch (error) {
|
|
84
|
+
displayWarning('Failed to load skills directory', error);
|
|
84
85
|
return [];
|
|
85
86
|
}
|
|
86
87
|
}
|
|
@@ -88,16 +89,16 @@ export function loadSkills() {
|
|
|
88
89
|
* Load and parse all skill definitions
|
|
89
90
|
* Returns structured skill definitions (including invalid skills)
|
|
90
91
|
*/
|
|
91
|
-
export function loadSkillDefinitions() {
|
|
92
|
-
const skills = loadSkills();
|
|
92
|
+
export function loadSkillDefinitions(fs = defaultFileSystem) {
|
|
93
|
+
const skills = loadSkills(fs);
|
|
93
94
|
return skills.map(({ key, content }) => parseSkillMarkdown(key, content));
|
|
94
95
|
}
|
|
95
96
|
/**
|
|
96
97
|
* Load skills and mark incomplete ones in their markdown
|
|
97
98
|
* Returns array of skill markdown with status markers
|
|
98
99
|
*/
|
|
99
|
-
export function loadSkillsWithValidation() {
|
|
100
|
-
const skills = loadSkills();
|
|
100
|
+
export function loadSkillsWithValidation(fs = defaultFileSystem) {
|
|
101
|
+
const skills = loadSkills(fs);
|
|
101
102
|
return skills.map(({ key, content }) => {
|
|
102
103
|
const parsed = parseSkillMarkdown(key, content);
|
|
103
104
|
// If skill is incomplete (either validation failed or needs more documentation), append (INCOMPLETE) to the name
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
import { defaultFileSystem } from './filesystem.js';
|
|
1
2
|
import { loadUserConfig, hasConfigPath } from './loader.js';
|
|
2
3
|
import { loadSkillDefinitions, createSkillLookup } from './skills.js';
|
|
3
4
|
/**
|
|
4
5
|
* Validate config requirements for execute tasks
|
|
5
6
|
* Returns validation result with missing config and validation errors
|
|
6
7
|
*/
|
|
7
|
-
export function validateExecuteTasks(tasks) {
|
|
8
|
-
const userConfig = loadUserConfig();
|
|
8
|
+
export function validateExecuteTasks(tasks, fs = defaultFileSystem) {
|
|
9
|
+
const userConfig = loadUserConfig(fs);
|
|
9
10
|
const missing = [];
|
|
10
11
|
const seenPaths = new Set();
|
|
11
12
|
const validationErrors = [];
|
|
12
13
|
const seenSkills = new Set();
|
|
13
14
|
// Load all skills (including invalid ones for validation)
|
|
14
|
-
const parsedSkills = loadSkillDefinitions();
|
|
15
|
+
const parsedSkills = loadSkillDefinitions(fs);
|
|
15
16
|
const skillLookup = createSkillLookup(parsedSkills);
|
|
16
17
|
// Check for invalid skills being used in tasks
|
|
17
18
|
for (const task of tasks) {
|
|
@@ -26,8 +26,8 @@ You will receive:
|
|
|
26
26
|
|
|
27
27
|
## Task
|
|
28
28
|
|
|
29
|
-
Present the concierge's capabilities as a list of
|
|
30
|
-
|
|
29
|
+
Present the concierge's capabilities as a list of capability objects, each
|
|
30
|
+
with a name, description, and origin.
|
|
31
31
|
|
|
32
32
|
## Response Format
|
|
33
33
|
|
|
@@ -77,7 +77,7 @@ NON-NEGOTIABLE and applies to EVERY response.
|
|
|
77
77
|
|
|
78
78
|
**CORRECT ORDER - FOLLOW EXACTLY:**
|
|
79
79
|
|
|
80
|
-
### Position 1-4:
|
|
80
|
+
### Position 1-4: system capabilities (origin: "system")
|
|
81
81
|
|
|
82
82
|
These MUST appear FIRST, in this EXACT sequence:
|
|
83
83
|
|
|
@@ -86,47 +86,56 @@ These MUST appear FIRST, in this EXACT sequence:
|
|
|
86
86
|
3. **Answer** ← ALWAYS THIRD
|
|
87
87
|
4. **Execute** ← ALWAYS FOURTH
|
|
88
88
|
|
|
89
|
-
### Position 5-7:
|
|
89
|
+
### Position 5-7: meta workflow capabilities (origin: "meta")
|
|
90
90
|
|
|
91
|
-
These MUST appear AFTER Execute and BEFORE user skills:
|
|
91
|
+
These MUST appear AFTER Execute and BEFORE user-provided skills:
|
|
92
92
|
|
|
93
93
|
5. **Schedule** ← NEVER FIRST, ALWAYS position 5 (after Execute)
|
|
94
94
|
6. **Validate** ← ALWAYS position 6 (after Schedule)
|
|
95
95
|
7. **Report** ← NEVER FIRST, ALWAYS position 7 (after Validate)
|
|
96
96
|
|
|
97
|
-
### 3.
|
|
97
|
+
### 3. 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:
|
|
101
101
|
- Extract the skill name from the first heading (# Skill Name)
|
|
102
|
-
-
|
|
103
|
-
|
|
102
|
+
- Set origin to "user"
|
|
103
|
+
- If the skill name contains "(INCOMPLETE)", set isIncomplete to true and
|
|
104
|
+
remove "(INCOMPLETE)" from the name
|
|
104
105
|
- Extract a brief description from the Description or Overview section
|
|
105
106
|
- Keep descriptions concise (1-2 lines maximum)
|
|
106
107
|
- If the user specified a filter (e.g., "skills for deployment"), only
|
|
107
108
|
include skills whose name or description matches the filter
|
|
108
109
|
|
|
109
|
-
##
|
|
110
|
+
## Capability Object Guidelines
|
|
110
111
|
|
|
111
|
-
Create
|
|
112
|
+
Create capability objects for each capability. Each object should have:
|
|
112
113
|
|
|
113
|
-
- **
|
|
114
|
-
-
|
|
115
|
-
|
|
116
|
-
-
|
|
117
|
-
|
|
114
|
+
- **name**: The capability or skill name
|
|
115
|
+
- Use title case (e.g., "Schedule", "Execute", "Deploy Application")
|
|
116
|
+
- NOT all uppercase (NOT "SCHEDULE", "EXECUTE")
|
|
117
|
+
- Maximum 32 characters
|
|
118
|
+
- Examples: "Introspect", "Execute", "Deploy Application"
|
|
119
|
+
|
|
120
|
+
- **description**: A concise description of what this capability does
|
|
121
|
+
- Maximum 64 characters
|
|
122
|
+
- Start with lowercase letter, no ending punctuation
|
|
123
|
+
- Focus on clarity and brevity
|
|
124
|
+
- Describe the core purpose in one short phrase
|
|
118
125
|
- Examples:
|
|
119
|
-
- "
|
|
120
|
-
- "
|
|
121
|
-
- "
|
|
122
|
-
|
|
123
|
-
- **
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
|
|
129
|
-
-
|
|
126
|
+
- "break down requests into actionable steps"
|
|
127
|
+
- "run shell commands and process operations"
|
|
128
|
+
- "build and deploy to staging or production"
|
|
129
|
+
|
|
130
|
+
- **origin**: The origin type of the capability
|
|
131
|
+
- Use "system" for system capabilities: Introspect, Configure, Answer,
|
|
132
|
+
Execute
|
|
133
|
+
- Use "meta" for meta workflow capabilities: Schedule, Validate, Report
|
|
134
|
+
- Use "user" for all user-provided skills
|
|
135
|
+
|
|
136
|
+
- **isIncomplete**: Optional boolean flag
|
|
137
|
+
- Only include if the skill is marked as incomplete
|
|
138
|
+
- Set to true if skill name contained "(INCOMPLETE)"
|
|
130
139
|
|
|
131
140
|
## Filtering
|
|
132
141
|
|
|
@@ -134,48 +143,48 @@ When the user specifies a filter (e.g., "skills for deployment", "what
|
|
|
134
143
|
can you do with files"):
|
|
135
144
|
1. Parse the filter keyword(s) from the request
|
|
136
145
|
2. Match against skill names and descriptions (case-insensitive)
|
|
137
|
-
3. Include
|
|
146
|
+
3. Include system capabilities if they match the filter
|
|
138
147
|
4. Only present capabilities that match the filter
|
|
139
148
|
|
|
140
149
|
Examples:
|
|
141
150
|
- "skills for deployment" → Only show skills with "deploy" in
|
|
142
151
|
name/description
|
|
143
152
|
- "what can you do with files" → Show EXECUTE and any file-related skills
|
|
144
|
-
- "list all skills" → Show all
|
|
153
|
+
- "list all skills" → Show all system capabilities + all user-provided skills
|
|
145
154
|
|
|
146
155
|
## Examples
|
|
147
156
|
|
|
148
157
|
### Example 1: List All Capabilities
|
|
149
158
|
|
|
150
159
|
When user asks "list your skills", create an introductory message like
|
|
151
|
-
"here are my capabilities:" followed by
|
|
152
|
-
(Introspect, Configure, Answer, Execute
|
|
153
|
-
(Schedule, Validate, Report
|
|
154
|
-
|
|
155
|
-
Each task uses type "introspect" with an action describing the
|
|
156
|
-
capability.
|
|
160
|
+
"here are my capabilities:" followed by capability objects for system
|
|
161
|
+
capabilities (Introspect, Configure, Answer, Execute with origin
|
|
162
|
+
"system"), then meta workflow capabilities (Schedule, Validate, Report
|
|
163
|
+
with origin "meta").
|
|
157
164
|
|
|
158
165
|
### Example 2: Filtered Skills
|
|
159
166
|
|
|
160
167
|
When user asks "skills for deployment" and a "deploy app" skill exists,
|
|
161
168
|
create an introductory message like "these skills match 'deployment':"
|
|
162
|
-
followed by only the
|
|
163
|
-
|
|
169
|
+
followed by only the capabilities that match the filter. Show the deploy
|
|
170
|
+
app skill with origin "user".
|
|
164
171
|
|
|
165
172
|
### Example 3: With User Skills
|
|
166
173
|
|
|
167
|
-
When user asks "what can you do" and user-
|
|
174
|
+
When user asks "what can you do" and user-provided skills like "process
|
|
168
175
|
data" and "backup files" exist, create an introductory message like "i can
|
|
169
|
-
help with these operations:" followed by all
|
|
170
|
-
(Introspect, Configure, Answer, Execute
|
|
171
|
-
|
|
172
|
-
"
|
|
176
|
+
help with these operations:" followed by all system capabilities
|
|
177
|
+
(Introspect, Configure, Answer, Execute with origin "system"), meta
|
|
178
|
+
capabilities (Schedule, Validate, Report with origin "meta"), plus the
|
|
179
|
+
user-provided skills with origin "user".
|
|
173
180
|
|
|
174
181
|
## Final Validation
|
|
175
182
|
|
|
176
183
|
Before finalizing:
|
|
177
|
-
1. Ensure every
|
|
178
|
-
|
|
184
|
+
1. Ensure every capability has the correct origin value ("system",
|
|
185
|
+
"meta", or "user")
|
|
186
|
+
2. Verify descriptions are concise (≤64 characters)
|
|
179
187
|
3. Confirm the introductory message ends with a colon
|
|
180
188
|
4. Check that filtering was applied correctly if specified
|
|
181
189
|
5. Ensure no duplicate capabilities are listed
|
|
190
|
+
6. Verify names use title case, not all uppercase
|
package/dist/skills/schedule.md
CHANGED
|
@@ -83,12 +83,17 @@ settings", type "configure", params { query: "app" }
|
|
|
83
83
|
|
|
84
84
|
Before creating tasks, evaluate the request type:
|
|
85
85
|
|
|
86
|
-
1. **
|
|
86
|
+
1. **Introspection requests** - User asks about your capabilities:
|
|
87
|
+
- "list your skills", "what can you do", "flex", "show off", "list
|
|
88
|
+
capabilities", "show skills"
|
|
89
|
+
- Example: "flex" → introspect type
|
|
90
|
+
|
|
91
|
+
2. **Information requests** (questions) - Use question keywords:
|
|
87
92
|
- "explain", "describe", "tell me", "what is", "how does", "find",
|
|
88
93
|
"search"
|
|
89
94
|
- Example: "explain docker" → answer type
|
|
90
95
|
|
|
91
|
-
|
|
96
|
+
3. **Action requests** (commands) - Must match available skills:
|
|
92
97
|
- Action verbs like "compile", "deploy", "process", "validate"
|
|
93
98
|
- If verb matches a skill → extract skill steps as subtasks
|
|
94
99
|
- If verb does NOT match any skill → ignore type with action
|
|
@@ -98,7 +103,7 @@ Before creating tasks, evaluate the request type:
|
|
|
98
103
|
- Example: "validate" with no skill → action "Ignore unknown
|
|
99
104
|
'validate' request"
|
|
100
105
|
|
|
101
|
-
|
|
106
|
+
4. **Vague/ambiguous requests** without clear verb:
|
|
102
107
|
- Phrases like "do something", "handle it" → ignore type
|
|
103
108
|
- Action format: "Ignore unknown 'X' request" where X is the phrase
|
|
104
109
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const introspectTool = {
|
|
2
2
|
name: 'introspect',
|
|
3
|
-
description: 'Execute a task with type "introspect" to list available capabilities and skills. Called after SCHEDULE has identified an introspection request and user has confirmed. Takes the task action and optional filter parameter to present
|
|
3
|
+
description: 'Execute a task with type "introspect" to list available capabilities and skills. Called after SCHEDULE has identified an introspection request and user has confirmed. Takes the task action and optional filter parameter to present system capabilities and user-provided skills.',
|
|
4
4
|
input_schema: {
|
|
5
5
|
type: 'object',
|
|
6
6
|
properties: {
|
|
@@ -8,25 +8,34 @@ export const introspectTool = {
|
|
|
8
8
|
type: 'string',
|
|
9
9
|
description: 'Introductory reply to display before the capabilities list. Must be a single sentence, maximum 64 characters (including the colon at the end). Vary this naturally - try to use a different phrase each time. Always end with a colon.',
|
|
10
10
|
},
|
|
11
|
-
|
|
11
|
+
capabilities: {
|
|
12
12
|
type: 'array',
|
|
13
|
-
description: 'Array of capabilities,
|
|
13
|
+
description: 'Array of capabilities and skills. Include system capabilities (Introspect, Configure, Answer, Execute) with origin "system", meta workflow capabilities (Schedule, Validate, Report) with origin "meta", and user-provided skills from the Available Skills section with origin "user".',
|
|
14
14
|
items: {
|
|
15
15
|
type: 'object',
|
|
16
16
|
properties: {
|
|
17
|
-
|
|
17
|
+
name: {
|
|
18
18
|
type: 'string',
|
|
19
|
-
description: 'Capability
|
|
19
|
+
description: 'Capability or skill name. Use title case. Maximum 32 characters. Examples: "Execute", "Deploy Application", "Process Data".',
|
|
20
20
|
},
|
|
21
|
-
|
|
21
|
+
description: {
|
|
22
22
|
type: 'string',
|
|
23
|
-
description: '
|
|
23
|
+
description: 'Brief description of what this capability does. Start with lowercase letter, no ending punctuation. Maximum 64 characters. Examples: "run shell commands and operations", "build and deploy to production".',
|
|
24
|
+
},
|
|
25
|
+
origin: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
enum: ['system', 'user', 'meta'],
|
|
28
|
+
description: 'Origin of the capability. Use "system" for system capabilities (Introspect, Configure, Answer, Execute), "meta" for meta workflow capabilities (Schedule, Validate, Report), and "user" for user-provided skills.',
|
|
29
|
+
},
|
|
30
|
+
isIncomplete: {
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
description: 'Optional. Set to true if the skill is marked as incomplete.',
|
|
24
33
|
},
|
|
25
34
|
},
|
|
26
|
-
required: ['
|
|
35
|
+
required: ['name', 'description', 'origin'],
|
|
27
36
|
},
|
|
28
37
|
},
|
|
29
38
|
},
|
|
30
|
-
required: ['message', '
|
|
39
|
+
required: ['message', 'capabilities'],
|
|
31
40
|
},
|
|
32
41
|
};
|