codepiper 0.1.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.
Files changed (149) hide show
  1. package/.env.example +28 -0
  2. package/CHANGELOG.md +10 -0
  3. package/LEGAL_NOTICE.md +39 -0
  4. package/LICENSE +21 -0
  5. package/README.md +524 -0
  6. package/package.json +90 -0
  7. package/packages/cli/package.json +13 -0
  8. package/packages/cli/src/commands/analytics.ts +157 -0
  9. package/packages/cli/src/commands/attach.ts +299 -0
  10. package/packages/cli/src/commands/audit.ts +50 -0
  11. package/packages/cli/src/commands/auth.ts +261 -0
  12. package/packages/cli/src/commands/daemon.ts +162 -0
  13. package/packages/cli/src/commands/doctor.ts +303 -0
  14. package/packages/cli/src/commands/env-set.ts +162 -0
  15. package/packages/cli/src/commands/hook-forward.ts +268 -0
  16. package/packages/cli/src/commands/keys.ts +77 -0
  17. package/packages/cli/src/commands/kill.ts +19 -0
  18. package/packages/cli/src/commands/logs.ts +419 -0
  19. package/packages/cli/src/commands/model.ts +172 -0
  20. package/packages/cli/src/commands/policy-set.ts +185 -0
  21. package/packages/cli/src/commands/policy.ts +227 -0
  22. package/packages/cli/src/commands/providers.ts +114 -0
  23. package/packages/cli/src/commands/resize.ts +34 -0
  24. package/packages/cli/src/commands/send.ts +184 -0
  25. package/packages/cli/src/commands/sessions.ts +202 -0
  26. package/packages/cli/src/commands/slash.ts +92 -0
  27. package/packages/cli/src/commands/start.ts +243 -0
  28. package/packages/cli/src/commands/stop.ts +19 -0
  29. package/packages/cli/src/commands/tail.ts +137 -0
  30. package/packages/cli/src/commands/workflow.ts +786 -0
  31. package/packages/cli/src/commands/workspace.ts +127 -0
  32. package/packages/cli/src/lib/api.ts +78 -0
  33. package/packages/cli/src/lib/args.ts +72 -0
  34. package/packages/cli/src/lib/format.ts +93 -0
  35. package/packages/cli/src/main.ts +563 -0
  36. package/packages/core/package.json +7 -0
  37. package/packages/core/src/config.ts +30 -0
  38. package/packages/core/src/errors.ts +38 -0
  39. package/packages/core/src/eventBus.ts +56 -0
  40. package/packages/core/src/eventBusAdapter.ts +143 -0
  41. package/packages/core/src/index.ts +10 -0
  42. package/packages/core/src/sqliteEventBus.ts +336 -0
  43. package/packages/core/src/types.ts +63 -0
  44. package/packages/daemon/package.json +11 -0
  45. package/packages/daemon/src/api/analyticsRoutes.ts +343 -0
  46. package/packages/daemon/src/api/authRoutes.ts +344 -0
  47. package/packages/daemon/src/api/bodyLimit.ts +133 -0
  48. package/packages/daemon/src/api/envSetRoutes.ts +170 -0
  49. package/packages/daemon/src/api/gitRoutes.ts +409 -0
  50. package/packages/daemon/src/api/hooks.ts +588 -0
  51. package/packages/daemon/src/api/inputPolicy.ts +249 -0
  52. package/packages/daemon/src/api/notificationRoutes.ts +532 -0
  53. package/packages/daemon/src/api/policyRoutes.ts +234 -0
  54. package/packages/daemon/src/api/policySetRoutes.ts +445 -0
  55. package/packages/daemon/src/api/routeUtils.ts +28 -0
  56. package/packages/daemon/src/api/routes.ts +1004 -0
  57. package/packages/daemon/src/api/server.ts +1388 -0
  58. package/packages/daemon/src/api/settingsRoutes.ts +367 -0
  59. package/packages/daemon/src/api/sqliteErrors.ts +47 -0
  60. package/packages/daemon/src/api/stt.ts +143 -0
  61. package/packages/daemon/src/api/terminalRoutes.ts +200 -0
  62. package/packages/daemon/src/api/validation.ts +287 -0
  63. package/packages/daemon/src/api/validationRoutes.ts +174 -0
  64. package/packages/daemon/src/api/workflowRoutes.ts +567 -0
  65. package/packages/daemon/src/api/workspaceRoutes.ts +151 -0
  66. package/packages/daemon/src/api/ws.ts +1588 -0
  67. package/packages/daemon/src/auth/apiRateLimiter.ts +73 -0
  68. package/packages/daemon/src/auth/authMiddleware.ts +305 -0
  69. package/packages/daemon/src/auth/authService.ts +496 -0
  70. package/packages/daemon/src/auth/rateLimiter.ts +137 -0
  71. package/packages/daemon/src/config/pricing.ts +79 -0
  72. package/packages/daemon/src/crypto/encryption.ts +196 -0
  73. package/packages/daemon/src/db/db.ts +2745 -0
  74. package/packages/daemon/src/db/index.ts +16 -0
  75. package/packages/daemon/src/db/migrations.ts +182 -0
  76. package/packages/daemon/src/db/policyDb.ts +349 -0
  77. package/packages/daemon/src/db/schema.sql +408 -0
  78. package/packages/daemon/src/db/workflowDb.ts +464 -0
  79. package/packages/daemon/src/git/gitUtils.ts +544 -0
  80. package/packages/daemon/src/index.ts +6 -0
  81. package/packages/daemon/src/main.ts +525 -0
  82. package/packages/daemon/src/notifications/pushNotifier.ts +369 -0
  83. package/packages/daemon/src/providers/codexAppServerScaffold.ts +49 -0
  84. package/packages/daemon/src/providers/registry.ts +111 -0
  85. package/packages/daemon/src/providers/types.ts +82 -0
  86. package/packages/daemon/src/sessions/auditLogger.ts +103 -0
  87. package/packages/daemon/src/sessions/policyEngine.ts +165 -0
  88. package/packages/daemon/src/sessions/policyMatcher.ts +114 -0
  89. package/packages/daemon/src/sessions/policyTypes.ts +94 -0
  90. package/packages/daemon/src/sessions/ptyProcess.ts +141 -0
  91. package/packages/daemon/src/sessions/sessionManager.ts +1770 -0
  92. package/packages/daemon/src/sessions/tmuxSession.ts +1073 -0
  93. package/packages/daemon/src/sessions/transcriptManager.ts +110 -0
  94. package/packages/daemon/src/sessions/transcriptParser.ts +149 -0
  95. package/packages/daemon/src/sessions/transcriptTailer.ts +214 -0
  96. package/packages/daemon/src/tracking/tokenTracker.ts +168 -0
  97. package/packages/daemon/src/workflows/contextManager.ts +83 -0
  98. package/packages/daemon/src/workflows/index.ts +31 -0
  99. package/packages/daemon/src/workflows/resultExtractor.ts +118 -0
  100. package/packages/daemon/src/workflows/waitConditionPoller.ts +131 -0
  101. package/packages/daemon/src/workflows/workflowParser.ts +217 -0
  102. package/packages/daemon/src/workflows/workflowRunner.ts +969 -0
  103. package/packages/daemon/src/workflows/workflowTypes.ts +188 -0
  104. package/packages/daemon/src/workflows/workflowValidator.ts +533 -0
  105. package/packages/providers/claude-code/package.json +11 -0
  106. package/packages/providers/claude-code/src/index.ts +7 -0
  107. package/packages/providers/claude-code/src/overlaySettings.ts +198 -0
  108. package/packages/providers/claude-code/src/provider.ts +311 -0
  109. package/packages/web/dist/android-chrome-192x192.png +0 -0
  110. package/packages/web/dist/android-chrome-512x512.png +0 -0
  111. package/packages/web/dist/apple-touch-icon.png +0 -0
  112. package/packages/web/dist/assets/AnalyticsPage-BIopKWRf.js +17 -0
  113. package/packages/web/dist/assets/PoliciesPage-CjdLN3dl.js +11 -0
  114. package/packages/web/dist/assets/SessionDetailPage-BtSA0V0M.js +179 -0
  115. package/packages/web/dist/assets/SettingsPage-Dbbz4Ca5.js +37 -0
  116. package/packages/web/dist/assets/WorkflowsPage-Dv6f3GgU.js +1 -0
  117. package/packages/web/dist/assets/chart-vendor-DlOHLaCG.js +49 -0
  118. package/packages/web/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  119. package/packages/web/dist/assets/css.worker-BvV5MPou.js +93 -0
  120. package/packages/web/dist/assets/editor.worker-CKy7Pnvo.js +26 -0
  121. package/packages/web/dist/assets/html.worker-BLJhxQJQ.js +470 -0
  122. package/packages/web/dist/assets/index-BbdhRfr2.css +1 -0
  123. package/packages/web/dist/assets/index-hgphORiw.js +204 -0
  124. package/packages/web/dist/assets/json.worker-usMZ-FED.js +58 -0
  125. package/packages/web/dist/assets/monaco-core-B_19GPAS.css +1 -0
  126. package/packages/web/dist/assets/monaco-core-DQ5Mk8AK.js +1234 -0
  127. package/packages/web/dist/assets/monaco-react-DfZNWvtW.js +11 -0
  128. package/packages/web/dist/assets/monacoSetup-DvBj52bT.js +1 -0
  129. package/packages/web/dist/assets/pencil-Dbczxz59.js +11 -0
  130. package/packages/web/dist/assets/react-vendor-B5MgMUHH.js +136 -0
  131. package/packages/web/dist/assets/refresh-cw-B0MGsYPL.js +6 -0
  132. package/packages/web/dist/assets/tabs-C8LsWiR5.js +1 -0
  133. package/packages/web/dist/assets/terminal-vendor-Cs8KPbV3.js +9 -0
  134. package/packages/web/dist/assets/terminal-vendor-LcAfv9l9.css +32 -0
  135. package/packages/web/dist/assets/trash-2-Btlg0d4l.js +6 -0
  136. package/packages/web/dist/assets/ts.worker-DGHjMaqB.js +67731 -0
  137. package/packages/web/dist/favicon.ico +0 -0
  138. package/packages/web/dist/icon.svg +1 -0
  139. package/packages/web/dist/index.html +29 -0
  140. package/packages/web/dist/manifest.json +29 -0
  141. package/packages/web/dist/og-image.png +0 -0
  142. package/packages/web/dist/originals/android-chrome-192x192.png +0 -0
  143. package/packages/web/dist/originals/android-chrome-512x512.png +0 -0
  144. package/packages/web/dist/originals/apple-touch-icon.png +0 -0
  145. package/packages/web/dist/originals/favicon.ico +0 -0
  146. package/packages/web/dist/piper.svg +1 -0
  147. package/packages/web/dist/sounds/codepiper-soft-chime.wav +0 -0
  148. package/packages/web/dist/sw.js +257 -0
  149. package/scripts/postinstall-link-workspaces.mjs +58 -0
@@ -0,0 +1,464 @@
1
+ /**
2
+ * Workflow database operations
3
+ */
4
+
5
+ import type { Database } from "./db";
6
+
7
+ /**
8
+ * Workflow execution status
9
+ */
10
+ export type WorkflowExecutionStatus = "pending" | "running" | "completed" | "failed" | "cancelled";
11
+
12
+ /**
13
+ * Workflow step status
14
+ */
15
+ export type WorkflowStepStatus = "pending" | "running" | "completed" | "failed" | "skipped";
16
+
17
+ /**
18
+ * Workflow record
19
+ */
20
+ export interface Workflow {
21
+ id: string;
22
+ name: string;
23
+ description?: string;
24
+ definition: any;
25
+ createdAt: Date;
26
+ updatedAt: Date;
27
+ }
28
+
29
+ /**
30
+ * Workflow execution record
31
+ */
32
+ export interface WorkflowExecution {
33
+ id: string;
34
+ workflowId: string;
35
+ status: WorkflowExecutionStatus;
36
+ startedAt: Date;
37
+ completedAt?: Date;
38
+ errorMessage?: string;
39
+ context?: any;
40
+ }
41
+
42
+ /**
43
+ * Workflow step record
44
+ */
45
+ export interface WorkflowStep {
46
+ id: number;
47
+ executionId: string;
48
+ stepName: string;
49
+ sessionId?: string;
50
+ status: WorkflowStepStatus;
51
+ startedAt?: Date;
52
+ completedAt?: Date;
53
+ result?: any;
54
+ errorMessage?: string;
55
+ }
56
+
57
+ /**
58
+ * Workflow creation parameters
59
+ */
60
+ export interface CreateWorkflowParams {
61
+ id: string;
62
+ name: string;
63
+ description?: string;
64
+ definition: any;
65
+ }
66
+
67
+ /**
68
+ * Workflow update parameters
69
+ */
70
+ export interface UpdateWorkflowParams {
71
+ name?: string;
72
+ description?: string;
73
+ definition?: any;
74
+ }
75
+
76
+ /**
77
+ * Workflow execution creation parameters
78
+ */
79
+ export interface CreateExecutionParams {
80
+ id: string;
81
+ workflowId: string;
82
+ status: WorkflowExecutionStatus;
83
+ context?: any;
84
+ }
85
+
86
+ /**
87
+ * Workflow execution update parameters
88
+ */
89
+ export interface UpdateExecutionParams {
90
+ status?: WorkflowExecutionStatus;
91
+ completedAt?: Date;
92
+ errorMessage?: string;
93
+ context?: any;
94
+ }
95
+
96
+ /**
97
+ * Workflow execution query options
98
+ */
99
+ export interface ListExecutionsOptions {
100
+ status?: WorkflowExecutionStatus;
101
+ limit?: number;
102
+ }
103
+
104
+ /**
105
+ * Workflow step creation parameters
106
+ */
107
+ export interface CreateStepParams {
108
+ executionId: string;
109
+ stepName: string;
110
+ sessionId?: string;
111
+ status: WorkflowStepStatus;
112
+ }
113
+
114
+ /**
115
+ * Workflow step update parameters
116
+ */
117
+ export interface UpdateStepParams {
118
+ sessionId?: string;
119
+ status?: WorkflowStepStatus;
120
+ startedAt?: Date;
121
+ completedAt?: Date;
122
+ result?: any;
123
+ errorMessage?: string;
124
+ }
125
+
126
+ /**
127
+ * Workflow step query options
128
+ */
129
+ export interface GetStepsOptions {
130
+ status?: WorkflowStepStatus;
131
+ }
132
+
133
+ /**
134
+ * Workflow database interface
135
+ */
136
+ export interface WorkflowDb {
137
+ // Workflow operations
138
+ createWorkflow(params: CreateWorkflowParams): void;
139
+ getWorkflow(id: string): Workflow | undefined;
140
+ updateWorkflow(id: string, params: UpdateWorkflowParams): void;
141
+ deleteWorkflow(id: string): void;
142
+ listWorkflows(): Workflow[];
143
+
144
+ // Execution operations
145
+ createExecution(params: CreateExecutionParams): void;
146
+ getExecution(id: string): WorkflowExecution | undefined;
147
+ updateExecution(id: string, params: UpdateExecutionParams): void;
148
+ listExecutions(workflowId: string, options?: ListExecutionsOptions): WorkflowExecution[];
149
+
150
+ // Step operations
151
+ createStep(params: CreateStepParams): number;
152
+ updateStep(id: number, params: UpdateStepParams): void;
153
+ getSteps(executionId: string, options?: GetStepsOptions): WorkflowStep[];
154
+ }
155
+
156
+ /**
157
+ * Create workflow database operations
158
+ */
159
+ export function createWorkflowDb(db: Database): WorkflowDb {
160
+ // Get access to underlying Bun database for raw queries
161
+ const bunDb = (db as any).db;
162
+
163
+ return {
164
+ /**
165
+ * Create a new workflow
166
+ */
167
+ createWorkflow(params: CreateWorkflowParams): void {
168
+ const now = Date.now();
169
+ const stmt = bunDb.prepare(`
170
+ INSERT INTO workflows (
171
+ id, name, description, definition_json, created_at, updated_at
172
+ ) VALUES (?, ?, ?, ?, ?, ?)
173
+ `);
174
+
175
+ stmt.run(
176
+ params.id,
177
+ params.name,
178
+ params.description ?? null,
179
+ JSON.stringify(params.definition),
180
+ now,
181
+ now
182
+ );
183
+ },
184
+
185
+ /**
186
+ * Get workflow by ID
187
+ */
188
+ getWorkflow(id: string): Workflow | undefined {
189
+ const stmt = bunDb.prepare("SELECT * FROM workflows WHERE id = ?");
190
+ const row = stmt.get(id) as any;
191
+
192
+ if (!row) return undefined;
193
+
194
+ return mapRowToWorkflow(row);
195
+ },
196
+
197
+ /**
198
+ * Update workflow fields
199
+ */
200
+ updateWorkflow(id: string, params: UpdateWorkflowParams): void {
201
+ const updates: string[] = [];
202
+ const values: unknown[] = [];
203
+
204
+ if (params.name !== undefined) {
205
+ updates.push("name = ?");
206
+ values.push(params.name);
207
+ }
208
+ if (params.description !== undefined) {
209
+ updates.push("description = ?");
210
+ values.push(params.description);
211
+ }
212
+ if (params.definition !== undefined) {
213
+ updates.push("definition_json = ?");
214
+ values.push(JSON.stringify(params.definition));
215
+ }
216
+
217
+ // Always update updated_at
218
+ updates.push("updated_at = ?");
219
+ values.push(Date.now());
220
+
221
+ values.push(id);
222
+
223
+ const sql = `UPDATE workflows SET ${updates.join(", ")} WHERE id = ?`;
224
+ const stmt = bunDb.prepare(sql);
225
+ stmt.run(...values);
226
+ },
227
+
228
+ /**
229
+ * Delete workflow
230
+ */
231
+ deleteWorkflow(id: string): void {
232
+ const stmt = bunDb.prepare("DELETE FROM workflows WHERE id = ?");
233
+ stmt.run(id);
234
+ },
235
+
236
+ /**
237
+ * List all workflows
238
+ */
239
+ listWorkflows(): Workflow[] {
240
+ const stmt = bunDb.prepare("SELECT * FROM workflows ORDER BY created_at DESC");
241
+ const rows = stmt.all() as any[];
242
+
243
+ return rows.map((row) => mapRowToWorkflow(row));
244
+ },
245
+
246
+ /**
247
+ * Create a new execution
248
+ */
249
+ createExecution(params: CreateExecutionParams): void {
250
+ const now = Date.now();
251
+ const stmt = bunDb.prepare(`
252
+ INSERT INTO workflow_executions (
253
+ id, workflow_id, status, started_at, context_json
254
+ ) VALUES (?, ?, ?, ?, ?)
255
+ `);
256
+
257
+ stmt.run(
258
+ params.id,
259
+ params.workflowId,
260
+ params.status,
261
+ now,
262
+ params.context ? JSON.stringify(params.context) : null
263
+ );
264
+ },
265
+
266
+ /**
267
+ * Get execution by ID
268
+ */
269
+ getExecution(id: string): WorkflowExecution | undefined {
270
+ const stmt = bunDb.prepare("SELECT * FROM workflow_executions WHERE id = ?");
271
+ const row = stmt.get(id) as any;
272
+
273
+ if (!row) return undefined;
274
+
275
+ return mapRowToExecution(row);
276
+ },
277
+
278
+ /**
279
+ * Update execution fields
280
+ */
281
+ updateExecution(id: string, params: UpdateExecutionParams): void {
282
+ const updates: string[] = [];
283
+ const values: unknown[] = [];
284
+
285
+ if (params.status !== undefined) {
286
+ updates.push("status = ?");
287
+ values.push(params.status);
288
+ }
289
+ if (params.completedAt !== undefined) {
290
+ updates.push("completed_at = ?");
291
+ values.push(params.completedAt.getTime());
292
+ }
293
+ if (params.errorMessage !== undefined) {
294
+ updates.push("error_message = ?");
295
+ values.push(params.errorMessage);
296
+ }
297
+ if (params.context !== undefined) {
298
+ updates.push("context_json = ?");
299
+ values.push(JSON.stringify(params.context));
300
+ }
301
+
302
+ if (updates.length === 0) {
303
+ return;
304
+ }
305
+
306
+ values.push(id);
307
+
308
+ const sql = `UPDATE workflow_executions SET ${updates.join(", ")} WHERE id = ?`;
309
+ const stmt = bunDb.prepare(sql);
310
+ stmt.run(...values);
311
+ },
312
+
313
+ /**
314
+ * List executions for a workflow
315
+ */
316
+ listExecutions(workflowId: string, options: ListExecutionsOptions = {}): WorkflowExecution[] {
317
+ let sql = "SELECT * FROM workflow_executions WHERE workflow_id = ?";
318
+ const values: unknown[] = [workflowId];
319
+
320
+ if (options.status) {
321
+ sql += " AND status = ?";
322
+ values.push(options.status);
323
+ }
324
+
325
+ sql += " ORDER BY started_at DESC";
326
+
327
+ if (options.limit) {
328
+ sql += " LIMIT ?";
329
+ values.push(options.limit);
330
+ }
331
+
332
+ const stmt = bunDb.prepare(sql);
333
+ const rows = stmt.all(...values) as any[];
334
+
335
+ return rows.map((row) => mapRowToExecution(row));
336
+ },
337
+
338
+ /**
339
+ * Create a new step
340
+ */
341
+ createStep(params: CreateStepParams): number {
342
+ const stmt = bunDb.prepare(`
343
+ INSERT INTO workflow_steps (
344
+ execution_id, step_name, session_id, status
345
+ ) VALUES (?, ?, ?, ?)
346
+ `);
347
+
348
+ stmt.run(params.executionId, params.stepName, params.sessionId ?? null, params.status);
349
+
350
+ // Get last inserted row id
351
+ const result = bunDb.query("SELECT last_insert_rowid() as id").get() as { id: number };
352
+ return result.id;
353
+ },
354
+
355
+ /**
356
+ * Update step fields
357
+ */
358
+ updateStep(id: number, params: UpdateStepParams): void {
359
+ const updates: string[] = [];
360
+ const values: unknown[] = [];
361
+
362
+ if (params.sessionId !== undefined) {
363
+ updates.push("session_id = ?");
364
+ values.push(params.sessionId);
365
+ }
366
+ if (params.status !== undefined) {
367
+ updates.push("status = ?");
368
+ values.push(params.status);
369
+ }
370
+ if (params.startedAt !== undefined) {
371
+ updates.push("started_at = ?");
372
+ values.push(params.startedAt.getTime());
373
+ }
374
+ if (params.completedAt !== undefined) {
375
+ updates.push("completed_at = ?");
376
+ values.push(params.completedAt.getTime());
377
+ }
378
+ if (params.result !== undefined) {
379
+ updates.push("result_json = ?");
380
+ values.push(JSON.stringify(params.result));
381
+ }
382
+ if (params.errorMessage !== undefined) {
383
+ updates.push("error_message = ?");
384
+ values.push(params.errorMessage);
385
+ }
386
+
387
+ if (updates.length === 0) {
388
+ return;
389
+ }
390
+
391
+ values.push(id);
392
+
393
+ const sql = `UPDATE workflow_steps SET ${updates.join(", ")} WHERE id = ?`;
394
+ const stmt = bunDb.prepare(sql);
395
+ stmt.run(...values);
396
+ },
397
+
398
+ /**
399
+ * Get steps for an execution
400
+ */
401
+ getSteps(executionId: string, options: GetStepsOptions = {}): WorkflowStep[] {
402
+ let sql = "SELECT * FROM workflow_steps WHERE execution_id = ?";
403
+ const values: unknown[] = [executionId];
404
+
405
+ if (options.status) {
406
+ sql += " AND status = ?";
407
+ values.push(options.status);
408
+ }
409
+
410
+ sql += " ORDER BY id ASC";
411
+
412
+ const stmt = bunDb.prepare(sql);
413
+ const rows = stmt.all(...values) as any[];
414
+
415
+ return rows.map((row) => mapRowToStep(row));
416
+ },
417
+ };
418
+ }
419
+
420
+ /**
421
+ * Map database row to Workflow
422
+ */
423
+ function mapRowToWorkflow(row: any): Workflow {
424
+ return {
425
+ id: row.id,
426
+ name: row.name,
427
+ description: row.description ?? undefined,
428
+ definition: JSON.parse(row.definition_json),
429
+ createdAt: new Date(row.created_at),
430
+ updatedAt: new Date(row.updated_at),
431
+ };
432
+ }
433
+
434
+ /**
435
+ * Map database row to WorkflowExecution
436
+ */
437
+ function mapRowToExecution(row: any): WorkflowExecution {
438
+ return {
439
+ id: row.id,
440
+ workflowId: row.workflow_id,
441
+ status: row.status as WorkflowExecutionStatus,
442
+ startedAt: new Date(row.started_at),
443
+ completedAt: row.completed_at ? new Date(row.completed_at) : undefined,
444
+ errorMessage: row.error_message ?? undefined,
445
+ context: row.context_json ? JSON.parse(row.context_json) : undefined,
446
+ };
447
+ }
448
+
449
+ /**
450
+ * Map database row to WorkflowStep
451
+ */
452
+ function mapRowToStep(row: any): WorkflowStep {
453
+ return {
454
+ id: row.id,
455
+ executionId: row.execution_id,
456
+ stepName: row.step_name,
457
+ sessionId: row.session_id ?? undefined,
458
+ status: row.status as WorkflowStepStatus,
459
+ startedAt: row.started_at ? new Date(row.started_at) : undefined,
460
+ completedAt: row.completed_at ? new Date(row.completed_at) : undefined,
461
+ result: row.result_json ? JSON.parse(row.result_json) : undefined,
462
+ errorMessage: row.error_message ?? undefined,
463
+ };
464
+ }