@pikku/kysely 0.13.13 → 0.13.16

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 (60) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/dist/src/index.d.ts +8 -11
  3. package/dist/src/index.js +5 -6
  4. package/dist/src/kysely-agent-run-scores.d.ts +10 -0
  5. package/dist/src/kysely-agent-run-scores.js +34 -0
  6. package/dist/src/kysely-agent-run-service.d.ts +22 -0
  7. package/dist/src/kysely-agent-run-service.js +190 -0
  8. package/dist/src/kysely-agent-run-state-service.d.ts +24 -0
  9. package/dist/src/kysely-agent-run-state-service.js +169 -0
  10. package/dist/src/kysely-agent-storage-service.d.ts +40 -0
  11. package/dist/src/kysely-agent-storage-service.js +533 -0
  12. package/dist/src/kysely-ai-agent-run-service.d.ts +2 -1
  13. package/dist/src/kysely-ai-run-scores.d.ts +10 -0
  14. package/dist/src/kysely-ai-run-scores.js +34 -0
  15. package/dist/src/kysely-ai-run-state-service.d.ts +6 -2
  16. package/dist/src/kysely-ai-run-state-service.js +7 -0
  17. package/dist/src/kysely-ai-storage-service.d.ts +4 -1
  18. package/dist/src/kysely-ai-storage-service.js +7 -0
  19. package/dist/src/kysely-audit-service.d.ts +3 -1
  20. package/dist/src/kysely-deployment-service.d.ts +1 -1
  21. package/dist/src/kysely-deployment-service.js +2 -2
  22. package/dist/src/kysely-eventhub-store.d.ts +1 -1
  23. package/dist/src/kysely-eventhub-store.js +1 -1
  24. package/dist/src/kysely-scope-service.d.ts +4 -3
  25. package/dist/src/kysely-tables.d.ts +23 -11
  26. package/dist/src/kysely-virtual-user-run-store.d.ts +1 -1
  27. package/dist/src/kysely-webhook-service.d.ts +2 -1
  28. package/dist/src/kysely-webhook-service.js +2 -1
  29. package/dist/src/kysely-workflow-mirror.d.ts +2 -2
  30. package/dist/src/kysely-workflow-run-service.d.ts +1 -1
  31. package/dist/src/kysely-workflow-service.d.ts +3 -2
  32. package/dist/src/kysely-workflow-service.js +1 -1
  33. package/dist/src/schema/agent.schema.d.ts +12 -0
  34. package/dist/src/schema/agent.schema.js +102 -0
  35. package/dist/src/schema/ai.schema.js +13 -0
  36. package/dist/src/schema/index.js +4 -4
  37. package/dist/src/serialize-plugin.d.ts +0 -4
  38. package/dist/src/serialize-plugin.js +0 -4
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +2 -2
  41. package/src/index.ts +9 -22
  42. package/src/kysely-agent-run-scores.ts +47 -0
  43. package/src/{kysely-ai-agent-run-service.ts → kysely-agent-run-service.ts} +17 -18
  44. package/src/{kysely-ai-run-state-service.ts → kysely-agent-run-state-service.ts} +27 -12
  45. package/src/{kysely-ai-storage-service.ts → kysely-agent-storage-service.ts} +61 -40
  46. package/src/kysely-audit-service.ts +4 -2
  47. package/src/kysely-deployment-service.ts +3 -3
  48. package/src/kysely-eventhub-store.ts +1 -1
  49. package/src/kysely-scope-service.ts +7 -4
  50. package/src/kysely-services.test.ts +11 -10
  51. package/src/kysely-tables.ts +24 -11
  52. package/src/kysely-virtual-user-run-store.ts +2 -2
  53. package/src/kysely-webhook-service.ts +2 -2
  54. package/src/kysely-workflow-mirror.ts +2 -2
  55. package/src/kysely-workflow-run-service.ts +1 -1
  56. package/src/kysely-workflow-service.ts +3 -12
  57. package/src/schema/{ai.schema.ts → agent.schema.ts} +46 -25
  58. package/src/schema/index.ts +4 -4
  59. package/src/schema/schema.test.ts +6 -6
  60. package/src/serialize-plugin.ts +0 -5
@@ -1,9 +1,8 @@
1
+ import type { AgentThread, AgentMessage } from '@pikku/core/agent'
1
2
  import type {
2
- AIThread,
3
- AIMessage,
4
3
  AgentRunRow,
5
4
  AgentRunService,
6
- } from '@pikku/core/ai-agent'
5
+ } from '@pikku/core/ecosystem/agent'
7
6
  import type { Kysely } from 'kysely'
8
7
  import { sql } from 'kysely'
9
8
  import type { KyselyPikkuDB } from './kysely-tables.js'
@@ -23,7 +22,7 @@ export class KyselyAgentRunService implements AgentRunService {
23
22
  owners?: string[]
24
23
  limit?: number
25
24
  offset?: number
26
- }): Promise<AIThread[]> {
25
+ }): Promise<AgentThread[]> {
27
26
  const {
28
27
  agentName,
29
28
  resourceId,
@@ -37,7 +36,7 @@ export class KyselyAgentRunService implements AgentRunService {
37
36
  if (owners && owners.length === 0) return []
38
37
 
39
38
  let query = this.db
40
- .selectFrom('aiThreads as t')
39
+ .selectFrom('agentThreads as t')
41
40
  .select([
42
41
  't.id',
43
42
  't.resourceId',
@@ -52,7 +51,7 @@ export class KyselyAgentRunService implements AgentRunService {
52
51
  't.id',
53
52
  'in',
54
53
  this.db
55
- .selectFrom('aiRun')
54
+ .selectFrom('agentRun')
56
55
  .select('threadId')
57
56
  .where('agentName', '=', agentName)
58
57
  .distinct()
@@ -87,9 +86,9 @@ export class KyselyAgentRunService implements AgentRunService {
87
86
  return result.map((row) => this.mapThreadRow(row))
88
87
  }
89
88
 
90
- async getThread(threadId: string): Promise<AIThread | null> {
89
+ async getThread(threadId: string): Promise<AgentThread | null> {
91
90
  const row = await this.db
92
- .selectFrom('aiThreads')
91
+ .selectFrom('agentThreads')
93
92
  .select([
94
93
  'id',
95
94
  'resourceId',
@@ -105,16 +104,16 @@ export class KyselyAgentRunService implements AgentRunService {
105
104
  return this.mapThreadRow(row)
106
105
  }
107
106
 
108
- async getThreadMessages(threadId: string): Promise<AIMessage[]> {
107
+ async getThreadMessages(threadId: string): Promise<AgentMessage[]> {
109
108
  const [msgResult, tcResult] = await Promise.all([
110
109
  this.db
111
- .selectFrom('aiMessage')
110
+ .selectFrom('agentMessage')
112
111
  .select(['id', 'role', 'content', 'createdAt'])
113
112
  .where('threadId', '=', threadId)
114
113
  .orderBy('createdAt', 'asc')
115
114
  .execute(),
116
115
  this.db
117
- .selectFrom('aiToolCall')
116
+ .selectFrom('agentToolCall')
118
117
  .select(['id', 'messageId', 'toolName', 'args', 'result'])
119
118
  .where('threadId', '=', threadId)
120
119
  .orderBy('createdAt', 'asc')
@@ -128,11 +127,11 @@ export class KyselyAgentRunService implements AgentRunService {
128
127
  tcByMessage.get(msgId)!.push(tc)
129
128
  }
130
129
 
131
- const messages: AIMessage[] = []
130
+ const messages: AgentMessage[] = []
132
131
  for (const row of msgResult) {
133
- const msg: AIMessage = {
132
+ const msg: AgentMessage = {
134
133
  id: row.id,
135
- role: row.role as AIMessage['role'],
134
+ role: row.role as AgentMessage['role'],
136
135
  content: row.content ?? undefined,
137
136
  createdAt: new Date(row.createdAt as unknown as string),
138
137
  }
@@ -170,7 +169,7 @@ export class KyselyAgentRunService implements AgentRunService {
170
169
 
171
170
  async getThreadRuns(threadId: string): Promise<AgentRunRow[]> {
172
171
  const result = await this.db
173
- .selectFrom('aiRun')
172
+ .selectFrom('agentRun')
174
173
  .select([
175
174
  'runId',
176
175
  'agentName',
@@ -195,7 +194,7 @@ export class KyselyAgentRunService implements AgentRunService {
195
194
 
196
195
  async deleteThread(threadId: string): Promise<boolean> {
197
196
  const result = await this.db
198
- .deleteFrom('aiThreads')
197
+ .deleteFrom('agentThreads')
199
198
  .where('id', '=', threadId)
200
199
  .executeTakeFirst()
201
200
 
@@ -204,7 +203,7 @@ export class KyselyAgentRunService implements AgentRunService {
204
203
 
205
204
  async getDistinctAgentNames(): Promise<string[]> {
206
205
  const result = await this.db
207
- .selectFrom('aiRun')
206
+ .selectFrom('agentRun')
208
207
  .select('agentName')
209
208
  .distinct()
210
209
  .orderBy('agentName')
@@ -213,7 +212,7 @@ export class KyselyAgentRunService implements AgentRunService {
213
212
  return result.map((row) => row.agentName)
214
213
  }
215
214
 
216
- private mapThreadRow(row: any): AIThread {
215
+ private mapThreadRow(row: any): AgentThread {
217
216
  return {
218
217
  id: row.id as string,
219
218
  resourceId: row.resourceId as string,
@@ -1,26 +1,33 @@
1
1
  import { sql } from 'kysely'
2
2
  import type { Kysely } from 'kysely'
3
3
  import type { KyselyPikkuDB } from './kysely-tables.js'
4
- import type { AIRunStateService, CreateRunInput } from '@pikku/core/services'
5
- import type { AgentRunState, PendingApproval } from '@pikku/core/ai-agent'
4
+ import type {
5
+ AgentRunStateService,
6
+ CreateRunInput,
7
+ SaveScoreInput,
8
+ } from '@pikku/core/services'
9
+ import type { AgentRunState } from '@pikku/core/agent'
10
+ import type { PendingApproval } from '@pikku/core/ecosystem/agent'
11
+ import type { AgentRunScore } from '@pikku/core/agent-scorer'
6
12
  import { ensurePikkuSchema } from './schema/index.js'
7
- import { aiSchema } from './schema/ai.schema.js'
13
+ import { agentSchema } from './schema/agent.schema.js'
14
+ import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
8
15
 
9
- export class KyselyAIRunStateService implements AIRunStateService {
16
+ export class KyselyAgentRunStateService implements AgentRunStateService {
10
17
  private initialized = false
11
18
 
12
19
  constructor(private db: Kysely<KyselyPikkuDB>) {}
13
20
 
14
21
  async init(): Promise<void> {
15
22
  if (this.initialized) return
16
- await ensurePikkuSchema(this.db, aiSchema)
23
+ await ensurePikkuSchema(this.db, agentSchema)
17
24
  this.initialized = true
18
25
  }
19
26
 
20
27
  async createRun(run: CreateRunInput): Promise<string> {
21
28
  const runId = `run-${crypto.randomUUID()}`
22
29
  await this.db
23
- .insertInto('aiRun')
30
+ .insertInto('agentRun')
24
31
  .values({
25
32
  runId,
26
33
  agentName: run.agentName,
@@ -61,7 +68,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
61
68
  }
62
69
 
63
70
  await this.db
64
- .updateTable('aiRun')
71
+ .updateTable('agentRun')
65
72
  .set(values)
66
73
  .where('runId', '=', runId)
67
74
  .execute()
@@ -69,7 +76,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
69
76
 
70
77
  async getRun(runId: string): Promise<AgentRunState | null> {
71
78
  const row = await this.db
72
- .selectFrom('aiRun')
79
+ .selectFrom('agentRun')
73
80
  .selectAll()
74
81
  .where('runId', '=', runId)
75
82
  .executeTakeFirst()
@@ -78,7 +85,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
78
85
 
79
86
  async getRunsByThread(threadId: string): Promise<AgentRunState[]> {
80
87
  const rows = await this.db
81
- .selectFrom('aiRun')
88
+ .selectFrom('agentRun')
82
89
  .selectAll()
83
90
  .where('threadId', '=', threadId)
84
91
  .orderBy('createdAt', 'desc')
@@ -91,7 +98,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
91
98
  status: 'approved' | 'denied'
92
99
  ): Promise<boolean> {
93
100
  const rows = await this.db
94
- .selectFrom('aiRun')
101
+ .selectFrom('agentRun')
95
102
  .select(['runId', 'pendingApprovals'])
96
103
  .where('status', '=', 'suspended')
97
104
  .execute()
@@ -120,7 +127,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
120
127
  // Compare-and-swap on the list we read: a concurrent approver that got
121
128
  // there first has already rewritten it, and this update matches no row.
122
129
  const result = await this.db
123
- .updateTable('aiRun')
130
+ .updateTable('agentRun')
124
131
  .set(updates as any)
125
132
  .where('runId', '=', row.runId)
126
133
  .where('status', '=', 'suspended')
@@ -136,7 +143,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
136
143
  toolCallId: string
137
144
  ): Promise<{ run: AgentRunState; approval: PendingApproval } | null> {
138
145
  const rows = await this.db
139
- .selectFrom('aiRun')
146
+ .selectFrom('agentRun')
140
147
  .selectAll()
141
148
  .where('status', '=', 'suspended')
142
149
  .execute()
@@ -160,6 +167,14 @@ export class KyselyAIRunStateService implements AIRunStateService {
160
167
  return null
161
168
  }
162
169
 
170
+ async saveScore(score: SaveScoreInput): Promise<void> {
171
+ await saveRunScore(this.db, score)
172
+ }
173
+
174
+ async getScores(runId: string): Promise<AgentRunScore[]> {
175
+ return getRunScores(this.db, runId)
176
+ }
177
+
163
178
  private toRunState(row: any): AgentRunState {
164
179
  return {
165
180
  runId: row.runId,
@@ -1,17 +1,24 @@
1
1
  import type {
2
- AIStorageService,
3
- AIRunStateService,
2
+ AgentStorageService,
3
+ AgentRunStateService,
4
4
  CreateRunInput,
5
+ SaveScoreInput,
5
6
  } from '@pikku/core/services'
6
- import type { AIThread, AIMessage, AgentRunState } from '@pikku/core/ai-agent'
7
+ import type {
8
+ AgentThread,
9
+ AgentMessage,
10
+ AgentRunState,
11
+ } from '@pikku/core/agent'
12
+ import type { AgentRunScore } from '@pikku/core/agent-scorer'
7
13
  import type { Kysely } from 'kysely'
8
14
  import type { KyselyPikkuDB } from './kysely-tables.js'
9
15
  import { parseJson } from './kysely-json.js'
16
+ import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
10
17
  import { ensurePikkuSchema } from './schema/index.js'
11
- import { aiSchema } from './schema/ai.schema.js'
18
+ import { agentSchema } from './schema/agent.schema.js'
12
19
 
13
- export class KyselyAIStorageService
14
- implements AIStorageService, AIRunStateService
20
+ export class KyselyAgentStorageService
21
+ implements AgentStorageService, AgentRunStateService
15
22
  {
16
23
  private initialized = false
17
24
 
@@ -19,7 +26,7 @@ export class KyselyAIStorageService
19
26
 
20
27
  public async init(): Promise<void> {
21
28
  if (this.initialized) return
22
- await ensurePikkuSchema(this.db, aiSchema)
29
+ await ensurePikkuSchema(this.db, agentSchema)
23
30
  this.initialized = true
24
31
  }
25
32
 
@@ -30,12 +37,12 @@ export class KyselyAIStorageService
30
37
  title?: string
31
38
  metadata?: Record<string, unknown>
32
39
  }
33
- ): Promise<AIThread> {
40
+ ): Promise<AgentThread> {
34
41
  const id = options?.threadId ?? crypto.randomUUID()
35
42
  const now = new Date()
36
43
 
37
44
  await this.db
38
- .insertInto('aiThreads')
45
+ .insertInto('agentThreads')
39
46
  .values({
40
47
  id,
41
48
  resourceId: resourceId,
@@ -56,9 +63,9 @@ export class KyselyAIStorageService
56
63
  }
57
64
  }
58
65
 
59
- async getThread(threadId: string): Promise<AIThread> {
66
+ async getThread(threadId: string): Promise<AgentThread> {
60
67
  const row = await this.db
61
- .selectFrom('aiThreads')
68
+ .selectFrom('agentThreads')
62
69
  .select([
63
70
  'id',
64
71
  'resourceId',
@@ -84,9 +91,9 @@ export class KyselyAIStorageService
84
91
  }
85
92
  }
86
93
 
87
- async getThreads(resourceId: string): Promise<AIThread[]> {
94
+ async getThreads(resourceId: string): Promise<AgentThread[]> {
88
95
  const result = await this.db
89
- .selectFrom('aiThreads')
96
+ .selectFrom('agentThreads')
90
97
  .select([
91
98
  'id',
92
99
  'resourceId',
@@ -110,21 +117,24 @@ export class KyselyAIStorageService
110
117
  }
111
118
 
112
119
  async deleteThread(threadId: string): Promise<void> {
113
- await this.db.deleteFrom('aiThreads').where('id', '=', threadId).execute()
120
+ await this.db
121
+ .deleteFrom('agentThreads')
122
+ .where('id', '=', threadId)
123
+ .execute()
114
124
  }
115
125
 
116
126
  async getMessages(
117
127
  threadId: string,
118
128
  options?: { lastN?: number; cursor?: string }
119
- ): Promise<AIMessage[]> {
129
+ ): Promise<AgentMessage[]> {
120
130
  let msgQuery = this.db
121
- .selectFrom('aiMessage')
131
+ .selectFrom('agentMessage')
122
132
  .select(['id', 'role', 'content', 'createdAt'])
123
133
  .where('threadId', '=', threadId)
124
134
 
125
135
  if (options?.cursor) {
126
136
  const cursorRow = await this.db
127
- .selectFrom('aiMessage')
137
+ .selectFrom('agentMessage')
128
138
  .select('createdAt')
129
139
  .where('id', '=', options.cursor)
130
140
  .executeTakeFirst()
@@ -147,7 +157,7 @@ export class KyselyAIStorageService
147
157
  }
148
158
 
149
159
  const tcResult = await this.db
150
- .selectFrom('aiToolCall')
160
+ .selectFrom('agentToolCall')
151
161
  .select(['id', 'messageId', 'toolName', 'args', 'result'])
152
162
  .where('threadId', '=', threadId)
153
163
  .orderBy('createdAt', 'asc')
@@ -160,10 +170,10 @@ export class KyselyAIStorageService
160
170
  tcByMessage.get(msgId)!.push(tc)
161
171
  }
162
172
 
163
- const messages: AIMessage[] = []
173
+ const messages: AgentMessage[] = []
164
174
  for (const row of msgResult) {
165
175
  const rawContent = row.content as string | undefined
166
- let parsedContent: AIMessage['content'] = rawContent ?? undefined
176
+ let parsedContent: AgentMessage['content'] = rawContent ?? undefined
167
177
  if (rawContent) {
168
178
  try {
169
179
  const parsed = JSON.parse(rawContent)
@@ -176,9 +186,9 @@ export class KyselyAIStorageService
176
186
  // Not JSON, use raw string
177
187
  }
178
188
  }
179
- const msg: AIMessage = {
189
+ const msg: AgentMessage = {
180
190
  id: row.id,
181
- role: row.role as AIMessage['role'],
191
+ role: row.role as AgentMessage['role'],
182
192
  content: parsedContent,
183
193
  createdAt: new Date(row.createdAt),
184
194
  }
@@ -214,7 +224,10 @@ export class KyselyAIStorageService
214
224
  return messages
215
225
  }
216
226
 
217
- async saveMessages(threadId: string, messages: AIMessage[]): Promise<void> {
227
+ async saveMessages(
228
+ threadId: string,
229
+ messages: AgentMessage[]
230
+ ): Promise<void> {
218
231
  if (messages.length === 0) return
219
232
 
220
233
  const toolMessages = messages.filter((m) => m.role === 'tool')
@@ -222,7 +235,7 @@ export class KyselyAIStorageService
222
235
 
223
236
  if (nonToolMessages.length > 0) {
224
237
  await this.db
225
- .insertInto('aiMessage')
238
+ .insertInto('agentMessage')
226
239
  .values(
227
240
  nonToolMessages.map((msg) => ({
228
241
  id: msg.id,
@@ -240,7 +253,7 @@ export class KyselyAIStorageService
240
253
  )
241
254
  if (toolCalls.length > 0) {
242
255
  await this.db
243
- .insertInto('aiToolCall')
256
+ .insertInto('agentToolCall')
244
257
  .values(
245
258
  toolCalls.map((tc) => ({
246
259
  id: tc.id,
@@ -257,7 +270,7 @@ export class KyselyAIStorageService
257
270
  if (!toolMsg.toolResults) continue
258
271
  for (const tr of toolMsg.toolResults) {
259
272
  await this.db
260
- .updateTable('aiToolCall')
273
+ .updateTable('agentToolCall')
261
274
  .set({ result: tr.result })
262
275
  .where('id', '=', tr.id)
263
276
  .execute()
@@ -265,7 +278,7 @@ export class KyselyAIStorageService
265
278
  }
266
279
 
267
280
  await this.db
268
- .updateTable('aiThreads')
281
+ .updateTable('agentThreads')
269
282
  .set({ updatedAt: new Date() })
270
283
  .where('id', '=', threadId)
271
284
  .execute()
@@ -276,7 +289,7 @@ export class KyselyAIStorageService
276
289
  scope: 'resource' | 'thread'
277
290
  ): Promise<Record<string, unknown> | null> {
278
291
  const row = await this.db
279
- .selectFrom('aiWorkingMemory')
292
+ .selectFrom('agentWorkingMemory')
280
293
  .select('data')
281
294
  .where('id', '=', id)
282
295
  .where('scope', '=', scope)
@@ -292,7 +305,7 @@ export class KyselyAIStorageService
292
305
  data: Record<string, unknown>
293
306
  ): Promise<void> {
294
307
  await this.db
295
- .insertInto('aiWorkingMemory')
308
+ .insertInto('agentWorkingMemory')
296
309
  .values({
297
310
  id,
298
311
  scope,
@@ -312,7 +325,7 @@ export class KyselyAIStorageService
312
325
  const runId = crypto.randomUUID()
313
326
 
314
327
  await this.db
315
- .insertInto('aiRun')
328
+ .insertInto('agentRun')
316
329
  .values({
317
330
  runId: runId,
318
331
  agentName: run.agentName,
@@ -362,14 +375,14 @@ export class KyselyAIStorageService
362
375
  }
363
376
 
364
377
  await this.db
365
- .updateTable('aiRun')
378
+ .updateTable('agentRun')
366
379
  .set(setValues)
367
380
  .where('runId', '=', runId)
368
381
  .execute()
369
382
 
370
383
  if (updates.pendingApprovals !== undefined) {
371
384
  await this.db
372
- .updateTable('aiToolCall')
385
+ .updateTable('agentToolCall')
373
386
  .set({
374
387
  approvalStatus: null,
375
388
  runId: null,
@@ -390,7 +403,7 @@ export class KyselyAIStorageService
390
403
 
391
404
  async getRun(runId: string): Promise<AgentRunState | null> {
392
405
  const row = await this.db
393
- .selectFrom('aiRun')
406
+ .selectFrom('agentRun')
394
407
  .select([
395
408
  'runId',
396
409
  'agentName',
@@ -412,7 +425,7 @@ export class KyselyAIStorageService
412
425
  if (!row) return null
413
426
 
414
427
  const approvals = await this.db
415
- .selectFrom('aiToolCall')
428
+ .selectFrom('agentToolCall')
416
429
  .select([
417
430
  'id',
418
431
  'toolName',
@@ -431,7 +444,7 @@ export class KyselyAIStorageService
431
444
 
432
445
  async getRunsByThread(threadId: string): Promise<AgentRunState[]> {
433
446
  const result = await this.db
434
- .selectFrom('aiRun')
447
+ .selectFrom('agentRun')
435
448
  .select([
436
449
  'runId',
437
450
  'agentName',
@@ -454,7 +467,7 @@ export class KyselyAIStorageService
454
467
  const runs: AgentRunState[] = []
455
468
  for (const row of result) {
456
469
  const approvals = await this.db
457
- .selectFrom('aiToolCall')
470
+ .selectFrom('agentToolCall')
458
471
  .select([
459
472
  'id',
460
473
  'toolName',
@@ -479,7 +492,7 @@ export class KyselyAIStorageService
479
492
  for (const a of approvals) {
480
493
  if (a.type === 'agent-call') {
481
494
  await this.db
482
- .updateTable('aiToolCall')
495
+ .updateTable('agentToolCall')
483
496
  .set({
484
497
  approvalStatus: 'pending',
485
498
  runId: runId,
@@ -492,7 +505,7 @@ export class KyselyAIStorageService
492
505
  .execute()
493
506
  } else {
494
507
  await this.db
495
- .updateTable('aiToolCall')
508
+ .updateTable('agentToolCall')
496
509
  .set({
497
510
  approvalStatus: 'pending',
498
511
  runId: runId,
@@ -551,7 +564,7 @@ export class KyselyAIStorageService
551
564
  approval: NonNullable<AgentRunState['pendingApprovals']>[number]
552
565
  } | null> {
553
566
  const tc = await this.db
554
- .selectFrom('aiToolCall')
567
+ .selectFrom('agentToolCall')
555
568
  .select([
556
569
  'id',
557
570
  'toolName',
@@ -599,7 +612,7 @@ export class KyselyAIStorageService
599
612
  ): Promise<boolean> {
600
613
  // Only the caller that moves the tool call off 'pending' has claimed it.
601
614
  const result = await this.db
602
- .updateTable('aiToolCall')
615
+ .updateTable('agentToolCall')
603
616
  .set({ approvalStatus: status })
604
617
  .where('id', '=', toolCallId)
605
618
  .where('approvalStatus', '=', 'pending')
@@ -607,5 +620,13 @@ export class KyselyAIStorageService
607
620
  return Number(result?.numUpdatedRows ?? 0) > 0
608
621
  }
609
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
+
610
631
  public async close(): Promise<void> {}
611
632
  }
@@ -1,11 +1,13 @@
1
+ import type { AuditService } from '@pikku/core'
1
2
  import type {
2
3
  AuditEvent,
3
4
  AuditEventBatch,
5
+ } from '@pikku/core/ecosystem/services'
6
+ import type {
4
7
  AuditFacets,
5
8
  AuditQuery,
6
9
  AuditQueryResult,
7
- AuditService,
8
- } from '@pikku/core'
10
+ } from '@pikku/core/ecosystem/types'
9
11
  import type { Kysely } from 'kysely'
10
12
  import { ensurePikkuSchema } from './schema/index.js'
11
13
  import { auditSchema } from './schema/audit.schema.js'
@@ -1,11 +1,11 @@
1
- import { buildRemoteHeaders } from '@pikku/core/remote'
1
+ import { buildRemoteHeaders } from '@pikku/core/ecosystem/remote'
2
2
  import type {
3
3
  DeploymentService,
4
4
  DeploymentServiceConfig,
5
5
  DeploymentConfig,
6
- } from '@pikku/core/services'
6
+ } from '@pikku/core/ecosystem/services'
7
7
  import type { JWTService, SecretService } from '@pikku/core/services'
8
- import { getAllFunctionNames } from '@pikku/core/function'
8
+ import { getAllFunctionNames } from '@pikku/core/ecosystem/function'
9
9
  import type { Kysely } from 'kysely'
10
10
  import type { KyselyPikkuDB } from './kysely-tables.js'
11
11
  import { ensurePikkuSchema } from './schema/index.js'
@@ -1,4 +1,4 @@
1
- import { EventHubStore } from '@pikku/core/channel'
1
+ import { EventHubStore } from '@pikku/core/ecosystem/channel'
2
2
  import type { Kysely } from 'kysely'
3
3
  import type { KyselyPikkuDB } from './kysely-tables.js'
4
4
 
@@ -1,6 +1,7 @@
1
- import type { Role, ScopeService } from '@pikku/core/services'
2
- import type { FlatScope } from '@pikku/core/scope'
3
- import type { SystemRole } from '@pikku/core/role'
1
+ import type { ScopeService } from '@pikku/core/services'
2
+ import type { Role } from '@pikku/core/ecosystem/services'
3
+ import type { FlatScope } from '@pikku/core/ecosystem/scope'
4
+ import type { SystemRole } from '@pikku/core/ecosystem/role'
4
5
  import {
5
6
  SystemRoleImmutableError,
6
7
  SystemRoleShadowedError,
@@ -378,7 +379,9 @@ export class KyselyScopeService implements ScopeService {
378
379
  * different decisions, and the number is what makes pruning a choice rather
379
380
  * than a formality.
380
381
  */
381
- async findStaleSystemRoles(): Promise<Array<{ role: string; users: number }>> {
382
+ async findStaleSystemRoles(): Promise<
383
+ Array<{ role: string; users: number }>
384
+ > {
382
385
  const stale = await this.db
383
386
  .selectFrom('pikkuRoles')
384
387
  .leftJoin('pikkuUserRole', 'pikkuUserRole.role', 'pikkuRoles.name')
@@ -5,7 +5,7 @@ import { SerializePlugin } from './serialize-plugin.js'
5
5
  import Database from 'better-sqlite3'
6
6
  import { PostgresJSDialect } from 'kysely-postgres-js'
7
7
  import postgres from 'postgres'
8
- import { defineServiceTests } from '@pikku/core/testing'
8
+ import { defineServiceTests } from '@pikku/core/ecosystem/testing'
9
9
 
10
10
  import type { KyselyPikkuDB } from './kysely-tables.js'
11
11
  import { KyselyChannelStore } from './kysely-channel-store.js'
@@ -13,8 +13,8 @@ import { KyselyEventHubStore } from './kysely-eventhub-store.js'
13
13
  import { KyselyWorkflowService } from './kysely-workflow-service.js'
14
14
  import { KyselyWorkflowRunService } from './kysely-workflow-run-service.js'
15
15
  import { KyselyDeploymentService } from './kysely-deployment-service.js'
16
- import { KyselyAIStorageService } from './kysely-ai-storage-service.js'
17
- import { KyselyAgentRunService } from './kysely-ai-agent-run-service.js'
16
+ import { KyselyAgentStorageService } from './kysely-agent-storage-service.js'
17
+ import { KyselyAgentRunService } from './kysely-agent-run-service.js'
18
18
  import { KyselySecretService } from './kysely-secret-service.js'
19
19
  import { KyselyCredentialService } from './kysely-credential-service.js'
20
20
  import { KyselySessionStore } from './kysely-session-store.js'
@@ -42,11 +42,12 @@ async function dropAllTables(db: Kysely<KyselyPikkuDB>): Promise<void> {
42
42
  const tables = [
43
43
  'pikku_deployment_functions',
44
44
  'pikku_deployments',
45
- 'ai_tool_call',
46
- 'ai_message',
47
- 'ai_run',
48
- 'ai_working_memory',
49
- 'ai_threads',
45
+ 'agent_tool_call',
46
+ 'agent_message',
47
+ 'agent_run_score',
48
+ 'agent_run',
49
+ 'agent_working_memory',
50
+ 'agent_threads',
50
51
  'channel_subscriptions',
51
52
  'channels',
52
53
  'workflow_step_history',
@@ -96,8 +97,8 @@ function registerTests(
96
97
  await s.init()
97
98
  return s
98
99
  },
99
- aiStorageService: async () => {
100
- const s = new KyselyAIStorageService(getDb())
100
+ agentStorageService: async () => {
101
+ const s = new KyselyAgentStorageService(getDb())
101
102
  await s.init()
102
103
  return s
103
104
  },