@hyperfixi/patterns-reference 3.1.1 → 3.3.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/CHANGELOG.md +186 -1
- package/README.md +47 -36
- package/data/engine-verification.json +58 -65
- package/data/patterns.db +0 -0
- package/data/patterns.db.stamp +1 -0
- package/dist/api/index.d.mts +2 -2
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.js +198 -98
- package/dist/api/index.mjs +197 -100
- package/dist/{index-6GkHj5yJ.d.mts → index-CoDUfq2P.d.mts} +39 -3
- package/dist/{index-6GkHj5yJ.d.ts → index-CoDUfq2P.d.ts} +39 -3
- package/dist/index.d.mts +87 -13
- package/dist/index.d.ts +87 -13
- package/dist/index.js +261 -144
- package/dist/index.mjs +258 -146
- package/dist/{llm-B5nGz8V1.d.mts → llm-CCCSw-yp.d.ts} +21 -10
- package/dist/{llm-rEdJQScF.d.ts → llm-PxnriEZ_.d.mts} +21 -10
- package/dist/sync/index.d.mts +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.js +4 -1
- package/dist/sync/index.mjs +4 -1
- package/package.json +16 -16
- package/src/adapters/llm-adapter.ts +64 -42
- package/src/api/engine-filter.ts +37 -0
- package/src/api/llm.ts +54 -64
- package/src/api/patterns.ts +92 -30
- package/src/api/roles.ts +6 -4
- package/src/api/translations.ts +34 -27
- package/src/database/connection.ts +16 -4
- package/src/html-snippets.ts +39 -10
- package/src/index.ts +12 -2
- package/src/registry/patterns-provider.ts +3 -1
- package/src/sync/db-stamp.ts +7 -4
- package/src/sync/markup-attributes.ts +15 -0
- package/src/sync/verify-parses.ts +42 -0
- package/src/types/better-sqlite3.d.ts +2 -0
- package/src/types/index.ts +44 -2
- package/src/sync/span-mask.ts +0 -166
- package/src/sync/translation-checks.ts +0 -282
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,83 @@
|
|
|
1
|
+
import { dirname, join, relative, sep, resolve } from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { canParse } from '@lokascript/semantic';
|
|
1
4
|
import Database from 'better-sqlite3';
|
|
2
5
|
import { readFileSync, writeFileSync, existsSync, statSync, readdirSync } from 'fs';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import { dirname, join, relative, sep, resolve } from 'path';
|
|
5
6
|
import { createHash } from 'crypto';
|
|
6
7
|
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
10
|
+
var __esm = (fn, res) => function __init() {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
};
|
|
13
|
+
var __export = (target, all) => {
|
|
14
|
+
for (var name in all)
|
|
15
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
|
+
};
|
|
17
|
+
var init_esm_shims = __esm({
|
|
18
|
+
"../../node_modules/tsup/assets/esm_shims.js"() {
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// src/sync/markup-attributes.ts
|
|
23
|
+
function findHyperscriptAttributes(markup) {
|
|
24
|
+
const spans = [];
|
|
25
|
+
ATTRIBUTE.lastIndex = 0;
|
|
26
|
+
let match;
|
|
27
|
+
while ((match = ATTRIBUTE.exec(markup)) !== null) {
|
|
28
|
+
const body = match[2] ?? match[3];
|
|
29
|
+
const start = match.index + match[0].length - body.length - 1;
|
|
30
|
+
spans.push({ start, end: start + body.length, body });
|
|
31
|
+
}
|
|
32
|
+
return spans;
|
|
33
|
+
}
|
|
34
|
+
function isMarkupRow(code) {
|
|
35
|
+
return /^\s*<[a-zA-Z!]/.test(code);
|
|
36
|
+
}
|
|
37
|
+
function hyperscriptBodies(code) {
|
|
38
|
+
if (!isMarkupRow(code)) return [code];
|
|
39
|
+
const bodies = findHyperscriptAttributes(code).map((span) => span.body);
|
|
40
|
+
for (const match of code.matchAll(HX_LIVE_ATTRIBUTE)) bodies.push(match[2] ?? match[3] ?? "");
|
|
41
|
+
return bodies.filter((body) => body.trim().length > 0);
|
|
42
|
+
}
|
|
43
|
+
var ATTRIBUTE, HX_LIVE_ATTRIBUTE;
|
|
44
|
+
var init_markup_attributes = __esm({
|
|
45
|
+
"src/sync/markup-attributes.ts"() {
|
|
46
|
+
init_esm_shims();
|
|
47
|
+
ATTRIBUTE = /(^|[\s"'])_\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
48
|
+
HX_LIVE_ATTRIBUTE = /(^|[\s"'])hx-live\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// src/sync/verify-parses.ts
|
|
53
|
+
var verify_parses_exports = {};
|
|
54
|
+
__export(verify_parses_exports, {
|
|
55
|
+
verifyParses: () => verifyParses
|
|
56
|
+
});
|
|
57
|
+
function verifyParses(code, language, translatable = true) {
|
|
58
|
+
const bodies = hyperscriptBodies(code);
|
|
59
|
+
if (bodies.length === 0) return false;
|
|
60
|
+
const parseLanguage = translatable ? language : "en";
|
|
61
|
+
return bodies.every((body) => {
|
|
62
|
+
try {
|
|
63
|
+
return canParse(body, parseLanguage);
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
var init_verify_parses = __esm({
|
|
70
|
+
"src/sync/verify-parses.ts"() {
|
|
71
|
+
init_esm_shims();
|
|
72
|
+
init_markup_attributes();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// src/index.ts
|
|
77
|
+
init_esm_shims();
|
|
78
|
+
|
|
7
79
|
// src/database/connection.ts
|
|
80
|
+
init_esm_shims();
|
|
8
81
|
var __filename$1 = fileURLToPath(import.meta.url);
|
|
9
82
|
var __dirname$1 = dirname(__filename$1);
|
|
10
83
|
var DEFAULT_DB_PATH = process.env.LSP_DB_PATH || process.env.HYPERSCRIPT_LSP_DB || join(__dirname$1, "../data/patterns.db");
|
|
@@ -12,10 +85,11 @@ var dbInstance = null;
|
|
|
12
85
|
var currentDbPath = null;
|
|
13
86
|
var openFileId = null;
|
|
14
87
|
var lastIdentityCheckAt = 0;
|
|
88
|
+
var openReadonly = false;
|
|
15
89
|
var IDENTITY_TTL_MS = 1e3;
|
|
16
|
-
function fileIdentity(
|
|
90
|
+
function fileIdentity(path2) {
|
|
17
91
|
try {
|
|
18
|
-
const s = statSync(
|
|
92
|
+
const s = statSync(path2);
|
|
19
93
|
return `${s.dev}:${s.ino}:${s.size}:${s.mtimeMs}`;
|
|
20
94
|
} catch {
|
|
21
95
|
return null;
|
|
@@ -26,7 +100,9 @@ function getDefaultDbPath() {
|
|
|
26
100
|
}
|
|
27
101
|
function getDatabase(options = {}) {
|
|
28
102
|
const dbPath = options.dbPath ?? DEFAULT_DB_PATH;
|
|
29
|
-
|
|
103
|
+
const readonly = options.readonly ?? false;
|
|
104
|
+
const canServe = !openReadonly || readonly;
|
|
105
|
+
if (dbInstance !== null && currentDbPath === dbPath && canServe) {
|
|
30
106
|
const now = Date.now();
|
|
31
107
|
if (now - lastIdentityCheckAt < IDENTITY_TTL_MS) {
|
|
32
108
|
return dbInstance;
|
|
@@ -42,9 +118,8 @@ function getDatabase(options = {}) {
|
|
|
42
118
|
if (dbInstance !== null) {
|
|
43
119
|
dbInstance.close();
|
|
44
120
|
}
|
|
45
|
-
dbInstance = new Database(dbPath, {
|
|
46
|
-
|
|
47
|
-
});
|
|
121
|
+
dbInstance = new Database(dbPath, { readonly });
|
|
122
|
+
openReadonly = readonly;
|
|
48
123
|
dbInstance.pragma("foreign_keys = ON");
|
|
49
124
|
currentDbPath = dbPath;
|
|
50
125
|
openFileId = fileIdentity(dbPath);
|
|
@@ -58,6 +133,7 @@ function closeDatabase() {
|
|
|
58
133
|
currentDbPath = null;
|
|
59
134
|
openFileId = null;
|
|
60
135
|
lastIdentityCheckAt = 0;
|
|
136
|
+
openReadonly = false;
|
|
61
137
|
}
|
|
62
138
|
}
|
|
63
139
|
function resetConnection() {
|
|
@@ -65,6 +141,7 @@ function resetConnection() {
|
|
|
65
141
|
currentDbPath = null;
|
|
66
142
|
openFileId = null;
|
|
67
143
|
lastIdentityCheckAt = 0;
|
|
144
|
+
openReadonly = false;
|
|
68
145
|
}
|
|
69
146
|
function isConnected() {
|
|
70
147
|
return dbInstance !== null;
|
|
@@ -73,12 +150,27 @@ function getCurrentDbPath() {
|
|
|
73
150
|
return currentDbPath;
|
|
74
151
|
}
|
|
75
152
|
|
|
153
|
+
// src/api/patterns.ts
|
|
154
|
+
init_esm_shims();
|
|
155
|
+
init_markup_attributes();
|
|
156
|
+
|
|
157
|
+
// src/api/engine-filter.ts
|
|
158
|
+
init_esm_shims();
|
|
159
|
+
function runsOn(column, engine) {
|
|
160
|
+
if (engine === null) return { sql: `${column} IS NULL`, params: [] };
|
|
161
|
+
if (engine === "both") return { sql: `${column} = 'both'`, params: [] };
|
|
162
|
+
return { sql: `${column} IN ('both', ?)`, params: [engine] };
|
|
163
|
+
}
|
|
164
|
+
function exampleCondition(column, engine) {
|
|
165
|
+
return engine === void 0 ? { sql: `${column} IS NOT NULL`, params: [] } : runsOn(column, engine);
|
|
166
|
+
}
|
|
167
|
+
|
|
76
168
|
// src/api/patterns.ts
|
|
77
169
|
async function getPatternById(id, options) {
|
|
78
170
|
const db = getDatabase({ ...options, readonly: true });
|
|
79
171
|
const row = db.prepare(
|
|
80
172
|
`
|
|
81
|
-
SELECT id, title, raw_code, description, feature, engine, created_at
|
|
173
|
+
SELECT id, title, raw_code, description, feature, engine, translatable, created_at
|
|
82
174
|
FROM code_examples
|
|
83
175
|
WHERE id = ?
|
|
84
176
|
`
|
|
@@ -89,7 +181,7 @@ async function getPatternsByCategory(category, options) {
|
|
|
89
181
|
const db = getDatabase({ ...options, readonly: true });
|
|
90
182
|
const rows = db.prepare(
|
|
91
183
|
`
|
|
92
|
-
SELECT id, title, raw_code, description, feature, engine, created_at
|
|
184
|
+
SELECT id, title, raw_code, description, feature, engine, translatable, created_at
|
|
93
185
|
FROM code_examples
|
|
94
186
|
WHERE feature = ?
|
|
95
187
|
ORDER BY title
|
|
@@ -101,7 +193,7 @@ async function getPatternsByCommand(command, options) {
|
|
|
101
193
|
const db = getDatabase({ ...options, readonly: true });
|
|
102
194
|
const rows = db.prepare(
|
|
103
195
|
`
|
|
104
|
-
SELECT id, title, raw_code, description, feature, engine, created_at
|
|
196
|
+
SELECT id, title, raw_code, description, feature, engine, translatable, created_at
|
|
105
197
|
FROM code_examples
|
|
106
198
|
WHERE raw_code LIKE ?
|
|
107
199
|
ORDER BY title
|
|
@@ -109,32 +201,45 @@ async function getPatternsByCommand(command, options) {
|
|
|
109
201
|
).all(`%${command}%`);
|
|
110
202
|
return rows.filter((row) => new RegExp(`\\b${command}\\b`, "i").test(row.raw_code)).map(mapRowToPattern);
|
|
111
203
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
204
|
+
function engineFilter(searchOptions) {
|
|
205
|
+
return searchOptions.engine === void 0 ? { sql: "1 = 1", params: [] } : runsOn("engine", searchOptions.engine);
|
|
206
|
+
}
|
|
207
|
+
function usableIn(db, language) {
|
|
115
208
|
const rows = db.prepare(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
ORDER BY title
|
|
121
|
-
LIMIT ? OFFSET ?
|
|
122
|
-
`
|
|
123
|
-
).all(`%${query}%`, `%${query}%`, `%${query}%`, limit, offset);
|
|
124
|
-
return rows.map(mapRowToPattern);
|
|
209
|
+
"SELECT code_example_id AS id FROM pattern_translations WHERE language = ? AND verified_parses = 1"
|
|
210
|
+
).all(language);
|
|
211
|
+
const verified = new Set(rows.map((row) => row.id));
|
|
212
|
+
return (pattern) => verified.has(pattern.id) || hyperscriptBodies(pattern.rawCode).length === 0;
|
|
125
213
|
}
|
|
126
|
-
|
|
214
|
+
function queryPatterns(searchOptions, defaultLimit, connOptions, match = { sql: "1 = 1", params: [] }) {
|
|
127
215
|
const db = getDatabase({ ...connOptions, readonly: true });
|
|
128
|
-
const { limit =
|
|
216
|
+
const { limit = defaultLimit, offset = 0, category, difficulty, language } = searchOptions;
|
|
217
|
+
const runs = engineFilter(searchOptions);
|
|
218
|
+
const inCategory = category === void 0 ? { sql: "1 = 1", params: [] } : { sql: "feature = ?", params: [category] };
|
|
129
219
|
const rows = db.prepare(
|
|
130
220
|
`
|
|
131
|
-
SELECT id, title, raw_code, description, feature, engine, created_at
|
|
221
|
+
SELECT id, title, raw_code, description, feature, engine, translatable, created_at
|
|
132
222
|
FROM code_examples
|
|
223
|
+
WHERE (${match.sql}) AND ${runs.sql} AND ${inCategory.sql}
|
|
133
224
|
ORDER BY title
|
|
134
|
-
LIMIT ? OFFSET ?
|
|
135
225
|
`
|
|
136
|
-
).all(
|
|
137
|
-
|
|
226
|
+
).all(...match.params, ...runs.params, ...inCategory.params);
|
|
227
|
+
const inLanguage = language === void 0 ? null : usableIn(db, language);
|
|
228
|
+
return rows.map(mapRowToPattern).filter((pattern) => difficulty === void 0 || pattern.difficulty === difficulty).filter((pattern) => inLanguage === null || inLanguage(pattern)).slice(offset, offset + limit);
|
|
229
|
+
}
|
|
230
|
+
async function searchPatterns(query, searchOptions = {}, connOptions) {
|
|
231
|
+
const like = `%${query}%`;
|
|
232
|
+
const inTranslation = searchOptions.language === void 0 ? { sql: "", params: [] } : {
|
|
233
|
+
sql: " OR id IN (SELECT code_example_id FROM pattern_translations WHERE language = ? AND hyperscript LIKE ?)",
|
|
234
|
+
params: [searchOptions.language, like]
|
|
235
|
+
};
|
|
236
|
+
return queryPatterns(searchOptions, 50, connOptions, {
|
|
237
|
+
sql: `title LIKE ? OR raw_code LIKE ? OR description LIKE ?${inTranslation.sql}`,
|
|
238
|
+
params: [like, like, like, ...inTranslation.params]
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
async function getAllPatterns(searchOptions = {}, connOptions) {
|
|
242
|
+
return queryPatterns(searchOptions, 1e3, connOptions);
|
|
138
243
|
}
|
|
139
244
|
async function getPatternStats(connOptions) {
|
|
140
245
|
const db = getDatabase({ ...connOptions, readonly: true });
|
|
@@ -193,6 +298,7 @@ function mapRowToPattern(row) {
|
|
|
193
298
|
tags: extractTags(row.raw_code),
|
|
194
299
|
difficulty: inferDifficulty(row.raw_code),
|
|
195
300
|
engine: row.engine || null,
|
|
301
|
+
translatable: row.translatable !== 0,
|
|
196
302
|
createdAt: new Date(row.created_at)
|
|
197
303
|
};
|
|
198
304
|
}
|
|
@@ -217,6 +323,7 @@ function inferDifficulty(code) {
|
|
|
217
323
|
}
|
|
218
324
|
|
|
219
325
|
// src/api/behavior-loader.ts
|
|
326
|
+
init_esm_shims();
|
|
220
327
|
async function loadBehaviors(runtime, options) {
|
|
221
328
|
const patterns = await getBehaviorPatterns(options?.connectionOptions);
|
|
222
329
|
const filtered = options?.names ? patterns.filter((p) => options.names.some((name) => p.rawCode.includes(`behavior ${name}(`))) : patterns;
|
|
@@ -245,6 +352,7 @@ async function loadBehaviors(runtime, options) {
|
|
|
245
352
|
}
|
|
246
353
|
|
|
247
354
|
// src/api/translations.ts
|
|
355
|
+
init_esm_shims();
|
|
248
356
|
async function getTranslation(patternId, language, options) {
|
|
249
357
|
const db = getDatabase({ ...options, readonly: true });
|
|
250
358
|
const row = db.prepare(
|
|
@@ -306,32 +414,35 @@ async function verifyTranslation(translation, options) {
|
|
|
306
414
|
let parseSuccess = false;
|
|
307
415
|
let errorMessage = null;
|
|
308
416
|
let confidence = translation.confidence;
|
|
417
|
+
const db = getDatabase(options);
|
|
418
|
+
const example = db.prepare("SELECT translatable FROM code_examples WHERE id = ?").get(translation.codeExampleId);
|
|
309
419
|
try {
|
|
310
|
-
const {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
420
|
+
const { verifyParses: verifyParses2 } = await Promise.resolve().then(() => (init_verify_parses(), verify_parses_exports));
|
|
421
|
+
parseSuccess = verifyParses2(
|
|
422
|
+
translation.hyperscript,
|
|
423
|
+
translation.language,
|
|
424
|
+
example?.translatable !== 0
|
|
425
|
+
);
|
|
426
|
+
if (!parseSuccess) errorMessage = "the semantic parser rejected it (or it has no hyperscript)";
|
|
317
427
|
} catch (e) {
|
|
318
428
|
errorMessage = e.message;
|
|
319
429
|
}
|
|
320
|
-
|
|
321
|
-
|
|
430
|
+
db.transaction(() => {
|
|
431
|
+
db.prepare(
|
|
432
|
+
`
|
|
433
|
+
UPDATE pattern_translations
|
|
434
|
+
SET verified_parses = ?, updated_at = datetime('now')
|
|
435
|
+
WHERE id = ?
|
|
322
436
|
`
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
437
|
+
).run(parseSuccess ? 1 : 0, translation.id);
|
|
438
|
+
db.prepare(
|
|
439
|
+
`
|
|
440
|
+
INSERT INTO pattern_tests
|
|
441
|
+
(code_example_id, language, test_type, success, error_message, test_date)
|
|
442
|
+
VALUES (?, ?, 'parse', ?, ?, datetime('now'))
|
|
329
443
|
`
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
VALUES (?, ?, datetime('now'), ?, ?)
|
|
333
|
-
`
|
|
334
|
-
).run(translation.codeExampleId, translation.language, parseSuccess ? 1 : 0, errorMessage);
|
|
444
|
+
).run(translation.codeExampleId, translation.language, parseSuccess ? 1 : 0, errorMessage);
|
|
445
|
+
})();
|
|
335
446
|
return {
|
|
336
447
|
translation,
|
|
337
448
|
parseSuccess,
|
|
@@ -401,74 +512,70 @@ function getWordOrder(language) {
|
|
|
401
512
|
}
|
|
402
513
|
|
|
403
514
|
// src/api/llm.ts
|
|
515
|
+
init_esm_shims();
|
|
516
|
+
var EXAMPLES_FROM = `
|
|
517
|
+
SELECT le.*, ce.engine AS engine
|
|
518
|
+
FROM llm_examples le
|
|
519
|
+
JOIN code_examples ce ON ce.id = le.code_example_id`;
|
|
404
520
|
async function getLLMExamples(prompt, language = "en", limit = 5, options) {
|
|
405
521
|
const db = getDatabase({ ...options, readonly: true });
|
|
522
|
+
const runs = exampleCondition("ce.engine", options?.engine);
|
|
406
523
|
const keywords = extractKeywords(prompt);
|
|
407
524
|
if (keywords.length === 0) {
|
|
408
525
|
const rows2 = db.prepare(
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
ORDER BY quality_score DESC, usage_count DESC
|
|
526
|
+
`${EXAMPLES_FROM}
|
|
527
|
+
WHERE le.language = ? AND ${runs.sql}
|
|
528
|
+
ORDER BY le.quality_score DESC, le.usage_count DESC
|
|
413
529
|
LIMIT ?
|
|
414
530
|
`
|
|
415
|
-
).all(language, limit);
|
|
416
|
-
trackUsage(
|
|
417
|
-
db,
|
|
418
|
-
rows2.map((r) => r.id)
|
|
419
|
-
);
|
|
531
|
+
).all(language, ...runs.params, limit);
|
|
420
532
|
return rows2.map(mapRowToLLMExample);
|
|
421
533
|
}
|
|
422
|
-
const likeClauses = keywords.map(() => "(prompt LIKE ? OR completion LIKE ?)").join(" OR ");
|
|
534
|
+
const likeClauses = keywords.map(() => "(le.prompt LIKE ? OR le.completion LIKE ?)").join(" OR ");
|
|
423
535
|
const params = keywords.flatMap((k) => [`%${k}%`, `%${k}%`]);
|
|
424
536
|
const rows = db.prepare(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
ORDER BY quality_score DESC
|
|
537
|
+
`${EXAMPLES_FROM}
|
|
538
|
+
WHERE le.language = ? AND ${runs.sql} AND (${likeClauses})
|
|
539
|
+
ORDER BY le.quality_score DESC
|
|
429
540
|
LIMIT ?
|
|
430
541
|
`
|
|
431
|
-
).all(language, ...params, limit);
|
|
432
|
-
trackUsage(
|
|
433
|
-
db,
|
|
434
|
-
rows.map((r) => r.id)
|
|
435
|
-
);
|
|
542
|
+
).all(language, ...runs.params, ...params, limit);
|
|
436
543
|
return rows.map(mapRowToLLMExample);
|
|
437
544
|
}
|
|
438
545
|
async function getExamplesByCommand(command, language = "en", limit = 5, options) {
|
|
439
546
|
const db = getDatabase({ ...options, readonly: true });
|
|
547
|
+
const runs = exampleCondition("ce.engine", options?.engine);
|
|
440
548
|
const rows = db.prepare(
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
ORDER BY quality_score DESC
|
|
549
|
+
`${EXAMPLES_FROM}
|
|
550
|
+
WHERE le.language = ? AND ${runs.sql} AND le.completion LIKE ?
|
|
551
|
+
ORDER BY le.quality_score DESC
|
|
445
552
|
LIMIT ?
|
|
446
553
|
`
|
|
447
|
-
).all(language, `%${command}%`, limit);
|
|
554
|
+
).all(language, ...runs.params, `%${command}%`, limit);
|
|
448
555
|
return rows.map(mapRowToLLMExample);
|
|
449
556
|
}
|
|
450
557
|
async function getHighQualityExamples(language = "en", minQuality = 0.8, limit = 10, options) {
|
|
451
558
|
const db = getDatabase({ ...options, readonly: true });
|
|
559
|
+
const runs = exampleCondition("ce.engine", options?.engine);
|
|
452
560
|
const rows = db.prepare(
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
ORDER BY quality_score DESC, usage_count DESC
|
|
561
|
+
`${EXAMPLES_FROM}
|
|
562
|
+
WHERE le.language = ? AND ${runs.sql} AND le.quality_score >= ?
|
|
563
|
+
ORDER BY le.quality_score DESC, le.usage_count DESC
|
|
457
564
|
LIMIT ?
|
|
458
565
|
`
|
|
459
|
-
).all(language, minQuality, limit);
|
|
566
|
+
).all(language, ...runs.params, minQuality, limit);
|
|
460
567
|
return rows.map(mapRowToLLMExample);
|
|
461
568
|
}
|
|
462
569
|
async function getMostUsedExamples(language = "en", limit = 10, options) {
|
|
463
570
|
const db = getDatabase({ ...options, readonly: true });
|
|
571
|
+
const runs = exampleCondition("ce.engine", options?.engine);
|
|
464
572
|
const rows = db.prepare(
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
ORDER BY usage_count DESC, quality_score DESC
|
|
573
|
+
`${EXAMPLES_FROM}
|
|
574
|
+
WHERE le.language = ? AND ${runs.sql}
|
|
575
|
+
ORDER BY le.usage_count DESC, le.quality_score DESC
|
|
469
576
|
LIMIT ?
|
|
470
577
|
`
|
|
471
|
-
).all(language, limit);
|
|
578
|
+
).all(language, ...runs.params, limit);
|
|
472
579
|
return rows.map(mapRowToLLMExample);
|
|
473
580
|
}
|
|
474
581
|
async function buildFewShotContext(prompt, language = "en", numExamples = 3, options) {
|
|
@@ -566,18 +673,6 @@ function extractKeywords(prompt) {
|
|
|
566
673
|
]);
|
|
567
674
|
return prompt.toLowerCase().split(/\W+/).filter((word) => word.length > 2 && !stopWords.has(word));
|
|
568
675
|
}
|
|
569
|
-
function trackUsage(db, ids) {
|
|
570
|
-
if (ids.length === 0) return;
|
|
571
|
-
try {
|
|
572
|
-
const stmt = db.prepare(`
|
|
573
|
-
UPDATE llm_examples SET usage_count = usage_count + 1 WHERE id = ?
|
|
574
|
-
`);
|
|
575
|
-
for (const id of ids) {
|
|
576
|
-
stmt.run(id);
|
|
577
|
-
}
|
|
578
|
-
} catch {
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
676
|
function mapRowToLLMExample(row) {
|
|
582
677
|
return {
|
|
583
678
|
id: row.id,
|
|
@@ -587,11 +682,13 @@ function mapRowToLLMExample(row) {
|
|
|
587
682
|
completion: row.completion,
|
|
588
683
|
qualityScore: row.quality_score,
|
|
589
684
|
usageCount: row.usage_count,
|
|
590
|
-
createdAt: new Date(row.created_at)
|
|
685
|
+
createdAt: new Date(row.created_at),
|
|
686
|
+
engine: row.engine ?? null
|
|
591
687
|
};
|
|
592
688
|
}
|
|
593
689
|
|
|
594
690
|
// src/api/language-docs.ts
|
|
691
|
+
init_esm_shims();
|
|
595
692
|
function mapCommand(row) {
|
|
596
693
|
return {
|
|
597
694
|
id: row.id,
|
|
@@ -837,6 +934,12 @@ async function getLanguageDocsStats(options) {
|
|
|
837
934
|
expressionOperators: getCount("expression_operators")
|
|
838
935
|
};
|
|
839
936
|
}
|
|
937
|
+
|
|
938
|
+
// src/sync/index.ts
|
|
939
|
+
init_esm_shims();
|
|
940
|
+
|
|
941
|
+
// src/sync/db-stamp.ts
|
|
942
|
+
init_esm_shims();
|
|
840
943
|
function repoRootFromDbPath(dbPath) {
|
|
841
944
|
return resolve(dirname(dbPath), "..", "..", "..");
|
|
842
945
|
}
|
|
@@ -862,7 +965,10 @@ function dbInputFiles(dbPath) {
|
|
|
862
965
|
for (const f of [
|
|
863
966
|
join(pr, "scripts", "init-db.ts"),
|
|
864
967
|
join(pr, "scripts", "sync-translations.ts"),
|
|
865
|
-
|
|
968
|
+
// Decides which markup `_` bodies are translated (and which stay English).
|
|
969
|
+
join(pr, "src", "sync", "markup-attributes.ts"),
|
|
970
|
+
// Writes every row's `verified_parses`.
|
|
971
|
+
join(pr, "src", "sync", "verify-parses.ts"),
|
|
866
972
|
// Committed engine-verification results are seeded into the engine
|
|
867
973
|
// column by init-db.ts, so they are DB input too.
|
|
868
974
|
join(pr, "data", "engine-verification.json")
|
|
@@ -922,6 +1028,12 @@ async function seedLLMExamples(_dryRun = false) {
|
|
|
922
1028
|
}
|
|
923
1029
|
|
|
924
1030
|
// src/adapters/llm-adapter.ts
|
|
1031
|
+
init_esm_shims();
|
|
1032
|
+
var RECORDS_FROM = `
|
|
1033
|
+
SELECT le.id, le.prompt, le.completion, le.language, le.quality_score as qualityScore,
|
|
1034
|
+
ce.engine AS engine
|
|
1035
|
+
FROM llm_examples le
|
|
1036
|
+
JOIN code_examples ce ON ce.id = le.code_example_id`;
|
|
925
1037
|
var syncDatabaseAvailable = true;
|
|
926
1038
|
function isDatabaseAvailable() {
|
|
927
1039
|
try {
|
|
@@ -932,42 +1044,31 @@ function isDatabaseAvailable() {
|
|
|
932
1044
|
return false;
|
|
933
1045
|
}
|
|
934
1046
|
}
|
|
935
|
-
function findRelevantExamples(prompt, language = "en", limit = 5) {
|
|
1047
|
+
function findRelevantExamples(prompt, language = "en", limit = 5, engine) {
|
|
936
1048
|
if (!syncDatabaseAvailable) return [];
|
|
937
1049
|
try {
|
|
938
1050
|
const db = getDatabase({ readonly: true });
|
|
1051
|
+
const runs = exampleCondition("ce.engine", engine);
|
|
939
1052
|
const keywords = extractKeywords2(prompt);
|
|
940
1053
|
if (keywords.length === 0) {
|
|
941
1054
|
const rows2 = db.prepare(
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
WHERE language = ?
|
|
946
|
-
ORDER BY quality_score DESC, usage_count DESC
|
|
1055
|
+
`${RECORDS_FROM}
|
|
1056
|
+
WHERE le.language = ? AND ${runs.sql}
|
|
1057
|
+
ORDER BY le.quality_score DESC, le.usage_count DESC
|
|
947
1058
|
LIMIT ?
|
|
948
1059
|
`
|
|
949
|
-
).all(language, limit);
|
|
950
|
-
trackUsageSync(
|
|
951
|
-
db,
|
|
952
|
-
rows2.map((r) => r.id)
|
|
953
|
-
);
|
|
1060
|
+
).all(language, ...runs.params, limit);
|
|
954
1061
|
return rows2;
|
|
955
1062
|
}
|
|
956
|
-
const likeClauses = keywords.map(() => "(prompt LIKE ? OR completion LIKE ?)").join(" OR ");
|
|
1063
|
+
const likeClauses = keywords.map(() => "(le.prompt LIKE ? OR le.completion LIKE ?)").join(" OR ");
|
|
957
1064
|
const params = keywords.flatMap((k) => [`%${k}%`, `%${k}%`]);
|
|
958
1065
|
const rows = db.prepare(
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
WHERE language = ? AND (${likeClauses})
|
|
963
|
-
ORDER BY quality_score DESC
|
|
1066
|
+
`${RECORDS_FROM}
|
|
1067
|
+
WHERE le.language = ? AND ${runs.sql} AND (${likeClauses})
|
|
1068
|
+
ORDER BY le.quality_score DESC
|
|
964
1069
|
LIMIT ?
|
|
965
1070
|
`
|
|
966
|
-
).all(language, ...params, limit);
|
|
967
|
-
trackUsageSync(
|
|
968
|
-
db,
|
|
969
|
-
rows.map((r) => r.id)
|
|
970
|
-
);
|
|
1071
|
+
).all(language, ...runs.params, ...params, limit);
|
|
971
1072
|
return rows;
|
|
972
1073
|
} catch (error) {
|
|
973
1074
|
console.warn(
|
|
@@ -978,19 +1079,18 @@ function findRelevantExamples(prompt, language = "en", limit = 5) {
|
|
|
978
1079
|
return [];
|
|
979
1080
|
}
|
|
980
1081
|
}
|
|
981
|
-
function findExamplesByCommand(command, language = "en", limit = 5) {
|
|
1082
|
+
function findExamplesByCommand(command, language = "en", limit = 5, engine) {
|
|
982
1083
|
if (!syncDatabaseAvailable) return [];
|
|
983
1084
|
try {
|
|
984
1085
|
const db = getDatabase({ readonly: true });
|
|
1086
|
+
const runs = exampleCondition("ce.engine", engine);
|
|
985
1087
|
const rows = db.prepare(
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
WHERE language = ? AND completion LIKE ?
|
|
990
|
-
ORDER BY quality_score DESC
|
|
1088
|
+
`${RECORDS_FROM}
|
|
1089
|
+
WHERE le.language = ? AND ${runs.sql} AND le.completion LIKE ?
|
|
1090
|
+
ORDER BY le.quality_score DESC
|
|
991
1091
|
LIMIT ?
|
|
992
1092
|
`
|
|
993
|
-
).all(language, `%${command}%`, limit);
|
|
1093
|
+
).all(language, ...runs.params, `%${command}%`, limit);
|
|
994
1094
|
return rows;
|
|
995
1095
|
} catch (error) {
|
|
996
1096
|
console.warn(
|
|
@@ -1000,8 +1100,8 @@ function findExamplesByCommand(command, language = "en", limit = 5) {
|
|
|
1000
1100
|
return [];
|
|
1001
1101
|
}
|
|
1002
1102
|
}
|
|
1003
|
-
function buildFewShotContextSync(prompt, language = "en", numExamples = 3) {
|
|
1004
|
-
const examples = findRelevantExamples(prompt, language, numExamples);
|
|
1103
|
+
function buildFewShotContextSync(prompt, language = "en", numExamples = 3, engine) {
|
|
1104
|
+
const examples = findRelevantExamples(prompt, language, numExamples, engine);
|
|
1005
1105
|
if (examples.length === 0) {
|
|
1006
1106
|
return "";
|
|
1007
1107
|
}
|
|
@@ -1104,11 +1204,12 @@ function createLLMAdapter(options) {
|
|
|
1104
1204
|
getLLMExampleStats,
|
|
1105
1205
|
isDatabaseAvailable,
|
|
1106
1206
|
// Async methods (preferred for new code)
|
|
1107
|
-
getLLMExamples: (prompt, language, limit) => getLLMExamples(prompt, language, limit, options),
|
|
1108
|
-
getExamplesByCommand: (command, language, limit) => getExamplesByCommand(command, language, limit, options),
|
|
1109
|
-
getHighQualityExamples: (language, minQuality, limit) => getHighQualityExamples(language, minQuality, limit, options),
|
|
1110
|
-
|
|
1111
|
-
|
|
1207
|
+
getLLMExamples: (prompt, language, limit, engine) => getLLMExamples(prompt, language, limit, { ...options, engine }),
|
|
1208
|
+
getExamplesByCommand: (command, language, limit, engine) => getExamplesByCommand(command, language, limit, { ...options, engine }),
|
|
1209
|
+
getHighQualityExamples: (language, minQuality, limit, engine) => getHighQualityExamples(language, minQuality, limit, { ...options, engine }),
|
|
1210
|
+
/** @deprecated See getMostUsedExamples. */
|
|
1211
|
+
getMostUsedExamples: (language, limit, engine) => getMostUsedExamples(language, limit, { ...options, engine }),
|
|
1212
|
+
buildFewShotContext: (prompt, language, numExamples, engine) => buildFewShotContext(prompt, language, numExamples, { ...options, engine }),
|
|
1112
1213
|
getLLMStats: () => getLLMStats(options),
|
|
1113
1214
|
// Cleanup
|
|
1114
1215
|
close: closeDatabase
|
|
@@ -1116,6 +1217,7 @@ function createLLMAdapter(options) {
|
|
|
1116
1217
|
}
|
|
1117
1218
|
|
|
1118
1219
|
// src/registry/patterns-provider.ts
|
|
1220
|
+
init_esm_shims();
|
|
1119
1221
|
var DatabasePatternsProvider = class {
|
|
1120
1222
|
id = "patterns-reference-db";
|
|
1121
1223
|
name = "Patterns Reference Database";
|
|
@@ -1165,7 +1267,9 @@ var DatabasePatternsProvider = class {
|
|
|
1165
1267
|
command: p.primaryCommand,
|
|
1166
1268
|
language: language || "en",
|
|
1167
1269
|
confidence: 1,
|
|
1168
|
-
|
|
1270
|
+
// The English source pattern: "verified" = some engine runs it
|
|
1271
|
+
// (code_examples.engine, mechanically checked) — not a constant.
|
|
1272
|
+
verified: p.engine !== null,
|
|
1169
1273
|
title: p.title,
|
|
1170
1274
|
category: p.category || void 0
|
|
1171
1275
|
}));
|
|
@@ -1267,6 +1371,7 @@ function resetDefaultProvider() {
|
|
|
1267
1371
|
}
|
|
1268
1372
|
|
|
1269
1373
|
// src/semantic-bridge.ts
|
|
1374
|
+
init_esm_shims();
|
|
1270
1375
|
var bridgeInitialized = false;
|
|
1271
1376
|
var bridgeProvider = null;
|
|
1272
1377
|
async function initializeSemanticIntegration(options) {
|
|
@@ -1326,7 +1431,7 @@ async function uninitializeSemanticIntegration() {
|
|
|
1326
1431
|
bridgeProvider = null;
|
|
1327
1432
|
bridgeInitialized = false;
|
|
1328
1433
|
}
|
|
1329
|
-
async function
|
|
1434
|
+
async function queryPatterns2(language) {
|
|
1330
1435
|
const provider = bridgeProvider || createPatternsProvider();
|
|
1331
1436
|
return provider.getPatternsForLanguage(language);
|
|
1332
1437
|
}
|
|
@@ -1340,15 +1445,17 @@ async function getSupportedLanguages() {
|
|
|
1340
1445
|
}
|
|
1341
1446
|
|
|
1342
1447
|
// src/html-snippets.ts
|
|
1448
|
+
init_esm_shims();
|
|
1343
1449
|
var HYPERFIXI_ONLY_ATTR_PREFIXES = ["hx-live", "sse-", "ws-"];
|
|
1344
1450
|
function extractHyperscriptFromMarkup(doc, markup) {
|
|
1345
1451
|
const container = doc.createElement("div");
|
|
1346
1452
|
try {
|
|
1347
1453
|
container.innerHTML = markup;
|
|
1348
1454
|
} catch {
|
|
1349
|
-
return { snippets: [], hyperfixiOnly: false };
|
|
1455
|
+
return { snippets: [], hyperfixiOnly: false, componentTags: [] };
|
|
1350
1456
|
}
|
|
1351
1457
|
const snippets = [];
|
|
1458
|
+
const componentTags = [];
|
|
1352
1459
|
let hyperfixiOnly = false;
|
|
1353
1460
|
for (const el of Array.from(container.querySelectorAll("*"))) {
|
|
1354
1461
|
for (const attr of Array.from(el.attributes)) {
|
|
@@ -1362,19 +1469,24 @@ function extractHyperscriptFromMarkup(doc, markup) {
|
|
|
1362
1469
|
hyperfixiOnly = true;
|
|
1363
1470
|
}
|
|
1364
1471
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1472
|
+
const tag = el.getAttribute("component");
|
|
1473
|
+
const isScriptTemplate = el.tagName === "SCRIPT" && el.getAttribute("type") === "text/hyperscript-template";
|
|
1474
|
+
if (tag && (isScriptTemplate || el.tagName === "TEMPLATE")) {
|
|
1475
|
+
componentTags.push(tag);
|
|
1476
|
+
const body = isScriptTemplate ? el.textContent ?? "" : el.innerHTML ?? "";
|
|
1477
|
+
const inner = extractHyperscriptFromMarkup(doc, body);
|
|
1478
|
+
snippets.push(...inner.snippets);
|
|
1479
|
+
componentTags.push(...inner.componentTags);
|
|
1480
|
+
hyperfixiOnly ||= inner.hyperfixiOnly;
|
|
1481
|
+
} else if (el.tagName === "SCRIPT" && el.getAttribute("type") === "text/hyperscript" && el.textContent?.trim()) {
|
|
1482
|
+
snippets.push(el.textContent);
|
|
1372
1483
|
}
|
|
1373
1484
|
}
|
|
1374
|
-
return { snippets, hyperfixiOnly };
|
|
1485
|
+
return { snippets, hyperfixiOnly, componentTags };
|
|
1375
1486
|
}
|
|
1376
1487
|
|
|
1377
1488
|
// src/index.ts
|
|
1489
|
+
init_markup_attributes();
|
|
1378
1490
|
function createPatternsReference(options) {
|
|
1379
1491
|
getDatabase(options);
|
|
1380
1492
|
return {
|
|
@@ -1388,7 +1500,7 @@ function createPatternsReference(options) {
|
|
|
1388
1500
|
getAllTranslations: (patternId) => getAllTranslations(patternId, options),
|
|
1389
1501
|
verifyTranslation: (translation) => verifyTranslation(translation, options),
|
|
1390
1502
|
// LLM
|
|
1391
|
-
getLLMExamples: (prompt, language, limit) => getLLMExamples(prompt, language, limit, options),
|
|
1503
|
+
getLLMExamples: (prompt, language, limit, engine) => getLLMExamples(prompt, language, limit, { ...options, engine }),
|
|
1392
1504
|
// Stats
|
|
1393
1505
|
getStats: () => getPatternStats(options),
|
|
1394
1506
|
// Connection
|
|
@@ -1397,4 +1509,4 @@ function createPatternsReference(options) {
|
|
|
1397
1509
|
}
|
|
1398
1510
|
var VERSION = "0.1.0";
|
|
1399
1511
|
|
|
1400
|
-
export { DatabasePatternsProvider, VERSION, addLLMExample, buildFewShotContext, buildFewShotContextSync, checkDbStamp, closeDatabase, computeDbInputHash, createLLMAdapter, createPatternsProvider, createPatternsReference, dbStampPath, discoverPatterns, extractHyperscriptFromMarkup, findExamplesByCommand, findRelevantExamples, getAllCommands, getAllExpressions, getAllFeatures, getAllKeywords, getAllPatterns, getAllSpecialSymbols, getAllTranslations, getBehaviorPatterns, getBridgeProvider, getCommandByName, getCurrentDbPath, getDatabase, getDefaultDbPath, getDefaultProvider, getExamplesByCommand, getExpressionByName, getExpressionsByCategory, getFeatureByName, getHighConfidenceTranslations, getHighQualityExamples, getKeywordByName, getLLMExampleStats, getLLMExamples, getLLMStats, getLanguageDocsStats, getMostUsedExamples, getPatternById, getPatternStats, getPatternsByCategory, getPatternsByCommand, getSpecialSymbolByName, getSupportedLanguages, getTranslation, getTranslationStats, getTranslationsByLanguage, getVerifiedTranslations, getWordOrder, initializeSemanticIntegration, isConnected, isDatabaseAvailable, isSemanticIntegrationInitialized, loadBehaviors, queryPatterns, queryPatternsForCommand, resetConnection, resetDefaultProvider, searchCommands, searchLanguageElements, searchPatterns, seedLLMExamples, syncTranslations, trackExampleUsage, uninitializeSemanticIntegration, updateQualityScore, validateAllTranslations, verifyTranslation, writeDbStamp };
|
|
1512
|
+
export { DatabasePatternsProvider, VERSION, addLLMExample, buildFewShotContext, buildFewShotContextSync, checkDbStamp, closeDatabase, computeDbInputHash, createLLMAdapter, createPatternsProvider, createPatternsReference, dbStampPath, discoverPatterns, extractHyperscriptFromMarkup, findExamplesByCommand, findHyperscriptAttributes, findRelevantExamples, getAllCommands, getAllExpressions, getAllFeatures, getAllKeywords, getAllPatterns, getAllSpecialSymbols, getAllTranslations, getBehaviorPatterns, getBridgeProvider, getCommandByName, getCurrentDbPath, getDatabase, getDefaultDbPath, getDefaultProvider, getExamplesByCommand, getExpressionByName, getExpressionsByCategory, getFeatureByName, getHighConfidenceTranslations, getHighQualityExamples, getKeywordByName, getLLMExampleStats, getLLMExamples, getLLMStats, getLanguageDocsStats, getMostUsedExamples, getPatternById, getPatternStats, getPatternsByCategory, getPatternsByCommand, getSpecialSymbolByName, getSupportedLanguages, getTranslation, getTranslationStats, getTranslationsByLanguage, getVerifiedTranslations, getWordOrder, initializeSemanticIntegration, isConnected, isDatabaseAvailable, isMarkupRow, isSemanticIntegrationInitialized, loadBehaviors, queryPatterns2 as queryPatterns, queryPatternsForCommand, resetConnection, resetDefaultProvider, searchCommands, searchLanguageElements, searchPatterns, seedLLMExamples, syncTranslations, trackExampleUsage, uninitializeSemanticIntegration, updateQualityScore, validateAllTranslations, verifyTranslation, writeDbStamp };
|