@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.
- package/bin/skill.mjs +27 -0
- package/dist/chunk-2NCCVTEE.js +22342 -0
- package/dist/chunk-2NCCVTEE.js.map +1 -0
- package/dist/chunk-3E3GYSZR.js +7071 -0
- package/dist/chunk-3E3GYSZR.js.map +1 -0
- package/dist/chunk-F4EM72IH.js +86 -0
- package/dist/chunk-F4EM72IH.js.map +1 -0
- package/dist/chunk-FGP7KUQW.js +432 -0
- package/dist/chunk-FGP7KUQW.js.map +1 -0
- package/dist/chunk-H3D6VCME.js +55 -0
- package/dist/chunk-H3D6VCME.js.map +1 -0
- package/dist/chunk-HK3PEWFD.js +208 -0
- package/dist/chunk-HK3PEWFD.js.map +1 -0
- package/dist/chunk-KEV3QKXP.js +4495 -0
- package/dist/chunk-KEV3QKXP.js.map +1 -0
- package/dist/chunk-MG37YDAK.js +882 -0
- package/dist/chunk-MG37YDAK.js.map +1 -0
- package/dist/chunk-MLNDSBZ4.js +482 -0
- package/dist/chunk-MLNDSBZ4.js.map +1 -0
- package/dist/chunk-N2WIV2JV.js +22 -0
- package/dist/chunk-N2WIV2JV.js.map +1 -0
- package/dist/chunk-PWWRCN5W.js +2067 -0
- package/dist/chunk-PWWRCN5W.js.map +1 -0
- package/dist/chunk-SKHBM3XP.js +7746 -0
- package/dist/chunk-SKHBM3XP.js.map +1 -0
- package/dist/chunk-WFANXVQG.js +64 -0
- package/dist/chunk-WFANXVQG.js.map +1 -0
- package/dist/chunk-WYKL32C3.js +275 -0
- package/dist/chunk-WYKL32C3.js.map +1 -0
- package/dist/chunk-ZNF7XD2S.js +134 -0
- package/dist/chunk-ZNF7XD2S.js.map +1 -0
- package/dist/config-AUAIYDSI.js +20 -0
- package/dist/config-AUAIYDSI.js.map +1 -0
- package/dist/fileFromPath-XN7LXIBI.js +134 -0
- package/dist/fileFromPath-XN7LXIBI.js.map +1 -0
- package/dist/getMachineId-bsd-KW2E7VK3.js +42 -0
- package/dist/getMachineId-bsd-KW2E7VK3.js.map +1 -0
- package/dist/getMachineId-darwin-ROXJUJX5.js +42 -0
- package/dist/getMachineId-darwin-ROXJUJX5.js.map +1 -0
- package/dist/getMachineId-linux-KVZEHQSU.js +34 -0
- package/dist/getMachineId-linux-KVZEHQSU.js.map +1 -0
- package/dist/getMachineId-unsupported-PPRILPPA.js +25 -0
- package/dist/getMachineId-unsupported-PPRILPPA.js.map +1 -0
- package/dist/getMachineId-win-IIF36LEJ.js +44 -0
- package/dist/getMachineId-win-IIF36LEJ.js.map +1 -0
- package/dist/index.js +112703 -0
- package/dist/index.js.map +1 -0
- package/dist/lib-R6DEEJCP.js +7623 -0
- package/dist/lib-R6DEEJCP.js.map +1 -0
- package/dist/pipeline-IAVVAKTU.js +120 -0
- package/dist/pipeline-IAVVAKTU.js.map +1 -0
- package/dist/query-NTP5NVXN.js +25 -0
- package/dist/query-NTP5NVXN.js.map +1 -0
- package/dist/routing-BAEPFB7V.js +390 -0
- package/dist/routing-BAEPFB7V.js.map +1 -0
- package/dist/stripe-lookup-charge-EPRUMZDL.js +56 -0
- package/dist/stripe-lookup-charge-EPRUMZDL.js.map +1 -0
- package/dist/stripe-payment-history-SJPKA63N.js +67 -0
- package/dist/stripe-payment-history-SJPKA63N.js.map +1 -0
- package/dist/stripe-subscription-status-L4Z65GB3.js +58 -0
- package/dist/stripe-subscription-status-L4Z65GB3.js.map +1 -0
- package/dist/stripe-verify-refund-FZDKCIUQ.js +54 -0
- package/dist/stripe-verify-refund-FZDKCIUQ.js.map +1 -0
- package/dist/support-memory-WSG7SDKG.js +10 -0
- package/dist/support-memory-WSG7SDKG.js.map +1 -0
- package/package.json +10 -7
- package/.env.encrypted +0 -0
- package/CHANGELOG.md +0 -35
- package/data/tt-archive-dataset.json +0 -1
- package/data/validate-test-dataset.json +0 -97
- package/docs/CLI-AUTH.md +0 -504
- package/preload.ts +0 -18
- package/src/__tests__/init.test.ts +0 -74
- package/src/alignment-test.ts +0 -64
- package/src/check-apps.ts +0 -16
- package/src/commands/auth/decrypt.ts +0 -123
- package/src/commands/auth/encrypt.ts +0 -81
- package/src/commands/auth/index.ts +0 -50
- package/src/commands/auth/keygen.ts +0 -41
- package/src/commands/auth/status.ts +0 -164
- package/src/commands/axiom/forensic.ts +0 -868
- package/src/commands/axiom/index.ts +0 -697
- package/src/commands/build-dataset.ts +0 -311
- package/src/commands/db-status.ts +0 -47
- package/src/commands/deploys.ts +0 -219
- package/src/commands/eval-local/compare.ts +0 -171
- package/src/commands/eval-local/health.ts +0 -212
- package/src/commands/eval-local/index.ts +0 -76
- package/src/commands/eval-local/real-tools.ts +0 -416
- package/src/commands/eval-local/run.ts +0 -1168
- package/src/commands/eval-local/score-production.ts +0 -256
- package/src/commands/eval-local/seed.ts +0 -276
- package/src/commands/eval-pipeline/index.ts +0 -53
- package/src/commands/eval-pipeline/real-tools.ts +0 -492
- package/src/commands/eval-pipeline/run.ts +0 -1316
- package/src/commands/eval-pipeline/seed.ts +0 -395
- package/src/commands/eval-prompt.ts +0 -496
- package/src/commands/eval.test.ts +0 -253
- package/src/commands/eval.ts +0 -108
- package/src/commands/faq-classify.ts +0 -460
- package/src/commands/faq-cluster.ts +0 -135
- package/src/commands/faq-extract.ts +0 -249
- package/src/commands/faq-mine.ts +0 -432
- package/src/commands/faq-review.ts +0 -426
- package/src/commands/front/index.ts +0 -351
- package/src/commands/front/pull-conversations.ts +0 -275
- package/src/commands/front/tags.ts +0 -825
- package/src/commands/front-cache.ts +0 -1277
- package/src/commands/front-stats.ts +0 -75
- package/src/commands/health.test.ts +0 -82
- package/src/commands/health.ts +0 -362
- package/src/commands/init.test.ts +0 -89
- package/src/commands/init.ts +0 -106
- package/src/commands/inngest/client.ts +0 -294
- package/src/commands/inngest/events.ts +0 -296
- package/src/commands/inngest/investigate.ts +0 -382
- package/src/commands/inngest/runs.ts +0 -149
- package/src/commands/inngest/signal.ts +0 -143
- package/src/commands/kb-sync.ts +0 -498
- package/src/commands/memory/find.ts +0 -135
- package/src/commands/memory/get.ts +0 -87
- package/src/commands/memory/index.ts +0 -97
- package/src/commands/memory/stats.ts +0 -163
- package/src/commands/memory/store.ts +0 -49
- package/src/commands/memory/vote.ts +0 -159
- package/src/commands/pipeline.ts +0 -127
- package/src/commands/responses.ts +0 -856
- package/src/commands/tools.ts +0 -293
- package/src/commands/wizard.ts +0 -319
- package/src/index.ts +0 -172
- package/src/lib/crypto.ts +0 -56
- package/src/lib/env-loader.ts +0 -206
- package/src/lib/onepassword.ts +0 -137
- package/src/test-agent-local.ts +0 -115
- package/tsconfig.json +0 -11
- package/vitest.config.ts +0 -10
|
@@ -1,395 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Seed command for eval-pipeline
|
|
3
|
-
* Populates MySQL and Qdrant with test fixtures for honest pipeline evals
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { join } from 'path'
|
|
7
|
-
import { readFile, readdir } from 'fs/promises'
|
|
8
|
-
import { glob } from 'glob'
|
|
9
|
-
import matter from 'gray-matter'
|
|
10
|
-
|
|
11
|
-
interface SeedOptions {
|
|
12
|
-
clean?: boolean
|
|
13
|
-
fixtures?: string
|
|
14
|
-
json?: boolean
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface SeedResult {
|
|
18
|
-
apps: number
|
|
19
|
-
trustScores: number
|
|
20
|
-
customers: number
|
|
21
|
-
knowledge: number
|
|
22
|
-
embeddings: number
|
|
23
|
-
scenarios: number
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface KnowledgeDoc {
|
|
27
|
-
id: string
|
|
28
|
-
content: string
|
|
29
|
-
type: string
|
|
30
|
-
app: string
|
|
31
|
-
tags: string[]
|
|
32
|
-
title: string
|
|
33
|
-
filePath: string
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
interface QdrantPoint {
|
|
37
|
-
id: string
|
|
38
|
-
vector: number[]
|
|
39
|
-
payload: Record<string, unknown>
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function generateUUID(): string {
|
|
43
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
44
|
-
const r = (Math.random() * 16) | 0
|
|
45
|
-
const v = c === 'x' ? r : (r & 0x3) | 0x8
|
|
46
|
-
return v.toString(16)
|
|
47
|
-
})
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export async function seed(options: SeedOptions): Promise<void> {
|
|
51
|
-
const fixturesPath = options.fixtures || 'fixtures'
|
|
52
|
-
|
|
53
|
-
if (!options.json) {
|
|
54
|
-
console.log('\n🌱 Seeding eval-pipeline environment...\n')
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const result: SeedResult = {
|
|
58
|
-
apps: 0,
|
|
59
|
-
trustScores: 0,
|
|
60
|
-
customers: 0,
|
|
61
|
-
knowledge: 0,
|
|
62
|
-
embeddings: 0,
|
|
63
|
-
scenarios: 0,
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
// Get MySQL connection
|
|
68
|
-
const mysql = await import('mysql2/promise')
|
|
69
|
-
const connection = await mysql.createConnection({
|
|
70
|
-
host: process.env.MYSQL_HOST || 'localhost',
|
|
71
|
-
port: parseInt(process.env.MYSQL_PORT || '3306'),
|
|
72
|
-
user: process.env.MYSQL_USER || 'eval_user',
|
|
73
|
-
password: process.env.MYSQL_PASSWORD || 'eval_pass',
|
|
74
|
-
database: process.env.MYSQL_DATABASE || 'support_eval',
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
if (options.clean) {
|
|
78
|
-
if (!options.json) console.log('🧹 Cleaning existing data...')
|
|
79
|
-
await cleanDatabase(connection)
|
|
80
|
-
await cleanQdrant()
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// 1. Seed apps
|
|
84
|
-
if (!options.json) console.log('📦 Seeding apps...')
|
|
85
|
-
const apps = await loadJsonFiles(join(fixturesPath, 'apps'))
|
|
86
|
-
result.apps = await seedApps(connection, apps)
|
|
87
|
-
|
|
88
|
-
// 2. Count trust scores seeded with apps
|
|
89
|
-
const [trustRows] = await connection.execute(
|
|
90
|
-
'SELECT COUNT(*) as count FROM SUPPORT_trust_scores'
|
|
91
|
-
)
|
|
92
|
-
result.trustScores = (trustRows as any)[0].count
|
|
93
|
-
|
|
94
|
-
// 3. Load customer fixtures (used by mock integration, not stored in DB)
|
|
95
|
-
if (!options.json) console.log('👥 Loading customer fixtures...')
|
|
96
|
-
const customers = await loadJsonFiles(join(fixturesPath, 'customers'))
|
|
97
|
-
result.customers = customers.length
|
|
98
|
-
|
|
99
|
-
// 4. Seed knowledge base with embeddings
|
|
100
|
-
if (!options.json) console.log('📚 Seeding knowledge base...')
|
|
101
|
-
const knowledge = await loadKnowledgeFiles(join(fixturesPath, 'knowledge'))
|
|
102
|
-
result.knowledge = knowledge.length
|
|
103
|
-
result.embeddings = await seedKnowledgeBase(knowledge, !options.json)
|
|
104
|
-
|
|
105
|
-
// 5. Count scenarios
|
|
106
|
-
const scenarioFiles = await glob(join(fixturesPath, 'scenarios/**/*.json'))
|
|
107
|
-
result.scenarios = scenarioFiles.length
|
|
108
|
-
|
|
109
|
-
await connection.end()
|
|
110
|
-
|
|
111
|
-
if (options.json) {
|
|
112
|
-
console.log(JSON.stringify({ success: true, result }, null, 2))
|
|
113
|
-
} else {
|
|
114
|
-
console.log('\n✅ Seeding complete!\n')
|
|
115
|
-
console.log(` Apps: ${result.apps}`)
|
|
116
|
-
console.log(` Trust Scores: ${result.trustScores}`)
|
|
117
|
-
console.log(` Customers: ${result.customers} (fixture files)`)
|
|
118
|
-
console.log(` Knowledge: ${result.knowledge} documents`)
|
|
119
|
-
console.log(` Embeddings: ${result.embeddings}`)
|
|
120
|
-
console.log(` Scenarios: ${result.scenarios}\n`)
|
|
121
|
-
}
|
|
122
|
-
} catch (error) {
|
|
123
|
-
if (options.json) {
|
|
124
|
-
console.log(
|
|
125
|
-
JSON.stringify({
|
|
126
|
-
success: false,
|
|
127
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
128
|
-
})
|
|
129
|
-
)
|
|
130
|
-
} else {
|
|
131
|
-
console.error('❌ Seeding failed:', error)
|
|
132
|
-
}
|
|
133
|
-
process.exit(1)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function cleanDatabase(connection: any): Promise<void> {
|
|
138
|
-
// Disable foreign key checks temporarily
|
|
139
|
-
await connection.execute('SET FOREIGN_KEY_CHECKS = 0')
|
|
140
|
-
|
|
141
|
-
const tables = [
|
|
142
|
-
'SUPPORT_dead_letter_queue',
|
|
143
|
-
'SUPPORT_trust_scores',
|
|
144
|
-
'SUPPORT_audit_log',
|
|
145
|
-
'SUPPORT_approval_requests',
|
|
146
|
-
'SUPPORT_actions',
|
|
147
|
-
'SUPPORT_conversations',
|
|
148
|
-
'SUPPORT_apps',
|
|
149
|
-
]
|
|
150
|
-
|
|
151
|
-
for (const table of tables) {
|
|
152
|
-
try {
|
|
153
|
-
await connection.execute(`TRUNCATE TABLE ${table}`)
|
|
154
|
-
} catch {
|
|
155
|
-
// Table might not exist yet, ignore
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
await connection.execute('SET FOREIGN_KEY_CHECKS = 1')
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
async function cleanQdrant(): Promise<void> {
|
|
163
|
-
const qdrantUrl = process.env.QDRANT_URL || 'http://localhost:6333'
|
|
164
|
-
const collection = process.env.QDRANT_COLLECTION || 'knowledge'
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
await fetch(`${qdrantUrl}/collections/${collection}`, {
|
|
168
|
-
method: 'DELETE',
|
|
169
|
-
})
|
|
170
|
-
} catch {
|
|
171
|
-
// Collection might not exist, ignore
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async function loadJsonFiles(dirPath: string): Promise<any[]> {
|
|
176
|
-
try {
|
|
177
|
-
const files = await readdir(dirPath)
|
|
178
|
-
const jsonFiles = files.filter((f) => f.endsWith('.json'))
|
|
179
|
-
|
|
180
|
-
const items = await Promise.all(
|
|
181
|
-
jsonFiles.map(async (file) => {
|
|
182
|
-
const content = await readFile(join(dirPath, file), 'utf-8')
|
|
183
|
-
return JSON.parse(content)
|
|
184
|
-
})
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
return items
|
|
188
|
-
} catch {
|
|
189
|
-
return []
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async function loadKnowledgeFiles(basePath: string): Promise<KnowledgeDoc[]> {
|
|
194
|
-
const files = await glob(join(basePath, '**/*.md'))
|
|
195
|
-
const docs: KnowledgeDoc[] = []
|
|
196
|
-
|
|
197
|
-
for (const filePath of files) {
|
|
198
|
-
const content = await readFile(filePath, 'utf-8')
|
|
199
|
-
const { data: frontmatter, content: body } = matter(content)
|
|
200
|
-
|
|
201
|
-
// Extract title from first markdown heading or filename
|
|
202
|
-
const titleMatch = body.match(/^#\s+(.+)$/m)
|
|
203
|
-
const title = titleMatch?.[1]
|
|
204
|
-
?? filePath.split('/').pop()?.replace('.md', '')
|
|
205
|
-
?? 'Untitled'
|
|
206
|
-
|
|
207
|
-
docs.push({
|
|
208
|
-
id: generateUUID(),
|
|
209
|
-
content: body.trim(),
|
|
210
|
-
type: frontmatter.type || 'general',
|
|
211
|
-
app: frontmatter.app || 'unknown',
|
|
212
|
-
tags: frontmatter.tags || [],
|
|
213
|
-
title,
|
|
214
|
-
filePath,
|
|
215
|
-
})
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return docs
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
async function seedApps(connection: any, apps: any[]): Promise<number> {
|
|
222
|
-
for (const app of apps) {
|
|
223
|
-
await connection.execute(
|
|
224
|
-
`INSERT INTO SUPPORT_apps (
|
|
225
|
-
id, slug, name, front_inbox_id, instructor_teammate_id,
|
|
226
|
-
stripe_account_id, stripe_connected, integration_base_url,
|
|
227
|
-
webhook_secret, capabilities, auto_approve_refund_days, auto_approve_transfer_days
|
|
228
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
229
|
-
ON DUPLICATE KEY UPDATE
|
|
230
|
-
name = VALUES(name),
|
|
231
|
-
integration_base_url = VALUES(integration_base_url),
|
|
232
|
-
capabilities = VALUES(capabilities)`,
|
|
233
|
-
[
|
|
234
|
-
app.id,
|
|
235
|
-
app.slug,
|
|
236
|
-
app.name,
|
|
237
|
-
app.front_inbox_id,
|
|
238
|
-
app.instructor_teammate_id || null,
|
|
239
|
-
app.stripe_account_id || null,
|
|
240
|
-
app.stripe_connected || false,
|
|
241
|
-
app.integration_base_url,
|
|
242
|
-
app.webhook_secret,
|
|
243
|
-
JSON.stringify(app.capabilities || []),
|
|
244
|
-
app.auto_approve_refund_days || 30,
|
|
245
|
-
app.auto_approve_transfer_days || 14,
|
|
246
|
-
]
|
|
247
|
-
)
|
|
248
|
-
|
|
249
|
-
// Seed default trust scores for this app
|
|
250
|
-
const categories = ['refund', 'access', 'technical', 'general', 'transfer']
|
|
251
|
-
for (const category of categories) {
|
|
252
|
-
const id = `ts_${app.id}_${category}`
|
|
253
|
-
await connection.execute(
|
|
254
|
-
`INSERT INTO SUPPORT_trust_scores (id, app_id, category, trust_score, sample_count)
|
|
255
|
-
VALUES (?, ?, ?, 0.75, 25)
|
|
256
|
-
ON DUPLICATE KEY UPDATE id = id`,
|
|
257
|
-
[id, app.id, category]
|
|
258
|
-
)
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return apps.length
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
async function seedKnowledgeBase(
|
|
266
|
-
docs: KnowledgeDoc[],
|
|
267
|
-
showProgress: boolean
|
|
268
|
-
): Promise<number> {
|
|
269
|
-
if (docs.length === 0) return 0
|
|
270
|
-
|
|
271
|
-
const qdrantUrl = process.env.QDRANT_URL || 'http://localhost:6333'
|
|
272
|
-
const collection = process.env.QDRANT_COLLECTION || 'knowledge'
|
|
273
|
-
const ollamaUrl = process.env.OLLAMA_BASE_URL || 'http://localhost:11434'
|
|
274
|
-
const embeddingModel = process.env.EMBEDDING_MODEL || 'mxbai-embed-large'
|
|
275
|
-
|
|
276
|
-
// Determine vector size based on model
|
|
277
|
-
const vectorSize = embeddingModel.includes('mxbai') ? 1024 : 768
|
|
278
|
-
|
|
279
|
-
// Ensure Qdrant collection exists
|
|
280
|
-
const existsRes = await fetch(`${qdrantUrl}/collections/${collection}`)
|
|
281
|
-
|
|
282
|
-
if (existsRes.status === 404) {
|
|
283
|
-
const createRes = await fetch(`${qdrantUrl}/collections/${collection}`, {
|
|
284
|
-
method: 'PUT',
|
|
285
|
-
headers: { 'Content-Type': 'application/json' },
|
|
286
|
-
body: JSON.stringify({
|
|
287
|
-
vectors: {
|
|
288
|
-
size: vectorSize,
|
|
289
|
-
distance: 'Cosine',
|
|
290
|
-
},
|
|
291
|
-
}),
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
if (!createRes.ok) {
|
|
295
|
-
const error = await createRes.text()
|
|
296
|
-
throw new Error(`Failed to create Qdrant collection: ${error}`)
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Check if Ollama is available
|
|
301
|
-
try {
|
|
302
|
-
const healthRes = await fetch(`${ollamaUrl}/api/tags`)
|
|
303
|
-
if (!healthRes.ok) {
|
|
304
|
-
throw new Error('Ollama is not responding')
|
|
305
|
-
}
|
|
306
|
-
} catch (error) {
|
|
307
|
-
throw new Error(
|
|
308
|
-
`Ollama not available at ${ollamaUrl}. ` +
|
|
309
|
-
'Make sure Ollama is running: ollama serve'
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
let embeddedCount = 0
|
|
314
|
-
const batchSize = 5
|
|
315
|
-
const points: QdrantPoint[] = []
|
|
316
|
-
|
|
317
|
-
for (let i = 0; i < docs.length; i++) {
|
|
318
|
-
const doc = docs[i]
|
|
319
|
-
if (!doc) continue
|
|
320
|
-
|
|
321
|
-
try {
|
|
322
|
-
// Generate embedding via Ollama
|
|
323
|
-
const embedRes = await fetch(`${ollamaUrl}/api/embed`, {
|
|
324
|
-
method: 'POST',
|
|
325
|
-
headers: { 'Content-Type': 'application/json' },
|
|
326
|
-
body: JSON.stringify({
|
|
327
|
-
model: embeddingModel,
|
|
328
|
-
input: doc.content,
|
|
329
|
-
}),
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
if (!embedRes.ok) {
|
|
333
|
-
const error = await embedRes.text()
|
|
334
|
-
throw new Error(`Embedding failed: ${error}`)
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const embedData = (await embedRes.json()) as {
|
|
338
|
-
embeddings?: number[][]
|
|
339
|
-
embedding?: number[]
|
|
340
|
-
}
|
|
341
|
-
const vector = embedData.embeddings?.[0] ?? embedData.embedding
|
|
342
|
-
|
|
343
|
-
if (!vector) {
|
|
344
|
-
throw new Error('No embedding returned from Ollama')
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
points.push({
|
|
348
|
-
id: doc.id,
|
|
349
|
-
vector,
|
|
350
|
-
payload: {
|
|
351
|
-
content: doc.content,
|
|
352
|
-
title: doc.title,
|
|
353
|
-
type: doc.type,
|
|
354
|
-
app: doc.app,
|
|
355
|
-
tags: doc.tags,
|
|
356
|
-
},
|
|
357
|
-
})
|
|
358
|
-
|
|
359
|
-
embeddedCount++
|
|
360
|
-
|
|
361
|
-
if (showProgress) {
|
|
362
|
-
process.stdout.write(`\r Embedded: ${embeddedCount}/${docs.length}`)
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Batch upsert every N documents or at the end
|
|
366
|
-
if (points.length >= batchSize || i === docs.length - 1) {
|
|
367
|
-
const upsertRes = await fetch(
|
|
368
|
-
`${qdrantUrl}/collections/${collection}/points`,
|
|
369
|
-
{
|
|
370
|
-
method: 'PUT',
|
|
371
|
-
headers: { 'Content-Type': 'application/json' },
|
|
372
|
-
body: JSON.stringify({ points }),
|
|
373
|
-
}
|
|
374
|
-
)
|
|
375
|
-
|
|
376
|
-
if (!upsertRes.ok) {
|
|
377
|
-
const error = await upsertRes.text()
|
|
378
|
-
throw new Error(`Failed to upsert points: ${error}`)
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
points.length = 0 // Clear batch
|
|
382
|
-
}
|
|
383
|
-
} catch (error) {
|
|
384
|
-
if (showProgress) {
|
|
385
|
-
console.error(`\n Failed to embed ${doc.title}:`, error)
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (showProgress) {
|
|
391
|
-
console.log('') // New line after progress
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
return embeddedCount
|
|
395
|
-
}
|