@pikku/kysely 0.13.16 → 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.
Files changed (68) hide show
  1. package/CHANGELOG.md +135 -0
  2. package/bin/pikku-kysely-pure.ts +0 -0
  3. package/dist/src/coercion-plugin.d.ts +41 -0
  4. package/dist/src/coercion-plugin.js +150 -0
  5. package/dist/src/create-audited-kysely.d.ts +1 -1
  6. package/dist/src/index.d.ts +4 -3
  7. package/dist/src/index.js +1 -0
  8. package/dist/src/kysely-agent-run-scores.d.ts +1 -1
  9. package/dist/src/kysely-agent-run-service.d.ts +1 -2
  10. package/dist/src/kysely-agent-run-state-service.d.ts +2 -2
  11. package/dist/src/kysely-agent-storage-service.d.ts +2 -2
  12. package/dist/src/kysely-audit-service.d.ts +3 -3
  13. package/dist/src/kysely-channel-store.d.ts +1 -1
  14. package/dist/src/kysely-credential-service.js +1 -1
  15. package/dist/src/kysely-deployment-service.d.ts +3 -2
  16. package/dist/src/kysely-deployment-service.js +2 -2
  17. package/dist/src/kysely-eventhub-store.d.ts +1 -1
  18. package/dist/src/kysely-eventhub-store.js +1 -1
  19. package/dist/src/kysely-scope-service.d.ts +3 -3
  20. package/dist/src/kysely-secret-service.d.ts +1 -1
  21. package/dist/src/kysely-secret-service.js +2 -2
  22. package/dist/src/kysely-session-store.d.ts +1 -1
  23. package/dist/src/kysely-tables.d.ts +1 -1
  24. package/dist/src/kysely-virtual-user-run-store.d.ts +1 -1
  25. package/dist/src/kysely-webhook-service.d.ts +1 -1
  26. package/dist/src/kysely-webhook-service.js +1 -1
  27. package/dist/src/kysely-workflow-mirror.d.ts +2 -2
  28. package/dist/src/kysely-workflow-run-service.d.ts +1 -1
  29. package/dist/src/kysely-workflow-service.d.ts +2 -2
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +7 -7
  32. package/src/coercion-plugin.test.ts +160 -0
  33. package/src/coercion-plugin.ts +187 -0
  34. package/src/create-audited-kysely.test.ts +1 -1
  35. package/src/create-audited-kysely.ts +1 -1
  36. package/src/index.ts +9 -6
  37. package/src/kysely-agent-run-scores.ts +1 -1
  38. package/src/kysely-agent-run-service.ts +3 -2
  39. package/src/kysely-agent-run-state-service.ts +3 -3
  40. package/src/kysely-agent-storage-service.ts +7 -7
  41. package/src/kysely-audit-service.test.ts +1 -1
  42. package/src/kysely-audit-service.ts +4 -8
  43. package/src/kysely-channel-store.ts +1 -1
  44. package/src/kysely-credential-service.ts +5 -5
  45. package/src/kysely-deployment-service.ts +5 -4
  46. package/src/kysely-eventhub-store.ts +1 -1
  47. package/src/kysely-scope-service.ts +3 -3
  48. package/src/kysely-secret-service.ts +7 -6
  49. package/src/kysely-services.test.ts +1 -1
  50. package/src/kysely-session-store.ts +1 -1
  51. package/src/kysely-tables.ts +1 -1
  52. package/src/kysely-virtual-user-run-store.ts +1 -1
  53. package/src/kysely-webhook-service.test.ts +1 -1
  54. package/src/kysely-webhook-service.ts +2 -2
  55. package/src/kysely-workflow-mirror.ts +2 -2
  56. package/src/kysely-workflow-run-service.ts +1 -1
  57. package/src/kysely-workflow-service.test.ts +0 -1
  58. package/src/kysely-workflow-service.ts +11 -2
  59. package/dist/src/kysely-ai-agent-run-service.d.ts +0 -22
  60. package/dist/src/kysely-ai-agent-run-service.js +0 -190
  61. package/dist/src/kysely-ai-run-scores.d.ts +0 -10
  62. package/dist/src/kysely-ai-run-scores.js +0 -34
  63. package/dist/src/kysely-ai-run-state-service.d.ts +0 -24
  64. package/dist/src/kysely-ai-run-state-service.js +0 -169
  65. package/dist/src/kysely-ai-storage-service.d.ts +0 -40
  66. package/dist/src/kysely-ai-storage-service.js +0 -530
  67. package/dist/src/schema/ai.schema.d.ts +0 -12
  68. package/dist/src/schema/ai.schema.js +0 -102
@@ -3,7 +3,7 @@ import type {
3
3
  StepState,
4
4
  WorkflowStatus,
5
5
  WorkflowRunService,
6
- } from '@pikku/core/ecosystem/workflow'
6
+ } from '@pikku/core/workflow'
7
7
  import type { Kysely } from 'kysely'
8
8
  import type { KyselyPikkuDB } from './kysely-tables.js'
9
9
  import { parseJson } from './kysely-json.js'
@@ -428,4 +428,3 @@ describe('KyselyWorkflowService — a transition that addresses no history row',
428
428
  assert.equal(history[0]!.status, 'succeeded')
429
429
  })
430
430
  })
431
-
@@ -1,6 +1,15 @@
1
- import type { SerializedError } from '@pikku/core/ecosystem/types'
1
+ import type { SerializedError } from '@pikku/core/errors'
2
2
  import { PikkuWorkflowService } from '@pikku/core/workflow'
3
- import type { WorkflowPlannedStep, WorkflowQueueOptions, WorkflowRun, WorkflowRunWire, StepState, StepStatus, WorkflowStatus, WorkflowVersionStatus } from '@pikku/core/ecosystem/workflow'
3
+ import type {
4
+ WorkflowPlannedStep,
5
+ WorkflowQueueOptions,
6
+ WorkflowRun,
7
+ WorkflowRunWire,
8
+ StepState,
9
+ StepStatus,
10
+ WorkflowStatus,
11
+ WorkflowVersionStatus,
12
+ } from '@pikku/core/workflow'
4
13
  import { sql, type Kysely } from 'kysely'
5
14
  import type { KyselyPikkuDB } from './kysely-tables.js'
6
15
  import { KyselyWorkflowRunService } from './kysely-workflow-run-service.js'
@@ -1,22 +0,0 @@
1
- import type { AIThread, AIMessage } from '@pikku/core/ai-agent';
2
- import type { AgentRunRow, AgentRunService } from '@pikku/core/ecosystem/ai-agent';
3
- import type { Kysely } from 'kysely';
4
- import type { KyselyPikkuDB } from './kysely-tables.js';
5
- export declare class KyselyAgentRunService implements AgentRunService {
6
- private db;
7
- constructor(db: Kysely<KyselyPikkuDB>);
8
- listThreads(options?: {
9
- agentName?: string;
10
- resourceId?: string;
11
- owners?: string[];
12
- limit?: number;
13
- offset?: number;
14
- }): Promise<AIThread[]>;
15
- getThread(threadId: string): Promise<AIThread | null>;
16
- getThreadMessages(threadId: string): Promise<AIMessage[]>;
17
- getThreadRuns(threadId: string): Promise<AgentRunRow[]>;
18
- deleteThread(threadId: string): Promise<boolean>;
19
- getDistinctAgentNames(): Promise<string[]>;
20
- private mapThreadRow;
21
- private mapRunRow;
22
- }
@@ -1,190 +0,0 @@
1
- import { sql } from 'kysely';
2
- import { parseJson } from './kysely-json.js';
3
- // Owner ids routinely contain `_` (e.g. `user_123`), which LIKE treats as a
4
- // single-character wildcard — so a raw prefix would match a foreign owner.
5
- const escapeLikePattern = (value) => value.replace(/[\\%_]/g, (char) => `\\${char}`);
6
- export class KyselyAgentRunService {
7
- db;
8
- constructor(db) {
9
- this.db = db;
10
- }
11
- async listThreads(options) {
12
- const { agentName, resourceId, owners, limit = 50, offset = 0, } = options ?? {};
13
- // An owners constraint is an authorization boundary, so an empty list must
14
- // match nothing rather than degrade to "no filter".
15
- if (owners && owners.length === 0)
16
- return [];
17
- let query = this.db
18
- .selectFrom('aiThreads as t')
19
- .select([
20
- 't.id',
21
- 't.resourceId',
22
- 't.title',
23
- 't.metadata',
24
- 't.createdAt',
25
- 't.updatedAt',
26
- ]);
27
- if (agentName) {
28
- query = query.where('t.id', 'in', this.db
29
- .selectFrom('aiRun')
30
- .select('threadId')
31
- .where('agentName', '=', agentName)
32
- .distinct());
33
- }
34
- if (resourceId) {
35
- query = query.where('t.resourceId', '=', resourceId);
36
- }
37
- if (owners) {
38
- query = query.where((eb) => eb.or(owners.flatMap((owner) => [
39
- eb('t.resourceId', '=', owner),
40
- eb('t.resourceId', 'like', sql `${`${escapeLikePattern(owner)}:%`} escape '\\'`),
41
- ])));
42
- }
43
- const result = await query
44
- .orderBy('t.updatedAt', 'desc')
45
- .limit(limit)
46
- .offset(offset)
47
- .execute();
48
- return result.map((row) => this.mapThreadRow(row));
49
- }
50
- async getThread(threadId) {
51
- const row = await this.db
52
- .selectFrom('aiThreads')
53
- .select([
54
- 'id',
55
- 'resourceId',
56
- 'title',
57
- 'metadata',
58
- 'createdAt',
59
- 'updatedAt',
60
- ])
61
- .where('id', '=', threadId)
62
- .executeTakeFirst();
63
- if (!row)
64
- return null;
65
- return this.mapThreadRow(row);
66
- }
67
- async getThreadMessages(threadId) {
68
- const [msgResult, tcResult] = await Promise.all([
69
- this.db
70
- .selectFrom('aiMessage')
71
- .select(['id', 'role', 'content', 'createdAt'])
72
- .where('threadId', '=', threadId)
73
- .orderBy('createdAt', 'asc')
74
- .execute(),
75
- this.db
76
- .selectFrom('aiToolCall')
77
- .select(['id', 'messageId', 'toolName', 'args', 'result'])
78
- .where('threadId', '=', threadId)
79
- .orderBy('createdAt', 'asc')
80
- .execute(),
81
- ]);
82
- const tcByMessage = new Map();
83
- for (const tc of tcResult) {
84
- const msgId = tc.messageId;
85
- if (!tcByMessage.has(msgId))
86
- tcByMessage.set(msgId, []);
87
- tcByMessage.get(msgId).push(tc);
88
- }
89
- const messages = [];
90
- for (const row of msgResult) {
91
- const msg = {
92
- id: row.id,
93
- role: row.role,
94
- content: row.content ?? undefined,
95
- createdAt: new Date(row.createdAt),
96
- };
97
- const tcs = tcByMessage.get(msg.id);
98
- if (tcs?.length) {
99
- msg.toolCalls = tcs.map((tc) => ({
100
- id: tc.id,
101
- name: tc.toolName,
102
- args: parseJson(tc.args),
103
- }));
104
- const completed = tcs.filter((tc) => tc.result != null);
105
- if (completed.length) {
106
- messages.push(msg);
107
- messages.push({
108
- id: `tool-results-${msg.id}`,
109
- role: 'tool',
110
- toolResults: completed.map((tc) => ({
111
- id: tc.id,
112
- name: tc.toolName,
113
- result: tc.result,
114
- })),
115
- createdAt: msg.createdAt,
116
- });
117
- continue;
118
- }
119
- }
120
- messages.push(msg);
121
- }
122
- return messages;
123
- }
124
- async getThreadRuns(threadId) {
125
- const result = await this.db
126
- .selectFrom('aiRun')
127
- .select([
128
- 'runId',
129
- 'agentName',
130
- 'threadId',
131
- 'resourceId',
132
- 'status',
133
- 'errorMessage',
134
- 'suspendReason',
135
- 'missingRpcs',
136
- 'usageInputTokens',
137
- 'usageOutputTokens',
138
- 'usageModel',
139
- 'createdAt',
140
- 'updatedAt',
141
- ])
142
- .where('threadId', '=', threadId)
143
- .orderBy('createdAt', 'desc')
144
- .execute();
145
- return result.map((row) => this.mapRunRow(row));
146
- }
147
- async deleteThread(threadId) {
148
- const result = await this.db
149
- .deleteFrom('aiThreads')
150
- .where('id', '=', threadId)
151
- .executeTakeFirst();
152
- return BigInt(result.numDeletedRows) > 0n;
153
- }
154
- async getDistinctAgentNames() {
155
- const result = await this.db
156
- .selectFrom('aiRun')
157
- .select('agentName')
158
- .distinct()
159
- .orderBy('agentName')
160
- .execute();
161
- return result.map((row) => row.agentName);
162
- }
163
- mapThreadRow(row) {
164
- return {
165
- id: row.id,
166
- resourceId: row.resourceId,
167
- title: row.title ?? undefined,
168
- metadata: parseJson(row.metadata),
169
- createdAt: new Date(row.createdAt),
170
- updatedAt: new Date(row.updatedAt),
171
- };
172
- }
173
- mapRunRow(row) {
174
- return {
175
- runId: row.runId,
176
- agentName: row.agentName,
177
- threadId: row.threadId,
178
- resourceId: row.resourceId,
179
- status: row.status,
180
- errorMessage: row.errorMessage ?? undefined,
181
- suspendReason: row.suspendReason ?? undefined,
182
- missingRpcs: parseJson(row.missingRpcs),
183
- usageInputTokens: Number(row.usageInputTokens),
184
- usageOutputTokens: Number(row.usageOutputTokens),
185
- usageModel: row.usageModel,
186
- createdAt: new Date(row.createdAt),
187
- updatedAt: new Date(row.updatedAt),
188
- };
189
- }
190
- }
@@ -1,10 +0,0 @@
1
- import type { Kysely } from 'kysely';
2
- import type { KyselyPikkuDB } from './kysely-tables.js';
3
- import type { SaveScoreInput } from '@pikku/core/services';
4
- import type { AIRunScore } from '@pikku/core/ai-scorer';
5
- /**
6
- * Shared by the two Kysely services that implement `AIRunStateService` — they
7
- * differ in how they store approvals, not in how they store grades.
8
- */
9
- export declare const saveRunScore: (db: Kysely<KyselyPikkuDB>, score: SaveScoreInput) => Promise<void>;
10
- export declare const getRunScores: (db: Kysely<KyselyPikkuDB>, runId: string) => Promise<AIRunScore[]>;
@@ -1,34 +0,0 @@
1
- import { parseJson } from './kysely-json.js';
2
- /**
3
- * Shared by the two Kysely services that implement `AIRunStateService` — they
4
- * differ in how they store approvals, not in how they store grades.
5
- */
6
- export const saveRunScore = async (db, score) => {
7
- await db
8
- .insertInto('aiRunScore')
9
- .values({
10
- id: crypto.randomUUID(),
11
- runId: score.runId,
12
- scorerName: score.scorerName,
13
- score: score.score,
14
- reason: score.reason ?? null,
15
- metadata: score.metadata ? JSON.stringify(score.metadata) : null,
16
- })
17
- .execute();
18
- };
19
- export const getRunScores = async (db, runId) => {
20
- const rows = await db
21
- .selectFrom('aiRunScore')
22
- .selectAll()
23
- .where('runId', '=', runId)
24
- .orderBy('createdAt', 'asc')
25
- .execute();
26
- return rows.map((row) => ({
27
- runId: row.runId,
28
- scorerName: row.scorerName,
29
- score: Number(row.score),
30
- reason: row.reason ?? undefined,
31
- metadata: parseJson(row.metadata),
32
- createdAt: new Date(row.createdAt),
33
- }));
34
- };
@@ -1,24 +0,0 @@
1
- import type { Kysely } from 'kysely';
2
- import type { KyselyPikkuDB } from './kysely-tables.js';
3
- import type { AIRunStateService, CreateRunInput, SaveScoreInput } from '@pikku/core/services';
4
- import type { AgentRunState } from '@pikku/core/ai-agent';
5
- import type { PendingApproval } from '@pikku/core/ecosystem/ai-agent';
6
- import type { AIRunScore } from '@pikku/core/ai-scorer';
7
- export declare class KyselyAIRunStateService implements AIRunStateService {
8
- private db;
9
- private initialized;
10
- constructor(db: Kysely<KyselyPikkuDB>);
11
- init(): Promise<void>;
12
- createRun(run: CreateRunInput): Promise<string>;
13
- updateRun(runId: string, updates: Partial<AgentRunState>): Promise<void>;
14
- getRun(runId: string): Promise<AgentRunState | null>;
15
- getRunsByThread(threadId: string): Promise<AgentRunState[]>;
16
- resolveApproval(toolCallId: string, status: 'approved' | 'denied'): Promise<boolean>;
17
- findRunByToolCallId(toolCallId: string): Promise<{
18
- run: AgentRunState;
19
- approval: PendingApproval;
20
- } | null>;
21
- saveScore(score: SaveScoreInput): Promise<void>;
22
- getScores(runId: string): Promise<AIRunScore[]>;
23
- private toRunState;
24
- }
@@ -1,169 +0,0 @@
1
- import { sql } from 'kysely';
2
- import { ensurePikkuSchema } from './schema/index.js';
3
- import { aiSchema } from './schema/ai.schema.js';
4
- import { getRunScores, saveRunScore } from './kysely-ai-run-scores.js';
5
- export class KyselyAIRunStateService {
6
- db;
7
- initialized = false;
8
- constructor(db) {
9
- this.db = db;
10
- }
11
- async init() {
12
- if (this.initialized)
13
- return;
14
- await ensurePikkuSchema(this.db, aiSchema);
15
- this.initialized = true;
16
- }
17
- async createRun(run) {
18
- const runId = `run-${crypto.randomUUID()}`;
19
- await this.db
20
- .insertInto('aiRun')
21
- .values({
22
- runId,
23
- agentName: run.agentName,
24
- threadId: run.threadId,
25
- resourceId: run.resourceId,
26
- status: run.status ?? 'running',
27
- errorMessage: run.errorMessage ?? null,
28
- suspendReason: run.suspendReason ?? null,
29
- missingRpcs: run.missingRpcs ? JSON.stringify(run.missingRpcs) : null,
30
- usageInputTokens: run.usage?.inputTokens ?? 0,
31
- usageOutputTokens: run.usage?.outputTokens ?? 0,
32
- usageModel: run.usage?.model ?? '',
33
- })
34
- .execute();
35
- return runId;
36
- }
37
- async updateRun(runId, updates) {
38
- const values = {
39
- updatedAt: sql `CURRENT_TIMESTAMP`,
40
- };
41
- if (updates.status !== undefined)
42
- values.status = updates.status;
43
- if (updates.errorMessage !== undefined)
44
- values.errorMessage = updates.errorMessage;
45
- if (updates.suspendReason !== undefined)
46
- values.suspendReason = updates.suspendReason;
47
- if (updates.missingRpcs !== undefined)
48
- values.missingRpcs = JSON.stringify(updates.missingRpcs);
49
- if (updates.pendingApprovals !== undefined)
50
- values.pendingApprovals = JSON.stringify(updates.pendingApprovals);
51
- if (updates.usage) {
52
- values.usageInputTokens = updates.usage.inputTokens;
53
- values.usageOutputTokens = updates.usage.outputTokens;
54
- values.usageModel = updates.usage.model;
55
- }
56
- await this.db
57
- .updateTable('aiRun')
58
- .set(values)
59
- .where('runId', '=', runId)
60
- .execute();
61
- }
62
- async getRun(runId) {
63
- const row = await this.db
64
- .selectFrom('aiRun')
65
- .selectAll()
66
- .where('runId', '=', runId)
67
- .executeTakeFirst();
68
- return row ? this.toRunState(row) : null;
69
- }
70
- async getRunsByThread(threadId) {
71
- const rows = await this.db
72
- .selectFrom('aiRun')
73
- .selectAll()
74
- .where('threadId', '=', threadId)
75
- .orderBy('createdAt', 'desc')
76
- .execute();
77
- return rows.map((r) => this.toRunState(r));
78
- }
79
- async resolveApproval(toolCallId, status) {
80
- const rows = await this.db
81
- .selectFrom('aiRun')
82
- .select(['runId', 'pendingApprovals'])
83
- .where('status', '=', 'suspended')
84
- .execute();
85
- for (const row of rows) {
86
- let approvals = [];
87
- if (row.pendingApprovals) {
88
- try {
89
- approvals = JSON.parse(row.pendingApprovals);
90
- }
91
- catch {
92
- console.warn(`Failed to parse pendingApprovals for run ${row.runId}, treating as empty`);
93
- }
94
- }
95
- const filtered = approvals.filter((a) => a.toolCallId !== toolCallId);
96
- if (filtered.length !== approvals.length) {
97
- const updates = {
98
- pendingApprovals: filtered.length > 0 ? JSON.stringify(filtered) : null,
99
- updatedAt: sql `CURRENT_TIMESTAMP`,
100
- };
101
- if (filtered.length === 0) {
102
- updates.status = status;
103
- }
104
- // Compare-and-swap on the list we read: a concurrent approver that got
105
- // there first has already rewritten it, and this update matches no row.
106
- const result = await this.db
107
- .updateTable('aiRun')
108
- .set(updates)
109
- .where('runId', '=', row.runId)
110
- .where('status', '=', 'suspended')
111
- .where('pendingApprovals', '=', row.pendingApprovals)
112
- .executeTakeFirst();
113
- return Number(result?.numUpdatedRows ?? 0) > 0;
114
- }
115
- }
116
- return false;
117
- }
118
- async findRunByToolCallId(toolCallId) {
119
- const rows = await this.db
120
- .selectFrom('aiRun')
121
- .selectAll()
122
- .where('status', '=', 'suspended')
123
- .execute();
124
- for (const row of rows) {
125
- let approvals = [];
126
- if (row.pendingApprovals) {
127
- try {
128
- approvals = JSON.parse(row.pendingApprovals);
129
- }
130
- catch {
131
- console.warn(`Failed to parse pendingApprovals for run ${row.runId}, treating as empty`);
132
- }
133
- }
134
- const approval = approvals.find((a) => a.toolCallId === toolCallId);
135
- if (approval) {
136
- return { run: this.toRunState(row), approval };
137
- }
138
- }
139
- return null;
140
- }
141
- async saveScore(score) {
142
- await saveRunScore(this.db, score);
143
- }
144
- async getScores(runId) {
145
- return getRunScores(this.db, runId);
146
- }
147
- toRunState(row) {
148
- return {
149
- runId: row.runId,
150
- agentName: row.agentName,
151
- threadId: row.threadId,
152
- resourceId: row.resourceId,
153
- status: row.status,
154
- errorMessage: row.errorMessage ?? undefined,
155
- suspendReason: row.suspendReason ?? undefined,
156
- missingRpcs: row.missingRpcs ? JSON.parse(row.missingRpcs) : undefined,
157
- pendingApprovals: row.pendingApprovals
158
- ? JSON.parse(row.pendingApprovals)
159
- : undefined,
160
- usage: {
161
- inputTokens: row.usageInputTokens ?? 0,
162
- outputTokens: row.usageOutputTokens ?? 0,
163
- model: row.usageModel ?? '',
164
- },
165
- createdAt: new Date(row.createdAt),
166
- updatedAt: new Date(row.updatedAt),
167
- };
168
- }
169
- }
@@ -1,40 +0,0 @@
1
- import type { AIStorageService, AIRunStateService, CreateRunInput, SaveScoreInput } from '@pikku/core/services';
2
- import type { AIThread, AIMessage, AgentRunState } from '@pikku/core/ai-agent';
3
- import type { AIRunScore } from '@pikku/core/ai-scorer';
4
- import type { Kysely } from 'kysely';
5
- import type { KyselyPikkuDB } from './kysely-tables.js';
6
- export declare class KyselyAIStorageService implements AIStorageService, AIRunStateService {
7
- private db;
8
- private initialized;
9
- constructor(db: Kysely<KyselyPikkuDB>);
10
- init(): Promise<void>;
11
- createThread(resourceId: string, options?: {
12
- threadId?: string;
13
- title?: string;
14
- metadata?: Record<string, unknown>;
15
- }): Promise<AIThread>;
16
- getThread(threadId: string): Promise<AIThread>;
17
- getThreads(resourceId: string): Promise<AIThread[]>;
18
- deleteThread(threadId: string): Promise<void>;
19
- getMessages(threadId: string, options?: {
20
- lastN?: number;
21
- cursor?: string;
22
- }): Promise<AIMessage[]>;
23
- saveMessages(threadId: string, messages: AIMessage[]): Promise<void>;
24
- getWorkingMemory(id: string, scope: 'resource' | 'thread'): Promise<Record<string, unknown> | null>;
25
- saveWorkingMemory(id: string, scope: 'resource' | 'thread', data: Record<string, unknown>): Promise<void>;
26
- createRun(run: CreateRunInput): Promise<string>;
27
- updateRun(runId: string, updates: Partial<AgentRunState>): Promise<void>;
28
- getRun(runId: string): Promise<AgentRunState | null>;
29
- getRunsByThread(threadId: string): Promise<AgentRunState[]>;
30
- private setApprovals;
31
- private mapRunRow;
32
- findRunByToolCallId(toolCallId: string): Promise<{
33
- run: AgentRunState;
34
- approval: NonNullable<AgentRunState['pendingApprovals']>[number];
35
- } | null>;
36
- resolveApproval(toolCallId: string, status: 'approved' | 'denied'): Promise<boolean>;
37
- saveScore(score: SaveScoreInput): Promise<void>;
38
- getScores(runId: string): Promise<AIRunScore[]>;
39
- close(): Promise<void>;
40
- }