@codemation/core-nodes 0.8.0 → 0.9.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.
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { AssistantModelMessage, ModelMessage, ToolModelMessage, ToolSet } from "ai";
2
2
  import { Cron, CronCallback } from "croner";
3
- import { ReadableStream } from "node:stream/web";
4
3
  import { ZodType, input, output, z } from "zod";
5
4
  import { DependencyContainer as Container, InjectionToken as TypeToken } from "tsyringe";
5
+ import { ReadableStream } from "node:stream/web";
6
6
 
7
7
  //#region src/canvasIconName.d.ts
8
8
  /**
@@ -14,6 +14,67 @@ import { DependencyContainer as Container, InjectionToken as TypeToken } from "t
14
14
  */
15
15
  type CanvasIconName = string;
16
16
  //#endregion
17
+ //#region ../core/src/contracts/testTriggerTypes.d.ts
18
+ /**
19
+ * Identifier minted by the host (or in-memory test runner) for one execution of a test suite.
20
+ * One TestSuiteRun produces N child workflow runs, one per item yielded by `generateItems`.
21
+ */
22
+ type TestSuiteRunId = string;
23
+ /**
24
+ * Setup context passed to a {@link TestTriggerNodeConfig.generateItems} callback. Distinct from
25
+ * {@link import("./runtimeTypes").TriggerSetupContext} on purpose: test triggers are not
26
+ * activated by the live trigger lifecycle (webhooks, cron, polling) and never call `emit` —
27
+ * the orchestrator pulls from the iterable they return and dispatches one run per item.
28
+ */
29
+ interface TestTriggerSetupContext<TConfig extends TestTriggerNodeConfig<unknown> = TestTriggerNodeConfig<unknown>> {
30
+ readonly workflowId: WorkflowId;
31
+ readonly nodeId: NodeId;
32
+ readonly config: TConfig;
33
+ readonly testSuiteRunId: TestSuiteRunId;
34
+ /**
35
+ * Resolves a credential session for a slot declared on this trigger's
36
+ * {@link import("./workflowTypes").NodeConfigBase.getCredentialRequirements}. Same contract as
37
+ * {@link import("./runtimeTypes").ExecutionContext.getCredential}.
38
+ */
39
+ getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
40
+ /** AbortSignal raised when the suite is cancelled — long-running pulls should bail out. */
41
+ readonly signal: AbortSignal;
42
+ }
43
+ /**
44
+ * A trigger config that emits **test cases**. Each item yielded by {@link generateItems}
45
+ * becomes one workflow run (with `executionOptions.testContext` set), so 10 yielded items
46
+ * → 10 runs marked under the same TestSuiteRun.
47
+ *
48
+ * The trigger is otherwise a normal {@link TriggerNodeConfig} (so the canvas treats it like
49
+ * any other trigger), but its `triggerKind` is `"test"` so the live activation policy skips it.
50
+ */
51
+ interface TestTriggerNodeConfig<TOutputJson$1 = unknown> extends TriggerNodeConfig<TOutputJson$1, undefined> {
52
+ readonly triggerKind: "test";
53
+ /**
54
+ * Author-supplied async iterable of items, evaluated lazily. Implementations may fetch from
55
+ * credentialed APIs, read fixture files, or yield hard-coded items. The orchestrator iterates
56
+ * and dispatches one run per item, with concurrency capped by {@link concurrency} (default 4).
57
+ */
58
+ generateItems(ctx: TestTriggerSetupContext<TestTriggerNodeConfig<TOutputJson$1>>): AsyncIterable<Item<TOutputJson$1>>;
59
+ /** Per-suite-run cap on simultaneously-executing test cases. Default: 4. */
60
+ readonly concurrency?: number;
61
+ /**
62
+ * Free-form description of where the test cases come from — surfaced in the node properties
63
+ * panel and the suite-detail header so authors revisiting the workflow six months later
64
+ * remember which mailbox / folder / fixture file the cases originate from.
65
+ *
66
+ * Example: `"All emails in the Gmail label \"test/triage-fixtures\" — 14 messages as of 2026-05-03."`
67
+ */
68
+ readonly description?: string;
69
+ /**
70
+ * Resolves a human-readable label for one yielded test case (e.g. email subject). The
71
+ * orchestrator calls this once per yielded item, persists the result on the run, and the
72
+ * Tests-tab UI uses it to render the case row instead of the opaque runId. Return
73
+ * `undefined` to fall back to "Case #N".
74
+ */
75
+ caseLabel?(item: Item<TOutputJson$1>): string | undefined;
76
+ }
77
+ //#endregion
17
78
  //#region ../core/src/contracts/baseTypes.d.ts
18
79
  /**
19
80
  * Minimal base types that have no dependencies on other contracts.
@@ -26,77 +87,333 @@ type OutputPortKey = string;
26
87
  type InputPortKey = string;
27
88
  type NodeConnectionName = string;
28
89
  //#endregion
29
- //#region ../core/src/contracts/credentialTypes.d.ts
30
- type CredentialTypeId = string;
31
- type CredentialInstanceId = string;
32
- type CredentialMaterialSourceKind = "db" | "env" | "code";
33
- type CredentialSetupStatus = "draft" | "ready";
34
- type CredentialHealthStatus = "unknown" | "healthy" | "failing";
35
- type CredentialFieldSchema = Readonly<{
36
- key: string;
37
- label: string;
38
- type: "string" | "password" | "textarea" | "json" | "boolean";
39
- required?: true;
40
- order?: number;
90
+ //#region ../core/src/contracts/CostTrackingTelemetryContract.d.ts
91
+ type CostTrackingComponent = "chat" | "ocr" | "rag";
92
+ interface CostTrackingUsageRecord {
93
+ readonly component: CostTrackingComponent;
94
+ readonly provider: string;
95
+ readonly operation: string;
96
+ readonly pricingKey: string;
97
+ readonly usageUnit: string;
98
+ readonly quantity: number;
99
+ readonly modelName?: string;
100
+ readonly attributes?: TelemetryAttributes;
101
+ }
102
+ interface CostTrackingPriceQuote {
103
+ readonly currency: string;
104
+ readonly currencyScale: number;
105
+ readonly estimatedAmountMinor: number;
106
+ readonly estimateKind: "catalog";
107
+ }
108
+ interface CostTrackingTelemetry {
109
+ captureUsage(args: CostTrackingUsageRecord): Promise<CostTrackingPriceQuote | undefined>;
110
+ forScope(scope: TelemetryScope): CostTrackingTelemetry;
111
+ }
112
+ //#endregion
113
+ //#region ../core/src/contracts/telemetryTypes.d.ts
114
+ type TelemetryAttributePrimitive = string | number | boolean | null;
115
+ interface TelemetryAttributes {
116
+ readonly [key: string]: TelemetryAttributePrimitive | undefined;
117
+ }
118
+ interface TelemetryMetricRecord {
119
+ readonly name: string;
120
+ readonly value: number;
121
+ readonly unit?: string;
122
+ readonly attributes?: TelemetryAttributes;
123
+ }
124
+ interface TelemetrySpanEventRecord {
125
+ readonly name: string;
126
+ readonly occurredAt?: Date;
127
+ readonly attributes?: TelemetryAttributes;
128
+ }
129
+ interface TelemetryArtifactAttachment {
130
+ readonly kind: string;
131
+ readonly contentType: string;
132
+ readonly previewText?: string;
133
+ readonly previewJson?: JsonValue;
134
+ readonly payloadText?: string;
135
+ readonly payloadJson?: JsonValue;
136
+ readonly bytes?: number;
137
+ readonly truncated?: boolean;
138
+ readonly expiresAt?: Date;
139
+ }
140
+ interface TelemetryArtifactReference {
141
+ readonly artifactId: string;
142
+ readonly traceId?: string;
143
+ readonly spanId?: string;
144
+ }
145
+ interface TelemetrySpanEnd {
146
+ readonly status?: "ok" | "error";
147
+ readonly statusMessage?: string;
148
+ readonly endedAt?: Date;
149
+ readonly attributes?: TelemetryAttributes;
150
+ }
151
+ interface TelemetryChildSpanStart {
152
+ readonly name: string;
153
+ readonly kind?: "internal" | "client";
154
+ readonly startedAt?: Date;
155
+ readonly attributes?: TelemetryAttributes;
156
+ }
157
+ interface TelemetryScope {
158
+ readonly traceId?: string;
159
+ readonly spanId?: string;
160
+ readonly costTracking?: CostTrackingTelemetry;
161
+ addSpanEvent(args: TelemetrySpanEventRecord): Promise<void> | void;
162
+ recordMetric(args: TelemetryMetricRecord): Promise<void> | void;
163
+ attachArtifact(args: TelemetryArtifactAttachment): Promise<TelemetryArtifactReference> | TelemetryArtifactReference;
164
+ }
165
+ interface TelemetrySpanScope extends TelemetryScope {
166
+ readonly traceId: string;
167
+ readonly spanId: string;
168
+ end(args?: TelemetrySpanEnd): Promise<void> | void;
41
169
  /**
42
- * Where this field appears in the credential dialog. Use `"advanced"` for optional or
43
- * power-user fields; they render inside a collapsible section (see `CredentialTypeDefinition.advancedSection`).
44
- * Defaults to `"default"` when omitted.
170
+ * Lift this span into a {@link NodeExecutionTelemetry} scoped to a different (nodeId, activationId).
171
+ * Children created via the returned telemetry's `startChildSpan` get this span as their parent.
172
+ *
173
+ * Used at the sub-agent boundary so that nested runtime telemetry parents under the agent.tool.call
174
+ * span instead of the orchestrator's node-level span.
45
175
  */
46
- visibility?: "default" | "advanced";
47
- placeholder?: string;
48
- helpText?: string;
49
- /** When set, host resolves this field from process.env at runtime; env wins over stored values. */
50
- envVarName?: string;
176
+ asNodeTelemetry(args: Readonly<{
177
+ nodeId: NodeId;
178
+ activationId: NodeActivationId;
179
+ }>): NodeExecutionTelemetry;
180
+ }
181
+ interface NodeExecutionTelemetry extends ExecutionTelemetry, TelemetrySpanScope {
182
+ startChildSpan(args: TelemetryChildSpanStart): TelemetrySpanScope;
183
+ }
184
+ interface ExecutionTelemetry extends TelemetryScope {
185
+ readonly traceId: string;
186
+ readonly spanId: string;
187
+ forNode(args: Readonly<{
188
+ nodeId: NodeId;
189
+ activationId: NodeActivationId;
190
+ }>): NodeExecutionTelemetry;
191
+ }
192
+ //#endregion
193
+ //#region ../core/src/contracts/agentMcpTypes.d.ts
194
+ /**
195
+ * An opaque MCP tool map: keyed by serverId → (toolName → tool definition).
196
+ * Typed as unknown so core does not depend on the AI SDK's ToolSet type.
197
+ * AIAgentNode (in core-nodes, which does depend on ai) casts this to
198
+ * ReadonlyMap<string, ToolSet> before passing to DeferredMetaToolStrategyFactory.
199
+ */
200
+ type AgentMcpToolMap = ReadonlyMap<string, Readonly<Record<string, unknown>>>;
201
+ /**
202
+ * Contract implemented by the host. Resolves MCP server bindings for an agent run
203
+ * via the standard credential-binding table (one slot per declared server, keyed
204
+ * by `(workflowId, mcpConnectionNodeId, "credential")`), and returns a ready-to-use
205
+ * tool map with wrapped execute callbacks for telemetry and 403 detection.
206
+ * Core-nodes imports this interface so AIAgentNode can inject it without
207
+ * depending on the host.
208
+ */
209
+ interface AgentMcpIntegration {
51
210
  /**
52
- * When set, the dialog shows a copy action for this exact string (e.g. a static OAuth redirect URI
53
- * pattern or documentation URL). Do not use for secret values.
211
+ * Look up the credential binding per server, validate scopes, open pool
212
+ * connections, and return a tool map keyed by serverId. Each tool's
213
+ * execute callback includes:
214
+ * - Telemetry child span (mcp.server_id, mcp.tool_name attributes)
215
+ * - 403/permission error detection → emits a NeedsReconsentEvent span event
216
+ *
217
+ * Throws `AgentBindError` on validation failures (missing server, unbound
218
+ * credential slot, missing credential instance, insufficient scopes).
54
219
  */
55
- copyValue?: string;
56
- /** Accessible label for the copy control (default: Copy). */
57
- copyButtonLabel?: string;
58
- }>;
59
- type CredentialRequirement = Readonly<{
60
- slotKey: string;
61
- label: string;
62
- acceptedTypes: ReadonlyArray<CredentialTypeId>;
63
- optional?: true;
64
- helpText?: string;
65
- helpUrl?: string;
66
- }>;
67
- type CredentialHealth = Readonly<{
68
- status: CredentialHealthStatus;
69
- message?: string;
70
- testedAt?: string;
71
- expiresAt?: string;
72
- details?: Readonly<Record<string, unknown>>;
73
- }>;
74
- type OAuth2ProviderFromPublicConfig = Readonly<{
75
- authorizeUrlFieldKey: string;
76
- tokenUrlFieldKey: string;
77
- userInfoUrlFieldKey?: string;
78
- }>;
79
- type CredentialOAuth2ScopesFromPublicConfig = Readonly<{
80
- presetFieldKey: string;
81
- presetScopes: Readonly<Record<string, ReadonlyArray<string>>>;
82
- customPresetKey?: string;
83
- customScopesFieldKey?: string;
84
- }>;
85
- type CredentialOAuth2AuthDefinition = Readonly<{
86
- kind: "oauth2";
87
- providerId: string;
88
- scopes: ReadonlyArray<string>;
89
- scopesFromPublicConfig?: CredentialOAuth2ScopesFromPublicConfig;
90
- clientIdFieldKey?: string;
91
- clientSecretFieldKey?: string;
92
- } | {
93
- kind: "oauth2";
94
- providerFromPublicConfig: OAuth2ProviderFromPublicConfig;
95
- scopes: ReadonlyArray<string>;
96
- scopesFromPublicConfig?: CredentialOAuth2ScopesFromPublicConfig;
97
- clientIdFieldKey?: string;
98
- clientSecretFieldKey?: string;
99
- } | {
220
+ prepareMcpTools(args: {
221
+ readonly workflowId: WorkflowId;
222
+ readonly agentNodeId: NodeId;
223
+ readonly serverIds: ReadonlyArray<string>;
224
+ readonly pinnedMcpTools: readonly string[];
225
+ readonly emitSpanEvent: (event: TelemetrySpanEventRecord) => void;
226
+ readonly startChildSpan: (args: {
227
+ readonly name: string;
228
+ readonly attributes?: Record<string, string>;
229
+ }) => {
230
+ readonly end: (args?: {
231
+ status?: "ok" | "error";
232
+ statusMessage?: string;
233
+ }) => void;
234
+ };
235
+ /** Per-MCP-tool-call invocation appender. Optional; when omitted the wrapper emits only telemetry spans. */
236
+ readonly appendMcpInvocation?: (args: ConnectionInvocationAppendArgs) => Promise<void>;
237
+ /** Agent activation id to attach to each invocation record (used by canvas + inspector grouping). */
238
+ readonly parentAgentActivationId?: NodeActivationId;
239
+ /** Per-item iteration id when the agent runs inside a per-item loop. */
240
+ readonly iterationId?: NodeIterationId;
241
+ /** Item index (0-based) of the iteration that owns these tool calls. */
242
+ readonly itemIndex?: number;
243
+ /** Parent invocation id when this agent is itself executing as a sub-agent. */
244
+ readonly parentInvocationId?: ConnectionInvocationId;
245
+ }): Promise<AgentMcpToolMap>;
246
+ }
247
+ //#endregion
248
+ //#region ../core/src/contracts/assertionTypes.d.ts
249
+ /**
250
+ * One assertion emitted by an assertion-emitting node (a node whose config sets
251
+ * `emitsAssertions: true`). Each emitted item on `main` carries one of these as `item.json`.
252
+ *
253
+ * Pass/fail is derived from `score >= (passThreshold ?? 0.5)` — see {@link deriveAssertionPassed}.
254
+ * The `errored` marker is for cases where the assertion code itself threw (distinct from
255
+ * "the assertion was evaluated and the score was low") and is treated as a hard fail in rollups
256
+ * regardless of `score`.
257
+ */
258
+ interface AssertionResult {
259
+ readonly name: string;
260
+ /** 0..1 score. Source of truth for pass/fail (compared against `passThreshold`). */
261
+ readonly score: number;
262
+ /** 0..1 threshold for "passed". When omitted, consumers default to 0.5. */
263
+ readonly passThreshold?: number;
264
+ /** True when evaluating the assertion threw — treated as fail regardless of `score`. */
265
+ readonly errored?: true;
266
+ /** What the assertion expected. Free-form JSON; UIs render with a JSON viewer. */
267
+ readonly expected?: JsonValue;
268
+ /** What the workflow actually produced. */
269
+ readonly actual?: JsonValue;
270
+ /** Short human-readable explanation, especially for fails / errors. */
271
+ readonly message?: string;
272
+ /** Bag of supplemental fields (e.g. judge prompt, judge raw response, comparison method). */
273
+ readonly details?: Readonly<Record<string, JsonValue>>;
274
+ }
275
+ //#endregion
276
+ //#region ../core/src/contracts/itemExpr.d.ts
277
+ declare const ITEM_EXPR_BRAND: unique symbol;
278
+ type ItemExprResolvedContext = Readonly<{
279
+ runId: RunId;
280
+ workflowId: WorkflowId;
281
+ nodeId: NodeId;
282
+ activationId: NodeActivationId;
283
+ data: RunDataSnapshot;
284
+ }>;
285
+ /**
286
+ * Context aligned with former {@link ItemInputMapperContext} — use **`data`** to read any completed upstream node.
287
+ */
288
+ type ItemExprContext = ItemExprResolvedContext;
289
+ type ItemExprArgs<TItemJson = unknown> = Readonly<{
290
+ item: Item<TItemJson>;
291
+ itemIndex: number;
292
+ items: Items<TItemJson>;
293
+ ctx: ItemExprContext;
294
+ }>;
295
+ type ItemExprCallback<T, TItemJson = unknown> = (args: ItemExprArgs<TItemJson>) => T | Promise<T>;
296
+ type ItemExpr<T, TItemJson = unknown> = Readonly<{
297
+ readonly [ITEM_EXPR_BRAND]: true;
298
+ readonly fn: ItemExprCallback<T, TItemJson>;
299
+ }>;
300
+ //#endregion
301
+ //#region ../core/src/contracts/params.d.ts
302
+ type Expr<T, TItemJson = unknown> = ItemExpr<T, TItemJson>;
303
+ type ParamDeep<T, TItemJson = unknown> = Expr<T, TItemJson> | (T extends readonly (infer U)[] ? ReadonlyArray<ParamDeep<U, TItemJson>> : never) | (T extends object ? { [K in keyof T]: ParamDeep<T[K], TItemJson> } : T);
304
+ //#endregion
305
+ //#region ../core/src/contracts/retryPolicySpec.types.d.ts
306
+ /**
307
+ * In-process retry policy for runnable nodes. Serialized configs use the same
308
+ * `kind` discriminator (`JSON.stringify` / persisted workflows).
309
+ *
310
+ * `maxAttempts` is the total number of tries including the first (e.g. 3 means up to 2 delays after failures).
311
+ */
312
+ type RetryPolicySpec = NoneRetryPolicySpec | FixedRetryPolicySpec | ExponentialRetryPolicySpec;
313
+ interface NoneRetryPolicySpec {
314
+ readonly kind: "none";
315
+ }
316
+ interface FixedRetryPolicySpec {
317
+ readonly kind: "fixed";
318
+ /** Total attempts including the first execution. Must be >= 1. */
319
+ readonly maxAttempts: number;
320
+ readonly delayMs: number;
321
+ }
322
+ interface ExponentialRetryPolicySpec {
323
+ readonly kind: "exponential";
324
+ /** Total attempts including the first execution. Must be >= 1. */
325
+ readonly maxAttempts: number;
326
+ readonly initialDelayMs: number;
327
+ readonly multiplier: number;
328
+ readonly maxDelayMs?: number;
329
+ /** When true, each delay is multiplied by a random factor in [1, 1.2). */
330
+ readonly jitter?: boolean;
331
+ }
332
+ //#endregion
333
+ //#region ../core/src/contracts/webhookTypes.d.ts
334
+ type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
335
+ interface WebhookControlSignal {
336
+ readonly __webhookControl: true;
337
+ readonly kind: "respondNow" | "respondNowAndContinue";
338
+ readonly responseItems: Items;
339
+ readonly continueItems?: Items;
340
+ }
341
+ interface TriggerInstanceId {
342
+ workflowId: WorkflowId;
343
+ nodeId: NodeId;
344
+ }
345
+ //#endregion
346
+ //#region ../core/src/contracts/credentialTypes.d.ts
347
+ type CredentialTypeId = string;
348
+ type CredentialInstanceId = string;
349
+ type CredentialMaterialSourceKind = "db" | "env" | "code";
350
+ type CredentialSetupStatus = "draft" | "ready";
351
+ type CredentialHealthStatus = "unknown" | "healthy" | "failing";
352
+ type CredentialFieldSchema = Readonly<{
353
+ key: string;
354
+ label: string;
355
+ type: "string" | "password" | "textarea" | "json" | "boolean";
356
+ required?: true;
357
+ order?: number;
358
+ /**
359
+ * Where this field appears in the credential dialog. Use `"advanced"` for optional or
360
+ * power-user fields; they render inside a collapsible section (see `CredentialTypeDefinition.advancedSection`).
361
+ * Defaults to `"default"` when omitted.
362
+ */
363
+ visibility?: "default" | "advanced";
364
+ placeholder?: string;
365
+ helpText?: string;
366
+ /** When set, host resolves this field from process.env at runtime; env wins over stored values. */
367
+ envVarName?: string;
368
+ /**
369
+ * When set, the dialog shows a copy action for this exact string (e.g. a static OAuth redirect URI
370
+ * pattern or documentation URL). Do not use for secret values.
371
+ */
372
+ copyValue?: string;
373
+ /** Accessible label for the copy control (default: Copy). */
374
+ copyButtonLabel?: string;
375
+ }>;
376
+ type CredentialRequirement = Readonly<{
377
+ slotKey: string;
378
+ label: string;
379
+ acceptedTypes: ReadonlyArray<CredentialTypeId>;
380
+ optional?: true;
381
+ helpText?: string;
382
+ helpUrl?: string;
383
+ }>;
384
+ type CredentialHealth = Readonly<{
385
+ status: CredentialHealthStatus;
386
+ message?: string;
387
+ testedAt?: string;
388
+ expiresAt?: string;
389
+ details?: Readonly<Record<string, unknown>>;
390
+ }>;
391
+ type OAuth2ProviderFromPublicConfig = Readonly<{
392
+ authorizeUrlFieldKey: string;
393
+ tokenUrlFieldKey: string;
394
+ userInfoUrlFieldKey?: string;
395
+ }>;
396
+ type CredentialOAuth2ScopesFromPublicConfig = Readonly<{
397
+ presetFieldKey: string;
398
+ presetScopes: Readonly<Record<string, ReadonlyArray<string>>>;
399
+ customPresetKey?: string;
400
+ customScopesFieldKey?: string;
401
+ }>;
402
+ type CredentialOAuth2AuthDefinition = Readonly<{
403
+ kind: "oauth2";
404
+ providerId: string;
405
+ scopes: ReadonlyArray<string>;
406
+ scopesFromPublicConfig?: CredentialOAuth2ScopesFromPublicConfig;
407
+ clientIdFieldKey?: string;
408
+ clientSecretFieldKey?: string;
409
+ } | {
410
+ kind: "oauth2";
411
+ providerFromPublicConfig: OAuth2ProviderFromPublicConfig;
412
+ scopes: ReadonlyArray<string>;
413
+ scopesFromPublicConfig?: CredentialOAuth2ScopesFromPublicConfig;
414
+ clientIdFieldKey?: string;
415
+ clientSecretFieldKey?: string;
416
+ } | {
100
417
  kind: "oauth2";
101
418
  /**
102
419
  * Free-form provider identifier for telemetry, DB rows, and Better Auth provider naming.
@@ -161,6 +478,19 @@ type CredentialInstanceRecord<TPublicConfig extends CredentialJsonRecord = Crede
161
478
  setupStatus: CredentialSetupStatus;
162
479
  createdAt: string;
163
480
  updatedAt: string;
481
+ /**
482
+ * Pointer to where the credential material bytes live. For OSS / standalone
483
+ * rows this is `{source: "local", ref: instanceId}` and the bytes co-locate
484
+ * with the row in the workspace DB. For managed-mode rows this is
485
+ * `{source: "control-plane", ref: <cp_id>}` and the bytes live at CP.
486
+ *
487
+ * The seam is read through `CredentialMaterialProvider`. See
488
+ * `docs/design/credentials-oauth-unification.md` ("Material provider seam").
489
+ */
490
+ material: Readonly<{
491
+ source: "local" | "control-plane";
492
+ ref: string;
493
+ }>;
164
494
  }>;
165
495
  /**
166
496
  * Arguments passed to `CredentialType.createSession` and `CredentialType.test`.
@@ -197,36 +527,282 @@ interface CredentialSessionService {
197
527
  }>): Promise<TSession>;
198
528
  }
199
529
  //#endregion
200
- //#region ../core/src/triggers/polling/PollingTriggerDedupWindow.d.ts
201
- /**
202
- * Merges processed-ID windows for polling triggers, capping the total to avoid unbounded growth.
203
- * Plugin code receives an instance of this class via {@link PollingTriggerHandle.dedup}.
204
- */
205
- declare class PollingTriggerDedupWindow {
206
- static readonly defaultCapN = 2000;
207
- merge(previous: ReadonlyArray<string>, incoming: ReadonlyArray<string>, capN?: number): ReadonlyArray<string>;
530
+ //#region ../core/src/contracts/mcpTypes.d.ts
531
+ type McpServerTransport = "http";
532
+ interface McpServerDeclaration {
533
+ /** Globally unique slug, e.g. "gmail". Workflow authors reference this. */
534
+ id: string;
535
+ displayName: string;
536
+ description: string;
537
+ transport: McpServerTransport;
538
+ url: string;
539
+ /**
540
+ * Credential types accepted by this MCP server, matching CredentialRequirement.acceptedTypes.
541
+ * Absent or empty means no credential is required.
542
+ */
543
+ acceptedCredentialTypes?: ReadonlyArray<string>;
544
+ /**
545
+ * Documentation only in MVP. The bind-time validator checks
546
+ * requiredScopes ⊆ CredentialInstance.scopesGranted.
547
+ */
548
+ requiredScopes?: string[];
549
+ /** Non-secret static headers merged onto every MCP request. */
550
+ staticHeaders?: Record<string, string>;
551
+ /**
552
+ * Overrides for tool descriptions advertised by the MCP server.
553
+ * Applied by the connection pool after tools/list.
554
+ * Key: exact tool name as returned by the server.
555
+ */
556
+ toolDescriptionOverrides?: Record<string, string>;
208
557
  }
209
558
  //#endregion
210
- //#region ../core/src/contracts/runTypes.d.ts
559
+ //#region ../core/src/contracts/collectionTypes.d.ts
211
560
  /**
212
- * Test-suite linkage for a run. When set, this run was started by a TestSuiteOrchestrator
213
- * as one test case inside a TestSuiteRun. The `IsTestRun` node and host-side persisters key
214
- * off the presence of this field. Subworkflow runs inherit it from their parent run.
561
+ * Represents a typed store for a single collection.
562
+ * All rows include auto-managed id, created_at, and updated_at fields.
215
563
  */
216
- interface RunTestContext {
217
- readonly testSuiteRunId: string;
218
- readonly testCaseIndex: number;
564
+ interface CollectionStore<TRow extends Record<string, unknown> = Record<string, unknown>> {
219
565
  /**
220
- * Optional human-friendly label for this test case (e.g. an email subject when fixtures
221
- * are loaded from a mailbox). Resolved per item by `TestTrigger.caseLabel(item)` if set,
222
- * persisted on `Run.test_case_label` so the Tests-tab tree-table can show "RFQ for batch 14"
223
- * instead of "run_1777755971399_bbb86beac1396".
566
+ * Insert a new row. id, created_at, and updated_at are auto-populated.
224
567
  */
225
- readonly testCaseLabel?: string;
226
- }
227
- type NodeInputsByPort = Readonly<Record<InputPortKey, Items>>;
228
- type NodeExecutionStatus = "pending" | "queued" | "running" | "completed" | "failed" | "skipped";
229
- interface NodeExecutionError {
568
+ insert(row: TRow): Promise<TRow & {
569
+ id: string;
570
+ created_at: Date;
571
+ updated_at: Date;
572
+ }>;
573
+ /**
574
+ * Get a single row by id.
575
+ */
576
+ get(id: string): Promise<(TRow & {
577
+ id: string;
578
+ created_at: Date;
579
+ updated_at: Date;
580
+ }) | null>;
581
+ /**
582
+ * Find a single row matching the provided filter.
583
+ */
584
+ findOne(filter: Partial<TRow>): Promise<(TRow & {
585
+ id: string;
586
+ created_at: Date;
587
+ updated_at: Date;
588
+ }) | null>;
589
+ /**
590
+ * List rows with optional pagination and filtering.
591
+ */
592
+ list(opts?: {
593
+ limit?: number;
594
+ offset?: number;
595
+ where?: Partial<TRow>;
596
+ }): Promise<{
597
+ rows: ReadonlyArray<TRow & {
598
+ id: string;
599
+ created_at: Date;
600
+ updated_at: Date;
601
+ }>;
602
+ total: number;
603
+ }>;
604
+ /**
605
+ * Update a row by id with partial data.
606
+ */
607
+ update(id: string, patch: Partial<TRow>): Promise<TRow & {
608
+ id: string;
609
+ created_at: Date;
610
+ updated_at: Date;
611
+ }>;
612
+ /**
613
+ * Delete a row by id. Hard delete only (no soft delete).
614
+ */
615
+ delete(id: string): Promise<{
616
+ deleted: boolean;
617
+ }>;
618
+ }
619
+ /**
620
+ * Runtime collections context: keyed by collection name.
621
+ */
622
+ type CollectionsContext = Readonly<Record<string, CollectionStore>>;
623
+ //#endregion
624
+ //#region ../core/src/contracts/emitPorts.d.ts
625
+ declare const EMIT_PORTS_BRAND: unique symbol;
626
+ type PortsEmission = Readonly<{
627
+ readonly [EMIT_PORTS_BRAND]: true;
628
+ readonly ports: Readonly<Partial<Record<OutputPortKey, Items | ReadonlyArray<JsonNonArray>>>>;
629
+ }>;
630
+ //#endregion
631
+ //#region ../core/src/authoring/defineNode.types.d.ts
632
+ type ResolvableCredentialType = AnyCredentialType | CredentialTypeId;
633
+ type DefinedNodeCredentialBinding = ResolvableCredentialType | Readonly<{
634
+ readonly type: ResolvableCredentialType | ReadonlyArray<ResolvableCredentialType>;
635
+ readonly label?: string;
636
+ readonly optional?: true;
637
+ readonly helpText?: string;
638
+ readonly helpUrl?: string;
639
+ }>;
640
+ type DefinedNodeCredentialBindings = Readonly<Record<string, DefinedNodeCredentialBinding>>;
641
+ type DefinedNodeConfigInput<TConfigResolved extends CredentialJsonRecord, TItemJson> = ParamDeep<TConfigResolved, TItemJson>;
642
+ interface DefinedNode<TKey$1 extends string, TConfig extends CredentialJsonRecord, TInputJson$1, TOutputJson$1, _TBindings extends DefinedNodeCredentialBindings | undefined = undefined> {
643
+ readonly kind: "defined-node";
644
+ readonly key: TKey$1;
645
+ readonly title: string;
646
+ readonly description?: string;
647
+ create<TConfigItemJson = TInputJson$1>(config: DefinedNodeConfigInput<TConfig, TConfigItemJson>, name?: string, id?: string): RunnableNodeConfig<TInputJson$1, TOutputJson$1>;
648
+ register(context: {
649
+ registerNode<TValue>(token: TypeToken<TValue>, implementation?: TypeToken<TValue>): void;
650
+ }): void;
651
+ }
652
+ //#endregion
653
+ //#region ../core/src/authoring/defineHumanApprovalNode.types.d.ts
654
+ /**
655
+ * Decision shape merged into `item.json` after a HITL approval task resolves.
656
+ *
657
+ * - `"approved"` / `"rejected"` — from a human decision (uses `approvedPredicate`).
658
+ * - `"timed-out"` — timeout fired with `onTimeout: "halt"`.
659
+ * - `"auto-accepted"` — timeout fired with `onTimeout: "auto-accept"`.
660
+ */
661
+ interface HumanApprovalDecisionResult {
662
+ readonly status: "approved" | "rejected" | "timed-out" | "auto-accepted";
663
+ /** Identity of the person who decided; absent for automated outcomes. */
664
+ readonly actor?: HumanTaskActor;
665
+ /** ISO 8601 timestamp of the decision. */
666
+ readonly decidedAt?: Date;
667
+ /** Optional free-text note from the reviewer. */
668
+ readonly note?: string;
669
+ /**
670
+ * Full raw decision payload (only present for `"approved"` / `"rejected"`).
671
+ * Shape is determined by the channel's `decisionSchema`.
672
+ */
673
+ readonly payload?: Record<string, unknown>;
674
+ }
675
+ /**
676
+ * Output item shape emitted by a `defineHumanApprovalNode`-based node.
677
+ * Original `item.json` fields are preserved and `decision` is merged in.
678
+ * If the input `item.json` already contained a `decision` key it is **overwritten**.
679
+ */
680
+ type HumanApprovalOutputJson<TInputJson$1 extends Record<string, unknown>> = TInputJson$1 & {
681
+ readonly decision: HumanApprovalDecisionResult;
682
+ };
683
+ /**
684
+ * Extends {@link DefinedNode} with the `humanApprovalToolBehavior` metadata marker.
685
+ * Story 10 reads this field when attaching the node as an agent tool.
686
+ */
687
+ interface DefinedHumanApprovalNode<TKey$1 extends string, TConfig extends CredentialJsonRecord, TInputJson$1 extends Record<string, unknown>, TBindings extends DefinedNodeCredentialBindings | undefined = undefined> extends DefinedNode<TKey$1, TConfig, TInputJson$1, HumanApprovalOutputJson<TInputJson$1>, TBindings> {
688
+ /**
689
+ * Behavior hint consumed by the agent runtime (story 10) when this node is attached as a tool.
690
+ * `"return"` (default) — return the rejection to the agent as a tool result.
691
+ * `"halt"` — halt the agent run on rejection.
692
+ *
693
+ * Standalone DSL usage ignores this field.
694
+ */
695
+ readonly humanApprovalToolBehavior: {
696
+ onRejected: "return" | "halt";
697
+ };
698
+ }
699
+ //#endregion
700
+ //#region ../core/src/workflow/dsl/workflowBuilderTypes.d.ts
701
+ type AnyRunnableNodeConfig = RunnableNodeConfig<any, any>;
702
+ type AnyTriggerNodeConfig = TriggerNodeConfig<any>;
703
+ type ValidStepSequence<TCurrentJson, TSteps extends ReadonlyArray<AnyRunnableNodeConfig>> = TSteps extends readonly [] ? readonly [] : TSteps extends readonly [infer TFirst, ...infer TRest] ? TFirst extends RunnableNodeConfig<TCurrentJson, infer TNextJson> ? TRest extends ReadonlyArray<AnyRunnableNodeConfig> ? readonly [TFirst, ...ValidStepSequence<TNextJson, TRest>] : never : never : TSteps;
704
+ type StepSequenceOutput<TCurrentJson, TSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined> = TSteps extends ReadonlyArray<AnyRunnableNodeConfig> ? TSteps extends readonly [] ? TCurrentJson : TSteps extends readonly [infer TFirst, ...infer TRest] ? TFirst extends RunnableNodeConfig<TCurrentJson, infer TNextJson> ? TRest extends ReadonlyArray<AnyRunnableNodeConfig> ? StepSequenceOutput<TNextJson, TRest> : never : never : TCurrentJson : TCurrentJson;
705
+ type TypesMatch<TLeft, TRight> = [TLeft] extends [TRight] ? ([TRight] extends [TLeft] ? true : false) : false;
706
+ type BranchOutputGuard<TCurrentJson, TTrueSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined, TFalseSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined> = TypesMatch<StepSequenceOutput<TCurrentJson, TTrueSteps>, StepSequenceOutput<TCurrentJson, TFalseSteps>> extends true ? unknown : never;
707
+ type BranchStepsArg<TCurrentJson, TSteps extends ReadonlyArray<AnyRunnableNodeConfig>> = TSteps & ValidStepSequence<TCurrentJson, TSteps>;
708
+ type BranchMoreArgs<TCurrentJson, TFirstStep extends RunnableNodeConfig<TCurrentJson, any>, TRestSteps extends ReadonlyArray<AnyRunnableNodeConfig>> = TRestSteps & ValidStepSequence<RunnableNodeOutputJson<TFirstStep>, TRestSteps>;
709
+ type BooleanWhenOverloads<TCurrentJson, TReturn> = {
710
+ <TSteps extends ReadonlyArray<AnyRunnableNodeConfig>>(branch: boolean, steps: BranchStepsArg<TCurrentJson, TSteps>): TReturn;
711
+ <TFirstStep extends RunnableNodeConfig<TCurrentJson, any>, TRestSteps extends ReadonlyArray<AnyRunnableNodeConfig>>(branch: boolean, step: TFirstStep, ...more: BranchMoreArgs<TCurrentJson, TFirstStep, TRestSteps>): TReturn;
712
+ };
713
+ //#endregion
714
+ //#region ../core/src/workflow/dsl/WhenBuilder.d.ts
715
+ declare class WhenBuilder<TCurrentJson> {
716
+ private readonly wf;
717
+ private readonly from;
718
+ private readonly branchPort;
719
+ constructor(wf: WorkflowBuilder, from: NodeRef, branchPort: OutputPortKey);
720
+ addBranch<TSteps extends ReadonlyArray<AnyRunnableNodeConfig>>(steps: TSteps & ValidStepSequence<TCurrentJson, TSteps>): this;
721
+ readonly when: BooleanWhenOverloads<TCurrentJson, WhenBuilder<TCurrentJson>>;
722
+ build(): WorkflowDefinition;
723
+ }
724
+ //#endregion
725
+ //#region ../core/src/workflow/dsl/ChainCursorResolver.d.ts
726
+ type ChainCursorEndpoint = Readonly<{
727
+ node: NodeRef;
728
+ output: OutputPortKey;
729
+ inputPortHint?: InputPortKey;
730
+ }>;
731
+ type ChainCursorWhenOverloads<TCurrentJson> = BooleanWhenOverloads<TCurrentJson, WhenBuilder<TCurrentJson>> & {
732
+ <TTrueSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined, TFalseSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined>(branches: Readonly<{
733
+ true?: TTrueSteps extends ReadonlyArray<AnyRunnableNodeConfig> ? BranchStepsArg<TCurrentJson, TTrueSteps> : never;
734
+ false?: TFalseSteps extends ReadonlyArray<AnyRunnableNodeConfig> ? BranchStepsArg<TCurrentJson, TFalseSteps> : never;
735
+ }> & BranchOutputGuard<TCurrentJson, TTrueSteps, TFalseSteps>): ChainCursor<StepSequenceOutput<TCurrentJson, TTrueSteps>>;
736
+ };
737
+ declare class ChainCursor<TCurrentJson> {
738
+ private readonly wf;
739
+ private readonly endpoints;
740
+ constructor(wf: WorkflowBuilder, endpoints: ReadonlyArray<ChainCursorEndpoint>);
741
+ then<TOutputJson$1, TConfig extends RunnableNodeConfig<TCurrentJson, TOutputJson$1>>(config: TConfig): ChainCursor<RunnableNodeOutputJson<TConfig>>;
742
+ thenIntoInputHints<TOutputJson$1, TConfig extends RunnableNodeConfig<any, TOutputJson$1>>(config: TConfig): ChainCursor<RunnableNodeOutputJson<TConfig>>;
743
+ readonly when: ChainCursorWhenOverloads<TCurrentJson>;
744
+ route<TNextJson$1>(branches: Readonly<Record<OutputPortKey, (branch: ChainCursor<TCurrentJson>) => ChainCursor<TNextJson$1> | undefined>>): ChainCursor<TNextJson$1>;
745
+ /**
746
+ * Chainable shorthand for `.then(node.create(config, metadata?.name, metadata?.nodeId))`.
747
+ *
748
+ * Signals to readers that this step suspends the run and waits for a human decision.
749
+ * Throws at workflow-build time if `node` was not created via `defineHumanApprovalNode`.
750
+ *
751
+ * @example
752
+ * ```ts
753
+ * workflow
754
+ * .trigger(...)
755
+ * .humanApproval(inboxApproval, { title: "Approve?", body: "...", priority: "normal" })
756
+ * .then(nextStep.create(...))
757
+ * .build();
758
+ * ```
759
+ */
760
+ humanApproval<TKey$1 extends string, TConfig extends Record<string, unknown>, TBindings extends DefinedNodeCredentialBindings | undefined = undefined>(node: DefinedHumanApprovalNode<TKey$1, TConfig, TCurrentJson & Record<string, unknown>, TBindings>, config: TConfig, metadata?: {
761
+ name?: string;
762
+ nodeId?: string;
763
+ }): ChainCursor<HumanApprovalOutputJson<TCurrentJson & Record<string, unknown>>>;
764
+ build(): WorkflowDefinition;
765
+ private resolveSharedInputPortHint;
766
+ }
767
+ //#endregion
768
+ //#region ../core/src/workflow/dsl/WorkflowBuilder.d.ts
769
+ declare class WorkflowBuilder {
770
+ private readonly meta;
771
+ private readonly options?;
772
+ private readonly nodes;
773
+ private readonly edges;
774
+ constructor(meta: {
775
+ id: WorkflowId;
776
+ name: string;
777
+ }, options?: Readonly<Record<string, never>> | undefined);
778
+ private add;
779
+ private connect;
780
+ trigger<TConfig extends AnyTriggerNodeConfig>(config: TConfig): ChainCursor<TriggerNodeOutputJson<TConfig>>;
781
+ start<TConfig extends AnyRunnableNodeConfig>(config: TConfig): ChainCursor<RunnableNodeOutputJson<TConfig>>;
782
+ build(): WorkflowDefinition;
783
+ private validateNodeIds;
784
+ }
785
+ //#endregion
786
+ //#region ../core/src/contracts/runTypes.d.ts
787
+ /**
788
+ * Test-suite linkage for a run. When set, this run was started by a TestSuiteOrchestrator
789
+ * as one test case inside a TestSuiteRun. The `IsTestRun` node and host-side persisters key
790
+ * off the presence of this field. Subworkflow runs inherit it from their parent run.
791
+ */
792
+ interface RunTestContext {
793
+ readonly testSuiteRunId: string;
794
+ readonly testCaseIndex: number;
795
+ /**
796
+ * Optional human-friendly label for this test case (e.g. an email subject when fixtures
797
+ * are loaded from a mailbox). Resolved per item by `TestTrigger.caseLabel(item)` if set,
798
+ * persisted on `Run.test_case_label` so the Tests-tab tree-table can show "RFQ for batch 14"
799
+ * instead of "run_1777755971399_bbb86beac1396".
800
+ */
801
+ readonly testCaseLabel?: string;
802
+ }
803
+ type NodeInputsByPort = Readonly<Record<InputPortKey, Items>>;
804
+ type NodeExecutionStatus = "pending" | "queued" | "running" | "completed" | "failed" | "skipped" | "hitl-approved" | "hitl-rejected" | "hitl-timeout" | "hitl-auto-accepted" | "hitl-cancelled";
805
+ interface NodeExecutionError {
230
806
  message: string;
231
807
  name?: string;
232
808
  stack?: string;
@@ -253,6 +829,8 @@ type ConnectionInvocationAppendArgs = Readonly<{
253
829
  itemIndex?: number;
254
830
  parentInvocationId?: ConnectionInvocationId;
255
831
  }>;
832
+ /** Reason a run transitioned to {@link RunStatus} `"halted"`. */
833
+ type RunHaltReason = "hitl-rejected" | "hitl-timeout" | "hitl-cancelled";
256
834
  interface PendingNodeExecution {
257
835
  runId: RunId;
258
836
  activationId: NodeActivationId;
@@ -285,36 +863,14 @@ type RunResult = {
285
863
  error: {
286
864
  message: string;
287
865
  };
866
+ } | {
867
+ runId: RunId;
868
+ workflowId: WorkflowId;
869
+ startedAt: string;
870
+ status: "halted";
871
+ reason: RunHaltReason;
288
872
  };
289
873
  //#endregion
290
- //#region ../core/src/contracts/retryPolicySpec.types.d.ts
291
- /**
292
- * In-process retry policy for runnable nodes. Serialized configs use the same
293
- * `kind` discriminator (`JSON.stringify` / persisted workflows).
294
- *
295
- * `maxAttempts` is the total number of tries including the first (e.g. 3 means up to 2 delays after failures).
296
- */
297
- type RetryPolicySpec = NoneRetryPolicySpec | FixedRetryPolicySpec | ExponentialRetryPolicySpec;
298
- interface NoneRetryPolicySpec {
299
- readonly kind: "none";
300
- }
301
- interface FixedRetryPolicySpec {
302
- readonly kind: "fixed";
303
- /** Total attempts including the first execution. Must be >= 1. */
304
- readonly maxAttempts: number;
305
- readonly delayMs: number;
306
- }
307
- interface ExponentialRetryPolicySpec {
308
- readonly kind: "exponential";
309
- /** Total attempts including the first execution. Must be >= 1. */
310
- readonly maxAttempts: number;
311
- readonly initialDelayMs: number;
312
- readonly multiplier: number;
313
- readonly maxDelayMs?: number;
314
- /** When true, each delay is multiplied by a random factor in [1, 1.2). */
315
- readonly jitter?: boolean;
316
- }
317
- //#endregion
318
874
  //#region ../core/src/contracts/workflowTypes.d.ts
319
875
  type NodeIdRef<TJson = unknown> = NodeId & Readonly<{
320
876
  __codemationNodeJson?: TJson;
@@ -484,535 +1040,163 @@ type BinaryAttachment = Readonly<{
484
1040
  id: string;
485
1041
  storageKey: string;
486
1042
  mimeType: string;
487
- size: number;
488
- storageDriver: string;
489
- previewKind: BinaryPreviewKind;
490
- createdAt: string;
491
- runId: RunId;
492
- workflowId: WorkflowId;
493
- nodeId: NodeId;
494
- activationId: NodeActivationId;
495
- filename?: string;
496
- sha256?: string;
497
- }>;
498
- type ItemBinary = Readonly<Record<string, BinaryAttachment>>;
499
- type Item<TJson = unknown> = Readonly<{
500
- json: TJson;
501
- binary?: ItemBinary;
502
- meta?: Readonly<Record<string, unknown>>;
503
- paired?: ReadonlyArray<PairedItemRef>;
504
- }>;
505
- type Items<TJson = unknown> = ReadonlyArray<Item<TJson>>;
506
- type NodeOutputs = Partial<Record<OutputPortKey, Items>>;
507
- type RunId = string;
508
- type NodeActivationId = string;
509
- /**
510
- * One per-item iteration of a runnable node's execute loop. Refines `NodeActivationId` for
511
- * per-item connection invocations and telemetry. Undefined when the executing node is a batch
512
- * node or trigger that does not iterate items.
513
- */
514
- type NodeIterationId = string;
515
- interface ParentExecutionRef {
516
- runId: RunId;
517
- workflowId: WorkflowId;
518
- nodeId: NodeId;
519
- /** Subworkflow depth of the **spawning** run (0 = root). Passed when starting a child run. */
520
- subworkflowDepth?: number;
521
- /** Effective max node activations from the parent run (propagated to child policy merge). */
522
- engineMaxNodeActivations?: number;
523
- /** Effective max subworkflow depth from the parent run (propagated to child policy merge). */
524
- engineMaxSubworkflowDepth?: number;
525
- /**
526
- * Test-suite linkage inherited by the child subworkflow run. Set by whichever node
527
- * spawns the subworkflow when its own `ctx.testContext` is present, so assertions
528
- * emitted inside a subworkflow land under the correct parent test case.
529
- */
530
- testContext?: RunTestContext;
531
- }
532
- interface RunDataSnapshot {
533
- getOutputs(nodeId: NodeId): NodeOutputs | undefined;
534
- getOutputItems<TJson = unknown>(nodeId: NodeId | NodeIdRef<TJson>, output?: OutputPortKey): Items<TJson>;
535
- getOutputItem<TJson = unknown>(nodeId: NodeId | NodeIdRef<TJson>, itemIndex: number, output?: OutputPortKey): Item<TJson> | undefined;
536
- }
537
- interface ActivationIdFactory {
538
- makeActivationId(): NodeActivationId;
539
- }
540
- type UpstreamRefPlaceholder = `$${number}`;
541
- /** Whether to persist run execution data after the workflow finishes. */
542
- type WorkflowStoragePolicyMode = "ALL" | "SUCCESS" | "ERROR" | "NEVER";
543
- type WorkflowStoragePolicySpec = WorkflowStoragePolicyMode | TypeToken<WorkflowStoragePolicyResolver>;
544
- interface WorkflowStoragePolicyResolver {
545
- shouldPersist(args: WorkflowStoragePolicyDecisionArgs): boolean | Promise<boolean>;
546
- }
547
- interface WorkflowStoragePolicyDecisionArgs {
548
- readonly runId: RunId;
549
- readonly workflowId: WorkflowId;
550
- readonly workflow: WorkflowDefinition;
551
- readonly finalStatus: "completed" | "failed";
552
- readonly startedAt: string;
553
- readonly finishedAt: string;
554
- }
555
- interface WorkflowPrunePolicySpec {
556
- readonly runDataRetentionSeconds?: number;
557
- readonly binaryRetentionSeconds?: number;
558
- readonly telemetrySpanRetentionSeconds?: number;
559
- readonly telemetryArtifactRetentionSeconds?: number;
560
- readonly telemetryMetricRetentionSeconds?: number;
561
- }
562
- interface WorkflowErrorHandler {
563
- onError(ctx: WorkflowErrorContext): void | Promise<void>;
564
- }
565
- interface WorkflowErrorContext {
566
- readonly runId: RunId;
567
- readonly workflowId: WorkflowId;
568
- readonly workflow: WorkflowDefinition;
569
- readonly failedNodeId: NodeId;
570
- readonly error: Error;
571
- readonly startedAt: string;
572
- readonly finishedAt: string;
573
- }
574
- type WorkflowErrorHandlerSpec = TypeToken<WorkflowErrorHandler> | WorkflowErrorHandler;
575
- interface NodeErrorHandlerArgs<TConfig extends NodeConfigBase = NodeConfigBase> {
576
- readonly kind: "single" | "multi";
577
- readonly items: Items;
578
- readonly inputsByPort: Readonly<Record<InputPortKey, Items>> | undefined;
579
- readonly ctx: NodeExecutionContext<TConfig>;
580
- readonly error: Error;
581
- }
582
- interface NodeErrorHandler {
583
- handle<TConfig extends NodeConfigBase>(args: NodeErrorHandlerArgs<TConfig>): Promise<NodeOutputs>;
584
- }
585
- type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandler;
586
- //#endregion
587
- //#region ../core/src/contracts/testTriggerTypes.d.ts
588
- /**
589
- * Identifier minted by the host (or in-memory test runner) for one execution of a test suite.
590
- * One TestSuiteRun produces N child workflow runs, one per item yielded by `generateItems`.
591
- */
592
- type TestSuiteRunId = string;
593
- /**
594
- * Setup context passed to a {@link TestTriggerNodeConfig.generateItems} callback. Distinct from
595
- * {@link import("./runtimeTypes").TriggerSetupContext} on purpose: test triggers are not
596
- * activated by the live trigger lifecycle (webhooks, cron, polling) and never call `emit` —
597
- * the orchestrator pulls from the iterable they return and dispatches one run per item.
598
- */
599
- interface TestTriggerSetupContext<TConfig extends TestTriggerNodeConfig<unknown> = TestTriggerNodeConfig<unknown>> {
600
- readonly workflowId: WorkflowId;
601
- readonly nodeId: NodeId;
602
- readonly config: TConfig;
603
- readonly testSuiteRunId: TestSuiteRunId;
604
- /**
605
- * Resolves a credential session for a slot declared on this trigger's
606
- * {@link import("./workflowTypes").NodeConfigBase.getCredentialRequirements}. Same contract as
607
- * {@link import("./runtimeTypes").ExecutionContext.getCredential}.
608
- */
609
- getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
610
- /** AbortSignal raised when the suite is cancelled — long-running pulls should bail out. */
611
- readonly signal: AbortSignal;
612
- }
613
- /**
614
- * A trigger config that emits **test cases**. Each item yielded by {@link generateItems}
615
- * becomes one workflow run (with `executionOptions.testContext` set), so 10 yielded items
616
- * → 10 runs marked under the same TestSuiteRun.
617
- *
618
- * The trigger is otherwise a normal {@link TriggerNodeConfig} (so the canvas treats it like
619
- * any other trigger), but its `triggerKind` is `"test"` so the live activation policy skips it.
620
- */
621
- interface TestTriggerNodeConfig<TOutputJson$1 = unknown> extends TriggerNodeConfig<TOutputJson$1, undefined> {
622
- readonly triggerKind: "test";
623
- /**
624
- * Author-supplied async iterable of items, evaluated lazily. Implementations may fetch from
625
- * credentialed APIs, read fixture files, or yield hard-coded items. The orchestrator iterates
626
- * and dispatches one run per item, with concurrency capped by {@link concurrency} (default 4).
627
- */
628
- generateItems(ctx: TestTriggerSetupContext<TestTriggerNodeConfig<TOutputJson$1>>): AsyncIterable<Item<TOutputJson$1>>;
629
- /** Per-suite-run cap on simultaneously-executing test cases. Default: 4. */
630
- readonly concurrency?: number;
631
- /**
632
- * Free-form description of where the test cases come from — surfaced in the node properties
633
- * panel and the suite-detail header so authors revisiting the workflow six months later
634
- * remember which mailbox / folder / fixture file the cases originate from.
635
- *
636
- * Example: `"All emails in the Gmail label \"test/triage-fixtures\" — 14 messages as of 2026-05-03."`
637
- */
638
- readonly description?: string;
639
- /**
640
- * Resolves a human-readable label for one yielded test case (e.g. email subject). The
641
- * orchestrator calls this once per yielded item, persists the result on the run, and the
642
- * Tests-tab UI uses it to render the case row instead of the opaque runId. Return
643
- * `undefined` to fall back to "Case #N".
644
- */
645
- caseLabel?(item: Item<TOutputJson$1>): string | undefined;
646
- }
647
- //#endregion
648
- //#region ../core/src/contracts/CostTrackingTelemetryContract.d.ts
649
- type CostTrackingComponent = "chat" | "ocr" | "rag";
650
- interface CostTrackingUsageRecord {
651
- readonly component: CostTrackingComponent;
652
- readonly provider: string;
653
- readonly operation: string;
654
- readonly pricingKey: string;
655
- readonly usageUnit: string;
656
- readonly quantity: number;
657
- readonly modelName?: string;
658
- readonly attributes?: TelemetryAttributes;
659
- }
660
- interface CostTrackingPriceQuote {
661
- readonly currency: string;
662
- readonly currencyScale: number;
663
- readonly estimatedAmountMinor: number;
664
- readonly estimateKind: "catalog";
665
- }
666
- interface CostTrackingTelemetry {
667
- captureUsage(args: CostTrackingUsageRecord): Promise<CostTrackingPriceQuote | undefined>;
668
- forScope(scope: TelemetryScope): CostTrackingTelemetry;
669
- }
670
- //#endregion
671
- //#region ../core/src/contracts/telemetryTypes.d.ts
672
- type TelemetryAttributePrimitive = string | number | boolean | null;
673
- interface TelemetryAttributes {
674
- readonly [key: string]: TelemetryAttributePrimitive | undefined;
675
- }
676
- interface TelemetryMetricRecord {
677
- readonly name: string;
678
- readonly value: number;
679
- readonly unit?: string;
680
- readonly attributes?: TelemetryAttributes;
681
- }
682
- interface TelemetrySpanEventRecord {
683
- readonly name: string;
684
- readonly occurredAt?: Date;
685
- readonly attributes?: TelemetryAttributes;
686
- }
687
- interface TelemetryArtifactAttachment {
688
- readonly kind: string;
689
- readonly contentType: string;
690
- readonly previewText?: string;
691
- readonly previewJson?: JsonValue;
692
- readonly payloadText?: string;
693
- readonly payloadJson?: JsonValue;
694
- readonly bytes?: number;
695
- readonly truncated?: boolean;
696
- readonly expiresAt?: Date;
697
- }
698
- interface TelemetryArtifactReference {
699
- readonly artifactId: string;
700
- readonly traceId?: string;
701
- readonly spanId?: string;
702
- }
703
- interface TelemetrySpanEnd {
704
- readonly status?: "ok" | "error";
705
- readonly statusMessage?: string;
706
- readonly endedAt?: Date;
707
- readonly attributes?: TelemetryAttributes;
708
- }
709
- interface TelemetryChildSpanStart {
710
- readonly name: string;
711
- readonly kind?: "internal" | "client";
712
- readonly startedAt?: Date;
713
- readonly attributes?: TelemetryAttributes;
714
- }
715
- interface TelemetryScope {
716
- readonly traceId?: string;
717
- readonly spanId?: string;
718
- readonly costTracking?: CostTrackingTelemetry;
719
- addSpanEvent(args: TelemetrySpanEventRecord): Promise<void> | void;
720
- recordMetric(args: TelemetryMetricRecord): Promise<void> | void;
721
- attachArtifact(args: TelemetryArtifactAttachment): Promise<TelemetryArtifactReference> | TelemetryArtifactReference;
722
- }
723
- interface TelemetrySpanScope extends TelemetryScope {
724
- readonly traceId: string;
725
- readonly spanId: string;
726
- end(args?: TelemetrySpanEnd): Promise<void> | void;
727
- /**
728
- * Lift this span into a {@link NodeExecutionTelemetry} scoped to a different (nodeId, activationId).
729
- * Children created via the returned telemetry's `startChildSpan` get this span as their parent.
730
- *
731
- * Used at the sub-agent boundary so that nested runtime telemetry parents under the agent.tool.call
732
- * span instead of the orchestrator's node-level span.
733
- */
734
- asNodeTelemetry(args: Readonly<{
735
- nodeId: NodeId;
736
- activationId: NodeActivationId;
737
- }>): NodeExecutionTelemetry;
738
- }
739
- interface NodeExecutionTelemetry extends ExecutionTelemetry, TelemetrySpanScope {
740
- startChildSpan(args: TelemetryChildSpanStart): TelemetrySpanScope;
741
- }
742
- interface ExecutionTelemetry extends TelemetryScope {
743
- readonly traceId: string;
744
- readonly spanId: string;
745
- forNode(args: Readonly<{
746
- nodeId: NodeId;
747
- activationId: NodeActivationId;
748
- }>): NodeExecutionTelemetry;
749
- }
750
- //#endregion
751
- //#region ../core/src/contracts/agentMcpTypes.d.ts
752
- /**
753
- * An opaque MCP tool map: keyed by serverId → (toolName → tool definition).
754
- * Typed as unknown so core does not depend on the AI SDK's ToolSet type.
755
- * AIAgentNode (in core-nodes, which does depend on ai) casts this to
756
- * ReadonlyMap<string, ToolSet> before passing to DeferredMetaToolStrategyFactory.
757
- */
758
- type AgentMcpToolMap = ReadonlyMap<string, Readonly<Record<string, unknown>>>;
759
- /**
760
- * Contract implemented by the host. Resolves MCP server bindings for an agent run
761
- * via the standard credential-binding table (one slot per declared server, keyed
762
- * by `(workflowId, mcpConnectionNodeId, "credential")`), and returns a ready-to-use
763
- * tool map with wrapped execute callbacks for telemetry and 403 detection.
764
- * Core-nodes imports this interface so AIAgentNode can inject it without
765
- * depending on the host.
766
- */
767
- interface AgentMcpIntegration {
768
- /**
769
- * Look up the credential binding per server, validate scopes, open pool
770
- * connections, and return a tool map keyed by serverId. Each tool's
771
- * execute callback includes:
772
- * - Telemetry child span (mcp.server_id, mcp.tool_name attributes)
773
- * - 403/permission error detection → emits a NeedsReconsentEvent span event
774
- *
775
- * Throws `AgentBindError` on validation failures (missing server, unbound
776
- * credential slot, missing credential instance, insufficient scopes).
777
- */
778
- prepareMcpTools(args: {
779
- readonly workflowId: WorkflowId;
780
- readonly agentNodeId: NodeId;
781
- readonly serverIds: ReadonlyArray<string>;
782
- readonly pinnedMcpTools: readonly string[];
783
- readonly emitSpanEvent: (event: TelemetrySpanEventRecord) => void;
784
- readonly startChildSpan: (args: {
785
- readonly name: string;
786
- readonly attributes?: Record<string, string>;
787
- }) => {
788
- readonly end: (args?: {
789
- status?: "ok" | "error";
790
- statusMessage?: string;
791
- }) => void;
792
- };
793
- /** Per-MCP-tool-call invocation appender. Optional; when omitted the wrapper emits only telemetry spans. */
794
- readonly appendMcpInvocation?: (args: ConnectionInvocationAppendArgs) => Promise<void>;
795
- /** Agent activation id to attach to each invocation record (used by canvas + inspector grouping). */
796
- readonly parentAgentActivationId?: NodeActivationId;
797
- /** Per-item iteration id when the agent runs inside a per-item loop. */
798
- readonly iterationId?: NodeIterationId;
799
- /** Item index (0-based) of the iteration that owns these tool calls. */
800
- readonly itemIndex?: number;
801
- /** Parent invocation id when this agent is itself executing as a sub-agent. */
802
- readonly parentInvocationId?: ConnectionInvocationId;
803
- }): Promise<AgentMcpToolMap>;
804
- }
805
- //#endregion
806
- //#region ../core/src/contracts/assertionTypes.d.ts
807
- /**
808
- * One assertion emitted by an assertion-emitting node (a node whose config sets
809
- * `emitsAssertions: true`). Each emitted item on `main` carries one of these as `item.json`.
810
- *
811
- * Pass/fail is derived from `score >= (passThreshold ?? 0.5)` — see {@link deriveAssertionPassed}.
812
- * The `errored` marker is for cases where the assertion code itself threw (distinct from
813
- * "the assertion was evaluated and the score was low") and is treated as a hard fail in rollups
814
- * regardless of `score`.
815
- */
816
- interface AssertionResult {
817
- readonly name: string;
818
- /** 0..1 score. Source of truth for pass/fail (compared against `passThreshold`). */
819
- readonly score: number;
820
- /** 0..1 threshold for "passed". When omitted, consumers default to 0.5. */
821
- readonly passThreshold?: number;
822
- /** True when evaluating the assertion threw — treated as fail regardless of `score`. */
823
- readonly errored?: true;
824
- /** What the assertion expected. Free-form JSON; UIs render with a JSON viewer. */
825
- readonly expected?: JsonValue;
826
- /** What the workflow actually produced. */
827
- readonly actual?: JsonValue;
828
- /** Short human-readable explanation, especially for fails / errors. */
829
- readonly message?: string;
830
- /** Bag of supplemental fields (e.g. judge prompt, judge raw response, comparison method). */
831
- readonly details?: Readonly<Record<string, JsonValue>>;
832
- }
833
- //#endregion
834
- //#region ../core/src/contracts/webhookTypes.d.ts
835
- type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
836
- interface WebhookControlSignal {
837
- readonly __webhookControl: true;
838
- readonly kind: "respondNow" | "respondNowAndContinue";
839
- readonly responseItems: Items;
840
- readonly continueItems?: Items;
841
- }
842
- interface TriggerInstanceId {
843
- workflowId: WorkflowId;
844
- nodeId: NodeId;
845
- }
846
- //#endregion
847
- //#region ../core/src/contracts/mcpTypes.d.ts
848
- type McpServerTransport = "http";
849
- interface McpServerDeclaration {
850
- /** Globally unique slug, e.g. "gmail". Workflow authors reference this. */
851
- id: string;
852
- displayName: string;
853
- description: string;
854
- transport: McpServerTransport;
855
- url: string;
856
- /**
857
- * Credential types accepted by this MCP server, matching CredentialRequirement.acceptedTypes.
858
- * Absent or empty means no credential is required.
859
- */
860
- acceptedCredentialTypes?: ReadonlyArray<string>;
861
- /**
862
- * Documentation only in MVP. The bind-time validator checks
863
- * requiredScopes ⊆ CredentialInstance.scopesGranted.
864
- */
865
- requiredScopes?: string[];
866
- /** Non-secret static headers merged onto every MCP request. */
867
- staticHeaders?: Record<string, string>;
868
- /**
869
- * Overrides for tool descriptions advertised by the MCP server.
870
- * Applied by the connection pool after tools/list.
871
- * Key: exact tool name as returned by the server.
872
- */
873
- toolDescriptionOverrides?: Record<string, string>;
874
- }
875
- //#endregion
876
- //#region ../core/src/contracts/collectionTypes.d.ts
877
- /**
878
- * Represents a typed store for a single collection.
879
- * All rows include auto-managed id, created_at, and updated_at fields.
880
- */
881
- interface CollectionStore<TRow extends Record<string, unknown> = Record<string, unknown>> {
882
- /**
883
- * Insert a new row. id, created_at, and updated_at are auto-populated.
884
- */
885
- insert(row: TRow): Promise<TRow & {
886
- id: string;
887
- created_at: Date;
888
- updated_at: Date;
889
- }>;
890
- /**
891
- * Get a single row by id.
892
- */
893
- get(id: string): Promise<(TRow & {
894
- id: string;
895
- created_at: Date;
896
- updated_at: Date;
897
- }) | null>;
898
- /**
899
- * Find a single row matching the provided filter.
900
- */
901
- findOne(filter: Partial<TRow>): Promise<(TRow & {
902
- id: string;
903
- created_at: Date;
904
- updated_at: Date;
905
- }) | null>;
906
- /**
907
- * List rows with optional pagination and filtering.
908
- */
909
- list(opts?: {
910
- limit?: number;
911
- offset?: number;
912
- where?: Partial<TRow>;
913
- }): Promise<{
914
- rows: ReadonlyArray<TRow & {
915
- id: string;
916
- created_at: Date;
917
- updated_at: Date;
918
- }>;
919
- total: number;
920
- }>;
921
- /**
922
- * Update a row by id with partial data.
923
- */
924
- update(id: string, patch: Partial<TRow>): Promise<TRow & {
925
- id: string;
926
- created_at: Date;
927
- updated_at: Date;
928
- }>;
1043
+ size: number;
1044
+ storageDriver: string;
1045
+ previewKind: BinaryPreviewKind;
1046
+ createdAt: string;
1047
+ runId: RunId;
1048
+ workflowId: WorkflowId;
1049
+ nodeId: NodeId;
1050
+ activationId: NodeActivationId;
1051
+ filename?: string;
1052
+ sha256?: string;
1053
+ }>;
1054
+ type ItemBinary = Readonly<Record<string, BinaryAttachment>>;
1055
+ type Item<TJson = unknown> = Readonly<{
1056
+ json: TJson;
1057
+ binary?: ItemBinary;
1058
+ meta?: Readonly<Record<string, unknown>>;
1059
+ paired?: ReadonlyArray<PairedItemRef>;
1060
+ }>;
1061
+ type Items<TJson = unknown> = ReadonlyArray<Item<TJson>>;
1062
+ type NodeOutputs = Partial<Record<OutputPortKey, Items>>;
1063
+ type RunId = string;
1064
+ type NodeActivationId = string;
1065
+ /**
1066
+ * One per-item iteration of a runnable node's execute loop. Refines `NodeActivationId` for
1067
+ * per-item connection invocations and telemetry. Undefined when the executing node is a batch
1068
+ * node or trigger that does not iterate items.
1069
+ */
1070
+ type NodeIterationId = string;
1071
+ interface ParentExecutionRef {
1072
+ runId: RunId;
1073
+ workflowId: WorkflowId;
1074
+ nodeId: NodeId;
1075
+ /** Subworkflow depth of the **spawning** run (0 = root). Passed when starting a child run. */
1076
+ subworkflowDepth?: number;
1077
+ /** Effective max node activations from the parent run (propagated to child policy merge). */
1078
+ engineMaxNodeActivations?: number;
1079
+ /** Effective max subworkflow depth from the parent run (propagated to child policy merge). */
1080
+ engineMaxSubworkflowDepth?: number;
929
1081
  /**
930
- * Delete a row by id. Hard delete only (no soft delete).
1082
+ * Test-suite linkage inherited by the child subworkflow run. Set by whichever node
1083
+ * spawns the subworkflow when its own `ctx.testContext` is present, so assertions
1084
+ * emitted inside a subworkflow land under the correct parent test case.
931
1085
  */
932
- delete(id: string): Promise<{
933
- deleted: boolean;
934
- }>;
1086
+ testContext?: RunTestContext;
935
1087
  }
936
- /**
937
- * Runtime collections context: keyed by collection name.
938
- */
939
- type CollectionsContext = Readonly<Record<string, CollectionStore>>;
940
- //#endregion
941
- //#region ../core/src/contracts/emitPorts.d.ts
942
- declare const EMIT_PORTS_BRAND: unique symbol;
943
- type PortsEmission = Readonly<{
944
- readonly [EMIT_PORTS_BRAND]: true;
945
- readonly ports: Readonly<Partial<Record<OutputPortKey, Items | ReadonlyArray<JsonNonArray>>>>;
946
- }>;
947
- //#endregion
948
- //#region ../core/src/workflow/dsl/workflowBuilderTypes.d.ts
949
- type AnyRunnableNodeConfig = RunnableNodeConfig<any, any>;
950
- type AnyTriggerNodeConfig = TriggerNodeConfig<any>;
951
- type ValidStepSequence<TCurrentJson, TSteps extends ReadonlyArray<AnyRunnableNodeConfig>> = TSteps extends readonly [] ? readonly [] : TSteps extends readonly [infer TFirst, ...infer TRest] ? TFirst extends RunnableNodeConfig<TCurrentJson, infer TNextJson> ? TRest extends ReadonlyArray<AnyRunnableNodeConfig> ? readonly [TFirst, ...ValidStepSequence<TNextJson, TRest>] : never : never : TSteps;
952
- type StepSequenceOutput<TCurrentJson, TSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined> = TSteps extends ReadonlyArray<AnyRunnableNodeConfig> ? TSteps extends readonly [] ? TCurrentJson : TSteps extends readonly [infer TFirst, ...infer TRest] ? TFirst extends RunnableNodeConfig<TCurrentJson, infer TNextJson> ? TRest extends ReadonlyArray<AnyRunnableNodeConfig> ? StepSequenceOutput<TNextJson, TRest> : never : never : TCurrentJson : TCurrentJson;
953
- type TypesMatch<TLeft, TRight> = [TLeft] extends [TRight] ? ([TRight] extends [TLeft] ? true : false) : false;
954
- type BranchOutputGuard<TCurrentJson, TTrueSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined, TFalseSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined> = TypesMatch<StepSequenceOutput<TCurrentJson, TTrueSteps>, StepSequenceOutput<TCurrentJson, TFalseSteps>> extends true ? unknown : never;
955
- type BranchStepsArg<TCurrentJson, TSteps extends ReadonlyArray<AnyRunnableNodeConfig>> = TSteps & ValidStepSequence<TCurrentJson, TSteps>;
956
- type BranchMoreArgs<TCurrentJson, TFirstStep extends RunnableNodeConfig<TCurrentJson, any>, TRestSteps extends ReadonlyArray<AnyRunnableNodeConfig>> = TRestSteps & ValidStepSequence<RunnableNodeOutputJson<TFirstStep>, TRestSteps>;
957
- type BooleanWhenOverloads<TCurrentJson, TReturn> = {
958
- <TSteps extends ReadonlyArray<AnyRunnableNodeConfig>>(branch: boolean, steps: BranchStepsArg<TCurrentJson, TSteps>): TReturn;
959
- <TFirstStep extends RunnableNodeConfig<TCurrentJson, any>, TRestSteps extends ReadonlyArray<AnyRunnableNodeConfig>>(branch: boolean, step: TFirstStep, ...more: BranchMoreArgs<TCurrentJson, TFirstStep, TRestSteps>): TReturn;
960
- };
961
- //#endregion
962
- //#region ../core/src/workflow/dsl/WhenBuilder.d.ts
963
- declare class WhenBuilder<TCurrentJson> {
964
- private readonly wf;
965
- private readonly from;
966
- private readonly branchPort;
967
- constructor(wf: WorkflowBuilder, from: NodeRef, branchPort: OutputPortKey);
968
- addBranch<TSteps extends ReadonlyArray<AnyRunnableNodeConfig>>(steps: TSteps & ValidStepSequence<TCurrentJson, TSteps>): this;
969
- readonly when: BooleanWhenOverloads<TCurrentJson, WhenBuilder<TCurrentJson>>;
970
- build(): WorkflowDefinition;
1088
+ interface RunDataSnapshot {
1089
+ getOutputs(nodeId: NodeId): NodeOutputs | undefined;
1090
+ getOutputItems<TJson = unknown>(nodeId: NodeId | NodeIdRef<TJson>, output?: OutputPortKey): Items<TJson>;
1091
+ getOutputItem<TJson = unknown>(nodeId: NodeId | NodeIdRef<TJson>, itemIndex: number, output?: OutputPortKey): Item<TJson> | undefined;
971
1092
  }
972
- //#endregion
973
- //#region ../core/src/workflow/dsl/ChainCursorResolver.d.ts
974
- type ChainCursorEndpoint = Readonly<{
975
- node: NodeRef;
976
- output: OutputPortKey;
977
- inputPortHint?: InputPortKey;
978
- }>;
979
- type ChainCursorWhenOverloads<TCurrentJson> = BooleanWhenOverloads<TCurrentJson, WhenBuilder<TCurrentJson>> & {
980
- <TTrueSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined, TFalseSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined>(branches: Readonly<{
981
- true?: TTrueSteps extends ReadonlyArray<AnyRunnableNodeConfig> ? BranchStepsArg<TCurrentJson, TTrueSteps> : never;
982
- false?: TFalseSteps extends ReadonlyArray<AnyRunnableNodeConfig> ? BranchStepsArg<TCurrentJson, TFalseSteps> : never;
983
- }> & BranchOutputGuard<TCurrentJson, TTrueSteps, TFalseSteps>): ChainCursor<StepSequenceOutput<TCurrentJson, TTrueSteps>>;
984
- };
985
- declare class ChainCursor<TCurrentJson> {
986
- private readonly wf;
987
- private readonly endpoints;
988
- constructor(wf: WorkflowBuilder, endpoints: ReadonlyArray<ChainCursorEndpoint>);
989
- then<TOutputJson$1, TConfig extends RunnableNodeConfig<TCurrentJson, TOutputJson$1>>(config: TConfig): ChainCursor<RunnableNodeOutputJson<TConfig>>;
990
- thenIntoInputHints<TOutputJson$1, TConfig extends RunnableNodeConfig<any, TOutputJson$1>>(config: TConfig): ChainCursor<RunnableNodeOutputJson<TConfig>>;
991
- readonly when: ChainCursorWhenOverloads<TCurrentJson>;
992
- route<TNextJson$1>(branches: Readonly<Record<OutputPortKey, (branch: ChainCursor<TCurrentJson>) => ChainCursor<TNextJson$1> | undefined>>): ChainCursor<TNextJson$1>;
993
- build(): WorkflowDefinition;
994
- private resolveSharedInputPortHint;
1093
+ interface ActivationIdFactory {
1094
+ makeActivationId(): NodeActivationId;
1095
+ }
1096
+ type UpstreamRefPlaceholder = `$${number}`;
1097
+ /** Whether to persist run execution data after the workflow finishes. */
1098
+ type WorkflowStoragePolicyMode = "ALL" | "SUCCESS" | "ERROR" | "NEVER";
1099
+ type WorkflowStoragePolicySpec = WorkflowStoragePolicyMode | TypeToken<WorkflowStoragePolicyResolver>;
1100
+ interface WorkflowStoragePolicyResolver {
1101
+ shouldPersist(args: WorkflowStoragePolicyDecisionArgs): boolean | Promise<boolean>;
1102
+ }
1103
+ interface WorkflowStoragePolicyDecisionArgs {
1104
+ readonly runId: RunId;
1105
+ readonly workflowId: WorkflowId;
1106
+ readonly workflow: WorkflowDefinition;
1107
+ readonly finalStatus: "completed" | "failed";
1108
+ readonly startedAt: string;
1109
+ readonly finishedAt: string;
1110
+ }
1111
+ interface WorkflowPrunePolicySpec {
1112
+ readonly runDataRetentionSeconds?: number;
1113
+ readonly binaryRetentionSeconds?: number;
1114
+ readonly telemetrySpanRetentionSeconds?: number;
1115
+ readonly telemetryArtifactRetentionSeconds?: number;
1116
+ readonly telemetryMetricRetentionSeconds?: number;
1117
+ }
1118
+ interface WorkflowErrorHandler {
1119
+ onError(ctx: WorkflowErrorContext): void | Promise<void>;
1120
+ }
1121
+ interface WorkflowErrorContext {
1122
+ readonly runId: RunId;
1123
+ readonly workflowId: WorkflowId;
1124
+ readonly workflow: WorkflowDefinition;
1125
+ readonly failedNodeId: NodeId;
1126
+ readonly error: Error;
1127
+ readonly startedAt: string;
1128
+ readonly finishedAt: string;
995
1129
  }
1130
+ type WorkflowErrorHandlerSpec = TypeToken<WorkflowErrorHandler> | WorkflowErrorHandler;
1131
+ interface NodeErrorHandlerArgs<TConfig extends NodeConfigBase = NodeConfigBase> {
1132
+ readonly kind: "single" | "multi";
1133
+ readonly items: Items;
1134
+ readonly inputsByPort: Readonly<Record<InputPortKey, Items>> | undefined;
1135
+ readonly ctx: NodeExecutionContext<TConfig>;
1136
+ readonly error: Error;
1137
+ }
1138
+ interface NodeErrorHandler {
1139
+ handle<TConfig extends NodeConfigBase>(args: NodeErrorHandlerArgs<TConfig>): Promise<NodeOutputs>;
1140
+ }
1141
+ type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandler;
996
1142
  //#endregion
997
- //#region ../core/src/workflow/dsl/WorkflowBuilder.d.ts
998
- declare class WorkflowBuilder {
999
- private readonly meta;
1000
- private readonly options?;
1001
- private readonly nodes;
1002
- private readonly edges;
1003
- constructor(meta: {
1004
- id: WorkflowId;
1005
- name: string;
1006
- }, options?: Readonly<Record<string, never>> | undefined);
1007
- private add;
1008
- private connect;
1009
- trigger<TConfig extends AnyTriggerNodeConfig>(config: TConfig): ChainCursor<TriggerNodeOutputJson<TConfig>>;
1010
- start<TConfig extends AnyRunnableNodeConfig>(config: TConfig): ChainCursor<RunnableNodeOutputJson<TConfig>>;
1011
- build(): WorkflowDefinition;
1012
- private validateNodeIds;
1143
+ //#region ../core/src/triggers/polling/PollingTriggerDedupWindow.d.ts
1144
+ /**
1145
+ * Merges processed-ID windows for polling triggers, capping the total to avoid unbounded growth.
1146
+ * Plugin code receives an instance of this class via {@link PollingTriggerHandle.dedup}.
1147
+ */
1148
+ declare class PollingTriggerDedupWindow {
1149
+ static readonly defaultCapN = 2000;
1150
+ merge(previous: ReadonlyArray<string>, incoming: ReadonlyArray<string>, capN?: number): ReadonlyArray<string>;
1013
1151
  }
1014
1152
  //#endregion
1015
1153
  //#region ../core/src/contracts/runtimeTypes.d.ts
1154
+ /** Opaque unique identifier for a single HumanTask instance. */
1155
+ type HumanTaskId = string;
1156
+ /**
1157
+ * Minimal handle handed to the `deliver` callback so it can route to the correct
1158
+ * inbox channel.
1159
+ */
1160
+ interface HumanTaskHandle {
1161
+ readonly taskId: HumanTaskId;
1162
+ readonly runId: string;
1163
+ readonly nodeId: string;
1164
+ readonly expiresAt: Date;
1165
+ /** TODO: real signed URL; placeholder empty string for now. */
1166
+ readonly resumeUrl: string;
1167
+ /**
1168
+ * Arbitrary JSON metadata copied from `SuspensionRequest.request.metadata` at suspension time.
1169
+ * Used by the agent runtime to round-trip the `agentCheckpoint` back to the
1170
+ * resumed node via `ctx.resumeContext.task.metadata`.
1171
+ */
1172
+ readonly metadata?: Readonly<Record<string, JsonValue>>;
1173
+ }
1174
+ /** Identity of the person who made a decision on the task. */
1175
+ interface HumanTaskActor {
1176
+ readonly actorId: string;
1177
+ readonly displayName?: string;
1178
+ }
1179
+ /**
1180
+ * Resume context injected into `NodeExecutionContext` when the engine re-activates
1181
+ * a previously suspended node. `defineHumanApprovalNode` wraps this with parsed
1182
+ * `TDecision`; at the engine layer `decision.value` is `unknown`.
1183
+ */
1184
+ interface ResumeContext {
1185
+ readonly decision: Readonly<{
1186
+ kind: "decided";
1187
+ value: unknown;
1188
+ actor: HumanTaskActor;
1189
+ decidedAt: Date;
1190
+ }> | Readonly<{
1191
+ kind: "timed_out";
1192
+ at: Date;
1193
+ }> | Readonly<{
1194
+ kind: "auto_accepted";
1195
+ at: Date;
1196
+ }>;
1197
+ readonly delivery: JsonValue;
1198
+ readonly task: HumanTaskHandle;
1199
+ }
1016
1200
  interface WorkflowRunnerService {
1017
1201
  runById(args: {
1018
1202
  workflowId: WorkflowId;
@@ -1112,6 +1296,14 @@ interface ExecutionContext {
1112
1296
  * Collections registered in the codemation config, keyed by collection name.
1113
1297
  */
1114
1298
  readonly collections?: CollectionsContext;
1299
+ /**
1300
+ * Resolve a DI token from the host container.
1301
+ * Allows nodes to reach host-side services (e.g. `InboxChannelResolverToken`)
1302
+ * without importing host code. Wired by `DefaultExecutionContextFactory`; throws
1303
+ * a clear error when no resolver is configured (e.g. in unit tests that don't
1304
+ * set up the full container).
1305
+ */
1306
+ resolve<T>(token: TypeToken<T>): T;
1115
1307
  }
1116
1308
  interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase> extends ExecutionContext {
1117
1309
  nodeId: NodeId;
@@ -1119,6 +1311,11 @@ interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase>
1119
1311
  config: TConfig;
1120
1312
  telemetry: NodeExecutionTelemetry;
1121
1313
  binary: NodeBinaryAttachmentService;
1314
+ /**
1315
+ * Present when this node activation is a HITL resume.
1316
+ * The node checks `ctx.resumeContext !== undefined` and takes the resume branch.
1317
+ */
1318
+ resumeContext?: ResumeContext;
1122
1319
  }
1123
1320
  interface PollingTriggerHandle {
1124
1321
  /**
@@ -1207,57 +1404,6 @@ interface TestableTriggerNode<TConfig extends TriggerNodeConfig<any, any> = Trig
1207
1404
  }
1208
1405
  type ExecutableTriggerNode<TConfig extends TriggerNodeConfig<any, any> = TriggerNodeConfig<any, any>> = TriggerNode<TConfig>;
1209
1406
  //#endregion
1210
- //#region ../core/src/contracts/itemExpr.d.ts
1211
- declare const ITEM_EXPR_BRAND: unique symbol;
1212
- type ItemExprResolvedContext = Readonly<{
1213
- runId: RunId;
1214
- workflowId: WorkflowId;
1215
- nodeId: NodeId;
1216
- activationId: NodeActivationId;
1217
- data: RunDataSnapshot;
1218
- }>;
1219
- /**
1220
- * Context aligned with former {@link ItemInputMapperContext} — use **`data`** to read any completed upstream node.
1221
- */
1222
- type ItemExprContext = ItemExprResolvedContext;
1223
- type ItemExprArgs<TItemJson = unknown> = Readonly<{
1224
- item: Item<TItemJson>;
1225
- itemIndex: number;
1226
- items: Items<TItemJson>;
1227
- ctx: ItemExprContext;
1228
- }>;
1229
- type ItemExprCallback<T, TItemJson = unknown> = (args: ItemExprArgs<TItemJson>) => T | Promise<T>;
1230
- type ItemExpr<T, TItemJson = unknown> = Readonly<{
1231
- readonly [ITEM_EXPR_BRAND]: true;
1232
- readonly fn: ItemExprCallback<T, TItemJson>;
1233
- }>;
1234
- //#endregion
1235
- //#region ../core/src/contracts/params.d.ts
1236
- type Expr<T, TItemJson = unknown> = ItemExpr<T, TItemJson>;
1237
- type ParamDeep<T, TItemJson = unknown> = Expr<T, TItemJson> | (T extends readonly (infer U)[] ? ReadonlyArray<ParamDeep<U, TItemJson>> : never) | (T extends object ? { [K in keyof T]: ParamDeep<T[K], TItemJson> } : T);
1238
- //#endregion
1239
- //#region ../core/src/authoring/defineNode.types.d.ts
1240
- type ResolvableCredentialType = AnyCredentialType | CredentialTypeId;
1241
- type DefinedNodeCredentialBinding = ResolvableCredentialType | Readonly<{
1242
- readonly type: ResolvableCredentialType | ReadonlyArray<ResolvableCredentialType>;
1243
- readonly label?: string;
1244
- readonly optional?: true;
1245
- readonly helpText?: string;
1246
- readonly helpUrl?: string;
1247
- }>;
1248
- type DefinedNodeCredentialBindings = Readonly<Record<string, DefinedNodeCredentialBinding>>;
1249
- type DefinedNodeConfigInput<TConfigResolved extends CredentialJsonRecord, TItemJson> = ParamDeep<TConfigResolved, TItemJson>;
1250
- interface DefinedNode<TKey$1 extends string, TConfig extends CredentialJsonRecord, TInputJson$1, TOutputJson$1, _TBindings extends DefinedNodeCredentialBindings | undefined = undefined> {
1251
- readonly kind: "defined-node";
1252
- readonly key: TKey$1;
1253
- readonly title: string;
1254
- readonly description?: string;
1255
- create<TConfigItemJson = TInputJson$1>(config: DefinedNodeConfigInput<TConfig, TConfigItemJson>, name?: string, id?: string): RunnableNodeConfig<TInputJson$1, TOutputJson$1>;
1256
- register(context: {
1257
- registerNode<TValue>(token: TypeToken<TValue>, implementation?: TypeToken<TValue>): void;
1258
- }): void;
1259
- }
1260
- //#endregion
1261
1407
  //#region ../core/src/ai/NodeBackedToolConfig.d.ts
1262
1408
  declare class NodeBackedToolConfig<TNodeConfig extends RunnableNodeConfig<any, any>, TInputSchema extends ZodSchemaAny, TOutputSchema extends ZodSchemaAny> implements ToolConfig {
1263
1409
  readonly name: string;
@@ -2134,11 +2280,18 @@ type ResolvedTool = Readonly<{
2134
2280
  * span and the planned tool-call's `invocationId`. Node-backed sub-agent tools use these hooks
2135
2281
  * via {@link ChildExecutionScopeFactory} to re-root their runtime ctx under the tool-call boundary
2136
2282
  * (fresh activationId, telemetry parented at the tool-call span, `parentInvocationId` set).
2283
+ *
2284
+ * `humanApproval` is present only when the tool was created via `defineHumanApprovalNode`
2285
+ * (via its marker) — detected during `resolveTools` in `AIAgentNode`.
2137
2286
  */
2138
2287
  type ItemScopedToolBinding = Readonly<{
2139
2288
  config: ToolConfig;
2140
2289
  inputSchema: ZodSchemaAny;
2141
2290
  execute(input: unknown, hooks?: ItemScopedToolCallHooks): Promise<unknown>;
2291
+ /** Present when this binding is backed by a HITL-approval node (story 10). */
2292
+ humanApproval?: Readonly<{
2293
+ onRejected: "halt" | "return";
2294
+ }>;
2142
2295
  }>;
2143
2296
  type ItemScopedToolCallHooks = Readonly<{
2144
2297
  /** Live agent.tool.call span (used to parent sub-agent telemetry). */
@@ -2374,6 +2527,14 @@ declare class AgentToolExecutionCoordinator {
2374
2527
  ctx: NodeExecutionContext<AIAgent<any, any>>;
2375
2528
  agentName: string;
2376
2529
  repairAttemptsByToolName: Map<string, number>;
2530
+ /** Conversation including the assistant message that emitted these tool_use blocks. Stored in checkpoint on HITL suspension. */
2531
+ conversationSnapshot?: ReadonlyArray<ModelMessage>;
2532
+ /** Turn count at the moment of this coordinator invocation. */
2533
+ turnCount?: number;
2534
+ /** Cumulative tool-call count up to and including this batch. */
2535
+ toolCallCount?: number;
2536
+ /** Model id for checkpoint migration safety. */
2537
+ modelId?: string;
2377
2538
  }>): Promise<ReadonlyArray<ExecutedToolCall>>;
2378
2539
  private executePlannedToolCall;
2379
2540
  private recordFailedInvocation;
@@ -2382,6 +2543,11 @@ declare class AgentToolExecutionCoordinator {
2382
2543
  private createValidationMessage;
2383
2544
  private toJsonValue;
2384
2545
  private extractErrorDetails;
2546
+ /**
2547
+ * Extracts the text content from the last assistant message in the conversation snapshot.
2548
+ * Used to populate `agentReasoning` in the HITL suspension metadata.
2549
+ */
2550
+ private extractLastAssistantText;
2385
2551
  private serializeIssue;
2386
2552
  }
2387
2553
  //#endregion
@@ -2479,6 +2645,17 @@ declare class AIAgentNode implements RunnableNode<AIAgent<any, any>> {
2479
2645
  private readonly preparedByExecutionContext;
2480
2646
  constructor(nodeResolver: NodeResolver, credentialSessions: CredentialSessionService, nodeBackedToolRuntime: NodeBackedToolRuntime, executionHelpers: AIAgentExecutionHelpersFactory, structuredOutputRunner: AgentStructuredOutputRunner, toolExecutionCoordinator: AgentToolExecutionCoordinator, toolLoadingStrategyFactory: DeferredMetaToolStrategyFactory, agentMcpIntegration: AgentMcpIntegration);
2481
2647
  execute(args: RunnableNodeExecuteArgs<AIAgent<any, any>>): Promise<unknown>;
2648
+ /**
2649
+ * Resume path: re-enters the agent loop after a HITL suspension.
2650
+ * Reconstructs the conversation from the checkpoint, injects the human decision
2651
+ * as a tool_result, and continues the loop from where it suspended.
2652
+ */
2653
+ private executeResumed;
2654
+ /**
2655
+ * Normalizes a {@link ResumeContext} decision into a flat JSON-serializable shape
2656
+ * suitable for injection as a tool_result content.
2657
+ */
2658
+ private normalizeDecision;
2482
2659
  private getOrPrepareExecution;
2483
2660
  private prepareExecution;
2484
2661
  private prepareMcpToolsByServer;
@@ -2501,6 +2678,11 @@ declare class AIAgentNode implements RunnableNode<AIAgent<any, any>> {
2501
2678
  private buildOutputItem;
2502
2679
  private resolveTools;
2503
2680
  private createItemScopedTools;
2681
+ /**
2682
+ * Detects whether a tool config is backed by a `defineHumanApprovalNode` marker
2683
+ * and returns the HITL behavior config, or `undefined` when not a HITL tool.
2684
+ */
2685
+ private resolveHumanApprovalBehavior;
2504
2686
  /**
2505
2687
  * Invoke a text turn using the merged tool set from item-scoped tools (coordinator-managed)
2506
2688
  * and strategy tools (find_tools + discovered MCP tools).
@@ -2515,6 +2697,8 @@ declare class AIAgentNode implements RunnableNode<AIAgent<any, any>> {
2515
2697
  /**
2516
2698
  * Builds a ToolSet from resolved tools for strategy initialization.
2517
2699
  * The strategy uses this for its "always-included" node-backed tool descriptions.
2700
+ * HITL tools (detected via the `humanApprovalToolBehavior` field set by `defineHumanApprovalNode`) get the solo-constraint sentence
2701
+ * appended to their description.
2518
2702
  */
2519
2703
  private buildToolSetFromResolved;
2520
2704
  /**
@@ -3664,5 +3848,33 @@ declare const collectionDeleteNode: DefinedNode<"collection-delete", {
3664
3848
  id: string;
3665
3849
  }, undefined>;
3666
3850
  //#endregion
3667
- export { AIAgent, AIAgentConnectionWorkflowExpander, AIAgentExecutionHelpersFactory, AIAgentNode, AgentItemPortMap, AgentMessageFactory, AgentOutputFactory, AgentStructuredOutputRepairPromptFactory, AgentStructuredOutputRunner, AgentToolCallPortMap, AgentToolErrorClassifier, AgentToolExecutionCoordinator, AgentToolRepairExhaustedError, AgentToolRepairPolicy, Aggregate, AggregateNode, Assertion, AssertionNode, AssertionOptions, BM25Index, BinaryRef, Callback, CallbackHandler, CallbackNode, CallbackOptions, CallbackResultNormalizer, CanvasIconName, CodemationChatModelConfig, CodemationChatModelFactory, CodemationManagedModel, ConnectionCredentialExecutionContextFactory, ConnectionCredentialNode, ConnectionCredentialNodeConfig, ConnectionCredentialNodeConfigFactory, CredentialSession, CronTickJson, CronTrigger, CronTriggerNode, DeferredMetaToolStrategy, DeferredMetaToolStrategyFactory, DefineRestNodeOptions, type ExecutedToolCall, Filter, FilterNode, type FindToolsResult, HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES, HttpBodySpec, HttpCredentialDelta, HttpRequest, HttpRequestDownloadMode, HttpRequestNode, HttpRequestOutputJson, HttpRequestResult, HttpRequestSpec, If, IfNode, IsTestRun, IsTestRunNode, type ItemScopedToolBinding, ManagedModelDto, ManagedModelFetcher, ManualTrigger, ManualTriggerNode, MapData, MapDataNode, MapDataOptions, Merge, MergeMode, MergeNode, NoOp, NoOpNode, OpenAIChatModelConfig, OpenAIChatModelFactory, OpenAiChatModelPresets, OpenAiCredentialSession, OpenAiStrictJsonSchemaFactory, type PlannedToolCall, type ResolvedTool, RestNodeApi, RestNodeErrorPolicy, RestNodeRequestShape, RestNodeResponseContext, SSRFBlockedError, Split, SplitNode, SsrfGuard, SubWorkflow, SubWorkflowNode, Switch, SwitchCaseKeyResolver, SwitchNode, TestTrigger, TestTriggerNode, TestTriggerOptions, type ToolLoadingStrategy, type ToolLoadingStrategyInitInput, type ToolLoadingStrategyTurnContext, Wait, WaitDuration, WaitNode, WebhookRespondNowAndContinueError, WebhookRespondNowError, WebhookTrigger, WebhookTriggerNode, type WorkflowAgentMessages, type WorkflowAgentOptions, WorkflowAuthoringBuilder, WorkflowBranchBuilder, WorkflowChain, apiKeyCredentialType, basicAuthCredentialType, bearerTokenCredentialType, collectionDeleteNode, collectionFindOneNode, collectionGetNode, collectionInsertNode, collectionListNode, collectionUpdateNode, createWorkflowBuilder, defineRestNode, oauth2ClientCredentialsType, openAiChatModelPresets, registerCoreNodes, workflow };
3851
+ //#region src/nodes/InboxApprovalNode.types.d.ts
3852
+ /**
3853
+ * A subject field (title / body) for an inbox approval. Either a static string
3854
+ * or a contextual callback that builds the string from the item using ordinary
3855
+ * JavaScript template literals — e.g. `({ item }) => `Approve ${item.json.vendor}``.
3856
+ * Code-first: no template DSL, just functions.
3857
+ */
3858
+ type InboxSubjectField = string | ((args: {
3859
+ item: Item;
3860
+ }) => string);
3861
+ /**
3862
+ * Auto-detecting inbox approval node.
3863
+ *
3864
+ * Uses `ctx.resolve(InboxChannelResolverToken)` to pick the right inbox channel
3865
+ * at runtime:
3866
+ * - In managed mode (PairingConfig present): routes to the control-plane inbox.
3867
+ * - Otherwise: routes to the local inbox.
3868
+ *
3869
+ * Authors use this node directly; no extra wiring needed per deployment mode.
3870
+ */
3871
+ declare const inboxApproval: DefinedHumanApprovalNode<"inbox.approval", {
3872
+ title: InboxSubjectField;
3873
+ body: InboxSubjectField;
3874
+ priority: "low" | "normal" | "high";
3875
+ timeout: string;
3876
+ onTimeout: "halt" | "auto-accept";
3877
+ }, Record<string, unknown>, undefined>;
3878
+ //#endregion
3879
+ export { AIAgent, AIAgentConnectionWorkflowExpander, AIAgentExecutionHelpersFactory, AIAgentNode, AgentItemPortMap, AgentMessageFactory, AgentOutputFactory, AgentStructuredOutputRepairPromptFactory, AgentStructuredOutputRunner, AgentToolCallPortMap, AgentToolErrorClassifier, AgentToolExecutionCoordinator, AgentToolRepairExhaustedError, AgentToolRepairPolicy, Aggregate, AggregateNode, Assertion, AssertionNode, AssertionOptions, BM25Index, BinaryRef, Callback, CallbackHandler, CallbackNode, CallbackOptions, CallbackResultNormalizer, CanvasIconName, CodemationChatModelConfig, CodemationChatModelFactory, CodemationManagedModel, ConnectionCredentialExecutionContextFactory, ConnectionCredentialNode, ConnectionCredentialNodeConfig, ConnectionCredentialNodeConfigFactory, CredentialSession, CronTickJson, CronTrigger, CronTriggerNode, DeferredMetaToolStrategy, DeferredMetaToolStrategyFactory, DefineRestNodeOptions, type ExecutedToolCall, Filter, FilterNode, type FindToolsResult, HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES, HttpBodySpec, HttpCredentialDelta, HttpRequest, HttpRequestDownloadMode, HttpRequestNode, HttpRequestOutputJson, HttpRequestResult, HttpRequestSpec, If, IfNode, IsTestRun, IsTestRunNode, type ItemScopedToolBinding, ManagedModelDto, ManagedModelFetcher, ManualTrigger, ManualTriggerNode, MapData, MapDataNode, MapDataOptions, Merge, MergeMode, MergeNode, NoOp, NoOpNode, OpenAIChatModelConfig, OpenAIChatModelFactory, OpenAiChatModelPresets, OpenAiCredentialSession, OpenAiStrictJsonSchemaFactory, type PlannedToolCall, type ResolvedTool, RestNodeApi, RestNodeErrorPolicy, RestNodeRequestShape, RestNodeResponseContext, SSRFBlockedError, Split, SplitNode, SsrfGuard, SubWorkflow, SubWorkflowNode, Switch, SwitchCaseKeyResolver, SwitchNode, TestTrigger, TestTriggerNode, TestTriggerOptions, type ToolLoadingStrategy, type ToolLoadingStrategyInitInput, type ToolLoadingStrategyTurnContext, Wait, WaitDuration, WaitNode, WebhookRespondNowAndContinueError, WebhookRespondNowError, WebhookTrigger, WebhookTriggerNode, type WorkflowAgentMessages, type WorkflowAgentOptions, WorkflowAuthoringBuilder, WorkflowBranchBuilder, WorkflowChain, apiKeyCredentialType, basicAuthCredentialType, bearerTokenCredentialType, collectionDeleteNode, collectionFindOneNode, collectionGetNode, collectionInsertNode, collectionListNode, collectionUpdateNode, createWorkflowBuilder, defineRestNode, inboxApproval, oauth2ClientCredentialsType, openAiChatModelPresets, registerCoreNodes, workflow };
3668
3880
  //# sourceMappingURL=index.d.ts.map