@pikku/kysely 0.13.15 → 0.13.18
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 +229 -0
- package/bin/pikku-kysely-pure.ts +0 -0
- package/dist/src/coercion-plugin.d.ts +41 -0
- package/dist/src/coercion-plugin.js +150 -0
- package/dist/src/create-audited-kysely.d.ts +1 -1
- package/dist/src/index.d.ts +6 -5
- package/dist/src/index.js +5 -4
- package/dist/src/{kysely-ai-run-scores.d.ts → kysely-agent-run-scores.d.ts} +3 -3
- package/dist/src/{kysely-ai-run-scores.js → kysely-agent-run-scores.js} +3 -3
- package/dist/src/{kysely-ai-agent-run-service.d.ts → kysely-agent-run-service.d.ts} +4 -4
- package/dist/src/{kysely-ai-agent-run-service.js → kysely-agent-run-service.js} +8 -8
- package/dist/src/{kysely-ai-run-state-service.d.ts → kysely-agent-run-state-service.d.ts} +6 -5
- package/dist/src/{kysely-ai-run-state-service.js → kysely-agent-run-state-service.js} +11 -11
- package/dist/src/{kysely-ai-storage-service.d.ts → kysely-agent-storage-service.d.ts} +10 -10
- package/dist/src/{kysely-ai-storage-service.js → kysely-agent-storage-service.js} +31 -28
- package/dist/src/kysely-audit-service.d.ts +3 -1
- package/dist/src/kysely-channel-store.d.ts +1 -1
- package/dist/src/kysely-credential-service.js +1 -1
- package/dist/src/kysely-deployment-service.d.ts +2 -1
- package/dist/src/kysely-scope-service.d.ts +2 -1
- package/dist/src/kysely-secret-service.d.ts +1 -1
- package/dist/src/kysely-secret-service.js +2 -2
- package/dist/src/kysely-session-store.d.ts +1 -1
- package/dist/src/kysely-tables.d.ts +12 -12
- 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 +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/{ai.schema.d.ts → agent.schema.d.ts} +4 -4
- package/dist/src/schema/{ai.schema.js → agent.schema.js} +29 -29
- 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 +7 -7
- package/src/coercion-plugin.test.ts +160 -0
- package/src/coercion-plugin.ts +187 -0
- package/src/create-audited-kysely.test.ts +1 -1
- package/src/create-audited-kysely.ts +1 -1
- package/src/index.ts +10 -5
- package/src/{kysely-ai-run-scores.ts → kysely-agent-run-scores.ts} +5 -5
- package/src/{kysely-ai-agent-run-service.ts → kysely-agent-run-service.ts} +18 -18
- package/src/{kysely-ai-run-state-service.ts → kysely-agent-run-state-service.ts} +16 -15
- package/src/{kysely-ai-storage-service.ts → kysely-agent-storage-service.ts} +53 -43
- package/src/kysely-audit-service.test.ts +1 -1
- package/src/kysely-audit-service.ts +4 -6
- package/src/kysely-channel-store.ts +1 -1
- package/src/kysely-credential-service.ts +5 -5
- package/src/kysely-deployment-service.ts +2 -1
- package/src/kysely-scope-service.ts +5 -2
- package/src/kysely-secret-service.ts +7 -6
- package/src/kysely-services.test.ts +10 -10
- package/src/kysely-session-store.ts +1 -1
- package/src/kysely-tables.ts +12 -12
- package/src/kysely-virtual-user-run-store.ts +1 -1
- package/src/kysely-webhook-service.test.ts +1 -1
- package/src/kysely-webhook-service.ts +2 -2
- package/src/kysely-workflow-mirror.ts +1 -1
- package/src/kysely-workflow-service.test.ts +0 -1
- package/src/kysely-workflow-service.ts +11 -11
- package/src/schema/{ai.schema.ts → agent.schema.ts} +29 -29
- 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,9 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
AgentThread,
|
|
3
|
+
AgentMessage,
|
|
4
4
|
AgentRunRow,
|
|
5
5
|
AgentRunService,
|
|
6
|
-
} from '@pikku/core/
|
|
6
|
+
} from '@pikku/core/agent'
|
|
7
7
|
import type { Kysely } from 'kysely'
|
|
8
8
|
import { sql } from 'kysely'
|
|
9
9
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
@@ -23,7 +23,7 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
23
23
|
owners?: string[]
|
|
24
24
|
limit?: number
|
|
25
25
|
offset?: number
|
|
26
|
-
}): Promise<
|
|
26
|
+
}): Promise<AgentThread[]> {
|
|
27
27
|
const {
|
|
28
28
|
agentName,
|
|
29
29
|
resourceId,
|
|
@@ -37,7 +37,7 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
37
37
|
if (owners && owners.length === 0) return []
|
|
38
38
|
|
|
39
39
|
let query = this.db
|
|
40
|
-
.selectFrom('
|
|
40
|
+
.selectFrom('agentThreads as t')
|
|
41
41
|
.select([
|
|
42
42
|
't.id',
|
|
43
43
|
't.resourceId',
|
|
@@ -52,7 +52,7 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
52
52
|
't.id',
|
|
53
53
|
'in',
|
|
54
54
|
this.db
|
|
55
|
-
.selectFrom('
|
|
55
|
+
.selectFrom('agentRun')
|
|
56
56
|
.select('threadId')
|
|
57
57
|
.where('agentName', '=', agentName)
|
|
58
58
|
.distinct()
|
|
@@ -87,9 +87,9 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
87
87
|
return result.map((row) => this.mapThreadRow(row))
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
async getThread(threadId: string): Promise<
|
|
90
|
+
async getThread(threadId: string): Promise<AgentThread | null> {
|
|
91
91
|
const row = await this.db
|
|
92
|
-
.selectFrom('
|
|
92
|
+
.selectFrom('agentThreads')
|
|
93
93
|
.select([
|
|
94
94
|
'id',
|
|
95
95
|
'resourceId',
|
|
@@ -105,16 +105,16 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
105
105
|
return this.mapThreadRow(row)
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
async getThreadMessages(threadId: string): Promise<
|
|
108
|
+
async getThreadMessages(threadId: string): Promise<AgentMessage[]> {
|
|
109
109
|
const [msgResult, tcResult] = await Promise.all([
|
|
110
110
|
this.db
|
|
111
|
-
.selectFrom('
|
|
111
|
+
.selectFrom('agentMessage')
|
|
112
112
|
.select(['id', 'role', 'content', 'createdAt'])
|
|
113
113
|
.where('threadId', '=', threadId)
|
|
114
114
|
.orderBy('createdAt', 'asc')
|
|
115
115
|
.execute(),
|
|
116
116
|
this.db
|
|
117
|
-
.selectFrom('
|
|
117
|
+
.selectFrom('agentToolCall')
|
|
118
118
|
.select(['id', 'messageId', 'toolName', 'args', 'result'])
|
|
119
119
|
.where('threadId', '=', threadId)
|
|
120
120
|
.orderBy('createdAt', 'asc')
|
|
@@ -128,11 +128,11 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
128
128
|
tcByMessage.get(msgId)!.push(tc)
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
const messages:
|
|
131
|
+
const messages: AgentMessage[] = []
|
|
132
132
|
for (const row of msgResult) {
|
|
133
|
-
const msg:
|
|
133
|
+
const msg: AgentMessage = {
|
|
134
134
|
id: row.id,
|
|
135
|
-
role: row.role as
|
|
135
|
+
role: row.role as AgentMessage['role'],
|
|
136
136
|
content: row.content ?? undefined,
|
|
137
137
|
createdAt: new Date(row.createdAt as unknown as string),
|
|
138
138
|
}
|
|
@@ -170,7 +170,7 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
170
170
|
|
|
171
171
|
async getThreadRuns(threadId: string): Promise<AgentRunRow[]> {
|
|
172
172
|
const result = await this.db
|
|
173
|
-
.selectFrom('
|
|
173
|
+
.selectFrom('agentRun')
|
|
174
174
|
.select([
|
|
175
175
|
'runId',
|
|
176
176
|
'agentName',
|
|
@@ -195,7 +195,7 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
195
195
|
|
|
196
196
|
async deleteThread(threadId: string): Promise<boolean> {
|
|
197
197
|
const result = await this.db
|
|
198
|
-
.deleteFrom('
|
|
198
|
+
.deleteFrom('agentThreads')
|
|
199
199
|
.where('id', '=', threadId)
|
|
200
200
|
.executeTakeFirst()
|
|
201
201
|
|
|
@@ -204,7 +204,7 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
204
204
|
|
|
205
205
|
async getDistinctAgentNames(): Promise<string[]> {
|
|
206
206
|
const result = await this.db
|
|
207
|
-
.selectFrom('
|
|
207
|
+
.selectFrom('agentRun')
|
|
208
208
|
.select('agentName')
|
|
209
209
|
.distinct()
|
|
210
210
|
.orderBy('agentName')
|
|
@@ -213,7 +213,7 @@ export class KyselyAgentRunService implements AgentRunService {
|
|
|
213
213
|
return result.map((row) => row.agentName)
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
private mapThreadRow(row: any):
|
|
216
|
+
private mapThreadRow(row: any): AgentThread {
|
|
217
217
|
return {
|
|
218
218
|
id: row.id as string,
|
|
219
219
|
resourceId: row.resourceId as string,
|
|
@@ -1,32 +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 { AgentRunState } from '@pikku/core/agent'
|
|
5
|
+
import type { AgentRunScore } from '@pikku/core/agent-scorer'
|
|
4
6
|
import type {
|
|
5
|
-
|
|
7
|
+
AgentRunStateService,
|
|
6
8
|
CreateRunInput,
|
|
7
9
|
SaveScoreInput,
|
|
8
10
|
} from '@pikku/core/services'
|
|
9
|
-
import type {
|
|
10
|
-
import type { AIRunScore } from '@pikku/core/ai-scorer'
|
|
11
|
+
import type { PendingApproval } from '@pikku/core/agent'
|
|
11
12
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
12
|
-
import {
|
|
13
|
-
import { getRunScores, saveRunScore } from './kysely-
|
|
13
|
+
import { agentSchema } from './schema/agent.schema.js'
|
|
14
|
+
import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
|
|
14
15
|
|
|
15
|
-
export class
|
|
16
|
+
export class KyselyAgentRunStateService implements AgentRunStateService {
|
|
16
17
|
private initialized = false
|
|
17
18
|
|
|
18
19
|
constructor(private db: Kysely<KyselyPikkuDB>) {}
|
|
19
20
|
|
|
20
21
|
async init(): Promise<void> {
|
|
21
22
|
if (this.initialized) return
|
|
22
|
-
await ensurePikkuSchema(this.db,
|
|
23
|
+
await ensurePikkuSchema(this.db, agentSchema)
|
|
23
24
|
this.initialized = true
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
async createRun(run: CreateRunInput): Promise<string> {
|
|
27
28
|
const runId = `run-${crypto.randomUUID()}`
|
|
28
29
|
await this.db
|
|
29
|
-
.insertInto('
|
|
30
|
+
.insertInto('agentRun')
|
|
30
31
|
.values({
|
|
31
32
|
runId,
|
|
32
33
|
agentName: run.agentName,
|
|
@@ -67,7 +68,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
await this.db
|
|
70
|
-
.updateTable('
|
|
71
|
+
.updateTable('agentRun')
|
|
71
72
|
.set(values)
|
|
72
73
|
.where('runId', '=', runId)
|
|
73
74
|
.execute()
|
|
@@ -75,7 +76,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
|
|
|
75
76
|
|
|
76
77
|
async getRun(runId: string): Promise<AgentRunState | null> {
|
|
77
78
|
const row = await this.db
|
|
78
|
-
.selectFrom('
|
|
79
|
+
.selectFrom('agentRun')
|
|
79
80
|
.selectAll()
|
|
80
81
|
.where('runId', '=', runId)
|
|
81
82
|
.executeTakeFirst()
|
|
@@ -84,7 +85,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
|
|
|
84
85
|
|
|
85
86
|
async getRunsByThread(threadId: string): Promise<AgentRunState[]> {
|
|
86
87
|
const rows = await this.db
|
|
87
|
-
.selectFrom('
|
|
88
|
+
.selectFrom('agentRun')
|
|
88
89
|
.selectAll()
|
|
89
90
|
.where('threadId', '=', threadId)
|
|
90
91
|
.orderBy('createdAt', 'desc')
|
|
@@ -97,7 +98,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
|
|
|
97
98
|
status: 'approved' | 'denied'
|
|
98
99
|
): Promise<boolean> {
|
|
99
100
|
const rows = await this.db
|
|
100
|
-
.selectFrom('
|
|
101
|
+
.selectFrom('agentRun')
|
|
101
102
|
.select(['runId', 'pendingApprovals'])
|
|
102
103
|
.where('status', '=', 'suspended')
|
|
103
104
|
.execute()
|
|
@@ -126,7 +127,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
|
|
|
126
127
|
// Compare-and-swap on the list we read: a concurrent approver that got
|
|
127
128
|
// there first has already rewritten it, and this update matches no row.
|
|
128
129
|
const result = await this.db
|
|
129
|
-
.updateTable('
|
|
130
|
+
.updateTable('agentRun')
|
|
130
131
|
.set(updates as any)
|
|
131
132
|
.where('runId', '=', row.runId)
|
|
132
133
|
.where('status', '=', 'suspended')
|
|
@@ -142,7 +143,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
|
|
|
142
143
|
toolCallId: string
|
|
143
144
|
): Promise<{ run: AgentRunState; approval: PendingApproval } | null> {
|
|
144
145
|
const rows = await this.db
|
|
145
|
-
.selectFrom('
|
|
146
|
+
.selectFrom('agentRun')
|
|
146
147
|
.selectAll()
|
|
147
148
|
.where('status', '=', 'suspended')
|
|
148
149
|
.execute()
|
|
@@ -170,7 +171,7 @@ export class KyselyAIRunStateService implements AIRunStateService {
|
|
|
170
171
|
await saveRunScore(this.db, score)
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
async getScores(runId: string): Promise<
|
|
174
|
+
async getScores(runId: string): Promise<AgentRunScore[]> {
|
|
174
175
|
return getRunScores(this.db, runId)
|
|
175
176
|
}
|
|
176
177
|
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
3
|
-
|
|
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,
|
|
4
10
|
CreateRunInput,
|
|
5
11
|
SaveScoreInput,
|
|
6
12
|
} from '@pikku/core/services'
|
|
7
|
-
import type { AIThread, AIMessage, AgentRunState } from '@pikku/core/ai-agent'
|
|
8
|
-
import type { AIRunScore } from '@pikku/core/ai-scorer'
|
|
9
13
|
import type { Kysely } from 'kysely'
|
|
10
14
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
11
15
|
import { parseJson } from './kysely-json.js'
|
|
12
|
-
import { getRunScores, saveRunScore } from './kysely-
|
|
16
|
+
import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
|
|
13
17
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
14
|
-
import {
|
|
18
|
+
import { agentSchema } from './schema/agent.schema.js'
|
|
15
19
|
|
|
16
|
-
export class
|
|
17
|
-
implements
|
|
20
|
+
export class KyselyAgentStorageService
|
|
21
|
+
implements AgentStorageService, AgentRunStateService
|
|
18
22
|
{
|
|
19
23
|
private initialized = false
|
|
20
24
|
|
|
@@ -22,7 +26,7 @@ export class KyselyAIStorageService
|
|
|
22
26
|
|
|
23
27
|
public async init(): Promise<void> {
|
|
24
28
|
if (this.initialized) return
|
|
25
|
-
await ensurePikkuSchema(this.db,
|
|
29
|
+
await ensurePikkuSchema(this.db, agentSchema)
|
|
26
30
|
this.initialized = true
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -33,12 +37,12 @@ export class KyselyAIStorageService
|
|
|
33
37
|
title?: string
|
|
34
38
|
metadata?: Record<string, unknown>
|
|
35
39
|
}
|
|
36
|
-
): Promise<
|
|
40
|
+
): Promise<AgentThread> {
|
|
37
41
|
const id = options?.threadId ?? crypto.randomUUID()
|
|
38
42
|
const now = new Date()
|
|
39
43
|
|
|
40
44
|
await this.db
|
|
41
|
-
.insertInto('
|
|
45
|
+
.insertInto('agentThreads')
|
|
42
46
|
.values({
|
|
43
47
|
id,
|
|
44
48
|
resourceId: resourceId,
|
|
@@ -59,9 +63,9 @@ export class KyselyAIStorageService
|
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
|
|
62
|
-
async getThread(threadId: string): Promise<
|
|
66
|
+
async getThread(threadId: string): Promise<AgentThread> {
|
|
63
67
|
const row = await this.db
|
|
64
|
-
.selectFrom('
|
|
68
|
+
.selectFrom('agentThreads')
|
|
65
69
|
.select([
|
|
66
70
|
'id',
|
|
67
71
|
'resourceId',
|
|
@@ -87,9 +91,9 @@ export class KyselyAIStorageService
|
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
async getThreads(resourceId: string): Promise<
|
|
94
|
+
async getThreads(resourceId: string): Promise<AgentThread[]> {
|
|
91
95
|
const result = await this.db
|
|
92
|
-
.selectFrom('
|
|
96
|
+
.selectFrom('agentThreads')
|
|
93
97
|
.select([
|
|
94
98
|
'id',
|
|
95
99
|
'resourceId',
|
|
@@ -113,21 +117,24 @@ export class KyselyAIStorageService
|
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
async deleteThread(threadId: string): Promise<void> {
|
|
116
|
-
await this.db
|
|
120
|
+
await this.db
|
|
121
|
+
.deleteFrom('agentThreads')
|
|
122
|
+
.where('id', '=', threadId)
|
|
123
|
+
.execute()
|
|
117
124
|
}
|
|
118
125
|
|
|
119
126
|
async getMessages(
|
|
120
127
|
threadId: string,
|
|
121
128
|
options?: { lastN?: number; cursor?: string }
|
|
122
|
-
): Promise<
|
|
129
|
+
): Promise<AgentMessage[]> {
|
|
123
130
|
let msgQuery = this.db
|
|
124
|
-
.selectFrom('
|
|
131
|
+
.selectFrom('agentMessage')
|
|
125
132
|
.select(['id', 'role', 'content', 'createdAt'])
|
|
126
133
|
.where('threadId', '=', threadId)
|
|
127
134
|
|
|
128
135
|
if (options?.cursor) {
|
|
129
136
|
const cursorRow = await this.db
|
|
130
|
-
.selectFrom('
|
|
137
|
+
.selectFrom('agentMessage')
|
|
131
138
|
.select('createdAt')
|
|
132
139
|
.where('id', '=', options.cursor)
|
|
133
140
|
.executeTakeFirst()
|
|
@@ -150,7 +157,7 @@ export class KyselyAIStorageService
|
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
const tcResult = await this.db
|
|
153
|
-
.selectFrom('
|
|
160
|
+
.selectFrom('agentToolCall')
|
|
154
161
|
.select(['id', 'messageId', 'toolName', 'args', 'result'])
|
|
155
162
|
.where('threadId', '=', threadId)
|
|
156
163
|
.orderBy('createdAt', 'asc')
|
|
@@ -163,10 +170,10 @@ export class KyselyAIStorageService
|
|
|
163
170
|
tcByMessage.get(msgId)!.push(tc)
|
|
164
171
|
}
|
|
165
172
|
|
|
166
|
-
const messages:
|
|
173
|
+
const messages: AgentMessage[] = []
|
|
167
174
|
for (const row of msgResult) {
|
|
168
175
|
const rawContent = row.content as string | undefined
|
|
169
|
-
let parsedContent:
|
|
176
|
+
let parsedContent: AgentMessage['content'] = rawContent ?? undefined
|
|
170
177
|
if (rawContent) {
|
|
171
178
|
try {
|
|
172
179
|
const parsed = JSON.parse(rawContent)
|
|
@@ -179,9 +186,9 @@ export class KyselyAIStorageService
|
|
|
179
186
|
// Not JSON, use raw string
|
|
180
187
|
}
|
|
181
188
|
}
|
|
182
|
-
const msg:
|
|
189
|
+
const msg: AgentMessage = {
|
|
183
190
|
id: row.id,
|
|
184
|
-
role: row.role as
|
|
191
|
+
role: row.role as AgentMessage['role'],
|
|
185
192
|
content: parsedContent,
|
|
186
193
|
createdAt: new Date(row.createdAt),
|
|
187
194
|
}
|
|
@@ -217,7 +224,10 @@ export class KyselyAIStorageService
|
|
|
217
224
|
return messages
|
|
218
225
|
}
|
|
219
226
|
|
|
220
|
-
async saveMessages(
|
|
227
|
+
async saveMessages(
|
|
228
|
+
threadId: string,
|
|
229
|
+
messages: AgentMessage[]
|
|
230
|
+
): Promise<void> {
|
|
221
231
|
if (messages.length === 0) return
|
|
222
232
|
|
|
223
233
|
const toolMessages = messages.filter((m) => m.role === 'tool')
|
|
@@ -225,7 +235,7 @@ export class KyselyAIStorageService
|
|
|
225
235
|
|
|
226
236
|
if (nonToolMessages.length > 0) {
|
|
227
237
|
await this.db
|
|
228
|
-
.insertInto('
|
|
238
|
+
.insertInto('agentMessage')
|
|
229
239
|
.values(
|
|
230
240
|
nonToolMessages.map((msg) => ({
|
|
231
241
|
id: msg.id,
|
|
@@ -243,7 +253,7 @@ export class KyselyAIStorageService
|
|
|
243
253
|
)
|
|
244
254
|
if (toolCalls.length > 0) {
|
|
245
255
|
await this.db
|
|
246
|
-
.insertInto('
|
|
256
|
+
.insertInto('agentToolCall')
|
|
247
257
|
.values(
|
|
248
258
|
toolCalls.map((tc) => ({
|
|
249
259
|
id: tc.id,
|
|
@@ -260,7 +270,7 @@ export class KyselyAIStorageService
|
|
|
260
270
|
if (!toolMsg.toolResults) continue
|
|
261
271
|
for (const tr of toolMsg.toolResults) {
|
|
262
272
|
await this.db
|
|
263
|
-
.updateTable('
|
|
273
|
+
.updateTable('agentToolCall')
|
|
264
274
|
.set({ result: tr.result })
|
|
265
275
|
.where('id', '=', tr.id)
|
|
266
276
|
.execute()
|
|
@@ -268,7 +278,7 @@ export class KyselyAIStorageService
|
|
|
268
278
|
}
|
|
269
279
|
|
|
270
280
|
await this.db
|
|
271
|
-
.updateTable('
|
|
281
|
+
.updateTable('agentThreads')
|
|
272
282
|
.set({ updatedAt: new Date() })
|
|
273
283
|
.where('id', '=', threadId)
|
|
274
284
|
.execute()
|
|
@@ -279,7 +289,7 @@ export class KyselyAIStorageService
|
|
|
279
289
|
scope: 'resource' | 'thread'
|
|
280
290
|
): Promise<Record<string, unknown> | null> {
|
|
281
291
|
const row = await this.db
|
|
282
|
-
.selectFrom('
|
|
292
|
+
.selectFrom('agentWorkingMemory')
|
|
283
293
|
.select('data')
|
|
284
294
|
.where('id', '=', id)
|
|
285
295
|
.where('scope', '=', scope)
|
|
@@ -295,7 +305,7 @@ export class KyselyAIStorageService
|
|
|
295
305
|
data: Record<string, unknown>
|
|
296
306
|
): Promise<void> {
|
|
297
307
|
await this.db
|
|
298
|
-
.insertInto('
|
|
308
|
+
.insertInto('agentWorkingMemory')
|
|
299
309
|
.values({
|
|
300
310
|
id,
|
|
301
311
|
scope,
|
|
@@ -315,7 +325,7 @@ export class KyselyAIStorageService
|
|
|
315
325
|
const runId = crypto.randomUUID()
|
|
316
326
|
|
|
317
327
|
await this.db
|
|
318
|
-
.insertInto('
|
|
328
|
+
.insertInto('agentRun')
|
|
319
329
|
.values({
|
|
320
330
|
runId: runId,
|
|
321
331
|
agentName: run.agentName,
|
|
@@ -365,14 +375,14 @@ export class KyselyAIStorageService
|
|
|
365
375
|
}
|
|
366
376
|
|
|
367
377
|
await this.db
|
|
368
|
-
.updateTable('
|
|
378
|
+
.updateTable('agentRun')
|
|
369
379
|
.set(setValues)
|
|
370
380
|
.where('runId', '=', runId)
|
|
371
381
|
.execute()
|
|
372
382
|
|
|
373
383
|
if (updates.pendingApprovals !== undefined) {
|
|
374
384
|
await this.db
|
|
375
|
-
.updateTable('
|
|
385
|
+
.updateTable('agentToolCall')
|
|
376
386
|
.set({
|
|
377
387
|
approvalStatus: null,
|
|
378
388
|
runId: null,
|
|
@@ -393,7 +403,7 @@ export class KyselyAIStorageService
|
|
|
393
403
|
|
|
394
404
|
async getRun(runId: string): Promise<AgentRunState | null> {
|
|
395
405
|
const row = await this.db
|
|
396
|
-
.selectFrom('
|
|
406
|
+
.selectFrom('agentRun')
|
|
397
407
|
.select([
|
|
398
408
|
'runId',
|
|
399
409
|
'agentName',
|
|
@@ -415,7 +425,7 @@ export class KyselyAIStorageService
|
|
|
415
425
|
if (!row) return null
|
|
416
426
|
|
|
417
427
|
const approvals = await this.db
|
|
418
|
-
.selectFrom('
|
|
428
|
+
.selectFrom('agentToolCall')
|
|
419
429
|
.select([
|
|
420
430
|
'id',
|
|
421
431
|
'toolName',
|
|
@@ -434,7 +444,7 @@ export class KyselyAIStorageService
|
|
|
434
444
|
|
|
435
445
|
async getRunsByThread(threadId: string): Promise<AgentRunState[]> {
|
|
436
446
|
const result = await this.db
|
|
437
|
-
.selectFrom('
|
|
447
|
+
.selectFrom('agentRun')
|
|
438
448
|
.select([
|
|
439
449
|
'runId',
|
|
440
450
|
'agentName',
|
|
@@ -457,7 +467,7 @@ export class KyselyAIStorageService
|
|
|
457
467
|
const runs: AgentRunState[] = []
|
|
458
468
|
for (const row of result) {
|
|
459
469
|
const approvals = await this.db
|
|
460
|
-
.selectFrom('
|
|
470
|
+
.selectFrom('agentToolCall')
|
|
461
471
|
.select([
|
|
462
472
|
'id',
|
|
463
473
|
'toolName',
|
|
@@ -482,7 +492,7 @@ export class KyselyAIStorageService
|
|
|
482
492
|
for (const a of approvals) {
|
|
483
493
|
if (a.type === 'agent-call') {
|
|
484
494
|
await this.db
|
|
485
|
-
.updateTable('
|
|
495
|
+
.updateTable('agentToolCall')
|
|
486
496
|
.set({
|
|
487
497
|
approvalStatus: 'pending',
|
|
488
498
|
runId: runId,
|
|
@@ -495,7 +505,7 @@ export class KyselyAIStorageService
|
|
|
495
505
|
.execute()
|
|
496
506
|
} else {
|
|
497
507
|
await this.db
|
|
498
|
-
.updateTable('
|
|
508
|
+
.updateTable('agentToolCall')
|
|
499
509
|
.set({
|
|
500
510
|
approvalStatus: 'pending',
|
|
501
511
|
runId: runId,
|
|
@@ -554,7 +564,7 @@ export class KyselyAIStorageService
|
|
|
554
564
|
approval: NonNullable<AgentRunState['pendingApprovals']>[number]
|
|
555
565
|
} | null> {
|
|
556
566
|
const tc = await this.db
|
|
557
|
-
.selectFrom('
|
|
567
|
+
.selectFrom('agentToolCall')
|
|
558
568
|
.select([
|
|
559
569
|
'id',
|
|
560
570
|
'toolName',
|
|
@@ -602,7 +612,7 @@ export class KyselyAIStorageService
|
|
|
602
612
|
): Promise<boolean> {
|
|
603
613
|
// Only the caller that moves the tool call off 'pending' has claimed it.
|
|
604
614
|
const result = await this.db
|
|
605
|
-
.updateTable('
|
|
615
|
+
.updateTable('agentToolCall')
|
|
606
616
|
.set({ approvalStatus: status })
|
|
607
617
|
.where('id', '=', toolCallId)
|
|
608
618
|
.where('approvalStatus', '=', 'pending')
|
|
@@ -614,7 +624,7 @@ export class KyselyAIStorageService
|
|
|
614
624
|
await saveRunScore(this.db, score)
|
|
615
625
|
}
|
|
616
626
|
|
|
617
|
-
async getScores(runId: string): Promise<
|
|
627
|
+
async getScores(runId: string): Promise<AgentRunScore[]> {
|
|
618
628
|
return getRunScores(this.db, runId)
|
|
619
629
|
}
|
|
620
630
|
|
|
@@ -2,7 +2,7 @@ import { describe, test, beforeEach } from 'node:test'
|
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
3
|
import Database from 'better-sqlite3'
|
|
4
4
|
import { CamelCasePlugin, Kysely, SqliteDialect, sql } from 'kysely'
|
|
5
|
-
import type { AuditEvent } from '
|
|
5
|
+
import type { AuditEvent } from '@pikku/core/services'
|
|
6
6
|
|
|
7
7
|
import { KyselyAuditService } from './kysely-audit-service.js'
|
|
8
8
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
import type { AuditService } from '@pikku/core/services'
|
|
2
|
+
import type { AuditEvent, AuditEventBatch } from '@pikku/core/services'
|
|
1
3
|
import type {
|
|
2
|
-
AuditEvent,
|
|
3
|
-
AuditEventBatch,
|
|
4
4
|
AuditFacets,
|
|
5
5
|
AuditQuery,
|
|
6
6
|
AuditQueryResult,
|
|
7
|
-
|
|
8
|
-
} from '@pikku/core'
|
|
7
|
+
} from '@pikku/core/services'
|
|
9
8
|
import type { Kysely } from 'kysely'
|
|
10
9
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
11
10
|
import { auditSchema } from './schema/audit.schema.js'
|
|
@@ -116,8 +115,7 @@ export class KyselyAuditService implements AuditService {
|
|
|
116
115
|
if (!batch.length) return
|
|
117
116
|
const rows = batch.map((e) => {
|
|
118
117
|
const metadata = e.metadata as
|
|
119
|
-
|
|
120
|
-
| undefined
|
|
118
|
+
{ tables?: unknown; changedColumns?: unknown } | undefined
|
|
121
119
|
return {
|
|
122
120
|
audit_id: e.eventId ?? e.queryId ?? fallbackId(),
|
|
123
121
|
occurred_at: e.occurredAt ?? new Date().toISOString(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Channel } from '@pikku/core/channel'
|
|
2
1
|
import { ChannelStore } from '@pikku/core/channel'
|
|
2
|
+
import type { Channel } from '@pikku/core/channel'
|
|
3
3
|
import type { Kysely } from 'kysely'
|
|
4
4
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
5
5
|
import { parseJson } from './kysely-json.js'
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { CredentialService } from '@pikku/core/services'
|
|
2
|
-
import type { Kysely } from 'kysely'
|
|
3
|
-
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
4
1
|
import {
|
|
5
2
|
deriveKEK,
|
|
6
|
-
generateKEKSalt,
|
|
7
|
-
envelopeEncrypt,
|
|
8
3
|
envelopeDecrypt,
|
|
4
|
+
envelopeEncrypt,
|
|
9
5
|
envelopeRewrap,
|
|
6
|
+
generateKEKSalt,
|
|
10
7
|
} from '@pikku/core/crypto-utils'
|
|
8
|
+
import type { CredentialService } from '@pikku/core/services'
|
|
9
|
+
import type { Kysely } from 'kysely'
|
|
10
|
+
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
11
11
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
12
12
|
import { credentialSchema } from './schema/credential.schema.js'
|
|
13
13
|
|
|
@@ -4,7 +4,8 @@ import type {
|
|
|
4
4
|
DeploymentServiceConfig,
|
|
5
5
|
DeploymentConfig,
|
|
6
6
|
} from '@pikku/core/services'
|
|
7
|
-
import type { JWTService
|
|
7
|
+
import type { JWTService } from '@pikku/core/services'
|
|
8
|
+
import type { SecretService } from '@pikku/core/services'
|
|
8
9
|
import { getAllFunctionNames } from '@pikku/core/function'
|
|
9
10
|
import type { Kysely } from 'kysely'
|
|
10
11
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ScopeService } from '@pikku/core/services'
|
|
2
|
+
import type { Role } from '@pikku/core/services'
|
|
2
3
|
import type { FlatScope } from '@pikku/core/scope'
|
|
3
4
|
import type { SystemRole } from '@pikku/core/role'
|
|
4
5
|
import {
|
|
@@ -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')
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { createSecretValue, isSecretValue, type SecretValue } from '@pikku/core'
|
|
2
|
-
import type { SecretService, SecretValues } from '@pikku/core/services'
|
|
3
|
-
import type { Kysely } from 'kysely'
|
|
4
|
-
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
5
1
|
import {
|
|
6
2
|
deriveKEK,
|
|
7
|
-
generateKEKSalt,
|
|
8
|
-
envelopeEncrypt,
|
|
9
3
|
envelopeDecrypt,
|
|
4
|
+
envelopeEncrypt,
|
|
10
5
|
envelopeRewrap,
|
|
6
|
+
generateKEKSalt,
|
|
11
7
|
} from '@pikku/core/crypto-utils'
|
|
8
|
+
import { createSecretValue, isSecretValue } from '@pikku/core/classification'
|
|
9
|
+
import type { SecretService, SecretValues } from '@pikku/core/services'
|
|
10
|
+
import type { SecretValue } from '@pikku/core/classification'
|
|
11
|
+
import type { Kysely } from 'kysely'
|
|
12
|
+
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
12
13
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
13
14
|
import { secretSchema } from './schema/secret.schema.js'
|
|
14
15
|
|