@pikku/kysely 0.13.24 → 0.13.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +271 -0
  2. package/dist/src/index.d.ts +4 -1
  3. package/dist/src/index.js +3 -1
  4. package/dist/src/kysely-analytics-service.d.ts +30 -0
  5. package/dist/src/kysely-analytics-service.js +80 -0
  6. package/dist/src/kysely-feature-flag-store.d.ts +37 -0
  7. package/dist/src/kysely-feature-flag-store.js +239 -0
  8. package/dist/src/kysely-scope-service.d.ts +1 -0
  9. package/dist/src/kysely-scope-service.js +29 -0
  10. package/dist/src/kysely-tables.d.ts +45 -0
  11. package/dist/src/schema/analytics.schema.d.ts +17 -0
  12. package/dist/src/schema/analytics.schema.js +48 -0
  13. package/dist/src/schema/flag.schema.d.ts +16 -0
  14. package/dist/src/schema/flag.schema.js +62 -0
  15. package/dist/src/schema/index.d.ts +2 -0
  16. package/dist/src/schema/index.js +6 -0
  17. package/package.json +11 -6
  18. package/run-tests.sh +9 -1
  19. package/bin/pikku-kysely-pure.ts +0 -59
  20. package/dist/src/kysely-lock-vault.d.ts +0 -34
  21. package/dist/src/kysely-lock-vault.js +0 -77
  22. package/dist/src/schema/data-lock.schema.d.ts +0 -15
  23. package/dist/src/schema/data-lock.schema.js +0 -27
  24. package/dist/tsconfig.tsbuildinfo +0 -1
  25. package/src/classification-crypto.test.ts +0 -143
  26. package/src/classification-crypto.ts +0 -163
  27. package/src/classification-plugin.pglite.test.ts +0 -226
  28. package/src/classification-plugin.test.ts +0 -265
  29. package/src/classification-plugin.ts +0 -249
  30. package/src/coercion-plugin.test.ts +0 -160
  31. package/src/coercion-plugin.ts +0 -187
  32. package/src/create-audited-kysely.test.ts +0 -560
  33. package/src/create-audited-kysely.ts +0 -254
  34. package/src/index.ts +0 -81
  35. package/src/kysely-agent-run-scores.ts +0 -47
  36. package/src/kysely-agent-run-service.ts +0 -244
  37. package/src/kysely-agent-run-state-service.ts +0 -200
  38. package/src/kysely-agent-storage-service.ts +0 -632
  39. package/src/kysely-audit-service.test.ts +0 -352
  40. package/src/kysely-audit-service.ts +0 -237
  41. package/src/kysely-channel-store.ts +0 -107
  42. package/src/kysely-credential-service.ts +0 -286
  43. package/src/kysely-deployment-service.ts +0 -163
  44. package/src/kysely-eventhub-store.ts +0 -53
  45. package/src/kysely-json.ts +0 -5
  46. package/src/kysely-scope-service.test.ts +0 -418
  47. package/src/kysely-scope-service.ts +0 -425
  48. package/src/kysely-secret-service.ts +0 -242
  49. package/src/kysely-services.test.ts +0 -405
  50. package/src/kysely-session-store.ts +0 -57
  51. package/src/kysely-tables.test.ts +0 -110
  52. package/src/kysely-tables.ts +0 -434
  53. package/src/kysely-virtual-user-run-store.test.ts +0 -369
  54. package/src/kysely-virtual-user-run-store.ts +0 -235
  55. package/src/kysely-virtual-user-schedule-store.test.ts +0 -187
  56. package/src/kysely-virtual-user-schedule-store.ts +0 -187
  57. package/src/kysely-webhook-service.test.ts +0 -153
  58. package/src/kysely-webhook-service.ts +0 -139
  59. package/src/kysely-workflow-mirror.test.ts +0 -259
  60. package/src/kysely-workflow-mirror.ts +0 -374
  61. package/src/kysely-workflow-run-service.ts +0 -305
  62. package/src/kysely-workflow-service.test.ts +0 -544
  63. package/src/kysely-workflow-service.ts +0 -820
  64. package/src/schema/agent.schema.ts +0 -162
  65. package/src/schema/audit.schema.ts +0 -57
  66. package/src/schema/channel.schema.ts +0 -38
  67. package/src/schema/credential.schema.ts +0 -58
  68. package/src/schema/deployment.schema.ts +0 -47
  69. package/src/schema/index.ts +0 -441
  70. package/src/schema/pikku-schema.types.ts +0 -169
  71. package/src/schema/schema.test.ts +0 -591
  72. package/src/schema/scope.schema.ts +0 -110
  73. package/src/schema/secret.schema.ts +0 -49
  74. package/src/schema/session.schema.ts +0 -20
  75. package/src/schema/virtual-user-schedule.schema.ts +0 -48
  76. package/src/schema/virtual-user.schema.ts +0 -106
  77. package/src/schema/webhook.schema.ts +0 -58
  78. package/src/schema/workflow.schema.ts +0 -150
  79. package/src/serialize-plugin.ts +0 -233
  80. package/tsconfig.json +0 -17
@@ -1,632 +0,0 @@
1
- import type {
2
- AgentMessage,
3
- AgentRunState,
4
- AgentThread,
5
- } from '@pikku/core/agent'
6
- import type { AgentRunScore } from '@pikku/core/agent-scorer'
7
- import type {
8
- AgentRunStateService,
9
- AgentStorageService,
10
- CreateRunInput,
11
- SaveScoreInput,
12
- } from '@pikku/core/services'
13
- import type { Kysely } from 'kysely'
14
- import type { KyselyPikkuDB } from './kysely-tables.js'
15
- import { parseJson } from './kysely-json.js'
16
- import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
17
- import { requirePikkuSchema } from './schema/index.js'
18
- import { agentSchema } from './schema/agent.schema.js'
19
-
20
- export class KyselyAgentStorageService
21
- implements AgentStorageService, AgentRunStateService
22
- {
23
- private initialized = false
24
-
25
- constructor(private db: Kysely<KyselyPikkuDB>) {}
26
-
27
- public async init(): Promise<void> {
28
- if (this.initialized) return
29
- await requirePikkuSchema(this.db, agentSchema)
30
- this.initialized = true
31
- }
32
-
33
- async createThread(
34
- resourceId: string,
35
- options?: {
36
- threadId?: string
37
- title?: string
38
- metadata?: Record<string, unknown>
39
- }
40
- ): Promise<AgentThread> {
41
- const id = options?.threadId ?? crypto.randomUUID()
42
- const now = new Date()
43
-
44
- await this.db
45
- .insertInto('agentThreads')
46
- .values({
47
- id,
48
- resourceId: resourceId,
49
- title: options?.title ?? null,
50
- metadata: JSON.stringify(options?.metadata ?? null),
51
- createdAt: now,
52
- updatedAt: now,
53
- })
54
- .execute()
55
-
56
- return {
57
- id,
58
- resourceId,
59
- title: options?.title,
60
- metadata: options?.metadata,
61
- createdAt: now,
62
- updatedAt: now,
63
- }
64
- }
65
-
66
- async getThread(threadId: string): Promise<AgentThread> {
67
- const row = await this.db
68
- .selectFrom('agentThreads')
69
- .select([
70
- 'id',
71
- 'resourceId',
72
- 'title',
73
- 'metadata',
74
- 'createdAt',
75
- 'updatedAt',
76
- ])
77
- .where('id', '=', threadId)
78
- .executeTakeFirst()
79
-
80
- if (!row) {
81
- throw new Error(`Thread not found: ${threadId}`)
82
- }
83
-
84
- return {
85
- id: row.id,
86
- resourceId: row.resourceId,
87
- title: row.title ?? undefined,
88
- metadata: parseJson(row.metadata),
89
- createdAt: new Date(row.createdAt),
90
- updatedAt: new Date(row.updatedAt),
91
- }
92
- }
93
-
94
- async getThreads(resourceId: string): Promise<AgentThread[]> {
95
- const result = await this.db
96
- .selectFrom('agentThreads')
97
- .select([
98
- 'id',
99
- 'resourceId',
100
- 'title',
101
- 'metadata',
102
- 'createdAt',
103
- 'updatedAt',
104
- ])
105
- .where('resourceId', '=', resourceId)
106
- .orderBy('updatedAt', 'desc')
107
- .execute()
108
-
109
- return result.map((row) => ({
110
- id: row.id,
111
- resourceId: row.resourceId,
112
- title: row.title ?? undefined,
113
- metadata: parseJson(row.metadata),
114
- createdAt: new Date(row.createdAt),
115
- updatedAt: new Date(row.updatedAt),
116
- }))
117
- }
118
-
119
- async deleteThread(threadId: string): Promise<void> {
120
- await this.db
121
- .deleteFrom('agentThreads')
122
- .where('id', '=', threadId)
123
- .execute()
124
- }
125
-
126
- async getMessages(
127
- threadId: string,
128
- options?: { lastN?: number; cursor?: string }
129
- ): Promise<AgentMessage[]> {
130
- let msgQuery = this.db
131
- .selectFrom('agentMessage')
132
- .select(['id', 'role', 'content', 'createdAt'])
133
- .where('threadId', '=', threadId)
134
-
135
- if (options?.cursor) {
136
- const cursorRow = await this.db
137
- .selectFrom('agentMessage')
138
- .select('createdAt')
139
- .where('id', '=', options.cursor)
140
- .executeTakeFirst()
141
-
142
- if (cursorRow) {
143
- msgQuery = msgQuery.where('createdAt', '<', cursorRow.createdAt)
144
- }
145
- }
146
-
147
- let msgResult
148
- if (options?.cursor || options?.lastN) {
149
- const innerResult = await msgQuery
150
- .orderBy('createdAt', 'desc')
151
- .limit(options?.lastN ?? 50)
152
- .execute()
153
- innerResult.reverse()
154
- msgResult = innerResult
155
- } else {
156
- msgResult = await msgQuery.orderBy('createdAt', 'asc').execute()
157
- }
158
-
159
- const tcResult = await this.db
160
- .selectFrom('agentToolCall')
161
- .select(['id', 'messageId', 'toolName', 'args', 'result'])
162
- .where('threadId', '=', threadId)
163
- .orderBy('createdAt', 'asc')
164
- .execute()
165
-
166
- const tcByMessage = new Map<string, (typeof tcResult)[number][]>()
167
- for (const tc of tcResult) {
168
- const msgId = tc.messageId
169
- if (!tcByMessage.has(msgId)) tcByMessage.set(msgId, [])
170
- tcByMessage.get(msgId)!.push(tc)
171
- }
172
-
173
- const messages: AgentMessage[] = []
174
- for (const row of msgResult) {
175
- const rawContent = row.content as string | undefined
176
- let parsedContent: AgentMessage['content'] = rawContent ?? undefined
177
- if (rawContent) {
178
- try {
179
- const parsed = JSON.parse(rawContent)
180
- if (Array.isArray(parsed)) {
181
- parsedContent = parsed
182
- } else if (typeof parsed === 'string') {
183
- parsedContent = parsed
184
- }
185
- } catch {
186
- // Not JSON, use raw string
187
- }
188
- }
189
- const msg: AgentMessage = {
190
- id: row.id,
191
- role: row.role as AgentMessage['role'],
192
- content: parsedContent,
193
- createdAt: new Date(row.createdAt),
194
- }
195
-
196
- const tcs = tcByMessage.get(msg.id)
197
- if (tcs?.length) {
198
- msg.toolCalls = tcs.map((tc) => ({
199
- id: tc.id,
200
- name: tc.toolName,
201
- args: parseJson(tc.args) as Record<string, unknown>,
202
- }))
203
-
204
- const completed = tcs.filter((tc) => tc.result != null)
205
- if (completed.length) {
206
- messages.push(msg)
207
- messages.push({
208
- id: `tool-results-${msg.id}`,
209
- role: 'tool',
210
- toolResults: completed.map((tc) => ({
211
- id: tc.id,
212
- name: tc.toolName,
213
- result: tc.result!,
214
- })),
215
- createdAt: msg.createdAt,
216
- })
217
- continue
218
- }
219
- }
220
-
221
- messages.push(msg)
222
- }
223
-
224
- return messages
225
- }
226
-
227
- async saveMessages(
228
- threadId: string,
229
- messages: AgentMessage[]
230
- ): Promise<void> {
231
- if (messages.length === 0) return
232
-
233
- const toolMessages = messages.filter((m) => m.role === 'tool')
234
- const nonToolMessages = messages.filter((m) => m.role !== 'tool')
235
-
236
- if (nonToolMessages.length > 0) {
237
- await this.db
238
- .insertInto('agentMessage')
239
- .values(
240
- nonToolMessages.map((msg) => ({
241
- id: msg.id,
242
- threadId: threadId,
243
- role: msg.role,
244
- content: msg.content != null ? JSON.stringify(msg.content) : null,
245
- createdAt: msg.createdAt ?? new Date(),
246
- }))
247
- )
248
- .execute()
249
- }
250
-
251
- const toolCalls = nonToolMessages.flatMap(
252
- (msg) => msg.toolCalls?.map((tc) => ({ ...tc, messageId: msg.id })) ?? []
253
- )
254
- if (toolCalls.length > 0) {
255
- await this.db
256
- .insertInto('agentToolCall')
257
- .values(
258
- toolCalls.map((tc) => ({
259
- id: tc.id,
260
- threadId: threadId,
261
- messageId: tc.messageId,
262
- toolName: tc.name,
263
- args: JSON.stringify(tc.args),
264
- }))
265
- )
266
- .execute()
267
- }
268
-
269
- for (const toolMsg of toolMessages) {
270
- if (!toolMsg.toolResults) continue
271
- for (const tr of toolMsg.toolResults) {
272
- await this.db
273
- .updateTable('agentToolCall')
274
- .set({ result: tr.result })
275
- .where('id', '=', tr.id)
276
- .execute()
277
- }
278
- }
279
-
280
- await this.db
281
- .updateTable('agentThreads')
282
- .set({ updatedAt: new Date() })
283
- .where('id', '=', threadId)
284
- .execute()
285
- }
286
-
287
- async getWorkingMemory(
288
- id: string,
289
- scope: 'resource' | 'thread'
290
- ): Promise<Record<string, unknown> | null> {
291
- const row = await this.db
292
- .selectFrom('agentWorkingMemory')
293
- .select('data')
294
- .where('id', '=', id)
295
- .where('scope', '=', scope)
296
- .executeTakeFirst()
297
-
298
- if (!row) return null
299
- return parseJson(row.data)
300
- }
301
-
302
- async saveWorkingMemory(
303
- id: string,
304
- scope: 'resource' | 'thread',
305
- data: Record<string, unknown>
306
- ): Promise<void> {
307
- await this.db
308
- .insertInto('agentWorkingMemory')
309
- .values({
310
- id,
311
- scope,
312
- data: JSON.stringify(data),
313
- updatedAt: new Date(),
314
- })
315
- .onConflict((oc) =>
316
- oc.columns(['id', 'scope']).doUpdateSet({
317
- data: JSON.stringify(data),
318
- updatedAt: new Date(),
319
- })
320
- )
321
- .execute()
322
- }
323
-
324
- async createRun(run: CreateRunInput): Promise<string> {
325
- const runId = crypto.randomUUID()
326
-
327
- await this.db
328
- .insertInto('agentRun')
329
- .values({
330
- runId: runId,
331
- agentName: run.agentName,
332
- threadId: run.threadId,
333
- resourceId: run.resourceId,
334
- status: run.status,
335
- errorMessage: run.errorMessage ?? null,
336
- suspendReason: run.suspendReason ?? null,
337
- missingRpcs: run.missingRpcs ? JSON.stringify(run.missingRpcs) : null,
338
- usageInputTokens: run.usage.inputTokens,
339
- usageOutputTokens: run.usage.outputTokens,
340
- usageModel: run.usage.model,
341
- createdAt: run.createdAt,
342
- updatedAt: run.updatedAt,
343
- })
344
- .execute()
345
-
346
- if (run.pendingApprovals?.length) {
347
- await this.setApprovals(runId, run.pendingApprovals)
348
- }
349
-
350
- return runId
351
- }
352
-
353
- async updateRun(
354
- runId: string,
355
- updates: Partial<AgentRunState>
356
- ): Promise<void> {
357
- const setValues: Record<string, unknown> = { updatedAt: new Date() }
358
-
359
- if (updates.status !== undefined) {
360
- setValues.status = updates.status
361
- }
362
- if (updates.errorMessage !== undefined) {
363
- setValues.errorMessage = updates.errorMessage
364
- }
365
- if (updates.suspendReason !== undefined) {
366
- setValues.suspendReason = updates.suspendReason
367
- }
368
- if (updates.missingRpcs !== undefined) {
369
- setValues.missingRpcs = JSON.stringify(updates.missingRpcs)
370
- }
371
- if (updates.usage !== undefined) {
372
- setValues.usageInputTokens = updates.usage.inputTokens
373
- setValues.usageOutputTokens = updates.usage.outputTokens
374
- setValues.usageModel = updates.usage.model
375
- }
376
-
377
- await this.db
378
- .updateTable('agentRun')
379
- .set(setValues)
380
- .where('runId', '=', runId)
381
- .execute()
382
-
383
- if (updates.pendingApprovals !== undefined) {
384
- await this.db
385
- .updateTable('agentToolCall')
386
- .set({
387
- approvalStatus: null,
388
- runId: null,
389
- approvalType: null,
390
- agentRunId: null,
391
- displayToolName: null,
392
- displayArgs: null,
393
- })
394
- .where('runId', '=', runId)
395
- .where('approvalStatus', 'is not', null)
396
- .execute()
397
-
398
- if (updates.pendingApprovals.length) {
399
- await this.setApprovals(runId, updates.pendingApprovals)
400
- }
401
- }
402
- }
403
-
404
- async getRun(runId: string): Promise<AgentRunState | null> {
405
- const row = await this.db
406
- .selectFrom('agentRun')
407
- .select([
408
- 'runId',
409
- 'agentName',
410
- 'threadId',
411
- 'resourceId',
412
- 'status',
413
- 'errorMessage',
414
- 'suspendReason',
415
- 'missingRpcs',
416
- 'usageInputTokens',
417
- 'usageOutputTokens',
418
- 'usageModel',
419
- 'createdAt',
420
- 'updatedAt',
421
- ])
422
- .where('runId', '=', runId)
423
- .executeTakeFirst()
424
-
425
- if (!row) return null
426
-
427
- const approvals = await this.db
428
- .selectFrom('agentToolCall')
429
- .select([
430
- 'id',
431
- 'toolName',
432
- 'args',
433
- 'approvalType',
434
- 'agentRunId',
435
- 'displayToolName',
436
- 'displayArgs',
437
- ])
438
- .where('runId', '=', runId)
439
- .where('approvalStatus', '=', 'pending')
440
- .execute()
441
-
442
- return this.mapRunRow(row, approvals)
443
- }
444
-
445
- async getRunsByThread(threadId: string): Promise<AgentRunState[]> {
446
- const result = await this.db
447
- .selectFrom('agentRun')
448
- .select([
449
- 'runId',
450
- 'agentName',
451
- 'threadId',
452
- 'resourceId',
453
- 'status',
454
- 'errorMessage',
455
- 'suspendReason',
456
- 'missingRpcs',
457
- 'usageInputTokens',
458
- 'usageOutputTokens',
459
- 'usageModel',
460
- 'createdAt',
461
- 'updatedAt',
462
- ])
463
- .where('threadId', '=', threadId)
464
- .orderBy('createdAt', 'desc')
465
- .execute()
466
-
467
- const runs: AgentRunState[] = []
468
- for (const row of result) {
469
- const approvals = await this.db
470
- .selectFrom('agentToolCall')
471
- .select([
472
- 'id',
473
- 'toolName',
474
- 'args',
475
- 'approvalType',
476
- 'agentRunId',
477
- 'displayToolName',
478
- 'displayArgs',
479
- ])
480
- .where('runId', '=', row.runId)
481
- .where('approvalStatus', '=', 'pending')
482
- .execute()
483
- runs.push(this.mapRunRow(row, approvals))
484
- }
485
- return runs
486
- }
487
-
488
- private async setApprovals(
489
- runId: string,
490
- approvals: NonNullable<AgentRunState['pendingApprovals']>
491
- ): Promise<void> {
492
- for (const a of approvals) {
493
- if (a.type === 'agent-call') {
494
- await this.db
495
- .updateTable('agentToolCall')
496
- .set({
497
- approvalStatus: 'pending',
498
- runId: runId,
499
- approvalType: 'agent-call',
500
- agentRunId: a.agentRunId,
501
- displayToolName: a.displayToolName,
502
- displayArgs: JSON.stringify(a.displayArgs),
503
- })
504
- .where('id', '=', a.toolCallId)
505
- .execute()
506
- } else {
507
- await this.db
508
- .updateTable('agentToolCall')
509
- .set({
510
- approvalStatus: 'pending',
511
- runId: runId,
512
- approvalType: 'tool-call',
513
- })
514
- .where('id', '=', a.toolCallId)
515
- .execute()
516
- }
517
- }
518
- }
519
-
520
- private mapRunRow(row: any, approvalRows?: any[]): AgentRunState {
521
- const pendingApprovals = approvalRows?.length
522
- ? approvalRows.map((a: any) => {
523
- if (a.approvalType === 'agent-call') {
524
- return {
525
- type: 'agent-call' as const,
526
- toolCallId: a.id as string,
527
- agentName: a.toolName as string,
528
- agentRunId: a.agentRunId as string,
529
- displayToolName: a.displayToolName as string,
530
- displayArgs: parseJson(a.displayArgs) as unknown,
531
- }
532
- }
533
- return {
534
- type: 'tool-call' as const,
535
- toolCallId: a.id as string,
536
- toolName: a.toolName as string,
537
- args: parseJson(a.args) as unknown,
538
- }
539
- })
540
- : undefined
541
-
542
- return {
543
- runId: row.runId as string,
544
- agentName: row.agentName as string,
545
- threadId: row.threadId as string,
546
- resourceId: row.resourceId as string,
547
- status: row.status as AgentRunState['status'],
548
- errorMessage: row.errorMessage ?? undefined,
549
- suspendReason: row.suspendReason as AgentRunState['suspendReason'],
550
- missingRpcs: parseJson(row.missingRpcs),
551
- pendingApprovals,
552
- usage: {
553
- inputTokens: Number(row.usageInputTokens),
554
- outputTokens: Number(row.usageOutputTokens),
555
- model: row.usageModel as string,
556
- },
557
- createdAt: new Date(row.createdAt as string),
558
- updatedAt: new Date(row.updatedAt as string),
559
- }
560
- }
561
-
562
- async findRunByToolCallId(toolCallId: string): Promise<{
563
- run: AgentRunState
564
- approval: NonNullable<AgentRunState['pendingApprovals']>[number]
565
- } | null> {
566
- const tc = await this.db
567
- .selectFrom('agentToolCall')
568
- .select([
569
- 'id',
570
- 'toolName',
571
- 'args',
572
- 'runId',
573
- 'approvalType',
574
- 'agentRunId',
575
- 'displayToolName',
576
- 'displayArgs',
577
- ])
578
- .where('id', '=', toolCallId)
579
- .where('approvalStatus', '=', 'pending')
580
- .executeTakeFirst()
581
-
582
- if (!tc || !tc.runId) return null
583
-
584
- const run = await this.getRun(tc.runId)
585
- if (!run) return null
586
-
587
- let approval: NonNullable<AgentRunState['pendingApprovals']>[number]
588
- if (tc.approvalType === 'agent-call') {
589
- approval = {
590
- type: 'agent-call',
591
- toolCallId: tc.id,
592
- agentName: tc.toolName,
593
- agentRunId: tc.agentRunId!,
594
- displayToolName: tc.displayToolName!,
595
- displayArgs: parseJson(tc.displayArgs) as unknown,
596
- }
597
- } else {
598
- approval = {
599
- type: 'tool-call',
600
- toolCallId: tc.id,
601
- toolName: tc.toolName,
602
- args: parseJson(tc.args) as unknown,
603
- }
604
- }
605
-
606
- return { run, approval }
607
- }
608
-
609
- async resolveApproval(
610
- toolCallId: string,
611
- status: 'approved' | 'denied'
612
- ): Promise<boolean> {
613
- // Only the caller that moves the tool call off 'pending' has claimed it.
614
- const result = await this.db
615
- .updateTable('agentToolCall')
616
- .set({ approvalStatus: status })
617
- .where('id', '=', toolCallId)
618
- .where('approvalStatus', '=', 'pending')
619
- .executeTakeFirst()
620
- return Number(result?.numUpdatedRows ?? 0) > 0
621
- }
622
-
623
- async saveScore(score: SaveScoreInput): Promise<void> {
624
- await saveRunScore(this.db, score)
625
- }
626
-
627
- async getScores(runId: string): Promise<AgentRunScore[]> {
628
- return getRunScores(this.db, runId)
629
- }
630
-
631
- public async close(): Promise<void> {}
632
- }