prompt-language-shell 0.3.0 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/PLAN.md +103 -54
- package/dist/index.js +2 -25
- package/dist/services/components.js +104 -0
- package/dist/services/config.js +63 -12
- package/dist/services/process.js +6 -0
- package/dist/types/components.js +11 -0
- package/dist/ui/Column.js +1 -1
- package/dist/ui/Command.js +2 -72
- package/dist/ui/Component.js +12 -5
- package/dist/ui/Config.js +169 -10
- package/dist/ui/Feedback.js +15 -4
- package/dist/ui/List.js +16 -2
- package/dist/ui/Main.js +145 -117
- package/dist/ui/Message.js +5 -0
- package/dist/ui/Plan.js +194 -0
- package/package.json +2 -1
package/dist/config/PLAN.md
CHANGED
|
@@ -18,9 +18,8 @@ Your task is to create structured task definitions that:
|
|
|
18
18
|
Each task should be precise and unambiguous, ready to be executed by the
|
|
19
19
|
appropriate handler.
|
|
20
20
|
|
|
21
|
-
**IMPORTANT**:
|
|
22
|
-
|
|
23
|
-
intentionally generic. This ensures the planning algorithm is not biased
|
|
21
|
+
**IMPORTANT**: All instructions and examples in this document are
|
|
22
|
+
intentionally generic to ensure the planning algorithm is not biased
|
|
24
23
|
toward any particular domain and can be validated to work correctly across
|
|
25
24
|
all scenarios. Do NOT assume or infer domain-specific context unless
|
|
26
25
|
explicitly provided in skills or user requests.
|
|
@@ -118,7 +117,7 @@ executable operations.
|
|
|
118
117
|
- Consult the skill's Description section for guidance on which steps are
|
|
119
118
|
optional or conditional
|
|
120
119
|
- Example: If description says "initialization only required for clean
|
|
121
|
-
|
|
120
|
+
operations" and user says "regenerate cache", skip initialization steps
|
|
122
121
|
- Only extract steps that align with the user's specific request
|
|
123
122
|
|
|
124
123
|
5. **Create task definitions:**
|
|
@@ -136,26 +135,27 @@ executable operations.
|
|
|
136
135
|
- NEVER create generic execute tasks for unmatched requirements
|
|
137
136
|
|
|
138
137
|
Example 1 - Skill with parameter, variant specified:
|
|
139
|
-
- Skill has {
|
|
140
|
-
- Skill steps: "- Navigate to the {
|
|
141
|
-
{
|
|
142
|
-
- User: "
|
|
138
|
+
- Skill has {TARGET} parameter with variants: Alpha, Beta, Gamma
|
|
139
|
+
- Skill steps: "- Navigate to the {TARGET} root directory. - Execute the
|
|
140
|
+
{TARGET} generation script. - Run the {TARGET} processing pipeline"
|
|
141
|
+
- User: "process Alpha"
|
|
143
142
|
- Correct: Three tasks with actions following the skill's steps, with
|
|
144
|
-
{
|
|
145
|
-
- WRONG: One task with action "
|
|
143
|
+
{TARGET} replaced by "Alpha"
|
|
144
|
+
- WRONG: One task with action "Process Alpha"
|
|
146
145
|
|
|
147
146
|
Example 2 - Skill with parameter, variant NOT specified:
|
|
148
147
|
- Same skill as Example 1
|
|
149
|
-
- User: "
|
|
150
|
-
- Correct: One task with type "define", action "Clarify which
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
- User: "process"
|
|
149
|
+
- Correct: One task with type "define", action "Clarify which target to
|
|
150
|
+
process", params { options: ["Process Alpha", "Process Beta", "Process
|
|
151
|
+
Gamma"] }
|
|
152
|
+
- WRONG: Three tasks with {TARGET} unreplaced or defaulted
|
|
153
153
|
|
|
154
154
|
Example 3 - Skill without parameters:
|
|
155
|
-
- Skill steps: "- Check prerequisites. - Run
|
|
156
|
-
- User: "run
|
|
155
|
+
- Skill steps: "- Check prerequisites. - Run processing. - Execute validation"
|
|
156
|
+
- User: "run validation and generate a report"
|
|
157
157
|
- Correct: Four tasks (the three from skill + one for report generation)
|
|
158
|
-
- WRONG: Two tasks ("run
|
|
158
|
+
- WRONG: Two tasks ("run validation", "generate a report")
|
|
159
159
|
|
|
160
160
|
Example 4 - NEGATIVE: Unmatched verb after matched skill:
|
|
161
161
|
- ONLY skill available: "backup" (with steps: connect, export, save)
|
|
@@ -189,22 +189,29 @@ derived from available skills:
|
|
|
189
189
|
2. For each applicable skill, extract specific, executable commands with their
|
|
190
190
|
parameters
|
|
191
191
|
3. Present these as concrete options, NOT generic categories
|
|
192
|
-
4. Each option should
|
|
193
|
-
|
|
192
|
+
4. Each option should represent a SINGLE atomic choice (e.g., which variant,
|
|
193
|
+
which environment, which product), NOT a complete sequence of steps
|
|
194
|
+
5. **CRITICAL: Options must be ATOMIC choices, not sequences.** Each option
|
|
195
|
+
should select ONE thing (variant, environment, target), and once selected,
|
|
196
|
+
that choice will be expanded into individual sequential steps
|
|
197
|
+
6. Format options WITHOUT brackets. Use commas to separate extra information
|
|
194
198
|
instead. For example:
|
|
195
|
-
- CORRECT: "
|
|
196
|
-
- WRONG: "
|
|
199
|
+
- CORRECT: "Process target Alpha, the legacy version"
|
|
200
|
+
- WRONG: "Process target Alpha (the legacy version)"
|
|
197
201
|
|
|
198
202
|
Example:
|
|
199
|
-
- Available skills: "
|
|
203
|
+
- Available skills: "Process Product" (variant A, variant B), "Deploy
|
|
200
204
|
Product" (staging, production), "Verify Product" (quick check, full
|
|
201
205
|
validation)
|
|
202
206
|
- User: "do something with the product"
|
|
203
|
-
- Correct: Create "define" task with options: ["
|
|
204
|
-
"
|
|
207
|
+
- Correct: Create "define" task with options: ["Process product variant A",
|
|
208
|
+
"Process product variant B", "Deploy product to staging", "Deploy product
|
|
205
209
|
to production", "Run quick verification", "Run full validation"]
|
|
206
|
-
- WRONG: Generic options like ["
|
|
210
|
+
- WRONG: Generic options like ["Process", "Deploy", "Verify"] - these
|
|
207
211
|
require further clarification
|
|
212
|
+
- WRONG: Options like ["Process A, run checks, deploy to staging", "Process
|
|
213
|
+
B, skip checks, deploy to production"] - these are sequences, not atomic
|
|
214
|
+
choices
|
|
208
215
|
|
|
209
216
|
## Evaluation of Requests
|
|
210
217
|
|
|
@@ -233,7 +240,7 @@ Examples that should be aborted as offensive:
|
|
|
233
240
|
- "what is the current directory" → type: "answer"
|
|
234
241
|
|
|
235
242
|
2. **Skill-based requests** - Use skills when verb matches a defined skill:
|
|
236
|
-
- If "
|
|
243
|
+
- If "process" skill exists and user says "process" → Use the process skill
|
|
237
244
|
- If "deploy" skill exists and user says "deploy" → Use the deploy skill
|
|
238
245
|
- Extract steps from the matching skill and create tasks for each step
|
|
239
246
|
|
|
@@ -262,32 +269,43 @@ type ONLY if there are concrete skill-based options:
|
|
|
262
269
|
**For skill-based disambiguation:**
|
|
263
270
|
|
|
264
271
|
When a skill exists but requires parameters or has multiple variants,
|
|
265
|
-
use "define" type
|
|
272
|
+
use "define" type to select ONE variant. The options should be ATOMIC choices,
|
|
273
|
+
not sequences of steps:
|
|
266
274
|
|
|
267
275
|
1. **Skill requires parameters** - Ask which variant:
|
|
268
|
-
- "
|
|
269
|
-
Delta) → Create "define" type with params { options: ["
|
|
270
|
-
"
|
|
276
|
+
- "process" + process skill with {TARGET} parameter (Alpha, Beta, Gamma,
|
|
277
|
+
Delta) → Create "define" type with params { options: ["Process Alpha",
|
|
278
|
+
"Process Beta", "Process Gamma", "Process Delta"] }
|
|
279
|
+
- Each option is ONE variant choice
|
|
280
|
+
- Once selected, that variant will expand into its individual steps
|
|
271
281
|
- User must specify which variant to execute the skill with
|
|
282
|
+
- **WRONG**: Options like ["Process Alpha and deploy", "Process Beta and
|
|
283
|
+
validate"] - these are sequences, not atomic variant choices
|
|
272
284
|
|
|
273
285
|
2. **Skill has multiple distinct operations** - Ask which one:
|
|
274
286
|
- "deploy" + deploy skill defining staging, production, canary
|
|
275
287
|
environments → Create "define" type with params { options: ["Deploy to
|
|
276
288
|
staging environment", "Deploy to production environment", "Deploy to
|
|
277
289
|
canary environment"] }
|
|
290
|
+
- Each option selects ONE environment
|
|
291
|
+
- **WRONG**: Options like ["Deploy to staging, then production", "Deploy
|
|
292
|
+
to production only"] - these mix sequences with choices
|
|
278
293
|
|
|
279
294
|
3. **Skill has single variant or user specifies variant** - Execute directly:
|
|
280
|
-
- "
|
|
281
|
-
{
|
|
295
|
+
- "process Alpha" + process skill with {TARGET} parameter → Replace
|
|
296
|
+
{TARGET} with "Alpha" and execute skill steps as SEPARATE sequential
|
|
297
|
+
tasks
|
|
282
298
|
- "deploy staging" + deploy skill with {ENV} parameter → Replace {ENV}
|
|
283
|
-
with "staging" and execute
|
|
284
|
-
- No disambiguation needed
|
|
299
|
+
with "staging" and execute each step as a SEPARATE task
|
|
300
|
+
- No disambiguation needed - proceed directly to breaking down into steps
|
|
285
301
|
|
|
286
302
|
4. **User specifies "all"** - Spread into multiple tasks:
|
|
287
303
|
- "deploy all" + deploy skill defining staging and production → Create
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
304
|
+
separate task sequences: first all staging steps, then all production
|
|
305
|
+
steps (as individual sequential tasks, not bundled)
|
|
306
|
+
- "process all" + process skill with multiple target variants → Create
|
|
307
|
+
separate task sequences for each variant (each variant's steps as
|
|
308
|
+
individual sequential tasks)
|
|
291
309
|
|
|
292
310
|
**For requests with no matching skills:**
|
|
293
311
|
|
|
@@ -305,8 +323,8 @@ Use "ignore" type:
|
|
|
305
323
|
|
|
306
324
|
**Critical rules:**
|
|
307
325
|
|
|
308
|
-
- NEVER create "define" type with generic categories like "Run
|
|
309
|
-
"
|
|
326
|
+
- NEVER create "define" type with generic categories like "Run validation",
|
|
327
|
+
"Process target" unless these map to actual skill commands
|
|
310
328
|
- NEVER create "define" type without a matching skill. The "define" type
|
|
311
329
|
is ONLY for disambiguating between multiple variants/operations within
|
|
312
330
|
an existing skill
|
|
@@ -338,14 +356,18 @@ When creating task definitions, focus on:
|
|
|
338
356
|
- **Type**: Categorize the operation using one of these supported types:
|
|
339
357
|
- `config` - Configuration changes, settings updates
|
|
340
358
|
- `plan` - Planning or breaking down tasks
|
|
341
|
-
- `execute` - Shell commands, running programs, scripts,
|
|
342
|
-
|
|
359
|
+
- `execute` - Shell commands, running programs, scripts, processing
|
|
360
|
+
operations
|
|
343
361
|
- `answer` - Answering questions, explaining concepts, providing
|
|
344
362
|
information
|
|
345
363
|
- `report` - Generating summaries, creating reports, displaying
|
|
346
364
|
results
|
|
347
365
|
- `define` - Presenting skill-based options when request matches
|
|
348
|
-
multiple skill variants
|
|
366
|
+
multiple skill variants. **CRITICAL: Options must be ATOMIC choices
|
|
367
|
+
(selecting ONE variant, ONE environment, ONE target), NOT sequences of
|
|
368
|
+
steps. Each option represents a single selection that will later be
|
|
369
|
+
expanded into individual sequential steps. NEVER bundle multiple steps
|
|
370
|
+
into a single option like "Process X, run validation, deploy Y".**
|
|
349
371
|
- `ignore` - Request is too vague and cannot be mapped to skills or
|
|
350
372
|
inferred from context
|
|
351
373
|
|
|
@@ -541,7 +563,7 @@ Only split when tasks are truly distinct operations:
|
|
|
541
563
|
dependencies" (type: execute) and "Run tests" (type: execute)
|
|
542
564
|
- "create file; add content" → Two tasks with actions "Create a file" (type:
|
|
543
565
|
execute) and "Add content" (type: execute)
|
|
544
|
-
- "
|
|
566
|
+
- "process data and deploy" → Two tasks with actions "Process the data"
|
|
545
567
|
(type: execute) and "Deploy" (type: execute)
|
|
546
568
|
|
|
547
569
|
### Correct Examples: Complex Questions
|
|
@@ -567,15 +589,15 @@ Split only when multiple distinct queries or operations are needed:
|
|
|
567
589
|
|
|
568
590
|
Examples showing proper use of skills and disambiguation:
|
|
569
591
|
|
|
570
|
-
- "
|
|
571
|
-
Delta) → One task: type "define", action "Clarify which
|
|
572
|
-
params { options: ["
|
|
573
|
-
Delta"] }. NOTE: If variants have descriptions, format as "
|
|
574
|
-
legacy version" NOT "
|
|
575
|
-
- "
|
|
576
|
-
steps: "Navigate to the Alpha
|
|
577
|
-
|
|
578
|
-
- "
|
|
592
|
+
- "process" with process skill requiring {TARGET} parameter (Alpha, Beta, Gamma,
|
|
593
|
+
Delta) → One task: type "define", action "Clarify which target to process",
|
|
594
|
+
params { options: ["Process Alpha", "Process Beta", "Process Gamma", "Process
|
|
595
|
+
Delta"] }. NOTE: If variants have descriptions, format as "Process Alpha, the
|
|
596
|
+
legacy version" NOT "Process Alpha (the legacy version)"
|
|
597
|
+
- "process Alpha" with same process skill → Three tasks extracted from skill
|
|
598
|
+
steps: "Navigate to the Alpha target's root directory", "Execute the Alpha
|
|
599
|
+
target generation script", "Run the Alpha processing pipeline"
|
|
600
|
+
- "process all" with same process skill → Twelve tasks (3 steps × 4 targets)
|
|
579
601
|
- "deploy" with deploy skill (staging, production, canary) → One task: type
|
|
580
602
|
"define", action "Clarify which environment to deploy to", params
|
|
581
603
|
{ options: ["Deploy to staging environment", "Deploy to production
|
|
@@ -590,13 +612,40 @@ Examples showing proper use of skills and disambiguation:
|
|
|
590
612
|
- "analyze data and generate report" with analyze skill but NO generate skill →
|
|
591
613
|
Tasks from analyze skill + one "ignore" type for unknown "generate"
|
|
592
614
|
|
|
615
|
+
### INCORRECT Examples: Sequence-Based Define Options
|
|
616
|
+
|
|
617
|
+
These examples show the WRONG way to use "define" type - bundling sequences
|
|
618
|
+
instead of atomic choices:
|
|
619
|
+
|
|
620
|
+
- "process alpha, verify, process beta" with process skill for targets Alpha
|
|
621
|
+
and Beta →
|
|
622
|
+
- WRONG: One task type "define" with options ["Process Alpha, run
|
|
623
|
+
verification, process Beta", "Process Alpha, skip verification, process
|
|
624
|
+
Beta"]
|
|
625
|
+
- CORRECT: Multiple sequential tasks: "Process Alpha", "Run verification",
|
|
626
|
+
"Process Beta" (no define needed - these are distinct sequential
|
|
627
|
+
operations)
|
|
628
|
+
|
|
629
|
+
- "deploy" with deploy skill (staging, production) →
|
|
630
|
+
- WRONG: One task type "define" with options ["Deploy to staging then
|
|
631
|
+
production", "Deploy to production only"]
|
|
632
|
+
- CORRECT: One task type "define" with options ["Deploy to staging", "Deploy
|
|
633
|
+
to production"] (atomic environment choices)
|
|
634
|
+
|
|
635
|
+
- "process and validate" with process skill ({TARGET} parameter: Alpha, Beta) →
|
|
636
|
+
- WRONG: One task type "define" with options ["Process Alpha and run
|
|
637
|
+
validation", "Process Beta and run validation"]
|
|
638
|
+
- CORRECT: One task type "define" to choose target ["Process Alpha",
|
|
639
|
+
"Process Beta"], then once selected, expand into separate sequential tasks
|
|
640
|
+
for process steps + validation step
|
|
641
|
+
|
|
593
642
|
### Correct Examples: Requests Without Matching Skills
|
|
594
643
|
|
|
595
644
|
- "lint" with NO lint skill → One task: type "ignore", action "Ignore
|
|
596
645
|
unknown 'lint' request"
|
|
597
646
|
- "format" with NO format skill → One task: type "ignore", action "Ignore
|
|
598
647
|
unknown 'format' request"
|
|
599
|
-
- "
|
|
600
|
-
unknown '
|
|
648
|
+
- "process" with NO process skill → One task: type "ignore", action "Ignore
|
|
649
|
+
unknown 'process' request"
|
|
601
650
|
- "do stuff" with NO skills → One task: type "ignore", action "Ignore
|
|
602
651
|
unknown 'do stuff' request"
|
package/dist/index.js
CHANGED
|
@@ -4,8 +4,6 @@ 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 { hasValidConfig, loadConfig, saveAnthropicConfig, } from './services/config.js';
|
|
8
|
-
import { createAnthropicService } from './services/anthropic.js';
|
|
9
7
|
import { Main } from './ui/Main.js';
|
|
10
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
9
|
const __dirname = dirname(__filename);
|
|
@@ -26,26 +24,5 @@ const app = {
|
|
|
26
24
|
// Get command from command-line arguments
|
|
27
25
|
const args = process.argv.slice(2);
|
|
28
26
|
const command = args.join(' ').trim() || null;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (hasValidConfig()) {
|
|
32
|
-
const config = loadConfig();
|
|
33
|
-
const service = createAnthropicService(config.anthropic);
|
|
34
|
-
render(_jsx(Main, { app: app, command: command, service: service, isReady: true }));
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
// Setup: config doesn't exist or is invalid
|
|
38
|
-
const { waitUntilExit, unmount } = render(_jsx(Main, { app: app, command: command, isReady: false, onConfigured: (config) => {
|
|
39
|
-
saveAnthropicConfig(config);
|
|
40
|
-
if (command) {
|
|
41
|
-
return createAnthropicService(config);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// No command - exit after showing completion message
|
|
45
|
-
setTimeout(() => unmount(), 100);
|
|
46
|
-
return undefined;
|
|
47
|
-
}
|
|
48
|
-
} }));
|
|
49
|
-
await waitUntilExit();
|
|
50
|
-
}
|
|
51
|
-
runApp();
|
|
27
|
+
// Render application
|
|
28
|
+
render(_jsx(Main, { app: app, command: command }));
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { ComponentName, } from '../types/components.js';
|
|
3
|
+
import { StepType } from '../ui/Config.js';
|
|
4
|
+
import { AnthropicModel, isValidAnthropicApiKey, isValidAnthropicModel, } from './config.js';
|
|
5
|
+
export function markAsDone(component) {
|
|
6
|
+
return { ...component, state: { ...component.state, done: true } };
|
|
7
|
+
}
|
|
8
|
+
export function createWelcomeDefinition(app) {
|
|
9
|
+
return {
|
|
10
|
+
id: randomUUID(),
|
|
11
|
+
name: ComponentName.Welcome,
|
|
12
|
+
props: { app },
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function createConfigSteps() {
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
description: 'Anthropic API key',
|
|
19
|
+
key: 'key',
|
|
20
|
+
type: StepType.Text,
|
|
21
|
+
value: null,
|
|
22
|
+
validate: isValidAnthropicApiKey,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
description: 'Model',
|
|
26
|
+
key: 'model',
|
|
27
|
+
type: StepType.Selection,
|
|
28
|
+
options: [
|
|
29
|
+
{ label: 'Haiku 4.5', value: AnthropicModel.Haiku },
|
|
30
|
+
{ label: 'Sonnet 4.5', value: AnthropicModel.Sonnet },
|
|
31
|
+
{ label: 'Opus 4.1', value: AnthropicModel.Opus },
|
|
32
|
+
],
|
|
33
|
+
defaultIndex: 0,
|
|
34
|
+
validate: isValidAnthropicModel,
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
export function createConfigDefinition(onFinished, onAborted) {
|
|
39
|
+
return {
|
|
40
|
+
id: randomUUID(),
|
|
41
|
+
name: ComponentName.Config,
|
|
42
|
+
state: { done: false },
|
|
43
|
+
props: {
|
|
44
|
+
steps: createConfigSteps(),
|
|
45
|
+
onFinished,
|
|
46
|
+
onAborted,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function createCommandDefinition(command, service, onError, onComplete) {
|
|
51
|
+
return {
|
|
52
|
+
id: randomUUID(),
|
|
53
|
+
name: ComponentName.Command,
|
|
54
|
+
state: {
|
|
55
|
+
done: false,
|
|
56
|
+
isLoading: true,
|
|
57
|
+
},
|
|
58
|
+
props: {
|
|
59
|
+
command,
|
|
60
|
+
service,
|
|
61
|
+
onError,
|
|
62
|
+
onComplete,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function createPlanDefinition(message, tasks, onSelectionConfirmed) {
|
|
67
|
+
return {
|
|
68
|
+
id: randomUUID(),
|
|
69
|
+
name: ComponentName.Plan,
|
|
70
|
+
state: {
|
|
71
|
+
done: false,
|
|
72
|
+
highlightedIndex: null,
|
|
73
|
+
currentDefineGroupIndex: 0,
|
|
74
|
+
completedSelections: [],
|
|
75
|
+
},
|
|
76
|
+
props: {
|
|
77
|
+
message,
|
|
78
|
+
tasks,
|
|
79
|
+
onSelectionConfirmed,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function createFeedback(type, ...messages) {
|
|
84
|
+
return {
|
|
85
|
+
id: randomUUID(),
|
|
86
|
+
name: ComponentName.Feedback,
|
|
87
|
+
props: {
|
|
88
|
+
type,
|
|
89
|
+
message: messages.join('\n\n'),
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export function createMessage(text) {
|
|
94
|
+
return {
|
|
95
|
+
id: randomUUID(),
|
|
96
|
+
name: ComponentName.Message,
|
|
97
|
+
props: {
|
|
98
|
+
text,
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export function isStateless(component) {
|
|
103
|
+
return !('state' in component);
|
|
104
|
+
}
|
package/dist/services/config.js
CHANGED
|
@@ -2,6 +2,13 @@ import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
|
2
2
|
import { homedir } from 'os';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import YAML from 'yaml';
|
|
5
|
+
export var AnthropicModel;
|
|
6
|
+
(function (AnthropicModel) {
|
|
7
|
+
AnthropicModel["Sonnet"] = "claude-sonnet-4-5";
|
|
8
|
+
AnthropicModel["Haiku"] = "claude-haiku-4-5";
|
|
9
|
+
AnthropicModel["Opus"] = "claude-opus-4-1";
|
|
10
|
+
})(AnthropicModel || (AnthropicModel = {}));
|
|
11
|
+
export const SUPPORTED_MODELS = Object.values(AnthropicModel);
|
|
5
12
|
export class ConfigError extends Error {
|
|
6
13
|
origin;
|
|
7
14
|
constructor(message, origin) {
|
|
@@ -10,7 +17,9 @@ export class ConfigError extends Error {
|
|
|
10
17
|
this.origin = origin;
|
|
11
18
|
}
|
|
12
19
|
}
|
|
13
|
-
|
|
20
|
+
function getConfigFile() {
|
|
21
|
+
return join(homedir(), '.plsrc');
|
|
22
|
+
}
|
|
14
23
|
function parseYamlConfig(content) {
|
|
15
24
|
try {
|
|
16
25
|
return YAML.parse(content);
|
|
@@ -37,30 +46,41 @@ function validateConfig(parsed) {
|
|
|
37
46
|
key,
|
|
38
47
|
},
|
|
39
48
|
};
|
|
40
|
-
// Optional model
|
|
41
|
-
if (model && typeof model === 'string') {
|
|
49
|
+
// Optional model - only set if valid
|
|
50
|
+
if (model && typeof model === 'string' && isValidAnthropicModel(model)) {
|
|
42
51
|
validatedConfig.anthropic.model = model;
|
|
43
52
|
}
|
|
44
53
|
return validatedConfig;
|
|
45
54
|
}
|
|
46
55
|
export function loadConfig() {
|
|
47
|
-
|
|
56
|
+
const configFile = getConfigFile();
|
|
57
|
+
if (!existsSync(configFile)) {
|
|
48
58
|
throw new ConfigError('Configuration not found');
|
|
49
59
|
}
|
|
50
|
-
const content = readFileSync(
|
|
60
|
+
const content = readFileSync(configFile, 'utf-8');
|
|
51
61
|
const parsed = parseYamlConfig(content);
|
|
52
62
|
return validateConfig(parsed);
|
|
53
63
|
}
|
|
54
64
|
export function getConfigPath() {
|
|
55
|
-
return
|
|
65
|
+
return getConfigFile();
|
|
56
66
|
}
|
|
57
67
|
export function configExists() {
|
|
58
|
-
return existsSync(
|
|
68
|
+
return existsSync(getConfigFile());
|
|
69
|
+
}
|
|
70
|
+
export function isValidAnthropicApiKey(key) {
|
|
71
|
+
// Anthropic API keys format: sk-ant-api03-XXXXX (108 chars total)
|
|
72
|
+
// - Prefix: sk-ant-api03- (13 chars)
|
|
73
|
+
// - Key body: 95 characters (uppercase, lowercase, digits, hyphens, underscores)
|
|
74
|
+
const apiKeyPattern = /^sk-ant-api03-[A-Za-z0-9_-]{95}$/;
|
|
75
|
+
return apiKeyPattern.test(key);
|
|
76
|
+
}
|
|
77
|
+
export function isValidAnthropicModel(model) {
|
|
78
|
+
return SUPPORTED_MODELS.includes(model);
|
|
59
79
|
}
|
|
60
|
-
export function
|
|
80
|
+
export function hasValidAnthropicKey() {
|
|
61
81
|
try {
|
|
62
82
|
const config = loadConfig();
|
|
63
|
-
return !!config.anthropic.key;
|
|
83
|
+
return (!!config.anthropic.key && isValidAnthropicApiKey(config.anthropic.key));
|
|
64
84
|
}
|
|
65
85
|
catch {
|
|
66
86
|
return false;
|
|
@@ -86,12 +106,43 @@ export function mergeConfig(existingContent, sectionName, newValues) {
|
|
|
86
106
|
return YAML.stringify(sortedConfig);
|
|
87
107
|
}
|
|
88
108
|
export function saveConfig(section, config) {
|
|
89
|
-
const
|
|
90
|
-
|
|
109
|
+
const configFile = getConfigFile();
|
|
110
|
+
const existingContent = existsSync(configFile)
|
|
111
|
+
? readFileSync(configFile, 'utf-8')
|
|
91
112
|
: '';
|
|
92
113
|
const newContent = mergeConfig(existingContent, section, config);
|
|
93
|
-
writeFileSync(
|
|
114
|
+
writeFileSync(configFile, newContent, 'utf-8');
|
|
94
115
|
}
|
|
95
116
|
export function saveAnthropicConfig(config) {
|
|
96
117
|
saveConfig('anthropic', config);
|
|
97
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Returns a message requesting initial setup.
|
|
121
|
+
* Provides natural language variations that sound like a professional concierge
|
|
122
|
+
* preparing to serve, avoiding technical jargon.
|
|
123
|
+
*
|
|
124
|
+
* @param forFutureUse - If true, indicates setup is for future requests rather than
|
|
125
|
+
* an immediate task
|
|
126
|
+
*/
|
|
127
|
+
export function getConfigurationRequiredMessage(forFutureUse = false) {
|
|
128
|
+
if (forFutureUse) {
|
|
129
|
+
const messages = [
|
|
130
|
+
"Before I can assist with your requests, let's get a few things ready.",
|
|
131
|
+
'Let me set up a few things so I can help you in the future.',
|
|
132
|
+
"I'll need to prepare a few things before I can assist you.",
|
|
133
|
+
"Let's get everything ready so I can help with your tasks.",
|
|
134
|
+
"I need to set up a few things first, then I'll be ready to assist.",
|
|
135
|
+
'Let me prepare everything so I can help you going forward.',
|
|
136
|
+
];
|
|
137
|
+
return messages[Math.floor(Math.random() * messages.length)];
|
|
138
|
+
}
|
|
139
|
+
const messages = [
|
|
140
|
+
'Before I can help, let me get a few things ready.',
|
|
141
|
+
'I need to set up a few things first.',
|
|
142
|
+
'Let me prepare everything before we begin.',
|
|
143
|
+
'Just a moment while I get ready to assist you.',
|
|
144
|
+
"I'll need to get set up before I can help with that.",
|
|
145
|
+
'Let me get everything ready for you.',
|
|
146
|
+
];
|
|
147
|
+
return messages[Math.floor(Math.random() * messages.length)];
|
|
148
|
+
}
|
package/dist/types/components.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
export var ComponentName;
|
|
2
|
+
(function (ComponentName) {
|
|
3
|
+
ComponentName["Welcome"] = "welcome";
|
|
4
|
+
ComponentName["Config"] = "config";
|
|
5
|
+
ComponentName["Feedback"] = "feedback";
|
|
6
|
+
ComponentName["Message"] = "message";
|
|
7
|
+
ComponentName["Plan"] = "plan";
|
|
8
|
+
ComponentName["Command"] = "command";
|
|
9
|
+
})(ComponentName || (ComponentName = {}));
|
|
1
10
|
export var TaskType;
|
|
2
11
|
(function (TaskType) {
|
|
3
12
|
TaskType["Config"] = "config";
|
|
@@ -8,9 +17,11 @@ export var TaskType;
|
|
|
8
17
|
TaskType["Define"] = "define";
|
|
9
18
|
TaskType["Ignore"] = "ignore";
|
|
10
19
|
TaskType["Select"] = "select";
|
|
20
|
+
TaskType["Discard"] = "discard";
|
|
11
21
|
})(TaskType || (TaskType = {}));
|
|
12
22
|
export var FeedbackType;
|
|
13
23
|
(function (FeedbackType) {
|
|
24
|
+
FeedbackType["Info"] = "info";
|
|
14
25
|
FeedbackType["Succeeded"] = "succeeded";
|
|
15
26
|
FeedbackType["Aborted"] = "aborted";
|
|
16
27
|
FeedbackType["Failed"] = "failed";
|
package/dist/ui/Column.js
CHANGED
|
@@ -2,5 +2,5 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box } from 'ink';
|
|
3
3
|
import { Component } from './Component.js';
|
|
4
4
|
export const Column = ({ items }) => {
|
|
5
|
-
return (_jsx(Box, { marginTop: 1, marginBottom: 1, flexDirection: "column", gap: 1, children: items.map((item
|
|
5
|
+
return (_jsx(Box, { marginTop: 1, marginBottom: 1, marginLeft: 1, flexDirection: "column", gap: 1, children: items.map((item) => (_jsx(Box, { children: _jsx(Component, { def: item }) }, item.id))) }));
|
|
6
6
|
};
|