@pikku/kysely 0.11.0 → 0.12.1

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 (34) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/dist/src/index.d.ts +10 -0
  3. package/dist/src/index.js +7 -0
  4. package/dist/src/kysely-agent-run-service.d.ts +19 -0
  5. package/dist/src/kysely-agent-run-service.js +171 -0
  6. package/dist/src/kysely-ai-storage-service.d.ts +37 -0
  7. package/dist/src/kysely-ai-storage-service.js +587 -0
  8. package/dist/src/kysely-channel-store.d.ts +18 -0
  9. package/dist/src/kysely-channel-store.js +80 -0
  10. package/dist/src/kysely-deployment-service.d.ts +17 -0
  11. package/dist/src/kysely-deployment-service.js +128 -0
  12. package/dist/src/kysely-eventhub-store.d.ts +13 -0
  13. package/dist/src/kysely-eventhub-store.js +45 -0
  14. package/dist/src/kysely-json.d.ts +1 -0
  15. package/dist/src/kysely-json.js +7 -0
  16. package/dist/src/kysely-tables.d.ts +136 -0
  17. package/dist/src/kysely-tables.js +1 -0
  18. package/dist/src/kysely-workflow-run-service.d.ts +29 -0
  19. package/dist/src/kysely-workflow-run-service.js +194 -0
  20. package/dist/src/kysely-workflow-service.d.ts +47 -0
  21. package/dist/src/kysely-workflow-service.js +485 -0
  22. package/dist/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +12 -6
  24. package/src/index.ts +12 -0
  25. package/src/kysely-agent-run-service.ts +205 -0
  26. package/src/kysely-ai-storage-service.ts +715 -0
  27. package/src/kysely-channel-store.ts +111 -0
  28. package/src/kysely-deployment-service.ts +172 -0
  29. package/src/kysely-eventhub-store.ts +53 -0
  30. package/src/kysely-json.ts +5 -0
  31. package/src/kysely-services.test.ts +800 -0
  32. package/src/kysely-tables.ts +150 -0
  33. package/src/kysely-workflow-run-service.ts +242 -0
  34. package/src/kysely-workflow-service.ts +643 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 0.12.0
2
+
3
+ ## 0.12.1
4
+
5
+ ### Patch Changes
6
+
7
+ - e04531f: Code quality improvements: resolve oxlint warnings and apply autofixes across the codebase (unused bindings, unnecessary constructors, prefer `const` over `let`, etc.). No behaviour changes.
8
+ - Updated dependencies [62a8725]
9
+ - Updated dependencies [a3bdb0d]
10
+ - Updated dependencies [e0349ff]
11
+ - Updated dependencies [62a8725]
12
+ - Updated dependencies [e04531f]
13
+ - Updated dependencies [62a8725]
14
+ - Updated dependencies [a83efb8]
15
+ - Updated dependencies [8eed717]
16
+ - Updated dependencies [62a8725]
17
+ - Updated dependencies [62a8725]
18
+ - Updated dependencies [62a8725]
19
+
20
+ - @pikku/core@0.12.1
21
+
22
+ - Updated dependencies
23
+
1
24
  ## 0.11.0
2
25
 
3
26
  ### Minor Changes
@@ -5,7 +28,6 @@
5
28
  - Remove Kysely-based channel and eventhub stores (use @pikku/pg instead)
6
29
  - Update to support shared connection instances
7
30
 
8
-
9
31
  # @pikku/kysely
10
32
 
11
33
  ## 0.10.0
@@ -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 type { 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 type { 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
+ }