eve 0.81.1 → 0.82.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/src/channel/channel-address.d.ts +21 -2
- package/dist/src/channel/channel-address.js +1 -1
- package/dist/src/channel/channel-operations.d.ts +32 -1
- package/dist/src/channel/channel-operations.js +1 -1
- package/dist/src/channel/delivery-idempotency.d.ts +4 -0
- package/dist/src/channel/delivery-idempotency.js +1 -0
- package/dist/src/channel/routes.d.ts +6 -0
- package/dist/src/channel/session.d.ts +5 -0
- package/dist/src/channel/session.js +1 -1
- package/dist/src/channel/types.d.ts +14 -11
- package/dist/src/chunks/{use-eve-agent-Bp6nbhfV.js → use-eve-agent-DTu78IAF.js} +36 -0
- package/dist/src/chunks/{use-eve-agent-DLkjJIm3.js → use-eve-agent-DlznYwQk.js} +36 -0
- package/dist/src/cli/dev/command-options.d.ts +1 -0
- package/dist/src/cli/dev/diagnostic-dump.js +1 -1
- package/dist/src/cli/run.d.ts +1 -0
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/message-reducer-types.d.ts +7 -3
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/client/transcript-reducer.d.ts +6 -3
- package/dist/src/client/transcript-reducer.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +19 -18
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/load-binding-namespace.d.ts +2 -0
- package/dist/src/compiler/load-binding-namespace.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/module-lifecycle.d.ts +1 -1
- package/dist/src/compiler/module-lifecycle.js +1 -1
- package/dist/src/compiler/module-map.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/compiler/project-sources.d.ts +6 -0
- package/dist/src/compiler/project-sources.js +1 -1
- package/dist/src/context/keys.d.ts +2 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/evals/cli/eval-state-directory.d.ts +7 -0
- package/dist/src/evals/cli/eval-state-directory.js +1 -0
- package/dist/src/evals/cli/eval.js +2 -2
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/eve-channel/support.d.ts +2 -0
- package/dist/src/eve-channel/support.js +1 -1
- package/dist/src/eve-channel/types.d.ts +7 -0
- package/dist/src/execution/agent-sessions/context.d.ts +2 -13
- package/dist/src/execution/agent-sessions/context.js +1 -1
- package/dist/src/execution/agent-sessions/runtime-overrides.d.ts +5 -0
- package/dist/src/execution/agent-sessions/runtime-overrides.js +1 -0
- package/dist/src/execution/agent-sessions/session.d.ts +2 -2
- package/dist/src/execution/agent-sessions/session.js +1 -1
- package/dist/src/execution/agent-sessions/steps.d.ts +2 -0
- package/dist/src/execution/agent-sessions/steps.js +1 -1
- package/dist/src/execution/coordination-dispatch-shared.d.ts +5 -5
- package/dist/src/execution/coordination-dispatch-step.d.ts +17 -2
- package/dist/src/execution/coordination-dispatch-step.js +1 -1
- package/dist/src/execution/create-session-step.d.ts +5 -2
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/deliver-payloads.js +1 -1
- package/dist/src/execution/durable-session-store.d.ts +0 -1
- package/dist/src/execution/dynamic-connection-recovery.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/effective-agent-config.d.ts +8 -2
- package/dist/src/execution/effective-agent-config.js +1 -1
- package/dist/src/execution/install-workflow-deployment-id.d.ts +3 -0
- package/dist/src/execution/install-workflow-deployment-id.js +1 -0
- package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
- package/dist/src/execution/node-step.d.ts +1 -0
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/runtime-context.d.ts +2 -0
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/session/active-turn.js +1 -1
- package/dist/src/execution/session/admission.js +1 -1
- package/dist/src/execution/session/checkpoint-migrations.js +1 -1
- package/dist/src/execution/session/entry-input.d.ts +1 -3
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/finalization.js +1 -1
- package/dist/src/execution/session/handoff.d.ts +6 -9
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/input-queue.d.ts +5 -1
- package/dist/src/execution/session/input-queue.js +1 -1
- package/dist/src/execution/session/pending-history.d.ts +5 -0
- package/dist/src/execution/session/pending-history.js +1 -0
- package/dist/src/execution/session/pending-turn-state.js +1 -1
- package/dist/src/execution/session/program.d.ts +1 -1
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/timeout-control.d.ts +18 -4
- package/dist/src/execution/session/timeout-control.js +1 -1
- package/dist/src/execution/session/timeout.d.ts +1 -2
- package/dist/src/execution/session/timeout.js +1 -1
- package/dist/src/execution/session/turn-event-handler.js +1 -1
- package/dist/src/execution/session/turn-step-result.js +1 -1
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn-waiting-step.js +1 -1
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/session-inbox/protocol.js +1 -1
- package/dist/src/execution/session.d.ts +0 -12
- package/dist/src/execution/session.js +2 -2
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/tasks/model-step.js +1 -1
- package/dist/src/execution/tasks/start.d.ts +4 -4
- package/dist/src/execution/tasks/start.js +1 -1
- package/dist/src/execution/tasks/steps.js +1 -1
- package/dist/src/execution/terminate-child-sessions-step.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/tools/workflow/body.d.ts +2 -2
- package/dist/src/execution/workflow-runtime.d.ts +5 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/hitl/approvals.js +1 -1
- package/dist/src/harness/hitl/budget-request.d.ts +12 -6
- package/dist/src/harness/hitl/budget-request.js +1 -1
- package/dist/src/harness/hitl/budget.d.ts +7 -1
- package/dist/src/harness/hitl/budget.js +1 -1
- package/dist/src/harness/hitl/coordinator.js +1 -1
- package/dist/src/harness/hitl/delivery.d.ts +1 -1
- package/dist/src/harness/hitl/delivery.js +1 -1
- package/dist/src/harness/hitl/index.js +1 -1
- package/dist/src/harness/hitl/intake.d.ts +2 -2
- package/dist/src/harness/hitl/intake.js +1 -1
- package/dist/src/harness/messages.d.ts +5 -0
- package/dist/src/harness/messages.js +1 -1
- package/dist/src/harness/model-call/call.d.ts +2 -2
- package/dist/src/harness/model-call/request.d.ts +2 -2
- package/dist/src/harness/session-machine/transitions.d.ts +3 -1
- package/dist/src/harness/session-machine/transitions.js +1 -1
- package/dist/src/harness/step/context.d.ts +3 -0
- package/dist/src/harness/step/context.js +1 -1
- package/dist/src/harness/step/intake.d.ts +5 -2
- package/dist/src/harness/step/intake.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/turn-tag-state.d.ts +7 -26
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/harness/types.d.ts +10 -25
- package/dist/src/internal/application/build-profile.d.ts +3 -0
- package/dist/src/internal/application/build-profile.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +2 -2
- package/dist/src/internal/application/dev-environment.d.ts +13 -0
- package/dist/src/internal/application/dev-environment.js +1 -1
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/internal/authored-definition/core.js +1 -1
- package/dist/src/internal/authored-module-build-options.d.ts +7 -0
- package/dist/src/internal/authored-module-build-options.js +1 -0
- package/dist/src/internal/authored-module-graph.d.ts +13 -0
- package/dist/src/internal/authored-module-graph.js +1 -0
- package/dist/src/internal/authored-module-loader.d.ts +22 -1
- package/dist/src/internal/authored-module-loader.js +1 -3
- package/dist/src/internal/authored-module.d.ts +7 -0
- package/dist/src/internal/authored-module.js +1 -1
- package/dist/src/internal/authored-package-boundary.js +1 -1
- package/dist/src/internal/bundler/nitro-rolldown.d.ts +5 -1
- package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
- package/dist/src/internal/development-programmatic-source-loader.d.ts +1 -0
- package/dist/src/internal/development-programmatic-source-loader.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-generation-metadata.js +1 -1
- package/dist/src/internal/nitro/host/build-application.js +1 -1
- package/dist/src/internal/nitro/host/build-deployment-id.d.ts +8 -0
- package/dist/src/internal/nitro/host/build-deployment-id.js +1 -0
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/dev-server-state.js +1 -1
- package/dist/src/internal/nitro/host/skill-server-assets.js +1 -1
- package/dist/src/internal/nitro/host/stage-build-deployment-id.d.ts +2 -0
- package/dist/src/internal/nitro/host/stage-build-deployment-id.js +1 -0
- package/dist/src/internal/nitro/host/start-production-server.d.ts +1 -0
- package/dist/src/internal/nitro/host/start-production-server.js +3 -3
- package/dist/src/internal/nitro/routes/schedule-task.d.ts +3 -0
- package/dist/src/internal/nitro/routes/schedule-task.js +1 -1
- package/dist/src/internal/programmatic-source-loader.d.ts +1 -0
- package/dist/src/internal/programmatic-source-loader.js +1 -1
- package/dist/src/internal/schedules/disabled.d.ts +2 -0
- package/dist/src/internal/schedules/disabled.js +1 -0
- package/dist/src/internal/workflow/development-world-server.js +1 -1
- package/dist/src/internal/workflow/local-world-data-directory.d.ts +2 -1
- package/dist/src/internal/workflow/local-world-data-directory.js +1 -1
- package/dist/src/internal/workflow-bundle/builder.js +1 -1
- package/dist/src/protocol/message.d.ts +27 -1
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +13 -0
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/chat-sdk/fetch-message.d.ts +10 -0
- package/dist/src/public/channels/chat-sdk/fetch-message.js +1 -0
- package/dist/src/public/channels/chat-sdk/index.d.ts +1 -1
- package/dist/src/public/channels/chat-sdk/reply-context.d.ts +15 -0
- package/dist/src/public/channels/chat-sdk/reply-context.js +2 -0
- package/dist/src/public/channels/discord/discordChannel.d.ts +3 -0
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/github/dispatch.js +1 -1
- package/dist/src/public/channels/github/githubChannel.d.ts +3 -0
- package/dist/src/public/channels/imessage-tapbacks.d.ts +74 -0
- package/dist/src/public/channels/imessage-tapbacks.js +1 -0
- package/dist/src/public/channels/index.d.ts +2 -1
- package/dist/src/public/channels/index.js +1 -1
- package/dist/src/public/channels/linear/linearChannel.d.ts +3 -0
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/linq/inboundContent.d.ts +7 -0
- package/dist/src/public/channels/linq/inboundContent.js +1 -1
- package/dist/src/public/channels/linq/index.d.ts +1 -0
- package/dist/src/public/channels/linq/index.js +1 -1
- package/dist/src/public/channels/linq/linqChannel.d.ts +17 -1
- package/dist/src/public/channels/linq/linqChannel.js +1 -1
- package/dist/src/public/channels/photon/inboundContent.d.ts +7 -0
- package/dist/src/public/channels/photon/inboundContent.js +2 -1
- package/dist/src/public/channels/photon/index.d.ts +1 -0
- package/dist/src/public/channels/photon/index.js +1 -1
- package/dist/src/public/channels/photon/photonIMessageChannel.d.ts +17 -1
- package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -1
- package/dist/src/public/channels/slack/api.d.ts +6 -0
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/model-context.d.ts +7 -0
- package/dist/src/public/channels/slack/model-context.js +1 -1
- package/dist/src/public/channels/slack/reply-delivery.d.ts +5 -0
- package/dist/src/public/channels/slack/reply-delivery.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +17 -3
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -0
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.d.ts +3 -0
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/definitions/agent.d.ts +1 -1
- package/dist/src/public/definitions/channel.d.ts +2 -2
- package/dist/src/public/definitions/channel.js +1 -1
- package/dist/src/public/definitions/hook.d.ts +1 -0
- package/dist/src/public/index.d.ts +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/runtime/agent/resolve-model.d.ts +4 -0
- package/dist/src/runtime/agent/resolve-model.js +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
- package/dist/src/runtime/subagents/dynamic-agent-config.d.ts +2 -1
- package/dist/src/runtime/subagents/dynamic-agent-config.js +1 -1
- package/dist/src/runtime/types.d.ts +3 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/shared/agent-definition.d.ts +31 -42
- package/dist/src/shared/session-history.d.ts +22 -0
- package/dist/src/shared/session-history.js +1 -0
- package/dist/src/subagents/tool.d.ts +1 -3
- package/dist/src/subagents/tool.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.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/tools/workflow-definition.d.ts +14 -1
- package/dist/src/tracing/eve/conversation-context.d.ts +4 -1
- package/dist/src/tracing/eve/conversation-context.js +1 -1
- package/dist/src/tracing/eve/invoke-tool-span.js +1 -1
- package/dist/src/tracing/eve/operation-input.d.ts +0 -5
- package/dist/src/tracing/eve/operation-input.js +1 -1
- package/dist/src/tracing/eve/otel-registration.js +1 -1
- package/dist/src/tracing/eve/session.d.ts +3 -2
- package/dist/src/tracing/eve/session.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/agent-config.md +86 -65
- package/docs/channels/chat-sdk.mdx +6 -1
- package/docs/channels/custom.mdx +38 -6
- package/docs/channels/eve.mdx +46 -0
- package/docs/channels/linq.mdx +51 -0
- package/docs/channels/photon.mdx +64 -0
- package/docs/channels/slack.mdx +4 -2
- package/docs/concepts/built-in-tools.md +1 -1
- package/docs/concepts/execution-model-and-durability.mdx +12 -5
- package/docs/concepts/sessions-runs-and-streaming.md +9 -8
- package/docs/connections/overview.mdx +1 -1
- package/docs/experimental/dynamic-schedules.mdx +186 -0
- package/docs/experimental/meta.json +4 -0
- package/docs/guides/client/streaming.mdx +1 -0
- package/docs/guides/deployment/self-hosting.md +3 -0
- package/docs/guides/hooks.md +21 -1
- package/docs/memory/overview.mdx +2 -1
- package/docs/patterns/dynamic-scheduling.md +3 -1
- package/docs/reference/cli.md +14 -7
- package/docs/schedules.mdx +2 -0
- package/docs/subagents/index.mdx +2 -0
- package/docs/tools/overview.mdx +2 -1
- package/docs/tools/tasks-upgrade.md +12 -7
- package/docs/tools/tasks.md +10 -6
- package/docs/tools/workflows.mdx +36 -5
- package/docs/tutorial/connect-a-warehouse.mdx +1 -1
- package/docs/tutorial/run-analysis.mdx +1 -1
- package/package.json +1 -1
- package/dist/src/execution/run-session-limits.d.ts +0 -12
- package/dist/src/execution/run-session-limits.js +0 -1
- package/dist/src/harness/session-usage-limits.d.ts +0 -49
- package/dist/src/harness/session-usage-limits.js +0 -1
- package/dist/src/subagents/token-budget.d.ts +0 -15
- package/dist/src/subagents/token-budget.js +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createConnection,createServer}from"node:net";import{existsSync}from"node:fs";import{join,resolve}from"node:path";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{spawn}from"node:child_process";import{setTimeout}from"node:timers/promises";const HEALTH_TIMEOUT_MS=6e4,LOCAL_SERVER_URL_PATTERN=/https?:\/\/(?:\[[^\]\s]+\]|[^\s/:[\]]+)(?::\d+)?/,WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`,`0.0.0.0`]);function resolveOutputServerEntry(e){return join(resolve(e),`.output`,`server`,`index.mjs`)}function readEnvironmentPort(){let e=process.env.PORT;if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>65535)throw Error(`Invalid PORT environment variable "${e}". Expected an integer between 0 and 65535.`);return t}function normalizeServerClientUrl(e){let t=new URL(e);return WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)&&(t.hostname=`127.0.0.1`),t.toString()}function formatClientHost(e){return WILDCARD_LISTEN_HOSTNAMES.has(e)?`127.0.0.1`:e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function createKnownPortUrl(e){return`http://${formatClientHost(e.host)}:${String(e.port)}/`}async function resolveListenPort(e){if(e.port!==0)return e.port;let t=createServer();return await new Promise((n,r)=>{t.once(`error`,r),t.listen(0,e.host,()=>{let e=t.address();t.close(t=>{if(t){r(t);return}if(e===null||typeof e==`string`){r(Error(`Failed to resolve an available port for eve start.`));return}n(e.port)})})})}function parseServerUrlFromOutput(e){let t=LOCAL_SERVER_URL_PATTERN.exec(e);if(t!==null)return normalizeServerClientUrl(t[0])}async function isListening(e){let t=new URL(e),n=Number(t.port||(t.protocol===`https:`?443:80));return await new Promise(e=>{let r=createConnection({host:t.hostname,port:n}),finish=t=>{r.destroy(),e(t)};r.setTimeout(2e3,()=>finish(!1)),r.once(`connect`,()=>finish(!0)),r.once(`error`,()=>finish(!1))})}async function waitForReady(e){let t=Date.now()+HEALTH_TIMEOUT_MS;for(;Date.now()<t;){let t=e.getStartError();if(t!==void 0)throw t;let n=parseServerUrlFromOutput(e.getOutput()),r=n??e.knownUrl;if(r!==void 0&&(n!==void 0||await isListening(r)))return new URL(r).toString();if(e.child.exitCode!==null||e.child.signalCode!==null)throw Error(`Built server process exited (code=${String(e.child.exitCode)}, signal=${String(e.child.signalCode)}) before printing its URL.`);await setTimeout(250)}throw Error([`Built server did not become ready within ${HEALTH_TIMEOUT_MS/1e3}s.`,`Output:`,e.getOutput()].join(`
|
|
2
|
-
`))}async function terminate(e){e.exitCode!==null||e.killed||(e.kill(`SIGTERM`),await Promise.race([once(e,`exit`),setTimeout(2e4).then(()=>`timeout`)])===`timeout`&&e.exitCode===null&&(e.kill(`SIGKILL`),await once(e,`exit`)),e.stdout?.destroy(),e.stderr?.destroy())}function once(e,t){return new Promise(n=>{e.once(t,()=>n())})}async function startProductionServer(e,t={}){let n=resolve(e),r=resolveOutputServerEntry(n);if(!existsSync(r))throw Error(`Missing eve build output at ${r}. Run "eve build" before "eve start".`);await loadDevelopmentEnvironmentFiles(n);let i=t.host??`0.0.0.0`,a=await resolveListenPort({host:i,port:t.port??readEnvironmentPort()??3e3}),o=createKnownPortUrl({host:i,port:a}),s=``,c=!1,l=!1,u,d=
|
|
3
|
-
`)))})});
|
|
1
|
+
import{createConnection,createServer}from"node:net";import{existsSync}from"node:fs";import{join,resolve}from"node:path";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{spawn}from"node:child_process";import{EVE_SCHEDULES_DISABLED_ENV}from"#internal/schedules/disabled.js";import{setTimeout}from"node:timers/promises";const HEALTH_TIMEOUT_MS=6e4,LOCAL_SERVER_URL_PATTERN=/https?:\/\/(?:\[[^\]\s]+\]|[^\s/:[\]]+)(?::\d+)?/,WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`,`0.0.0.0`]);function resolveOutputServerEntry(e){return join(resolve(e),`.output`,`server`,`index.mjs`)}function readEnvironmentPort(){let e=process.env.PORT;if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>65535)throw Error(`Invalid PORT environment variable "${e}". Expected an integer between 0 and 65535.`);return t}function normalizeServerClientUrl(e){let t=new URL(e);return WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)&&(t.hostname=`127.0.0.1`),t.toString()}function formatClientHost(e){return WILDCARD_LISTEN_HOSTNAMES.has(e)?`127.0.0.1`:e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function createKnownPortUrl(e){return`http://${formatClientHost(e.host)}:${String(e.port)}/`}async function resolveListenPort(e){if(e.port!==0)return e.port;let t=createServer();return await new Promise((n,r)=>{t.once(`error`,r),t.listen(0,e.host,()=>{let e=t.address();t.close(t=>{if(t){r(t);return}if(e===null||typeof e==`string`){r(Error(`Failed to resolve an available port for eve start.`));return}n(e.port)})})})}function parseServerUrlFromOutput(e){let t=LOCAL_SERVER_URL_PATTERN.exec(e);if(t!==null)return normalizeServerClientUrl(t[0])}async function isListening(e){let t=new URL(e),n=Number(t.port||(t.protocol===`https:`?443:80));return await new Promise(e=>{let r=createConnection({host:t.hostname,port:n}),finish=t=>{r.destroy(),e(t)};r.setTimeout(2e3,()=>finish(!1)),r.once(`connect`,()=>finish(!0)),r.once(`error`,()=>finish(!1))})}async function waitForReady(e){let t=Date.now()+HEALTH_TIMEOUT_MS;for(;Date.now()<t;){let t=e.getStartError();if(t!==void 0)throw t;let n=parseServerUrlFromOutput(e.getOutput()),r=n??e.knownUrl;if(r!==void 0&&(n!==void 0||await isListening(r)))return new URL(r).toString();if(e.child.exitCode!==null||e.child.signalCode!==null)throw Error(`Built server process exited (code=${String(e.child.exitCode)}, signal=${String(e.child.signalCode)}) before printing its URL.`);await setTimeout(250)}throw Error([`Built server did not become ready within ${HEALTH_TIMEOUT_MS/1e3}s.`,`Output:`,e.getOutput()].join(`
|
|
2
|
+
`))}async function terminate(e){e.exitCode!==null||e.killed||(e.kill(`SIGTERM`),await Promise.race([once(e,`exit`),setTimeout(2e4).then(()=>`timeout`)])===`timeout`&&e.exitCode===null&&(e.kill(`SIGKILL`),await once(e,`exit`)),e.stdout?.destroy(),e.stderr?.destroy())}function once(e,t){return new Promise(n=>{e.once(t,()=>n())})}async function startProductionServer(e,t={}){let n=resolve(e),r=resolveOutputServerEntry(n);if(!existsSync(r))throw Error(`Missing eve build output at ${r}. Run "eve build" before "eve start".`);await loadDevelopmentEnvironmentFiles(n);let i=t.host??`0.0.0.0`,a=await resolveListenPort({host:i,port:t.port??readEnvironmentPort()??3e3}),o=createKnownPortUrl({host:i,port:a}),s=``,c=!1,l=!1,u,d={...process.env,HOST:i,NITRO_HOST:i,NITRO_PORT:String(a),PORT:String(a)};t.schedules===!1&&(d[EVE_SCHEDULES_DISABLED_ENV]=`1`);let f=spawn(process.execPath,[r],{cwd:n,env:d,stdio:[`ignore`,`pipe`,`pipe`]});f.stdout?.on(`data`,e=>{c||(s+=e.toString(`utf8`)),process.stdout.write(e)}),f.stderr?.on(`data`,e=>{c||(s+=e.toString(`utf8`)),process.stderr.write(e)});let p=new Promise((e,t)=>{f.once(`error`,e=>{u=e,t(e)}),f.once(`exit`,(n,r)=>{if(l||n===0){e();return}t(Error([`Built server process exited unexpectedly (code=${String(n)}, signal=${String(r)}).`,s].join(`
|
|
3
|
+
`)))})});p.catch(()=>void 0);try{let e=await waitForReady({child:f,getStartError:()=>u,getOutput:()=>s,knownUrl:o});return c=!0,s=``,{async close(){l=!0,await terminate(f)},url:e,async wait(){await p}}}catch(e){throw l=!0,await terminate(f),e instanceof Error&&e.name===`AbortError`?Error(`Timed out waiting for built eve server to respond.`,{cause:e}):e}}export{startProductionServer};
|
|
@@ -10,6 +10,9 @@ import type { RuntimeCompiledArtifactsSource } from "#runtime/compiled-artifacts
|
|
|
10
10
|
export declare function dispatchScheduleTask(taskName: string, config: NitroArtifactsConfig): Promise<{
|
|
11
11
|
scheduleId: string;
|
|
12
12
|
sessionIds: readonly string[];
|
|
13
|
+
} | {
|
|
14
|
+
skipped: "schedules-disabled";
|
|
15
|
+
taskName: string;
|
|
13
16
|
}>;
|
|
14
17
|
/**
|
|
15
18
|
* Variant of {@link dispatchScheduleTask} for callers that already resolved
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{loadResolvedCompiledScheduleByTaskName}from"#runtime/schedules/resolve-schedule.js";import{ScheduleDispatcher,expectScheduleRun}from"#channel/schedule.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";async function dispatchScheduleTask(e,t){return await dispatchScheduleTaskFromArtifacts(e,resolveNitroCompiledArtifactsSource(t))}async function dispatchScheduleTaskFromArtifacts(e,t){let n=await loadResolvedCompiledScheduleByTaskName(e,{compiledArtifactsSource:t}),r=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:t}),i=createWorkflowRuntime({compiledArtifactsSource:t}),a=new ScheduleDispatcher({runtime:i,channels:r.graph.root.channels}),o={scheduleId:n.name};n.hasRun&&(o.run=await loadScheduleRun(n,r.moduleMap)),n.markdown!==void 0&&(o.markdown=n.markdown);let s=await a.trigger(o);return s.waitUntilTasks.length>0&&await Promise.allSettled(s.waitUntilTasks),{scheduleId:n.name,sessionIds:s.sessions.map(e=>e.id)}}async function loadScheduleRun(e,t){if(e.sourceKind!==`module`)throw Error(`Schedule "${e.name}" claims hasRun but is not a module-backed schedule.`);let n=e,r=await loadResolvedModuleExport({definition:{exportName:n.exportName,logicalPath:n.logicalPath,sourceId:n.sourceId},kindLabel:`schedule`,moduleMap:t,nodeId:void 0});return expectScheduleRun(r,n.logicalPath,n.exportName)}export{dispatchScheduleTask,dispatchScheduleTaskFromArtifacts};
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{EVE_SCHEDULES_DISABLED_ENV,areSchedulesDisabled}from"#internal/schedules/disabled.js";import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{loadResolvedCompiledScheduleByTaskName}from"#runtime/schedules/resolve-schedule.js";import{ScheduleDispatcher,expectScheduleRun}from"#channel/schedule.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";const log=createLogger(`schedule.dispatch`);let loggedSchedulesDisabled=!1;async function dispatchScheduleTask(e,t){return areSchedulesDisabled()?(loggedSchedulesDisabled||(loggedSchedulesDisabled=!0,log.info(`Schedules are disabled in this process (${EVE_SCHEDULES_DISABLED_ENV}); skipping "${e}"`)),{skipped:`schedules-disabled`,taskName:e}):await dispatchScheduleTaskFromArtifacts(e,resolveNitroCompiledArtifactsSource(t))}async function dispatchScheduleTaskFromArtifacts(e,t){let n=await loadResolvedCompiledScheduleByTaskName(e,{compiledArtifactsSource:t}),r=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:t}),i=createWorkflowRuntime({compiledArtifactsSource:t}),a=new ScheduleDispatcher({runtime:i,channels:r.graph.root.channels}),o={scheduleId:n.name};n.hasRun&&(o.run=await loadScheduleRun(n,r.moduleMap)),n.markdown!==void 0&&(o.markdown=n.markdown);let s=await a.trigger(o);return s.waitUntilTasks.length>0&&await Promise.allSettled(s.waitUntilTasks),{scheduleId:n.name,sessionIds:s.sessions.map(e=>e.id)}}async function loadScheduleRun(e,t){if(e.sourceKind!==`module`)throw Error(`Schedule "${e.name}" claims hasRun but is not a module-backed schedule.`);let n=e,r=await loadResolvedModuleExport({definition:{exportName:n.exportName,logicalPath:n.logicalPath,sourceId:n.sourceId},kindLabel:`schedule`,moduleMap:t,nodeId:void 0});return expectScheduleRun(r,n.logicalPath,n.exportName)}export{dispatchScheduleTask,dispatchScheduleTaskFromArtifacts};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{memoizeModuleNamespaceFactories}from"#compiler/source-graph.js";import{loadFrameworkProgrammaticModule}from"#framework/sources/registry.js";export{loadFrameworkProgrammaticModule,memoizeModuleNamespaceFactories};
|
|
1
|
+
import{interopAuthoredModuleNamespace}from"#internal/authored-module.js";import{memoizeModuleNamespaceFactories}from"#compiler/source-graph.js";import{loadFrameworkProgrammaticModule}from"#framework/sources/registry.js";export{interopAuthoredModuleNamespace,loadFrameworkProgrammaticModule,memoizeModuleNamespaceFactories};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const EVE_SCHEDULES_DISABLED_ENV=`EVE_SCHEDULES_DISABLED`;function areSchedulesDisabled(e=process.env){let t=e[EVE_SCHEDULES_DISABLED_ENV]?.toLowerCase();return t===`1`||t===`true`}export{EVE_SCHEDULES_DISABLED_ENV,areSchedulesDisabled};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{displayLocalWorkflowWorldDataDirectory,resolveLocalWorkflowWorldDataDirectory}from"#internal/workflow/local-world-data-directory.js";import{DevelopmentRunUnavailableError}from"#internal/workflow/development-run-unavailable-error.js";import{DEVELOPMENT_WORKFLOW_DELIVERY_HEADER,DEVELOPMENT_WORKFLOW_STREAM_ROUTE,DEVELOPMENT_WORKFLOW_TRANSPORT_HEADER,DEVELOPMENT_WORKFLOW_WORLD_ROUTE,DEVELOPMENT_WORLD_OPERATIONS}from"#internal/workflow/development-world-protocol.js";import{timingSafeEqualStrings}from"#internal/nitro/dev-client-address.js";import{listDevelopmentGenerationIds}from"#internal/nitro/dev-runtime-generation-metadata.js";import{deriveEveWorkflowQueuePrefix}from"#internal/workflow/queue-namespace.js";import{decodeDevelopmentWorldValue,encodeDevelopmentWorldValue,serializeDevelopmentWorldError}from"#internal/workflow/development-world-codec.js";import{cancelExpiredDevelopmentRun}from"#internal/workflow/cancel-expired-development-run.js";import{readDevelopmentGenerationAvailability}from"#internal/workflow/development-runtime-compatibility.js";import{createWorld}from"#compiled/@workflow/world-local/index.js";import{applyLocalWorkflowWorldDeliveryTimeoutDefaults}from"#internal/workflow/local-world-delivery-timeouts.js";function createParentDevelopmentWorkflowWorld(e){return new LocalParentDevelopmentWorkflowWorld(e)}var LocalParentDevelopmentWorkflowWorld=class{#e;#t;#n;#r;#i;#a;#o=new Map;#s=!1;#c=!1;#l=Promise.resolve();constructor(e){if(e.transportSecret.length<16)throw Error(`Development Workflow transport secret is too short to be trusted.`);this.#a=e.resume===!0,this.#e=e.agentName,this.#t=e.appRoot,this.#n=e.resolveActiveGenerationId,this.#r=e.transportSecret,applyLocalWorkflowWorldDeliveryTimeoutDefaults(),this.#i=createWorld({dataDir:resolveLocalWorkflowWorldDataDirectory(e.appRoot),recoverActiveRuns:!1})}async start(){if(this.#c)return;let e=this.#n();this.#o.clear();for(let t of await listDevelopmentGenerationIds(this.#t)){if(t===e)continue;if(!this.#a){this.#o.set(t,{kind:`dormant`});continue}let n=await readDevelopmentGenerationAvailability(this.#t,t);n.kind===`ineligible`&&this.#o.set(t,n)}await this.#i.start?.(),this.#c=!0;try{if(await this.#u(),!this.#a)return;let e=new Set;await reenqueueActiveDevelopmentRuns({appRoot:this.#t,enqueue:this.#m.bind(this),prefix:deriveEveWorkflowQueuePrefix(this.#e),world:this.#i,canRecover:async t=>{let n=await this.#_(t);return n.kind===`ineligible`&&!e.has(t)&&(e.add(t),console.warn(`[eve:dev] Skipping retained Workflow generation "${t}": ${n.reason}`)),n.kind===`ready`}})}catch(e){throw this.#c=!1,e}}async close(){this.#s||(this.#s=!0,this.#c=!1,await this.#l.catch(()=>void 0),await this.#i.close?.())}async handleRequest(e){let t=new URL(e.url);if(t.pathname===DEVELOPMENT_WORKFLOW_WORLD_ROUTE)return await this.#f(e);if(t.pathname===DEVELOPMENT_WORKFLOW_STREAM_ROUTE)return await this.#p(e,t)}async reconcileExpiredRuns(){!this.#c||this.#s||await this.#u()}#u(){return this.#l=this.#l.catch(()=>void 0).then(async()=>{if(this.#s)return;let e=await this.#d();for(let t of e)await cancelExpiredDevelopmentRun(this.#i,t)}),this.#l}async#d(){let e=[];for(let t of[`pending`,`running`]){let n;do{let r;try{r=await this.#i.runs.list({pagination:{cursor:n,limit:1e3},resolveData:`none`,status:t})}catch(e){throw Error(`Failed to read the app's active local Workflow runs. Remove "${displayLocalWorkflowWorldDataDirectory(this.#t)}" to discard them.`,{cause:e})}for(let t of r.data)(await readDevelopmentGenerationAvailability(this.#t,t.deploymentId)).kind===`missing`&&e.push(t.runId);n=r.hasMore?r.cursor??void 0:void 0}while(n!==void 0)}return e}async#f(e){if(!this.#g(e)||e.method!==`POST`)return Response.json({error:`Workflow World request is not trusted.`},{status:401});try{let t=decodeDevelopmentWorldValue(await e.text()),n=await this.#h(t);return new Response(encodeDevelopmentWorldValue(n))}catch(e){return new Response(encodeDevelopmentWorldValue(serializeDevelopmentWorldError(e)),{status:500})}}async#p(e,t){if(!this.#g(e)||e.method!==`GET`)return Response.json({error:`Workflow World request is not trusted.`},{status:401});let n=t.searchParams.get(`runId`),r=t.searchParams.get(`name`),i=t.searchParams.get(`startIndex`);if(n===null||r===null)return Response.json({error:`Workflow stream request is malformed.`},{status:400});let a=i===null||i===``?void 0:Number(i);if(i===``||a!==void 0&&!Number.isInteger(a))return Response.json({error:`Workflow stream start index is invalid.`},{status:400});try{return new Response(await this.#i.streams.get(n,r,a))}catch(e){return new Response(encodeDevelopmentWorldValue(serializeDevelopmentWorldError(e)),{status:500})}}async#m(...e){let[t,n,r]=e;return await this.#i.queue(t,n,{...r,headers:{...r?.headers,[DEVELOPMENT_WORKFLOW_DELIVERY_HEADER]:this.#r}})}async#h(e){if(!isDevelopmentWorldRequest(e))throw Error(`Development Workflow World call is malformed.`);if(e.operation===`eve.getGenerationAvailability`)return await this.#_(e.generationId);let t=[...e.arguments];if(e.operation===`getDeploymentId`||e.operation===`resolveLatestDeploymentId`)return this.#n();if(e.operation===`queue`)return await this.#m(...t);if(e.operation===`hooks.getByToken`||e.operation===`hooks.get`){if(!this.#c)throw Error(`Local Workflow World is still starting.`);let n=e.operation===`hooks.getByToken`?await this.#i.hooks.getByToken(...t):await this.#i.hooks.get(...t),r=await this.#i.runs.get(n.runId,{resolveData:`none`}),i=await this.#_(r.deploymentId);if(i.kind===`dormant`||i.kind===`ineligible`)throw new DevelopmentRunUnavailableError({availability:i.kind,runId:n.runId});return n}if(e.operation===`streams.writeMulti`&&this.#i.streams.writeMulti===void 0){for(let e of t[2])await this.#i.streams.write(t[0],t[1],e);return}let n=e.operation.indexOf(`.`),r=this.#i[e.operation.slice(0,n)],i=typeof r==`object`&&r?r[e.operation.slice(n+1)]:void 0;if(typeof i==`function`)return await Reflect.apply(i,r,t)}#g(e){let t=e.headers.get(DEVELOPMENT_WORKFLOW_TRANSPORT_HEADER);return t!==null&&timingSafeEqualStrings(t,this.#r)}async#_(e){let t=await readDevelopmentGenerationAvailability(this.#t,e);return t.kind===`ready`?this.#o.get(e)??t:t}};const DEVELOPMENT_WORLD_OPERATION_SET=new Set(DEVELOPMENT_WORLD_OPERATIONS);function isDevelopmentWorldRequest(e){return isObject(e)&&typeof e.operation==`string`&&(e.operation===`eve.getGenerationAvailability`?typeof e.generationId==`string`:DEVELOPMENT_WORLD_OPERATION_SET.has(e.operation)&&Array.isArray(e.arguments))}function isObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function reenqueueActiveDevelopmentRuns(e){for(let t of[`pending`,`running`]){let n;do{let r;try{r=await e.world.runs.list({pagination:{cursor:n},resolveData:`none`,status:t})}catch(t){throw Error(`Failed to read the app's active local Workflow runs. Remove "${displayLocalWorkflowWorldDataDirectory(e.appRoot)}" to discard them.`,{cause:t})}for(let t of r.data)await e.canRecover(t.deploymentId)&&await e.enqueue(`${e.prefix}${t.workflowName}`,{runId:t.runId});n=r.hasMore?r.cursor??void 0:void 0}while(n!==void 0)}}export{createParentDevelopmentWorkflowWorld};
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export declare const LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH = ".eve/.workflow-data";
|
|
2
1
|
export declare function resolveLocalWorkflowWorldDataDirectory(appRoot: string): string;
|
|
2
|
+
/** App-relative store path for messages that name the directory to inspect or remove. */
|
|
3
|
+
export declare function displayLocalWorkflowWorldDataDirectory(appRoot: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join}from"node:path";
|
|
1
|
+
import{join,relative}from"node:path";import{resolveDevelopmentStateDirectory}from"#internal/application/dev-environment.js";function resolveLocalWorkflowWorldDataDirectory(e){return join(resolveDevelopmentStateDirectory(e),`.workflow-data`)}function displayLocalWorkflowWorldDataDirectory(e){return relative(e,resolveLocalWorkflowWorldDataDirectory(e)).replaceAll(`\\`,`/`)}export{displayLocalWorkflowWorldDataDirectory,resolveLocalWorkflowWorldDataDirectory};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{mkdir,readFile,writeFile}from"node:fs/promises";import{dirname,join,resolve}from"node:path";import{resolvePackageSourceDirectoryPath,resolveWorkflowModulePath}from"#internal/application/package.js";import{
|
|
1
|
+
import{mkdir,readFile,writeFile}from"node:fs/promises";import{dirname,join,resolve}from"node:path";import{resolvePackageSourceDirectoryPath,resolveWorkflowModulePath}from"#internal/application/package.js";import{createAuthoredPackageTsConfigPathsPlugin}from"#internal/authored-package-tsconfig-paths.js";import{createAuthoredRelativeExtensionResolverPlugin}from"#internal/authored-relative-extension-resolver.js";import{buildSingleRolldownChunk}from"#internal/bundler/nitro-rolldown.js";import{findWorkflowPatterns}from"#internal/workflow-bundle/workflow-builders.js";import{mapConcurrent}from"#shared/map-concurrent.js";import{onVendoredDependencyLog}from"#internal/bundler/vendored-dependency-log.js";import{prepareEveVersionedCacheDirectory,writeEveVersionedCacheMetadata}from"#internal/application/cache-metadata.js";import{WORKFLOW_BUILDER_DEFERRED_PACKAGES,WORKFLOW_STEP_EXTERNAL_PACKAGES}from"#internal/workflow-bundle/vercel-workflow-output.js";import{deriveEveWorkflowQueueNamespace}from"#internal/workflow/queue-namespace.js";import{runQueuedWorkflowBuild}from"#internal/workflow-bundle/build-queue.js";import{WORKFLOW_SOURCE_EXTENSIONS,WORKFLOW_VIRTUAL_ENTRY_ID,bundleFinalWorkflowOutput,collectWorkflowInputFiles,composeWorkflowDriverCode,convertClassesManifest,convertStepsManifest,convertWorkflowsManifest,createEvePackageImportsPlugin,createWorkflowDriverAliasPlugin,createWorkflowImport,createWorkflowNodeBuiltinGuardPlugin,createWorkflowPseudoPackagePlugin,createWorkflowTransformPlugin,createWorkflowVirtualEntryPlugin,mergeWorkflowManifest}from"#internal/workflow-bundle/builder-support.js";import{writeNitroStepEntrypoint}from"#internal/workflow-bundle/nitro-step-entry.js";var WorkflowBundleBuilder=class{#e;#t;#n;#r;config;constructor(e){let t=[resolvePackageSourceDirectoryPath(`src/execution`),resolvePackageSourceDirectoryPath(`src/runtime/subagents`),resolvePackageSourceDirectoryPath(`src/runtime/connections/events`),resolvePackageSourceDirectoryPath(`src/subagents`),resolvePackageSourceDirectoryPath(`src/tools/provided`)];e.includeTestFixtures===!0&&t.push(resolvePackageSourceDirectoryPath(`src/internal/testing`)),this.config={buildTarget:`standalone`,dirs:t,externalPackages:[...WORKFLOW_STEP_EXTERNAL_PACKAGES,...WORKFLOW_BUILDER_DEFERRED_PACKAGES],projectRoot:e.appRoot,watch:e.watch,workingDir:e.rootDir},this.#e=e.authoredWorkflowModules??{directiveModules:[],workflowModules:[]},this.#t=e.compiledArtifactsBootstrapPath,this.#n=e.outDir,this.#r=deriveEveWorkflowQueueNamespace(e.agentName)}async build(e={}){await runQueuedWorkflowBuild(this.#n,async()=>this.#i(e))}async#i(e){await prepareEveVersionedCacheDirectory(this.#n);let t=await this.#o();if(t.length===0)throw Error(`Expected framework workflow source files under eve's execution, runtime/subagents, subagents, or tools/provided source directories.`);let n=await this.findTsConfigPath();await mkdir(this.#n,{recursive:!0});let r=await this.discoverEntries(t),i=this.#e,a=mergeStepEntries(r,i),o=join(this.#n,`steps.mjs`),s=join(this.#n,`workflows.mjs`),c=e.nitroStepOutfile,l=e.nitroWorkflowOutfile,writeStepEntry=(e,t)=>writeNitroStepEntrypoint({builtinsPath:resolveWorkflowModulePath(`workflow/internal/builtins`),discoveredEntries:a,outfile:e,precomputedManifest:t,preferAbsoluteFileImports:!0,projectRoot:this.config.projectRoot??this.config.workingDir,sideEffectFiles:[this.#t],workingDir:this.config.workingDir}),u=await writeStepEntry(o);c!==void 0&&c!==o&&await writeStepEntry(c,u);let{manifest:d}=await this.createWorkflowsBundle({additionalOutputs:l===void 0||l===s?[]:[{outfile:l,stepRegistrationsPath:c??o}],appWorkflowFiles:i.workflowModules,frameworkSerdeFiles:r.discoveredSerdeFiles,frameworkWorkflowFiles:r.discoveredWorkflows,outfile:s,stepRegistrationsPath:o,tsconfigPath:n});await this.createManifest({workflowBundlePath:join(this.#n,`workflows.mjs`),manifestDir:this.#n,manifest:{steps:{...u.steps,...d.steps},workflows:{...u.workflows,...d.workflows},classes:{...u.classes,...d.classes}}}),await writeEveVersionedCacheMetadata(this.#n)}get transformProjectRoot(){return this.config.projectRoot??this.config.workingDir}async findTsConfigPath(){let e=this.transformProjectRoot;for(;;){for(let t of[`tsconfig.json`,`jsconfig.json`]){let n=join(e,t);try{return await readFile(n),n}catch(e){if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e}}let t=dirname(e);if(t===e)return;e=t}}async getInputFiles(){let e=this.config.dirs.map(e=>resolve(this.config.workingDir,e));return(await Promise.all(e.map(e=>collectWorkflowInputFiles(e)))).flat()}async discoverEntries(e){let t={discoveredSerdeFiles:[],discoveredSteps:[],discoveredWorkflows:[]},n=await mapConcurrent(e,async e=>{let t=await readFile(e,`utf8`);return{filePath:e,patterns:await findWorkflowPatterns(e,t)}});for(let{filePath:e,patterns:r}of n)r.hasUseStep&&t.discoveredSteps.push(e),r.hasUseWorkflow&&t.discoveredWorkflows.push(e),r.hasSerde&&t.discoveredSerdeFiles.push(e);return t}async createWorkflowsBundle({additionalOutputs:e=[],appWorkflowFiles:t,frameworkSerdeFiles:n,frameworkWorkflowFiles:r,outfile:i,stepRegistrationsPath:a,tsconfigPath:o}){let s={},c=await mapConcurrent([{label:`framework`,serdeFiles:n,workflowFiles:r},{label:`app`,serdeFiles:[],workflowFiles:t}],async e=>{let t={};return{code:await this.#a({...e,manifest:t,tsconfigPath:o}),manifest:t}});for(let e of c)mergeWorkflowManifest(s,e.manifest);let l=composeWorkflowDriverCode(c.map(e=>e.code));return await Promise.all([{outfile:i,stepRegistrationsPath:a},...e].map(e=>bundleFinalWorkflowOutput({code:l,outfile:e.outfile,queueNamespace:this.#r,stepRegistrationsPath:e.stepRegistrationsPath}))),{manifest:s}}async#a(e){let t=[...e.workflowFiles].sort(),n=new Set(t),r=[...e.serdeFiles].sort().filter(e=>!n.has(e));if(t.length===0&&r.length===0)return``;let i=[...t.map(e=>createWorkflowImport(e,this.config.workingDir)),...r.map(e=>createWorkflowImport(e,this.config.workingDir))].join(`
|
|
2
2
|
`);return(await buildSingleRolldownChunk(`${e.label} workflow driver chunk`,{cwd:this.config.workingDir,onLog(e,t,n){if(e===`warn`&&t.code===`UNRESOLVED_IMPORT`)throw Error(`Cannot build workflow bundle: ${t.message}`);onVendoredDependencyLog(e,t,n)},input:WORKFLOW_VIRTUAL_ENTRY_ID,platform:`neutral`,plugins:[createWorkflowVirtualEntryPlugin(i),createWorkflowPseudoPackagePlugin(),createWorkflowDriverAliasPlugin(this.config.workingDir),createAuthoredRelativeExtensionResolverPlugin({extensions:WORKFLOW_SOURCE_EXTENSIONS}),createAuthoredPackageTsConfigPathsPlugin({appPackageRoot:this.transformProjectRoot,extensions:WORKFLOW_SOURCE_EXTENSIONS}),createEvePackageImportsPlugin(this.config.workingDir,{workflowCondition:!0}),createWorkflowTransformPlugin({manifest:e.manifest,projectRoot:this.transformProjectRoot,sideEffectFiles:[...t,...r],workingDir:this.config.workingDir}),createWorkflowNodeBuiltinGuardPlugin()],resolve:{conditionNames:[`eve-source`,`workflow`],extensions:WORKFLOW_SOURCE_EXTENSIONS,mainFields:[`module`,`main`]},tsconfig:e.tsconfigPath??!1,output:{comments:!1,format:`cjs`,sourcemap:`inline`}})).code}async createManifest({manifest:e,manifestDir:t}){let n={version:`1.0.0`,steps:convertStepsManifest(e.steps),workflows:convertWorkflowsManifest(e.workflows),classes:convertClassesManifest(e.classes)},r=JSON.stringify(n,null,2);return await mkdir(t,{recursive:!0}),await writeFile(join(t,`manifest.json`),r),r}async#o(){return await this.getInputFiles()}};function mergeStepEntries(e,t){return{discoveredSerdeFiles:e.discoveredSerdeFiles,discoveredSteps:[...new Set([...e.discoveredSteps,...t.directiveModules])]}}export{WorkflowBundleBuilder};
|
|
@@ -159,6 +159,26 @@ export interface SessionStartedStreamEvent {
|
|
|
159
159
|
};
|
|
160
160
|
type: "session.started";
|
|
161
161
|
}
|
|
162
|
+
/** One message a delivery added with `history`, as `history.imported` publishes it. */
|
|
163
|
+
export interface HistoryImportedMessage {
|
|
164
|
+
/** App-owned id the history entry carried, when one was supplied. */
|
|
165
|
+
readonly id?: string;
|
|
166
|
+
readonly role: "user" | "assistant";
|
|
167
|
+
readonly text: string;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Stream event emitted when a delivery adds prior conversation with `history`.
|
|
171
|
+
* It precedes that delivery's `message.received` in the same turn; the
|
|
172
|
+
* messages sit in model history just before that turn's input.
|
|
173
|
+
*/
|
|
174
|
+
export interface HistoryImportedStreamEvent {
|
|
175
|
+
data: {
|
|
176
|
+
messages: readonly HistoryImportedMessage[];
|
|
177
|
+
sequence: number;
|
|
178
|
+
turnId: string;
|
|
179
|
+
};
|
|
180
|
+
type: "history.imported";
|
|
181
|
+
}
|
|
162
182
|
/**
|
|
163
183
|
* Stream event emitted when one runtime turn starts.
|
|
164
184
|
*/
|
|
@@ -808,7 +828,7 @@ export interface SessionCompletedStreamEvent {
|
|
|
808
828
|
* Internal emitters use this type while constructing events. Public stream
|
|
809
829
|
* consumers receive {@link MessageStreamEvent}.
|
|
810
830
|
*/
|
|
811
|
-
export type UnstampedMessageStreamEvent = ActionInputAppendedStreamEvent | AgentStartedStreamEvent | ApprovalCandidateStreamEvent | ApprovalSettledStreamEvent | ContextClearedStreamEvent | CompactionCompletedStreamEvent | CompactionRequestedStreamEvent | AuthorizationCompletedStreamEvent | AuthorizationRequiredStreamEvent | MessageAppendedStreamEvent | MessageCompletedStreamEvent | MessageReceivedStreamEvent | ReasoningAppendedStreamEvent | SessionCompletedStreamEvent | SessionFailedStreamEvent | SessionStartedStreamEvent | SessionWaitingStreamEvent | ResultCompletedStreamEvent | TaskSettledStreamEvent | TaskStartedStreamEvent | ActionsRequestedStreamEvent | InputRequestedStreamEvent | InputResolvedStreamEvent | ActionPartialStreamEvent | ActionResultStreamEvent | ReasoningCompletedStreamEvent | StepCompletedStreamEvent | StepFailedStreamEvent | StepStartedStreamEvent | TurnCancelledStreamEvent | TurnCompletedStreamEvent | TurnFailedStreamEvent | TurnStartedStreamEvent | TurnWaitingStreamEvent;
|
|
831
|
+
export type UnstampedMessageStreamEvent = ActionInputAppendedStreamEvent | AgentStartedStreamEvent | ApprovalCandidateStreamEvent | ApprovalSettledStreamEvent | ContextClearedStreamEvent | CompactionCompletedStreamEvent | HistoryImportedStreamEvent | CompactionRequestedStreamEvent | AuthorizationCompletedStreamEvent | AuthorizationRequiredStreamEvent | MessageAppendedStreamEvent | MessageCompletedStreamEvent | MessageReceivedStreamEvent | ReasoningAppendedStreamEvent | SessionCompletedStreamEvent | SessionFailedStreamEvent | SessionStartedStreamEvent | SessionWaitingStreamEvent | ResultCompletedStreamEvent | TaskSettledStreamEvent | TaskStartedStreamEvent | ActionsRequestedStreamEvent | InputRequestedStreamEvent | InputResolvedStreamEvent | ActionPartialStreamEvent | ActionResultStreamEvent | ReasoningCompletedStreamEvent | StepCompletedStreamEvent | StepFailedStreamEvent | StepStartedStreamEvent | TurnCancelledStreamEvent | TurnCompletedStreamEvent | TurnFailedStreamEvent | TurnStartedStreamEvent | TurnWaitingStreamEvent;
|
|
812
832
|
/**
|
|
813
833
|
* Stream events that represent an unrecovered turn/session failure.
|
|
814
834
|
*/
|
|
@@ -837,6 +857,12 @@ export declare function isCurrentTurnBoundaryEvent(event: UnstampedMessageStream
|
|
|
837
857
|
* {@link MessageStreamEvent} narrows to a stamped failure event.
|
|
838
858
|
*/
|
|
839
859
|
export declare function isTurnFailureEvent<TEvent extends UnstampedMessageStreamEvent>(event: TEvent): event is TEvent & TurnFailureStreamEvent;
|
|
860
|
+
/** Creates the `history.imported` event for the messages one delivery added. */
|
|
861
|
+
export declare function createHistoryImportedEvent(input: {
|
|
862
|
+
readonly messages: readonly HistoryImportedMessage[];
|
|
863
|
+
readonly sequence: number;
|
|
864
|
+
readonly turnId: string;
|
|
865
|
+
}): HistoryImportedStreamEvent;
|
|
840
866
|
/**
|
|
841
867
|
* Creates the `session.started` event for one session.
|
|
842
868
|
*/
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{deserializeUrlFilePart,hasInternalRefScheme,isSerializedUrlFilePart}from"#internal/attachments/url-refs.js";import{createEveSessionStreamRoutePath,createEveSubagentStreamRoutePath}from"#protocol/routes.js";import{decodeSandboxRef,isSandboxRefUrl}from"#internal/attachments/sandbox-refs.js";import{getKnownByteLength}from"#internal/attachments/data.js";import{createEventId}from"#protocol/event-id.js";const EVE_SESSION_ID_HEADER=`x-eve-session-id`,EVE_STREAM_FORMAT_HEADER=`x-eve-stream-format`,EVE_STREAM_TAIL_INDEX_HEADER=`x-eve-stream-tail-index`,EVE_STREAM_VERSION_HEADER=`x-eve-stream-version`,EVE_MESSAGE_STREAM_CONTENT_TYPE=`application/x-ndjson; charset=utf-8`,EVE_MESSAGE_STREAM_FORMAT=`ndjson`,EVE_MESSAGE_STREAM_VERSION=`26`,EVE_STREAM_CONTROL_VERSION=`1`,EVE_STREAM_CONTROL_VERSION_QUERY=`streamControlVersion`,EVE_STREAM_LEASE_ENDED_CONTROL={$eve:`stream.lease-ended`,version:1},textEncoder=new TextEncoder;function isCurrentTurnBoundaryEvent(e){return e.type===`session.completed`||e.type===`session.failed`||e.type===`session.waiting`}function isTurnFailureEvent(e){return e.type===`session.failed`||e.type===`step.failed`||e.type===`turn.failed`}function createSessionStartedEvent(e){let t={};return e?.invocation!==void 0&&(t.invocation=e.invocation),e?.predecessor!==void 0&&(t.predecessor=e.predecessor),e?.runtime!==void 0&&(t.runtime=e.runtime),e?.trace!==void 0&&(t.trace=e.trace),{data:t,type:`session.started`}}function createTurnStartedEvent(e){let t={sequence:e.sequence,turnId:e.turnId};return e.trace!==void 0&&(t.trace=e.trace),{data:t,type:`turn.started`}}function createMessageReceivedEvent(e){return{data:{message:summarizeUserContent(e.message),parts:projectUserContentParts(e.message),sequence:e.sequence,turnId:e.turnId},type:`message.received`}}function summarizeUserContent(e){if(typeof e==`string`)return e;let t=[];for(let n of e)if(n.type===`text`)t.push(n.text);else if(n.type===`file`){let e=n.filename??n.mediaType;t.push(`[file: ${e} (${n.mediaType})]`)}else n.type===`image`&&t.push(`[image: ${n.mediaType??`image`}]`);return t.join(`
|
|
2
|
-
`)}function projectUserContentParts(e){if(typeof e==`string`)return[{text:e,type:`text`}];let t=[];for(let n of e)n.type===`text`?t.push({text:n.text,type:`text`}):n.type===`file`?t.push(projectFileLikePart(n.data,n.mediaType,n.filename)):n.type===`image`&&t.push(projectFileLikePart(n.image,n.mediaType??`application/octet-stream`,void 0));return t}function projectFileLikePart(e,t,n){if(isSandboxRefUrl(e)){let t=decodeSandboxRef(e);return createProjectedFilePart({filename:basenameOf(n??t.path),mediaType:t.mediaType,size:t.size})}let r=projectTaggedFileData(e,t,n);if(r!==void 0)return r;let i=clientUrlFragment(e);if(i.url!==void 0)return createProjectedFilePart({filename:n,mediaType:t,...i});let a=getKnownByteLength(e);return createProjectedFilePart(a===null?{filename:n,mediaType:t}:{filename:n,mediaType:t,size:a})}function projectTaggedFileData(e,t,n){if(isTaggedFileData(e))switch(e.type){case`data`:{let r=byteLengthOf(e.data);return createProjectedFilePart(r===void 0?{filename:n,mediaType:t}:{filename:n,mediaType:t,size:r})}case`reference`:case`text`:return createProjectedFilePart({filename:n,mediaType:t});case`url`:return createProjectedFilePart({filename:n,mediaType:t,...clientUrlFragment(e.url)})}}function createProjectedFilePart(e){let t={mediaType:e.mediaType,type:`file`};return e.filename!==void 0&&(t.filename=e.filename),e.size!==void 0&&(t.size=e.size),e.url!==void 0&&(t.url=e.url),t}function isTaggedFileData(e){if(typeof e!=`object`||!e)return!1;let t=e.type;return t===`data`||t===`reference`||t===`text`||t===`url`}function byteLengthOf(e){if(e instanceof Uint8Array||e instanceof ArrayBuffer)return e.byteLength}function clientUrlFragment(e){if(isSerializedUrlFilePart(e))try{let t=deserializeUrlFilePart(e);return isClientResolvableUrl(t)?{url:t.href}:{}}catch{return{}}if(e instanceof URL)return isClientResolvableUrl(e)?{url:e.href}:{};if(typeof e!=`string`||hasInternalRefScheme(e))return{};try{let t=new URL(e);return isClientResolvableUrl(t)?{url:t.href}:{}}catch{return{}}}function isClientResolvableUrl(e){return e.protocol===`http:`||e.protocol===`https:`}function basenameOf(e){let t=e.replaceAll(`\\`,`/`),n=t.slice(t.lastIndexOf(`/`)+1);return n.length>0?n:e}function createActionsRequestedEvent(e){return{data:{actions:e.actions,...optionalPresentation(e.presentation),sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`actions.requested`}}function optionalPresentation(e){return e===void 0?{}:{presentation:e}}function createActionInputAppendedEvent(e){return{data:{callId:e.callId,inputTextDelta:e.inputTextDelta,sequence:e.sequence,stepIndex:e.stepIndex,toolName:e.toolName,turnId:e.turnId},type:`action.input.appended`}}function createAuthorizationRequiredEvent(e){let t={description:e.description,name:e.name,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId};return e.attemptId!==void 0&&(t.attemptId=e.attemptId),e.authorization!==void 0&&(t.authorization=e.authorization),e.candidateId!==void 0&&(t.candidateId=e.candidateId),e.grant!==void 0&&(t.grant=e.grant),e.principal!==void 0&&(t.principal=e.principal),e.principalId!==void 0&&(t.principalId=e.principalId),e.webhookUrl!==void 0&&(t.webhookUrl=e.webhookUrl),e.taskId!==void 0&&(t.taskId=e.taskId),{data:t,type:`authorization.required`}}function createAuthorizationCompletedEvent(e){let t={name:e.name,outcome:e.outcome,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId};return e.attemptId!==void 0&&(t.attemptId=e.attemptId),e.authorization!==void 0&&(t.authorization=e.authorization),e.candidateId!==void 0&&(t.candidateId=e.candidateId),e.grant!==void 0&&(t.grant=e.grant),e.principal!==void 0&&(t.principal=e.principal),e.principalId!==void 0&&(t.principalId=e.principalId),e.reason!==void 0&&(t.reason=e.reason),e.retryable!==void 0&&(t.retryable=e.retryable),e.taskId!==void 0&&(t.taskId=e.taskId),{data:t,type:`authorization.completed`}}function createApprovalCandidateEvent(e){return{data:e,type:`approval.candidate`}}function createApprovalSettledEvent(e){return{data:e,type:`approval.settled`}}function createInputRequestedEvent(e){let t={requests:e.requests,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId};return e.callId!==void 0&&(t.callId=e.callId),e.taskId!==void 0&&(t.taskId=e.taskId),{data:t,type:`input.requested`}}function createInputResolvedEvent(e){return{data:{resolutions:e.resolutions,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`input.resolved`}}function createActionResultEvent(e){let t=e.rejected===!0?{error:buildActionResultError(e.result),status:`rejected`}:normalizeActionResultOutcome(e.result);return{data:{error:t.error,...optionalPresentation(e.presentation),result:e.result,sequence:e.sequence,status:t.status,stepIndex:e.stepIndex,turnId:e.turnId},type:`action.result`}}function createActionPartialEvent(e){return{data:{...optionalPresentation(e.presentation),result:e.result,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`action.partial`}}function createTaskStartedEvent(e){return{data:{callId:e.callId,kind:e.kind,name:e.name,taskId:e.taskId,turnId:e.turnId},type:`task.started`}}function createTaskSettledEvent(e){let t={callId:e.callId,...e.kind!==void 0&&{kind:e.kind},...e.name!==void 0&&{name:e.name},status:e.status,taskId:e.taskId,turnId:e.turnId};return e.output!==void 0&&(t.output=e.output),e.error!==void 0&&(t.error=e.error),e.cancel!==void 0&&(t.cancel=e.cancel),{data:t,type:`task.settled`}}function createAgentStartedEvent(e){let t={callId:e.callId,turnId:e.turnId,name:e.name,sessionId:e.sessionId,streamPath:createEveSessionStreamRoutePath(e.sessionId)};return e.taskId!==void 0&&(t.taskId=e.taskId),e.remote!==void 0&&(t.remote=e.remote,t.streamPath=createEveSubagentStreamRoutePath({callId:e.callId,childSessionId:e.sessionId,parentSessionId:e.parentSessionId})),{data:t,type:`agent.started`}}function createMessageAppendedEvent(e){return{data:{messageDelta:e.messageDelta,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`message.appended`}}function createReasoningAppendedEvent(e){return{data:{reasoningDelta:e.reasoningDelta,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`reasoning.appended`}}function createMessageCompletedEvent(e){return{data:{finishReason:e.finishReason??`stop`,message:e.message,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`message.completed`}}function createReasoningCompletedEvent(e){return{data:{reasoning:e.reasoning,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`reasoning.completed`}}function createResultCompletedEvent(e){return{data:{result:e.result,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`result.completed`}}function createStepStartedEvent(e){return{data:{modelId:e.modelId,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`step.started`}}function createStepCompletedEvent(e){let t={finishReason:e.finishReason,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId};return e.usage!==void 0&&(t.usage=e.usage),e.providerMetadata!==void 0&&(t.providerMetadata=e.providerMetadata),{data:t,type:`step.completed`}}function createStepFailedEvent(e){return{data:{code:e.code,details:e.details,message:e.message,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`step.failed`}}function createTurnCompletedEvent(e){return{data:{sequence:e.sequence,turnId:e.turnId},type:`turn.completed`}}function createTurnWaitingEvent(e){return{data:{on:e.on,sequence:e.sequence,turnId:e.turnId,...e.usage!==void 0&&{usage:e.usage}},type:`turn.waiting`}}function createTurnFailedEvent(e){return{data:{code:e.code,details:e.details,message:e.message,sequence:e.sequence,terminal:e.terminal,turnId:e.turnId},type:`turn.failed`}}function createTurnCancelledEvent(e){return{data:{sequence:e.sequence,turnId:e.turnId},type:`turn.cancelled`}}function createContextClearedEvent(e){return{data:{sequence:e.sequence,sessionId:e.sessionId,turnId:e.turnId},type:`context.cleared`}}function createCompactionRequestedEvent(e){return{data:{modelId:e.modelId,sequence:e.sequence,sessionId:e.sessionId,stepIndex:e.stepIndex,turnId:e.turnId,usageInputTokens:e.usageInputTokens??null},type:`compaction.requested`}}function createCompactionCompletedEvent(e){return{data:{modelId:e.modelId,sequence:e.sequence,sessionId:e.sessionId,stepIndex:e.stepIndex,turnId:e.turnId},type:`compaction.completed`}}function createSessionWaitingEvent(e){return{data:{continuationToken:``,...e!==void 0&&{usage:e},wait:`next-user-message`},type:`session.waiting`}}function createSessionFailedEvent(e){return{data:{code:e.code,details:e.details,message:e.message,sessionId:e.sessionId,...e.usage!==void 0&&{usage:e.usage}},type:`session.failed`}}function createSessionCompletedEvent(e){return e===void 0?{type:`session.completed`}:{data:{usage:e},type:`session.completed`}}function stampMessageStreamEvent(e,t){let n={at:new Date().toISOString(),id:createEventId()};return t!==void 0&&t.length>0&&(n.deliveryIds=t),{...e,meta:n}}function encodeMessageStreamEvent(e){return textEncoder.encode(`${JSON.stringify(e)}\n`)}function normalizeActionResultOutcome(e){return e.isError===!0?{error:buildActionResultError(e),status:`failed`}:{status:`completed`}}function buildActionResultError(e){let t=readActionResultOutputError(e.output)??{code:`ACTION_RESULT_FAILED`,message:formatActionResultOutput(e.output)};return e.kind===`tool-result`&&e.errorName!==void 0?{...t,name:e.errorName}:t}function readActionResultOutputError(e){let t=parseActionResultOutputRecord(e);if(t===void 0)return;let n=typeof t.code==`string`&&t.code.length>0?t.code:void 0,r=typeof t.message==`string`&&t.message.length>0?t.message:void 0;if(n!==void 0&&r!==void 0)return{code:n,message:r}}function parseActionResultOutputRecord(e){if(typeof e==`object`&&e)return e;if(typeof e!=`string`)return;let t=e.trim();if(t.length!==0)try{let e=JSON.parse(t);if(typeof e==`object`&&e)return e}catch{return}}function formatActionResultOutput(e){if(typeof e==`string`)return e;let t=JSON.stringify(e);return typeof t==`string`&&t.length>0?t:`Action failed.`}export{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,createActionInputAppendedEvent,createActionPartialEvent,createActionResultEvent,createActionsRequestedEvent,createAgentStartedEvent,createApprovalCandidateEvent,createApprovalSettledEvent,createAuthorizationCompletedEvent,createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createContextClearedEvent,createInputRequestedEvent,createInputResolvedEvent,createMessageAppendedEvent,createMessageCompletedEvent,createMessageReceivedEvent,createReasoningAppendedEvent,createReasoningCompletedEvent,createResultCompletedEvent,createSessionCompletedEvent,createSessionFailedEvent,createSessionStartedEvent,createSessionWaitingEvent,createStepCompletedEvent,createStepFailedEvent,createStepStartedEvent,createTaskSettledEvent,createTaskStartedEvent,createTurnCancelledEvent,createTurnCompletedEvent,createTurnFailedEvent,createTurnStartedEvent,createTurnWaitingEvent,encodeMessageStreamEvent,isCurrentTurnBoundaryEvent,isTurnFailureEvent,stampMessageStreamEvent};
|
|
1
|
+
import{deserializeUrlFilePart,hasInternalRefScheme,isSerializedUrlFilePart}from"#internal/attachments/url-refs.js";import{createEveSessionStreamRoutePath,createEveSubagentStreamRoutePath}from"#protocol/routes.js";import{decodeSandboxRef,isSandboxRefUrl}from"#internal/attachments/sandbox-refs.js";import{getKnownByteLength}from"#internal/attachments/data.js";import{createEventId}from"#protocol/event-id.js";const EVE_SESSION_ID_HEADER=`x-eve-session-id`,EVE_STREAM_FORMAT_HEADER=`x-eve-stream-format`,EVE_STREAM_TAIL_INDEX_HEADER=`x-eve-stream-tail-index`,EVE_STREAM_VERSION_HEADER=`x-eve-stream-version`,EVE_MESSAGE_STREAM_CONTENT_TYPE=`application/x-ndjson; charset=utf-8`,EVE_MESSAGE_STREAM_FORMAT=`ndjson`,EVE_MESSAGE_STREAM_VERSION=`26`,EVE_STREAM_CONTROL_VERSION=`1`,EVE_STREAM_CONTROL_VERSION_QUERY=`streamControlVersion`,EVE_STREAM_LEASE_ENDED_CONTROL={$eve:`stream.lease-ended`,version:1},textEncoder=new TextEncoder;function isCurrentTurnBoundaryEvent(e){return e.type===`session.completed`||e.type===`session.failed`||e.type===`session.waiting`}function isTurnFailureEvent(e){return e.type===`session.failed`||e.type===`step.failed`||e.type===`turn.failed`}function createHistoryImportedEvent(e){return{data:{messages:e.messages,sequence:e.sequence,turnId:e.turnId},type:`history.imported`}}function createSessionStartedEvent(e){let t={};return e?.invocation!==void 0&&(t.invocation=e.invocation),e?.predecessor!==void 0&&(t.predecessor=e.predecessor),e?.runtime!==void 0&&(t.runtime=e.runtime),e?.trace!==void 0&&(t.trace=e.trace),{data:t,type:`session.started`}}function createTurnStartedEvent(e){let t={sequence:e.sequence,turnId:e.turnId};return e.trace!==void 0&&(t.trace=e.trace),{data:t,type:`turn.started`}}function createMessageReceivedEvent(e){return{data:{message:summarizeUserContent(e.message),parts:projectUserContentParts(e.message),sequence:e.sequence,turnId:e.turnId},type:`message.received`}}function summarizeUserContent(e){if(typeof e==`string`)return e;let t=[];for(let n of e)if(n.type===`text`)t.push(n.text);else if(n.type===`file`){let e=n.filename??n.mediaType;t.push(`[file: ${e} (${n.mediaType})]`)}else n.type===`image`&&t.push(`[image: ${n.mediaType??`image`}]`);return t.join(`
|
|
2
|
+
`)}function projectUserContentParts(e){if(typeof e==`string`)return[{text:e,type:`text`}];let t=[];for(let n of e)n.type===`text`?t.push({text:n.text,type:`text`}):n.type===`file`?t.push(projectFileLikePart(n.data,n.mediaType,n.filename)):n.type===`image`&&t.push(projectFileLikePart(n.image,n.mediaType??`application/octet-stream`,void 0));return t}function projectFileLikePart(e,t,n){if(isSandboxRefUrl(e)){let t=decodeSandboxRef(e);return createProjectedFilePart({filename:basenameOf(n??t.path),mediaType:t.mediaType,size:t.size})}let r=projectTaggedFileData(e,t,n);if(r!==void 0)return r;let i=clientUrlFragment(e);if(i.url!==void 0)return createProjectedFilePart({filename:n,mediaType:t,...i});let a=getKnownByteLength(e);return createProjectedFilePart(a===null?{filename:n,mediaType:t}:{filename:n,mediaType:t,size:a})}function projectTaggedFileData(e,t,n){if(isTaggedFileData(e))switch(e.type){case`data`:{let r=byteLengthOf(e.data);return createProjectedFilePart(r===void 0?{filename:n,mediaType:t}:{filename:n,mediaType:t,size:r})}case`reference`:case`text`:return createProjectedFilePart({filename:n,mediaType:t});case`url`:return createProjectedFilePart({filename:n,mediaType:t,...clientUrlFragment(e.url)})}}function createProjectedFilePart(e){let t={mediaType:e.mediaType,type:`file`};return e.filename!==void 0&&(t.filename=e.filename),e.size!==void 0&&(t.size=e.size),e.url!==void 0&&(t.url=e.url),t}function isTaggedFileData(e){if(typeof e!=`object`||!e)return!1;let t=e.type;return t===`data`||t===`reference`||t===`text`||t===`url`}function byteLengthOf(e){if(e instanceof Uint8Array||e instanceof ArrayBuffer)return e.byteLength}function clientUrlFragment(e){if(isSerializedUrlFilePart(e))try{let t=deserializeUrlFilePart(e);return isClientResolvableUrl(t)?{url:t.href}:{}}catch{return{}}if(e instanceof URL)return isClientResolvableUrl(e)?{url:e.href}:{};if(typeof e!=`string`||hasInternalRefScheme(e))return{};try{let t=new URL(e);return isClientResolvableUrl(t)?{url:t.href}:{}}catch{return{}}}function isClientResolvableUrl(e){return e.protocol===`http:`||e.protocol===`https:`}function basenameOf(e){let t=e.replaceAll(`\\`,`/`),n=t.slice(t.lastIndexOf(`/`)+1);return n.length>0?n:e}function createActionsRequestedEvent(e){return{data:{actions:e.actions,...optionalPresentation(e.presentation),sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`actions.requested`}}function optionalPresentation(e){return e===void 0?{}:{presentation:e}}function createActionInputAppendedEvent(e){return{data:{callId:e.callId,inputTextDelta:e.inputTextDelta,sequence:e.sequence,stepIndex:e.stepIndex,toolName:e.toolName,turnId:e.turnId},type:`action.input.appended`}}function createAuthorizationRequiredEvent(e){let t={description:e.description,name:e.name,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId};return e.attemptId!==void 0&&(t.attemptId=e.attemptId),e.authorization!==void 0&&(t.authorization=e.authorization),e.candidateId!==void 0&&(t.candidateId=e.candidateId),e.grant!==void 0&&(t.grant=e.grant),e.principal!==void 0&&(t.principal=e.principal),e.principalId!==void 0&&(t.principalId=e.principalId),e.webhookUrl!==void 0&&(t.webhookUrl=e.webhookUrl),e.taskId!==void 0&&(t.taskId=e.taskId),{data:t,type:`authorization.required`}}function createAuthorizationCompletedEvent(e){let t={name:e.name,outcome:e.outcome,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId};return e.attemptId!==void 0&&(t.attemptId=e.attemptId),e.authorization!==void 0&&(t.authorization=e.authorization),e.candidateId!==void 0&&(t.candidateId=e.candidateId),e.grant!==void 0&&(t.grant=e.grant),e.principal!==void 0&&(t.principal=e.principal),e.principalId!==void 0&&(t.principalId=e.principalId),e.reason!==void 0&&(t.reason=e.reason),e.retryable!==void 0&&(t.retryable=e.retryable),e.taskId!==void 0&&(t.taskId=e.taskId),{data:t,type:`authorization.completed`}}function createApprovalCandidateEvent(e){return{data:e,type:`approval.candidate`}}function createApprovalSettledEvent(e){return{data:e,type:`approval.settled`}}function createInputRequestedEvent(e){let t={requests:e.requests,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId};return e.callId!==void 0&&(t.callId=e.callId),e.taskId!==void 0&&(t.taskId=e.taskId),{data:t,type:`input.requested`}}function createInputResolvedEvent(e){return{data:{resolutions:e.resolutions,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`input.resolved`}}function createActionResultEvent(e){let t=e.rejected===!0?{error:buildActionResultError(e.result),status:`rejected`}:normalizeActionResultOutcome(e.result);return{data:{error:t.error,...optionalPresentation(e.presentation),result:e.result,sequence:e.sequence,status:t.status,stepIndex:e.stepIndex,turnId:e.turnId},type:`action.result`}}function createActionPartialEvent(e){return{data:{...optionalPresentation(e.presentation),result:e.result,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`action.partial`}}function createTaskStartedEvent(e){return{data:{callId:e.callId,kind:e.kind,name:e.name,taskId:e.taskId,turnId:e.turnId},type:`task.started`}}function createTaskSettledEvent(e){let t={callId:e.callId,...e.kind!==void 0&&{kind:e.kind},...e.name!==void 0&&{name:e.name},status:e.status,taskId:e.taskId,turnId:e.turnId};return e.output!==void 0&&(t.output=e.output),e.error!==void 0&&(t.error=e.error),e.cancel!==void 0&&(t.cancel=e.cancel),{data:t,type:`task.settled`}}function createAgentStartedEvent(e){let t={callId:e.callId,turnId:e.turnId,name:e.name,sessionId:e.sessionId,streamPath:createEveSessionStreamRoutePath(e.sessionId)};return e.taskId!==void 0&&(t.taskId=e.taskId),e.remote!==void 0&&(t.remote=e.remote,t.streamPath=createEveSubagentStreamRoutePath({callId:e.callId,childSessionId:e.sessionId,parentSessionId:e.parentSessionId})),{data:t,type:`agent.started`}}function createMessageAppendedEvent(e){return{data:{messageDelta:e.messageDelta,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`message.appended`}}function createReasoningAppendedEvent(e){return{data:{reasoningDelta:e.reasoningDelta,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`reasoning.appended`}}function createMessageCompletedEvent(e){return{data:{finishReason:e.finishReason??`stop`,message:e.message,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`message.completed`}}function createReasoningCompletedEvent(e){return{data:{reasoning:e.reasoning,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`reasoning.completed`}}function createResultCompletedEvent(e){return{data:{result:e.result,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`result.completed`}}function createStepStartedEvent(e){return{data:{modelId:e.modelId,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`step.started`}}function createStepCompletedEvent(e){let t={finishReason:e.finishReason,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId};return e.usage!==void 0&&(t.usage=e.usage),e.providerMetadata!==void 0&&(t.providerMetadata=e.providerMetadata),{data:t,type:`step.completed`}}function createStepFailedEvent(e){return{data:{code:e.code,details:e.details,message:e.message,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},type:`step.failed`}}function createTurnCompletedEvent(e){return{data:{sequence:e.sequence,turnId:e.turnId},type:`turn.completed`}}function createTurnWaitingEvent(e){return{data:{on:e.on,sequence:e.sequence,turnId:e.turnId,...e.usage!==void 0&&{usage:e.usage}},type:`turn.waiting`}}function createTurnFailedEvent(e){return{data:{code:e.code,details:e.details,message:e.message,sequence:e.sequence,terminal:e.terminal,turnId:e.turnId},type:`turn.failed`}}function createTurnCancelledEvent(e){return{data:{sequence:e.sequence,turnId:e.turnId},type:`turn.cancelled`}}function createContextClearedEvent(e){return{data:{sequence:e.sequence,sessionId:e.sessionId,turnId:e.turnId},type:`context.cleared`}}function createCompactionRequestedEvent(e){return{data:{modelId:e.modelId,sequence:e.sequence,sessionId:e.sessionId,stepIndex:e.stepIndex,turnId:e.turnId,usageInputTokens:e.usageInputTokens??null},type:`compaction.requested`}}function createCompactionCompletedEvent(e){return{data:{modelId:e.modelId,sequence:e.sequence,sessionId:e.sessionId,stepIndex:e.stepIndex,turnId:e.turnId},type:`compaction.completed`}}function createSessionWaitingEvent(e){return{data:{continuationToken:``,...e!==void 0&&{usage:e},wait:`next-user-message`},type:`session.waiting`}}function createSessionFailedEvent(e){return{data:{code:e.code,details:e.details,message:e.message,sessionId:e.sessionId,...e.usage!==void 0&&{usage:e.usage}},type:`session.failed`}}function createSessionCompletedEvent(e){return e===void 0?{type:`session.completed`}:{data:{usage:e},type:`session.completed`}}function stampMessageStreamEvent(e,t){let n={at:new Date().toISOString(),id:createEventId()};return t!==void 0&&t.length>0&&(n.deliveryIds=t),{...e,meta:n}}function encodeMessageStreamEvent(e){return textEncoder.encode(`${JSON.stringify(e)}\n`)}function normalizeActionResultOutcome(e){return e.isError===!0?{error:buildActionResultError(e),status:`failed`}:{status:`completed`}}function buildActionResultError(e){let t=readActionResultOutputError(e.output)??{code:`ACTION_RESULT_FAILED`,message:formatActionResultOutput(e.output)};return e.kind===`tool-result`&&e.errorName!==void 0?{...t,name:e.errorName}:t}function readActionResultOutputError(e){let t=parseActionResultOutputRecord(e);if(t===void 0)return;let n=typeof t.code==`string`&&t.code.length>0?t.code:void 0,r=typeof t.message==`string`&&t.message.length>0?t.message:void 0;if(n!==void 0&&r!==void 0)return{code:n,message:r}}function parseActionResultOutputRecord(e){if(typeof e==`object`&&e)return e;if(typeof e!=`string`)return;let t=e.trim();if(t.length!==0)try{let e=JSON.parse(t);if(typeof e==`object`&&e)return e}catch{return}}function formatActionResultOutput(e){if(typeof e==`string`)return e;let t=JSON.stringify(e);return typeof t==`string`&&t.length>0?t:`Action failed.`}export{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,createActionInputAppendedEvent,createActionPartialEvent,createActionResultEvent,createActionsRequestedEvent,createAgentStartedEvent,createApprovalCandidateEvent,createApprovalSettledEvent,createAuthorizationCompletedEvent,createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createContextClearedEvent,createHistoryImportedEvent,createInputRequestedEvent,createInputResolvedEvent,createMessageAppendedEvent,createMessageCompletedEvent,createMessageReceivedEvent,createReasoningAppendedEvent,createReasoningCompletedEvent,createResultCompletedEvent,createSessionCompletedEvent,createSessionFailedEvent,createSessionStartedEvent,createSessionWaitingEvent,createStepCompletedEvent,createStepFailedEvent,createStepStartedEvent,createTaskSettledEvent,createTaskStartedEvent,createTurnCancelledEvent,createTurnCompletedEvent,createTurnFailedEvent,createTurnStartedEvent,createTurnWaitingEvent,encodeMessageStreamEvent,isCurrentTurnBoundaryEvent,isTurnFailureEvent,stampMessageStreamEvent};
|
|
@@ -33,6 +33,8 @@ export interface ChatSdkChannelState extends Record<string, unknown>, PromptQueu
|
|
|
33
33
|
usersByPrincipal?: Record<string, string | null>;
|
|
34
34
|
/** Posted input request cards, keyed by message id, until eve resolves every request on them. */
|
|
35
35
|
pendingInputCards?: Record<string, ChatSdkPendingInputCard>;
|
|
36
|
+
/** Id of the latest message someone other than the bot sent in the thread. */
|
|
37
|
+
latestMessageId?: string;
|
|
36
38
|
streamStepIndex?: number | null;
|
|
37
39
|
}
|
|
38
40
|
/** One posted card's requests and the resolutions eve has reported for them so far. */
|
|
@@ -97,12 +99,23 @@ interface ChatSdkThreadOptions {
|
|
|
97
99
|
* determines the eve continuation token and persisted channel state.
|
|
98
100
|
*/
|
|
99
101
|
export interface ChatSdkSendOptions extends ChatSdkThreadOptions, Omit<ChannelSendOptions, "auth"> {
|
|
102
|
+
/**
|
|
103
|
+
* Answers the input request on the card eve posted as `messageId` with
|
|
104
|
+
* `optionId`, when that card is still waiting on it. Otherwise eve delivers
|
|
105
|
+
* the message as usual.
|
|
106
|
+
*/
|
|
107
|
+
readonly inputAnswer?: ChatSdkInputAnswer;
|
|
100
108
|
/**
|
|
101
109
|
* Controls how this input interacts with an active eve turn on the same
|
|
102
110
|
* thread. Defaults to the channel's `turnPolicy`, then `"steer"`.
|
|
103
111
|
*/
|
|
104
112
|
readonly turnPolicy?: TurnPolicy;
|
|
105
113
|
}
|
|
114
|
+
/** An option chosen for the input request card posted as `messageId`. */
|
|
115
|
+
export interface ChatSdkInputAnswer {
|
|
116
|
+
readonly messageId: string;
|
|
117
|
+
readonly optionId: string;
|
|
118
|
+
}
|
|
106
119
|
/** Options for `bridge.respond`: channel respond options plus the thread. */
|
|
107
120
|
export interface ChatSdkRespondOptions extends ChatSdkThreadOptions, Omit<ChannelRespondOptions, "auth" | "state"> {
|
|
108
121
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{actionLabel,visibleActions}from"#shared/action-label.js";import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{parseInputResponses}from"#shared/input.js";import{defaultDeliverResult}from"#channel/adapter.js";import{ContextContainer,contextStorage}from"#context/container.js";import{GET,POST,defineChannel}from"#public/definitions/channel.js";import{ContextKey}from"#context/key.js";import{DEFAULT_UPLOAD_POLICY}from"#public/channels/upload-policy.js";import{EveAttachmentError}from"#internal/attachments/errors.js";import{assertWithinLimit}from"#internal/attachments/limited-read.js";import{isNotImplemented}from"#public/channels/chat-sdk/notImplemented.js";import{promptQueueEvents}from"#channel/prompt-queue.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import{Chat,Message,ThreadImpl}from"#compiled/chat/index.js";import{defaultAuthorizationEvents}from"#public/channels/chat-sdk/authorization.js";import{parseChatSdkFileRef}from"#public/channels/chat-sdk/attachment-refs.js";import{decodeInputAction,renderInputRequests,renderRetiredInputRequest}from"#public/channels/chat-sdk/input-actions.js";import{chatSdkInstrumentation}from"#public/channels/chat-sdk/audience.js";const log=createLogger(`chat-sdk.channel`),streamTextByState=new WeakMap,ActiveWebhookKey=new ContextKey(`chat-sdk.active-webhook`);function chatSdkChannel(e){let t=new Chat(e),n=e.inputActionPrefix??`eve_input:`,r=e.streaming??!0,i=e.streamingEditIntervalMs??1e3,a={...defaultEvents(n),...e.events};return t.onAction(async r=>{let i=decodeInputAction(r.actionId,n,r.value);if(!i)return;let{thread:a}=r;if(!a)throw Error(`chatSdkChannel input actions require a thread on the Chat SDK action event.`);let o=e.resolveInputAuth?await e.resolveInputAuth(r):null,s=await respondOrRetireInactivePrompt(()=>bridgeRespond(t,[i],{auth:o,thread:a.toJSON()}),{retirePrompt:e=>retireInputCard(a,r.messageId,e)},log);if(s.outcome===`failed`)throw s.error;s.outcome!==`delivered`&&await Promise.all([s.retirement,a.postEphemeral(r.user,{markdown:INACTIVE_REQUEST_NOTICE},{fallbackToDM:!0}).catch(e=>log.error(`inactive prompt notice failed`,{error:e}))])}),{bot:t,channel:defineChannel({kindHint:`chat-sdk`,turnPolicy:e.turnPolicy,fetchFile:e=>fetchAttachment(t,e),state:initialState(),...chatSdkInstrumentation,context(e){return{bot:t,state:e,streaming:r,streamingEditIntervalMs:i,thread:threadFromState(t,e)}},routes:adapterNames(e.adapters).flatMap(n=>{let r=routeForAdapter(n,e),handler=async(r,i)=>{let a=t.webhooks[n],o=new ContextContainer;return o.setVirtualContext(ActiveWebhookKey,{from:i.from}),contextStorage.run(o,()=>a(r,{...e.webhook,waitUntil(e){i.waitUntil(e)}}))};return[GET(r,handler),POST(r,handler)]}),async receive(e,{from:n}){let r=serializeReceiveTarget(t,e.target);return n(r.id).send(e.message,{auth:e.auth,state:{thread:r}})},deliver(e,t){
|
|
1
|
+
import{actionLabel,visibleActions}from"#shared/action-label.js";import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{parseInputResponses}from"#shared/input.js";import{defaultDeliverResult}from"#channel/adapter.js";import{ContextContainer,contextStorage}from"#context/container.js";import{GET,POST,defineChannel}from"#public/definitions/channel.js";import{ContextKey}from"#context/key.js";import{DEFAULT_UPLOAD_POLICY}from"#public/channels/upload-policy.js";import{EveAttachmentError}from"#internal/attachments/errors.js";import{assertWithinLimit}from"#internal/attachments/limited-read.js";import{isNotImplemented}from"#public/channels/chat-sdk/notImplemented.js";import{promptQueueEvents}from"#channel/prompt-queue.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import{Chat,Message,ThreadImpl}from"#compiled/chat/index.js";import{defaultAuthorizationEvents}from"#public/channels/chat-sdk/authorization.js";import{parseChatSdkFileRef}from"#public/channels/chat-sdk/attachment-refs.js";import{decodeInputAction,renderInputRequests,renderRetiredInputRequest}from"#public/channels/chat-sdk/input-actions.js";import{chatSdkInstrumentation}from"#public/channels/chat-sdk/audience.js";const log=createLogger(`chat-sdk.channel`),streamTextByState=new WeakMap,ActiveWebhookKey=new ContextKey(`chat-sdk.active-webhook`);function chatSdkChannel(e){let t=new Chat(e),n=e.inputActionPrefix??`eve_input:`,r=e.streaming??!0,i=e.streamingEditIntervalMs??1e3,a={...defaultEvents(n),...e.events};return t.onAction(async r=>{let i=decodeInputAction(r.actionId,n,r.value);if(!i)return;let{thread:a}=r;if(!a)throw Error(`chatSdkChannel input actions require a thread on the Chat SDK action event.`);let o=e.resolveInputAuth?await e.resolveInputAuth(r):null,s=await respondOrRetireInactivePrompt(()=>bridgeRespond(t,[i],{auth:o,thread:a.toJSON()}),{retirePrompt:e=>retireInputCard(a,r.messageId,e)},log);if(s.outcome===`failed`)throw s.error;s.outcome!==`delivered`&&await Promise.all([s.retirement,a.postEphemeral(r.user,{markdown:INACTIVE_REQUEST_NOTICE},{fallbackToDM:!0}).catch(e=>log.error(`inactive prompt notice failed`,{error:e}))])}),{bot:t,channel:defineChannel({kindHint:`chat-sdk`,turnPolicy:e.turnPolicy,fetchFile:e=>fetchAttachment(t,e),state:initialState(),...chatSdkInstrumentation,context(e){return{bot:t,state:e,streaming:r,streamingEditIntervalMs:i,thread:threadFromState(t,e)}},routes:adapterNames(e.adapters).flatMap(n=>{let r=routeForAdapter(n,e),handler=async(r,i)=>{let a=t.webhooks[n],o=new ContextContainer;return o.setVirtualContext(ActiveWebhookKey,{from:i.from}),contextStorage.run(o,()=>a(r,{...e.webhook,waitUntil(e){i.waitUntil(e)}}))};return[GET(r,handler),POST(r,handler)]}),async receive(e,{from:n}){let r=serializeReceiveTarget(t,e.target);return n(r.id).send(e.message,{auth:e.auth,state:{thread:r}})},deliver(e,t){recordPrincipalUser(t.state,t.session.auth.current,e),recordLatestMessage(t.state,e);let n=resolveInputAnswer(t.state,e);return n===void 0?defaultDeliverResult(e):{context:e.context,inputResponses:parseInputResponses([n])}},events:a}),send(e,n){return bridgeSend(t,e,n)},respond(e,n){return bridgeRespond(t,e,n)}}}function defaultEvents(e){async function showPrompt(t,n){if(!t.thread)return!1;let r=await t.thread.post(renderInputRequests([n],e));r.id&&(t.state.pendingInputCards={...t.state.pendingInputCards,[r.id]:{requests:[n],resolved:{}}})}async function clearAnsweredCards(t,n){let r=n.thread;if(r)for(let[i,a]of Object.entries(n.state.pendingInputCards??{})){let o=t.resolutions.filter(e=>a.requests.some(t=>t.requestId===e.requestId));if(o.length===0)continue;let s={...a.resolved,...Object.fromEntries(o.map(e=>[e.requestId,e]))},{[i]:c,...l}=n.state.pendingInputCards??{};if(n.state.pendingInputCards=a.requests.every(e=>s[e.requestId]!==void 0)?l:{...l,[i]:{requests:a.requests,resolved:s}},n.state.editSupported!==!1)try{await r.adapter.editMessage(r.id,i,renderInputRequests(a.requests,e,s))}catch(e){if(!isNotImplemented(e)){log.warn(`answered input card edit failed`,{error:e,messageId:i});continue}n.state.editSupported=!1}}}let t=promptQueueEvents(showPrompt);return{...defaultAuthorizationEvents(),async"turn.started"(e,t,n){t.state.pendingToolCallMessage=null,clearStream(t.state),await safeStartTyping(t.thread,`Working...`)},async"actions.requested"(e,t,n){let r=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,r){await safeStartTyping(t.thread,truncate(r));return}let i=visibleActions(e.actions).map(t=>actionLabel(t,e.presentation));i.length!==0&&await safeStartTyping(t.thread,truncate(`${i.join(`, `)}...`))},async"message.appended"(e,t,n){if(!t.thread||!canStream(t))return;let r=((t.state.streamStepIndex===e.stepIndex?streamTextByState.get(t.state):void 0)??``)+e.messageDelta;if(!r)return;streamTextByState.set(t.state,r);let i=t.state.anchorMessageId;if(!i||t.state.streamStepIndex!==e.stepIndex){let n=await t.thread.post({markdown:r});t.state.anchorMessageId=n.id,t.state.streamStepIndex=e.stepIndex,t.state.lastEditAtMs=Date.now();return}let a=t.state.lastEditAtMs??0;if(!(Date.now()-a<t.streamingEditIntervalMs))try{await editMessage(t.thread,i,r),t.state.lastEditAtMs=Date.now()}catch(e){if(!isNotImplemented(e))throw e;t.state.editSupported=!1,clearStream(t.state)}},...t,async"input.resolved"(e,n,r){await clearAnsweredCards(e,n),await t[`input.resolved`](e,n)},async"message.completed"(e,t,n){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null,e.message?await finalizeStreamedMessage(t,e.message,!1):clearStream(t.state);return}if(t.state.pendingToolCallMessage=null,!e.message){clearStream(t.state);return}await finalizeStreamedMessage(t,e.message,!0)},async"turn.failed"(e,t,n){e.terminal||await postFailure(t.thread,`I hit an error while handling your request`,`Please try again, rephrase, or reach out if it keeps failing.`,e)},async"session.failed"(e,t){await postFailure(t.thread,`This session could not recover from an error`,`Start a new conversation to continue.`,e)}}}async function safeStartTyping(e,t){if(e)try{await e.startTyping(t)}catch(e){if(!isNotImplemented(e))throw e}}async function editMessage(e,t,n){await e.adapter.editMessage(e.id,t,{markdown:n})}async function retireInputCard(e,t,n){try{await e.adapter.editMessage(e.id,t,renderRetiredInputRequest(n))}catch(e){if(!isNotImplemented(e))throw e}}async function finalizeStreamedMessage(e,t,n){let r=e.thread;if(!r){clearStream(e.state);return}let i=e.state.anchorMessageId;if(canStream(e)&&i)try{await editMessage(r,i,t)}catch(i){if(!isNotImplemented(i))throw i;e.state.editSupported=!1,n&&await r.post({markdown:t})}else n&&await r.post({markdown:t});clearStream(e.state)}function canStream(e){return e.streaming&&e.state.editSupported!==!1}function clearStream(e){e.anchorMessageId=null,e.lastEditAtMs=null,e.streamStepIndex=null,streamTextByState.delete(e)}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function truncate(e,t=80){return e.length<=t?e:`${e.slice(0,t-1)}\u2026`}async function postFailure(e,t,n,r){if(!e)return;let i=formatErrorHint(r),a=extractErrorId(r.details);await e.post([`${t}${i}.`,n,...a?[`Error id: ${a}`]:[]].join(`
|
|
2
2
|
|
|
3
|
-
`))}async function bridgeSend(e,t,n){let r=activeFrom(`send`),{adapterName:i,auth:a,thread:
|
|
3
|
+
`))}async function bridgeSend(e,t,n){let r=activeFrom(`send`),{adapterName:i,auth:a,inputAnswer:o,thread:s,...c}=n,l=serializeThread(e,s,i),u={thread:l};return o!==void 0&&(u.inputAnswer=o),r(l.id).send(t,{...c,auth:a??null,state:u})}async function bridgeRespond(e,t,n){let r=activeFrom(`respond`),{adapterName:i,auth:a,thread:o,...s}=n;return r(serializeThread(e,o,i).id).respond(parseInputResponses(t),{...s,auth:a??null})}function recordPrincipalUser(e,t,n){if(t===null)return;let r=(n.state?.thread)?.currentMessage?.author;if(r===void 0||r.isBot===!0||r.isMe)return;let i=e.usersByPrincipal?.[t.principalId];i!==r.userId&&i!==null&&(e.usersByPrincipal={...e.usersByPrincipal,[t.principalId]:i===void 0?r.userId:null})}function recordLatestMessage(e,t){let n=t.state?.thread?.currentMessage;n===void 0||n.author.isMe||(e.latestMessageId=n.id)}function resolveInputAnswer(e,t){let n=t.state?.inputAnswer;if(n===void 0)return;let r=e.pendingInputCards?.[n.messageId],i=r?.requests.find(e=>r.resolved[e.requestId]===void 0&&e.options?.some(e=>e.id===n.optionId)===!0);return i===void 0?void 0:{optionId:n.optionId,requestId:i.requestId}}function activeFrom(e){let t=contextStorage.getStore()?.get(ActiveWebhookKey);if(!t)throw Error(`chatSdkChannel().${e} can only run during a Chat SDK webhook handler for this bridge.`);return t.from}function initialState(){return{pendingAuthMessageIds:{},thread:null}}async function fetchAttachment(e,t){let n=parseChatSdkFileRef(new URL(t));if(n===null)return null;await e.initialize();let r=e.getAdapter(n.adapter).rehydrateAttachment?.(n.attachment);if(r?.fetchData===void 0)throw new EveAttachmentError({adapterKind:`chat-sdk`,kind:`resolver-threw`,message:`the ${n.adapter} adapter can't download it after the webhook returns.`});let i;try{i=await r.fetchData()}catch(e){throw e instanceof EveAttachmentError?e:new EveAttachmentError({adapterKind:`chat-sdk`,cause:e,kind:`resolver-threw`,message:`the ${n.adapter} download failed.`})}let a=Buffer.isBuffer(i)?i:Buffer.from(i);return assertWithinLimit(a,DEFAULT_UPLOAD_POLICY.maxBytes,`chat-sdk`),{bytes:a,mediaType:n.attachment.mimeType}}function threadFromState(e,t){if(!t.thread)return null;try{let n=t.thread;return new ThreadImpl({adapter:e.getAdapter(n.adapterName),channelId:n.channelId,channelVisibility:n.channelVisibility,currentMessage:n.currentMessage?Message.fromJSON(n.currentMessage):void 0,id:n.id,isDM:n.isDM,stateAdapter:e.getState()})}catch(e){return log.warn(`failed to rebuild Chat SDK thread from channel state`,{error:e}),null}}function serializeReceiveTarget(e,t){if(t.thread)return t.thread;if(!t.threadId)throw Error(`chatSdkChannel().receive requires target.thread or target.threadId.`);return serializeThread(e,t.threadId,t.adapterName)}function serializeThread(e,t,n){if(typeof t==`string`){let r=n??inferAdapterName(t),i=e.getAdapter(r);return{_type:`chat:Thread`,adapterName:r,channelId:i.channelIdFromThreadId(t),channelVisibility:i.getChannelVisibility?.(t),id:t,isDM:!1}}return isSerializedThread(t)?t:t.toJSON()}function isSerializedThread(e){return`_type`in e&&e._type===`chat:Thread`}function inferAdapterName(e){let t=e.indexOf(`:`);if(t<=0)throw Error(`chatSdkChannel string thread references require options.adapterName.`);return e.slice(0,t)}function adapterNames(e){return Object.keys(e)}function routeForAdapter(e,t){return t.routes?.[e]||`${(t.route??`/eve/v1`).replace(/\/$/u,``)}/${e}`}export{chatSdkChannel};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Message } from "#compiled/chat/index.js";
|
|
2
|
+
/** The slice of a Chat SDK adapter that fetches one message by id. */
|
|
3
|
+
export interface MessageLookup {
|
|
4
|
+
fetchMessage?(threadId: string, messageId: string): Promise<Message | null>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Fetches a message by id, or returns `null` when the adapter can't, the
|
|
8
|
+
* lookup fails, or it takes longer than a few seconds.
|
|
9
|
+
*/
|
|
10
|
+
export declare function fetchMessageBestEffort(adapter: MessageLookup, threadId: string, messageId: string): Promise<Message | null>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
async function fetchMessageBestEffort(e,t,n){if(e.fetchMessage===void 0)return null;let r;try{return await Promise.race([e.fetchMessage(t,n),new Promise(e=>{r=setTimeout(e,3e3,null)})])}catch{return null}finally{clearTimeout(r)}}export{fetchMessageBestEffort};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { chatSdkChannel, type ChatSdkChannel, type ChatSdkChannelBridge, type ChatSdkChannelConfig, type ChatSdkChannelContext, type ChatSdkChannelEvents, type ChatSdkChannelState, type ChatSdkEventContext, type ChatSdkInstrumentationMetadata, type ChatSdkReceiveTarget, type ChatSdkRespondOptions, type ChatSdkSendOptions, } from "#public/channels/chat-sdk/chatSdkChannel.js";
|
|
1
|
+
export { chatSdkChannel, type ChatSdkChannel, type ChatSdkChannelBridge, type ChatSdkChannelConfig, type ChatSdkChannelContext, type ChatSdkChannelEvents, type ChatSdkChannelState, type ChatSdkEventContext, type ChatSdkInputAnswer, type ChatSdkInstrumentationMetadata, type ChatSdkReceiveTarget, type ChatSdkRespondOptions, type ChatSdkSendOptions, } from "#public/channels/chat-sdk/chatSdkChannel.js";
|
|
2
2
|
export { messageToUserContent } from "#public/channels/chat-sdk/messageToUserContent.js";
|
|
3
3
|
export { isNotImplemented } from "#public/channels/chat-sdk/notImplemented.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** What a channel knows about the earlier message a person replied to. */
|
|
2
|
+
export interface QuotedMessage {
|
|
3
|
+
/** Platform id of the replied-to message. */
|
|
4
|
+
readonly id: string;
|
|
5
|
+
/** Text of the replied-to message, when the platform supplies it. */
|
|
6
|
+
readonly text?: string;
|
|
7
|
+
/** Whether the agent sent the replied-to message, when the platform says. */
|
|
8
|
+
readonly fromAgent?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Renders a `context` entry telling the model that the person's message is a
|
|
12
|
+
* reply to an earlier message, and what that message said. Messaging apps show
|
|
13
|
+
* the quote above the reply; without this the model sees only the reply.
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatReplyContext(quoted: QuotedMessage, reply: string): string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function formatReplyContext(e,t){let n=e.fromAgent===!0?`one of your earlier messages`:`an earlier message`,r=e.text===void 0?void 0:neutralizeTags(e.text.trim()),i=neutralizeTags(t.trim());return[`<reply_context>`,`${i?`The person's message ${JSON.stringify(truncate(i,200))}`:`The person's next message`} is a reply to ${n} (message_id: ${e.id}).`,...r?[`<quoted_message>`,truncate(r,1e3),`</quoted_message>`]:[`The replied-to message's text is not available.`],`</reply_context>`].join(`
|
|
2
|
+
`)}function truncate(e,t){return e.length>t?`${e.slice(0,t)}…`:e}function neutralizeTags(e){return e.replace(/<(\/?)(reply_context|quoted_message)/giu,`<$1$2`)}export{formatReplyContext};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DiscordInstrumentationMetadata } from "#public/channels/discord/index.js";
|
|
2
|
+
import type { SessionHistoryMessage } from "#shared/session-history.js";
|
|
2
3
|
import type { SessionAuthContext, TurnPolicy } from "#channel/types.js";
|
|
3
4
|
import type { SessionContext } from "#public/definitions/callback-context.js";
|
|
4
5
|
import type { ChannelContinuationOps } from "#public/definitions/channel.js";
|
|
@@ -80,6 +81,8 @@ export type DiscordCommandResult = {
|
|
|
80
81
|
readonly auth: SessionAuthContext | null;
|
|
81
82
|
readonly ephemeral?: boolean;
|
|
82
83
|
readonly context?: readonly string[];
|
|
84
|
+
/** Prior conversation added as user and assistant turns before this message. */
|
|
85
|
+
readonly history?: readonly SessionHistoryMessage[];
|
|
83
86
|
readonly title?: string;
|
|
84
87
|
} | null;
|
|
85
88
|
/** Sync or async {@link DiscordCommandResult}. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{discordAudience,discordInstrumentationMetadata}from"./audience.js";import{createLogger,logError}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import"#public/channels/discord/verify.js";import{callDiscordApi,createDiscordFollowupMessage,discordContinuationToken,editDiscordOriginalResponse,resolveDiscordBotToken,sendDiscordChannelMessage,splitDiscordMessageContent,triggerDiscordTypingIndicator}from"#public/channels/discord/api.js";import{buildFreeformModalResponse,deriveComponentInputResponses,deriveModalInputResponses,isDiscordFreeformComponent}from"#public/channels/discord/hitl.js";import{defaultDiscordAuth,defaultEvents,defaultOnCommand,editDiscordResolvedPrompt}from"#public/channels/discord/defaults.js";import{DISCORD_EPHEMERAL_MESSAGE_FLAG,DISCORD_INTERACTION_RESPONSE_TYPE,DISCORD_INTERACTION_TYPE,commandInteractionMessage,formatDiscordContextBlock,parseDiscordInteraction}from"#public/channels/discord/inbound.js";import{discordDeferredJson,discordJson,discordJsonBody,readMessageContent}from"#public/channels/discord/responses.js";import{verifyDiscordInbound}from"#public/channels/discord/verifyInbound.js";import{createDiscordFetchFile,discordCommandContent}from"#public/channels/discord/attachments.js";const log=createLogger(`discord.channel`);function discordChannel(e={}){let t=e.onCommand??defaultOnCommand,n=e.onInputResponse??(e.onCommand===void 0?acceptAsPresser:dropUnmappedInputResponse),r={...defaultEvents,...e.events};return defineChannel({kindHint:`discord`,turnPolicy:e.turnPolicy,state:initialDiscordState(),metadata:discordInstrumentationMetadata,audience:({state:e})=>e.audience??`unknown`,fetchFile:createDiscordFetchFile(e.api?.fetch),context(t,n){return rebuildDiscordContext(t,n,e)},routes:[POST(e.route??`/eve/v1/discord`,async(r,{from:i,waitUntil:a})=>{let o=await verifyDiscordInbound(r,e.credentials);if(o===null)return new Response(`unauthorized`,{status:401});let s;try{s=parseJsonObject(JSON.parse(o))}catch(e){return log.warn(`inbound Discord body is not valid JSON`,{error:e}),discordJson({content:`invalid request`,ephemeral:!0})}if(s.type===DISCORD_INTERACTION_TYPE.PING)return discordJson({type:DISCORD_INTERACTION_RESPONSE_TYPE.PONG});let c=parseDiscordInteraction(s);return c===null?discordJson({content:`Unsupported Discord interaction.`,ephemeral:!0}):handleInteraction({config:e,interaction:c,onCommand:t,onInputResponse:n,from:i,waitUntil:a})})],async receive(t,{from:n}){let r=t.target,i=readNonEmptyString(r.channelId);if(!i)throw Error(`discordChannel().receive requires target.channelId.`);let a=readNonEmptyString(r.conversationId),o=r.initialMessage;if(o!==void 0&&a!==void 0)throw Error("discordChannel().receive: `conversationId` and `initialMessage` are mutually exclusive.");let s=a??``,c=a!==void 0;if(o!==void 0){let t=await buildDiscordHandle({config:e,state:{...initialDiscordState(),channelId:i}}).sendChannelMessage(o);s=t.id,c=t.id.length>0}return n(discordContinuationToken(i,s)).send(t.message,{auth:t.auth,state:{applicationId:null,channelId:i,conversationId:s||null,guildId:null,hasMessageAnchor:c,initialResponseSent:!0,interactionToken:null}})},events:r})}function rebuildDiscordContext(e,t,n){return{discord:buildDiscordHandle({config:n,session:t,state:e}),state:e}}function buildDiscordHandle(e){let t=e.config.api,n=e.state,r=mergeCredentials(e.config.credentials,n);function anchor(t,r){t.id&&(n.hasMessageAnchor&&r.components===void 0||(n.hasMessageAnchor||=(n.conversationId=t.id,!0),n.channelId&&e.session?.continuation?.alias(discordContinuationToken(n.channelId,t.id))))}async function sendViaChannel(e){let i=n.channelId??``;if(!i)throw Error(`discordChannel: missing channel id for outbound message.`);let a=normalizePostInput(e),o=await sendDiscordChannelMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,channelId:i});return anchor(o,a),o}async function editOriginal(e){let i=n.interactionToken??``;if(!i)throw Error(`discordChannel: missing interaction token for original response edit.`);let a=normalizePostInput(e),o=await editDiscordOriginalResponse({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,interactionToken:i});return n.initialResponseSent=!0,anchor(o,a),o}async function followup(e){let i=n.interactionToken??``;if(!i)throw Error(`discordChannel: missing interaction token for followup message.`);let a=normalizePostInput(e),o=await createDiscordFollowupMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,interactionToken:i});return anchor(o,a),o}async function startTyping(){let e=n.channelId??``;if(e)try{await triggerDiscordTypingIndicator({apiBaseUrl:t?.apiBaseUrl,credentials:r,fetch:t?.fetch,channelId:e})}catch(t){logError(log,`Discord typing indicator failed — swallowed`,t,{channelId:e})}}return{applicationId:n.applicationId??void 0,channelId:n.channelId??``,conversationId:n.conversationId??``,guildId:n.guildId??void 0,interactionToken:n.interactionToken??void 0,request(e,n,i){return callDiscordApi({apiBaseUrl:t?.apiBaseUrl,body:n,botToken:i?.botAuth===!0?r.botToken:void 0,fetch:t?.fetch,method:i?.method,path:e})},async post(e){let t=expandPostBodies(normalizePostInput(e)),r;for(let e of t){let t=await postOne({body:e,editOriginal,followup,sendViaChannel,state:n});r===void 0&&(r=t)}return r??{id:``,raw:null}},editOriginalResponse:editOriginal,followup,sendChannelMessage:sendViaChannel,startTyping}}async function postOne(e){if(e.state.interactionToken&&e.state.applicationId)try{return e.state.initialResponseSent?await e.followup(e.body):await e.editOriginal(e.body)}catch(e){log.warn(`Discord interaction-token delivery failed, falling back to channel message`,{error:e})}return e.sendViaChannel(e.body)}async function handleInteraction(e){return e.interaction.type===DISCORD_INTERACTION_TYPE.APPLICATION_COMMAND?handleCommandInteraction({config:e.config,interaction:e.interaction,onCommand:e.onCommand,from:e.from,waitUntil:e.waitUntil}):e.interaction.type===DISCORD_INTERACTION_TYPE.MESSAGE_COMPONENT?handleComponentInteraction({config:e.config,interaction:e.interaction,onInputResponse:e.onInputResponse,from:e.from,waitUntil:e.waitUntil}):handleModalSubmitInteraction({config:e.config,interaction:e.interaction,onInputResponse:e.onInputResponse,from:e.from,waitUntil:e.waitUntil})}async function handleCommandInteraction(e){let t=stateFromInteraction(e.interaction,{conversationId:e.interaction.id,hasMessageAnchor:!1,initialResponseSent:!1}),n={discord:buildDiscordHandle({config:e.config,state:t})},r;try{r=await e.onCommand(n,e.interaction)}catch(e){return log.error(`command handler failed`,{error:e}),discordJson({content:`The Discord command handler failed.`,ephemeral:!0})}return r==null?discordJson({content:`Command ignored.`,ephemeral:!0}):(e.waitUntil(dispatchCommand({interaction:e.interaction,result:r,from:e.from,state:t})),discordDeferredJson(r.ephemeral===!0))}function handleComponentInteraction(e){if(isDiscordFreeformComponent(e.interaction.customId)){let t=readMessageContent(e.interaction.raw);return discordJsonBody(buildFreeformModalResponse({customId:e.interaction.customId,prompt:t}))}let t=deriveComponentInputResponses(e.interaction);return t.length>0&&e.waitUntil(dispatchInputResponses({config:e.config,onInputResponse:e.onInputResponse,conversationId:e.interaction.messageId,inputResponses:t,interaction:e.interaction,from:e.from})),discordJsonBody({type:DISCORD_INTERACTION_RESPONSE_TYPE.DEFERRED_UPDATE_MESSAGE})}function handleModalSubmitInteraction(e){let t=deriveModalInputResponses(e.interaction);return t.length>0&&e.waitUntil(dispatchInputResponses({config:e.config,onInputResponse:e.onInputResponse,conversationId:e.interaction.messageId??e.interaction.id,inputResponses:t,interaction:e.interaction,from:e.from})),discordJson({content:`Answer received.`,ephemeral:!0})}async function dispatchCommand(e){let t=discordCommandContent(commandInteractionMessage(e.interaction),e.interaction.attachments),n=formatDiscordContextBlock({applicationId:e.interaction.applicationId,channelId:e.interaction.channelId,commandName:e.interaction.commandName,guildId:e.interaction.guildId,interactionId:e.interaction.id,userId:e.interaction.user.id,username:e.interaction.user.username}),r=e.result.context??[];try{await e.from(discordContinuationToken(e.interaction.channelId,e.interaction.id)).send(t,{auth:e.result.auth,context:[n,...r],state:e.state,title:e.result.title})}catch(e){log.error(`command delivery failed`,{error:e})}}async function dispatchInputResponses(e){let t=stateFromInteraction(e.interaction,{conversationId:e.conversationId,hasMessageAnchor:e.conversationId!==e.interaction.id,initialResponseSent:!0}),n=buildDiscordHandle({config:e.config,state:t}),r;try{r=await e.onInputResponse({defaultAuth:defaultDiscordAuth(e.interaction),discord:n},e.interaction)}catch(e){log.error(`input response handler failed`,{error:e});return}if(r===null)return;let{auth:i}=r,a=e.from(discordContinuationToken(e.interaction.channelId,e.conversationId)),o=await respondOrRetireInactivePrompt(()=>a.respond(e.inputResponses,{auth:i}),{retirePrompt:async t=>{let r=e.interaction.messageId,i=readMessageContent(e.interaction.raw);r!==void 0&&i!==void 0&&await editDiscordResolvedPrompt(n,{content:i,messageId:r},t)}},log);o.outcome===`inactive`&&await Promise.all([o.retirement,sendInactiveNotice(n)])}async function sendInactiveNotice(e){try{await e.followup({content:INACTIVE_REQUEST_NOTICE,flags:DISCORD_EPHEMERAL_MESSAGE_FLAG})}catch(e){log.error(`inactive prompt notice failed`,{error:e})}}function acceptAsPresser(e){return{auth:e.defaultAuth}}function dropUnmappedInputResponse(){return log.warn(`dropped a Discord input response: onCommand is customized but onInputResponse is not; set onInputResponse to accept button presses and modal submissions`),null}function stateFromInteraction(e,t){return{audience:discordAudience(e.channelType),applicationId:e.applicationId,channelId:e.channelId,conversationId:t.conversationId,guildId:e.guildId??null,hasMessageAnchor:t.hasMessageAnchor,initialResponseSent:t.initialResponseSent,interactionToken:e.token}}function initialDiscordState(){return{applicationId:null,channelId:null,conversationId:null,guildId:null,hasMessageAnchor:!1,initialResponseSent:!1,interactionToken:null}}function mergeCredentials(e,t){return{applicationId:t.applicationId??e?.applicationId,botToken:e?.botToken??(()=>resolveDiscordBotToken()),publicKey:e?.publicKey,webhookVerifier:e?.webhookVerifier}}function normalizePostInput(e){return typeof e==`string`?{content:e}:e}function expandPostBodies(e){return typeof e.content==`string`?splitDiscordMessageContent(e.content).map((t,n)=>n===0?{...e,content:t}:{allowed_mentions:e.allowed_mentions,content:t}):[e]}export{discordChannel};
|
|
1
|
+
import{discordAudience,discordInstrumentationMetadata}from"./audience.js";import{createLogger,logError}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import"#public/channels/discord/verify.js";import{callDiscordApi,createDiscordFollowupMessage,discordContinuationToken,editDiscordOriginalResponse,resolveDiscordBotToken,sendDiscordChannelMessage,splitDiscordMessageContent,triggerDiscordTypingIndicator}from"#public/channels/discord/api.js";import{buildFreeformModalResponse,deriveComponentInputResponses,deriveModalInputResponses,isDiscordFreeformComponent}from"#public/channels/discord/hitl.js";import{defaultDiscordAuth,defaultEvents,defaultOnCommand,editDiscordResolvedPrompt}from"#public/channels/discord/defaults.js";import{DISCORD_EPHEMERAL_MESSAGE_FLAG,DISCORD_INTERACTION_RESPONSE_TYPE,DISCORD_INTERACTION_TYPE,commandInteractionMessage,formatDiscordContextBlock,parseDiscordInteraction}from"#public/channels/discord/inbound.js";import{discordDeferredJson,discordJson,discordJsonBody,readMessageContent}from"#public/channels/discord/responses.js";import{verifyDiscordInbound}from"#public/channels/discord/verifyInbound.js";import{createDiscordFetchFile,discordCommandContent}from"#public/channels/discord/attachments.js";const log=createLogger(`discord.channel`);function discordChannel(e={}){let t=e.onCommand??defaultOnCommand,n=e.onInputResponse??(e.onCommand===void 0?acceptAsPresser:dropUnmappedInputResponse),r={...defaultEvents,...e.events};return defineChannel({kindHint:`discord`,turnPolicy:e.turnPolicy,state:initialDiscordState(),metadata:discordInstrumentationMetadata,audience:({state:e})=>e.audience??`unknown`,fetchFile:createDiscordFetchFile(e.api?.fetch),context(t,n){return rebuildDiscordContext(t,n,e)},routes:[POST(e.route??`/eve/v1/discord`,async(r,{from:i,waitUntil:a})=>{let o=await verifyDiscordInbound(r,e.credentials);if(o===null)return new Response(`unauthorized`,{status:401});let s;try{s=parseJsonObject(JSON.parse(o))}catch(e){return log.warn(`inbound Discord body is not valid JSON`,{error:e}),discordJson({content:`invalid request`,ephemeral:!0})}if(s.type===DISCORD_INTERACTION_TYPE.PING)return discordJson({type:DISCORD_INTERACTION_RESPONSE_TYPE.PONG});let c=parseDiscordInteraction(s);return c===null?discordJson({content:`Unsupported Discord interaction.`,ephemeral:!0}):handleInteraction({config:e,interaction:c,onCommand:t,onInputResponse:n,from:i,waitUntil:a})})],async receive(t,{from:n}){let r=t.target,i=readNonEmptyString(r.channelId);if(!i)throw Error(`discordChannel().receive requires target.channelId.`);let a=readNonEmptyString(r.conversationId),o=r.initialMessage;if(o!==void 0&&a!==void 0)throw Error("discordChannel().receive: `conversationId` and `initialMessage` are mutually exclusive.");let s=a??``,c=a!==void 0;if(o!==void 0){let t=await buildDiscordHandle({config:e,state:{...initialDiscordState(),channelId:i}}).sendChannelMessage(o);s=t.id,c=t.id.length>0}return n(discordContinuationToken(i,s)).send(t.message,{auth:t.auth,state:{applicationId:null,channelId:i,conversationId:s||null,guildId:null,hasMessageAnchor:c,initialResponseSent:!0,interactionToken:null}})},events:r})}function rebuildDiscordContext(e,t,n){return{discord:buildDiscordHandle({config:n,session:t,state:e}),state:e}}function buildDiscordHandle(e){let t=e.config.api,n=e.state,r=mergeCredentials(e.config.credentials,n);function anchor(t,r){t.id&&(n.hasMessageAnchor&&r.components===void 0||(n.hasMessageAnchor||=(n.conversationId=t.id,!0),n.channelId&&e.session?.continuation?.alias(discordContinuationToken(n.channelId,t.id))))}async function sendViaChannel(e){let i=n.channelId??``;if(!i)throw Error(`discordChannel: missing channel id for outbound message.`);let a=normalizePostInput(e),o=await sendDiscordChannelMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,channelId:i});return anchor(o,a),o}async function editOriginal(e){let i=n.interactionToken??``;if(!i)throw Error(`discordChannel: missing interaction token for original response edit.`);let a=normalizePostInput(e),o=await editDiscordOriginalResponse({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,interactionToken:i});return n.initialResponseSent=!0,anchor(o,a),o}async function followup(e){let i=n.interactionToken??``;if(!i)throw Error(`discordChannel: missing interaction token for followup message.`);let a=normalizePostInput(e),o=await createDiscordFollowupMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,interactionToken:i});return anchor(o,a),o}async function startTyping(){let e=n.channelId??``;if(e)try{await triggerDiscordTypingIndicator({apiBaseUrl:t?.apiBaseUrl,credentials:r,fetch:t?.fetch,channelId:e})}catch(t){logError(log,`Discord typing indicator failed — swallowed`,t,{channelId:e})}}return{applicationId:n.applicationId??void 0,channelId:n.channelId??``,conversationId:n.conversationId??``,guildId:n.guildId??void 0,interactionToken:n.interactionToken??void 0,request(e,n,i){return callDiscordApi({apiBaseUrl:t?.apiBaseUrl,body:n,botToken:i?.botAuth===!0?r.botToken:void 0,fetch:t?.fetch,method:i?.method,path:e})},async post(e){let t=expandPostBodies(normalizePostInput(e)),r;for(let e of t){let t=await postOne({body:e,editOriginal,followup,sendViaChannel,state:n});r===void 0&&(r=t)}return r??{id:``,raw:null}},editOriginalResponse:editOriginal,followup,sendChannelMessage:sendViaChannel,startTyping}}async function postOne(e){if(e.state.interactionToken&&e.state.applicationId)try{return e.state.initialResponseSent?await e.followup(e.body):await e.editOriginal(e.body)}catch(e){log.warn(`Discord interaction-token delivery failed, falling back to channel message`,{error:e})}return e.sendViaChannel(e.body)}async function handleInteraction(e){return e.interaction.type===DISCORD_INTERACTION_TYPE.APPLICATION_COMMAND?handleCommandInteraction({config:e.config,interaction:e.interaction,onCommand:e.onCommand,from:e.from,waitUntil:e.waitUntil}):e.interaction.type===DISCORD_INTERACTION_TYPE.MESSAGE_COMPONENT?handleComponentInteraction({config:e.config,interaction:e.interaction,onInputResponse:e.onInputResponse,from:e.from,waitUntil:e.waitUntil}):handleModalSubmitInteraction({config:e.config,interaction:e.interaction,onInputResponse:e.onInputResponse,from:e.from,waitUntil:e.waitUntil})}async function handleCommandInteraction(e){let t=stateFromInteraction(e.interaction,{conversationId:e.interaction.id,hasMessageAnchor:!1,initialResponseSent:!1}),n={discord:buildDiscordHandle({config:e.config,state:t})},r;try{r=await e.onCommand(n,e.interaction)}catch(e){return log.error(`command handler failed`,{error:e}),discordJson({content:`The Discord command handler failed.`,ephemeral:!0})}return r==null?discordJson({content:`Command ignored.`,ephemeral:!0}):(e.waitUntil(dispatchCommand({interaction:e.interaction,result:r,from:e.from,state:t})),discordDeferredJson(r.ephemeral===!0))}function handleComponentInteraction(e){if(isDiscordFreeformComponent(e.interaction.customId)){let t=readMessageContent(e.interaction.raw);return discordJsonBody(buildFreeformModalResponse({customId:e.interaction.customId,prompt:t}))}let t=deriveComponentInputResponses(e.interaction);return t.length>0&&e.waitUntil(dispatchInputResponses({config:e.config,onInputResponse:e.onInputResponse,conversationId:e.interaction.messageId,inputResponses:t,interaction:e.interaction,from:e.from})),discordJsonBody({type:DISCORD_INTERACTION_RESPONSE_TYPE.DEFERRED_UPDATE_MESSAGE})}function handleModalSubmitInteraction(e){let t=deriveModalInputResponses(e.interaction);return t.length>0&&e.waitUntil(dispatchInputResponses({config:e.config,onInputResponse:e.onInputResponse,conversationId:e.interaction.messageId??e.interaction.id,inputResponses:t,interaction:e.interaction,from:e.from})),discordJson({content:`Answer received.`,ephemeral:!0})}async function dispatchCommand(e){let t=discordCommandContent(commandInteractionMessage(e.interaction),e.interaction.attachments),n=formatDiscordContextBlock({applicationId:e.interaction.applicationId,channelId:e.interaction.channelId,commandName:e.interaction.commandName,guildId:e.interaction.guildId,interactionId:e.interaction.id,userId:e.interaction.user.id,username:e.interaction.user.username}),r=e.result.context??[];try{await e.from(discordContinuationToken(e.interaction.channelId,e.interaction.id)).send(t,{auth:e.result.auth,context:[n,...r],history:e.result.history,state:e.state,title:e.result.title})}catch(e){log.error(`command delivery failed`,{error:e})}}async function dispatchInputResponses(e){let t=stateFromInteraction(e.interaction,{conversationId:e.conversationId,hasMessageAnchor:e.conversationId!==e.interaction.id,initialResponseSent:!0}),n=buildDiscordHandle({config:e.config,state:t}),r;try{r=await e.onInputResponse({defaultAuth:defaultDiscordAuth(e.interaction),discord:n},e.interaction)}catch(e){log.error(`input response handler failed`,{error:e});return}if(r===null)return;let{auth:i}=r,a=e.from(discordContinuationToken(e.interaction.channelId,e.conversationId)),o=await respondOrRetireInactivePrompt(()=>a.respond(e.inputResponses,{auth:i}),{retirePrompt:async t=>{let r=e.interaction.messageId,i=readMessageContent(e.interaction.raw);r!==void 0&&i!==void 0&&await editDiscordResolvedPrompt(n,{content:i,messageId:r},t)}},log);o.outcome===`inactive`&&await Promise.all([o.retirement,sendInactiveNotice(n)])}async function sendInactiveNotice(e){try{await e.followup({content:INACTIVE_REQUEST_NOTICE,flags:DISCORD_EPHEMERAL_MESSAGE_FLAG})}catch(e){log.error(`inactive prompt notice failed`,{error:e})}}function acceptAsPresser(e){return{auth:e.defaultAuth}}function dropUnmappedInputResponse(){return log.warn(`dropped a Discord input response: onCommand is customized but onInputResponse is not; set onInputResponse to accept button presses and modal submissions`),null}function stateFromInteraction(e,t){return{audience:discordAudience(e.channelType),applicationId:e.applicationId,channelId:e.channelId,conversationId:t.conversationId,guildId:e.guildId??null,hasMessageAnchor:t.hasMessageAnchor,initialResponseSent:t.initialResponseSent,interactionToken:e.token}}function initialDiscordState(){return{applicationId:null,channelId:null,conversationId:null,guildId:null,hasMessageAnchor:!1,initialResponseSent:!1,interactionToken:null}}function mergeCredentials(e,t){return{applicationId:t.applicationId??e?.applicationId,botToken:e?.botToken??(()=>resolveDiscordBotToken()),publicKey:e?.publicKey,webhookVerifier:e?.webhookVerifier}}function normalizePostInput(e){return typeof e==`string`?{content:e}:e}function expandPostBodies(e){return typeof e.content==`string`?splitDiscordMessageContent(e.content).map((t,n)=>n===0?{...e,content:t}:{allowed_mentions:e.allowed_mentions,content:t}):[e]}export{discordChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{extractGitHubCommentTrigger,formatGitHubContextBlock}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{buildGitHubPullRequestContext,mergeGitHubContext}from"#public/channels/github/pr-context.js";import{continuationTokenFromState,stateFromCiEvent,stateFromIssueCommentEvent,stateFromIssueEvent,stateFromPullRequestEvent,stateFromPullRequestReviewCommentEvent}from"#public/channels/github/state.js";const log=createLogger(`github.dispatch`);async function dispatchIssueComment(e){let t=await e.botName();if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,t))return;let n=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:t,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(n,toGitHubComment(e.event.comment)),config:e.config,from:e.from,state:stateFromIssueCommentEvent(e.event)})}async function dispatchPullRequestReviewComment(e){let t=await e.botName();if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,t))return;let n=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:t,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(n,toGitHubComment(e.event.comment)),config:e.config,from:e.from,state:stateFromPullRequestReviewCommentEvent(e.event)})}async function dispatchIssue(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({botName:e.botName,config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.issue),message:formatIssueEventMessage(e.event),from:e.from,state:stateFromIssueEvent(e.event)})}async function dispatchPullRequest(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({botName:e.botName,config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.pullRequest),message:formatPullRequestEventMessage(e.event),from:e.from,state:stateFromPullRequestEvent(e.event)})}async function dispatchCheckSuite(e){await dispatchCiEvent({...e,ci:e.event.checkSuite,handlerResult:t=>e.handler(t,e.event.checkSuite),label:`Check suite`})}async function dispatchCheckRun(e){await dispatchCiEvent({...e,ci:e.event.checkRun,handlerResult:t=>e.handler(t,e.event.checkRun),label:`Check run`})}async function dispatchWorkflowRun(e){await dispatchCiEvent({...e,ci:e.event.workflowRun,handlerResult:t=>e.handler(t,e.event.workflowRun),label:`Workflow run`})}async function dispatchCiEvent(e){let t=stateFromCiEvent(e.event),n=buildInboundContext(e.config,e.event);if(t.pullRequestNumber===null){await runInboundHandler({event:e.event,handlerResult:()=>e.handlerResult(n)})!=null&&log.warn(`GitHub CI event cannot dispatch without an associated pull request`,{deliveryId:e.event.delivery.id,event:e.event.kind});return}await dispatchWebhookEventTurn({botName:e.botName,config:e.config,event:e.event,handlerResult:()=>e.handlerResult(n),message:formatCiEventMessage(e.label,e.ci),from:e.from,state:t})}async function dispatchWebhookEventTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});if(t==null)return;let n=await e.botName();await sendGitHubTurn({auth:t.auth,botName:n,event:e.event,message:e.message,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),from:e.from,state:e.state,title:t.title})}async function dispatchCommentTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});if(t==null)return;let n=extractGitHubCommentTrigger({body:e.body,botName:e.botName}),r=n?.message??e.body.trim();await sendGitHubTurn({auth:t.auth,botName:e.botName,commentUrl:e.commentUrl,event:e.event,isMentioned:n!==null,message:r,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),from:e.from,state:e.state,title:t.title})}async function runInboundHandler(e){try{return await e.handlerResult()}catch(t){logError(log,`GitHub inbound handler failed`,t,{deliveryId:e.event.delivery.id});return}}async function sendGitHubTurn(e){let t=formatGitHubContextBlock({botName:e.botName,deliveryId:e.event.delivery.id,commentUrl:e.commentUrl,headSha:e.state.headSha,issueNumber:e.state.issueNumber,isMentioned:e.isMentioned,pullRequestNumber:e.state.pullRequestNumber,repository:e.event.repository,sender:e.event.sender});try{await e.from(continuationTokenFromState(e.state)).send(e.message,{auth:e.auth,context:[t,...e.context??[]],state:e.state,title:e.title})}catch(t){logError(log,e.logMessage??`GitHub delivery failed`,t,{deliveryId:e.event.delivery.id})}}async function buildPullRequestContext(e,t,n){try{return await buildGitHubPullRequestContext({api:e.api,baseSha:t.baseSha,config:e.pullRequestContext,credentials:e.credentials,headSha:t.headSha,installationId:t.installationId??void 0,owner:t.owner,pullRequestNumber:t.pullRequestNumber,repo:t.repo})}catch(e){logError(log,`GitHub pull-request context failed — swallowed`,e,{deliveryId:n});return}}function buildInboundContext(e,t){let n=t.kind===`check_suite`||t.kind===`check_run`||t.kind===`workflow_run`?stateFromCiEvent(t):t.kind===`issue_comment`?stateFromIssueCommentEvent(t):t.kind===`issues`?stateFromIssueEvent(t):t.kind===`pull_request`?stateFromPullRequestEvent(t):stateFromPullRequestReviewCommentEvent(t),r=buildGitHubBinding({config:e,state:n});return{conversation:t.conversation,delivery:t.delivery,github:r.github,repository:t.repository,sender:t.sender,thread:r.thread}}function toGitHubComment(e){return{author:e.author,body:e.body,htmlUrl:e.htmlUrl,id:e.id,raw:e.raw,url:e.url}}function formatIssueEventMessage(e){let t=readString(e.issue.raw.title);return`Issue ${e.issue.action}: #${e.issue.issueNumber}${t?` ${t}`:``}`}function formatPullRequestEventMessage(e){let t=readString(e.pullRequest.raw.title);return`Pull request ${e.pullRequest.action}: #${e.pullRequest.pullRequestNumber}${t?` ${t}`:``}`}function formatCiEventMessage(e,t){let n=t.conclusion??t.status;return`${e} ${t.action}: ${ciEventId(t)}${n?` (${n})`:``}`}function ciEventId(e){return`checkSuiteId`in e?e.checkSuiteId:`checkRunId`in e?e.checkRunId:e.workflowRunId}function isIgnoredInboundComment(e,t,n){if(e.includes(`<!-- eve:github:`)||t?.type===`Bot`)return!0;let r=n?`${n}[bot]`.toLowerCase():``;return r.length>0&&t?.login.toLowerCase()===r}function readString(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}export{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun};
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{extractGitHubCommentTrigger,formatGitHubContextBlock}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{buildGitHubPullRequestContext,mergeGitHubContext}from"#public/channels/github/pr-context.js";import{continuationTokenFromState,stateFromCiEvent,stateFromIssueCommentEvent,stateFromIssueEvent,stateFromPullRequestEvent,stateFromPullRequestReviewCommentEvent}from"#public/channels/github/state.js";const log=createLogger(`github.dispatch`);async function dispatchIssueComment(e){let t=await e.botName();if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,t))return;let n=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:t,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(n,toGitHubComment(e.event.comment)),config:e.config,from:e.from,state:stateFromIssueCommentEvent(e.event)})}async function dispatchPullRequestReviewComment(e){let t=await e.botName();if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,t))return;let n=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:t,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(n,toGitHubComment(e.event.comment)),config:e.config,from:e.from,state:stateFromPullRequestReviewCommentEvent(e.event)})}async function dispatchIssue(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({botName:e.botName,config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.issue),message:formatIssueEventMessage(e.event),from:e.from,state:stateFromIssueEvent(e.event)})}async function dispatchPullRequest(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({botName:e.botName,config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.pullRequest),message:formatPullRequestEventMessage(e.event),from:e.from,state:stateFromPullRequestEvent(e.event)})}async function dispatchCheckSuite(e){await dispatchCiEvent({...e,ci:e.event.checkSuite,handlerResult:t=>e.handler(t,e.event.checkSuite),label:`Check suite`})}async function dispatchCheckRun(e){await dispatchCiEvent({...e,ci:e.event.checkRun,handlerResult:t=>e.handler(t,e.event.checkRun),label:`Check run`})}async function dispatchWorkflowRun(e){await dispatchCiEvent({...e,ci:e.event.workflowRun,handlerResult:t=>e.handler(t,e.event.workflowRun),label:`Workflow run`})}async function dispatchCiEvent(e){let t=stateFromCiEvent(e.event),n=buildInboundContext(e.config,e.event);if(t.pullRequestNumber===null){await runInboundHandler({event:e.event,handlerResult:()=>e.handlerResult(n)})!=null&&log.warn(`GitHub CI event cannot dispatch without an associated pull request`,{deliveryId:e.event.delivery.id,event:e.event.kind});return}await dispatchWebhookEventTurn({botName:e.botName,config:e.config,event:e.event,handlerResult:()=>e.handlerResult(n),message:formatCiEventMessage(e.label,e.ci),from:e.from,state:t})}async function dispatchWebhookEventTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});if(t==null)return;let n=await e.botName();await sendGitHubTurn({auth:t.auth,botName:n,event:e.event,message:e.message,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),from:e.from,history:t.history,state:e.state,title:t.title})}async function dispatchCommentTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});if(t==null)return;let n=extractGitHubCommentTrigger({body:e.body,botName:e.botName}),r=n?.message??e.body.trim();await sendGitHubTurn({auth:t.auth,botName:e.botName,commentUrl:e.commentUrl,event:e.event,isMentioned:n!==null,message:r,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),from:e.from,history:t.history,state:e.state,title:t.title})}async function runInboundHandler(e){try{return await e.handlerResult()}catch(t){logError(log,`GitHub inbound handler failed`,t,{deliveryId:e.event.delivery.id});return}}async function sendGitHubTurn(e){let t=formatGitHubContextBlock({botName:e.botName,deliveryId:e.event.delivery.id,commentUrl:e.commentUrl,headSha:e.state.headSha,issueNumber:e.state.issueNumber,isMentioned:e.isMentioned,pullRequestNumber:e.state.pullRequestNumber,repository:e.event.repository,sender:e.event.sender});try{await e.from(continuationTokenFromState(e.state)).send(e.message,{auth:e.auth,context:[t,...e.context??[]],history:e.history,state:e.state,title:e.title})}catch(t){logError(log,e.logMessage??`GitHub delivery failed`,t,{deliveryId:e.event.delivery.id})}}async function buildPullRequestContext(e,t,n){try{return await buildGitHubPullRequestContext({api:e.api,baseSha:t.baseSha,config:e.pullRequestContext,credentials:e.credentials,headSha:t.headSha,installationId:t.installationId??void 0,owner:t.owner,pullRequestNumber:t.pullRequestNumber,repo:t.repo})}catch(e){logError(log,`GitHub pull-request context failed — swallowed`,e,{deliveryId:n});return}}function buildInboundContext(e,t){let n=t.kind===`check_suite`||t.kind===`check_run`||t.kind===`workflow_run`?stateFromCiEvent(t):t.kind===`issue_comment`?stateFromIssueCommentEvent(t):t.kind===`issues`?stateFromIssueEvent(t):t.kind===`pull_request`?stateFromPullRequestEvent(t):stateFromPullRequestReviewCommentEvent(t),r=buildGitHubBinding({config:e,state:n});return{conversation:t.conversation,delivery:t.delivery,github:r.github,repository:t.repository,sender:t.sender,thread:r.thread}}function toGitHubComment(e){return{author:e.author,body:e.body,htmlUrl:e.htmlUrl,id:e.id,raw:e.raw,url:e.url}}function formatIssueEventMessage(e){let t=readString(e.issue.raw.title);return`Issue ${e.issue.action}: #${e.issue.issueNumber}${t?` ${t}`:``}`}function formatPullRequestEventMessage(e){let t=readString(e.pullRequest.raw.title);return`Pull request ${e.pullRequest.action}: #${e.pullRequest.pullRequestNumber}${t?` ${t}`:``}`}function formatCiEventMessage(e,t){let n=t.conclusion??t.status;return`${e} ${t.action}: ${ciEventId(t)}${n?` (${n})`:``}`}function ciEventId(e){return`checkSuiteId`in e?e.checkSuiteId:`checkRunId`in e?e.checkRunId:e.workflowRunId}function isIgnoredInboundComment(e,t,n){if(e.includes(`<!-- eve:github:`)||t?.type===`Bot`)return!0;let r=n?`${n}[bot]`.toLowerCase():``;return r.length>0&&t?.login.toLowerCase()===r}function readString(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}export{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SessionHistoryMessage } from "#shared/session-history.js";
|
|
1
2
|
import type { SessionAuthContext, TurnPolicy } from "#channel/types.js";
|
|
2
3
|
import type { SessionContext } from "#public/definitions/callback-context.js";
|
|
3
4
|
import type { ChannelContinuationOps } from "#public/definitions/channel.js";
|
|
@@ -61,6 +62,8 @@ export interface GitHubEventContext extends GitHubChannelContext, ChannelContinu
|
|
|
61
62
|
export type GitHubInboundResult = {
|
|
62
63
|
readonly auth: SessionAuthContext | null;
|
|
63
64
|
readonly context?: readonly string[];
|
|
65
|
+
/** Prior conversation added as user and assistant turns before this message. */
|
|
66
|
+
readonly history?: readonly SessionHistoryMessage[];
|
|
64
67
|
/** Overrides the workflow run title without changing the message sent to the model. */
|
|
65
68
|
readonly title?: string;
|
|
66
69
|
} | null;
|