@skillrecordings/cli 0.1.0 → 0.2.1

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 +21 -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,293 +0,0 @@
1
- /**
2
- * CLI commands for testing agent tools against live app integrations.
3
- *
4
- * Usage:
5
- * skill tools search <app-slug> <query>
6
- * skill tools lookup <app-slug> <email>
7
- * skill tools list
8
- */
9
-
10
- import { AppsTable, eq, getDb } from '@skillrecordings/database'
11
- import { IntegrationClient } from '@skillrecordings/sdk/client'
12
- import type { Command } from 'commander'
13
-
14
- /**
15
- * Get app config from database by slug
16
- */
17
- async function getAppConfig(slug: string) {
18
- const db = getDb()
19
- const results = await db
20
- .select()
21
- .from(AppsTable)
22
- .where(eq(AppsTable.slug, slug))
23
- .limit(1)
24
-
25
- const app = results[0]
26
- if (!app) {
27
- return null
28
- }
29
-
30
- // baseUrl should be the complete endpoint URL
31
- // SDK client will POST directly to this URL with action in body
32
- return {
33
- slug: app.slug,
34
- name: app.name,
35
- baseUrl: app.integration_base_url,
36
- webhookSecret: app.webhook_secret,
37
- stripeAccountId: app.stripe_account_id,
38
- instructorTeammateId: app.instructor_teammate_id,
39
- }
40
- }
41
-
42
- /**
43
- * List all registered apps
44
- */
45
- async function listApps(options: { json?: boolean }) {
46
- const db = getDb()
47
- const apps = await db
48
- .select({
49
- slug: AppsTable.slug,
50
- name: AppsTable.name,
51
- baseUrl: AppsTable.integration_base_url,
52
- })
53
- .from(AppsTable)
54
-
55
- if (options.json) {
56
- console.log(JSON.stringify(apps, null, 2))
57
- process.exit(0)
58
- }
59
-
60
- console.log('\nRegistered Apps:')
61
- console.log('================')
62
- for (const app of apps) {
63
- console.log(` ${app.slug} - ${app.name}`)
64
- console.log(` URL: ${app.baseUrl}`)
65
- console.log()
66
- }
67
- process.exit(0)
68
- }
69
-
70
- /**
71
- * Test content search against an app
72
- */
73
- async function searchContent(
74
- slug: string,
75
- query: string,
76
- options: { types?: string; limit?: string; json?: boolean }
77
- ) {
78
- const app = await getAppConfig(slug)
79
- if (!app) {
80
- console.error(`App not found: ${slug}`)
81
- console.error('Use "skill tools list" to see registered apps')
82
- process.exit(1)
83
- }
84
-
85
- if (!app.baseUrl || !app.webhookSecret) {
86
- console.error(`App ${slug} is missing baseUrl or webhookSecret`)
87
- process.exit(1)
88
- }
89
-
90
- const client = new IntegrationClient({
91
- baseUrl: app.baseUrl,
92
- webhookSecret: app.webhookSecret,
93
- })
94
-
95
- console.log(`\nSearching ${app.name} for: "${query}"`)
96
- console.log(`Endpoint: ${app.baseUrl}`)
97
- console.log()
98
-
99
- try {
100
- const result = await client.searchContent({
101
- query,
102
- types: options.types?.split(',') as any,
103
- limit: options.limit ? parseInt(options.limit, 10) : 5,
104
- })
105
-
106
- if (options.json) {
107
- console.log(JSON.stringify(result, null, 2))
108
- process.exit(0)
109
- }
110
-
111
- if (!result.results || result.results.length === 0) {
112
- console.log('No results found.')
113
- process.exit(0)
114
- }
115
-
116
- console.log(`Found ${result.results.length} results:\n`)
117
- for (const item of result.results) {
118
- console.log(` [${item.type}] ${item.title}`)
119
- if (item.url) {
120
- console.log(` URL: ${item.url}`)
121
- }
122
- if (item.description) {
123
- console.log(
124
- ` ${item.description.slice(0, 200)}${item.description.length > 200 ? '...' : ''}`
125
- )
126
- }
127
- console.log()
128
- }
129
- process.exit(0)
130
- } catch (error) {
131
- console.error(
132
- 'Search failed:',
133
- error instanceof Error ? error.message : error
134
- )
135
- process.exit(1)
136
- }
137
- }
138
-
139
- /**
140
- * Test user lookup against an app
141
- */
142
- async function lookupUser(
143
- slug: string,
144
- email: string,
145
- options: { json?: boolean }
146
- ) {
147
- const app = await getAppConfig(slug)
148
- if (!app) {
149
- console.error(`App not found: ${slug}`)
150
- process.exit(1)
151
- }
152
-
153
- if (!app.baseUrl || !app.webhookSecret) {
154
- console.error(`App ${slug} is missing baseUrl or webhookSecret`)
155
- process.exit(1)
156
- }
157
-
158
- const client = new IntegrationClient({
159
- baseUrl: app.baseUrl,
160
- webhookSecret: app.webhookSecret,
161
- })
162
-
163
- console.log(`\nLooking up user: ${email}`)
164
- console.log(`Endpoint: ${app.baseUrl}`)
165
- console.log()
166
-
167
- try {
168
- const user = await client.lookupUser(email)
169
-
170
- if (options.json) {
171
- console.log(JSON.stringify(user, null, 2))
172
- process.exit(0)
173
- }
174
-
175
- if (!user) {
176
- console.log('User not found.')
177
- process.exit(0)
178
- }
179
-
180
- console.log('User found:')
181
- console.log(` ID: ${user.id}`)
182
- console.log(` Email: ${user.email}`)
183
- if (user.name) console.log(` Name: ${user.name}`)
184
- console.log()
185
- process.exit(0)
186
- } catch (error) {
187
- console.error(
188
- 'Lookup failed:',
189
- error instanceof Error ? error.message : error
190
- )
191
- process.exit(1)
192
- }
193
- }
194
-
195
- /**
196
- * Test purchases lookup against an app
197
- */
198
- async function getPurchases(
199
- slug: string,
200
- userId: string,
201
- options: { json?: boolean }
202
- ) {
203
- const app = await getAppConfig(slug)
204
- if (!app) {
205
- console.error(`App not found: ${slug}`)
206
- process.exit(1)
207
- }
208
-
209
- if (!app.baseUrl || !app.webhookSecret) {
210
- console.error(`App ${slug} is missing baseUrl or webhookSecret`)
211
- process.exit(1)
212
- }
213
-
214
- const client = new IntegrationClient({
215
- baseUrl: app.baseUrl,
216
- webhookSecret: app.webhookSecret,
217
- })
218
-
219
- console.log(`\nFetching purchases for user: ${userId}`)
220
- console.log(`Endpoint: ${app.baseUrl}`)
221
- console.log()
222
-
223
- try {
224
- const purchases = await client.getPurchases(userId)
225
-
226
- if (options.json) {
227
- console.log(JSON.stringify(purchases, null, 2))
228
- process.exit(0)
229
- }
230
-
231
- if (!purchases || purchases.length === 0) {
232
- console.log('No purchases found.')
233
- process.exit(0)
234
- }
235
-
236
- console.log(`Found ${purchases.length} purchases:\n`)
237
- for (const p of purchases) {
238
- console.log(` [${p.id}] ${p.productName}`)
239
- console.log(` Status: ${p.status}`)
240
- console.log(` Amount: ${p.amount} ${p.currency}`)
241
- console.log(` Date: ${new Date(p.purchasedAt).toLocaleDateString()}`)
242
- console.log()
243
- }
244
- process.exit(0)
245
- } catch (error) {
246
- console.error(
247
- 'Fetch failed:',
248
- error instanceof Error ? error.message : error
249
- )
250
- process.exit(1)
251
- }
252
- }
253
-
254
- /**
255
- * Register tools commands
256
- */
257
- export function registerToolsCommands(program: Command) {
258
- const tools = program
259
- .command('tools')
260
- .description('Test agent tools against live app integrations')
261
-
262
- tools
263
- .command('list')
264
- .description('List all registered apps')
265
- .option('--json', 'Output as JSON')
266
- .action(listApps)
267
-
268
- tools
269
- .command('search')
270
- .description('Test content search against an app')
271
- .argument('<app-slug>', 'App slug (e.g., total-typescript)')
272
- .argument('<query>', 'Search query')
273
- .option('-t, --types <types>', 'Filter by content types (comma-separated)')
274
- .option('-l, --limit <limit>', 'Max results (default: 5)')
275
- .option('--json', 'Output as JSON')
276
- .action(searchContent)
277
-
278
- tools
279
- .command('lookup')
280
- .description('Test user lookup against an app')
281
- .argument('<app-slug>', 'App slug')
282
- .argument('<email>', 'User email to look up')
283
- .option('--json', 'Output as JSON')
284
- .action(lookupUser)
285
-
286
- tools
287
- .command('purchases')
288
- .description('Test purchases lookup against an app')
289
- .argument('<app-slug>', 'App slug')
290
- .argument('<user-id>', 'User ID')
291
- .option('--json', 'Output as JSON')
292
- .action(getPurchases)
293
- }
@@ -1,319 +0,0 @@
1
- import { randomBytes, randomUUID } from 'node:crypto'
2
- import { checkbox, confirm, input, select } from '@inquirer/prompts'
3
-
4
- /**
5
- * All available capabilities an app can implement
6
- */
7
- const ALL_CAPABILITIES = [
8
- {
9
- value: 'lookupUser',
10
- name: 'lookupUser - Find user by email',
11
- checked: true,
12
- },
13
- {
14
- value: 'getPurchases',
15
- name: 'getPurchases - Fetch purchase history',
16
- checked: true,
17
- },
18
- {
19
- value: 'revokeAccess',
20
- name: 'revokeAccess - Revoke access after refund',
21
- checked: true,
22
- },
23
- {
24
- value: 'transferPurchase',
25
- name: 'transferPurchase - Transfer license to new owner',
26
- checked: true,
27
- },
28
- {
29
- value: 'generateMagicLink',
30
- name: 'generateMagicLink - Send login links',
31
- checked: true,
32
- },
33
- {
34
- value: 'getSubscriptions',
35
- name: 'getSubscriptions - Fetch subscriptions (optional)',
36
- checked: false,
37
- },
38
- {
39
- value: 'updateEmail',
40
- name: 'updateEmail - Change user email (optional)',
41
- checked: false,
42
- },
43
- {
44
- value: 'updateName',
45
- name: 'updateName - Change user name (optional)',
46
- checked: false,
47
- },
48
- {
49
- value: 'getClaimedSeats',
50
- name: 'getClaimedSeats - Team seat management (optional)',
51
- checked: false,
52
- },
53
- ] as const
54
-
55
- export interface WizardOptions {
56
- json?: boolean
57
- }
58
-
59
- export interface WizardResult {
60
- success: boolean
61
- app?: {
62
- id: string
63
- slug: string
64
- name: string
65
- frontInboxId: string
66
- integrationBaseUrl: string
67
- webhookSecret: string
68
- capabilities: string[]
69
- stripeAccountId?: string
70
- escalationSlackChannel?: string
71
- autoApproveRefundDays: number
72
- autoApproveTransferDays: number
73
- }
74
- error?: string
75
- }
76
-
77
- /**
78
- * Convert name to URL-friendly slug
79
- */
80
- function slugify(name: string): string {
81
- return name
82
- .toLowerCase()
83
- .replace(/[^a-z0-9]+/g, '-')
84
- .replace(/^-|-$/g, '')
85
- }
86
-
87
- /**
88
- * Interactive wizard for setting up a new property (app)
89
- */
90
- export async function wizard(options: WizardOptions = {}): Promise<void> {
91
- const { json = false } = options
92
-
93
- if (!process.stdin.isTTY && !json) {
94
- console.error(
95
- 'Error: Wizard requires an interactive terminal. Use --json for non-interactive mode.'
96
- )
97
- process.exit(1)
98
- }
99
-
100
- try {
101
- console.log('\nšŸ§™ Property Setup Wizard\n')
102
- console.log(
103
- 'This will walk you through setting up a new app in the support platform.\n'
104
- )
105
-
106
- // Basic info
107
- const name = await input({
108
- message: 'App name (e.g., "Total TypeScript"):',
109
- validate: (v) => v.trim().length > 0 || 'Name is required',
110
- })
111
-
112
- const suggestedSlug = slugify(name)
113
- const slug = await input({
114
- message: 'URL slug:',
115
- default: suggestedSlug,
116
- validate: (v) =>
117
- /^[a-z0-9-]+$/.test(v) ||
118
- 'Slug must be lowercase alphanumeric with dashes',
119
- })
120
-
121
- // Front inbox
122
- const frontInboxId = await input({
123
- message: 'Front inbox ID (e.g., "inb_abc123"):',
124
- validate: (v) =>
125
- v.startsWith('inb_') ||
126
- 'Must be a valid Front inbox ID (starts with inb_)',
127
- })
128
-
129
- // Integration URL
130
- const integrationBaseUrl = await input({
131
- message: 'Integration base URL (where SDK endpoints live):',
132
- default: `https://${slug}.com`,
133
- validate: (v) => {
134
- try {
135
- new URL(v)
136
- return true
137
- } catch {
138
- return 'Must be a valid URL'
139
- }
140
- },
141
- })
142
-
143
- // Capabilities
144
- const capabilities = await checkbox({
145
- message: 'Select capabilities to implement:',
146
- choices: ALL_CAPABILITIES.map((c) => ({
147
- value: c.value,
148
- name: c.name,
149
- checked: c.checked,
150
- })),
151
- })
152
-
153
- // Stripe Connect (optional)
154
- const useStripe = await confirm({
155
- message: 'Enable Stripe Connect for refund processing?',
156
- default: true,
157
- })
158
-
159
- let stripeAccountId: string | undefined
160
- if (useStripe) {
161
- stripeAccountId =
162
- (await input({
163
- message:
164
- 'Stripe Connect account ID (e.g., "acct_xxx") or leave blank to connect later:',
165
- default: '',
166
- })) || undefined
167
- }
168
-
169
- // Escalation channel (optional)
170
- const useSlackEscalation = await confirm({
171
- message: 'Configure Slack escalation channel?',
172
- default: false,
173
- })
174
-
175
- let escalationSlackChannel: string | undefined
176
- if (useSlackEscalation) {
177
- escalationSlackChannel = await input({
178
- message: 'Slack channel ID for escalations (e.g., "C0123456789"):',
179
- validate: (v) =>
180
- v.startsWith('C') || 'Must be a valid Slack channel ID',
181
- })
182
- }
183
-
184
- // Auto-approval settings
185
- const configureAutoApproval = await confirm({
186
- message:
187
- 'Configure auto-approval thresholds? (default: 30 days refund, 14 days transfer)',
188
- default: false,
189
- })
190
-
191
- let autoApproveRefundDays = 30
192
- let autoApproveTransferDays = 14
193
-
194
- if (configureAutoApproval) {
195
- const refundDaysStr = await input({
196
- message: 'Auto-approve refunds within X days of purchase:',
197
- default: '30',
198
- validate: (v) =>
199
- (!isNaN(parseInt(v)) && parseInt(v) >= 0) ||
200
- 'Must be a non-negative number',
201
- })
202
- autoApproveRefundDays = parseInt(refundDaysStr)
203
-
204
- const transferDaysStr = await input({
205
- message: 'Auto-approve transfers within X days of purchase:',
206
- default: '14',
207
- validate: (v) =>
208
- (!isNaN(parseInt(v)) && parseInt(v) >= 0) ||
209
- 'Must be a non-negative number',
210
- })
211
- autoApproveTransferDays = parseInt(transferDaysStr)
212
- }
213
-
214
- // Generate secrets
215
- const id = `app_${randomUUID().replace(/-/g, '').slice(0, 16)}`
216
- const webhookSecret = randomBytes(32).toString('hex')
217
-
218
- const result: WizardResult = {
219
- success: true,
220
- app: {
221
- id,
222
- slug,
223
- name,
224
- frontInboxId,
225
- integrationBaseUrl,
226
- webhookSecret,
227
- capabilities,
228
- stripeAccountId,
229
- escalationSlackChannel,
230
- autoApproveRefundDays,
231
- autoApproveTransferDays,
232
- },
233
- }
234
-
235
- if (json) {
236
- console.log(JSON.stringify(result, null, 2))
237
- } else {
238
- console.log('\n' + '='.repeat(60))
239
- console.log('āœ… Configuration complete!\n')
240
-
241
- console.log('šŸ“‹ App Details:')
242
- console.log(` ID: ${id}`)
243
- console.log(` Slug: ${slug}`)
244
- console.log(` Name: ${name}`)
245
- console.log(` URL: ${integrationBaseUrl}`)
246
-
247
- console.log('\nšŸ”— Front Integration:')
248
- console.log(` Inbox ID: ${frontInboxId}`)
249
-
250
- if (stripeAccountId) {
251
- console.log('\nšŸ’³ Stripe Connect:')
252
- console.log(` Account ID: ${stripeAccountId}`)
253
- }
254
-
255
- console.log('\nšŸ”§ Capabilities:')
256
- capabilities.forEach((c) => console.log(` - ${c}`))
257
-
258
- console.log('\nā±ļø Auto-Approval:')
259
- console.log(` Refunds: within ${autoApproveRefundDays} days`)
260
- console.log(` Transfers: within ${autoApproveTransferDays} days`)
261
-
262
- console.log('\n' + '='.repeat(60))
263
- console.log('\nšŸ“ Next Steps:\n')
264
-
265
- console.log("1. Add to your app's .env:")
266
- console.log(' ```')
267
- console.log(` SUPPORT_WEBHOOK_SECRET=${webhookSecret}`)
268
- console.log(' ```\n')
269
-
270
- console.log('2. Implement the SDK handler in your app:')
271
- console.log(' ```typescript')
272
- console.log(' // app/api/support/[...action]/route.ts')
273
- console.log(
274
- " import { createSupportHandler } from '@skillrecordings/sdk/handler'"
275
- )
276
- console.log(" import { integration } from './integration'")
277
- console.log('')
278
- console.log(' const handler = createSupportHandler({')
279
- console.log(' integration,')
280
- console.log(` secret: process.env.SUPPORT_WEBHOOK_SECRET!,`)
281
- console.log(' })')
282
- console.log('')
283
- console.log(' export { handler as POST }')
284
- console.log(' ```\n')
285
-
286
- console.log('3. Insert into database:')
287
- console.log(' ```sql')
288
- console.log(
289
- ` INSERT INTO SUPPORT_apps (id, slug, name, front_inbox_id, integration_base_url, webhook_secret, capabilities, auto_approve_refund_days, auto_approve_transfer_days)`
290
- )
291
- console.log(
292
- ` VALUES ('${id}', '${slug}', '${name}', '${frontInboxId}', '${integrationBaseUrl}', '${webhookSecret}', '${JSON.stringify(capabilities)}', ${autoApproveRefundDays}, ${autoApproveTransferDays});`
293
- )
294
- console.log(' ```\n')
295
-
296
- if (!stripeAccountId && useStripe) {
297
- console.log('4. Connect Stripe account:')
298
- console.log(
299
- ' Visit https://skill-support-agent-web.vercel.app/api/stripe/connect/authorize?appSlug=' +
300
- slug
301
- )
302
- console.log('')
303
- }
304
-
305
- console.log(
306
- 'šŸ“– See docs/support-app-prd/67-sdk.md for full integration guide.\n'
307
- )
308
- }
309
-
310
- process.exit(0)
311
- } catch (error) {
312
- if ((error as Error).name === 'ExitPromptError') {
313
- // User cancelled
314
- console.log('\n\nWizard cancelled.')
315
- process.exit(1)
316
- }
317
- throw error
318
- }
319
- }