@codemation/node-example 0.0.43 → 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,19 @@
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
+
10
+ ## 0.0.44
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [[`675260a`](https://github.com/MadeRelevant/codemation/commit/675260aa7a30c55a34b5a6107ad2222937f4a769), [`13f9f11`](https://github.com/MadeRelevant/codemation/commit/13f9f11454855f44cd0849ea7e8f0c60f4a28964), [`675260a`](https://github.com/MadeRelevant/codemation/commit/675260aa7a30c55a34b5a6107ad2222937f4a769), [`675260a`](https://github.com/MadeRelevant/codemation/commit/675260aa7a30c55a34b5a6107ad2222937f4a769), [`0881b46`](https://github.com/MadeRelevant/codemation/commit/0881b4676d2db29f36415d9b47709128d4c15e0e)]:
15
+ - @codemation/core@0.14.0
16
+
3
17
  ## 0.0.43
4
18
 
5
19
  ### 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,76 +225,31 @@ interface NodeConfigBase {
284
225
  readonly name?: string;
285
226
  readonly id?: NodeId;
286
227
  readonly icon?: string;
228
+ readonly description?: string;
287
229
  readonly execution?: Readonly<{
288
230
  hint?: "local" | "worker";
289
231
  queue?: string;
290
232
  }>;
291
- /** In-process execute retries (runnable nodes). Triggers typically omit this. */
292
233
  readonly retryPolicy?: RetryPolicySpec;
293
- /** Recover from execute failures; return outputs to continue, or rethrow to fail the node. */
294
234
  readonly nodeErrorHandler?: NodeErrorHandlerSpec;
295
- /**
296
- * When true, edges carrying zero items on an output port still schedule single-input downstream nodes.
297
- * Decided from the **source** node that produced the (empty) output. Default (false/undefined): empty
298
- * main batches skip downstream execution and propagate the empty path.
299
- */
300
235
  readonly continueWhenEmptyOutput?: boolean;
301
- /**
302
- * Declared I/O port names for canvas authoring (unioned with ports inferred from edges).
303
- * Use for dynamic routers (Switch) and future error ports.
304
- */
305
236
  readonly declaredOutputPorts?: ReadonlyArray<OutputPortKey>;
306
237
  readonly declaredInputPorts?: ReadonlyArray<InputPortKey>;
307
238
  getCredentialRequirements?(): ReadonlyArray<CredentialRequirement>;
308
- /**
309
- * Marker: this node emits {@link import("./assertionTypes").AssertionResult}-shaped items on its
310
- * `main` port. The TestSuiteOrchestrator (and host-side TestAssertionPersister) listen for
311
- * `nodeCompleted` events from nodes with this flag set, and persist their output items as
312
- * TestAssertion records (only when the run carries a `testContext`). Set on assertion node
313
- * configs (e.g. `AssertionNodeConfig`, `StringEqualsAssertionNodeConfig`).
314
- */
315
239
  readonly emitsAssertions?: true;
316
- /**
317
- * Static configuration summary surfaced in the workflow inspector — the design-time
318
- * "what does this node do" panel that renders before any run telemetry exists.
319
- *
320
- * Return 2–6 short label/value pairs derived from this config (method + url for an HTTP
321
- * call, model + tool list for an agent, schedule + timezone for a cron trigger, etc.).
322
- * Values are truncated by the UI; aim for one line each. Return `undefined` to opt out
323
- * — the inspector hides the section when no rows are produced.
324
- *
325
- * Implement on the config class instance so the function can read sibling config fields.
326
- * `defineNode({ inspectorSummary })` plumbs through to this.
327
- */
328
240
  inspectorSummary?(): ReadonlyArray<NodeInspectorSummaryRow> | undefined;
329
241
  }
330
- /**
331
- * One row of a node's static configuration summary. See {@link NodeConfigBase.inspectorSummary}.
332
- */
333
242
  interface NodeInspectorSummaryRow {
334
243
  readonly label: string;
335
244
  readonly value: string;
336
245
  }
337
246
  declare const runnableNodeInputType: unique symbol;
338
247
  declare const runnableNodeOutputType: unique symbol;
339
- /**
340
- * Runnable node: **`TInputJson`** is what **`inputSchema`** validates on **`item.json`** (the wire payload).
341
- * **`TOutputJson`** is emitted `item.json` on outputs.
342
- */
343
248
  interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown> extends NodeConfigBase {
344
249
  readonly kind: "node";
345
250
  readonly [runnableNodeInputType]?: TInputJson$1;
346
251
  readonly [runnableNodeOutputType]?: TOutputJson$1;
347
- /**
348
- * Optional Zod input contract for {@link RunnableNode} when not set on the node class.
349
- * Resolution order: node instance `inputSchema`, then config `inputSchema`, then `z.unknown()`.
350
- */
351
252
  readonly inputSchema?: ZodType<TInputJson$1>;
352
- /**
353
- * When an activation receives **zero** input items, the engine normally runs `execute` zero times.
354
- * Set to **`runOnce`** to run `execute` once with an empty `items` batch (and a synthetic wire item for schema parsing).
355
- * Used by batch-style callback nodes (built-in `Callback`) so `callback([], ctx)` still runs.
356
- */
357
253
  readonly emptyBatchExecution?: "skip" | "runOnce";
358
254
  }
359
255
  type PairedItemRef = Readonly<{
@@ -388,27 +284,14 @@ type Items<TJson = unknown> = ReadonlyArray<Item<TJson>>;
388
284
  type NodeOutputs = Partial<Record<OutputPortKey, Items>>;
389
285
  type RunId = string;
390
286
  type NodeActivationId = string;
391
- /**
392
- * One per-item iteration of a runnable node's execute loop. Refines `NodeActivationId` for
393
- * per-item connection invocations and telemetry. Undefined when the executing node is a batch
394
- * node or trigger that does not iterate items.
395
- */
396
287
  type NodeIterationId = string;
397
288
  interface ParentExecutionRef {
398
289
  runId: RunId;
399
290
  workflowId: WorkflowId;
400
291
  nodeId: NodeId;
401
- /** Subworkflow depth of the **spawning** run (0 = root). Passed when starting a child run. */
402
292
  subworkflowDepth?: number;
403
- /** Effective max node activations from the parent run (propagated to child policy merge). */
404
293
  engineMaxNodeActivations?: number;
405
- /** Effective max subworkflow depth from the parent run (propagated to child policy merge). */
406
294
  engineMaxSubworkflowDepth?: number;
407
- /**
408
- * Test-suite linkage inherited by the child subworkflow run. Set by whichever node
409
- * spawns the subworkflow when its own `ctx.testContext` is present, so assertions
410
- * emitted inside a subworkflow land under the correct parent test case.
411
- */
412
295
  testContext?: RunTestContext;
413
296
  }
414
297
  interface RunDataSnapshot {
@@ -429,36 +312,19 @@ interface NodeErrorHandler {
429
312
  type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandler;
430
313
  //#endregion
431
314
  //#region ../core/src/contracts/runtimeTypes.d.ts
432
- /** Opaque unique identifier for a single HumanTask instance. */
433
315
  type HumanTaskId = string;
434
- /**
435
- * Minimal handle handed to the `deliver` callback so it can route to the correct
436
- * inbox channel.
437
- */
438
316
  interface HumanTaskHandle {
439
317
  readonly taskId: HumanTaskId;
440
318
  readonly runId: string;
441
319
  readonly nodeId: string;
442
320
  readonly expiresAt: Date;
443
- /** TODO: real signed URL; placeholder empty string for now. */
444
321
  readonly resumeUrl: string;
445
- /**
446
- * Arbitrary JSON metadata copied from `SuspensionRequest.request.metadata` at suspension time.
447
- * Used by the agent runtime to round-trip the `agentCheckpoint` back to the
448
- * resumed node via `ctx.resumeContext.task.metadata`.
449
- */
450
322
  readonly metadata?: Readonly<Record<string, JsonValue>>;
451
323
  }
452
- /** Identity of the person who made a decision on the task. */
453
324
  interface HumanTaskActor {
454
325
  readonly actorId: string;
455
326
  readonly displayName?: string;
456
327
  }
457
- /**
458
- * Resume context injected into `NodeExecutionContext` when the engine re-activates
459
- * a previously suspended node. `defineHumanApprovalNode` wraps this with parsed
460
- * `TDecision`; at the engine layer `decision.value` is `unknown`.
461
- */
462
328
  interface ResumeContext {
463
329
  readonly decision: Readonly<{
464
330
  kind: "decided";
@@ -499,11 +365,6 @@ interface NodeExecutionStatePublisher {
499
365
  error: Error;
500
366
  }): Promise<void>;
501
367
  appendConnectionInvocation(args: ConnectionInvocationAppendArgs): Promise<void>;
502
- /**
503
- * Annotates the current snapshot for `nodeId` with the id of the child run spawned by a
504
- * SubWorkflow invocation. Called from `SubWorkflowNode.execute` after `runById` resolves.
505
- * The engine's subsequent `markCompleted` call preserves the value via `previous.childRunId`.
506
- */
507
368
  setChildRunId?(args: {
508
369
  nodeId: NodeId;
509
370
  childRunId: RunId;
@@ -531,32 +392,16 @@ interface ExecutionBinaryService {
531
392
  activationId: NodeActivationId;
532
393
  }): NodeBinaryAttachmentService;
533
394
  openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
534
- /**
535
- * Reads all bytes from the attachment into a contiguous `Uint8Array`.
536
- * Checks `attachment.size` against `maxBytes` *before* any allocation; throws a bounded-read
537
- * error when exceeded (no OOM). Throws if the stream is unavailable or the byte count mismatches.
538
- */
539
395
  getBytes(attachment: BinaryAttachment, maxBytes?: number): Promise<Uint8Array>;
540
- /**
541
- * Reads the attachment and decodes the bytes as UTF-8 text.
542
- * Subject to the same bounded-read safety as `getBytes`.
543
- */
544
396
  getText(attachment: BinaryAttachment, maxBytes?: number): Promise<string>;
545
- /**
546
- * Reads the attachment, decodes as UTF-8 text, and parses as JSON.
547
- * Throws a clear error on invalid JSON. Subject to the same bounded-read safety.
548
- */
549
397
  getJson<T = unknown>(attachment: BinaryAttachment, maxBytes?: number): Promise<T>;
550
398
  }
551
399
  interface ExecutionContext {
552
400
  runId: RunId;
553
401
  workflowId: WorkflowId;
554
402
  parent?: ParentExecutionRef;
555
- /** This run's subworkflow depth (0 = root). */
556
403
  subworkflowDepth: number;
557
- /** Effective activation budget cap for this run (after policy merge). */
558
404
  engineMaxNodeActivations: number;
559
- /** Effective subworkflow nesting cap for this run (after policy merge). */
560
405
  engineMaxSubworkflowDepth: number;
561
406
  now: () => Date;
562
407
  data: RunDataSnapshot;
@@ -564,28 +409,11 @@ interface ExecutionContext {
564
409
  telemetry: ExecutionTelemetry;
565
410
  binary: ExecutionBinaryService;
566
411
  getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
567
- /** Per-item iteration id, set by {@link NodeExecutor} on the ctx passed into runnable `execute`. */
568
412
  iterationId?: NodeIterationId;
569
- /** Item index (0-based) within the current activation's batch; set alongside {@link iterationId}. */
570
413
  itemIndex?: number;
571
- /** When set, this ctx is executing inside a sub-agent triggered by the named parent invocation. */
572
414
  parentInvocationId?: ConnectionInvocationId;
573
- /**
574
- * Present iff the run was started by a TestSuiteOrchestrator. The {@link IsTestRunNode}
575
- * branches on this; assertion-emitting nodes use it to decide whether to record results.
576
- */
577
415
  testContext?: RunTestContext;
578
- /**
579
- * Collections registered in the codemation config, keyed by collection name.
580
- */
581
416
  readonly collections?: CollectionsContext;
582
- /**
583
- * Resolve a DI token from the host container.
584
- * Allows nodes to reach host-side services (e.g. `InboxChannelResolverToken`)
585
- * without importing host code. Wired by `DefaultExecutionContextFactory`; throws
586
- * a clear error when no resolver is configured (e.g. in unit tests that don't
587
- * set up the full container).
588
- */
589
417
  resolve<T>(token: TypeToken<T>): T;
590
418
  }
591
419
  interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase> extends ExecutionContext {
@@ -594,18 +422,8 @@ interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase>
594
422
  config: TConfig;
595
423
  telemetry: NodeExecutionTelemetry;
596
424
  binary: NodeBinaryAttachmentService;
597
- /**
598
- * Present when this node activation is a HITL resume.
599
- * The node checks `ctx.resumeContext !== undefined` and takes the resume branch.
600
- */
601
425
  resumeContext?: ResumeContext;
602
426
  }
603
- /**
604
- * Per-item runnable node: return JSON, an array to fan-out on `main`, an explicit `Item`, or {@link emitPorts}
605
- * for multi-port emission. Engine applies `inputSchema.parse(item.json)` and passes the result as `args.input`
606
- * (wire `item.json` is unchanged). Transform helpers may opt into binary preservation, while routers and
607
- * pass-through nodes should return explicit items when they need to preserve full item state.
608
- */
609
427
  interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown> {
610
428
  readonly input: TInputJson$1;
611
429
  readonly item: Item;
@@ -615,14 +433,7 @@ interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> =
615
433
  }
616
434
  interface RunnableNode<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown, _TOutputJson = unknown> {
617
435
  readonly kind: "node";
618
- /**
619
- * Declared output ports (e.g. `["main"]`).
620
- *
621
- * Prefer describing dynamic router ports (Switch) and fixed multi-ports (If true/false)
622
- * via {@link NodeConfigBase.declaredOutputPorts}. Engine defaults to `["main"]` when omitted.
623
- */
624
436
  readonly outputPorts?: ReadonlyArray<OutputPortKey>;
625
- /** When omitted, engine uses {@link RunnableNodeConfig.inputSchema} or `z.unknown()`. */
626
437
  readonly inputSchema?: ZodType<TInputJson$1>;
627
438
  execute(args: RunnableNodeExecuteArgs<TConfig, TInputJson$1>): Promise<unknown> | unknown;
628
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,76 +225,31 @@ interface NodeConfigBase {
284
225
  readonly name?: string;
285
226
  readonly id?: NodeId;
286
227
  readonly icon?: string;
228
+ readonly description?: string;
287
229
  readonly execution?: Readonly<{
288
230
  hint?: "local" | "worker";
289
231
  queue?: string;
290
232
  }>;
291
- /** In-process execute retries (runnable nodes). Triggers typically omit this. */
292
233
  readonly retryPolicy?: RetryPolicySpec;
293
- /** Recover from execute failures; return outputs to continue, or rethrow to fail the node. */
294
234
  readonly nodeErrorHandler?: NodeErrorHandlerSpec;
295
- /**
296
- * When true, edges carrying zero items on an output port still schedule single-input downstream nodes.
297
- * Decided from the **source** node that produced the (empty) output. Default (false/undefined): empty
298
- * main batches skip downstream execution and propagate the empty path.
299
- */
300
235
  readonly continueWhenEmptyOutput?: boolean;
301
- /**
302
- * Declared I/O port names for canvas authoring (unioned with ports inferred from edges).
303
- * Use for dynamic routers (Switch) and future error ports.
304
- */
305
236
  readonly declaredOutputPorts?: ReadonlyArray<OutputPortKey>;
306
237
  readonly declaredInputPorts?: ReadonlyArray<InputPortKey>;
307
238
  getCredentialRequirements?(): ReadonlyArray<CredentialRequirement>;
308
- /**
309
- * Marker: this node emits {@link import("./assertionTypes").AssertionResult}-shaped items on its
310
- * `main` port. The TestSuiteOrchestrator (and host-side TestAssertionPersister) listen for
311
- * `nodeCompleted` events from nodes with this flag set, and persist their output items as
312
- * TestAssertion records (only when the run carries a `testContext`). Set on assertion node
313
- * configs (e.g. `AssertionNodeConfig`, `StringEqualsAssertionNodeConfig`).
314
- */
315
239
  readonly emitsAssertions?: true;
316
- /**
317
- * Static configuration summary surfaced in the workflow inspector — the design-time
318
- * "what does this node do" panel that renders before any run telemetry exists.
319
- *
320
- * Return 2–6 short label/value pairs derived from this config (method + url for an HTTP
321
- * call, model + tool list for an agent, schedule + timezone for a cron trigger, etc.).
322
- * Values are truncated by the UI; aim for one line each. Return `undefined` to opt out
323
- * — the inspector hides the section when no rows are produced.
324
- *
325
- * Implement on the config class instance so the function can read sibling config fields.
326
- * `defineNode({ inspectorSummary })` plumbs through to this.
327
- */
328
240
  inspectorSummary?(): ReadonlyArray<NodeInspectorSummaryRow> | undefined;
329
241
  }
330
- /**
331
- * One row of a node's static configuration summary. See {@link NodeConfigBase.inspectorSummary}.
332
- */
333
242
  interface NodeInspectorSummaryRow {
334
243
  readonly label: string;
335
244
  readonly value: string;
336
245
  }
337
246
  declare const runnableNodeInputType: unique symbol;
338
247
  declare const runnableNodeOutputType: unique symbol;
339
- /**
340
- * Runnable node: **`TInputJson`** is what **`inputSchema`** validates on **`item.json`** (the wire payload).
341
- * **`TOutputJson`** is emitted `item.json` on outputs.
342
- */
343
248
  interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown> extends NodeConfigBase {
344
249
  readonly kind: "node";
345
250
  readonly [runnableNodeInputType]?: TInputJson$1;
346
251
  readonly [runnableNodeOutputType]?: TOutputJson$1;
347
- /**
348
- * Optional Zod input contract for {@link RunnableNode} when not set on the node class.
349
- * Resolution order: node instance `inputSchema`, then config `inputSchema`, then `z.unknown()`.
350
- */
351
252
  readonly inputSchema?: ZodType<TInputJson$1>;
352
- /**
353
- * When an activation receives **zero** input items, the engine normally runs `execute` zero times.
354
- * Set to **`runOnce`** to run `execute` once with an empty `items` batch (and a synthetic wire item for schema parsing).
355
- * Used by batch-style callback nodes (built-in `Callback`) so `callback([], ctx)` still runs.
356
- */
357
253
  readonly emptyBatchExecution?: "skip" | "runOnce";
358
254
  }
359
255
  type PairedItemRef = Readonly<{
@@ -388,27 +284,14 @@ type Items<TJson = unknown> = ReadonlyArray<Item<TJson>>;
388
284
  type NodeOutputs = Partial<Record<OutputPortKey, Items>>;
389
285
  type RunId = string;
390
286
  type NodeActivationId = string;
391
- /**
392
- * One per-item iteration of a runnable node's execute loop. Refines `NodeActivationId` for
393
- * per-item connection invocations and telemetry. Undefined when the executing node is a batch
394
- * node or trigger that does not iterate items.
395
- */
396
287
  type NodeIterationId = string;
397
288
  interface ParentExecutionRef {
398
289
  runId: RunId;
399
290
  workflowId: WorkflowId;
400
291
  nodeId: NodeId;
401
- /** Subworkflow depth of the **spawning** run (0 = root). Passed when starting a child run. */
402
292
  subworkflowDepth?: number;
403
- /** Effective max node activations from the parent run (propagated to child policy merge). */
404
293
  engineMaxNodeActivations?: number;
405
- /** Effective max subworkflow depth from the parent run (propagated to child policy merge). */
406
294
  engineMaxSubworkflowDepth?: number;
407
- /**
408
- * Test-suite linkage inherited by the child subworkflow run. Set by whichever node
409
- * spawns the subworkflow when its own `ctx.testContext` is present, so assertions
410
- * emitted inside a subworkflow land under the correct parent test case.
411
- */
412
295
  testContext?: RunTestContext;
413
296
  }
414
297
  interface RunDataSnapshot {
@@ -429,36 +312,19 @@ interface NodeErrorHandler {
429
312
  type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandler;
430
313
  //#endregion
431
314
  //#region ../core/src/contracts/runtimeTypes.d.ts
432
- /** Opaque unique identifier for a single HumanTask instance. */
433
315
  type HumanTaskId = string;
434
- /**
435
- * Minimal handle handed to the `deliver` callback so it can route to the correct
436
- * inbox channel.
437
- */
438
316
  interface HumanTaskHandle {
439
317
  readonly taskId: HumanTaskId;
440
318
  readonly runId: string;
441
319
  readonly nodeId: string;
442
320
  readonly expiresAt: Date;
443
- /** TODO: real signed URL; placeholder empty string for now. */
444
321
  readonly resumeUrl: string;
445
- /**
446
- * Arbitrary JSON metadata copied from `SuspensionRequest.request.metadata` at suspension time.
447
- * Used by the agent runtime to round-trip the `agentCheckpoint` back to the
448
- * resumed node via `ctx.resumeContext.task.metadata`.
449
- */
450
322
  readonly metadata?: Readonly<Record<string, JsonValue>>;
451
323
  }
452
- /** Identity of the person who made a decision on the task. */
453
324
  interface HumanTaskActor {
454
325
  readonly actorId: string;
455
326
  readonly displayName?: string;
456
327
  }
457
- /**
458
- * Resume context injected into `NodeExecutionContext` when the engine re-activates
459
- * a previously suspended node. `defineHumanApprovalNode` wraps this with parsed
460
- * `TDecision`; at the engine layer `decision.value` is `unknown`.
461
- */
462
328
  interface ResumeContext {
463
329
  readonly decision: Readonly<{
464
330
  kind: "decided";
@@ -499,11 +365,6 @@ interface NodeExecutionStatePublisher {
499
365
  error: Error;
500
366
  }): Promise<void>;
501
367
  appendConnectionInvocation(args: ConnectionInvocationAppendArgs): Promise<void>;
502
- /**
503
- * Annotates the current snapshot for `nodeId` with the id of the child run spawned by a
504
- * SubWorkflow invocation. Called from `SubWorkflowNode.execute` after `runById` resolves.
505
- * The engine's subsequent `markCompleted` call preserves the value via `previous.childRunId`.
506
- */
507
368
  setChildRunId?(args: {
508
369
  nodeId: NodeId;
509
370
  childRunId: RunId;
@@ -531,32 +392,16 @@ interface ExecutionBinaryService {
531
392
  activationId: NodeActivationId;
532
393
  }): NodeBinaryAttachmentService;
533
394
  openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
534
- /**
535
- * Reads all bytes from the attachment into a contiguous `Uint8Array`.
536
- * Checks `attachment.size` against `maxBytes` *before* any allocation; throws a bounded-read
537
- * error when exceeded (no OOM). Throws if the stream is unavailable or the byte count mismatches.
538
- */
539
395
  getBytes(attachment: BinaryAttachment, maxBytes?: number): Promise<Uint8Array>;
540
- /**
541
- * Reads the attachment and decodes the bytes as UTF-8 text.
542
- * Subject to the same bounded-read safety as `getBytes`.
543
- */
544
396
  getText(attachment: BinaryAttachment, maxBytes?: number): Promise<string>;
545
- /**
546
- * Reads the attachment, decodes as UTF-8 text, and parses as JSON.
547
- * Throws a clear error on invalid JSON. Subject to the same bounded-read safety.
548
- */
549
397
  getJson<T = unknown>(attachment: BinaryAttachment, maxBytes?: number): Promise<T>;
550
398
  }
551
399
  interface ExecutionContext {
552
400
  runId: RunId;
553
401
  workflowId: WorkflowId;
554
402
  parent?: ParentExecutionRef;
555
- /** This run's subworkflow depth (0 = root). */
556
403
  subworkflowDepth: number;
557
- /** Effective activation budget cap for this run (after policy merge). */
558
404
  engineMaxNodeActivations: number;
559
- /** Effective subworkflow nesting cap for this run (after policy merge). */
560
405
  engineMaxSubworkflowDepth: number;
561
406
  now: () => Date;
562
407
  data: RunDataSnapshot;
@@ -564,28 +409,11 @@ interface ExecutionContext {
564
409
  telemetry: ExecutionTelemetry;
565
410
  binary: ExecutionBinaryService;
566
411
  getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
567
- /** Per-item iteration id, set by {@link NodeExecutor} on the ctx passed into runnable `execute`. */
568
412
  iterationId?: NodeIterationId;
569
- /** Item index (0-based) within the current activation's batch; set alongside {@link iterationId}. */
570
413
  itemIndex?: number;
571
- /** When set, this ctx is executing inside a sub-agent triggered by the named parent invocation. */
572
414
  parentInvocationId?: ConnectionInvocationId;
573
- /**
574
- * Present iff the run was started by a TestSuiteOrchestrator. The {@link IsTestRunNode}
575
- * branches on this; assertion-emitting nodes use it to decide whether to record results.
576
- */
577
415
  testContext?: RunTestContext;
578
- /**
579
- * Collections registered in the codemation config, keyed by collection name.
580
- */
581
416
  readonly collections?: CollectionsContext;
582
- /**
583
- * Resolve a DI token from the host container.
584
- * Allows nodes to reach host-side services (e.g. `InboxChannelResolverToken`)
585
- * without importing host code. Wired by `DefaultExecutionContextFactory`; throws
586
- * a clear error when no resolver is configured (e.g. in unit tests that don't
587
- * set up the full container).
588
- */
589
417
  resolve<T>(token: TypeToken<T>): T;
590
418
  }
591
419
  interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase> extends ExecutionContext {
@@ -594,18 +422,8 @@ interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase>
594
422
  config: TConfig;
595
423
  telemetry: NodeExecutionTelemetry;
596
424
  binary: NodeBinaryAttachmentService;
597
- /**
598
- * Present when this node activation is a HITL resume.
599
- * The node checks `ctx.resumeContext !== undefined` and takes the resume branch.
600
- */
601
425
  resumeContext?: ResumeContext;
602
426
  }
603
- /**
604
- * Per-item runnable node: return JSON, an array to fan-out on `main`, an explicit `Item`, or {@link emitPorts}
605
- * for multi-port emission. Engine applies `inputSchema.parse(item.json)` and passes the result as `args.input`
606
- * (wire `item.json` is unchanged). Transform helpers may opt into binary preservation, while routers and
607
- * pass-through nodes should return explicit items when they need to preserve full item state.
608
- */
609
427
  interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown> {
610
428
  readonly input: TInputJson$1;
611
429
  readonly item: Item;
@@ -615,14 +433,7 @@ interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> =
615
433
  }
616
434
  interface RunnableNode<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown, _TOutputJson = unknown> {
617
435
  readonly kind: "node";
618
- /**
619
- * Declared output ports (e.g. `["main"]`).
620
- *
621
- * Prefer describing dynamic router ports (Switch) and fixed multi-ports (If true/false)
622
- * via {@link NodeConfigBase.declaredOutputPorts}. Engine defaults to `["main"]` when omitted.
623
- */
624
436
  readonly outputPorts?: ReadonlyArray<OutputPortKey>;
625
- /** When omitted, engine uses {@link RunnableNodeConfig.inputSchema} or `z.unknown()`. */
626
437
  readonly inputSchema?: ZodType<TInputJson$1>;
627
438
  execute(args: RunnableNodeExecuteArgs<TConfig, TInputJson$1>): Promise<unknown> | unknown;
628
439
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemation/node-example",
3
- "version": "0.0.43",
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.13.2"
31
+ "@codemation/core": "0.15.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^25.3.5",