@codemation/core 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/{EngineRuntimeRegistration.types-Dm129RJ6.d.ts → EngineRuntimeRegistration.types-_M7KFD3D.d.ts} +2 -2
  3. package/dist/{EngineWorkflowRunnerService-Bf88QtwB.d.cts → EngineWorkflowRunnerService-D0Cwngv7.d.cts} +2 -2
  4. package/dist/{InMemoryRunDataFactory-Dyl4p2s8.d.cts → InMemoryRunDataFactory-BIWx6e02.d.cts} +6 -6
  5. package/dist/{RunIntentService-B1Y3v1H6.d.cts → RunIntentService-5k0p-J67.d.cts} +8 -4
  6. package/dist/{RunIntentService-BDiodxhf.d.ts → RunIntentService-CuXAIO6_.d.ts} +29 -20
  7. package/dist/bootstrap/index.cjs +2 -2
  8. package/dist/bootstrap/index.d.cts +5 -5
  9. package/dist/bootstrap/index.d.ts +3 -3
  10. package/dist/bootstrap/index.js +2 -2
  11. package/dist/{bootstrap-DdeiJ8cd.js → bootstrap-BhYxSivA.js} +3 -3
  12. package/dist/bootstrap-BhYxSivA.js.map +1 -0
  13. package/dist/{bootstrap-DVL2ue5v.cjs → bootstrap-D-TDU9Lu.cjs} +3 -3
  14. package/dist/bootstrap-D-TDU9Lu.cjs.map +1 -0
  15. package/dist/{index-C2af8ssM.d.ts → index-BnJ7_IrO.d.ts} +11 -10
  16. package/dist/index.cjs +16 -10
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +27 -21
  19. package/dist/index.d.ts +3 -3
  20. package/dist/index.js +11 -6
  21. package/dist/index.js.map +1 -1
  22. package/dist/{runtime-DVBwxFvX.cjs → runtime-3YVDd2vY.cjs} +42 -42
  23. package/dist/runtime-3YVDd2vY.cjs.map +1 -0
  24. package/dist/{runtime-7Xh9z3dw.js → runtime-CJnObwsU.js} +33 -33
  25. package/dist/runtime-CJnObwsU.js.map +1 -0
  26. package/dist/testing.cjs +2 -2
  27. package/dist/testing.d.cts +2 -2
  28. package/dist/testing.d.ts +2 -2
  29. package/dist/testing.js +2 -2
  30. package/package.json +1 -1
  31. package/src/ai/AgentConfigInspectorFactory.ts +2 -2
  32. package/src/ai/AgentMessageConfigNormalizerFactory.ts +3 -3
  33. package/src/ai/AiHost.ts +2 -2
  34. package/src/authoring/defineNode.types.ts +35 -9
  35. package/src/authoring/index.ts +1 -0
  36. package/src/bootstrap/runtime/EngineRuntimeRegistrar.ts +3 -3
  37. package/src/contracts/index.ts +2 -1
  38. package/src/contracts/{itemValue.ts → itemExpr.ts} +31 -32
  39. package/src/contracts/params.ts +10 -0
  40. package/src/contracts/workflowTypes.ts +11 -2
  41. package/src/execution/{ItemValueResolver.ts → ItemExprResolver.ts} +5 -5
  42. package/src/execution/NodeExecutor.ts +6 -6
  43. package/src/execution/index.ts +1 -1
  44. package/src/index.ts +1 -1
  45. package/src/runStorage/InMemoryRunData.ts +9 -5
  46. package/src/types/index.ts +2 -1
  47. package/src/workflowSnapshots/WorkflowSnapshotCodec.ts +1 -1
  48. package/dist/bootstrap-DVL2ue5v.cjs.map +0 -1
  49. package/dist/bootstrap-DdeiJ8cd.js.map +0 -1
  50. package/dist/runtime-7Xh9z3dw.js.map +0 -1
  51. package/dist/runtime-DVBwxFvX.cjs.map +0 -1
package/dist/testing.cjs CHANGED
@@ -1,6 +1,6 @@
1
- const require_runtime = require('./runtime-DVBwxFvX.cjs');
1
+ const require_runtime = require('./runtime-3YVDd2vY.cjs');
2
2
  const require_workflowActivationPolicy = require('./workflowActivationPolicy-6V3OJD3N.cjs');
3
- const require_bootstrap = require('./bootstrap-DVL2ue5v.cjs');
3
+ const require_bootstrap = require('./bootstrap-D-TDU9Lu.cjs');
4
4
  let tsyringe = require("tsyringe");
5
5
  tsyringe = require_runtime.__toESM(tsyringe);
6
6
 
@@ -1,5 +1,5 @@
1
- import { $n as WorkflowExecutionRepository, Bt as NodeExecutionRequest, E as NodeId, Er as Container, Gn as RunResult, Gr as EngineExecutionLimitsPolicy, Ht as NodeExecutionScheduler, J as WorkflowDefinition, Jr as RunEventBus, Jt as RunnableNode, L as RunDataFactory, Mr as TypeToken, O as NodeOffloadPolicy, P as ParentExecutionRef, Qt as TriggerNode, V as RunnableNodeConfig, W as TriggerNodeConfig, Yt as RunnableNodeExecuteArgs, en as TriggerSetupContext, et as WorkflowId, f as Items, k as NodeOutputs, kt as ExecutionContextFactory, n as InMemoryLiveWorkflowRepository, nn as TriggerSetupStateRepository, r as Engine, sn as WorkflowRunnerService, t as RunIntentService, u as Item, vr as CredentialSessionService, zt as NodeExecutionContext } from "./RunIntentService-B1Y3v1H6.cjs";
2
- import { a as WorkflowSnapshotCodec, n as EngineRuntimeRegistrationOptions, t as EngineWorkflowRunnerService } from "./EngineWorkflowRunnerService-Bf88QtwB.cjs";
1
+ import { A as NodeOutputs, E as NodeId, F as ParentExecutionRef, G as TriggerNodeConfig, H as RunnableNodeConfig, Ht as NodeExecutionRequest, Or as Container, Pr as TypeToken, R as RunDataFactory, Vt as NodeExecutionContext, Wt as NodeExecutionScheduler, Xr as RunEventBus, Xt as RunnableNode, Y as WorkflowDefinition, Zt as RunnableNodeExecuteArgs, br as CredentialSessionService, en as TriggerNode, f as Items, in as TriggerSetupStateRepository, jt as ExecutionContextFactory, k as NodeOffloadPolicy, ln as WorkflowRunnerService, n as InMemoryLiveWorkflowRepository, nn as TriggerSetupContext, qn as RunResult, qr as EngineExecutionLimitsPolicy, r as Engine, t as RunIntentService, tr as WorkflowExecutionRepository, tt as WorkflowId, u as Item } from "./RunIntentService-5k0p-J67.cjs";
2
+ import { a as WorkflowSnapshotCodec, n as EngineRuntimeRegistrationOptions, t as EngineWorkflowRunnerService } from "./EngineWorkflowRunnerService-D0Cwngv7.cjs";
3
3
  import { DependencyContainer, InjectionToken } from "tsyringe";
4
4
  import { ZodType } from "zod";
5
5
 
package/dist/testing.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { $i as RunEventBus, $n as RunnableNode, $t as WorkflowDefinition, Ci as CredentialSessionService, Gn as NodeExecutionRequest, Ht as RunDataFactory, Kt as RunnableNodeConfig, Li as TypeToken, Nt as NodeOffloadPolicy, Pn as ExecutionContextFactory, Pt as NodeOutputs, Wn as NodeExecutionContext, Xi as EngineExecutionLimitsPolicy, Xr as RunResult, Yt as TriggerNodeConfig, _t as Items, an as WorkflowId, ar as TriggerSetupContext, er as RunnableNodeExecuteArgs, fr as WorkflowRunnerService, ht as Item, ii as WorkflowExecutionRepository, ji as Container, jt as NodeId, l as WorkflowSnapshotCodec, n as InMemoryLiveWorkflowRepository, qn as NodeExecutionScheduler, r as EngineWorkflowRunnerService, rr as TriggerNode, sr as TriggerSetupStateRepository, t as RunIntentService, u as Engine, zt as ParentExecutionRef } from "./RunIntentService-BDiodxhf.js";
2
- import { t as EngineRuntimeRegistrationOptions } from "./EngineRuntimeRegistration.types-Dm129RJ6.js";
1
+ import { $t as TriggerNodeConfig, Hi as TypeToken, Ii as Container, Kt as RunDataFactory, Lt as NodeOffloadPolicy, Oi as CredentialSessionService, Pt as NodeId, Qn as NodeExecutionScheduler, Rt as NodeOutputs, Ut as ParentExecutionRef, Xn as NodeExecutionRequest, Xt as RunnableNodeConfig, Yn as NodeExecutionContext, _r as WorkflowRunnerService, ar as RunnableNodeExecuteArgs, bt as Items, cr as TriggerNode, fr as TriggerSetupStateRepository, ia as RunEventBus, ir as RunnableNode, l as WorkflowSnapshotCodec, li as WorkflowExecutionRepository, ln as WorkflowId, n as InMemoryLiveWorkflowRepository, r as EngineWorkflowRunnerService, rn as WorkflowDefinition, t as RunIntentService, ta as EngineExecutionLimitsPolicy, ti as RunResult, u as Engine, ur as TriggerSetupContext, vt as Item, zn as ExecutionContextFactory } from "./RunIntentService-CuXAIO6_.js";
2
+ import { t as EngineRuntimeRegistrationOptions } from "./EngineRuntimeRegistration.types-_M7KFD3D.js";
3
3
  import { DependencyContainer, InjectionToken } from "tsyringe";
4
4
  import { ZodType } from "zod";
5
5
 
package/dist/testing.js CHANGED
@@ -1,6 +1,6 @@
1
- import { A as NodeExecutor, B as DefaultAsyncSleeper, D as PersistedWorkflowTokenRegistry, E as WorkflowSnapshotCodec, P as emitPorts, R as InProcessRetryRunner, T as NodeInstanceFactory, _t as CoreTokens, a as InMemoryLiveWorkflowRepository, b as HintOnlyOffloadPolicy, d as InMemoryRunDataFactory, i as RunIntentService, l as Engine, x as DefaultDrivingScheduler, y as InlineDrivingScheduler, z as DefaultExecutionContextFactory } from "./runtime-7Xh9z3dw.js";
1
+ import { A as NodeExecutor, B as DefaultAsyncSleeper, D as PersistedWorkflowTokenRegistry, E as WorkflowSnapshotCodec, P as emitPorts, R as InProcessRetryRunner, T as NodeInstanceFactory, _t as CoreTokens, a as InMemoryLiveWorkflowRepository, b as HintOnlyOffloadPolicy, d as InMemoryRunDataFactory, i as RunIntentService, l as Engine, x as DefaultDrivingScheduler, y as InlineDrivingScheduler, z as DefaultExecutionContextFactory } from "./runtime-CJnObwsU.js";
2
2
  import { n as InMemoryRunEventBus, r as WorkflowBuilder, t as AllWorkflowsActiveWorkflowActivationPolicy } from "./workflowActivationPolicy-Td9HTOuD.js";
3
- import { n as InMemoryWorkflowExecutionRepository, t as EngineRuntimeRegistrar } from "./bootstrap-DdeiJ8cd.js";
3
+ import { n as InMemoryWorkflowExecutionRepository, t as EngineRuntimeRegistrar } from "./bootstrap-BhYxSivA.js";
4
4
  import { container } from "tsyringe";
5
5
 
6
6
  //#region src/testing/RejectingCredentialSessionService.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemation/core",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -1,5 +1,5 @@
1
1
  import type { NodeConfigBase } from "../types";
2
- import { isItemValue } from "../contracts/itemValue";
2
+ import { isItemExpr } from "../contracts/itemExpr";
3
3
  import type { AgentNodeConfig } from "./AiHost";
4
4
 
5
5
  export class AgentConfigInspector {
@@ -18,7 +18,7 @@ export class AgentConfigInspector {
18
18
  return messages.length > 0;
19
19
  }
20
20
  if (typeof messages === "object") {
21
- if (isItemValue(messages)) {
21
+ if (isItemExpr(messages)) {
22
22
  return true;
23
23
  }
24
24
  const o = messages as { prompt?: unknown; buildMessages?: unknown };
@@ -1,4 +1,4 @@
1
- import { isItemValue } from "../contracts/itemValue";
1
+ import { isItemExpr } from "../contracts/itemExpr";
2
2
 
3
3
  import type {
4
4
  AgentMessageBuildArgs,
@@ -69,9 +69,9 @@ export class AgentMessageConfigNormalizer {
69
69
  config: AgentMessageConfig<TInputJson>,
70
70
  args: AgentMessageBuildArgs<TInputJson>,
71
71
  ): ReadonlyArray<AgentMessageDto> {
72
- if (isItemValue(config)) {
72
+ if (isItemExpr(config)) {
73
73
  throw new Error(
74
- "AIAgent messages wrapped in itemValue(...) must be resolved by the engine before prompt normalization.",
74
+ "AIAgent messages wrapped in itemExpr(...) must be resolved by the engine before prompt normalization.",
75
75
  );
76
76
  }
77
77
  if (Array.isArray(config)) {
package/src/ai/AiHost.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { TypeToken } from "../di";
2
2
 
3
3
  import type { CredentialRequirement } from "../contracts/credentialTypes";
4
- import type { ItemValue } from "../contracts/itemValue";
4
+ import type { Expr } from "../contracts/params";
5
5
 
6
6
  import type {
7
7
  Item,
@@ -92,7 +92,7 @@ export type AgentMessageLine<TInputJson = unknown> = AgentMessageDto | AgentMess
92
92
  * Use the object form only when you need `buildMessages` to append messages after optional `prompt` lines.
93
93
  */
94
94
  export type AgentMessageConfig<TInputJson = unknown> =
95
- | ItemValue<ReadonlyArray<AgentMessageLine<TInputJson>>, TInputJson>
95
+ | Expr<ReadonlyArray<AgentMessageLine<TInputJson>>, TInputJson>
96
96
  | ReadonlyArray<AgentMessageLine<TInputJson>>
97
97
  | {
98
98
  readonly prompt?: ReadonlyArray<AgentMessageLine<TInputJson>>;
@@ -4,6 +4,7 @@ import type {
4
4
  CredentialRequirement,
5
5
  CredentialTypeId,
6
6
  } from "../contracts/credentialTypes";
7
+ import type { ParamDeep } from "../contracts/params";
7
8
  import type { RunnableNode, RunnableNodeExecuteArgs, NodeExecutionContext } from "../contracts/runtimeTypes";
8
9
  import type { Item, Items, RunnableNodeConfig } from "../contracts/workflowTypes";
9
10
  import type { TypeToken } from "../di";
@@ -67,6 +68,11 @@ export type DefineNodeExecuteArgs<TConfig extends CredentialJsonRecord, TInputJs
67
68
  ctx: NodeExecutionContext<RunnableNodeConfig<TInputJson, unknown> & Readonly<{ config: TConfig }>>;
68
69
  }>;
69
70
 
71
+ export type DefinedNodeConfigInput<TConfigResolved extends CredentialJsonRecord, TItemJson> = ParamDeep<
72
+ TConfigResolved,
73
+ TItemJson
74
+ >;
75
+
70
76
  export interface DefinedNode<
71
77
  TKey extends string,
72
78
  TConfig extends CredentialJsonRecord,
@@ -78,7 +84,11 @@ export interface DefinedNode<
78
84
  readonly key: TKey;
79
85
  readonly title: string;
80
86
  readonly description?: string;
81
- create(config: TConfig, name?: string, id?: string): RunnableNodeConfig<TInputJson, TOutputJson>;
87
+ create<TConfigItemJson = TInputJson>(
88
+ config: DefinedNodeConfigInput<TConfig, TConfigItemJson>,
89
+ name?: string,
90
+ id?: string,
91
+ ): RunnableNodeConfig<TInputJson, TOutputJson>;
82
92
  register(context: { registerNode<TValue>(token: TypeToken<TValue>, implementation?: TypeToken<TValue>): void }): void;
83
93
  }
84
94
 
@@ -252,9 +262,13 @@ export function defineNode<
252
262
 
253
263
  constructor(
254
264
  public readonly name: string,
255
- public readonly config: TConfig,
265
+ config: DefinedNodeConfigInput<TConfig, unknown>,
256
266
  public readonly id?: string,
257
- ) {}
267
+ ) {
268
+ this.config = config as unknown as TConfig;
269
+ }
270
+
271
+ public readonly config: TConfig;
258
272
 
259
273
  getCredentialRequirements(): ReadonlyArray<CredentialRequirement> {
260
274
  return credentialRequirements;
@@ -266,8 +280,12 @@ export function defineNode<
266
280
  key: options.key,
267
281
  title: options.title,
268
282
  description: options.description,
269
- create(config, name = options.title, id) {
270
- return new DefinedRunnableNodeConfig(name, config, id);
283
+ create<TConfigItemJson = TInputJson>(
284
+ config: DefinedNodeConfigInput<TConfig, TConfigItemJson>,
285
+ name = options.title,
286
+ id?: string,
287
+ ) {
288
+ return new DefinedRunnableNodeConfig(name, config as DefinedNodeConfigInput<TConfig, unknown>, id);
271
289
  },
272
290
  register(context) {
273
291
  context.registerNode(DefinedNodeRuntime);
@@ -327,9 +345,13 @@ export function defineBatchNode<
327
345
 
328
346
  constructor(
329
347
  public readonly name: string,
330
- public readonly config: TConfig,
348
+ config: DefinedNodeConfigInput<TConfig, unknown>,
331
349
  public readonly id?: string,
332
- ) {}
350
+ ) {
351
+ this.config = config as unknown as TConfig;
352
+ }
353
+
354
+ public readonly config: TConfig;
333
355
 
334
356
  getCredentialRequirements(): ReadonlyArray<CredentialRequirement> {
335
357
  return credentialRequirements;
@@ -341,8 +363,12 @@ export function defineBatchNode<
341
363
  key: options.key,
342
364
  title: options.title,
343
365
  description: options.description,
344
- create(config, name = options.title, id) {
345
- return new DefinedRunnableNodeConfig(name, config, id);
366
+ create<TConfigItemJson = TInputJson>(
367
+ config: DefinedNodeConfigInput<TConfig, TConfigItemJson>,
368
+ name = options.title,
369
+ id?: string,
370
+ ) {
371
+ return new DefinedRunnableNodeConfig(name, config as DefinedNodeConfigInput<TConfig, unknown>, id);
346
372
  },
347
373
  register(context) {
348
374
  context.registerNode(DefinedNodeRuntime);
@@ -1,6 +1,7 @@
1
1
  export { DefinedNodeRegistry } from "./DefinedNodeRegistry";
2
2
  export type {
3
3
  DefinedNode,
4
+ DefinedNodeConfigInput,
4
5
  DefinedNodeCredentialAccessors,
5
6
  DefinedNodeCredentialBinding,
6
7
  DefinedNodeCredentialBindings,
@@ -4,7 +4,7 @@ import { EngineExecutionLimitsPolicyFactory } from "../../policies/executionLimi
4
4
  import {
5
5
  DefaultAsyncSleeper,
6
6
  InProcessRetryRunnerFactory,
7
- ItemValueResolver,
7
+ ItemExprResolver,
8
8
  NodeExecutor,
9
9
  NodeExecutorFactory,
10
10
  NodeInstanceFactoryFactory,
@@ -41,8 +41,8 @@ export class EngineRuntimeRegistrar {
41
41
  }
42
42
 
43
43
  private registerSupportFactories(container: DependencyContainer): void {
44
- if (!container.isRegistered(ItemValueResolver, true)) {
45
- container.registerSingleton(ItemValueResolver, ItemValueResolver);
44
+ if (!container.isRegistered(ItemExprResolver, true)) {
45
+ container.registerSingleton(ItemExprResolver, ItemExprResolver);
46
46
  }
47
47
  if (!container.isRegistered(NodeOutputNormalizer, true)) {
48
48
  container.registerSingleton(NodeOutputNormalizer, NodeOutputNormalizer);
@@ -2,7 +2,8 @@ export * from "./credentialTypes";
2
2
  export * from "./emitPorts";
3
3
  export * from "./executionPersistenceContracts";
4
4
  export * from "./itemMeta";
5
- export * from "./itemValue";
5
+ export * from "./params";
6
+ export * from "./itemExpr";
6
7
  export * from "./runtimeTypes";
7
8
  export * from "./runFinishedAtFactory";
8
9
  export * from "./runTypes";
@@ -1,9 +1,9 @@
1
1
  import type { NodeExecutionContext } from "./runtimeTypes";
2
2
  import type { Item, Items, NodeActivationId, NodeId, RunDataSnapshot, RunId, WorkflowId } from "./workflowTypes";
3
3
 
4
- const ITEM_VALUE_BRAND = Symbol.for("codemation.itemValue");
4
+ const ITEM_EXPR_BRAND = Symbol.for("codemation.itemExpr");
5
5
 
6
- export type ItemValueResolvedContext = Readonly<{
6
+ export type ItemExprResolvedContext = Readonly<{
7
7
  runId: RunId;
8
8
  workflowId: WorkflowId;
9
9
  nodeId: NodeId;
@@ -14,52 +14,51 @@ export type ItemValueResolvedContext = Readonly<{
14
14
  /**
15
15
  * Context aligned with former {@link ItemInputMapperContext} — use **`data`** to read any completed upstream node.
16
16
  */
17
- export type ItemValueContext = ItemValueResolvedContext;
17
+ export type ItemExprContext = ItemExprResolvedContext;
18
18
 
19
- export type ItemValueArgs<TItemJson = unknown> = Readonly<{
19
+ export type ItemExprArgs<TItemJson = unknown> = Readonly<{
20
20
  item: Item<TItemJson>;
21
21
  itemIndex: number;
22
22
  items: Items<TItemJson>;
23
- ctx: ItemValueContext;
23
+ ctx: ItemExprContext;
24
24
  }>;
25
25
 
26
- export type ItemValueCallback<T, TItemJson = unknown> = (args: ItemValueArgs<TItemJson>) => T | Promise<T>;
26
+ export type ItemExprCallback<T, TItemJson = unknown> = (args: ItemExprArgs<TItemJson>) => T | Promise<T>;
27
27
 
28
- export type ItemValue<T, TItemJson = unknown> = Readonly<{
29
- readonly [ITEM_VALUE_BRAND]: true;
30
- readonly fn: ItemValueCallback<T, TItemJson>;
28
+ export type ItemExpr<T, TItemJson = unknown> = Readonly<{
29
+ readonly [ITEM_EXPR_BRAND]: true;
30
+ readonly fn: ItemExprCallback<T, TItemJson>;
31
31
  }>;
32
32
 
33
- export function itemValue<T, TItemJson = unknown>(fn: ItemValueCallback<T, TItemJson>): ItemValue<T, TItemJson> {
34
- return { [ITEM_VALUE_BRAND]: true, fn };
33
+ export function itemExpr<T, TItemJson = unknown>(fn: ItemExprCallback<T, TItemJson>): ItemExpr<T, TItemJson> {
34
+ return { [ITEM_EXPR_BRAND]: true, fn };
35
35
  }
36
36
 
37
- export function isItemValue<T, TItemJson = unknown>(value: unknown): value is ItemValue<T, TItemJson> {
37
+ export function isItemExpr<T, TItemJson = unknown>(value: unknown): value is ItemExpr<T, TItemJson> {
38
38
  if (typeof value !== "object" || value === null) {
39
39
  return false;
40
40
  }
41
41
  const v = value as Record<PropertyKey, unknown>;
42
- if (v[ITEM_VALUE_BRAND] === true) {
42
+ if (v[ITEM_EXPR_BRAND] === true) {
43
43
  return true;
44
44
  }
45
- // Support snapshot-hydrated itemValue wrappers where the symbol brand was lost but the callback survived.
45
+ // Support snapshot-hydrated itemExpr wrappers where the symbol brand was lost but the callback survived.
46
46
  // Workflow snapshot hydration currently restores function-valued fields (like `fn`) but may drop symbol-keyed brands.
47
- // We treat the minimal `{ fn: Function }` shape as an itemValue wrapper to keep runnable configs working.
47
+ // We treat the minimal `{ fn: Function }` shape as an itemExpr wrapper to keep runnable configs working.
48
48
  const keys = Object.keys(v);
49
49
  if (keys.length === 1 && keys[0] === "fn" && typeof (v as { fn?: unknown }).fn === "function") {
50
50
  return true;
51
51
  }
52
- // Support legacy module-local Symbol("codemation.itemValue") brands (e.g. duplicate module graphs).
53
52
  for (const sym of Object.getOwnPropertySymbols(v)) {
54
- if (sym.description === "codemation.itemValue" && v[sym] === true) {
53
+ if (sym.description === "codemation.itemExpr" && v[sym] === true) {
55
54
  return true;
56
55
  }
57
56
  }
58
57
  return false;
59
58
  }
60
59
 
61
- function containsItemValueInUnknown(value: unknown, seen: WeakSet<object> = new WeakSet()): boolean {
62
- if (isItemValue(value)) {
60
+ function containsItemExprInUnknown(value: unknown, seen: WeakSet<object> = new WeakSet()): boolean {
61
+ if (isItemExpr(value)) {
63
62
  return true;
64
63
  }
65
64
  if (value === null || typeof value !== "object") {
@@ -70,10 +69,10 @@ function containsItemValueInUnknown(value: unknown, seen: WeakSet<object> = new
70
69
  }
71
70
  seen.add(value as object);
72
71
  if (Array.isArray(value)) {
73
- return value.some((entry) => containsItemValueInUnknown(entry, seen));
72
+ return value.some((entry) => containsItemExprInUnknown(entry, seen));
74
73
  }
75
74
  for (const entry of Object.values(value as Record<string, unknown>)) {
76
- if (containsItemValueInUnknown(entry, seen)) {
75
+ if (containsItemExprInUnknown(entry, seen)) {
77
76
  return true;
78
77
  }
79
78
  }
@@ -81,14 +80,14 @@ function containsItemValueInUnknown(value: unknown, seen: WeakSet<object> = new
81
80
  }
82
81
 
83
82
  /**
84
- * Deep-resolves {@link itemValue} leaves. Returns a new graph (does not mutate the original config object).
83
+ * Deep-resolves {@link itemExpr} leaves. Returns a new graph (does not mutate the original config object).
85
84
  */
86
- export async function resolveItemValuesInUnknown(
85
+ export async function resolveItemExprsInUnknown(
87
86
  value: unknown,
88
- args: ItemValueArgs,
87
+ args: ItemExprArgs,
89
88
  seen: WeakSet<object> = new WeakSet(),
90
89
  ): Promise<unknown> {
91
- if (isItemValue(value)) {
90
+ if (isItemExpr(value)) {
92
91
  return await Promise.resolve(value.fn(args));
93
92
  }
94
93
  if (value === null || typeof value !== "object") {
@@ -101,7 +100,7 @@ export async function resolveItemValuesInUnknown(
101
100
  if (Array.isArray(value)) {
102
101
  const out: unknown[] = [];
103
102
  for (let i = 0; i < value.length; i++) {
104
- out.push(await resolveItemValuesInUnknown(value[i], args, seen));
103
+ out.push(await resolveItemExprsInUnknown(value[i], args, seen));
105
104
  }
106
105
  return out;
107
106
  }
@@ -113,22 +112,22 @@ export async function resolveItemValuesInUnknown(
113
112
  }
114
113
  const out = Object.create(proto) as Record<string, unknown>;
115
114
  for (const [k, v] of entries) {
116
- out[k] = await resolveItemValuesInUnknown(v, args, seen);
115
+ out[k] = await resolveItemExprsInUnknown(v, args, seen);
117
116
  }
118
117
  return out;
119
118
  }
120
119
 
121
120
  /**
122
- * Clones runnable config (best-effort) so per-item {@link itemValue} resolution never mutates shared instances.
121
+ * Clones runnable config (best-effort) so per-item {@link itemExpr} resolution never mutates shared instances.
123
122
  */
124
- export async function resolveItemValuesForExecution(
123
+ export async function resolveItemExprsForExecution(
125
124
  config: unknown,
126
125
  nodeCtx: NodeExecutionContext,
127
126
  item: Item,
128
127
  itemIndex: number,
129
128
  items: Items,
130
129
  ): Promise<unknown | undefined> {
131
- const ivArgs: ItemValueArgs = {
130
+ const exprArgs: ItemExprArgs = {
132
131
  item,
133
132
  itemIndex,
134
133
  items,
@@ -140,8 +139,8 @@ export async function resolveItemValuesForExecution(
140
139
  data: nodeCtx.data,
141
140
  },
142
141
  };
143
- if (!containsItemValueInUnknown(config)) {
142
+ if (!containsItemExprInUnknown(config)) {
144
143
  return undefined;
145
144
  }
146
- return await resolveItemValuesInUnknown(config, ivArgs);
145
+ return await resolveItemExprsInUnknown(config, exprArgs);
147
146
  }
@@ -0,0 +1,10 @@
1
+ import type { ItemExpr } from "./itemExpr";
2
+
3
+ export type Expr<T, TItemJson = unknown> = ItemExpr<T, TItemJson>;
4
+
5
+ export type Param<T, TItemJson = unknown> = T | Expr<T, TItemJson>;
6
+
7
+ export type ParamDeep<T, TItemJson = unknown> =
8
+ | Expr<T, TItemJson>
9
+ | (T extends readonly (infer U)[] ? ReadonlyArray<ParamDeep<U, TItemJson>> : never)
10
+ | (T extends object ? { [K in keyof T]: ParamDeep<T[K], TItemJson> } : T);
@@ -6,6 +6,7 @@ import type { RetryPolicySpec } from "./retryPolicySpec.types";
6
6
 
7
7
  export type WorkflowId = string;
8
8
  export type NodeId = string;
9
+ export type NodeIdRef<TJson = unknown> = NodeId & Readonly<{ __codemationNodeJson?: TJson }>;
9
10
  export type OutputPortKey = string;
10
11
  export type InputPortKey = string;
11
12
  export type PersistedTokenId = string;
@@ -154,6 +155,10 @@ export interface NodeRef {
154
155
  name?: string;
155
156
  }
156
157
 
158
+ export function nodeRef<TJson>(nodeId: NodeId): NodeIdRef<TJson> {
159
+ return nodeId as NodeIdRef<TJson>;
160
+ }
161
+
157
162
  export type PairedItemRef = Readonly<{ nodeId: NodeId; output: OutputPortKey; itemIndex: number }>;
158
163
 
159
164
  export type BinaryPreviewKind = "image" | "audio" | "video" | "download";
@@ -204,8 +209,12 @@ export interface ParentExecutionRef {
204
209
 
205
210
  export interface RunDataSnapshot {
206
211
  getOutputs(nodeId: NodeId): NodeOutputs | undefined;
207
- getOutputItems(nodeId: NodeId, output?: OutputPortKey): Items;
208
- getOutputItem(nodeId: NodeId, itemIndex: number, output?: OutputPortKey): Item | undefined;
212
+ getOutputItems<TJson = unknown>(nodeId: NodeId | NodeIdRef<TJson>, output?: OutputPortKey): Items<TJson>;
213
+ getOutputItem<TJson = unknown>(
214
+ nodeId: NodeId | NodeIdRef<TJson>,
215
+ itemIndex: number,
216
+ output?: OutputPortKey,
217
+ ): Item<TJson> | undefined;
209
218
  }
210
219
 
211
220
  export interface MutableRunData extends RunDataSnapshot {
@@ -1,10 +1,10 @@
1
- import { resolveItemValuesForExecution } from "../contracts/itemValue";
1
+ import { resolveItemExprsForExecution } from "../contracts/itemExpr";
2
2
  import type { Item, NodeExecutionContext, RunnableNodeConfig } from "../types";
3
3
 
4
4
  /**
5
- * Resolves {@link import("../contracts/itemValue").ItemValue} leaves on runnable config before {@link RunnableNode.execute}.
5
+ * Resolves {@link import("../contracts/itemExpr").ItemExpr} leaves on runnable config before {@link RunnableNode.execute}.
6
6
  */
7
- export class ItemValueResolver {
7
+ export class ItemExprResolver {
8
8
  async resolveConfigForItem<TConfig extends RunnableNodeConfig<any, any>>(
9
9
  ctx: NodeExecutionContext<TConfig>,
10
10
  item: Item,
@@ -12,9 +12,9 @@ export class ItemValueResolver {
12
12
  items: ReadonlyArray<Item>,
13
13
  ): Promise<NodeExecutionContext<TConfig>> {
14
14
  if (!ctx) {
15
- throw new Error("ItemValueResolver.resolveConfigForItem: ctx is required");
15
+ throw new Error("ItemExprResolver.resolveConfigForItem: ctx is required");
16
16
  }
17
- const resolvedConfig = await resolveItemValuesForExecution(ctx.config, ctx, item, itemIndex, items);
17
+ const resolvedConfig = await resolveItemExprsForExecution(ctx.config, ctx, item, itemIndex, items);
18
18
  const merged = resolvedConfig !== undefined && resolvedConfig !== null ? resolvedConfig : ctx.config;
19
19
  if (merged === undefined || merged === null) {
20
20
  return ctx;
@@ -15,7 +15,7 @@ import type {
15
15
  } from "../types";
16
16
 
17
17
  import { FanInMergeByOriginMerger } from "./FanInMergeByOriginMerger";
18
- import { ItemValueResolver } from "./ItemValueResolver";
18
+ import { ItemExprResolver } from "./ItemExprResolver";
19
19
  import { InProcessRetryRunner } from "./InProcessRetryRunner";
20
20
  import { NodeOutputNormalizer } from "./NodeOutputNormalizer";
21
21
  import { RunnableOutputBehaviorResolver } from "./RunnableOutputBehaviorResolver";
@@ -23,16 +23,16 @@ import { RunnableOutputBehaviorResolver } from "./RunnableOutputBehaviorResolver
23
23
  export class NodeExecutor {
24
24
  private readonly fanInMerger = new FanInMergeByOriginMerger();
25
25
  private readonly outputNormalizer = new NodeOutputNormalizer();
26
- private readonly itemValueResolver: ItemValueResolver;
26
+ private readonly itemExprResolver: ItemExprResolver;
27
27
  private readonly outputBehaviorResolver: RunnableOutputBehaviorResolver;
28
28
 
29
29
  constructor(
30
30
  private readonly nodeInstanceFactory: WorkflowNodeInstanceFactory,
31
31
  private readonly retryRunner: InProcessRetryRunner,
32
- itemValueResolver?: ItemValueResolver,
32
+ itemExprResolver?: ItemExprResolver,
33
33
  outputBehaviorResolver?: RunnableOutputBehaviorResolver,
34
34
  ) {
35
- this.itemValueResolver = itemValueResolver ?? new ItemValueResolver();
35
+ this.itemExprResolver = itemExprResolver ?? new ItemExprResolver();
36
36
  this.outputBehaviorResolver = outputBehaviorResolver ?? new RunnableOutputBehaviorResolver();
37
37
  }
38
38
 
@@ -135,7 +135,7 @@ export class NodeExecutor {
135
135
  const syntheticItem: Item = { json: {} };
136
136
  const parsed = inputSchema.parse(syntheticItem.json);
137
137
  const runnableCtx = request.ctx as NodeExecutionContext<RunnableNodeConfig>;
138
- const resolvedCtx = await this.itemValueResolver.resolveConfigForItem(runnableCtx, syntheticItem, 0, inputBatch);
138
+ const resolvedCtx = await this.itemExprResolver.resolveConfigForItem(runnableCtx, syntheticItem, 0, inputBatch);
139
139
  const ctx = this.pickExecutionContext(runnableCtx, resolvedCtx);
140
140
  const args: RunnableNodeExecuteArgs = {
141
141
  input: parsed,
@@ -157,7 +157,7 @@ export class NodeExecutor {
157
157
  this.assertItemJsonNotTopLevelArray(request.nodeId, item);
158
158
  const parsed = inputSchema.parse(item.json);
159
159
  const runnableCtx = request.ctx as NodeExecutionContext<RunnableNodeConfig>;
160
- const resolvedCtx = await this.itemValueResolver.resolveConfigForItem(runnableCtx, item, i, inputBatch);
160
+ const resolvedCtx = await this.itemExprResolver.resolveConfigForItem(runnableCtx, item, i, inputBatch);
161
161
  const ctx = this.pickExecutionContext(runnableCtx, resolvedCtx);
162
162
  const args: RunnableNodeExecuteArgs = {
163
163
  input: parsed,
@@ -5,7 +5,7 @@ export { CredentialResolverFactory } from "./CredentialResolverFactory";
5
5
  export { DefaultAsyncSleeper } from "./DefaultAsyncSleeper";
6
6
  export { DefaultExecutionContextFactory } from "./DefaultExecutionContextFactory";
7
7
  export { InProcessRetryRunner } from "./InProcessRetryRunner";
8
- export { ItemValueResolver } from "./ItemValueResolver";
8
+ export { ItemExprResolver } from "./ItemExprResolver";
9
9
  export { NodeOutputNormalizer } from "./NodeOutputNormalizer";
10
10
  export { RunnableOutputBehaviorResolver } from "./RunnableOutputBehaviorResolver";
11
11
  export { InProcessRetryRunnerFactory } from "./InProcessRetryRunnerFactory";
package/src/index.ts CHANGED
@@ -18,7 +18,7 @@ export {
18
18
  DefaultAsyncSleeper,
19
19
  DefaultExecutionContextFactory,
20
20
  InProcessRetryRunner,
21
- ItemValueResolver,
21
+ ItemExprResolver,
22
22
  NodeOutputNormalizer,
23
23
  RunnableOutputBehaviorResolver,
24
24
  } from "./execution";
@@ -1,4 +1,4 @@
1
- import type { Items, MutableRunData, NodeId, NodeOutputs, OutputPortKey } from "../types";
1
+ import type { Items, MutableRunData, NodeId, NodeIdRef, NodeOutputs, OutputPortKey, Item } from "../types";
2
2
 
3
3
  export class InMemoryRunData implements MutableRunData {
4
4
  private readonly byNode = new Map<NodeId, NodeOutputs>();
@@ -17,12 +17,16 @@ export class InMemoryRunData implements MutableRunData {
17
17
  return this.byNode.get(nodeId);
18
18
  }
19
19
 
20
- getOutputItems(nodeId: NodeId, output: OutputPortKey = "main"): Items {
21
- return this.byNode.get(nodeId)?.[output] ?? [];
20
+ getOutputItems<TJson = unknown>(nodeId: NodeId | NodeIdRef<TJson>, output: OutputPortKey = "main"): Items<TJson> {
21
+ return (this.byNode.get(nodeId)?.[output] ?? []) as Items<TJson>;
22
22
  }
23
23
 
24
- getOutputItem(nodeId: NodeId, itemIndex: number, output: OutputPortKey = "main") {
25
- return this.getOutputItems(nodeId, output)[itemIndex];
24
+ getOutputItem<TJson = unknown>(
25
+ nodeId: NodeId | NodeIdRef<TJson>,
26
+ itemIndex: number,
27
+ output: OutputPortKey = "main",
28
+ ): Item<TJson> | undefined {
29
+ return this.getOutputItems<TJson>(nodeId, output)[itemIndex];
26
30
  }
27
31
 
28
32
  dump(): Record<NodeId, NodeOutputs> {
@@ -1,6 +1,7 @@
1
1
  export * from "../contracts/emitPorts";
2
2
  export * from "../contracts/itemMeta";
3
- export * from "../contracts/itemValue";
3
+ export * from "../contracts/params";
4
+ export * from "../contracts/itemExpr";
4
5
  export * from "../contracts/retryPolicySpec.types";
5
6
  export * from "../contracts/NoRetryPolicy";
6
7
  export * from "../contracts/RetryPolicy";
@@ -134,7 +134,7 @@ export class WorkflowSnapshotCodec {
134
134
  hydrated[key] = value;
135
135
  }
136
136
  }
137
- // Preserve symbol-keyed brands (e.g. itemValue / emitPorts) and other runtime-only keys.
137
+ // Preserve symbol-keyed brands (e.g. itemExpr / emitPorts) and other runtime-only keys.
138
138
  for (const sym of Object.getOwnPropertySymbols(liveRecord)) {
139
139
  hydrated[sym] = liveRecord[sym];
140
140
  }