@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.
- package/CHANGELOG.md +128 -0
- package/dist/src/index.d.ts +8 -11
- package/dist/src/index.js +5 -6
- package/dist/src/kysely-agent-run-scores.d.ts +10 -0
- package/dist/src/kysely-agent-run-scores.js +34 -0
- package/dist/src/kysely-agent-run-service.d.ts +22 -0
- package/dist/src/kysely-agent-run-service.js +190 -0
- package/dist/src/kysely-agent-run-state-service.d.ts +24 -0
- package/dist/src/kysely-agent-run-state-service.js +169 -0
- package/dist/src/kysely-agent-storage-service.d.ts +40 -0
- package/dist/src/kysely-agent-storage-service.js +533 -0
- package/dist/src/kysely-ai-agent-run-service.d.ts +2 -1
- package/dist/src/kysely-ai-run-scores.d.ts +10 -0
- package/dist/src/kysely-ai-run-scores.js +34 -0
- package/dist/src/kysely-ai-run-state-service.d.ts +6 -2
- package/dist/src/kysely-ai-run-state-service.js +7 -0
- package/dist/src/kysely-ai-storage-service.d.ts +4 -1
- package/dist/src/kysely-ai-storage-service.js +7 -0
- package/dist/src/kysely-audit-service.d.ts +3 -1
- package/dist/src/kysely-deployment-service.d.ts +1 -1
- package/dist/src/kysely-deployment-service.js +2 -2
- package/dist/src/kysely-eventhub-store.d.ts +1 -1
- package/dist/src/kysely-eventhub-store.js +1 -1
- package/dist/src/kysely-scope-service.d.ts +4 -3
- package/dist/src/kysely-tables.d.ts +23 -11
- package/dist/src/kysely-virtual-user-run-store.d.ts +1 -1
- package/dist/src/kysely-webhook-service.d.ts +2 -1
- package/dist/src/kysely-webhook-service.js +2 -1
- package/dist/src/kysely-workflow-mirror.d.ts +2 -2
- package/dist/src/kysely-workflow-run-service.d.ts +1 -1
- package/dist/src/kysely-workflow-service.d.ts +3 -2
- package/dist/src/kysely-workflow-service.js +1 -1
- package/dist/src/schema/agent.schema.d.ts +12 -0
- package/dist/src/schema/agent.schema.js +102 -0
- package/dist/src/schema/ai.schema.js +13 -0
- package/dist/src/schema/index.js +4 -4
- package/dist/src/serialize-plugin.d.ts +0 -4
- package/dist/src/serialize-plugin.js +0 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/index.ts +9 -22
- package/src/kysely-agent-run-scores.ts +47 -0
- package/src/{kysely-ai-agent-run-service.ts → kysely-agent-run-service.ts} +17 -18
- package/src/{kysely-ai-run-state-service.ts → kysely-agent-run-state-service.ts} +27 -12
- package/src/{kysely-ai-storage-service.ts → kysely-agent-storage-service.ts} +61 -40
- package/src/kysely-audit-service.ts +4 -2
- package/src/kysely-deployment-service.ts +3 -3
- package/src/kysely-eventhub-store.ts +1 -1
- package/src/kysely-scope-service.ts +7 -4
- package/src/kysely-services.test.ts +11 -10
- package/src/kysely-tables.ts +24 -11
- package/src/kysely-virtual-user-run-store.ts +2 -2
- package/src/kysely-webhook-service.ts +2 -2
- package/src/kysely-workflow-mirror.ts +2 -2
- package/src/kysely-workflow-run-service.ts +1 -1
- package/src/kysely-workflow-service.ts +3 -12
- package/src/schema/{ai.schema.ts → agent.schema.ts} +46 -25
- package/src/schema/index.ts +4 -4
- package/src/schema/schema.test.ts +6 -6
- 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/
|
|
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<
|
|
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('
|
|
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('
|
|
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<
|
|
89
|
+
async getThread(threadId: string): Promise<AgentThread | null> {
|
|
91
90
|
const row = await this.db
|
|
92
|
-
.selectFrom('
|
|
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<
|
|
107
|
+
async getThreadMessages(threadId: string): Promise<AgentMessage[]> {
|
|
109
108
|
const [msgResult, tcResult] = await Promise.all([
|
|
110
109
|
this.db
|
|
111
|
-
.selectFrom('
|
|
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('
|
|
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:
|
|
130
|
+
const messages: AgentMessage[] = []
|
|
132
131
|
for (const row of msgResult) {
|
|
133
|
-
const msg:
|
|
132
|
+
const msg: AgentMessage = {
|
|
134
133
|
id: row.id,
|
|
135
|
-
role: row.role as
|
|
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('
|
|
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('
|
|
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('
|
|
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):
|
|
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 {
|
|
5
|
-
|
|
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 {
|
|
13
|
+
import { agentSchema } from './schema/agent.schema.js'
|
|
14
|
+
import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
|
|
8
15
|
|
|
9
|
-
export class
|
|
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,
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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
|
-
|
|
3
|
-
|
|
2
|
+
AgentStorageService,
|
|
3
|
+
AgentRunStateService,
|
|
4
4
|
CreateRunInput,
|
|
5
|
+
SaveScoreInput,
|
|
5
6
|
} from '@pikku/core/services'
|
|
6
|
-
import type {
|
|
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 {
|
|
18
|
+
import { agentSchema } from './schema/agent.schema.js'
|
|
12
19
|
|
|
13
|
-
export class
|
|
14
|
-
implements
|
|
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,
|
|
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<
|
|
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('
|
|
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<
|
|
66
|
+
async getThread(threadId: string): Promise<AgentThread> {
|
|
60
67
|
const row = await this.db
|
|
61
|
-
.selectFrom('
|
|
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<
|
|
94
|
+
async getThreads(resourceId: string): Promise<AgentThread[]> {
|
|
88
95
|
const result = await this.db
|
|
89
|
-
.selectFrom('
|
|
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
|
|
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<
|
|
129
|
+
): Promise<AgentMessage[]> {
|
|
120
130
|
let msgQuery = this.db
|
|
121
|
-
.selectFrom('
|
|
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('
|
|
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('
|
|
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:
|
|
173
|
+
const messages: AgentMessage[] = []
|
|
164
174
|
for (const row of msgResult) {
|
|
165
175
|
const rawContent = row.content as string | undefined
|
|
166
|
-
let parsedContent:
|
|
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:
|
|
189
|
+
const msg: AgentMessage = {
|
|
180
190
|
id: row.id,
|
|
181
|
-
role: row.role as
|
|
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(
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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
|
-
|
|
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,6 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
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<
|
|
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 {
|
|
17
|
-
import { KyselyAgentRunService } from './kysely-
|
|
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
|
-
'
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
'
|
|
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
|
-
|
|
100
|
-
const s = new
|
|
100
|
+
agentStorageService: async () => {
|
|
101
|
+
const s = new KyselyAgentStorageService(getDb())
|
|
101
102
|
await s.init()
|
|
102
103
|
return s
|
|
103
104
|
},
|