@pikku/kysely 0.12.10 → 0.12.12
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 +22 -4
- package/dist/src/create-audited-kysely.d.ts +10 -0
- package/dist/src/create-audited-kysely.js +167 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/kysely-ai-agent-run-service.d.ts +1 -0
- package/dist/src/kysely-ai-agent-run-service.js +4 -1
- package/dist/src/kysely-channel-store.d.ts +3 -0
- package/dist/src/kysely-channel-store.js +25 -0
- package/dist/src/kysely-tables.d.ts +4 -0
- package/dist/src/kysely-workflow-mirror.d.ts +60 -0
- package/dist/src/kysely-workflow-mirror.js +329 -0
- package/dist/src/kysely-workflow-run-service.js +6 -0
- package/dist/src/kysely-workflow-service.d.ts +17 -14
- package/dist/src/kysely-workflow-service.js +19 -13
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/create-audited-kysely.test.ts +560 -0
- package/src/create-audited-kysely.ts +254 -0
- package/src/index.ts +5 -0
- package/src/kysely-ai-agent-run-service.ts +6 -1
- package/src/kysely-ai-run-state-service.ts +6 -2
- package/src/kysely-channel-store.ts +27 -0
- package/src/kysely-session-store.ts +1 -3
- package/src/kysely-tables.ts +4 -0
- package/src/kysely-workflow-mirror.test.ts +246 -0
- package/src/kysely-workflow-mirror.ts +438 -0
- package/src/kysely-workflow-run-service.ts +6 -0
- package/src/kysely-workflow-service.ts +37 -14
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { sql } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Kysely-backed `WorkflowRunMirror`.
|
|
4
|
+
*
|
|
5
|
+
* Forwards executor writes to the same `workflow_runs` / `workflow_step` /
|
|
6
|
+
* `workflow_step_history` / `workflow_versions` tables that
|
|
7
|
+
* `KyselyWorkflowService` uses, so a `KyselyWorkflowRunService` reading
|
|
8
|
+
* those tables will see runs driven by any executor (Cloudflare Durable
|
|
9
|
+
* Object, Redis, MongoDB, in-memory) — not just kysely-driven runs.
|
|
10
|
+
*
|
|
11
|
+
* Errors thrown here are caught by the executor's `safeMirror` wrapper
|
|
12
|
+
* and logged, so a mirror outage cannot break a running workflow.
|
|
13
|
+
*/
|
|
14
|
+
export class KyselyWorkflowMirror {
|
|
15
|
+
db;
|
|
16
|
+
initialized = false;
|
|
17
|
+
constructor(db) {
|
|
18
|
+
this.db = db;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create the underlying tables if they don't exist. Safe to call from
|
|
22
|
+
* either the mirror or `KyselyWorkflowService.init()` — schema is the
|
|
23
|
+
* same and uses `ifNotExists`.
|
|
24
|
+
*/
|
|
25
|
+
async init() {
|
|
26
|
+
if (this.initialized)
|
|
27
|
+
return;
|
|
28
|
+
await this.db.schema
|
|
29
|
+
.createTable('workflow_runs')
|
|
30
|
+
.ifNotExists()
|
|
31
|
+
.addColumn('workflow_run_id', 'text', (col) => col.primaryKey())
|
|
32
|
+
.addColumn('workflow', 'text', (col) => col.notNull())
|
|
33
|
+
.addColumn('status', 'text', (col) => col.notNull())
|
|
34
|
+
.addColumn('input', 'text', (col) => col.notNull())
|
|
35
|
+
.addColumn('output', 'text')
|
|
36
|
+
.addColumn('error', 'text')
|
|
37
|
+
.addColumn('state', 'text', (col) => col.defaultTo('{}'))
|
|
38
|
+
.addColumn('inline', 'boolean', (col) => col.defaultTo(false))
|
|
39
|
+
.addColumn('graph_hash', 'text')
|
|
40
|
+
.addColumn('deterministic', 'boolean', (col) => col.defaultTo(false))
|
|
41
|
+
.addColumn('planned_steps', 'text')
|
|
42
|
+
.addColumn('wire', 'text')
|
|
43
|
+
.addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
44
|
+
.addColumn('updated_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
45
|
+
.execute();
|
|
46
|
+
await this.db.schema
|
|
47
|
+
.createTable('workflow_step')
|
|
48
|
+
.ifNotExists()
|
|
49
|
+
.addColumn('workflow_step_id', 'text', (col) => col.primaryKey())
|
|
50
|
+
.addColumn('workflow_run_id', 'text', (col) => col
|
|
51
|
+
.notNull()
|
|
52
|
+
.references('workflow_runs.workflow_run_id')
|
|
53
|
+
.onDelete('cascade'))
|
|
54
|
+
.addColumn('step_name', 'text', (col) => col.notNull())
|
|
55
|
+
.addColumn('rpc_name', 'text')
|
|
56
|
+
.addColumn('data', 'text')
|
|
57
|
+
.addColumn('status', 'text', (col) => col.notNull().defaultTo('pending'))
|
|
58
|
+
.addColumn('result', 'text')
|
|
59
|
+
.addColumn('error', 'text')
|
|
60
|
+
.addColumn('child_run_id', 'text')
|
|
61
|
+
.addColumn('branch_taken', 'text')
|
|
62
|
+
.addColumn('retries', 'integer')
|
|
63
|
+
.addColumn('retry_delay', 'text')
|
|
64
|
+
.addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
65
|
+
.addColumn('updated_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
66
|
+
.addUniqueConstraint('workflow_step_run_name_unique', [
|
|
67
|
+
'workflow_run_id',
|
|
68
|
+
'step_name',
|
|
69
|
+
])
|
|
70
|
+
.execute();
|
|
71
|
+
await this.db.schema
|
|
72
|
+
.createTable('workflow_step_history')
|
|
73
|
+
.ifNotExists()
|
|
74
|
+
.addColumn('history_id', 'text', (col) => col.primaryKey())
|
|
75
|
+
.addColumn('workflow_step_id', 'text', (col) => col
|
|
76
|
+
.notNull()
|
|
77
|
+
.references('workflow_step.workflow_step_id')
|
|
78
|
+
.onDelete('cascade'))
|
|
79
|
+
.addColumn('status', 'text', (col) => col.notNull())
|
|
80
|
+
.addColumn('result', 'text')
|
|
81
|
+
.addColumn('error', 'text')
|
|
82
|
+
.addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
83
|
+
.addColumn('running_at', 'timestamp')
|
|
84
|
+
.addColumn('scheduled_at', 'timestamp')
|
|
85
|
+
.addColumn('succeeded_at', 'timestamp')
|
|
86
|
+
.addColumn('failed_at', 'timestamp')
|
|
87
|
+
.execute();
|
|
88
|
+
await this.db.schema
|
|
89
|
+
.createTable('workflow_versions')
|
|
90
|
+
.ifNotExists()
|
|
91
|
+
.addColumn('workflow_name', 'text', (col) => col.notNull())
|
|
92
|
+
.addColumn('graph_hash', 'text', (col) => col.notNull())
|
|
93
|
+
.addColumn('graph', 'text', (col) => col.notNull())
|
|
94
|
+
.addColumn('source', 'text', (col) => col.notNull())
|
|
95
|
+
.addColumn('status', 'text', (col) => col.notNull().defaultTo('active'))
|
|
96
|
+
.addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
97
|
+
.addPrimaryKeyConstraint('workflow_versions_pk', [
|
|
98
|
+
'workflow_name',
|
|
99
|
+
'graph_hash',
|
|
100
|
+
])
|
|
101
|
+
.execute();
|
|
102
|
+
this.initialized = true;
|
|
103
|
+
}
|
|
104
|
+
async createRun(runId, workflowName, input, inline, graphHash, wire, options) {
|
|
105
|
+
await this.db
|
|
106
|
+
.insertInto('workflowRuns')
|
|
107
|
+
.values({
|
|
108
|
+
workflowRunId: runId,
|
|
109
|
+
workflow: workflowName,
|
|
110
|
+
status: 'running',
|
|
111
|
+
input: JSON.stringify(input),
|
|
112
|
+
inline,
|
|
113
|
+
graphHash: graphHash ?? null,
|
|
114
|
+
deterministic: options?.deterministic ?? false,
|
|
115
|
+
plannedSteps: options?.plannedSteps
|
|
116
|
+
? JSON.stringify(options.plannedSteps)
|
|
117
|
+
: null,
|
|
118
|
+
wire: wire ? JSON.stringify(wire) : null,
|
|
119
|
+
})
|
|
120
|
+
.execute();
|
|
121
|
+
}
|
|
122
|
+
async updateRunStatus(id, status, output, error) {
|
|
123
|
+
await this.db
|
|
124
|
+
.updateTable('workflowRuns')
|
|
125
|
+
.set({
|
|
126
|
+
status,
|
|
127
|
+
output: output !== undefined ? JSON.stringify(output) : null,
|
|
128
|
+
error: error !== undefined ? JSON.stringify(error) : null,
|
|
129
|
+
updatedAt: new Date(),
|
|
130
|
+
})
|
|
131
|
+
.where('workflowRunId', '=', id)
|
|
132
|
+
.execute();
|
|
133
|
+
}
|
|
134
|
+
async insertStepState(runId, step) {
|
|
135
|
+
const now = step.createdAt ?? new Date();
|
|
136
|
+
await this.db
|
|
137
|
+
.insertInto('workflowStep')
|
|
138
|
+
.values({
|
|
139
|
+
workflowStepId: step.stepId,
|
|
140
|
+
workflowRunId: runId,
|
|
141
|
+
stepName: step.stepName,
|
|
142
|
+
rpcName: step.rpcName,
|
|
143
|
+
data: step.data != null ? JSON.stringify(step.data) : null,
|
|
144
|
+
status: step.status,
|
|
145
|
+
retries: step.retries ?? null,
|
|
146
|
+
retryDelay: step.retryDelay?.toString() ?? null,
|
|
147
|
+
createdAt: now,
|
|
148
|
+
updatedAt: now,
|
|
149
|
+
})
|
|
150
|
+
.execute();
|
|
151
|
+
await this.insertHistoryRecord(step.stepId, step.status);
|
|
152
|
+
}
|
|
153
|
+
async setStepRunning(stepId) {
|
|
154
|
+
await this.updateStepStatus(stepId, 'running');
|
|
155
|
+
await this.appendOrUpdateLatestHistory(stepId, 'running');
|
|
156
|
+
}
|
|
157
|
+
async setStepScheduled(stepId) {
|
|
158
|
+
await this.updateStepStatus(stepId, 'scheduled');
|
|
159
|
+
}
|
|
160
|
+
async setStepResult(stepId, result) {
|
|
161
|
+
const resultJson = JSON.stringify(result);
|
|
162
|
+
await this.db
|
|
163
|
+
.updateTable('workflowStep')
|
|
164
|
+
.set({
|
|
165
|
+
status: 'succeeded',
|
|
166
|
+
result: resultJson,
|
|
167
|
+
error: null,
|
|
168
|
+
updatedAt: new Date(),
|
|
169
|
+
})
|
|
170
|
+
.where('workflowStepId', '=', stepId)
|
|
171
|
+
.execute();
|
|
172
|
+
await this.appendOrUpdateLatestHistory(stepId, 'succeeded', resultJson);
|
|
173
|
+
}
|
|
174
|
+
async setStepChildRunId(stepId, childRunId) {
|
|
175
|
+
await this.db
|
|
176
|
+
.updateTable('workflowStep')
|
|
177
|
+
.set({ childRunId, updatedAt: new Date() })
|
|
178
|
+
.where('workflowStepId', '=', stepId)
|
|
179
|
+
.execute();
|
|
180
|
+
}
|
|
181
|
+
async setStepError(stepId, error) {
|
|
182
|
+
const errorJson = JSON.stringify(error);
|
|
183
|
+
await this.db
|
|
184
|
+
.updateTable('workflowStep')
|
|
185
|
+
.set({
|
|
186
|
+
status: 'failed',
|
|
187
|
+
error: errorJson,
|
|
188
|
+
result: null,
|
|
189
|
+
updatedAt: new Date(),
|
|
190
|
+
})
|
|
191
|
+
.where('workflowStepId', '=', stepId)
|
|
192
|
+
.execute();
|
|
193
|
+
await this.appendOrUpdateLatestHistory(stepId, 'failed', undefined, errorJson);
|
|
194
|
+
}
|
|
195
|
+
async createRetryAttempt(failedStepId, newStep) {
|
|
196
|
+
await this.db
|
|
197
|
+
.updateTable('workflowStep')
|
|
198
|
+
.set({
|
|
199
|
+
status: newStep.status,
|
|
200
|
+
result: null,
|
|
201
|
+
error: null,
|
|
202
|
+
updatedAt: new Date(),
|
|
203
|
+
})
|
|
204
|
+
.where('workflowStepId', '=', failedStepId)
|
|
205
|
+
.execute();
|
|
206
|
+
await this.insertHistoryRecord(failedStepId, newStep.status);
|
|
207
|
+
}
|
|
208
|
+
async setBranchTaken(stepId, branchKey) {
|
|
209
|
+
await this.db
|
|
210
|
+
.updateTable('workflowStep')
|
|
211
|
+
.set({ branchTaken: branchKey, updatedAt: new Date() })
|
|
212
|
+
.where('workflowStepId', '=', stepId)
|
|
213
|
+
.execute();
|
|
214
|
+
}
|
|
215
|
+
async updateRunState(runId, name, value) {
|
|
216
|
+
const row = await this.db
|
|
217
|
+
.selectFrom('workflowRuns')
|
|
218
|
+
.select('state')
|
|
219
|
+
.where('workflowRunId', '=', runId)
|
|
220
|
+
.executeTakeFirst();
|
|
221
|
+
const state = row?.state != null
|
|
222
|
+
? typeof row.state === 'string'
|
|
223
|
+
? JSON.parse(row.state)
|
|
224
|
+
: row.state
|
|
225
|
+
: {};
|
|
226
|
+
state[name] = value;
|
|
227
|
+
await this.db
|
|
228
|
+
.updateTable('workflowRuns')
|
|
229
|
+
.set({ state: JSON.stringify(state), updatedAt: new Date() })
|
|
230
|
+
.where('workflowRunId', '=', runId)
|
|
231
|
+
.execute();
|
|
232
|
+
}
|
|
233
|
+
async upsertWorkflowVersion(name, graphHash, graph, source, status = 'active') {
|
|
234
|
+
await this.db
|
|
235
|
+
.insertInto('workflowVersions')
|
|
236
|
+
.values({
|
|
237
|
+
workflowName: name,
|
|
238
|
+
graphHash,
|
|
239
|
+
graph: JSON.stringify(graph),
|
|
240
|
+
source,
|
|
241
|
+
status,
|
|
242
|
+
})
|
|
243
|
+
.onConflict((oc) => oc.columns(['workflowName', 'graphHash']).doNothing())
|
|
244
|
+
.execute();
|
|
245
|
+
}
|
|
246
|
+
async updateWorkflowVersionStatus(name, graphHash, status) {
|
|
247
|
+
await this.db
|
|
248
|
+
.updateTable('workflowVersions')
|
|
249
|
+
.set({ status })
|
|
250
|
+
.where('workflowName', '=', name)
|
|
251
|
+
.where('graphHash', '=', graphHash)
|
|
252
|
+
.execute();
|
|
253
|
+
}
|
|
254
|
+
// ─── internals ────────────────────────────────────────────────────
|
|
255
|
+
async updateStepStatus(stepId, status) {
|
|
256
|
+
await this.db
|
|
257
|
+
.updateTable('workflowStep')
|
|
258
|
+
.set({ status, updatedAt: new Date() })
|
|
259
|
+
.where('workflowStepId', '=', stepId)
|
|
260
|
+
.execute();
|
|
261
|
+
}
|
|
262
|
+
async insertHistoryRecord(stepId, status, resultJson, errorJson) {
|
|
263
|
+
const now = new Date();
|
|
264
|
+
const values = {
|
|
265
|
+
historyId: crypto.randomUUID(),
|
|
266
|
+
workflowStepId: stepId,
|
|
267
|
+
status,
|
|
268
|
+
result: resultJson ?? null,
|
|
269
|
+
error: errorJson ?? null,
|
|
270
|
+
createdAt: now,
|
|
271
|
+
};
|
|
272
|
+
const tsField = timestampFieldFor(status);
|
|
273
|
+
if (tsField)
|
|
274
|
+
values[tsField] = now;
|
|
275
|
+
await this.db
|
|
276
|
+
.insertInto('workflowStepHistory')
|
|
277
|
+
.values(values)
|
|
278
|
+
.execute();
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The executor pattern is: `insertStepState` writes a 'pending' history
|
|
282
|
+
* row, then later transitions UPDATE that latest row in place rather
|
|
283
|
+
* than appending a new one — except for retry attempts which append.
|
|
284
|
+
*
|
|
285
|
+
* We mirror the same shape so `KyselyWorkflowRunService.getRunHistory`
|
|
286
|
+
* returns the same sequence the executor would have produced.
|
|
287
|
+
*/
|
|
288
|
+
async appendOrUpdateLatestHistory(stepId, status, resultJson, errorJson) {
|
|
289
|
+
const latest = await this.db
|
|
290
|
+
.selectFrom('workflowStepHistory')
|
|
291
|
+
.select('historyId')
|
|
292
|
+
.where('workflowStepId', '=', stepId)
|
|
293
|
+
.orderBy('createdAt', 'desc')
|
|
294
|
+
.limit(1)
|
|
295
|
+
.executeTakeFirst();
|
|
296
|
+
if (latest) {
|
|
297
|
+
const update = { status };
|
|
298
|
+
if (resultJson !== undefined)
|
|
299
|
+
update.result = resultJson;
|
|
300
|
+
if (errorJson !== undefined)
|
|
301
|
+
update.error = errorJson;
|
|
302
|
+
const tsField = timestampFieldFor(status);
|
|
303
|
+
if (tsField)
|
|
304
|
+
update[tsField] = new Date();
|
|
305
|
+
await this.db
|
|
306
|
+
.updateTable('workflowStepHistory')
|
|
307
|
+
.set(update)
|
|
308
|
+
.where('historyId', '=', latest.historyId)
|
|
309
|
+
.execute();
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
await this.insertHistoryRecord(stepId, status, resultJson, errorJson);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function timestampFieldFor(status) {
|
|
317
|
+
switch (status) {
|
|
318
|
+
case 'running':
|
|
319
|
+
return 'runningAt';
|
|
320
|
+
case 'scheduled':
|
|
321
|
+
return 'scheduledAt';
|
|
322
|
+
case 'succeeded':
|
|
323
|
+
return 'succeededAt';
|
|
324
|
+
case 'failed':
|
|
325
|
+
return 'failedAt';
|
|
326
|
+
default:
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
@@ -17,6 +17,8 @@ export class KyselyWorkflowRunService {
|
|
|
17
17
|
'error',
|
|
18
18
|
'inline',
|
|
19
19
|
'graphHash',
|
|
20
|
+
'deterministic',
|
|
21
|
+
'plannedSteps',
|
|
20
22
|
'wire',
|
|
21
23
|
'createdAt',
|
|
22
24
|
'updatedAt',
|
|
@@ -46,6 +48,8 @@ export class KyselyWorkflowRunService {
|
|
|
46
48
|
'error',
|
|
47
49
|
'inline',
|
|
48
50
|
'graphHash',
|
|
51
|
+
'deterministic',
|
|
52
|
+
'plannedSteps',
|
|
49
53
|
'wire',
|
|
50
54
|
'createdAt',
|
|
51
55
|
'updatedAt',
|
|
@@ -204,6 +208,8 @@ export class KyselyWorkflowRunService {
|
|
|
204
208
|
error: parseJson(row.error),
|
|
205
209
|
inline: row.inline,
|
|
206
210
|
graphHash: row.graphHash,
|
|
211
|
+
deterministic: row.deterministic,
|
|
212
|
+
plannedSteps: parseJson(row.plannedSteps),
|
|
207
213
|
wire: parseJson(row.wire) ?? { type: 'unknown' },
|
|
208
214
|
createdAt: new Date(row.createdAt),
|
|
209
215
|
updatedAt: new Date(row.updatedAt),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SerializedError } from '@pikku/core';
|
|
2
|
-
import { PikkuWorkflowService, type WorkflowRun, type WorkflowRunWire, type StepState, type WorkflowStatus, type WorkflowVersionStatus } from '@pikku/core/workflow';
|
|
2
|
+
import { PikkuWorkflowService, type WorkflowPlannedStep, type WorkflowRun, type WorkflowRunWire, type StepState, type WorkflowStatus, type WorkflowVersionStatus } from '@pikku/core/workflow';
|
|
3
3
|
import type { Kysely } from 'kysely';
|
|
4
4
|
import type { KyselyPikkuDB } from './kysely-tables.js';
|
|
5
5
|
export declare class KyselyWorkflowService extends PikkuWorkflowService {
|
|
@@ -8,10 +8,13 @@ export declare class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
8
8
|
private runService;
|
|
9
9
|
constructor(db: Kysely<KyselyPikkuDB>);
|
|
10
10
|
init(): Promise<void>;
|
|
11
|
-
|
|
11
|
+
protected createRunImpl(workflowName: string, input: any, inline: boolean, graphHash: string, wire: WorkflowRunWire, options?: {
|
|
12
|
+
deterministic?: boolean;
|
|
13
|
+
plannedSteps?: WorkflowPlannedStep[];
|
|
14
|
+
}): Promise<string>;
|
|
12
15
|
getRun(id: string): Promise<WorkflowRun | null>;
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
protected updateRunStatusImpl(id: string, status: WorkflowStatus, output?: any, error?: SerializedError): Promise<void>;
|
|
17
|
+
protected insertStepStateImpl(runId: string, stepName: string, rpcName: string | null, data: any, stepOptions?: {
|
|
15
18
|
retries?: number;
|
|
16
19
|
retryDelay?: string | number;
|
|
17
20
|
}): Promise<StepState>;
|
|
@@ -19,14 +22,14 @@ export declare class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
19
22
|
getRunHistory(runId: string): Promise<Array<StepState & {
|
|
20
23
|
stepName: string;
|
|
21
24
|
}>>;
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
protected setStepRunningImpl(stepId: string): Promise<void>;
|
|
26
|
+
protected setStepScheduledImpl(stepId: string): Promise<void>;
|
|
24
27
|
private insertHistoryRecord;
|
|
25
28
|
private getTimestampFieldForStatus;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
protected setStepChildRunIdImpl(stepId: string, childRunId: string): Promise<void>;
|
|
30
|
+
protected setStepResultImpl(stepId: string, result: any): Promise<void>;
|
|
31
|
+
protected setStepErrorImpl(stepId: string, error: Error): Promise<void>;
|
|
32
|
+
protected createRetryAttemptImpl(stepId: string, status: 'pending' | 'running'): Promise<StepState>;
|
|
30
33
|
withRunLock<T>(_id: string, fn: () => Promise<T>): Promise<T>;
|
|
31
34
|
withStepLock<T>(_runId: string, _stepName: string, fn: () => Promise<T>): Promise<T>;
|
|
32
35
|
getCompletedGraphState(runId: string): Promise<{
|
|
@@ -36,11 +39,11 @@ export declare class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
36
39
|
}>;
|
|
37
40
|
getNodesWithoutSteps(runId: string, nodeIds: string[]): Promise<string[]>;
|
|
38
41
|
getNodeResults(runId: string, nodeIds: string[]): Promise<Record<string, any>>;
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
protected setBranchTakenImpl(stepId: string, branchKey: string): Promise<void>;
|
|
43
|
+
protected updateRunStateImpl(runId: string, name: string, value: unknown): Promise<void>;
|
|
41
44
|
getRunState(runId: string): Promise<Record<string, unknown>>;
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
protected upsertWorkflowVersionImpl(name: string, graphHash: string, graph: any, source: string, status?: WorkflowVersionStatus): Promise<void>;
|
|
46
|
+
protected updateWorkflowVersionStatusImpl(name: string, graphHash: string, status: WorkflowVersionStatus): Promise<void>;
|
|
44
47
|
getWorkflowVersion(name: string, graphHash: string): Promise<{
|
|
45
48
|
graph: any;
|
|
46
49
|
source: string;
|
|
@@ -29,6 +29,8 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
29
29
|
.addColumn('state', 'text', (col) => col.defaultTo('{}'))
|
|
30
30
|
.addColumn('inline', 'boolean', (col) => col.defaultTo(false))
|
|
31
31
|
.addColumn('graph_hash', 'text')
|
|
32
|
+
.addColumn('deterministic', 'boolean', (col) => col.defaultTo(false))
|
|
33
|
+
.addColumn('planned_steps', 'text')
|
|
32
34
|
.addColumn('wire', 'text')
|
|
33
35
|
.addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
34
36
|
.addColumn('updated_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
@@ -95,7 +97,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
95
97
|
.execute();
|
|
96
98
|
this.initialized = true;
|
|
97
99
|
}
|
|
98
|
-
async
|
|
100
|
+
async createRunImpl(workflowName, input, inline, graphHash, wire, options) {
|
|
99
101
|
const id = crypto.randomUUID();
|
|
100
102
|
await this.db
|
|
101
103
|
.insertInto('workflowRuns')
|
|
@@ -106,6 +108,10 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
106
108
|
input: JSON.stringify(input),
|
|
107
109
|
inline,
|
|
108
110
|
graphHash: graphHash ?? null,
|
|
111
|
+
deterministic: options?.deterministic ?? false,
|
|
112
|
+
plannedSteps: options?.plannedSteps
|
|
113
|
+
? JSON.stringify(options.plannedSteps)
|
|
114
|
+
: null,
|
|
109
115
|
wire: wire ? JSON.stringify(wire) : null,
|
|
110
116
|
})
|
|
111
117
|
.execute();
|
|
@@ -114,7 +120,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
114
120
|
async getRun(id) {
|
|
115
121
|
return this.runService.getRun(id);
|
|
116
122
|
}
|
|
117
|
-
async
|
|
123
|
+
async updateRunStatusImpl(id, status, output, error) {
|
|
118
124
|
await this.db
|
|
119
125
|
.updateTable('workflowRuns')
|
|
120
126
|
.set({
|
|
@@ -126,7 +132,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
126
132
|
.where('workflowRunId', '=', id)
|
|
127
133
|
.execute();
|
|
128
134
|
}
|
|
129
|
-
async
|
|
135
|
+
async insertStepStateImpl(runId, stepName, rpcName, data, stepOptions) {
|
|
130
136
|
const stepId = crypto.randomUUID();
|
|
131
137
|
const now = new Date();
|
|
132
138
|
await this.db
|
|
@@ -196,7 +202,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
196
202
|
async getRunHistory(runId) {
|
|
197
203
|
return this.runService.getRunHistory(runId);
|
|
198
204
|
}
|
|
199
|
-
async
|
|
205
|
+
async setStepRunningImpl(stepId) {
|
|
200
206
|
await this.db
|
|
201
207
|
.updateTable('workflowStep')
|
|
202
208
|
.set({ status: 'running', updatedAt: new Date() })
|
|
@@ -217,7 +223,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
217
223
|
.execute();
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
|
-
async
|
|
226
|
+
async setStepScheduledImpl(stepId) {
|
|
221
227
|
await this.db
|
|
222
228
|
.updateTable('workflowStep')
|
|
223
229
|
.set({ status: 'scheduled', updatedAt: new Date() })
|
|
@@ -257,7 +263,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
257
263
|
return 'createdAt';
|
|
258
264
|
}
|
|
259
265
|
}
|
|
260
|
-
async
|
|
266
|
+
async setStepChildRunIdImpl(stepId, childRunId) {
|
|
261
267
|
await this.db
|
|
262
268
|
.updateTable('workflowStep')
|
|
263
269
|
.set({
|
|
@@ -267,7 +273,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
267
273
|
.where('workflowStepId', '=', stepId)
|
|
268
274
|
.execute();
|
|
269
275
|
}
|
|
270
|
-
async
|
|
276
|
+
async setStepResultImpl(stepId, result) {
|
|
271
277
|
const resultJson = JSON.stringify(result);
|
|
272
278
|
await this.db
|
|
273
279
|
.updateTable('workflowStep')
|
|
@@ -294,7 +300,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
294
300
|
.execute();
|
|
295
301
|
}
|
|
296
302
|
}
|
|
297
|
-
async
|
|
303
|
+
async setStepErrorImpl(stepId, error) {
|
|
298
304
|
const serializedError = {
|
|
299
305
|
message: error.message,
|
|
300
306
|
stack: error.stack,
|
|
@@ -326,7 +332,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
326
332
|
.execute();
|
|
327
333
|
}
|
|
328
334
|
}
|
|
329
|
-
async
|
|
335
|
+
async createRetryAttemptImpl(stepId, status) {
|
|
330
336
|
await this.db
|
|
331
337
|
.updateTable('workflowStep')
|
|
332
338
|
.set({ status, result: null, error: null, updatedAt: new Date() })
|
|
@@ -430,14 +436,14 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
430
436
|
}
|
|
431
437
|
return results;
|
|
432
438
|
}
|
|
433
|
-
async
|
|
439
|
+
async setBranchTakenImpl(stepId, branchKey) {
|
|
434
440
|
await this.db
|
|
435
441
|
.updateTable('workflowStep')
|
|
436
442
|
.set({ branchTaken: branchKey, updatedAt: new Date() })
|
|
437
443
|
.where('workflowStepId', '=', stepId)
|
|
438
444
|
.execute();
|
|
439
445
|
}
|
|
440
|
-
async
|
|
446
|
+
async updateRunStateImpl(runId, name, value) {
|
|
441
447
|
const row = await this.db
|
|
442
448
|
.selectFrom('workflowRuns')
|
|
443
449
|
.select('state')
|
|
@@ -461,7 +467,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
461
467
|
return {};
|
|
462
468
|
return parseJson(row.state) ?? {};
|
|
463
469
|
}
|
|
464
|
-
async
|
|
470
|
+
async upsertWorkflowVersionImpl(name, graphHash, graph, source, status) {
|
|
465
471
|
await this.db
|
|
466
472
|
.insertInto('workflowVersions')
|
|
467
473
|
.values({
|
|
@@ -474,7 +480,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
474
480
|
.onConflict((oc) => oc.columns(['workflowName', 'graphHash']).doNothing())
|
|
475
481
|
.execute();
|
|
476
482
|
}
|
|
477
|
-
async
|
|
483
|
+
async updateWorkflowVersionStatusImpl(name, graphHash, status) {
|
|
478
484
|
await this.db
|
|
479
485
|
.updateTable('workflowVersions')
|
|
480
486
|
.set({ status })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/index.ts","../src/kysely-ai-agent-run-service.ts","../src/kysely-ai-run-state-service.ts","../src/kysely-ai-storage-service.ts","../src/kysely-channel-store.ts","../src/kysely-credential-service.ts","../src/kysely-deployment-service.ts","../src/kysely-eventhub-store.ts","../src/kysely-json.ts","../src/kysely-secret-service.ts","../src/kysely-session-store.ts","../src/kysely-tables.ts","../src/kysely-workflow-run-service.ts","../src/kysely-workflow-service.ts","../bin/pikku-kysely-pure.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/create-audited-kysely.ts","../src/index.ts","../src/kysely-ai-agent-run-service.ts","../src/kysely-ai-run-state-service.ts","../src/kysely-ai-storage-service.ts","../src/kysely-channel-store.ts","../src/kysely-credential-service.ts","../src/kysely-deployment-service.ts","../src/kysely-eventhub-store.ts","../src/kysely-json.ts","../src/kysely-secret-service.ts","../src/kysely-session-store.ts","../src/kysely-tables.ts","../src/kysely-workflow-mirror.ts","../src/kysely-workflow-run-service.ts","../src/kysely-workflow-service.ts","../bin/pikku-kysely-pure.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/kysely",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.12",
|
|
4
4
|
"author": "yasser.fadl@gmail.com",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"module": "dist/src/index.js",
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
"prepublishOnly": "yarn build"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@pikku/core": "^0.12.
|
|
23
|
+
"@pikku/core": "^0.12.24"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"kysely": "^0.28.12"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/better-sqlite3": "^7.6.13",
|
|
30
|
-
"better-sqlite3": "^12.
|
|
30
|
+
"better-sqlite3": "^12.10.0",
|
|
31
31
|
"kysely-codegen": "^0.20.0",
|
|
32
32
|
"kysely-plugin-serialize": "^0.8.2",
|
|
33
33
|
"kysely-postgres-js": "^3.0.0",
|