@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.
- package/README.md +311 -0
- package/data/hyperfixi-extensions.json +106 -0
- package/dist/api/index.d.mts +59 -0
- package/dist/api/index.d.ts +59 -0
- package/dist/api/index.js +769 -0
- package/dist/api/index.mjs +731 -0
- package/dist/index-CBoczxz7.d.mts +296 -0
- package/dist/index-CBoczxz7.d.ts +296 -0
- package/dist/index.d.mts +403 -0
- package/dist/index.d.ts +403 -0
- package/dist/index.js +1312 -0
- package/dist/index.mjs +1240 -0
- package/dist/llm-DMR6tmkM.d.ts +123 -0
- package/dist/llm-UOOBXwj3.d.mts +123 -0
- package/dist/sync/index.d.mts +42 -0
- package/dist/sync/index.d.ts +42 -0
- package/dist/sync/index.js +28 -0
- package/dist/sync/index.mjs +23 -0
- package/package.json +92 -0
- package/src/adapters/index.ts +7 -0
- package/src/adapters/llm-adapter.ts +394 -0
- package/src/api/index.ts +52 -0
- package/src/api/language-docs.ts +529 -0
- package/src/api/llm.ts +357 -0
- package/src/api/patterns.ts +276 -0
- package/src/api/roles.ts +401 -0
- package/src/api/translations.ts +283 -0
- package/src/database/connection.ts +85 -0
- package/src/index.ts +266 -0
- package/src/registry/index.ts +7 -0
- package/src/registry/patterns-provider.ts +250 -0
- package/src/semantic-bridge.ts +204 -0
- package/src/sync/index.ts +70 -0
- package/src/types/better-sqlite3.d.ts +44 -0
- package/src/types/index.ts +434 -0
package/src/api/roles.ts
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Roles API
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to query semantic roles extracted from patterns.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getDatabase } from '../database/connection';
|
|
8
|
+
import type {
|
|
9
|
+
PatternRole,
|
|
10
|
+
SemanticRole,
|
|
11
|
+
RoleType,
|
|
12
|
+
ConnectionOptions,
|
|
13
|
+
Pattern,
|
|
14
|
+
EngineCompat,
|
|
15
|
+
} from '../types';
|
|
16
|
+
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Database Row Types
|
|
19
|
+
// =============================================================================
|
|
20
|
+
|
|
21
|
+
interface PatternRoleRow {
|
|
22
|
+
id: number;
|
|
23
|
+
code_example_id: string;
|
|
24
|
+
command_index: number;
|
|
25
|
+
role: string;
|
|
26
|
+
role_value: string | null;
|
|
27
|
+
role_type: string | null;
|
|
28
|
+
required: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface CodeExampleRow {
|
|
32
|
+
id: string;
|
|
33
|
+
title: string;
|
|
34
|
+
raw_code: string;
|
|
35
|
+
description: string | null;
|
|
36
|
+
feature: string | null;
|
|
37
|
+
engine: string | null;
|
|
38
|
+
created_at: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// Role Queries
|
|
43
|
+
// =============================================================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get all semantic roles for a pattern.
|
|
47
|
+
*/
|
|
48
|
+
export async function getPatternRoles(
|
|
49
|
+
patternId: string,
|
|
50
|
+
options?: ConnectionOptions
|
|
51
|
+
): Promise<PatternRole[]> {
|
|
52
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
53
|
+
const rows = db
|
|
54
|
+
.prepare(
|
|
55
|
+
`
|
|
56
|
+
SELECT id, code_example_id, command_index, role, role_value, role_type, required
|
|
57
|
+
FROM pattern_roles
|
|
58
|
+
WHERE code_example_id = ?
|
|
59
|
+
ORDER BY command_index, role
|
|
60
|
+
`
|
|
61
|
+
)
|
|
62
|
+
.all(patternId) as PatternRoleRow[];
|
|
63
|
+
|
|
64
|
+
return rows.map(mapRowToPatternRole);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get all patterns that contain a specific semantic role.
|
|
69
|
+
*/
|
|
70
|
+
export async function getPatternsByRole(
|
|
71
|
+
role: SemanticRole,
|
|
72
|
+
options?: ConnectionOptions
|
|
73
|
+
): Promise<Pattern[]> {
|
|
74
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
75
|
+
const rows = db
|
|
76
|
+
.prepare(
|
|
77
|
+
`
|
|
78
|
+
SELECT DISTINCT ce.id, ce.title, ce.raw_code, ce.description, ce.feature, ce.engine, ce.created_at
|
|
79
|
+
FROM code_examples ce
|
|
80
|
+
INNER JOIN pattern_roles pr ON ce.id = pr.code_example_id
|
|
81
|
+
WHERE pr.role = ?
|
|
82
|
+
ORDER BY ce.title
|
|
83
|
+
`
|
|
84
|
+
)
|
|
85
|
+
.all(role) as CodeExampleRow[];
|
|
86
|
+
|
|
87
|
+
return rows.map(mapRowToPattern);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get patterns that contain all specified roles.
|
|
92
|
+
*/
|
|
93
|
+
export async function getPatternsByRoles(
|
|
94
|
+
roles: SemanticRole[],
|
|
95
|
+
matchMode: 'all' | 'any' = 'any',
|
|
96
|
+
options?: ConnectionOptions
|
|
97
|
+
): Promise<Pattern[]> {
|
|
98
|
+
if (roles.length === 0) return [];
|
|
99
|
+
|
|
100
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
101
|
+
|
|
102
|
+
if (matchMode === 'any') {
|
|
103
|
+
// Match patterns with ANY of the specified roles
|
|
104
|
+
const placeholders = roles.map(() => '?').join(', ');
|
|
105
|
+
const rows = db
|
|
106
|
+
.prepare(
|
|
107
|
+
`
|
|
108
|
+
SELECT DISTINCT ce.id, ce.title, ce.raw_code, ce.description, ce.feature, ce.engine, ce.created_at
|
|
109
|
+
FROM code_examples ce
|
|
110
|
+
INNER JOIN pattern_roles pr ON ce.id = pr.code_example_id
|
|
111
|
+
WHERE pr.role IN (${placeholders})
|
|
112
|
+
ORDER BY ce.title
|
|
113
|
+
`
|
|
114
|
+
)
|
|
115
|
+
.all(...roles) as CodeExampleRow[];
|
|
116
|
+
|
|
117
|
+
return rows.map(mapRowToPattern);
|
|
118
|
+
} else {
|
|
119
|
+
// Match patterns with ALL of the specified roles
|
|
120
|
+
const placeholders = roles.map(() => '?').join(', ');
|
|
121
|
+
const rows = db
|
|
122
|
+
.prepare(
|
|
123
|
+
`
|
|
124
|
+
SELECT ce.id, ce.title, ce.raw_code, ce.description, ce.feature, ce.engine, ce.created_at
|
|
125
|
+
FROM code_examples ce
|
|
126
|
+
WHERE (
|
|
127
|
+
SELECT COUNT(DISTINCT pr.role)
|
|
128
|
+
FROM pattern_roles pr
|
|
129
|
+
WHERE pr.code_example_id = ce.id AND pr.role IN (${placeholders})
|
|
130
|
+
) = ?
|
|
131
|
+
ORDER BY ce.title
|
|
132
|
+
`
|
|
133
|
+
)
|
|
134
|
+
.all(...roles, roles.length) as CodeExampleRow[];
|
|
135
|
+
|
|
136
|
+
return rows.map(mapRowToPattern);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get patterns by role value (e.g., all patterns that target ".active").
|
|
142
|
+
*/
|
|
143
|
+
export async function getPatternsByRoleValue(
|
|
144
|
+
role: SemanticRole,
|
|
145
|
+
value: string,
|
|
146
|
+
options?: ConnectionOptions
|
|
147
|
+
): Promise<Pattern[]> {
|
|
148
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
149
|
+
const rows = db
|
|
150
|
+
.prepare(
|
|
151
|
+
`
|
|
152
|
+
SELECT DISTINCT ce.id, ce.title, ce.raw_code, ce.description, ce.feature, ce.engine, ce.created_at
|
|
153
|
+
FROM code_examples ce
|
|
154
|
+
INNER JOIN pattern_roles pr ON ce.id = pr.code_example_id
|
|
155
|
+
WHERE pr.role = ? AND pr.role_value LIKE ?
|
|
156
|
+
ORDER BY ce.title
|
|
157
|
+
`
|
|
158
|
+
)
|
|
159
|
+
.all(role, `%${value}%`) as CodeExampleRow[];
|
|
160
|
+
|
|
161
|
+
return rows.map(mapRowToPattern);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// =============================================================================
|
|
165
|
+
// Role Statistics
|
|
166
|
+
// =============================================================================
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get statistics about role usage across all patterns.
|
|
170
|
+
*/
|
|
171
|
+
export async function getRoleStats(options?: ConnectionOptions): Promise<{
|
|
172
|
+
totalRoles: number;
|
|
173
|
+
byRole: Record<SemanticRole, number>;
|
|
174
|
+
byRoleType: Record<RoleType, number>;
|
|
175
|
+
topRoleValues: Array<{ role: SemanticRole; value: string; count: number }>;
|
|
176
|
+
patternsWithRoles: number;
|
|
177
|
+
patternsWithoutRoles: number;
|
|
178
|
+
}> {
|
|
179
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
180
|
+
|
|
181
|
+
// Total roles
|
|
182
|
+
const totalRow = db.prepare('SELECT COUNT(*) as count FROM pattern_roles').get() as {
|
|
183
|
+
count: number;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// Count by role
|
|
187
|
+
const roleRows = db
|
|
188
|
+
.prepare(
|
|
189
|
+
`
|
|
190
|
+
SELECT role, COUNT(*) as count
|
|
191
|
+
FROM pattern_roles
|
|
192
|
+
GROUP BY role
|
|
193
|
+
ORDER BY count DESC
|
|
194
|
+
`
|
|
195
|
+
)
|
|
196
|
+
.all() as { role: string; count: number }[];
|
|
197
|
+
|
|
198
|
+
const byRole: Record<string, number> = {};
|
|
199
|
+
for (const row of roleRows) {
|
|
200
|
+
byRole[row.role] = row.count;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Count by role type
|
|
204
|
+
const typeRows = db
|
|
205
|
+
.prepare(
|
|
206
|
+
`
|
|
207
|
+
SELECT role_type, COUNT(*) as count
|
|
208
|
+
FROM pattern_roles
|
|
209
|
+
WHERE role_type IS NOT NULL
|
|
210
|
+
GROUP BY role_type
|
|
211
|
+
`
|
|
212
|
+
)
|
|
213
|
+
.all() as { role_type: string; count: number }[];
|
|
214
|
+
|
|
215
|
+
const byRoleType: Record<string, number> = {};
|
|
216
|
+
for (const row of typeRows) {
|
|
217
|
+
byRoleType[row.role_type] = row.count;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Top role values
|
|
221
|
+
const valueRows = db
|
|
222
|
+
.prepare(
|
|
223
|
+
`
|
|
224
|
+
SELECT role, role_value, COUNT(*) as count
|
|
225
|
+
FROM pattern_roles
|
|
226
|
+
WHERE role_value IS NOT NULL
|
|
227
|
+
GROUP BY role, role_value
|
|
228
|
+
ORDER BY count DESC
|
|
229
|
+
LIMIT 20
|
|
230
|
+
`
|
|
231
|
+
)
|
|
232
|
+
.all() as { role: string; role_value: string; count: number }[];
|
|
233
|
+
|
|
234
|
+
const topRoleValues = valueRows.map(row => ({
|
|
235
|
+
role: row.role as SemanticRole,
|
|
236
|
+
value: row.role_value,
|
|
237
|
+
count: row.count,
|
|
238
|
+
}));
|
|
239
|
+
|
|
240
|
+
// Patterns with/without roles
|
|
241
|
+
const withRolesRow = db
|
|
242
|
+
.prepare(
|
|
243
|
+
`
|
|
244
|
+
SELECT COUNT(DISTINCT code_example_id) as count
|
|
245
|
+
FROM pattern_roles
|
|
246
|
+
`
|
|
247
|
+
)
|
|
248
|
+
.get() as { count: number };
|
|
249
|
+
|
|
250
|
+
const totalPatternsRow = db.prepare('SELECT COUNT(*) as count FROM code_examples').get() as {
|
|
251
|
+
count: number;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
totalRoles: totalRow.count,
|
|
256
|
+
byRole: byRole as Record<SemanticRole, number>,
|
|
257
|
+
byRoleType: byRoleType as Record<RoleType, number>,
|
|
258
|
+
topRoleValues,
|
|
259
|
+
patternsWithRoles: withRolesRow.count,
|
|
260
|
+
patternsWithoutRoles: totalPatternsRow.count - withRolesRow.count,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get role distribution for a specific command.
|
|
266
|
+
*/
|
|
267
|
+
export async function getRolesByCommand(
|
|
268
|
+
command: string,
|
|
269
|
+
options?: ConnectionOptions
|
|
270
|
+
): Promise<Record<SemanticRole, number>> {
|
|
271
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
272
|
+
|
|
273
|
+
const rows = db
|
|
274
|
+
.prepare(
|
|
275
|
+
`
|
|
276
|
+
SELECT pr.role, COUNT(*) as count
|
|
277
|
+
FROM pattern_roles pr
|
|
278
|
+
INNER JOIN code_examples ce ON pr.code_example_id = ce.id
|
|
279
|
+
WHERE ce.raw_code LIKE ?
|
|
280
|
+
GROUP BY pr.role
|
|
281
|
+
`
|
|
282
|
+
)
|
|
283
|
+
.all(`%${command}%`) as { role: string; count: number }[];
|
|
284
|
+
|
|
285
|
+
const result: Record<string, number> = {};
|
|
286
|
+
for (const row of rows) {
|
|
287
|
+
result[row.role] = row.count;
|
|
288
|
+
}
|
|
289
|
+
return result as Record<SemanticRole, number>;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// =============================================================================
|
|
293
|
+
// Role Write Operations
|
|
294
|
+
// =============================================================================
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Insert a pattern role into the database.
|
|
298
|
+
*/
|
|
299
|
+
export async function insertPatternRole(
|
|
300
|
+
role: Omit<PatternRole, 'id'>,
|
|
301
|
+
options?: ConnectionOptions
|
|
302
|
+
): Promise<number> {
|
|
303
|
+
const db = getDatabase(options);
|
|
304
|
+
const result = db
|
|
305
|
+
.prepare(
|
|
306
|
+
`
|
|
307
|
+
INSERT INTO pattern_roles (code_example_id, command_index, role, role_value, role_type, required)
|
|
308
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
309
|
+
`
|
|
310
|
+
)
|
|
311
|
+
.run(
|
|
312
|
+
role.codeExampleId,
|
|
313
|
+
role.commandIndex,
|
|
314
|
+
role.role,
|
|
315
|
+
role.roleValue,
|
|
316
|
+
role.roleType,
|
|
317
|
+
role.required ? 1 : 0
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
return result.lastInsertRowid as number;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Delete all roles for a pattern.
|
|
325
|
+
*/
|
|
326
|
+
export async function deletePatternRoles(
|
|
327
|
+
patternId: string,
|
|
328
|
+
options?: ConnectionOptions
|
|
329
|
+
): Promise<number> {
|
|
330
|
+
const db = getDatabase(options);
|
|
331
|
+
const result = db.prepare('DELETE FROM pattern_roles WHERE code_example_id = ?').run(patternId);
|
|
332
|
+
return result.changes;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Delete all roles from the database.
|
|
337
|
+
*/
|
|
338
|
+
export async function clearAllRoles(options?: ConnectionOptions): Promise<number> {
|
|
339
|
+
const db = getDatabase(options);
|
|
340
|
+
const result = db.prepare('DELETE FROM pattern_roles').run();
|
|
341
|
+
return result.changes;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// =============================================================================
|
|
345
|
+
// Helper Functions
|
|
346
|
+
// =============================================================================
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Map database row to PatternRole type.
|
|
350
|
+
*/
|
|
351
|
+
function mapRowToPatternRole(row: PatternRoleRow): PatternRole {
|
|
352
|
+
return {
|
|
353
|
+
id: row.id,
|
|
354
|
+
codeExampleId: row.code_example_id,
|
|
355
|
+
commandIndex: row.command_index,
|
|
356
|
+
role: row.role as SemanticRole,
|
|
357
|
+
roleValue: row.role_value,
|
|
358
|
+
roleType: row.role_type as RoleType | null,
|
|
359
|
+
required: Boolean(row.required),
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Map database row to Pattern type.
|
|
365
|
+
*/
|
|
366
|
+
function mapRowToPattern(row: CodeExampleRow): Pattern {
|
|
367
|
+
return {
|
|
368
|
+
id: row.id,
|
|
369
|
+
title: row.title,
|
|
370
|
+
description: row.description,
|
|
371
|
+
rawCode: row.raw_code,
|
|
372
|
+
category: row.feature,
|
|
373
|
+
primaryCommand: extractPrimaryCommand(row.raw_code),
|
|
374
|
+
tags: extractTags(row.raw_code),
|
|
375
|
+
difficulty: inferDifficulty(row.raw_code),
|
|
376
|
+
engine: (row.engine as EngineCompat) || null,
|
|
377
|
+
createdAt: new Date(row.created_at),
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function extractPrimaryCommand(code: string): string | null {
|
|
382
|
+
const match = code.match(/^(on|toggle|put|set|add|remove|show|hide|wait|log|send|fetch|call)\b/i);
|
|
383
|
+
return match ? match[1].toLowerCase() : null;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function extractTags(code: string): string[] {
|
|
387
|
+
const tags: string[] = [];
|
|
388
|
+
if (code.includes('.')) tags.push('class');
|
|
389
|
+
if (code.includes('#')) tags.push('id');
|
|
390
|
+
if (code.includes('on ')) tags.push('event');
|
|
391
|
+
if (code.includes('fetch')) tags.push('async');
|
|
392
|
+
if (code.includes('wait')) tags.push('timing');
|
|
393
|
+
return tags;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function inferDifficulty(code: string): 'beginner' | 'intermediate' | 'advanced' {
|
|
397
|
+
const lines = code.split('\n').filter(l => l.trim()).length;
|
|
398
|
+
if (lines === 1 && !code.includes('then')) return 'beginner';
|
|
399
|
+
if (lines <= 3) return 'intermediate';
|
|
400
|
+
return 'advanced';
|
|
401
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation Operations API
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to query and manage translations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getDatabase } from '../database/connection';
|
|
8
|
+
import type {
|
|
9
|
+
Translation,
|
|
10
|
+
VerificationResult,
|
|
11
|
+
WordOrder,
|
|
12
|
+
TranslationMethod,
|
|
13
|
+
ConnectionOptions,
|
|
14
|
+
} from '../types';
|
|
15
|
+
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// Database Row Types
|
|
18
|
+
// =============================================================================
|
|
19
|
+
|
|
20
|
+
interface PatternTranslationRow {
|
|
21
|
+
id: number;
|
|
22
|
+
code_example_id: string;
|
|
23
|
+
language: string;
|
|
24
|
+
hyperscript: string;
|
|
25
|
+
word_order: string;
|
|
26
|
+
translation_method: string;
|
|
27
|
+
confidence: number;
|
|
28
|
+
verified_parses: number;
|
|
29
|
+
verified_executes: number;
|
|
30
|
+
role_alignment_score: number | null;
|
|
31
|
+
created_at: string;
|
|
32
|
+
updated_at: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// Query Functions
|
|
37
|
+
// =============================================================================
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get a translation for a pattern in a specific language.
|
|
41
|
+
*/
|
|
42
|
+
export async function getTranslation(
|
|
43
|
+
patternId: string,
|
|
44
|
+
language: string,
|
|
45
|
+
options?: ConnectionOptions
|
|
46
|
+
): Promise<Translation | null> {
|
|
47
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
48
|
+
const row = db
|
|
49
|
+
.prepare(
|
|
50
|
+
`
|
|
51
|
+
SELECT * FROM pattern_translations
|
|
52
|
+
WHERE code_example_id = ? AND language = ?
|
|
53
|
+
`
|
|
54
|
+
)
|
|
55
|
+
.get(patternId, language) as PatternTranslationRow | undefined;
|
|
56
|
+
|
|
57
|
+
return row ? mapRowToTranslation(row) : null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get all translations for a pattern.
|
|
62
|
+
*/
|
|
63
|
+
export async function getAllTranslations(
|
|
64
|
+
patternId: string,
|
|
65
|
+
options?: ConnectionOptions
|
|
66
|
+
): Promise<Translation[]> {
|
|
67
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
68
|
+
const rows = db
|
|
69
|
+
.prepare(
|
|
70
|
+
`
|
|
71
|
+
SELECT * FROM pattern_translations
|
|
72
|
+
WHERE code_example_id = ?
|
|
73
|
+
ORDER BY language
|
|
74
|
+
`
|
|
75
|
+
)
|
|
76
|
+
.all(patternId) as PatternTranslationRow[];
|
|
77
|
+
|
|
78
|
+
return rows.map(mapRowToTranslation);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get translations by language.
|
|
83
|
+
*/
|
|
84
|
+
export async function getTranslationsByLanguage(
|
|
85
|
+
language: string,
|
|
86
|
+
limit: number = 100,
|
|
87
|
+
options?: ConnectionOptions
|
|
88
|
+
): Promise<Translation[]> {
|
|
89
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
90
|
+
const rows = db
|
|
91
|
+
.prepare(
|
|
92
|
+
`
|
|
93
|
+
SELECT * FROM pattern_translations
|
|
94
|
+
WHERE language = ?
|
|
95
|
+
ORDER BY confidence DESC
|
|
96
|
+
LIMIT ?
|
|
97
|
+
`
|
|
98
|
+
)
|
|
99
|
+
.all(language, limit) as PatternTranslationRow[];
|
|
100
|
+
|
|
101
|
+
return rows.map(mapRowToTranslation);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get verified translations (successfully parsed).
|
|
106
|
+
*/
|
|
107
|
+
export async function getVerifiedTranslations(
|
|
108
|
+
language: string,
|
|
109
|
+
limit: number = 100,
|
|
110
|
+
options?: ConnectionOptions
|
|
111
|
+
): Promise<Translation[]> {
|
|
112
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
113
|
+
const rows = db
|
|
114
|
+
.prepare(
|
|
115
|
+
`
|
|
116
|
+
SELECT * FROM pattern_translations
|
|
117
|
+
WHERE language = ? AND verified_parses = 1
|
|
118
|
+
ORDER BY confidence DESC
|
|
119
|
+
LIMIT ?
|
|
120
|
+
`
|
|
121
|
+
)
|
|
122
|
+
.all(language, limit) as PatternTranslationRow[];
|
|
123
|
+
|
|
124
|
+
return rows.map(mapRowToTranslation);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get high-confidence translations.
|
|
129
|
+
*/
|
|
130
|
+
export async function getHighConfidenceTranslations(
|
|
131
|
+
minConfidence: number = 0.8,
|
|
132
|
+
limit: number = 100,
|
|
133
|
+
options?: ConnectionOptions
|
|
134
|
+
): Promise<Translation[]> {
|
|
135
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
136
|
+
const rows = db
|
|
137
|
+
.prepare(
|
|
138
|
+
`
|
|
139
|
+
SELECT * FROM pattern_translations
|
|
140
|
+
WHERE confidence >= ? AND verified_parses = 1
|
|
141
|
+
ORDER BY confidence DESC
|
|
142
|
+
LIMIT ?
|
|
143
|
+
`
|
|
144
|
+
)
|
|
145
|
+
.all(minConfidence, limit) as PatternTranslationRow[];
|
|
146
|
+
|
|
147
|
+
return rows.map(mapRowToTranslation);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Verify a translation parses correctly.
|
|
152
|
+
* Note: This requires @lokascript/semantic to be available.
|
|
153
|
+
*/
|
|
154
|
+
export async function verifyTranslation(
|
|
155
|
+
translation: Translation,
|
|
156
|
+
options?: ConnectionOptions
|
|
157
|
+
): Promise<VerificationResult> {
|
|
158
|
+
let parseSuccess = false;
|
|
159
|
+
let errorMessage: string | null = null;
|
|
160
|
+
let confidence = translation.confidence;
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
// Dynamic import to avoid bundling issues
|
|
164
|
+
const { canParse, parse } = await import('@lokascript/semantic');
|
|
165
|
+
|
|
166
|
+
if (canParse(translation.hyperscript, translation.language)) {
|
|
167
|
+
parse(translation.hyperscript, translation.language);
|
|
168
|
+
parseSuccess = true;
|
|
169
|
+
} else {
|
|
170
|
+
errorMessage = 'canParse returned false';
|
|
171
|
+
}
|
|
172
|
+
} catch (e) {
|
|
173
|
+
errorMessage = (e as Error).message;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Update database
|
|
177
|
+
const db = getDatabase(options);
|
|
178
|
+
db.prepare(
|
|
179
|
+
`
|
|
180
|
+
UPDATE pattern_translations
|
|
181
|
+
SET verified_parses = ?, updated_at = datetime('now')
|
|
182
|
+
WHERE id = ?
|
|
183
|
+
`
|
|
184
|
+
).run(parseSuccess ? 1 : 0, translation.id);
|
|
185
|
+
|
|
186
|
+
// Record test result
|
|
187
|
+
db.prepare(
|
|
188
|
+
`
|
|
189
|
+
INSERT INTO pattern_tests
|
|
190
|
+
(code_example_id, language, test_date, parse_success, error_message)
|
|
191
|
+
VALUES (?, ?, datetime('now'), ?, ?)
|
|
192
|
+
`
|
|
193
|
+
).run(translation.codeExampleId, translation.language, parseSuccess ? 1 : 0, errorMessage);
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
translation,
|
|
197
|
+
parseSuccess,
|
|
198
|
+
executeSuccess: false, // Not implemented yet
|
|
199
|
+
errorMessage,
|
|
200
|
+
confidence,
|
|
201
|
+
testedAt: new Date(),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Get translation statistics by language.
|
|
207
|
+
*/
|
|
208
|
+
export async function getTranslationStats(
|
|
209
|
+
options?: ConnectionOptions
|
|
210
|
+
): Promise<Record<string, { total: number; verified: number; avgConfidence: number }>> {
|
|
211
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
212
|
+
|
|
213
|
+
const rows = db
|
|
214
|
+
.prepare(
|
|
215
|
+
`
|
|
216
|
+
SELECT
|
|
217
|
+
language,
|
|
218
|
+
COUNT(*) as total,
|
|
219
|
+
SUM(verified_parses) as verified,
|
|
220
|
+
AVG(confidence) as avg_confidence
|
|
221
|
+
FROM pattern_translations
|
|
222
|
+
GROUP BY language
|
|
223
|
+
`
|
|
224
|
+
)
|
|
225
|
+
.all() as { language: string; total: number; verified: number; avg_confidence: number }[];
|
|
226
|
+
|
|
227
|
+
const stats: Record<string, { total: number; verified: number; avgConfidence: number }> = {};
|
|
228
|
+
for (const row of rows) {
|
|
229
|
+
stats[row.language] = {
|
|
230
|
+
total: row.total,
|
|
231
|
+
verified: row.verified,
|
|
232
|
+
avgConfidence: row.avg_confidence || 0,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return stats;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// =============================================================================
|
|
240
|
+
// Helper Functions
|
|
241
|
+
// =============================================================================
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Map database row to Translation type.
|
|
245
|
+
*/
|
|
246
|
+
function mapRowToTranslation(row: PatternTranslationRow): Translation {
|
|
247
|
+
return {
|
|
248
|
+
id: row.id,
|
|
249
|
+
codeExampleId: row.code_example_id,
|
|
250
|
+
language: row.language,
|
|
251
|
+
hyperscript: row.hyperscript,
|
|
252
|
+
wordOrder: row.word_order as WordOrder,
|
|
253
|
+
translationMethod: row.translation_method as TranslationMethod,
|
|
254
|
+
confidence: row.confidence,
|
|
255
|
+
verifiedParses: row.verified_parses === 1,
|
|
256
|
+
verifiedExecutes: row.verified_executes === 1,
|
|
257
|
+
roleAlignmentScore: row.role_alignment_score ?? null,
|
|
258
|
+
createdAt: new Date(row.created_at),
|
|
259
|
+
updatedAt: new Date(row.updated_at),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Get word order for a language.
|
|
265
|
+
*/
|
|
266
|
+
export function getWordOrder(language: string): WordOrder {
|
|
267
|
+
const wordOrders: Record<string, WordOrder> = {
|
|
268
|
+
en: 'SVO',
|
|
269
|
+
es: 'SVO',
|
|
270
|
+
fr: 'SVO',
|
|
271
|
+
pt: 'SVO',
|
|
272
|
+
id: 'SVO',
|
|
273
|
+
sw: 'SVO',
|
|
274
|
+
zh: 'SVO',
|
|
275
|
+
ja: 'SOV',
|
|
276
|
+
ko: 'SOV',
|
|
277
|
+
tr: 'SOV',
|
|
278
|
+
qu: 'SOV',
|
|
279
|
+
ar: 'VSO',
|
|
280
|
+
de: 'V2',
|
|
281
|
+
};
|
|
282
|
+
return wordOrders[language] || 'SVO';
|
|
283
|
+
}
|