workflow 5.0.0-beta.43 → 5.0.0-beta.44

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.
Files changed (182) hide show
  1. package/README.md +6 -4
  2. package/dist/internal/builtins.d.ts +4 -4
  3. package/dist/internal/builtins.js +6 -6
  4. package/docs/ai/chat-session-modeling.mdx +23 -24
  5. package/docs/ai/defining-tools.mdx +5 -6
  6. package/docs/ai/human-in-the-loop.mdx +11 -11
  7. package/docs/ai/index.mdx +20 -20
  8. package/docs/ai/message-queueing.mdx +6 -6
  9. package/docs/ai/meta.json +1 -0
  10. package/docs/ai/resumable-streams.mdx +28 -28
  11. package/docs/ai/sleep-and-delays.mdx +9 -9
  12. package/docs/ai/streaming-updates-from-tools.mdx +4 -4
  13. package/docs/api-reference/vitest/index.mdx +8 -8
  14. package/docs/api-reference/workflow/create-hook.mdx +15 -15
  15. package/docs/api-reference/workflow/create-webhook.mdx +15 -15
  16. package/docs/api-reference/workflow/define-hook.mdx +10 -10
  17. package/docs/api-reference/workflow/fatal-error.mdx +2 -2
  18. package/docs/api-reference/workflow/fetch.mdx +7 -7
  19. package/docs/api-reference/workflow/get-step-metadata.mdx +2 -2
  20. package/docs/api-reference/workflow/get-workflow-metadata.mdx +3 -3
  21. package/docs/api-reference/workflow/get-writable.mdx +7 -7
  22. package/docs/api-reference/workflow/index.mdx +1 -1
  23. package/docs/api-reference/workflow/retryable-error.mdx +1 -1
  24. package/docs/api-reference/workflow/set-attributes.mdx +2 -2
  25. package/docs/api-reference/workflow/sleep.mdx +3 -3
  26. package/docs/api-reference/workflow-ai/durable-agent.mdx +42 -42
  27. package/docs/api-reference/workflow-ai/index.mdx +3 -3
  28. package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +28 -28
  29. package/docs/api-reference/workflow-api/get-hook-by-token.mdx +11 -11
  30. package/docs/api-reference/workflow-api/get-run.mdx +10 -10
  31. package/docs/api-reference/workflow-api/index.mdx +2 -4
  32. package/docs/api-reference/workflow-api/resume-hook.mdx +14 -14
  33. package/docs/api-reference/workflow-api/resume-webhook.mdx +3 -3
  34. package/docs/api-reference/workflow-api/start.mdx +16 -15
  35. package/docs/api-reference/workflow-astro/workflow.mdx +3 -3
  36. package/docs/api-reference/workflow-errors/entity-conflict-error.mdx +4 -4
  37. package/docs/api-reference/workflow-errors/hook-conflict-error.mdx +4 -4
  38. package/docs/api-reference/workflow-errors/hook-not-found-error.mdx +8 -8
  39. package/docs/api-reference/workflow-errors/index.mdx +6 -6
  40. package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +9 -9
  41. package/docs/api-reference/workflow-errors/run-expired-error.mdx +2 -2
  42. package/docs/api-reference/workflow-errors/run-not-supported-error.mdx +4 -4
  43. package/docs/api-reference/workflow-errors/step-not-registered-error.mdx +5 -5
  44. package/docs/api-reference/workflow-errors/throttle-error.mdx +2 -2
  45. package/docs/api-reference/workflow-errors/too-early-error.mdx +2 -2
  46. package/docs/api-reference/workflow-errors/workflow-error.mdx +4 -4
  47. package/docs/api-reference/workflow-errors/workflow-not-registered-error.mdx +5 -6
  48. package/docs/api-reference/workflow-errors/workflow-run-cancelled-error.mdx +6 -6
  49. package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +5 -5
  50. package/docs/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +4 -4
  51. package/docs/api-reference/workflow-errors/workflow-run-not-found-error.mdx +4 -4
  52. package/docs/api-reference/workflow-errors/workflow-runtime-error.mdx +2 -2
  53. package/docs/api-reference/workflow-errors/workflow-world-error.mdx +8 -8
  54. package/docs/api-reference/workflow-globals.mdx +12 -11
  55. package/docs/api-reference/workflow-nest/configure-workflow-controller.mdx +2 -2
  56. package/docs/api-reference/workflow-nest/nest-local-builder.mdx +4 -4
  57. package/docs/api-reference/workflow-nest/workflow-controller.mdx +1 -1
  58. package/docs/api-reference/workflow-nest/workflow-module.mdx +4 -4
  59. package/docs/api-reference/workflow-next/with-workflow.mdx +16 -16
  60. package/docs/api-reference/workflow-nitro/index.mdx +6 -6
  61. package/docs/api-reference/workflow-nuxt/index.mdx +4 -4
  62. package/docs/api-reference/workflow-observability/hydrate-data.mdx +5 -5
  63. package/docs/api-reference/workflow-observability/hydrate-resource-io.mdx +4 -4
  64. package/docs/api-reference/workflow-observability/index.mdx +6 -8
  65. package/docs/api-reference/workflow-observability/observability-revivers.mdx +2 -2
  66. package/docs/api-reference/workflow-observability/parse-class-name.mdx +3 -3
  67. package/docs/api-reference/workflow-observability/parse-step-name.mdx +4 -4
  68. package/docs/api-reference/workflow-observability/parse-workflow-name.mdx +4 -4
  69. package/docs/api-reference/workflow-runtime/create-world.mdx +8 -8
  70. package/docs/api-reference/workflow-runtime/get-world-handlers.mdx +6 -6
  71. package/docs/api-reference/workflow-runtime/get-world.mdx +4 -4
  72. package/docs/api-reference/workflow-runtime/health-check.mdx +1 -1
  73. package/docs/api-reference/workflow-runtime/index.mdx +2 -4
  74. package/docs/api-reference/workflow-runtime/set-world.mdx +15 -13
  75. package/docs/api-reference/workflow-runtime/workflow-entrypoint.mdx +6 -5
  76. package/docs/api-reference/workflow-runtime/world/analytics.mdx +9 -9
  77. package/docs/api-reference/workflow-runtime/world/index.mdx +5 -3
  78. package/docs/api-reference/workflow-runtime/world/queue.mdx +11 -11
  79. package/docs/api-reference/workflow-runtime/world/storage.mdx +62 -28
  80. package/docs/api-reference/workflow-runtime/world/streams.mdx +7 -7
  81. package/docs/api-reference/workflow-serde/index.mdx +1 -1
  82. package/docs/api-reference/workflow-serde/workflow-deserialize.mdx +2 -2
  83. package/docs/api-reference/workflow-serde/workflow-serialize.mdx +7 -7
  84. package/docs/api-reference/workflow-sveltekit/workflow-plugin.mdx +3 -3
  85. package/docs/api-reference/workflow-vite/workflow.mdx +5 -5
  86. package/docs/changelog/attributes-mvp.mdx +39 -39
  87. package/docs/changelog/batched-event-writes.mdx +12 -12
  88. package/docs/changelog/eager-processing.mdx +63 -63
  89. package/docs/changelog/index.mdx +3 -3
  90. package/docs/changelog/lazy-event-creation.md +27 -27
  91. package/docs/changelog/resilient-resume.mdx +5 -5
  92. package/docs/changelog/resilient-start.mdx +14 -14
  93. package/docs/changelog/step-message-ownership.mdx +47 -47
  94. package/docs/changelog/turbo-mode.md +20 -20
  95. package/docs/comparisons/index.mdx +13 -13
  96. package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +15 -15
  97. package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +12 -12
  98. package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +11 -11
  99. package/docs/comparisons/workflow-sdk-vs-inngest.mdx +19 -19
  100. package/docs/comparisons/workflow-sdk-vs-temporal.mdx +23 -23
  101. package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +18 -17
  102. package/docs/configuration/build-and-diagnostics.mdx +5 -5
  103. package/docs/configuration/cli-and-web-ui.mdx +4 -4
  104. package/docs/configuration/runtime-tuning.mdx +86 -23
  105. package/docs/configuration/worlds.mdx +28 -14
  106. package/docs/cookbook/advanced/child-workflows.mdx +25 -25
  107. package/docs/cookbook/advanced/publishing-libraries.mdx +40 -40
  108. package/docs/cookbook/advanced/serializable-steps.mdx +21 -21
  109. package/docs/cookbook/advanced/upgrading-workflows.mdx +31 -31
  110. package/docs/cookbook/agent-patterns/agent-cancellation.mdx +20 -20
  111. package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +22 -22
  112. package/docs/cookbook/common-patterns/batching.mdx +14 -14
  113. package/docs/cookbook/common-patterns/idempotency.mdx +9 -9
  114. package/docs/cookbook/common-patterns/rate-limiting.mdx +3 -3
  115. package/docs/cookbook/common-patterns/saga.mdx +19 -19
  116. package/docs/cookbook/common-patterns/scheduling.mdx +23 -23
  117. package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +26 -26
  118. package/docs/cookbook/common-patterns/timeouts.mdx +23 -23
  119. package/docs/cookbook/common-patterns/webhooks.mdx +6 -6
  120. package/docs/cookbook/common-patterns/workflow-composition.mdx +19 -19
  121. package/docs/cookbook/index.mdx +22 -22
  122. package/docs/cookbook/integrations/ai-sdk.mdx +43 -41
  123. package/docs/cookbook/integrations/chat-sdk.mdx +34 -34
  124. package/docs/cookbook/integrations/sandbox.mdx +46 -46
  125. package/docs/deploying.mdx +15 -15
  126. package/docs/errors/abort-signal-timeout-in-workflow.mdx +12 -12
  127. package/docs/errors/corrupted-event-log.mdx +11 -11
  128. package/docs/errors/deployment-mismatch.mdx +14 -14
  129. package/docs/errors/fetch-in-workflow.mdx +8 -8
  130. package/docs/errors/hook-conflict.mdx +11 -11
  131. package/docs/errors/index.mdx +1 -1
  132. package/docs/errors/node-js-module-in-workflow.mdx +5 -5
  133. package/docs/errors/replay-divergence.mdx +2 -2
  134. package/docs/errors/runtime-decryption-failed.mdx +12 -12
  135. package/docs/errors/serialization-failed.mdx +40 -12
  136. package/docs/errors/start-invalid-workflow-function.mdx +5 -5
  137. package/docs/errors/step-executed-multiple-times.mdx +2 -2
  138. package/docs/errors/step-not-registered.mdx +5 -5
  139. package/docs/errors/timeout-in-workflow.mdx +8 -8
  140. package/docs/errors/webhook-invalid-respond-with-value.mdx +18 -18
  141. package/docs/errors/webhook-response-not-sent.mdx +16 -16
  142. package/docs/errors/workflow-not-registered.mdx +5 -5
  143. package/docs/foundations/cancellation.mdx +31 -31
  144. package/docs/foundations/errors-and-retries.mdx +42 -11
  145. package/docs/foundations/hooks.mdx +35 -35
  146. package/docs/foundations/idempotency.mdx +9 -9
  147. package/docs/foundations/serialization.mdx +21 -22
  148. package/docs/foundations/starting-workflows.mdx +36 -37
  149. package/docs/foundations/streaming.mdx +46 -41
  150. package/docs/foundations/versioning.mdx +3 -3
  151. package/docs/foundations/workflows-and-steps.mdx +9 -9
  152. package/docs/getting-started/astro.mdx +16 -16
  153. package/docs/getting-started/express.mdx +8 -8
  154. package/docs/getting-started/fastify.mdx +8 -8
  155. package/docs/getting-started/hono.mdx +8 -8
  156. package/docs/getting-started/nestjs.mdx +18 -17
  157. package/docs/getting-started/next.mdx +11 -11
  158. package/docs/getting-started/nitro.mdx +16 -16
  159. package/docs/getting-started/nuxt.mdx +8 -8
  160. package/docs/getting-started/python.mdx +4 -4
  161. package/docs/getting-started/react-router/v7.mdx +1 -1
  162. package/docs/getting-started/react-router/v8.mdx +1 -1
  163. package/docs/getting-started/sveltekit.mdx +14 -14
  164. package/docs/getting-started/tanstack-start.mdx +12 -12
  165. package/docs/getting-started/vite.mdx +8 -8
  166. package/docs/how-it-works/cancellation.mdx +62 -62
  167. package/docs/how-it-works/code-transform.mdx +66 -54
  168. package/docs/how-it-works/encryption.mdx +25 -21
  169. package/docs/how-it-works/event-sourcing.mdx +53 -35
  170. package/docs/how-it-works/framework-integrations.mdx +12 -12
  171. package/docs/how-it-works/understanding-directives.mdx +21 -21
  172. package/docs/internal/index.mdx +6 -6
  173. package/docs/internal/nitro-native-build.mdx +2 -2
  174. package/docs/internal/nitro-web-ui.mdx +4 -4
  175. package/docs/internal/serializable-abort-controller.mdx +7 -7
  176. package/docs/observability/attributes.mdx +3 -3
  177. package/docs/observability/index.mdx +14 -10
  178. package/docs/observability/tracing.mdx +10 -10
  179. package/docs/testing/index.mdx +33 -33
  180. package/docs/testing/server-based.mdx +10 -10
  181. package/docs/whats-new.mdx +185 -0
  182. package/package.json +12 -12
package/README.md CHANGED
@@ -8,9 +8,9 @@
8
8
  <h1>Workflow SDK</h1>
9
9
 
10
10
  <a href="https://vercel.com"><img alt="Vercel logo" src="https://img.shields.io/badge/MADE%20BY%20Vercel-000000.svg?style=for-the-badge&logo=Vercel&labelColor=000"></a>
11
- <a href="https://www.npmjs.com/package/workflow"><img alt="NPM version" src="https://img.shields.io/npm/v/workflow?style=for-the-badge&labelColor=000000"></a>
11
+ <a href="https://www.npmjs.com/package/workflow"><img alt="npm version" src="https://img.shields.io/npm/v/workflow?style=for-the-badge&labelColor=000000"></a>
12
12
  <a href="https://github.com/vercel/workflow/blob/main/LICENSE.md"><img alt="License" src="https://img.shields.io/npm/l/workflow.svg?style=for-the-badge&labelColor=000000"></a>
13
- <a href="https://github.com/vercel/workflow/discussions"><img alt="Join the community on GitHub" src="https://img.shields.io/badge/Join%20the%20community-blueviolet.svg?style=for-the-badge&logo=Github&labelColor=000000&logoWidth=20"></a>
13
+ <a href="https://github.com/vercel/workflow/discussions"><img alt="Join the community on GitHub" src="https://img.shields.io/badge/Join%20the%20community-blueviolet.svg?style=for-the-badge&logo=GitHub&labelColor=000000&logoWidth=20"></a>
14
14
 
15
15
  </div>
16
16
 
@@ -70,7 +70,9 @@ Vercel for managed storage, queuing, scaling, and observability. To self-host,
70
70
  use the Postgres backend or implement a custom
71
71
  [World](https://workflow-sdk.dev/docs/deploying).
72
72
 
73
- There are many third-party Worlds (both self-hosted or managed), see [the Worlds page](https://workflow-sdk.dev/worlds) for a list of maintainer-curated third party worlds. Submit your world by opening updating the [Worlds Manifest](https://github.com/vercel/workflow/blob/main/worlds-manifest.json).
73
+ The [Worlds page](https://workflow-sdk.dev/worlds) lists maintainer-curated
74
+ third-party Worlds, including self-hosted and managed options. Submit your World
75
+ by updating the [Worlds Manifest](https://github.com/vercel/workflow/blob/main/worlds-manifest.json).
74
76
 
75
77
  ## Community
76
78
 
@@ -88,7 +90,7 @@ with the team and wider community. By participating, you agree to our
88
90
 
89
91
  ## Security
90
92
 
91
- If you believe you have found a security vulnerability in Workflow SDK, we encourage you to **_responsibly disclose this and not open a public issue_**.
93
+ If you find a security vulnerability in Workflow SDK, **_disclose it responsibly instead of opening a public issue_**.
92
94
 
93
95
  To participate in our Open Source Software Bug Bounty program, please email
94
96
  [responsible.disclosure@vercel.com](mailto:responsible.disclosure@vercel.com).
@@ -1,7 +1,7 @@
1
1
  /**
2
- * These are the built-in steps that are "automatically available" in the workflow scope. They are
3
- * similar to "stdlib" except that are not meant to be imported by users, but are instead "just available"
4
- * alongside user defined steps. They are used internally by the runtime
2
+ * Built-in steps available in the workflow scope. Like a standard library,
3
+ * they are available alongside user-defined steps, but users do not import
4
+ * them. The runtime uses these steps internally.
5
5
  */
6
6
  export declare function __builtin_response_array_buffer(this: Request | Response): Promise<ArrayBuffer>;
7
7
  export declare function __builtin_response_json(this: Request | Response): Promise<unknown>;
@@ -12,7 +12,7 @@ export declare function __builtin_response_text(this: Request | Response): Promi
12
12
  * runs in normal Node context with full world access.
13
13
  *
14
14
  * The dispatch reads the world and current run id directly from
15
- * `globalThis` symbols populated by the workflow/step runtime — this
15
+ * `globalThis` symbols populated by the workflow/step runtime. This
16
16
  * intentionally avoids importing `@workflow/core` so the Next.js
17
17
  * deferred-entries discoverer can't walk a chain into world adapters
18
18
  * and `@vercel/queue` from this step file.
@@ -1,7 +1,7 @@
1
1
  /**
2
- * These are the built-in steps that are "automatically available" in the workflow scope. They are
3
- * similar to "stdlib" except that are not meant to be imported by users, but are instead "just available"
4
- * alongside user defined steps. They are used internally by the runtime
2
+ * Built-in steps available in the workflow scope. Like a standard library,
3
+ * they are available alongside user-defined steps, but users do not import
4
+ * them. The runtime uses these steps internally.
5
5
  */
6
6
  export async function __builtin_response_array_buffer() {
7
7
  'use step';
@@ -33,7 +33,7 @@ function formatUnknownError(error) {
33
33
  * runs in normal Node context with full world access.
34
34
  *
35
35
  * The dispatch reads the world and current run id directly from
36
- * `globalThis` symbols populated by the workflow/step runtime — this
36
+ * `globalThis` symbols populated by the workflow/step runtime. This
37
37
  * intentionally avoids importing `@workflow/core` so the Next.js
38
38
  * deferred-entries discoverer can't walk a chain into world adapters
39
39
  * and `@vercel/queue` from this step file.
@@ -50,7 +50,7 @@ export async function __builtin_set_attributes(changes, options) {
50
50
  : INTERNAL_ATTRIBUTES_MAX_ATTEMPTS;
51
51
  const world = g[Symbol.for('@workflow/world//cache')];
52
52
  if (typeof world?.runs?.experimentalSetAttributes !== 'function') {
53
- // World adapter doesn't implement attributes yet no-op the call,
53
+ // World adapter doesn't implement attributes yet, so no-op the call,
54
54
  // but emit one process-wide warning so users know their writes are
55
55
  // being dropped. The VM-side validation already ran so the input
56
56
  // is well-formed.
@@ -79,4 +79,4 @@ export async function __builtin_set_attributes(changes, options) {
79
79
  }
80
80
  }
81
81
  __builtin_set_attributes.maxRetries = INTERNAL_ATTRIBUTES_MAX_ATTEMPTS - 1;
82
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbHRpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJuYWwvYnVpbHRpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE1BQU0sQ0FBQyxLQUFLLFVBQVUsK0JBQStCO0lBR25ELFVBQVUsQ0FBQztJQUNYLE9BQU8sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0FBQzVCLENBQUM7QUFFRCxNQUFNLENBQUMsS0FBSyxVQUFVLHVCQUF1QjtJQUMzQyxVQUFVLENBQUM7SUFDWCxPQUFPLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNyQixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSx1QkFBdUI7SUFDM0MsVUFBVSxDQUFDO0lBQ1gsT0FBTyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDckIsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sd0JBQXdCLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FDekMsaURBQWlELENBQ2xELENBQUM7QUFFRixNQUFNLGdDQUFnQyxHQUFHLENBQUMsQ0FBQztBQUUzQyxTQUFTLGtCQUFrQixDQUFDLEtBQWM7SUFDeEMsSUFBSSxLQUFLLFlBQVksS0FBSyxFQUFFLENBQUM7UUFDM0IsT0FBTyxLQUFLLENBQUMsS0FBSyxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDMUQsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3ZCLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSx3QkFBd0IsQ0FDNUMsT0FBcUQsRUFDckQsT0FBK0M7SUFFL0MsVUFBVSxDQUFDO0lBQ1gsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPO0lBQ2pDLE1BQU0sQ0FBQyxHQUFHLFVBQXFDLENBQUM7SUFFaEQsTUFBTSxjQUFjLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FTdkQsQ0FBQztJQUNkLE1BQU0sS0FBSyxHQUFHLGNBQWMsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDO0lBQzNDLE1BQU0sT0FBTyxHQUNYLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxPQUFPLEtBQUssUUFBUTtRQUM5QyxDQUFDLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPO1FBQzVCLENBQUMsQ0FBQyxnQ0FBZ0MsQ0FBQztJQUV2QyxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxDQVd2QyxDQUFDO0lBQ2QsSUFBSSxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUseUJBQXlCLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDakUsbUVBQW1FO1FBQ25FLG1FQUFtRTtRQUNuRSxpRUFBaUU7UUFDakUsa0JBQWtCO1FBQ2xCLElBQUksQ0FBQyxDQUFDLENBQUMsd0JBQXdCLENBQUMsRUFBRSxDQUFDO1lBQ2pDLENBQUMsQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLElBQUksQ0FBQztZQUNuQyxNQUFNLFNBQVMsR0FBRyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3hELE9BQU8sQ0FBQyxJQUFJLENBQ1YsNkRBQTZELFNBQVMscU1BQXFNLENBQzVRLENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsYUFBYSxDQUFDO1FBQ3JELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQ2Isd0VBQXdFLENBQ3pFLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixJQUFJLE9BQU8sR0FBRyxnQ0FBZ0MsRUFBRSxDQUFDO1lBQy9DLE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztRQUVELDRFQUE0RTtRQUM1RSxzRUFBc0U7UUFDdEUsK0RBQStEO1FBQy9ELE9BQU8sQ0FBQyxLQUFLLENBQ1gsdURBQXVELGdDQUFnQyxxREFBcUQsa0JBQWtCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FDeEssQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDO0FBR0Msd0JBR0QsQ0FBQyxVQUFVLEdBQUcsZ0NBQWdDLEdBQUcsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGVzZSBhcmUgdGhlIGJ1aWx0LWluIHN0ZXBzIHRoYXQgYXJlIFwiYXV0b21hdGljYWxseSBhdmFpbGFibGVcIiBpbiB0aGUgd29ya2Zsb3cgc2NvcGUuIFRoZXkgYXJlXG4gKiBzaW1pbGFyIHRvIFwic3RkbGliXCIgZXhjZXB0IHRoYXQgYXJlIG5vdCBtZWFudCB0byBiZSBpbXBvcnRlZCBieSB1c2VycywgYnV0IGFyZSBpbnN0ZWFkIFwianVzdCBhdmFpbGFibGVcIlxuICogYWxvbmdzaWRlIHVzZXIgZGVmaW5lZCBzdGVwcy4gVGhleSBhcmUgdXNlZCBpbnRlcm5hbGx5IGJ5IHRoZSBydW50aW1lXG4gKi9cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9fYnVpbHRpbl9yZXNwb25zZV9hcnJheV9idWZmZXIoXG4gIHRoaXM6IFJlcXVlc3QgfCBSZXNwb25zZVxuKSB7XG4gICd1c2Ugc3RlcCc7XG4gIHJldHVybiB0aGlzLmFycmF5QnVmZmVyKCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBfX2J1aWx0aW5fcmVzcG9uc2VfanNvbih0aGlzOiBSZXF1ZXN0IHwgUmVzcG9uc2UpIHtcbiAgJ3VzZSBzdGVwJztcbiAgcmV0dXJuIHRoaXMuanNvbigpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX19idWlsdGluX3Jlc3BvbnNlX3RleHQodGhpczogUmVxdWVzdCB8IFJlc3BvbnNlKSB7XG4gICd1c2Ugc3RlcCc7XG4gIHJldHVybiB0aGlzLnRleHQoKTtcbn1cblxuLyoqXG4gKiBQcm9jZXNzLXdpZGUgZGVkdXBlIGZvciB0aGUgdW5zdXBwb3J0ZWQtd29ybGQgd2FybmluZyBzbyBoaWdoLXZvbHVtZVxuICogY2FsbGVycyBkb24ndCBmbG9vZCBsb2dzLlxuICovXG5jb25zdCBVTlNVUFBPUlRFRF9XT1JMRF9XQVJORUQgPSBTeW1ib2wuZm9yKFxuICAnQHdvcmtmbG93L3NldEF0dHJpYnV0ZXMvL3Vuc3VwcG9ydGVkV29ybGRXYXJuZWQnXG4pO1xuXG5jb25zdCBJTlRFUk5BTF9BVFRSSUJVVEVTX01BWF9BVFRFTVBUUyA9IDM7XG5cbmZ1bmN0aW9uIGZvcm1hdFVua25vd25FcnJvcihlcnJvcjogdW5rbm93bikge1xuICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHJldHVybiBlcnJvci5zdGFjayA/PyBgJHtlcnJvci5uYW1lfTogJHtlcnJvci5tZXNzYWdlfWA7XG4gIH1cbiAgcmV0dXJuIFN0cmluZyhlcnJvcik7XG59XG5cbi8qKlxuICogU3RlcCBicmlkZ2UgZm9yIHdvcmtmbG93LWJvZHkgYHNldEF0dHJpYnV0ZXNgIGNhbGxzLiBUaGUgVk0tc2lkZVxuICogaGVscGVyIHZhbGlkYXRlcyBpbnB1dCBhbmQgZGlzcGF0Y2hlcyBoZXJlIHZpYSBgdXNlU3RlcGAuIFRoaXMgc3RlcFxuICogcnVucyBpbiBub3JtYWwgTm9kZSBjb250ZXh0IHdpdGggZnVsbCB3b3JsZCBhY2Nlc3MuXG4gKlxuICogVGhlIGRpc3BhdGNoIHJlYWRzIHRoZSB3b3JsZCBhbmQgY3VycmVudCBydW4gaWQgZGlyZWN0bHkgZnJvbVxuICogYGdsb2JhbFRoaXNgIHN5bWJvbHMgcG9wdWxhdGVkIGJ5IHRoZSB3b3JrZmxvdy9zdGVwIHJ1bnRpbWUg4oCUIHRoaXNcbiAqIGludGVudGlvbmFsbHkgYXZvaWRzIGltcG9ydGluZyBgQHdvcmtmbG93L2NvcmVgIHNvIHRoZSBOZXh0LmpzXG4gKiBkZWZlcnJlZC1lbnRyaWVzIGRpc2NvdmVyZXIgY2FuJ3Qgd2FsayBhIGNoYWluIGludG8gd29ybGQgYWRhcHRlcnNcbiAqIGFuZCBgQHZlcmNlbC9xdWV1ZWAgZnJvbSB0aGlzIHN0ZXAgZmlsZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9fYnVpbHRpbl9zZXRfYXR0cmlidXRlcyhcbiAgY2hhbmdlczogQXJyYXk8eyBrZXk6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB8IG51bGwgfT4sXG4gIG9wdGlvbnM/OiB7IGFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzPzogYm9vbGVhbiB9XG4pIHtcbiAgJ3VzZSBzdGVwJztcbiAgaWYgKGNoYW5nZXMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gIGNvbnN0IGcgPSBnbG9iYWxUaGlzIGFzIFJlY29yZDxzeW1ib2wsIHVua25vd24+O1xuXG4gIGNvbnN0IGNvbnRleHRTdG9yYWdlID0gZ1tTeW1ib2wuZm9yKCdXT1JLRkxPV19TVEVQX0NPTlRFWFRfU1RPUkFHRScpXSBhc1xuICAgIHwge1xuICAgICAgICBnZXRTdG9yZTogKCkgPT5cbiAgICAgICAgICB8IHtcbiAgICAgICAgICAgICAgc3RlcE1ldGFkYXRhPzogeyBhdHRlbXB0PzogbnVtYmVyIH07XG4gICAgICAgICAgICAgIHdvcmtmbG93TWV0YWRhdGE/OiB7IHdvcmtmbG93UnVuSWQ/OiBzdHJpbmcgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB8IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB8IHVuZGVmaW5lZDtcbiAgY29uc3Qgc3RvcmUgPSBjb250ZXh0U3RvcmFnZT8uZ2V0U3RvcmU/LigpO1xuICBjb25zdCBhdHRlbXB0ID1cbiAgICB0eXBlb2Ygc3RvcmU/LnN0ZXBNZXRhZGF0YT8uYXR0ZW1wdCA9PT0gJ251bWJlcidcbiAgICAgID8gc3RvcmUuc3RlcE1ldGFkYXRhLmF0dGVtcHRcbiAgICAgIDogSU5URVJOQUxfQVRUUklCVVRFU19NQVhfQVRURU1QVFM7XG5cbiAgY29uc3Qgd29ybGQgPSBnW1N5bWJvbC5mb3IoJ0B3b3JrZmxvdy93b3JsZC8vY2FjaGUnKV0gYXNcbiAgICB8IHtcbiAgICAgICAgbmFtZT86IHN0cmluZztcbiAgICAgICAgcnVucz86IHtcbiAgICAgICAgICBleHBlcmltZW50YWxTZXRBdHRyaWJ1dGVzPzogKFxuICAgICAgICAgICAgcnVuSWQ6IHN0cmluZyxcbiAgICAgICAgICAgIGNoYW5nZXM6IEFycmF5PHsga2V5OiBzdHJpbmc7IHZhbHVlOiBzdHJpbmcgfCBudWxsIH0+LFxuICAgICAgICAgICAgb3B0aW9ucz86IHsgYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXM/OiBib29sZWFuIH1cbiAgICAgICAgICApID0+IFByb21pc2U8dW5rbm93bj47XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfCB1bmRlZmluZWQ7XG4gIGlmICh0eXBlb2Ygd29ybGQ/LnJ1bnM/LmV4cGVyaW1lbnRhbFNldEF0dHJpYnV0ZXMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAvLyBXb3JsZCBhZGFwdGVyIGRvZXNuJ3QgaW1wbGVtZW50IGF0dHJpYnV0ZXMgeWV0IOKAlCBuby1vcCB0aGUgY2FsbCxcbiAgICAvLyBidXQgZW1pdCBvbmUgcHJvY2Vzcy13aWRlIHdhcm5pbmcgc28gdXNlcnMga25vdyB0aGVpciB3cml0ZXMgYXJlXG4gICAgLy8gYmVpbmcgZHJvcHBlZC4gVGhlIFZNLXNpZGUgdmFsaWRhdGlvbiBhbHJlYWR5IHJhbiBzbyB0aGUgaW5wdXRcbiAgICAvLyBpcyB3ZWxsLWZvcm1lZC5cbiAgICBpZiAoIWdbVU5TVVBQT1JURURfV09STERfV0FSTkVEXSkge1xuICAgICAgZ1tVTlNVUFBPUlRFRF9XT1JMRF9XQVJORURdID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHdvcmxkTmFtZSA9IHdvcmxkPy5uYW1lID8gYCAoJHt3b3JsZC5uYW1lfSlgIDogJyc7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBbd29ya2Zsb3ddIHNldEF0dHJpYnV0ZXM6IHRoZSBjdXJyZW50IHdvcmxkIGltcGxlbWVudGF0aW9uJHt3b3JsZE5hbWV9IGRvZXMgbm90IGltcGxlbWVudCBleHBlcmltZW50YWxTZXRBdHRyaWJ1dGVzOyB0aGlzIGNhbGwgKGFuZCBhbnkgc3Vic2VxdWVudCBzZXRBdHRyaWJ1dGVzIGNhbGxzIGluIHRoaXMgcHJvY2VzcykgaXMgYSBuby1vcC4gQXR0cmlidXRlcyB3aWxsIGJlY29tZSBhdmFpbGFibGUgb25jZSB0aGUgd29ybGQgYWRhcHRlciBhZGRzIHN1cHBvcnQuYFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBydW5JZCA9IHN0b3JlPy53b3JrZmxvd01ldGFkYXRhPy53b3JrZmxvd1J1bklkO1xuICAgIGlmICghcnVuSWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ19fYnVpbHRpbl9zZXRfYXR0cmlidXRlczogbm8gd29ya2Zsb3cgcnVuIGlkIGF2YWlsYWJsZSBpbiBzdGVwIGNvbnRleHQnXG4gICAgICApO1xuICAgIH1cblxuICAgIGF3YWl0IHdvcmxkLnJ1bnMuZXhwZXJpbWVudGFsU2V0QXR0cmlidXRlcyhydW5JZCwgY2hhbmdlcywgb3B0aW9ucyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGF0dGVtcHQgPCBJTlRFUk5BTF9BVFRSSUJVVEVTX01BWF9BVFRFTVBUUykge1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuXG4gICAgLy8gRmFpbGluZyB0byBwb3N0IHRhZ3Mgc2hvdWxkIG5vdCBmYWlsIGEgcnVuIGR1cmluZyB0aGUgZXhwZXJpbWVudGFsIHBoYXNlLlxuICAgIC8vIEFmdGVyIHRocmVlIGF0dGVtcHRzLCBsb2cgYW5kIGxldCB0aGUgaW50ZXJuYWwgc3RlcCBjb21wbGV0ZSBzbyB0aGVcbiAgICAvLyBydW50aW1lIGRvZXMgbm90IGNvbnZlcnQgcmV0cnkgZXhoYXVzdGlvbiBpbnRvIGEgRmF0YWxFcnJvci5cbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgYFt3b3JrZmxvd10gc2V0QXR0cmlidXRlczogZmFpbGVkIHRvIHBvc3QgdGFncyBhZnRlciAke0lOVEVSTkFMX0FUVFJJQlVURVNfTUFYX0FUVEVNUFRTfSBhdHRlbXB0czsgZHJvcHBpbmcgdGhlIGludGVybmFsIGF0dHJpYnV0ZSB3cml0ZS4gJHtmb3JtYXRVbmtub3duRXJyb3IoZXJyb3IpfWBcbiAgICApO1xuICB9XG59XG5cbihcbiAgX19idWlsdGluX3NldF9hdHRyaWJ1dGVzIGFzIHR5cGVvZiBfX2J1aWx0aW5fc2V0X2F0dHJpYnV0ZXMgJiB7XG4gICAgbWF4UmV0cmllczogbnVtYmVyO1xuICB9XG4pLm1heFJldHJpZXMgPSBJTlRFUk5BTF9BVFRSSUJVVEVTX01BWF9BVFRFTVBUUyAtIDE7XG4iXX0=
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbHRpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJuYWwvYnVpbHRpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE1BQU0sQ0FBQyxLQUFLLFVBQVUsK0JBQStCO0lBR25ELFVBQVUsQ0FBQztJQUNYLE9BQU8sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0FBQzVCLENBQUM7QUFFRCxNQUFNLENBQUMsS0FBSyxVQUFVLHVCQUF1QjtJQUMzQyxVQUFVLENBQUM7SUFDWCxPQUFPLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNyQixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSx1QkFBdUI7SUFDM0MsVUFBVSxDQUFDO0lBQ1gsT0FBTyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDckIsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sd0JBQXdCLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FDekMsaURBQWlELENBQ2xELENBQUM7QUFFRixNQUFNLGdDQUFnQyxHQUFHLENBQUMsQ0FBQztBQUUzQyxTQUFTLGtCQUFrQixDQUFDLEtBQWM7SUFDeEMsSUFBSSxLQUFLLFlBQVksS0FBSyxFQUFFLENBQUM7UUFDM0IsT0FBTyxLQUFLLENBQUMsS0FBSyxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDMUQsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3ZCLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSx3QkFBd0IsQ0FDNUMsT0FBcUQsRUFDckQsT0FBK0M7SUFFL0MsVUFBVSxDQUFDO0lBQ1gsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPO0lBQ2pDLE1BQU0sQ0FBQyxHQUFHLFVBQXFDLENBQUM7SUFFaEQsTUFBTSxjQUFjLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FTdkQsQ0FBQztJQUNkLE1BQU0sS0FBSyxHQUFHLGNBQWMsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDO0lBQzNDLE1BQU0sT0FBTyxHQUNYLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxPQUFPLEtBQUssUUFBUTtRQUM5QyxDQUFDLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPO1FBQzVCLENBQUMsQ0FBQyxnQ0FBZ0MsQ0FBQztJQUV2QyxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxDQVd2QyxDQUFDO0lBQ2QsSUFBSSxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUseUJBQXlCLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDakUscUVBQXFFO1FBQ3JFLG1FQUFtRTtRQUNuRSxpRUFBaUU7UUFDakUsa0JBQWtCO1FBQ2xCLElBQUksQ0FBQyxDQUFDLENBQUMsd0JBQXdCLENBQUMsRUFBRSxDQUFDO1lBQ2pDLENBQUMsQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLElBQUksQ0FBQztZQUNuQyxNQUFNLFNBQVMsR0FBRyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3hELE9BQU8sQ0FBQyxJQUFJLENBQ1YsNkRBQTZELFNBQVMscU1BQXFNLENBQzVRLENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsYUFBYSxDQUFDO1FBQ3JELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQ2Isd0VBQXdFLENBQ3pFLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixJQUFJLE9BQU8sR0FBRyxnQ0FBZ0MsRUFBRSxDQUFDO1lBQy9DLE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztRQUVELDRFQUE0RTtRQUM1RSxzRUFBc0U7UUFDdEUsK0RBQStEO1FBQy9ELE9BQU8sQ0FBQyxLQUFLLENBQ1gsdURBQXVELGdDQUFnQyxxREFBcUQsa0JBQWtCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FDeEssQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDO0FBR0Msd0JBR0QsQ0FBQyxVQUFVLEdBQUcsZ0NBQWdDLEdBQUcsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCdWlsdC1pbiBzdGVwcyBhdmFpbGFibGUgaW4gdGhlIHdvcmtmbG93IHNjb3BlLiBMaWtlIGEgc3RhbmRhcmQgbGlicmFyeSxcbiAqIHRoZXkgYXJlIGF2YWlsYWJsZSBhbG9uZ3NpZGUgdXNlci1kZWZpbmVkIHN0ZXBzLCBidXQgdXNlcnMgZG8gbm90IGltcG9ydFxuICogdGhlbS4gVGhlIHJ1bnRpbWUgdXNlcyB0aGVzZSBzdGVwcyBpbnRlcm5hbGx5LlxuICovXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBfX2J1aWx0aW5fcmVzcG9uc2VfYXJyYXlfYnVmZmVyKFxuICB0aGlzOiBSZXF1ZXN0IHwgUmVzcG9uc2Vcbikge1xuICAndXNlIHN0ZXAnO1xuICByZXR1cm4gdGhpcy5hcnJheUJ1ZmZlcigpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX19idWlsdGluX3Jlc3BvbnNlX2pzb24odGhpczogUmVxdWVzdCB8IFJlc3BvbnNlKSB7XG4gICd1c2Ugc3RlcCc7XG4gIHJldHVybiB0aGlzLmpzb24oKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9fYnVpbHRpbl9yZXNwb25zZV90ZXh0KHRoaXM6IFJlcXVlc3QgfCBSZXNwb25zZSkge1xuICAndXNlIHN0ZXAnO1xuICByZXR1cm4gdGhpcy50ZXh0KCk7XG59XG5cbi8qKlxuICogUHJvY2Vzcy13aWRlIGRlZHVwZSBmb3IgdGhlIHVuc3VwcG9ydGVkLXdvcmxkIHdhcm5pbmcgc28gaGlnaC12b2x1bWVcbiAqIGNhbGxlcnMgZG9uJ3QgZmxvb2QgbG9ncy5cbiAqL1xuY29uc3QgVU5TVVBQT1JURURfV09STERfV0FSTkVEID0gU3ltYm9sLmZvcihcbiAgJ0B3b3JrZmxvdy9zZXRBdHRyaWJ1dGVzLy91bnN1cHBvcnRlZFdvcmxkV2FybmVkJ1xuKTtcblxuY29uc3QgSU5URVJOQUxfQVRUUklCVVRFU19NQVhfQVRURU1QVFMgPSAzO1xuXG5mdW5jdGlvbiBmb3JtYXRVbmtub3duRXJyb3IoZXJyb3I6IHVua25vd24pIHtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICByZXR1cm4gZXJyb3Iuc3RhY2sgPz8gYCR7ZXJyb3IubmFtZX06ICR7ZXJyb3IubWVzc2FnZX1gO1xuICB9XG4gIHJldHVybiBTdHJpbmcoZXJyb3IpO1xufVxuXG4vKipcbiAqIFN0ZXAgYnJpZGdlIGZvciB3b3JrZmxvdy1ib2R5IGBzZXRBdHRyaWJ1dGVzYCBjYWxscy4gVGhlIFZNLXNpZGVcbiAqIGhlbHBlciB2YWxpZGF0ZXMgaW5wdXQgYW5kIGRpc3BhdGNoZXMgaGVyZSB2aWEgYHVzZVN0ZXBgLiBUaGlzIHN0ZXBcbiAqIHJ1bnMgaW4gbm9ybWFsIE5vZGUgY29udGV4dCB3aXRoIGZ1bGwgd29ybGQgYWNjZXNzLlxuICpcbiAqIFRoZSBkaXNwYXRjaCByZWFkcyB0aGUgd29ybGQgYW5kIGN1cnJlbnQgcnVuIGlkIGRpcmVjdGx5IGZyb21cbiAqIGBnbG9iYWxUaGlzYCBzeW1ib2xzIHBvcHVsYXRlZCBieSB0aGUgd29ya2Zsb3cvc3RlcCBydW50aW1lLiBUaGlzXG4gKiBpbnRlbnRpb25hbGx5IGF2b2lkcyBpbXBvcnRpbmcgYEB3b3JrZmxvdy9jb3JlYCBzbyB0aGUgTmV4dC5qc1xuICogZGVmZXJyZWQtZW50cmllcyBkaXNjb3ZlcmVyIGNhbid0IHdhbGsgYSBjaGFpbiBpbnRvIHdvcmxkIGFkYXB0ZXJzXG4gKiBhbmQgYEB2ZXJjZWwvcXVldWVgIGZyb20gdGhpcyBzdGVwIGZpbGUuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBfX2J1aWx0aW5fc2V0X2F0dHJpYnV0ZXMoXG4gIGNoYW5nZXM6IEFycmF5PHsga2V5OiBzdHJpbmc7IHZhbHVlOiBzdHJpbmcgfCBudWxsIH0+LFxuICBvcHRpb25zPzogeyBhbGxvd1Jlc2VydmVkQXR0cmlidXRlcz86IGJvb2xlYW4gfVxuKSB7XG4gICd1c2Ugc3RlcCc7XG4gIGlmIChjaGFuZ2VzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICBjb25zdCBnID0gZ2xvYmFsVGhpcyBhcyBSZWNvcmQ8c3ltYm9sLCB1bmtub3duPjtcblxuICBjb25zdCBjb250ZXh0U3RvcmFnZSA9IGdbU3ltYm9sLmZvcignV09SS0ZMT1dfU1RFUF9DT05URVhUX1NUT1JBR0UnKV0gYXNcbiAgICB8IHtcbiAgICAgICAgZ2V0U3RvcmU6ICgpID0+XG4gICAgICAgICAgfCB7XG4gICAgICAgICAgICAgIHN0ZXBNZXRhZGF0YT86IHsgYXR0ZW1wdD86IG51bWJlciB9O1xuICAgICAgICAgICAgICB3b3JrZmxvd01ldGFkYXRhPzogeyB3b3JrZmxvd1J1bklkPzogc3RyaW5nIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfCB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfCB1bmRlZmluZWQ7XG4gIGNvbnN0IHN0b3JlID0gY29udGV4dFN0b3JhZ2U/LmdldFN0b3JlPy4oKTtcbiAgY29uc3QgYXR0ZW1wdCA9XG4gICAgdHlwZW9mIHN0b3JlPy5zdGVwTWV0YWRhdGE/LmF0dGVtcHQgPT09ICdudW1iZXInXG4gICAgICA/IHN0b3JlLnN0ZXBNZXRhZGF0YS5hdHRlbXB0XG4gICAgICA6IElOVEVSTkFMX0FUVFJJQlVURVNfTUFYX0FUVEVNUFRTO1xuXG4gIGNvbnN0IHdvcmxkID0gZ1tTeW1ib2wuZm9yKCdAd29ya2Zsb3cvd29ybGQvL2NhY2hlJyldIGFzXG4gICAgfCB7XG4gICAgICAgIG5hbWU/OiBzdHJpbmc7XG4gICAgICAgIHJ1bnM/OiB7XG4gICAgICAgICAgZXhwZXJpbWVudGFsU2V0QXR0cmlidXRlcz86IChcbiAgICAgICAgICAgIHJ1bklkOiBzdHJpbmcsXG4gICAgICAgICAgICBjaGFuZ2VzOiBBcnJheTx7IGtleTogc3RyaW5nOyB2YWx1ZTogc3RyaW5nIHwgbnVsbCB9PixcbiAgICAgICAgICAgIG9wdGlvbnM/OiB7IGFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzPzogYm9vbGVhbiB9XG4gICAgICAgICAgKSA9PiBQcm9taXNlPHVua25vd24+O1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIHwgdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIHdvcmxkPy5ydW5zPy5leHBlcmltZW50YWxTZXRBdHRyaWJ1dGVzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgLy8gV29ybGQgYWRhcHRlciBkb2Vzbid0IGltcGxlbWVudCBhdHRyaWJ1dGVzIHlldCwgc28gbm8tb3AgdGhlIGNhbGwsXG4gICAgLy8gYnV0IGVtaXQgb25lIHByb2Nlc3Mtd2lkZSB3YXJuaW5nIHNvIHVzZXJzIGtub3cgdGhlaXIgd3JpdGVzIGFyZVxuICAgIC8vIGJlaW5nIGRyb3BwZWQuIFRoZSBWTS1zaWRlIHZhbGlkYXRpb24gYWxyZWFkeSByYW4gc28gdGhlIGlucHV0XG4gICAgLy8gaXMgd2VsbC1mb3JtZWQuXG4gICAgaWYgKCFnW1VOU1VQUE9SVEVEX1dPUkxEX1dBUk5FRF0pIHtcbiAgICAgIGdbVU5TVVBQT1JURURfV09STERfV0FSTkVEXSA9IHRydWU7XG4gICAgICBjb25zdCB3b3JsZE5hbWUgPSB3b3JsZD8ubmFtZSA/IGAgKCR7d29ybGQubmFtZX0pYCA6ICcnO1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgW3dvcmtmbG93XSBzZXRBdHRyaWJ1dGVzOiB0aGUgY3VycmVudCB3b3JsZCBpbXBsZW1lbnRhdGlvbiR7d29ybGROYW1lfSBkb2VzIG5vdCBpbXBsZW1lbnQgZXhwZXJpbWVudGFsU2V0QXR0cmlidXRlczsgdGhpcyBjYWxsIChhbmQgYW55IHN1YnNlcXVlbnQgc2V0QXR0cmlidXRlcyBjYWxscyBpbiB0aGlzIHByb2Nlc3MpIGlzIGEgbm8tb3AuIEF0dHJpYnV0ZXMgd2lsbCBiZWNvbWUgYXZhaWxhYmxlIG9uY2UgdGhlIHdvcmxkIGFkYXB0ZXIgYWRkcyBzdXBwb3J0LmBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3QgcnVuSWQgPSBzdG9yZT8ud29ya2Zsb3dNZXRhZGF0YT8ud29ya2Zsb3dSdW5JZDtcbiAgICBpZiAoIXJ1bklkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdfX2J1aWx0aW5fc2V0X2F0dHJpYnV0ZXM6IG5vIHdvcmtmbG93IHJ1biBpZCBhdmFpbGFibGUgaW4gc3RlcCBjb250ZXh0J1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBhd2FpdCB3b3JsZC5ydW5zLmV4cGVyaW1lbnRhbFNldEF0dHJpYnV0ZXMocnVuSWQsIGNoYW5nZXMsIG9wdGlvbnMpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChhdHRlbXB0IDwgSU5URVJOQUxfQVRUUklCVVRFU19NQVhfQVRURU1QVFMpIHtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIC8vIEZhaWxpbmcgdG8gcG9zdCB0YWdzIHNob3VsZCBub3QgZmFpbCBhIHJ1biBkdXJpbmcgdGhlIGV4cGVyaW1lbnRhbCBwaGFzZS5cbiAgICAvLyBBZnRlciB0aHJlZSBhdHRlbXB0cywgbG9nIGFuZCBsZXQgdGhlIGludGVybmFsIHN0ZXAgY29tcGxldGUgc28gdGhlXG4gICAgLy8gcnVudGltZSBkb2VzIG5vdCBjb252ZXJ0IHJldHJ5IGV4aGF1c3Rpb24gaW50byBhIEZhdGFsRXJyb3IuXG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgIGBbd29ya2Zsb3ddIHNldEF0dHJpYnV0ZXM6IGZhaWxlZCB0byBwb3N0IHRhZ3MgYWZ0ZXIgJHtJTlRFUk5BTF9BVFRSSUJVVEVTX01BWF9BVFRFTVBUU30gYXR0ZW1wdHM7IGRyb3BwaW5nIHRoZSBpbnRlcm5hbCBhdHRyaWJ1dGUgd3JpdGUuICR7Zm9ybWF0VW5rbm93bkVycm9yKGVycm9yKX1gXG4gICAgKTtcbiAgfVxufVxuXG4oXG4gIF9fYnVpbHRpbl9zZXRfYXR0cmlidXRlcyBhcyB0eXBlb2YgX19idWlsdGluX3NldF9hdHRyaWJ1dGVzICYge1xuICAgIG1heFJldHJpZXM6IG51bWJlcjtcbiAgfVxuKS5tYXhSZXRyaWVzID0gSU5URVJOQUxfQVRUUklCVVRFU19NQVhfQVRURU1QVFMgLSAxO1xuIl19
@@ -22,7 +22,7 @@ Chat sessions in AI agents can be modeled at different layers of your architectu
22
22
 
23
23
  While there are many ways to model chat sessions, the two most common categories are single-turn and multi-turn.
24
24
 
25
- ## Single-Turn Workflows
25
+ ## Single-turn workflows
26
26
 
27
27
  Each user message triggers a new workflow run. The client or API route owns the conversation history and sends the full message array with each request.
28
28
 
@@ -81,7 +81,7 @@ export async function POST(req: Request) {
81
81
 
82
82
  <Tab value="Client">
83
83
 
84
- Chat messages need to be stored somewheretypically a database. In this example, we assume a route like `/chats/:id` passes the session ID, allowing us to fetch existing messages and persist new ones.
84
+ Chat messages need to be stored somewhere, typically a database. In this example, we assume a route like `/chats/:id` passes the session ID, allowing us to fetch existing messages and persist new ones.
85
85
 
86
86
  ```typescript title="app/chats/[id]/page.tsx" lineNumbers
87
87
  "use client";
@@ -138,14 +138,13 @@ This is the pattern used in the [Building Durable AI Agents](/docs/ai) guide.
138
138
 
139
139
  In this pattern, the client owns conversation state, with the latest turn managed by the AI SDK's `useChat`, and past turns persisted to a user-managed database.
140
140
 
141
- Persisting the turn is usually done through either:
141
+ Persist the turn through one of these methods:
142
142
 
143
- - A step on the workflow that runs after `agent.stream()` and takes the message history from the agent return value (either `messages: ModelMessage[]` or `uiMessages: UIMessage[]`)
144
- - A hook on `useChat`in the client that calls an API to persist state (or localStorage, etc.), either on every new message, or `onFinish`
145
- - The resumable stream attached to the workflow (see [Resumable Streams](/docs/ai/resumable-streams))
146
- - Note that user messages are not persisted to the stream by default, and need to be explicitly persisted separately
143
+ - Run a workflow step after `agent.stream()` that takes the message history from the agent return value (either `messages: ModelMessage[]` or `uiMessages: UIMessage[]`).
144
+ - Use a `useChat` client hook that calls an API to persist state, such as on every new message or in `onFinish`.
145
+ - Use the resumable stream attached to the workflow (see [Resumable streams](/docs/ai/resumable-streams)). User messages are not persisted to the stream by default, so persist them separately.
147
146
 
148
- ## Multi-Turn Workflows
147
+ ## Multi-turn workflows
149
148
 
150
149
  A single workflow handles the entire conversation session across multiple turns, and owns the current conversation state. The clients/API routes inject new messages via hooks. The workflow run ID serves as the session identifier.
151
150
 
@@ -191,7 +190,7 @@ export async function chat(initialMessages: UIMessage[]) {
191
190
  tools: flightBookingTools,
192
191
  });
193
192
 
194
- // Use run ID as the hook token for easy resumption
193
+ // Use run ID as the hook token for resumption
195
194
  const hook = chatMessageHook.create({ token: runId });
196
195
  let turnNumber = 0;
197
196
 
@@ -254,7 +253,7 @@ export async function writeStreamClose(writable: WritableStream<UIMessageChunk>)
254
253
 
255
254
  <Tab value="API Routes">
256
255
 
257
- Three endpoints: start a session, send follow-up messages, and reconnect to the stream.
256
+ Use three endpoints to start a session, send follow-up messages, and reconnect to the stream.
258
257
 
259
258
  ```typescript title="app/api/chat/route.ts" lineNumbers
260
259
  import { createUIMessageStreamResponse, type UIMessage } from "ai";
@@ -493,13 +492,13 @@ In this pattern, the workflow owns the entire conversation session. All messages
493
492
 
494
493
  The client hook processes these markers by:
495
494
 
496
- 1. Iterating through message parts in order
497
- 2. When a `user-message` marker is found, flushing any accumulated assistant content and inserting the user message
498
- 3. Deduplicating against optimistic sends from the initial message
495
+ 1. Iterate through message parts in order.
496
+ 2. When a `user-message` marker is found, flush any accumulated assistant content and insert the user message.
497
+ 3. Deduplicate against optimistic sends from the initial message.
499
498
 
500
499
  This ensures the conversation displays as User → AI → User → AI regardless of whether viewing live or replaying from the stream.
501
500
 
502
- ## Choosing a Pattern
501
+ ## Choosing a pattern
503
502
 
504
503
  | Consideration | Single-Turn | Multi-Turn |
505
504
  |--------------|-------------|------------|
@@ -509,13 +508,13 @@ This ensures the conversation displays as User → AI → User → AI regardless
509
508
  | Workflow time horizon | Minutes | Hours to indefinitely |
510
509
  | Observability scope | Per-turn traces | Full session traces |
511
510
 
512
- **Multi-turn is recommended for most production use-cases.** If you're starting fresh, go with multi-turn. It's more flexible and grows with your requirements. You don't need to maintain the chat history yourself and can offload all that to the workflow's built in persistence. It also enables native message injection and full session observability, which becomes increasingly valuable as your agent matures.
511
+ **Multi-turn is recommended for most production use cases.** For new applications, use multi-turn workflows. The workflow's built-in persistence maintains the chat history and supports native message injection and full-session observability.
513
512
 
514
- **Single-turn works well when adapting existing architectures.** If you already have a system for managing message state, and want to adopt durable agents incrementally, single-turn workflows slot in with minimal changes. Each turn maps cleanly to an independent workflow run.
513
+ **Single-turn works well when adapting existing architectures.** If you already have a system for managing message state and want to adopt durable agents incrementally, single-turn workflows require fewer changes. Each turn maps to an independent workflow run.
515
514
 
516
- ## Multiplayer Chat Sessions
515
+ ## Multiplayer chat sessions
517
516
 
518
- The multi-turn pattern also easily enables multi-player chat sessions. New messages can come from system events, external services, and other users. Since a `hook` injects messages into workflow at any point, and the entire history is a single stream that clients can reconnect to, it doesn't matter where the injected messages come from. Here are different use-cases for multi-player chat sessions:
517
+ The multi-turn pattern also enables multiplayer chat sessions. Messages can come from system events, external services, and other users. A `hook` can inject messages into a workflow at any point, while clients reconnect to one stream containing the entire history.
519
518
 
520
519
  <Tabs items={['System Event', 'External Service', 'Multiple Users']}>
521
520
 
@@ -542,7 +541,7 @@ export async function POST(req: Request) {
542
541
 
543
542
  <Tab value="External Service">
544
543
 
545
- External webhooks from third-party services (Stripe, Twilio, etc.) can notify the conversation of events.
544
+ External webhooks from third-party services, such as Stripe and Twilio, can notify the conversation of events.
546
545
 
547
546
  ```typescript title="app/api/webhooks/payment/route.ts" lineNumbers
548
547
  import { chatMessageHook } from "@/workflows/chat/hooks/chat-message";
@@ -591,9 +590,9 @@ export async function POST(
591
590
 
592
591
  </Tabs>
593
592
 
594
- ## Related Documentation
593
+ ## Related documentation
595
594
 
596
- - [Building Durable AI Agents](/docs/ai) - Foundation guide for durable agents
597
- - [Message Queueing](/docs/ai/message-queueing) - Queueing messages during tool execution
598
- - [`defineHook()` API Reference](/docs/api-reference/workflow/define-hook) - Hook configuration options
599
- - [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) - AI SDK API for durable, resumable agents
595
+ - [Building Durable AI Agents](/docs/ai): Foundation guide for durable agents
596
+ - [Message Queueing](/docs/ai/message-queueing): Queueing messages during tool execution
597
+ - [`defineHook()` API reference](/docs/api-reference/workflow/define-hook): Hook configuration options
598
+ - [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent): AI SDK API for durable, resumable agents
@@ -14,16 +14,15 @@ related:
14
14
 
15
15
  This page covers the details for some common patterns when defining tools for AI agents using Workflow SDK.
16
16
 
17
- Using WorkflowAgent, we model most tools as steps. These can be anything from a simple function call to a entire multi-day long workflow.
17
+ Using WorkflowAgent, we model most tools as steps. These can range from a single function call to an entire multi-day workflow.
18
18
 
19
19
  ## Accessing message context in tools
20
20
 
21
- Just like in regular AI SDK tool definitions, tool in WorkflowAgent are called with a first argument of the tool's input parameters, and a second argument of the tool call context.
21
+ As with regular AI SDK tool definitions, tools in WorkflowAgent receive the tool's input parameters as the first argument and the tool call context as the second.
22
22
 
23
23
  When you tool needs access to the full message history, you can access it via the `messages` property of the tool call context:
24
24
 
25
25
  ```typescript title="tools.ts" lineNumbers
26
- import { Experimental_Agent as Agent } from "ai";
27
26
  import type { ModelMessage } from "ai";
28
27
 
29
28
  async function getWeather(
@@ -34,9 +33,9 @@ async function getWeather(
34
33
  }
35
34
  ```
36
35
 
37
- ## Writing to Streams
36
+ ## Writing to streams
38
37
 
39
- As discussed in [Streaming Updates from Tools](/docs/ai/streaming-updates-from-tools), it's common to use a step just to call `getWritable()` for writing custom data parts to the stream.
38
+ As discussed in [Streaming Updates from Tools](/docs/ai/streaming-updates-from-tools), it's common to use a step only to call `getWritable()` for writing custom data parts to the stream.
40
39
 
41
40
  This can be made generic, by creating a helper step function to write arbitrary data to the stream:
42
41
 
@@ -53,7 +52,7 @@ async function writeToStream(data: any) {
53
52
  }
54
53
  ```
55
54
 
56
- ## Step-Level vs Workflow-Level Tools
55
+ ## Step-level vs workflow-level tools
57
56
 
58
57
  Tools can be implemented either at the step level or the workflow level, with different capabilities and constraints.
59
58
 
@@ -19,7 +19,7 @@ Workflow SDK's [webhook](/docs/api-reference/workflow/create-webhook) and [hook]
19
19
 
20
20
  If you need to react to external events programmatically, see the [hooks](/docs/foundations/hooks) documentation for more information. This part of the guide will focus on the human-in-the-loop pattern, which is a subset of the more general hook pattern.
21
21
 
22
- ## How It Works
22
+ ## How it works
23
23
 
24
24
  <Steps>
25
25
 
@@ -45,9 +45,9 @@ The workflow receives the approval data and resumes execution.
45
45
 
46
46
  </Steps>
47
47
 
48
- While this demo will use a client side button for human approval, you could just as easily create a webhook and send the approval link over email or slack to resume the agent.
48
+ While this demo uses a client-side button for human approval, you could instead create a webhook and send the approval link over email or Slack to resume the agent.
49
49
 
50
- ## Creating a Booking Approval Tool
50
+ ## Creating a booking approval tool
51
51
 
52
52
  Add a tool that allows the agent to deliberately pause execution until a human approves or rejects a flight booking:
53
53
 
@@ -55,7 +55,7 @@ Add a tool that allows the agent to deliberately pause execution until a human a
55
55
 
56
56
  <Step>
57
57
 
58
- ### Define the Hook
58
+ ### Define the hook
59
59
 
60
60
  Create a typed hook with a Zod schema for validation:
61
61
 
@@ -78,7 +78,7 @@ export const bookingApprovalHook = defineHook({
78
78
 
79
79
  <Step>
80
80
 
81
- ### Implement the Tool
81
+ ### Implement the tool
82
82
 
83
83
  Create a tool that creates a hook instance using the tool call ID as the token. The UI will use this ID to submit the approval.
84
84
 
@@ -126,14 +126,14 @@ export const flightBookingTools = {
126
126
  ```
127
127
 
128
128
  <Callout type="info">
129
- Note that the `defineHook().create()` function must be called from within a workflow context, not from within a step. This is why `executeBookingApproval` does not have `"use step"` - it runs in the workflow context where hooks are available.
129
+ Call `defineHook().create()` from within a workflow context, not from within a step. `executeBookingApproval` does not have `"use step"` because it runs in the workflow context where hooks are available.
130
130
  </Callout>
131
131
 
132
132
  </Step>
133
133
 
134
134
  <Step>
135
135
 
136
- ### Create the API Route
136
+ ### Create the API route
137
137
 
138
138
  Create a new API endpoint that the UI will call to submit the approval decision:
139
139
 
@@ -158,7 +158,7 @@ export async function POST(request: Request) {
158
158
 
159
159
  <Step>
160
160
 
161
- ### Create the Approval Component
161
+ ### Create the approval component
162
162
 
163
163
  Build a new component that reacts to the tool call data, and allows the user to approve or reject the booking:
164
164
 
@@ -253,7 +253,7 @@ export function BookingApproval({ toolCallId, input, output }: BookingApprovalPr
253
253
 
254
254
  <Step>
255
255
 
256
- ### Show the Tool Status in the UI
256
+ ### Show the tool status in the UI
257
257
 
258
258
  Use the component we just created to render the tool call and approval controls in your chat interface:
259
259
 
@@ -332,7 +332,7 @@ export default function ChatPage() {
332
332
 
333
333
  </Steps>
334
334
 
335
- ## Using Webhooks Directly
335
+ ## Using webhooks directly
336
336
 
337
337
  For simpler cases where you don't need type-safe validation or programmatic resumption, you can use [`createWebhook()`](/docs/api-reference/workflow/create-webhook) directly. This generates a unique URL that can be called to resume the workflow:
338
338
 
@@ -367,7 +367,7 @@ The webhook URL can be called directly with a POST request containing the approv
367
367
  - Payment provider callbacks
368
368
  - Email-based approval links
369
369
 
370
- ## Related Documentation
370
+ ## Related documentation
371
371
 
372
372
  - [Hooks & Webhooks](/docs/foundations/hooks) - Complete guide to hooks and webhooks
373
373
  - [`createWebhook()` API Reference](/docs/api-reference/workflow/create-webhook) - Webhook configuration options
package/docs/ai/index.mdx CHANGED
@@ -22,7 +22,7 @@ Workflow SDK makes your agents production-ready, by turning them into durable, r
22
22
 
23
23
  This guide walks you through converting a basic AI chat app into a durable AI agent using Workflow SDK.
24
24
 
25
- ## Why Durable Agents?
25
+ ## Why durable agents?
26
26
 
27
27
  Aside from the usual challenges of getting your long-running tasks to be production-ready, building mature AI agents typically requires solving several **additional challenges**:
28
28
 
@@ -31,22 +31,22 @@ Aside from the usual challenges of getting your long-running tasks to be product
31
31
  - **Resumability**: Resuming streams requires not just storing your messages, but also storing streams, and piping them across services.
32
32
  - **Human-in-the-loop**: Your client, API, and async job orchestration need to work together to create, track, route to, and display human approval requests, or similar webhook operations.
33
33
 
34
- Workflow SDK provides all of these capabilities out of the box. Your agent becomes a workflow, your tools become steps, and the framework handles interplay with your existing infrastructure.
34
+ Workflow SDK provides all of these capabilities without additional infrastructure. Your agent becomes a workflow, your tools become steps, and the framework handles interplay with your existing infrastructure.
35
35
 
36
- ## Getting Started
36
+ ## Getting started
37
37
 
38
38
  To make an Agent durable, we first need an Agent, which we'll be setting up here. If you already have an app you'd like to follow along with, you can skip this section.
39
39
 
40
- For our example, we'll need an app with a simple chat interface and an API route calling an LLM, so that we can add Workflow SDK to it. We'll use the [Flight Booking Agent](https://github.com/vercel/workflow-examples/tree/main/flight-booking-app) example as a starting point, which comes with a chat interface built using Next.js, AI SDK, and Shadcn UI.
40
+ For our example, we'll need an app with a basic chat interface and an API route calling an LLM, so that we can add Workflow SDK to it. We'll use the [Flight Booking Agent](https://github.com/vercel/workflow-examples/tree/main/flight-booking-app) example as a starting point, which comes with a chat interface built using Next.js, AI SDK, and Shadcn UI.
41
41
 
42
42
  <Steps>
43
43
 
44
44
  <Step>
45
45
  ### Clone example app
46
46
 
47
- We'll need an app with a simple chat interface and an API route calling an LLM, so that we can add Workflow SDK to it. For the follow-along steps, we'll use the [Flight Booking Agent](https://github.com/vercel/workflow-examples/tree/main/flight-booking-app) example as a starting point, which comes with a chat interface built using Next.js, AI SDK, and Shadcn UI.
47
+ We'll need an app with a basic chat interface and an API route calling an LLM, so that we can add Workflow SDK to it. For the follow-along steps, we'll use the [Flight Booking Agent](https://github.com/vercel/workflow-examples/tree/main/flight-booking-app) example as a starting point, which comes with a chat interface built using Next.js, AI SDK, and Shadcn UI.
48
48
 
49
- If you have your own project, you can skip this step, and simply apply the changes of the following steps to your own project.
49
+ If you have your own project, skip this step and apply the changes in the following steps to your project.
50
50
 
51
51
  ```bash
52
52
  git clone https://github.com/vercel/workflow-examples -b plain-ai-sdk
@@ -59,7 +59,7 @@ cd workflow-examples/flight-booking-app
59
59
 
60
60
  ### Set up API keys
61
61
 
62
- In order to connect to an LLM, we'll need to set up an API key. The easiest way to do this is to use Vercel Gateway (works with all providers at zero markup), or you can configure a custom provider.
62
+ To connect to an LLM, set up an API key. You can use Vercel Gateway, which works with all providers at zero markup, or configure a custom provider.
63
63
  <Tabs items={['Gateway', 'Custom Provider']}>
64
64
 
65
65
  <Tab value="Gateway">
@@ -113,15 +113,15 @@ export async function POST(req: Request) {
113
113
 
114
114
  ### Get familiar with the code
115
115
 
116
- Let's take a moment to see what we're working with. Run the app with `npm run dev` and open [http://localhost:3000](http://localhost:3000) in your browser. You should see a simple chat interface to play with. Go ahead and give it a try.
116
+ Run the app with `npm run dev` and open [http://localhost:3000](http://localhost:3000) in your browser. You should see a basic chat interface to test.
117
117
 
118
- The core code that makes all of this happen is quite simple. Here's a breakdown of the main parts. Note that there's no changes needed here, we're simply taking a look at the code to understand what's happening.
118
+ The following sections break down the core code. You don't need to make changes yet.
119
119
 
120
120
  <Tabs items={['API Route', 'Tools', 'Client']}>
121
121
 
122
122
  <Tab value="API Route">
123
123
 
124
- Our API route makes a simple call to [AI SDK's `ToolLoopAgent` class](https://ai-sdk.dev/docs/agents/overview), which encapsulates the LLM call, tool execution loop, and stopping conditions on top of [AI SDK's `streamText` function](https://ai-sdk.dev/docs/reference/ai-sdk-core/stream-text#streamtext). This is also where we pass tools to the agent.
124
+ Our API route calls [AI SDK's `ToolLoopAgent` class](https://ai-sdk.dev/docs/agents/overview), which encapsulates the LLM call, tool execution loop, and stopping conditions on top of [AI SDK's `streamText` function](https://ai-sdk.dev/docs/reference/ai-sdk-core/stream-text#streamtext). This is also where we pass tools to the agent.
125
125
 
126
126
  ```typescript title="app/api/chat/route.ts" lineNumbers
127
127
  import { ToolLoopAgent } from "ai";
@@ -170,7 +170,7 @@ async function searchFlights({ from, to, date }: { from: string; to: string; dat
170
170
 
171
171
  <Tab value="Client">
172
172
 
173
- Our `ChatPage` component has a lot of logic for nicely displaying the chat messages, but at it's core, it's simply managing input/output for the [`useChat` hook](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat#usechat) from AI SDK.
173
+ Our `ChatPage` component contains logic for displaying chat messages, but its core responsibility is managing input and output for the [`useChat` hook](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat#usechat) from AI SDK.
174
174
 
175
175
  ```typescript title="app/chat.tsx" lineNumbers
176
176
  "use client";
@@ -228,7 +228,7 @@ Now that we have a basic agent using AI SDK, we can modify it to make it durable
228
228
  <Steps>
229
229
  <Step>
230
230
 
231
- ### Install Dependencies
231
+ ### Install dependencies
232
232
 
233
233
  Add the Workflow SDK packages to your project:
234
234
 
@@ -253,7 +253,7 @@ export default withWorkflow(nextConfig);
253
253
 
254
254
  <Step>
255
255
 
256
- ### Create a Workflow Function
256
+ ### Create a workflow function
257
257
 
258
258
  Move the agent logic into a separate function, which will serve as our workflow definition.
259
259
 
@@ -272,7 +272,7 @@ export async function chatWorkflow(messages: UIMessage[]) {
272
272
 
273
273
  const agent = new WorkflowAgent({ // [!code highlight]
274
274
 
275
- // If using AI Gateway, just specify the model name as a string:
275
+ // If using AI Gateway, specify the model name as a string:
276
276
  model: "bedrock/claude-4-5-haiku-20251001-v1", // [!code highlight]
277
277
 
278
278
  // ELSE if using a custom provider, pass the provider call as an argument:
@@ -300,7 +300,7 @@ Key changes:
300
300
  </Step>
301
301
 
302
302
  <Step>
303
- ### Update the API Route
303
+ ### Update the API route
304
304
 
305
305
  Remove the agent call that we just extracted, and replace it with a call to `start()` to run the workflow:
306
306
 
@@ -330,7 +330,7 @@ Key changes:
330
330
  </Step>
331
331
 
332
332
  <Step>
333
- ### Convert Tools to Steps
333
+ ### Convert tools to steps
334
334
 
335
335
  Mark all tool definitions with `"use step"` to make them durable. This enables automatic retries and observability for each tool call:
336
336
 
@@ -389,7 +389,7 @@ With `"use step"`:
389
389
 
390
390
  </Steps>
391
391
 
392
- That's all you need to do to convert your basic AI SDK agent into a durable agent. If you run your development server, and send a chat message, you should see your agent respond just as before, but now with added durability and observability.
392
+ Your basic AI SDK agent is now durable. Run your development server and send a chat message. The agent should respond as before, with added durability and observability.
393
393
 
394
394
  ## Observability
395
395
 
@@ -401,7 +401,7 @@ npx workflow web
401
401
 
402
402
  This opens a local dashboard showing all workflow runs and their status, as well as a trace viewer to inspect the workflow in detail, including retry attempts, and the data being passed between steps.
403
403
 
404
- ## Next Steps
404
+ ## Next steps
405
405
 
406
406
  Now that you have a basic durable agent, it's a only a short step to add these additional features:
407
407
 
@@ -420,11 +420,11 @@ Now that you have a basic durable agent, it's a only a short step to add these a
420
420
  </Card>
421
421
  </Cards>
422
422
 
423
- ## Complete Example
423
+ ## Complete example
424
424
 
425
425
  A complete example that includes all of the above, plus all of the "next steps" features is available on the main branch of the [Flight Booking Agent](https://github.com/vercel/workflow-examples/tree/main/flight-booking-app) example.
426
426
 
427
- ## Related Documentation
427
+ ## Related documentation
428
428
 
429
429
  - [Tools](/docs/ai/defining-tools) - Patterns for defining tools for your agent
430
430
  - [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) - AI SDK API for durable, resumable agents
@@ -15,7 +15,7 @@ When using [multi-turn workflows](/docs/ai/chat-session-modeling#multi-turn-work
15
15
 
16
16
  `WorkflowAgent`'s `prepareStep` callback enables this by running before each step in the agent loop, giving you a chance to inject queued messages into the conversation. `prepareStep` also allows you to modify the model choice and existing messages mid-turn, see AI SDK's [prepareStep callback](https://ai-sdk.dev/docs/agents/loop-control#prepare-step) for more details.
17
17
 
18
- ## When to Use This
18
+ ## When to use this
19
19
 
20
20
  Message queueing is useful when:
21
21
 
@@ -24,10 +24,10 @@ Message queueing is useful when:
24
24
  - You want messages to influence the agent's next step rather than waiting for the current turn to complete
25
25
 
26
26
  <Callout type="info">
27
- If you just need basic multi-turn conversations where messages arrive between turns, see [Chat Session Modeling](/docs/ai/chat-session-modeling). This guide covers the more advanced case of injecting messages *during* turns.
27
+ If you need basic multi-turn conversations where messages arrive between turns, see [Chat Session Modeling](/docs/ai/chat-session-modeling). This guide covers the more advanced case of injecting messages *during* turns.
28
28
  </Callout>
29
29
 
30
- ## The `prepareStep` Callback
30
+ ## The `prepareStep` callback
31
31
 
32
32
  The `prepareStep` callback runs before each step in the agent loop. It receives the current state and can modify the messages sent to the model:
33
33
 
@@ -47,7 +47,7 @@ interface PrepareStepResult {
47
47
  }
48
48
  ```
49
49
 
50
- ## Injecting Queued Messages
50
+ ## Injecting queued messages
51
51
 
52
52
  Once you have a [multi-turn workflow](/docs/ai/chat-session-modeling#multi-turn-workflows), you can combine a message queue with `prepareStep` to inject messages that arrive during processing:
53
53
 
@@ -106,7 +106,7 @@ Messages sent via `chatMessageHook.resume()` accumulate in the queue and get inj
106
106
  The `prepareStep` callback receives messages in `ModelMessage[]` format (with content arrays), which is the internal format used by the AI SDK.
107
107
  </Callout>
108
108
 
109
- ## Combining with Multi-Turn Sessions
109
+ ## Combining with multi-turn sessions
110
110
 
111
111
  You can also combine message queueing with the standard multi-turn pattern:
112
112
 
@@ -169,7 +169,7 @@ export async function chat(initialMessages: ModelMessage[]) {
169
169
  }
170
170
  ```
171
171
 
172
- ## Related Documentation
172
+ ## Related documentation
173
173
 
174
174
  - [Chat Session Modeling](/docs/ai/chat-session-modeling) - Single-turn vs multi-turn patterns
175
175
  - [Building Durable AI Agents](/docs/ai) - Complete guide to creating durable agents
package/docs/ai/meta.json CHANGED
@@ -7,6 +7,7 @@
7
7
  "sleep-and-delays",
8
8
  "human-in-the-loop",
9
9
  "defining-tools",
10
+ "message-queueing",
10
11
  "chat-session-modeling"
11
12
  ],
12
13
  "defaultOpen": true