@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,9 @@
1
+ /**
2
+ * Hooks command - Manage husky pre-commit hooks for Principal View
3
+ *
4
+ * This command installs/removes pre-commit hooks into a target project
5
+ * that will run `npx @principal-ai/principal-studio-cli doctor` and `npx @principal-ai/principal-studio-cli validate` before each commit.
6
+ */
7
+ import { Command } from 'commander';
8
+ export declare function createHooksCommand(): Command;
9
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4NpC,wBAAgB,kBAAkB,IAAI,OAAO,CA+F5C"}
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Hooks command - Manage husky pre-commit hooks for Principal View
3
+ *
4
+ * This command installs/removes pre-commit hooks into a target project
5
+ * that will run `npx @principal-ai/principal-studio-cli doctor` and `npx @principal-ai/principal-studio-cli validate` before each commit.
6
+ */
7
+ import { Command } from 'commander';
8
+ import { existsSync, readFileSync, writeFileSync, unlinkSync, chmodSync } from 'node:fs';
9
+ import { resolve, join } from 'node:path';
10
+ import chalk from 'chalk';
11
+ import { execSync } from 'node:child_process';
12
+ const HUSKY_DIR = '.husky';
13
+ const PRE_COMMIT_HOOK = 'pre-commit';
14
+ const VV_HOOK_MARKER = '# Principal View checks';
15
+ /**
16
+ * Get the Principal View pre-commit hook content
17
+ */
18
+ function getVVHookContent() {
19
+ return `${VV_HOOK_MARKER}
20
+ echo "Running Principal View doctor check..."
21
+ npx @principal-ai/principal-studio-cli@latest doctor --errors-only || {
22
+ echo "❌ Principal View doctor check failed (errors found)"
23
+ echo " Run 'npx @principal-ai/principal-studio-cli doctor' to see details"
24
+ exit 1
25
+ }
26
+
27
+ echo "Running Principal View canvas validation..."
28
+ npx @principal-ai/principal-studio-cli@latest validate --quiet 2>/dev/null || {
29
+ if [ $? -ne 0 ]; then
30
+ echo "❌ Canvas validation failed"
31
+ echo " Run 'npx @principal-ai/principal-studio-cli validate' to see details"
32
+ exit 1
33
+ fi
34
+ }
35
+ `;
36
+ }
37
+ /**
38
+ * Find the repository root by looking for .git directory
39
+ */
40
+ function findRepoRoot(startPath) {
41
+ let current = resolve(startPath);
42
+ const root = resolve('/');
43
+ while (current !== root) {
44
+ if (existsSync(join(current, '.git'))) {
45
+ return current;
46
+ }
47
+ current = resolve(current, '..');
48
+ }
49
+ throw new Error('Not a git repository (or any parent up to mount point)');
50
+ }
51
+ /**
52
+ * Check if husky is installed
53
+ */
54
+ function isHuskyInstalled(repoPath) {
55
+ const huskyPath = join(repoPath, HUSKY_DIR);
56
+ return existsSync(huskyPath);
57
+ }
58
+ /**
59
+ * Initialize husky if not already installed
60
+ */
61
+ function initializeHusky(repoPath) {
62
+ if (!isHuskyInstalled(repoPath)) {
63
+ console.log('📦 Installing husky...');
64
+ try {
65
+ // Check if package.json exists
66
+ const packageJsonPath = join(repoPath, 'package.json');
67
+ if (!existsSync(packageJsonPath)) {
68
+ throw new Error('No package.json found. Please run npm init first.');
69
+ }
70
+ // Install husky
71
+ execSync('npm install --save-dev husky', {
72
+ cwd: repoPath,
73
+ stdio: 'inherit',
74
+ });
75
+ // Initialize husky
76
+ execSync('npx husky init', {
77
+ cwd: repoPath,
78
+ stdio: 'inherit',
79
+ });
80
+ // Remove the default placeholder if it exists
81
+ const hookPath = join(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
82
+ if (existsSync(hookPath)) {
83
+ const content = readFileSync(hookPath, 'utf8').trim();
84
+ if (content === 'npm test') {
85
+ // Remove the placeholder file - we'll create our own when --add is used
86
+ unlinkSync(hookPath);
87
+ console.log('ℹ️ Removed default husky placeholder hook');
88
+ }
89
+ }
90
+ console.log('✅ Husky installed and initialized');
91
+ }
92
+ catch (error) {
93
+ throw new Error(`Failed to initialize husky: ${error instanceof Error ? error.message : String(error)}`);
94
+ }
95
+ }
96
+ }
97
+ /**
98
+ * Check if pre-commit hook has PV validation
99
+ */
100
+ function hasVVHook(repoPath) {
101
+ const hookPath = join(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
102
+ if (!existsSync(hookPath)) {
103
+ return false;
104
+ }
105
+ const content = readFileSync(hookPath, 'utf8');
106
+ return content.includes(VV_HOOK_MARKER);
107
+ }
108
+ /**
109
+ * Add PV validation to pre-commit hook
110
+ */
111
+ function addVVHook(repoPath) {
112
+ const hookPath = join(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
113
+ const vvContent = getVVHookContent();
114
+ if (existsSync(hookPath)) {
115
+ // Append to existing hook
116
+ const existingContent = readFileSync(hookPath, 'utf8');
117
+ // Check if already has PV hook
118
+ if (existingContent.includes(VV_HOOK_MARKER)) {
119
+ return;
120
+ }
121
+ // Remove default husky placeholder if it's the only content
122
+ const trimmedContent = existingContent.trim();
123
+ if (trimmedContent === 'npm test') {
124
+ // Replace the placeholder entirely
125
+ writeFileSync(hookPath, vvContent, 'utf8');
126
+ console.log('ℹ️ Replaced default husky placeholder with Principal View checks');
127
+ }
128
+ else {
129
+ // Add PV hook at the end
130
+ const updatedContent = existingContent.trimEnd() + '\n\n' + vvContent;
131
+ writeFileSync(hookPath, updatedContent, 'utf8');
132
+ }
133
+ }
134
+ else {
135
+ // Create new hook file
136
+ writeFileSync(hookPath, vvContent, 'utf8');
137
+ // Make it executable
138
+ chmodSync(hookPath, 0o755);
139
+ }
140
+ }
141
+ /**
142
+ * Remove PV validation from pre-commit hook
143
+ */
144
+ function removeVVHook(repoPath) {
145
+ const hookPath = join(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
146
+ if (!existsSync(hookPath)) {
147
+ return;
148
+ }
149
+ const content = readFileSync(hookPath, 'utf8');
150
+ if (!content.includes(VV_HOOK_MARKER)) {
151
+ return;
152
+ }
153
+ // Split content by lines and find the PV section
154
+ const lines = content.split('\n');
155
+ const startIndex = lines.findIndex((line) => line.includes(VV_HOOK_MARKER));
156
+ if (startIndex === -1) {
157
+ return;
158
+ }
159
+ // Find the end of the PV section
160
+ let endIndex = lines.length - 1;
161
+ let inVVBlock = true;
162
+ let i = startIndex + 1;
163
+ while (i < lines.length && inVVBlock) {
164
+ const line = lines[i];
165
+ // Check if this line is part of the PV block
166
+ if (line &&
167
+ (line.includes('@principal-ai/principal-studio-cli ') ||
168
+ line.includes('Principal View') ||
169
+ line.includes('echo "Running Visual') ||
170
+ (line.includes('exit 1') && i > startIndex && i < startIndex + 15) ||
171
+ (line === '}' && i > startIndex && i < startIndex + 15) ||
172
+ (line.trim() === '' && i === startIndex + 1))) {
173
+ endIndex = i;
174
+ i++;
175
+ }
176
+ else if (line && line.trim() === '' && i < startIndex + 15) {
177
+ // Empty line might be part of our block
178
+ endIndex = i;
179
+ i++;
180
+ }
181
+ else {
182
+ // We've reached content that's not part of our block
183
+ inVVBlock = false;
184
+ }
185
+ }
186
+ // Remove the section (inclusive)
187
+ lines.splice(startIndex, endIndex - startIndex + 1);
188
+ // Clean up extra blank lines
189
+ let result = lines.join('\n');
190
+ result = result.replace(/\n{3,}/g, '\n\n').trim();
191
+ if (result) {
192
+ writeFileSync(hookPath, result + '\n', 'utf8');
193
+ }
194
+ else {
195
+ // If hook is now empty, remove it
196
+ unlinkSync(hookPath);
197
+ }
198
+ }
199
+ export function createHooksCommand() {
200
+ const command = new Command('hooks');
201
+ command
202
+ .description('Manage husky pre-commit hooks for Principal View')
203
+ .option('-p, --path <path>', 'Repository path (defaults to current directory)')
204
+ .option('--add', 'Add Principal View checks to pre-commit hook')
205
+ .option('--remove', 'Remove Principal View checks from pre-commit hook')
206
+ .option('--check', 'Check if Principal View checks exist in pre-commit hook')
207
+ .option('--init', 'Initialize husky if not already installed')
208
+ .action((options) => {
209
+ try {
210
+ const repoPath = findRepoRoot(options.path || process.cwd());
211
+ // Check if it's a git repository
212
+ if (!existsSync(join(repoPath, '.git'))) {
213
+ console.error(chalk.red('❌ Not a git repository'));
214
+ process.exit(1);
215
+ }
216
+ // Handle init option
217
+ if (options.init) {
218
+ initializeHusky(repoPath);
219
+ return;
220
+ }
221
+ // Check if husky is installed
222
+ if (!isHuskyInstalled(repoPath)) {
223
+ if (options.check) {
224
+ console.log(chalk.red('❌ Husky is not installed'));
225
+ console.log(' Run "npx @principal-ai/principal-studio-cli hooks --init" to install husky');
226
+ process.exit(1);
227
+ }
228
+ else if (options.add) {
229
+ console.log(chalk.red('❌ Husky is not installed'));
230
+ console.log(' Run "npx @principal-ai/principal-studio-cli hooks --init" first to install husky');
231
+ process.exit(1);
232
+ }
233
+ else if (options.remove) {
234
+ console.log('ℹ️ Husky is not installed');
235
+ return;
236
+ }
237
+ else {
238
+ console.log(chalk.red('❌ Husky is not installed in this repository'));
239
+ console.log('\nTo install husky and set up Principal View hooks:');
240
+ console.log(' npx @principal-ai/principal-studio-cli hooks --init --add');
241
+ process.exit(1);
242
+ }
243
+ }
244
+ const hasHook = hasVVHook(repoPath);
245
+ if (options.check) {
246
+ if (hasHook) {
247
+ console.log(chalk.green('✅ Principal View checks found in pre-commit hook'));
248
+ }
249
+ else {
250
+ console.log(chalk.red('❌ No Principal View checks in pre-commit hook'));
251
+ process.exit(1);
252
+ }
253
+ }
254
+ else if (options.add) {
255
+ if (hasHook) {
256
+ console.log('ℹ️ Principal View checks already exist in pre-commit hook');
257
+ }
258
+ else {
259
+ addVVHook(repoPath);
260
+ console.log(chalk.green('✅ Added Principal View checks to pre-commit hook'));
261
+ console.log('\nPre-commit hook will now:');
262
+ console.log(' • Run npx @principal-ai/principal-studio-cli doctor to check for stale configurations');
263
+ console.log(' • Validate all .canvas files');
264
+ }
265
+ }
266
+ else if (options.remove) {
267
+ if (!hasHook) {
268
+ console.log('ℹ️ No Principal View checks found in pre-commit hook');
269
+ }
270
+ else {
271
+ removeVVHook(repoPath);
272
+ console.log(chalk.green('✅ Removed Principal View checks from pre-commit hook'));
273
+ }
274
+ }
275
+ else {
276
+ // Default action: show status
277
+ console.log(chalk.bold('\nPrincipal View Hooks Status\n'));
278
+ console.log(`Repository: ${repoPath}`);
279
+ console.log(`Husky: ${chalk.green('installed')}`);
280
+ console.log(`PV Hooks: ${hasHook ? chalk.green('configured') : chalk.yellow('not configured')}`);
281
+ if (hasHook) {
282
+ console.log('\nUse --remove to remove or --check to verify');
283
+ }
284
+ else {
285
+ console.log('\nUse --add to add or --check to verify');
286
+ }
287
+ }
288
+ }
289
+ catch (error) {
290
+ console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
291
+ process.exit(1);
292
+ }
293
+ });
294
+ return command;
295
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Inbox command — fetch your trail inbox state from the Principal ADE backend.
3
+ *
4
+ * Resolves a GitHub token locally (gh CLI → git credential helper) and calls
5
+ * `GET /api/trails/inbox` with `Authorization: Bearer <token>`. The token is
6
+ * never echoed to argv, env, stdout, or stderr. The response carries a
7
+ * server-derived `notification` per row ({ dot, unread, noteCount,
8
+ * newNoteCount }) plus a top-level `unreadCount`, so an agent can see which
9
+ * shared trails need attention and how many notes are new since last open.
10
+ */
11
+ import { Command } from 'commander';
12
+ export declare function createInboxCommand(): Command;
13
+ //# sourceMappingURL=inbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/commands/inbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4MpC,wBAAgB,kBAAkB,IAAI,OAAO,CAW5C"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Inbox command — fetch your trail inbox state from the Principal ADE backend.
3
+ *
4
+ * Resolves a GitHub token locally (gh CLI → git credential helper) and calls
5
+ * `GET /api/trails/inbox` with `Authorization: Bearer <token>`. The token is
6
+ * never echoed to argv, env, stdout, or stderr. The response carries a
7
+ * server-derived `notification` per row ({ dot, unread, noteCount,
8
+ * newNoteCount }) plus a top-level `unreadCount`, so an agent can see which
9
+ * shared trails need attention and how many notes are new since last open.
10
+ */
11
+ import { Command } from 'commander';
12
+ import { spawnSync } from 'node:child_process';
13
+ import chalk from 'chalk';
14
+ const BASE_URL = 'https://app.principal-ade.com';
15
+ function resolveTokenViaGh() {
16
+ const result = spawnSync('gh', ['auth', 'token'], {
17
+ encoding: 'utf8',
18
+ stdio: ['ignore', 'pipe', 'ignore'],
19
+ });
20
+ if (result.status === 0 && result.stdout) {
21
+ const token = result.stdout.trim();
22
+ if (token)
23
+ return token;
24
+ }
25
+ return null;
26
+ }
27
+ function resolveTokenViaGitCredential() {
28
+ const result = spawnSync('git', ['credential', 'fill'], {
29
+ encoding: 'utf8',
30
+ input: 'protocol=https\nhost=github.com\n\n',
31
+ stdio: ['pipe', 'pipe', 'ignore'],
32
+ });
33
+ if (result.status !== 0 || !result.stdout)
34
+ return null;
35
+ for (const line of result.stdout.split('\n')) {
36
+ if (line.startsWith('password=')) {
37
+ const token = line.slice('password='.length).trim();
38
+ if (token)
39
+ return token;
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ function resolveToken() {
45
+ return resolveTokenViaGh() ?? resolveTokenViaGitCredential();
46
+ }
47
+ function exitWithTokenError() {
48
+ process.stderr.write('Could not resolve a GitHub token. Run `gh auth login`, or configure a git credential helper for github.com.\n');
49
+ process.exit(2);
50
+ }
51
+ /** Compact "3d ago" / "5m ago" relative time; falls back to the raw value. */
52
+ function timeAgo(iso) {
53
+ const then = Date.parse(iso);
54
+ if (Number.isNaN(then))
55
+ return iso;
56
+ const seconds = Math.max(0, Math.round((Date.now() - then) / 1000));
57
+ const units = [
58
+ [60, 's'],
59
+ [60, 'm'],
60
+ [24, 'h'],
61
+ [7, 'd'],
62
+ [4.345, 'w'],
63
+ [12, 'mo'],
64
+ [Number.POSITIVE_INFINITY, 'y'],
65
+ ];
66
+ let value = seconds;
67
+ let unit = 's';
68
+ for (const [size, label] of units) {
69
+ if (value < size) {
70
+ unit = label;
71
+ break;
72
+ }
73
+ value = Math.floor(value / size);
74
+ unit = label;
75
+ }
76
+ return `${value}${unit} ago`;
77
+ }
78
+ /** One-line note status, e.g. "2 notes (1 new)" or "no notes". */
79
+ function formatNotes(notif, fallbackCount) {
80
+ const total = notif?.noteCount ?? fallbackCount;
81
+ const fresh = notif?.newNoteCount ?? 0;
82
+ if (total === 0)
83
+ return chalk.dim('no notes');
84
+ const base = `${total} ${total === 1 ? 'note' : 'notes'}`;
85
+ if (fresh > 0)
86
+ return `${base} ${chalk.cyan(`(${fresh} new)`)}`;
87
+ return chalk.dim(base);
88
+ }
89
+ function renderHuman(data, unreadOnly) {
90
+ const { entries, unreadCount } = data;
91
+ const heading = unreadOnly
92
+ ? `Inbox — ${entries.length} needing attention`
93
+ : `Inbox — ${entries.length} ${entries.length === 1 ? 'trail' : 'trails'}, ${unreadCount} unread`;
94
+ console.log(chalk.bold(`\n${heading}\n`));
95
+ if (entries.length === 0) {
96
+ console.log(chalk.dim(' Nothing here.\n'));
97
+ return;
98
+ }
99
+ for (const entry of entries) {
100
+ const notif = entry.notification;
101
+ const dot = notif?.dot ?? entry.readAt === null;
102
+ const title = entry.snapshot?.title || `${entry.owner}/${entry.repo}`;
103
+ const marker = dot ? chalk.hex('#f59e0b')('●') : chalk.dim('·');
104
+ const titleText = dot ? chalk.bold(title) : title;
105
+ console.log(` ${marker} ${titleText}`);
106
+ const opened = entry.readAt === null ? chalk.yellow('unopened') : chalk.dim('opened');
107
+ const meta = [
108
+ chalk.dim(`trail ${entry.trailId}`),
109
+ `from @${entry.sender.githubLogin}`,
110
+ formatNotes(notif, entry.snapshot?.noteCount ?? 0),
111
+ chalk.dim(`sent ${timeAgo(entry.sentAt)}`),
112
+ opened,
113
+ ].join(chalk.dim(' · '));
114
+ console.log(` ${meta}`);
115
+ console.log(chalk.dim(` ${entry.owner}/${entry.repo}`));
116
+ if (entry.comment)
117
+ console.log(chalk.dim(` “${entry.comment}”`));
118
+ console.log('');
119
+ }
120
+ }
121
+ async function fetchInbox(options) {
122
+ const token = resolveToken();
123
+ if (!token)
124
+ exitWithTokenError();
125
+ const params = new URLSearchParams();
126
+ if (options.unread)
127
+ params.set('unreadOnly', 'true');
128
+ if (options.limit)
129
+ params.set('limit', options.limit);
130
+ const query = params.toString();
131
+ const url = `${BASE_URL}/api/trails/inbox${query ? `?${query}` : ''}`;
132
+ let response;
133
+ try {
134
+ response = await fetch(url, {
135
+ headers: {
136
+ Authorization: `Bearer ${token}`,
137
+ Accept: 'application/json',
138
+ },
139
+ });
140
+ }
141
+ catch (error) {
142
+ process.stderr.write(`Failed to reach ${BASE_URL}: ${error.message}\n`);
143
+ process.exit(1);
144
+ }
145
+ if (response.status === 401) {
146
+ process.stderr.write('Unauthorized (401). Your GitHub token may be expired — run `gh auth login` and retry.\n');
147
+ process.exit(1);
148
+ }
149
+ if (!response.ok) {
150
+ process.stderr.write(`Request failed: HTTP ${response.status} ${response.statusText}\n`);
151
+ process.exit(1);
152
+ }
153
+ const body = await response.text();
154
+ let data;
155
+ try {
156
+ data = JSON.parse(body);
157
+ }
158
+ catch {
159
+ process.stderr.write('Unexpected non-JSON response from the inbox endpoint.\n');
160
+ process.exit(1);
161
+ }
162
+ if (options.json) {
163
+ console.log(JSON.stringify(data, null, 2));
164
+ return;
165
+ }
166
+ renderHuman(data, Boolean(options.unread));
167
+ }
168
+ export function createInboxCommand() {
169
+ const command = new Command('inbox');
170
+ command
171
+ .description('Show your trail inbox: which shared trails need attention and how many notes are new')
172
+ .option('--json', 'Output the raw inbox response as JSON (for agents)')
173
+ .option('--unread', 'Only show rows needing attention (unopened or with new notes)')
174
+ .option('--limit <n>', 'Maximum number of rows to fetch')
175
+ .action(async (options) => {
176
+ await fetchInbox(options);
177
+ });
178
+ return command;
179
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Init command - Initialize a .principal-views folder with template files and linting setup
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function createInitCommand(): Command;
6
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwDpC,wBAAgB,iBAAiB,IAAI,OAAO,CA+L3C"}