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.
- package/dist/index.js +2 -1
- package/dist/services/anthropic.js +21 -2
- package/dist/services/components.js +11 -0
- package/dist/services/configuration.js +23 -5
- package/dist/services/logger.js +64 -0
- package/dist/services/messages.js +17 -2
- package/dist/services/{skill-parser.js → parser.js} +34 -15
- package/dist/services/refinement.js +5 -1
- package/dist/services/{tool-registry.js → registry.js} +14 -24
- package/dist/services/{task-router.js → router.js} +29 -21
- package/dist/services/skills.js +165 -17
- package/dist/services/{execution-validator.js → validator.js} +6 -8
- package/dist/{config/ANSWER.md → skills/answer.md} +10 -9
- package/dist/{config/CONFIG.md → skills/config.md} +16 -9
- package/dist/{config/EXECUTE.md → skills/execute.md} +91 -53
- package/dist/{config/INTROSPECT.md → skills/introspect.md} +63 -47
- package/dist/{config/PLAN.md → skills/plan.md} +419 -337
- package/dist/{config/VALIDATE.md → skills/validate.md} +26 -12
- package/dist/types/types.js +1 -0
- package/dist/ui/Command.js +5 -1
- package/dist/ui/Component.js +3 -0
- package/dist/ui/Config.js +3 -2
- package/dist/ui/Debug.js +8 -0
- package/dist/ui/Execute.js +2 -2
- package/dist/ui/Introspect.js +3 -2
- package/dist/ui/Main.js +19 -5
- package/dist/ui/Plan.js +3 -2
- package/dist/ui/Validate.js +8 -2
- package/dist/ui/Workflow.js +2 -1
- package/package.json +2 -2
- package/dist/services/skill-expander.js +0 -87
- /package/dist/services/{config-loader.js → loader.js} +0 -0
- /package/dist/services/{placeholder-resolver.js → resolver.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { existsSync, readFileSync } from 'fs';
|
|
|
4
4
|
import { dirname, join } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { render } from 'ink';
|
|
7
|
+
import { DebugLevel } from './services/configuration.js';
|
|
7
8
|
import { Main } from './ui/Main.js';
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
10
|
const __dirname = dirname(__filename);
|
|
@@ -20,7 +21,7 @@ const app = {
|
|
|
20
21
|
version: packageJson.version,
|
|
21
22
|
description: packageJson.description,
|
|
22
23
|
isDev,
|
|
23
|
-
|
|
24
|
+
debug: DebugLevel.None,
|
|
24
25
|
};
|
|
25
26
|
// Get command from command-line arguments
|
|
26
27
|
const args = process.argv.slice(2);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Anthropic from '@anthropic-ai/sdk';
|
|
2
2
|
import { getAvailableConfigStructure, getConfiguredKeys, } from './configuration.js';
|
|
3
|
+
import { logPrompt, logResponse } from './logger.js';
|
|
3
4
|
import { formatSkillsForPrompt, loadSkillsWithValidation } from './skills.js';
|
|
4
|
-
import { toolRegistry } from './
|
|
5
|
+
import { toolRegistry } from './registry.js';
|
|
5
6
|
/**
|
|
6
7
|
* Wraps text to ensure no line exceeds the specified width.
|
|
7
8
|
* Breaks at word boundaries to maintain readability.
|
|
@@ -70,7 +71,7 @@ export class AnthropicService {
|
|
|
70
71
|
if (toolName === 'config') {
|
|
71
72
|
const configStructure = getAvailableConfigStructure();
|
|
72
73
|
const configuredKeys = getConfiguredKeys();
|
|
73
|
-
const configSection = '\n
|
|
74
|
+
const configSection = '\n## Available Configuration\n\n' +
|
|
74
75
|
'Config structure (key: description):\n' +
|
|
75
76
|
JSON.stringify(configStructure, null, 2) +
|
|
76
77
|
'\n\nConfigured keys (keys that exist in config file):\n' +
|
|
@@ -85,7 +86,15 @@ export class AnthropicService {
|
|
|
85
86
|
name: 'web_search',
|
|
86
87
|
});
|
|
87
88
|
}
|
|
89
|
+
// Collect debug components
|
|
90
|
+
const debug = [];
|
|
91
|
+
// Log prompt at Verbose level
|
|
92
|
+
const promptDebug = logPrompt(toolName, command, systemPrompt);
|
|
93
|
+
if (promptDebug) {
|
|
94
|
+
debug.push(promptDebug);
|
|
95
|
+
}
|
|
88
96
|
// Call API with tool
|
|
97
|
+
const startTime = Date.now();
|
|
89
98
|
const response = await this.client.messages.create({
|
|
90
99
|
model: this.model,
|
|
91
100
|
max_tokens: 1024,
|
|
@@ -99,6 +108,12 @@ export class AnthropicService {
|
|
|
99
108
|
},
|
|
100
109
|
],
|
|
101
110
|
});
|
|
111
|
+
const duration = Date.now() - startTime;
|
|
112
|
+
// Log response at Verbose level
|
|
113
|
+
const responseDebug = logResponse(toolName, response, duration);
|
|
114
|
+
if (responseDebug) {
|
|
115
|
+
debug.push(responseDebug);
|
|
116
|
+
}
|
|
102
117
|
// Check for truncation
|
|
103
118
|
if (response.stop_reason === 'max_tokens') {
|
|
104
119
|
throw new Error('Response was truncated due to length. Please simplify your request or break it into smaller parts.');
|
|
@@ -113,6 +128,7 @@ export class AnthropicService {
|
|
|
113
128
|
message: '',
|
|
114
129
|
tasks: [],
|
|
115
130
|
answer: cleanAnswerText(textContent.text),
|
|
131
|
+
debug,
|
|
116
132
|
};
|
|
117
133
|
}
|
|
118
134
|
}
|
|
@@ -143,6 +159,7 @@ export class AnthropicService {
|
|
|
143
159
|
message: input.message,
|
|
144
160
|
tasks: [],
|
|
145
161
|
commands: input.commands,
|
|
162
|
+
debug,
|
|
146
163
|
};
|
|
147
164
|
}
|
|
148
165
|
// Handle answer tool response
|
|
@@ -157,6 +174,7 @@ export class AnthropicService {
|
|
|
157
174
|
message: '',
|
|
158
175
|
tasks: [],
|
|
159
176
|
answer: cleanAnswerText(input.answer),
|
|
177
|
+
debug,
|
|
160
178
|
};
|
|
161
179
|
}
|
|
162
180
|
// Handle plan and introspect tool responses
|
|
@@ -175,6 +193,7 @@ export class AnthropicService {
|
|
|
175
193
|
return {
|
|
176
194
|
message: input.message,
|
|
177
195
|
tasks: input.tasks,
|
|
196
|
+
debug,
|
|
178
197
|
};
|
|
179
198
|
}
|
|
180
199
|
}
|
|
@@ -252,6 +252,17 @@ export function createMessage(text) {
|
|
|
252
252
|
},
|
|
253
253
|
};
|
|
254
254
|
}
|
|
255
|
+
export function createDebugDefinition(title, content, color) {
|
|
256
|
+
return {
|
|
257
|
+
id: randomUUID(),
|
|
258
|
+
name: ComponentName.Debug,
|
|
259
|
+
props: {
|
|
260
|
+
title,
|
|
261
|
+
content,
|
|
262
|
+
color,
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
255
266
|
export function createRefinement(text, onAborted) {
|
|
256
267
|
return {
|
|
257
268
|
id: randomUUID(),
|
|
@@ -9,6 +9,13 @@ export var AnthropicModel;
|
|
|
9
9
|
AnthropicModel["Opus"] = "claude-opus-4-1";
|
|
10
10
|
})(AnthropicModel || (AnthropicModel = {}));
|
|
11
11
|
export const SUPPORTED_MODELS = Object.values(AnthropicModel);
|
|
12
|
+
export var DebugLevel;
|
|
13
|
+
(function (DebugLevel) {
|
|
14
|
+
DebugLevel["None"] = "none";
|
|
15
|
+
DebugLevel["Info"] = "info";
|
|
16
|
+
DebugLevel["Verbose"] = "verbose";
|
|
17
|
+
})(DebugLevel || (DebugLevel = {}));
|
|
18
|
+
export const SUPPORTED_DEBUG_LEVELS = Object.values(DebugLevel);
|
|
12
19
|
export var ConfigDefinitionType;
|
|
13
20
|
(function (ConfigDefinitionType) {
|
|
14
21
|
ConfigDefinitionType["RegExp"] = "regexp";
|
|
@@ -62,8 +69,17 @@ function validateConfig(parsed) {
|
|
|
62
69
|
if (config.settings && typeof config.settings === 'object') {
|
|
63
70
|
const settings = config.settings;
|
|
64
71
|
validatedConfig.settings = {};
|
|
65
|
-
if ('debug' in settings
|
|
66
|
-
|
|
72
|
+
if ('debug' in settings) {
|
|
73
|
+
// Handle migration from boolean to enum
|
|
74
|
+
if (typeof settings.debug === 'boolean') {
|
|
75
|
+
validatedConfig.settings.debug = settings.debug
|
|
76
|
+
? DebugLevel.Info
|
|
77
|
+
: DebugLevel.None;
|
|
78
|
+
}
|
|
79
|
+
else if (typeof settings.debug === 'string' &&
|
|
80
|
+
SUPPORTED_DEBUG_LEVELS.includes(settings.debug)) {
|
|
81
|
+
validatedConfig.settings.debug = settings.debug;
|
|
82
|
+
}
|
|
67
83
|
}
|
|
68
84
|
}
|
|
69
85
|
return validatedConfig;
|
|
@@ -139,10 +155,10 @@ export function saveDebugSetting(debug) {
|
|
|
139
155
|
export function loadDebugSetting() {
|
|
140
156
|
try {
|
|
141
157
|
const config = loadConfig();
|
|
142
|
-
return config.settings?.debug ??
|
|
158
|
+
return config.settings?.debug ?? DebugLevel.None;
|
|
143
159
|
}
|
|
144
160
|
catch {
|
|
145
|
-
return
|
|
161
|
+
return DebugLevel.None;
|
|
146
162
|
}
|
|
147
163
|
}
|
|
148
164
|
/**
|
|
@@ -193,8 +209,10 @@ const coreConfigSchema = {
|
|
|
193
209
|
description: 'Anthropic model',
|
|
194
210
|
},
|
|
195
211
|
'settings.debug': {
|
|
196
|
-
type: ConfigDefinitionType.
|
|
212
|
+
type: ConfigDefinitionType.Enum,
|
|
197
213
|
required: false,
|
|
214
|
+
values: SUPPORTED_DEBUG_LEVELS,
|
|
215
|
+
default: DebugLevel.None,
|
|
198
216
|
description: 'Debug mode',
|
|
199
217
|
},
|
|
200
218
|
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createDebugDefinition } from './components.js';
|
|
2
|
+
import { DebugLevel, loadDebugSetting } from './configuration.js';
|
|
3
|
+
import { Palette } from './colors.js';
|
|
4
|
+
/**
|
|
5
|
+
* Debug logger for the application
|
|
6
|
+
* Logs information based on the current debug level setting
|
|
7
|
+
*/
|
|
8
|
+
let currentDebugLevel = DebugLevel.None;
|
|
9
|
+
/**
|
|
10
|
+
* Initialize the logger with the current debug level from config
|
|
11
|
+
*/
|
|
12
|
+
export function initializeLogger() {
|
|
13
|
+
currentDebugLevel = loadDebugSetting();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Set the debug level (used for testing or runtime changes)
|
|
17
|
+
*/
|
|
18
|
+
export function setDebugLevel(debug) {
|
|
19
|
+
currentDebugLevel = debug;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get the current debug level
|
|
23
|
+
*/
|
|
24
|
+
export function getDebugLevel() {
|
|
25
|
+
return currentDebugLevel;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create debug component for system prompts sent to the LLM
|
|
29
|
+
* Only creates at Verbose level
|
|
30
|
+
*/
|
|
31
|
+
export function logPrompt(toolName, command, instructions) {
|
|
32
|
+
if (currentDebugLevel !== DebugLevel.Verbose) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const content = [
|
|
36
|
+
'',
|
|
37
|
+
`Tool: ${toolName}`,
|
|
38
|
+
`Command: ${command}`,
|
|
39
|
+
'',
|
|
40
|
+
instructions,
|
|
41
|
+
].join('\n');
|
|
42
|
+
// Calculate stats for the instructions
|
|
43
|
+
const lines = instructions.split('\n').length;
|
|
44
|
+
const bytes = Buffer.byteLength(instructions, 'utf-8');
|
|
45
|
+
const title = `SYSTEM PROMPT (${String(lines)} lines, ${String(bytes)} bytes)`;
|
|
46
|
+
return createDebugDefinition(title, content, Palette.Gray);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create debug component for LLM responses received
|
|
50
|
+
* Only creates at Verbose level
|
|
51
|
+
*/
|
|
52
|
+
export function logResponse(toolName, response, durationMs) {
|
|
53
|
+
if (currentDebugLevel !== DebugLevel.Verbose) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const content = [
|
|
57
|
+
'',
|
|
58
|
+
`Tool: ${toolName}`,
|
|
59
|
+
'',
|
|
60
|
+
JSON.stringify(response, null, 2),
|
|
61
|
+
].join('\n');
|
|
62
|
+
const title = `LLM RESPONSE (${String(durationMs)} ms)`;
|
|
63
|
+
return createDebugDefinition(title, content, Palette.AshGray);
|
|
64
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { loadDebugSetting } from './configuration.js';
|
|
1
|
+
import { DebugLevel, loadDebugSetting } from './configuration.js';
|
|
2
2
|
export { formatDuration } from './utils.js';
|
|
3
3
|
/**
|
|
4
4
|
* Returns a natural language confirmation message for plan execution.
|
|
@@ -58,6 +58,21 @@ export function getUnknownRequestMessage() {
|
|
|
58
58
|
];
|
|
59
59
|
return messages[Math.floor(Math.random() * messages.length)];
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns an error message for unknown skill references.
|
|
63
|
+
* Randomly selects from variations to sound natural.
|
|
64
|
+
* Skill name should be a verb with details (e.g., "Deploy Application")
|
|
65
|
+
*/
|
|
66
|
+
export function getUnknownSkillMessage(skillName) {
|
|
67
|
+
const templates = [
|
|
68
|
+
`I don't know how to "${skillName}".`,
|
|
69
|
+
`I'm not familiar with the "${skillName}" command.`,
|
|
70
|
+
`I haven't learned how to "${skillName}" yet.`,
|
|
71
|
+
`I can't "${skillName}".`,
|
|
72
|
+
`I'm unable to "${skillName}".`,
|
|
73
|
+
];
|
|
74
|
+
return templates[Math.floor(Math.random() * templates.length)];
|
|
75
|
+
}
|
|
61
76
|
/**
|
|
62
77
|
* Returns an error message for mixed task types.
|
|
63
78
|
*/
|
|
@@ -81,7 +96,7 @@ export const FeedbackMessages = {
|
|
|
81
96
|
*/
|
|
82
97
|
export function formatErrorMessage(error) {
|
|
83
98
|
const rawMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
84
|
-
if (loadDebugSetting()) {
|
|
99
|
+
if (loadDebugSetting() !== DebugLevel.None) {
|
|
85
100
|
return rawMessage;
|
|
86
101
|
}
|
|
87
102
|
// Try to extract message from Anthropic API error format
|
|
@@ -2,18 +2,13 @@ import YAML from 'yaml';
|
|
|
2
2
|
/**
|
|
3
3
|
* Validate a skill without parsing it fully
|
|
4
4
|
* Returns validation error if skill is invalid, null if valid
|
|
5
|
+
* Note: Name section is optional - key from filename is used as fallback
|
|
5
6
|
*/
|
|
6
|
-
export function
|
|
7
|
+
export function validateSkillStructure(content, key) {
|
|
7
8
|
const sections = extractSections(content);
|
|
8
|
-
//
|
|
9
|
-
const skillName = sections.name ||
|
|
10
|
-
// Check required sections
|
|
11
|
-
if (!sections.name) {
|
|
12
|
-
return {
|
|
13
|
-
skillName,
|
|
14
|
-
error: 'The skill file is missing a Name section',
|
|
15
|
-
};
|
|
16
|
-
}
|
|
9
|
+
// Use key for error reporting if name not present
|
|
10
|
+
const skillName = sections.name || key;
|
|
11
|
+
// Check required sections (Name is now optional)
|
|
17
12
|
if (!sections.description) {
|
|
18
13
|
return {
|
|
19
14
|
skillName,
|
|
@@ -41,17 +36,40 @@ export function validateSkill(content) {
|
|
|
41
36
|
}
|
|
42
37
|
return null;
|
|
43
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Convert kebab-case key to Title Case display name
|
|
41
|
+
* Examples: "deploy-app" -> "Deploy App", "build-project-2" -> "Build Project 2"
|
|
42
|
+
*/
|
|
43
|
+
function keyToDisplayName(key) {
|
|
44
|
+
return key
|
|
45
|
+
.split('-')
|
|
46
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
47
|
+
.join(' ');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Convert display name to kebab-case key
|
|
51
|
+
* Examples: "Deploy App" -> "deploy-app", "Navigate To Product" -> "navigate-to-product"
|
|
52
|
+
*/
|
|
53
|
+
export function displayNameToKey(name) {
|
|
54
|
+
return name
|
|
55
|
+
.toLowerCase()
|
|
56
|
+
.replace(/\s+/g, '-')
|
|
57
|
+
.replace(/[^a-z0-9-]/g, '');
|
|
58
|
+
}
|
|
44
59
|
/**
|
|
45
60
|
* Parse a skill markdown file into structured definition
|
|
46
61
|
*/
|
|
47
|
-
export function parseSkillMarkdown(content) {
|
|
62
|
+
export function parseSkillMarkdown(key, content) {
|
|
48
63
|
const sections = extractSections(content);
|
|
49
|
-
//
|
|
50
|
-
const
|
|
64
|
+
// Determine display name: prefer Name section, otherwise derive from key
|
|
65
|
+
const displayName = sections.name || keyToDisplayName(key);
|
|
66
|
+
// Validate the skill (Name is no longer required since we have key)
|
|
67
|
+
const validationError = validateSkillStructure(content, key);
|
|
51
68
|
// For invalid skills, return minimal definition with error
|
|
52
69
|
if (validationError) {
|
|
53
70
|
return {
|
|
54
|
-
|
|
71
|
+
key,
|
|
72
|
+
name: displayName,
|
|
55
73
|
description: sections.description || '',
|
|
56
74
|
steps: sections.steps || [],
|
|
57
75
|
execution: sections.execution || [],
|
|
@@ -63,7 +81,8 @@ export function parseSkillMarkdown(content) {
|
|
|
63
81
|
// Valid skill - all required fields are present (validation passed)
|
|
64
82
|
const description = sections.description;
|
|
65
83
|
const skill = {
|
|
66
|
-
|
|
84
|
+
key,
|
|
85
|
+
name: displayName,
|
|
67
86
|
description,
|
|
68
87
|
steps: sections.steps,
|
|
69
88
|
execution: sections.execution,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRefinement } from './components.js';
|
|
2
2
|
import { formatErrorMessage, getRefiningMessage } from './messages.js';
|
|
3
|
-
import { routeTasksWithConfirm } from './
|
|
3
|
+
import { routeTasksWithConfirm } from './router.js';
|
|
4
4
|
/**
|
|
5
5
|
* Handle refinement flow for DEFINE tasks
|
|
6
6
|
* Called when user selects options from a plan with DEFINE tasks
|
|
@@ -24,6 +24,10 @@ export async function handleRefinement(selectedTasks, service, originalCommand,
|
|
|
24
24
|
const refinedResult = await service.processWithTool(refinedCommand, 'plan');
|
|
25
25
|
// Complete the Refinement component
|
|
26
26
|
handlers.completeActive();
|
|
27
|
+
// Add debug components to timeline if present
|
|
28
|
+
if (refinedResult.debug && refinedResult.debug.length > 0) {
|
|
29
|
+
handlers.addToTimeline(...refinedResult.debug);
|
|
30
|
+
}
|
|
27
31
|
// Route refined tasks to appropriate components
|
|
28
32
|
routeTasksWithConfirm(refinedResult.tasks, refinedResult.message, service, originalCommand, handlers, false // No DEFINE tasks in refined result
|
|
29
33
|
);
|
|
@@ -39,27 +39,17 @@ import { executeTool } from '../tools/execute.tool.js';
|
|
|
39
39
|
import { introspectTool } from '../tools/introspect.tool.js';
|
|
40
40
|
import { planTool } from '../tools/plan.tool.js';
|
|
41
41
|
import { validateTool } from '../tools/validate.tool.js';
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
instructionsPath: 'config/CONFIG.md',
|
|
57
|
-
});
|
|
58
|
-
toolRegistry.register('execute', {
|
|
59
|
-
schema: executeTool,
|
|
60
|
-
instructionsPath: 'config/EXECUTE.md',
|
|
61
|
-
});
|
|
62
|
-
toolRegistry.register('validate', {
|
|
63
|
-
schema: validateTool,
|
|
64
|
-
instructionsPath: 'config/VALIDATE.md',
|
|
65
|
-
});
|
|
42
|
+
const tools = {
|
|
43
|
+
answer: answerTool,
|
|
44
|
+
config: configTool,
|
|
45
|
+
execute: executeTool,
|
|
46
|
+
introspect: introspectTool,
|
|
47
|
+
plan: planTool,
|
|
48
|
+
validate: validateTool,
|
|
49
|
+
};
|
|
50
|
+
for (const [name, schema] of Object.entries(tools)) {
|
|
51
|
+
toolRegistry.register(name, {
|
|
52
|
+
schema,
|
|
53
|
+
instructionsPath: `skills/${name}.md`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -2,7 +2,7 @@ import { TaskType } from '../types/types.js';
|
|
|
2
2
|
import { createAnswerDefinition, createConfigDefinitionWithKeys, createConfirmDefinition, createExecuteDefinition, createFeedback, createIntrospectDefinition, createMessage, createPlanDefinition, createValidateDefinition, } from './components.js';
|
|
3
3
|
import { saveConfig, unflattenConfig } from './configuration.js';
|
|
4
4
|
import { FeedbackType } from '../types/types.js';
|
|
5
|
-
import { validateExecuteTasks } from './
|
|
5
|
+
import { validateExecuteTasks } from './validator.js';
|
|
6
6
|
import { getCancellationMessage, getMixedTaskTypesError, getUnknownRequestMessage, } from './messages.js';
|
|
7
7
|
/**
|
|
8
8
|
* Determine the operation name based on task types
|
|
@@ -125,28 +125,36 @@ function executeTasksAfterConfirm(tasks, service, userRequest, handlers) {
|
|
|
125
125
|
}
|
|
126
126
|
else {
|
|
127
127
|
// Execute tasks with validation
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
handlers.
|
|
142
|
-
|
|
128
|
+
try {
|
|
129
|
+
const validation = validateExecuteTasks(tasks);
|
|
130
|
+
if (validation.validationErrors.length > 0) {
|
|
131
|
+
// Show error feedback for invalid skills
|
|
132
|
+
const errorMessages = validation.validationErrors.map((error) => {
|
|
133
|
+
const issuesList = error.issues
|
|
134
|
+
.map((issue) => ` - ${issue}`)
|
|
135
|
+
.join('\n');
|
|
136
|
+
return `Invalid skill definition "${error.skill}":\n\n${issuesList}`;
|
|
137
|
+
});
|
|
138
|
+
handlers.addToQueue(createFeedback(FeedbackType.Failed, errorMessages.join('\n\n')));
|
|
139
|
+
}
|
|
140
|
+
else if (validation.missingConfig.length > 0) {
|
|
141
|
+
handlers.addToQueue(createValidateDefinition(validation.missingConfig, userRequest, service, (error) => {
|
|
142
|
+
handlers.onError(error);
|
|
143
|
+
}, () => {
|
|
144
|
+
handlers.addToQueue(createExecuteDefinition(tasks, service));
|
|
145
|
+
}, (operation) => {
|
|
146
|
+
handlers.onAborted(operation);
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
143
150
|
handlers.addToQueue(createExecuteDefinition(tasks, service));
|
|
144
|
-
}
|
|
145
|
-
handlers.onAborted(operation);
|
|
146
|
-
}));
|
|
151
|
+
}
|
|
147
152
|
}
|
|
148
|
-
|
|
149
|
-
|
|
153
|
+
catch (error) {
|
|
154
|
+
// Handle skill reference errors (e.g., unknown skills)
|
|
155
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
156
|
+
const message = createMessage(errorMessage);
|
|
157
|
+
handlers.addToQueue(message);
|
|
150
158
|
}
|
|
151
159
|
}
|
|
152
160
|
}
|