@principal-ai/principal-studio-cli 0.35.3
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/README.md +172 -0
- package/dist/commands/agent-session.d.ts +3 -0
- package/dist/commands/agent-session.d.ts.map +1 -0
- package/dist/commands/agent-session.js +67 -0
- package/dist/commands/agent-sessions.d.ts +11 -0
- package/dist/commands/agent-sessions.d.ts.map +1 -0
- package/dist/commands/agent-sessions.js +39 -0
- package/dist/commands/auxiliary/index.d.ts +3 -0
- package/dist/commands/auxiliary/index.d.ts.map +1 -0
- package/dist/commands/auxiliary/index.js +9 -0
- package/dist/commands/auxiliary/validate.d.ts +3 -0
- package/dist/commands/auxiliary/validate.d.ts.map +1 -0
- package/dist/commands/auxiliary/validate.js +123 -0
- package/dist/commands/collector/check.d.ts +6 -0
- package/dist/commands/collector/check.d.ts.map +1 -0
- package/dist/commands/collector/check.js +153 -0
- package/dist/commands/collector/diagnose.d.ts +6 -0
- package/dist/commands/collector/diagnose.d.ts.map +1 -0
- package/dist/commands/collector/diagnose.js +229 -0
- package/dist/commands/collector/index.d.ts +6 -0
- package/dist/commands/collector/index.d.ts.map +1 -0
- package/dist/commands/collector/index.js +16 -0
- package/dist/commands/collector/status.d.ts +6 -0
- package/dist/commands/collector/status.d.ts.map +1 -0
- package/dist/commands/collector/status.js +77 -0
- package/dist/commands/collector/utils.d.ts +92 -0
- package/dist/commands/collector/utils.d.ts.map +1 -0
- package/dist/commands/collector/utils.js +154 -0
- package/dist/commands/coverage.d.ts +9 -0
- package/dist/commands/coverage.d.ts.map +1 -0
- package/dist/commands/coverage.js +252 -0
- package/dist/commands/create.d.ts +6 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +50 -0
- package/dist/commands/events/index.d.ts +3 -0
- package/dist/commands/events/index.d.ts.map +1 -0
- package/dist/commands/events/index.js +9 -0
- package/dist/commands/events/validate.d.ts +3 -0
- package/dist/commands/events/validate.d.ts.map +1 -0
- package/dist/commands/events/validate.js +124 -0
- package/dist/commands/formats.d.ts +6 -0
- package/dist/commands/formats.d.ts.map +1 -0
- package/dist/commands/formats.js +1118 -0
- package/dist/commands/hooks.d.ts +9 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +295 -0
- package/dist/commands/inbox.d.ts +13 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +179 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +220 -0
- package/dist/commands/lint.d.ts +11 -0
- package/dist/commands/lint.d.ts.map +1 -0
- package/dist/commands/lint.js +71 -0
- package/dist/commands/list.d.ts +6 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +78 -0
- package/dist/commands/migrate-nodes.d.ts +9 -0
- package/dist/commands/migrate-nodes.d.ts.map +1 -0
- package/dist/commands/migrate-nodes.js +363 -0
- package/dist/commands/migrate-scopes-to-canvas.d.ts +3 -0
- package/dist/commands/migrate-scopes-to-canvas.d.ts.map +1 -0
- package/dist/commands/migrate-scopes-to-canvas.js +143 -0
- package/dist/commands/migration.d.ts +6 -0
- package/dist/commands/migration.d.ts.map +1 -0
- package/dist/commands/migration.js +247 -0
- package/dist/commands/open-studio.d.ts +10 -0
- package/dist/commands/open-studio.d.ts.map +1 -0
- package/dist/commands/open-studio.js +32 -0
- package/dist/commands/opencode/fetch.d.ts +3 -0
- package/dist/commands/opencode/fetch.d.ts.map +1 -0
- package/dist/commands/opencode/fetch.js +25 -0
- package/dist/commands/opencode/index.d.ts +3 -0
- package/dist/commands/opencode/index.d.ts.map +1 -0
- package/dist/commands/opencode/index.js +11 -0
- package/dist/commands/opencode/list-sessions.d.ts +3 -0
- package/dist/commands/opencode/list-sessions.d.ts.map +1 -0
- package/dist/commands/opencode/list-sessions.js +20 -0
- package/dist/commands/repo.d.ts +18 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +233 -0
- package/dist/commands/schema.d.ts +6 -0
- package/dist/commands/schema.d.ts.map +1 -0
- package/dist/commands/schema.js +367 -0
- package/dist/commands/scopes/index.d.ts +3 -0
- package/dist/commands/scopes/index.d.ts.map +1 -0
- package/dist/commands/scopes/index.js +9 -0
- package/dist/commands/scopes/validate.d.ts +3 -0
- package/dist/commands/scopes/validate.d.ts.map +1 -0
- package/dist/commands/scopes/validate.js +187 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +406 -0
- package/dist/commands/starred-collections.d.ts +12 -0
- package/dist/commands/starred-collections.d.ts.map +1 -0
- package/dist/commands/starred-collections.js +310 -0
- package/dist/commands/subsystem-model.d.ts +11 -0
- package/dist/commands/subsystem-model.d.ts.map +1 -0
- package/dist/commands/subsystem-model.js +249 -0
- package/dist/commands/topic.d.ts +15 -0
- package/dist/commands/topic.d.ts.map +1 -0
- package/dist/commands/topic.js +683 -0
- package/dist/commands/tour.d.ts +23 -0
- package/dist/commands/tour.d.ts.map +1 -0
- package/dist/commands/tour.js +783 -0
- package/dist/commands/trace/flow.d.ts +6 -0
- package/dist/commands/trace/flow.d.ts.map +1 -0
- package/dist/commands/trace/flow.js +158 -0
- package/dist/commands/trace/index.d.ts +6 -0
- package/dist/commands/trace/index.d.ts.map +1 -0
- package/dist/commands/trace/index.js +20 -0
- package/dist/commands/trace/inspect.d.ts +6 -0
- package/dist/commands/trace/inspect.d.ts.map +1 -0
- package/dist/commands/trace/inspect.js +187 -0
- package/dist/commands/trace/list.d.ts +6 -0
- package/dist/commands/trace/list.d.ts.map +1 -0
- package/dist/commands/trace/list.js +145 -0
- package/dist/commands/trace/registrations.d.ts +6 -0
- package/dist/commands/trace/registrations.d.ts.map +1 -0
- package/dist/commands/trace/registrations.js +81 -0
- package/dist/commands/trace/validate.d.ts +6 -0
- package/dist/commands/trace/validate.d.ts.map +1 -0
- package/dist/commands/trace/validate.js +276 -0
- package/dist/commands/trail.d.ts +36 -0
- package/dist/commands/trail.d.ts.map +1 -0
- package/dist/commands/trail.js +622 -0
- package/dist/commands/validate.d.ts +12 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +3334 -0
- package/dist/commands/workflow/implementation.d.ts +3 -0
- package/dist/commands/workflow/implementation.d.ts.map +1 -0
- package/dist/commands/workflow/implementation.js +51 -0
- package/dist/commands/workflow/index.d.ts +3 -0
- package/dist/commands/workflow/index.d.ts.map +1 -0
- package/dist/commands/workflow/index.js +19 -0
- package/dist/commands/workflow/inspect.d.ts +3 -0
- package/dist/commands/workflow/inspect.d.ts.map +1 -0
- package/dist/commands/workflow/inspect.js +123 -0
- package/dist/commands/workflow/list.d.ts +3 -0
- package/dist/commands/workflow/list.d.ts.map +1 -0
- package/dist/commands/workflow/list.js +95 -0
- package/dist/commands/workflow/render.d.ts +3 -0
- package/dist/commands/workflow/render.d.ts.map +1 -0
- package/dist/commands/workflow/render.js +88 -0
- package/dist/commands/workflow/test.d.ts +3 -0
- package/dist/commands/workflow/test.d.ts.map +1 -0
- package/dist/commands/workflow/test.js +141 -0
- package/dist/commands/workflow/utils.d.ts +49 -0
- package/dist/commands/workflow/utils.d.ts.map +1 -0
- package/dist/commands/workflow/utils.js +164 -0
- package/dist/commands/workflow/validate.d.ts +3 -0
- package/dist/commands/workflow/validate.d.ts.map +1 -0
- package/dist/commands/workflow/validate.js +344 -0
- package/dist/file-utils.d.ts +15 -0
- package/dist/file-utils.d.ts.map +1 -0
- package/dist/file-utils.js +29 -0
- package/dist/index.cjs +285718 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +81 -0
- package/dist/lib/bridge-ipc.d.ts +29 -0
- package/dist/lib/bridge-ipc.d.ts.map +1 -0
- package/dist/lib/bridge-ipc.js +128 -0
- package/dist/lib/github-user.d.ts +17 -0
- package/dist/lib/github-user.d.ts.map +1 -0
- package/dist/lib/github-user.js +53 -0
- package/dist/lib/open-url.d.ts +11 -0
- package/dist/lib/open-url.d.ts.map +1 -0
- package/dist/lib/open-url.js +45 -0
- package/dist/lib/subsystem-model-store.d.ts +74 -0
- package/dist/lib/subsystem-model-store.d.ts.map +1 -0
- package/dist/lib/subsystem-model-store.js +292 -0
- package/dist/lib/tour-cache.d.ts +26 -0
- package/dist/lib/tour-cache.d.ts.map +1 -0
- package/dist/lib/tour-cache.js +46 -0
- package/dist/lib/trail-cache.d.ts +40 -0
- package/dist/lib/trail-cache.d.ts.map +1 -0
- package/dist/lib/trail-cache.js +97 -0
- package/dist/lib/viewer-ipc.d.ts +44 -0
- package/dist/lib/viewer-ipc.d.ts.map +1 -0
- package/dist/lib/viewer-ipc.js +68 -0
- package/package.json +68 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration command - Display the migration guide for moving from legacy flat structure to storyboards
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
const MIGRATION_GUIDE = `
|
|
7
|
+
${chalk.bold.cyan('Migration Guide: Legacy Flat Structure → Storyboards')}
|
|
8
|
+
|
|
9
|
+
${chalk.bold('Overview')}
|
|
10
|
+
|
|
11
|
+
This guide will help you migrate from the legacy flat structure to the new
|
|
12
|
+
hierarchical storyboard structure for organizing Principal Views.
|
|
13
|
+
|
|
14
|
+
${chalk.yellow('Status:')} The legacy flat structure is ${chalk.bold('fully deprecated')} as of version 1.0.0
|
|
15
|
+
and will produce validation errors. Both structures are currently supported for
|
|
16
|
+
backward compatibility, but the flat structure is no longer recommended and will
|
|
17
|
+
be removed in v2.0.0.
|
|
18
|
+
|
|
19
|
+
${chalk.bold('Why Migrate?')}
|
|
20
|
+
|
|
21
|
+
${chalk.bold('Problems with Legacy Flat Structure:')}
|
|
22
|
+
|
|
23
|
+
The legacy flat structure stores all files directly in .principal-views/:
|
|
24
|
+
|
|
25
|
+
.principal-views/
|
|
26
|
+
├── checkout-flow.otel.canvas
|
|
27
|
+
├── checkout-flow.workflow.json
|
|
28
|
+
└── __executions__/
|
|
29
|
+
├── success-test.otel.json
|
|
30
|
+
└── error-test.otel.json
|
|
31
|
+
|
|
32
|
+
${chalk.yellow('Limitations:')}
|
|
33
|
+
• Hard to associate multiple workflows with one canvas
|
|
34
|
+
• Hard to associate executions with specific workflows
|
|
35
|
+
• No clear relationship between workflow and its test executions
|
|
36
|
+
• Doesn't scale well with multiple workflows per feature area
|
|
37
|
+
|
|
38
|
+
${chalk.bold('Benefits of Storyboard Structure:')}
|
|
39
|
+
|
|
40
|
+
The new storyboard structure provides clear hierarchy:
|
|
41
|
+
|
|
42
|
+
.principal-views/
|
|
43
|
+
└── checkout-flow/ # Storyboard folder
|
|
44
|
+
├── checkout-flow.otel.canvas # Canvas definition
|
|
45
|
+
├── happy-path/ # Workflow folder
|
|
46
|
+
│ ├── happy-path.workflow.json # Workflow definition
|
|
47
|
+
│ ├── success-1.otel.json # Execution files
|
|
48
|
+
│ └── success-2.otel.json
|
|
49
|
+
└── payment-failures/ # Another workflow
|
|
50
|
+
├── payment-failures.workflow.json
|
|
51
|
+
├── declined-1.otel.json
|
|
52
|
+
└── timeout-1.otel.json
|
|
53
|
+
|
|
54
|
+
${chalk.green('Advantages:')}
|
|
55
|
+
• ${chalk.bold('Clear Hierarchy:')} Storyboard → Workflows → Executions
|
|
56
|
+
• ${chalk.bold('Multiple Workflows:')} Easy to have many workflow variations for one canvas
|
|
57
|
+
• ${chalk.bold('Organized Executions:')} Each workflow has its own execution files
|
|
58
|
+
• ${chalk.bold('Better Discoverability:')} Related files are co-located
|
|
59
|
+
|
|
60
|
+
${chalk.bold('Migration Steps')}
|
|
61
|
+
|
|
62
|
+
${chalk.bold('Step 1: Understand Your Current Structure')}
|
|
63
|
+
|
|
64
|
+
First, identify what you have in your current .principal-views/ directory:
|
|
65
|
+
|
|
66
|
+
${chalk.dim('$ ls -R .principal-views/')}
|
|
67
|
+
|
|
68
|
+
Look for:
|
|
69
|
+
• Canvas files (.canvas or .otel.canvas)
|
|
70
|
+
• Workflow files (.workflow.json)
|
|
71
|
+
• Execution files (.otel.json) in __executions__/
|
|
72
|
+
|
|
73
|
+
${chalk.bold('Step 2: Plan Your Storyboard Organization')}
|
|
74
|
+
|
|
75
|
+
For each canvas file, decide:
|
|
76
|
+
1. What is the storyboard name? (Usually the canvas basename)
|
|
77
|
+
2. What workflows belong to this canvas?
|
|
78
|
+
3. Which execution files belong to each workflow?
|
|
79
|
+
|
|
80
|
+
${chalk.bold('Step 3: Create Storyboard Folder Structure')}
|
|
81
|
+
|
|
82
|
+
For each canvas:
|
|
83
|
+
|
|
84
|
+
${chalk.bold('3.1. Create Storyboard Directory')}
|
|
85
|
+
|
|
86
|
+
${chalk.dim('# Example: migrating checkout-flow.otel.canvas')}
|
|
87
|
+
${chalk.cyan('$ mkdir -p .principal-views/checkout-flow')}
|
|
88
|
+
|
|
89
|
+
${chalk.bold('3.2. Move Canvas File')}
|
|
90
|
+
|
|
91
|
+
${chalk.cyan('$ mv .principal-views/checkout-flow.otel.canvas \\\\')}
|
|
92
|
+
${chalk.cyan(' .principal-views/checkout-flow/checkout-flow.otel.canvas')}
|
|
93
|
+
|
|
94
|
+
${chalk.bold('3.3. Create Workflow Folders')}
|
|
95
|
+
|
|
96
|
+
${chalk.dim('# Example: creating a happy-path workflow')}
|
|
97
|
+
${chalk.cyan('$ mkdir -p .principal-views/checkout-flow/happy-path')}
|
|
98
|
+
|
|
99
|
+
${chalk.bold('3.4. Create or Move Workflow File')}
|
|
100
|
+
|
|
101
|
+
If you have an existing workflow file:
|
|
102
|
+
|
|
103
|
+
${chalk.cyan('$ mv .principal-views/checkout-flow.workflow.json \\\\')}
|
|
104
|
+
${chalk.cyan(' .principal-views/checkout-flow/happy-path/happy-path.workflow.json')}
|
|
105
|
+
|
|
106
|
+
If you need to create a new workflow file:
|
|
107
|
+
|
|
108
|
+
${chalk.dim('{')}
|
|
109
|
+
${chalk.dim(' "version": "1.0.0",')}
|
|
110
|
+
${chalk.dim(' "canvas": "../checkout-flow.otel.canvas",')}
|
|
111
|
+
${chalk.dim(' "name": "Happy Path",')}
|
|
112
|
+
${chalk.dim(' "description": "Successful checkout flow",')}
|
|
113
|
+
${chalk.dim(' "mode": "test",')}
|
|
114
|
+
${chalk.dim(' "scenarios": [...]')}
|
|
115
|
+
${chalk.dim('}')}
|
|
116
|
+
|
|
117
|
+
${chalk.yellow('Important:')} The ${chalk.bold('canvas')} field must be a relative path pointing to
|
|
118
|
+
the parent canvas file.
|
|
119
|
+
|
|
120
|
+
${chalk.bold('3.5. Move Execution Files')}
|
|
121
|
+
|
|
122
|
+
Move execution files from __executions__/ into the appropriate workflow folder:
|
|
123
|
+
|
|
124
|
+
${chalk.cyan('$ mv .principal-views/__executions__/success-1.otel.json \\\\')}
|
|
125
|
+
${chalk.cyan(' .principal-views/checkout-flow/happy-path/success-1.otel.json')}
|
|
126
|
+
|
|
127
|
+
${chalk.bold('Step 4: Update Canvas References in Workflow Files')}
|
|
128
|
+
|
|
129
|
+
Ensure all workflow files have the correct relative canvas path:
|
|
130
|
+
|
|
131
|
+
${chalk.dim('{')}
|
|
132
|
+
${chalk.dim(' "canvas": "../checkout-flow.otel.canvas"')}
|
|
133
|
+
${chalk.dim('}')}
|
|
134
|
+
|
|
135
|
+
The path should use ${chalk.bold('..')} to reference the parent storyboard canvas.
|
|
136
|
+
|
|
137
|
+
${chalk.bold('Step 5: Cleanup Legacy Directories')}
|
|
138
|
+
|
|
139
|
+
Once all files are migrated, remove the old __executions__/ directory if empty:
|
|
140
|
+
|
|
141
|
+
${chalk.cyan('$ rmdir .principal-views/__executions__/')}
|
|
142
|
+
|
|
143
|
+
${chalk.bold('Step 6: Verify Migration')}
|
|
144
|
+
|
|
145
|
+
Check your new structure:
|
|
146
|
+
|
|
147
|
+
${chalk.cyan('$ tree .principal-views/')}
|
|
148
|
+
|
|
149
|
+
${chalk.bold('Complete Migration Example')}
|
|
150
|
+
|
|
151
|
+
${chalk.bold('Before (Legacy Flat Structure):')}
|
|
152
|
+
|
|
153
|
+
.principal-views/
|
|
154
|
+
├── checkout.otel.canvas
|
|
155
|
+
├── checkout.workflow.json
|
|
156
|
+
├── refund.workflow.json
|
|
157
|
+
└── __executions__/
|
|
158
|
+
├── checkout-success.otel.json
|
|
159
|
+
├── checkout-declined.otel.json
|
|
160
|
+
└── refund-full.otel.json
|
|
161
|
+
|
|
162
|
+
${chalk.bold('After (Storyboard Structure):')}
|
|
163
|
+
|
|
164
|
+
.principal-views/
|
|
165
|
+
└── checkout/
|
|
166
|
+
├── checkout.otel.canvas
|
|
167
|
+
├── checkout-flow/
|
|
168
|
+
│ ├── checkout-flow.workflow.json
|
|
169
|
+
│ ├── checkout-success.otel.json
|
|
170
|
+
│ └── checkout-declined.otel.json
|
|
171
|
+
└── refund-flow/
|
|
172
|
+
├── refund-flow.workflow.json
|
|
173
|
+
└── refund-full.otel.json
|
|
174
|
+
|
|
175
|
+
${chalk.bold('Common Issues and Solutions')}
|
|
176
|
+
|
|
177
|
+
${chalk.bold('Issue 1: Deprecation Errors')}
|
|
178
|
+
|
|
179
|
+
${chalk.red('Problem:')} You see errors like:
|
|
180
|
+
"DEPRECATED: Legacy flat canvas structure is no longer supported"
|
|
181
|
+
|
|
182
|
+
${chalk.green('Solution:')} Follow this migration guide to move to the storyboard
|
|
183
|
+
structure immediately.
|
|
184
|
+
|
|
185
|
+
${chalk.bold('Issue 2: Canvas Reference Not Found')}
|
|
186
|
+
|
|
187
|
+
${chalk.red('Problem:')} Workflow files cannot find the canvas file.
|
|
188
|
+
|
|
189
|
+
${chalk.green('Solution:')} Update the "canvas" field in workflow.json to use the
|
|
190
|
+
correct relative path:
|
|
191
|
+
${chalk.dim('"canvas": "../storyboard-name.otel.canvas"')}
|
|
192
|
+
|
|
193
|
+
${chalk.bold('Issue 3: Executions Not Associated with Workflow')}
|
|
194
|
+
|
|
195
|
+
${chalk.red('Problem:')} Execution files in the old __executions__/ directory are
|
|
196
|
+
not linked to workflows.
|
|
197
|
+
|
|
198
|
+
${chalk.green('Solution:')} Move execution files into the appropriate workflow folder.
|
|
199
|
+
|
|
200
|
+
${chalk.bold('Best Practices')}
|
|
201
|
+
|
|
202
|
+
${chalk.bold('Naming Conventions:')}
|
|
203
|
+
|
|
204
|
+
${chalk.green('✓')} Storyboard Names: Use the feature or component name
|
|
205
|
+
Examples: checkout-flow, user-authentication
|
|
206
|
+
|
|
207
|
+
${chalk.green('✓')} Workflow Names: Describe the scenario or test case
|
|
208
|
+
Examples: happy-path, payment-failures, edge-cases
|
|
209
|
+
|
|
210
|
+
${chalk.green('✓')} Execution Files: Include scenario prefix or variant number
|
|
211
|
+
Examples: success-1.otel.json, declined-card-1.otel.json
|
|
212
|
+
|
|
213
|
+
${chalk.bold('Timeline')}
|
|
214
|
+
|
|
215
|
+
• v0.15.0: Legacy structure shows deprecation warnings
|
|
216
|
+
• v1.0.0 (Current): Legacy structure produces validation errors
|
|
217
|
+
• v2.0.0 (Future): Legacy structure will be completely removed
|
|
218
|
+
|
|
219
|
+
${chalk.bold('Getting Help')}
|
|
220
|
+
|
|
221
|
+
If you encounter issues during migration:
|
|
222
|
+
|
|
223
|
+
1. Check this guide for common issues
|
|
224
|
+
2. Run ${chalk.cyan('principal-ai doctor')} to check for configuration issues
|
|
225
|
+
3. Run ${chalk.cyan('principal-ai validate')} to verify your structure
|
|
226
|
+
4. Open an issue in the repository with your current file structure
|
|
227
|
+
|
|
228
|
+
${chalk.bold('Related Commands')}
|
|
229
|
+
|
|
230
|
+
${chalk.cyan('principal-ai doctor')} - Check for configuration staleness and issues
|
|
231
|
+
${chalk.cyan('principal-ai validate')} - Validate your Principal View files
|
|
232
|
+
${chalk.cyan('principal-ai init')} - Initialize a new .principal-views directory
|
|
233
|
+
${chalk.cyan('principal-ai create')} - Create new canvas or workflow files
|
|
234
|
+
|
|
235
|
+
${chalk.dim('For the full detailed guide with more examples, visit:')}
|
|
236
|
+
${chalk.dim('https://github.com/principal-ai/principal-view-core-library/blob/main/docs/MIGRATION_GUIDE.md')}
|
|
237
|
+
`;
|
|
238
|
+
export function createMigrationCommand() {
|
|
239
|
+
const command = new Command('migration');
|
|
240
|
+
command
|
|
241
|
+
.description('Display the migration guide for moving to storyboard structure')
|
|
242
|
+
.alias('migrate')
|
|
243
|
+
.action(() => {
|
|
244
|
+
console.log(MIGRATION_GUIDE);
|
|
245
|
+
});
|
|
246
|
+
return command;
|
|
247
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `principal-ai open-studio` — open Principal Studio.
|
|
3
|
+
*
|
|
4
|
+
* Launches the standalone principal-studio bundle with its default tabs. If
|
|
5
|
+
* Studio is already running, focuses its window via the IPC socket instead of
|
|
6
|
+
* spawning a second instance (and without switching tabs).
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
export declare function createOpenStudioCommand(): Command;
|
|
10
|
+
//# sourceMappingURL=open-studio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open-studio.d.ts","sourceRoot":"","sources":["../../src/commands/open-studio.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,uBAAuB,IAAI,OAAO,CA0BjD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `principal-ai open-studio` — open Principal Studio.
|
|
3
|
+
*
|
|
4
|
+
* Launches the standalone principal-studio bundle with its default tabs. If
|
|
5
|
+
* Studio is already running, focuses its window via the IPC socket instead of
|
|
6
|
+
* spawning a second instance (and without switching tabs).
|
|
7
|
+
*/
|
|
8
|
+
import { spawn } from 'node:child_process';
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
import { handoffToRunning } from '../lib/viewer-ipc.js';
|
|
11
|
+
import { resolveViewerLaunch } from './trail.js';
|
|
12
|
+
export function createOpenStudioCommand() {
|
|
13
|
+
return new Command('open-studio')
|
|
14
|
+
.description('Open Principal Studio (or focus it if already running)')
|
|
15
|
+
.option('--viewer-dir <path>', 'Path to the @principal-ai/subsystems-studio package (overrides PRINCIPAL_STUDIO_DIR)')
|
|
16
|
+
.action(async (options) => {
|
|
17
|
+
if (await handoffToRunning({ kind: 'FOCUS' })) {
|
|
18
|
+
process.stderr.write('Principal Studio focused.\n');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const launch = resolveViewerLaunch(options.viewerDir);
|
|
22
|
+
const env = process.env;
|
|
23
|
+
process.stderr.write('Launching Principal Studio…\n');
|
|
24
|
+
const child = launch.kind === 'installed'
|
|
25
|
+
? spawn(launch.bin, [], { env, stdio: 'inherit' })
|
|
26
|
+
: spawn('bun', ['start'], { cwd: launch.dir, env, stdio: 'inherit' });
|
|
27
|
+
child.on('error', (err) => {
|
|
28
|
+
process.stderr.write(`Failed to launch Principal Studio: ${err.message}\n`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/commands/opencode/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,wBAAgB,kBAAkB,IAAI,OAAO,CAuB5C"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { OpenCodeEventStore } from "@principal-ai/subsystems-core/node";
|
|
3
|
+
export function createFetchCommand() {
|
|
4
|
+
const command = new Command("fetch");
|
|
5
|
+
command
|
|
6
|
+
.description("Fetch events for an opencode session and print as JSON")
|
|
7
|
+
.argument("<session-id>", "The session ID (aggregate_id) to fetch events for")
|
|
8
|
+
.option("-l, --limit <number>", "Maximum events to fetch", "10000")
|
|
9
|
+
.option("-a, --after <number>", "Sequence number to start after", "-1")
|
|
10
|
+
.option("--db-path <path>", "Path to opencode.db (defaults to XDG data dir)")
|
|
11
|
+
.action((sessionId, options) => {
|
|
12
|
+
const store = new OpenCodeEventStore({ dbPath: options.dbPath });
|
|
13
|
+
try {
|
|
14
|
+
const result = store.readAggregate(sessionId, {
|
|
15
|
+
after: options.after ? Number(options.after) : -1,
|
|
16
|
+
limit: options.limit ? Number(options.limit) : 10000,
|
|
17
|
+
});
|
|
18
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
store.close();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return command;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/opencode/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,wBAAgB,qBAAqB,IAAI,OAAO,CAS/C"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { createFetchCommand } from "./fetch.js";
|
|
3
|
+
import { createListSessionsCommand } from "./list-sessions.js";
|
|
4
|
+
export function createOpencodeCommand() {
|
|
5
|
+
const command = new Command("opencode");
|
|
6
|
+
command
|
|
7
|
+
.description("Read events from opencode's local SQLite database")
|
|
8
|
+
.addCommand(createListSessionsCommand())
|
|
9
|
+
.addCommand(createFetchCommand());
|
|
10
|
+
return command;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-sessions.d.ts","sourceRoot":"","sources":["../../../src/commands/opencode/list-sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,wBAAgB,yBAAyB,IAAI,OAAO,CAkBnD"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { OpenCodeEventStore } from "@principal-ai/subsystems-core/node";
|
|
3
|
+
export function createListSessionsCommand() {
|
|
4
|
+
const command = new Command("list-sessions");
|
|
5
|
+
command
|
|
6
|
+
.description("List session IDs in the opencode database")
|
|
7
|
+
.option("--db-path <path>", "Path to opencode.db (defaults to XDG data dir)")
|
|
8
|
+
.option("--limit <number>", "Maximum sessions to list", "50")
|
|
9
|
+
.action((options) => {
|
|
10
|
+
const store = new OpenCodeEventStore({ dbPath: options.dbPath });
|
|
11
|
+
try {
|
|
12
|
+
const ids = store.listSessionIds(options.limit ? Number(options.limit) : 50);
|
|
13
|
+
process.stdout.write(JSON.stringify(ids, null, 2) + "\n");
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
store.close();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return command;
|
|
20
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo command — fetch package information for a GitHub repo from web-ade.
|
|
3
|
+
*
|
|
4
|
+
* Hits `GET /api/github/repo/{owner}/{name}/packages` which mirrors the live
|
|
5
|
+
* package discovery the in-app repo explorer uses (`PackageLayerModule`).
|
|
6
|
+
* The response is `{ packages: PackageLayer[], summary, treeSha }` where
|
|
7
|
+
* `summary` carries the monorepo flag, root package name, workspace list,
|
|
8
|
+
* and aggregated dependency / script counts.
|
|
9
|
+
*
|
|
10
|
+
* Resolves a GitHub token locally (gh CLI → git credential helper) and calls
|
|
11
|
+
* the web-ade API with `Authorization: Bearer <token>`. The token is never
|
|
12
|
+
* echoed to argv, env, stdout, or stderr.
|
|
13
|
+
*
|
|
14
|
+
* Set `PRINCIPAL_ADE_BASE_URL` to point at a non-prod deployment.
|
|
15
|
+
*/
|
|
16
|
+
import { Command } from 'commander';
|
|
17
|
+
export declare function createRepoCommand(): Command;
|
|
18
|
+
//# sourceMappingURL=repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/commands/repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuSpC,wBAAgB,iBAAiB,IAAI,OAAO,CAkB3C"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo command — fetch package information for a GitHub repo from web-ade.
|
|
3
|
+
*
|
|
4
|
+
* Hits `GET /api/github/repo/{owner}/{name}/packages` which mirrors the live
|
|
5
|
+
* package discovery the in-app repo explorer uses (`PackageLayerModule`).
|
|
6
|
+
* The response is `{ packages: PackageLayer[], summary, treeSha }` where
|
|
7
|
+
* `summary` carries the monorepo flag, root package name, workspace list,
|
|
8
|
+
* and aggregated dependency / script counts.
|
|
9
|
+
*
|
|
10
|
+
* Resolves a GitHub token locally (gh CLI → git credential helper) and calls
|
|
11
|
+
* the web-ade API with `Authorization: Bearer <token>`. The token is never
|
|
12
|
+
* echoed to argv, env, stdout, or stderr.
|
|
13
|
+
*
|
|
14
|
+
* Set `PRINCIPAL_ADE_BASE_URL` to point at a non-prod deployment.
|
|
15
|
+
*/
|
|
16
|
+
import { Command } from 'commander';
|
|
17
|
+
import { spawnSync } from 'node:child_process';
|
|
18
|
+
const BASE_URL = process.env.PRINCIPAL_ADE_BASE_URL?.replace(/\/+$/, '') ||
|
|
19
|
+
'https://app.principal-ade.com';
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Auth
|
|
22
|
+
// ============================================================================
|
|
23
|
+
function resolveTokenViaGh() {
|
|
24
|
+
const result = spawnSync('gh', ['auth', 'token'], {
|
|
25
|
+
encoding: 'utf8',
|
|
26
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
27
|
+
});
|
|
28
|
+
if (result.status === 0 && result.stdout) {
|
|
29
|
+
const token = result.stdout.trim();
|
|
30
|
+
if (token)
|
|
31
|
+
return token;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function resolveTokenViaGitCredential() {
|
|
36
|
+
const result = spawnSync('git', ['credential', 'fill'], {
|
|
37
|
+
encoding: 'utf8',
|
|
38
|
+
input: 'protocol=https\nhost=github.com\n\n',
|
|
39
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
40
|
+
});
|
|
41
|
+
if (result.status !== 0 || !result.stdout)
|
|
42
|
+
return null;
|
|
43
|
+
for (const line of result.stdout.split('\n')) {
|
|
44
|
+
if (line.startsWith('password=')) {
|
|
45
|
+
const token = line.slice('password='.length).trim();
|
|
46
|
+
if (token)
|
|
47
|
+
return token;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function resolveToken() {
|
|
53
|
+
return resolveTokenViaGh() ?? resolveTokenViaGitCredential();
|
|
54
|
+
}
|
|
55
|
+
function exitWithTokenError() {
|
|
56
|
+
process.stderr.write('Could not resolve a GitHub token. Run `gh auth login`, or configure a git credential helper for github.com.\n');
|
|
57
|
+
process.exit(2);
|
|
58
|
+
}
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// HTTP helpers
|
|
61
|
+
// ============================================================================
|
|
62
|
+
async function describeHttpError(response) {
|
|
63
|
+
let serverMessage = '';
|
|
64
|
+
let code = '';
|
|
65
|
+
try {
|
|
66
|
+
const body = (await response.clone().json());
|
|
67
|
+
serverMessage = body.error ?? '';
|
|
68
|
+
code = body.code ?? '';
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// body wasn't JSON — fall through to status-only message
|
|
72
|
+
}
|
|
73
|
+
const fallback = response.status === 404
|
|
74
|
+
? 'Repository not found (or token lacks read access)'
|
|
75
|
+
: response.status === 403
|
|
76
|
+
? 'Not authorized (token may lack repo scope)'
|
|
77
|
+
: response.status === 401
|
|
78
|
+
? 'GitHub token rejected'
|
|
79
|
+
: `HTTP ${response.status}`;
|
|
80
|
+
const human = serverMessage || fallback;
|
|
81
|
+
return `${human}${code ? ` [${code}]` : ''}`;
|
|
82
|
+
}
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// repo parsing
|
|
85
|
+
// ============================================================================
|
|
86
|
+
function parseOwnerRepo(ownerRepo) {
|
|
87
|
+
const slashIndex = ownerRepo.indexOf('/');
|
|
88
|
+
if (slashIndex === -1 || slashIndex === 0 || slashIndex === ownerRepo.length - 1) {
|
|
89
|
+
process.stderr.write(`Invalid repo format: "${ownerRepo}". Use <owner>/<repo> (e.g. "principal-ai/web-ade").\n`);
|
|
90
|
+
process.exit(2);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
owner: ownerRepo.slice(0, slashIndex),
|
|
94
|
+
repo: ownerRepo.slice(slashIndex + 1),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async function fetchPackages(ownerRepo, options) {
|
|
98
|
+
const { owner, repo } = parseOwnerRepo(ownerRepo);
|
|
99
|
+
const token = resolveToken();
|
|
100
|
+
if (!token)
|
|
101
|
+
exitWithTokenError();
|
|
102
|
+
const url = `${BASE_URL}/api/github/repo/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/packages`;
|
|
103
|
+
let response;
|
|
104
|
+
try {
|
|
105
|
+
response = await fetch(url, {
|
|
106
|
+
headers: {
|
|
107
|
+
Authorization: `Bearer ${token}`,
|
|
108
|
+
Accept: 'application/json',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
process.stderr.write(`Network error fetching packages: ${err.message}\n`);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
process.stderr.write(`${await describeHttpError(response)}\n`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
let body;
|
|
121
|
+
try {
|
|
122
|
+
body = (await response.json());
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
process.stderr.write('Unexpected non-JSON response from the packages endpoint.\n');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
// A 200 may still carry a server-side error message (degraded fallback).
|
|
129
|
+
if (body.error) {
|
|
130
|
+
process.stderr.write(`Server reported an error: ${body.error}\n`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
if (options.json) {
|
|
134
|
+
const out = options.summaryOnly ? { summary: body.summary, treeSha: body.treeSha } : body;
|
|
135
|
+
process.stdout.write(JSON.stringify(out, null, 2));
|
|
136
|
+
process.stdout.write('\n');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
renderPackagesHuman(body, options.summaryOnly === true);
|
|
140
|
+
}
|
|
141
|
+
// ============================================================================
|
|
142
|
+
// Human rendering
|
|
143
|
+
// ============================================================================
|
|
144
|
+
function renderPackagesHuman(body, summaryOnly) {
|
|
145
|
+
const { summary = {}, packages, treeSha } = body;
|
|
146
|
+
const pkgCount = summary.totalPackages ?? packages.length;
|
|
147
|
+
const heading = summary.isMonorepo
|
|
148
|
+
? `Monorepo — ${pkgCount} package${pkgCount === 1 ? '' : 's'}`
|
|
149
|
+
: `${pkgCount} package${pkgCount === 1 ? '' : 's'}`;
|
|
150
|
+
console.log(`\n${heading}`);
|
|
151
|
+
if (summary.rootPackageName) {
|
|
152
|
+
console.log(` root: ${summary.rootPackageName}`);
|
|
153
|
+
}
|
|
154
|
+
if (treeSha)
|
|
155
|
+
console.log(` tree: ${treeSha}`);
|
|
156
|
+
console.log('');
|
|
157
|
+
const deps = summary.totalDependencies ?? 0;
|
|
158
|
+
const devDeps = summary.totalDevDependencies ?? 0;
|
|
159
|
+
console.log(` dependencies: ${deps} dev: ${devDeps}`);
|
|
160
|
+
const scripts = summary.availableScripts ?? [];
|
|
161
|
+
if (scripts.length > 0) {
|
|
162
|
+
console.log(` available scripts: ${scripts.length}`);
|
|
163
|
+
const preview = scripts.slice(0, 10).join(', ');
|
|
164
|
+
const more = scripts.length > 10 ? ` (+${scripts.length - 10} more)` : '';
|
|
165
|
+
console.log(` ${preview}${more}`);
|
|
166
|
+
}
|
|
167
|
+
console.log('');
|
|
168
|
+
if (summaryOnly)
|
|
169
|
+
return;
|
|
170
|
+
const workspacePackages = summary.workspacePackages ?? [];
|
|
171
|
+
if (workspacePackages.length > 0) {
|
|
172
|
+
console.log(' workspaces:');
|
|
173
|
+
for (const ws of workspacePackages) {
|
|
174
|
+
const name = ws.name || '(unnamed)';
|
|
175
|
+
const path = ws.path || '';
|
|
176
|
+
console.log(` ${name}${path ? ` ${path}` : ''}`);
|
|
177
|
+
}
|
|
178
|
+
console.log('');
|
|
179
|
+
}
|
|
180
|
+
if (packages.length === 0) {
|
|
181
|
+
console.log(' (no package manifests detected)');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
console.log(' packages:');
|
|
185
|
+
for (const p of packages) {
|
|
186
|
+
const data = p.packageData;
|
|
187
|
+
if (!data) {
|
|
188
|
+
console.log(' (entry without packageData)');
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const name = data.name || '(unnamed)';
|
|
192
|
+
const path = data.path || '';
|
|
193
|
+
const flags = [];
|
|
194
|
+
if (data.isMonorepoRoot)
|
|
195
|
+
flags.push('monorepo-root');
|
|
196
|
+
if (data.isWorkspace)
|
|
197
|
+
flags.push('workspace');
|
|
198
|
+
const flagText = flags.length > 0 ? ` [${flags.join(', ')}]` : '';
|
|
199
|
+
console.log(` ${name}${path ? ` ${path}` : ''}${flagText}`);
|
|
200
|
+
const depCount = Object.keys(data.dependencies || {}).length;
|
|
201
|
+
const devDepCount = Object.keys(data.devDependencies || {}).length;
|
|
202
|
+
if (depCount || devDepCount) {
|
|
203
|
+
console.log(` deps: ${depCount}, devDeps: ${devDepCount}`);
|
|
204
|
+
}
|
|
205
|
+
const commands = data.availableCommands ?? [];
|
|
206
|
+
if (commands.length > 0) {
|
|
207
|
+
const names = commands.map((c) => c.name).filter(Boolean);
|
|
208
|
+
if (names.length > 0) {
|
|
209
|
+
const preview = names.slice(0, 8).join(', ');
|
|
210
|
+
const more = names.length > 8 ? ` (+${names.length - 8} more)` : '';
|
|
211
|
+
console.log(` scripts: ${preview}${more}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
console.log('');
|
|
216
|
+
}
|
|
217
|
+
// ============================================================================
|
|
218
|
+
// Command wiring
|
|
219
|
+
// ============================================================================
|
|
220
|
+
export function createRepoCommand() {
|
|
221
|
+
const command = new Command('repo');
|
|
222
|
+
command.description('Fetch repository data from web-ade');
|
|
223
|
+
command
|
|
224
|
+
.command('packages')
|
|
225
|
+
.description('Detect and return package information for a GitHub repository (live discovery via web-ade).')
|
|
226
|
+
.argument('<owner/repo>', 'Repo in owner/repo format (e.g. principal-ai/web-ade)')
|
|
227
|
+
.option('--summary-only', 'Print only the aggregate summary (no per-package list)')
|
|
228
|
+
.option('--json', 'Output the raw response as JSON (for agents / storing in a story)')
|
|
229
|
+
.action(async (ownerRepo, options) => {
|
|
230
|
+
await fetchPackages(ownerRepo, options);
|
|
231
|
+
});
|
|
232
|
+
return command;
|
|
233
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6WpC,wBAAgB,mBAAmB,IAAI,OAAO,CA0B7C"}
|