@codemation/host 1.0.0 → 1.0.2

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 (70) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/{AppConfigFactory-BPp02HMv.js → AppConfigFactory-C4OXGOs2.js} +16 -7
  3. package/dist/{AppConfigFactory-BPp02HMv.js.map → AppConfigFactory-C4OXGOs2.js.map} +1 -1
  4. package/dist/{AppConfigFactory-PFmDg5Sg.d.ts → AppConfigFactory-D3k-R3Ch.d.ts} +338 -6
  5. package/dist/{AppContainerFactory-Cr3JeVmg.js → AppContainerFactory-CKRDz8kQ.js} +409 -92
  6. package/dist/AppContainerFactory-CKRDz8kQ.js.map +1 -0
  7. package/dist/{CodemationAppContext-DP_-56c6.d.ts → CodemationAppContext-YgJRUHWF.d.ts} +2 -2
  8. package/dist/{CodemationAuthoring.types-zJ2t73Bn.d.ts → CodemationAuthoring.types-lUdxXYq-.d.ts} +7 -6
  9. package/dist/{CodemationConfigNormalizer-B8RGUwAe.d.ts → CodemationConfigNormalizer-BWBp7mFB.d.ts} +2 -2
  10. package/dist/{CodemationConsumerConfigLoader-C_QVwcI3.d.ts → CodemationConsumerConfigLoader-Bka3v6lh.d.ts} +2 -2
  11. package/dist/{CodemationPluginListMerger-Bgn1CIX9.d.ts → CodemationPluginListMerger-Oz-GAkxz.d.ts} +17 -5
  12. package/dist/{CredentialServices-95DPogx-.d.ts → CredentialServices-CKXPg5xu.d.ts} +3 -3
  13. package/dist/{PublicFrontendBootstrapFactory-C_iLgPV-.d.ts → PublicFrontendBootstrapFactory-DkQoSYDo.d.ts} +2 -2
  14. package/dist/authoring.d.ts +3 -3
  15. package/dist/consumer.d.ts +4 -4
  16. package/dist/credentials.d.ts +3 -3
  17. package/dist/devServerSidecar.d.ts +1 -1
  18. package/dist/{index-W4eSjdCM.d.ts → index-BxIc_L4D.d.ts} +233 -151
  19. package/dist/index.d.ts +11 -11
  20. package/dist/index.js +4 -4
  21. package/dist/nextServer.d.ts +7 -7
  22. package/dist/nextServer.js +2 -2
  23. package/dist/{persistenceServer-_pqP_0nw.d.ts → persistenceServer-BLG7_6B5.d.ts} +2 -2
  24. package/dist/{persistenceServer-CA0_q0D7.js → persistenceServer-KyHL0u01.js} +2 -2
  25. package/dist/{persistenceServer-CA0_q0D7.js.map → persistenceServer-KyHL0u01.js.map} +1 -1
  26. package/dist/persistenceServer.d.ts +5 -5
  27. package/dist/persistenceServer.js +2 -2
  28. package/dist/{server-Q5uwa6iR.d.ts → server-B0SD6Nvk.d.ts} +5 -5
  29. package/dist/{server-BE4PLhcb.js → server-CMUVhYIc.js} +3 -3
  30. package/dist/{server-BE4PLhcb.js.map → server-CMUVhYIc.js.map} +1 -1
  31. package/dist/server.d.ts +8 -8
  32. package/dist/server.js +4 -4
  33. package/package.json +5 -5
  34. package/prisma/migrations/20260430120000_telemetry_iteration_identity/migration.sql +17 -0
  35. package/prisma/migrations/20260430130000_execution_instance_iteration_identity/migration.sql +11 -0
  36. package/prisma/migrations.sqlite/20260430120000_telemetry_iteration_identity/migration.sql +14 -0
  37. package/prisma/migrations.sqlite/20260430130000_execution_instance_iteration_identity/migration.sql +10 -0
  38. package/prisma/schema.postgresql.prisma +12 -0
  39. package/prisma/schema.sqlite.prisma +12 -0
  40. package/src/application/contracts/IterationCostContracts.ts +11 -0
  41. package/src/application/queries/GetIterationCostQuery.ts +14 -0
  42. package/src/application/queries/GetIterationCostQueryHandler.ts +92 -0
  43. package/src/application/queries/GetWorkflowRunDetailQueryHandler.ts +44 -2
  44. package/src/application/queries/RunIterationProjectionFactory.ts +123 -0
  45. package/src/application/queries/WorkflowQueryHandlers.ts +1 -0
  46. package/src/application/telemetry/OtelExecutionTelemetry.types.ts +3 -0
  47. package/src/application/telemetry/RunEventBusTelemetryReporter.ts +7 -0
  48. package/src/application/telemetry/StoredNodeExecutionTelemetry.ts +14 -0
  49. package/src/application/telemetry/StoredTelemetrySpanScope.ts +90 -1
  50. package/src/bootstrap/AppContainerFactory.ts +5 -0
  51. package/src/domain/telemetry/TelemetryContracts.ts +12 -0
  52. package/src/infrastructure/persistence/InMemoryTelemetryMetricPointStore.ts +3 -0
  53. package/src/infrastructure/persistence/InMemoryTelemetrySpanStore.ts +3 -0
  54. package/src/infrastructure/persistence/InMemoryWorkflowRunRepository.ts +23 -0
  55. package/src/infrastructure/persistence/PrismaTelemetryMetricPointStore.ts +9 -0
  56. package/src/infrastructure/persistence/PrismaTelemetrySpanStore.ts +6 -0
  57. package/src/infrastructure/persistence/PrismaWorkflowRunRepository.ts +12 -0
  58. package/src/infrastructure/persistence/generated/prisma-postgresql-client/edge.js +15 -6
  59. package/src/infrastructure/persistence/generated/prisma-postgresql-client/index-browser.js +11 -2
  60. package/src/infrastructure/persistence/generated/prisma-postgresql-client/index.d.ts +343 -5
  61. package/src/infrastructure/persistence/generated/prisma-postgresql-client/index.js +15 -6
  62. package/src/infrastructure/persistence/generated/prisma-postgresql-client/package.json +1 -1
  63. package/src/infrastructure/persistence/generated/prisma-postgresql-client/schema.prisma +12 -0
  64. package/src/infrastructure/persistence/generated/prisma-sqlite-client/edge.js +15 -6
  65. package/src/infrastructure/persistence/generated/prisma-sqlite-client/index-browser.js +11 -2
  66. package/src/infrastructure/persistence/generated/prisma-sqlite-client/index.d.ts +343 -5
  67. package/src/infrastructure/persistence/generated/prisma-sqlite-client/index.js +15 -6
  68. package/src/infrastructure/persistence/generated/prisma-sqlite-client/package.json +1 -1
  69. package/src/infrastructure/persistence/generated/prisma-sqlite-client/schema.prisma +12 -0
  70. package/dist/AppContainerFactory-Cr3JeVmg.js.map +0 -1
@@ -38,4 +38,7 @@ export type StoredSpanScopeArgs = StoredExecutionTelemetryDeps &
38
38
  initialStartTime?: Date;
39
39
  connectionInvocationId?: string;
40
40
  modelName?: string;
41
+ iterationId?: string;
42
+ itemIndex?: number;
43
+ parentInvocationId?: string;
41
44
  }>;
@@ -67,6 +67,13 @@ export class RunEventBusTelemetryReporter {
67
67
  case "nodeFailed":
68
68
  await this.handleNodeSnapshot(event);
69
69
  return;
70
+ case "connectionInvocationStarted":
71
+ case "connectionInvocationCompleted":
72
+ case "connectionInvocationFailed":
73
+ // Per-invocation events are surfaced to the realtime UI via the websocket bridge;
74
+ // they do not need additional span/metric persistence here because the underlying
75
+ // child spans are already produced by the engine's telemetry scopes.
76
+ return;
70
77
  }
71
78
  }
72
79
 
@@ -13,6 +13,13 @@ export class StoredNodeExecutionTelemetry extends StoredTelemetrySpanScope imple
13
13
  }
14
14
 
15
15
  startChildSpan(args: TelemetryChildSpanStart): TelemetrySpanScope {
16
+ // Iteration / parent-invocation identity is read from the attribute bag when present (the
17
+ // engine passes them in for runnable per-item loops and sub-agent boundaries) and falls back
18
+ // to the parent scope's identity otherwise (so spans started outside the iteration loop still
19
+ // inherit a non-iteration scope).
20
+ const iterationIdFromAttrs = this.toStringAttribute(args.attributes?.["codemation.iteration.id"]);
21
+ const itemIndexFromAttrs = this.toNumberAttribute(args.attributes?.["codemation.iteration.index"]);
22
+ const parentInvocationIdFromAttrs = this.toStringAttribute(args.attributes?.["codemation.parent.invocation_id"]);
16
23
  // eslint-disable-next-line codemation/no-manual-di-new
17
24
  const span = new StoredTelemetrySpanScope({
18
25
  ...this.deps,
@@ -28,8 +35,15 @@ export class StoredNodeExecutionTelemetry extends StoredTelemetrySpanScope imple
28
35
  args.attributes?.["codemation.connection.invocation_id"] ?? args.attributes?.["connection.invocation_id"],
29
36
  ),
30
37
  modelName: this.toStringAttribute(args.attributes?.[GenAiTelemetryAttributeNames.requestModel]),
38
+ iterationId: iterationIdFromAttrs ?? this.iterationId,
39
+ itemIndex: itemIndexFromAttrs ?? this.itemIndex,
40
+ parentInvocationId: parentInvocationIdFromAttrs ?? this.parentInvocationId,
31
41
  });
32
42
  void span.markStarted();
33
43
  return span;
34
44
  }
45
+
46
+ private toNumberAttribute(value: unknown): number | undefined {
47
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
48
+ }
35
49
  }
@@ -1,4 +1,7 @@
1
1
  import type {
2
+ NodeActivationId,
3
+ NodeExecutionTelemetry,
4
+ NodeId,
2
5
  TelemetryArtifactAttachment,
3
6
  TelemetryArtifactReference,
4
7
  TelemetryAttributes,
@@ -25,6 +28,9 @@ export class StoredTelemetrySpanScope implements TelemetrySpanScope {
25
28
  private readonly initialStartTime: Date | undefined;
26
29
  private readonly connectionInvocationId: string | undefined;
27
30
  private readonly modelName: string | undefined;
31
+ protected readonly iterationId: string | undefined;
32
+ protected readonly itemIndex: number | undefined;
33
+ protected readonly parentInvocationId: string | undefined;
28
34
 
29
35
  constructor(args: StoredSpanScopeArgs) {
30
36
  this.deps = args;
@@ -39,6 +45,9 @@ export class StoredTelemetrySpanScope implements TelemetrySpanScope {
39
45
  this.initialStartTime = args.initialStartTime;
40
46
  this.connectionInvocationId = args.connectionInvocationId;
41
47
  this.modelName = args.modelName;
48
+ this.iterationId = args.iterationId;
49
+ this.itemIndex = args.itemIndex;
50
+ this.parentInvocationId = args.parentInvocationId;
42
51
  }
43
52
 
44
53
  async addSpanEvent(args: TelemetrySpanEventRecord): Promise<void> {
@@ -66,6 +75,9 @@ export class StoredTelemetrySpanScope implements TelemetrySpanScope {
66
75
  nodeType: enrichment.nodeType,
67
76
  nodeRole: enrichment.nodeRole,
68
77
  modelName: this.modelName,
78
+ iterationId: this.iterationId,
79
+ itemIndex: this.itemIndex,
80
+ parentInvocationId: this.parentInvocationId,
69
81
  retentionExpiresAt: this.deps.telemetryRetentionTimestampFactory.createMetricExpiry(
70
82
  this.deps.policySnapshot,
71
83
  observedAt,
@@ -121,16 +133,93 @@ export class StoredTelemetrySpanScope implements TelemetrySpanScope {
121
133
  });
122
134
  }
123
135
 
136
+ asNodeTelemetry(args: Readonly<{ nodeId: NodeId; activationId: NodeActivationId }>): NodeExecutionTelemetry {
137
+ return this.buildNodeTelemetryView(args);
138
+ }
139
+
140
+ private buildNodeTelemetryView(
141
+ args: Readonly<{ nodeId: NodeId; activationId: NodeActivationId }>,
142
+ ): NodeExecutionTelemetry {
143
+ // Returns a NodeExecutionTelemetry view of THIS span: children created via the returned
144
+ // telemetry's `startChildSpan` parent under this span (e.g. agent.tool.call) and inherit the
145
+ // child execution scope's nodeId/activationId. Used at the sub-agent boundary so nested
146
+ // runtime telemetry parents under the tool-call span instead of the orchestrator's node span.
147
+ const buildChildScope = (
148
+ childName: string,
149
+ childKind: "internal" | "client",
150
+ childAttrs?: TelemetryAttributes,
151
+ childStart?: Date,
152
+ ): StoredTelemetrySpanScope => {
153
+ // eslint-disable-next-line codemation/no-manual-di-new
154
+ const child = new StoredTelemetrySpanScope({
155
+ ...this.deps,
156
+ spanId: this.deps.otelIdentityFactory.createEphemeralSpanId(),
157
+ parentSpanId: this.spanId,
158
+ nodeId: args.nodeId,
159
+ activationId: args.activationId,
160
+ spanName: childName,
161
+ spanKind: childKind,
162
+ initialAttributes: childAttrs,
163
+ initialStartTime: childStart,
164
+ connectionInvocationId: this.toStringAttribute(
165
+ childAttrs?.["codemation.connection.invocation_id"] ?? childAttrs?.["connection.invocation_id"],
166
+ ),
167
+ modelName: this.toStringAttribute(childAttrs?.["gen_ai.request.model"]),
168
+ iterationId: this.iterationId,
169
+ itemIndex: this.itemIndex,
170
+ parentInvocationId: this.parentInvocationId,
171
+ });
172
+ void child.markStarted();
173
+ return child;
174
+ };
175
+ const view: NodeExecutionTelemetry = {
176
+ traceId: this.traceId,
177
+ spanId: this.spanId,
178
+ addSpanEvent: (event) => this.addSpanEvent(event),
179
+ recordMetric: (metric) => this.recordMetric(metric),
180
+ attachArtifact: (artifact) => this.attachArtifact(artifact),
181
+ end: (endArgs) => this.end(endArgs),
182
+ asNodeTelemetry: (rescope) => this.asNodeTelemetry(rescope),
183
+ forNode: () => view,
184
+ startChildSpan: (childArgs) =>
185
+ buildChildScope(childArgs.name, childArgs.kind ?? "internal", childArgs.attributes, childArgs.startedAt),
186
+ };
187
+ return view;
188
+ }
189
+
124
190
  async markStarted(): Promise<void> {
125
191
  await this.upsert({
126
192
  status: "running",
127
193
  startTime: (this.initialStartTime ?? new Date()).toISOString(),
128
- attributes: this.initialAttributes,
194
+ attributes: this.attributesWithIdentity(this.initialAttributes),
129
195
  modelName: this.modelName,
130
196
  connectionInvocationId: this.connectionInvocationId,
197
+ iterationId: this.iterationId,
198
+ itemIndex: this.itemIndex,
199
+ parentInvocationId: this.parentInvocationId,
131
200
  });
132
201
  }
133
202
 
203
+ /**
204
+ * Stamps `codemation.iteration.id`, `codemation.iteration.index`, and
205
+ * `codemation.parent.invocation_id` onto the attribute bag so dashboards/queries can filter by
206
+ * iteration without joining on the dedicated columns. The dedicated columns are still the
207
+ * authoritative source — these attributes are convenience for downstream consumers.
208
+ */
209
+ protected attributesWithIdentity(attrs: TelemetryAttributes | undefined): TelemetryAttributes | undefined {
210
+ const base: Record<string, TelemetryAttributes[string]> = { ...(attrs ?? {}) };
211
+ if (typeof this.iterationId === "string" && this.iterationId.length > 0) {
212
+ base["codemation.iteration.id"] = this.iterationId;
213
+ }
214
+ if (typeof this.itemIndex === "number") {
215
+ base["codemation.iteration.index"] = this.itemIndex;
216
+ }
217
+ if (typeof this.parentInvocationId === "string" && this.parentInvocationId.length > 0) {
218
+ base["codemation.parent.invocation_id"] = this.parentInvocationId;
219
+ }
220
+ return Object.keys(base).length > 0 ? base : undefined;
221
+ }
222
+
134
223
  protected async upsert(update: Partial<TelemetrySpanUpsert>): Promise<void> {
135
224
  const enrichment = await this.resolveEnrichment();
136
225
  const observedAt = this.resolveObservedAt(update);
@@ -62,6 +62,7 @@ import {
62
62
  VerifyUserInviteQueryHandler,
63
63
  } from "../application/queries/UserAccountQueryHandlers";
64
64
  import {
65
+ GetIterationCostQueryHandler,
65
66
  GetRunBinaryAttachmentQueryHandler,
66
67
  GetTelemetryDashboardDimensionsQueryHandler,
67
68
  GetTelemetryDashboardRunsQueryHandler,
@@ -76,6 +77,7 @@ import {
76
77
  GetWorkflowSummariesQueryHandler,
77
78
  ListWorkflowRunsQueryHandler,
78
79
  } from "../application/queries/WorkflowQueryHandlers";
80
+ import { RunIterationProjectionFactory } from "../application/queries/RunIterationProjectionFactory";
79
81
  import { OpenAiApiKeyCredentialHealthTester } from "../infrastructure/credentials/OpenAiApiKeyCredentialHealthTester";
80
82
  import { OpenAiApiKeyCredentialTypeFactory } from "../infrastructure/credentials/OpenAiApiKeyCredentialTypeFactory";
81
83
  import { CodemationPluginRegistrar } from "../infrastructure/config/CodemationPluginRegistrar";
@@ -222,6 +224,7 @@ export class AppContainerFactory {
222
224
  ListCredentialTypesQueryHandler,
223
225
  ListUserAccountsQueryHandler,
224
226
  VerifyUserInviteQueryHandler,
227
+ GetIterationCostQueryHandler,
225
228
  GetRunBinaryAttachmentQueryHandler,
226
229
  GetTelemetryDashboardDimensionsQueryHandler,
227
230
  GetTelemetryDashboardRunsQueryHandler,
@@ -442,6 +445,8 @@ export class AppContainerFactory {
442
445
  }),
443
446
  });
444
447
  container.registerSingleton(PrismaClientFactory, PrismaClientFactory);
448
+ container.registerSingleton(RunIterationProjectionFactory, RunIterationProjectionFactory);
449
+ container.registerSingleton(GetIterationCostQueryHandler, GetIterationCostQueryHandler);
445
450
  container.registerSingleton(WorkflowPolicyUiPresentationFactory, WorkflowPolicyUiPresentationFactory);
446
451
  container.registerSingleton(WorkflowDefinitionMapper, WorkflowDefinitionMapper);
447
452
  container.registerSingleton(RequestToWebhookItemMapper, RequestToWebhookItemMapper);
@@ -40,6 +40,9 @@ export interface TelemetrySpanRecord {
40
40
  readonly attributes?: TelemetryAttributes;
41
41
  readonly events?: ReadonlyArray<TelemetrySpanEventRecord>;
42
42
  readonly retentionExpiresAt?: string;
43
+ readonly iterationId?: string;
44
+ readonly itemIndex?: number;
45
+ readonly parentInvocationId?: string;
43
46
  }
44
47
 
45
48
  export interface TelemetrySpanUpsert {
@@ -64,6 +67,9 @@ export interface TelemetrySpanUpsert {
64
67
  readonly attributes?: TelemetryAttributes;
65
68
  readonly events?: ReadonlyArray<TelemetrySpanEventRecord>;
66
69
  readonly retentionExpiresAt?: string;
70
+ readonly iterationId?: string;
71
+ readonly itemIndex?: number;
72
+ readonly parentInvocationId?: string;
67
73
  }
68
74
 
69
75
  export interface TelemetryArtifactRecord {
@@ -115,6 +121,9 @@ export interface TelemetryMetricPointRecord {
115
121
  readonly modelName?: string;
116
122
  readonly dimensions?: TelemetryAttributes;
117
123
  readonly retentionExpiresAt?: string;
124
+ readonly iterationId?: string;
125
+ readonly itemIndex?: number;
126
+ readonly parentInvocationId?: string;
118
127
  }
119
128
 
120
129
  export interface TelemetryMetricPointWrite extends TelemetryMetricRecord {
@@ -130,6 +139,9 @@ export interface TelemetryMetricPointWrite extends TelemetryMetricRecord {
130
139
  readonly nodeRole?: string;
131
140
  readonly modelName?: string;
132
141
  readonly retentionExpiresAt?: string;
142
+ readonly iterationId?: string;
143
+ readonly itemIndex?: number;
144
+ readonly parentInvocationId?: string;
133
145
  }
134
146
 
135
147
  export interface TelemetrySpanListQuery {
@@ -32,6 +32,9 @@ export class InMemoryTelemetryMetricPointStore implements TelemetryMetricPointSt
32
32
  modelName: record.modelName,
33
33
  dimensions: record.attributes,
34
34
  retentionExpiresAt: record.retentionExpiresAt,
35
+ iterationId: record.iterationId,
36
+ itemIndex: record.itemIndex,
37
+ parentInvocationId: record.parentInvocationId,
35
38
  };
36
39
  this.rows.set(created.metricPointId, created);
37
40
  return created;
@@ -63,6 +63,9 @@ export class InMemoryTelemetrySpanStore implements TelemetrySpanStore {
63
63
  },
64
64
  events: [...(existing?.events ?? []), ...(update.events ?? [])],
65
65
  retentionExpiresAt: update.retentionExpiresAt ?? existing?.retentionExpiresAt,
66
+ iterationId: update.iterationId ?? existing?.iterationId,
67
+ itemIndex: update.itemIndex ?? existing?.itemIndex,
68
+ parentInvocationId: update.parentInvocationId ?? existing?.parentInvocationId,
66
69
  };
67
70
  }
68
71
 
@@ -121,6 +121,29 @@ export class InMemoryWorkflowRunRepository implements WorkflowRunRepository, Wor
121
121
  error: snapshot.error,
122
122
  }),
123
123
  );
124
+ const invocationInstances: ExecutionInstanceDto[] = (state.connectionInvocations ?? []).map(
125
+ (invocation, index) => ({
126
+ instanceId: invocation.invocationId,
127
+ slotNodeId: invocation.connectionNodeId,
128
+ workflowNodeId: invocation.parentAgentNodeId,
129
+ kind: "connectionInvocation",
130
+ runIndex: index,
131
+ batchId: state.pending?.batchId ?? "batch_1",
132
+ activationId: invocation.parentAgentActivationId,
133
+ status: invocation.status,
134
+ queuedAt: invocation.queuedAt,
135
+ startedAt: invocation.startedAt,
136
+ finishedAt: invocation.finishedAt,
137
+ itemCount: 0,
138
+ inputJson: invocation.managedInput as never,
139
+ outputJson: invocation.managedOutput as never,
140
+ error: invocation.error,
141
+ iterationId: invocation.iterationId,
142
+ itemIndex: invocation.itemIndex,
143
+ parentInvocationId: invocation.parentInvocationId,
144
+ }),
145
+ );
146
+ executionInstances.push(...invocationInstances);
124
147
  return {
125
148
  runId: state.runId,
126
149
  workflowId: state.workflowId,
@@ -38,6 +38,9 @@ export class PrismaTelemetryMetricPointStore implements TelemetryMetricPointStor
38
38
  modelName: record.modelName ?? null,
39
39
  dimensionsJson: record.attributes ? JSON.stringify(record.attributes) : null,
40
40
  retentionExpiresAt: record.retentionExpiresAt ?? null,
41
+ iterationId: record.iterationId ?? null,
42
+ itemIndex: record.itemIndex ?? null,
43
+ parentInvocationId: record.parentInvocationId ?? null,
41
44
  },
42
45
  });
43
46
  return {
@@ -58,6 +61,9 @@ export class PrismaTelemetryMetricPointStore implements TelemetryMetricPointStor
58
61
  modelName: record.modelName,
59
62
  dimensions: record.attributes,
60
63
  retentionExpiresAt: record.retentionExpiresAt,
64
+ iterationId: record.iterationId,
65
+ itemIndex: record.itemIndex,
66
+ parentInvocationId: record.parentInvocationId,
61
67
  };
62
68
  }
63
69
 
@@ -96,6 +102,9 @@ export class PrismaTelemetryMetricPointStore implements TelemetryMetricPointStor
96
102
  modelName: row.modelName ?? undefined,
97
103
  dimensions: this.parseJson<TelemetryAttributes>(row.dimensionsJson),
98
104
  retentionExpiresAt: row.retentionExpiresAt ?? undefined,
105
+ iterationId: row.iterationId ?? undefined,
106
+ itemIndex: row.itemIndex ?? undefined,
107
+ parentInvocationId: row.parentInvocationId ?? undefined,
99
108
  }));
100
109
  }
101
110
 
@@ -49,6 +49,9 @@ export class PrismaTelemetrySpanStore implements TelemetrySpanStore {
49
49
  attributesJson: attributes ? JSON.stringify(attributes) : null,
50
50
  eventsJson: events.length > 0 ? JSON.stringify(events) : null,
51
51
  retentionExpiresAt: record.retentionExpiresAt ?? existing?.retentionExpiresAt ?? null,
52
+ iterationId: record.iterationId ?? existing?.iterationId ?? null,
53
+ itemIndex: record.itemIndex ?? existing?.itemIndex ?? null,
54
+ parentInvocationId: record.parentInvocationId ?? existing?.parentInvocationId ?? null,
52
55
  updatedAt: new Date().toISOString(),
53
56
  };
54
57
  await this.prisma.telemetrySpan.upsert({
@@ -100,6 +103,9 @@ export class PrismaTelemetrySpanStore implements TelemetrySpanStore {
100
103
  attributes: this.parseJson<TelemetryAttributes>(row.attributesJson),
101
104
  events: this.parseJson<ReadonlyArray<TelemetrySpanEventRecord>>(row.eventsJson) ?? [],
102
105
  retentionExpiresAt: row.retentionExpiresAt ?? undefined,
106
+ iterationId: row.iterationId ?? undefined,
107
+ itemIndex: row.itemIndex ?? undefined,
108
+ parentInvocationId: row.parentInvocationId ?? undefined,
103
109
  }));
104
110
  }
105
111
 
@@ -49,6 +49,9 @@ type ExecutionInstanceRow = {
49
49
  successfulItemCount: number | null;
50
50
  failedItemCount: number | null;
51
51
  usedPinnedOutput: boolean | null;
52
+ iterationId: string | null;
53
+ itemIndex: number | null;
54
+ parentInvocationId: string | null;
52
55
  };
53
56
 
54
57
  type RunWorkItemRecord = {
@@ -513,6 +516,9 @@ export class PrismaWorkflowRunRepository implements WorkflowRunRepository, Workf
513
516
  startedAt: row.startedAt ?? undefined,
514
517
  finishedAt: row.finishedAt ?? undefined,
515
518
  updatedAt: row.updatedAt,
519
+ iterationId: row.iterationId ?? undefined,
520
+ itemIndex: row.itemIndex ?? undefined,
521
+ parentInvocationId: row.parentInvocationId ?? undefined,
516
522
  };
517
523
  }
518
524
 
@@ -535,6 +541,9 @@ export class PrismaWorkflowRunRepository implements WorkflowRunRepository, Workf
535
541
  inputJson: row.inputJson ? (JSON.parse(row.inputJson) as ExecutionInstanceDto["inputJson"]) : undefined,
536
542
  outputJson: row.outputJson ? (JSON.parse(row.outputJson) as ExecutionInstanceDto["outputJson"]) : undefined,
537
543
  error: row.errorJson ? (JSON.parse(row.errorJson) as ExecutionInstanceDto["error"]) : undefined,
544
+ iterationId: row.iterationId ?? undefined,
545
+ itemIndex: row.itemIndex ?? undefined,
546
+ parentInvocationId: row.parentInvocationId ?? undefined,
538
547
  };
539
548
  }
540
549
 
@@ -645,6 +654,9 @@ export class PrismaWorkflowRunRepository implements WorkflowRunRepository, Workf
645
654
  failedItemCount: null,
646
655
  inputStorageKind: "inline",
647
656
  outputStorageKind: "inline",
657
+ iterationId: inv.iterationId ?? null,
658
+ itemIndex: inv.itemIndex ?? null,
659
+ parentInvocationId: inv.parentInvocationId ?? null,
648
660
  });
649
661
  cIdx += 1;
650
662
  }