@skillrecordings/cli 0.1.0 → 0.2.0

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 (136) hide show
  1. package/bin/skill.mjs +27 -0
  2. package/dist/chunk-2NCCVTEE.js +22342 -0
  3. package/dist/chunk-2NCCVTEE.js.map +1 -0
  4. package/dist/chunk-3E3GYSZR.js +7071 -0
  5. package/dist/chunk-3E3GYSZR.js.map +1 -0
  6. package/dist/chunk-F4EM72IH.js +86 -0
  7. package/dist/chunk-F4EM72IH.js.map +1 -0
  8. package/dist/chunk-FGP7KUQW.js +432 -0
  9. package/dist/chunk-FGP7KUQW.js.map +1 -0
  10. package/dist/chunk-H3D6VCME.js +55 -0
  11. package/dist/chunk-H3D6VCME.js.map +1 -0
  12. package/dist/chunk-HK3PEWFD.js +208 -0
  13. package/dist/chunk-HK3PEWFD.js.map +1 -0
  14. package/dist/chunk-KEV3QKXP.js +4495 -0
  15. package/dist/chunk-KEV3QKXP.js.map +1 -0
  16. package/dist/chunk-MG37YDAK.js +882 -0
  17. package/dist/chunk-MG37YDAK.js.map +1 -0
  18. package/dist/chunk-MLNDSBZ4.js +482 -0
  19. package/dist/chunk-MLNDSBZ4.js.map +1 -0
  20. package/dist/chunk-N2WIV2JV.js +22 -0
  21. package/dist/chunk-N2WIV2JV.js.map +1 -0
  22. package/dist/chunk-PWWRCN5W.js +2067 -0
  23. package/dist/chunk-PWWRCN5W.js.map +1 -0
  24. package/dist/chunk-SKHBM3XP.js +7746 -0
  25. package/dist/chunk-SKHBM3XP.js.map +1 -0
  26. package/dist/chunk-WFANXVQG.js +64 -0
  27. package/dist/chunk-WFANXVQG.js.map +1 -0
  28. package/dist/chunk-WYKL32C3.js +275 -0
  29. package/dist/chunk-WYKL32C3.js.map +1 -0
  30. package/dist/chunk-ZNF7XD2S.js +134 -0
  31. package/dist/chunk-ZNF7XD2S.js.map +1 -0
  32. package/dist/config-AUAIYDSI.js +20 -0
  33. package/dist/config-AUAIYDSI.js.map +1 -0
  34. package/dist/fileFromPath-XN7LXIBI.js +134 -0
  35. package/dist/fileFromPath-XN7LXIBI.js.map +1 -0
  36. package/dist/getMachineId-bsd-KW2E7VK3.js +42 -0
  37. package/dist/getMachineId-bsd-KW2E7VK3.js.map +1 -0
  38. package/dist/getMachineId-darwin-ROXJUJX5.js +42 -0
  39. package/dist/getMachineId-darwin-ROXJUJX5.js.map +1 -0
  40. package/dist/getMachineId-linux-KVZEHQSU.js +34 -0
  41. package/dist/getMachineId-linux-KVZEHQSU.js.map +1 -0
  42. package/dist/getMachineId-unsupported-PPRILPPA.js +25 -0
  43. package/dist/getMachineId-unsupported-PPRILPPA.js.map +1 -0
  44. package/dist/getMachineId-win-IIF36LEJ.js +44 -0
  45. package/dist/getMachineId-win-IIF36LEJ.js.map +1 -0
  46. package/dist/index.js +112703 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/lib-R6DEEJCP.js +7623 -0
  49. package/dist/lib-R6DEEJCP.js.map +1 -0
  50. package/dist/pipeline-IAVVAKTU.js +120 -0
  51. package/dist/pipeline-IAVVAKTU.js.map +1 -0
  52. package/dist/query-NTP5NVXN.js +25 -0
  53. package/dist/query-NTP5NVXN.js.map +1 -0
  54. package/dist/routing-BAEPFB7V.js +390 -0
  55. package/dist/routing-BAEPFB7V.js.map +1 -0
  56. package/dist/stripe-lookup-charge-EPRUMZDL.js +56 -0
  57. package/dist/stripe-lookup-charge-EPRUMZDL.js.map +1 -0
  58. package/dist/stripe-payment-history-SJPKA63N.js +67 -0
  59. package/dist/stripe-payment-history-SJPKA63N.js.map +1 -0
  60. package/dist/stripe-subscription-status-L4Z65GB3.js +58 -0
  61. package/dist/stripe-subscription-status-L4Z65GB3.js.map +1 -0
  62. package/dist/stripe-verify-refund-FZDKCIUQ.js +54 -0
  63. package/dist/stripe-verify-refund-FZDKCIUQ.js.map +1 -0
  64. package/dist/support-memory-WSG7SDKG.js +10 -0
  65. package/dist/support-memory-WSG7SDKG.js.map +1 -0
  66. package/package.json +10 -7
  67. package/.env.encrypted +0 -0
  68. package/CHANGELOG.md +0 -35
  69. package/data/tt-archive-dataset.json +0 -1
  70. package/data/validate-test-dataset.json +0 -97
  71. package/docs/CLI-AUTH.md +0 -504
  72. package/preload.ts +0 -18
  73. package/src/__tests__/init.test.ts +0 -74
  74. package/src/alignment-test.ts +0 -64
  75. package/src/check-apps.ts +0 -16
  76. package/src/commands/auth/decrypt.ts +0 -123
  77. package/src/commands/auth/encrypt.ts +0 -81
  78. package/src/commands/auth/index.ts +0 -50
  79. package/src/commands/auth/keygen.ts +0 -41
  80. package/src/commands/auth/status.ts +0 -164
  81. package/src/commands/axiom/forensic.ts +0 -868
  82. package/src/commands/axiom/index.ts +0 -697
  83. package/src/commands/build-dataset.ts +0 -311
  84. package/src/commands/db-status.ts +0 -47
  85. package/src/commands/deploys.ts +0 -219
  86. package/src/commands/eval-local/compare.ts +0 -171
  87. package/src/commands/eval-local/health.ts +0 -212
  88. package/src/commands/eval-local/index.ts +0 -76
  89. package/src/commands/eval-local/real-tools.ts +0 -416
  90. package/src/commands/eval-local/run.ts +0 -1168
  91. package/src/commands/eval-local/score-production.ts +0 -256
  92. package/src/commands/eval-local/seed.ts +0 -276
  93. package/src/commands/eval-pipeline/index.ts +0 -53
  94. package/src/commands/eval-pipeline/real-tools.ts +0 -492
  95. package/src/commands/eval-pipeline/run.ts +0 -1316
  96. package/src/commands/eval-pipeline/seed.ts +0 -395
  97. package/src/commands/eval-prompt.ts +0 -496
  98. package/src/commands/eval.test.ts +0 -253
  99. package/src/commands/eval.ts +0 -108
  100. package/src/commands/faq-classify.ts +0 -460
  101. package/src/commands/faq-cluster.ts +0 -135
  102. package/src/commands/faq-extract.ts +0 -249
  103. package/src/commands/faq-mine.ts +0 -432
  104. package/src/commands/faq-review.ts +0 -426
  105. package/src/commands/front/index.ts +0 -351
  106. package/src/commands/front/pull-conversations.ts +0 -275
  107. package/src/commands/front/tags.ts +0 -825
  108. package/src/commands/front-cache.ts +0 -1277
  109. package/src/commands/front-stats.ts +0 -75
  110. package/src/commands/health.test.ts +0 -82
  111. package/src/commands/health.ts +0 -362
  112. package/src/commands/init.test.ts +0 -89
  113. package/src/commands/init.ts +0 -106
  114. package/src/commands/inngest/client.ts +0 -294
  115. package/src/commands/inngest/events.ts +0 -296
  116. package/src/commands/inngest/investigate.ts +0 -382
  117. package/src/commands/inngest/runs.ts +0 -149
  118. package/src/commands/inngest/signal.ts +0 -143
  119. package/src/commands/kb-sync.ts +0 -498
  120. package/src/commands/memory/find.ts +0 -135
  121. package/src/commands/memory/get.ts +0 -87
  122. package/src/commands/memory/index.ts +0 -97
  123. package/src/commands/memory/stats.ts +0 -163
  124. package/src/commands/memory/store.ts +0 -49
  125. package/src/commands/memory/vote.ts +0 -159
  126. package/src/commands/pipeline.ts +0 -127
  127. package/src/commands/responses.ts +0 -856
  128. package/src/commands/tools.ts +0 -293
  129. package/src/commands/wizard.ts +0 -319
  130. package/src/index.ts +0 -172
  131. package/src/lib/crypto.ts +0 -56
  132. package/src/lib/env-loader.ts +0 -206
  133. package/src/lib/onepassword.ts +0 -137
  134. package/src/test-agent-local.ts +0 -115
  135. package/tsconfig.json +0 -11
  136. package/vitest.config.ts +0 -10
@@ -1,426 +0,0 @@
1
- /**
2
- * FAQ Review CLI Command
3
- *
4
- * Interactive CLI for human curation of FAQ candidates.
5
- * Approve, edit, reject, or skip candidates before publishing to KB.
6
- *
7
- * Usage:
8
- * skill faq-review --app total-typescript
9
- * skill faq-review --app epic-react --stats
10
- */
11
-
12
- import { spawnSync } from 'node:child_process'
13
- import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
14
- import { tmpdir } from 'node:os'
15
- import { join } from 'node:path'
16
- import { confirm, select } from '@inquirer/prompts'
17
- import {
18
- type StoredFaqCandidate,
19
- approveCandidate,
20
- getPendingCandidates,
21
- getQueueStats,
22
- rejectCandidate,
23
- } from '@skillrecordings/core/faq/review'
24
- import type { Command } from 'commander'
25
-
26
- /**
27
- * Color codes for terminal output
28
- */
29
- const COLORS = {
30
- reset: '\x1b[0m',
31
- green: '\x1b[32m',
32
- yellow: '\x1b[33m',
33
- red: '\x1b[31m',
34
- blue: '\x1b[34m',
35
- cyan: '\x1b[36m',
36
- dim: '\x1b[2m',
37
- bold: '\x1b[1m',
38
- } as const
39
-
40
- /**
41
- * Word wrap text to specified width
42
- */
43
- function wordWrap(text: string, width: number): string {
44
- const words = text.split(' ')
45
- const lines: string[] = []
46
- let currentLine = ''
47
-
48
- for (const word of words) {
49
- if (currentLine.length + word.length + 1 <= width) {
50
- currentLine += (currentLine ? ' ' : '') + word
51
- } else {
52
- if (currentLine) lines.push(currentLine)
53
- currentLine = word
54
- }
55
- }
56
-
57
- if (currentLine) lines.push(currentLine)
58
- return lines.join('\n')
59
- }
60
-
61
- /**
62
- * Display a single FAQ candidate
63
- */
64
- function displayCandidate(
65
- candidate: StoredFaqCandidate,
66
- index: number,
67
- total: number
68
- ): void {
69
- console.log('\n' + '═'.repeat(70))
70
- console.log(
71
- `${COLORS.bold}FAQ Candidate ${index + 1} of ${total}${COLORS.reset}`
72
- )
73
- console.log('═'.repeat(70))
74
-
75
- // Metadata row
76
- const confPct = (candidate.confidence * 100).toFixed(0)
77
- const unchangedPct = (candidate.unchangedRate * 100).toFixed(0)
78
- console.log(
79
- `${COLORS.dim}Confidence: ${confPct}% | Cluster: ${candidate.clusterSize} convos | Unchanged: ${unchangedPct}%${COLORS.reset}`
80
- )
81
-
82
- if (candidate.suggestedCategory) {
83
- console.log(
84
- `${COLORS.dim}Category: ${candidate.suggestedCategory}${COLORS.reset}`
85
- )
86
- }
87
-
88
- if (candidate.tags.length > 0) {
89
- console.log(
90
- `${COLORS.dim}Tags: ${candidate.tags.slice(0, 5).join(', ')}${COLORS.reset}`
91
- )
92
- }
93
-
94
- // Question
95
- console.log(`\n${COLORS.bold}${COLORS.cyan}Question:${COLORS.reset}`)
96
- console.log(wordWrap(candidate.question, 68))
97
-
98
- // Answer
99
- console.log(`\n${COLORS.bold}${COLORS.green}Answer:${COLORS.reset}`)
100
- console.log(wordWrap(candidate.answer, 68))
101
-
102
- console.log('\n' + '-'.repeat(70))
103
- }
104
-
105
- /**
106
- * Get editor command
107
- */
108
- function getEditor(): string {
109
- return process.env.EDITOR || process.env.VISUAL || 'nano'
110
- }
111
-
112
- /**
113
- * Open content in editor and return edited content
114
- */
115
- function editInEditor(
116
- question: string,
117
- answer: string
118
- ): { question: string; answer: string } | null {
119
- const editor = getEditor()
120
- const tmpFile = join(tmpdir(), `faq-edit-${Date.now()}.md`)
121
-
122
- // Write content to temp file
123
- const content = `# FAQ Edit
124
-
125
- ## Question
126
- ${question}
127
-
128
- ## Answer
129
- ${answer}
130
-
131
- <!--
132
- Edit the question and answer above.
133
- Save and close the editor when done.
134
- The sections are separated by "## Question" and "## Answer" headers.
135
- -->
136
- `
137
-
138
- writeFileSync(tmpFile, content, 'utf-8')
139
-
140
- try {
141
- // Open editor (blocking)
142
- const result = spawnSync(editor, [tmpFile], {
143
- stdio: 'inherit',
144
- shell: true,
145
- })
146
-
147
- if (result.status !== 0) {
148
- console.log(`${COLORS.red}Editor exited with error${COLORS.reset}`)
149
- return null
150
- }
151
-
152
- // Read edited content
153
- const edited = readFileSync(tmpFile, 'utf-8')
154
-
155
- // Parse sections
156
- const questionMatch = edited.match(
157
- /## Question\s*\n([\s\S]*?)(?=\n## Answer|$)/
158
- )
159
- const answerMatch = edited.match(/## Answer\s*\n([\s\S]*?)(?=\n<!--|$)/)
160
-
161
- const editedQuestion = questionMatch?.[1]?.trim()
162
- const editedAnswer = answerMatch?.[1]?.trim()
163
-
164
- if (!editedQuestion || !editedAnswer) {
165
- console.log(
166
- `${COLORS.red}Could not parse edited content. Please keep the ## headers.${COLORS.reset}`
167
- )
168
- return null
169
- }
170
-
171
- return {
172
- question: editedQuestion,
173
- answer: editedAnswer,
174
- }
175
- } finally {
176
- // Clean up temp file
177
- if (existsSync(tmpFile)) {
178
- unlinkSync(tmpFile)
179
- }
180
- }
181
- }
182
-
183
- /**
184
- * Run interactive review session
185
- */
186
- async function runReviewSession(options: {
187
- app: string
188
- }): Promise<void> {
189
- console.log(`\n${COLORS.bold}📋 FAQ Review Session${COLORS.reset}`)
190
- console.log(`App: ${options.app}`)
191
- console.log('Loading candidates...\n')
192
-
193
- // Load pending candidates
194
- const candidates = await getPendingCandidates(options.app, 100)
195
-
196
- if (candidates.length === 0) {
197
- console.log(
198
- `${COLORS.yellow}No pending FAQ candidates found.${COLORS.reset}`
199
- )
200
- console.log(
201
- `Run ${COLORS.cyan}skill faq-mine --app ${options.app} --since 30d${COLORS.reset} to generate candidates.`
202
- )
203
- return
204
- }
205
-
206
- console.log(
207
- `Found ${COLORS.bold}${candidates.length}${COLORS.reset} pending candidates.`
208
- )
209
-
210
- // Session stats
211
- let approved = 0
212
- let rejected = 0
213
- let skipped = 0
214
- let edited = 0
215
-
216
- // Review loop
217
- for (let i = 0; i < candidates.length; i++) {
218
- const candidate = candidates[i]!
219
-
220
- displayCandidate(candidate, i, candidates.length)
221
-
222
- // Get action
223
- const action = await select({
224
- message: 'Action:',
225
- choices: [
226
- {
227
- name: `${COLORS.green}[A]pprove${COLORS.reset} - Publish to KB`,
228
- value: 'approve',
229
- },
230
- {
231
- name: `${COLORS.blue}[E]dit${COLORS.reset} - Edit then publish`,
232
- value: 'edit',
233
- },
234
- {
235
- name: `${COLORS.red}[R]eject${COLORS.reset} - Won't resurface`,
236
- value: 'reject',
237
- },
238
- {
239
- name: `${COLORS.dim}[S]kip${COLORS.reset} - Review later`,
240
- value: 'skip',
241
- },
242
- {
243
- name: `${COLORS.dim}[Q]uit${COLORS.reset} - End session`,
244
- value: 'quit',
245
- },
246
- ],
247
- })
248
-
249
- if (action === 'quit') {
250
- break
251
- }
252
-
253
- if (action === 'skip') {
254
- skipped++
255
- console.log(`${COLORS.dim}⏭ Skipped${COLORS.reset}`)
256
- continue
257
- }
258
-
259
- if (action === 'reject') {
260
- const result = await rejectCandidate(
261
- candidate.id,
262
- 'Rejected via CLI review'
263
- )
264
- if (result.success) {
265
- rejected++
266
- console.log(`${COLORS.red}✗ Rejected - won't resurface${COLORS.reset}`)
267
- } else {
268
- console.log(
269
- `${COLORS.red}✗ Failed to reject: ${result.error}${COLORS.reset}`
270
- )
271
- }
272
- continue
273
- }
274
-
275
- // approve or edit
276
- let finalQuestion = candidate.question
277
- let finalAnswer = candidate.answer
278
- let wasEdited = false
279
-
280
- if (action === 'edit') {
281
- console.log(`\nOpening ${getEditor()}...`)
282
- const editResult = editInEditor(candidate.question, candidate.answer)
283
-
284
- if (!editResult) {
285
- console.log('Edit cancelled. Skipping candidate.')
286
- skipped++
287
- continue
288
- }
289
-
290
- finalQuestion = editResult.question
291
- finalAnswer = editResult.answer
292
- wasEdited =
293
- finalQuestion !== candidate.question || finalAnswer !== candidate.answer
294
-
295
- if (wasEdited) {
296
- console.log(`\n${COLORS.yellow}Content was edited.${COLORS.reset}`)
297
- console.log(`\n${COLORS.bold}New Question:${COLORS.reset}`)
298
- console.log(wordWrap(finalQuestion, 68))
299
- console.log(`\n${COLORS.bold}New Answer:${COLORS.reset}`)
300
- console.log(wordWrap(finalAnswer, 68))
301
-
302
- const confirmPublish = await confirm({
303
- message: 'Publish edited FAQ?',
304
- default: true,
305
- })
306
-
307
- if (!confirmPublish) {
308
- skipped++
309
- continue
310
- }
311
- }
312
- }
313
-
314
- // Publish (approve or edit)
315
- const result = await approveCandidate(candidate.id, {
316
- question: wasEdited ? finalQuestion : undefined,
317
- answer: wasEdited ? finalAnswer : undefined,
318
- editNotes: wasEdited ? 'Edited during CLI review' : undefined,
319
- })
320
-
321
- if (result.success) {
322
- approved++
323
- if (wasEdited) edited++
324
- console.log(
325
- `${COLORS.green}✓ Published as ${result.articleId}${COLORS.reset}`
326
- )
327
- } else {
328
- console.log(
329
- `${COLORS.red}✗ Failed to publish: ${result.error}${COLORS.reset}`
330
- )
331
- }
332
- }
333
-
334
- // Session summary
335
- console.log('\n' + '═'.repeat(70))
336
- console.log(`${COLORS.bold}📊 Session Summary${COLORS.reset}`)
337
- console.log('═'.repeat(70))
338
- console.log(
339
- `${COLORS.green}Approved: ${approved}${edited > 0 ? ` (${edited} edited)` : ''}${COLORS.reset}`
340
- )
341
- console.log(`${COLORS.red}Rejected: ${rejected}${COLORS.reset}`)
342
- console.log(`${COLORS.dim}Skipped: ${skipped}${COLORS.reset}`)
343
- console.log('')
344
- }
345
-
346
- /**
347
- * Display review statistics
348
- */
349
- async function showStats(appId: string, json: boolean): Promise<void> {
350
- const stats = await getQueueStats(appId)
351
-
352
- if (json) {
353
- console.log(JSON.stringify(stats, null, 2))
354
- return
355
- }
356
-
357
- console.log(
358
- `\n${COLORS.bold}📊 Review Queue Statistics for ${appId}${COLORS.reset}`
359
- )
360
- console.log('─'.repeat(40))
361
- console.log(`Pending: ${stats.pending}`)
362
- console.log(
363
- `${COLORS.green}Approved: ${stats.approved}${COLORS.reset}`
364
- )
365
- console.log(`${COLORS.red}Rejected: ${stats.rejected}${COLORS.reset}`)
366
- console.log(`Total: ${stats.total}`)
367
-
368
- if (stats.total > 0 && stats.approved + stats.rejected > 0) {
369
- const approvalRate = (
370
- (stats.approved / (stats.approved + stats.rejected)) *
371
- 100
372
- ).toFixed(1)
373
- console.log(`\nApproval rate: ${approvalRate}%`)
374
- }
375
-
376
- console.log('')
377
- }
378
-
379
- /**
380
- * Main command handler
381
- */
382
- async function faqReview(options: {
383
- app: string
384
- stats?: boolean
385
- json?: boolean
386
- }): Promise<void> {
387
- if (!options.app) {
388
- console.error('Error: --app is required')
389
- process.exit(1)
390
- }
391
-
392
- try {
393
- if (options.stats) {
394
- await showStats(options.app, options.json ?? false)
395
- } else {
396
- await runReviewSession({
397
- app: options.app,
398
- })
399
- }
400
- } catch (error) {
401
- if ((error as any)?.name === 'ExitPromptError') {
402
- // User pressed Ctrl+C
403
- console.log('\n\nReview session cancelled.')
404
- process.exit(0)
405
- }
406
-
407
- console.error(
408
- 'Error:',
409
- error instanceof Error ? error.message : String(error)
410
- )
411
- process.exit(1)
412
- }
413
- }
414
-
415
- /**
416
- * Register FAQ review commands with Commander
417
- */
418
- export function registerFaqReviewCommands(program: Command): void {
419
- program
420
- .command('faq-review')
421
- .description('Interactive review of FAQ candidates')
422
- .requiredOption('-a, --app <slug>', 'App slug to review (required)')
423
- .option('--stats', 'Show review statistics instead of interactive review')
424
- .option('--json', 'Output stats as JSON (use with --stats)')
425
- .action(faqReview)
426
- }