@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,498 +0,0 @@
1
- /**
2
- * KB Sync CLI Command
3
- *
4
- * Syncs FAQ sources to Upstash Vector + Redis knowledge base.
5
- * Supports single app sync, all apps sync, and stats viewing.
6
- */
7
-
8
- import { createHash } from 'node:crypto'
9
- import {
10
- type IngestResult,
11
- PRODUCT_SOURCES,
12
- ingest,
13
- listProductSources,
14
- } from '@skillrecordings/core/knowledge/ingest'
15
- import {
16
- type KnowledgeArticle,
17
- getKnowledgeNamespace,
18
- getKnowledgeRedisKey,
19
- } from '@skillrecordings/core/knowledge/types'
20
- import { getRedis } from '@skillrecordings/core/redis/client'
21
- import {
22
- getVectorIndex,
23
- upsertVector,
24
- } from '@skillrecordings/core/vector/client'
25
- import type { Command } from 'commander'
26
-
27
- /**
28
- * Hash content to enable idempotent updates
29
- */
30
- function hashContent(content: string): string {
31
- return createHash('sha256').update(content).digest('hex').slice(0, 16)
32
- }
33
-
34
- /**
35
- * Fetch content from a URL
36
- */
37
- async function fetchContent(url: string): Promise<string> {
38
- // Handle local file:// URLs
39
- if (url.startsWith('file://')) {
40
- const fs = await import('node:fs/promises')
41
- const filePath = url.replace('file://', '')
42
- return fs.readFile(filePath, 'utf-8')
43
- }
44
-
45
- const response = await fetch(url)
46
- if (!response.ok) {
47
- throw new Error(
48
- `Failed to fetch ${url}: ${response.status} ${response.statusText}`
49
- )
50
- }
51
- return response.text()
52
- }
53
-
54
- /**
55
- * Get stored hash for an article from Redis
56
- */
57
- async function getStoredHash(
58
- id: string,
59
- namespace: string
60
- ): Promise<string | null> {
61
- const redis = getRedis()
62
- const key = getKnowledgeRedisKey(id, namespace)
63
- const data = await redis.hget(key, 'content_hash')
64
- return data as string | null
65
- }
66
-
67
- /**
68
- * Store article in Redis with content hash
69
- */
70
- async function storeArticle(
71
- article: KnowledgeArticle,
72
- contentHash: string
73
- ): Promise<void> {
74
- const redis = getRedis()
75
- const namespace = getKnowledgeNamespace(article.appId)
76
- const key = getKnowledgeRedisKey(article.id, namespace)
77
-
78
- await redis.hset(key, {
79
- id: article.id,
80
- title: article.title,
81
- question: article.question,
82
- answer: article.answer,
83
- appId: article.appId,
84
- metadata: JSON.stringify(article.metadata),
85
- content_hash: contentHash,
86
- })
87
- }
88
-
89
- /**
90
- * Store article in vector index
91
- */
92
- async function storeVector(article: KnowledgeArticle): Promise<void> {
93
- const searchableText = `${article.title}\n\n${article.question}`
94
- await upsertVector({
95
- id: article.id,
96
- data: searchableText,
97
- metadata: {
98
- type: 'knowledge',
99
- appId: article.appId,
100
- category: article.metadata.category as any,
101
- source: article.metadata.source as any,
102
- trustScore: article.metadata.trust_score ?? 1.0,
103
- },
104
- })
105
- }
106
-
107
- /**
108
- * Sync result for a single app
109
- */
110
- interface SyncResult {
111
- appId: string
112
- total: number
113
- added: number
114
- updated: number
115
- unchanged: number
116
- errors: string[]
117
- }
118
-
119
- /**
120
- * Sync a single app's knowledge base
121
- */
122
- async function syncApp(appId: string, dryRun: boolean): Promise<SyncResult> {
123
- const result: SyncResult = {
124
- appId,
125
- total: 0,
126
- added: 0,
127
- updated: 0,
128
- unchanged: 0,
129
- errors: [],
130
- }
131
-
132
- const source = PRODUCT_SOURCES[appId]
133
- if (!source) {
134
- result.errors.push(`Unknown app: ${appId}`)
135
- return result
136
- }
137
-
138
- if (!source.enabled) {
139
- result.errors.push(`App ${appId} is not enabled for sync`)
140
- return result
141
- }
142
-
143
- if (!source.sourceUrls || source.sourceUrls.length === 0) {
144
- result.errors.push(`No source URLs configured for ${appId}`)
145
- return result
146
- }
147
-
148
- const namespace = getKnowledgeNamespace(appId)
149
-
150
- // Fetch content from all source URLs
151
- const allContent: string[] = []
152
- for (const url of source.sourceUrls) {
153
- try {
154
- const content = await fetchContent(url)
155
- allContent.push(content)
156
- } catch (error) {
157
- result.errors.push(
158
- `Failed to fetch ${url}: ${error instanceof Error ? error.message : String(error)}`
159
- )
160
- }
161
- }
162
-
163
- if (allContent.length === 0) {
164
- result.errors.push(`No content fetched for ${appId}`)
165
- return result
166
- }
167
-
168
- // Parse content based on format
169
- let ingestResult: IngestResult
170
- try {
171
- // For single URL, pass content directly; for multiple, pass as array
172
- const content =
173
- allContent.length === 1
174
- ? allContent[0]
175
- : allContent.map((c, i) => ({
176
- filePath: source.sourceUrls![i],
177
- content: c,
178
- }))
179
-
180
- ingestResult = await ingest({
181
- productId: appId,
182
- content: content as any,
183
- format: source.format,
184
- })
185
-
186
- if (ingestResult.errors.length > 0) {
187
- for (const error of ingestResult.errors) {
188
- result.errors.push(error.message)
189
- }
190
- }
191
- } catch (error) {
192
- result.errors.push(
193
- `Parse error: ${error instanceof Error ? error.message : String(error)}`
194
- )
195
- return result
196
- }
197
-
198
- result.total = ingestResult.articles.length
199
-
200
- // Process each article
201
- for (const article of ingestResult.articles) {
202
- const contentHash = hashContent(
203
- `${article.title}|${article.question}|${article.answer}`
204
- )
205
- const storedHash = await getStoredHash(article.id, namespace)
206
-
207
- if (storedHash === contentHash) {
208
- result.unchanged++
209
- continue
210
- }
211
-
212
- if (dryRun) {
213
- if (storedHash) {
214
- result.updated++
215
- } else {
216
- result.added++
217
- }
218
- continue
219
- }
220
-
221
- // Store in Redis and Vector
222
- try {
223
- await storeArticle(article, contentHash)
224
- await storeVector(article)
225
-
226
- if (storedHash) {
227
- result.updated++
228
- } else {
229
- result.added++
230
- }
231
- } catch (error) {
232
- result.errors.push(
233
- `Failed to store ${article.id}: ${error instanceof Error ? error.message : String(error)}`
234
- )
235
- }
236
- }
237
-
238
- return result
239
- }
240
-
241
- /**
242
- * Format duration in human-readable form
243
- */
244
- function formatDuration(ms: number): string {
245
- if (ms < 1000) return `${ms}ms`
246
- if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`
247
- return `${(ms / 60000).toFixed(1)}m`
248
- }
249
-
250
- /**
251
- * Sync knowledge base from FAQ sources
252
- */
253
- export async function sync(options: {
254
- app?: string
255
- all?: boolean
256
- dryRun?: boolean
257
- json?: boolean
258
- }): Promise<void> {
259
- const startTime = Date.now()
260
-
261
- try {
262
- // Determine which apps to sync
263
- let appsToSync: string[] = []
264
-
265
- if (options.all) {
266
- appsToSync = listProductSources()
267
- .filter((s) => s.enabled)
268
- .map((s) => s.appId)
269
- } else if (options.app) {
270
- appsToSync = [options.app]
271
- } else {
272
- if (options.json) {
273
- console.error(JSON.stringify({ error: 'Must specify --app or --all' }))
274
- } else {
275
- console.error('Error: Must specify --app <appId> or --all')
276
- }
277
- process.exit(1)
278
- }
279
-
280
- if (appsToSync.length === 0) {
281
- if (options.json) {
282
- console.error(JSON.stringify({ error: 'No apps enabled for sync' }))
283
- } else {
284
- console.error('No apps enabled for sync')
285
- }
286
- process.exit(1)
287
- }
288
-
289
- const results: SyncResult[] = []
290
-
291
- for (const appId of appsToSync) {
292
- if (!options.json) {
293
- console.log(
294
- `\n${options.dryRun ? '[DRY RUN] ' : ''}Syncing ${appId}...`
295
- )
296
- }
297
-
298
- const result = await syncApp(appId, options.dryRun ?? false)
299
- results.push(result)
300
-
301
- if (!options.json) {
302
- if (result.errors.length > 0) {
303
- console.log(` āš ļø Errors:`)
304
- for (const error of result.errors) {
305
- console.log(` - ${error}`)
306
- }
307
- }
308
- console.log(` šŸ“š Total: ${result.total}`)
309
- console.log(` āœ… Added: ${result.added}`)
310
- console.log(` šŸ”„ Updated: ${result.updated}`)
311
- console.log(` ā­ļø Unchanged: ${result.unchanged}`)
312
- }
313
- }
314
-
315
- const elapsed = Date.now() - startTime
316
-
317
- // Summary
318
- const summary = {
319
- dryRun: options.dryRun ?? false,
320
- duration: formatDuration(elapsed),
321
- apps: results.length,
322
- total: results.reduce((sum, r) => sum + r.total, 0),
323
- added: results.reduce((sum, r) => sum + r.added, 0),
324
- updated: results.reduce((sum, r) => sum + r.updated, 0),
325
- unchanged: results.reduce((sum, r) => sum + r.unchanged, 0),
326
- errors: results.reduce((sum, r) => sum + r.errors.length, 0),
327
- results,
328
- }
329
-
330
- if (options.json) {
331
- console.log(JSON.stringify(summary, null, 2))
332
- } else {
333
- console.log('\n' + '─'.repeat(50))
334
- console.log(
335
- `${options.dryRun ? '[DRY RUN] ' : ''}Sync complete in ${summary.duration}`
336
- )
337
- console.log(
338
- `Apps: ${summary.apps} | Total: ${summary.total} | Added: ${summary.added} | Updated: ${summary.updated} | Unchanged: ${summary.unchanged}`
339
- )
340
- if (summary.errors > 0) {
341
- console.log(`āš ļø ${summary.errors} errors occurred`)
342
- }
343
- }
344
- } catch (error) {
345
- if (options.json) {
346
- console.error(
347
- JSON.stringify({
348
- error: error instanceof Error ? error.message : 'Unknown error',
349
- })
350
- )
351
- } else {
352
- console.error(
353
- 'Error:',
354
- error instanceof Error ? error.message : 'Unknown error'
355
- )
356
- }
357
- process.exit(1)
358
- }
359
- }
360
-
361
- /**
362
- * Display knowledge base statistics
363
- */
364
- export async function stats(options: {
365
- app?: string
366
- json?: boolean
367
- }): Promise<void> {
368
- try {
369
- const sources = listProductSources()
370
- const redis = getRedis()
371
-
372
- const appStats: Array<{
373
- appId: string
374
- enabled: boolean
375
- format: string
376
- articleCount: number
377
- }> = []
378
-
379
- for (const source of sources) {
380
- if (options.app && source.appId !== options.app) {
381
- continue
382
- }
383
-
384
- const namespace = getKnowledgeNamespace(source.appId)
385
- const pattern = `${namespace}:article:*`
386
-
387
- // Count articles using SCAN
388
- let cursor = 0
389
- let count = 0
390
- do {
391
- const [nextCursor, keys] = await redis.scan(cursor, {
392
- match: pattern,
393
- count: 100,
394
- })
395
- cursor = Number(nextCursor)
396
- count += keys.length
397
- } while (cursor !== 0)
398
-
399
- appStats.push({
400
- appId: source.appId,
401
- enabled: source.enabled ?? false,
402
- format: source.format,
403
- articleCount: count,
404
- })
405
- }
406
-
407
- if (options.json) {
408
- console.log(JSON.stringify(appStats, null, 2))
409
- return
410
- }
411
-
412
- console.log('\nKnowledge Base Statistics')
413
- console.log('─'.repeat(60))
414
-
415
- const total = appStats.reduce((sum, s) => sum + s.articleCount, 0)
416
-
417
- for (const stat of appStats) {
418
- const status = stat.enabled ? 'āœ…' : 'āøļø'
419
- console.log(`\n${status} ${stat.appId} (${stat.format})`)
420
- console.log(` Articles: ${stat.articleCount}`)
421
- }
422
-
423
- console.log('\n' + '─'.repeat(60))
424
- console.log(`Total articles: ${total}`)
425
- console.log('')
426
- } catch (error) {
427
- if (options.json) {
428
- console.error(
429
- JSON.stringify({
430
- error: error instanceof Error ? error.message : 'Unknown error',
431
- })
432
- )
433
- } else {
434
- console.error(
435
- 'Error:',
436
- error instanceof Error ? error.message : 'Unknown error'
437
- )
438
- }
439
- process.exit(1)
440
- }
441
- }
442
-
443
- /**
444
- * List configured product sources
445
- */
446
- export async function list(options: { json?: boolean }): Promise<void> {
447
- const sources = listProductSources()
448
-
449
- if (options.json) {
450
- console.log(JSON.stringify(sources, null, 2))
451
- return
452
- }
453
-
454
- console.log('\nConfigured Knowledge Sources')
455
- console.log('─'.repeat(60))
456
-
457
- for (const source of sources) {
458
- const status = source.enabled ? 'āœ…' : 'āøļø'
459
- console.log(`\n${status} ${source.appId}`)
460
- console.log(` Format: ${source.format}`)
461
- console.log(` Source: ${source.defaultSource || 'docs'}`)
462
- console.log(` Category: ${source.defaultCategory || 'general'}`)
463
- if (source.sourceUrls && source.sourceUrls.length > 0) {
464
- console.log(` URLs:`)
465
- for (const url of source.sourceUrls) {
466
- console.log(` - ${url}`)
467
- }
468
- }
469
- }
470
-
471
- console.log('')
472
- }
473
-
474
- /**
475
- * Register kb commands with Commander
476
- */
477
- export function registerKbCommands(program: Command): void {
478
- const kb = program.command('kb').description('Manage knowledge base content')
479
-
480
- kb.command('sync')
481
- .description('Sync FAQ sources to knowledge base')
482
- .option('--app <appId>', 'Sync specific app')
483
- .option('--all', 'Sync all enabled apps')
484
- .option('--dry-run', 'Show what would be synced without making changes')
485
- .option('--json', 'Output as JSON')
486
- .action(sync)
487
-
488
- kb.command('stats')
489
- .description('Show knowledge base statistics')
490
- .option('--app <appId>', 'Filter by app')
491
- .option('--json', 'Output as JSON')
492
- .action(stats)
493
-
494
- kb.command('list')
495
- .description('List configured knowledge sources')
496
- .option('--json', 'Output as JSON')
497
- .action(list)
498
- }
@@ -1,135 +0,0 @@
1
- import { calculateConfidence } from '@skillrecordings/memory/decay'
2
- import { MemoryService } from '@skillrecordings/memory/memory'
3
-
4
- /**
5
- * Pad string to fixed width
6
- */
7
- function pad(str: string, width: number): string {
8
- return str.padEnd(width).slice(0, width)
9
- }
10
-
11
- /**
12
- * Format confidence score as percentage
13
- */
14
- function formatConfidence(confidence: number): string {
15
- return `${(confidence * 100).toFixed(0)}%`
16
- }
17
-
18
- /**
19
- * Find memories by semantic search
20
- */
21
- export async function find(
22
- query: string,
23
- options: {
24
- limit?: string
25
- collection?: string
26
- app?: string
27
- minConfidence?: string
28
- json?: boolean
29
- }
30
- ): Promise<void> {
31
- try {
32
- const limit = options.limit ? parseInt(options.limit, 10) : 10
33
- const threshold = options.minConfidence
34
- ? parseFloat(options.minConfidence)
35
- : 0.5
36
-
37
- if (limit < 1 || limit > 100) {
38
- console.error('Error: --limit must be between 1 and 100')
39
- process.exit(1)
40
- }
41
-
42
- if (threshold < 0 || threshold > 1) {
43
- console.error('Error: --min-confidence must be between 0 and 1')
44
- process.exit(1)
45
- }
46
-
47
- const results = await MemoryService.find(query, {
48
- collection: options.collection || 'learnings',
49
- limit,
50
- threshold,
51
- app_slug: options.app,
52
- })
53
-
54
- if (options.json) {
55
- console.log(JSON.stringify(results, null, 2))
56
- return
57
- }
58
-
59
- if (results.length === 0) {
60
- console.log('No memories found.')
61
- return
62
- }
63
-
64
- console.log(`\nFound ${results.length} memories:\n`)
65
- console.log(
66
- pad('ID', 36) +
67
- ' ' +
68
- pad('SCORE', 8) +
69
- ' ' +
70
- pad('CONF', 6) +
71
- ' ' +
72
- pad('AGE', 8) +
73
- ' ' +
74
- 'CONTENT'
75
- )
76
- console.log('-'.repeat(100))
77
-
78
- for (const result of results) {
79
- const confidence = calculateConfidence(result.memory)
80
- const ageDays = Math.floor(result.age_days)
81
- const ageStr =
82
- ageDays === 0 ? 'today' : ageDays === 1 ? '1 day' : `${ageDays} days`
83
-
84
- const contentPreview =
85
- result.memory.content.length > 40
86
- ? result.memory.content.slice(0, 37) + '...'
87
- : result.memory.content
88
-
89
- console.log(
90
- pad(result.memory.id, 36) +
91
- ' ' +
92
- pad(result.score.toFixed(2), 8) +
93
- ' ' +
94
- pad(formatConfidence(confidence), 6) +
95
- ' ' +
96
- pad(ageStr, 8) +
97
- ' ' +
98
- contentPreview
99
- )
100
-
101
- if (
102
- result.memory.metadata.tags &&
103
- result.memory.metadata.tags.length > 0
104
- ) {
105
- console.log(
106
- pad('', 36) +
107
- ' ' +
108
- pad('', 8) +
109
- ' ' +
110
- pad('', 6) +
111
- ' ' +
112
- pad('', 8) +
113
- ' ' +
114
- `Tags: ${result.memory.metadata.tags.join(', ')}`
115
- )
116
- }
117
- }
118
-
119
- console.log('')
120
- } catch (error) {
121
- if (options.json) {
122
- console.error(
123
- JSON.stringify({
124
- error: error instanceof Error ? error.message : 'Unknown error',
125
- })
126
- )
127
- } else {
128
- console.error(
129
- 'Error:',
130
- error instanceof Error ? error.message : 'Unknown error'
131
- )
132
- }
133
- process.exit(1)
134
- }
135
- }
@@ -1,87 +0,0 @@
1
- import { calculateConfidence } from '@skillrecordings/memory/decay'
2
- import { MemoryService } from '@skillrecordings/memory/memory'
3
-
4
- /**
5
- * Get a specific memory by ID
6
- */
7
- export async function get(
8
- id: string,
9
- options: {
10
- collection?: string
11
- json?: boolean
12
- }
13
- ): Promise<void> {
14
- try {
15
- const memory = await MemoryService.get(
16
- id,
17
- options.collection || 'learnings'
18
- )
19
-
20
- if (!memory) {
21
- if (options.json) {
22
- console.error(JSON.stringify({ error: 'Memory not found' }))
23
- } else {
24
- console.error('Error: Memory not found')
25
- }
26
- process.exit(1)
27
- }
28
-
29
- if (options.json) {
30
- console.log(JSON.stringify(memory, null, 2))
31
- return
32
- }
33
-
34
- const confidence = calculateConfidence(memory)
35
- const createdAt = new Date(memory.metadata.created_at)
36
- const lastValidated = memory.metadata.last_validated_at
37
- ? new Date(memory.metadata.last_validated_at)
38
- : null
39
-
40
- console.log('\nšŸ“‹ Memory Details:')
41
- console.log(` ID: ${memory.id}`)
42
- console.log(` Collection: ${memory.metadata.collection}`)
43
- console.log(` Source: ${memory.metadata.source}`)
44
- console.log(` Confidence: ${(confidence * 100).toFixed(0)}%`)
45
- console.log(` Created: ${createdAt.toLocaleString()}`)
46
- if (lastValidated) {
47
- console.log(` Validated: ${lastValidated.toLocaleString()}`)
48
- }
49
-
50
- if (memory.metadata.app_slug) {
51
- console.log(` App: ${memory.metadata.app_slug}`)
52
- }
53
-
54
- if (memory.metadata.tags && memory.metadata.tags.length > 0) {
55
- console.log(` Tags: ${memory.metadata.tags.join(', ')}`)
56
- }
57
-
58
- console.log('\nšŸ“ Content:')
59
- console.log(` ${memory.content}\n`)
60
-
61
- if (memory.metadata.votes) {
62
- const { upvotes, downvotes, citations, success_rate } =
63
- memory.metadata.votes
64
- if (upvotes > 0 || downvotes > 0 || citations > 0) {
65
- console.log('šŸ“Š Votes:')
66
- console.log(` Upvotes: ${upvotes}`)
67
- console.log(` Downvotes: ${downvotes}`)
68
- console.log(` Citations: ${citations}`)
69
- console.log(` Success Rate: ${(success_rate * 100).toFixed(0)}%\n`)
70
- }
71
- }
72
- } catch (error) {
73
- if (options.json) {
74
- console.error(
75
- JSON.stringify({
76
- error: error instanceof Error ? error.message : 'Unknown error',
77
- })
78
- )
79
- } else {
80
- console.error(
81
- 'Error:',
82
- error instanceof Error ? error.message : 'Unknown error'
83
- )
84
- }
85
- process.exit(1)
86
- }
87
- }