@pikku/kysely 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -1
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +7 -0
- package/dist/src/kysely-agent-run-service.d.ts +19 -0
- package/dist/src/kysely-agent-run-service.js +171 -0
- package/dist/src/kysely-ai-storage-service.d.ts +37 -0
- package/dist/src/kysely-ai-storage-service.js +586 -0
- package/dist/src/kysely-channel-store.d.ts +17 -0
- package/dist/src/kysely-channel-store.js +80 -0
- package/dist/src/kysely-deployment-service.d.ts +17 -0
- package/dist/src/kysely-deployment-service.js +128 -0
- package/dist/src/kysely-eventhub-store.d.ts +13 -0
- package/dist/src/kysely-eventhub-store.js +45 -0
- package/dist/src/kysely-json.d.ts +1 -0
- package/dist/src/kysely-json.js +7 -0
- package/dist/src/kysely-tables.d.ts +136 -0
- package/dist/src/kysely-tables.js +1 -0
- package/dist/src/kysely-workflow-run-service.d.ts +29 -0
- package/dist/src/kysely-workflow-run-service.js +194 -0
- package/dist/src/kysely-workflow-service.d.ts +47 -0
- package/dist/src/kysely-workflow-service.js +485 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -6
- package/src/index.ts +12 -0
- package/src/kysely-agent-run-service.ts +205 -0
- package/src/kysely-ai-storage-service.ts +713 -0
- package/src/kysely-channel-store.ts +109 -0
- package/src/kysely-deployment-service.ts +171 -0
- package/src/kysely-eventhub-store.ts +53 -0
- package/src/kysely-json.ts +5 -0
- package/src/kysely-services.test.ts +800 -0
- package/src/kysely-tables.ts +150 -0
- package/src/kysely-workflow-run-service.ts +242 -0
- package/src/kysely-workflow-service.ts +642 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 0.12.0
|
|
2
|
+
|
|
3
|
+
- Updated dependencies
|
|
4
|
+
|
|
1
5
|
## 0.11.0
|
|
2
6
|
|
|
3
7
|
### Minor Changes
|
|
@@ -5,7 +9,6 @@
|
|
|
5
9
|
- Remove Kysely-based channel and eventhub stores (use @pikku/pg instead)
|
|
6
10
|
- Update to support shared connection instances
|
|
7
11
|
|
|
8
|
-
|
|
9
12
|
# @pikku/kysely
|
|
10
13
|
|
|
11
14
|
## 0.10.0
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
1
|
export { PikkuKysely } from './pikku-kysely.js';
|
|
2
|
+
export { KyselyChannelStore } from './kysely-channel-store.js';
|
|
3
|
+
export { KyselyEventHubStore } from './kysely-eventhub-store.js';
|
|
4
|
+
export { KyselyWorkflowService } from './kysely-workflow-service.js';
|
|
5
|
+
export { KyselyWorkflowRunService } from './kysely-workflow-run-service.js';
|
|
6
|
+
export { KyselyDeploymentService } from './kysely-deployment-service.js';
|
|
7
|
+
export { KyselyAIStorageService } from './kysely-ai-storage-service.js';
|
|
8
|
+
export { KyselyAgentRunService } from './kysely-agent-run-service.js';
|
|
9
|
+
export type { KyselyPikkuDB } from './kysely-tables.js';
|
|
10
|
+
export type { WorkflowRunService } from '@pikku/core/workflow';
|
|
11
|
+
export type { AgentRunService, AgentRunRow } from '@pikku/core/ai-agent';
|
package/dist/src/index.js
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
1
|
export { PikkuKysely } from './pikku-kysely.js';
|
|
2
|
+
export { KyselyChannelStore } from './kysely-channel-store.js';
|
|
3
|
+
export { KyselyEventHubStore } from './kysely-eventhub-store.js';
|
|
4
|
+
export { KyselyWorkflowService } from './kysely-workflow-service.js';
|
|
5
|
+
export { KyselyWorkflowRunService } from './kysely-workflow-run-service.js';
|
|
6
|
+
export { KyselyDeploymentService } from './kysely-deployment-service.js';
|
|
7
|
+
export { KyselyAIStorageService } from './kysely-ai-storage-service.js';
|
|
8
|
+
export { KyselyAgentRunService } from './kysely-agent-run-service.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AIThread, AIMessage, AgentRunRow, AgentRunService } from '@pikku/core/ai-agent';
|
|
2
|
+
import { Kysely } from 'kysely';
|
|
3
|
+
import type { KyselyPikkuDB } from './kysely-tables.js';
|
|
4
|
+
export declare class KyselyAgentRunService implements AgentRunService {
|
|
5
|
+
private db;
|
|
6
|
+
constructor(db: Kysely<KyselyPikkuDB>);
|
|
7
|
+
listThreads(options?: {
|
|
8
|
+
agentName?: string;
|
|
9
|
+
limit?: number;
|
|
10
|
+
offset?: number;
|
|
11
|
+
}): Promise<AIThread[]>;
|
|
12
|
+
getThread(threadId: string): Promise<AIThread | null>;
|
|
13
|
+
getThreadMessages(threadId: string): Promise<AIMessage[]>;
|
|
14
|
+
getThreadRuns(threadId: string): Promise<AgentRunRow[]>;
|
|
15
|
+
deleteThread(threadId: string): Promise<boolean>;
|
|
16
|
+
getDistinctAgentNames(): Promise<string[]>;
|
|
17
|
+
private mapThreadRow;
|
|
18
|
+
private mapRunRow;
|
|
19
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { parseJson } from './kysely-json.js';
|
|
2
|
+
export class KyselyAgentRunService {
|
|
3
|
+
db;
|
|
4
|
+
constructor(db) {
|
|
5
|
+
this.db = db;
|
|
6
|
+
}
|
|
7
|
+
async listThreads(options) {
|
|
8
|
+
const { agentName, limit = 50, offset = 0 } = options ?? {};
|
|
9
|
+
let query = this.db
|
|
10
|
+
.selectFrom('ai_threads as t')
|
|
11
|
+
.select([
|
|
12
|
+
't.id',
|
|
13
|
+
't.resource_id',
|
|
14
|
+
't.title',
|
|
15
|
+
't.metadata',
|
|
16
|
+
't.created_at',
|
|
17
|
+
't.updated_at',
|
|
18
|
+
]);
|
|
19
|
+
if (agentName) {
|
|
20
|
+
query = query.where('t.id', 'in', this.db
|
|
21
|
+
.selectFrom('ai_run')
|
|
22
|
+
.select('thread_id')
|
|
23
|
+
.where('agent_name', '=', agentName)
|
|
24
|
+
.distinct());
|
|
25
|
+
}
|
|
26
|
+
const result = await query
|
|
27
|
+
.orderBy('t.updated_at', 'desc')
|
|
28
|
+
.limit(limit)
|
|
29
|
+
.offset(offset)
|
|
30
|
+
.execute();
|
|
31
|
+
return result.map((row) => this.mapThreadRow(row));
|
|
32
|
+
}
|
|
33
|
+
async getThread(threadId) {
|
|
34
|
+
const row = await this.db
|
|
35
|
+
.selectFrom('ai_threads')
|
|
36
|
+
.select([
|
|
37
|
+
'id',
|
|
38
|
+
'resource_id',
|
|
39
|
+
'title',
|
|
40
|
+
'metadata',
|
|
41
|
+
'created_at',
|
|
42
|
+
'updated_at',
|
|
43
|
+
])
|
|
44
|
+
.where('id', '=', threadId)
|
|
45
|
+
.executeTakeFirst();
|
|
46
|
+
if (!row)
|
|
47
|
+
return null;
|
|
48
|
+
return this.mapThreadRow(row);
|
|
49
|
+
}
|
|
50
|
+
async getThreadMessages(threadId) {
|
|
51
|
+
const [msgResult, tcResult] = await Promise.all([
|
|
52
|
+
this.db
|
|
53
|
+
.selectFrom('ai_message')
|
|
54
|
+
.select(['id', 'role', 'content', 'created_at'])
|
|
55
|
+
.where('thread_id', '=', threadId)
|
|
56
|
+
.orderBy('created_at', 'asc')
|
|
57
|
+
.execute(),
|
|
58
|
+
this.db
|
|
59
|
+
.selectFrom('ai_tool_call')
|
|
60
|
+
.select(['id', 'message_id', 'tool_name', 'args', 'result'])
|
|
61
|
+
.where('thread_id', '=', threadId)
|
|
62
|
+
.orderBy('created_at', 'asc')
|
|
63
|
+
.execute(),
|
|
64
|
+
]);
|
|
65
|
+
const tcByMessage = new Map();
|
|
66
|
+
for (const tc of tcResult) {
|
|
67
|
+
const msgId = tc.message_id;
|
|
68
|
+
if (!tcByMessage.has(msgId))
|
|
69
|
+
tcByMessage.set(msgId, []);
|
|
70
|
+
tcByMessage.get(msgId).push(tc);
|
|
71
|
+
}
|
|
72
|
+
const messages = [];
|
|
73
|
+
for (const row of msgResult) {
|
|
74
|
+
const msg = {
|
|
75
|
+
id: row.id,
|
|
76
|
+
role: row.role,
|
|
77
|
+
content: row.content ?? undefined,
|
|
78
|
+
createdAt: new Date(row.created_at),
|
|
79
|
+
};
|
|
80
|
+
const tcs = tcByMessage.get(msg.id);
|
|
81
|
+
if (tcs?.length) {
|
|
82
|
+
msg.toolCalls = tcs.map((tc) => ({
|
|
83
|
+
id: tc.id,
|
|
84
|
+
name: tc.tool_name,
|
|
85
|
+
args: parseJson(tc.args),
|
|
86
|
+
}));
|
|
87
|
+
const completed = tcs.filter((tc) => tc.result != null);
|
|
88
|
+
if (completed.length) {
|
|
89
|
+
messages.push(msg);
|
|
90
|
+
messages.push({
|
|
91
|
+
id: `tool-results-${msg.id}`,
|
|
92
|
+
role: 'tool',
|
|
93
|
+
toolResults: completed.map((tc) => ({
|
|
94
|
+
id: tc.id,
|
|
95
|
+
name: tc.tool_name,
|
|
96
|
+
result: tc.result,
|
|
97
|
+
})),
|
|
98
|
+
createdAt: msg.createdAt,
|
|
99
|
+
});
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
messages.push(msg);
|
|
104
|
+
}
|
|
105
|
+
return messages;
|
|
106
|
+
}
|
|
107
|
+
async getThreadRuns(threadId) {
|
|
108
|
+
const result = await this.db
|
|
109
|
+
.selectFrom('ai_run')
|
|
110
|
+
.select([
|
|
111
|
+
'run_id',
|
|
112
|
+
'agent_name',
|
|
113
|
+
'thread_id',
|
|
114
|
+
'resource_id',
|
|
115
|
+
'status',
|
|
116
|
+
'suspend_reason',
|
|
117
|
+
'missing_rpcs',
|
|
118
|
+
'usage_input_tokens',
|
|
119
|
+
'usage_output_tokens',
|
|
120
|
+
'usage_model',
|
|
121
|
+
'created_at',
|
|
122
|
+
'updated_at',
|
|
123
|
+
])
|
|
124
|
+
.where('thread_id', '=', threadId)
|
|
125
|
+
.orderBy('created_at', 'desc')
|
|
126
|
+
.execute();
|
|
127
|
+
return result.map((row) => this.mapRunRow(row));
|
|
128
|
+
}
|
|
129
|
+
async deleteThread(threadId) {
|
|
130
|
+
const result = await this.db
|
|
131
|
+
.deleteFrom('ai_threads')
|
|
132
|
+
.where('id', '=', threadId)
|
|
133
|
+
.executeTakeFirst();
|
|
134
|
+
return BigInt(result.numDeletedRows) > 0n;
|
|
135
|
+
}
|
|
136
|
+
async getDistinctAgentNames() {
|
|
137
|
+
const result = await this.db
|
|
138
|
+
.selectFrom('ai_run')
|
|
139
|
+
.select('agent_name')
|
|
140
|
+
.distinct()
|
|
141
|
+
.orderBy('agent_name')
|
|
142
|
+
.execute();
|
|
143
|
+
return result.map((row) => row.agent_name);
|
|
144
|
+
}
|
|
145
|
+
mapThreadRow(row) {
|
|
146
|
+
return {
|
|
147
|
+
id: row.id,
|
|
148
|
+
resourceId: row.resource_id,
|
|
149
|
+
title: row.title ?? undefined,
|
|
150
|
+
metadata: parseJson(row.metadata),
|
|
151
|
+
createdAt: new Date(row.created_at),
|
|
152
|
+
updatedAt: new Date(row.updated_at),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
mapRunRow(row) {
|
|
156
|
+
return {
|
|
157
|
+
runId: row.run_id,
|
|
158
|
+
agentName: row.agent_name,
|
|
159
|
+
threadId: row.thread_id,
|
|
160
|
+
resourceId: row.resource_id,
|
|
161
|
+
status: row.status,
|
|
162
|
+
suspendReason: row.suspend_reason ?? undefined,
|
|
163
|
+
missingRpcs: parseJson(row.missing_rpcs),
|
|
164
|
+
usageInputTokens: Number(row.usage_input_tokens),
|
|
165
|
+
usageOutputTokens: Number(row.usage_output_tokens),
|
|
166
|
+
usageModel: row.usage_model,
|
|
167
|
+
createdAt: new Date(row.created_at),
|
|
168
|
+
updatedAt: new Date(row.updated_at),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AIStorageService, AIRunStateService, CreateRunInput } from '@pikku/core/services';
|
|
2
|
+
import type { AIThread, AIMessage, AgentRunState } from '@pikku/core/ai-agent';
|
|
3
|
+
import { Kysely } from 'kysely';
|
|
4
|
+
import type { KyselyPikkuDB } from './kysely-tables.js';
|
|
5
|
+
export declare class KyselyAIStorageService implements AIStorageService, AIRunStateService {
|
|
6
|
+
private db;
|
|
7
|
+
private initialized;
|
|
8
|
+
constructor(db: Kysely<KyselyPikkuDB>);
|
|
9
|
+
init(): Promise<void>;
|
|
10
|
+
createThread(resourceId: string, options?: {
|
|
11
|
+
threadId?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
metadata?: Record<string, unknown>;
|
|
14
|
+
}): Promise<AIThread>;
|
|
15
|
+
getThread(threadId: string): Promise<AIThread>;
|
|
16
|
+
getThreads(resourceId: string): Promise<AIThread[]>;
|
|
17
|
+
deleteThread(threadId: string): Promise<void>;
|
|
18
|
+
getMessages(threadId: string, options?: {
|
|
19
|
+
lastN?: number;
|
|
20
|
+
cursor?: string;
|
|
21
|
+
}): Promise<AIMessage[]>;
|
|
22
|
+
saveMessages(threadId: string, messages: AIMessage[]): Promise<void>;
|
|
23
|
+
getWorkingMemory(id: string, scope: 'resource' | 'thread'): Promise<Record<string, unknown> | null>;
|
|
24
|
+
saveWorkingMemory(id: string, scope: 'resource' | 'thread', data: Record<string, unknown>): Promise<void>;
|
|
25
|
+
createRun(run: CreateRunInput): Promise<string>;
|
|
26
|
+
updateRun(runId: string, updates: Partial<AgentRunState>): Promise<void>;
|
|
27
|
+
getRun(runId: string): Promise<AgentRunState | null>;
|
|
28
|
+
getRunsByThread(threadId: string): Promise<AgentRunState[]>;
|
|
29
|
+
private setApprovals;
|
|
30
|
+
private mapRunRow;
|
|
31
|
+
findRunByToolCallId(toolCallId: string): Promise<{
|
|
32
|
+
run: AgentRunState;
|
|
33
|
+
approval: NonNullable<AgentRunState['pendingApprovals']>[number];
|
|
34
|
+
} | null>;
|
|
35
|
+
resolveApproval(toolCallId: string, status: 'approved' | 'denied'): Promise<void>;
|
|
36
|
+
close(): Promise<void>;
|
|
37
|
+
}
|