@workflow/core 4.0.1-beta.9 → 4.1.0-beta.52
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/builtins.js +1 -1
- package/dist/class-serialization.d.ts +26 -0
- package/dist/class-serialization.d.ts.map +1 -0
- package/dist/class-serialization.js +66 -0
- package/dist/create-hook.js +1 -1
- package/dist/define-hook.d.ts +40 -25
- package/dist/define-hook.d.ts.map +1 -1
- package/dist/define-hook.js +22 -27
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +5 -1
- package/dist/flushable-stream.d.ts +82 -0
- package/dist/flushable-stream.d.ts.map +1 -0
- package/dist/flushable-stream.js +214 -0
- package/dist/global.d.ts +4 -1
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +21 -9
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/logger.js +1 -1
- package/dist/observability.d.ts +60 -0
- package/dist/observability.d.ts.map +1 -1
- package/dist/observability.js +265 -32
- package/dist/private.d.ts +10 -1
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +6 -1
- package/dist/runtime/helpers.d.ts +52 -0
- package/dist/runtime/helpers.d.ts.map +1 -0
- package/dist/runtime/helpers.js +264 -0
- package/dist/runtime/resume-hook.d.ts +17 -12
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +79 -64
- package/dist/runtime/run.d.ts +100 -0
- package/dist/runtime/run.d.ts.map +1 -0
- package/dist/runtime/run.js +132 -0
- package/dist/runtime/start.d.ts +15 -1
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +72 -46
- package/dist/runtime/step-handler.d.ts +7 -0
- package/dist/runtime/step-handler.d.ts.map +1 -0
- package/dist/runtime/step-handler.js +337 -0
- package/dist/runtime/suspension-handler.d.ts +25 -0
- package/dist/runtime/suspension-handler.d.ts.map +1 -0
- package/dist/runtime/suspension-handler.js +182 -0
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +20 -21
- package/dist/runtime.d.ts +4 -105
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +97 -531
- package/dist/schemas.d.ts +1 -15
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +2 -15
- package/dist/serialization.d.ts +112 -21
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +469 -85
- package/dist/sleep.d.ts +10 -0
- package/dist/sleep.d.ts.map +1 -1
- package/dist/sleep.js +1 -1
- package/dist/source-map.d.ts +10 -0
- package/dist/source-map.d.ts.map +1 -0
- package/dist/source-map.js +56 -0
- package/dist/step/context-storage.d.ts +2 -1
- package/dist/step/context-storage.d.ts.map +1 -1
- package/dist/step/context-storage.js +1 -1
- package/dist/step/get-closure-vars.d.ts +9 -0
- package/dist/step/get-closure-vars.d.ts.map +1 -0
- package/dist/step/get-closure-vars.js +16 -0
- package/dist/step/get-step-metadata.js +1 -1
- package/dist/step/get-workflow-metadata.js +1 -1
- package/dist/step/writable-stream.d.ts +10 -2
- package/dist/step/writable-stream.d.ts.map +1 -1
- package/dist/step/writable-stream.js +6 -5
- package/dist/step.d.ts +1 -1
- package/dist/step.d.ts.map +1 -1
- package/dist/step.js +93 -47
- package/dist/symbols.d.ts +6 -0
- package/dist/symbols.d.ts.map +1 -1
- package/dist/symbols.js +7 -1
- package/dist/telemetry/semantic-conventions.d.ts +66 -38
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +16 -3
- package/dist/telemetry.d.ts +8 -4
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +39 -6
- package/dist/types.js +1 -1
- package/dist/util.d.ts +5 -24
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +19 -38
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/vm/index.js +2 -2
- package/dist/vm/uuid.js +1 -1
- package/dist/workflow/create-hook.js +1 -1
- package/dist/workflow/define-hook.d.ts +3 -3
- package/dist/workflow/define-hook.d.ts.map +1 -1
- package/dist/workflow/define-hook.js +1 -1
- package/dist/workflow/get-workflow-metadata.js +1 -1
- package/dist/workflow/hook.d.ts.map +1 -1
- package/dist/workflow/hook.js +49 -14
- package/dist/workflow/index.d.ts +1 -1
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +2 -2
- package/dist/workflow/sleep.d.ts +1 -1
- package/dist/workflow/sleep.d.ts.map +1 -1
- package/dist/workflow/sleep.js +26 -39
- package/dist/workflow/writable-stream.d.ts +1 -1
- package/dist/workflow/writable-stream.d.ts.map +1 -1
- package/dist/workflow/writable-stream.js +1 -1
- package/dist/workflow.d.ts +1 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +72 -9
- package/docs/api-reference/create-hook.mdx +134 -0
- package/docs/api-reference/create-webhook.mdx +226 -0
- package/docs/api-reference/define-hook.mdx +207 -0
- package/docs/api-reference/fatal-error.mdx +38 -0
- package/docs/api-reference/fetch.mdx +140 -0
- package/docs/api-reference/get-step-metadata.mdx +77 -0
- package/docs/api-reference/get-workflow-metadata.mdx +45 -0
- package/docs/api-reference/get-writable.mdx +292 -0
- package/docs/api-reference/index.mdx +56 -0
- package/docs/api-reference/meta.json +3 -0
- package/docs/api-reference/retryable-error.mdx +107 -0
- package/docs/api-reference/sleep.mdx +60 -0
- package/docs/foundations/common-patterns.mdx +254 -0
- package/docs/foundations/errors-and-retries.mdx +191 -0
- package/docs/foundations/hooks.mdx +456 -0
- package/docs/foundations/idempotency.mdx +56 -0
- package/docs/foundations/index.mdx +33 -0
- package/docs/foundations/meta.json +14 -0
- package/docs/foundations/serialization.mdx +158 -0
- package/docs/foundations/starting-workflows.mdx +212 -0
- package/docs/foundations/streaming.mdx +570 -0
- package/docs/foundations/workflows-and-steps.mdx +198 -0
- package/docs/how-it-works/code-transform.mdx +335 -0
- package/docs/how-it-works/event-sourcing.mdx +255 -0
- package/docs/how-it-works/framework-integrations.mdx +438 -0
- package/docs/how-it-works/meta.json +10 -0
- package/docs/how-it-works/understanding-directives.mdx +612 -0
- package/package.json +31 -25
- package/dist/builtins.js.map +0 -1
- package/dist/create-hook.js.map +0 -1
- package/dist/define-hook.js.map +0 -1
- package/dist/events-consumer.js.map +0 -1
- package/dist/global.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/observability.js.map +0 -1
- package/dist/parse-name.d.ts +0 -25
- package/dist/parse-name.d.ts.map +0 -1
- package/dist/parse-name.js +0 -40
- package/dist/parse-name.js.map +0 -1
- package/dist/private.js.map +0 -1
- package/dist/runtime/resume-hook.js.map +0 -1
- package/dist/runtime/start.js.map +0 -1
- package/dist/runtime/world.js.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/schemas.js.map +0 -1
- package/dist/serialization.js.map +0 -1
- package/dist/sleep.js.map +0 -1
- package/dist/step/context-storage.js.map +0 -1
- package/dist/step/get-step-metadata.js.map +0 -1
- package/dist/step/get-workflow-metadata.js.map +0 -1
- package/dist/step/writable-stream.js.map +0 -1
- package/dist/step.js.map +0 -1
- package/dist/symbols.js.map +0 -1
- package/dist/telemetry/semantic-conventions.js.map +0 -1
- package/dist/telemetry.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/util.js.map +0 -1
- package/dist/vm/index.js.map +0 -1
- package/dist/vm/uuid.js.map +0 -1
- package/dist/workflow/create-hook.js.map +0 -1
- package/dist/workflow/define-hook.js.map +0 -1
- package/dist/workflow/get-workflow-metadata.js.map +0 -1
- package/dist/workflow/hook.js.map +0 -1
- package/dist/workflow/index.js.map +0 -1
- package/dist/workflow/sleep.js.map +0 -1
- package/dist/workflow/writable-stream.js.map +0 -1
- package/dist/workflow.js.map +0 -1
- package/dist/writable-stream.d.ts +0 -23
- package/dist/writable-stream.d.ts.map +0 -1
- package/dist/writable-stream.js +0 -17
- package/dist/writable-stream.js.map +0 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Serialization
|
|
3
|
+
description: Understand how workflow data is serialized and persisted across suspensions and resumptions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
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.
|
|
7
|
+
|
|
8
|
+
<Callout type="info">
|
|
9
|
+
The serialization system ensures that all data persists correctly across workflow suspensions and resumptions, enabling durable execution.
|
|
10
|
+
</Callout>
|
|
11
|
+
|
|
12
|
+
## Supported Serializable Types
|
|
13
|
+
|
|
14
|
+
The following types can be serialized and passed through workflow functions:
|
|
15
|
+
|
|
16
|
+
**Standard JSON Types:**
|
|
17
|
+
|
|
18
|
+
- `string`
|
|
19
|
+
- `number`
|
|
20
|
+
- `boolean`
|
|
21
|
+
- `null`
|
|
22
|
+
- Arrays of serializable values
|
|
23
|
+
- Objects with string keys and serializable values
|
|
24
|
+
|
|
25
|
+
**Extended Types:**
|
|
26
|
+
|
|
27
|
+
- `undefined`
|
|
28
|
+
- `bigint`
|
|
29
|
+
- `ArrayBuffer`
|
|
30
|
+
- `BigInt64Array`, `BigUint64Array`
|
|
31
|
+
- `Date`
|
|
32
|
+
- `Float32Array`, `Float64Array`
|
|
33
|
+
- `Int8Array`, `Int16Array`, `Int32Array`
|
|
34
|
+
- `Map<Serializable, Serializable>`
|
|
35
|
+
- `RegExp`
|
|
36
|
+
- `Set<Serializable>`
|
|
37
|
+
- `URL`
|
|
38
|
+
- `URLSearchParams`
|
|
39
|
+
- `Uint8Array`, `Uint8ClampedArray`, `Uint16Array`, `Uint32Array`
|
|
40
|
+
|
|
41
|
+
**Notable:**
|
|
42
|
+
|
|
43
|
+
<Callout type="info">
|
|
44
|
+
These types have special handling and are explained in detail in the sections below.
|
|
45
|
+
</Callout>
|
|
46
|
+
|
|
47
|
+
- `Headers`
|
|
48
|
+
- `Request`
|
|
49
|
+
- `Response`
|
|
50
|
+
- `ReadableStream<Serializable>`
|
|
51
|
+
- `WritableStream<Serializable>`
|
|
52
|
+
|
|
53
|
+
## Streaming
|
|
54
|
+
|
|
55
|
+
`ReadableStream` and `WritableStream` are supported as serializable types with special handling. These streams can be passed between workflow and step functions while maintaining their streaming capabilities.
|
|
56
|
+
|
|
57
|
+
For complete information about using streams in workflows, including patterns for AI streaming, file processing, and progress updates, see the [Streaming Guide](/docs/foundations/streaming).
|
|
58
|
+
|
|
59
|
+
## Request & Response
|
|
60
|
+
|
|
61
|
+
The Web API [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) APIs are supported by the serialization system,
|
|
62
|
+
and can be passed around between workflow and step functions similarly to other data types.
|
|
63
|
+
|
|
64
|
+
As a convenience, these two APIs are treated slightly differently when used
|
|
65
|
+
within a workflow function: calling the `text()` / `json()` / `arrayBuffer()` instance
|
|
66
|
+
methods is automatically treated as a step function invocation. This allows you to consume
|
|
67
|
+
the body directly in the workflow context while maintaining proper serialization and caching.
|
|
68
|
+
|
|
69
|
+
For example, consider how receiving a webhook request provides the entire `Request`
|
|
70
|
+
instance into the workflow context. You may consume the body of that request directly
|
|
71
|
+
in the workflow, which will be cached as a step result for future resumptions of the workflow:
|
|
72
|
+
|
|
73
|
+
```typescript title="workflows/webhook.ts" lineNumbers
|
|
74
|
+
import { createWebhook } from "workflow";
|
|
75
|
+
|
|
76
|
+
export async function handleWebhookWorkflow() {
|
|
77
|
+
"use workflow";
|
|
78
|
+
|
|
79
|
+
const webhook = createWebhook();
|
|
80
|
+
const request = await webhook;
|
|
81
|
+
|
|
82
|
+
// The body of the request will only be consumed once // [!code highlight]
|
|
83
|
+
const body = await request.json(); // [!code highlight]
|
|
84
|
+
|
|
85
|
+
// …
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Using `fetch` in Workflows
|
|
90
|
+
|
|
91
|
+
Because `Request` and `Response` are serializable, Workflow DevKit provides a `fetch` function that can be used directly in workflow functions:
|
|
92
|
+
|
|
93
|
+
```typescript title="workflows/api-call.ts" lineNumbers
|
|
94
|
+
import { fetch } from "workflow"; // [!code highlight]
|
|
95
|
+
|
|
96
|
+
export async function apiWorkflow() {
|
|
97
|
+
"use workflow";
|
|
98
|
+
|
|
99
|
+
// fetch can be called directly in workflows // [!code highlight]
|
|
100
|
+
const response = await fetch("https://api.example.com/data"); // [!code highlight]
|
|
101
|
+
const data = await response.json();
|
|
102
|
+
|
|
103
|
+
return data;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The implementation is straightforward - `fetch` from workflow is a step function that wraps the standard `fetch`:
|
|
108
|
+
|
|
109
|
+
```typescript title="Implementation" lineNumbers
|
|
110
|
+
export async function fetch(...args: Parameters<typeof globalThis.fetch>) {
|
|
111
|
+
"use step";
|
|
112
|
+
return globalThis.fetch(...args);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This allows you to make HTTP requests directly in workflow functions while maintaining deterministic replay behavior through automatic caching.
|
|
117
|
+
|
|
118
|
+
## Pass-by-Value Semantics
|
|
119
|
+
|
|
120
|
+
**Parameters are passed by value, not by reference.** Steps receive deserialized copies of data. Mutations inside a step won't affect the original in the workflow.
|
|
121
|
+
|
|
122
|
+
**Incorrect:**
|
|
123
|
+
|
|
124
|
+
```typescript title="workflows/incorrect-mutation.ts" lineNumbers
|
|
125
|
+
export async function updateUserWorkflow(userId: string) {
|
|
126
|
+
"use workflow";
|
|
127
|
+
|
|
128
|
+
let user = { id: userId, name: "John", email: "john@example.com" };
|
|
129
|
+
await updateUserStep(user);
|
|
130
|
+
|
|
131
|
+
// user.email is still "john@example.com" // [!code highlight]
|
|
132
|
+
console.log(user.email); // [!code highlight]
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function updateUserStep(user: { id: string; name: string; email: string }) {
|
|
136
|
+
"use step";
|
|
137
|
+
user.email = "newemail@example.com"; // Changes are lost // [!code highlight]
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Correct - return the modified data:**
|
|
142
|
+
|
|
143
|
+
```typescript title="workflows/correct-mutation.ts" lineNumbers
|
|
144
|
+
export async function updateUserWorkflow(userId: string) {
|
|
145
|
+
"use workflow";
|
|
146
|
+
|
|
147
|
+
let user = { id: userId, name: "John", email: "john@example.com" };
|
|
148
|
+
user = await updateUserStep(user); // Reassign the return value // [!code highlight]
|
|
149
|
+
|
|
150
|
+
console.log(user.email); // "newemail@example.com"
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function updateUserStep(user: { id: string; name: string; email: string }) {
|
|
154
|
+
"use step";
|
|
155
|
+
user.email = "newemail@example.com";
|
|
156
|
+
return user; // [!code highlight]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Starting Workflows
|
|
3
|
+
description: Trigger workflow execution with the start() function and track progress with Run objects.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
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.
|
|
7
|
+
|
|
8
|
+
## The `start()` Function
|
|
9
|
+
|
|
10
|
+
The [`start()`](/docs/api-reference/workflow-api/start) function is used to programmatically trigger workflow executions from runtime contexts like API routes, Server Actions, or any server-side code.
|
|
11
|
+
|
|
12
|
+
```typescript lineNumbers
|
|
13
|
+
import { start } from "workflow/api";
|
|
14
|
+
import { handleUserSignup } from "./workflows/user-signup";
|
|
15
|
+
|
|
16
|
+
export async function POST(request: Request) {
|
|
17
|
+
const { email } = await request.json();
|
|
18
|
+
|
|
19
|
+
// Start the workflow
|
|
20
|
+
const run = await start(handleUserSignup, [email]); // [!code highlight]
|
|
21
|
+
|
|
22
|
+
return Response.json({
|
|
23
|
+
message: "Workflow started",
|
|
24
|
+
runId: run.runId
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Key Points:**
|
|
30
|
+
|
|
31
|
+
- `start()` returns immediately after enqueuing the workflow - it doesn't wait for completion
|
|
32
|
+
- The first argument is your workflow function
|
|
33
|
+
- The second argument is an array of arguments to pass to the workflow (optional if the workflow takes no arguments)
|
|
34
|
+
- All arguments must be [serializable](/docs/foundations/serialization)
|
|
35
|
+
|
|
36
|
+
**Learn more**: [`start()` API Reference](/docs/api-reference/workflow-api/start)
|
|
37
|
+
|
|
38
|
+
## The `Run` Object
|
|
39
|
+
|
|
40
|
+
When you call `start()`, it returns a [`Run`](/docs/api-reference/workflow-api/start#returns) object that provides access to the workflow's status and results.
|
|
41
|
+
|
|
42
|
+
```typescript lineNumbers
|
|
43
|
+
import { start } from "workflow/api";
|
|
44
|
+
import { processOrder } from "./workflows/process-order";
|
|
45
|
+
|
|
46
|
+
const run = await start(processOrder, [/* orderId */]);
|
|
47
|
+
|
|
48
|
+
// The run object has properties you can await
|
|
49
|
+
console.log("Run ID:", run.runId);
|
|
50
|
+
|
|
51
|
+
// Check the workflow status
|
|
52
|
+
const status = await run.status; // "running" | "completed" | "failed"
|
|
53
|
+
|
|
54
|
+
// Get the workflow's return value (blocks until completion)
|
|
55
|
+
const result = await run.returnValue;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Key Properties:**
|
|
59
|
+
|
|
60
|
+
- `runId` - Unique identifier for this workflow run
|
|
61
|
+
- `status` - Current status of the workflow (async)
|
|
62
|
+
- `returnValue` - The value returned by the workflow function (async, blocks until completion)
|
|
63
|
+
- `readable` - ReadableStream for streaming updates from the workflow
|
|
64
|
+
|
|
65
|
+
<Callout type="info">
|
|
66
|
+
Most `Run` properties are async getters that return promises. You need to `await` them to get their values. For a complete list of properties and methods, see the API reference below.
|
|
67
|
+
</Callout>
|
|
68
|
+
|
|
69
|
+
**Learn more**: [`Run` API Reference](/docs/api-reference/workflow-api/start#returns)
|
|
70
|
+
|
|
71
|
+
## Common Patterns
|
|
72
|
+
|
|
73
|
+
### Fire and Forget
|
|
74
|
+
|
|
75
|
+
The most common pattern is to start a workflow and immediately return, letting it execute in the background:
|
|
76
|
+
|
|
77
|
+
```typescript lineNumbers
|
|
78
|
+
import { start } from "workflow/api";
|
|
79
|
+
import { sendNotifications } from "./workflows/notifications";
|
|
80
|
+
|
|
81
|
+
export async function POST(request: Request) {
|
|
82
|
+
// Start workflow and don't wait for it
|
|
83
|
+
const run = await start(sendNotifications, [userId]);
|
|
84
|
+
|
|
85
|
+
// Return immediately
|
|
86
|
+
return Response.json({
|
|
87
|
+
message: "Notifications queued",
|
|
88
|
+
runId: run.runId
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Wait for Completion
|
|
94
|
+
|
|
95
|
+
If you need to wait for the workflow to complete before responding:
|
|
96
|
+
|
|
97
|
+
```typescript lineNumbers
|
|
98
|
+
import { start } from "workflow/api";
|
|
99
|
+
import { generateReport } from "./workflows/reports";
|
|
100
|
+
|
|
101
|
+
export async function POST(request: Request) {
|
|
102
|
+
const run = await start(generateReport, [reportId]);
|
|
103
|
+
|
|
104
|
+
// Wait for the workflow to complete
|
|
105
|
+
const report = await run.returnValue; // [!code highlight]
|
|
106
|
+
|
|
107
|
+
return Response.json({ report });
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
<Callout type="warn">
|
|
112
|
+
Be cautious when waiting for `returnValue` - if your workflow takes a long time, your API route may timeout.
|
|
113
|
+
</Callout>
|
|
114
|
+
|
|
115
|
+
### Stream Updates to Client
|
|
116
|
+
|
|
117
|
+
Stream real-time updates from your workflow as it executes, without waiting for completion:
|
|
118
|
+
|
|
119
|
+
```typescript lineNumbers
|
|
120
|
+
import { start } from "workflow/api";
|
|
121
|
+
import { generateAIContent } from "./workflows/ai-generation";
|
|
122
|
+
|
|
123
|
+
export async function POST(request: Request) {
|
|
124
|
+
const { prompt } = await request.json();
|
|
125
|
+
|
|
126
|
+
// Start the workflow
|
|
127
|
+
const run = await start(generateAIContent, [prompt]);
|
|
128
|
+
|
|
129
|
+
// Get the readable stream (can also use run.readable as shorthand)
|
|
130
|
+
const stream = run.getReadable(); // [!code highlight]
|
|
131
|
+
|
|
132
|
+
// Return the stream immediately
|
|
133
|
+
return new Response(stream, {
|
|
134
|
+
headers: {
|
|
135
|
+
"Content-Type": "application/octet-stream",
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Your workflow can write to the stream using [`getWritable()`](/docs/api-reference/workflow/get-writable):
|
|
142
|
+
|
|
143
|
+
```typescript lineNumbers
|
|
144
|
+
import { getWritable } from "workflow";
|
|
145
|
+
|
|
146
|
+
export async function generateAIContent(prompt: string) {
|
|
147
|
+
"use workflow";
|
|
148
|
+
|
|
149
|
+
const writable = getWritable(); // [!code highlight]
|
|
150
|
+
|
|
151
|
+
await streamContentToClient(writable, prompt);
|
|
152
|
+
|
|
153
|
+
return { status: "complete" };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function streamContentToClient(
|
|
157
|
+
writable: WritableStream,
|
|
158
|
+
prompt: string
|
|
159
|
+
) {
|
|
160
|
+
"use step";
|
|
161
|
+
|
|
162
|
+
const writer = writable.getWriter();
|
|
163
|
+
|
|
164
|
+
// Stream updates as they become available
|
|
165
|
+
for (let i = 0; i < 10; i++) {
|
|
166
|
+
const chunk = new TextEncoder().encode(`Update ${i}\n`);
|
|
167
|
+
await writer.write(chunk);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
writer.releaseLock();
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
<Callout type="info">
|
|
175
|
+
Streams are particularly useful for AI workflows where you want to show progress to users in real-time, or for long-running processes that produce intermediate results.
|
|
176
|
+
</Callout>
|
|
177
|
+
|
|
178
|
+
**Learn more**: [Streaming in Workflows](/docs/foundations/serialization#streaming)
|
|
179
|
+
|
|
180
|
+
### Check Status Later
|
|
181
|
+
|
|
182
|
+
You can retrieve a workflow run later using its `runId` with [`getRun()`](/docs/api-reference/workflow-api/get-run):
|
|
183
|
+
|
|
184
|
+
```typescript lineNumbers
|
|
185
|
+
import { getRun } from "workflow/api";
|
|
186
|
+
|
|
187
|
+
export async function GET(request: Request) {
|
|
188
|
+
const url = new URL(request.url);
|
|
189
|
+
const runId = url.searchParams.get("runId");
|
|
190
|
+
|
|
191
|
+
// Retrieve the existing run
|
|
192
|
+
const run = getRun(runId); // [!code highlight]
|
|
193
|
+
|
|
194
|
+
// Check its status
|
|
195
|
+
const status = await run.status;
|
|
196
|
+
|
|
197
|
+
if (status === "completed") {
|
|
198
|
+
const result = await run.returnValue;
|
|
199
|
+
return Response.json({ result });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return Response.json({ status });
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Next Steps
|
|
207
|
+
|
|
208
|
+
Now that you understand how to start workflows and track their execution:
|
|
209
|
+
|
|
210
|
+
- Learn about [Common Patterns](/docs/foundations/common-patterns) for organizing complex workflows
|
|
211
|
+
- Explore [Errors & Retrying](/docs/foundations/errors-and-retries) to handle failures gracefully
|
|
212
|
+
- Check the [`start()` API Reference](/docs/api-reference/workflow-api/start) for complete details
|