@workflow/core 4.1.0-beta.54 → 4.1.0-beta.56
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/private.d.ts.map +1 -1
- package/dist/private.js +43 -2
- package/dist/runtime/helpers.d.ts +21 -0
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +91 -4
- package/dist/runtime/step-handler.d.ts.map +1 -1
- package/dist/runtime/step-handler.js +53 -29
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +160 -134
- package/dist/serialization-format.d.ts +117 -0
- package/dist/serialization-format.d.ts.map +1 -0
- package/dist/serialization-format.js +363 -0
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +67 -18
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +62 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/api-reference/create-hook.mdx +7 -0
- package/docs/api-reference/create-webhook.mdx +6 -0
- package/docs/api-reference/define-hook.mdx +6 -0
- package/docs/api-reference/fatal-error.mdx +6 -0
- package/docs/api-reference/fetch.mdx +6 -0
- package/docs/api-reference/get-step-metadata.mdx +4 -0
- package/docs/api-reference/get-workflow-metadata.mdx +4 -0
- package/docs/api-reference/get-writable.mdx +4 -0
- package/docs/api-reference/index.mdx +7 -0
- package/docs/api-reference/retryable-error.mdx +6 -0
- package/docs/api-reference/sleep.mdx +6 -0
- package/docs/foundations/common-patterns.mdx +7 -0
- package/docs/foundations/errors-and-retries.mdx +7 -0
- package/docs/foundations/hooks.mdx +8 -0
- package/docs/foundations/idempotency.mdx +6 -0
- package/docs/foundations/index.mdx +5 -0
- package/docs/foundations/serialization.mdx +6 -0
- package/docs/foundations/starting-workflows.mdx +6 -0
- package/docs/foundations/streaming.mdx +7 -0
- package/docs/foundations/workflows-and-steps.mdx +7 -0
- package/docs/how-it-works/code-transform.mdx +6 -0
- package/docs/how-it-works/event-sourcing.mdx +6 -0
- package/docs/how-it-works/framework-integrations.mdx +6 -0
- package/docs/how-it-works/understanding-directives.mdx +6 -0
- package/package.json +9 -10
- package/dist/observability.d.ts +0 -84
- package/dist/observability.d.ts.map +0 -1
- package/dist/observability.js +0 -360
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Idempotency
|
|
3
3
|
description: Ensure operations can be safely retried without producing duplicate side effects.
|
|
4
|
+
type: conceptual
|
|
5
|
+
summary: Prevent duplicate side effects when retrying operations in steps.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/foundations/errors-and-retries
|
|
4
10
|
---
|
|
5
11
|
|
|
6
12
|
Idempotency is a property of an operation that ensures it can be safely retried without producing duplicate side effects.
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Foundations
|
|
3
3
|
description: Learn the core concepts of workflow programming to build durable, long-running applications.
|
|
4
|
+
type: overview
|
|
5
|
+
summary: Explore the core concepts you need to use workflows effectively.
|
|
6
|
+
related:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
- /docs/getting-started
|
|
4
9
|
---
|
|
5
10
|
|
|
6
11
|
Workflow programming can be a slight shift from how you traditionally write real-world applications. Learning the foundations now will go a long way toward helping you use workflows effectively.
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Serialization
|
|
3
3
|
description: Understand how workflow data is serialized and persisted across suspensions and resumptions.
|
|
4
|
+
type: conceptual
|
|
5
|
+
summary: Learn which types can be passed between workflow and step functions.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/errors/serialization-failed
|
|
4
10
|
---
|
|
5
11
|
|
|
6
12
|
All function arguments and return values passed between workflow and step functions must be serializable. Workflow DevKit uses a custom serialization system built on top of [devalue](https://github.com/sveltejs/devalue). This system supports standard JSON types, as well as a few additional popular Web API types.
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Starting Workflows
|
|
3
3
|
description: Trigger workflow execution with the start() function and track progress with Run objects.
|
|
4
|
+
type: guide
|
|
5
|
+
summary: Trigger workflows and track their execution using the start() function.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/api-reference/workflow-api/start
|
|
4
10
|
---
|
|
5
11
|
|
|
6
12
|
Once you've defined your workflow functions, you need to trigger them to begin execution. This is done using the `start()` function from `workflow/api`, which enqueues a new workflow run and returns a `Run` object that you can use to track its progress.
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Streaming
|
|
3
3
|
description: Stream data in real-time to clients for progress updates and incremental content delivery.
|
|
4
|
+
type: conceptual
|
|
5
|
+
summary: Stream real-time data to clients without waiting for workflow completion.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/api-reference/workflow/get-writable
|
|
10
|
+
- /docs/ai/resumable-streams
|
|
4
11
|
---
|
|
5
12
|
|
|
6
13
|
Workflows can stream data in real-time to clients without waiting for the entire workflow to complete. This enables progress updates, AI-generated content, log messages, and other incremental data to be delivered as workflows execute.
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Workflows and Steps
|
|
3
3
|
description: Build long-running, stateful application logic that persists progress and resumes after failures.
|
|
4
|
+
type: conceptual
|
|
5
|
+
summary: Understand the two function types that make up a workflow.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations
|
|
8
|
+
related:
|
|
9
|
+
- /docs/how-it-works/understanding-directives
|
|
10
|
+
- /docs/foundations/serialization
|
|
4
11
|
---
|
|
5
12
|
|
|
6
13
|
import { File, Folder, Files } from "fumadocs-ui/components/files";
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: How the Directives Work
|
|
3
3
|
description: Deep dive into the internals of how Workflow DevKit directives transform your code.
|
|
4
|
+
type: conceptual
|
|
5
|
+
summary: Learn how the compiler transforms directive-annotated code into three execution modes.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/how-it-works/understanding-directives
|
|
8
|
+
related:
|
|
9
|
+
- /docs/foundations/workflows-and-steps
|
|
4
10
|
---
|
|
5
11
|
|
|
6
12
|
<Callout>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Event Sourcing
|
|
3
3
|
description: Learn how Workflow DevKit uses event sourcing internally for debugging and observability.
|
|
4
|
+
type: conceptual
|
|
5
|
+
summary: Understand the event log that powers workflow replay and debugging.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/observability
|
|
4
10
|
---
|
|
5
11
|
|
|
6
12
|
<Callout>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Framework Integrations
|
|
3
3
|
description: Guide for framework authors to integrate Workflow DevKit with custom frameworks or runtimes.
|
|
4
|
+
type: guide
|
|
5
|
+
summary: Build a custom framework integration using the Workflow DevKit compiler and runtime.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/deploying/building-a-world
|
|
4
10
|
---
|
|
5
11
|
|
|
6
12
|
<Callout>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Understanding Directives
|
|
3
3
|
description: Explore how JavaScript directives enable the Workflow DevKit's durable execution model.
|
|
4
|
+
type: conceptual
|
|
5
|
+
summary: Explore the design decisions behind "use workflow" and "use step" directives.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/how-it-works/code-transform
|
|
4
10
|
---
|
|
5
11
|
|
|
6
12
|
import { File, Folder, Files } from "fumadocs-ui/components/files";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workflow/core",
|
|
3
|
-
"version": "4.1.0-beta.
|
|
3
|
+
"version": "4.1.0-beta.56",
|
|
4
4
|
"description": "Core runtime and engine for Workflow DevKit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -60,10 +60,9 @@
|
|
|
60
60
|
"types": "./dist/serialization.d.ts",
|
|
61
61
|
"default": "./dist/serialization.js"
|
|
62
62
|
},
|
|
63
|
-
"./
|
|
64
|
-
"types": "./dist/
|
|
65
|
-
"
|
|
66
|
-
"default": "./dist/observability.js"
|
|
63
|
+
"./serialization-format": {
|
|
64
|
+
"types": "./dist/serialization-format.d.ts",
|
|
65
|
+
"default": "./dist/serialization-format.js"
|
|
67
66
|
},
|
|
68
67
|
"./_workflow": "./dist/workflow/index.js"
|
|
69
68
|
},
|
|
@@ -80,12 +79,12 @@
|
|
|
80
79
|
"seedrandom": "3.0.5",
|
|
81
80
|
"ulid": "3.0.1",
|
|
82
81
|
"zod": "4.1.11",
|
|
83
|
-
"@workflow/errors": "4.1.0-beta.
|
|
82
|
+
"@workflow/errors": "4.1.0-beta.15",
|
|
84
83
|
"@workflow/serde": "4.1.0-beta.2",
|
|
85
|
-
"@workflow/utils": "4.1.0-beta.
|
|
86
|
-
"@workflow/world": "4.1.0-beta.
|
|
87
|
-
"@workflow/world-local": "4.1.0-beta.
|
|
88
|
-
"@workflow/world-vercel": "4.1.0-beta.
|
|
84
|
+
"@workflow/utils": "4.1.0-beta.12",
|
|
85
|
+
"@workflow/world": "4.1.0-beta.4",
|
|
86
|
+
"@workflow/world-local": "4.1.0-beta.32",
|
|
87
|
+
"@workflow/world-vercel": "4.1.0-beta.32"
|
|
89
88
|
},
|
|
90
89
|
"devDependencies": {
|
|
91
90
|
"@opentelemetry/api": "1.9.0",
|
package/dist/observability.d.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Observability utilities for workflow inspection.
|
|
3
|
-
* Shared between CLI and Web UI for consistent behavior.
|
|
4
|
-
*/
|
|
5
|
-
import { inspect } from 'node:util';
|
|
6
|
-
/**
|
|
7
|
-
* Marker for stream reference objects that can be rendered as links
|
|
8
|
-
*/
|
|
9
|
-
export declare const STREAM_REF_TYPE = "__workflow_stream_ref__";
|
|
10
|
-
/**
|
|
11
|
-
* A stream reference object that contains the stream ID and can be
|
|
12
|
-
* detected in the UI to render as a clickable link
|
|
13
|
-
*/
|
|
14
|
-
export interface StreamRef {
|
|
15
|
-
__type: typeof STREAM_REF_TYPE;
|
|
16
|
-
streamId: string;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Marker for custom class instance references.
|
|
20
|
-
* Used in observability to represent serialized class instances
|
|
21
|
-
* that cannot be fully deserialized (because the class is not registered).
|
|
22
|
-
*/
|
|
23
|
-
export declare const CLASS_INSTANCE_REF_TYPE = "__workflow_class_instance_ref__";
|
|
24
|
-
/**
|
|
25
|
-
* A class instance reference that contains the class name and serialized data.
|
|
26
|
-
* This is used during o11y hydration when a custom class instance is encountered
|
|
27
|
-
* but the class is not registered for deserialization.
|
|
28
|
-
*
|
|
29
|
-
* Provides a custom `util.inspect.custom` representation for nice CLI output:
|
|
30
|
-
* `Point { x: 1, y: 2 } [class//path/to/file.ts//Point]`
|
|
31
|
-
*/
|
|
32
|
-
export declare class ClassInstanceRef {
|
|
33
|
-
readonly className: string;
|
|
34
|
-
readonly classId: string;
|
|
35
|
-
readonly data: unknown;
|
|
36
|
-
readonly __type = "__workflow_class_instance_ref__";
|
|
37
|
-
constructor(className: string, classId: string, data: unknown);
|
|
38
|
-
/**
|
|
39
|
-
* Custom inspect for Node.js util.inspect (used by console.log, CLI, etc.)
|
|
40
|
-
* Renders as: ClassName@filename { ...data }
|
|
41
|
-
* The @filename portion is styled gray (like undefined in Node.js)
|
|
42
|
-
*/
|
|
43
|
-
[inspect.custom](_depth: number, options: import('node:util').InspectOptionsStylized): string;
|
|
44
|
-
/**
|
|
45
|
-
* For JSON.stringify - returns a plain object representation
|
|
46
|
-
*/
|
|
47
|
-
toJSON(): {
|
|
48
|
-
__type: string;
|
|
49
|
-
className: string;
|
|
50
|
-
classId: string;
|
|
51
|
-
data: unknown;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Check if a value is a ClassInstanceRef object
|
|
56
|
-
*/
|
|
57
|
-
export declare const isClassInstanceRef: (value: unknown) => value is ClassInstanceRef;
|
|
58
|
-
/**
|
|
59
|
-
* Check if a value is a stream ID string
|
|
60
|
-
*/
|
|
61
|
-
export declare const isStreamId: (value: unknown) => boolean;
|
|
62
|
-
/**
|
|
63
|
-
* Check if a value is a StreamRef object
|
|
64
|
-
*/
|
|
65
|
-
export declare const isStreamRef: (value: unknown) => value is StreamRef;
|
|
66
|
-
export declare const hydrateResourceIO: <T extends {
|
|
67
|
-
stepId?: string;
|
|
68
|
-
hookId?: string;
|
|
69
|
-
eventId?: string;
|
|
70
|
-
input?: any;
|
|
71
|
-
output?: any;
|
|
72
|
-
metadata?: any;
|
|
73
|
-
eventData?: any;
|
|
74
|
-
executionContext?: any;
|
|
75
|
-
}>(resource: T) => T;
|
|
76
|
-
/**
|
|
77
|
-
* Extract all stream IDs from a value (recursively traverses objects/arrays)
|
|
78
|
-
*/
|
|
79
|
-
export declare function extractStreamIds(obj: unknown): string[];
|
|
80
|
-
/**
|
|
81
|
-
* Truncate a string to a maximum length, adding ellipsis if needed
|
|
82
|
-
*/
|
|
83
|
-
export declare function truncateId(id: string, maxLength?: number): string;
|
|
84
|
-
//# sourceMappingURL=observability.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../src/observability.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC;;GAEG;AACH,eAAO,MAAM,eAAe,4BAA4B,CAAC;AAEzD;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,OAAO,eAAe,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,oCAAoC,CAAC;AAEzE;;;;;;;GAOG;AACH,qBAAa,gBAAgB;aAIT,SAAS,EAAE,MAAM;aACjB,OAAO,EAAE,MAAM;aACf,IAAI,EAAE,OAAO;IAL/B,QAAQ,CAAC,MAAM,qCAA2B;gBAGxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,OAAO;IAG/B;;;;OAIG;IACH,CAAC,OAAO,CAAC,MAAM,CAAC,CACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,WAAW,EAAE,sBAAsB,GAClD,MAAM;IAaT;;OAEG;IACH,MAAM,IAAI;QACR,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,OAAO,CAAC;KACf;CAQF;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,OAAO,KACb,KAAK,IAAI,gBAUX,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,OAE3C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,SASrD,CAAC;AAyQF,eAAO,MAAM,iBAAiB,GAC5B,CAAC,SAAS;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,gBAAgB,CAAC,EAAE,GAAG,CAAC;CACxB,EAED,UAAU,CAAC,KACV,CA6BF,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CAmBvD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,SAAK,GAAG,MAAM,CAG7D"}
|
package/dist/observability.js
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Observability utilities for workflow inspection.
|
|
3
|
-
* Shared between CLI and Web UI for consistent behavior.
|
|
4
|
-
*/
|
|
5
|
-
import { inspect } from 'node:util';
|
|
6
|
-
import { parseClassName } from '@workflow/utils/parse-name';
|
|
7
|
-
import { unflatten } from 'devalue';
|
|
8
|
-
import { runtimeLogger } from './logger.js';
|
|
9
|
-
import { getCommonRevivers, hydrateStepArguments, hydrateStepReturnValue, hydrateWorkflowArguments, hydrateWorkflowReturnValue, } from './serialization.js';
|
|
10
|
-
const STREAM_ID_PREFIX = 'strm_';
|
|
11
|
-
/**
|
|
12
|
-
* Marker for stream reference objects that can be rendered as links
|
|
13
|
-
*/
|
|
14
|
-
export const STREAM_REF_TYPE = '__workflow_stream_ref__';
|
|
15
|
-
/**
|
|
16
|
-
* Marker for custom class instance references.
|
|
17
|
-
* Used in observability to represent serialized class instances
|
|
18
|
-
* that cannot be fully deserialized (because the class is not registered).
|
|
19
|
-
*/
|
|
20
|
-
export const CLASS_INSTANCE_REF_TYPE = '__workflow_class_instance_ref__';
|
|
21
|
-
/**
|
|
22
|
-
* A class instance reference that contains the class name and serialized data.
|
|
23
|
-
* This is used during o11y hydration when a custom class instance is encountered
|
|
24
|
-
* but the class is not registered for deserialization.
|
|
25
|
-
*
|
|
26
|
-
* Provides a custom `util.inspect.custom` representation for nice CLI output:
|
|
27
|
-
* `Point { x: 1, y: 2 } [class//path/to/file.ts//Point]`
|
|
28
|
-
*/
|
|
29
|
-
export class ClassInstanceRef {
|
|
30
|
-
className;
|
|
31
|
-
classId;
|
|
32
|
-
data;
|
|
33
|
-
__type = CLASS_INSTANCE_REF_TYPE;
|
|
34
|
-
constructor(className, classId, data) {
|
|
35
|
-
this.className = className;
|
|
36
|
-
this.classId = classId;
|
|
37
|
-
this.data = data;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Custom inspect for Node.js util.inspect (used by console.log, CLI, etc.)
|
|
41
|
-
* Renders as: ClassName@filename { ...data }
|
|
42
|
-
* The @filename portion is styled gray (like undefined in Node.js)
|
|
43
|
-
*/
|
|
44
|
-
[inspect.custom](_depth, options) {
|
|
45
|
-
const dataStr = inspect(this.data, { ...options, depth: options.depth });
|
|
46
|
-
const parsed = parseClassName(this.classId);
|
|
47
|
-
const moduleSpecifier = parsed?.moduleSpecifier ?? this.classId;
|
|
48
|
-
// Extract just the module name from the specifier
|
|
49
|
-
const fileName = moduleSpecifier.split('/').pop() ?? moduleSpecifier;
|
|
50
|
-
// Style the @filename portion gray using the 'undefined' style
|
|
51
|
-
const styledFileName = options.stylize
|
|
52
|
-
? options.stylize(`@${fileName}`, 'undefined')
|
|
53
|
-
: `@${fileName}`;
|
|
54
|
-
return `${this.className}${styledFileName} ${dataStr}`;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* For JSON.stringify - returns a plain object representation
|
|
58
|
-
*/
|
|
59
|
-
toJSON() {
|
|
60
|
-
return {
|
|
61
|
-
__type: this.__type,
|
|
62
|
-
className: this.className,
|
|
63
|
-
classId: this.classId,
|
|
64
|
-
data: this.data,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Check if a value is a ClassInstanceRef object
|
|
70
|
-
*/
|
|
71
|
-
export const isClassInstanceRef = (value) => {
|
|
72
|
-
return (value instanceof ClassInstanceRef ||
|
|
73
|
-
(value !== null &&
|
|
74
|
-
typeof value === 'object' &&
|
|
75
|
-
'__type' in value &&
|
|
76
|
-
value.__type === CLASS_INSTANCE_REF_TYPE &&
|
|
77
|
-
'className' in value &&
|
|
78
|
-
typeof value.className === 'string'));
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* Check if a value is a stream ID string
|
|
82
|
-
*/
|
|
83
|
-
export const isStreamId = (value) => {
|
|
84
|
-
return typeof value === 'string' && value.startsWith(STREAM_ID_PREFIX);
|
|
85
|
-
};
|
|
86
|
-
/**
|
|
87
|
-
* Check if a value is a StreamRef object
|
|
88
|
-
*/
|
|
89
|
-
export const isStreamRef = (value) => {
|
|
90
|
-
return (value !== null &&
|
|
91
|
-
typeof value === 'object' &&
|
|
92
|
-
'__type' in value &&
|
|
93
|
-
value.__type === STREAM_REF_TYPE &&
|
|
94
|
-
'streamId' in value &&
|
|
95
|
-
typeof value.streamId === 'string');
|
|
96
|
-
};
|
|
97
|
-
/**
|
|
98
|
-
* Create a StreamRef object from a stream value.
|
|
99
|
-
* This is used during hydration to convert serialized streams into
|
|
100
|
-
* objects that can be rendered as links in the UI.
|
|
101
|
-
*/
|
|
102
|
-
const streamToStreamRef = (value) => {
|
|
103
|
-
let streamId;
|
|
104
|
-
if ('name' in value) {
|
|
105
|
-
const name = String(value.name);
|
|
106
|
-
if (!name.startsWith(STREAM_ID_PREFIX)) {
|
|
107
|
-
streamId = `${STREAM_ID_PREFIX}${name}`;
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
streamId = name;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
streamId = `${STREAM_ID_PREFIX}null`;
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
__type: STREAM_REF_TYPE,
|
|
118
|
-
streamId,
|
|
119
|
-
};
|
|
120
|
-
};
|
|
121
|
-
const serializedStepFunctionToString = (value) => {
|
|
122
|
-
if (!value)
|
|
123
|
-
return 'null';
|
|
124
|
-
if (typeof value !== 'object')
|
|
125
|
-
return 'null';
|
|
126
|
-
if ('stepId' in value) {
|
|
127
|
-
const stepId = value.stepId;
|
|
128
|
-
// TODO: Add closure vars to the string representation.
|
|
129
|
-
// value.closureVars
|
|
130
|
-
return `<step:${stepId}>`;
|
|
131
|
-
}
|
|
132
|
-
return '<function>';
|
|
133
|
-
};
|
|
134
|
-
/**
|
|
135
|
-
* Extract the class name from a classId.
|
|
136
|
-
* The classId format is typically "path/to/file/ClassName" so we extract the last segment.
|
|
137
|
-
*/
|
|
138
|
-
const extractClassName = (classId) => {
|
|
139
|
-
if (!classId)
|
|
140
|
-
return 'Unknown';
|
|
141
|
-
const parts = classId.split('/');
|
|
142
|
-
return parts[parts.length - 1] || classId;
|
|
143
|
-
};
|
|
144
|
-
/**
|
|
145
|
-
* Convert a serialized class instance to a ClassInstanceRef for o11y display.
|
|
146
|
-
* This allows viewing custom class instances in the UI without needing
|
|
147
|
-
* the class to be registered for deserialization.
|
|
148
|
-
*/
|
|
149
|
-
const serializedInstanceToRef = (value) => {
|
|
150
|
-
return new ClassInstanceRef(extractClassName(value.classId), value.classId, value.data);
|
|
151
|
-
};
|
|
152
|
-
/**
|
|
153
|
-
* Convert a serialized class reference to a string representation.
|
|
154
|
-
* This is used for Class type (the constructor reference itself, not an instance).
|
|
155
|
-
*/
|
|
156
|
-
const serializedClassToString = (value) => {
|
|
157
|
-
const className = extractClassName(value.classId);
|
|
158
|
-
return `<class:${className}>`;
|
|
159
|
-
};
|
|
160
|
-
/**
|
|
161
|
-
* This is an extra reviver for devalue that takes any streams that would be converted,
|
|
162
|
-
* into actual streams, and instead formats them as StreamRef objects for display in the UI.
|
|
163
|
-
*
|
|
164
|
-
* This is mainly because we don't want to open any streams that we aren't going to read from,
|
|
165
|
-
* and so we can get the string ID/name, which the serializer stream doesn't provide.
|
|
166
|
-
*
|
|
167
|
-
* Also handles custom class instances (Instance) and class references (Class) by converting
|
|
168
|
-
* them to opaque markers, since the custom classes are not registered for deserialization
|
|
169
|
-
* in the o11y context.
|
|
170
|
-
*/
|
|
171
|
-
const streamPrintRevivers = {
|
|
172
|
-
ReadableStream: streamToStreamRef,
|
|
173
|
-
WritableStream: streamToStreamRef,
|
|
174
|
-
TransformStream: streamToStreamRef,
|
|
175
|
-
StepFunction: serializedStepFunctionToString,
|
|
176
|
-
Instance: serializedInstanceToRef,
|
|
177
|
-
Class: serializedClassToString,
|
|
178
|
-
};
|
|
179
|
-
/**
|
|
180
|
-
* Combined revivers for observability hydration.
|
|
181
|
-
* Merges common revivers with stream print revivers.
|
|
182
|
-
*/
|
|
183
|
-
const getObservabilityRevivers = () => ({
|
|
184
|
-
...getCommonRevivers(globalThis),
|
|
185
|
-
...streamPrintRevivers,
|
|
186
|
-
});
|
|
187
|
-
/**
|
|
188
|
-
* Check if data is in legacy format (devalue parsed array).
|
|
189
|
-
* Legacy specVersion 1 runs stored data as JSON arrays from devalue.
|
|
190
|
-
*/
|
|
191
|
-
const isLegacyFormat = (data) => {
|
|
192
|
-
return Array.isArray(data);
|
|
193
|
-
};
|
|
194
|
-
/**
|
|
195
|
-
* Check if data is in binary format (Uint8Array).
|
|
196
|
-
* specVersion 2+ runs store data as binary Uint8Array with a format prefix.
|
|
197
|
-
*/
|
|
198
|
-
const isBinaryFormat = (data) => {
|
|
199
|
-
return data instanceof Uint8Array;
|
|
200
|
-
};
|
|
201
|
-
/**
|
|
202
|
-
* Hydrate legacy format data (array) using unflatten.
|
|
203
|
-
*/
|
|
204
|
-
const hydrateLegacyData = (data) => {
|
|
205
|
-
return unflatten(data, getObservabilityRevivers());
|
|
206
|
-
};
|
|
207
|
-
const hydrateStepIO = (step) => {
|
|
208
|
-
let hydratedInput = step.input;
|
|
209
|
-
let hydratedOutput = step.output;
|
|
210
|
-
// Hydrate input - handle both binary (specVersion 2) and legacy (specVersion 1) formats
|
|
211
|
-
if (isBinaryFormat(step.input) && step.input.byteLength > 0) {
|
|
212
|
-
hydratedInput = hydrateStepArguments(step.input, [], step.runId, globalThis, streamPrintRevivers);
|
|
213
|
-
}
|
|
214
|
-
else if (isLegacyFormat(step.input) && step.input.length > 0) {
|
|
215
|
-
hydratedInput = hydrateLegacyData(step.input);
|
|
216
|
-
}
|
|
217
|
-
// Hydrate output - handle both binary (specVersion 2) and legacy (specVersion 1) formats
|
|
218
|
-
if (isBinaryFormat(step.output)) {
|
|
219
|
-
hydratedOutput = hydrateStepReturnValue(step.output, globalThis, streamPrintRevivers);
|
|
220
|
-
}
|
|
221
|
-
else if (isLegacyFormat(step.output) && step.output.length > 0) {
|
|
222
|
-
hydratedOutput = hydrateLegacyData(step.output);
|
|
223
|
-
}
|
|
224
|
-
return {
|
|
225
|
-
...step,
|
|
226
|
-
input: hydratedInput,
|
|
227
|
-
output: hydratedOutput,
|
|
228
|
-
};
|
|
229
|
-
};
|
|
230
|
-
const hydrateWorkflowIO = (workflow) => {
|
|
231
|
-
let hydratedInput = workflow.input;
|
|
232
|
-
let hydratedOutput = workflow.output;
|
|
233
|
-
// Hydrate input - handle both binary (specVersion 2) and legacy (specVersion 1) formats
|
|
234
|
-
if (isBinaryFormat(workflow.input) && workflow.input.byteLength > 0) {
|
|
235
|
-
hydratedInput = hydrateWorkflowArguments(workflow.input, globalThis, streamPrintRevivers);
|
|
236
|
-
}
|
|
237
|
-
else if (isLegacyFormat(workflow.input) && workflow.input.length > 0) {
|
|
238
|
-
hydratedInput = hydrateLegacyData(workflow.input);
|
|
239
|
-
}
|
|
240
|
-
// Hydrate output - handle both binary (specVersion 2) and legacy (specVersion 1) formats
|
|
241
|
-
if (isBinaryFormat(workflow.output)) {
|
|
242
|
-
hydratedOutput = hydrateWorkflowReturnValue(workflow.output, [], workflow.runId, globalThis, streamPrintRevivers);
|
|
243
|
-
}
|
|
244
|
-
else if (isLegacyFormat(workflow.output) && workflow.output.length > 0) {
|
|
245
|
-
hydratedOutput = hydrateLegacyData(workflow.output);
|
|
246
|
-
}
|
|
247
|
-
return {
|
|
248
|
-
...workflow,
|
|
249
|
-
input: hydratedInput,
|
|
250
|
-
output: hydratedOutput,
|
|
251
|
-
};
|
|
252
|
-
};
|
|
253
|
-
const hydrateEventData = (event) => {
|
|
254
|
-
if (!event.eventData) {
|
|
255
|
-
return event;
|
|
256
|
-
}
|
|
257
|
-
const eventData = { ...event.eventData };
|
|
258
|
-
// Events can have various eventData with non-devalued keys.
|
|
259
|
-
// So far, only eventData.result is devalued (though this may change),
|
|
260
|
-
// so we need to hydrate it specifically.
|
|
261
|
-
try {
|
|
262
|
-
if ('result' in eventData && typeof eventData.result === 'object') {
|
|
263
|
-
// Handle both binary (specVersion 2) and legacy (specVersion 1) formats
|
|
264
|
-
if (isBinaryFormat(eventData.result)) {
|
|
265
|
-
eventData.result = hydrateStepReturnValue(eventData.result, globalThis, streamPrintRevivers);
|
|
266
|
-
}
|
|
267
|
-
else if (isLegacyFormat(eventData.result) &&
|
|
268
|
-
eventData.result.length > 0) {
|
|
269
|
-
eventData.result = hydrateLegacyData(eventData.result);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
catch (error) {
|
|
274
|
-
runtimeLogger.error('Error hydrating event data', { error });
|
|
275
|
-
}
|
|
276
|
-
return {
|
|
277
|
-
...event,
|
|
278
|
-
eventData,
|
|
279
|
-
};
|
|
280
|
-
};
|
|
281
|
-
const hydrateHookMetadata = (hook) => {
|
|
282
|
-
let hydratedMetadata = hook.metadata;
|
|
283
|
-
if (hook.metadata && 'runId' in hook) {
|
|
284
|
-
// Handle both binary (specVersion 2) and legacy (specVersion 1) formats
|
|
285
|
-
if (isBinaryFormat(hook.metadata)) {
|
|
286
|
-
hydratedMetadata = hydrateStepArguments(hook.metadata, [], hook.runId, globalThis, streamPrintRevivers);
|
|
287
|
-
}
|
|
288
|
-
else if (isLegacyFormat(hook.metadata) && hook.metadata.length > 0) {
|
|
289
|
-
hydratedMetadata = hydrateLegacyData(hook.metadata);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return {
|
|
293
|
-
...hook,
|
|
294
|
-
metadata: hydratedMetadata,
|
|
295
|
-
};
|
|
296
|
-
};
|
|
297
|
-
export const hydrateResourceIO = (resource) => {
|
|
298
|
-
if (!resource) {
|
|
299
|
-
return resource;
|
|
300
|
-
}
|
|
301
|
-
let hydrated;
|
|
302
|
-
if ('stepId' in resource) {
|
|
303
|
-
hydrated = hydrateStepIO(resource);
|
|
304
|
-
}
|
|
305
|
-
else if ('hookId' in resource) {
|
|
306
|
-
hydrated = hydrateHookMetadata(resource);
|
|
307
|
-
}
|
|
308
|
-
else if ('eventId' in resource) {
|
|
309
|
-
hydrated = hydrateEventData(resource);
|
|
310
|
-
}
|
|
311
|
-
else {
|
|
312
|
-
hydrated = hydrateWorkflowIO(resource);
|
|
313
|
-
}
|
|
314
|
-
if ('executionContext' in hydrated) {
|
|
315
|
-
const { executionContext, ...rest } = hydrated;
|
|
316
|
-
// Preserve workflowCoreVersion from executionContext for observability
|
|
317
|
-
const workflowCoreVersion = executionContext &&
|
|
318
|
-
typeof executionContext === 'object' &&
|
|
319
|
-
'workflowCoreVersion' in executionContext
|
|
320
|
-
? executionContext.workflowCoreVersion
|
|
321
|
-
: undefined;
|
|
322
|
-
if (workflowCoreVersion) {
|
|
323
|
-
return { ...rest, workflowCoreVersion };
|
|
324
|
-
}
|
|
325
|
-
return rest;
|
|
326
|
-
}
|
|
327
|
-
return hydrated;
|
|
328
|
-
};
|
|
329
|
-
/**
|
|
330
|
-
* Extract all stream IDs from a value (recursively traverses objects/arrays)
|
|
331
|
-
*/
|
|
332
|
-
export function extractStreamIds(obj) {
|
|
333
|
-
const streamIds = [];
|
|
334
|
-
function traverse(value) {
|
|
335
|
-
if (isStreamId(value)) {
|
|
336
|
-
streamIds.push(value);
|
|
337
|
-
}
|
|
338
|
-
else if (Array.isArray(value)) {
|
|
339
|
-
for (const item of value) {
|
|
340
|
-
traverse(item);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
else if (value && typeof value === 'object') {
|
|
344
|
-
for (const val of Object.values(value)) {
|
|
345
|
-
traverse(val);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
traverse(obj);
|
|
350
|
-
return Array.from(new Set(streamIds)); // Remove duplicates
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Truncate a string to a maximum length, adding ellipsis if needed
|
|
354
|
-
*/
|
|
355
|
-
export function truncateId(id, maxLength = 12) {
|
|
356
|
-
if (id.length <= maxLength)
|
|
357
|
-
return id;
|
|
358
|
-
return `${id.slice(0, maxLength)}...`;
|
|
359
|
-
}
|
|
360
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JzZXJ2YWJpbGl0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9vYnNlcnZhYmlsaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDcEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDcEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLG9CQUFvQixFQUNwQixzQkFBc0IsRUFDdEIsd0JBQXdCLEVBQ3hCLDBCQUEwQixHQUMzQixNQUFNLG9CQUFvQixDQUFDO0FBRTVCLE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDO0FBRWpDOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLHlCQUF5QixDQUFDO0FBV3pEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxpQ0FBaUMsQ0FBQztBQUV6RTs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQUlUO0lBQ0E7SUFDQTtJQUxULE1BQU0sR0FBRyx1QkFBdUIsQ0FBQztJQUUxQyxZQUNrQixTQUFpQixFQUNqQixPQUFlLEVBQ2YsSUFBYTtRQUZiLGNBQVMsR0FBVCxTQUFTLENBQVE7UUFDakIsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUNmLFNBQUksR0FBSixJQUFJLENBQVM7SUFDNUIsQ0FBQztJQUVKOzs7O09BSUc7SUFDSCxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FDZCxNQUFjLEVBQ2QsT0FBbUQ7UUFFbkQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLEtB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
|