@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
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 0.12.12
|
|
2
|
+
|
|
3
|
+
### Patch Changes
|
|
4
|
+
|
|
5
|
+
- 55ba75a: Update the OSS runtime dependency set for newer Node support by bumping `uWebSockets.js` to `v20.68.0` and `better-sqlite3` to `v12.10.0`.
|
|
6
|
+
- Updated dependencies [c02275f]
|
|
7
|
+
- Updated dependencies [0bd0433]
|
|
8
|
+
- @pikku/core@0.12.24
|
|
9
|
+
|
|
10
|
+
## 0.12.11
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- b9ed73e: Add deterministic workflow planned-step metadata support and SSE init stream payload generation.
|
|
15
|
+
- Persist `deterministic` and `plannedSteps` on workflow runs in core and service adapters.
|
|
16
|
+
- Expose planned-step metadata on workflow run status responses.
|
|
17
|
+
- Emit an initial `type: 'init'` SSE event for deterministic workflow streams before incremental updates.
|
|
18
|
+
- Add CLI tests covering serialized stream route output for init/update/done event behavior.
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [b9ed73e]
|
|
21
|
+
- @pikku/core@0.12.19
|
|
22
|
+
|
|
1
23
|
## 0.12.0
|
|
2
24
|
|
|
3
25
|
## 0.12.10
|
|
@@ -5,7 +27,6 @@
|
|
|
5
27
|
### Patch Changes
|
|
6
28
|
|
|
7
29
|
- 311c0c4: Unify session persistence through SessionStore, remove session blob from ChannelStore
|
|
8
|
-
|
|
9
30
|
- PikkuSessionService now persists sessions via SessionStore on set()/clear() instead of every function call
|
|
10
31
|
- ChannelStore no longer stores session data — maps channelId to pikkuUserId only
|
|
11
32
|
- ChannelStore API: setUserSession/getChannelAndSession replaced with setPikkuUserId/getChannel
|
|
@@ -19,7 +40,6 @@
|
|
|
19
40
|
### Patch Changes
|
|
20
41
|
|
|
21
42
|
- 624097e: Add deploy pipeline with provider-agnostic architecture
|
|
22
|
-
|
|
23
43
|
- Add MetaService with explicit typed API, absorb WiringService reads
|
|
24
44
|
- Add deployment service, traceId propagation, scoped logger
|
|
25
45
|
- Rewrite analyzer: one function = one worker, gateways dispatch via RPC
|
|
@@ -39,7 +59,6 @@
|
|
|
39
59
|
### Patch Changes
|
|
40
60
|
|
|
41
61
|
- f85c234: Add unified credential system with per-user OAuth and AI agent pre-flight checks
|
|
42
|
-
|
|
43
62
|
- Unified CredentialService with lazy loading per user via pikkuUserId
|
|
44
63
|
- wire.getCredential() for typed single credential lookup
|
|
45
64
|
- MissingCredentialError with structured payload for client-side connect flows
|
|
@@ -144,7 +163,6 @@
|
|
|
144
163
|
- Updated dependencies [62a8725]
|
|
145
164
|
- Updated dependencies [62a8725]
|
|
146
165
|
- Updated dependencies [62a8725]
|
|
147
|
-
|
|
148
166
|
- @pikku/core@0.12.1
|
|
149
167
|
|
|
150
168
|
- Updated dependencies
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AuditLog } from '@pikku/core';
|
|
2
|
+
import type { Kysely } from 'kysely';
|
|
3
|
+
export interface CreateAuditedKyselyOptions {
|
|
4
|
+
audit: AuditLog;
|
|
5
|
+
auditReads?: boolean;
|
|
6
|
+
eventType?: string;
|
|
7
|
+
transactionId?: string | null;
|
|
8
|
+
queryIdPrefix?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function createAuditedKysely<DB>(db: Kysely<DB>, options: CreateAuditedKyselyOptions): Kysely<DB>;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
const QUERY_KIND_BY_NODE = {
|
|
2
|
+
SelectQueryNode: 'select',
|
|
3
|
+
InsertQueryNode: 'insert',
|
|
4
|
+
UpdateQueryNode: 'update',
|
|
5
|
+
DeleteQueryNode: 'delete',
|
|
6
|
+
};
|
|
7
|
+
function getIdentifierName(node) {
|
|
8
|
+
if (!node || typeof node !== 'object')
|
|
9
|
+
return undefined;
|
|
10
|
+
const candidate = node;
|
|
11
|
+
return (candidate.name ??
|
|
12
|
+
candidate.column?.name ??
|
|
13
|
+
candidate.identifier?.name ??
|
|
14
|
+
candidate.table?.identifier?.name);
|
|
15
|
+
}
|
|
16
|
+
function collectTableNames(node, out) {
|
|
17
|
+
if (!node || typeof node !== 'object')
|
|
18
|
+
return;
|
|
19
|
+
const candidate = node;
|
|
20
|
+
if (candidate.kind === 'TableNode' &&
|
|
21
|
+
typeof candidate.table?.identifier?.name === 'string') {
|
|
22
|
+
out.add(candidate.table.identifier.name);
|
|
23
|
+
}
|
|
24
|
+
for (const value of Object.values(node)) {
|
|
25
|
+
if (Array.isArray(value)) {
|
|
26
|
+
for (const item of value)
|
|
27
|
+
collectTableNames(item, out);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
collectTableNames(value, out);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function extractValue(node) {
|
|
34
|
+
if (!node || typeof node !== 'object')
|
|
35
|
+
return node;
|
|
36
|
+
const candidate = node;
|
|
37
|
+
switch (candidate.kind) {
|
|
38
|
+
case 'ValueNode':
|
|
39
|
+
return candidate.value;
|
|
40
|
+
case 'PrimitiveValueListNode':
|
|
41
|
+
case 'ValueListNode':
|
|
42
|
+
return (candidate.values ?? []).map(extractValue);
|
|
43
|
+
case 'DefaultInsertValueNode':
|
|
44
|
+
return '[default]';
|
|
45
|
+
case 'ColumnNode':
|
|
46
|
+
case 'ReferenceNode':
|
|
47
|
+
return `[${candidate.kind}]`;
|
|
48
|
+
case 'RawNode':
|
|
49
|
+
return '[raw]';
|
|
50
|
+
case 'SelectQueryNode':
|
|
51
|
+
return '[subquery]';
|
|
52
|
+
case 'ParensNode':
|
|
53
|
+
return extractValue(candidate.node);
|
|
54
|
+
case 'BinaryOperationNode':
|
|
55
|
+
return {
|
|
56
|
+
left: extractValue(candidate.left),
|
|
57
|
+
right: extractValue(candidate.right),
|
|
58
|
+
};
|
|
59
|
+
default:
|
|
60
|
+
return `[${candidate.kind ?? 'expression'}]`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function extractInsertChanges(node) {
|
|
64
|
+
const columns = Array.isArray(node.columns)
|
|
65
|
+
? node.columns
|
|
66
|
+
.map((column) => getIdentifierName(column))
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
: [];
|
|
69
|
+
const values = Array.isArray(node.values?.values) ? node.values.values : [];
|
|
70
|
+
if (columns.length === 0 || values.length === 0) {
|
|
71
|
+
return {
|
|
72
|
+
changedColumns: columns.length > 0 ? columns : undefined,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const rows = values.map((row) => {
|
|
76
|
+
const rowValues = Array.isArray(row?.values)
|
|
77
|
+
? row.values.map(extractValue)
|
|
78
|
+
: [];
|
|
79
|
+
return Object.fromEntries(columns.map((column, index) => [column, rowValues[index]]));
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
changedColumns: columns,
|
|
83
|
+
changes: rows.length === 1 ? rows[0] : rows,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function extractUpdateChanges(node) {
|
|
87
|
+
const updates = Array.isArray(node.updates) ? node.updates : [];
|
|
88
|
+
const entries = updates
|
|
89
|
+
.map((update) => {
|
|
90
|
+
const column = getIdentifierName(update.column);
|
|
91
|
+
if (!column)
|
|
92
|
+
return null;
|
|
93
|
+
return [column, extractValue(update.value)];
|
|
94
|
+
})
|
|
95
|
+
.filter(Boolean);
|
|
96
|
+
if (entries.length === 0) {
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
changedColumns: entries.map(([column]) => column),
|
|
101
|
+
changes: Object.fromEntries(entries),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function extractChangeSet(node, queryKind) {
|
|
105
|
+
if (queryKind === 'insert') {
|
|
106
|
+
return extractInsertChanges(node);
|
|
107
|
+
}
|
|
108
|
+
if (queryKind === 'update') {
|
|
109
|
+
return extractUpdateChanges(node);
|
|
110
|
+
}
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
class AuditedKyselyPlugin {
|
|
114
|
+
options;
|
|
115
|
+
pending = new Map();
|
|
116
|
+
queryCounter = 0;
|
|
117
|
+
constructor(options) {
|
|
118
|
+
this.options = options;
|
|
119
|
+
}
|
|
120
|
+
transformQuery(args) {
|
|
121
|
+
const queryKind = QUERY_KIND_BY_NODE[args.node.kind ?? ''];
|
|
122
|
+
if (!queryKind) {
|
|
123
|
+
return args.node;
|
|
124
|
+
}
|
|
125
|
+
if (queryKind === 'select' && this.options.auditReads === false) {
|
|
126
|
+
return args.node;
|
|
127
|
+
}
|
|
128
|
+
const tables = new Set();
|
|
129
|
+
collectTableNames(args.node, tables);
|
|
130
|
+
const queryId = `${this.options.queryIdPrefix ?? 'q'}-${++this.queryCounter}`;
|
|
131
|
+
this.pending.set(args.queryId, {
|
|
132
|
+
queryKind,
|
|
133
|
+
queryId,
|
|
134
|
+
tables: [...tables].sort(),
|
|
135
|
+
...extractChangeSet(args.node, queryKind),
|
|
136
|
+
});
|
|
137
|
+
return args.node;
|
|
138
|
+
}
|
|
139
|
+
async transformResult(args) {
|
|
140
|
+
const pending = this.pending.get(args.queryId);
|
|
141
|
+
if (!pending) {
|
|
142
|
+
return args.result;
|
|
143
|
+
}
|
|
144
|
+
this.pending.delete(args.queryId);
|
|
145
|
+
const rawResult = args.result;
|
|
146
|
+
const rowCount = rawResult.rows.length > 0
|
|
147
|
+
? rawResult.rows.length
|
|
148
|
+
: Number(rawResult.numUpdatedOrDeletedRows ?? rawResult.numAffectedRows ?? 0n);
|
|
149
|
+
await this.options.audit.write({
|
|
150
|
+
type: this.options.eventType ?? 'db.query',
|
|
151
|
+
source: 'auto',
|
|
152
|
+
transactionId: this.options.transactionId ?? null,
|
|
153
|
+
queryId: pending.queryId,
|
|
154
|
+
metadata: {
|
|
155
|
+
queryKind: pending.queryKind,
|
|
156
|
+
tables: pending.tables,
|
|
157
|
+
changedColumns: pending.changedColumns,
|
|
158
|
+
changes: pending.changes,
|
|
159
|
+
rowCount,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
return rawResult;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
export function createAuditedKysely(db, options) {
|
|
166
|
+
return db.withPlugin(new AuditedKyselyPlugin(options));
|
|
167
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { KyselyChannelStore } from './kysely-channel-store.js';
|
|
|
2
2
|
export { KyselyEventHubStore } from './kysely-eventhub-store.js';
|
|
3
3
|
export { KyselyWorkflowService } from './kysely-workflow-service.js';
|
|
4
4
|
export { KyselyWorkflowRunService } from './kysely-workflow-run-service.js';
|
|
5
|
+
export { KyselyWorkflowMirror } from './kysely-workflow-mirror.js';
|
|
5
6
|
export { KyselyDeploymentService } from './kysely-deployment-service.js';
|
|
6
7
|
export { KyselyAIStorageService } from './kysely-ai-storage-service.js';
|
|
7
8
|
export { KyselyAgentRunService } from './kysely-ai-agent-run-service.js';
|
|
@@ -11,6 +12,7 @@ export type { KyselySecretServiceConfig } from './kysely-secret-service.js';
|
|
|
11
12
|
export { KyselyCredentialService } from './kysely-credential-service.js';
|
|
12
13
|
export type { KyselyCredentialServiceConfig } from './kysely-credential-service.js';
|
|
13
14
|
export { KyselySessionStore } from './kysely-session-store.js';
|
|
15
|
+
export { createAuditedKysely, type CreateAuditedKyselyOptions, } from './create-audited-kysely.js';
|
|
14
16
|
export type { KyselyPikkuDB } from './kysely-tables.js';
|
|
15
17
|
export type { WorkflowRunService } from '@pikku/core/workflow';
|
|
16
18
|
export type { AgentRunService, AgentRunRow } from '@pikku/core/ai-agent';
|
package/dist/src/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export { KyselyChannelStore } from './kysely-channel-store.js';
|
|
|
2
2
|
export { KyselyEventHubStore } from './kysely-eventhub-store.js';
|
|
3
3
|
export { KyselyWorkflowService } from './kysely-workflow-service.js';
|
|
4
4
|
export { KyselyWorkflowRunService } from './kysely-workflow-run-service.js';
|
|
5
|
+
export { KyselyWorkflowMirror } from './kysely-workflow-mirror.js';
|
|
5
6
|
export { KyselyDeploymentService } from './kysely-deployment-service.js';
|
|
6
7
|
export { KyselyAIStorageService } from './kysely-ai-storage-service.js';
|
|
7
8
|
export { KyselyAgentRunService } from './kysely-ai-agent-run-service.js';
|
|
@@ -9,3 +10,4 @@ export { KyselyAIRunStateService } from './kysely-ai-run-state-service.js';
|
|
|
9
10
|
export { KyselySecretService } from './kysely-secret-service.js';
|
|
10
11
|
export { KyselyCredentialService } from './kysely-credential-service.js';
|
|
11
12
|
export { KyselySessionStore } from './kysely-session-store.js';
|
|
13
|
+
export { createAuditedKysely, } from './create-audited-kysely.js';
|
|
@@ -5,7 +5,7 @@ export class KyselyAgentRunService {
|
|
|
5
5
|
this.db = db;
|
|
6
6
|
}
|
|
7
7
|
async listThreads(options) {
|
|
8
|
-
const { agentName, limit = 50, offset = 0 } = options ?? {};
|
|
8
|
+
const { agentName, resourceId, limit = 50, offset = 0 } = options ?? {};
|
|
9
9
|
let query = this.db
|
|
10
10
|
.selectFrom('aiThreads as t')
|
|
11
11
|
.select([
|
|
@@ -23,6 +23,9 @@ export class KyselyAgentRunService {
|
|
|
23
23
|
.where('agentName', '=', agentName)
|
|
24
24
|
.distinct());
|
|
25
25
|
}
|
|
26
|
+
if (resourceId) {
|
|
27
|
+
query = query.where('t.resourceId', '=', resourceId);
|
|
28
|
+
}
|
|
26
29
|
const result = await query
|
|
27
30
|
.orderBy('t.updatedAt', 'desc')
|
|
28
31
|
.limit(limit)
|
|
@@ -13,5 +13,8 @@ export declare class KyselyChannelStore extends ChannelStore {
|
|
|
13
13
|
getChannel(channelId: string): Promise<Channel & {
|
|
14
14
|
pikkuUserId?: string;
|
|
15
15
|
}>;
|
|
16
|
+
setState(channelId: string, state: unknown): Promise<void>;
|
|
17
|
+
getState(channelId: string): Promise<unknown | undefined>;
|
|
18
|
+
clearState(channelId: string): Promise<void>;
|
|
16
19
|
close(): Promise<void>;
|
|
17
20
|
}
|
|
@@ -20,6 +20,7 @@ export class KyselyChannelStore extends ChannelStore {
|
|
|
20
20
|
.addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
21
21
|
.addColumn('opening_data', 'text', (col) => col.notNull().defaultTo('{}'))
|
|
22
22
|
.addColumn('pikku_user_id', 'text')
|
|
23
|
+
.addColumn('state', 'text')
|
|
23
24
|
.addColumn('last_wire', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull())
|
|
24
25
|
.execute();
|
|
25
26
|
await this.db.schema
|
|
@@ -76,5 +77,29 @@ export class KyselyChannelStore extends ChannelStore {
|
|
|
76
77
|
pikkuUserId: row.pikkuUserId ?? undefined,
|
|
77
78
|
};
|
|
78
79
|
}
|
|
80
|
+
async setState(channelId, state) {
|
|
81
|
+
await this.db
|
|
82
|
+
.updateTable('channels')
|
|
83
|
+
.set({ state: JSON.stringify(state ?? null) })
|
|
84
|
+
.where('channelId', '=', channelId)
|
|
85
|
+
.execute();
|
|
86
|
+
}
|
|
87
|
+
async getState(channelId) {
|
|
88
|
+
const row = await this.db
|
|
89
|
+
.selectFrom('channels')
|
|
90
|
+
.select(['state'])
|
|
91
|
+
.where('channelId', '=', channelId)
|
|
92
|
+
.executeTakeFirst();
|
|
93
|
+
if (!row || !row.state)
|
|
94
|
+
return undefined;
|
|
95
|
+
return parseJson(row.state) ?? undefined;
|
|
96
|
+
}
|
|
97
|
+
async clearState(channelId) {
|
|
98
|
+
await this.db
|
|
99
|
+
.updateTable('channels')
|
|
100
|
+
.set({ state: null })
|
|
101
|
+
.where('channelId', '=', channelId)
|
|
102
|
+
.execute();
|
|
103
|
+
}
|
|
79
104
|
async close() { }
|
|
80
105
|
}
|
|
@@ -6,6 +6,8 @@ export interface ChannelsTable {
|
|
|
6
6
|
createdAt: Generated<Date>;
|
|
7
7
|
openingData: string;
|
|
8
8
|
pikkuUserId: string | null;
|
|
9
|
+
/** JSON-serialized per-socket channel state, keyed by channelId. */
|
|
10
|
+
state: string | null;
|
|
9
11
|
lastWire: Generated<Date>;
|
|
10
12
|
}
|
|
11
13
|
export interface ChannelSubscriptionsTable {
|
|
@@ -22,6 +24,8 @@ export interface WorkflowRunsTable {
|
|
|
22
24
|
state: Generated<string>;
|
|
23
25
|
inline: Generated<boolean>;
|
|
24
26
|
graphHash: string | null;
|
|
27
|
+
deterministic: Generated<boolean>;
|
|
28
|
+
plannedSteps: string | null;
|
|
25
29
|
wire: string | null;
|
|
26
30
|
createdAt: Generated<Date>;
|
|
27
31
|
updatedAt: Generated<Date>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { SerializedError } from '@pikku/core';
|
|
2
|
+
import type { StepState, WorkflowRunMirror, WorkflowRunWire, WorkflowStatus, WorkflowPlannedStep, WorkflowVersionStatus } from '@pikku/core/workflow';
|
|
3
|
+
import type { Kysely } from 'kysely';
|
|
4
|
+
import type { KyselyPikkuDB } from './kysely-tables.js';
|
|
5
|
+
/**
|
|
6
|
+
* Kysely-backed `WorkflowRunMirror`.
|
|
7
|
+
*
|
|
8
|
+
* Forwards executor writes to the same `workflow_runs` / `workflow_step` /
|
|
9
|
+
* `workflow_step_history` / `workflow_versions` tables that
|
|
10
|
+
* `KyselyWorkflowService` uses, so a `KyselyWorkflowRunService` reading
|
|
11
|
+
* those tables will see runs driven by any executor (Cloudflare Durable
|
|
12
|
+
* Object, Redis, MongoDB, in-memory) — not just kysely-driven runs.
|
|
13
|
+
*
|
|
14
|
+
* Errors thrown here are caught by the executor's `safeMirror` wrapper
|
|
15
|
+
* and logged, so a mirror outage cannot break a running workflow.
|
|
16
|
+
*/
|
|
17
|
+
export declare class KyselyWorkflowMirror implements WorkflowRunMirror {
|
|
18
|
+
protected db: Kysely<KyselyPikkuDB>;
|
|
19
|
+
private initialized;
|
|
20
|
+
constructor(db: Kysely<KyselyPikkuDB>);
|
|
21
|
+
/**
|
|
22
|
+
* Create the underlying tables if they don't exist. Safe to call from
|
|
23
|
+
* either the mirror or `KyselyWorkflowService.init()` — schema is the
|
|
24
|
+
* same and uses `ifNotExists`.
|
|
25
|
+
*/
|
|
26
|
+
init(): Promise<void>;
|
|
27
|
+
createRun(runId: string, workflowName: string, input: any, inline: boolean, graphHash: string, wire: WorkflowRunWire, options?: {
|
|
28
|
+
deterministic?: boolean;
|
|
29
|
+
plannedSteps?: WorkflowPlannedStep[];
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
updateRunStatus(id: string, status: WorkflowStatus, output?: any, error?: SerializedError): Promise<void>;
|
|
32
|
+
insertStepState(runId: string, step: StepState & {
|
|
33
|
+
stepName: string;
|
|
34
|
+
rpcName: string | null;
|
|
35
|
+
data: any;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
setStepRunning(stepId: string): Promise<void>;
|
|
38
|
+
setStepScheduled(stepId: string): Promise<void>;
|
|
39
|
+
setStepResult(stepId: string, result: any): Promise<void>;
|
|
40
|
+
setStepChildRunId(stepId: string, childRunId: string): Promise<void>;
|
|
41
|
+
setStepError(stepId: string, error: SerializedError): Promise<void>;
|
|
42
|
+
createRetryAttempt(failedStepId: string, newStep: StepState & {
|
|
43
|
+
stepName: string;
|
|
44
|
+
}): Promise<void>;
|
|
45
|
+
setBranchTaken(stepId: string, branchKey: string): Promise<void>;
|
|
46
|
+
updateRunState(runId: string, name: string, value: unknown): Promise<void>;
|
|
47
|
+
upsertWorkflowVersion(name: string, graphHash: string, graph: any, source: string, status?: WorkflowVersionStatus): Promise<void>;
|
|
48
|
+
updateWorkflowVersionStatus(name: string, graphHash: string, status: WorkflowVersionStatus): Promise<void>;
|
|
49
|
+
private updateStepStatus;
|
|
50
|
+
private insertHistoryRecord;
|
|
51
|
+
/**
|
|
52
|
+
* The executor pattern is: `insertStepState` writes a 'pending' history
|
|
53
|
+
* row, then later transitions UPDATE that latest row in place rather
|
|
54
|
+
* than appending a new one — except for retry attempts which append.
|
|
55
|
+
*
|
|
56
|
+
* We mirror the same shape so `KyselyWorkflowRunService.getRunHistory`
|
|
57
|
+
* returns the same sequence the executor would have produced.
|
|
58
|
+
*/
|
|
59
|
+
private appendOrUpdateLatestHistory;
|
|
60
|
+
}
|