eve 0.81.0 → 0.81.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/src/compiled/.vendor-stamp.json +2 -2
- package/dist/src/compiled/@eve/catalog/index.js +1 -1
- package/dist/src/eve-channel/create-request.d.ts +2 -1
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/eve-channel/request.d.ts +2 -1
- package/dist/src/eve-channel/request.js +1 -2
- package/dist/src/eve-channel/support.d.ts +9 -1
- package/dist/src/eve-channel/support.js +2 -1
- package/dist/src/eve-channel/types.d.ts +18 -0
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/hook-ownership.d.ts +8 -0
- package/dist/src/execution/hook-ownership.js +1 -1
- package/dist/src/execution/session/entry-input.d.ts +19 -5
- package/dist/src/execution/session/entry-input.js +1 -1
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/handoff-steps.d.ts +75 -13
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/handoff.d.ts +69 -27
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/run-watch.d.ts +22 -0
- package/dist/src/execution/session/run-watch.js +1 -0
- package/dist/src/execution/session-inbox/address.d.ts +4 -1
- package/dist/src/execution/session-inbox/end-stranded-session.js +1 -1
- package/dist/src/execution/session-inbox/hook-release.d.ts +9 -2
- package/dist/src/execution/session-inbox/hook-release.js +1 -1
- package/dist/src/execution/session-inbox/inbox.d.ts +66 -6
- package/dist/src/execution/session-inbox/inbox.js +1 -1
- package/dist/src/execution/session-inbox/resume.d.ts +4 -3
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +6 -11
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/model-call/call.js +1 -1
- package/dist/src/instrumentation/content.d.ts +1 -1
- package/dist/src/instrumentation/content.js +1 -1
- package/dist/src/instrumentation/lifecycle.d.ts +4 -2
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/internal/authored-definition/connection.js +1 -1
- package/dist/src/internal/mcp/skills.js +1 -1
- package/dist/src/internal/workflow/development-world-client.js +1 -1
- package/dist/src/public/channels/chat-sdk/messageToUserContent.d.ts +2 -1
- package/dist/src/public/channels/chat-sdk/messageToUserContent.js +1 -1
- package/dist/src/public/channels/photon/attachments.d.ts +5 -2
- package/dist/src/public/channels/photon/attachments.js +1 -1
- package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -1
- package/dist/src/public/channels/slack/api.d.ts +8 -1
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/shared/gateway-routing.d.ts +20 -0
- package/dist/src/shared/gateway-routing.js +1 -0
- package/dist/src/shared/skill-package.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/tracing/eve/agent-otel-provider.js +1 -1
- package/dist/src/tracing/eve/gateway.d.ts +5 -0
- package/dist/src/tracing/eve/gateway.js +1 -1
- package/dist/src/tracing/eve/operation-input.d.ts +0 -7
- package/dist/src/tracing/eve/operation-input.js +1 -1
- package/dist/src/tracing/eve/policy.d.ts +1 -1
- package/dist/src/tracing/eve/policy.js +1 -1
- package/dist/src/tracing/eve/session.d.ts +2 -0
- package/dist/src/tracing/eve/session.js +1 -1
- package/docs/README.md +1 -0
- package/docs/agent-config.md +22 -0
- package/docs/channels/chat-sdk.mdx +4 -2
- package/docs/channels/eve.mdx +27 -0
- package/docs/channels/photon.mdx +4 -2
- package/docs/channels/slack.mdx +2 -0
- package/docs/concepts/execution-model-and-durability.mdx +16 -7
- package/docs/guides/instrumentation/otel.mdx +20 -0
- package/docs/patterns/meta.json +1 -0
- package/docs/patterns/voice-notes.md +67 -0
- package/docs/sandbox/index.mdx +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.81.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e4e0cd1: Fix activation trace-content markers to respect the resolved session policy, provider capture settings, and live audience ceiling. Metadata-only sessions now report withheld content accurately without removing content allowed by an explicit trace policy.
|
|
8
|
+
- 54d63fd: A session keeps accepting messages during a deployment or compaction handoff, so the first message after a handoff reaches the model sooner and messages sent mid-handoff no longer retry or return `409 session_not_ready`; messages already waiting when a compaction finishes now run before the session moves. Sessions started on an earlier eve release still move to this release: their first move uses the previous handoff, and every move after it uses the new one. On Workflow worlds without hook force-claim support, sessions no longer move between runs, so their run history keeps growing for as long as the session lives.
|
|
9
|
+
- fc4dbd0: Cancelling a turn while the model is responding no longer marks its `agent.step` span as an error, so user-initiated stops stop showing up as failures in error tracking.
|
|
10
|
+
- 299db19: Connections now accept the documented `auth.displayName` field instead of failing validation with `Unknown key "displayName"`.
|
|
11
|
+
- 09b423a: `agent.step` spans for AI Gateway model calls now record the Gateway's session affinity report: the session ID, where that ID came from, the affinity outcome, and the pinned and displaced providers. Use these attributes to match a step to its session in the AI Gateway logs Sessions view.
|
|
12
|
+
- f9ea546: The eve channel's `onMessage` can now read the request's `clientContext` as `ctx.eve.clientContext` and return its own `clientContext` to replace it for that turn, so the model sees server-checked context without it being kept in session history.
|
|
13
|
+
- 4d9fc9f: iMessage voice notes now reach Photon agents. Photon's webhook leaves out a voice note's attachment id, so eve refetches the message by id to download it. Across Chat SDK channels, an attachment the platform gives no way to download now reaches the agent as a short note instead of being dropped, so an attachment-only message still gets a reply.
|
|
14
|
+
- 02bb7c4: `ctx.thread.postEphemeral()` on a fresh top-level Slack message now posts to the channel instead of an empty thread, where Slack hid it. Replies inside an existing thread stay threaded.
|
|
15
|
+
|
|
3
16
|
## 0.81.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"moduleFingerprints": {
|
|
3
|
-
"@eve/catalog": "
|
|
3
|
+
"@eve/catalog": "caf42af3641de8f7cd2e10bb9133b2bdbc46d1c24e59f6c5ba79f572c1b1559e",
|
|
4
4
|
"just-secrets": "1ce67d437d0bb06df02e4e99180a3c5f5edf0010314010226e97b96d462bba5d",
|
|
5
5
|
"@vercel/agent-runs": "94231f05d03adf6e62c1c56a941d763e7ed8a25a7c2f3c17a920f68225319325",
|
|
6
6
|
"@workflow/world-local": "a10e78551f65fc607cf75261a569d852c40bc9cfac13a7fb6e15c88bf1ccf429"
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"zod": "4.5.4",
|
|
62
62
|
"zod-validation-error": "5.0.0"
|
|
63
63
|
},
|
|
64
|
-
"scriptHash": "
|
|
64
|
+
"scriptHash": "ec188bdd3997976a304da1fe9805dde1e5cb5eeaa480ea31665a1ae38d6e4908",
|
|
65
65
|
"toolVersions": {
|
|
66
66
|
"rolldown": "1.2.9",
|
|
67
67
|
"typescript": "7.0.2"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e){return[e.mcp?`mcp`:null,e.openapi?`openapi`:null].filter(e=>e!==null)}const t=[{slug:`eve`,name:`Web Chat`,kind:`channel`,tagline:`Embed a first-party web chat UI backed by your agent.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0}},{slug:`slack`,name:`Slack`,kind:`channel`,tagline:`Mention your agent in channels and DMs, with Connect-managed auth.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0}},{slug:`discord`,name:`Discord`,kind:`channel`,tagline:`Run your agent as a Discord bot across servers and threads.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`teams`,name:`Microsoft Teams`,kind:`channel`,tagline:`Bring your agent into Teams chats and channels.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`telegram`,name:`Telegram`,kind:`channel`,tagline:`Connect your agent to a Telegram bot for 1:1 and group chats.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`twilio`,name:`Twilio`,kind:`channel`,tagline:`Put your agent on a phone number: SMS and speech-transcribed calls.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`blooio`,name:`Blooio`,kind:`channel`,tagline:`Send and receive iMessage, RCS, and SMS through Blooio.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`github`,name:`GitHub`,kind:`channel`,tagline:`Drive your agent from issues, pull requests, and comments, with guided Connect setup.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`linear-agent`,name:`Linear Agent`,kind:`channel`,tagline:`Delegate Linear issues and comments through Agent Sessions, with guided Connect setup.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-gchat`,name:`Google Chat`,kind:`channel`,tagline:`Google Chat spaces and DMs via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-whatsapp`,name:`WhatsApp`,kind:`channel`,tagline:`Customer messaging through WhatsApp Business Cloud via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-x`,name:`X`,kind:`channel`,tagline:`Public mentions and DMs on X via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-messenger`,name:`Messenger`,kind:`channel`,tagline:`Facebook Messenger bots with templates, buttons, and reactions via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-zernio`,name:`Zernio`,kind:`channel`,tagline:`Reach seven social and messaging platforms through one Zernio integration.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-velt`,name:`Velt`,kind:`channel`,tagline:`Add agents to anchored comments across documents, canvases, PDFs, and video.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-sendblue`,name:`Sendblue`,kind:`channel`,tagline:`Send and receive iMessage, SMS, and RCS through Sendblue.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-novu`,name:`Novu`,kind:`channel`,tagline:`Reach Slack, Teams, WhatsApp, Telegram, and email through Novu.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-liveblocks`,name:`Liveblocks`,kind:`channel`,tagline:`Bring your agent into Liveblocks comment threads, mentions, and reactions.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`linq`,name:`Linq`,kind:`channel`,tagline:`iMessage and SMS conversations through Linq, with guided Connect or portable setup.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-kapso`,name:`Kapso`,kind:`channel`,tagline:`Managed WhatsApp conversations, media, buttons, and history through Kapso.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`photon`,name:`Photon`,kind:`channel`,tagline:`iMessage through Photon, with guided project and phone setup.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-dial`,name:`Dial`,kind:`channel`,tagline:`Give your agent a phone number for SMS, MMS, iMessage, and voice transcripts.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-agentphone`,name:`AgentPhone`,kind:`channel`,tagline:`SMS, MMS, iMessage, and voice conversations through AgentPhone.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-lark`,name:`Lark / Feishu`,kind:`channel`,tagline:`Lark and Feishu chats with native card streaming via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-beeper`,name:`Beeper`,kind:`channel`,tagline:`Matrix rooms and bridged messaging networks through Beeper.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-resend`,name:`Resend`,kind:`channel`,tagline:`Send and receive threaded email through Resend via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-gmail`,name:`Gmail`,kind:`channel`,tagline:`Turn labelled Gmail threads into agent conversations via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`agent-browser`,name:`agent-browser`,kind:`extension`,tagline:`Add browser automation tools backed by agent-browser to an eve agent.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`blitzreels`,name:`BlitzReels`,kind:`extension`,tagline:`Turn long videos into short clips, generate media, repair edits, and export.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`mux-video`,name:`Mux Video`,kind:`extension`,tagline:`Create and inspect video assets, make clips, and run Mux Robots workflows.`,surfaces:{scaffoldable:!1,registry:!1,gallery:!0}},{slug:`browserbase`,name:`Browserbase`,kind:`extension`,tagline:`Search, fetch, and automate the web with Browserbase and Stagehand.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`github-tools`,name:`GitHub Tools`,kind:`extension`,tagline:`Add scoped GitHub tools with Vercel Connect authentication and approval rules.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`jetty`,name:`Jetty`,kind:`extension`,tagline:`Grade agent turns, compare experiments, and store durable evaluation trajectories.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`link`,name:`Link`,kind:`extension`,tagline:`Give your eve agent guarded access to Link wallet and purchase tools.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`kernel`,name:`KERNEL`,kind:`extension`,tagline:`Let your eve agent use the Internet with KERNEL browser infra, o11y, and stealth. Integrated natively with Vercel Connect and AI Gateway.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`file`,name:`File memory`,kind:`memory`,tagline:`Store durable per-principal memory in a private Vercel Blob store provisioned for the agent.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`supermemory`,name:`Supermemory`,kind:`memory`,tagline:`Give your agents long-term memory, user profiles, and SuperRAG across conversations and context.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`upstash-agentkit`,name:`Upstash AgentKit`,kind:`memory`,tagline:`Give your agents ranked recall and automatic capture on Upstash Redis, or a Redis backend for file memory.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`arcana`,name:`Kybernesis Arcana`,kind:`memory`,tagline:`Give your agents workspace-scoped long-term memory with automatic recall and deliberate storage.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`hindsight`,name:`Hindsight`,kind:`extension`,tagline:`Recall relevant context before every turn and retain each exchange automatically.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`browser-use`,name:`Browser Use`,kind:`connection`,tagline:`Run managed browser automation tasks through Browser Use's MCP server.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Browser Use: run browser automation tasks, inspect sessions, and manage browser profiles.`,mcp:{url:`https://api.browser-use.com/v3/mcp`}}},{slug:`dataforseo`,name:`DataForSEO`,kind:`connection`,tagline:`Run SEO, keyword, and SERP data lookups through DataForSEO's MCP server.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!1},connection:{description:`DataForSEO: run SEO, keyword, and SERP data lookups through DataForSEO's MCP server.`,mcp:{url:`https://mcp.dataforseo.com/v3/mcp`}}},{slug:`vercel`,name:`Vercel`,kind:`connection`,tagline:`Manage Vercel projects, deployments, and logs through Vercel's MCP server.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Vercel: manage projects and deployments, inspect logs, and search documentation.`,mcp:{url:`https://mcp.vercel.com`}}},{slug:`linear`,name:`Linear`,kind:`connection`,tagline:`Issues, projects, cycles, and comments via Linear's MCP server.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Linear workspace: issues, projects, cycles, and comments.`,mcp:{url:`https://mcp.linear.app/mcp`}}},{slug:`notion`,name:`Notion`,kind:`connection`,tagline:`Search and edit Notion pages and databases over MCP or OpenAPI.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Notion workspace: search and edit pages and databases.`,mcp:{url:`https://mcp.notion.com/mcp`},openapi:{spec:`https://developers.notion.com/openapi.json`,baseUrl:`https://api.notion.com`,headers:{"Notion-Version":`2022-06-28`}}}},{slug:`datadog`,name:`Datadog`,kind:`connection`,tagline:`Query metrics, monitors, and logs through Datadog's MCP server.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Datadog: query metrics, monitors, logs, and incidents.`,mcp:{url:`https://mcp.datadoghq.com/api/mcp`}}},{slug:`honeycomb`,name:`Honeycomb`,kind:`connection`,tagline:`Explore traces and run queries through Honeycomb's MCP server.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Honeycomb: explore traces, run queries, and inspect datasets.`,mcp:{url:`https://mcp.honeycomb.io/mcp`}}},{slug:`agentcard`,name:`Agentcard`,kind:`connection`,tagline:`let agents buy online`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:"Agentcard: the agent's wallet. Shop and check out at real merchants (DoorDash, Good Eggs, flights) with the conversational `buy` tool (thread conversation_id on follow-ups), issue a single-use virtual card to pay at any checkout, let the user add their own card, and manage the cash that funds it: balance, top-ups, transactions, KYC, human support.",mcp:{url:`https://mcp.agentcard.sh/mcp`}}},{slug:`airtable`,name:`Airtable`,kind:`connection`,tagline:`Bases, tables, and records through Airtable's MCP server.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Airtable: bases, tables, and records.`,mcp:{url:`https://mcp.airtable.com/mcp`}}},{slug:`bitly`,name:`Bitly`,kind:`connection`,tagline:`Shorten links, generate QR Codes, and track performance.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Bitly: shorten links, generate QR Codes, and track link performance.`,mcp:{url:`https://api-ssl.bitly.com/v4/mcp`}}},{slug:`brex`,name:`Brex`,kind:`connection`,tagline:`Expenses, cards, and cash through Brex's finance automation.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Brex: expenses, cards, budgets, and cash.`,mcp:{url:`https://api.brex.com/mcp`}}},{slug:`candid`,name:`Candid`,kind:`connection`,tagline:`Research nonprofits and funders using Candid's data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Candid: research nonprofits, funders, and grants.`,mcp:{url:`https://mcp.candid.org/mcp`}}},{slug:`clickhouse`,name:`ClickHouse`,kind:`connection`,tagline:`Query and explore your ClickHouse Cloud data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`ClickHouse Cloud: query and explore databases and tables.`,mcp:{url:`https://mcp.clickhouse.cloud/mcp`}}},{slug:`cloudinary`,name:`Cloudinary`,kind:`connection`,tagline:`Manage, transform, and deliver your images and videos.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Cloudinary: manage, transform, and deliver image and video assets.`,mcp:{url:`https://asset-management.mcp.cloudinary.com/sse`}}},{slug:`coda`,name:`Coda`,kind:`connection`,tagline:`Create, search, and update docs and tables.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Coda: create, search, and update docs and tables.`,mcp:{url:`https://coda.io/apis/mcp`}}},{slug:`context`,name:`context.dev`,kind:`connection`,tagline:`search, scrape, extract, and monitor live web data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`context.dev: search the live web, scrape and crawl sites, extract structured data, parse files, retrieve brand intelligence, monitor changes, and run batch jobs.`,mcp:{url:`https://mcp.context.dev/mcp`}}},{slug:`egnyte`,name:`Egnyte`,kind:`connection`,tagline:`Securely access and analyze Egnyte content.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Egnyte: search, access, and analyze governed content.`,mcp:{url:`https://mcp-server.egnyte.com/mcp`}}},{slug:`embat`,name:`Embat`,kind:`connection`,tagline:`Ask Embat about cash, debt, payments, and accounting.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Embat: cash, debt, payments, and accounting.`,mcp:{url:`https://tellme.embat.io/mcp`}}},{slug:`hugging-face`,name:`Hugging Face`,kind:`connection`,tagline:`Access the Hugging Face Hub and thousands of Gradio apps.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Hugging Face: models, datasets, Spaces, and Gradio apps on the Hub.`,mcp:{url:`https://huggingface.co/mcp?login&gradio=none`}}},{slug:`local-falcon`,name:`Local Falcon`,kind:`connection`,tagline:`AI visibility and local search intelligence.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Local Falcon: local search rankings and AI visibility reports.`,mcp:{url:`https://mcp.localfalcon.com`}}},{slug:`make`,name:`Make`,kind:`connection`,tagline:`Run Make scenarios and manage your Make account.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Make: run scenarios and manage automations.`,mcp:{url:`https://mcp.make.com`}}},{slug:`manufact`,name:`Manufact`,kind:`connection`,tagline:`Deploy and monitor MCP servers with Manufact.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Manufact: deploy and monitor MCP servers.`,mcp:{url:`https://mcp.manufact.com/mcp`}}},{slug:`mem0`,name:`Mem0`,kind:`connection`,tagline:`Persistent memory for AI agents and assistants.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Mem0: store and retrieve persistent agent memory.`,mcp:{url:`https://mcp.mem0.ai/mcp`}}},{slug:`miro`,name:`Miro`,kind:`connection`,tagline:`Access and create content on Miro boards.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Miro: read and create content on boards.`,mcp:{url:`https://mcp.miro.com/`}}},{slug:`mixpanel`,name:`Mixpanel`,kind:`connection`,tagline:`Analyze, query, and manage your Mixpanel data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Mixpanel: analyze, query, and manage analytics data.`,mcp:{url:`https://mcp.mixpanel.com/mcp`}}},{slug:`natural`,name:`Natural`,kind:`connection`,tagline:`Send, request, and manage payments with Natural.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Natural: agentic payments — send and request payments, check balances, and move funds.`,mcp:{url:`https://mcp.natural.com/mcp`}}},{slug:`neon`,name:`Neon`,kind:`connection`,tagline:`Manage Neon projects, run queries, and make schema changes.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Neon: manage projects, run queries, and make schema changes.`,mcp:{url:`https://mcp.neon.tech/mcp`}}},{slug:`netlify`,name:`Netlify`,kind:`connection`,tagline:`Create, deploy, manage, and secure websites on Netlify.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Netlify: create, deploy, manage, and secure sites.`,mcp:{url:`https://netlify-mcp.netlify.app/mcp`}}},{slug:`oreilly`,name:`O'Reilly`,kind:`connection`,tagline:`Discover O'Reilly's expert learning content.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`O'Reilly: search books, courses, and learning content.`,mcp:{url:`https://api.oreilly.com/api/content-discovery/v1/mcp/`}}},{slug:`planetscale`,name:`PlanetScale`,kind:`connection`,tagline:`Authenticated access to your PlanetScale Postgres and MySQL databases.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`PlanetScale: query Postgres and MySQL databases.`,mcp:{url:`https://mcp.pscale.dev/mcp/planetscale`}}},{slug:`posthog`,name:`PostHog`,kind:`connection`,tagline:`Query, analyze, and manage your PostHog insights.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`PostHog: insights, events, and feature flags.`,mcp:{url:`https://mcp.posthog.com/mcp`}}},{slug:`postman`,name:`Postman`,kind:`connection`,tagline:`Give API context to your coding agents with Postman.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Postman: APIs, collections, and workspaces.`,mcp:{url:`https://mcp.postman.com/minimal`}}},{slug:`razorpay`,name:`Razorpay`,kind:`connection`,tagline:`Razorpay payments, settlements, and dashboard data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Razorpay: payments, settlements, and dashboard data.`,mcp:{url:`https://mcp.razorpay.com/mcp`}}},{slug:`sanity`,name:`Sanity`,kind:`connection`,tagline:`Query and edit Sanity content, inspect schemas, and manage releases.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Sanity: query content with GROQ, edit documents, inspect schemas, and manage releases.`,mcp:{url:`https://mcp.sanity.io`}}},{slug:`sentry`,name:`Sentry`,kind:`connection`,tagline:`Search, query, and debug errors intelligently.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Sentry: search, query, and debug errors and issues.`,mcp:{url:`https://mcp.sentry.dev/mcp`}}},{slug:`similarweb`,name:`Similarweb`,kind:`connection`,tagline:`Real-time web, mobile app, and market data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Similarweb: web traffic, app, and market intelligence data.`,mcp:{url:`https://mcp.similarweb.com`}}},{slug:`shopify`,name:`Shopify`,kind:`connection`,tagline:`Search products and manage carts and checkouts on a Shopify storefront.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Search products and build carts and checkouts on a Shopify storefront.`,mcp:{url:`https://{shop}.myshopify.com/api/ucp/mcp`}}},{slug:`stripe`,name:`Stripe`,kind:`connection`,tagline:`Payment processing and financial infrastructure tools.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Stripe: payments, customers, billing, and financial infrastructure.`,mcp:{url:`https://mcp.stripe.com`}}},{slug:`supabase`,name:`Supabase`,kind:`connection`,tagline:`Manage databases, authentication, and storage.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Supabase: databases, authentication, and storage.`,mcp:{url:`https://mcp.supabase.com/mcp`}}},{slug:`ticket-tailor`,name:`Ticket Tailor`,kind:`connection`,tagline:`Manage tickets, orders, and events with Ticket Tailor.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Ticket Tailor: events, tickets, and orders.`,mcp:{url:`https://mcp.tickettailor.ai/mcp`}}},{slug:`ticktick`,name:`TickTick`,kind:`connection`,tagline:`Search, create, and manage your tasks and habits in TickTick.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`TickTick: tasks, habits, and lists.`,mcp:{url:`https://mcp.ticktick.com`}}},{slug:`tinybird`,name:`Tinybird`,kind:`connection`,tagline:`Query pipes and data sources in your Tinybird Workspace.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Tinybird: query pipes and data sources, and run SQL. A token grants one Workspace, so add a connection per Workspace.`,mcp:{url:`https://mcp.tinybird.co`}}},{slug:`todoist`,name:`Todoist`,kind:`connection`,tagline:`Search, complete, and manage your tasks in Todoist.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Todoist: search, complete, and manage tasks.`,mcp:{url:`https://ai.todoist.net/mcp`}}},{slug:`webflow`,name:`Webflow`,kind:`connection`,tagline:`Manage Webflow CMS, pages, assets, and sites.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Webflow: CMS items, pages, assets, and sites.`,mcp:{url:`https://mcp.webflow.com/mcp`}}},{slug:`wix`,name:`Wix`,kind:`connection`,tagline:`Manage and build sites and apps on Wix.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Wix: manage and build sites and apps.`,mcp:{url:`https://mcp.wix.com/mcp`}}},{slug:`zapier`,name:`Zapier`,kind:`connection`,tagline:`Automate workflows across thousands of apps.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Zapier: run and manage automations across apps.`,mcp:{url:`https://mcp.zapier.com/api/v1/connect`}}},{slug:`zomato`,name:`Zomato`,kind:`connection`,tagline:`Online food ordering and delivery through Zomato.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Zomato: food ordering and delivery.`,mcp:{url:`https://mcp-server.zomato.com/mcp`}}},{slug:`braintrust`,name:`Braintrust`,kind:`instrumentation`,tagline:`Export AI SDK spans to Braintrust for tracing, evals, and monitoring.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`posthog-instrumentation`,name:`PostHog`,kind:`instrumentation`,tagline:`Send agent traces and generations to PostHog AI Observability.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`sentry-instrumentation`,name:`Sentry`,kind:`instrumentation`,tagline:`Send agent traces to Sentry's OTLP endpoint for tracing and debugging.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`datadog-instrumentation`,name:`Datadog`,kind:`instrumentation`,tagline:`Export agent traces to Datadog APM alongside the rest of your stack.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`honeycomb-instrumentation`,name:`Honeycomb`,kind:`instrumentation`,tagline:`Send OpenTelemetry traces to Honeycomb and query every agent turn.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`arize`,name:`Arize`,kind:`instrumentation`,tagline:`Export traces to Arize AX for LLM observability and evaluation.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`raindrop`,name:`Raindrop`,kind:`instrumentation`,tagline:`Send agent traces to Raindrop to detect and debug AI product issues.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`jaeger`,name:`Jaeger`,kind:`instrumentation`,tagline:`Trace your agent with a local or self-hosted Jaeger OTLP backend.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}}],n=new Map(t.map(e=>[e.slug,e]));function r(e){return n.get(e)}function i(e){return t.filter(t=>t.kind===e)}function a(){return i(`connection`)}function o(){return i(`channel`)}function s(){return i(`extension`)}function c(){return i(`instrumentation`)}function l(){return i(`memory`)}export{t as INTEGRATIONS,o as channelEntries,a as connectionEntries,e as connectionProtocols,s as extensionEntries,r as getIntegrationEntry,c as instrumentationEntries,i as integrationsByKind,l as memoryEntries};
|
|
1
|
+
function e(e){return[e.mcp?`mcp`:null,e.openapi?`openapi`:null].filter(e=>e!==null)}const t=[{slug:`eve`,name:`Web Chat`,kind:`channel`,tagline:`Embed a first-party web chat UI backed by your agent.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0}},{slug:`slack`,name:`Slack`,kind:`channel`,tagline:`Mention your agent in channels and DMs, with Connect-managed auth.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0}},{slug:`discord`,name:`Discord`,kind:`channel`,tagline:`Run your agent as a Discord bot across servers and threads.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`teams`,name:`Microsoft Teams`,kind:`channel`,tagline:`Bring your agent into Teams chats and channels.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`telegram`,name:`Telegram`,kind:`channel`,tagline:`Connect your agent to a Telegram bot for 1:1 and group chats.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`twilio`,name:`Twilio`,kind:`channel`,tagline:`Put your agent on a phone number: SMS and speech-transcribed calls.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`blooio`,name:`Blooio`,kind:`channel`,tagline:`Send and receive iMessage, RCS, and SMS through Blooio.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`github`,name:`GitHub`,kind:`channel`,tagline:`Drive your agent from issues, pull requests, and comments, with guided Connect setup.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`linear-agent`,name:`Linear Agent`,kind:`channel`,tagline:`Delegate Linear issues and comments through Agent Sessions, with guided Connect setup.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-gchat`,name:`Google Chat`,kind:`channel`,tagline:`Google Chat spaces and DMs via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-whatsapp`,name:`WhatsApp`,kind:`channel`,tagline:`Customer messaging through WhatsApp Business Cloud via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-x`,name:`X`,kind:`channel`,tagline:`Public mentions and DMs on X via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-messenger`,name:`Messenger`,kind:`channel`,tagline:`Facebook Messenger bots with templates, buttons, and reactions via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-zernio`,name:`Zernio`,kind:`channel`,tagline:`Reach seven social and messaging platforms through one Zernio integration.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-velt`,name:`Velt`,kind:`channel`,tagline:`Add agents to anchored comments across documents, canvases, PDFs, and video.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-sendblue`,name:`Sendblue`,kind:`channel`,tagline:`Send and receive iMessage, SMS, and RCS through Sendblue.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-novu`,name:`Novu`,kind:`channel`,tagline:`Reach Slack, Teams, WhatsApp, Telegram, and email through Novu.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-liveblocks`,name:`Liveblocks`,kind:`channel`,tagline:`Bring your agent into Liveblocks comment threads, mentions, and reactions.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`linq`,name:`Linq`,kind:`channel`,tagline:`iMessage and SMS conversations through Linq, with guided Connect or portable setup.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-kapso`,name:`Kapso`,kind:`channel`,tagline:`Managed WhatsApp conversations, media, buttons, and history through Kapso.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`photon`,name:`Photon`,kind:`channel`,tagline:`iMessage through Photon, with guided project and phone setup.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-dial`,name:`Dial`,kind:`channel`,tagline:`Give your agent a phone number for SMS, MMS, iMessage, and voice transcripts.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-agentphone`,name:`AgentPhone`,kind:`channel`,tagline:`SMS, MMS, iMessage, and voice conversations through AgentPhone.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-lark`,name:`Lark / Feishu`,kind:`channel`,tagline:`Lark and Feishu chats with native card streaming via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-beeper`,name:`Beeper`,kind:`channel`,tagline:`Matrix rooms and bridged messaging networks through Beeper.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-resend`,name:`Resend`,kind:`channel`,tagline:`Send and receive threaded email through Resend via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`chat-sdk-gmail`,name:`Gmail`,kind:`channel`,tagline:`Turn labelled Gmail threads into agent conversations via the Chat SDK.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`agent-browser`,name:`agent-browser`,kind:`extension`,tagline:`Add browser automation tools backed by agent-browser to an eve agent.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`blitzreels`,name:`BlitzReels`,kind:`extension`,tagline:`Turn long videos into short clips, generate media, repair edits, and export.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`mux-video`,name:`Mux Video`,kind:`extension`,tagline:`Create and inspect video assets, make clips, and run Mux Robots workflows.`,surfaces:{scaffoldable:!1,registry:!1,gallery:!0}},{slug:`browserbase`,name:`Browserbase`,kind:`extension`,tagline:`Search, fetch, and automate the web with Browserbase and Stagehand.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`github-tools`,name:`GitHub Tools`,kind:`extension`,tagline:`Add scoped GitHub tools with Vercel Connect authentication and approval rules.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`jetty`,name:`Jetty`,kind:`extension`,tagline:`Grade agent turns, compare experiments, and store durable evaluation trajectories.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`link`,name:`Link`,kind:`extension`,tagline:`Give your eve agent guarded access to Link wallet and purchase tools.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`kernel`,name:`KERNEL`,kind:`extension`,tagline:`Let your eve agent use the Internet with KERNEL browser infra, o11y, and stealth. Integrated natively with Vercel Connect and AI Gateway.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`file`,name:`File memory`,kind:`memory`,tagline:`Store durable per-principal memory in a private Vercel Blob store provisioned for the agent.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`supermemory`,name:`Supermemory`,kind:`memory`,tagline:`Give your agents long-term memory, user profiles, and SuperRAG across conversations and context.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`upstash-agentkit`,name:`Upstash AgentKit`,kind:`memory`,tagline:`Give your agents ranked recall and automatic capture on Upstash Redis, or a Redis backend for file memory.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`arcana`,name:`Kybernesis Arcana`,kind:`memory`,tagline:`Give your agents workspace-scoped long-term memory with automatic recall and deliberate storage.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`hindsight`,name:`Hindsight`,kind:`memory`,tagline:`Recall relevant context before every turn and retain each exchange automatically.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`browser-use`,name:`Browser Use`,kind:`connection`,tagline:`Run managed browser automation tasks through Browser Use's MCP server.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Browser Use: run browser automation tasks, inspect sessions, and manage browser profiles.`,mcp:{url:`https://api.browser-use.com/v3/mcp`}}},{slug:`dataforseo`,name:`DataForSEO`,kind:`connection`,tagline:`Run SEO, keyword, and SERP data lookups through DataForSEO's MCP server.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!1},connection:{description:`DataForSEO: run SEO, keyword, and SERP data lookups through DataForSEO's MCP server.`,mcp:{url:`https://mcp.dataforseo.com/v3/mcp`}}},{slug:`vercel`,name:`Vercel`,kind:`connection`,tagline:`Manage Vercel projects, deployments, and logs through Vercel's MCP server.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Vercel: manage projects and deployments, inspect logs, and search documentation.`,mcp:{url:`https://mcp.vercel.com`}}},{slug:`linear`,name:`Linear`,kind:`connection`,tagline:`Issues, projects, cycles, and comments via Linear's MCP server.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Linear workspace: issues, projects, cycles, and comments.`,mcp:{url:`https://mcp.linear.app/mcp`}}},{slug:`notion`,name:`Notion`,kind:`connection`,tagline:`Search and edit Notion pages and databases over MCP or OpenAPI.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Notion workspace: search and edit pages and databases.`,mcp:{url:`https://mcp.notion.com/mcp`},openapi:{spec:`https://developers.notion.com/openapi.json`,baseUrl:`https://api.notion.com`,headers:{"Notion-Version":`2022-06-28`}}}},{slug:`datadog`,name:`Datadog`,kind:`connection`,tagline:`Query metrics, monitors, and logs through Datadog's MCP server.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Datadog: query metrics, monitors, logs, and incidents.`,mcp:{url:`https://mcp.datadoghq.com/api/mcp`}}},{slug:`honeycomb`,name:`Honeycomb`,kind:`connection`,tagline:`Explore traces and run queries through Honeycomb's MCP server.`,surfaces:{scaffoldable:!0,registry:!0,gallery:!0},connection:{description:`Honeycomb: explore traces, run queries, and inspect datasets.`,mcp:{url:`https://mcp.honeycomb.io/mcp`}}},{slug:`agentcard`,name:`Agentcard`,kind:`connection`,tagline:`let agents buy online`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:"Agentcard: the agent's wallet. Shop and check out at real merchants (DoorDash, Good Eggs, flights) with the conversational `buy` tool (thread conversation_id on follow-ups), issue a single-use virtual card to pay at any checkout, let the user add their own card, and manage the cash that funds it: balance, top-ups, transactions, KYC, human support.",mcp:{url:`https://mcp.agentcard.sh/mcp`}}},{slug:`airtable`,name:`Airtable`,kind:`connection`,tagline:`Bases, tables, and records through Airtable's MCP server.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Airtable: bases, tables, and records.`,mcp:{url:`https://mcp.airtable.com/mcp`}}},{slug:`bitly`,name:`Bitly`,kind:`connection`,tagline:`Shorten links, generate QR Codes, and track performance.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Bitly: shorten links, generate QR Codes, and track link performance.`,mcp:{url:`https://api-ssl.bitly.com/v4/mcp`}}},{slug:`brex`,name:`Brex`,kind:`connection`,tagline:`Expenses, cards, and cash through Brex's finance automation.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Brex: expenses, cards, budgets, and cash.`,mcp:{url:`https://api.brex.com/mcp`}}},{slug:`candid`,name:`Candid`,kind:`connection`,tagline:`Research nonprofits and funders using Candid's data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Candid: research nonprofits, funders, and grants.`,mcp:{url:`https://mcp.candid.org/mcp`}}},{slug:`clickhouse`,name:`ClickHouse`,kind:`connection`,tagline:`Query and explore your ClickHouse Cloud data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`ClickHouse Cloud: query and explore databases and tables.`,mcp:{url:`https://mcp.clickhouse.cloud/mcp`}}},{slug:`cloudinary`,name:`Cloudinary`,kind:`connection`,tagline:`Manage, transform, and deliver your images and videos.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Cloudinary: manage, transform, and deliver image and video assets.`,mcp:{url:`https://asset-management.mcp.cloudinary.com/sse`}}},{slug:`coda`,name:`Coda`,kind:`connection`,tagline:`Create, search, and update docs and tables.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Coda: create, search, and update docs and tables.`,mcp:{url:`https://coda.io/apis/mcp`}}},{slug:`context`,name:`context.dev`,kind:`connection`,tagline:`search, scrape, extract, and monitor live web data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`context.dev: search the live web, scrape and crawl sites, extract structured data, parse files, retrieve brand intelligence, monitor changes, and run batch jobs.`,mcp:{url:`https://mcp.context.dev/mcp`}}},{slug:`egnyte`,name:`Egnyte`,kind:`connection`,tagline:`Securely access and analyze Egnyte content.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Egnyte: search, access, and analyze governed content.`,mcp:{url:`https://mcp-server.egnyte.com/mcp`}}},{slug:`embat`,name:`Embat`,kind:`connection`,tagline:`Ask Embat about cash, debt, payments, and accounting.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Embat: cash, debt, payments, and accounting.`,mcp:{url:`https://tellme.embat.io/mcp`}}},{slug:`hugging-face`,name:`Hugging Face`,kind:`connection`,tagline:`Access the Hugging Face Hub and thousands of Gradio apps.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Hugging Face: models, datasets, Spaces, and Gradio apps on the Hub.`,mcp:{url:`https://huggingface.co/mcp?login&gradio=none`}}},{slug:`local-falcon`,name:`Local Falcon`,kind:`connection`,tagline:`AI visibility and local search intelligence.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Local Falcon: local search rankings and AI visibility reports.`,mcp:{url:`https://mcp.localfalcon.com`}}},{slug:`make`,name:`Make`,kind:`connection`,tagline:`Run Make scenarios and manage your Make account.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Make: run scenarios and manage automations.`,mcp:{url:`https://mcp.make.com`}}},{slug:`manufact`,name:`Manufact`,kind:`connection`,tagline:`Deploy and monitor MCP servers with Manufact.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Manufact: deploy and monitor MCP servers.`,mcp:{url:`https://mcp.manufact.com/mcp`}}},{slug:`mem0`,name:`Mem0`,kind:`connection`,tagline:`Persistent memory for AI agents and assistants.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Mem0: store and retrieve persistent agent memory.`,mcp:{url:`https://mcp.mem0.ai/mcp`}}},{slug:`miro`,name:`Miro`,kind:`connection`,tagline:`Access and create content on Miro boards.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Miro: read and create content on boards.`,mcp:{url:`https://mcp.miro.com/`}}},{slug:`mixpanel`,name:`Mixpanel`,kind:`connection`,tagline:`Analyze, query, and manage your Mixpanel data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Mixpanel: analyze, query, and manage analytics data.`,mcp:{url:`https://mcp.mixpanel.com/mcp`}}},{slug:`natural`,name:`Natural`,kind:`connection`,tagline:`Send, request, and manage payments with Natural.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Natural: agentic payments — send and request payments, check balances, and move funds.`,mcp:{url:`https://mcp.natural.com/mcp`}}},{slug:`neon`,name:`Neon`,kind:`connection`,tagline:`Manage Neon projects, run queries, and make schema changes.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Neon: manage projects, run queries, and make schema changes.`,mcp:{url:`https://mcp.neon.tech/mcp`}}},{slug:`netlify`,name:`Netlify`,kind:`connection`,tagline:`Create, deploy, manage, and secure websites on Netlify.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Netlify: create, deploy, manage, and secure sites.`,mcp:{url:`https://netlify-mcp.netlify.app/mcp`}}},{slug:`oreilly`,name:`O'Reilly`,kind:`connection`,tagline:`Discover O'Reilly's expert learning content.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`O'Reilly: search books, courses, and learning content.`,mcp:{url:`https://api.oreilly.com/api/content-discovery/v1/mcp/`}}},{slug:`planetscale`,name:`PlanetScale`,kind:`connection`,tagline:`Authenticated access to your PlanetScale Postgres and MySQL databases.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`PlanetScale: query Postgres and MySQL databases.`,mcp:{url:`https://mcp.pscale.dev/mcp/planetscale`}}},{slug:`posthog`,name:`PostHog`,kind:`connection`,tagline:`Query, analyze, and manage your PostHog insights.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`PostHog: insights, events, and feature flags.`,mcp:{url:`https://mcp.posthog.com/mcp`}}},{slug:`postman`,name:`Postman`,kind:`connection`,tagline:`Give API context to your coding agents with Postman.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Postman: APIs, collections, and workspaces.`,mcp:{url:`https://mcp.postman.com/minimal`}}},{slug:`razorpay`,name:`Razorpay`,kind:`connection`,tagline:`Razorpay payments, settlements, and dashboard data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Razorpay: payments, settlements, and dashboard data.`,mcp:{url:`https://mcp.razorpay.com/mcp`}}},{slug:`sanity`,name:`Sanity`,kind:`connection`,tagline:`Query and edit Sanity content, inspect schemas, and manage releases.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Sanity: query content with GROQ, edit documents, inspect schemas, and manage releases.`,mcp:{url:`https://mcp.sanity.io`}}},{slug:`sentry`,name:`Sentry`,kind:`connection`,tagline:`Search, query, and debug errors intelligently.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Sentry: search, query, and debug errors and issues.`,mcp:{url:`https://mcp.sentry.dev/mcp`}}},{slug:`similarweb`,name:`Similarweb`,kind:`connection`,tagline:`Real-time web, mobile app, and market data.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Similarweb: web traffic, app, and market intelligence data.`,mcp:{url:`https://mcp.similarweb.com`}}},{slug:`shopify`,name:`Shopify`,kind:`connection`,tagline:`Search products and manage carts and checkouts on a Shopify storefront.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Search products and build carts and checkouts on a Shopify storefront.`,mcp:{url:`https://{shop}.myshopify.com/api/ucp/mcp`}}},{slug:`stripe`,name:`Stripe`,kind:`connection`,tagline:`Payment processing and financial infrastructure tools.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Stripe: payments, customers, billing, and financial infrastructure.`,mcp:{url:`https://mcp.stripe.com`}}},{slug:`supabase`,name:`Supabase`,kind:`connection`,tagline:`Manage databases, authentication, and storage.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Supabase: databases, authentication, and storage.`,mcp:{url:`https://mcp.supabase.com/mcp`}}},{slug:`ticket-tailor`,name:`Ticket Tailor`,kind:`connection`,tagline:`Manage tickets, orders, and events with Ticket Tailor.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Ticket Tailor: events, tickets, and orders.`,mcp:{url:`https://mcp.tickettailor.ai/mcp`}}},{slug:`ticktick`,name:`TickTick`,kind:`connection`,tagline:`Search, create, and manage your tasks and habits in TickTick.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`TickTick: tasks, habits, and lists.`,mcp:{url:`https://mcp.ticktick.com`}}},{slug:`tinybird`,name:`Tinybird`,kind:`connection`,tagline:`Query pipes and data sources in your Tinybird Workspace.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Tinybird: query pipes and data sources, and run SQL. A token grants one Workspace, so add a connection per Workspace.`,mcp:{url:`https://mcp.tinybird.co`}}},{slug:`todoist`,name:`Todoist`,kind:`connection`,tagline:`Search, complete, and manage your tasks in Todoist.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Todoist: search, complete, and manage tasks.`,mcp:{url:`https://ai.todoist.net/mcp`}}},{slug:`webflow`,name:`Webflow`,kind:`connection`,tagline:`Manage Webflow CMS, pages, assets, and sites.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Webflow: CMS items, pages, assets, and sites.`,mcp:{url:`https://mcp.webflow.com/mcp`}}},{slug:`wix`,name:`Wix`,kind:`connection`,tagline:`Manage and build sites and apps on Wix.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Wix: manage and build sites and apps.`,mcp:{url:`https://mcp.wix.com/mcp`}}},{slug:`zapier`,name:`Zapier`,kind:`connection`,tagline:`Automate workflows across thousands of apps.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Zapier: run and manage automations across apps.`,mcp:{url:`https://mcp.zapier.com/api/v1/connect`}}},{slug:`zomato`,name:`Zomato`,kind:`connection`,tagline:`Online food ordering and delivery through Zomato.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0},connection:{description:`Zomato: food ordering and delivery.`,mcp:{url:`https://mcp-server.zomato.com/mcp`}}},{slug:`braintrust`,name:`Braintrust`,kind:`instrumentation`,tagline:`Export AI SDK spans to Braintrust for tracing, evals, and monitoring.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`posthog-instrumentation`,name:`PostHog`,kind:`instrumentation`,tagline:`Send agent traces and generations to PostHog AI Observability.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`sentry-instrumentation`,name:`Sentry`,kind:`instrumentation`,tagline:`Send agent traces to Sentry's OTLP endpoint for tracing and debugging.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`datadog-instrumentation`,name:`Datadog`,kind:`instrumentation`,tagline:`Export agent traces to Datadog APM alongside the rest of your stack.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`honeycomb-instrumentation`,name:`Honeycomb`,kind:`instrumentation`,tagline:`Send OpenTelemetry traces to Honeycomb and query every agent turn.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`arize`,name:`Arize`,kind:`instrumentation`,tagline:`Export traces to Arize AX for LLM observability and evaluation.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`raindrop`,name:`Raindrop`,kind:`instrumentation`,tagline:`Send agent traces to Raindrop to detect and debug AI product issues.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}},{slug:`jaeger`,name:`Jaeger`,kind:`instrumentation`,tagline:`Trace your agent with a local or self-hosted Jaeger OTLP backend.`,surfaces:{scaffoldable:!1,registry:!0,gallery:!0}}],n=new Map(t.map(e=>[e.slug,e]));function r(e){return n.get(e)}function i(e){return t.filter(t=>t.kind===e)}function a(){return i(`connection`)}function o(){return i(`channel`)}function s(){return i(`extension`)}function c(){return i(`instrumentation`)}function l(){return i(`memory`)}export{t as INTEGRATIONS,o as channelEntries,a as connectionEntries,e as connectionProtocols,s as extensionEntries,r as getIntegrationEntry,c as instrumentationEntries,i as integrationsByKind,l as memoryEntries};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { UserContent } from "ai";
|
|
2
2
|
import type { SessionCallback, SessionCapabilities } from "#channel/types.js";
|
|
3
3
|
import type { LegacyRemoteAgentCaller } from "#execution/legacy-remote-agent/protocol.js";
|
|
4
|
+
import type { ClientContextValue } from "#eve-channel/types.js";
|
|
4
5
|
import type { JsonObject } from "#shared/json.js";
|
|
5
6
|
import type { ToolStub } from "#tool-stubs/types.js";
|
|
6
7
|
export interface ParsedCreateBody {
|
|
@@ -8,7 +9,7 @@ export interface ParsedCreateBody {
|
|
|
8
9
|
callback?: SessionCallback;
|
|
9
10
|
capabilities?: SessionCapabilities;
|
|
10
11
|
message?: string | UserContent;
|
|
11
|
-
context?:
|
|
12
|
+
context?: ClientContextValue;
|
|
12
13
|
operationId?: string;
|
|
13
14
|
outputSchema?: JsonObject;
|
|
14
15
|
/** Remote agent protocol of a delegating caller; set only with {@link callback}. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{attachClientContext}from"#internal/client-context.js";import{createLogger,logError}from"#internal/logging.js";import{FAIL_CLOSED_FORWARDED_TRACE_ASSERTION,formatTraceContentCeiling}from"#shared/forwarded-trace-policy.js";import{EVE_CALLBACK_ROUTE_PATTERN,EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH,EVE_ROUTE_PREFIX,EVE_SESSION_CANCEL_ROUTE_PATTERN,EVE_SESSION_CLEAR_ROUTE_PATTERN,EVE_SESSION_COMPACT_ROUTE_PATTERN,EVE_SESSION_RESET_ROUTE_PATTERN,EVE_SESSION_ROUTE_PATH,EVE_SESSION_ROUTE_PATTERN,EVE_SESSION_STREAM_ROUTE_PATTERN,EVE_SESSION_STUBS_ROUTE_PATTERN,EVE_SUBAGENT_STREAM_ROUTE_PATTERN,createEveSessionStreamRoutePath,createEveSubagentStreamRoutePath}from"#protocol/routes.js";import{EVE_SESSION_ID_HEADER,EVE_STREAM_CONTROL_VERSION_QUERY}from"#protocol/message.js";import{DELETE,GET,HEAD,PATCH,POST,PUT,defineChannel}from"#public/definitions/channel.js";import{readMatchedStubRules,readStubFailure}from"#execution/tool-stubs/steps.js";import{InvalidToolStubTargetError}from"#tool-stubs/validate-targets.js";import{getRun}from"#internal/workflow/runtime.js";import{proxyStreamHeaders}from"#eve-channel/stream-headers.js";import{handleExpiredLegacyAuthorization}from"#execution/legacy-session/authorization.js";import{resolveForwardedPrincipal}from"#channel/forwarded-principal.js";import{handleConnectionCallbackRequest}from"#execution/connections/callback-route.js";import{handleSessionCallbackRequest}from"#subagents/callback-route.js";import{WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest}from"#execution/workflow-webhook-route.js";import{readAgentInfoRouteResponse,readRemoteAgentStreamHeadersResolver,readRouteSessionCreator}from"#internal/nitro/routes/channel-route-context.js";import{legacyTaskInputRoute}from"#execution/legacy-remote-agent/protocol.js";import{parseTraceparent,readAgentDispatchTraceContext}from"#protocol/traceparent.js";import{readForwardedAudienceBaggage,readForwardedParentSessionBaggage}from"#protocol/baggage.js";import{agentDelegation}from"#tracing/eve/delegation.js";import{sessionAuthFromResult}from"#channel/auth/result.js";import{routeAuth}from"#public/channels/auth.js";import{defaultEveAudience}from"#eve-channel/audience.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{checkUploadPolicy,createSessionStreamResponse,deriveOperationContinuationToken,parseCancelTurnBody,parseCreateBody,parseIncludeTailIndex,parseJsonRequest,parseOptionalJsonRequest,parseResetBody,parseSessionControlBody,parseSessionMessageBody,parseStartIndex,rejectSessionContinuationToken,requireSessionId}from"#eve-channel/request.js";import{findRemoteAgentBinding,healthResponse,normalizeEveCors,resolveOnMessage,strandedSessionResponse}from"#eve-channel/support.js";export*from"#eve-channel/types.js";const log=createLogger(`eve.channel`);function createdSessionBody(e,t){let n={ok:!0,sessionId:e,status:`accepted`};return t.protocolVersion!==void 0&&(n.protocolVersion=t.protocolVersion),n}function eveChannel(e){let t=mergeUploadPolicy(e.uploadPolicy);return defineChannel({cors:normalizeEveCors(e.cors),turnPolicy:e.turnPolicy,audience:t=>{let n=e.audience??defaultEveAudience;return typeof n==`function`?n(t):n},routes:[GET(EVE_HEALTH_ROUTE_PATH,async()=>healthResponse()),HEAD(EVE_HEALTH_ROUTE_PATH,async()=>healthResponse()),GET(EVE_INFO_ROUTE_PATH,async(t,n)=>{let r=await routeAuth(t,e.auth);if(r instanceof Response)return r;let i=readAgentInfoRouteResponse(n);return i===void 0?Response.json({error:`Agent info route requires internal channel dispatch context.`,ok:!1},{status:500}):await i()}),GET(`${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`,handleExpiredLegacyAuthorization),POST(`${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`,handleExpiredLegacyAuthorization),GET(EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,handleConnectionCallbackRequest),POST(EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,handleConnectionCallbackRequest),POST(EVE_CALLBACK_ROUTE_PATTERN,handleSessionCallbackRequest),POST(legacyTaskInputRoute.path,legacyTaskInputRoute.handler),GET(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),POST(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),PUT(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),PATCH(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),DELETE(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),POST(EVE_SESSION_ROUTE_PATH,async(n,r)=>{let i=await routeAuth(n,e.auth);if(i instanceof Response)return i;let a=sessionAuthFromResult(i),o=await parseOptionalJsonRequest(n);if(o instanceof Response)return o;if(o.stubs!==void 0&&i.allowToolStubs!==!0)return Response.json({ok:!1,error:`Tool stubbing is not permitted for this caller.`},{status:403});let s=rejectSessionContinuationToken(o);if(s!==null)return s;let c=await resolveForwardedPrincipal({trustedForwarders:e.trustedForwarders,forwarder:a,payload:o});if(c instanceof Response)return c;let l=parseCreateBody(o);if(l instanceof Response)return l;l.callback!==void 0&&l.legacyRemoteAgentCaller!==void 0&&log.info(`serving a remote agent protocol 1 caller`,{callerOrigin:new URL(l.callback.url).origin,forwarder:i.principalId});let u=l.callback===void 0?`absent`:readForwardedParentSessionBaggage(n.headers.get(`baggage`)),d;if(typeof u==`object`){if(u.callId!==l.callback?.callId)log.warn(`ignoring remote parent lineage with a mismatched callback`,{forwarder:i.principalId});else{let t=c.accepted;if(!t&&e.trustedForwarders!==void 0)try{t=await e.trustedForwarders(a,{})}catch(e){let t=logError(log,`trustedForwarders handler failed`,e,{forwarder:i.principalId});return Response.json({error:`trustedForwarders handler failed.`,errorId:t,ok:!1},{status:500})}t?d=u:log.warn(`ignoring remote parent lineage from an untrusted forwarder`,{forwarder:i.principalId})}}else u===`malformed`&&log.warn(`ignoring malformed remote parent lineage`,{forwarder:i.principalId});let f=l.callback===void 0?void 0:parseTraceparent(n.headers.get(`traceparent`)),p=l.callback===void 0?void 0:readAgentDispatchTraceContext(n.headers.get(`tracestate`),f)??f,m=checkUploadPolicy(l,t);if(m!==null)return m;if(l.operationId!==void 0&&c.auth.principalType===`anonymous`)return Response.json({error:`operationId requires an authenticated principal.`,ok:!1},{status:400});let h=l.operationId===void 0?void 0:await deriveOperationContinuationToken({auth:c.auth,operationId:l.operationId});if(h!==void 0){let e=await r.resolveSession(h);if(e!==void 0)return Response.json(createdSessionBody(e.id,l),{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:e.id},status:202})}let g=f===void 0?`absent`:readForwardedAudienceBaggage(n.headers.get(`baggage`)),_=c.accepted&&f!==void 0&&(f.traceFlags&1)==1?typeof g==`object`?g:g===`malformed`?FAIL_CLOSED_FORWARDED_TRACE_ASSERTION:void 0:void 0,v=p;_!==void 0&&p!==void 0&&(v={...p,forwardedTracePolicy:_}),g===`malformed`?log.warn(`using metadata-only policy for malformed forwarded audience baggage`,{forwarder:i.principalId}):typeof g==`object`&&(_===void 0?log.warn(`ignoring forwarded trace policy without an accepted sampled principal`,{forwarder:i.principalId}):log.info(`accepted forwarded trace policy`,{audience:g.originAudience,ceiling:formatTraceContentCeiling(g.ceiling),forwarder:i.principalId}));let y=l.message===void 0?{auth:c.auth}:await resolveOnMessage({auth:c.auth,config:e,invocation:d===void 0||l.operationId===void 0?void 0:{operationId:l.operationId},message:l.message,request:n});if(y instanceof Response)return y;let b=readRouteSessionCreator(r);if(b===void 0)return Response.json({error:`Session creation requires internal channel dispatch context.`,ok:!1},{status:500});let x;try{x=await agentDelegation.receive({headers:n.headers,delegated:l.callback!==void 0,trusted:c.accepted,parent:d,callerTrace:p,parentTraceContext:v},({conversationId:e,parentTraceContext:t})=>b({audienceAuth:a,toolStubs:l.stubs===void 0?void 0:{rules:l.stubs,token:crypto.randomUUID()},auth:y.auth,capabilities:l.capabilities??{requestInput:!0},callback:l.callback,legacyRemoteAgentCaller:l.legacyRemoteAgentCaller,continuationToken:h,initiatorAuth:c.accepted?c.initiatorAuth:void 0,input:attachClientContext({message:l.message,context:y.context,outputSchema:l.outputSchema},l.context),conversationId:e,parent:d,parentTraceContext:t,traceRoot:d===void 0?void 0:{kind:`own`},title:y.title}))}catch(e){if(e instanceof InvalidToolStubTargetError)return Response.json({error:e.message,ok:!1},{status:400});let t=logError(log,`session-create request failed`,e);return Response.json({error:`Failed to create the session.`,errorId:t,ok:!1},{status:500})}return Response.json(createdSessionBody(x.sessionId,l),{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:x.sessionId},status:202})}),POST(EVE_SESSION_ROUTE_PATTERN,async(n,{attachSession:r,params:i})=>{let a=await routeAuth(n,e.auth);if(a instanceof Response)return a;let o=requireSessionId(i);if(o instanceof Response)return o;let s=await parseJsonRequest(n);if(s instanceof Response)return s;let c=await resolveForwardedPrincipal({trustedForwarders:e.trustedForwarders,forwarder:sessionAuthFromResult(a),payload:s});if(c instanceof Response)return c;let l=parseSessionMessageBody(s);if(l instanceof Response)return l;let u=checkUploadPolicy(l,t);if(u!==null)return u;let d,f,p=c.auth;if(l.message!==void 0){let t=await resolveOnMessage({auth:c.auth,config:e,message:l.message,request:n,sessionId:o});if(t instanceof Response)return t;d=t.context,f=t.title,p=t.auth}let m;try{let e=r(o),t=attachClientContext({auth:p,callback:l.callback,context:d,outputSchema:l.outputSchema,turnPolicy:l.turnPolicy,title:f},l.context);m=l.inputResponses===void 0?await e.send(l.message,t):await e.respond(l.inputResponses,t)}catch(e){let t=strandedSessionResponse(e);if(t!==void 0)return t;let n=logError(log,`session-message request failed`,e,{sessionId:o});return Response.json({error:`Failed to send the session message.`,errorId:n,ok:!1},{status:500})}return m.status===`accepted`?Response.json({ok:!0,sessionId:m.sessionId,status:`accepted`,deliveryId:m.deliveryId},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:m.sessionId},status:202}):Response.json({code:m.retryable?`session_not_ready`:`session_not_active`,error:m.retryable===!0?`The session is not ready to accept messages yet.`:`The session is no longer active.`,ok:!1},{headers:{"cache-control":`no-store`},status:409})}),POST(EVE_SESSION_CANCEL_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);if(a instanceof Response)return a;let o=await parseCancelTurnBody(t);if(o instanceof Response)return o;let s;try{s=await n(a).cancel({turnId:o.turnId})}catch(e){let t=logError(log,`cancel-turn request failed`,e,{sessionId:a});return Response.json({error:`Failed to cancel the turn.`,errorId:t,ok:!1},{status:500})}return Response.json(s.status===`accepted`?{ok:!0,sessionId:s.sessionId,status:`accepted`}:{ok:!0,status:`no_active_turn`},{headers:{"cache-control":`no-store`},status:s.status===`accepted`?202:200})}),POST(EVE_SESSION_COMPACT_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);if(a instanceof Response)return a;let o=await parseSessionControlBody(t);if(o instanceof Response)return o;let s;try{s=await n(a).compact()}catch(e){let t=logError(log,`session-compaction request failed`,e,{sessionId:a});return Response.json({error:`Failed to compact the session.`,errorId:t,ok:!1},{status:500})}return Response.json(s.status===`accepted`?{ok:!0,sessionId:s.sessionId,status:`accepted`}:{ok:!0,status:`no_active_session`},{headers:{"cache-control":`no-store`},status:s.status===`accepted`?202:200})}),POST(EVE_SESSION_CLEAR_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);if(a instanceof Response)return a;let o=await parseSessionControlBody(t);if(o instanceof Response)return o;let s;try{s=await n(a).clear()}catch(e){let t=strandedSessionResponse(e);if(t!==void 0)return t;let n=logError(log,`session-clear request failed`,e,{sessionId:a});return Response.json({error:`Failed to clear the session context.`,errorId:n,ok:!1},{status:500})}return Response.json({ok:!0,...s},{headers:{"cache-control":`no-store`},status:s.status===`accepted`?202:200})}),POST(EVE_SESSION_RESET_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);if(a instanceof Response)return a;let o=await parseResetBody(t);if(o instanceof Response)return o;let s;try{s=await n(a).reset({reason:o.reason})}catch(e){let t=logError(log,`session-reset request failed`,e,{sessionId:a});return Response.json({error:`Failed to reset the session.`,errorId:t,ok:!1},{status:500})}return Response.json(s.status===`reset`?{ok:!0,previousSessionId:s.previousSessionId,status:`reset`}:{ok:!0,status:`no_active_session`},{headers:{"cache-control":`no-store`}})}),GET(EVE_SESSION_STUBS_ROUTE_PATTERN,async(t,{params:n})=>{let r=await routeAuth(t,e.auth);if(r instanceof Response)return r;if(r.allowToolStubs!==!0)return Response.json({error:`Tool stubbing is not permitted for this caller.`,ok:!1},{status:403});let i=requireSessionId(n);if(i instanceof Response)return i;try{return await getRun(i).exists?Response.json({error:await readStubFailure(i)??null,matchedRuleIds:await readMatchedStubRules(i)},{headers:{"cache-control":`no-store`}}):Response.json({error:`Session not found.`,ok:!1},{status:404})}catch(e){let t=logError(log,`tool-stub verification request failed`,e,{sessionId:i});return Response.json({error:`Failed to verify tool stubs.`,errorId:t,ok:!1},{status:500})}}),GET(EVE_SESSION_STREAM_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);return a instanceof Response?a:await createSessionStreamResponse(t,n(a))}),GET(EVE_SUBAGENT_STREAM_ROUTE_PATTERN,async(t,n)=>{let r=await routeAuth(t,e.auth);if(r instanceof Response)return r;let i=n.params.parentSessionId,a=n.params.callId,o=n.params.childSessionId;if(!i||!a||!o)return Response.json({error:`Missing subagent stream coordinates.`,ok:!1},{status:400});let s=parseStartIndex(t);if(s instanceof Response)return s;let c=parseIncludeTailIndex(t),l=createEveSubagentStreamRoutePath({callId:a,childSessionId:o,parentSessionId:i}),u;try{let e=n.attachSession(i),t=await findRemoteAgentBinding({callId:a,childSessionId:o,childStreamPath:l,parent:e});if(t===void 0)throw Error(`Remote subagent binding not found.`);u=t}catch{return Response.json({error:`Subagent stream not found.`,ok:!1},{status:404})}let d=readRemoteAgentStreamHeadersResolver(n);if(d===void 0)return Response.json({error:`Subagent stream proxy requires internal channel dispatch context.`,ok:!1},{status:500});let f;try{f=await d(u)}catch{return Response.json({error:`Subagent stream not found.`,ok:!1},{status:404})}let p=new URL(createEveSessionStreamRoutePath(o).replace(/^\/+/,``),`${u.url.replace(/\/+$/,``)}/`);s!==void 0&&p.searchParams.set(`startIndex`,String(s));let m=new URL(t.url).searchParams.get(EVE_STREAM_CONTROL_VERSION_QUERY);m!==null&&p.searchParams.set(EVE_STREAM_CONTROL_VERSION_QUERY,m),c&&p.searchParams.set(`includeTailIndex`,`1`);let h=await fetch(p,{cache:`no-store`,headers:f,redirect:`manual`,signal:t.signal}),g=proxyStreamHeaders(h.headers);return new Response(h.body,{headers:g,status:h.status,statusText:h.statusText})})],events:e.events,fetchFile:e.fetchFile,uploadPolicy:e.uploadPolicy})}export{eveChannel};
|
|
1
|
+
import{attachClientContext}from"#internal/client-context.js";import{createLogger,logError}from"#internal/logging.js";import{FAIL_CLOSED_FORWARDED_TRACE_ASSERTION,formatTraceContentCeiling}from"#shared/forwarded-trace-policy.js";import{EVE_CALLBACK_ROUTE_PATTERN,EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH,EVE_ROUTE_PREFIX,EVE_SESSION_CANCEL_ROUTE_PATTERN,EVE_SESSION_CLEAR_ROUTE_PATTERN,EVE_SESSION_COMPACT_ROUTE_PATTERN,EVE_SESSION_RESET_ROUTE_PATTERN,EVE_SESSION_ROUTE_PATH,EVE_SESSION_ROUTE_PATTERN,EVE_SESSION_STREAM_ROUTE_PATTERN,EVE_SESSION_STUBS_ROUTE_PATTERN,EVE_SUBAGENT_STREAM_ROUTE_PATTERN,createEveSessionStreamRoutePath,createEveSubagentStreamRoutePath}from"#protocol/routes.js";import{EVE_SESSION_ID_HEADER,EVE_STREAM_CONTROL_VERSION_QUERY}from"#protocol/message.js";import{DELETE,GET,HEAD,PATCH,POST,PUT,defineChannel}from"#public/definitions/channel.js";import{readMatchedStubRules,readStubFailure}from"#execution/tool-stubs/steps.js";import{InvalidToolStubTargetError}from"#tool-stubs/validate-targets.js";import{getRun}from"#internal/workflow/runtime.js";import{proxyStreamHeaders}from"#eve-channel/stream-headers.js";import{handleExpiredLegacyAuthorization}from"#execution/legacy-session/authorization.js";import{resolveForwardedPrincipal}from"#channel/forwarded-principal.js";import{handleConnectionCallbackRequest}from"#execution/connections/callback-route.js";import{handleSessionCallbackRequest}from"#subagents/callback-route.js";import{WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest}from"#execution/workflow-webhook-route.js";import{readAgentInfoRouteResponse,readRemoteAgentStreamHeadersResolver,readRouteSessionCreator}from"#internal/nitro/routes/channel-route-context.js";import{legacyTaskInputRoute}from"#execution/legacy-remote-agent/protocol.js";import{parseTraceparent,readAgentDispatchTraceContext}from"#protocol/traceparent.js";import{readForwardedAudienceBaggage,readForwardedParentSessionBaggage}from"#protocol/baggage.js";import{agentDelegation}from"#tracing/eve/delegation.js";import{sessionAuthFromResult}from"#channel/auth/result.js";import{routeAuth}from"#public/channels/auth.js";import{defaultEveAudience}from"#eve-channel/audience.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{checkUploadPolicy,createSessionStreamResponse,deriveOperationContinuationToken,parseCancelTurnBody,parseCreateBody,parseIncludeTailIndex,parseJsonRequest,parseOptionalJsonRequest,parseResetBody,parseSessionControlBody,parseSessionMessageBody,parseStartIndex,rejectSessionContinuationToken,requireSessionId}from"#eve-channel/request.js";import{findRemoteAgentBinding,healthResponse,normalizeEveCors,resolveOnMessage,resolveTurnClientContext,strandedSessionResponse}from"#eve-channel/support.js";export*from"#eve-channel/types.js";const log=createLogger(`eve.channel`);function createdSessionBody(e,t){let n={ok:!0,sessionId:e,status:`accepted`};return t.protocolVersion!==void 0&&(n.protocolVersion=t.protocolVersion),n}function eveChannel(e){let t=mergeUploadPolicy(e.uploadPolicy);return defineChannel({cors:normalizeEveCors(e.cors),turnPolicy:e.turnPolicy,audience:t=>{let n=e.audience??defaultEveAudience;return typeof n==`function`?n(t):n},routes:[GET(EVE_HEALTH_ROUTE_PATH,async()=>healthResponse()),HEAD(EVE_HEALTH_ROUTE_PATH,async()=>healthResponse()),GET(EVE_INFO_ROUTE_PATH,async(t,n)=>{let r=await routeAuth(t,e.auth);if(r instanceof Response)return r;let i=readAgentInfoRouteResponse(n);return i===void 0?Response.json({error:`Agent info route requires internal channel dispatch context.`,ok:!1},{status:500}):await i()}),GET(`${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`,handleExpiredLegacyAuthorization),POST(`${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`,handleExpiredLegacyAuthorization),GET(EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,handleConnectionCallbackRequest),POST(EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,handleConnectionCallbackRequest),POST(EVE_CALLBACK_ROUTE_PATTERN,handleSessionCallbackRequest),POST(legacyTaskInputRoute.path,legacyTaskInputRoute.handler),GET(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),POST(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),PUT(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),PATCH(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),DELETE(WORKFLOW_WEBHOOK_ROUTE_PATTERN,handleWorkflowWebhookRequest),POST(EVE_SESSION_ROUTE_PATH,async(n,r)=>{let i=await routeAuth(n,e.auth);if(i instanceof Response)return i;let a=sessionAuthFromResult(i),o=await parseOptionalJsonRequest(n);if(o instanceof Response)return o;if(o.stubs!==void 0&&i.allowToolStubs!==!0)return Response.json({ok:!1,error:`Tool stubbing is not permitted for this caller.`},{status:403});let s=rejectSessionContinuationToken(o);if(s!==null)return s;let c=await resolveForwardedPrincipal({trustedForwarders:e.trustedForwarders,forwarder:a,payload:o});if(c instanceof Response)return c;let l=parseCreateBody(o);if(l instanceof Response)return l;l.callback!==void 0&&l.legacyRemoteAgentCaller!==void 0&&log.info(`serving a remote agent protocol 1 caller`,{callerOrigin:new URL(l.callback.url).origin,forwarder:i.principalId});let u=l.callback===void 0?`absent`:readForwardedParentSessionBaggage(n.headers.get(`baggage`)),d;if(typeof u==`object`){if(u.callId!==l.callback?.callId)log.warn(`ignoring remote parent lineage with a mismatched callback`,{forwarder:i.principalId});else{let t=c.accepted;if(!t&&e.trustedForwarders!==void 0)try{t=await e.trustedForwarders(a,{})}catch(e){let t=logError(log,`trustedForwarders handler failed`,e,{forwarder:i.principalId});return Response.json({error:`trustedForwarders handler failed.`,errorId:t,ok:!1},{status:500})}t?d=u:log.warn(`ignoring remote parent lineage from an untrusted forwarder`,{forwarder:i.principalId})}}else u===`malformed`&&log.warn(`ignoring malformed remote parent lineage`,{forwarder:i.principalId});let f=l.callback===void 0?void 0:parseTraceparent(n.headers.get(`traceparent`)),p=l.callback===void 0?void 0:readAgentDispatchTraceContext(n.headers.get(`tracestate`),f)??f,m=checkUploadPolicy(l,t);if(m!==null)return m;if(l.operationId!==void 0&&c.auth.principalType===`anonymous`)return Response.json({error:`operationId requires an authenticated principal.`,ok:!1},{status:400});let h=l.operationId===void 0?void 0:await deriveOperationContinuationToken({auth:c.auth,operationId:l.operationId});if(h!==void 0){let e=await r.resolveSession(h);if(e!==void 0)return Response.json(createdSessionBody(e.id,l),{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:e.id},status:202})}let g=f===void 0?`absent`:readForwardedAudienceBaggage(n.headers.get(`baggage`)),_=c.accepted&&f!==void 0&&(f.traceFlags&1)==1?typeof g==`object`?g:g===`malformed`?FAIL_CLOSED_FORWARDED_TRACE_ASSERTION:void 0:void 0,v=p;_!==void 0&&p!==void 0&&(v={...p,forwardedTracePolicy:_}),g===`malformed`?log.warn(`using metadata-only policy for malformed forwarded audience baggage`,{forwarder:i.principalId}):typeof g==`object`&&(_===void 0?log.warn(`ignoring forwarded trace policy without an accepted sampled principal`,{forwarder:i.principalId}):log.info(`accepted forwarded trace policy`,{audience:g.originAudience,ceiling:formatTraceContentCeiling(g.ceiling),forwarder:i.principalId}));let y=l.message===void 0?{auth:c.auth,clientContext:resolveTurnClientContext(void 0,l.context)}:await resolveOnMessage({auth:c.auth,clientContext:l.context,config:e,invocation:d===void 0||l.operationId===void 0?void 0:{operationId:l.operationId},message:l.message,request:n});if(y instanceof Response)return y;let b=readRouteSessionCreator(r);if(b===void 0)return Response.json({error:`Session creation requires internal channel dispatch context.`,ok:!1},{status:500});let x;try{x=await agentDelegation.receive({headers:n.headers,delegated:l.callback!==void 0,trusted:c.accepted,parent:d,callerTrace:p,parentTraceContext:v},({conversationId:e,parentTraceContext:t})=>b({audienceAuth:a,toolStubs:l.stubs===void 0?void 0:{rules:l.stubs,token:crypto.randomUUID()},auth:y.auth,capabilities:l.capabilities??{requestInput:!0},callback:l.callback,legacyRemoteAgentCaller:l.legacyRemoteAgentCaller,continuationToken:h,initiatorAuth:c.accepted?c.initiatorAuth:void 0,input:attachClientContext({message:l.message,context:y.context,outputSchema:l.outputSchema},y.clientContext),conversationId:e,parent:d,parentTraceContext:t,traceRoot:d===void 0?void 0:{kind:`own`},title:y.title}))}catch(e){if(e instanceof InvalidToolStubTargetError)return Response.json({error:e.message,ok:!1},{status:400});let t=logError(log,`session-create request failed`,e);return Response.json({error:`Failed to create the session.`,errorId:t,ok:!1},{status:500})}return Response.json(createdSessionBody(x.sessionId,l),{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:x.sessionId},status:202})}),POST(EVE_SESSION_ROUTE_PATTERN,async(n,{attachSession:r,params:i})=>{let a=await routeAuth(n,e.auth);if(a instanceof Response)return a;let o=requireSessionId(i);if(o instanceof Response)return o;let s=await parseJsonRequest(n);if(s instanceof Response)return s;let c=await resolveForwardedPrincipal({trustedForwarders:e.trustedForwarders,forwarder:sessionAuthFromResult(a),payload:s});if(c instanceof Response)return c;let l=parseSessionMessageBody(s);if(l instanceof Response)return l;let u=checkUploadPolicy(l,t);if(u!==null)return u;let d=resolveTurnClientContext(void 0,l.context),f,p,m=c.auth;if(l.message!==void 0){let t=await resolveOnMessage({auth:c.auth,clientContext:l.context,config:e,message:l.message,request:n,sessionId:o});if(t instanceof Response)return t;d=t.clientContext,f=t.context,p=t.title,m=t.auth}let h;try{let e=r(o),t=attachClientContext({auth:m,callback:l.callback,context:f,outputSchema:l.outputSchema,turnPolicy:l.turnPolicy,title:p},d);h=l.inputResponses===void 0?await e.send(l.message,t):await e.respond(l.inputResponses,t)}catch(e){let t=strandedSessionResponse(e);if(t!==void 0)return t;let n=logError(log,`session-message request failed`,e,{sessionId:o});return Response.json({error:`Failed to send the session message.`,errorId:n,ok:!1},{status:500})}return h.status===`accepted`?Response.json({ok:!0,sessionId:h.sessionId,status:`accepted`,deliveryId:h.deliveryId},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:h.sessionId},status:202}):Response.json({code:h.retryable?`session_not_ready`:`session_not_active`,error:h.retryable===!0?`The session is not ready to accept messages yet.`:`The session is no longer active.`,ok:!1},{headers:{"cache-control":`no-store`},status:409})}),POST(EVE_SESSION_CANCEL_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);if(a instanceof Response)return a;let o=await parseCancelTurnBody(t);if(o instanceof Response)return o;let s;try{s=await n(a).cancel({turnId:o.turnId})}catch(e){let t=logError(log,`cancel-turn request failed`,e,{sessionId:a});return Response.json({error:`Failed to cancel the turn.`,errorId:t,ok:!1},{status:500})}return Response.json(s.status===`accepted`?{ok:!0,sessionId:s.sessionId,status:`accepted`}:{ok:!0,status:`no_active_turn`},{headers:{"cache-control":`no-store`},status:s.status===`accepted`?202:200})}),POST(EVE_SESSION_COMPACT_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);if(a instanceof Response)return a;let o=await parseSessionControlBody(t);if(o instanceof Response)return o;let s;try{s=await n(a).compact()}catch(e){let t=logError(log,`session-compaction request failed`,e,{sessionId:a});return Response.json({error:`Failed to compact the session.`,errorId:t,ok:!1},{status:500})}return Response.json(s.status===`accepted`?{ok:!0,sessionId:s.sessionId,status:`accepted`}:{ok:!0,status:`no_active_session`},{headers:{"cache-control":`no-store`},status:s.status===`accepted`?202:200})}),POST(EVE_SESSION_CLEAR_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);if(a instanceof Response)return a;let o=await parseSessionControlBody(t);if(o instanceof Response)return o;let s;try{s=await n(a).clear()}catch(e){let t=strandedSessionResponse(e);if(t!==void 0)return t;let n=logError(log,`session-clear request failed`,e,{sessionId:a});return Response.json({error:`Failed to clear the session context.`,errorId:n,ok:!1},{status:500})}return Response.json({ok:!0,...s},{headers:{"cache-control":`no-store`},status:s.status===`accepted`?202:200})}),POST(EVE_SESSION_RESET_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);if(a instanceof Response)return a;let o=await parseResetBody(t);if(o instanceof Response)return o;let s;try{s=await n(a).reset({reason:o.reason})}catch(e){let t=logError(log,`session-reset request failed`,e,{sessionId:a});return Response.json({error:`Failed to reset the session.`,errorId:t,ok:!1},{status:500})}return Response.json(s.status===`reset`?{ok:!0,previousSessionId:s.previousSessionId,status:`reset`}:{ok:!0,status:`no_active_session`},{headers:{"cache-control":`no-store`}})}),GET(EVE_SESSION_STUBS_ROUTE_PATTERN,async(t,{params:n})=>{let r=await routeAuth(t,e.auth);if(r instanceof Response)return r;if(r.allowToolStubs!==!0)return Response.json({error:`Tool stubbing is not permitted for this caller.`,ok:!1},{status:403});let i=requireSessionId(n);if(i instanceof Response)return i;try{return await getRun(i).exists?Response.json({error:await readStubFailure(i)??null,matchedRuleIds:await readMatchedStubRules(i)},{headers:{"cache-control":`no-store`}}):Response.json({error:`Session not found.`,ok:!1},{status:404})}catch(e){let t=logError(log,`tool-stub verification request failed`,e,{sessionId:i});return Response.json({error:`Failed to verify tool stubs.`,errorId:t,ok:!1},{status:500})}}),GET(EVE_SESSION_STREAM_ROUTE_PATTERN,async(t,{attachSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=requireSessionId(r);return a instanceof Response?a:await createSessionStreamResponse(t,n(a))}),GET(EVE_SUBAGENT_STREAM_ROUTE_PATTERN,async(t,n)=>{let r=await routeAuth(t,e.auth);if(r instanceof Response)return r;let i=n.params.parentSessionId,a=n.params.callId,o=n.params.childSessionId;if(!i||!a||!o)return Response.json({error:`Missing subagent stream coordinates.`,ok:!1},{status:400});let s=parseStartIndex(t);if(s instanceof Response)return s;let c=parseIncludeTailIndex(t),l=createEveSubagentStreamRoutePath({callId:a,childSessionId:o,parentSessionId:i}),u;try{let e=n.attachSession(i),t=await findRemoteAgentBinding({callId:a,childSessionId:o,childStreamPath:l,parent:e});if(t===void 0)throw Error(`Remote subagent binding not found.`);u=t}catch{return Response.json({error:`Subagent stream not found.`,ok:!1},{status:404})}let d=readRemoteAgentStreamHeadersResolver(n);if(d===void 0)return Response.json({error:`Subagent stream proxy requires internal channel dispatch context.`,ok:!1},{status:500});let f;try{f=await d(u)}catch{return Response.json({error:`Subagent stream not found.`,ok:!1},{status:404})}let p=new URL(createEveSessionStreamRoutePath(o).replace(/^\/+/,``),`${u.url.replace(/\/+$/,``)}/`);s!==void 0&&p.searchParams.set(`startIndex`,String(s));let m=new URL(t.url).searchParams.get(EVE_STREAM_CONTROL_VERSION_QUERY);m!==null&&p.searchParams.set(EVE_STREAM_CONTROL_VERSION_QUERY,m),c&&p.searchParams.set(`includeTailIndex`,`1`);let h=await fetch(p,{cache:`no-store`,headers:f,redirect:`manual`,signal:t.signal}),g=proxyStreamHeaders(h.headers);return new Response(h.body,{headers:g,status:h.status,statusText:h.statusText})})],events:e.events,fetchFile:e.fetchFile,uploadPolicy:e.uploadPolicy})}export{eveChannel};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { UserContent } from "ai";
|
|
2
2
|
import type { SessionAuthContext, SessionCallback, TurnPolicy } from "#channel/types.js";
|
|
3
3
|
import type { Session } from "#channel/session.js";
|
|
4
|
+
import type { ClientContextValue } from "#eve-channel/types.js";
|
|
4
5
|
import { type UploadPolicy } from "#public/channels/upload-policy.js";
|
|
5
6
|
import { type ValidatedInputResponse } from "#shared/input.js";
|
|
6
7
|
import { type JsonObject } from "#shared/json.js";
|
|
@@ -15,7 +16,7 @@ interface ParsedSessionMessageBody {
|
|
|
15
16
|
callback?: SessionCallback;
|
|
16
17
|
message?: string | UserContent;
|
|
17
18
|
inputResponses?: readonly ValidatedInputResponse[];
|
|
18
|
-
context?:
|
|
19
|
+
context?: ClientContextValue;
|
|
19
20
|
outputSchema?: JsonObject;
|
|
20
21
|
turnPolicy?: TurnPolicy;
|
|
21
22
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import{isInputResponse}from"#shared/input.js";import{hasInternalRefScheme}from"#internal/attachments/url-refs.js";import{EVE_MESSAGE_STREAM_CONTENT_TYPE,EVE_MESSAGE_STREAM_FORMAT,EVE_MESSAGE_STREAM_VERSION,EVE_SESSION_ID_HEADER,EVE_STREAM_CONTROL_VERSION,EVE_STREAM_CONTROL_VERSION_QUERY,EVE_STREAM_FORMAT_HEADER,EVE_STREAM_LEASE_ENDED_CONTROL,EVE_STREAM_TAIL_INDEX_HEADER,EVE_STREAM_VERSION_HEADER}from"#protocol/message.js";import{parseJsonObject}from"#shared/json.js";import{LEGACY_REMOTE_AGENT_PROTOCOL_VERSION,splitLegacyTaskFields}from"#execution/legacy-remote-agent/protocol.js";import{collectUploadPolicyViolations,formatUploadPolicyViolation}from"#public/channels/upload-policy.js";import{strandedSessionResponse}from"#eve-channel/support.js";import{parseToolStubs}from"#tool-stubs/rules.js";import{parseSessionCallback}from"#channel/session-callback.js";import{isExpiredWorkflowRunError,isMissingWorkflowRunError}from"#internal/workflow/is-inactive-workflow-run-error.js";import{REMOTE_AGENT_PROTOCOL_MISMATCH,REMOTE_AGENT_PROTOCOL_VERSION,readRemoteAgentProtocolVersion}from"#protocol/remote-agent-protocol.js";import{parseTurnPolicyField}from"#eve-channel/turn-policy-request.js";import{validateMessageFreeCreate}from"#eve-channel/create-request.js";async function deriveOperationContinuationToken(e){let t=JSON.stringify([`eve:create-session:v1`,e.auth.authenticator,e.auth.issuer??null,e.auth.principalType,e.auth.principalId,e.operationId]),n=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(t));return`eve:op:${Array.from(new Uint8Array(n),e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,32)}`}function parseCreateBody(e){let t=splitLegacyTaskFields(e),{payload:n}=t;if(n.inputResponses!==void 0)return Response.json({error:`'inputResponses' is only accepted for an existing session.`,ok:!1},{status:400});let r=parseMessageField(n.message);if(r instanceof Response)return r;let i=parseClientContextField(n.clientContext);if(i instanceof Response)return i;let a=parseCallbackField(n.callback);if(a instanceof Response)return a;let o=a===void 0?void 0:parseProtocolVersionField(n.protocolVersion);if(o instanceof Response)return o;let s=parseCapabilitiesField(n.capabilities);if(s instanceof Response)return s;let c=parseOutputSchemaField(n.outputSchema);if(c instanceof Response)return c;let l=validateMessageFreeCreate({callback:a,hasClientContext:n.clientContext!==void 0,hasMessageField:`message`in n,message:r,outputSchema:c});if(l!==void 0)return l;let u=n.operationId;if(u!==void 0&&(typeof u!=`string`||!u))return Response.json({error:`Expected 'operationId' to be a non-empty string.`,ok:!1},{status:400});let d={callback:a,capabilities:s,context:i,outputSchema:c};if(n.stubs!==void 0)try{d.stubs=parseToolStubs(n.stubs)}catch(e){return Response.json({ok:!1,error:e instanceof Error?e.message:`Invalid tool stubs.`},{status:400})}return r!==void 0&&(d.message=r),typeof u==`string`&&(d.operationId=u),o!==void 0&&(d.protocolVersion=o),o===LEGACY_REMOTE_AGENT_PROTOCOL_VERSION&&(d.legacyRemoteAgentCaller=t.taskId===void 0?{}:{taskId:t.taskId}),d}function parseSessionMessageBody(e){let{payload:t}=splitLegacyTaskFields(e);if(Object.hasOwn(t,`stubs`))return Response.json({ok:!1,error:`Tool stubs are fixed at session creation.`},{status:400});let n=rejectSessionContinuationToken(t);if(n!==null)return n;let r=parseMessageField(t.message);if(r instanceof Response)return r;let i=parseCallbackField(t.callback);if(i instanceof Response)return i;let a=parseInputResponses$1(t.inputResponses);if(a instanceof Response)return a;let o=parseClientContextField(t.clientContext);if(o instanceof Response)return o;let s=parseOutputSchemaField(t.outputSchema);if(s instanceof Response)return s;let c=parseTurnPolicyField(t.turnPolicy);return c instanceof Response?c:r===void 0&&a===void 0?Response.json({error:`Expected a non-empty 'message' or a non-empty 'inputResponses' array.`,ok:!1},{status:400}):r!==void 0&&a!==void 0?Response.json({error:`'message' and 'inputResponses' are mutually exclusive.`,ok:!1},{status:400}):{callback:i,message:r,inputResponses:a,context:o,outputSchema:s,turnPolicy:c}}async function parseCancelTurnBody(e){let t=await parseOptionalJsonRequest(e);if(t instanceof Response)return t;let n=rejectSessionContinuationToken(t);if(n!==null)return n;let r=t.turnId;return r!==void 0&&(typeof r!=`string`||r.length===0)?Response.json({error:`Expected 'turnId' to be a non-empty string.`,ok:!1},{status:400}):typeof r==`string`?{turnId:r}:{}}async function parseJsonRequest(e){let t;try{t=await e.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}return typeof t!=`object`||!t||Array.isArray(t)?Response.json({error:`Expected a JSON object.`,ok:!1},{status:400}):t}async function parseResetBody(e){let t=await parseOptionalJsonRequest(e);if(t instanceof Response)return t;let n=rejectSessionContinuationToken(t);if(n!==null)return n;let r=t.reason;return r!==void 0&&(typeof r!=`string`||r.length===0)?Response.json({error:`Expected 'reason' to be a non-empty string.`,ok:!1},{status:400}):r===void 0?{}:{reason:r}}async function parseSessionControlBody(e){let t=await parseOptionalJsonRequest(e);return t instanceof Response?t:rejectSessionContinuationToken(t)??t}async function parseOptionalJsonRequest(e){let t;try{t=await e.text()}catch{return Response.json({error:`Unreadable request body.`,ok:!1},{status:400})}if(t.trim().length===0)return{};let n;try{n=JSON.parse(t)}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}return typeof n!=`object`||!n||Array.isArray(n)?Response.json({error:`Expected a JSON object.`,ok:!1},{status:400}):n}function rejectSessionContinuationToken(e){return`continuationToken`in e?Response.json({error:`Session-ID routes do not accept 'continuationToken'.`,ok:!1},{status:400}):null}function requireSessionId(e){return e.sessionId||Response.json({error:`Missing session id.`,ok:!1},{status:400})}async function createSessionStreamResponse(e,t){let n=parseStartIndex(e);if(n instanceof Response)return n;let r=parseFollow(e),i=!r||parseIncludeTailIndex(e);try{let a=t.getEventStream({follow:r,startIndex:n});a.catch(()=>{});let o;try{o=await t.getStreamTailIndex()}catch(e){throw a.then(e=>e.cancel()).catch(()=>{}),e}let s=await a,c=new URL(e.url).searchParams.get(EVE_STREAM_CONTROL_VERSION_QUERY)===EVE_STREAM_CONTROL_VERSION?EVE_STREAM_CONTROL_VERSION:void 0,l=new Headers({"cache-control":`no-store, no-transform`,"content-type":EVE_MESSAGE_STREAM_CONTENT_TYPE,"x-accel-buffering":`no`,[EVE_SESSION_ID_HEADER]:t.id,[EVE_STREAM_FORMAT_HEADER]:EVE_MESSAGE_STREAM_FORMAT,[EVE_STREAM_VERSION_HEADER]:EVE_MESSAGE_STREAM_VERSION});return i&&l.set(EVE_STREAM_TAIL_INDEX_HEADER,String(o)),new Response(serializeAsNdjson(s,e.signal,i?streamEventLimit(n,o):void 0,c!==void 0),{headers:l})}catch(e){let t=strandedSessionResponse(e);if(t!==void 0)return t;if(isExpiredWorkflowRunError(e))return Response.json({code:`session_expired`,error:`Session history is no longer available.`,ok:!1},{headers:{"cache-control":`no-store`},status:410});let n=isMissingWorkflowRunError(e);return Response.json({error:n?`Session not found.`:`Session stream unavailable.`,ok:!1},{status:n?404:503})}}function parseOutputSchemaField(e){if(e!==void 0)try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'outputSchema' to be a JSON-serializable object.`,ok:!1},{status:400})}}function parseCallbackField(e){if(e===void 0)return;let t=parseSessionCallback(e);return t.ok?t.callback:Response.json({error:t.message,ok:!1},{status:400})}function parseProtocolVersionField(e){if(e!==void 0&&typeof e!=`number`)return Response.json({error:`Expected 'protocolVersion' to be a number.`,ok:!1},{status:400});let t=readRemoteAgentProtocolVersion(e);return t===REMOTE_AGENT_PROTOCOL_VERSION||t===LEGACY_REMOTE_AGENT_PROTOCOL_VERSION?t:Response.json({code:REMOTE_AGENT_PROTOCOL_MISMATCH,error:`This deployment speaks eve remote agent protocol ${String(REMOTE_AGENT_PROTOCOL_VERSION)}, but the caller speaks protocol ${String(t)}. Upgrade both deployments to the same eve release.`,ok:!1,protocolVersion:REMOTE_AGENT_PROTOCOL_VERSION},{status:409})}function parseCapabilitiesField(e){if(e===void 0)return;if(typeof e!=`object`||!e||Array.isArray(e))return Response.json({error:`Expected 'capabilities' to be an object.`,ok:!1},{status:400});let t=Object.keys(e),n=Reflect.get(e,`requestInput`);return t.some(e=>e!==`requestInput`)||n!==void 0&&typeof n!=`boolean`?Response.json({error:`Expected 'capabilities.requestInput' to be a boolean when provided.`,ok:!1},{status:400}):n===void 0?{}:{requestInput:n}}function parseMessageField(e){if(e===void 0)return;if(typeof e==`string`)return e.length>0?e:void 0;if(!Array.isArray(e))return Response.json({error:`Expected 'message' to be a string or an array of text/file parts.`,ok:!1},{status:400});if(e.length===0)return;let t=[];for(let n of e){let e=parseMessagePart(n);if(e instanceof Response)return e;t.push(e)}return t}function parseMessagePart(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected each message part to be an object.`,ok:!1},{status:400});let t=e;if(t.type===`text`)return typeof t.text!=`string`||t.text.length===0?Response.json({error:`Text parts require a non-empty 'text' string.`,ok:!1},{status:400}):{type:`text`,text:t.text};if(t.type===`file`){if(typeof t.mediaType!=`string`||t.mediaType.length===0)return Response.json({error:`File parts require a non-empty 'mediaType' string.`,ok:!1},{status:400});if(typeof t.data!=`string`)return Response.json({error:`File parts require a 'data' string (base64, data URL, or URL).`,ok:!1},{status:400});if(hasInternalRefScheme(t.data))return Response.json({error:`File part 'data' must not use a framework-internal ref scheme.`,ok:!1},{status:400});let e={type:`file`,mediaType:t.mediaType,data:t.data};return typeof t.filename==`string`&&t.filename.length>0&&(e.filename=t.filename),e}return Response.json({error:`Unsupported message part type "${String(t.type)}". Use 'text' or 'file'.`,ok:!1},{status:400})}function checkUploadPolicy(e,t){if(!e.message)return null;let n=collectUploadPolicyViolations(e.message,t);if(n.length===0)return null;let[r]=n;if(!r)return null;let i=r.kind===`too-large`?413:415;return Response.json({error:formatUploadPolicyViolation(r),ok:!1,violations:n.map(e=>e.kind===`too-large`?{byteLength:e.byteLength,filename:e.filename,kind:e.kind,limit:e.limit,mediaType:e.mediaType}:{allowedMediaTypes:e.allowedMediaTypes,filename:e.filename,kind:e.kind,mediaType:e.mediaType})},{status:i})}function parseInputResponses$1(e){if(e===void 0)return;if(!Array.isArray(e)||e.length===0)return Response.json({error:`Expected 'inputResponses' to be a non-empty array.`,ok:!1},{status:400});let t=e.filter(isInputResponse);return t.length===e.length?t:Response.json({error:`Expected every 'inputResponses' entry to match the HITL response schema.`,ok:!1},{status:400})}function parseClientContextField(e){if(e!==void 0){if(typeof e==`string`)return e.length>0?[toClientContextMessage(e)]:void 0;if(Array.isArray(e))return e.length===0?void 0:e.every(e=>typeof e==`string`&&e.length>0)?e.map(e=>toClientContextMessage(e)):Response.json({error:`Expected 'clientContext' array entries to be non-empty strings.`,ok:!1},{status:400});if(typeof e!=`object`||!e)return Response.json({error:`Expected 'clientContext' to be a string, string array, or JSON object.`,ok:!1},{status:400});try{let t=parseJsonObject(e);return[toClientContextMessage(JSON.stringify(t))]}catch{return Response.json({error:`Expected 'clientContext' to be a JSON-serializable object.`,ok:!1},{status:400})}}}function toClientContextMessage(e){return`Client context:
|
|
2
|
-
${e}`}function parseIncludeTailIndex(e){let t=new URL(e.url).searchParams.get(`includeTailIndex`);return t===`1`||t===`true`}function parseFollow(e){let t=new URL(e.url).searchParams.get(`follow`);return t!==`0`&&t!==`false`}function parseStartIndex(e){let t=new URL(e.url).searchParams.get(`startIndex`);if(t===null)return;let n=Number(t);return!/^-?\d+$/.test(t)||!Number.isSafeInteger(n)?Response.json({error:`Expected startIndex to be an integer.`,ok:!1},{status:400}):n}function streamEventLimit(e,t){if(t===void 0)return;let n=e===void 0?0:e<0?Math.max(0,t+1+e):e;return Math.max(0,t-n+1)}function serializeAsNdjson(e,t,n,r=!1){let i=new TextEncoder,a=0,o,s,clearTimers=()=>{clearTimeout(o),clearTimeout(s),o=void 0,s=void 0},scheduleHeartbeat=e=>{clearTimeout(o),o=setTimeout(()=>{try{e.enqueue(i.encode(`
|
|
1
|
+
import{isInputResponse}from"#shared/input.js";import{hasInternalRefScheme}from"#internal/attachments/url-refs.js";import{EVE_MESSAGE_STREAM_CONTENT_TYPE,EVE_MESSAGE_STREAM_FORMAT,EVE_MESSAGE_STREAM_VERSION,EVE_SESSION_ID_HEADER,EVE_STREAM_CONTROL_VERSION,EVE_STREAM_CONTROL_VERSION_QUERY,EVE_STREAM_FORMAT_HEADER,EVE_STREAM_LEASE_ENDED_CONTROL,EVE_STREAM_TAIL_INDEX_HEADER,EVE_STREAM_VERSION_HEADER}from"#protocol/message.js";import{parseJsonObject}from"#shared/json.js";import{LEGACY_REMOTE_AGENT_PROTOCOL_VERSION,splitLegacyTaskFields}from"#execution/legacy-remote-agent/protocol.js";import{collectUploadPolicyViolations,formatUploadPolicyViolation}from"#public/channels/upload-policy.js";import{strandedSessionResponse}from"#eve-channel/support.js";import{parseToolStubs}from"#tool-stubs/rules.js";import{parseSessionCallback}from"#channel/session-callback.js";import{isExpiredWorkflowRunError,isMissingWorkflowRunError}from"#internal/workflow/is-inactive-workflow-run-error.js";import{REMOTE_AGENT_PROTOCOL_MISMATCH,REMOTE_AGENT_PROTOCOL_VERSION,readRemoteAgentProtocolVersion}from"#protocol/remote-agent-protocol.js";import{parseTurnPolicyField}from"#eve-channel/turn-policy-request.js";import{validateMessageFreeCreate}from"#eve-channel/create-request.js";async function deriveOperationContinuationToken(e){let t=JSON.stringify([`eve:create-session:v1`,e.auth.authenticator,e.auth.issuer??null,e.auth.principalType,e.auth.principalId,e.operationId]),n=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(t));return`eve:op:${Array.from(new Uint8Array(n),e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,32)}`}function parseCreateBody(e){let t=splitLegacyTaskFields(e),{payload:n}=t;if(n.inputResponses!==void 0)return Response.json({error:`'inputResponses' is only accepted for an existing session.`,ok:!1},{status:400});let r=parseMessageField(n.message);if(r instanceof Response)return r;let i=parseClientContextField(n.clientContext);if(i instanceof Response)return i;let a=parseCallbackField(n.callback);if(a instanceof Response)return a;let o=a===void 0?void 0:parseProtocolVersionField(n.protocolVersion);if(o instanceof Response)return o;let s=parseCapabilitiesField(n.capabilities);if(s instanceof Response)return s;let c=parseOutputSchemaField(n.outputSchema);if(c instanceof Response)return c;let l=validateMessageFreeCreate({callback:a,hasClientContext:n.clientContext!==void 0,hasMessageField:`message`in n,message:r,outputSchema:c});if(l!==void 0)return l;let u=n.operationId;if(u!==void 0&&(typeof u!=`string`||!u))return Response.json({error:`Expected 'operationId' to be a non-empty string.`,ok:!1},{status:400});let d={callback:a,capabilities:s,context:i,outputSchema:c};if(n.stubs!==void 0)try{d.stubs=parseToolStubs(n.stubs)}catch(e){return Response.json({ok:!1,error:e instanceof Error?e.message:`Invalid tool stubs.`},{status:400})}return r!==void 0&&(d.message=r),typeof u==`string`&&(d.operationId=u),o!==void 0&&(d.protocolVersion=o),o===LEGACY_REMOTE_AGENT_PROTOCOL_VERSION&&(d.legacyRemoteAgentCaller=t.taskId===void 0?{}:{taskId:t.taskId}),d}function parseSessionMessageBody(e){let{payload:t}=splitLegacyTaskFields(e);if(Object.hasOwn(t,`stubs`))return Response.json({ok:!1,error:`Tool stubs are fixed at session creation.`},{status:400});let n=rejectSessionContinuationToken(t);if(n!==null)return n;let r=parseMessageField(t.message);if(r instanceof Response)return r;let i=parseCallbackField(t.callback);if(i instanceof Response)return i;let a=parseInputResponses$1(t.inputResponses);if(a instanceof Response)return a;let o=parseClientContextField(t.clientContext);if(o instanceof Response)return o;let s=parseOutputSchemaField(t.outputSchema);if(s instanceof Response)return s;let c=parseTurnPolicyField(t.turnPolicy);return c instanceof Response?c:r===void 0&&a===void 0?Response.json({error:`Expected a non-empty 'message' or a non-empty 'inputResponses' array.`,ok:!1},{status:400}):r!==void 0&&a!==void 0?Response.json({error:`'message' and 'inputResponses' are mutually exclusive.`,ok:!1},{status:400}):{callback:i,message:r,inputResponses:a,context:o,outputSchema:s,turnPolicy:c}}async function parseCancelTurnBody(e){let t=await parseOptionalJsonRequest(e);if(t instanceof Response)return t;let n=rejectSessionContinuationToken(t);if(n!==null)return n;let r=t.turnId;return r!==void 0&&(typeof r!=`string`||r.length===0)?Response.json({error:`Expected 'turnId' to be a non-empty string.`,ok:!1},{status:400}):typeof r==`string`?{turnId:r}:{}}async function parseJsonRequest(e){let t;try{t=await e.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}return typeof t!=`object`||!t||Array.isArray(t)?Response.json({error:`Expected a JSON object.`,ok:!1},{status:400}):t}async function parseResetBody(e){let t=await parseOptionalJsonRequest(e);if(t instanceof Response)return t;let n=rejectSessionContinuationToken(t);if(n!==null)return n;let r=t.reason;return r!==void 0&&(typeof r!=`string`||r.length===0)?Response.json({error:`Expected 'reason' to be a non-empty string.`,ok:!1},{status:400}):r===void 0?{}:{reason:r}}async function parseSessionControlBody(e){let t=await parseOptionalJsonRequest(e);return t instanceof Response?t:rejectSessionContinuationToken(t)??t}async function parseOptionalJsonRequest(e){let t;try{t=await e.text()}catch{return Response.json({error:`Unreadable request body.`,ok:!1},{status:400})}if(t.trim().length===0)return{};let n;try{n=JSON.parse(t)}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}return typeof n!=`object`||!n||Array.isArray(n)?Response.json({error:`Expected a JSON object.`,ok:!1},{status:400}):n}function rejectSessionContinuationToken(e){return`continuationToken`in e?Response.json({error:`Session-ID routes do not accept 'continuationToken'.`,ok:!1},{status:400}):null}function requireSessionId(e){return e.sessionId||Response.json({error:`Missing session id.`,ok:!1},{status:400})}async function createSessionStreamResponse(e,t){let n=parseStartIndex(e);if(n instanceof Response)return n;let r=parseFollow(e),i=!r||parseIncludeTailIndex(e);try{let a=t.getEventStream({follow:r,startIndex:n});a.catch(()=>{});let o;try{o=await t.getStreamTailIndex()}catch(e){throw a.then(e=>e.cancel()).catch(()=>{}),e}let s=await a,c=new URL(e.url).searchParams.get(EVE_STREAM_CONTROL_VERSION_QUERY)===EVE_STREAM_CONTROL_VERSION?EVE_STREAM_CONTROL_VERSION:void 0,l=new Headers({"cache-control":`no-store, no-transform`,"content-type":EVE_MESSAGE_STREAM_CONTENT_TYPE,"x-accel-buffering":`no`,[EVE_SESSION_ID_HEADER]:t.id,[EVE_STREAM_FORMAT_HEADER]:EVE_MESSAGE_STREAM_FORMAT,[EVE_STREAM_VERSION_HEADER]:EVE_MESSAGE_STREAM_VERSION});return i&&l.set(EVE_STREAM_TAIL_INDEX_HEADER,String(o)),new Response(serializeAsNdjson(s,e.signal,i?streamEventLimit(n,o):void 0,c!==void 0),{headers:l})}catch(e){let t=strandedSessionResponse(e);if(t!==void 0)return t;if(isExpiredWorkflowRunError(e))return Response.json({code:`session_expired`,error:`Session history is no longer available.`,ok:!1},{headers:{"cache-control":`no-store`},status:410});let n=isMissingWorkflowRunError(e);return Response.json({error:n?`Session not found.`:`Session stream unavailable.`,ok:!1},{status:n?404:503})}}function parseOutputSchemaField(e){if(e!==void 0)try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'outputSchema' to be a JSON-serializable object.`,ok:!1},{status:400})}}function parseCallbackField(e){if(e===void 0)return;let t=parseSessionCallback(e);return t.ok?t.callback:Response.json({error:t.message,ok:!1},{status:400})}function parseProtocolVersionField(e){if(e!==void 0&&typeof e!=`number`)return Response.json({error:`Expected 'protocolVersion' to be a number.`,ok:!1},{status:400});let t=readRemoteAgentProtocolVersion(e);return t===REMOTE_AGENT_PROTOCOL_VERSION||t===LEGACY_REMOTE_AGENT_PROTOCOL_VERSION?t:Response.json({code:REMOTE_AGENT_PROTOCOL_MISMATCH,error:`This deployment speaks eve remote agent protocol ${String(REMOTE_AGENT_PROTOCOL_VERSION)}, but the caller speaks protocol ${String(t)}. Upgrade both deployments to the same eve release.`,ok:!1,protocolVersion:REMOTE_AGENT_PROTOCOL_VERSION},{status:409})}function parseCapabilitiesField(e){if(e===void 0)return;if(typeof e!=`object`||!e||Array.isArray(e))return Response.json({error:`Expected 'capabilities' to be an object.`,ok:!1},{status:400});let t=Object.keys(e),n=Reflect.get(e,`requestInput`);return t.some(e=>e!==`requestInput`)||n!==void 0&&typeof n!=`boolean`?Response.json({error:`Expected 'capabilities.requestInput' to be a boolean when provided.`,ok:!1},{status:400}):n===void 0?{}:{requestInput:n}}function parseMessageField(e){if(e===void 0)return;if(typeof e==`string`)return e.length>0?e:void 0;if(!Array.isArray(e))return Response.json({error:`Expected 'message' to be a string or an array of text/file parts.`,ok:!1},{status:400});if(e.length===0)return;let t=[];for(let n of e){let e=parseMessagePart(n);if(e instanceof Response)return e;t.push(e)}return t}function parseMessagePart(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected each message part to be an object.`,ok:!1},{status:400});let t=e;if(t.type===`text`)return typeof t.text!=`string`||t.text.length===0?Response.json({error:`Text parts require a non-empty 'text' string.`,ok:!1},{status:400}):{type:`text`,text:t.text};if(t.type===`file`){if(typeof t.mediaType!=`string`||t.mediaType.length===0)return Response.json({error:`File parts require a non-empty 'mediaType' string.`,ok:!1},{status:400});if(typeof t.data!=`string`)return Response.json({error:`File parts require a 'data' string (base64, data URL, or URL).`,ok:!1},{status:400});if(hasInternalRefScheme(t.data))return Response.json({error:`File part 'data' must not use a framework-internal ref scheme.`,ok:!1},{status:400});let e={type:`file`,mediaType:t.mediaType,data:t.data};return typeof t.filename==`string`&&t.filename.length>0&&(e.filename=t.filename),e}return Response.json({error:`Unsupported message part type "${String(t.type)}". Use 'text' or 'file'.`,ok:!1},{status:400})}function checkUploadPolicy(e,t){if(!e.message)return null;let n=collectUploadPolicyViolations(e.message,t);if(n.length===0)return null;let[r]=n;if(!r)return null;let i=r.kind===`too-large`?413:415;return Response.json({error:formatUploadPolicyViolation(r),ok:!1,violations:n.map(e=>e.kind===`too-large`?{byteLength:e.byteLength,filename:e.filename,kind:e.kind,limit:e.limit,mediaType:e.mediaType}:{allowedMediaTypes:e.allowedMediaTypes,filename:e.filename,kind:e.kind,mediaType:e.mediaType})},{status:i})}function parseInputResponses$1(e){if(e===void 0)return;if(!Array.isArray(e)||e.length===0)return Response.json({error:`Expected 'inputResponses' to be a non-empty array.`,ok:!1},{status:400});let t=e.filter(isInputResponse);return t.length===e.length?t:Response.json({error:`Expected every 'inputResponses' entry to match the HITL response schema.`,ok:!1},{status:400})}function parseClientContextField(e){if(e!==void 0){if(typeof e==`string`)return e.length>0?e:void 0;if(Array.isArray(e))return e.length===0?void 0:e.every(e=>typeof e==`string`&&e.length>0)?e:Response.json({error:`Expected 'clientContext' array entries to be non-empty strings.`,ok:!1},{status:400});if(typeof e!=`object`||!e)return Response.json({error:`Expected 'clientContext' to be a string, string array, or JSON object.`,ok:!1},{status:400});try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'clientContext' to be a JSON-serializable object.`,ok:!1},{status:400})}}}function parseIncludeTailIndex(e){let t=new URL(e.url).searchParams.get(`includeTailIndex`);return t===`1`||t===`true`}function parseFollow(e){let t=new URL(e.url).searchParams.get(`follow`);return t!==`0`&&t!==`false`}function parseStartIndex(e){let t=new URL(e.url).searchParams.get(`startIndex`);if(t===null)return;let n=Number(t);return!/^-?\d+$/.test(t)||!Number.isSafeInteger(n)?Response.json({error:`Expected startIndex to be an integer.`,ok:!1},{status:400}):n}function streamEventLimit(e,t){if(t===void 0)return;let n=e===void 0?0:e<0?Math.max(0,t+1+e):e;return Math.max(0,t-n+1)}function serializeAsNdjson(e,t,n,r=!1){let i=new TextEncoder,a=0,o,s,clearTimers=()=>{clearTimeout(o),clearTimeout(s),o=void 0,s=void 0},scheduleHeartbeat=e=>{clearTimeout(o),o=setTimeout(()=>{try{e.enqueue(i.encode(`
|
|
3
2
|
`)),scheduleHeartbeat(e)}catch{clearTimers()}},1e4)},startLease=e=>{scheduleHeartbeat(e),s=setTimeout(()=>{clearTimers();try{e.enqueue(i.encode(`${JSON.stringify(EVE_STREAM_LEASE_ENDED_CONTROL)}\n`)),e.terminate()}catch{}},6e4)},c=new TransformStream({start(e){e.enqueue(i.encode(`
|
|
4
3
|
`)),n===0?e.terminate():r&&startLease(e)},transform(e,t){t.enqueue(i.encode(`${JSON.stringify(e)}\n`)),a+=1,a===n?(clearTimers(),t.terminate()):r&&scheduleHeartbeat(t)},flush(){clearTimers()}});return e.pipeTo(c.writable,{signal:t}).catch(()=>{}).finally(clearTimers),c.readable}export{checkUploadPolicy,createSessionStreamResponse,deriveOperationContinuationToken,parseCancelTurnBody,parseCreateBody,parseIncludeTailIndex,parseJsonRequest,parseOptionalJsonRequest,parseResetBody,parseSessionControlBody,parseSessionMessageBody,parseStartIndex,rejectSessionContinuationToken,requireSessionId};
|
|
@@ -2,7 +2,7 @@ import type { UserContent } from "ai";
|
|
|
2
2
|
import type { SessionAuthContext } from "#channel/types.js";
|
|
3
3
|
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
4
4
|
import type { ChannelCors } from "#public/definitions/channel.js";
|
|
5
|
-
import { type EveChannelCors, type EveChannelInput, type EveHandle } from "#eve-channel/types.js";
|
|
5
|
+
import { type ClientContextValue, type EveChannelCors, type EveChannelInput, type EveHandle } from "#eve-channel/types.js";
|
|
6
6
|
export declare function healthResponse(): Response;
|
|
7
7
|
/** Clients display the error text directly; keep operator details in structured fields. */
|
|
8
8
|
export declare function strandedSessionResponse(error: unknown): Response | undefined;
|
|
@@ -30,15 +30,23 @@ export declare function findRemoteAgentBinding(input: RemoteAgentStreamCoordinat
|
|
|
30
30
|
export declare function normalizeEveCors(cors: EveChannelCors | undefined): ChannelCors;
|
|
31
31
|
interface OnMessageOutcome {
|
|
32
32
|
readonly auth: SessionAuthContext | null;
|
|
33
|
+
/** Model-ready turn context: `onMessage`'s replacement, or the request's labeled entries. */
|
|
34
|
+
readonly clientContext?: readonly string[];
|
|
33
35
|
readonly context?: readonly string[];
|
|
34
36
|
readonly title?: string;
|
|
35
37
|
}
|
|
36
38
|
export declare function resolveOnMessage(input: {
|
|
37
39
|
readonly auth: SessionAuthContext | null;
|
|
40
|
+
readonly clientContext?: ClientContextValue;
|
|
38
41
|
readonly config: EveChannelInput;
|
|
39
42
|
readonly invocation?: EveHandle["invocation"];
|
|
40
43
|
readonly message: string | UserContent;
|
|
41
44
|
readonly request: Request;
|
|
42
45
|
readonly sessionId?: string;
|
|
43
46
|
}): Promise<OnMessageOutcome | Response>;
|
|
47
|
+
/**
|
|
48
|
+
* The turn's model context messages: `onMessage`'s replacement as written, otherwise
|
|
49
|
+
* the request's entries labeled as client-supplied. Empty means none.
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveTurnClientContext(replacement: ClientContextValue | undefined, requested: ClientContextValue | undefined): readonly string[] | undefined;
|
|
44
52
|
export {};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{SessionStrandedError}from"#channel/session-stranded-error.js";import{defaultEveAuth}from"#eve-channel/types.js";import{workflowEntryReference}from"#execution/workflow-runtime.js";const log=createLogger(`eve.channel`);function healthResponse(){return Response.json({ok:!0,status:`ready`,workflowId:workflowEntryReference.workflowId})}function strandedSessionResponse(e){if(!SessionStrandedError.is(e))return;let t={code:`session_stranded`,error:`This session is no longer available.`,ok:!1};return e.owner.eveVersion!==void 0&&(t.eveVersion=e.owner.eveVersion),Response.json(t,{headers:{"cache-control":`no-store`},status:409})}async function findRemoteAgentBinding(e){let t=await e.parent.getStreamTailIndex();if(t<0)return;let n=(await e.parent.getEventStream({startIndex:0})).getReader();try{for(let r=0;r<=t;r+=1){let t=await n.read();if(t.done)break;let r=readRemoteAgentBinding(t.value,e);if(r!==void 0)return r}}finally{await n.cancel().catch(()=>{})}}function readRemoteAgentBinding(e,t){if(e.type!==`agent.started`)return;let{data:n}=e;if(n.callId===t.callId&&n.sessionId===t.childSessionId&&n.streamPath===t.childStreamPath&&n.remote!==void 0)return{name:n.name,...n.remote}}function normalizeEveCors(e){if(e===void 0||e===!1)return!1;if(e===!0)return!0;let t={};return e.origin!==void 0&&(t.origin=normalizeEveCorsOrigin(e.origin)),e.methods!==void 0&&(t.methods=e.methods),e.allowedHeaders!==void 0&&(t.allowHeaders=e.allowedHeaders),e.exposedHeaders!==void 0&&(t.exposeHeaders=e.exposedHeaders),e.credentials!==void 0&&(t.credentials=e.credentials),e.maxAge!==void 0&&(t.maxAge=e.maxAge),e.preflightStatus!==void 0&&(t.preflight={statusCode:e.preflightStatus}),t}function normalizeEveCorsOrigin(e){return e===`*`||e===`null`?e:typeof e==`string`?[e]:e}async function resolveOnMessage(e){let t=e.config.onMessage??defaultOnMessage,n;try{let r={caller:e.auth,request:e.request};if(n=await t({eve:e.sessionId===void 0?e.invocation===void 0?r:{...r,invocation:e.invocation}:{...r,sessionId:e.sessionId}},e.message),n==null)throw TypeError(`eveChannel onMessage must return an auth result.`)}catch(t){let n=logError(log,`onMessage handler failed`,t,{sessionId:e.sessionId});return Response.json({error:`onMessage handler failed.`,errorId:n,ok:!1},{status:500})}return{auth:n.auth,context:n.context,title:n.title}}function
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{SessionStrandedError}from"#channel/session-stranded-error.js";import{defaultEveAuth}from"#eve-channel/types.js";import{workflowEntryReference}from"#execution/workflow-runtime.js";const log=createLogger(`eve.channel`);function healthResponse(){return Response.json({ok:!0,status:`ready`,workflowId:workflowEntryReference.workflowId})}function strandedSessionResponse(e){if(!SessionStrandedError.is(e))return;let t={code:`session_stranded`,error:`This session is no longer available.`,ok:!1};return e.owner.eveVersion!==void 0&&(t.eveVersion=e.owner.eveVersion),Response.json(t,{headers:{"cache-control":`no-store`},status:409})}async function findRemoteAgentBinding(e){let t=await e.parent.getStreamTailIndex();if(t<0)return;let n=(await e.parent.getEventStream({startIndex:0})).getReader();try{for(let r=0;r<=t;r+=1){let t=await n.read();if(t.done)break;let r=readRemoteAgentBinding(t.value,e);if(r!==void 0)return r}}finally{await n.cancel().catch(()=>{})}}function readRemoteAgentBinding(e,t){if(e.type!==`agent.started`)return;let{data:n}=e;if(n.callId===t.callId&&n.sessionId===t.childSessionId&&n.streamPath===t.childStreamPath&&n.remote!==void 0)return{name:n.name,...n.remote}}function normalizeEveCors(e){if(e===void 0||e===!1)return!1;if(e===!0)return!0;let t={};return e.origin!==void 0&&(t.origin=normalizeEveCorsOrigin(e.origin)),e.methods!==void 0&&(t.methods=e.methods),e.allowedHeaders!==void 0&&(t.allowHeaders=e.allowedHeaders),e.exposedHeaders!==void 0&&(t.exposeHeaders=e.exposedHeaders),e.credentials!==void 0&&(t.credentials=e.credentials),e.maxAge!==void 0&&(t.maxAge=e.maxAge),e.preflightStatus!==void 0&&(t.preflight={statusCode:e.preflightStatus}),t}function normalizeEveCorsOrigin(e){return e===`*`||e===`null`?e:typeof e==`string`?[e]:e}async function resolveOnMessage(e){let t=e.config.onMessage??defaultOnMessage,n;try{let r={caller:e.auth,clientContext:e.clientContext,request:e.request};if(n=await t({eve:e.sessionId===void 0?e.invocation===void 0?r:{...r,invocation:e.invocation}:{...r,sessionId:e.sessionId}},e.message),n==null)throw TypeError(`eveChannel onMessage must return an auth result.`)}catch(t){let n=logError(log,`onMessage handler failed`,t,{sessionId:e.sessionId});return Response.json({error:`onMessage handler failed.`,errorId:n,ok:!1},{status:500})}return{auth:n.auth,clientContext:resolveTurnClientContext(n.clientContext,e.clientContext),context:n.context,title:n.title}}function resolveTurnClientContext(e,t){let n=e===void 0?toContextEntries(t).map(e=>`Client context:
|
|
2
|
+
${e}`):toContextEntries(e);return n.length===0?void 0:n}function toContextEntries(e){return e===void 0||e===``?[]:typeof e==`string`?[e]:Array.isArray(e)?e:[JSON.stringify(e)]}function defaultOnMessage(e){return{auth:defaultEveAuth(e)}}export{findRemoteAgentBinding,healthResponse,normalizeEveCors,resolveOnMessage,resolveTurnClientContext,strandedSessionResponse};
|
|
@@ -4,6 +4,7 @@ import type { TrustedForwarders } from "#channel/forwarded-principal.js";
|
|
|
4
4
|
import type { AuthFn } from "#public/channels/auth.js";
|
|
5
5
|
import type { UploadPolicyInput } from "#public/channels/upload-policy.js";
|
|
6
6
|
import type { FetchFileFunction } from "#shared/channel-definition.js";
|
|
7
|
+
import type { JsonObject } from "#shared/json.js";
|
|
7
8
|
import type { AudienceContext, Channel, ChannelContinuationOps, ChannelEvents, ChannelMethod } from "#public/definitions/channel.js";
|
|
8
9
|
import type { ChannelAudience } from "#shared/channel-audience.js";
|
|
9
10
|
export type { ForwardedAssertion, TrustedForwarders } from "#channel/forwarded-principal.js";
|
|
@@ -39,10 +40,17 @@ export interface EveChannelCorsOptions {
|
|
|
39
40
|
* fully permissive browser access, or pass an options object to narrow it.
|
|
40
41
|
*/
|
|
41
42
|
export type EveChannelCors = boolean | EveChannelCorsOptions;
|
|
43
|
+
/**
|
|
44
|
+
* Turn-scoped context: a string, an array of strings, or a JSON object. The same
|
|
45
|
+
* shape the eve client sends as `clientContext`.
|
|
46
|
+
*/
|
|
47
|
+
export type ClientContextValue = string | readonly string[] | JsonObject;
|
|
42
48
|
/** Low-level eve HTTP handle exposed to `eveChannel({ onMessage })`. */
|
|
43
49
|
export interface EveHandle {
|
|
44
50
|
/** Route-auth result for the request; `onMessage` chooses session auth by returning `{ auth }`. */
|
|
45
51
|
readonly caller: SessionAuthContext | null;
|
|
52
|
+
/** The request's `clientContext`, exactly as the client sent it. `undefined` when it sent none. */
|
|
53
|
+
readonly clientContext?: ClientContextValue;
|
|
46
54
|
/** Replay-stable identity of a trusted remote-subagent create operation. */
|
|
47
55
|
readonly invocation?: {
|
|
48
56
|
readonly operationId: string;
|
|
@@ -61,7 +69,17 @@ export interface EveMessageContext {
|
|
|
61
69
|
*/
|
|
62
70
|
export type EveMessageResult = {
|
|
63
71
|
readonly auth: SessionAuthContext | null;
|
|
72
|
+
/** Context strings prepended as user messages and kept in session history. */
|
|
64
73
|
readonly context?: readonly string[];
|
|
74
|
+
/**
|
|
75
|
+
* Context for this turn only, replacing the request's `clientContext`. Like
|
|
76
|
+
* request `clientContext`, it reaches every model call in the turn and is not
|
|
77
|
+
* kept in session history. It takes the same shape as request `clientContext`
|
|
78
|
+
* and becomes model messages the same way, without the `Client context:` label
|
|
79
|
+
* eve adds to client-supplied entries. Return `[]` to drop the request's
|
|
80
|
+
* context; omit it to keep the request's context.
|
|
81
|
+
*/
|
|
82
|
+
readonly clientContext?: ClientContextValue;
|
|
65
83
|
/** Sets the title when creating a workflow or sending its first message after prewarming. */
|
|
66
84
|
readonly title?: string;
|
|
67
85
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{runJsProgram}from"#execution/dynamic-workflow/workflow.js";async function runWorkflowProgramTask(e,t){"use workflow";return runJsProgram(e.js,t,{maxSubagents:e.maxSubagents??0})}runWorkflowProgramTask.workflowId=`workflow//eve@0.81.
|
|
1
|
+
import{runJsProgram}from"#execution/dynamic-workflow/workflow.js";async function runWorkflowProgramTask(e,t){"use workflow";return runJsProgram(e.js,t,{maxSubagents:e.maxSubagents??0})}runWorkflowProgramTask.workflowId=`workflow//eve@0.81.1//runWorkflowProgramTask`;export{runWorkflowProgramTask};
|
|
@@ -9,3 +9,11 @@ export declare function isHookConflictError(error: unknown): error is {
|
|
|
9
9
|
readonly name: "HookConflictError";
|
|
10
10
|
readonly token?: unknown;
|
|
11
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Another run took the hook's token with `experimental_force`. Matched by name:
|
|
14
|
+
* `HookForceClaimedError.is` lives in a module the workflow bundle cannot load.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isHookForceClaimedError(error: unknown): error is {
|
|
17
|
+
readonly claimedByRunId: string;
|
|
18
|
+
readonly name: "HookForceClaimedError";
|
|
19
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
async function claimHookOwnership(e){let t;try{t=await e.getConflict()}catch(t){return await disposeAndThrow(e,t)}if(t!==null)return await disposeAndThrow(e,createHookConflictError(e.token,t.runId))}async function disposeHook(e){await e.dispose()}async function disposeAndThrow(e,t){try{await disposeHook(e)}catch{}throw t}function isHookConflictError(e){return typeof e==`object`&&!!e&&`name`in e&&e.name===`HookConflictError`}function createHookConflictError(e,t){let n=` (run "${t}")`;return Object.assign(Error(`Hook token "${e}" is already in use${n}`),{conflictingRunId:t,name:`HookConflictError`,token:e})}export{claimHookOwnership,disposeHook,isHookConflictError};
|
|
1
|
+
async function claimHookOwnership(e){let t;try{t=await e.getConflict()}catch(t){return await disposeAndThrow(e,t)}if(t!==null)return await disposeAndThrow(e,createHookConflictError(e.token,t.runId))}async function disposeHook(e){await e.dispose()}async function disposeAndThrow(e,t){try{await disposeHook(e)}catch{}throw t}function isHookConflictError(e){return typeof e==`object`&&!!e&&`name`in e&&e.name===`HookConflictError`}function isHookForceClaimedError(e){return typeof e==`object`&&!!e&&`name`in e&&e.name===`HookForceClaimedError`&&`claimedByRunId`in e&&typeof e.claimedByRunId==`string`}function createHookConflictError(e,t){let n=` (run "${t}")`;return Object.assign(Error(`Hook token "${e}" is already in use${n}`),{conflictingRunId:t,name:`HookConflictError`,token:e})}export{claimHookOwnership,disposeHook,isHookConflictError,isHookForceClaimedError};
|
|
@@ -2,8 +2,12 @@ import type { TokenUsage } from "#shared/token-usage.js";
|
|
|
2
2
|
import type { DeliverHookPayload, RunInput, SessionCommand } from "#channel/types.js";
|
|
3
3
|
import type { SessionCheckpoint } from "#execution/session/handoff.js";
|
|
4
4
|
import type { AgentWorkflowRetentionDefinition } from "#shared/agent-definition.js";
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Version 3 sources keep their hooks while the successor starts: it takes
|
|
7
|
+
* them over with forced claims and the source hands over what it accepted
|
|
8
|
+
* meanwhile. Earlier sources released their hooks before starting it.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SESSION_HANDOFF_VERSION = 3;
|
|
7
11
|
/**
|
|
8
12
|
* Serializable workflow-entry input. All runtime state travels via
|
|
9
13
|
* `serializedContext`, which is produced by `serializeContext(ctx)`
|
|
@@ -34,8 +38,9 @@ export type SessionHandoffStart = {
|
|
|
34
38
|
*/
|
|
35
39
|
readonly reason: "compaction";
|
|
36
40
|
/**
|
|
37
|
-
*
|
|
38
|
-
* first. Without one, the
|
|
41
|
+
* Only sources older than version 3 send one: the lone delivery that
|
|
42
|
+
* arrived before they could move, processed first. Without one, the
|
|
43
|
+
* successor parks until the next input arrives.
|
|
39
44
|
*/
|
|
40
45
|
readonly delivery?: DeliverHookPayload;
|
|
41
46
|
/** Compaction does not extend the session's lifetime. */
|
|
@@ -44,9 +49,18 @@ export type SessionHandoffStart = {
|
|
|
44
49
|
/** A successor owner started by a previous owner during a handoff. */
|
|
45
50
|
export type HandoffWorkflowEntryInput = SessionHandoffStart & {
|
|
46
51
|
readonly activationToken: string;
|
|
52
|
+
/**
|
|
53
|
+
* Version 3: names this attempt, so a duplicate candidate fences itself out
|
|
54
|
+
* and the source's handover reaches the successor that expects it.
|
|
55
|
+
*/
|
|
56
|
+
readonly attemptKey?: string;
|
|
47
57
|
readonly checkpoint: SessionCheckpoint;
|
|
48
|
-
/** Omitted by version 1 sources
|
|
58
|
+
/** Omitted by version 1 sources. */
|
|
49
59
|
readonly handoffVersion?: number;
|
|
60
|
+
/** Version 3: the source's logical hook set, which the successor takes over. */
|
|
61
|
+
readonly hookTokens?: readonly string[];
|
|
62
|
+
/** Version 3: the source run, whose handover the successor waits for while it lives. */
|
|
63
|
+
readonly sourceRunId?: string;
|
|
50
64
|
readonly kind: "handoff";
|
|
51
65
|
readonly ownerDeploymentId: string;
|
|
52
66
|
readonly sessionWritable: WritableStream<Uint8Array>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const SESSION_HANDOFF_VERSION=
|
|
1
|
+
const SESSION_HANDOFF_VERSION=3;export{SESSION_HANDOFF_VERSION};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{attachClientContext,readClientContext}from"#internal/client-context.js";import{SESSION_INBOX_CONTEXT_KEY,sessionCommandHookToken}from"#execution/session-inbox/address.js";import{readSerializedSessionSchedule}from"#context/session-schedule.js";import{getWorkflowMetadata,getWritable}from"#compiled/@workflow/core/index.js";import{isHookConflictError}from"#execution/hook-ownership.js";import{DEFAULT_SESSION_TIMEOUT_MS,sessionTimeoutDeadline}from"#execution/session/timeout.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{createSessionInbox}from"#execution/session-inbox/inbox.js";import{failSession,runPreparedSession}from"#execution/session/program.js";import{createSessionTimeoutControl}from"#execution/session/timeout-control.js";import{
|
|
1
|
+
import{attachClientContext,readClientContext}from"#internal/client-context.js";import{SESSION_INBOX_CONTEXT_KEY,sessionCommandHookToken}from"#execution/session-inbox/address.js";import{readSerializedSessionSchedule}from"#context/session-schedule.js";import{createHook,getWorkflowMetadata,getWritable}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,isHookConflictError}from"#execution/hook-ownership.js";import{DEFAULT_SESSION_TIMEOUT_MS,sessionTimeoutDeadline}from"#execution/session/timeout.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{createSessionInbox}from"#execution/session-inbox/inbox.js";import{failSession,runPreparedSession}from"#execution/session/program.js";import{createSessionTimeoutControl}from"#execution/session/timeout-control.js";import{prepareSuccessorStep,signalSessionOwnerActivationStep,stopUntrackedChildSessionsStep}from"#execution/session/handoff-steps.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{readChannelRequestId,readRootSessionId}from"#execution/eve-workflow-attributes.js";import{createTurnControl}from"#execution/session/turn-control.js";import{HANDOFF_LEASE_RETENTION,handoffLeaseToken,sendSessionHandover}from"#execution/session/handoff.js";import{resolveInitialTurnCallerStep}from"#subagents/parent-notification.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{createSessionStep}from"#execution/create-session-step.js";import{settleContinuationConflictStep}from"#execution/continuation-conflict-step.js";import{migrateSessionCheckpoint}from"#execution/session/checkpoint-migrations.js";import{abandonHandoverIfRunEnds,watchRunEnd}from"#execution/session/run-watch.js";async function workflowEntry(e){"use workflow";let t=e.kind===`initial`?await bootInitialOwner(e,getWorkflowMetadata().workflowRunId):(e.handoffVersion??0)>=3?await bootForcedHandoffOwner(e):await bootReleasedHandoffOwner(e);return t===void 0?{output:``}:{output:(await runPreparedSession(t.session,t.inbox)).output}}function stampSessionIdentity(e,t){return{...e,"eve.sessionId":t,[SESSION_INBOX_CONTEXT_KEY]:{sessionId:t}}}async function prepareInitialOwner(e,t){let[n,r]=await Promise.allSettled([e.claimSessionHook(sessionCommandHookToken(t.sessionId)),t.continuationToken===``?Promise.resolve():e.claimSessionHook(t.continuationToken)]);if(n.status===`rejected`)throw n.reason;if(r.status===`rejected`){if(isHookConflictError(r.reason))return{kind:`alias-conflict`};throw r.reason}let i=createTurnControl(),a=t.deadline===void 0?void 0:createSessionTimeoutControl({deadline:t.deadline,sessionId:t.sessionId}),o={kind:`owned`,timeoutControl:a,turnControl:i,async dispose(){i.dispose(),await a?.dispose()}};return a?.start().catch(()=>{}),o}function unwrapSettled(e){if(e.status===`rejected`)throw e.reason;return e.value}async function disposeInitialBoot(e,t){let[n,r]=await Promise.allSettled([t?.dispose(),e.dispose()]);if(n.status===`rejected`)throw n.reason;if(r.status===`rejected`)throw r.reason}async function bootInitialOwner(e,t){let n=stampSessionIdentity(e.serializedContext,t),r=getWritable(),i=createSessionInbox(t),a=e.sessionTimeoutMs??DEFAULT_SESSION_TIMEOUT_MS,o=sessionTimeoutDeadline(a,Date.now()),s=n[`eve.continuationToken`]||``,c=n[`eve.bundle`],l;try{let u=createSessionStep({compiledArtifactsSource:c.source,continuationToken:s,dynamicSubagentAgentConfig:n[`eve.dynamicSubagentAgentConfig`],inheritedLimits:e.limits,nodeId:c.nodeId,outputSchema:e.input.outputSchema,rootSessionId:readRootSessionId(n),sessionId:t}),d=prepareInitialOwner(i,{continuationToken:s,deadline:o,sessionId:t}),f=hasDelegatedSessionContext(n)?resolveInitialTurnCallerStep({serializedContext:n}):Promise.resolve(void 0),[p,m,h]=await Promise.allSettled([u,d,f]);m.status===`fulfilled`&&m.value.kind===`owned`&&(l=m.value);let g=unwrapSettled(p),_=unwrapSettled(m);if(_.kind===`alias-conflict`){e.continuationConflictCommand!==void 0&&await settleContinuationConflictStep({command:e.continuationConflictCommand,continuationToken:s}),await disposeInitialBoot(i,l);return}return{inbox:i,session:{anchor:{kind:`self`},caller:unwrapSettled(h),capabilities:n[`eve.capabilities`],deploymentId:e.ownerDeploymentId,history:g.history,start:e.input.message===void 0?{kind:`first-message`}:{input:createInitialDelivery(e,n),kind:`turn`},initialTurnControl:_.turnControl,retention:e.retention,serializedContext:n,sessionId:t,sessionState:g.state,sessionTimeoutControl:_.timeoutControl,sessionTimeoutMs:a,sessionTimeoutDeadline:o,sessionWritable:r}}}catch(e){return await disposeInitialBoot(i,l),await failSession({error:e,serializedContext:n,sessionId:t,sessionState:void 0,sessionWritable:r})}}async function prepareSuccessor(e,t){let{sessionId:n}=e,r=migrateSessionCheckpoint(e.checkpoint),i=await prepareSuccessorStep({handoffVersion:e.handoffVersion,migration:r,sessionId:n,...t!==void 0&&{source:t}});if(r.kind===`incompatible`||i.kind===`incompatible`){await signalSessionOwnerActivationStep({activation:{kind:`incompatible`,payloads:[],reason:`checkpoint-version`,runId:getWorkflowMetadata().workflowRunId},token:e.activationToken});return}if(i.kind===`source-gone`){await signalFailedActivation(e,Error(`The session's previous owner no longer holds all of its addresses.`),{payloads:[]});return}let{checkpoint:a,childRunIdsToStop:o}=r;return{checkpoint:a,childRunIdsToStop:o,serializedContext:stampSessionIdentity(a.serializedContext,n)}}async function signalFailedActivation(e,t,n){await signalSessionOwnerActivationStep({activation:{error:normalizeSerializableError(t),kind:`failed`,runId:getWorkflowMetadata().workflowRunId,...n},token:e.activationToken})}async function bootForcedHandoffOwner(e){let{attemptKey:t,hookTokens:n,sessionId:r,sourceRunId:i}=e;if(t===void 0||n===void 0||i===void 0){await signalFailedActivation(e,Error(`Session handoff version 3 input is missing attemptKey, hookTokens, or sourceRunId.`),{payloads:[]});return}try{let e=createHook({experimental_minRetention:HANDOFF_LEASE_RETENTION,token:handoffLeaseToken(t)});await claimHookOwnership(e)}catch(t){if(isHookConflictError(t))return;await signalFailedActivation(e,t,{payloads:[]});return}let a;try{a=await prepareSuccessor(e,{hookTokens:n,runId:i})}catch(t){await signalFailedActivation(e,t,{payloads:[]});return}if(a===void 0)return;let o=createSessionInbox(r);try{await o.claimSessionHooks(n,{force:!0,handover:t})}catch(n){let a=o.claimedTokens.length>0;await signalFailedActivation(e,n,{claimedHooks:a,payloads:[]}),a&&await handBack(o,{attemptKey:t,sessionId:r,sourceRunId:i}),await o.dispose();return}return abandonHandoverIfRunEnds(o,{attemptKey:t,sourceRunId:i}),await startSuccessor(e,o,a)}async function handBack(e,t){let n=watchRunEnd(t.sourceRunId),r=new AbortController;try{if(await Promise.race([e.whenTakenOver(r.signal).then(()=>`taken-back`),n.ended.then(()=>`source-ended`)])===`source-ended`)return}finally{n.stop(),r.abort()}await sendSessionHandover({attemptKey:t.attemptKey,payloads:e.drain(),sessionId:t.sessionId})}async function bootReleasedHandoffOwner(e){let t=createSessionInbox(e.sessionId),n;try{if(n=await prepareSuccessor(e),n===void 0)return;await t.claimSessionHooks(sessionHookTokens({serializedContext:n.serializedContext,sessionState:n.checkpoint.sessionState})),await signalSessionOwnerActivationStep({activation:{kind:`active`},token:e.activationToken})}catch(n){await signalFailedActivation(e,n,{payloads:await t.release()});return}return await startSuccessor(e,t,n)}async function startSuccessor(e,t,n){let{sessionId:r}=e,{checkpoint:i,childRunIdsToStop:a,serializedContext:o}=n;a.length>0&&await stopUntrackedChildSessionsStep({runIds:a,sessionId:r});let s=e.reason===`compaction`?e.sessionTimeoutDeadline:sessionTimeoutDeadline(i.sessionTimeoutMs,Date.now()),c=s===void 0?void 0:createSessionTimeoutControl({deadline:s,sessionId:r});return{inbox:t,session:{anchor:{kind:`successor`},caller:e.delivery?.caller,capabilities:i.capabilities,deploymentId:e.ownerDeploymentId,history:i.history,start:e.delivery===void 0?{kind:`parked`}:{input:e.delivery,kind:`turn`},retention:i.retention,serializedContext:o,sessionId:r,sessionState:i.sessionState,sessionTimeoutControl:c,sessionTimeoutMs:i.sessionTimeoutMs,sessionTimeoutDeadline:s,sessionWritable:e.sessionWritable}}}function createInitialDelivery(e,t){if(e.input.message!==void 0)return{schedule:readSerializedSessionSchedule(t),deliveryMetadata:t[`eve.channelDelivery`]===void 0?void 0:[{...t[`eve.channelDelivery`],payloadIndex:0}],kind:`deliver`,payloads:[attachClientContext({message:e.input.message,context:e.input.context,outputSchema:e.input.outputSchema,state:e.input.state},readClientContext(e.input))],requestId:readChannelRequestId(t)}}workflowEntry.workflowId=`workflow//eve//workflowEntry`;export{bootInitialOwner,workflowEntry};
|