@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.
Files changed (184) hide show
  1. package/README.md +172 -0
  2. package/dist/commands/agent-session.d.ts +3 -0
  3. package/dist/commands/agent-session.d.ts.map +1 -0
  4. package/dist/commands/agent-session.js +67 -0
  5. package/dist/commands/agent-sessions.d.ts +11 -0
  6. package/dist/commands/agent-sessions.d.ts.map +1 -0
  7. package/dist/commands/agent-sessions.js +39 -0
  8. package/dist/commands/auxiliary/index.d.ts +3 -0
  9. package/dist/commands/auxiliary/index.d.ts.map +1 -0
  10. package/dist/commands/auxiliary/index.js +9 -0
  11. package/dist/commands/auxiliary/validate.d.ts +3 -0
  12. package/dist/commands/auxiliary/validate.d.ts.map +1 -0
  13. package/dist/commands/auxiliary/validate.js +123 -0
  14. package/dist/commands/collector/check.d.ts +6 -0
  15. package/dist/commands/collector/check.d.ts.map +1 -0
  16. package/dist/commands/collector/check.js +153 -0
  17. package/dist/commands/collector/diagnose.d.ts +6 -0
  18. package/dist/commands/collector/diagnose.d.ts.map +1 -0
  19. package/dist/commands/collector/diagnose.js +229 -0
  20. package/dist/commands/collector/index.d.ts +6 -0
  21. package/dist/commands/collector/index.d.ts.map +1 -0
  22. package/dist/commands/collector/index.js +16 -0
  23. package/dist/commands/collector/status.d.ts +6 -0
  24. package/dist/commands/collector/status.d.ts.map +1 -0
  25. package/dist/commands/collector/status.js +77 -0
  26. package/dist/commands/collector/utils.d.ts +92 -0
  27. package/dist/commands/collector/utils.d.ts.map +1 -0
  28. package/dist/commands/collector/utils.js +154 -0
  29. package/dist/commands/coverage.d.ts +9 -0
  30. package/dist/commands/coverage.d.ts.map +1 -0
  31. package/dist/commands/coverage.js +252 -0
  32. package/dist/commands/create.d.ts +6 -0
  33. package/dist/commands/create.d.ts.map +1 -0
  34. package/dist/commands/create.js +50 -0
  35. package/dist/commands/events/index.d.ts +3 -0
  36. package/dist/commands/events/index.d.ts.map +1 -0
  37. package/dist/commands/events/index.js +9 -0
  38. package/dist/commands/events/validate.d.ts +3 -0
  39. package/dist/commands/events/validate.d.ts.map +1 -0
  40. package/dist/commands/events/validate.js +124 -0
  41. package/dist/commands/formats.d.ts +6 -0
  42. package/dist/commands/formats.d.ts.map +1 -0
  43. package/dist/commands/formats.js +1118 -0
  44. package/dist/commands/hooks.d.ts +9 -0
  45. package/dist/commands/hooks.d.ts.map +1 -0
  46. package/dist/commands/hooks.js +295 -0
  47. package/dist/commands/inbox.d.ts +13 -0
  48. package/dist/commands/inbox.d.ts.map +1 -0
  49. package/dist/commands/inbox.js +179 -0
  50. package/dist/commands/init.d.ts +6 -0
  51. package/dist/commands/init.d.ts.map +1 -0
  52. package/dist/commands/init.js +220 -0
  53. package/dist/commands/lint.d.ts +11 -0
  54. package/dist/commands/lint.d.ts.map +1 -0
  55. package/dist/commands/lint.js +71 -0
  56. package/dist/commands/list.d.ts +6 -0
  57. package/dist/commands/list.d.ts.map +1 -0
  58. package/dist/commands/list.js +78 -0
  59. package/dist/commands/migrate-nodes.d.ts +9 -0
  60. package/dist/commands/migrate-nodes.d.ts.map +1 -0
  61. package/dist/commands/migrate-nodes.js +363 -0
  62. package/dist/commands/migrate-scopes-to-canvas.d.ts +3 -0
  63. package/dist/commands/migrate-scopes-to-canvas.d.ts.map +1 -0
  64. package/dist/commands/migrate-scopes-to-canvas.js +143 -0
  65. package/dist/commands/migration.d.ts +6 -0
  66. package/dist/commands/migration.d.ts.map +1 -0
  67. package/dist/commands/migration.js +247 -0
  68. package/dist/commands/open-studio.d.ts +10 -0
  69. package/dist/commands/open-studio.d.ts.map +1 -0
  70. package/dist/commands/open-studio.js +32 -0
  71. package/dist/commands/opencode/fetch.d.ts +3 -0
  72. package/dist/commands/opencode/fetch.d.ts.map +1 -0
  73. package/dist/commands/opencode/fetch.js +25 -0
  74. package/dist/commands/opencode/index.d.ts +3 -0
  75. package/dist/commands/opencode/index.d.ts.map +1 -0
  76. package/dist/commands/opencode/index.js +11 -0
  77. package/dist/commands/opencode/list-sessions.d.ts +3 -0
  78. package/dist/commands/opencode/list-sessions.d.ts.map +1 -0
  79. package/dist/commands/opencode/list-sessions.js +20 -0
  80. package/dist/commands/repo.d.ts +18 -0
  81. package/dist/commands/repo.d.ts.map +1 -0
  82. package/dist/commands/repo.js +233 -0
  83. package/dist/commands/schema.d.ts +6 -0
  84. package/dist/commands/schema.d.ts.map +1 -0
  85. package/dist/commands/schema.js +367 -0
  86. package/dist/commands/scopes/index.d.ts +3 -0
  87. package/dist/commands/scopes/index.d.ts.map +1 -0
  88. package/dist/commands/scopes/index.js +9 -0
  89. package/dist/commands/scopes/validate.d.ts +3 -0
  90. package/dist/commands/scopes/validate.d.ts.map +1 -0
  91. package/dist/commands/scopes/validate.js +187 -0
  92. package/dist/commands/setup.d.ts +6 -0
  93. package/dist/commands/setup.d.ts.map +1 -0
  94. package/dist/commands/setup.js +406 -0
  95. package/dist/commands/starred-collections.d.ts +12 -0
  96. package/dist/commands/starred-collections.d.ts.map +1 -0
  97. package/dist/commands/starred-collections.js +310 -0
  98. package/dist/commands/subsystem-model.d.ts +11 -0
  99. package/dist/commands/subsystem-model.d.ts.map +1 -0
  100. package/dist/commands/subsystem-model.js +249 -0
  101. package/dist/commands/topic.d.ts +15 -0
  102. package/dist/commands/topic.d.ts.map +1 -0
  103. package/dist/commands/topic.js +683 -0
  104. package/dist/commands/tour.d.ts +23 -0
  105. package/dist/commands/tour.d.ts.map +1 -0
  106. package/dist/commands/tour.js +783 -0
  107. package/dist/commands/trace/flow.d.ts +6 -0
  108. package/dist/commands/trace/flow.d.ts.map +1 -0
  109. package/dist/commands/trace/flow.js +158 -0
  110. package/dist/commands/trace/index.d.ts +6 -0
  111. package/dist/commands/trace/index.d.ts.map +1 -0
  112. package/dist/commands/trace/index.js +20 -0
  113. package/dist/commands/trace/inspect.d.ts +6 -0
  114. package/dist/commands/trace/inspect.d.ts.map +1 -0
  115. package/dist/commands/trace/inspect.js +187 -0
  116. package/dist/commands/trace/list.d.ts +6 -0
  117. package/dist/commands/trace/list.d.ts.map +1 -0
  118. package/dist/commands/trace/list.js +145 -0
  119. package/dist/commands/trace/registrations.d.ts +6 -0
  120. package/dist/commands/trace/registrations.d.ts.map +1 -0
  121. package/dist/commands/trace/registrations.js +81 -0
  122. package/dist/commands/trace/validate.d.ts +6 -0
  123. package/dist/commands/trace/validate.d.ts.map +1 -0
  124. package/dist/commands/trace/validate.js +276 -0
  125. package/dist/commands/trail.d.ts +36 -0
  126. package/dist/commands/trail.d.ts.map +1 -0
  127. package/dist/commands/trail.js +622 -0
  128. package/dist/commands/validate.d.ts +12 -0
  129. package/dist/commands/validate.d.ts.map +1 -0
  130. package/dist/commands/validate.js +3334 -0
  131. package/dist/commands/workflow/implementation.d.ts +3 -0
  132. package/dist/commands/workflow/implementation.d.ts.map +1 -0
  133. package/dist/commands/workflow/implementation.js +51 -0
  134. package/dist/commands/workflow/index.d.ts +3 -0
  135. package/dist/commands/workflow/index.d.ts.map +1 -0
  136. package/dist/commands/workflow/index.js +19 -0
  137. package/dist/commands/workflow/inspect.d.ts +3 -0
  138. package/dist/commands/workflow/inspect.d.ts.map +1 -0
  139. package/dist/commands/workflow/inspect.js +123 -0
  140. package/dist/commands/workflow/list.d.ts +3 -0
  141. package/dist/commands/workflow/list.d.ts.map +1 -0
  142. package/dist/commands/workflow/list.js +95 -0
  143. package/dist/commands/workflow/render.d.ts +3 -0
  144. package/dist/commands/workflow/render.d.ts.map +1 -0
  145. package/dist/commands/workflow/render.js +88 -0
  146. package/dist/commands/workflow/test.d.ts +3 -0
  147. package/dist/commands/workflow/test.d.ts.map +1 -0
  148. package/dist/commands/workflow/test.js +141 -0
  149. package/dist/commands/workflow/utils.d.ts +49 -0
  150. package/dist/commands/workflow/utils.d.ts.map +1 -0
  151. package/dist/commands/workflow/utils.js +164 -0
  152. package/dist/commands/workflow/validate.d.ts +3 -0
  153. package/dist/commands/workflow/validate.d.ts.map +1 -0
  154. package/dist/commands/workflow/validate.js +344 -0
  155. package/dist/file-utils.d.ts +15 -0
  156. package/dist/file-utils.d.ts.map +1 -0
  157. package/dist/file-utils.js +29 -0
  158. package/dist/index.cjs +285718 -0
  159. package/dist/index.cjs.map +7 -0
  160. package/dist/index.d.ts +8 -0
  161. package/dist/index.d.ts.map +1 -0
  162. package/dist/index.js +81 -0
  163. package/dist/lib/bridge-ipc.d.ts +29 -0
  164. package/dist/lib/bridge-ipc.d.ts.map +1 -0
  165. package/dist/lib/bridge-ipc.js +128 -0
  166. package/dist/lib/github-user.d.ts +17 -0
  167. package/dist/lib/github-user.d.ts.map +1 -0
  168. package/dist/lib/github-user.js +53 -0
  169. package/dist/lib/open-url.d.ts +11 -0
  170. package/dist/lib/open-url.d.ts.map +1 -0
  171. package/dist/lib/open-url.js +45 -0
  172. package/dist/lib/subsystem-model-store.d.ts +74 -0
  173. package/dist/lib/subsystem-model-store.d.ts.map +1 -0
  174. package/dist/lib/subsystem-model-store.js +292 -0
  175. package/dist/lib/tour-cache.d.ts +26 -0
  176. package/dist/lib/tour-cache.d.ts.map +1 -0
  177. package/dist/lib/tour-cache.js +46 -0
  178. package/dist/lib/trail-cache.d.ts +40 -0
  179. package/dist/lib/trail-cache.d.ts.map +1 -0
  180. package/dist/lib/trail-cache.js +97 -0
  181. package/dist/lib/viewer-ipc.d.ts +44 -0
  182. package/dist/lib/viewer-ipc.d.ts.map +1 -0
  183. package/dist/lib/viewer-ipc.js +68 -0
  184. 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,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createFetchCommand(): Command;
3
+ //# sourceMappingURL=fetch.d.ts.map
@@ -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,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createOpencodeCommand(): Command;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createListSessionsCommand(): Command;
3
+ //# sourceMappingURL=list-sessions.d.ts.map
@@ -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,6 @@
1
+ /**
2
+ * Schema command - Display documentation about the canvas format
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function createSchemaCommand(): Command;
6
+ //# sourceMappingURL=schema.d.ts.map
@@ -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"}