prompt-language-shell 0.9.0 → 0.9.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.
Files changed (64) hide show
  1. package/dist/{ui/Main.js → Main.js} +24 -17
  2. package/dist/{ui → components}/Component.js +31 -26
  3. package/dist/{ui → components}/Workflow.js +23 -7
  4. package/dist/{ui → components/controllers}/Answer.js +18 -17
  5. package/dist/{ui → components/controllers}/Command.js +21 -24
  6. package/dist/{ui → components/controllers}/Config.js +17 -119
  7. package/dist/components/controllers/Confirm.js +42 -0
  8. package/dist/components/controllers/Execute.js +288 -0
  9. package/dist/{ui → components/controllers}/Introspect.js +22 -39
  10. package/dist/components/controllers/Refinement.js +18 -0
  11. package/dist/{ui → components/controllers}/Schedule.js +8 -124
  12. package/dist/{ui → components/controllers}/Validate.js +37 -50
  13. package/dist/components/views/Answer.js +28 -0
  14. package/dist/components/views/Command.js +11 -0
  15. package/dist/components/views/Config.js +115 -0
  16. package/dist/components/views/Confirm.js +24 -0
  17. package/dist/components/views/Execute.js +60 -0
  18. package/dist/{ui → components/views}/Feedback.js +3 -3
  19. package/dist/components/views/Introspect.js +17 -0
  20. package/dist/{ui → components/views}/Label.js +3 -3
  21. package/dist/{ui → components/views}/List.js +3 -3
  22. package/dist/{ui → components/views}/Output.js +2 -2
  23. package/dist/components/views/Refinement.js +9 -0
  24. package/dist/{ui → components/views}/Report.js +1 -1
  25. package/dist/components/views/Schedule.js +120 -0
  26. package/dist/{ui → components/views}/Separator.js +1 -1
  27. package/dist/{ui → components/views}/Spinner.js +1 -1
  28. package/dist/{ui → components/views}/Subtask.js +10 -7
  29. package/dist/components/views/Task.js +18 -0
  30. package/dist/components/views/Upcoming.js +30 -0
  31. package/dist/{ui → components/views}/UserQuery.js +1 -1
  32. package/dist/components/views/Validate.js +17 -0
  33. package/dist/{ui → components/views}/Welcome.js +1 -1
  34. package/dist/{services/config-labels.js → configuration/labels.js} +1 -1
  35. package/dist/configuration/schema.js +2 -2
  36. package/dist/configuration/steps.js +171 -0
  37. package/dist/configuration/transformation.js +17 -0
  38. package/dist/execution/handlers.js +20 -60
  39. package/dist/execution/processing.js +3 -1
  40. package/dist/execution/reducer.js +34 -44
  41. package/dist/execution/runner.js +99 -0
  42. package/dist/execution/types.js +4 -4
  43. package/dist/execution/utils.js +23 -1
  44. package/dist/index.js +1 -1
  45. package/dist/services/components.js +109 -394
  46. package/dist/services/logger.js +3 -3
  47. package/dist/services/messages.js +19 -0
  48. package/dist/services/refinement.js +5 -2
  49. package/dist/services/router.js +136 -55
  50. package/dist/services/shell.js +26 -6
  51. package/dist/services/timing.js +1 -0
  52. package/dist/skills/execute.md +40 -14
  53. package/dist/tools/execute.tool.js +0 -4
  54. package/dist/types/schemas.js +0 -1
  55. package/package.json +1 -1
  56. package/dist/parser.js +0 -13
  57. package/dist/services/config-utils.js +0 -20
  58. package/dist/ui/Confirm.js +0 -62
  59. package/dist/ui/Execute.js +0 -294
  60. package/dist/ui/Refinement.js +0 -23
  61. package/dist/ui/Task.js +0 -175
  62. /package/dist/{ui → components/views}/Debug.js +0 -0
  63. /package/dist/{ui → components/views}/Message.js +0 -0
  64. /package/dist/{ui → components/views}/Panel.js +0 -0
@@ -1,407 +1,122 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { parse as parseYaml } from 'yaml';
3
- import { ConfigDefinitionType, } from '../configuration/types.js';
4
2
  import { ComponentStatus, } from '../types/components.js';
5
3
  import { ComponentName } from '../types/types.js';
6
- import { getConfigPath, loadConfig } from '../configuration/io.js';
7
- import { getConfigSchema } from '../configuration/schema.js';
8
- import { getConfigLabel } from './config-labels.js';
9
- import { defaultFileSystem } from './filesystem.js';
10
- import { getConfirmationMessage } from './messages.js';
11
- import { StepType } from '../ui/Config.js';
12
- export function createWelcomeDefinition(app) {
13
- return {
14
- id: randomUUID(),
15
- name: ComponentName.Welcome,
16
- props: { app },
17
- status: ComponentStatus.Awaiting,
18
- };
19
- }
20
- export function createConfigSteps() {
21
- // Use schema-based config step generation for required Anthropic settings
22
- return createConfigStepsFromSchema(['anthropic.key', 'anthropic.model']);
23
- }
24
4
  /**
25
- * Get current config value for a dotted key path
5
+ * Shared component creation utility
26
6
  */
27
- function getConfigValue(config, key) {
28
- if (!config)
29
- return undefined;
30
- const parts = key.split('.');
31
- let value = config;
32
- for (const part of parts) {
33
- if (value && typeof value === 'object' && part in value) {
34
- value = value[part];
35
- }
36
- else {
37
- return undefined;
38
- }
39
- }
40
- return value;
41
- }
7
+ const createComponent = (name, props, state, status = ComponentStatus.Awaiting) => ({
8
+ id: randomUUID(),
9
+ name,
10
+ props,
11
+ ...(state !== undefined ? { state } : {}),
12
+ status,
13
+ });
42
14
  /**
43
- * Get validation function for a config definition
15
+ * Create a simple component without state
44
16
  */
45
- function getValidator(definition) {
46
- switch (definition.type) {
47
- case ConfigDefinitionType.RegExp:
48
- return (value) => definition.pattern.test(value);
49
- case ConfigDefinitionType.String:
50
- return () => true; // Strings are always valid
51
- case ConfigDefinitionType.Enum:
52
- return (value) => definition.values.includes(value);
53
- case ConfigDefinitionType.Number:
54
- return (value) => !isNaN(Number(value));
55
- case ConfigDefinitionType.Boolean:
56
- return (value) => value === 'true' || value === 'false';
57
- }
58
- }
17
+ const createSimpleComponent = (name, props, status) => createComponent(name, props, undefined, status);
59
18
  /**
60
- * Create config steps from schema for specified keys
19
+ * Create a managed component with state
61
20
  */
62
- export function createConfigStepsFromSchema(keys, fs = defaultFileSystem) {
63
- const schema = getConfigSchema();
64
- let currentConfig = null;
65
- let rawConfig = null;
66
- // Load validated config (may fail if config has validation errors)
67
- try {
68
- currentConfig = loadConfig(fs);
69
- }
70
- catch {
71
- // Config doesn't exist or has validation errors, use defaults
72
- }
73
- // Load raw config separately (for discovered keys not in schema)
74
- try {
75
- const configFile = getConfigPath();
76
- if (fs.exists(configFile)) {
77
- const content = fs.readFile(configFile, 'utf-8');
78
- rawConfig = parseYaml(content);
79
- }
80
- }
81
- catch {
82
- // Config file doesn't exist or can't be parsed
83
- }
84
- return keys.map((key) => {
85
- // Check if key is in schema (system config)
86
- if (!(key in schema)) {
87
- // Key is not in schema - it's from a skill or discovered config
88
- // Create a simple text step with cached label or full path as description
89
- const keyParts = key.split('.');
90
- const shortKey = keyParts[keyParts.length - 1];
91
- // Load current value if it exists (use rawConfig since discovered keys aren't in validated config)
92
- const currentValue = getConfigValue(rawConfig, key);
93
- const value = currentValue !== undefined && typeof currentValue === 'string'
94
- ? currentValue
95
- : null;
96
- // Use cached label if available, fallback to key path
97
- const cachedLabel = getConfigLabel(key, fs);
98
- return {
99
- description: cachedLabel ?? key,
100
- key: shortKey,
101
- path: key,
102
- type: StepType.Text,
103
- value,
104
- validate: () => true, // Accept any string for now
105
- };
106
- }
107
- const definition = schema[key];
108
- const currentValue = getConfigValue(currentConfig, key);
109
- const keyParts = key.split('.');
110
- const shortKey = keyParts[keyParts.length - 1];
111
- // Map definition to ConfigStep based on type
112
- switch (definition.type) {
113
- case ConfigDefinitionType.RegExp:
114
- case ConfigDefinitionType.String: {
115
- const value = currentValue !== undefined && typeof currentValue === 'string'
116
- ? currentValue
117
- : definition.type === ConfigDefinitionType.String
118
- ? (definition.default ?? '')
119
- : null;
120
- return {
121
- description: definition.description,
122
- key: shortKey,
123
- path: key,
124
- type: StepType.Text,
125
- value,
126
- validate: getValidator(definition),
127
- };
128
- }
129
- case ConfigDefinitionType.Number: {
130
- const value = currentValue !== undefined && typeof currentValue === 'number'
131
- ? String(currentValue)
132
- : definition.default !== undefined
133
- ? String(definition.default)
134
- : '0';
135
- return {
136
- description: definition.description,
137
- key: shortKey,
138
- path: key,
139
- type: StepType.Text,
140
- value,
141
- validate: getValidator(definition),
142
- };
143
- }
144
- case ConfigDefinitionType.Enum: {
145
- const currentStr = currentValue !== undefined && typeof currentValue === 'string'
146
- ? currentValue
147
- : definition.default;
148
- const defaultIndex = currentStr
149
- ? definition.values.indexOf(currentStr)
150
- : 0;
151
- return {
152
- description: definition.description,
153
- key: shortKey,
154
- path: key,
155
- type: StepType.Selection,
156
- options: definition.values.map((value) => ({
157
- label: value,
158
- value,
159
- })),
160
- defaultIndex: Math.max(0, defaultIndex),
161
- validate: getValidator(definition),
162
- };
163
- }
164
- case ConfigDefinitionType.Boolean: {
165
- const currentBool = currentValue !== undefined && typeof currentValue === 'boolean'
166
- ? currentValue
167
- : undefined;
168
- return {
169
- description: definition.description,
170
- key: shortKey,
171
- path: key,
172
- type: StepType.Selection,
173
- options: [
174
- { label: 'yes', value: 'true' },
175
- { label: 'no', value: 'false' },
176
- ],
177
- defaultIndex: currentBool !== undefined ? (currentBool ? 0 : 1) : 0,
178
- validate: getValidator(definition),
179
- };
180
- }
181
- }
182
- });
183
- }
184
- export function createConfigDefinition(onFinished, onAborted) {
185
- return {
186
- id: randomUUID(),
187
- name: ComponentName.Config,
188
- status: ComponentStatus.Awaiting,
189
- state: {
190
- values: {},
191
- completedStep: 0,
192
- selectedIndex: 0,
193
- },
194
- props: {
195
- steps: createConfigSteps(),
196
- onFinished,
197
- onAborted,
198
- },
199
- };
200
- }
21
+ const createManagedComponent = (name, props, state, status) => createComponent(name, props, state, status);
201
22
  /**
202
- * Create config definition with specific keys
23
+ * Initial state constants for managed components
203
24
  */
204
- export function createConfigDefinitionWithKeys(keys, onFinished, onAborted) {
205
- return {
206
- id: randomUUID(),
207
- name: ComponentName.Config,
208
- status: ComponentStatus.Awaiting,
209
- state: {
210
- values: {},
211
- completedStep: 0,
212
- selectedIndex: 0,
213
- },
214
- props: {
215
- steps: createConfigStepsFromSchema(keys),
216
- onFinished,
217
- onAborted,
218
- },
219
- };
220
- }
221
- export function createCommandDefinition(command, service) {
222
- return {
223
- id: randomUUID(),
224
- name: ComponentName.Command,
225
- status: ComponentStatus.Awaiting,
226
- state: {
227
- error: null,
228
- message: null,
229
- tasks: [],
230
- },
231
- props: {
232
- command,
233
- service,
234
- },
235
- };
236
- }
237
- export function createScheduleDefinition(message, tasks, onSelectionConfirmed) {
238
- return {
239
- id: randomUUID(),
240
- name: ComponentName.Schedule,
241
- status: ComponentStatus.Awaiting,
242
- state: {
243
- highlightedIndex: null,
244
- currentDefineGroupIndex: 0,
245
- completedSelections: [],
246
- },
247
- props: {
248
- message,
249
- tasks,
250
- onSelectionConfirmed,
251
- },
252
- };
253
- }
254
- export function createFeedback(type, ...messages) {
255
- return {
256
- id: randomUUID(),
257
- name: ComponentName.Feedback,
258
- props: {
259
- type,
260
- message: messages.join('\n\n'),
261
- },
262
- status: ComponentStatus.Awaiting,
263
- };
264
- }
265
- export function createMessage(text) {
266
- return {
267
- id: randomUUID(),
268
- name: ComponentName.Message,
269
- props: {
270
- text,
271
- },
272
- status: ComponentStatus.Awaiting,
273
- };
274
- }
275
- export function createDebugDefinition(title, content, color) {
276
- return {
277
- id: randomUUID(),
278
- name: ComponentName.Debug,
279
- props: {
280
- title,
281
- content,
282
- color,
283
- },
284
- status: ComponentStatus.Awaiting,
285
- };
286
- }
287
- export function createRefinement(text, onAborted) {
288
- return {
289
- id: randomUUID(),
290
- name: ComponentName.Refinement,
291
- status: ComponentStatus.Awaiting,
292
- state: {},
293
- props: {
294
- text,
295
- onAborted,
296
- },
297
- };
298
- }
299
- export function createConfirmDefinition(onConfirmed, onCancelled) {
300
- return {
301
- id: randomUUID(),
302
- name: ComponentName.Confirm,
303
- status: ComponentStatus.Awaiting,
304
- state: {
305
- confirmed: false,
306
- selectedIndex: 0,
307
- },
308
- props: {
309
- message: getConfirmationMessage(),
310
- onConfirmed,
311
- onCancelled,
312
- },
313
- };
314
- }
315
- export function createIntrospectDefinition(tasks, service) {
316
- return {
317
- id: randomUUID(),
318
- name: ComponentName.Introspect,
319
- status: ComponentStatus.Awaiting,
320
- state: {
321
- error: null,
322
- capabilities: [],
323
- message: null,
324
- },
325
- props: {
326
- tasks,
327
- service,
328
- },
329
- };
330
- }
331
- export function createReportDefinition(message, capabilities) {
332
- return {
333
- id: randomUUID(),
334
- name: ComponentName.Report,
335
- props: {
336
- message,
337
- capabilities,
338
- },
339
- status: ComponentStatus.Awaiting,
340
- };
341
- }
342
- export function createAnswerDefinition(question, service) {
343
- return {
344
- id: randomUUID(),
345
- name: ComponentName.Answer,
346
- status: ComponentStatus.Awaiting,
347
- state: {
348
- error: null,
349
- answer: null,
350
- },
351
- props: {
352
- question,
353
- service,
354
- },
355
- };
356
- }
357
- export function isSimple(component) {
358
- return !('state' in component);
359
- }
25
+ const InitialConfigState = {
26
+ values: {},
27
+ completedStep: 0,
28
+ selectedIndex: 0,
29
+ };
30
+ const InitialCommandState = {
31
+ error: null,
32
+ message: null,
33
+ tasks: [],
34
+ };
35
+ const InitialScheduleState = {
36
+ highlightedIndex: null,
37
+ currentDefineGroupIndex: 0,
38
+ completedSelections: [],
39
+ };
40
+ const InitialRefinementState = {};
41
+ const InitialConfirmState = {
42
+ confirmed: false,
43
+ selectedIndex: 0,
44
+ };
45
+ const InitialIntrospectState = {
46
+ error: null,
47
+ capabilities: [],
48
+ message: null,
49
+ };
50
+ const InitialAnswerState = {
51
+ error: null,
52
+ answer: null,
53
+ };
54
+ const InitialExecuteState = {
55
+ error: null,
56
+ message: '',
57
+ summary: '',
58
+ tasks: [],
59
+ completionMessage: null,
60
+ };
61
+ const InitialValidateState = {
62
+ error: null,
63
+ completionMessage: null,
64
+ configRequirements: [],
65
+ validated: false,
66
+ };
360
67
  /**
361
- * Mark a component as done. Returns the component to be added to timeline.
362
- * Components use handlers.updateState to save their state before completion,
363
- * so this function sets the status to Done and returns the updated component.
68
+ * Create a welcome component that displays application information
364
69
  */
365
- export function markAsDone(component) {
366
- return { ...component, status: ComponentStatus.Done };
367
- }
368
- export function createExecuteDefinition(tasks, service) {
369
- return {
370
- id: randomUUID(),
371
- name: ComponentName.Execute,
372
- status: ComponentStatus.Awaiting,
373
- state: {
374
- error: null,
375
- message: '',
376
- summary: '',
377
- tasks: [],
378
- completed: 0,
379
- completionMessage: null,
380
- },
381
- props: {
382
- tasks,
383
- service,
384
- },
385
- };
386
- }
387
- export function createValidateDefinition(missingConfig, userRequest, service, onError, onValidationComplete, onAborted) {
388
- return {
389
- id: randomUUID(),
390
- name: ComponentName.Validate,
391
- status: ComponentStatus.Awaiting,
392
- state: {
393
- error: null,
394
- completionMessage: null,
395
- configRequirements: [],
396
- validated: false,
397
- },
398
- props: {
399
- missingConfig,
400
- userRequest,
401
- service,
402
- onError,
403
- onValidationComplete,
404
- onAborted,
405
- },
406
- };
407
- }
70
+ export const createWelcome = (props, status) => createSimpleComponent(ComponentName.Welcome, props, status);
71
+ /**
72
+ * Create a feedback component that displays status messages
73
+ */
74
+ export const createFeedback = (props, status) => createSimpleComponent(ComponentName.Feedback, props, status);
75
+ /**
76
+ * Create a message component that displays informational text
77
+ */
78
+ export const createMessage = (props, status) => createSimpleComponent(ComponentName.Message, props, status);
79
+ /**
80
+ * Create a debug component that displays diagnostic information
81
+ */
82
+ export const createDebug = (props, status) => createSimpleComponent(ComponentName.Debug, props, status);
83
+ /**
84
+ * Create a report component that displays capability listings
85
+ */
86
+ export const createReport = (props, status) => createSimpleComponent(ComponentName.Report, props, status);
87
+ /**
88
+ * Create a configuration component for multi-step user input
89
+ */
90
+ export const createConfig = (props, status) => createManagedComponent(ComponentName.Config, props, InitialConfigState, status);
91
+ /**
92
+ * Create a command component that processes user requests via LLM
93
+ */
94
+ export const createCommand = (props, status) => createManagedComponent(ComponentName.Command, props, InitialCommandState, status);
95
+ /**
96
+ * Create a schedule component that displays and manages task execution plans
97
+ */
98
+ export const createSchedule = (props, status) => createManagedComponent(ComponentName.Schedule, props, InitialScheduleState, status);
99
+ /**
100
+ * Create a refinement component for interactive task selection
101
+ */
102
+ export const createRefinement = (props, status) => createManagedComponent(ComponentName.Refinement, props, InitialRefinementState, status);
103
+ /**
104
+ * Create a confirmation component that prompts user for yes/no decisions
105
+ */
106
+ export const createConfirm = (props, status) => createManagedComponent(ComponentName.Confirm, props, InitialConfirmState, status);
107
+ /**
108
+ * Create an introspect component that lists available capabilities
109
+ */
110
+ export const createIntrospect = (props, status) => createManagedComponent(ComponentName.Introspect, props, InitialIntrospectState, status);
111
+ /**
112
+ * Create an answer component that responds to information requests via LLM
113
+ */
114
+ export const createAnswer = (props, status) => createManagedComponent(ComponentName.Answer, props, InitialAnswerState, status);
115
+ /**
116
+ * Create an execute component that runs shell commands and processes operations
117
+ */
118
+ export const createExecute = (props, status) => createManagedComponent(ComponentName.Execute, props, InitialExecuteState, status);
119
+ /**
120
+ * Create a validate component that checks and collects missing configuration
121
+ */
122
+ export const createValidate = (props, status) => createManagedComponent(ComponentName.Validate, props, InitialValidateState, status);
@@ -1,5 +1,5 @@
1
1
  import { DebugLevel } from '../configuration/types.js';
2
- import { createDebugDefinition } from './components.js';
2
+ import { createDebug } from './components.js';
3
3
  import { loadDebugSetting } from '../configuration/io.js';
4
4
  import { Palette } from './colors.js';
5
5
  /**
@@ -68,7 +68,7 @@ export function logPrompt(toolName, command, instructions) {
68
68
  const lines = instructions.split('\n').length;
69
69
  const bytes = Buffer.byteLength(instructions, 'utf-8');
70
70
  const title = `SYSTEM PROMPT (${String(lines)} lines, ${String(bytes)} bytes)`;
71
- return createDebugDefinition(title, content, Palette.Gray);
71
+ return createDebug({ title, content, color: Palette.Gray });
72
72
  }
73
73
  /**
74
74
  * Create debug component for LLM responses received
@@ -85,5 +85,5 @@ export function logResponse(toolName, response, durationMs) {
85
85
  JSON.stringify(response, null, 2),
86
86
  ].join('\n');
87
87
  const title = `LLM RESPONSE (${String(durationMs)} ms)`;
88
- return createDebugDefinition(title, content, Palette.AshGray);
88
+ return createDebug({ title, content, color: Palette.AshGray });
89
89
  }
@@ -162,3 +162,22 @@ export function getExecutionErrorMessage(_error) {
162
162
  ];
163
163
  return messages[Math.floor(Math.random() * messages.length)];
164
164
  }
165
+ /**
166
+ * Returns a loading message while fetching an answer.
167
+ * Randomly selects from variations to sound natural.
168
+ */
169
+ export function getAnswerLoadingMessage() {
170
+ const messages = [
171
+ 'Finding that out for you.',
172
+ 'Looking into this.',
173
+ 'Let me find out.',
174
+ 'One moment please.',
175
+ 'Checking on that.',
176
+ 'Let me look that up.',
177
+ 'Give me a moment.',
178
+ 'Looking that up now.',
179
+ 'Let me check.',
180
+ 'Just a moment.',
181
+ ];
182
+ return messages[Math.floor(Math.random() * messages.length)];
183
+ }
@@ -8,8 +8,11 @@ import { routeTasksWithConfirm } from './router.js';
8
8
  */
9
9
  export async function handleRefinement(selectedTasks, service, originalCommand, lifecycleHandlers, workflowHandlers, requestHandlers) {
10
10
  // Create and add refinement component to queue
11
- const refinementDef = createRefinement(getRefiningMessage(), (operation) => {
12
- requestHandlers.onAborted(operation);
11
+ const refinementDef = createRefinement({
12
+ text: getRefiningMessage(),
13
+ onAborted: (operation) => {
14
+ requestHandlers.onAborted(operation);
15
+ },
13
16
  });
14
17
  workflowHandlers.addToQueue(refinementDef);
15
18
  try {