agents 0.16.1 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/dist/{agent-tool-types-NofdbL9X.d.ts → agent-tool-types-Cd1TZPfB.d.ts} +595 -137
- package/dist/agent-tool-types.d.ts +34 -18
- package/dist/agent-tool-types.js +20 -1
- package/dist/agent-tool-types.js.map +1 -0
- package/dist/agent-tools-BXlsuX0d.js +304 -0
- package/dist/agent-tools-BXlsuX0d.js.map +1 -0
- package/dist/agent-tools-_E8wxUIK.d.ts +119 -0
- package/dist/agent-tools.d.ts +24 -18
- package/dist/agent-tools.js.map +1 -1
- package/dist/ai-chat-agent.d.ts +1 -1
- package/dist/ai-chat-agent.js +1 -2
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.d.ts +1 -1
- package/dist/ai-chat-v5-migration.js +1 -2
- package/dist/ai-chat-v5-migration.js.map +1 -1
- package/dist/ai-react.d.ts +1 -1
- package/dist/ai-react.js +1 -2
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +1 -7
- package/dist/ai-types.js +2 -8
- package/dist/ai-types.js.map +1 -1
- package/dist/browser/ai.js +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/chat/index.d.ts +1923 -76
- package/dist/chat/index.js +1784 -278
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +602 -0
- package/dist/chat/react.js +1506 -0
- package/dist/chat/react.js.map +1 -0
- package/dist/chat-sdk/index.d.ts +4 -4
- package/dist/{classPrivateFieldGet2-CZ7QjTXN.js → classPrivateFieldGet2-DZBYAB34.js} +5 -5
- package/dist/{classPrivateMethodInitSpec-D-0__zd9.js → classPrivateMethodInitSpec-qMjJ6sHQ.js} +2 -2
- package/dist/{client-FUizKzj2.js → client-BZ-B3NhC.js} +19 -3
- package/dist/client-BZ-B3NhC.js.map +1 -0
- package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
- package/dist/client.d.ts +76 -57
- package/dist/client.js +33 -5
- package/dist/client.js.map +1 -1
- package/dist/{compaction-helpers-DVcu5lPN.d.ts → compaction-helpers-wUz6M3us.d.ts} +20 -1
- package/dist/{connector-CrKhowfD.js → connector-CdldGF3h.js} +5 -5
- package/dist/{connector-CrKhowfD.js.map → connector-CdldGF3h.js.map} +1 -1
- package/dist/email.js +1 -1
- package/dist/email.js.map +1 -1
- package/dist/experimental/memory/session/index.d.ts +1 -1
- package/dist/experimental/memory/session/index.js +20 -2
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/experimental/memory/utils/index.d.ts +1 -1
- package/dist/{index-B7IbEeze.d.ts → index-CcbnKkNh.d.ts} +188 -14
- package/dist/index.d.ts +91 -71
- package/dist/index.js +562 -24
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +18 -14
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/index.d.ts +30 -30
- package/dist/mcp/index.js +7 -7
- package/dist/mcp/index.js.map +1 -1
- package/dist/{agent-tools-3zLG7MgA.js → message-builder-BymO4N_D.js} +45 -126
- package/dist/message-builder-BymO4N_D.js.map +1 -0
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.js +4 -2
- package/dist/observability/index.js.map +1 -1
- package/dist/react.d.ts +123 -110
- package/dist/react.js +44 -11
- package/dist/react.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/skills/compile.js +1 -1
- package/dist/skills/compile.js.map +1 -1
- package/dist/skills/index.js +5 -5
- package/dist/skills/index.js.map +1 -1
- package/dist/sub-routing.d.ts +6 -6
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/vite.js +5 -5
- package/dist/vite.js.map +1 -1
- package/dist/wire-types-nflOzNuU.js +240 -0
- package/dist/wire-types-nflOzNuU.js.map +1 -0
- package/dist/{workflow-types-SrZK_o9p.d.ts → workflow-types-Baz_PO5v.d.ts} +42 -22
- package/dist/workflow-types.d.ts +25 -21
- package/dist/workflow-types.js.map +1 -1
- package/dist/workflows.d.ts +22 -21
- package/dist/workflows.js +31 -7
- package/dist/workflows.js.map +1 -1
- package/docs/adding-to-existing-project.md +450 -0
- package/docs/agent-class.md +503 -0
- package/docs/agent-tools.md +552 -0
- package/docs/browse-the-web.md +430 -0
- package/docs/callable-methods.md +627 -0
- package/docs/chat-agents.md +1687 -0
- package/docs/chat-sdk.md +181 -0
- package/docs/client-sdk.md +520 -0
- package/docs/client-tools-continuation.md +177 -0
- package/docs/codemode.md +440 -0
- package/docs/configuration.md +775 -0
- package/docs/cross-domain-authentication.md +171 -0
- package/docs/durable-execution.md +537 -0
- package/docs/email.md +663 -0
- package/docs/get-current-agent.md +204 -0
- package/docs/getting-started.md +305 -0
- package/docs/http-websockets.md +668 -0
- package/docs/human-in-the-loop.md +661 -0
- package/docs/index.md +151 -0
- package/docs/long-running-agents.md +730 -0
- package/docs/mcp-client.md +620 -0
- package/docs/mcp-servers.md +526 -0
- package/docs/mcp-transports.md +308 -0
- package/docs/migration-to-ai-sdk-v5.md +96 -0
- package/docs/migration-to-ai-sdk-v6.md +163 -0
- package/docs/observability.md +261 -0
- package/docs/push-notifications.md +367 -0
- package/docs/queue.md +329 -0
- package/docs/readonly-connections.md +278 -0
- package/docs/resumable-streaming.md +127 -0
- package/docs/retries.md +444 -0
- package/docs/routing.md +749 -0
- package/docs/scheduling.md +898 -0
- package/docs/securing-mcp-servers.md +359 -0
- package/docs/server-driven-messages.md +477 -0
- package/docs/sessions.md +1024 -0
- package/docs/state.md +512 -0
- package/docs/sub-agents.md +389 -0
- package/docs/webhooks.md +604 -0
- package/docs/workflows.md +877 -0
- package/package.json +47 -15
- package/dist/agent-tools-3zLG7MgA.js.map +0 -1
- package/dist/agent-tools-DLquv-dp.d.ts +0 -14
- package/dist/client-FUizKzj2.js.map +0 -1
package/dist/vite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","names":["parseYaml"],"sources":["../src/vite.ts"],"sourcesContent":["import babel from \"@rolldown/plugin-babel\";\nimport { createHash } from \"node:crypto\";\nimport { readdir, readFile, stat } from \"node:fs/promises\";\nimport { basename, join, resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { Plugin } from \"vite\";\nimport { compileSkillScript, isCompilableSkillScript } from \"./skills/compile\";\n\nconst SKILLS_SPECIFIER = \"agents:skills\";\nconst SKILLS_VIRTUAL_PREFIX = \"\\0agents:skills:\";\nconst SKILL_RESOURCE_ROOTS = new Set([\n \"references\",\n \"scripts\",\n \"assets\",\n \"graphics\",\n \"fonts\",\n \"templates\",\n \"rendered-files\",\n \"illustrations\"\n]);\nconst SKILL_IGNORED_ROOTS = new Set([\n \".git\",\n \".hg\",\n \".svn\",\n \".DS_Store\",\n \".idea\",\n \".vscode\",\n \"dist\",\n \"build\",\n \"coverage\",\n \"node_modules\"\n]);\nconst SPEC_RESOURCE_ROOTS = new Set([\"references\", \"scripts\", \"assets\"]);\n\n// Bundled skill resources are base64-embedded into the Worker bundle, which\n// inflates them by ~1.33x and competes with app code for the bundle-size\n// budget. These heuristic thresholds (raw bytes) trigger a recommendation to\n// move large assets to an R2-backed skill source instead.\nconst SKILL_ASSET_WARN_BYTES = 256 * 1024;\nconst SKILL_BUNDLE_WARN_BYTES = 1024 * 1024;\n\nfunction formatBytes(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(0)}KB`;\n return `${bytes}B`;\n}\n\ninterface SkillFile {\n name: string;\n description: string;\n body: string;\n rawContent: string;\n compatibility?: string;\n license?: string;\n allowedTools?: string;\n metadata?: Record<string, unknown>;\n resources: Array<{\n path: string;\n kind: \"reference\" | \"script\" | \"asset\" | \"file\";\n size: number;\n encoding: \"text\" | \"base64\";\n mimeType?: string;\n content: string;\n precompiled?: boolean;\n }>;\n}\n\nfunction parseFrontmatter(raw: string): {\n data: Record<string, unknown>;\n body: string;\n} {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) return { data: {}, body: raw };\n const parsed = parseYaml(match[1] ?? \"\");\n const data =\n parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n return { data, body: match[2] ?? \"\" };\n}\n\nfunction stringField(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction recordField(value: unknown): Record<string, unknown> | undefined {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction resourceKind(path: string): \"reference\" | \"script\" | \"asset\" | \"file\" {\n if (path.startsWith(\"references/\")) return \"reference\";\n if (path.startsWith(\"scripts/\")) return \"script\";\n if (\n path.startsWith(\"assets/\") ||\n path.startsWith(\"graphics/\") ||\n path.startsWith(\"fonts/\") ||\n path.startsWith(\"templates/\") ||\n path.startsWith(\"rendered-files/\") ||\n path.startsWith(\"illustrations/\")\n ) {\n return \"asset\";\n }\n return \"file\";\n}\n\nconst TEXT_EXTENSIONS = new Set([\n \".bash\",\n \".css\",\n \".csv\",\n \".html\",\n \".js\",\n \".json\",\n \".jsx\",\n \".md\",\n \".mjs\",\n \".py\",\n \".sh\",\n \".svg\",\n \".ts\",\n \".tsx\",\n \".txt\",\n \".xml\",\n \".yaml\",\n \".yml\"\n]);\n\nconst MIME_TYPES = new Map([\n [\".css\", \"text/css\"],\n [\".gif\", \"image/gif\"],\n [\".html\", \"text/html\"],\n [\".jpg\", \"image/jpeg\"],\n [\".jpeg\", \"image/jpeg\"],\n [\".js\", \"text/javascript\"],\n [\".json\", \"application/json\"],\n [\".md\", \"text/markdown\"],\n [\".mjs\", \"text/javascript\"],\n [\".pdf\", \"application/pdf\"],\n [\".png\", \"image/png\"],\n [\".py\", \"text/x-python\"],\n [\".sh\", \"text/x-shellscript\"],\n [\".svg\", \"image/svg+xml\"],\n [\".ts\", \"text/typescript\"],\n [\".tsx\", \"text/typescript\"],\n [\".txt\", \"text/plain\"],\n [\".webp\", \"image/webp\"],\n [\".woff\", \"font/woff\"],\n [\".woff2\", \"font/woff2\"],\n [\".xml\", \"application/xml\"],\n [\".yaml\", \"application/yaml\"],\n [\".yml\", \"application/yaml\"]\n]);\n\nfunction extensionOf(path: string): string {\n const file = path.split(\"/\").at(-1) ?? path;\n const index = file.lastIndexOf(\".\");\n return index === -1 ? \"\" : file.slice(index).toLowerCase();\n}\n\nfunction resourceEncoding(path: string): \"text\" | \"base64\" {\n return TEXT_EXTENSIONS.has(extensionOf(path)) ? \"text\" : \"base64\";\n}\n\nfunction resourceMimeType(path: string): string | undefined {\n return MIME_TYPES.get(extensionOf(path));\n}\n\nasync function collectFiles(\n root: string,\n relativeRoot = \"\",\n warn?: (message: string) => void\n): Promise<Array<{ path: string; absolutePath: string; size: number }>> {\n const entries = await readdir(join(root, relativeRoot), {\n withFileTypes: true\n }).catch(() => []);\n const files: Array<{ path: string; absolutePath: string; size: number }> = [];\n\n for (const entry of entries) {\n if (SKILL_IGNORED_ROOTS.has(entry.name)) continue;\n const relativePath = relativeRoot\n ? `${relativeRoot}/${entry.name}`\n : entry.name;\n const absolutePath = join(root, relativePath);\n if (entry.isDirectory()) {\n const resourceRoot = relativePath.split(\"/\")[0];\n if (!resourceRoot || SKILL_IGNORED_ROOTS.has(resourceRoot)) continue;\n if (!SKILL_RESOURCE_ROOTS.has(resourceRoot)) {\n if (!relativeRoot) {\n warn?.(\n `Ignoring skill directory \"${relativePath}\". Bundled skill resources should live under references/, scripts/, assets/, or a known asset root.`\n );\n }\n continue;\n }\n if (!SPEC_RESOURCE_ROOTS.has(resourceRoot) && !relativeRoot) {\n warn?.(\n `Bundling non-standard skill resource root \"${resourceRoot}/\". Prefer assets/ for portable Agent Skills when possible.`\n );\n }\n files.push(...(await collectFiles(root, relativePath, warn)));\n } else if (entry.isFile() && relativePath !== \"SKILL.md\") {\n const resourceRoot = relativePath.split(\"/\")[0];\n if (!resourceRoot || SKILL_IGNORED_ROOTS.has(resourceRoot)) continue;\n if (!SKILL_RESOURCE_ROOTS.has(resourceRoot)) {\n warn?.(\n `Ignoring skill file \"${relativePath}\". Bundled skill resources should live under references/, scripts/, assets/, or a known asset root.`\n );\n continue;\n }\n const info = await stat(absolutePath);\n files.push({ path: relativePath, absolutePath, size: info.size });\n }\n }\n\n return files.sort((a, b) => a.path.localeCompare(b.path));\n}\n\nasync function collectWatchTargets(\n root: string,\n relativeRoot = \"\"\n): Promise<string[]> {\n const directory = join(root, relativeRoot);\n const entries = await readdir(directory, { withFileTypes: true }).catch(\n () => []\n );\n const targets = [directory];\n\n for (const entry of entries) {\n if (SKILL_IGNORED_ROOTS.has(entry.name)) continue;\n const relativePath = relativeRoot\n ? `${relativeRoot}/${entry.name}`\n : entry.name;\n const resourceRoot = relativePath.split(\"/\")[0];\n if (!resourceRoot || SKILL_IGNORED_ROOTS.has(resourceRoot)) continue;\n\n const absolutePath = join(root, relativePath);\n targets.push(absolutePath);\n\n if (entry.isDirectory()) {\n targets.push(...(await collectWatchTargets(root, relativePath)));\n }\n }\n\n return targets;\n}\n\nasync function readSkill(\n skillDir: string,\n warn?: (message: string) => void\n): Promise<SkillFile | null> {\n const skillPath = join(skillDir, \"SKILL.md\");\n const rawContent = await readFile(skillPath, \"utf8\").catch(() => null);\n if (rawContent === null) return null;\n\n const { data, body } = parseFrontmatter(rawContent);\n const name = stringField(data.name);\n const description = stringField(data.description);\n if (!name || !description) return null;\n\n const resources = await Promise.all(\n (await collectFiles(skillDir, \"\", warn)).map(async (file) => {\n const encoding = resourceEncoding(file.path);\n const bytes = await readFile(file.absolutePath);\n const kind = resourceKind(file.path);\n let content =\n encoding === \"base64\" ? bytes.toString(\"base64\") : bytes.toString();\n let precompiled = false;\n\n // Compile text script resources to self-contained JS at build time so the\n // runtime never needs an in-Worker bundler to run them.\n let size = file.size;\n if (\n kind === \"script\" &&\n encoding === \"text\" &&\n isCompilableSkillScript(file.path)\n ) {\n try {\n content = (await compileSkillScript(file.absolutePath)).content;\n precompiled = true;\n // The compiled bundle (which may inline sibling files and bundled\n // dependencies) is what actually ships, so report its size for the\n // bundle-size warnings rather than the raw source size.\n size = Buffer.byteLength(content);\n } catch (error) {\n warn?.(\n `Failed to compile skill script \"${file.path}\": ${\n error instanceof Error ? error.message : String(error)\n }. Skill scripts must be self-contained, compilable modules to run at runtime.`\n );\n }\n }\n\n return {\n path: file.path,\n kind,\n size,\n encoding,\n mimeType: resourceMimeType(file.path),\n content,\n precompiled\n };\n })\n );\n\n return {\n name,\n description,\n body,\n rawContent,\n compatibility: stringField(data.compatibility),\n license: stringField(data.license),\n allowedTools: stringField(data[\"allowed-tools\"]),\n metadata: recordField(data.metadata),\n resources\n };\n}\n\nasync function buildSkillsModule(\n dir: string,\n warn?: (message: string) => void\n): Promise<string> {\n const entries = await readdir(dir, { withFileTypes: true });\n const skills: SkillFile[] = [];\n const seen = new Set<string>();\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skill = await readSkill(join(dir, entry.name), warn);\n if (!skill) continue;\n if (seen.has(skill.name)) {\n warn?.(\n `Duplicate bundled skill name \"${skill.name}\" in \"${entry.name}/\"; keeping the first occurrence and ignoring this one.`\n );\n continue;\n }\n seen.add(skill.name);\n skills.push(skill);\n }\n\n skills.sort((a, b) => a.name.localeCompare(b.name));\n\n let totalBytes = 0;\n for (const skill of skills) {\n for (const resource of skill.resources) {\n totalBytes += resource.size;\n if (resource.size > SKILL_ASSET_WARN_BYTES) {\n warn?.(\n `Bundled skill resource \"${skill.name}/${resource.path}\" is ${formatBytes(resource.size)}; large assets bloat the Worker bundle (base64, ~1.33x). Prefer an R2-backed source via skills.r2().`\n );\n }\n }\n }\n if (totalBytes > SKILL_BUNDLE_WARN_BYTES) {\n warn?.(\n `Bundled skills total ${formatBytes(totalBytes)} of embedded resources; this competes with the Worker bundle-size budget. Consider serving large skills from R2 via skills.r2().`\n );\n }\n\n const hash = createHash(\"sha256\");\n hash.update(JSON.stringify(skills));\n\n const manifest = {\n id: `bundle:${basename(dir)}`,\n fingerprint: hash.digest(\"hex\"),\n skills\n };\n\n return `const manifest = ${JSON.stringify(manifest)};\\nexport default {\\n id: manifest.id,\\n fingerprint: manifest.fingerprint,\\n async list() {\\n return manifest.skills.map(({ body, rawContent, resources, ...skill }) => skill);\\n },\\n async load(name) {\\n const skill = manifest.skills.find((entry) => entry.name === name);\\n if (!skill) return null;\\n return {\\n ...skill,\\n resources: skill.resources.map(({ content, ...resource }) => resource)\\n };\\n },\\n async readResource(name, path) {\\n const skill = manifest.skills.find((entry) => entry.name === name);\\n const resource = skill?.resources.find((entry) => entry.path === path);\\n return resource ? { ...resource } : null;\\n }\\n};\\n`;\n}\n\nconst TURNDOWN_STUB_ID = \"\\0agents:turndown-stub\";\n\n// `just-bash` (pulled in by the workspace bash tool / skill runner) statically\n// depends on `turndown`, whose ESM build runs a top-level `require()` on its\n// Node DOM fallback. Workers is ESM with no global `require`, so the module\n// throws at startup — even when the bash tool is never used. turndown is only\n// needed by just-bash's niche `html-to-markdown` command, so we replace it with\n// an inert stub by default to keep Workers deploys clean. Opt out with\n// `agents({ stubTurndown: false })` if you rely on turndown elsewhere.\nfunction turndownStubPlugin(): Plugin {\n return {\n name: \"agents-turndown-stub\",\n enforce: \"pre\",\n resolveId(source) {\n if (source === \"turndown\") return TURNDOWN_STUB_ID;\n return null;\n },\n load(id) {\n if (id !== TURNDOWN_STUB_ID) return null;\n return `class TurndownService {\n constructor() {}\n use() { return this; }\n addRule() { return this; }\n keep() { return this; }\n remove() { return this; }\n turndown() { return \"\"; }\n}\nexport default TurndownService;\n`;\n }\n };\n}\n\nfunction skillsImportPlugin(): Plugin {\n return {\n name: \"agents-skills-import\",\n async resolveId(source, importer) {\n // `agents:skills` resolves to a `./skills` directory next to the\n // importer; `agents:skills/<dir>` points at a sibling directory.\n if (\n source !== SKILLS_SPECIFIER &&\n !source.startsWith(`${SKILLS_SPECIFIER}/`)\n ) {\n return null;\n }\n if (!importer) return null;\n const relative =\n source === SKILLS_SPECIFIER\n ? \"skills\"\n : source.slice(SKILLS_SPECIFIER.length + 1);\n const resolved = resolve(importer, \"..\", relative);\n return `${SKILLS_VIRTUAL_PREFIX}${resolved}`;\n },\n async load(id) {\n if (!id.startsWith(SKILLS_VIRTUAL_PREFIX)) return null;\n const dir = id.slice(SKILLS_VIRTUAL_PREFIX.length);\n for (const target of await collectWatchTargets(dir)) {\n this.addWatchFile(target);\n }\n return buildSkillsModule(dir, (message) => this.warn(message));\n }\n };\n}\n\nexport interface AgentsPluginOptions {\n /**\n * Replace `turndown` with an inert stub so `just-bash` (workspace bash tool /\n * skill runner) doesn't drag turndown's `require()`-using DOM fallback into\n * the Worker's module-init path and break deploys. Enabled by default. Set to\n * `false` if your app uses turndown directly and needs the real\n * implementation.\n */\n stubTurndown?: boolean;\n}\n\n/**\n * Vite plugin for Agents SDK projects.\n *\n * Handles TC39 decorator transforms (Oxc doesn't support them yet, oxc#9170) so\n * `@callable()` works at runtime, the `agents:skills` import transform, and\n * stubbing `turndown` to keep Workers deploys clean. Will grow to cover other\n * Agents-specific build concerns as needed.\n */\nexport default function agents(options: AgentsPluginOptions = {}): Plugin[] {\n const { stubTurndown = true } = options;\n return [\n ...(stubTurndown ? [turndownStubPlugin()] : []),\n skillsImportPlugin(),\n babel({\n presets: [\n {\n preset: () => ({\n plugins: [\n [\"@babel/plugin-proposal-decorators\", { version: \"2023-11\" }]\n ]\n }),\n rolldown: { filter: { code: \"@\" } }\n }\n ]\n }) as unknown as Plugin\n ];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vite.js","names":["parseYaml"],"sources":["../src/vite.ts"],"sourcesContent":["import babel from \"@rolldown/plugin-babel\";\nimport { createHash } from \"node:crypto\";\nimport { readdir, readFile, stat } from \"node:fs/promises\";\nimport { basename, join, resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { Plugin } from \"vite\";\nimport { compileSkillScript, isCompilableSkillScript } from \"./skills/compile\";\n\nconst SKILLS_SPECIFIER = \"agents:skills\";\nconst SKILLS_VIRTUAL_PREFIX = \"\\0agents:skills:\";\nconst SKILL_RESOURCE_ROOTS = new Set([\n \"references\",\n \"scripts\",\n \"assets\",\n \"graphics\",\n \"fonts\",\n \"templates\",\n \"rendered-files\",\n \"illustrations\"\n]);\nconst SKILL_IGNORED_ROOTS = new Set([\n \".git\",\n \".hg\",\n \".svn\",\n \".DS_Store\",\n \".idea\",\n \".vscode\",\n \"dist\",\n \"build\",\n \"coverage\",\n \"node_modules\"\n]);\nconst SPEC_RESOURCE_ROOTS = new Set([\"references\", \"scripts\", \"assets\"]);\n\n// Bundled skill resources are base64-embedded into the Worker bundle, which\n// inflates them by ~1.33x and competes with app code for the bundle-size\n// budget. These heuristic thresholds (raw bytes) trigger a recommendation to\n// move large assets to an R2-backed skill source instead.\nconst SKILL_ASSET_WARN_BYTES = 256 * 1024;\nconst SKILL_BUNDLE_WARN_BYTES = 1024 * 1024;\n\nfunction formatBytes(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(0)}KB`;\n return `${bytes}B`;\n}\n\ninterface SkillFile {\n name: string;\n description: string;\n body: string;\n rawContent: string;\n compatibility?: string;\n license?: string;\n allowedTools?: string;\n metadata?: Record<string, unknown>;\n resources: Array<{\n path: string;\n kind: \"reference\" | \"script\" | \"asset\" | \"file\";\n size: number;\n encoding: \"text\" | \"base64\";\n mimeType?: string;\n content: string;\n precompiled?: boolean;\n }>;\n}\n\nfunction parseFrontmatter(raw: string): {\n data: Record<string, unknown>;\n body: string;\n} {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) return { data: {}, body: raw };\n const parsed = parseYaml(match[1] ?? \"\");\n const data =\n parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n return { data, body: match[2] ?? \"\" };\n}\n\nfunction stringField(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction recordField(value: unknown): Record<string, unknown> | undefined {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction resourceKind(path: string): \"reference\" | \"script\" | \"asset\" | \"file\" {\n if (path.startsWith(\"references/\")) return \"reference\";\n if (path.startsWith(\"scripts/\")) return \"script\";\n if (\n path.startsWith(\"assets/\") ||\n path.startsWith(\"graphics/\") ||\n path.startsWith(\"fonts/\") ||\n path.startsWith(\"templates/\") ||\n path.startsWith(\"rendered-files/\") ||\n path.startsWith(\"illustrations/\")\n ) {\n return \"asset\";\n }\n return \"file\";\n}\n\nconst TEXT_EXTENSIONS = new Set([\n \".bash\",\n \".css\",\n \".csv\",\n \".html\",\n \".js\",\n \".json\",\n \".jsx\",\n \".md\",\n \".mjs\",\n \".py\",\n \".sh\",\n \".svg\",\n \".ts\",\n \".tsx\",\n \".txt\",\n \".xml\",\n \".yaml\",\n \".yml\"\n]);\n\nconst MIME_TYPES = new Map([\n [\".css\", \"text/css\"],\n [\".gif\", \"image/gif\"],\n [\".html\", \"text/html\"],\n [\".jpg\", \"image/jpeg\"],\n [\".jpeg\", \"image/jpeg\"],\n [\".js\", \"text/javascript\"],\n [\".json\", \"application/json\"],\n [\".md\", \"text/markdown\"],\n [\".mjs\", \"text/javascript\"],\n [\".pdf\", \"application/pdf\"],\n [\".png\", \"image/png\"],\n [\".py\", \"text/x-python\"],\n [\".sh\", \"text/x-shellscript\"],\n [\".svg\", \"image/svg+xml\"],\n [\".ts\", \"text/typescript\"],\n [\".tsx\", \"text/typescript\"],\n [\".txt\", \"text/plain\"],\n [\".webp\", \"image/webp\"],\n [\".woff\", \"font/woff\"],\n [\".woff2\", \"font/woff2\"],\n [\".xml\", \"application/xml\"],\n [\".yaml\", \"application/yaml\"],\n [\".yml\", \"application/yaml\"]\n]);\n\nfunction extensionOf(path: string): string {\n const file = path.split(\"/\").at(-1) ?? path;\n const index = file.lastIndexOf(\".\");\n return index === -1 ? \"\" : file.slice(index).toLowerCase();\n}\n\nfunction resourceEncoding(path: string): \"text\" | \"base64\" {\n return TEXT_EXTENSIONS.has(extensionOf(path)) ? \"text\" : \"base64\";\n}\n\nfunction resourceMimeType(path: string): string | undefined {\n return MIME_TYPES.get(extensionOf(path));\n}\n\nasync function collectFiles(\n root: string,\n relativeRoot = \"\",\n warn?: (message: string) => void\n): Promise<Array<{ path: string; absolutePath: string; size: number }>> {\n const entries = await readdir(join(root, relativeRoot), {\n withFileTypes: true\n }).catch(() => []);\n const files: Array<{ path: string; absolutePath: string; size: number }> = [];\n\n for (const entry of entries) {\n if (SKILL_IGNORED_ROOTS.has(entry.name)) continue;\n const relativePath = relativeRoot\n ? `${relativeRoot}/${entry.name}`\n : entry.name;\n const absolutePath = join(root, relativePath);\n if (entry.isDirectory()) {\n const resourceRoot = relativePath.split(\"/\")[0];\n if (!resourceRoot || SKILL_IGNORED_ROOTS.has(resourceRoot)) continue;\n if (!SKILL_RESOURCE_ROOTS.has(resourceRoot)) {\n if (!relativeRoot) {\n warn?.(\n `Ignoring skill directory \"${relativePath}\". Bundled skill resources should live under references/, scripts/, assets/, or a known asset root.`\n );\n }\n continue;\n }\n if (!SPEC_RESOURCE_ROOTS.has(resourceRoot) && !relativeRoot) {\n warn?.(\n `Bundling non-standard skill resource root \"${resourceRoot}/\". Prefer assets/ for portable Agent Skills when possible.`\n );\n }\n files.push(...(await collectFiles(root, relativePath, warn)));\n } else if (entry.isFile() && relativePath !== \"SKILL.md\") {\n const resourceRoot = relativePath.split(\"/\")[0];\n if (!resourceRoot || SKILL_IGNORED_ROOTS.has(resourceRoot)) continue;\n if (!SKILL_RESOURCE_ROOTS.has(resourceRoot)) {\n warn?.(\n `Ignoring skill file \"${relativePath}\". Bundled skill resources should live under references/, scripts/, assets/, or a known asset root.`\n );\n continue;\n }\n const info = await stat(absolutePath);\n files.push({ path: relativePath, absolutePath, size: info.size });\n }\n }\n\n return files.sort((a, b) => a.path.localeCompare(b.path));\n}\n\nasync function collectWatchTargets(\n root: string,\n relativeRoot = \"\"\n): Promise<string[]> {\n const directory = join(root, relativeRoot);\n const entries = await readdir(directory, { withFileTypes: true }).catch(\n () => []\n );\n const targets = [directory];\n\n for (const entry of entries) {\n if (SKILL_IGNORED_ROOTS.has(entry.name)) continue;\n const relativePath = relativeRoot\n ? `${relativeRoot}/${entry.name}`\n : entry.name;\n const resourceRoot = relativePath.split(\"/\")[0];\n if (!resourceRoot || SKILL_IGNORED_ROOTS.has(resourceRoot)) continue;\n\n const absolutePath = join(root, relativePath);\n targets.push(absolutePath);\n\n if (entry.isDirectory()) {\n targets.push(...(await collectWatchTargets(root, relativePath)));\n }\n }\n\n return targets;\n}\n\nasync function readSkill(\n skillDir: string,\n warn?: (message: string) => void\n): Promise<SkillFile | null> {\n const skillPath = join(skillDir, \"SKILL.md\");\n const rawContent = await readFile(skillPath, \"utf8\").catch(() => null);\n if (rawContent === null) return null;\n\n const { data, body } = parseFrontmatter(rawContent);\n const name = stringField(data.name);\n const description = stringField(data.description);\n if (!name || !description) return null;\n\n const resources = await Promise.all(\n (await collectFiles(skillDir, \"\", warn)).map(async (file) => {\n const encoding = resourceEncoding(file.path);\n const bytes = await readFile(file.absolutePath);\n const kind = resourceKind(file.path);\n let content =\n encoding === \"base64\" ? bytes.toString(\"base64\") : bytes.toString();\n let precompiled = false;\n\n // Compile text script resources to self-contained JS at build time so the\n // runtime never needs an in-Worker bundler to run them.\n let size = file.size;\n if (\n kind === \"script\" &&\n encoding === \"text\" &&\n isCompilableSkillScript(file.path)\n ) {\n try {\n content = (await compileSkillScript(file.absolutePath)).content;\n precompiled = true;\n // The compiled bundle (which may inline sibling files and bundled\n // dependencies) is what actually ships, so report its size for the\n // bundle-size warnings rather than the raw source size.\n size = Buffer.byteLength(content);\n } catch (error) {\n warn?.(\n `Failed to compile skill script \"${file.path}\": ${\n error instanceof Error ? error.message : String(error)\n }. Skill scripts must be self-contained, compilable modules to run at runtime.`\n );\n }\n }\n\n return {\n path: file.path,\n kind,\n size,\n encoding,\n mimeType: resourceMimeType(file.path),\n content,\n precompiled\n };\n })\n );\n\n return {\n name,\n description,\n body,\n rawContent,\n compatibility: stringField(data.compatibility),\n license: stringField(data.license),\n allowedTools: stringField(data[\"allowed-tools\"]),\n metadata: recordField(data.metadata),\n resources\n };\n}\n\nasync function buildSkillsModule(\n dir: string,\n warn?: (message: string) => void\n): Promise<string> {\n const entries = await readdir(dir, { withFileTypes: true });\n const skills: SkillFile[] = [];\n const seen = new Set<string>();\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skill = await readSkill(join(dir, entry.name), warn);\n if (!skill) continue;\n if (seen.has(skill.name)) {\n warn?.(\n `Duplicate bundled skill name \"${skill.name}\" in \"${entry.name}/\"; keeping the first occurrence and ignoring this one.`\n );\n continue;\n }\n seen.add(skill.name);\n skills.push(skill);\n }\n\n skills.sort((a, b) => a.name.localeCompare(b.name));\n\n let totalBytes = 0;\n for (const skill of skills) {\n for (const resource of skill.resources) {\n totalBytes += resource.size;\n if (resource.size > SKILL_ASSET_WARN_BYTES) {\n warn?.(\n `Bundled skill resource \"${skill.name}/${resource.path}\" is ${formatBytes(resource.size)}; large assets bloat the Worker bundle (base64, ~1.33x). Prefer an R2-backed source via skills.r2().`\n );\n }\n }\n }\n if (totalBytes > SKILL_BUNDLE_WARN_BYTES) {\n warn?.(\n `Bundled skills total ${formatBytes(totalBytes)} of embedded resources; this competes with the Worker bundle-size budget. Consider serving large skills from R2 via skills.r2().`\n );\n }\n\n const hash = createHash(\"sha256\");\n hash.update(JSON.stringify(skills));\n\n const manifest = {\n id: `bundle:${basename(dir)}`,\n fingerprint: hash.digest(\"hex\"),\n skills\n };\n\n return `const manifest = ${JSON.stringify(manifest)};\\nexport default {\\n id: manifest.id,\\n fingerprint: manifest.fingerprint,\\n async list() {\\n return manifest.skills.map(({ body, rawContent, resources, ...skill }) => skill);\\n },\\n async load(name) {\\n const skill = manifest.skills.find((entry) => entry.name === name);\\n if (!skill) return null;\\n return {\\n ...skill,\\n resources: skill.resources.map(({ content, ...resource }) => resource)\\n };\\n },\\n async readResource(name, path) {\\n const skill = manifest.skills.find((entry) => entry.name === name);\\n const resource = skill?.resources.find((entry) => entry.path === path);\\n return resource ? { ...resource } : null;\\n }\\n};\\n`;\n}\n\nconst TURNDOWN_STUB_ID = \"\\0agents:turndown-stub\";\n\n// `just-bash` (pulled in by the workspace bash tool / skill runner) statically\n// depends on `turndown`, whose ESM build runs a top-level `require()` on its\n// Node DOM fallback. Workers is ESM with no global `require`, so the module\n// throws at startup — even when the bash tool is never used. turndown is only\n// needed by just-bash's niche `html-to-markdown` command, so we replace it with\n// an inert stub by default to keep Workers deploys clean. Opt out with\n// `agents({ stubTurndown: false })` if you rely on turndown elsewhere.\nfunction turndownStubPlugin(): Plugin {\n return {\n name: \"agents-turndown-stub\",\n enforce: \"pre\",\n resolveId(source) {\n if (source === \"turndown\") return TURNDOWN_STUB_ID;\n return null;\n },\n load(id) {\n if (id !== TURNDOWN_STUB_ID) return null;\n return `class TurndownService {\n constructor() {}\n use() { return this; }\n addRule() { return this; }\n keep() { return this; }\n remove() { return this; }\n turndown() { return \"\"; }\n}\nexport default TurndownService;\n`;\n }\n };\n}\n\nfunction skillsImportPlugin(): Plugin {\n return {\n name: \"agents-skills-import\",\n async resolveId(source, importer) {\n // `agents:skills` resolves to a `./skills` directory next to the\n // importer; `agents:skills/<dir>` points at a sibling directory.\n if (\n source !== SKILLS_SPECIFIER &&\n !source.startsWith(`${SKILLS_SPECIFIER}/`)\n ) {\n return null;\n }\n if (!importer) return null;\n const relative =\n source === SKILLS_SPECIFIER\n ? \"skills\"\n : source.slice(SKILLS_SPECIFIER.length + 1);\n const resolved = resolve(importer, \"..\", relative);\n return `${SKILLS_VIRTUAL_PREFIX}${resolved}`;\n },\n async load(id) {\n if (!id.startsWith(SKILLS_VIRTUAL_PREFIX)) return null;\n const dir = id.slice(SKILLS_VIRTUAL_PREFIX.length);\n for (const target of await collectWatchTargets(dir)) {\n this.addWatchFile(target);\n }\n return buildSkillsModule(dir, (message) => this.warn(message));\n }\n };\n}\n\nexport interface AgentsPluginOptions {\n /**\n * Replace `turndown` with an inert stub so `just-bash` (workspace bash tool /\n * skill runner) doesn't drag turndown's `require()`-using DOM fallback into\n * the Worker's module-init path and break deploys. Enabled by default. Set to\n * `false` if your app uses turndown directly and needs the real\n * implementation.\n */\n stubTurndown?: boolean;\n}\n\n/**\n * Vite plugin for Agents SDK projects.\n *\n * Handles TC39 decorator transforms (Oxc doesn't support them yet, oxc#9170) so\n * `@callable()` works at runtime, the `agents:skills` import transform, and\n * stubbing `turndown` to keep Workers deploys clean. Will grow to cover other\n * Agents-specific build concerns as needed.\n */\nexport default function agents(options: AgentsPluginOptions = {}): Plugin[] {\n const { stubTurndown = true } = options;\n return [\n ...(stubTurndown ? [turndownStubPlugin()] : []),\n skillsImportPlugin(),\n babel({\n presets: [\n {\n preset: () => ({\n plugins: [\n [\"@babel/plugin-proposal-decorators\", { version: \"2023-11\" }]\n ]\n }),\n rolldown: { filter: { code: \"@\" } }\n }\n ]\n }) as unknown as Plugin\n ];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { t as applyChunkToParts } from "./message-builder-BymO4N_D.js";
|
|
2
|
+
//#region src/chat/stream-accumulator.ts
|
|
3
|
+
function asMetadata(value) {
|
|
4
|
+
if (value != null && typeof value === "object" && !Array.isArray(value)) return value;
|
|
5
|
+
}
|
|
6
|
+
var StreamAccumulator = class {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.messageId = options.messageId;
|
|
9
|
+
this._isContinuation = options.continuation ?? false;
|
|
10
|
+
this.parts = options.existingParts ? [...options.existingParts] : [];
|
|
11
|
+
this.metadata = options.existingMetadata ? { ...options.existingMetadata } : void 0;
|
|
12
|
+
}
|
|
13
|
+
applyChunk(chunk) {
|
|
14
|
+
const handled = applyChunkToParts(this.parts, chunk);
|
|
15
|
+
if (chunk.type === "tool-approval-request" && chunk.toolCallId) return {
|
|
16
|
+
handled,
|
|
17
|
+
action: {
|
|
18
|
+
type: "tool-approval-request",
|
|
19
|
+
toolCallId: chunk.toolCallId
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
if ((chunk.type === "tool-output-available" || chunk.type === "tool-output-error") && chunk.toolCallId) {
|
|
23
|
+
if (!this.parts.some((p) => "toolCallId" in p && p.toolCallId === chunk.toolCallId)) return {
|
|
24
|
+
handled,
|
|
25
|
+
action: {
|
|
26
|
+
type: "cross-message-tool-update",
|
|
27
|
+
updateType: chunk.type === "tool-output-available" ? "output-available" : "output-error",
|
|
28
|
+
toolCallId: chunk.toolCallId,
|
|
29
|
+
output: chunk.output,
|
|
30
|
+
errorText: chunk.errorText,
|
|
31
|
+
preliminary: chunk.preliminary
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (!handled) switch (chunk.type) {
|
|
36
|
+
case "start": {
|
|
37
|
+
if (chunk.messageId != null && !this._isContinuation) this.messageId = chunk.messageId;
|
|
38
|
+
const startMeta = asMetadata(chunk.messageMetadata);
|
|
39
|
+
if (startMeta) this.metadata = this.metadata ? {
|
|
40
|
+
...this.metadata,
|
|
41
|
+
...startMeta
|
|
42
|
+
} : { ...startMeta };
|
|
43
|
+
return {
|
|
44
|
+
handled: true,
|
|
45
|
+
action: {
|
|
46
|
+
type: "start",
|
|
47
|
+
messageId: chunk.messageId,
|
|
48
|
+
metadata: startMeta
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
case "finish": {
|
|
53
|
+
const finishMeta = asMetadata(chunk.messageMetadata);
|
|
54
|
+
if (finishMeta) this.metadata = this.metadata ? {
|
|
55
|
+
...this.metadata,
|
|
56
|
+
...finishMeta
|
|
57
|
+
} : { ...finishMeta };
|
|
58
|
+
return {
|
|
59
|
+
handled: true,
|
|
60
|
+
action: {
|
|
61
|
+
type: "finish",
|
|
62
|
+
finishReason: "finishReason" in chunk ? chunk.finishReason : void 0,
|
|
63
|
+
metadata: finishMeta
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
case "message-metadata": {
|
|
68
|
+
const msgMeta = asMetadata(chunk.messageMetadata);
|
|
69
|
+
if (msgMeta) this.metadata = this.metadata ? {
|
|
70
|
+
...this.metadata,
|
|
71
|
+
...msgMeta
|
|
72
|
+
} : { ...msgMeta };
|
|
73
|
+
return {
|
|
74
|
+
handled: true,
|
|
75
|
+
action: {
|
|
76
|
+
type: "message-metadata",
|
|
77
|
+
metadata: msgMeta ?? {}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
case "finish-step": return { handled: true };
|
|
82
|
+
case "error": return {
|
|
83
|
+
handled: true,
|
|
84
|
+
action: {
|
|
85
|
+
type: "error",
|
|
86
|
+
error: chunk.errorText ?? JSON.stringify(chunk)
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return { handled };
|
|
91
|
+
}
|
|
92
|
+
/** Snapshot the current state as a UIMessage. */
|
|
93
|
+
toMessage() {
|
|
94
|
+
return {
|
|
95
|
+
id: this.messageId,
|
|
96
|
+
role: "assistant",
|
|
97
|
+
parts: [...this.parts],
|
|
98
|
+
...this.metadata != null && { metadata: this.metadata }
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Merge this accumulator's message into an existing message array.
|
|
103
|
+
* Handles continuation (walk backward for last assistant), replacement
|
|
104
|
+
* (update existing by messageId), or append (new message).
|
|
105
|
+
*/
|
|
106
|
+
mergeInto(messages) {
|
|
107
|
+
let existingIdx = messages.findIndex((m) => m.id === this.messageId);
|
|
108
|
+
if (existingIdx < 0 && this._isContinuation) {
|
|
109
|
+
for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "assistant") {
|
|
110
|
+
existingIdx = i;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const partialMessage = {
|
|
115
|
+
id: existingIdx >= 0 ? messages[existingIdx].id : this.messageId,
|
|
116
|
+
role: "assistant",
|
|
117
|
+
parts: [...this.parts],
|
|
118
|
+
...this.metadata != null && { metadata: this.metadata }
|
|
119
|
+
};
|
|
120
|
+
if (existingIdx >= 0) {
|
|
121
|
+
const updated = [...messages];
|
|
122
|
+
updated[existingIdx] = partialMessage;
|
|
123
|
+
return updated;
|
|
124
|
+
}
|
|
125
|
+
return [...messages, partialMessage];
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/chat/broadcast-state.ts
|
|
130
|
+
function transition(state, event) {
|
|
131
|
+
switch (event.type) {
|
|
132
|
+
case "clear": return {
|
|
133
|
+
state: { status: "idle" },
|
|
134
|
+
isStreaming: false
|
|
135
|
+
};
|
|
136
|
+
case "resume-fallback": {
|
|
137
|
+
const accumulator = new StreamAccumulator({ messageId: event.messageId });
|
|
138
|
+
return {
|
|
139
|
+
state: {
|
|
140
|
+
status: "observing",
|
|
141
|
+
streamId: event.streamId,
|
|
142
|
+
accumulator
|
|
143
|
+
},
|
|
144
|
+
isStreaming: true
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
case "response": {
|
|
148
|
+
let accumulator;
|
|
149
|
+
const isReplayedStart = event.replay === true && event.chunkData?.type === "start";
|
|
150
|
+
if (state.status === "idle" || state.streamId !== event.streamId || isReplayedStart) {
|
|
151
|
+
let messageId = event.messageId;
|
|
152
|
+
let existingParts;
|
|
153
|
+
let existingMetadata;
|
|
154
|
+
if (event.continuation && event.currentMessages) {
|
|
155
|
+
for (let i = event.currentMessages.length - 1; i >= 0; i--) if (event.currentMessages[i].role === "assistant") {
|
|
156
|
+
messageId = event.currentMessages[i].id;
|
|
157
|
+
existingParts = [...event.currentMessages[i].parts];
|
|
158
|
+
if (event.currentMessages[i].metadata != null) existingMetadata = { ...event.currentMessages[i].metadata };
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
accumulator = new StreamAccumulator({
|
|
163
|
+
messageId,
|
|
164
|
+
continuation: event.continuation,
|
|
165
|
+
existingParts,
|
|
166
|
+
existingMetadata
|
|
167
|
+
});
|
|
168
|
+
} else accumulator = state.accumulator;
|
|
169
|
+
if (event.chunkData) accumulator.applyChunk(event.chunkData);
|
|
170
|
+
let messagesUpdate;
|
|
171
|
+
if (event.done) {
|
|
172
|
+
messagesUpdate = (prev) => accumulator.mergeInto(prev);
|
|
173
|
+
return {
|
|
174
|
+
state: { status: "idle" },
|
|
175
|
+
messagesUpdate,
|
|
176
|
+
isStreaming: false
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
if (event.chunkData && !event.replay) messagesUpdate = (prev) => accumulator.mergeInto(prev);
|
|
180
|
+
else if (event.replayComplete) messagesUpdate = (prev) => accumulator.mergeInto(prev);
|
|
181
|
+
return {
|
|
182
|
+
state: {
|
|
183
|
+
status: "observing",
|
|
184
|
+
streamId: event.streamId,
|
|
185
|
+
accumulator
|
|
186
|
+
},
|
|
187
|
+
messagesUpdate,
|
|
188
|
+
isStreaming: true
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/chat/wire-types.ts
|
|
195
|
+
/**
|
|
196
|
+
* Enum for message types to improve type safety and maintainability
|
|
197
|
+
*/
|
|
198
|
+
let MessageType = /* @__PURE__ */ function(MessageType) {
|
|
199
|
+
MessageType["CF_AGENT_CHAT_MESSAGES"] = "cf_agent_chat_messages";
|
|
200
|
+
MessageType["CF_AGENT_USE_CHAT_REQUEST"] = "cf_agent_use_chat_request";
|
|
201
|
+
MessageType["CF_AGENT_USE_CHAT_RESPONSE"] = "cf_agent_use_chat_response";
|
|
202
|
+
MessageType["CF_AGENT_CHAT_CLEAR"] = "cf_agent_chat_clear";
|
|
203
|
+
MessageType["CF_AGENT_CHAT_REQUEST_CANCEL"] = "cf_agent_chat_request_cancel";
|
|
204
|
+
/** Sent by server when client connects and there's an active stream to resume */
|
|
205
|
+
MessageType["CF_AGENT_STREAM_RESUMING"] = "cf_agent_stream_resuming";
|
|
206
|
+
/** Sent by client to acknowledge stream resuming notification and request chunks */
|
|
207
|
+
MessageType["CF_AGENT_STREAM_RESUME_ACK"] = "cf_agent_stream_resume_ack";
|
|
208
|
+
/** Sent by client after message handler is ready, requesting stream resume check */
|
|
209
|
+
MessageType["CF_AGENT_STREAM_RESUME_REQUEST"] = "cf_agent_stream_resume_request";
|
|
210
|
+
/** Sent by server when client requests resume but no active stream exists */
|
|
211
|
+
MessageType["CF_AGENT_STREAM_RESUME_NONE"] = "cf_agent_stream_resume_none";
|
|
212
|
+
/**
|
|
213
|
+
* Sent by server when a turn is accepted but its resumable stream has not
|
|
214
|
+
* started yet (queued / debouncing / waiting on MCP / async setup). Tells a
|
|
215
|
+
* reconnecting client to keep waiting rather than resolve its resume probe to
|
|
216
|
+
* "no stream". Resolved by a later `CF_AGENT_STREAM_RESUMING` (stream started)
|
|
217
|
+
* or `CF_AGENT_STREAM_RESUME_NONE` (settled without streaming). See #1784.
|
|
218
|
+
*/
|
|
219
|
+
MessageType["CF_AGENT_STREAM_PENDING"] = "cf_agent_stream_pending";
|
|
220
|
+
/** Client sends tool result to server (for client-side tools) */
|
|
221
|
+
MessageType["CF_AGENT_TOOL_RESULT"] = "cf_agent_tool_result";
|
|
222
|
+
/** Server notifies client that a message was updated (e.g., tool result applied) */
|
|
223
|
+
MessageType["CF_AGENT_MESSAGE_UPDATED"] = "cf_agent_message_updated";
|
|
224
|
+
/** Client sends tool approval response to server (for tools with needsApproval) */
|
|
225
|
+
MessageType["CF_AGENT_TOOL_APPROVAL"] = "cf_agent_tool_approval";
|
|
226
|
+
/**
|
|
227
|
+
* Server→client progress hint: a durable chat turn is being recovered
|
|
228
|
+
* (interrupted by a deploy/eviction or a stream-stall watchdog abort and now
|
|
229
|
+
* resuming). Sent when a recovery continuation is scheduled and cleared on
|
|
230
|
+
* every terminal outcome. (`@cloudflare/think` also replays it on connect;
|
|
231
|
+
* `@cloudflare/ai-chat` broadcasts the live signal only — see #1645.)
|
|
232
|
+
* Backward-compatible — clients that don't understand it ignore it. See #1620.
|
|
233
|
+
*/
|
|
234
|
+
MessageType["CF_AGENT_CHAT_RECOVERING"] = "cf_agent_chat_recovering";
|
|
235
|
+
return MessageType;
|
|
236
|
+
}({});
|
|
237
|
+
//#endregion
|
|
238
|
+
export { transition as n, StreamAccumulator as r, MessageType as t };
|
|
239
|
+
|
|
240
|
+
//# sourceMappingURL=wire-types-nflOzNuU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire-types-nflOzNuU.js","names":[],"sources":["../src/chat/stream-accumulator.ts","../src/chat/broadcast-state.ts","../src/chat/wire-types.ts"],"sourcesContent":["/**\n * StreamAccumulator — unified chunk-to-message builder.\n *\n * Used by @cloudflare/ai-chat (server + client) and @cloudflare/think\n * to incrementally build a UIMessage from stream chunks. Wraps\n * applyChunkToParts and handles the metadata chunk types (start, finish,\n * message-metadata, error) that applyChunkToParts does not cover.\n *\n * The accumulator signals domain-specific concerns (early persistence,\n * cross-message tool updates) via ChunkAction returns — callers handle\n * these according to their context.\n */\n\nimport type { UIMessage } from \"ai\";\nimport { applyChunkToParts, type StreamChunkData } from \"./message-builder\";\n\nfunction asMetadata(value: unknown): Record<string, unknown> | undefined {\n if (value != null && typeof value === \"object\" && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n return undefined;\n}\n\nexport interface StreamAccumulatorOptions {\n messageId: string;\n continuation?: boolean;\n existingParts?: UIMessage[\"parts\"];\n existingMetadata?: Record<string, unknown>;\n}\n\nexport type ChunkAction =\n | {\n type: \"start\";\n messageId?: string;\n metadata?: Record<string, unknown>;\n }\n | {\n type: \"finish\";\n finishReason?: string;\n metadata?: Record<string, unknown>;\n }\n | { type: \"message-metadata\"; metadata: Record<string, unknown> }\n | { type: \"tool-approval-request\"; toolCallId: string }\n | {\n type: \"cross-message-tool-update\";\n updateType: \"output-available\" | \"output-error\";\n toolCallId: string;\n output?: unknown;\n errorText?: string;\n preliminary?: boolean;\n }\n | { type: \"error\"; error: string };\n\nexport interface ChunkResult {\n handled: boolean;\n action?: ChunkAction;\n}\n\nexport class StreamAccumulator {\n messageId: string;\n readonly parts: UIMessage[\"parts\"];\n metadata?: Record<string, unknown>;\n private _isContinuation: boolean;\n\n constructor(options: StreamAccumulatorOptions) {\n this.messageId = options.messageId;\n this._isContinuation = options.continuation ?? false;\n this.parts = options.existingParts ? [...options.existingParts] : [];\n this.metadata = options.existingMetadata\n ? { ...options.existingMetadata }\n : undefined;\n }\n\n applyChunk(chunk: StreamChunkData): ChunkResult {\n const handled = applyChunkToParts(this.parts, chunk);\n\n // Detect tool-approval-request for early persistence signaling\n if (chunk.type === \"tool-approval-request\" && chunk.toolCallId) {\n return {\n handled,\n action: { type: \"tool-approval-request\", toolCallId: chunk.toolCallId }\n };\n }\n\n // Detect cross-message tool output/error: applyChunkToParts returns true\n // for recognized types but silently does nothing when the toolCallId\n // doesn't exist in the current parts array.\n if (\n (chunk.type === \"tool-output-available\" ||\n chunk.type === \"tool-output-error\") &&\n chunk.toolCallId\n ) {\n const foundInParts = this.parts.some(\n (p) => \"toolCallId\" in p && p.toolCallId === chunk.toolCallId\n );\n if (!foundInParts) {\n return {\n handled,\n action: {\n type: \"cross-message-tool-update\",\n updateType:\n chunk.type === \"tool-output-available\"\n ? \"output-available\"\n : \"output-error\",\n toolCallId: chunk.toolCallId,\n output: chunk.output,\n errorText: chunk.errorText,\n preliminary: chunk.preliminary\n }\n };\n }\n }\n\n if (!handled) {\n switch (chunk.type) {\n case \"start\": {\n if (chunk.messageId != null && !this._isContinuation) {\n this.messageId = chunk.messageId;\n }\n const startMeta = asMetadata(chunk.messageMetadata);\n if (startMeta) {\n this.metadata = this.metadata\n ? { ...this.metadata, ...startMeta }\n : { ...startMeta };\n }\n return {\n handled: true,\n action: {\n type: \"start\",\n messageId: chunk.messageId,\n metadata: startMeta\n }\n };\n }\n case \"finish\": {\n const finishMeta = asMetadata(chunk.messageMetadata);\n if (finishMeta) {\n this.metadata = this.metadata\n ? { ...this.metadata, ...finishMeta }\n : { ...finishMeta };\n }\n const finishReason =\n \"finishReason\" in chunk\n ? (chunk.finishReason as string)\n : undefined;\n return {\n handled: true,\n action: {\n type: \"finish\",\n finishReason,\n metadata: finishMeta\n }\n };\n }\n case \"message-metadata\": {\n const msgMeta = asMetadata(chunk.messageMetadata);\n if (msgMeta) {\n this.metadata = this.metadata\n ? { ...this.metadata, ...msgMeta }\n : { ...msgMeta };\n }\n return {\n handled: true,\n action: {\n type: \"message-metadata\",\n metadata: msgMeta ?? {}\n }\n };\n }\n case \"finish-step\": {\n return { handled: true };\n }\n case \"error\": {\n return {\n handled: true,\n action: {\n type: \"error\",\n error: chunk.errorText ?? JSON.stringify(chunk)\n }\n };\n }\n }\n }\n\n return { handled };\n }\n\n /** Snapshot the current state as a UIMessage. */\n toMessage(): UIMessage {\n return {\n id: this.messageId,\n role: \"assistant\",\n parts: [...this.parts],\n ...(this.metadata != null && { metadata: this.metadata })\n } as UIMessage;\n }\n\n /**\n * Merge this accumulator's message into an existing message array.\n * Handles continuation (walk backward for last assistant), replacement\n * (update existing by messageId), or append (new message).\n */\n mergeInto(messages: UIMessage[]): UIMessage[] {\n let existingIdx = messages.findIndex((m) => m.id === this.messageId);\n\n if (existingIdx < 0 && this._isContinuation) {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"assistant\") {\n existingIdx = i;\n break;\n }\n }\n }\n\n const messageId =\n existingIdx >= 0 ? messages[existingIdx].id : this.messageId;\n\n const partialMessage: UIMessage = {\n id: messageId,\n role: \"assistant\",\n parts: [...this.parts],\n ...(this.metadata != null && { metadata: this.metadata })\n } as UIMessage;\n\n if (existingIdx >= 0) {\n const updated = [...messages];\n updated[existingIdx] = partialMessage;\n return updated;\n }\n return [...messages, partialMessage];\n }\n}\n","/**\n * Broadcast stream state machine.\n *\n * Manages the lifecycle of a StreamAccumulator for broadcast/resume\n * streams — the path where this client is *observing* a stream owned\n * by another tab or resumed after reconnect, rather than the transport-\n * owned path that feeds directly into useChat.\n *\n * The transition function is pure (no React, no WebSocket, no side\n * effects). Callers dispatch events and apply the returned state +\n * messagesUpdate. Side effects (sending ACKs, calling onData) stay\n * in the caller.\n */\n\nimport type { UIMessage } from \"ai\";\nimport { StreamAccumulator } from \"./stream-accumulator\";\nimport type { StreamChunkData } from \"./message-builder\";\n\n// ── State ──────────────────────────────────────────────────────────\n\nexport type BroadcastStreamState =\n | { status: \"idle\" }\n | {\n status: \"observing\";\n streamId: string;\n accumulator: StreamAccumulator;\n };\n\n// ── Events ─────────────────────────────────────────────────────────\n\nexport type BroadcastStreamEvent =\n | {\n type: \"response\";\n streamId: string;\n /** Fallback message ID for a new accumulator (ignored if one exists for this stream). */\n messageId: string;\n chunkData?: unknown;\n done?: boolean;\n error?: boolean;\n replay?: boolean;\n replayComplete?: boolean;\n continuation?: boolean;\n /** Required when continuation=true so the accumulator can pick up existing parts. */\n currentMessages?: UIMessage[];\n }\n | {\n type: \"resume-fallback\";\n streamId: string;\n messageId: string;\n }\n | { type: \"clear\" };\n\n// ── Result ─────────────────────────────────────────────────────────\n\nexport interface TransitionResult {\n state: BroadcastStreamState;\n messagesUpdate?: (prev: UIMessage[]) => UIMessage[];\n isStreaming: boolean;\n}\n\n// ── Transition ─────────────────────────────────────────────────────\n\nexport function transition(\n state: BroadcastStreamState,\n event: BroadcastStreamEvent\n): TransitionResult {\n switch (event.type) {\n case \"clear\":\n return { state: { status: \"idle\" }, isStreaming: false };\n\n case \"resume-fallback\": {\n const accumulator = new StreamAccumulator({\n messageId: event.messageId\n });\n return {\n state: {\n status: \"observing\",\n streamId: event.streamId,\n accumulator\n },\n isStreaming: true\n };\n }\n\n case \"response\": {\n let accumulator: StreamAccumulator;\n\n // A replayed `start` chunk means the server is re-sending the stream\n // buffer from chunk 0 (resume replay). Re-initialize the accumulator\n // instead of appending into an existing one: replaying into an\n // accumulator that already holds this stream's parts would duplicate\n // them (a second `text-start` unconditionally opens a second text\n // part — #1733). Re-initializing makes replay idempotent under any\n // number of replays, including a second replay triggered by a\n // duplicate STREAM_RESUMING → ACK cycle or a reconnect.\n const isReplayedStart =\n event.replay === true &&\n (event.chunkData as { type?: string } | null | undefined)?.type ===\n \"start\";\n\n if (\n state.status === \"idle\" ||\n state.streamId !== event.streamId ||\n isReplayedStart\n ) {\n let messageId = event.messageId;\n let existingParts: UIMessage[\"parts\"] | undefined;\n let existingMetadata: Record<string, unknown> | undefined;\n\n if (event.continuation && event.currentMessages) {\n for (let i = event.currentMessages.length - 1; i >= 0; i--) {\n if (event.currentMessages[i].role === \"assistant\") {\n messageId = event.currentMessages[i].id;\n existingParts = [...event.currentMessages[i].parts];\n if (event.currentMessages[i].metadata != null) {\n existingMetadata = {\n ...(event.currentMessages[i].metadata as Record<\n string,\n unknown\n >)\n };\n }\n break;\n }\n }\n }\n\n accumulator = new StreamAccumulator({\n messageId,\n continuation: event.continuation,\n existingParts,\n existingMetadata\n });\n } else {\n accumulator = state.accumulator;\n }\n\n if (event.chunkData) {\n accumulator.applyChunk(event.chunkData as StreamChunkData);\n }\n\n let messagesUpdate: ((prev: UIMessage[]) => UIMessage[]) | undefined;\n\n if (event.done) {\n messagesUpdate = (prev) => accumulator.mergeInto(prev);\n return {\n state: { status: \"idle\" },\n messagesUpdate,\n isStreaming: false\n };\n }\n\n if (event.chunkData && !event.replay) {\n messagesUpdate = (prev) => accumulator.mergeInto(prev);\n } else if (event.replayComplete) {\n messagesUpdate = (prev) => accumulator.mergeInto(prev);\n }\n\n return {\n state: {\n status: \"observing\",\n streamId: event.streamId,\n accumulator\n },\n messagesUpdate,\n isStreaming: true\n };\n }\n }\n}\n","import type { JSONSchema7, UIMessage } from \"ai\";\n\n/**\n * Enum for message types to improve type safety and maintainability\n */\nexport enum MessageType {\n CF_AGENT_CHAT_MESSAGES = \"cf_agent_chat_messages\",\n CF_AGENT_USE_CHAT_REQUEST = \"cf_agent_use_chat_request\",\n CF_AGENT_USE_CHAT_RESPONSE = \"cf_agent_use_chat_response\",\n CF_AGENT_CHAT_CLEAR = \"cf_agent_chat_clear\",\n CF_AGENT_CHAT_REQUEST_CANCEL = \"cf_agent_chat_request_cancel\",\n\n /** Sent by server when client connects and there's an active stream to resume */\n CF_AGENT_STREAM_RESUMING = \"cf_agent_stream_resuming\",\n /** Sent by client to acknowledge stream resuming notification and request chunks */\n CF_AGENT_STREAM_RESUME_ACK = \"cf_agent_stream_resume_ack\",\n /** Sent by client after message handler is ready, requesting stream resume check */\n CF_AGENT_STREAM_RESUME_REQUEST = \"cf_agent_stream_resume_request\",\n /** Sent by server when client requests resume but no active stream exists */\n CF_AGENT_STREAM_RESUME_NONE = \"cf_agent_stream_resume_none\",\n /**\n * Sent by server when a turn is accepted but its resumable stream has not\n * started yet (queued / debouncing / waiting on MCP / async setup). Tells a\n * reconnecting client to keep waiting rather than resolve its resume probe to\n * \"no stream\". Resolved by a later `CF_AGENT_STREAM_RESUMING` (stream started)\n * or `CF_AGENT_STREAM_RESUME_NONE` (settled without streaming). See #1784.\n */\n CF_AGENT_STREAM_PENDING = \"cf_agent_stream_pending\",\n\n /** Client sends tool result to server (for client-side tools) */\n CF_AGENT_TOOL_RESULT = \"cf_agent_tool_result\",\n /** Server notifies client that a message was updated (e.g., tool result applied) */\n CF_AGENT_MESSAGE_UPDATED = \"cf_agent_message_updated\",\n /** Client sends tool approval response to server (for tools with needsApproval) */\n CF_AGENT_TOOL_APPROVAL = \"cf_agent_tool_approval\",\n\n /**\n * Server→client progress hint: a durable chat turn is being recovered\n * (interrupted by a deploy/eviction or a stream-stall watchdog abort and now\n * resuming). Sent when a recovery continuation is scheduled and cleared on\n * every terminal outcome. (`@cloudflare/think` also replays it on connect;\n * `@cloudflare/ai-chat` broadcasts the live signal only — see #1645.)\n * Backward-compatible — clients that don't understand it ignore it. See #1620.\n */\n CF_AGENT_CHAT_RECOVERING = \"cf_agent_chat_recovering\"\n}\n\n/**\n * Types of messages sent from the Agent to clients\n */\nexport type OutgoingMessage<ChatMessage extends UIMessage = UIMessage> =\n | {\n /** Indicates this message is a command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n }\n | {\n /** Indicates this message contains updated chat messages */\n type: MessageType.CF_AGENT_CHAT_MESSAGES;\n /** Array of chat messages */\n messages: readonly ChatMessage[];\n }\n | {\n /** Indicates this message is a response to a chat request */\n type: MessageType.CF_AGENT_USE_CHAT_RESPONSE;\n /** Unique ID of the request this response corresponds to */\n id: string;\n /** Content body of the response */\n body: string;\n /** Whether this is the final chunk of the response */\n done: boolean;\n /** Whether this response contains an error */\n error?: boolean;\n /** Whether this is a continuation (append to last assistant message) */\n continuation?: boolean;\n /** Whether this chunk is being replayed from storage (stream resumption) */\n replay?: boolean;\n /** Signals that replay of stored chunks is complete (stream is still active) */\n replayComplete?: boolean;\n }\n | {\n /** Indicates the server is resuming an active stream */\n type: MessageType.CF_AGENT_STREAM_RESUMING;\n /** The request ID of the stream being resumed */\n id: string;\n }\n | {\n /** Server notifies client that a message was updated (e.g., tool result applied) */\n type: MessageType.CF_AGENT_MESSAGE_UPDATED;\n /** The updated message */\n message: ChatMessage;\n }\n | {\n /** Server responds to resume request when no active stream exists */\n type: MessageType.CF_AGENT_STREAM_RESUME_NONE;\n }\n | {\n /**\n * Server signals an accepted turn whose resumable stream has not started\n * yet — the client should keep waiting for `STREAM_RESUMING` (or a later\n * `STREAM_RESUME_NONE`) rather than give up. See #1784.\n */\n type: MessageType.CF_AGENT_STREAM_PENDING;\n /** The accepted request id, when known. */\n id?: string;\n }\n | {\n /**\n * Progress hint: a durable chat turn is being recovered (`recovering:\n * true`) or recovery has resolved (`recovering: false`). Purely advisory;\n * a client renders a \"recovering…\" indicator while true.\n */\n type: MessageType.CF_AGENT_CHAT_RECOVERING;\n /** Whether recovery is in progress (true) or has resolved (false). */\n recovering: boolean;\n /** The recovery-root request id of the turn being recovered, if known. */\n id?: string;\n };\n\n/**\n * Types of messages sent from clients to the Agent\n */\nexport type IncomingMessage<ChatMessage extends UIMessage = UIMessage> =\n | {\n /** Indicates this message is a command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n }\n | {\n /** Indicates this message is a request to the chat API */\n type: MessageType.CF_AGENT_USE_CHAT_REQUEST;\n /** Unique ID for this request */\n id: string;\n /** Request initialization options */\n init: Pick<\n RequestInit,\n | \"method\"\n | \"keepalive\"\n | \"headers\"\n | \"body\"\n | \"redirect\"\n | \"integrity\"\n | \"credentials\"\n | \"mode\"\n | \"referrer\"\n | \"referrerPolicy\"\n | \"window\"\n >;\n }\n | {\n /** Indicates this message contains updated chat messages */\n type: MessageType.CF_AGENT_CHAT_MESSAGES;\n /** Array of chat messages */\n messages: ChatMessage[];\n }\n | {\n /** Indicates the user wants to stop generation of this message */\n type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL;\n id: string;\n }\n | {\n /** Client acknowledges stream resuming notification and is ready to receive chunks */\n type: MessageType.CF_AGENT_STREAM_RESUME_ACK;\n /** The request ID of the stream being resumed */\n id: string;\n }\n | {\n /** Client requests stream resume check after message handler is registered */\n type: MessageType.CF_AGENT_STREAM_RESUME_REQUEST;\n }\n | {\n /** Client sends tool result to server (for client-side tools) */\n type: MessageType.CF_AGENT_TOOL_RESULT;\n /** The tool call ID this result is for */\n toolCallId: string;\n /** The name of the tool */\n toolName: string;\n /** The output from the tool execution */\n output: unknown;\n /** Override the tool part state (e.g. \"output-error\" for custom denial) */\n state?: \"output-available\" | \"output-error\";\n /** Error message when state is \"output-error\" */\n errorText?: string;\n /** Whether server should auto-continue the conversation after applying result */\n autoContinue?: boolean;\n /** Client tool schemas for continuation (client is source of truth) */\n clientTools?: Array<{\n name: string;\n description?: string;\n parameters?: JSONSchema7;\n }>;\n }\n | {\n /** Client sends tool approval response to server (for tools with needsApproval) */\n type: MessageType.CF_AGENT_TOOL_APPROVAL;\n /** The tool call ID this approval is for */\n toolCallId: string;\n /** Whether the tool execution was approved */\n approved: boolean;\n /** Whether server should auto-continue the conversation after applying approval */\n autoContinue?: boolean;\n };\n"],"mappings":"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"}
|
|
@@ -5,6 +5,23 @@ import {
|
|
|
5
5
|
} from "cloudflare:workers";
|
|
6
6
|
|
|
7
7
|
//#region src/workflow-types.d.ts
|
|
8
|
+
type AgentWorkflowPathStep = {
|
|
9
|
+
className: string;
|
|
10
|
+
name: string;
|
|
11
|
+
};
|
|
12
|
+
type AgentWorkflowOrigin =
|
|
13
|
+
| {
|
|
14
|
+
kind: "agent";
|
|
15
|
+
version: 1 /** Environment binding name for the top-level Agent namespace */;
|
|
16
|
+
binding: string /** Name/ID of the top-level Agent */;
|
|
17
|
+
name: string;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
kind: "facet";
|
|
21
|
+
version: 1 /** Environment binding name for the root Agent namespace */;
|
|
22
|
+
rootBinding: string /** Root-first path to the originating facet, including itself */;
|
|
23
|
+
path: AgentWorkflowPathStep[];
|
|
24
|
+
};
|
|
8
25
|
/**
|
|
9
26
|
* Type alias for WorkflowEvent in AgentWorkflow context.
|
|
10
27
|
* Identical to WorkflowEvent - provided for naming consistency with AgentWorkflowStep.
|
|
@@ -58,7 +75,8 @@ interface AgentWorkflowStep extends WorkflowStep {
|
|
|
58
75
|
type AgentWorkflowInternalParams = {
|
|
59
76
|
/** Name/ID of the Agent that started this workflow */ __agentName: string /** Environment binding name for the Agent's namespace */;
|
|
60
77
|
__agentBinding: string /** Workflow binding name (for callbacks) */;
|
|
61
|
-
__workflowName: string
|
|
78
|
+
__workflowName: string /** Versioned origin identity for top-level Agents and sub-agent facets */;
|
|
79
|
+
__agentOrigin?: AgentWorkflowOrigin;
|
|
62
80
|
};
|
|
63
81
|
/**
|
|
64
82
|
* Combined workflow params: user params + internal agent params
|
|
@@ -234,27 +252,29 @@ declare class WorkflowRejectedError extends Error {
|
|
|
234
252
|
}
|
|
235
253
|
//#endregion
|
|
236
254
|
export {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
255
|
+
WorkflowStatus as C,
|
|
256
|
+
WorkflowRejectedError as S,
|
|
257
|
+
WorkflowEventPayload as _,
|
|
258
|
+
AgentWorkflowPathStep as a,
|
|
259
|
+
WorkflowProgressCallback as b,
|
|
260
|
+
DefaultProgress as c,
|
|
261
|
+
WorkflowCallback as d,
|
|
262
|
+
WorkflowCallbackBase as f,
|
|
263
|
+
WorkflowEventCallback as g,
|
|
264
|
+
WorkflowErrorCallback as h,
|
|
265
|
+
AgentWorkflowParams as i,
|
|
266
|
+
RunWorkflowOptions as l,
|
|
267
|
+
WorkflowCompleteCallback as m,
|
|
249
268
|
AgentWorkflowInternalParams as n,
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
269
|
+
AgentWorkflowStep as o,
|
|
270
|
+
WorkflowCallbackType as p,
|
|
271
|
+
AgentWorkflowOrigin as r,
|
|
272
|
+
ApprovalEventPayload as s,
|
|
254
273
|
AgentWorkflowEvent as t,
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
WorkflowQueryCriteria as
|
|
274
|
+
WaitForApprovalOptions as u,
|
|
275
|
+
WorkflowInfo as v,
|
|
276
|
+
WorkflowTrackingRow as w,
|
|
277
|
+
WorkflowQueryCriteria as x,
|
|
278
|
+
WorkflowPage as y
|
|
259
279
|
};
|
|
260
|
-
//# sourceMappingURL=workflow-types-
|
|
280
|
+
//# sourceMappingURL=workflow-types-Baz_PO5v.d.ts.map
|
package/dist/workflow-types.d.ts
CHANGED
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
C as WorkflowStatus,
|
|
3
|
+
S as WorkflowRejectedError,
|
|
4
|
+
_ as WorkflowEventPayload,
|
|
5
|
+
a as AgentWorkflowPathStep,
|
|
6
|
+
b as WorkflowProgressCallback,
|
|
7
|
+
c as DefaultProgress,
|
|
8
|
+
d as WorkflowCallback,
|
|
9
|
+
f as WorkflowCallbackBase,
|
|
10
|
+
g as WorkflowEventCallback,
|
|
11
|
+
h as WorkflowErrorCallback,
|
|
12
|
+
i as AgentWorkflowParams,
|
|
13
|
+
l as RunWorkflowOptions,
|
|
14
|
+
m as WorkflowCompleteCallback,
|
|
14
15
|
n as AgentWorkflowInternalParams,
|
|
15
|
-
o as
|
|
16
|
-
p as
|
|
17
|
-
r as
|
|
18
|
-
s as
|
|
16
|
+
o as AgentWorkflowStep,
|
|
17
|
+
p as WorkflowCallbackType,
|
|
18
|
+
r as AgentWorkflowOrigin,
|
|
19
|
+
s as ApprovalEventPayload,
|
|
19
20
|
t as AgentWorkflowEvent,
|
|
20
|
-
u as
|
|
21
|
-
v as
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
u as WaitForApprovalOptions,
|
|
22
|
+
v as WorkflowInfo,
|
|
23
|
+
w as WorkflowTrackingRow,
|
|
24
|
+
x as WorkflowQueryCriteria,
|
|
25
|
+
y as WorkflowPage
|
|
26
|
+
} from "./workflow-types-Baz_PO5v.js";
|
|
25
27
|
export {
|
|
26
28
|
AgentWorkflowEvent,
|
|
27
29
|
AgentWorkflowInternalParams,
|
|
30
|
+
AgentWorkflowOrigin,
|
|
28
31
|
AgentWorkflowParams,
|
|
32
|
+
AgentWorkflowPathStep,
|
|
29
33
|
AgentWorkflowStep,
|
|
30
34
|
ApprovalEventPayload,
|
|
31
35
|
DefaultProgress,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-types.js","names":[],"sources":["../src/workflow-types.ts"],"sourcesContent":["/**\n * Workflow integration types for Agents\n *\n * These types provide seamless integration between Cloudflare Agents\n * and Cloudflare Workflows for durable, multi-step background processing.\n *\n * Note: This file is kept separate from workflows.ts to avoid circular dependencies.\n * Both index.ts (Agent class) and workflows.ts (AgentWorkflow class) import from here.\n */\n\nimport type {\n WorkflowEvent,\n WorkflowStep,\n WorkflowSleepDuration\n} from \"cloudflare:workers\";\n\n/**\n * Type alias for WorkflowEvent in AgentWorkflow context.\n * Identical to WorkflowEvent - provided for naming consistency with AgentWorkflowStep.\n */\nexport type AgentWorkflowEvent<Params = unknown> = WorkflowEvent<Params>;\n\n/**\n * Extended WorkflowStep with durable Agent communication methods.\n * All added methods on this interface are durable - they're idempotent and won't\n * repeat on workflow retry.\n */\nexport interface AgentWorkflowStep extends WorkflowStep {\n /**\n * Report successful completion to the Agent (durable).\n * Triggers onWorkflowComplete() on the Agent.\n * @param result - Optional result data\n */\n reportComplete<T = unknown>(result?: T): Promise<void>;\n\n /**\n * Report an error to the Agent (durable).\n * Triggers onWorkflowError() on the Agent.\n * @param error - Error or error message\n */\n reportError(error: Error | string): Promise<void>;\n\n /**\n * Send a custom event to the Agent (durable).\n * Triggers onWorkflowEvent() on the Agent.\n * @param event - Custom event payload\n */\n sendEvent<T = unknown>(event: T): Promise<void>;\n\n /**\n * Update the Agent's state entirely (durable).\n * This will replace the Agent's state and broadcast to all connected clients.\n * @param state - New state to set\n */\n updateAgentState(state: unknown): Promise<void>;\n\n /**\n * Merge partial state into the Agent's existing state (durable).\n * Performs a shallow merge and broadcasts to all connected clients.\n * @param partialState - Partial state to merge\n */\n mergeAgentState(partialState: Record<string, unknown>): Promise<void>;\n\n /**\n * Reset the Agent's state to its initialState (durable).\n * Broadcasts the reset state to all connected clients.\n */\n resetAgentState(): Promise<void>;\n}\n\n/**\n * Internal parameters injected by runWorkflow() to identify the originating Agent\n */\nexport type AgentWorkflowInternalParams = {\n /** Name/ID of the Agent that started this workflow */\n __agentName: string;\n /** Environment binding name for the Agent's namespace */\n __agentBinding: string;\n /** Workflow binding name (for callbacks) */\n __workflowName: string;\n};\n\n/**\n * Combined workflow params: user params + internal agent params\n */\nexport type AgentWorkflowParams<T = unknown> = T & AgentWorkflowInternalParams;\n\n/**\n * Workflow callback types for Agent-Workflow communication\n */\nexport type WorkflowCallbackType = \"progress\" | \"complete\" | \"error\" | \"event\";\n\n/**\n * Base callback structure sent from Workflow to Agent\n */\nexport type WorkflowCallbackBase = {\n /** Workflow binding name */\n workflowName: string;\n /** ID of the workflow instance */\n workflowId: string;\n /** Type of callback */\n type: WorkflowCallbackType;\n /** Timestamp when callback was sent */\n timestamp: number;\n};\n\n/**\n * Default progress type - covers common use cases.\n * Developers can define their own progress type for domain-specific needs.\n */\nexport type DefaultProgress = {\n /** Current step name */\n step?: string;\n /** Step/overall status */\n status?: \"pending\" | \"running\" | \"complete\" | \"error\";\n /** Human-readable message */\n message?: string;\n /** Progress percentage (0-1) */\n percent?: number;\n /** Allow additional custom fields */\n [key: string]: unknown;\n};\n\n/**\n * Progress callback - reports workflow progress with typed payload\n */\nexport type WorkflowProgressCallback<P = DefaultProgress> =\n WorkflowCallbackBase & {\n type: \"progress\";\n /** Typed progress data */\n progress: P;\n };\n\n/**\n * Complete callback - workflow finished successfully\n */\nexport type WorkflowCompleteCallback = WorkflowCallbackBase & {\n type: \"complete\";\n /** Result of the workflow */\n result?: unknown;\n};\n\n/**\n * Error callback - workflow encountered an error\n */\nexport type WorkflowErrorCallback = WorkflowCallbackBase & {\n type: \"error\";\n /** Error message */\n error: string;\n};\n\n/**\n * Event callback - custom event from workflow\n */\nexport type WorkflowEventCallback = WorkflowCallbackBase & {\n type: \"event\";\n /** Custom event payload */\n event: unknown;\n};\n\n/**\n * Union of all callback types\n */\nexport type WorkflowCallback<P = DefaultProgress> =\n | WorkflowProgressCallback<P>\n | WorkflowCompleteCallback\n | WorkflowErrorCallback\n | WorkflowEventCallback;\n\n/**\n * Workflow status values - derived from Cloudflare's InstanceStatus\n */\nexport type WorkflowStatus = InstanceStatus[\"status\"];\n\n/**\n * Row structure for cf_agents_workflows tracking table\n */\nexport type WorkflowTrackingRow = {\n /** Internal row ID (UUID) */\n id: string;\n /** Cloudflare Workflow instance ID */\n workflow_id: string;\n /** Workflow binding name */\n workflow_name: string;\n /** Current workflow status */\n status: WorkflowStatus;\n /** JSON-serialized metadata for querying */\n metadata: string | null;\n /** Error name if workflow failed */\n error_name: string | null;\n /** Error message if workflow failed */\n error_message: string | null;\n /** Unix timestamp when workflow was created */\n created_at: number;\n /** Unix timestamp when workflow was last updated */\n updated_at: number;\n /** Unix timestamp when workflow completed (null if not complete) */\n completed_at: number | null;\n};\n\n/**\n * Options for runWorkflow()\n */\nexport type RunWorkflowOptions = {\n /** Custom workflow instance ID (auto-generated if not provided) */\n id?: string;\n /** Optional metadata for querying (stored as JSON) */\n metadata?: Record<string, unknown>;\n /** Agent binding name (auto-detected from class name if not provided) */\n agentBinding?: string;\n};\n\n/**\n * Event payload for sendWorkflowEvent()\n */\nexport type WorkflowEventPayload = {\n /** Event type name */\n type: string;\n /** Event payload data */\n payload: unknown;\n};\n\n/**\n * Parsed workflow tracking info returned by getWorkflow()\n */\nexport type WorkflowInfo = {\n /** Internal row ID */\n id: string;\n /** Cloudflare Workflow instance ID */\n workflowId: string;\n /** Workflow binding name */\n workflowName: string;\n /** Current workflow status */\n status: WorkflowStatus;\n /** Metadata (parsed from JSON) */\n metadata: Record<string, unknown> | null;\n /** Error info if workflow failed */\n error: { name: string; message: string } | null;\n /** When workflow was created */\n createdAt: Date;\n /** When workflow was last updated */\n updatedAt: Date;\n /** When workflow completed (null if not complete) */\n completedAt: Date | null;\n};\n\n/**\n * Criteria for querying tracked workflows\n */\nexport type WorkflowQueryCriteria = {\n /** Filter by status */\n status?: WorkflowStatus | WorkflowStatus[];\n /** Filter by workflow binding name */\n workflowName?: string;\n /** Filter by metadata key-value pairs (exact match) */\n metadata?: Record<string, string | number | boolean>;\n /** Limit number of results (default 50, max 100) */\n limit?: number;\n /** Order by created_at */\n orderBy?: \"asc\" | \"desc\";\n /** Cursor for pagination (from previous WorkflowPage.nextCursor) */\n cursor?: string;\n};\n\n/**\n * Paginated result from getWorkflows()\n */\nexport type WorkflowPage = {\n /** Workflows for this page */\n workflows: WorkflowInfo[];\n /** Total count of workflows matching the criteria (ignoring pagination) */\n total: number;\n /** Cursor for next page, or null if no more pages */\n nextCursor: string | null;\n};\n\n/**\n * Standard approval event payload used by approveWorkflow/rejectWorkflow\n */\nexport type ApprovalEventPayload = {\n /** Whether the workflow was approved */\n approved: boolean;\n /** Optional reason for approval/rejection */\n reason?: string;\n /** Optional additional metadata */\n metadata?: Record<string, unknown>;\n};\n\n/**\n * Options for waitForApproval()\n */\nexport type WaitForApprovalOptions = {\n /** Step name for waitForEvent (default: \"wait-for-approval\") */\n stepName?: string;\n /** Timeout duration (e.g., \"7 days\") */\n timeout?: WorkflowSleepDuration;\n /** Event type to wait for (default: \"approval\") */\n eventType?: string;\n};\n\n/**\n * Error thrown when a workflow is rejected via rejectWorkflow()\n */\nexport class WorkflowRejectedError extends Error {\n constructor(\n public readonly reason?: string,\n public readonly workflowId?: string\n ) {\n super(reason ? `Workflow rejected: ${reason}` : \"Workflow rejected\");\n this.name = \"WorkflowRejectedError\";\n }\n}\n"],"mappings":";;;;AA+SA,IAAa,wBAAb,cAA2C,MAAM;CAC/C,YACE,QACA,YACA;EACA,MAAM,SAAS,sBAAsB,WAAW,mBAAmB;EAHnD,KAAA,SAAA;EACA,KAAA,aAAA;EAGhB,KAAK,OAAO;CACd;AACF"}
|
|
1
|
+
{"version":3,"file":"workflow-types.js","names":[],"sources":["../src/workflow-types.ts"],"sourcesContent":["/**\n * Workflow integration types for Agents\n *\n * These types provide seamless integration between Cloudflare Agents\n * and Cloudflare Workflows for durable, multi-step background processing.\n *\n * Note: This file is kept separate from workflows.ts to avoid circular dependencies.\n * Both index.ts (Agent class) and workflows.ts (AgentWorkflow class) import from here.\n */\n\nimport type {\n WorkflowEvent,\n WorkflowStep,\n WorkflowSleepDuration\n} from \"cloudflare:workers\";\n\nexport type AgentWorkflowPathStep = { className: string; name: string };\n\nexport type AgentWorkflowOrigin =\n | {\n kind: \"agent\";\n version: 1;\n /** Environment binding name for the top-level Agent namespace */\n binding: string;\n /** Name/ID of the top-level Agent */\n name: string;\n }\n | {\n kind: \"facet\";\n version: 1;\n /** Environment binding name for the root Agent namespace */\n rootBinding: string;\n /** Root-first path to the originating facet, including itself */\n path: AgentWorkflowPathStep[];\n };\n\n/**\n * Type alias for WorkflowEvent in AgentWorkflow context.\n * Identical to WorkflowEvent - provided for naming consistency with AgentWorkflowStep.\n */\nexport type AgentWorkflowEvent<Params = unknown> = WorkflowEvent<Params>;\n\n/**\n * Extended WorkflowStep with durable Agent communication methods.\n * All added methods on this interface are durable - they're idempotent and won't\n * repeat on workflow retry.\n */\nexport interface AgentWorkflowStep extends WorkflowStep {\n /**\n * Report successful completion to the Agent (durable).\n * Triggers onWorkflowComplete() on the Agent.\n * @param result - Optional result data\n */\n reportComplete<T = unknown>(result?: T): Promise<void>;\n\n /**\n * Report an error to the Agent (durable).\n * Triggers onWorkflowError() on the Agent.\n * @param error - Error or error message\n */\n reportError(error: Error | string): Promise<void>;\n\n /**\n * Send a custom event to the Agent (durable).\n * Triggers onWorkflowEvent() on the Agent.\n * @param event - Custom event payload\n */\n sendEvent<T = unknown>(event: T): Promise<void>;\n\n /**\n * Update the Agent's state entirely (durable).\n * This will replace the Agent's state and broadcast to all connected clients.\n * @param state - New state to set\n */\n updateAgentState(state: unknown): Promise<void>;\n\n /**\n * Merge partial state into the Agent's existing state (durable).\n * Performs a shallow merge and broadcasts to all connected clients.\n * @param partialState - Partial state to merge\n */\n mergeAgentState(partialState: Record<string, unknown>): Promise<void>;\n\n /**\n * Reset the Agent's state to its initialState (durable).\n * Broadcasts the reset state to all connected clients.\n */\n resetAgentState(): Promise<void>;\n}\n\n/**\n * Internal parameters injected by runWorkflow() to identify the originating Agent\n */\nexport type AgentWorkflowInternalParams = {\n /** Name/ID of the Agent that started this workflow */\n __agentName: string;\n /** Environment binding name for the Agent's namespace */\n __agentBinding: string;\n /** Workflow binding name (for callbacks) */\n __workflowName: string;\n /** Versioned origin identity for top-level Agents and sub-agent facets */\n __agentOrigin?: AgentWorkflowOrigin;\n};\n\n/**\n * Combined workflow params: user params + internal agent params\n */\nexport type AgentWorkflowParams<T = unknown> = T & AgentWorkflowInternalParams;\n\n/**\n * Workflow callback types for Agent-Workflow communication\n */\nexport type WorkflowCallbackType = \"progress\" | \"complete\" | \"error\" | \"event\";\n\n/**\n * Base callback structure sent from Workflow to Agent\n */\nexport type WorkflowCallbackBase = {\n /** Workflow binding name */\n workflowName: string;\n /** ID of the workflow instance */\n workflowId: string;\n /** Type of callback */\n type: WorkflowCallbackType;\n /** Timestamp when callback was sent */\n timestamp: number;\n};\n\n/**\n * Default progress type - covers common use cases.\n * Developers can define their own progress type for domain-specific needs.\n */\nexport type DefaultProgress = {\n /** Current step name */\n step?: string;\n /** Step/overall status */\n status?: \"pending\" | \"running\" | \"complete\" | \"error\";\n /** Human-readable message */\n message?: string;\n /** Progress percentage (0-1) */\n percent?: number;\n /** Allow additional custom fields */\n [key: string]: unknown;\n};\n\n/**\n * Progress callback - reports workflow progress with typed payload\n */\nexport type WorkflowProgressCallback<P = DefaultProgress> =\n WorkflowCallbackBase & {\n type: \"progress\";\n /** Typed progress data */\n progress: P;\n };\n\n/**\n * Complete callback - workflow finished successfully\n */\nexport type WorkflowCompleteCallback = WorkflowCallbackBase & {\n type: \"complete\";\n /** Result of the workflow */\n result?: unknown;\n};\n\n/**\n * Error callback - workflow encountered an error\n */\nexport type WorkflowErrorCallback = WorkflowCallbackBase & {\n type: \"error\";\n /** Error message */\n error: string;\n};\n\n/**\n * Event callback - custom event from workflow\n */\nexport type WorkflowEventCallback = WorkflowCallbackBase & {\n type: \"event\";\n /** Custom event payload */\n event: unknown;\n};\n\n/**\n * Union of all callback types\n */\nexport type WorkflowCallback<P = DefaultProgress> =\n | WorkflowProgressCallback<P>\n | WorkflowCompleteCallback\n | WorkflowErrorCallback\n | WorkflowEventCallback;\n\n/**\n * Workflow status values - derived from Cloudflare's InstanceStatus\n */\nexport type WorkflowStatus = InstanceStatus[\"status\"];\n\n/**\n * Row structure for cf_agents_workflows tracking table\n */\nexport type WorkflowTrackingRow = {\n /** Internal row ID (UUID) */\n id: string;\n /** Cloudflare Workflow instance ID */\n workflow_id: string;\n /** Workflow binding name */\n workflow_name: string;\n /** Current workflow status */\n status: WorkflowStatus;\n /** JSON-serialized metadata for querying */\n metadata: string | null;\n /** Error name if workflow failed */\n error_name: string | null;\n /** Error message if workflow failed */\n error_message: string | null;\n /** Unix timestamp when workflow was created */\n created_at: number;\n /** Unix timestamp when workflow was last updated */\n updated_at: number;\n /** Unix timestamp when workflow completed (null if not complete) */\n completed_at: number | null;\n};\n\n/**\n * Options for runWorkflow()\n */\nexport type RunWorkflowOptions = {\n /** Custom workflow instance ID (auto-generated if not provided) */\n id?: string;\n /** Optional metadata for querying (stored as JSON) */\n metadata?: Record<string, unknown>;\n /** Agent binding name (auto-detected from class name if not provided) */\n agentBinding?: string;\n};\n\n/**\n * Event payload for sendWorkflowEvent()\n */\nexport type WorkflowEventPayload = {\n /** Event type name */\n type: string;\n /** Event payload data */\n payload: unknown;\n};\n\n/**\n * Parsed workflow tracking info returned by getWorkflow()\n */\nexport type WorkflowInfo = {\n /** Internal row ID */\n id: string;\n /** Cloudflare Workflow instance ID */\n workflowId: string;\n /** Workflow binding name */\n workflowName: string;\n /** Current workflow status */\n status: WorkflowStatus;\n /** Metadata (parsed from JSON) */\n metadata: Record<string, unknown> | null;\n /** Error info if workflow failed */\n error: { name: string; message: string } | null;\n /** When workflow was created */\n createdAt: Date;\n /** When workflow was last updated */\n updatedAt: Date;\n /** When workflow completed (null if not complete) */\n completedAt: Date | null;\n};\n\n/**\n * Criteria for querying tracked workflows\n */\nexport type WorkflowQueryCriteria = {\n /** Filter by status */\n status?: WorkflowStatus | WorkflowStatus[];\n /** Filter by workflow binding name */\n workflowName?: string;\n /** Filter by metadata key-value pairs (exact match) */\n metadata?: Record<string, string | number | boolean>;\n /** Limit number of results (default 50, max 100) */\n limit?: number;\n /** Order by created_at */\n orderBy?: \"asc\" | \"desc\";\n /** Cursor for pagination (from previous WorkflowPage.nextCursor) */\n cursor?: string;\n};\n\n/**\n * Paginated result from getWorkflows()\n */\nexport type WorkflowPage = {\n /** Workflows for this page */\n workflows: WorkflowInfo[];\n /** Total count of workflows matching the criteria (ignoring pagination) */\n total: number;\n /** Cursor for next page, or null if no more pages */\n nextCursor: string | null;\n};\n\n/**\n * Standard approval event payload used by approveWorkflow/rejectWorkflow\n */\nexport type ApprovalEventPayload = {\n /** Whether the workflow was approved */\n approved: boolean;\n /** Optional reason for approval/rejection */\n reason?: string;\n /** Optional additional metadata */\n metadata?: Record<string, unknown>;\n};\n\n/**\n * Options for waitForApproval()\n */\nexport type WaitForApprovalOptions = {\n /** Step name for waitForEvent (default: \"wait-for-approval\") */\n stepName?: string;\n /** Timeout duration (e.g., \"7 days\") */\n timeout?: WorkflowSleepDuration;\n /** Event type to wait for (default: \"approval\") */\n eventType?: string;\n};\n\n/**\n * Error thrown when a workflow is rejected via rejectWorkflow()\n */\nexport class WorkflowRejectedError extends Error {\n constructor(\n public readonly reason?: string,\n public readonly workflowId?: string\n ) {\n super(reason ? `Workflow rejected: ${reason}` : \"Workflow rejected\");\n this.name = \"WorkflowRejectedError\";\n }\n}\n"],"mappings":";;;;AAqUA,IAAa,wBAAb,cAA2C,MAAM;CAC/C,YACE,QACA,YACA;EACA,MAAM,SAAS,sBAAsB,WAAW,mBAAmB;EAHnD,KAAA,SAAA;EACA,KAAA,aAAA;EAGhB,KAAK,OAAO;CACd;AACF"}
|