@hyperfixi/patterns-reference 2.0.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.
@@ -0,0 +1,769 @@
1
+ 'use strict';
2
+
3
+ var Database = require('better-sqlite3');
4
+ var url = require('url');
5
+ var path = require('path');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var Database__default = /*#__PURE__*/_interopDefault(Database);
10
+
11
+ // ../../node_modules/tsup/assets/cjs_shims.js
12
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
13
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
14
+ var __filename2 = url.fileURLToPath(importMetaUrl);
15
+ var __dirname$1 = path.dirname(__filename2);
16
+ var DEFAULT_DB_PATH = process.env.LSP_DB_PATH || process.env.HYPERSCRIPT_LSP_DB || path.join(__dirname$1, "../data/patterns.db");
17
+ var dbInstance = null;
18
+ var currentDbPath = null;
19
+ function getDatabase(options = {}) {
20
+ const dbPath = options.dbPath ?? DEFAULT_DB_PATH;
21
+ if (dbInstance !== null && currentDbPath === dbPath) {
22
+ return dbInstance;
23
+ }
24
+ if (dbInstance !== null) {
25
+ dbInstance.close();
26
+ }
27
+ dbInstance = new Database__default.default(dbPath, {
28
+ readonly: options.readonly ?? false
29
+ });
30
+ dbInstance.pragma("foreign_keys = ON");
31
+ currentDbPath = dbPath;
32
+ return dbInstance;
33
+ }
34
+
35
+ // src/api/patterns.ts
36
+ async function getPatternById(id, options) {
37
+ const db = getDatabase({ ...options, readonly: true });
38
+ const row = db.prepare(
39
+ `
40
+ SELECT id, title, raw_code, description, feature, engine, created_at
41
+ FROM code_examples
42
+ WHERE id = ?
43
+ `
44
+ ).get(id);
45
+ return row ? mapRowToPattern(row) : null;
46
+ }
47
+ async function getPatternsByCategory(category, options) {
48
+ const db = getDatabase({ ...options, readonly: true });
49
+ const rows = db.prepare(
50
+ `
51
+ SELECT id, title, raw_code, description, feature, engine, created_at
52
+ FROM code_examples
53
+ WHERE feature = ?
54
+ ORDER BY title
55
+ `
56
+ ).all(category);
57
+ return rows.map(mapRowToPattern);
58
+ }
59
+ async function getPatternsByCommand(command, options) {
60
+ const db = getDatabase({ ...options, readonly: true });
61
+ const rows = db.prepare(
62
+ `
63
+ SELECT id, title, raw_code, description, feature, engine, created_at
64
+ FROM code_examples
65
+ WHERE raw_code LIKE ?
66
+ ORDER BY title
67
+ `
68
+ ).all(`%${command}%`);
69
+ return rows.filter((row) => new RegExp(`\\b${command}\\b`, "i").test(row.raw_code)).map(mapRowToPattern);
70
+ }
71
+ async function searchPatterns(query, searchOptions = {}, connOptions) {
72
+ const db = getDatabase({ ...connOptions, readonly: true });
73
+ const { limit = 50, offset = 0 } = searchOptions;
74
+ const rows = db.prepare(
75
+ `
76
+ SELECT id, title, raw_code, description, feature, engine, created_at
77
+ FROM code_examples
78
+ WHERE title LIKE ? OR raw_code LIKE ? OR description LIKE ?
79
+ ORDER BY title
80
+ LIMIT ? OFFSET ?
81
+ `
82
+ ).all(`%${query}%`, `%${query}%`, `%${query}%`, limit, offset);
83
+ return rows.map(mapRowToPattern);
84
+ }
85
+ async function getAllPatterns(searchOptions = {}, connOptions) {
86
+ const db = getDatabase({ ...connOptions, readonly: true });
87
+ const { limit = 1e3, offset = 0 } = searchOptions;
88
+ const rows = db.prepare(
89
+ `
90
+ SELECT id, title, raw_code, description, feature, engine, created_at
91
+ FROM code_examples
92
+ ORDER BY title
93
+ LIMIT ? OFFSET ?
94
+ `
95
+ ).all(limit, offset);
96
+ return rows.map(mapRowToPattern);
97
+ }
98
+ async function getPatternStats(connOptions) {
99
+ const db = getDatabase({ ...connOptions, readonly: true });
100
+ const patternCount = db.prepare("SELECT COUNT(*) as count FROM code_examples").get();
101
+ const translationCount = db.prepare("SELECT COUNT(*) as count FROM pattern_translations").get();
102
+ const byLangRows = db.prepare(
103
+ `
104
+ SELECT
105
+ language,
106
+ COUNT(*) as count,
107
+ SUM(verified_parses) as verified_count
108
+ FROM pattern_translations
109
+ GROUP BY language
110
+ `
111
+ ).all();
112
+ const byLanguage = {};
113
+ for (const row of byLangRows) {
114
+ byLanguage[row.language] = {
115
+ count: row.count,
116
+ verifiedCount: row.verified_count
117
+ };
118
+ }
119
+ const byCatRows = db.prepare(
120
+ `
121
+ SELECT feature, COUNT(*) as count
122
+ FROM code_examples
123
+ WHERE feature IS NOT NULL
124
+ GROUP BY feature
125
+ `
126
+ ).all();
127
+ const byCategory = {};
128
+ for (const row of byCatRows) {
129
+ byCategory[row.feature] = row.count;
130
+ }
131
+ const avgConfResult = db.prepare("SELECT AVG(confidence) as avg FROM pattern_translations WHERE confidence > 0").get();
132
+ return {
133
+ totalPatterns: patternCount.count,
134
+ totalTranslations: translationCount.count,
135
+ byLanguage,
136
+ byCategory,
137
+ avgConfidence: avgConfResult.avg || 0
138
+ };
139
+ }
140
+ function mapRowToPattern(row) {
141
+ return {
142
+ id: row.id,
143
+ title: row.title,
144
+ description: row.description,
145
+ rawCode: row.raw_code,
146
+ category: row.feature,
147
+ primaryCommand: extractPrimaryCommand(row.raw_code),
148
+ tags: extractTags(row.raw_code),
149
+ difficulty: inferDifficulty(row.raw_code),
150
+ engine: row.engine || null,
151
+ createdAt: new Date(row.created_at)
152
+ };
153
+ }
154
+ function extractPrimaryCommand(code) {
155
+ const match = code.match(/^(on|toggle|put|set|add|remove|show|hide|wait|log|send|fetch|call)\b/i);
156
+ return match ? match[1].toLowerCase() : null;
157
+ }
158
+ function extractTags(code) {
159
+ const tags = [];
160
+ if (code.includes(".")) tags.push("class");
161
+ if (code.includes("#")) tags.push("id");
162
+ if (code.includes("on ")) tags.push("event");
163
+ if (code.includes("fetch")) tags.push("async");
164
+ if (code.includes("wait")) tags.push("timing");
165
+ return tags;
166
+ }
167
+ function inferDifficulty(code) {
168
+ const lines = code.split("\n").filter((l) => l.trim()).length;
169
+ if (lines === 1 && !code.includes("then")) return "beginner";
170
+ if (lines <= 3) return "intermediate";
171
+ return "advanced";
172
+ }
173
+
174
+ // src/api/translations.ts
175
+ async function getTranslation(patternId, language, options) {
176
+ const db = getDatabase({ ...options, readonly: true });
177
+ const row = db.prepare(
178
+ `
179
+ SELECT * FROM pattern_translations
180
+ WHERE code_example_id = ? AND language = ?
181
+ `
182
+ ).get(patternId, language);
183
+ return row ? mapRowToTranslation(row) : null;
184
+ }
185
+ async function getAllTranslations(patternId, options) {
186
+ const db = getDatabase({ ...options, readonly: true });
187
+ const rows = db.prepare(
188
+ `
189
+ SELECT * FROM pattern_translations
190
+ WHERE code_example_id = ?
191
+ ORDER BY language
192
+ `
193
+ ).all(patternId);
194
+ return rows.map(mapRowToTranslation);
195
+ }
196
+ async function getTranslationsByLanguage(language, limit = 100, options) {
197
+ const db = getDatabase({ ...options, readonly: true });
198
+ const rows = db.prepare(
199
+ `
200
+ SELECT * FROM pattern_translations
201
+ WHERE language = ?
202
+ ORDER BY confidence DESC
203
+ LIMIT ?
204
+ `
205
+ ).all(language, limit);
206
+ return rows.map(mapRowToTranslation);
207
+ }
208
+ async function getVerifiedTranslations(language, limit = 100, options) {
209
+ const db = getDatabase({ ...options, readonly: true });
210
+ const rows = db.prepare(
211
+ `
212
+ SELECT * FROM pattern_translations
213
+ WHERE language = ? AND verified_parses = 1
214
+ ORDER BY confidence DESC
215
+ LIMIT ?
216
+ `
217
+ ).all(language, limit);
218
+ return rows.map(mapRowToTranslation);
219
+ }
220
+ async function getHighConfidenceTranslations(minConfidence = 0.8, limit = 100, options) {
221
+ const db = getDatabase({ ...options, readonly: true });
222
+ const rows = db.prepare(
223
+ `
224
+ SELECT * FROM pattern_translations
225
+ WHERE confidence >= ? AND verified_parses = 1
226
+ ORDER BY confidence DESC
227
+ LIMIT ?
228
+ `
229
+ ).all(minConfidence, limit);
230
+ return rows.map(mapRowToTranslation);
231
+ }
232
+ async function verifyTranslation(translation, options) {
233
+ let parseSuccess = false;
234
+ let errorMessage = null;
235
+ let confidence = translation.confidence;
236
+ try {
237
+ const { canParse, parse } = await import('@lokascript/semantic');
238
+ if (canParse(translation.hyperscript, translation.language)) {
239
+ parse(translation.hyperscript, translation.language);
240
+ parseSuccess = true;
241
+ } else {
242
+ errorMessage = "canParse returned false";
243
+ }
244
+ } catch (e) {
245
+ errorMessage = e.message;
246
+ }
247
+ const db = getDatabase(options);
248
+ db.prepare(
249
+ `
250
+ UPDATE pattern_translations
251
+ SET verified_parses = ?, updated_at = datetime('now')
252
+ WHERE id = ?
253
+ `
254
+ ).run(parseSuccess ? 1 : 0, translation.id);
255
+ db.prepare(
256
+ `
257
+ INSERT INTO pattern_tests
258
+ (code_example_id, language, test_date, parse_success, error_message)
259
+ VALUES (?, ?, datetime('now'), ?, ?)
260
+ `
261
+ ).run(translation.codeExampleId, translation.language, parseSuccess ? 1 : 0, errorMessage);
262
+ return {
263
+ translation,
264
+ parseSuccess,
265
+ executeSuccess: false,
266
+ // Not implemented yet
267
+ errorMessage,
268
+ confidence,
269
+ testedAt: /* @__PURE__ */ new Date()
270
+ };
271
+ }
272
+ async function getTranslationStats(options) {
273
+ const db = getDatabase({ ...options, readonly: true });
274
+ const rows = db.prepare(
275
+ `
276
+ SELECT
277
+ language,
278
+ COUNT(*) as total,
279
+ SUM(verified_parses) as verified,
280
+ AVG(confidence) as avg_confidence
281
+ FROM pattern_translations
282
+ GROUP BY language
283
+ `
284
+ ).all();
285
+ const stats = {};
286
+ for (const row of rows) {
287
+ stats[row.language] = {
288
+ total: row.total,
289
+ verified: row.verified,
290
+ avgConfidence: row.avg_confidence || 0
291
+ };
292
+ }
293
+ return stats;
294
+ }
295
+ function mapRowToTranslation(row) {
296
+ return {
297
+ id: row.id,
298
+ codeExampleId: row.code_example_id,
299
+ language: row.language,
300
+ hyperscript: row.hyperscript,
301
+ wordOrder: row.word_order,
302
+ translationMethod: row.translation_method,
303
+ confidence: row.confidence,
304
+ verifiedParses: row.verified_parses === 1,
305
+ verifiedExecutes: row.verified_executes === 1,
306
+ roleAlignmentScore: row.role_alignment_score ?? null,
307
+ createdAt: new Date(row.created_at),
308
+ updatedAt: new Date(row.updated_at)
309
+ };
310
+ }
311
+ function getWordOrder(language) {
312
+ const wordOrders = {
313
+ en: "SVO",
314
+ es: "SVO",
315
+ fr: "SVO",
316
+ pt: "SVO",
317
+ id: "SVO",
318
+ sw: "SVO",
319
+ zh: "SVO",
320
+ ja: "SOV",
321
+ ko: "SOV",
322
+ tr: "SOV",
323
+ qu: "SOV",
324
+ ar: "VSO",
325
+ de: "V2"
326
+ };
327
+ return wordOrders[language] || "SVO";
328
+ }
329
+
330
+ // src/api/llm.ts
331
+ async function getLLMExamples(prompt, language = "en", limit = 5, options) {
332
+ const db = getDatabase({ ...options, readonly: true });
333
+ const keywords = extractKeywords(prompt);
334
+ if (keywords.length === 0) {
335
+ const rows2 = db.prepare(
336
+ `
337
+ SELECT * FROM llm_examples
338
+ WHERE language = ?
339
+ ORDER BY quality_score DESC, usage_count DESC
340
+ LIMIT ?
341
+ `
342
+ ).all(language, limit);
343
+ trackUsage(
344
+ db,
345
+ rows2.map((r) => r.id)
346
+ );
347
+ return rows2.map(mapRowToLLMExample);
348
+ }
349
+ const likeClauses = keywords.map(() => "(prompt LIKE ? OR completion LIKE ?)").join(" OR ");
350
+ const params = keywords.flatMap((k) => [`%${k}%`, `%${k}%`]);
351
+ const rows = db.prepare(
352
+ `
353
+ SELECT * FROM llm_examples
354
+ WHERE language = ? AND (${likeClauses})
355
+ ORDER BY quality_score DESC
356
+ LIMIT ?
357
+ `
358
+ ).all(language, ...params, limit);
359
+ trackUsage(
360
+ db,
361
+ rows.map((r) => r.id)
362
+ );
363
+ return rows.map(mapRowToLLMExample);
364
+ }
365
+ async function getExamplesByCommand(command, language = "en", limit = 5, options) {
366
+ const db = getDatabase({ ...options, readonly: true });
367
+ const rows = db.prepare(
368
+ `
369
+ SELECT * FROM llm_examples
370
+ WHERE language = ? AND completion LIKE ?
371
+ ORDER BY quality_score DESC
372
+ LIMIT ?
373
+ `
374
+ ).all(language, `%${command}%`, limit);
375
+ return rows.map(mapRowToLLMExample);
376
+ }
377
+ async function getHighQualityExamples(language = "en", minQuality = 0.8, limit = 10, options) {
378
+ const db = getDatabase({ ...options, readonly: true });
379
+ const rows = db.prepare(
380
+ `
381
+ SELECT * FROM llm_examples
382
+ WHERE language = ? AND quality_score >= ?
383
+ ORDER BY quality_score DESC, usage_count DESC
384
+ LIMIT ?
385
+ `
386
+ ).all(language, minQuality, limit);
387
+ return rows.map(mapRowToLLMExample);
388
+ }
389
+ async function getMostUsedExamples(language = "en", limit = 10, options) {
390
+ const db = getDatabase({ ...options, readonly: true });
391
+ const rows = db.prepare(
392
+ `
393
+ SELECT * FROM llm_examples
394
+ WHERE language = ?
395
+ ORDER BY usage_count DESC, quality_score DESC
396
+ LIMIT ?
397
+ `
398
+ ).all(language, limit);
399
+ return rows.map(mapRowToLLMExample);
400
+ }
401
+ async function buildFewShotContext(prompt, language = "en", numExamples = 3, options) {
402
+ const examples = await getLLMExamples(prompt, language, numExamples, options);
403
+ if (examples.length === 0) {
404
+ return "";
405
+ }
406
+ let context = "Here are some example hyperscript patterns:\n\n";
407
+ for (const ex of examples) {
408
+ context += `Task: ${ex.prompt}
409
+ `;
410
+ context += `Code: ${ex.completion}
411
+
412
+ `;
413
+ }
414
+ context += `Now generate hyperscript for: ${prompt}
415
+ `;
416
+ return context;
417
+ }
418
+ async function addLLMExample(example, options) {
419
+ const db = getDatabase(options);
420
+ const result = db.prepare(
421
+ `
422
+ INSERT INTO llm_examples
423
+ (code_example_id, language, prompt, completion, quality_score, usage_count, created_at)
424
+ VALUES (?, ?, ?, ?, ?, 0, datetime('now'))
425
+ `
426
+ ).run(
427
+ example.patternId,
428
+ example.language,
429
+ example.prompt,
430
+ example.completion,
431
+ example.qualityScore
432
+ );
433
+ return result.lastInsertRowid;
434
+ }
435
+ async function updateQualityScore(id, qualityScore, options) {
436
+ const db = getDatabase(options);
437
+ db.prepare(
438
+ `
439
+ UPDATE llm_examples SET quality_score = ? WHERE id = ?
440
+ `
441
+ ).run(qualityScore, id);
442
+ }
443
+ async function getLLMStats(options) {
444
+ const db = getDatabase({ ...options, readonly: true });
445
+ const totalResult = db.prepare("SELECT COUNT(*) as count FROM llm_examples").get();
446
+ const byLangResult = db.prepare(
447
+ `
448
+ SELECT language, COUNT(*) as count
449
+ FROM llm_examples
450
+ GROUP BY language
451
+ `
452
+ ).all();
453
+ const avgResult = db.prepare("SELECT AVG(quality_score) as avg FROM llm_examples").get();
454
+ const usageResult = db.prepare("SELECT SUM(usage_count) as total FROM llm_examples").get();
455
+ const byLanguage = {};
456
+ for (const { language, count } of byLangResult) {
457
+ byLanguage[language] = count;
458
+ }
459
+ return {
460
+ total: totalResult.count,
461
+ byLanguage,
462
+ avgQuality: avgResult.avg || 0,
463
+ totalUsage: usageResult.total || 0
464
+ };
465
+ }
466
+ function extractKeywords(prompt) {
467
+ const stopWords = /* @__PURE__ */ new Set([
468
+ "a",
469
+ "an",
470
+ "the",
471
+ "to",
472
+ "on",
473
+ "in",
474
+ "for",
475
+ "is",
476
+ "it",
477
+ "when",
478
+ "i",
479
+ "want",
480
+ "need",
481
+ "create",
482
+ "make",
483
+ "please",
484
+ "can",
485
+ "you",
486
+ "would",
487
+ "should",
488
+ "like",
489
+ "that",
490
+ "this",
491
+ "with",
492
+ "from"
493
+ ]);
494
+ return prompt.toLowerCase().split(/\W+/).filter((word) => word.length > 2 && !stopWords.has(word));
495
+ }
496
+ function trackUsage(db, ids) {
497
+ if (ids.length === 0) return;
498
+ try {
499
+ const stmt = db.prepare(`
500
+ UPDATE llm_examples SET usage_count = usage_count + 1 WHERE id = ?
501
+ `);
502
+ for (const id of ids) {
503
+ stmt.run(id);
504
+ }
505
+ } catch {
506
+ }
507
+ }
508
+ function mapRowToLLMExample(row) {
509
+ return {
510
+ id: row.id,
511
+ patternId: row.code_example_id,
512
+ language: row.language,
513
+ prompt: row.prompt,
514
+ completion: row.completion,
515
+ qualityScore: row.quality_score,
516
+ usageCount: row.usage_count,
517
+ createdAt: new Date(row.created_at)
518
+ };
519
+ }
520
+
521
+ // src/api/roles.ts
522
+ async function getPatternRoles(patternId, options) {
523
+ const db = getDatabase({ ...options, readonly: true });
524
+ const rows = db.prepare(
525
+ `
526
+ SELECT id, code_example_id, command_index, role, role_value, role_type, required
527
+ FROM pattern_roles
528
+ WHERE code_example_id = ?
529
+ ORDER BY command_index, role
530
+ `
531
+ ).all(patternId);
532
+ return rows.map(mapRowToPatternRole);
533
+ }
534
+ async function getPatternsByRole(role, options) {
535
+ const db = getDatabase({ ...options, readonly: true });
536
+ const rows = db.prepare(
537
+ `
538
+ SELECT DISTINCT ce.id, ce.title, ce.raw_code, ce.description, ce.feature, ce.engine, ce.created_at
539
+ FROM code_examples ce
540
+ INNER JOIN pattern_roles pr ON ce.id = pr.code_example_id
541
+ WHERE pr.role = ?
542
+ ORDER BY ce.title
543
+ `
544
+ ).all(role);
545
+ return rows.map(mapRowToPattern2);
546
+ }
547
+ async function getPatternsByRoles(roles, matchMode = "any", options) {
548
+ if (roles.length === 0) return [];
549
+ const db = getDatabase({ ...options, readonly: true });
550
+ if (matchMode === "any") {
551
+ const placeholders = roles.map(() => "?").join(", ");
552
+ const rows = db.prepare(
553
+ `
554
+ SELECT DISTINCT ce.id, ce.title, ce.raw_code, ce.description, ce.feature, ce.engine, ce.created_at
555
+ FROM code_examples ce
556
+ INNER JOIN pattern_roles pr ON ce.id = pr.code_example_id
557
+ WHERE pr.role IN (${placeholders})
558
+ ORDER BY ce.title
559
+ `
560
+ ).all(...roles);
561
+ return rows.map(mapRowToPattern2);
562
+ } else {
563
+ const placeholders = roles.map(() => "?").join(", ");
564
+ const rows = db.prepare(
565
+ `
566
+ SELECT ce.id, ce.title, ce.raw_code, ce.description, ce.feature, ce.engine, ce.created_at
567
+ FROM code_examples ce
568
+ WHERE (
569
+ SELECT COUNT(DISTINCT pr.role)
570
+ FROM pattern_roles pr
571
+ WHERE pr.code_example_id = ce.id AND pr.role IN (${placeholders})
572
+ ) = ?
573
+ ORDER BY ce.title
574
+ `
575
+ ).all(...roles, roles.length);
576
+ return rows.map(mapRowToPattern2);
577
+ }
578
+ }
579
+ async function getPatternsByRoleValue(role, value, options) {
580
+ const db = getDatabase({ ...options, readonly: true });
581
+ const rows = db.prepare(
582
+ `
583
+ SELECT DISTINCT ce.id, ce.title, ce.raw_code, ce.description, ce.feature, ce.engine, ce.created_at
584
+ FROM code_examples ce
585
+ INNER JOIN pattern_roles pr ON ce.id = pr.code_example_id
586
+ WHERE pr.role = ? AND pr.role_value LIKE ?
587
+ ORDER BY ce.title
588
+ `
589
+ ).all(role, `%${value}%`);
590
+ return rows.map(mapRowToPattern2);
591
+ }
592
+ async function getRoleStats(options) {
593
+ const db = getDatabase({ ...options, readonly: true });
594
+ const totalRow = db.prepare("SELECT COUNT(*) as count FROM pattern_roles").get();
595
+ const roleRows = db.prepare(
596
+ `
597
+ SELECT role, COUNT(*) as count
598
+ FROM pattern_roles
599
+ GROUP BY role
600
+ ORDER BY count DESC
601
+ `
602
+ ).all();
603
+ const byRole = {};
604
+ for (const row of roleRows) {
605
+ byRole[row.role] = row.count;
606
+ }
607
+ const typeRows = db.prepare(
608
+ `
609
+ SELECT role_type, COUNT(*) as count
610
+ FROM pattern_roles
611
+ WHERE role_type IS NOT NULL
612
+ GROUP BY role_type
613
+ `
614
+ ).all();
615
+ const byRoleType = {};
616
+ for (const row of typeRows) {
617
+ byRoleType[row.role_type] = row.count;
618
+ }
619
+ const valueRows = db.prepare(
620
+ `
621
+ SELECT role, role_value, COUNT(*) as count
622
+ FROM pattern_roles
623
+ WHERE role_value IS NOT NULL
624
+ GROUP BY role, role_value
625
+ ORDER BY count DESC
626
+ LIMIT 20
627
+ `
628
+ ).all();
629
+ const topRoleValues = valueRows.map((row) => ({
630
+ role: row.role,
631
+ value: row.role_value,
632
+ count: row.count
633
+ }));
634
+ const withRolesRow = db.prepare(
635
+ `
636
+ SELECT COUNT(DISTINCT code_example_id) as count
637
+ FROM pattern_roles
638
+ `
639
+ ).get();
640
+ const totalPatternsRow = db.prepare("SELECT COUNT(*) as count FROM code_examples").get();
641
+ return {
642
+ totalRoles: totalRow.count,
643
+ byRole,
644
+ byRoleType,
645
+ topRoleValues,
646
+ patternsWithRoles: withRolesRow.count,
647
+ patternsWithoutRoles: totalPatternsRow.count - withRolesRow.count
648
+ };
649
+ }
650
+ async function getRolesByCommand(command, options) {
651
+ const db = getDatabase({ ...options, readonly: true });
652
+ const rows = db.prepare(
653
+ `
654
+ SELECT pr.role, COUNT(*) as count
655
+ FROM pattern_roles pr
656
+ INNER JOIN code_examples ce ON pr.code_example_id = ce.id
657
+ WHERE ce.raw_code LIKE ?
658
+ GROUP BY pr.role
659
+ `
660
+ ).all(`%${command}%`);
661
+ const result = {};
662
+ for (const row of rows) {
663
+ result[row.role] = row.count;
664
+ }
665
+ return result;
666
+ }
667
+ async function insertPatternRole(role, options) {
668
+ const db = getDatabase(options);
669
+ const result = db.prepare(
670
+ `
671
+ INSERT INTO pattern_roles (code_example_id, command_index, role, role_value, role_type, required)
672
+ VALUES (?, ?, ?, ?, ?, ?)
673
+ `
674
+ ).run(
675
+ role.codeExampleId,
676
+ role.commandIndex,
677
+ role.role,
678
+ role.roleValue,
679
+ role.roleType,
680
+ role.required ? 1 : 0
681
+ );
682
+ return result.lastInsertRowid;
683
+ }
684
+ async function deletePatternRoles(patternId, options) {
685
+ const db = getDatabase(options);
686
+ const result = db.prepare("DELETE FROM pattern_roles WHERE code_example_id = ?").run(patternId);
687
+ return result.changes;
688
+ }
689
+ async function clearAllRoles(options) {
690
+ const db = getDatabase(options);
691
+ const result = db.prepare("DELETE FROM pattern_roles").run();
692
+ return result.changes;
693
+ }
694
+ function mapRowToPatternRole(row) {
695
+ return {
696
+ id: row.id,
697
+ codeExampleId: row.code_example_id,
698
+ commandIndex: row.command_index,
699
+ role: row.role,
700
+ roleValue: row.role_value,
701
+ roleType: row.role_type,
702
+ required: Boolean(row.required)
703
+ };
704
+ }
705
+ function mapRowToPattern2(row) {
706
+ return {
707
+ id: row.id,
708
+ title: row.title,
709
+ description: row.description,
710
+ rawCode: row.raw_code,
711
+ category: row.feature,
712
+ primaryCommand: extractPrimaryCommand2(row.raw_code),
713
+ tags: extractTags2(row.raw_code),
714
+ difficulty: inferDifficulty2(row.raw_code),
715
+ engine: row.engine || null,
716
+ createdAt: new Date(row.created_at)
717
+ };
718
+ }
719
+ function extractPrimaryCommand2(code) {
720
+ const match = code.match(/^(on|toggle|put|set|add|remove|show|hide|wait|log|send|fetch|call)\b/i);
721
+ return match ? match[1].toLowerCase() : null;
722
+ }
723
+ function extractTags2(code) {
724
+ const tags = [];
725
+ if (code.includes(".")) tags.push("class");
726
+ if (code.includes("#")) tags.push("id");
727
+ if (code.includes("on ")) tags.push("event");
728
+ if (code.includes("fetch")) tags.push("async");
729
+ if (code.includes("wait")) tags.push("timing");
730
+ return tags;
731
+ }
732
+ function inferDifficulty2(code) {
733
+ const lines = code.split("\n").filter((l) => l.trim()).length;
734
+ if (lines === 1 && !code.includes("then")) return "beginner";
735
+ if (lines <= 3) return "intermediate";
736
+ return "advanced";
737
+ }
738
+
739
+ exports.addLLMExample = addLLMExample;
740
+ exports.buildFewShotContext = buildFewShotContext;
741
+ exports.clearAllRoles = clearAllRoles;
742
+ exports.deletePatternRoles = deletePatternRoles;
743
+ exports.getAllPatterns = getAllPatterns;
744
+ exports.getAllTranslations = getAllTranslations;
745
+ exports.getExamplesByCommand = getExamplesByCommand;
746
+ exports.getHighConfidenceTranslations = getHighConfidenceTranslations;
747
+ exports.getHighQualityExamples = getHighQualityExamples;
748
+ exports.getLLMExamples = getLLMExamples;
749
+ exports.getLLMStats = getLLMStats;
750
+ exports.getMostUsedExamples = getMostUsedExamples;
751
+ exports.getPatternById = getPatternById;
752
+ exports.getPatternRoles = getPatternRoles;
753
+ exports.getPatternStats = getPatternStats;
754
+ exports.getPatternsByCategory = getPatternsByCategory;
755
+ exports.getPatternsByCommand = getPatternsByCommand;
756
+ exports.getPatternsByRole = getPatternsByRole;
757
+ exports.getPatternsByRoleValue = getPatternsByRoleValue;
758
+ exports.getPatternsByRoles = getPatternsByRoles;
759
+ exports.getRoleStats = getRoleStats;
760
+ exports.getRolesByCommand = getRolesByCommand;
761
+ exports.getTranslation = getTranslation;
762
+ exports.getTranslationStats = getTranslationStats;
763
+ exports.getTranslationsByLanguage = getTranslationsByLanguage;
764
+ exports.getVerifiedTranslations = getVerifiedTranslations;
765
+ exports.getWordOrder = getWordOrder;
766
+ exports.insertPatternRole = insertPatternRole;
767
+ exports.searchPatterns = searchPatterns;
768
+ exports.updateQualityScore = updateQualityScore;
769
+ exports.verifyTranslation = verifyTranslation;