@kortyx/hooks 0.19.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/CHANGELOG.md +30 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +79 -5
- package/dist/index.js.map +1 -1
- package/dist/internal.js +8 -2
- package/dist/internal.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.21.0](https://github.com/kortyx-io/kortyx/compare/hooks-v0.20.0...hooks-v0.21.0) (2026-09-10)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **runtime:** add shared execution limits and checkpoint continuation ([#163](https://github.com/kortyx-io/kortyx/issues/163)) ([e22232c](https://github.com/kortyx-io/kortyx/commit/e22232c059fae4f7df1bd36423902bd365887942))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @kortyx/core bumped to 0.8.0
|
|
16
|
+
* @kortyx/telemetry-contracts bumped to 0.4.0
|
|
17
|
+
|
|
18
|
+
## [0.20.0](https://github.com/kortyx-io/kortyx/compare/hooks-v0.19.0...hooks-v0.20.0) (2026-09-10)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Features
|
|
22
|
+
|
|
23
|
+
* cancel workflow trees and reflect cancellation in Studio ([#161](https://github.com/kortyx-io/kortyx/issues/161)) ([699ad18](https://github.com/kortyx-io/kortyx/commit/699ad18905955c6340c3d85b9fae7f0bffd00a0d))
|
|
24
|
+
* execute and resume workflows without chat transport ([#159](https://github.com/kortyx-io/kortyx/issues/159)) ([6decb17](https://github.com/kortyx-io/kortyx/commit/6decb1714fedc021ac9e125b6ed9f75475ed928a))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Dependencies
|
|
28
|
+
|
|
29
|
+
* The following workspace dependencies were updated
|
|
30
|
+
* dependencies
|
|
31
|
+
* @kortyx/core bumped to 0.7.0
|
|
32
|
+
|
|
3
33
|
## [0.19.0](https://github.com/kortyx-io/kortyx/compare/hooks-v0.18.0...hooks-v0.19.0) (2026-09-09)
|
|
4
34
|
|
|
5
35
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as _kortyx_core from '@kortyx/core';
|
|
1
2
|
import { WorkflowDefinition, TokenUsage, InterruptInput, NodeConfig, InterruptResult, GraphState } from '@kortyx/core';
|
|
2
3
|
import { K as KortyxTelemetryConfig, R as ReasonTraceAdapter, a as KortyxTraceMetadata, b as KortyxTelemetryEventType } from './tracing-BI6YKHSf.js';
|
|
3
4
|
export { E as EnsureWorkflowTopologyRequest, c as EnsureWorkflowTopologyResponse, d as KortyxTelemetryContentCapture, e as KortyxTelemetryCorrelation, f as KortyxTelemetryEvent, g as KortyxTelemetryPrompt, h as KortyxTelemetryReporter, i as KortyxTelemetryService, j as KortyxTraceAdapter, k as ReasonTraceAttributes, l as ReasonTraceSpan, m as ReasonTraceSpanEndArgs, n as ReasonTraceSpanStartArgs } from './tracing-BI6YKHSf.js';
|
|
@@ -13,6 +14,7 @@ type WorkflowCallOutcome = {
|
|
|
13
14
|
status: "interrupted";
|
|
14
15
|
request: InterruptInput;
|
|
15
16
|
snapshot: unknown;
|
|
17
|
+
usage?: TokenUsage | undefined;
|
|
16
18
|
};
|
|
17
19
|
type WorkflowCallService = (args: {
|
|
18
20
|
id: string;
|
|
@@ -60,6 +62,9 @@ declare function useWorkflow(args: {
|
|
|
60
62
|
}>;
|
|
61
63
|
|
|
62
64
|
type HookNodeRuntimeContext = {
|
|
65
|
+
/** Transient execution control; never part of checkpointed state. */
|
|
66
|
+
abortSignal?: AbortSignal | undefined;
|
|
67
|
+
consumeExecution?: ((limit: _kortyx_core.ExecutionLimit) => void) | undefined;
|
|
63
68
|
graph: {
|
|
64
69
|
name: string;
|
|
65
70
|
node: string;
|
|
@@ -214,6 +219,8 @@ type StateSetter<T> = (next: T | ((prev: T) => T)) => void;
|
|
|
214
219
|
declare function useStructuredData<TData = unknown>(args: UseStructuredDataArgs<TData>): void;
|
|
215
220
|
declare function useReason<TOutput = unknown, TRequest extends InterruptInput = InterruptInput, TResponse = InterruptResult>(args: UseReasonArgs<TOutput, TRequest, TResponse>): Promise<UseReasonResult<TOutput, TResponse>>;
|
|
216
221
|
declare function useInterrupt<TRequest extends InterruptInput = InterruptInput, TResponse = InterruptResult>(args: UseInterruptArgs<TRequest, TResponse>): Promise<TResponse>;
|
|
222
|
+
/** Live execution signal for cooperative I/O. Never store it in workflow state. */
|
|
223
|
+
declare function useAbortSignal(): AbortSignal | undefined;
|
|
217
224
|
declare function useRuntimeContext<TContext extends Record<string, unknown> = Record<string, unknown>>(): TContext;
|
|
218
225
|
declare function useNodeState<T>(initialValue: T): [T, StateSetter<T>];
|
|
219
226
|
declare function useWorkflowState<T>(key: string, ...rest: [] | [T]): [T, StateSetter<T>];
|
|
@@ -221,4 +228,4 @@ declare function useWorkflowState<T>(key: string, ...rest: [] | [T]): [T, StateS
|
|
|
221
228
|
/** Best effort lifecycle facts. Engine snapshots and interrupt tokens never leave the runtime. */
|
|
222
229
|
declare function emitWorkflowCall(telemetry: KortyxTelemetryConfig | undefined, type: KortyxTelemetryEventType, payload: Record<string, unknown>): void;
|
|
223
230
|
|
|
224
|
-
export { type HookRuntimeContext, KortyxTelemetryConfig, KortyxTelemetryEventType, KortyxTraceMetadata, ReasonTraceAdapter, type UseInterruptArgs, type UseReasonArgs, type UseReasonResult, type UseReasonStep, type UseReasonToolExecution, type UseStructuredDataArgs, WorkflowCallError, type WorkflowCallOutcome, type WorkflowCallService, createWorkflowHooks, emitWorkflowCall, runWithHookContext, useInterrupt, useNodeState, useReason, useRuntimeContext, useStructuredData, useWorkflow, useWorkflowState, workflowCallFingerprint };
|
|
231
|
+
export { type HookRuntimeContext, KortyxTelemetryConfig, KortyxTelemetryEventType, KortyxTraceMetadata, ReasonTraceAdapter, type UseInterruptArgs, type UseReasonArgs, type UseReasonResult, type UseReasonStep, type UseReasonToolExecution, type UseStructuredDataArgs, WorkflowCallError, type WorkflowCallOutcome, type WorkflowCallService, createWorkflowHooks, emitWorkflowCall, runWithHookContext, useAbortSignal, useInterrupt, useNodeState, useReason, useRuntimeContext, useStructuredData, useWorkflow, useWorkflowState, workflowCallFingerprint };
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ __export(index_exports, {
|
|
|
23
23
|
createWorkflowHooks: () => createWorkflowHooks,
|
|
24
24
|
emitWorkflowCall: () => emitWorkflowCall,
|
|
25
25
|
runWithHookContext: () => runWithHookContext,
|
|
26
|
+
useAbortSignal: () => useAbortSignal,
|
|
26
27
|
useInterrupt: () => useInterrupt,
|
|
27
28
|
useNodeState: () => useNodeState,
|
|
28
29
|
useReason: () => useReason2,
|
|
@@ -188,6 +189,9 @@ function getHookContext() {
|
|
|
188
189
|
return ctx;
|
|
189
190
|
}
|
|
190
191
|
|
|
192
|
+
// src/interrupt.ts
|
|
193
|
+
var import_core = require("@kortyx/core");
|
|
194
|
+
|
|
191
195
|
// src/reason/checkpoint.ts
|
|
192
196
|
var resolveReasonCheckpointKey = (args) => typeof args.id === "string" && args.id.length > 0 ? `__useReason:${args.id}` : `__useReason:auto:${args.autoIndex}`;
|
|
193
197
|
var readReasonCheckpoint = (raw) => {
|
|
@@ -243,6 +247,7 @@ var parseWithSchema = (schema, value, label) => {
|
|
|
243
247
|
// src/interrupt.ts
|
|
244
248
|
var awaitInterruptInternal = (args) => {
|
|
245
249
|
const ctx = getHookContext();
|
|
250
|
+
(0, import_core.throwIfExecutionAborted)(ctx.node.abortSignal);
|
|
246
251
|
const request = parseWithSchema(
|
|
247
252
|
args.requestSchema,
|
|
248
253
|
args.request,
|
|
@@ -276,6 +281,9 @@ var awaitInterruptInternal = (args) => {
|
|
|
276
281
|
return Promise.resolve(response);
|
|
277
282
|
};
|
|
278
283
|
|
|
284
|
+
// src/reason/use-reason.ts
|
|
285
|
+
var import_core5 = require("@kortyx/core");
|
|
286
|
+
|
|
279
287
|
// src/structured.ts
|
|
280
288
|
var import_node_crypto = require("crypto");
|
|
281
289
|
|
|
@@ -370,9 +378,11 @@ var shouldStreamStructured = (cfg) => Boolean(cfg) && (cfg?.stream ?? true);
|
|
|
370
378
|
|
|
371
379
|
// src/reason/engine.ts
|
|
372
380
|
var import_node_crypto3 = require("crypto");
|
|
381
|
+
var import_core3 = require("@kortyx/core");
|
|
373
382
|
|
|
374
383
|
// src/reason-engine.ts
|
|
375
384
|
var import_node_crypto2 = require("crypto");
|
|
385
|
+
var import_core2 = require("@kortyx/core");
|
|
376
386
|
var toError = (value) => value instanceof Error ? value : new Error(String(value));
|
|
377
387
|
var createRuntimeId = () => {
|
|
378
388
|
try {
|
|
@@ -399,6 +409,7 @@ async function runReasonEngine(args) {
|
|
|
399
409
|
const responseFormat = args.responseFormat ?? args.model.options?.responseFormat;
|
|
400
410
|
const providerOptions = args.providerOptions ?? args.model.options?.providerOptions;
|
|
401
411
|
const tools = args.tools ?? args.model.options?.tools;
|
|
412
|
+
(0, import_core2.throwIfExecutionAborted)(abortSignal);
|
|
402
413
|
const model = args.model.provider.getModel(args.model.modelId, {
|
|
403
414
|
...temperature !== void 0 ? { temperature } : {},
|
|
404
415
|
streaming: stream,
|
|
@@ -491,6 +502,7 @@ async function runReasonEngine(args) {
|
|
|
491
502
|
}
|
|
492
503
|
const response2 = await model.stream(messages);
|
|
493
504
|
for await (const chunk of response2) {
|
|
505
|
+
(0, import_core2.throwIfExecutionAborted)(abortSignal);
|
|
494
506
|
switch (chunk.type) {
|
|
495
507
|
case "text-delta": {
|
|
496
508
|
if (chunk.delta.length === 0) break;
|
|
@@ -569,10 +581,12 @@ async function runReasonEngine(args) {
|
|
|
569
581
|
...providerMetadata !== void 0 ? { providerMetadata } : {},
|
|
570
582
|
...warnings !== void 0 ? { warnings } : {}
|
|
571
583
|
};
|
|
584
|
+
(0, import_core2.throwIfExecutionAborted)(abortSignal);
|
|
572
585
|
endTrace(traceSpan, result2);
|
|
573
586
|
return result2;
|
|
574
587
|
}
|
|
575
588
|
const response = await model.invoke(messages);
|
|
589
|
+
(0, import_core2.throwIfExecutionAborted)(abortSignal);
|
|
576
590
|
if (emit) {
|
|
577
591
|
emitNodeEvent(args.emitEvent, args.nodeId, "text-start", {
|
|
578
592
|
...commonMeta
|
|
@@ -599,8 +613,9 @@ async function runReasonEngine(args) {
|
|
|
599
613
|
endTrace(traceSpan, result);
|
|
600
614
|
return result;
|
|
601
615
|
} catch (error) {
|
|
602
|
-
|
|
603
|
-
|
|
616
|
+
const failure = abortSignal?.aborted ? (0, import_core2.createExecutionCancelledError)() : error;
|
|
617
|
+
failTrace(traceSpan, failure);
|
|
618
|
+
throw failure;
|
|
604
619
|
}
|
|
605
620
|
}
|
|
606
621
|
|
|
@@ -614,6 +629,13 @@ var createRuntimeId2 = () => {
|
|
|
614
629
|
};
|
|
615
630
|
async function reasonEngine(args, meta, inputOverride) {
|
|
616
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");
|
|
617
639
|
return runReasonEngine({
|
|
618
640
|
model: args.model,
|
|
619
641
|
input: inputOverride ?? args.input,
|
|
@@ -621,7 +643,7 @@ async function reasonEngine(args, meta, inputOverride) {
|
|
|
621
643
|
temperature: args.temperature,
|
|
622
644
|
maxOutputTokens: args.maxOutputTokens,
|
|
623
645
|
stopSequences: args.stopSequences,
|
|
624
|
-
abortSignal
|
|
646
|
+
abortSignal,
|
|
625
647
|
reasoning: args.reasoning,
|
|
626
648
|
responseFormat: args.responseFormat,
|
|
627
649
|
providerOptions: args.providerOptions,
|
|
@@ -1572,6 +1594,7 @@ var extractStreamingStringValues = (args) => {
|
|
|
1572
1594
|
};
|
|
1573
1595
|
|
|
1574
1596
|
// src/reason/tools.ts
|
|
1597
|
+
var import_core4 = require("@kortyx/core");
|
|
1575
1598
|
var toErrorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
1576
1599
|
var toToolDefinitions = (tools) => tools.map((tool) => ({
|
|
1577
1600
|
name: tool.name,
|
|
@@ -1625,6 +1648,11 @@ var createInitialMessages = (args) => [
|
|
|
1625
1648
|
var runReasonToolLoop = async (args) => {
|
|
1626
1649
|
const { useReasonArgs, id, opId, traceSpan } = args;
|
|
1627
1650
|
const ctx = getHookContext();
|
|
1651
|
+
const abortSignal = (0, import_core4.combineAbortSignals)(
|
|
1652
|
+
ctx.node.abortSignal,
|
|
1653
|
+
useReasonArgs.abortSignal,
|
|
1654
|
+
useReasonArgs.model.options?.abortSignal
|
|
1655
|
+
);
|
|
1628
1656
|
const tools = useReasonArgs.tools ?? [];
|
|
1629
1657
|
const toolByName = /* @__PURE__ */ new Map();
|
|
1630
1658
|
let validationCompleted = false;
|
|
@@ -1674,6 +1702,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
1674
1702
|
};
|
|
1675
1703
|
try {
|
|
1676
1704
|
for (let stepIndex = 0; stepIndex < maxSteps; stepIndex += 1) {
|
|
1705
|
+
(0, import_core4.throwIfExecutionAborted)(abortSignal);
|
|
1677
1706
|
traceSpan?.addEvent?.("useReason.tool-step.start", {
|
|
1678
1707
|
stepIndex,
|
|
1679
1708
|
toolCount: toolDefinitions.length
|
|
@@ -1691,6 +1720,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
1691
1720
|
finalText = step.text;
|
|
1692
1721
|
finalRaw = step.raw;
|
|
1693
1722
|
aggregatedUsage = mergeUsage(aggregatedUsage, step.usage);
|
|
1723
|
+
accumulateTokenUsage(step.usage);
|
|
1694
1724
|
finalFinishReason = step.finishReason;
|
|
1695
1725
|
aggregatedProviderMetadata = mergeProviderMetadata(
|
|
1696
1726
|
aggregatedProviderMetadata,
|
|
@@ -1724,6 +1754,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
1724
1754
|
toolCalls
|
|
1725
1755
|
});
|
|
1726
1756
|
for (const toolCall of toolCalls) {
|
|
1757
|
+
(0, import_core4.throwIfExecutionAborted)(abortSignal);
|
|
1727
1758
|
const tool = toolByName.get(toolCall.name);
|
|
1728
1759
|
if (!tool) {
|
|
1729
1760
|
throw new Error(
|
|
@@ -1791,10 +1822,13 @@ var runReasonToolLoop = async (args) => {
|
|
|
1791
1822
|
}
|
|
1792
1823
|
}
|
|
1793
1824
|
try {
|
|
1825
|
+
(0, import_core4.throwIfExecutionAborted)(abortSignal);
|
|
1826
|
+
ctx.node.consumeExecution?.("maxToolCalls");
|
|
1794
1827
|
const rawResult = await tool.execute(toolCall.input, {
|
|
1795
1828
|
toolCallId: toolCall.id,
|
|
1796
|
-
...
|
|
1829
|
+
...abortSignal ? { abortSignal } : {}
|
|
1797
1830
|
});
|
|
1831
|
+
(0, import_core4.throwIfExecutionAborted)(abortSignal);
|
|
1798
1832
|
const result2 = normalizeToolResult(toolCall, rawResult);
|
|
1799
1833
|
toolResults.push(result2);
|
|
1800
1834
|
allToolResults.push(result2);
|
|
@@ -1814,6 +1848,9 @@ var runReasonToolLoop = async (args) => {
|
|
|
1814
1848
|
isError: Boolean(result2.isError)
|
|
1815
1849
|
});
|
|
1816
1850
|
} catch (error) {
|
|
1851
|
+
(0, import_core4.throwIfExecutionAborted)(abortSignal);
|
|
1852
|
+
if ((0, import_core4.isExecutionLimitReached)(error) || (0, import_core4.isExecutionCancelled)(error))
|
|
1853
|
+
throw error;
|
|
1817
1854
|
const result2 = {
|
|
1818
1855
|
toolCallId: toolCall.id,
|
|
1819
1856
|
name: tool.name,
|
|
@@ -1937,6 +1974,13 @@ var assertReasoningThoughtsCompatibility = (args) => {
|
|
|
1937
1974
|
async function useReason(args) {
|
|
1938
1975
|
assertReasoningThoughtsCompatibility(args);
|
|
1939
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 };
|
|
1940
1984
|
const id = typeof args.id === "string" && args.id.length > 0 ? args.id : void 0;
|
|
1941
1985
|
const opId = createRuntimeId2();
|
|
1942
1986
|
const checkpointKey = resolveReasonCheckpointKey({
|
|
@@ -2306,6 +2350,9 @@ function useReason2(args) {
|
|
|
2306
2350
|
function useInterrupt(args) {
|
|
2307
2351
|
return awaitInterruptInternal(args);
|
|
2308
2352
|
}
|
|
2353
|
+
function useAbortSignal() {
|
|
2354
|
+
return getHookContext().node.abortSignal;
|
|
2355
|
+
}
|
|
2309
2356
|
function useRuntimeContext() {
|
|
2310
2357
|
const ctx = getHookContext();
|
|
2311
2358
|
const config = ctx.state.config;
|
|
@@ -2350,6 +2397,7 @@ function useWorkflowState(key, ...rest) {
|
|
|
2350
2397
|
|
|
2351
2398
|
// src/workflow.ts
|
|
2352
2399
|
var import_node_crypto5 = require("crypto");
|
|
2400
|
+
var import_core6 = require("@kortyx/core");
|
|
2353
2401
|
|
|
2354
2402
|
// src/workflow-telemetry.ts
|
|
2355
2403
|
var import_node_crypto4 = require("crypto");
|
|
@@ -2436,6 +2484,7 @@ function createWorkflowHooks(workflows) {
|
|
|
2436
2484
|
}
|
|
2437
2485
|
async function useWorkflow(args) {
|
|
2438
2486
|
const ctx = getHookContext();
|
|
2487
|
+
(0, import_core6.throwIfExecutionAborted)(ctx.node.abortSignal);
|
|
2439
2488
|
const service = ctx.node.callWorkflow;
|
|
2440
2489
|
if (!service)
|
|
2441
2490
|
throw new Error("useWorkflow requires an agent workflow registry.");
|
|
@@ -2469,6 +2518,7 @@ async function useWorkflow(args) {
|
|
|
2469
2518
|
workflow,
|
|
2470
2519
|
"call input or target changed during replay"
|
|
2471
2520
|
);
|
|
2521
|
+
if (!record) ctx.node.consumeExecution?.("maxChildInvocations");
|
|
2472
2522
|
record ??= {
|
|
2473
2523
|
fingerprint,
|
|
2474
2524
|
invocationId: (0, import_node_crypto5.randomUUID)(),
|
|
@@ -2502,6 +2552,15 @@ async function useWorkflow(args) {
|
|
|
2502
2552
|
...content
|
|
2503
2553
|
});
|
|
2504
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
|
+
};
|
|
2505
2564
|
const cached = record.status === "completed";
|
|
2506
2565
|
try {
|
|
2507
2566
|
for (const interruption of record.interrupts) {
|
|
@@ -2530,14 +2589,28 @@ async function useWorkflow(args) {
|
|
|
2530
2589
|
...record.interrupts.length ? { response: record.interrupts.at(-1)?.response } : {}
|
|
2531
2590
|
});
|
|
2532
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
|
+
}
|
|
2533
2605
|
record.status = "failed";
|
|
2534
2606
|
record.error = error instanceof Error ? error.message : String(error);
|
|
2535
2607
|
report("failed", { error: "Child workflow failed" });
|
|
2536
2608
|
throw new WorkflowCallError(workflow, record.error);
|
|
2537
2609
|
}
|
|
2610
|
+
(0, import_core6.throwIfExecutionAborted)(ctx.node.abortSignal);
|
|
2611
|
+
recordUsage(outcome.usage);
|
|
2538
2612
|
if (outcome.status === "completed") {
|
|
2539
2613
|
record.data = outcome.data;
|
|
2540
|
-
accumulateTokenUsage(outcome.usage);
|
|
2541
2614
|
workflowCallFingerprint(record.data);
|
|
2542
2615
|
record.status = "completed";
|
|
2543
2616
|
delete record.snapshot;
|
|
@@ -2577,6 +2650,7 @@ async function useWorkflow(args) {
|
|
|
2577
2650
|
createWorkflowHooks,
|
|
2578
2651
|
emitWorkflowCall,
|
|
2579
2652
|
runWithHookContext,
|
|
2653
|
+
useAbortSignal,
|
|
2580
2654
|
useInterrupt,
|
|
2581
2655
|
useNodeState,
|
|
2582
2656
|
useReason,
|