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
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
## Overview
|
|
2
2
|
|
|
3
|
-
You are the validation component of "pls" (please), responsible for
|
|
3
|
+
You are the validation component of "pls" (please), responsible for
|
|
4
|
+
validating skill requirements and generating natural language descriptions
|
|
5
|
+
for missing configuration values.
|
|
4
6
|
|
|
5
|
-
Your role is to help users understand what configuration values are needed
|
|
7
|
+
Your role is to help users understand what configuration values are needed
|
|
8
|
+
and why, using context from skill descriptions to create clear, helpful
|
|
9
|
+
prompts.
|
|
6
10
|
|
|
7
11
|
## Input
|
|
8
12
|
|
|
@@ -21,18 +25,22 @@ Generate a response with two required fields:
|
|
|
21
25
|
|
|
22
26
|
For each CONFIG task, create a natural language description that:
|
|
23
27
|
|
|
24
|
-
1. **Explains what the value is for** using context from the skill's
|
|
28
|
+
1. **Explains what the value is for** using context from the skill's
|
|
29
|
+
description
|
|
25
30
|
2. **Keeps it SHORT** - one brief phrase (3-6 words max)
|
|
26
|
-
3. **Does NOT include the config path** - the path will be shown
|
|
31
|
+
3. **Does NOT include the config path** - the path will be shown
|
|
32
|
+
separately in debug mode
|
|
27
33
|
|
|
28
|
-
**CRITICAL**: You MUST include both the `message` field (set to empty
|
|
34
|
+
**CRITICAL**: You MUST include both the `message` field (set to empty
|
|
35
|
+
string) and the `tasks` array in your response.
|
|
29
36
|
|
|
30
37
|
## Description Format
|
|
31
38
|
|
|
32
39
|
**Format:** "Brief description" (DO NOT include {config.path}!)
|
|
33
40
|
|
|
34
41
|
The description should:
|
|
35
|
-
- Start with what the config value represents (e.g., "Path to...", "URL
|
|
42
|
+
- Start with what the config value represents (e.g., "Path to...", "URL
|
|
43
|
+
for...", "Name of...")
|
|
36
44
|
- Be SHORT and direct - no extra details or variant explanations
|
|
37
45
|
- NEVER include the config path in curly brackets like {config.path}
|
|
38
46
|
|
|
@@ -97,11 +105,16 @@ tasks: [
|
|
|
97
105
|
|
|
98
106
|
## Guidelines
|
|
99
107
|
|
|
100
|
-
1. **Use skill context**: Read the skill's Description section to
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
1. **Use skill context**: Read the skill's Description section to
|
|
109
|
+
understand what the variant represents
|
|
110
|
+
2. **Be specific**: Don't just say "Repository path" - say "Path to Alpha
|
|
111
|
+
repository"
|
|
112
|
+
3. **Add helpful details**: Include information from the description when
|
|
113
|
+
relevant
|
|
114
|
+
4. **Keep it concise**: One brief phrase that clearly explains what's
|
|
115
|
+
needed
|
|
116
|
+
5. **Never include the path**: Do not append `{config.path}` - it's shown
|
|
117
|
+
separately in debug mode
|
|
105
118
|
|
|
106
119
|
## Common Config Types
|
|
107
120
|
|
|
@@ -137,4 +150,5 @@ tasks: [
|
|
|
137
150
|
- Descriptions should be helpful and contextual, not just technical
|
|
138
151
|
- Use information from Available Skills section to provide context
|
|
139
152
|
- Keep descriptions to one brief phrase (3-6 words)
|
|
140
|
-
- NEVER include the config path in the action/description - it's shown
|
|
153
|
+
- NEVER include the config path in the action/description - it's shown
|
|
154
|
+
separately
|
package/dist/types/types.js
CHANGED
|
@@ -3,6 +3,7 @@ export var ComponentName;
|
|
|
3
3
|
ComponentName["Welcome"] = "welcome";
|
|
4
4
|
ComponentName["Config"] = "config";
|
|
5
5
|
ComponentName["Message"] = "message";
|
|
6
|
+
ComponentName["Debug"] = "debug";
|
|
6
7
|
ComponentName["Command"] = "command";
|
|
7
8
|
ComponentName["Plan"] = "plan";
|
|
8
9
|
ComponentName["Refinement"] = "refinement";
|
package/dist/ui/Command.js
CHANGED
|
@@ -8,7 +8,7 @@ import { createPlanDefinition } 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';
|
|
11
|
-
import { routeTasksWithConfirm } from '../services/
|
|
11
|
+
import { routeTasksWithConfirm } from '../services/router.js';
|
|
12
12
|
import { ensureMinimumTime } from '../services/timing.js';
|
|
13
13
|
import { Spinner } from './Spinner.js';
|
|
14
14
|
import { UserQuery } from './UserQuery.js';
|
|
@@ -48,6 +48,10 @@ export function Command({ command, state, status, service, handlers, onAborted,
|
|
|
48
48
|
}
|
|
49
49
|
await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
|
|
50
50
|
if (mounted) {
|
|
51
|
+
// Add debug components to timeline if present
|
|
52
|
+
if (result.debug && result.debug.length > 0) {
|
|
53
|
+
handlers?.addToTimeline(...result.debug);
|
|
54
|
+
}
|
|
51
55
|
// Save result to state for timeline display
|
|
52
56
|
handlers?.updateState({
|
|
53
57
|
message: result.message,
|
package/dist/ui/Component.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Answer } from './Answer.js';
|
|
|
5
5
|
import { Command } from './Command.js';
|
|
6
6
|
import { Confirm } from './Confirm.js';
|
|
7
7
|
import { Config } from './Config.js';
|
|
8
|
+
import { Debug } from './Debug.js';
|
|
8
9
|
import { Execute } from './Execute.js';
|
|
9
10
|
import { Feedback } from './Feedback.js';
|
|
10
11
|
import { Introspect } from './Introspect.js';
|
|
@@ -28,6 +29,8 @@ export const Component = memo(function Component({ def, debug, }) {
|
|
|
28
29
|
return _jsx(Feedback, { ...def.props, status: def.status });
|
|
29
30
|
case ComponentName.Message:
|
|
30
31
|
return _jsx(Message, { ...def.props, status: def.status });
|
|
32
|
+
case ComponentName.Debug:
|
|
33
|
+
return _jsx(Debug, { ...def.props, status: def.status });
|
|
31
34
|
case ComponentName.Refinement:
|
|
32
35
|
return (_jsx(Refinement, { ...def.props, state: def.state, status: def.status }));
|
|
33
36
|
case ComponentName.Confirm:
|
package/dist/ui/Config.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Box, Text, useFocus } from 'ink';
|
|
|
4
4
|
import TextInput from 'ink-text-input';
|
|
5
5
|
import { ComponentStatus } from '../types/components.js';
|
|
6
6
|
import { Colors } from '../services/colors.js';
|
|
7
|
+
import { DebugLevel } from '../services/configuration.js';
|
|
7
8
|
import { useInput } from '../services/keyboard.js';
|
|
8
9
|
export var StepType;
|
|
9
10
|
(function (StepType) {
|
|
@@ -58,7 +59,7 @@ function SelectionStep({ options, selectedIndex, isCurrentStep, }) {
|
|
|
58
59
|
return (_jsx(Box, { marginRight: 2, children: _jsx(Text, { dimColor: !isSelected || !isCurrentStep, bold: isSelected, children: option.label }) }, option.value));
|
|
59
60
|
}) }));
|
|
60
61
|
}
|
|
61
|
-
export function Config({ steps, state, status, debug, handlers, onFinished, onAborted, }) {
|
|
62
|
+
export function Config({ steps, state, status, debug = DebugLevel.None, handlers, onFinished, onAborted, }) {
|
|
62
63
|
const isActive = status === ComponentStatus.Active;
|
|
63
64
|
const [step, setStep] = useState(!isActive ? (state?.completedStep ?? steps.length) : 0);
|
|
64
65
|
const [values, setValues] = useState(() => {
|
|
@@ -243,6 +244,6 @@ export function Config({ steps, state, status, debug, handlers, onFinished, onAb
|
|
|
243
244
|
if (!shouldShow) {
|
|
244
245
|
return null;
|
|
245
246
|
}
|
|
246
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: index === 0 ? 0 : 1, children: [_jsxs(Box, { children: [_jsx(Text, { children: stepConfig.description }), _jsx(Text, { children: ": " }), debug && stepConfig.path && (_jsxs(Text, { color: Colors.Type.Define, children: ['{', stepConfig.path, '}'] }))] }), _jsxs(Box, { children: [_jsx(Text, { children: " " }), _jsx(Text, { color: Colors.Action.Select, dimColor: !isCurrentStep, children: ">" }), _jsx(Text, { children: " " }), renderStepInput(stepConfig, isCurrentStep)] })] }, stepConfig.path || stepConfig.key));
|
|
247
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: index === 0 ? 0 : 1, children: [_jsxs(Box, { children: [_jsx(Text, { children: stepConfig.description }), _jsx(Text, { children: ": " }), debug !== DebugLevel.None && stepConfig.path && (_jsxs(Text, { color: Colors.Type.Define, children: ['{', stepConfig.path, '}'] }))] }), _jsxs(Box, { children: [_jsx(Text, { children: " " }), _jsx(Text, { color: Colors.Action.Select, dimColor: !isCurrentStep, children: ">" }), _jsx(Text, { children: " " }), renderStepInput(stepConfig, isCurrentStep)] })] }, stepConfig.path || stepConfig.key));
|
|
247
248
|
}) }));
|
|
248
249
|
}
|
package/dist/ui/Debug.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
const MIN_CONTENT_WIDTH = 80;
|
|
4
|
+
const HORIZONTAL_PADDING = 2;
|
|
5
|
+
const BORDER_WIDTH = 1;
|
|
6
|
+
export const Debug = ({ title, content, color }) => {
|
|
7
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: HORIZONTAL_PADDING, paddingY: 1, borderStyle: "single", borderColor: color, alignSelf: "flex-start", minWidth: MIN_CONTENT_WIDTH + 2 * HORIZONTAL_PADDING + 2 * BORDER_WIDTH, children: [_jsx(Text, { color: color, children: title }), _jsx(Text, { color: color, children: content })] }));
|
|
8
|
+
};
|
package/dist/ui/Execute.js
CHANGED
|
@@ -7,8 +7,8 @@ import { useInput } from '../services/keyboard.js';
|
|
|
7
7
|
import { formatErrorMessage } from '../services/messages.js';
|
|
8
8
|
import { formatDuration } from '../services/utils.js';
|
|
9
9
|
import { ExecutionStatus, executeCommands, } from '../services/shell.js';
|
|
10
|
-
import { replacePlaceholders } from '../services/
|
|
11
|
-
import { loadUserConfig } from '../services/
|
|
10
|
+
import { replacePlaceholders } from '../services/resolver.js';
|
|
11
|
+
import { loadUserConfig } from '../services/loader.js';
|
|
12
12
|
import { ensureMinimumTime } from '../services/timing.js';
|
|
13
13
|
import { Spinner } from './Spinner.js';
|
|
14
14
|
const MINIMUM_PROCESSING_TIME = 400;
|
package/dist/ui/Introspect.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Box, Text } from 'ink';
|
|
|
4
4
|
import { ComponentStatus, } from '../types/components.js';
|
|
5
5
|
import { Colors, getTextColor } from '../services/colors.js';
|
|
6
6
|
import { createReportDefinition } from '../services/components.js';
|
|
7
|
+
import { DebugLevel } from '../services/configuration.js';
|
|
7
8
|
import { useInput } from '../services/keyboard.js';
|
|
8
9
|
import { formatErrorMessage } from '../services/messages.js';
|
|
9
10
|
import { ensureMinimumTime } from '../services/timing.js';
|
|
@@ -51,7 +52,7 @@ function parseCapabilityFromTask(task) {
|
|
|
51
52
|
isIncomplete,
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
|
-
export function Introspect({ tasks, state, status, service, children, debug =
|
|
55
|
+
export function Introspect({ tasks, state, status, service, children, debug = DebugLevel.None, handlers, }) {
|
|
55
56
|
const isActive = status === ComponentStatus.Active;
|
|
56
57
|
// isActive passed as prop
|
|
57
58
|
const [error, setError] = useState(null);
|
|
@@ -83,7 +84,7 @@ export function Introspect({ tasks, state, status, service, children, debug = fa
|
|
|
83
84
|
// Parse capabilities from returned tasks
|
|
84
85
|
let capabilities = result.tasks.map(parseCapabilityFromTask);
|
|
85
86
|
// Filter out internal capabilities when not in debug mode
|
|
86
|
-
if (
|
|
87
|
+
if (debug === DebugLevel.None) {
|
|
87
88
|
capabilities = capabilities.filter((cap) => cap.name.toUpperCase() !== 'PLAN' &&
|
|
88
89
|
cap.name.toUpperCase() !== 'VALIDATE' &&
|
|
89
90
|
cap.name.toUpperCase() !== 'REPORT');
|
package/dist/ui/Main.js
CHANGED
|
@@ -3,18 +3,32 @@ import { useEffect, useState } from 'react';
|
|
|
3
3
|
import { FeedbackType } from '../types/types.js';
|
|
4
4
|
import { createAnthropicService, } from '../services/anthropic.js';
|
|
5
5
|
import { createCommandDefinition, createConfigDefinitionWithKeys, createFeedback, createMessage, createWelcomeDefinition, } from '../services/components.js';
|
|
6
|
-
import { getConfigurationRequiredMessage, getMissingConfigKeys, loadConfig, loadDebugSetting, saveAnthropicConfig, saveDebugSetting, } from '../services/configuration.js';
|
|
6
|
+
import { DebugLevel, getConfigurationRequiredMessage, getMissingConfigKeys, loadConfig, loadDebugSetting, saveAnthropicConfig, saveDebugSetting, } from '../services/configuration.js';
|
|
7
7
|
import { registerGlobalShortcut } from '../services/keyboard.js';
|
|
8
|
+
import { initializeLogger, setDebugLevel } from '../services/logger.js';
|
|
8
9
|
import { Workflow } from './Workflow.js';
|
|
9
10
|
export const Main = ({ app, command }) => {
|
|
10
11
|
const [service, setService] = useState(null);
|
|
11
12
|
const [initialQueue, setInitialQueue] = useState(null);
|
|
12
|
-
const [
|
|
13
|
+
const [debug, setDebugLevelState] = useState(() => loadDebugSetting());
|
|
14
|
+
// Initialize logger on mount
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
initializeLogger();
|
|
17
|
+
}, []);
|
|
18
|
+
// Update logger when debug level changes
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
setDebugLevel(debug);
|
|
21
|
+
}, [debug]);
|
|
13
22
|
// Register global keyboard shortcuts
|
|
14
23
|
useEffect(() => {
|
|
15
24
|
registerGlobalShortcut('shift+tab', () => {
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
setDebugLevelState((prev) => {
|
|
26
|
+
// Cycle through: None -> Info -> Verbose -> None
|
|
27
|
+
const newValue = prev === DebugLevel.None
|
|
28
|
+
? DebugLevel.Info
|
|
29
|
+
: prev === DebugLevel.Info
|
|
30
|
+
? DebugLevel.Verbose
|
|
31
|
+
: DebugLevel.None;
|
|
18
32
|
saveDebugSetting(newValue);
|
|
19
33
|
return newValue;
|
|
20
34
|
});
|
|
@@ -90,5 +104,5 @@ export const Main = ({ app, command }) => {
|
|
|
90
104
|
if (initialQueue === null) {
|
|
91
105
|
return null;
|
|
92
106
|
}
|
|
93
|
-
return _jsx(Workflow, { initialQueue: initialQueue, debug:
|
|
107
|
+
return _jsx(Workflow, { initialQueue: initialQueue, debug: debug });
|
|
94
108
|
};
|
package/dist/ui/Plan.js
CHANGED
|
@@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
|
|
|
3
3
|
import { Box } from 'ink';
|
|
4
4
|
import { ComponentStatus } from '../types/components.js';
|
|
5
5
|
import { TaskType } from '../types/types.js';
|
|
6
|
+
import { DebugLevel } from '../services/configuration.js';
|
|
6
7
|
import { getTaskColors } from '../services/colors.js';
|
|
7
8
|
import { useInput } from '../services/keyboard.js';
|
|
8
9
|
import { Label } from './Label.js';
|
|
@@ -50,7 +51,7 @@ function taskToListItem(task, highlightedChildIndex = null, isDefineTaskWithoutS
|
|
|
50
51
|
}
|
|
51
52
|
return item;
|
|
52
53
|
}
|
|
53
|
-
export function Plan({ message, tasks, state, status, debug =
|
|
54
|
+
export function Plan({ message, tasks, state, status, debug = DebugLevel.None, handlers, onSelectionConfirmed, }) {
|
|
54
55
|
const isActive = status === ComponentStatus.Active;
|
|
55
56
|
// isActive passed as prop
|
|
56
57
|
const [highlightedIndex, setHighlightedIndex] = useState(state?.highlightedIndex ?? null);
|
|
@@ -201,5 +202,5 @@ export function Plan({ message, tasks, state, status, debug = false, handlers, o
|
|
|
201
202
|
isActive;
|
|
202
203
|
return taskToListItem(task, childIndex, isDefineWithoutSelection, isActive);
|
|
203
204
|
});
|
|
204
|
-
return (_jsxs(Box, { flexDirection: "column", children: [message && (_jsx(Box, { marginBottom: 1, marginLeft: 1, children: _jsx(Label, { description: message, taskType: TaskType.Plan, showType: debug, isCurrent: isActive }) })), _jsx(Box, { marginLeft: 1, children: _jsx(List, { items: listItems, highlightedIndex: currentDefineTaskIndex >= 0 ? highlightedIndex : null, highlightedParentIndex: currentDefineTaskIndex, showType: debug }) })] }));
|
|
205
|
+
return (_jsxs(Box, { flexDirection: "column", children: [message && (_jsx(Box, { marginBottom: 1, marginLeft: 1, children: _jsx(Label, { description: message, taskType: TaskType.Plan, showType: debug !== DebugLevel.None, isCurrent: isActive }) })), _jsx(Box, { marginLeft: 1, children: _jsx(List, { items: listItems, highlightedIndex: currentDefineTaskIndex >= 0 ? highlightedIndex : null, highlightedParentIndex: currentDefineTaskIndex, showType: debug !== DebugLevel.None }) })] }));
|
|
205
206
|
}
|
package/dist/ui/Validate.js
CHANGED
|
@@ -7,11 +7,11 @@ import { Colors, getTextColor } from '../services/colors.js';
|
|
|
7
7
|
import { useInput } from '../services/keyboard.js';
|
|
8
8
|
import { formatErrorMessage } from '../services/messages.js';
|
|
9
9
|
import { ensureMinimumTime } from '../services/timing.js';
|
|
10
|
-
import { saveConfig, unflattenConfig } from '../services/configuration.js';
|
|
10
|
+
import { DebugLevel, saveConfig, unflattenConfig, } from '../services/configuration.js';
|
|
11
11
|
import { Config, StepType } from './Config.js';
|
|
12
12
|
import { Spinner } from './Spinner.js';
|
|
13
13
|
const MIN_PROCESSING_TIME = 1000;
|
|
14
|
-
export function Validate({ missingConfig, userRequest, state, status, service, children, debug, onError, onComplete, onAborted, handlers, }) {
|
|
14
|
+
export function Validate({ missingConfig, userRequest, state, status, service, children, debug = DebugLevel.None, onError, onComplete, onAborted, handlers, }) {
|
|
15
15
|
const isActive = status === ComponentStatus.Active;
|
|
16
16
|
const [error, setError] = useState(null);
|
|
17
17
|
const [completionMessage, setCompletionMessage] = useState(null);
|
|
@@ -128,9 +128,15 @@ export function Validate({ missingConfig, userRequest, state, status, service, c
|
|
|
128
128
|
for (const [section, sectionConfig] of Object.entries(configBySection)) {
|
|
129
129
|
saveConfig(section, sectionConfig);
|
|
130
130
|
}
|
|
131
|
+
// Mark validation component as complete before invoking callback
|
|
132
|
+
// This allows the workflow to proceed to execution
|
|
133
|
+
handlers?.completeActive();
|
|
134
|
+
// Invoke callback which will queue the Execute component
|
|
131
135
|
onComplete?.(configRequirements);
|
|
132
136
|
};
|
|
133
137
|
const handleConfigAborted = (operation) => {
|
|
138
|
+
// Mark validation component as complete when aborted
|
|
139
|
+
handlers?.completeActive();
|
|
134
140
|
onAborted(operation);
|
|
135
141
|
};
|
|
136
142
|
return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isActive && !completionMessage && !error && (_jsxs(Box, { marginLeft: 1, children: [_jsxs(Text, { color: getTextColor(isActive), children: ["Validating configuration requirements.", ' '] }), _jsx(Spinner, {})] })), completionMessage && (_jsx(Box, { marginLeft: 1, children: _jsx(Text, { color: getTextColor(isActive), children: completionMessage }) })), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) })), configSteps && !error && (_jsx(Box, { marginTop: 1, children: _jsx(Config, { steps: configSteps, status: status, debug: debug, onFinished: handleConfigFinished, onAborted: handleConfigAborted, handlers: handlers }) })), children] }));
|
package/dist/ui/Workflow.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Box, Static } from 'ink';
|
|
|
4
4
|
import { ComponentStatus, } from '../types/components.js';
|
|
5
5
|
import { ComponentName, FeedbackType } from '../types/types.js';
|
|
6
6
|
import { createFeedback, isStateless, markAsDone, } from '../services/components.js';
|
|
7
|
+
import { DebugLevel } from '../services/configuration.js';
|
|
7
8
|
import { exitApp } from '../services/process.js';
|
|
8
9
|
import { getCancellationMessage } from '../services/messages.js';
|
|
9
10
|
import { Component } from './Component.js';
|
|
@@ -188,5 +189,5 @@ export const Workflow = ({ initialQueue, debug }) => {
|
|
|
188
189
|
// Pending components don't receive input
|
|
189
190
|
return _jsx(Component, { def: pending, debug: debug }, pending.id);
|
|
190
191
|
}, [current, debug]);
|
|
191
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: timeline, children: (item) => (_jsx(Box, { marginTop: 1, children: _jsx(Component, { def: item, debug:
|
|
192
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: timeline, children: (item) => (_jsx(Box, { marginTop: 1, children: _jsx(Component, { def: item, debug: DebugLevel.None }) }, item.id)) }, "timeline"), pendingComponent && _jsx(Box, { marginTop: 1, children: pendingComponent }), activeComponent && _jsx(Box, { marginTop: 1, children: activeComponent })] }));
|
|
192
193
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prompt-language-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Your personal command-line concierge. Ask politely, and it gets things done.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"clean": "rm -rf dist",
|
|
15
15
|
"typecheck": "tsc --project tsconfig.eslint.json",
|
|
16
|
-
"build": "npm run typecheck && npm run clean && tsc && chmod +x dist/index.js && mkdir -p dist/
|
|
16
|
+
"build": "npm run typecheck && npm run clean && tsc && chmod +x dist/index.js && mkdir -p dist/skills && cp src/skills/*.md dist/skills/",
|
|
17
17
|
"dev": "npm run build && tsc --watch",
|
|
18
18
|
"prepare": "husky",
|
|
19
19
|
"prepublishOnly": "npm run check",
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse skill reference from execution line
|
|
3
|
-
* Returns skill name if line is a reference, otherwise null
|
|
4
|
-
*/
|
|
5
|
-
export function parseSkillReference(line) {
|
|
6
|
-
const match = line.match(/^\[(.+)\]$/);
|
|
7
|
-
return match ? match[1].trim() : null;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Check if execution line is a skill reference
|
|
11
|
-
*/
|
|
12
|
-
export function isSkillReference(line) {
|
|
13
|
-
return /^\[.+\]$/.test(line.trim());
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Expand skill references in execution commands
|
|
17
|
-
* Returns expanded execution lines with references replaced
|
|
18
|
-
* Throws error if circular reference detected
|
|
19
|
-
*/
|
|
20
|
-
export function expandSkillReferences(execution, skillLookup, visited = new Set()) {
|
|
21
|
-
const expanded = [];
|
|
22
|
-
for (const line of execution) {
|
|
23
|
-
const skillName = parseSkillReference(line);
|
|
24
|
-
if (!skillName) {
|
|
25
|
-
// Not a reference, keep as-is
|
|
26
|
-
expanded.push(line);
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
// Check for circular reference
|
|
30
|
-
if (visited.has(skillName)) {
|
|
31
|
-
throw new Error(`Circular skill reference detected: ${Array.from(visited).join(' → ')} → ${skillName}`);
|
|
32
|
-
}
|
|
33
|
-
// Look up referenced skill
|
|
34
|
-
const skill = skillLookup(skillName);
|
|
35
|
-
if (!skill) {
|
|
36
|
-
// Referenced skill not found, keep as-is
|
|
37
|
-
expanded.push(line);
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
// Recursively expand referenced skill's execution
|
|
41
|
-
const newVisited = new Set(visited);
|
|
42
|
-
newVisited.add(skillName);
|
|
43
|
-
const referencedExecution = expandSkillReferences(skill.execution, skillLookup, newVisited);
|
|
44
|
-
expanded.push(...referencedExecution);
|
|
45
|
-
}
|
|
46
|
-
return expanded;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Get all skill names referenced in execution (including nested)
|
|
50
|
-
* Returns unique set of skill names
|
|
51
|
-
*/
|
|
52
|
-
export function getReferencedSkills(execution, skillLookup, visited = new Set()) {
|
|
53
|
-
const referenced = new Set();
|
|
54
|
-
for (const line of execution) {
|
|
55
|
-
const skillName = parseSkillReference(line);
|
|
56
|
-
if (!skillName || visited.has(skillName)) {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
referenced.add(skillName);
|
|
60
|
-
const skill = skillLookup(skillName);
|
|
61
|
-
if (skill) {
|
|
62
|
-
const newVisited = new Set(visited);
|
|
63
|
-
newVisited.add(skillName);
|
|
64
|
-
const nested = getReferencedSkills(skill.execution, skillLookup, newVisited);
|
|
65
|
-
for (const name of nested) {
|
|
66
|
-
referenced.add(name);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return referenced;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Validate skill references don't form cycles
|
|
74
|
-
* Returns true if valid, false if circular reference detected
|
|
75
|
-
*/
|
|
76
|
-
export function validateNoCycles(execution, skillLookup, visited = new Set()) {
|
|
77
|
-
try {
|
|
78
|
-
expandSkillReferences(execution, skillLookup, visited);
|
|
79
|
-
return true;
|
|
80
|
-
}
|
|
81
|
-
catch (error) {
|
|
82
|
-
if (error instanceof Error && error.message.includes('Circular')) {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
File without changes
|
|
File without changes
|