@pikku/mongodb 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/src/index.d.ts +12 -0
  3. package/dist/src/index.js +9 -0
  4. package/dist/src/mongodb-agent-run-service.d.ts +21 -0
  5. package/dist/src/mongodb-agent-run-service.js +127 -0
  6. package/dist/src/mongodb-ai-storage-service.d.ts +41 -0
  7. package/dist/src/mongodb-ai-storage-service.js +408 -0
  8. package/dist/src/mongodb-channel-store.d.ts +19 -0
  9. package/dist/src/mongodb-channel-store.js +52 -0
  10. package/dist/src/mongodb-deployment-service.d.ts +17 -0
  11. package/dist/src/mongodb-deployment-service.js +75 -0
  12. package/dist/src/mongodb-eventhub-store.d.ts +13 -0
  13. package/dist/src/mongodb-eventhub-store.js +37 -0
  14. package/dist/src/mongodb-secret-service.d.ts +30 -0
  15. package/dist/src/mongodb-secret-service.js +110 -0
  16. package/dist/src/mongodb-workflow-run-service.d.ts +36 -0
  17. package/dist/src/mongodb-workflow-run-service.js +146 -0
  18. package/dist/src/mongodb-workflow-service.d.ts +55 -0
  19. package/dist/src/mongodb-workflow-service.js +351 -0
  20. package/dist/src/pikku-mongodb.d.ts +12 -0
  21. package/dist/src/pikku-mongodb.js +37 -0
  22. package/dist/tsconfig.tsbuildinfo +1 -0
  23. package/package.json +29 -0
  24. package/run-tests.sh +53 -0
  25. package/src/index.ts +14 -0
  26. package/src/mongodb-agent-run-service.ts +206 -0
  27. package/src/mongodb-ai-storage-service.ts +576 -0
  28. package/src/mongodb-channel-store.ts +96 -0
  29. package/src/mongodb-deployment-service.ts +114 -0
  30. package/src/mongodb-eventhub-store.ts +52 -0
  31. package/src/mongodb-secret-service.ts +178 -0
  32. package/src/mongodb-services.test.ts +149 -0
  33. package/src/mongodb-workflow-run-service.ts +246 -0
  34. package/src/mongodb-workflow-service.ts +583 -0
  35. package/src/pikku-mongodb.ts +41 -0
  36. package/tsconfig.json +17 -0
@@ -0,0 +1,246 @@
1
+ import type {
2
+ WorkflowRun,
3
+ StepState,
4
+ WorkflowStatus,
5
+ WorkflowRunService,
6
+ } from '@pikku/core/workflow'
7
+ import type { Db, Collection } from 'mongodb'
8
+
9
+ interface WorkflowRunDoc {
10
+ _id: string
11
+ workflow: string
12
+ status: string
13
+ input: any
14
+ output: any | null
15
+ error: any | null
16
+ state: Record<string, unknown>
17
+ inline: boolean
18
+ graphHash: string | null
19
+ wire: any | null
20
+ createdAt: Date
21
+ updatedAt: Date
22
+ }
23
+
24
+ interface WorkflowStepDoc {
25
+ _id: string
26
+ workflowRunId: string
27
+ stepName: string
28
+ rpcName: string | null
29
+ data: any | null
30
+ status: string
31
+ result: any | null
32
+ error: any | null
33
+ branchTaken: string | null
34
+ retries: number | null
35
+ retryDelay: string | null
36
+ createdAt: Date
37
+ updatedAt: Date
38
+ }
39
+
40
+ interface WorkflowStepHistoryDoc {
41
+ _id: string
42
+ workflowStepId: string
43
+ status: string
44
+ result: any | null
45
+ error: any | null
46
+ createdAt: Date
47
+ runningAt: Date | null
48
+ scheduledAt: Date | null
49
+ succeededAt: Date | null
50
+ failedAt: Date | null
51
+ }
52
+
53
+ interface WorkflowVersionDoc {
54
+ workflowName: string
55
+ graphHash: string
56
+ graph: any
57
+ source: string
58
+ createdAt: Date
59
+ }
60
+
61
+ export class MongoDBWorkflowRunService implements WorkflowRunService {
62
+ private runs: Collection<WorkflowRunDoc>
63
+ private steps: Collection<WorkflowStepDoc>
64
+ private stepHistory: Collection<WorkflowStepHistoryDoc>
65
+ private versions: Collection<WorkflowVersionDoc>
66
+
67
+ constructor(db: Db) {
68
+ this.runs = db.collection<WorkflowRunDoc>('workflow_runs')
69
+ this.steps = db.collection<WorkflowStepDoc>('workflow_step')
70
+ this.stepHistory = db.collection<WorkflowStepHistoryDoc>(
71
+ 'workflow_step_history'
72
+ )
73
+ this.versions = db.collection<WorkflowVersionDoc>('workflow_versions')
74
+ }
75
+
76
+ async listRuns(options?: {
77
+ workflowName?: string
78
+ status?: string
79
+ limit?: number
80
+ offset?: number
81
+ }): Promise<WorkflowRun[]> {
82
+ const { workflowName, status, limit = 50, offset = 0 } = options ?? {}
83
+
84
+ const filter: Record<string, any> = {}
85
+ if (workflowName) filter.workflow = workflowName
86
+ if (status) filter.status = status
87
+
88
+ const result = await this.runs
89
+ .find(filter)
90
+ .sort({ createdAt: -1 })
91
+ .skip(offset)
92
+ .limit(limit)
93
+ .toArray()
94
+
95
+ return result.map((row) => this.mapRunRow(row))
96
+ }
97
+
98
+ async getRun(id: string): Promise<WorkflowRun | null> {
99
+ const row = await this.runs.findOne({ _id: id })
100
+ if (!row) return null
101
+ return this.mapRunRow(row)
102
+ }
103
+
104
+ async getRunSteps(
105
+ runId: string
106
+ ): Promise<
107
+ Array<StepState & { stepName: string; rpcName?: string; data?: any }>
108
+ > {
109
+ const result = await this.steps
110
+ .find({ workflowRunId: runId })
111
+ .sort({ createdAt: 1 })
112
+ .toArray()
113
+
114
+ const stepIds = result.map((r) => r._id)
115
+ const historyCounts = await this.stepHistory
116
+ .aggregate<{
117
+ _id: string
118
+ count: number
119
+ }>([
120
+ { $match: { workflowStepId: { $in: stepIds } } },
121
+ { $group: { _id: '$workflowStepId', count: { $sum: 1 } } },
122
+ ])
123
+ .toArray()
124
+
125
+ const countMap = new Map(historyCounts.map((h) => [h._id, h.count]))
126
+
127
+ return result.map((row) => ({
128
+ stepId: row._id,
129
+ stepName: row.stepName,
130
+ rpcName: row.rpcName ?? undefined,
131
+ data: row.data ?? undefined,
132
+ status: row.status as StepState['status'],
133
+ result: row.result ?? undefined,
134
+ error: row.error ?? undefined,
135
+ attemptCount: countMap.get(row._id) ?? 1,
136
+ retries: row.retries != null ? Number(row.retries) : undefined,
137
+ retryDelay: row.retryDelay ?? undefined,
138
+ createdAt: new Date(row.createdAt),
139
+ updatedAt: new Date(row.updatedAt),
140
+ }))
141
+ }
142
+
143
+ async getRunHistory(
144
+ runId: string
145
+ ): Promise<Array<StepState & { stepName: string }>> {
146
+ const steps = await this.steps.find({ workflowRunId: runId }).toArray()
147
+
148
+ const stepMap = new Map(steps.map((s) => [s._id, s]))
149
+ const stepIds = steps.map((s) => s._id)
150
+
151
+ const history = await this.stepHistory
152
+ .find({ workflowStepId: { $in: stepIds } })
153
+ .sort({ createdAt: 1 })
154
+ .toArray()
155
+
156
+ let attemptCounters: Record<string, number> = {}
157
+ return history.map((row) => {
158
+ const stepId = row.workflowStepId
159
+ const step = stepMap.get(stepId)!
160
+ attemptCounters[stepId] = (attemptCounters[stepId] ?? 0) + 1
161
+
162
+ return {
163
+ stepId,
164
+ stepName: step.stepName,
165
+ status: row.status as StepState['status'],
166
+ result: row.result ?? undefined,
167
+ error: row.error ?? undefined,
168
+ attemptCount: attemptCounters[stepId]!,
169
+ retries: step.retries != null ? Number(step.retries) : undefined,
170
+ retryDelay: step.retryDelay ?? undefined,
171
+ createdAt: new Date(row.createdAt),
172
+ updatedAt: new Date(row.createdAt),
173
+ runningAt: row.runningAt ? new Date(row.runningAt) : undefined,
174
+ scheduledAt: row.scheduledAt ? new Date(row.scheduledAt) : undefined,
175
+ succeededAt: row.succeededAt ? new Date(row.succeededAt) : undefined,
176
+ failedAt: row.failedAt ? new Date(row.failedAt) : undefined,
177
+ }
178
+ })
179
+ }
180
+
181
+ async getDistinctWorkflowNames(): Promise<string[]> {
182
+ const result = await this.runs.distinct('workflow')
183
+ return result.sort()
184
+ }
185
+
186
+ async getWorkflowVersion(
187
+ name: string,
188
+ graphHash: string
189
+ ): Promise<{ graph: any; source: string } | null> {
190
+ const row = await this.versions.findOne({
191
+ workflowName: name,
192
+ graphHash,
193
+ })
194
+
195
+ if (!row) return null
196
+ return {
197
+ graph: row.graph,
198
+ source: row.source,
199
+ }
200
+ }
201
+
202
+ async getAIGeneratedWorkflows(
203
+ agentName?: string
204
+ ): Promise<Array<{ workflowName: string; graphHash: string; graph: any }>> {
205
+ const filter: Record<string, any> = { source: 'ai-agent', status: 'active' }
206
+ if (agentName) {
207
+ const escaped = agentName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
208
+ filter.workflowName = { $regex: `^ai:${escaped}:` }
209
+ }
210
+ const rows = await this.versions.find(filter).toArray()
211
+ return rows.map((row) => ({
212
+ workflowName: row.workflowName,
213
+ graphHash: row.graphHash,
214
+ graph: row.graph,
215
+ }))
216
+ }
217
+
218
+ async deleteRun(id: string): Promise<boolean> {
219
+ const steps = await this.steps.find({ workflowRunId: id }).toArray()
220
+ const stepIds = steps.map((s) => s._id)
221
+
222
+ if (stepIds.length > 0) {
223
+ await this.stepHistory.deleteMany({ workflowStepId: { $in: stepIds } })
224
+ await this.steps.deleteMany({ workflowRunId: id })
225
+ }
226
+
227
+ const result = await this.runs.deleteOne({ _id: id })
228
+ return result.deletedCount > 0
229
+ }
230
+
231
+ private mapRunRow(row: WorkflowRunDoc): WorkflowRun {
232
+ return {
233
+ id: row._id,
234
+ workflow: row.workflow,
235
+ status: row.status as WorkflowStatus,
236
+ input: row.input,
237
+ output: row.output ?? undefined,
238
+ error: row.error ?? undefined,
239
+ inline: row.inline,
240
+ graphHash: row.graphHash ?? undefined,
241
+ wire: row.wire ?? { type: 'unknown' },
242
+ createdAt: new Date(row.createdAt),
243
+ updatedAt: new Date(row.updatedAt),
244
+ }
245
+ }
246
+ }