@kortyx/hooks 0.18.0 → 0.21.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.js CHANGED
@@ -19,13 +19,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  // src/index.ts
20
20
  var index_exports = {};
21
21
  __export(index_exports, {
22
+ WorkflowCallError: () => WorkflowCallError,
23
+ createWorkflowHooks: () => createWorkflowHooks,
24
+ emitWorkflowCall: () => emitWorkflowCall,
22
25
  runWithHookContext: () => runWithHookContext,
26
+ useAbortSignal: () => useAbortSignal,
23
27
  useInterrupt: () => useInterrupt,
24
28
  useNodeState: () => useNodeState,
25
29
  useReason: () => useReason2,
26
30
  useRuntimeContext: () => useRuntimeContext,
27
31
  useStructuredData: () => useStructuredData,
28
- useWorkflowState: () => useWorkflowState
32
+ useWorkflow: () => useWorkflow,
33
+ useWorkflowState: () => useWorkflowState,
34
+ workflowCallFingerprint: () => workflowCallFingerprint
29
35
  });
30
36
  module.exports = __toCommonJS(index_exports);
31
37
 
@@ -78,6 +84,8 @@ var createInternalContext = (ctx) => {
78
84
  const currentNodeState = storedNodeId && storedNodeId === nodeId ? normalizeNodeState(storedState) : { byIndex: [], byKey: {} };
79
85
  return {
80
86
  ...ctx,
87
+ workflowCallActive: false,
88
+ workflowCallIds: /* @__PURE__ */ new Set(),
81
89
  nodeStateIndex: 0,
82
90
  reasonCallIndex: 0,
83
91
  currentNodeState,
@@ -151,6 +159,12 @@ async function runWithHookContext(ctx, fn) {
151
159
  try {
152
160
  const result = await storage.run(internal, fn);
153
161
  cleanupCompletedReasonCheckpoints(internal);
162
+ for (const key of Object.keys(internal.currentNodeState.byKey)) {
163
+ if (key.startsWith("__useWorkflow:") || key === "__useWorkflowActivation") {
164
+ internal.currentNodeState.byKey[key] = null;
165
+ internal.stateDirty = true;
166
+ }
167
+ }
154
168
  return { result, runtimeUpdates: buildRuntimeStateUpdates(internal) };
155
169
  } catch (err) {
156
170
  const runtimeUpdates = buildRuntimeStateUpdates(internal);
@@ -175,6 +189,9 @@ function getHookContext() {
175
189
  return ctx;
176
190
  }
177
191
 
192
+ // src/interrupt.ts
193
+ var import_core = require("@kortyx/core");
194
+
178
195
  // src/reason/checkpoint.ts
179
196
  var resolveReasonCheckpointKey = (args) => typeof args.id === "string" && args.id.length > 0 ? `__useReason:${args.id}` : `__useReason:auto:${args.autoIndex}`;
180
197
  var readReasonCheckpoint = (raw) => {
@@ -230,6 +247,7 @@ var parseWithSchema = (schema, value, label) => {
230
247
  // src/interrupt.ts
231
248
  var awaitInterruptInternal = (args) => {
232
249
  const ctx = getHookContext();
250
+ (0, import_core.throwIfExecutionAborted)(ctx.node.abortSignal);
233
251
  const request = parseWithSchema(
234
252
  args.requestSchema,
235
253
  args.request,
@@ -248,7 +266,10 @@ var awaitInterruptInternal = (args) => {
248
266
  ...typeof args.id === "string" && args.id.length > 0 ? { id: args.id } : {},
249
267
  meta: {
250
268
  ...userMeta,
251
- __kortyxResumeStatePatch: resumeStatePatch
269
+ __kortyxResumeStatePatch: {
270
+ ...resumeStatePatch,
271
+ ...ctx.tokenUsage ? { tokenUsage: ctx.tokenUsage } : {}
272
+ }
252
273
  }
253
274
  };
254
275
  const raw = ctx.node.awaitInterrupt(enrichedRequest);
@@ -260,6 +281,9 @@ var awaitInterruptInternal = (args) => {
260
281
  return Promise.resolve(response);
261
282
  };
262
283
 
284
+ // src/reason/use-reason.ts
285
+ var import_core5 = require("@kortyx/core");
286
+
263
287
  // src/structured.ts
264
288
  var import_node_crypto = require("crypto");
265
289
 
@@ -354,9 +378,11 @@ var shouldStreamStructured = (cfg) => Boolean(cfg) && (cfg?.stream ?? true);
354
378
 
355
379
  // src/reason/engine.ts
356
380
  var import_node_crypto3 = require("crypto");
381
+ var import_core3 = require("@kortyx/core");
357
382
 
358
383
  // src/reason-engine.ts
359
384
  var import_node_crypto2 = require("crypto");
385
+ var import_core2 = require("@kortyx/core");
360
386
  var toError = (value) => value instanceof Error ? value : new Error(String(value));
361
387
  var createRuntimeId = () => {
362
388
  try {
@@ -383,6 +409,7 @@ async function runReasonEngine(args) {
383
409
  const responseFormat = args.responseFormat ?? args.model.options?.responseFormat;
384
410
  const providerOptions = args.providerOptions ?? args.model.options?.providerOptions;
385
411
  const tools = args.tools ?? args.model.options?.tools;
412
+ (0, import_core2.throwIfExecutionAborted)(abortSignal);
386
413
  const model = args.model.provider.getModel(args.model.modelId, {
387
414
  ...temperature !== void 0 ? { temperature } : {},
388
415
  streaming: stream,
@@ -475,6 +502,7 @@ async function runReasonEngine(args) {
475
502
  }
476
503
  const response2 = await model.stream(messages);
477
504
  for await (const chunk of response2) {
505
+ (0, import_core2.throwIfExecutionAborted)(abortSignal);
478
506
  switch (chunk.type) {
479
507
  case "text-delta": {
480
508
  if (chunk.delta.length === 0) break;
@@ -553,10 +581,12 @@ async function runReasonEngine(args) {
553
581
  ...providerMetadata !== void 0 ? { providerMetadata } : {},
554
582
  ...warnings !== void 0 ? { warnings } : {}
555
583
  };
584
+ (0, import_core2.throwIfExecutionAborted)(abortSignal);
556
585
  endTrace(traceSpan, result2);
557
586
  return result2;
558
587
  }
559
588
  const response = await model.invoke(messages);
589
+ (0, import_core2.throwIfExecutionAborted)(abortSignal);
560
590
  if (emit) {
561
591
  emitNodeEvent(args.emitEvent, args.nodeId, "text-start", {
562
592
  ...commonMeta
@@ -583,8 +613,9 @@ async function runReasonEngine(args) {
583
613
  endTrace(traceSpan, result);
584
614
  return result;
585
615
  } catch (error) {
586
- failTrace(traceSpan, error);
587
- throw error;
616
+ const failure = abortSignal?.aborted ? (0, import_core2.createExecutionCancelledError)() : error;
617
+ failTrace(traceSpan, failure);
618
+ throw failure;
588
619
  }
589
620
  }
590
621
 
@@ -598,6 +629,13 @@ var createRuntimeId2 = () => {
598
629
  };
599
630
  async function reasonEngine(args, meta, inputOverride) {
600
631
  const ctx = getHookContext();
632
+ const abortSignal = (0, import_core3.combineAbortSignals)(
633
+ ctx.node.abortSignal,
634
+ args.abortSignal,
635
+ args.model.options?.abortSignal
636
+ );
637
+ (0, import_core3.throwIfExecutionAborted)(abortSignal);
638
+ ctx.node.consumeExecution?.("maxModelPasses");
601
639
  return runReasonEngine({
602
640
  model: args.model,
603
641
  input: inputOverride ?? args.input,
@@ -605,7 +643,7 @@ async function reasonEngine(args, meta, inputOverride) {
605
643
  temperature: args.temperature,
606
644
  maxOutputTokens: args.maxOutputTokens,
607
645
  stopSequences: args.stopSequences,
608
- abortSignal: args.abortSignal,
646
+ abortSignal,
609
647
  reasoning: args.reasoning,
610
648
  responseFormat: args.responseFormat,
611
649
  providerOptions: args.providerOptions,
@@ -1556,6 +1594,7 @@ var extractStreamingStringValues = (args) => {
1556
1594
  };
1557
1595
 
1558
1596
  // src/reason/tools.ts
1597
+ var import_core4 = require("@kortyx/core");
1559
1598
  var toErrorMessage = (error) => error instanceof Error ? error.message : String(error);
1560
1599
  var toToolDefinitions = (tools) => tools.map((tool) => ({
1561
1600
  name: tool.name,
@@ -1609,6 +1648,11 @@ var createInitialMessages = (args) => [
1609
1648
  var runReasonToolLoop = async (args) => {
1610
1649
  const { useReasonArgs, id, opId, traceSpan } = args;
1611
1650
  const ctx = getHookContext();
1651
+ const abortSignal = (0, import_core4.combineAbortSignals)(
1652
+ ctx.node.abortSignal,
1653
+ useReasonArgs.abortSignal,
1654
+ useReasonArgs.model.options?.abortSignal
1655
+ );
1612
1656
  const tools = useReasonArgs.tools ?? [];
1613
1657
  const toolByName = /* @__PURE__ */ new Map();
1614
1658
  let validationCompleted = false;
@@ -1658,6 +1702,7 @@ var runReasonToolLoop = async (args) => {
1658
1702
  };
1659
1703
  try {
1660
1704
  for (let stepIndex = 0; stepIndex < maxSteps; stepIndex += 1) {
1705
+ (0, import_core4.throwIfExecutionAborted)(abortSignal);
1661
1706
  traceSpan?.addEvent?.("useReason.tool-step.start", {
1662
1707
  stepIndex,
1663
1708
  toolCount: toolDefinitions.length
@@ -1675,6 +1720,7 @@ var runReasonToolLoop = async (args) => {
1675
1720
  finalText = step.text;
1676
1721
  finalRaw = step.raw;
1677
1722
  aggregatedUsage = mergeUsage(aggregatedUsage, step.usage);
1723
+ accumulateTokenUsage(step.usage);
1678
1724
  finalFinishReason = step.finishReason;
1679
1725
  aggregatedProviderMetadata = mergeProviderMetadata(
1680
1726
  aggregatedProviderMetadata,
@@ -1708,6 +1754,7 @@ var runReasonToolLoop = async (args) => {
1708
1754
  toolCalls
1709
1755
  });
1710
1756
  for (const toolCall of toolCalls) {
1757
+ (0, import_core4.throwIfExecutionAborted)(abortSignal);
1711
1758
  const tool = toolByName.get(toolCall.name);
1712
1759
  if (!tool) {
1713
1760
  throw new Error(
@@ -1775,10 +1822,13 @@ var runReasonToolLoop = async (args) => {
1775
1822
  }
1776
1823
  }
1777
1824
  try {
1825
+ (0, import_core4.throwIfExecutionAborted)(abortSignal);
1826
+ ctx.node.consumeExecution?.("maxToolCalls");
1778
1827
  const rawResult = await tool.execute(toolCall.input, {
1779
1828
  toolCallId: toolCall.id,
1780
- ...useReasonArgs.abortSignal ? { abortSignal: useReasonArgs.abortSignal } : {}
1829
+ ...abortSignal ? { abortSignal } : {}
1781
1830
  });
1831
+ (0, import_core4.throwIfExecutionAborted)(abortSignal);
1782
1832
  const result2 = normalizeToolResult(toolCall, rawResult);
1783
1833
  toolResults.push(result2);
1784
1834
  allToolResults.push(result2);
@@ -1798,6 +1848,9 @@ var runReasonToolLoop = async (args) => {
1798
1848
  isError: Boolean(result2.isError)
1799
1849
  });
1800
1850
  } catch (error) {
1851
+ (0, import_core4.throwIfExecutionAborted)(abortSignal);
1852
+ if ((0, import_core4.isExecutionLimitReached)(error) || (0, import_core4.isExecutionCancelled)(error))
1853
+ throw error;
1801
1854
  const result2 = {
1802
1855
  toolCallId: toolCall.id,
1803
1856
  name: tool.name,
@@ -1921,6 +1974,13 @@ var assertReasoningThoughtsCompatibility = (args) => {
1921
1974
  async function useReason(args) {
1922
1975
  assertReasoningThoughtsCompatibility(args);
1923
1976
  const ctx = getHookContext();
1977
+ const abortSignal = (0, import_core5.combineAbortSignals)(
1978
+ ctx.node.abortSignal,
1979
+ args.abortSignal,
1980
+ args.model.options?.abortSignal
1981
+ );
1982
+ (0, import_core5.throwIfExecutionAborted)(abortSignal);
1983
+ args = { ...args, abortSignal };
1924
1984
  const id = typeof args.id === "string" && args.id.length > 0 ? args.id : void 0;
1925
1985
  const opId = createRuntimeId2();
1926
1986
  const checkpointKey = resolveReasonCheckpointKey({
@@ -2290,6 +2350,9 @@ function useReason2(args) {
2290
2350
  function useInterrupt(args) {
2291
2351
  return awaitInterruptInternal(args);
2292
2352
  }
2353
+ function useAbortSignal() {
2354
+ return getHookContext().node.abortSignal;
2355
+ }
2293
2356
  function useRuntimeContext() {
2294
2357
  const ctx = getHookContext();
2295
2358
  const config = ctx.state.config;
@@ -2331,14 +2394,270 @@ function useWorkflowState(key, ...rest) {
2331
2394
  };
2332
2395
  return [getValue(), setValue];
2333
2396
  }
2397
+
2398
+ // src/workflow.ts
2399
+ var import_node_crypto5 = require("crypto");
2400
+ var import_core6 = require("@kortyx/core");
2401
+
2402
+ // src/workflow-telemetry.ts
2403
+ var import_node_crypto4 = require("crypto");
2404
+ function emitWorkflowCall(telemetry, type, payload) {
2405
+ const base = telemetry?.correlation;
2406
+ if (!telemetry?.reporter || !telemetry.environment || !telemetry.service || !base?.runId || !base.workflowId)
2407
+ return;
2408
+ try {
2409
+ const active = telemetry.trace?.getActiveContext?.();
2410
+ void Promise.resolve(
2411
+ telemetry.reporter.emit([
2412
+ {
2413
+ schemaVersion: 1,
2414
+ eventId: (0, import_node_crypto4.randomUUID)(),
2415
+ occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
2416
+ environment: telemetry.environment,
2417
+ service: telemetry.service,
2418
+ correlation: {
2419
+ ...base,
2420
+ runId: base.runId,
2421
+ workflowId: base.workflowId,
2422
+ ...active
2423
+ },
2424
+ type,
2425
+ payload
2426
+ }
2427
+ ])
2428
+ ).catch(() => {
2429
+ });
2430
+ } catch {
2431
+ }
2432
+ }
2433
+ function workflowCallContent(telemetry, side, value) {
2434
+ const policy = telemetry?.captureContent;
2435
+ if (!(policy === true || policy && typeof policy === "object" && policy[side]))
2436
+ return {};
2437
+ const serialized = JSON.stringify(value);
2438
+ return serialized && Buffer.byteLength(serialized, "utf8") <= 16384 ? { [side]: JSON.parse(serialized) } : { [`${side}Omitted`]: "Content exceeds 16 KiB" };
2439
+ }
2440
+
2441
+ // src/workflow.ts
2442
+ var WorkflowCallError = class extends Error {
2443
+ constructor(workflow, message) {
2444
+ super(`Workflow '${workflow}': ${message}`);
2445
+ this.workflow = workflow;
2446
+ this.name = "WorkflowCallError";
2447
+ }
2448
+ workflow;
2449
+ };
2450
+ function workflowCallFingerprint(value) {
2451
+ const seen = /* @__PURE__ */ new Set();
2452
+ const canonical = (v) => {
2453
+ if (v === null || typeof v === "string" || typeof v === "boolean") return v;
2454
+ if (typeof v === "number" && Number.isFinite(v)) return v;
2455
+ if (typeof v !== "object" || !v || seen.has(v)) {
2456
+ throw new Error("Workflow input and output must be JSON serializable.");
2457
+ }
2458
+ if (!Array.isArray(v) && Object.getPrototypeOf(v) !== Object.prototype) {
2459
+ throw new Error(
2460
+ "Workflow input and output must contain plain JSON objects."
2461
+ );
2462
+ }
2463
+ seen.add(v);
2464
+ const result = Array.isArray(v) ? v.map(canonical) : Object.fromEntries(
2465
+ Object.keys(v).sort().map((key) => [
2466
+ key,
2467
+ canonical(v[key])
2468
+ ])
2469
+ );
2470
+ seen.delete(v);
2471
+ return result;
2472
+ };
2473
+ return JSON.stringify(canonical(value));
2474
+ }
2475
+ function createWorkflowHooks(workflows) {
2476
+ return {
2477
+ useWorkflow: (args) => {
2478
+ const workflow = workflows[args.workflow];
2479
+ if (!workflow || workflow.id !== args.workflow)
2480
+ throw new Error("Workflow registry keys must match definition ids.");
2481
+ return useWorkflow({ ...args, workflow });
2482
+ }
2483
+ };
2484
+ }
2485
+ async function useWorkflow(args) {
2486
+ const ctx = getHookContext();
2487
+ (0, import_core6.throwIfExecutionAborted)(ctx.node.abortSignal);
2488
+ const service = ctx.node.callWorkflow;
2489
+ if (!service)
2490
+ throw new Error("useWorkflow requires an agent workflow registry.");
2491
+ if (!args.id.trim())
2492
+ throw new Error("useWorkflow requires a stable, nonempty id.");
2493
+ if (ctx.workflowCallActive)
2494
+ throw new Error(
2495
+ "Concurrent workflow calls are not supported; await each call."
2496
+ );
2497
+ if (ctx.workflowCallIds.has(args.id))
2498
+ throw new Error(
2499
+ `Duplicate workflow call id '${args.id}' in one node activation.`
2500
+ );
2501
+ if (ctx.workflowCallIds.size >= 64)
2502
+ throw new Error(
2503
+ "A node may call at most 64 child workflows per activation."
2504
+ );
2505
+ ctx.workflowCallIds.add(args.id);
2506
+ const definition = typeof args.workflow === "string" ? void 0 : args.workflow;
2507
+ const workflow = definition?.id ?? args.workflow;
2508
+ const input = args.input;
2509
+ const fingerprint = workflowCallFingerprint({
2510
+ workflow,
2511
+ input,
2512
+ version: definition?.version ?? null
2513
+ });
2514
+ const key = `__useWorkflow:${args.id}`;
2515
+ let record = ctx.currentNodeState.byKey[key];
2516
+ if (record && record.fingerprint !== fingerprint)
2517
+ throw new WorkflowCallError(
2518
+ workflow,
2519
+ "call input or target changed during replay"
2520
+ );
2521
+ if (!record) ctx.node.consumeExecution?.("maxChildInvocations");
2522
+ record ??= {
2523
+ fingerprint,
2524
+ invocationId: (0, import_node_crypto5.randomUUID)(),
2525
+ status: "running",
2526
+ interrupts: []
2527
+ };
2528
+ ctx.currentNodeState.byKey[key] = record;
2529
+ ctx.stateDirty = true;
2530
+ ctx.workflowCallActive = true;
2531
+ const telemetry = ctx.node.workflowCallTelemetry;
2532
+ const activationKey = "__useWorkflowActivation";
2533
+ ctx.currentNodeState.byKey[activationKey] ??= (0, import_node_crypto5.randomUUID)();
2534
+ const callerNodeExecutionId = ctx.currentNodeState.byKey[activationKey];
2535
+ const metadata = {
2536
+ invocationId: record.invocationId,
2537
+ parentInvocationId: telemetry?.correlation?.invocationId ?? null,
2538
+ branchId: telemetry?.correlation?.branchId ?? telemetry?.correlation?.runId ?? "unknown",
2539
+ callId: args.id,
2540
+ callerNodeId: ctx.node.graph.node,
2541
+ callerNodeExecutionId,
2542
+ sourceWorkflowId: ctx.node.graph.name,
2543
+ targetWorkflowId: workflow,
2544
+ targetVersion: definition?.version ?? null
2545
+ };
2546
+ record.telemetry = metadata;
2547
+ const report = (status, content = {}) => {
2548
+ record.sequence = (record.sequence ?? 0) + 1;
2549
+ emitWorkflowCall(telemetry, `workflow.call.${status}`, {
2550
+ ...metadata,
2551
+ sequence: record.sequence,
2552
+ ...content
2553
+ });
2554
+ };
2555
+ const recordUsage = (usage) => {
2556
+ if (!usage) return;
2557
+ accumulateTokenUsage({
2558
+ input: usage.input - (record.usage?.input ?? 0),
2559
+ output: usage.output - (record.usage?.output ?? 0),
2560
+ total: usage.total - (record.usage?.total ?? 0)
2561
+ });
2562
+ record.usage = usage;
2563
+ };
2564
+ const cached = record.status === "completed";
2565
+ try {
2566
+ for (const interruption of record.interrupts) {
2567
+ interruption.response = await awaitInterruptInternal({
2568
+ request: interruption.request,
2569
+ ...interruption.request.meta ? { meta: interruption.request.meta } : {}
2570
+ });
2571
+ }
2572
+ if (record.status === "failed")
2573
+ throw new WorkflowCallError(workflow, record.error ?? "child failed");
2574
+ while (record.status !== "completed") {
2575
+ let outcome;
2576
+ try {
2577
+ report(
2578
+ record.snapshot ? "resumed" : "started",
2579
+ workflowCallContent(telemetry, "input", input)
2580
+ );
2581
+ outcome = await service({
2582
+ callerNodeExecutionId,
2583
+ id: args.id,
2584
+ workflow,
2585
+ input,
2586
+ definition,
2587
+ invocationId: record.invocationId,
2588
+ ...record.snapshot ? { snapshot: record.snapshot } : {},
2589
+ ...record.interrupts.length ? { response: record.interrupts.at(-1)?.response } : {}
2590
+ });
2591
+ } catch (error) {
2592
+ (0, import_core6.throwIfExecutionAborted)(ctx.node.abortSignal);
2593
+ if ((0, import_core6.isExecutionCancelled)(error)) throw error;
2594
+ if ((0, import_core6.isExecutionLimitReached)(error)) {
2595
+ const child = error;
2596
+ if (child.__kortyxChildSnapshot)
2597
+ record.snapshot = child.__kortyxChildSnapshot;
2598
+ recordUsage(child.__kortyxChildUsage);
2599
+ report("suspended", {
2600
+ reason: "limit_reached",
2601
+ limit: error.limitReached
2602
+ });
2603
+ throw error;
2604
+ }
2605
+ record.status = "failed";
2606
+ record.error = error instanceof Error ? error.message : String(error);
2607
+ report("failed", { error: "Child workflow failed" });
2608
+ throw new WorkflowCallError(workflow, record.error);
2609
+ }
2610
+ (0, import_core6.throwIfExecutionAborted)(ctx.node.abortSignal);
2611
+ recordUsage(outcome.usage);
2612
+ if (outcome.status === "completed") {
2613
+ record.data = outcome.data;
2614
+ workflowCallFingerprint(record.data);
2615
+ record.status = "completed";
2616
+ delete record.snapshot;
2617
+ report(
2618
+ "completed",
2619
+ workflowCallContent(telemetry, "output", record.data)
2620
+ );
2621
+ } else {
2622
+ record.status = "interrupted";
2623
+ record.snapshot = outcome.snapshot;
2624
+ report("suspended", {
2625
+ leaf: outcome.request.meta?.workflowCall ?? null
2626
+ });
2627
+ const interruption = {
2628
+ request: outcome.request
2629
+ };
2630
+ record.interrupts.push(interruption);
2631
+ interruption.response = await awaitInterruptInternal({
2632
+ request: interruption.request,
2633
+ ...interruption.request.meta ? { meta: interruption.request.meta } : {}
2634
+ });
2635
+ }
2636
+ }
2637
+ if (cached)
2638
+ report("reused", workflowCallContent(telemetry, "output", record.data));
2639
+ const data = record.data ?? {};
2640
+ return {
2641
+ data: JSON.parse(JSON.stringify(data))
2642
+ };
2643
+ } finally {
2644
+ ctx.workflowCallActive = false;
2645
+ }
2646
+ }
2334
2647
  // Annotate the CommonJS export names for ESM import in node:
2335
2648
  0 && (module.exports = {
2649
+ WorkflowCallError,
2650
+ createWorkflowHooks,
2651
+ emitWorkflowCall,
2336
2652
  runWithHookContext,
2653
+ useAbortSignal,
2337
2654
  useInterrupt,
2338
2655
  useNodeState,
2339
2656
  useReason,
2340
2657
  useRuntimeContext,
2341
2658
  useStructuredData,
2342
- useWorkflowState
2659
+ useWorkflow,
2660
+ useWorkflowState,
2661
+ workflowCallFingerprint
2343
2662
  });
2344
2663
  //# sourceMappingURL=index.js.map