@codemation/node-example 0.0.44 → 0.0.45

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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # @codemation/node-example
2
2
 
3
+ ## 0.0.45
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`60f23a3`](https://github.com/MadeRelevant/codemation/commit/60f23a37660cdda34e3d61acca8b2bf581a9db0e), [`a5457bb`](https://github.com/MadeRelevant/codemation/commit/a5457bb58edafec01e85cdcf6d30f9ca54521e27), [`510e0d8`](https://github.com/MadeRelevant/codemation/commit/510e0d8a5f137a4fe10f43cbf46e40d05fea4977), [`d5f49f7`](https://github.com/MadeRelevant/codemation/commit/d5f49f7f80deafc109dbc29f16ff0d571ee8591a), [`364507a`](https://github.com/MadeRelevant/codemation/commit/364507a9fba45fd66cb208d5a41ee1f3bdc68311), [`0dc8a9d`](https://github.com/MadeRelevant/codemation/commit/0dc8a9def376e4cd1821f3b92b0f887720e0c842), [`3facadf`](https://github.com/MadeRelevant/codemation/commit/3facadf3bc09d21f33e698213a521fb64168d5dd), [`c08cf33`](https://github.com/MadeRelevant/codemation/commit/c08cf33ead44fec64d3d43b9294fccfdf6674156), [`597fa8f`](https://github.com/MadeRelevant/codemation/commit/597fa8f697300d8d861a02c11e9819892f7947fa), [`b15f8c6`](https://github.com/MadeRelevant/codemation/commit/b15f8c68125e3ec3082bab8d79414871f942e409), [`bfdd759`](https://github.com/MadeRelevant/codemation/commit/bfdd7590b4903676b223c2f302b9bcd0f4a4583c), [`0a681b3`](https://github.com/MadeRelevant/codemation/commit/0a681b357afd7b15ba3925788c732fd439d8e6b0), [`ab5185a`](https://github.com/MadeRelevant/codemation/commit/ab5185a839118868eda1aab42b82f7a921037f37), [`fd188a2`](https://github.com/MadeRelevant/codemation/commit/fd188a2bac65c86dd62cf2f540034769c5bc0ac7), [`f2aa0c4`](https://github.com/MadeRelevant/codemation/commit/f2aa0c42b2f9d2e9eb7bc4f3393f74342f7ef460), [`cf2b146`](https://github.com/MadeRelevant/codemation/commit/cf2b146b452317e1ccaa1dfeaaa1a0e153181e30)]:
8
+ - @codemation/core@0.15.0
9
+
3
10
  ## 0.0.44
4
11
 
5
12
  ### Patch Changes
package/dist/index.d.cts CHANGED
@@ -3,11 +3,6 @@ import { InjectionToken as TypeToken } from "tsyringe";
3
3
  import { ReadableStream } from "node:stream/web";
4
4
 
5
5
  //#region ../core/src/contracts/baseTypes.d.ts
6
- /**
7
- * Minimal base types that have no dependencies on other contracts.
8
- * Used by credentialTypes, workflowTypes, and other contract layers
9
- * to avoid circular dependencies.
10
- */
11
6
  type WorkflowId = string;
12
7
  type NodeId = string;
13
8
  type OutputPortKey = string;
@@ -92,13 +87,6 @@ interface TelemetrySpanScope extends TelemetryScope {
92
87
  readonly traceId: string;
93
88
  readonly spanId: string;
94
89
  end(args?: TelemetrySpanEnd): Promise<void> | void;
95
- /**
96
- * Lift this span into a {@link NodeExecutionTelemetry} scoped to a different (nodeId, activationId).
97
- * Children created via the returned telemetry's `startChildSpan` get this span as their parent.
98
- *
99
- * Used at the sub-agent boundary so that nested runtime telemetry parents under the agent.tool.call
100
- * span instead of the orchestrator's node-level span.
101
- */
102
90
  asNodeTelemetry(args: Readonly<{
103
91
  nodeId: NodeId;
104
92
  activationId: NodeActivationId;
@@ -117,30 +105,21 @@ interface ExecutionTelemetry extends TelemetryScope {
117
105
  }
118
106
  //#endregion
119
107
  //#region ../core/src/contracts/retryPolicySpec.types.d.ts
120
- /**
121
- * In-process retry policy for runnable nodes. Serialized configs use the same
122
- * `kind` discriminator (`JSON.stringify` / persisted workflows).
123
- *
124
- * `maxAttempts` is the total number of tries including the first (e.g. 3 means up to 2 delays after failures).
125
- */
126
108
  type RetryPolicySpec = NoneRetryPolicySpec | FixedRetryPolicySpec | ExponentialRetryPolicySpec;
127
109
  interface NoneRetryPolicySpec {
128
110
  readonly kind: "none";
129
111
  }
130
112
  interface FixedRetryPolicySpec {
131
113
  readonly kind: "fixed";
132
- /** Total attempts including the first execution. Must be >= 1. */
133
114
  readonly maxAttempts: number;
134
115
  readonly delayMs: number;
135
116
  }
136
117
  interface ExponentialRetryPolicySpec {
137
118
  readonly kind: "exponential";
138
- /** Total attempts including the first execution. Must be >= 1. */
139
119
  readonly maxAttempts: number;
140
120
  readonly initialDelayMs: number;
141
121
  readonly multiplier: number;
142
122
  readonly maxDelayMs?: number;
143
- /** When true, each delay is multiplied by a random factor in [1, 1.2). */
144
123
  readonly jitter?: boolean;
145
124
  }
146
125
  //#endregion
@@ -156,38 +135,22 @@ type CredentialRequirement = Readonly<{
156
135
  }>;
157
136
  //#endregion
158
137
  //#region ../core/src/contracts/collectionTypes.d.ts
159
- /**
160
- * Represents a typed store for a single collection.
161
- * All rows include auto-managed id, created_at, and updated_at fields.
162
- */
163
138
  interface CollectionStore<TRow extends Record<string, unknown> = Record<string, unknown>> {
164
- /**
165
- * Insert a new row. id, created_at, and updated_at are auto-populated.
166
- */
167
139
  insert(row: TRow): Promise<TRow & {
168
140
  id: string;
169
141
  created_at: Date;
170
142
  updated_at: Date;
171
143
  }>;
172
- /**
173
- * Get a single row by id.
174
- */
175
144
  get(id: string): Promise<(TRow & {
176
145
  id: string;
177
146
  created_at: Date;
178
147
  updated_at: Date;
179
148
  }) | null>;
180
- /**
181
- * Find a single row matching the provided filter.
182
- */
183
149
  findOne(filter: Partial<TRow>): Promise<(TRow & {
184
150
  id: string;
185
151
  created_at: Date;
186
152
  updated_at: Date;
187
153
  }) | null>;
188
- /**
189
- * List rows with optional pagination and filtering.
190
- */
191
154
  list(opts?: {
192
155
  limit?: number;
193
156
  offset?: number;
@@ -200,41 +163,21 @@ interface CollectionStore<TRow extends Record<string, unknown> = Record<string,
200
163
  }>;
201
164
  total: number;
202
165
  }>;
203
- /**
204
- * Update a row by id with partial data.
205
- */
206
166
  update(id: string, patch: Partial<TRow>): Promise<TRow & {
207
167
  id: string;
208
168
  created_at: Date;
209
169
  updated_at: Date;
210
170
  }>;
211
- /**
212
- * Delete a row by id. Hard delete only (no soft delete).
213
- */
214
171
  delete(id: string): Promise<{
215
172
  deleted: boolean;
216
173
  }>;
217
174
  }
218
- /**
219
- * Runtime collections context: keyed by collection name.
220
- */
221
175
  type CollectionsContext = Readonly<Record<string, CollectionStore>>;
222
176
  //#endregion
223
177
  //#region ../core/src/contracts/runTypes.d.ts
224
- /**
225
- * Test-suite linkage for a run. When set, this run was started by a TestSuiteOrchestrator
226
- * as one test case inside a TestSuiteRun. The `IsTestRun` node and host-side persisters key
227
- * off the presence of this field. Subworkflow runs inherit it from their parent run.
228
- */
229
178
  interface RunTestContext {
230
179
  readonly testSuiteRunId: string;
231
180
  readonly testCaseIndex: number;
232
- /**
233
- * Optional human-friendly label for this test case (e.g. an email subject when fixtures
234
- * are loaded from a mailbox). Resolved per item by `TestTrigger.caseLabel(item)` if set,
235
- * persisted on `Run.test_case_label` so the Tests-tab tree-table can show "RFQ for batch 14"
236
- * instead of "run_1777755971399_bbb86beac1396".
237
- */
238
181
  readonly testCaseLabel?: string;
239
182
  }
240
183
  type NodeInputsByPort = Readonly<Record<InputPortKey, Items>>;
@@ -245,9 +188,7 @@ interface NodeExecutionError {
245
188
  stack?: string;
246
189
  details?: JsonValue;
247
190
  }
248
- /** Stable id for a single connection invocation row in {@link ConnectionInvocationRecord}. */
249
191
  type ConnectionInvocationId = string;
250
- /** Arguments for appending a {@link ConnectionInvocationRecord} (engine fills run/workflow ids and timestamps). */
251
192
  type ConnectionInvocationAppendArgs = Readonly<{
252
193
  invocationId: ConnectionInvocationId;
253
194
  connectionNodeId: NodeId;
@@ -284,83 +225,31 @@ interface NodeConfigBase {
284
225
  readonly name?: string;
285
226
  readonly id?: NodeId;
286
227
  readonly icon?: string;
287
- /**
288
- * Plain-language, non-technical explanation of what this node does, surfaced in the workflow
289
- * inspector / node properties sidebar. A first-class config option every authorable node accepts
290
- * directly (alongside `id`), so it flows into the persisted config the mappers read. Distinct from
291
- * {@link inspectorSummary} (config-derived label/value rows).
292
- */
293
228
  readonly description?: string;
294
229
  readonly execution?: Readonly<{
295
230
  hint?: "local" | "worker";
296
231
  queue?: string;
297
232
  }>;
298
- /** In-process execute retries (runnable nodes). Triggers typically omit this. */
299
233
  readonly retryPolicy?: RetryPolicySpec;
300
- /** Recover from execute failures; return outputs to continue, or rethrow to fail the node. */
301
234
  readonly nodeErrorHandler?: NodeErrorHandlerSpec;
302
- /**
303
- * When true, edges carrying zero items on an output port still schedule single-input downstream nodes.
304
- * Decided from the **source** node that produced the (empty) output. Default (false/undefined): empty
305
- * main batches skip downstream execution and propagate the empty path.
306
- */
307
235
  readonly continueWhenEmptyOutput?: boolean;
308
- /**
309
- * Declared I/O port names for canvas authoring (unioned with ports inferred from edges).
310
- * Use for dynamic routers (Switch) and future error ports.
311
- */
312
236
  readonly declaredOutputPorts?: ReadonlyArray<OutputPortKey>;
313
237
  readonly declaredInputPorts?: ReadonlyArray<InputPortKey>;
314
238
  getCredentialRequirements?(): ReadonlyArray<CredentialRequirement>;
315
- /**
316
- * Marker: this node emits {@link import("./assertionTypes").AssertionResult}-shaped items on its
317
- * `main` port. The TestSuiteOrchestrator (and host-side TestAssertionPersister) listen for
318
- * `nodeCompleted` events from nodes with this flag set, and persist their output items as
319
- * TestAssertion records (only when the run carries a `testContext`). Set on assertion node
320
- * configs (e.g. `AssertionNodeConfig`, `StringEqualsAssertionNodeConfig`).
321
- */
322
239
  readonly emitsAssertions?: true;
323
- /**
324
- * Static configuration summary surfaced in the workflow inspector — the design-time
325
- * "what does this node do" panel that renders before any run telemetry exists.
326
- *
327
- * Return 2–6 short label/value pairs derived from this config (method + url for an HTTP
328
- * call, model + tool list for an agent, schedule + timezone for a cron trigger, etc.).
329
- * Values are truncated by the UI; aim for one line each. Return `undefined` to opt out
330
- * — the inspector hides the section when no rows are produced.
331
- *
332
- * Implement on the config class instance so the function can read sibling config fields.
333
- * `defineNode({ inspectorSummary })` plumbs through to this.
334
- */
335
240
  inspectorSummary?(): ReadonlyArray<NodeInspectorSummaryRow> | undefined;
336
241
  }
337
- /**
338
- * One row of a node's static configuration summary. See {@link NodeConfigBase.inspectorSummary}.
339
- */
340
242
  interface NodeInspectorSummaryRow {
341
243
  readonly label: string;
342
244
  readonly value: string;
343
245
  }
344
246
  declare const runnableNodeInputType: unique symbol;
345
247
  declare const runnableNodeOutputType: unique symbol;
346
- /**
347
- * Runnable node: **`TInputJson`** is what **`inputSchema`** validates on **`item.json`** (the wire payload).
348
- * **`TOutputJson`** is emitted `item.json` on outputs.
349
- */
350
248
  interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown> extends NodeConfigBase {
351
249
  readonly kind: "node";
352
250
  readonly [runnableNodeInputType]?: TInputJson$1;
353
251
  readonly [runnableNodeOutputType]?: TOutputJson$1;
354
- /**
355
- * Optional Zod input contract for {@link RunnableNode} when not set on the node class.
356
- * Resolution order: node instance `inputSchema`, then config `inputSchema`, then `z.unknown()`.
357
- */
358
252
  readonly inputSchema?: ZodType<TInputJson$1>;
359
- /**
360
- * When an activation receives **zero** input items, the engine normally runs `execute` zero times.
361
- * Set to **`runOnce`** to run `execute` once with an empty `items` batch (and a synthetic wire item for schema parsing).
362
- * Used by batch-style callback nodes (built-in `Callback`) so `callback([], ctx)` still runs.
363
- */
364
253
  readonly emptyBatchExecution?: "skip" | "runOnce";
365
254
  }
366
255
  type PairedItemRef = Readonly<{
@@ -395,27 +284,14 @@ type Items<TJson = unknown> = ReadonlyArray<Item<TJson>>;
395
284
  type NodeOutputs = Partial<Record<OutputPortKey, Items>>;
396
285
  type RunId = string;
397
286
  type NodeActivationId = string;
398
- /**
399
- * One per-item iteration of a runnable node's execute loop. Refines `NodeActivationId` for
400
- * per-item connection invocations and telemetry. Undefined when the executing node is a batch
401
- * node or trigger that does not iterate items.
402
- */
403
287
  type NodeIterationId = string;
404
288
  interface ParentExecutionRef {
405
289
  runId: RunId;
406
290
  workflowId: WorkflowId;
407
291
  nodeId: NodeId;
408
- /** Subworkflow depth of the **spawning** run (0 = root). Passed when starting a child run. */
409
292
  subworkflowDepth?: number;
410
- /** Effective max node activations from the parent run (propagated to child policy merge). */
411
293
  engineMaxNodeActivations?: number;
412
- /** Effective max subworkflow depth from the parent run (propagated to child policy merge). */
413
294
  engineMaxSubworkflowDepth?: number;
414
- /**
415
- * Test-suite linkage inherited by the child subworkflow run. Set by whichever node
416
- * spawns the subworkflow when its own `ctx.testContext` is present, so assertions
417
- * emitted inside a subworkflow land under the correct parent test case.
418
- */
419
295
  testContext?: RunTestContext;
420
296
  }
421
297
  interface RunDataSnapshot {
@@ -436,36 +312,19 @@ interface NodeErrorHandler {
436
312
  type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandler;
437
313
  //#endregion
438
314
  //#region ../core/src/contracts/runtimeTypes.d.ts
439
- /** Opaque unique identifier for a single HumanTask instance. */
440
315
  type HumanTaskId = string;
441
- /**
442
- * Minimal handle handed to the `deliver` callback so it can route to the correct
443
- * inbox channel.
444
- */
445
316
  interface HumanTaskHandle {
446
317
  readonly taskId: HumanTaskId;
447
318
  readonly runId: string;
448
319
  readonly nodeId: string;
449
320
  readonly expiresAt: Date;
450
- /** TODO: real signed URL; placeholder empty string for now. */
451
321
  readonly resumeUrl: string;
452
- /**
453
- * Arbitrary JSON metadata copied from `SuspensionRequest.request.metadata` at suspension time.
454
- * Used by the agent runtime to round-trip the `agentCheckpoint` back to the
455
- * resumed node via `ctx.resumeContext.task.metadata`.
456
- */
457
322
  readonly metadata?: Readonly<Record<string, JsonValue>>;
458
323
  }
459
- /** Identity of the person who made a decision on the task. */
460
324
  interface HumanTaskActor {
461
325
  readonly actorId: string;
462
326
  readonly displayName?: string;
463
327
  }
464
- /**
465
- * Resume context injected into `NodeExecutionContext` when the engine re-activates
466
- * a previously suspended node. `defineHumanApprovalNode` wraps this with parsed
467
- * `TDecision`; at the engine layer `decision.value` is `unknown`.
468
- */
469
328
  interface ResumeContext {
470
329
  readonly decision: Readonly<{
471
330
  kind: "decided";
@@ -506,11 +365,6 @@ interface NodeExecutionStatePublisher {
506
365
  error: Error;
507
366
  }): Promise<void>;
508
367
  appendConnectionInvocation(args: ConnectionInvocationAppendArgs): Promise<void>;
509
- /**
510
- * Annotates the current snapshot for `nodeId` with the id of the child run spawned by a
511
- * SubWorkflow invocation. Called from `SubWorkflowNode.execute` after `runById` resolves.
512
- * The engine's subsequent `markCompleted` call preserves the value via `previous.childRunId`.
513
- */
514
368
  setChildRunId?(args: {
515
369
  nodeId: NodeId;
516
370
  childRunId: RunId;
@@ -538,32 +392,16 @@ interface ExecutionBinaryService {
538
392
  activationId: NodeActivationId;
539
393
  }): NodeBinaryAttachmentService;
540
394
  openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
541
- /**
542
- * Reads all bytes from the attachment into a contiguous `Uint8Array`.
543
- * Checks `attachment.size` against `maxBytes` *before* any allocation; throws a bounded-read
544
- * error when exceeded (no OOM). Throws if the stream is unavailable or the byte count mismatches.
545
- */
546
395
  getBytes(attachment: BinaryAttachment, maxBytes?: number): Promise<Uint8Array>;
547
- /**
548
- * Reads the attachment and decodes the bytes as UTF-8 text.
549
- * Subject to the same bounded-read safety as `getBytes`.
550
- */
551
396
  getText(attachment: BinaryAttachment, maxBytes?: number): Promise<string>;
552
- /**
553
- * Reads the attachment, decodes as UTF-8 text, and parses as JSON.
554
- * Throws a clear error on invalid JSON. Subject to the same bounded-read safety.
555
- */
556
397
  getJson<T = unknown>(attachment: BinaryAttachment, maxBytes?: number): Promise<T>;
557
398
  }
558
399
  interface ExecutionContext {
559
400
  runId: RunId;
560
401
  workflowId: WorkflowId;
561
402
  parent?: ParentExecutionRef;
562
- /** This run's subworkflow depth (0 = root). */
563
403
  subworkflowDepth: number;
564
- /** Effective activation budget cap for this run (after policy merge). */
565
404
  engineMaxNodeActivations: number;
566
- /** Effective subworkflow nesting cap for this run (after policy merge). */
567
405
  engineMaxSubworkflowDepth: number;
568
406
  now: () => Date;
569
407
  data: RunDataSnapshot;
@@ -571,28 +409,11 @@ interface ExecutionContext {
571
409
  telemetry: ExecutionTelemetry;
572
410
  binary: ExecutionBinaryService;
573
411
  getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
574
- /** Per-item iteration id, set by {@link NodeExecutor} on the ctx passed into runnable `execute`. */
575
412
  iterationId?: NodeIterationId;
576
- /** Item index (0-based) within the current activation's batch; set alongside {@link iterationId}. */
577
413
  itemIndex?: number;
578
- /** When set, this ctx is executing inside a sub-agent triggered by the named parent invocation. */
579
414
  parentInvocationId?: ConnectionInvocationId;
580
- /**
581
- * Present iff the run was started by a TestSuiteOrchestrator. The {@link IsTestRunNode}
582
- * branches on this; assertion-emitting nodes use it to decide whether to record results.
583
- */
584
415
  testContext?: RunTestContext;
585
- /**
586
- * Collections registered in the codemation config, keyed by collection name.
587
- */
588
416
  readonly collections?: CollectionsContext;
589
- /**
590
- * Resolve a DI token from the host container.
591
- * Allows nodes to reach host-side services (e.g. `InboxChannelResolverToken`)
592
- * without importing host code. Wired by `DefaultExecutionContextFactory`; throws
593
- * a clear error when no resolver is configured (e.g. in unit tests that don't
594
- * set up the full container).
595
- */
596
417
  resolve<T>(token: TypeToken<T>): T;
597
418
  }
598
419
  interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase> extends ExecutionContext {
@@ -601,18 +422,8 @@ interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase>
601
422
  config: TConfig;
602
423
  telemetry: NodeExecutionTelemetry;
603
424
  binary: NodeBinaryAttachmentService;
604
- /**
605
- * Present when this node activation is a HITL resume.
606
- * The node checks `ctx.resumeContext !== undefined` and takes the resume branch.
607
- */
608
425
  resumeContext?: ResumeContext;
609
426
  }
610
- /**
611
- * Per-item runnable node: return JSON, an array to fan-out on `main`, an explicit `Item`, or {@link emitPorts}
612
- * for multi-port emission. Engine applies `inputSchema.parse(item.json)` and passes the result as `args.input`
613
- * (wire `item.json` is unchanged). Transform helpers may opt into binary preservation, while routers and
614
- * pass-through nodes should return explicit items when they need to preserve full item state.
615
- */
616
427
  interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown> {
617
428
  readonly input: TInputJson$1;
618
429
  readonly item: Item;
@@ -622,14 +433,7 @@ interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> =
622
433
  }
623
434
  interface RunnableNode<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown, _TOutputJson = unknown> {
624
435
  readonly kind: "node";
625
- /**
626
- * Declared output ports (e.g. `["main"]`).
627
- *
628
- * Prefer describing dynamic router ports (Switch) and fixed multi-ports (If true/false)
629
- * via {@link NodeConfigBase.declaredOutputPorts}. Engine defaults to `["main"]` when omitted.
630
- */
631
436
  readonly outputPorts?: ReadonlyArray<OutputPortKey>;
632
- /** When omitted, engine uses {@link RunnableNodeConfig.inputSchema} or `z.unknown()`. */
633
437
  readonly inputSchema?: ZodType<TInputJson$1>;
634
438
  execute(args: RunnableNodeExecuteArgs<TConfig, TInputJson$1>): Promise<unknown> | unknown;
635
439
  }
package/dist/index.d.ts CHANGED
@@ -3,11 +3,6 @@ import { InjectionToken as TypeToken } from "tsyringe";
3
3
  import { ReadableStream } from "node:stream/web";
4
4
 
5
5
  //#region ../core/src/contracts/baseTypes.d.ts
6
- /**
7
- * Minimal base types that have no dependencies on other contracts.
8
- * Used by credentialTypes, workflowTypes, and other contract layers
9
- * to avoid circular dependencies.
10
- */
11
6
  type WorkflowId = string;
12
7
  type NodeId = string;
13
8
  type OutputPortKey = string;
@@ -92,13 +87,6 @@ interface TelemetrySpanScope extends TelemetryScope {
92
87
  readonly traceId: string;
93
88
  readonly spanId: string;
94
89
  end(args?: TelemetrySpanEnd): Promise<void> | void;
95
- /**
96
- * Lift this span into a {@link NodeExecutionTelemetry} scoped to a different (nodeId, activationId).
97
- * Children created via the returned telemetry's `startChildSpan` get this span as their parent.
98
- *
99
- * Used at the sub-agent boundary so that nested runtime telemetry parents under the agent.tool.call
100
- * span instead of the orchestrator's node-level span.
101
- */
102
90
  asNodeTelemetry(args: Readonly<{
103
91
  nodeId: NodeId;
104
92
  activationId: NodeActivationId;
@@ -117,30 +105,21 @@ interface ExecutionTelemetry extends TelemetryScope {
117
105
  }
118
106
  //#endregion
119
107
  //#region ../core/src/contracts/retryPolicySpec.types.d.ts
120
- /**
121
- * In-process retry policy for runnable nodes. Serialized configs use the same
122
- * `kind` discriminator (`JSON.stringify` / persisted workflows).
123
- *
124
- * `maxAttempts` is the total number of tries including the first (e.g. 3 means up to 2 delays after failures).
125
- */
126
108
  type RetryPolicySpec = NoneRetryPolicySpec | FixedRetryPolicySpec | ExponentialRetryPolicySpec;
127
109
  interface NoneRetryPolicySpec {
128
110
  readonly kind: "none";
129
111
  }
130
112
  interface FixedRetryPolicySpec {
131
113
  readonly kind: "fixed";
132
- /** Total attempts including the first execution. Must be >= 1. */
133
114
  readonly maxAttempts: number;
134
115
  readonly delayMs: number;
135
116
  }
136
117
  interface ExponentialRetryPolicySpec {
137
118
  readonly kind: "exponential";
138
- /** Total attempts including the first execution. Must be >= 1. */
139
119
  readonly maxAttempts: number;
140
120
  readonly initialDelayMs: number;
141
121
  readonly multiplier: number;
142
122
  readonly maxDelayMs?: number;
143
- /** When true, each delay is multiplied by a random factor in [1, 1.2). */
144
123
  readonly jitter?: boolean;
145
124
  }
146
125
  //#endregion
@@ -156,38 +135,22 @@ type CredentialRequirement = Readonly<{
156
135
  }>;
157
136
  //#endregion
158
137
  //#region ../core/src/contracts/collectionTypes.d.ts
159
- /**
160
- * Represents a typed store for a single collection.
161
- * All rows include auto-managed id, created_at, and updated_at fields.
162
- */
163
138
  interface CollectionStore<TRow extends Record<string, unknown> = Record<string, unknown>> {
164
- /**
165
- * Insert a new row. id, created_at, and updated_at are auto-populated.
166
- */
167
139
  insert(row: TRow): Promise<TRow & {
168
140
  id: string;
169
141
  created_at: Date;
170
142
  updated_at: Date;
171
143
  }>;
172
- /**
173
- * Get a single row by id.
174
- */
175
144
  get(id: string): Promise<(TRow & {
176
145
  id: string;
177
146
  created_at: Date;
178
147
  updated_at: Date;
179
148
  }) | null>;
180
- /**
181
- * Find a single row matching the provided filter.
182
- */
183
149
  findOne(filter: Partial<TRow>): Promise<(TRow & {
184
150
  id: string;
185
151
  created_at: Date;
186
152
  updated_at: Date;
187
153
  }) | null>;
188
- /**
189
- * List rows with optional pagination and filtering.
190
- */
191
154
  list(opts?: {
192
155
  limit?: number;
193
156
  offset?: number;
@@ -200,41 +163,21 @@ interface CollectionStore<TRow extends Record<string, unknown> = Record<string,
200
163
  }>;
201
164
  total: number;
202
165
  }>;
203
- /**
204
- * Update a row by id with partial data.
205
- */
206
166
  update(id: string, patch: Partial<TRow>): Promise<TRow & {
207
167
  id: string;
208
168
  created_at: Date;
209
169
  updated_at: Date;
210
170
  }>;
211
- /**
212
- * Delete a row by id. Hard delete only (no soft delete).
213
- */
214
171
  delete(id: string): Promise<{
215
172
  deleted: boolean;
216
173
  }>;
217
174
  }
218
- /**
219
- * Runtime collections context: keyed by collection name.
220
- */
221
175
  type CollectionsContext = Readonly<Record<string, CollectionStore>>;
222
176
  //#endregion
223
177
  //#region ../core/src/contracts/runTypes.d.ts
224
- /**
225
- * Test-suite linkage for a run. When set, this run was started by a TestSuiteOrchestrator
226
- * as one test case inside a TestSuiteRun. The `IsTestRun` node and host-side persisters key
227
- * off the presence of this field. Subworkflow runs inherit it from their parent run.
228
- */
229
178
  interface RunTestContext {
230
179
  readonly testSuiteRunId: string;
231
180
  readonly testCaseIndex: number;
232
- /**
233
- * Optional human-friendly label for this test case (e.g. an email subject when fixtures
234
- * are loaded from a mailbox). Resolved per item by `TestTrigger.caseLabel(item)` if set,
235
- * persisted on `Run.test_case_label` so the Tests-tab tree-table can show "RFQ for batch 14"
236
- * instead of "run_1777755971399_bbb86beac1396".
237
- */
238
181
  readonly testCaseLabel?: string;
239
182
  }
240
183
  type NodeInputsByPort = Readonly<Record<InputPortKey, Items>>;
@@ -245,9 +188,7 @@ interface NodeExecutionError {
245
188
  stack?: string;
246
189
  details?: JsonValue;
247
190
  }
248
- /** Stable id for a single connection invocation row in {@link ConnectionInvocationRecord}. */
249
191
  type ConnectionInvocationId = string;
250
- /** Arguments for appending a {@link ConnectionInvocationRecord} (engine fills run/workflow ids and timestamps). */
251
192
  type ConnectionInvocationAppendArgs = Readonly<{
252
193
  invocationId: ConnectionInvocationId;
253
194
  connectionNodeId: NodeId;
@@ -284,83 +225,31 @@ interface NodeConfigBase {
284
225
  readonly name?: string;
285
226
  readonly id?: NodeId;
286
227
  readonly icon?: string;
287
- /**
288
- * Plain-language, non-technical explanation of what this node does, surfaced in the workflow
289
- * inspector / node properties sidebar. A first-class config option every authorable node accepts
290
- * directly (alongside `id`), so it flows into the persisted config the mappers read. Distinct from
291
- * {@link inspectorSummary} (config-derived label/value rows).
292
- */
293
228
  readonly description?: string;
294
229
  readonly execution?: Readonly<{
295
230
  hint?: "local" | "worker";
296
231
  queue?: string;
297
232
  }>;
298
- /** In-process execute retries (runnable nodes). Triggers typically omit this. */
299
233
  readonly retryPolicy?: RetryPolicySpec;
300
- /** Recover from execute failures; return outputs to continue, or rethrow to fail the node. */
301
234
  readonly nodeErrorHandler?: NodeErrorHandlerSpec;
302
- /**
303
- * When true, edges carrying zero items on an output port still schedule single-input downstream nodes.
304
- * Decided from the **source** node that produced the (empty) output. Default (false/undefined): empty
305
- * main batches skip downstream execution and propagate the empty path.
306
- */
307
235
  readonly continueWhenEmptyOutput?: boolean;
308
- /**
309
- * Declared I/O port names for canvas authoring (unioned with ports inferred from edges).
310
- * Use for dynamic routers (Switch) and future error ports.
311
- */
312
236
  readonly declaredOutputPorts?: ReadonlyArray<OutputPortKey>;
313
237
  readonly declaredInputPorts?: ReadonlyArray<InputPortKey>;
314
238
  getCredentialRequirements?(): ReadonlyArray<CredentialRequirement>;
315
- /**
316
- * Marker: this node emits {@link import("./assertionTypes").AssertionResult}-shaped items on its
317
- * `main` port. The TestSuiteOrchestrator (and host-side TestAssertionPersister) listen for
318
- * `nodeCompleted` events from nodes with this flag set, and persist their output items as
319
- * TestAssertion records (only when the run carries a `testContext`). Set on assertion node
320
- * configs (e.g. `AssertionNodeConfig`, `StringEqualsAssertionNodeConfig`).
321
- */
322
239
  readonly emitsAssertions?: true;
323
- /**
324
- * Static configuration summary surfaced in the workflow inspector — the design-time
325
- * "what does this node do" panel that renders before any run telemetry exists.
326
- *
327
- * Return 2–6 short label/value pairs derived from this config (method + url for an HTTP
328
- * call, model + tool list for an agent, schedule + timezone for a cron trigger, etc.).
329
- * Values are truncated by the UI; aim for one line each. Return `undefined` to opt out
330
- * — the inspector hides the section when no rows are produced.
331
- *
332
- * Implement on the config class instance so the function can read sibling config fields.
333
- * `defineNode({ inspectorSummary })` plumbs through to this.
334
- */
335
240
  inspectorSummary?(): ReadonlyArray<NodeInspectorSummaryRow> | undefined;
336
241
  }
337
- /**
338
- * One row of a node's static configuration summary. See {@link NodeConfigBase.inspectorSummary}.
339
- */
340
242
  interface NodeInspectorSummaryRow {
341
243
  readonly label: string;
342
244
  readonly value: string;
343
245
  }
344
246
  declare const runnableNodeInputType: unique symbol;
345
247
  declare const runnableNodeOutputType: unique symbol;
346
- /**
347
- * Runnable node: **`TInputJson`** is what **`inputSchema`** validates on **`item.json`** (the wire payload).
348
- * **`TOutputJson`** is emitted `item.json` on outputs.
349
- */
350
248
  interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown> extends NodeConfigBase {
351
249
  readonly kind: "node";
352
250
  readonly [runnableNodeInputType]?: TInputJson$1;
353
251
  readonly [runnableNodeOutputType]?: TOutputJson$1;
354
- /**
355
- * Optional Zod input contract for {@link RunnableNode} when not set on the node class.
356
- * Resolution order: node instance `inputSchema`, then config `inputSchema`, then `z.unknown()`.
357
- */
358
252
  readonly inputSchema?: ZodType<TInputJson$1>;
359
- /**
360
- * When an activation receives **zero** input items, the engine normally runs `execute` zero times.
361
- * Set to **`runOnce`** to run `execute` once with an empty `items` batch (and a synthetic wire item for schema parsing).
362
- * Used by batch-style callback nodes (built-in `Callback`) so `callback([], ctx)` still runs.
363
- */
364
253
  readonly emptyBatchExecution?: "skip" | "runOnce";
365
254
  }
366
255
  type PairedItemRef = Readonly<{
@@ -395,27 +284,14 @@ type Items<TJson = unknown> = ReadonlyArray<Item<TJson>>;
395
284
  type NodeOutputs = Partial<Record<OutputPortKey, Items>>;
396
285
  type RunId = string;
397
286
  type NodeActivationId = string;
398
- /**
399
- * One per-item iteration of a runnable node's execute loop. Refines `NodeActivationId` for
400
- * per-item connection invocations and telemetry. Undefined when the executing node is a batch
401
- * node or trigger that does not iterate items.
402
- */
403
287
  type NodeIterationId = string;
404
288
  interface ParentExecutionRef {
405
289
  runId: RunId;
406
290
  workflowId: WorkflowId;
407
291
  nodeId: NodeId;
408
- /** Subworkflow depth of the **spawning** run (0 = root). Passed when starting a child run. */
409
292
  subworkflowDepth?: number;
410
- /** Effective max node activations from the parent run (propagated to child policy merge). */
411
293
  engineMaxNodeActivations?: number;
412
- /** Effective max subworkflow depth from the parent run (propagated to child policy merge). */
413
294
  engineMaxSubworkflowDepth?: number;
414
- /**
415
- * Test-suite linkage inherited by the child subworkflow run. Set by whichever node
416
- * spawns the subworkflow when its own `ctx.testContext` is present, so assertions
417
- * emitted inside a subworkflow land under the correct parent test case.
418
- */
419
295
  testContext?: RunTestContext;
420
296
  }
421
297
  interface RunDataSnapshot {
@@ -436,36 +312,19 @@ interface NodeErrorHandler {
436
312
  type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandler;
437
313
  //#endregion
438
314
  //#region ../core/src/contracts/runtimeTypes.d.ts
439
- /** Opaque unique identifier for a single HumanTask instance. */
440
315
  type HumanTaskId = string;
441
- /**
442
- * Minimal handle handed to the `deliver` callback so it can route to the correct
443
- * inbox channel.
444
- */
445
316
  interface HumanTaskHandle {
446
317
  readonly taskId: HumanTaskId;
447
318
  readonly runId: string;
448
319
  readonly nodeId: string;
449
320
  readonly expiresAt: Date;
450
- /** TODO: real signed URL; placeholder empty string for now. */
451
321
  readonly resumeUrl: string;
452
- /**
453
- * Arbitrary JSON metadata copied from `SuspensionRequest.request.metadata` at suspension time.
454
- * Used by the agent runtime to round-trip the `agentCheckpoint` back to the
455
- * resumed node via `ctx.resumeContext.task.metadata`.
456
- */
457
322
  readonly metadata?: Readonly<Record<string, JsonValue>>;
458
323
  }
459
- /** Identity of the person who made a decision on the task. */
460
324
  interface HumanTaskActor {
461
325
  readonly actorId: string;
462
326
  readonly displayName?: string;
463
327
  }
464
- /**
465
- * Resume context injected into `NodeExecutionContext` when the engine re-activates
466
- * a previously suspended node. `defineHumanApprovalNode` wraps this with parsed
467
- * `TDecision`; at the engine layer `decision.value` is `unknown`.
468
- */
469
328
  interface ResumeContext {
470
329
  readonly decision: Readonly<{
471
330
  kind: "decided";
@@ -506,11 +365,6 @@ interface NodeExecutionStatePublisher {
506
365
  error: Error;
507
366
  }): Promise<void>;
508
367
  appendConnectionInvocation(args: ConnectionInvocationAppendArgs): Promise<void>;
509
- /**
510
- * Annotates the current snapshot for `nodeId` with the id of the child run spawned by a
511
- * SubWorkflow invocation. Called from `SubWorkflowNode.execute` after `runById` resolves.
512
- * The engine's subsequent `markCompleted` call preserves the value via `previous.childRunId`.
513
- */
514
368
  setChildRunId?(args: {
515
369
  nodeId: NodeId;
516
370
  childRunId: RunId;
@@ -538,32 +392,16 @@ interface ExecutionBinaryService {
538
392
  activationId: NodeActivationId;
539
393
  }): NodeBinaryAttachmentService;
540
394
  openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
541
- /**
542
- * Reads all bytes from the attachment into a contiguous `Uint8Array`.
543
- * Checks `attachment.size` against `maxBytes` *before* any allocation; throws a bounded-read
544
- * error when exceeded (no OOM). Throws if the stream is unavailable or the byte count mismatches.
545
- */
546
395
  getBytes(attachment: BinaryAttachment, maxBytes?: number): Promise<Uint8Array>;
547
- /**
548
- * Reads the attachment and decodes the bytes as UTF-8 text.
549
- * Subject to the same bounded-read safety as `getBytes`.
550
- */
551
396
  getText(attachment: BinaryAttachment, maxBytes?: number): Promise<string>;
552
- /**
553
- * Reads the attachment, decodes as UTF-8 text, and parses as JSON.
554
- * Throws a clear error on invalid JSON. Subject to the same bounded-read safety.
555
- */
556
397
  getJson<T = unknown>(attachment: BinaryAttachment, maxBytes?: number): Promise<T>;
557
398
  }
558
399
  interface ExecutionContext {
559
400
  runId: RunId;
560
401
  workflowId: WorkflowId;
561
402
  parent?: ParentExecutionRef;
562
- /** This run's subworkflow depth (0 = root). */
563
403
  subworkflowDepth: number;
564
- /** Effective activation budget cap for this run (after policy merge). */
565
404
  engineMaxNodeActivations: number;
566
- /** Effective subworkflow nesting cap for this run (after policy merge). */
567
405
  engineMaxSubworkflowDepth: number;
568
406
  now: () => Date;
569
407
  data: RunDataSnapshot;
@@ -571,28 +409,11 @@ interface ExecutionContext {
571
409
  telemetry: ExecutionTelemetry;
572
410
  binary: ExecutionBinaryService;
573
411
  getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
574
- /** Per-item iteration id, set by {@link NodeExecutor} on the ctx passed into runnable `execute`. */
575
412
  iterationId?: NodeIterationId;
576
- /** Item index (0-based) within the current activation's batch; set alongside {@link iterationId}. */
577
413
  itemIndex?: number;
578
- /** When set, this ctx is executing inside a sub-agent triggered by the named parent invocation. */
579
414
  parentInvocationId?: ConnectionInvocationId;
580
- /**
581
- * Present iff the run was started by a TestSuiteOrchestrator. The {@link IsTestRunNode}
582
- * branches on this; assertion-emitting nodes use it to decide whether to record results.
583
- */
584
415
  testContext?: RunTestContext;
585
- /**
586
- * Collections registered in the codemation config, keyed by collection name.
587
- */
588
416
  readonly collections?: CollectionsContext;
589
- /**
590
- * Resolve a DI token from the host container.
591
- * Allows nodes to reach host-side services (e.g. `InboxChannelResolverToken`)
592
- * without importing host code. Wired by `DefaultExecutionContextFactory`; throws
593
- * a clear error when no resolver is configured (e.g. in unit tests that don't
594
- * set up the full container).
595
- */
596
417
  resolve<T>(token: TypeToken<T>): T;
597
418
  }
598
419
  interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase> extends ExecutionContext {
@@ -601,18 +422,8 @@ interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase>
601
422
  config: TConfig;
602
423
  telemetry: NodeExecutionTelemetry;
603
424
  binary: NodeBinaryAttachmentService;
604
- /**
605
- * Present when this node activation is a HITL resume.
606
- * The node checks `ctx.resumeContext !== undefined` and takes the resume branch.
607
- */
608
425
  resumeContext?: ResumeContext;
609
426
  }
610
- /**
611
- * Per-item runnable node: return JSON, an array to fan-out on `main`, an explicit `Item`, or {@link emitPorts}
612
- * for multi-port emission. Engine applies `inputSchema.parse(item.json)` and passes the result as `args.input`
613
- * (wire `item.json` is unchanged). Transform helpers may opt into binary preservation, while routers and
614
- * pass-through nodes should return explicit items when they need to preserve full item state.
615
- */
616
427
  interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown> {
617
428
  readonly input: TInputJson$1;
618
429
  readonly item: Item;
@@ -622,14 +433,7 @@ interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> =
622
433
  }
623
434
  interface RunnableNode<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown, _TOutputJson = unknown> {
624
435
  readonly kind: "node";
625
- /**
626
- * Declared output ports (e.g. `["main"]`).
627
- *
628
- * Prefer describing dynamic router ports (Switch) and fixed multi-ports (If true/false)
629
- * via {@link NodeConfigBase.declaredOutputPorts}. Engine defaults to `["main"]` when omitted.
630
- */
631
436
  readonly outputPorts?: ReadonlyArray<OutputPortKey>;
632
- /** When omitted, engine uses {@link RunnableNodeConfig.inputSchema} or `z.unknown()`. */
633
437
  readonly inputSchema?: ZodType<TInputJson$1>;
634
438
  execute(args: RunnableNodeExecuteArgs<TConfig, TInputJson$1>): Promise<unknown> | unknown;
635
439
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemation/node-example",
3
- "version": "0.0.44",
3
+ "version": "0.0.45",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -28,7 +28,7 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
- "@codemation/core": "0.14.0"
31
+ "@codemation/core": "0.15.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^25.3.5",