prompt-language-shell 0.4.9 → 0.5.2

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.
@@ -0,0 +1,43 @@
1
+ export const validateTool = {
2
+ name: 'validate',
3
+ description: 'Validate skill requirements and generate natural language descriptions for missing configuration values. Given skill context and missing config paths, create CONFIG tasks with helpful, contextual descriptions.',
4
+ input_schema: {
5
+ type: 'object',
6
+ properties: {
7
+ message: {
8
+ type: 'string',
9
+ description: 'Empty string or brief message (not shown to user, can be left empty)',
10
+ },
11
+ tasks: {
12
+ type: 'array',
13
+ description: 'Array of CONFIG tasks with natural language descriptions for missing config values',
14
+ items: {
15
+ type: 'object',
16
+ properties: {
17
+ action: {
18
+ type: 'string',
19
+ description: 'Natural language description explaining what the config value is for, followed by the config path in curly brackets {config.path}. Example: "Path to Alpha project repository (legacy implementation) {project.alpha.repo}"',
20
+ },
21
+ type: {
22
+ type: 'string',
23
+ description: 'Must be "config" for all tasks returned by this tool',
24
+ },
25
+ params: {
26
+ type: 'object',
27
+ description: 'Must include key field with the config path',
28
+ properties: {
29
+ key: {
30
+ type: 'string',
31
+ description: 'The config path (e.g., "opera.gx.repo")',
32
+ },
33
+ },
34
+ required: ['key'],
35
+ },
36
+ },
37
+ required: ['action', 'type', 'params'],
38
+ },
39
+ },
40
+ },
41
+ required: ['message', 'tasks'],
42
+ },
43
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Type definitions for the structured skill system
3
+ */
4
+ export {};
@@ -13,6 +13,7 @@ export var ComponentName;
13
13
  ComponentName["Answer"] = "answer";
14
14
  ComponentName["AnswerDisplay"] = "answerDisplay";
15
15
  ComponentName["Execute"] = "execute";
16
+ ComponentName["Validate"] = "validate";
16
17
  })(ComponentName || (ComponentName = {}));
17
18
  export var TaskType;
18
19
  (function (TaskType) {
package/dist/ui/Answer.js CHANGED
@@ -4,6 +4,7 @@ import { Box, Text } from 'ink';
4
4
  import { Colors, getTextColor } from '../services/colors.js';
5
5
  import { useInput } from '../services/keyboard.js';
6
6
  import { formatErrorMessage } from '../services/messages.js';
7
+ import { withMinimumTime } from '../services/timing.js';
7
8
  import { Spinner } from './Spinner.js';
8
9
  const MINIMUM_PROCESSING_TIME = 400;
9
10
  export function Answer({ question, state, service, onError, onComplete, onAborted, }) {
@@ -30,13 +31,9 @@ export function Answer({ question, state, service, onError, onComplete, onAborte
30
31
  }
31
32
  let mounted = true;
32
33
  async function process(svc) {
33
- const startTime = Date.now();
34
34
  try {
35
- // Call answer tool
36
- const result = await svc.processWithTool(question, 'answer');
37
- const elapsed = Date.now() - startTime;
38
- const remainingTime = Math.max(0, MINIMUM_PROCESSING_TIME - elapsed);
39
- await new Promise((resolve) => setTimeout(resolve, remainingTime));
35
+ // Call answer tool with minimum processing time for UX polish
36
+ const result = await withMinimumTime(() => svc.processWithTool(question, 'answer'), MINIMUM_PROCESSING_TIME);
40
37
  if (mounted) {
41
38
  // Extract answer from result
42
39
  const answer = result.answer || '';
@@ -45,9 +42,6 @@ export function Answer({ question, state, service, onError, onComplete, onAborte
45
42
  }
46
43
  }
47
44
  catch (err) {
48
- const elapsed = Date.now() - startTime;
49
- const remainingTime = Math.max(0, MINIMUM_PROCESSING_TIME - elapsed);
50
- await new Promise((resolve) => setTimeout(resolve, remainingTime));
51
45
  if (mounted) {
52
46
  const errorMessage = formatErrorMessage(err);
53
47
  setIsLoading(false);
@@ -5,6 +5,7 @@ import { TaskType } from '../types/types.js';
5
5
  import { Colors } from '../services/colors.js';
6
6
  import { useInput } from '../services/keyboard.js';
7
7
  import { formatErrorMessage } from '../services/messages.js';
8
+ import { ensureMinimumTime } from '../services/timing.js';
8
9
  import { Spinner } from './Spinner.js';
9
10
  const MIN_PROCESSING_TIME = 1000; // purely for visual effect
10
11
  export function Command({ command, state, service, children, onError, onComplete, onAborted, }) {
@@ -42,18 +43,14 @@ export function Command({ command, state, service, children, onError, onComplete
42
43
  // Call CONFIG tool to get specific config keys
43
44
  result = await svc.processWithTool(query, 'config');
44
45
  }
45
- const elapsed = Date.now() - startTime;
46
- const remainingTime = Math.max(0, MIN_PROCESSING_TIME - elapsed);
47
- await new Promise((resolve) => setTimeout(resolve, remainingTime));
46
+ await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
48
47
  if (mounted) {
49
48
  setIsLoading(false);
50
49
  onComplete?.(result.message, result.tasks);
51
50
  }
52
51
  }
53
52
  catch (err) {
54
- const elapsed = Date.now() - startTime;
55
- const remainingTime = Math.max(0, MIN_PROCESSING_TIME - elapsed);
56
- await new Promise((resolve) => setTimeout(resolve, remainingTime));
53
+ await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
57
54
  if (mounted) {
58
55
  const errorMessage = formatErrorMessage(err);
59
56
  setIsLoading(false);
@@ -13,6 +13,7 @@ import { Message } from './Message.js';
13
13
  import { Plan } from './Plan.js';
14
14
  import { Refinement } from './Refinement.js';
15
15
  import { Report } from './Report.js';
16
+ import { Validate } from './Validate.js';
16
17
  import { Welcome } from './Welcome.js';
17
18
  export const Component = React.memo(function Component({ def, debug, }) {
18
19
  switch (def.name) {
@@ -21,7 +22,7 @@ export const Component = React.memo(function Component({ def, debug, }) {
21
22
  case ComponentName.Config: {
22
23
  const props = def.props;
23
24
  const state = def.state;
24
- return _jsx(Config, { ...props, state: state });
25
+ return _jsx(Config, { ...props, state: state, debug: debug });
25
26
  }
26
27
  case ComponentName.Command: {
27
28
  const props = def.props;
@@ -66,5 +67,10 @@ export const Component = React.memo(function Component({ def, debug, }) {
66
67
  const state = def.state;
67
68
  return _jsx(Execute, { ...props, state: state });
68
69
  }
70
+ case ComponentName.Validate: {
71
+ const props = def.props;
72
+ const state = def.state;
73
+ return _jsx(Validate, { ...props, state: state });
74
+ }
69
75
  }
70
76
  });
package/dist/ui/Config.js CHANGED
@@ -57,7 +57,7 @@ function SelectionStep({ options, selectedIndex, isCurrentStep, }) {
57
57
  return (_jsx(Box, { marginRight: 2, children: _jsx(Text, { dimColor: !isSelected || !isCurrentStep, bold: isSelected, children: option.label }) }, option.value));
58
58
  }) }));
59
59
  }
60
- export function Config({ steps, state, onFinished, onAborted }) {
60
+ export function Config({ steps, state, debug, onFinished, onAborted }) {
61
61
  const done = state?.done ?? false;
62
62
  const [step, setStep] = React.useState(done ? steps.length : 0);
63
63
  const [values, setValues] = React.useState(() => {
@@ -220,6 +220,6 @@ export function Config({ steps, state, onFinished, onAborted }) {
220
220
  if (!shouldShow) {
221
221
  return null;
222
222
  }
223
- return (_jsxs(Box, { flexDirection: "column", marginTop: index === 0 ? 0 : 1, children: [_jsx(Box, { children: _jsxs(Text, { children: [stepConfig.description, ":"] }) }), _jsxs(Box, { children: [_jsx(Text, { children: " " }), _jsx(Text, { color: Colors.Action.Select, dimColor: !isCurrentStep, children: ">" }), _jsx(Text, { children: " " }), renderStepInput(stepConfig, isCurrentStep)] })] }, stepConfig.key));
223
+ 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.key));
224
224
  }) }));
225
225
  }
@@ -6,6 +6,9 @@ import { useInput } from '../services/keyboard.js';
6
6
  import { formatErrorMessage } from '../services/messages.js';
7
7
  import { formatDuration } from '../services/utils.js';
8
8
  import { ExecutionStatus, executeCommands, } from '../services/shell.js';
9
+ import { replacePlaceholders } from '../services/placeholder-resolver.js';
10
+ import { loadUserConfig } from '../services/config-loader.js';
11
+ import { ensureMinimumTime } from '../services/timing.js';
9
12
  import { Spinner } from './Spinner.js';
10
13
  const MINIMUM_PROCESSING_TIME = 400;
11
14
  const STATUS_ICONS = {
@@ -13,7 +16,22 @@ const STATUS_ICONS = {
13
16
  [ExecutionStatus.Running]: '• ',
14
17
  [ExecutionStatus.Success]: '✓ ',
15
18
  [ExecutionStatus.Failed]: '✗ ',
19
+ [ExecutionStatus.Aborted]: '⊘ ',
16
20
  };
21
+ function calculateTotalElapsed(commandStatuses) {
22
+ return commandStatuses.reduce((sum, cmd) => {
23
+ if (cmd.elapsed !== undefined) {
24
+ return sum + cmd.elapsed;
25
+ }
26
+ if (cmd.startTime) {
27
+ const elapsed = cmd.endTime
28
+ ? cmd.endTime - cmd.startTime
29
+ : Date.now() - cmd.startTime;
30
+ return sum + elapsed;
31
+ }
32
+ return sum;
33
+ }, 0);
34
+ }
17
35
  function getStatusColors(status) {
18
36
  switch (status) {
19
37
  case ExecutionStatus.Pending:
@@ -44,6 +62,13 @@ function getStatusColors(status) {
44
62
  command: Colors.Status.Error,
45
63
  symbol: Palette.Gray,
46
64
  };
65
+ case ExecutionStatus.Aborted:
66
+ return {
67
+ icon: Palette.DarkOrange,
68
+ description: getTextColor(true),
69
+ command: Palette.DarkOrange,
70
+ symbol: Palette.Gray,
71
+ };
47
72
  }
48
73
  }
49
74
  function CommandStatusDisplay({ item, elapsed }) {
@@ -75,7 +100,24 @@ export function Execute({ tasks, state, service, onError, onComplete, onAborted,
75
100
  if (key.escape && (isLoading || isExecuting) && !done) {
76
101
  setIsLoading(false);
77
102
  setIsExecuting(false);
78
- onAborted();
103
+ setRunningIndex(null);
104
+ // Mark any running command as aborted when cancelled
105
+ const now = Date.now();
106
+ setCommandStatuses((prev) => prev.map((item) => {
107
+ if (item.status === ExecutionStatus.Running) {
108
+ const elapsed = item.startTime
109
+ ? Math.floor((now - item.startTime) / 1000) * 1000
110
+ : undefined;
111
+ return {
112
+ ...item,
113
+ status: ExecutionStatus.Aborted,
114
+ endTime: now,
115
+ elapsed,
116
+ };
117
+ }
118
+ return item;
119
+ }));
120
+ onAborted(calculateTotalElapsed(commandStatuses));
79
121
  }
80
122
  }, { isActive: (isLoading || isExecuting) && !done });
81
123
  // Update elapsed time for running command
@@ -97,9 +139,7 @@ export function Execute({ tasks, state, service, onError, onComplete, onAborted,
97
139
  useEffect(() => {
98
140
  if (isExecuting || commandStatuses.length === 0 || !outputs.length)
99
141
  return;
100
- // Sum up elapsed times from all commands
101
- const totalElapsed = commandStatuses.reduce((sum, cmd) => sum + (cmd.elapsed ?? 0), 0);
102
- onComplete?.(outputs, totalElapsed);
142
+ onComplete?.(outputs, calculateTotalElapsed(commandStatuses));
103
143
  }, [isExecuting, commandStatuses, outputs, onComplete]);
104
144
  useEffect(() => {
105
145
  if (done) {
@@ -114,20 +154,22 @@ export function Execute({ tasks, state, service, onError, onComplete, onAborted,
114
154
  async function process(svc) {
115
155
  const startTime = Date.now();
116
156
  try {
117
- // Format tasks for the execute tool
157
+ // Load user config for placeholder resolution
158
+ const userConfig = loadUserConfig();
159
+ // Format tasks for the execute tool and resolve placeholders
118
160
  const taskDescriptions = tasks
119
161
  .map((task) => {
162
+ // Resolve placeholders in task action
163
+ const resolvedAction = replacePlaceholders(task.action, userConfig);
120
164
  const params = task.params
121
165
  ? ` (params: ${JSON.stringify(task.params)})`
122
166
  : '';
123
- return `- ${task.action}${params}`;
167
+ return `- ${resolvedAction}${params}`;
124
168
  })
125
169
  .join('\n');
126
170
  // Call execute tool to get commands
127
171
  const result = await svc.processWithTool(taskDescriptions, 'execute');
128
- const elapsed = Date.now() - startTime;
129
- const remainingTime = Math.max(0, MINIMUM_PROCESSING_TIME - elapsed);
130
- await new Promise((resolve) => setTimeout(resolve, remainingTime));
172
+ await ensureMinimumTime(startTime, MINIMUM_PROCESSING_TIME);
131
173
  if (!mounted)
132
174
  return;
133
175
  if (!result.commands || result.commands.length === 0) {
@@ -136,9 +178,14 @@ export function Execute({ tasks, state, service, onError, onComplete, onAborted,
136
178
  onComplete?.([], 0);
137
179
  return;
138
180
  }
181
+ // Resolve placeholders in command strings before execution
182
+ const resolvedCommands = result.commands.map((cmd) => ({
183
+ ...cmd,
184
+ command: replacePlaceholders(cmd.command, userConfig),
185
+ }));
139
186
  // Set message and initialize command statuses
140
187
  setMessage(result.message);
141
- setCommandStatuses(result.commands.map((cmd, index) => ({
188
+ setCommandStatuses(resolvedCommands.map((cmd, index) => ({
142
189
  command: cmd,
143
190
  status: ExecutionStatus.Pending,
144
191
  label: tasks[index]?.action,
@@ -146,7 +193,7 @@ export function Execute({ tasks, state, service, onError, onComplete, onAborted,
146
193
  setIsLoading(false);
147
194
  setIsExecuting(true);
148
195
  // Execute commands sequentially
149
- const outputs = await executeCommands(result.commands, (progress) => {
196
+ const outputs = await executeCommands(resolvedCommands, (progress) => {
150
197
  if (!mounted)
151
198
  return;
152
199
  const now = Date.now();
@@ -186,9 +233,7 @@ export function Execute({ tasks, state, service, onError, onComplete, onAborted,
186
233
  }
187
234
  }
188
235
  catch (err) {
189
- const elapsed = Date.now() - startTime;
190
- const remainingTime = Math.max(0, MINIMUM_PROCESSING_TIME - elapsed);
191
- await new Promise((resolve) => setTimeout(resolve, remainingTime));
236
+ await ensureMinimumTime(startTime, MINIMUM_PROCESSING_TIME);
192
237
  if (mounted) {
193
238
  const errorMessage = formatErrorMessage(err);
194
239
  setIsLoading(false);
@@ -4,6 +4,7 @@ import { Box, Text } from 'ink';
4
4
  import { Colors, getTextColor } from '../services/colors.js';
5
5
  import { useInput } from '../services/keyboard.js';
6
6
  import { formatErrorMessage } from '../services/messages.js';
7
+ import { ensureMinimumTime } from '../services/timing.js';
7
8
  import { Spinner } from './Spinner.js';
8
9
  const MIN_PROCESSING_TIME = 1000;
9
10
  const BUILT_IN_CAPABILITIES = new Set([
@@ -12,9 +13,10 @@ const BUILT_IN_CAPABILITIES = new Set([
12
13
  'INTROSPECT',
13
14
  'ANSWER',
14
15
  'EXECUTE',
16
+ 'VALIDATE',
15
17
  'REPORT',
16
18
  ]);
17
- const INDIRECT_CAPABILITIES = new Set(['PLAN', 'REPORT']);
19
+ const INDIRECT_CAPABILITIES = new Set(['PLAN', 'VALIDATE', 'REPORT']);
18
20
  function parseCapabilityFromTask(task) {
19
21
  // Parse "NAME: Description" format from task.action
20
22
  const colonIndex = task.action.indexOf(':');
@@ -69,15 +71,14 @@ export function Introspect({ tasks, state, service, children, debug = false, onE
69
71
  const introspectAction = tasks[0]?.action || 'list capabilities';
70
72
  // Call introspect tool
71
73
  const result = await svc.processWithTool(introspectAction, 'introspect');
72
- const elapsed = Date.now() - startTime;
73
- const remainingTime = Math.max(0, MIN_PROCESSING_TIME - elapsed);
74
- await new Promise((resolve) => setTimeout(resolve, remainingTime));
74
+ await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
75
75
  if (mounted) {
76
76
  // Parse capabilities from returned tasks
77
77
  let capabilities = result.tasks.map(parseCapabilityFromTask);
78
78
  // Filter out internal capabilities when not in debug mode
79
79
  if (!debug) {
80
80
  capabilities = capabilities.filter((cap) => cap.name.toUpperCase() !== 'PLAN' &&
81
+ cap.name.toUpperCase() !== 'VALIDATE' &&
81
82
  cap.name.toUpperCase() !== 'REPORT');
82
83
  }
83
84
  setIsLoading(false);
@@ -85,9 +86,7 @@ export function Introspect({ tasks, state, service, children, debug = false, onE
85
86
  }
86
87
  }
87
88
  catch (err) {
88
- const elapsed = Date.now() - startTime;
89
- const remainingTime = Math.max(0, MIN_PROCESSING_TIME - elapsed);
90
- await new Promise((resolve) => setTimeout(resolve, remainingTime));
89
+ await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
91
90
  if (mounted) {
92
91
  const errorMessage = formatErrorMessage(err);
93
92
  setIsLoading(false);
@@ -0,0 +1,120 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { Box, Text } from 'ink';
4
+ import { TaskType } from '../types/types.js';
5
+ import { Colors, getTextColor } from '../services/colors.js';
6
+ import { useInput } from '../services/keyboard.js';
7
+ import { formatErrorMessage } from '../services/messages.js';
8
+ import { ensureMinimumTime } from '../services/timing.js';
9
+ import { Spinner } from './Spinner.js';
10
+ const MIN_PROCESSING_TIME = 1000;
11
+ export function Validate({ missingConfig, userRequest, state, service, children, onError, onComplete, onAborted, }) {
12
+ const done = state?.done ?? false;
13
+ const isCurrent = done === false;
14
+ const [error, setError] = useState(null);
15
+ const [isLoading, setIsLoading] = useState(state?.isLoading ?? !done);
16
+ const [completionMessage, setCompletionMessage] = useState(null);
17
+ useInput((input, key) => {
18
+ if (key.escape && isLoading && !done) {
19
+ setIsLoading(false);
20
+ onAborted();
21
+ }
22
+ }, { isActive: isLoading && !done });
23
+ useEffect(() => {
24
+ // Skip processing if done
25
+ if (done) {
26
+ return;
27
+ }
28
+ // Skip processing if no service available
29
+ if (!service) {
30
+ setError('No service available');
31
+ setIsLoading(false);
32
+ return;
33
+ }
34
+ let mounted = true;
35
+ async function process(svc) {
36
+ const startTime = Date.now();
37
+ try {
38
+ // Build prompt for VALIDATE tool
39
+ const prompt = buildValidatePrompt(missingConfig, userRequest);
40
+ // Call validate tool
41
+ const result = await svc.processWithTool(prompt, 'validate');
42
+ await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
43
+ if (mounted) {
44
+ // Extract CONFIG tasks with descriptions from result
45
+ const configTasks = result.tasks.filter((task) => task.type === TaskType.Config);
46
+ // Build ConfigRequirements with descriptions
47
+ const withDescriptions = configTasks.map((task) => {
48
+ const key = typeof task.params?.key === 'string'
49
+ ? task.params.key
50
+ : 'unknown';
51
+ const original = missingConfig.find((req) => req.path === key);
52
+ return {
53
+ path: key,
54
+ type: original?.type || 'string',
55
+ description: task.action,
56
+ };
57
+ });
58
+ // Build completion message showing which config properties are needed
59
+ const count = withDescriptions.length;
60
+ const propertyWord = count === 1 ? 'property' : 'properties';
61
+ // Shuffle between different message variations
62
+ const messages = [
63
+ `Additional configuration ${propertyWord} required.`,
64
+ `Configuration ${propertyWord} needed.`,
65
+ `Missing configuration ${propertyWord} detected.`,
66
+ `Setup requires configuration ${propertyWord}.`,
67
+ ];
68
+ const message = messages[Math.floor(Math.random() * messages.length)];
69
+ setCompletionMessage(message);
70
+ setIsLoading(false);
71
+ onComplete?.(withDescriptions);
72
+ }
73
+ }
74
+ catch (err) {
75
+ await ensureMinimumTime(startTime, MIN_PROCESSING_TIME);
76
+ if (mounted) {
77
+ const errorMessage = formatErrorMessage(err);
78
+ setIsLoading(false);
79
+ if (onError) {
80
+ onError(errorMessage);
81
+ }
82
+ else {
83
+ setError(errorMessage);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ process(service);
89
+ return () => {
90
+ mounted = false;
91
+ };
92
+ }, [
93
+ missingConfig,
94
+ userRequest,
95
+ done,
96
+ service,
97
+ onComplete,
98
+ onError,
99
+ onAborted,
100
+ ]);
101
+ // Don't render when done and nothing to show
102
+ if (done && !completionMessage && !error && !children) {
103
+ return null;
104
+ }
105
+ return (_jsxs(Box, { alignSelf: "flex-start", flexDirection: "column", children: [isLoading && (_jsxs(Box, { children: [_jsxs(Text, { color: getTextColor(isCurrent), children: ["Validating configuration requirements.", ' '] }), _jsx(Spinner, {})] })), completionMessage && !isLoading && (_jsx(Box, { children: _jsx(Text, { color: getTextColor(isCurrent), children: completionMessage }) })), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: Colors.Status.Error, children: ["Error: ", error] }) })), children] }));
106
+ }
107
+ /**
108
+ * Build prompt for VALIDATE tool
109
+ */
110
+ function buildValidatePrompt(missingConfig, userRequest) {
111
+ const configList = missingConfig
112
+ .map((req) => `- Config path: ${req.path}\n Type: ${req.type}`)
113
+ .join('\n');
114
+ return `User requested: "${userRequest}"
115
+
116
+ Missing configuration values:
117
+ ${configList}
118
+
119
+ Generate natural language descriptions for these configuration values based on the skill context.`;
120
+ }
@@ -1,22 +1,29 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Box, Text } from 'ink';
3
+ import { Palette } from '../services/colors.js';
3
4
  import { Panel } from './Panel.js';
5
+ export function Welcome({ app }) {
6
+ return (_jsx(Box, { alignSelf: "flex-start", children: _jsxs(Panel, { children: [_jsx(Header, { app: app }), _jsx(Description, { description: app.description }), _jsx(Usage, {})] }) }));
7
+ }
4
8
  function Header({ app }) {
5
9
  const words = app.name
6
10
  .split('-')
7
11
  .map((word) => word.charAt(0).toUpperCase() + word.slice(1));
8
- return (_jsxs(Box, { marginBottom: 1, gap: 1, children: [words.map((word, index) => (_jsx(Text, { color: "greenBright", bold: true, children: word }, index))), _jsxs(Text, { color: "whiteBright", dimColor: true, children: ["v", app.version] }), app.isDev && _jsx(Text, { color: "yellowBright", children: "dev" })] }));
12
+ return (_jsxs(Box, { marginBottom: 1, gap: 1, children: [words.map((word, index) => (_jsx(Text, { color: Palette.BrightGreen, bold: true, children: word }, index))), _jsxs(Text, { color: Palette.AshGray, children: ["v", app.version] }), app.isDev && _jsx(Text, { color: Palette.Yellow, children: "dev" })] }));
9
13
  }
10
14
  function Description({ description }) {
11
15
  const lines = description
12
16
  .split('. ')
13
17
  .map((line) => line.replace(/\.$/, ''))
14
18
  .filter(Boolean);
15
- return (_jsx(_Fragment, { children: lines.map((line, index) => (_jsx(Box, { children: _jsxs(Text, { color: "white", children: [line, "."] }) }, index))) }));
19
+ return (_jsx(_Fragment, { children: lines.map((line, index) => (_jsx(Box, { children: _jsxs(Text, { color: Palette.White, children: [line, "."] }) }, index))) }));
16
20
  }
17
21
  function Usage() {
18
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "brightWhite", bold: true, children: "Usage:" }), _jsxs(Box, { gap: 1, children: [_jsx(Text, { color: "whiteBright", dimColor: true, children: ">" }), _jsxs(Box, { gap: 1, children: [_jsx(Text, { color: "greenBright", bold: true, children: "pls" }), _jsx(Text, { color: "yellow", bold: true, children: "[describe your request]" })] })] })] }));
22
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, gap: 1, children: [_jsx(Section, { title: "Get started:", children: _jsx(Example, { children: "list skills" }) }), _jsx(Section, { title: "Usage:", children: _jsx(Example, { children: "[describe your request]" }) })] }));
19
23
  }
20
- export function Welcome({ app }) {
21
- return (_jsx(Box, { alignSelf: "flex-start", children: _jsxs(Panel, { children: [_jsx(Header, { app: app }), _jsx(Description, { description: app.description }), _jsx(Usage, {})] }) }));
24
+ function Section({ title, children, }) {
25
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: Palette.White, children: title }), children] }));
26
+ }
27
+ function Example({ children }) {
28
+ return (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: Palette.Gray, children: ">" }), _jsx(Text, { color: Palette.BrightGreen, bold: true, children: "pls" }), _jsx(Text, { color: Palette.Yellow, children: children })] }));
22
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prompt-language-shell",
3
- "version": "0.4.9",
3
+ "version": "0.5.2",
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",