eve 0.37.1 → 0.38.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 +16 -0
- package/dist/src/chunks/{use-eve-agent-DbKUBhl-.js → use-eve-agent-BbSsu99c.js} +70 -31
- package/dist/src/chunks/{use-eve-agent-Bi5fRxcZ.js → use-eve-agent-Dt8Y5QtW.js} +69 -30
- package/dist/src/cli/acp/command.d.ts +2 -1
- package/dist/src/cli/acp/command.js +2 -2
- package/dist/src/cli/application-command.d.ts +8 -0
- package/dist/src/cli/application-command.js +1 -0
- package/dist/src/cli/application-root.d.ts +8 -0
- package/dist/src/cli/application-root.js +1 -0
- package/dist/src/cli/commands/build.d.ts +2 -1
- package/dist/src/cli/commands/build.js +1 -1
- package/dist/src/cli/commands/init-repl.js +1 -1
- package/dist/src/cli/commands/register-integration-commands.d.ts +2 -1
- package/dist/src/cli/commands/register-integration-commands.js +1 -1
- package/dist/src/cli/commands/register-project-commands.d.ts +2 -1
- package/dist/src/cli/commands/register-project-commands.js +1 -1
- package/dist/src/cli/commands/register-registry-commands.d.ts +2 -1
- package/dist/src/cli/commands/register-registry-commands.js +4 -1
- package/dist/src/cli/commands/registry-recovery.d.ts +14 -0
- package/dist/src/cli/commands/registry-recovery.js +1 -0
- package/dist/src/cli/commands/registry.d.ts +2 -5
- package/dist/src/cli/commands/registry.js +1 -1
- package/dist/src/cli/dev/diagnostic-dump.js +1 -1
- package/dist/src/cli/dev/environment.js +1 -1
- package/dist/src/cli/invoke/command.d.ts +3 -2
- package/dist/src/cli/invoke/command.js +1 -1
- package/dist/src/cli/run.d.ts +3 -2
- package/dist/src/cli/run.js +3 -3
- package/dist/src/client/eve-agent-store.d.ts +15 -3
- package/dist/src/client/eve-agent-store.js +2 -2
- package/dist/src/client/message-response.d.ts +10 -2
- package/dist/src/client/message-response.js +1 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +4 -1
- package/dist/src/compiled/@ai-sdk/otel/index.js +3 -3
- package/dist/src/compiled/@chat-adapter/slack/index.js +25 -25
- package/dist/src/compiled/@opentelemetry/api/index.js +1 -1
- package/dist/src/compiled/@opentelemetry/otlp-transformer/index.js +1 -1
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +61 -61
- package/dist/src/compiled/@vercel/oidc/index.js +14 -14
- package/dist/src/compiled/@vercel/otel/index.js +1 -1
- package/dist/src/compiled/@vercel/sandbox/index.js +1 -1
- package/dist/src/compiled/@workflow/core/index.js +1 -1
- package/dist/src/compiled/@workflow/core/private.js +1 -1
- package/dist/src/compiled/@workflow/core/runtime.js +2 -2
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/errors/index.js +1 -1
- package/dist/src/compiled/@workflow/world-local/index.js +5 -5
- package/dist/src/compiled/@workflow/world-vercel/index.js +13 -13
- package/dist/src/compiled/_chunks/workflow/{attribute-changes-BoH7JsWp.js → attribute-changes-DZtQkszH.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/chunk-5MU5Z6L3-B_3nkJFi.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{chunk-NWCAEW5Y-Oxw40oRR.js → chunk-NWCAEW5Y-BgbcH0OK.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{dist-DlFv0aHY.js → dist-CPlyFOVo.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{dist-tJoQXAF6.js → dist-DpYyXbJv.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{dist-CRTn4Sg8.js → dist-xQXN70ED.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/esm-seIr7a6j.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{frames-CTpeJYEQ.js → frames-BBs-9k1d.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/{functions-CeeNvKsq.js → functions-DAYiHNti.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{getMachineId-bsd-WEBNKY2R-CEYkx6Nv.js → getMachineId-bsd-WEBNKY2R-BTaxrQ52.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{getMachineId-darwin-LT47KAXP-DPwWlhif.js → getMachineId-darwin-LT47KAXP-DhYmwE_R.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{getMachineId-linux-LTVQO6VW-DAFXHwZp.js → getMachineId-linux-LTVQO6VW-Dru_L5ru.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{getMachineId-unsupported-UKWBA27G-BZKOI8mG.js → getMachineId-unsupported-UKWBA27G-DGfoqVW1.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{getMachineId-win-NLJKOPY6-r7_CJB5o.js → getMachineId-win-NLJKOPY6-CLM98q4X.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{private-tvMBynnC.js → private-UQtz8ZcW.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{resume-hook-BPQHjeY5.js → resume-hook-CYtSorp6.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{rolldown-runtime-DaDcL9Zw.js → rolldown-runtime-8V8biNmG.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{run-DQ5dOyjm.js → run-Cjo0A3NO.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{signal-exit-C8vsI6zj.js → signal-exit-o3IPQwwv.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/sleep-C1P0OWBm.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{token-DHD-q-fS.js → token-DGzfw-Vb.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{token-DtCUEpJs.js → token-DNbxVpeq.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/token-util-BneBe0g5.js +27 -0
- package/dist/src/compiled/_chunks/workflow/{token-util-Ldar52H7.js → token-util-DjMgNdXS.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{undici-CUIybhQ2.js → undici-BBG5cZTy.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{wait-until-DK2lnH6U.js → wait-until-CT1ve8qB.js} +3 -3
- package/dist/src/compiled/_chunks/workflow/{wrapper-CMGju7QA.js → wrapper-CQNxP9mU.js} +3 -3
- package/dist/src/compiled/_chunks/workflow/{ws-transport-Csi6Cydc.js → ws-transport-beXxD0s_.js} +1 -1
- package/dist/src/compiled/env-runner/node-worker.js +1 -1
- package/dist/src/compiled/jose/index.js +1 -1
- package/dist/src/compiled/shadcn-registry/index.js +403 -403
- package/dist/src/compiler/artifacts.js +1 -1
- package/dist/src/compiler/compile-agent.js +2 -2
- package/dist/src/compiler/extension-compatibility.d.ts +10 -0
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/normalize-extension.d.ts +8 -5
- package/dist/src/compiler/normalize-extension.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/discover/discover-agent.js +1 -1
- package/dist/src/discover/extensions.d.ts +0 -6
- package/dist/src/discover/extensions.js +1 -1
- package/dist/src/evals/cli/eval.d.ts +1 -1
- package/dist/src/evals/cli/eval.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker-templates.js +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-templates.js +1 -1
- package/dist/src/execution/sandbox/prewarm.js +1 -1
- package/dist/src/harness/instrumentation/providers.js +1 -1
- package/dist/src/harness/instrumentation/runtime-context.d.ts +2 -0
- package/dist/src/harness/instrumentation/runtime-context.js +1 -1
- package/dist/src/harness/instrumentation/runtime.d.ts +3 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/cache-metadata.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +2 -2
- package/dist/src/internal/application/optional-package-install.js +1 -1
- package/dist/src/internal/application/output-publication-lock.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/application/paths.js +1 -1
- package/dist/src/internal/application/tsconfig-dependencies.js +1 -1
- package/dist/src/internal/authored-module-evaluation-error.js +4 -4
- package/dist/src/internal/authored-module-loader.js +3 -3
- package/dist/src/internal/authored-package-boundary.js +1 -1
- package/dist/src/internal/authored-relative-extension-resolver.js +1 -1
- package/dist/src/internal/bundler/extension-scope-plugin.js +1 -1
- package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
- package/dist/src/internal/instrumentation-layout.js +1 -1
- package/dist/src/internal/materialized-authored-modules.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts-retention.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
- package/dist/src/internal/nitro/host/application-route-registry.d.ts +88 -0
- package/dist/src/internal/nitro/host/application-route-registry.js +1 -0
- package/dist/src/internal/nitro/host/build-application.js +1 -1
- package/dist/src/internal/nitro/host/build-extension.js +1 -1
- package/dist/src/internal/nitro/host/build-vercel-agent-summary.js +1 -1
- package/dist/src/internal/nitro/host/channel-routes.d.ts +4 -11
- package/dist/src/internal/nitro/host/channel-routes.js +3 -3
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +3 -3
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
- package/dist/src/internal/nitro/host/dev-runner.js +1 -1
- package/dist/src/internal/nitro/host/dev-workspace-extensions.js +1 -1
- package/dist/src/internal/nitro/host/extension-capability-requirements.js +1 -1
- package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.js +1 -1
- package/dist/src/internal/nitro/host/nitro-bundler-config.js +1 -1
- package/dist/src/internal/nitro/host/start-development-server.js +2 -2
- package/dist/src/internal/nitro/host/start-production-server.js +2 -2
- package/dist/src/internal/nitro/host/vercel-build-output-config.js +1 -1
- package/dist/src/internal/process/pnpm.js +1 -1
- package/dist/src/internal/workflow/development-world-client.js +1 -1
- package/dist/src/internal/workflow/development-world-server.js +1 -1
- package/dist/src/internal/workflow-bundle/builder-support.d.ts +12 -8
- package/dist/src/internal/workflow-bundle/builder-support.js +8 -7
- package/dist/src/internal/workflow-bundle/builder.d.ts +1 -1
- package/dist/src/internal/workflow-bundle/builder.js +2 -3
- package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
- package/dist/src/public/channels/discord/discordChannel.d.ts +2 -0
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/eve.d.ts +2 -0
- package/dist/src/public/channels/eve.js +1 -1
- package/dist/src/public/channels/github/dispatch.js +1 -1
- package/dist/src/public/channels/github/githubChannel.d.ts +2 -0
- package/dist/src/public/channels/linear/linearChannel.d.ts +2 -0
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/photon/photonIMessageChannel.d.ts +2 -0
- package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +3 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.d.ts +2 -0
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.d.ts +2 -0
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/channels/twilio/twilioChannel.d.ts +2 -0
- package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
- package/dist/src/public/instrumentation/index.d.ts +9 -3
- package/dist/src/public/next/server.js +1 -1
- package/dist/src/public/nuxt/dev-server.js +1 -1
- package/dist/src/public/sveltekit/dev-server.js +1 -1
- package/dist/src/react/use-eve-agent.d.ts +4 -4
- package/dist/src/react/use-eve-agent.js +1 -1
- package/dist/src/services/inspect-application.js +1 -1
- package/dist/src/setup/primitives/pm/pnpm.js +2 -2
- package/dist/src/setup/primitives/run-vercel.js +1 -1
- package/dist/src/setup/scaffold/create/extension.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +8 -86
- package/dist/src/setup/scaffold/version-tokens.js +1 -1
- package/dist/src/setup/scaffold/workspace-root.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.d.ts +3 -3
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tracing/install-instrumentation-runtime.d.ts +2 -1
- package/dist/src/tracing/install-instrumentation-runtime.js +1 -1
- package/dist/src/tracing/otel-declaration.d.ts +32 -3
- package/dist/src/tracing/otel-declaration.js +1 -1
- package/dist/src/tracing/otel-registration.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.d.ts +3 -3
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/custom.mdx +1 -1
- package/docs/channels/discord.mdx +1 -1
- package/docs/channels/eve.mdx +1 -2
- package/docs/channels/github.mdx +1 -1
- package/docs/channels/linear.mdx +1 -1
- package/docs/channels/overview.mdx +1 -1
- package/docs/channels/photon.mdx +1 -1
- package/docs/channels/slack.mdx +1 -1
- package/docs/channels/teams.mdx +1 -1
- package/docs/channels/telegram.mdx +1 -1
- package/docs/channels/twilio.mdx +1 -1
- package/docs/extensions.md +10 -6
- package/docs/guides/client/streaming.mdx +6 -5
- package/docs/guides/frontend/overview.mdx +10 -8
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +10 -10
- package/docs/guides/frontend/use-eve-agent-vue.mdx +10 -10
- package/docs/install-integrations.mdx +4 -0
- package/docs/reference/cli.md +1 -1
- package/docs/schedules.mdx +2 -2
- package/package.json +1 -1
- package/dist/src/compiled/_chunks/workflow/chunk-5MU5Z6L3-CaJgXkVg.js +0 -1
- package/dist/src/compiled/_chunks/workflow/sleep-CzdoBiqy.js +0 -1
- package/dist/src/compiled/_chunks/workflow/src-Cj3P1ChQ.js +0 -1
- package/dist/src/compiled/_chunks/workflow/token-util-DNwIAn_u.js +0 -27
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const WEB_APP_TEMPLATE_FILES: {
|
|
2
2
|
readonly "agent/channels/eve.ts": 'import { eveChannel } from "eve/channels/eve";\nimport { localDev, placeholderAuth, vercelOidc } from "eve/channels/auth";\n\nexport default eveChannel({\n auth: [\n // Lets the eve TUI and your Vercel deployments reach the deployed agent.\n vercelOidc(),\n // Open on localhost for `eve dev` and the REPL; ignored in production.\n localDev(),\n // This placeholder will not allow browser requests in production.\n // Replace it with your app\'s auth provider, like Auth.js or Clerk,\n // or use none() for a public demo.\n placeholderAuth(),\n ],\n});\n';
|
|
3
|
-
readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport type { UserContent } from "ai";\nimport {
|
|
3
|
+
readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport type { UserContent } from "ai";\nimport { useEveAgent } from "eve/react";\nimport { AlertCircleIcon } from "lucide-react";\nimport { useState } from "react";\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from "@/components/ai-elements/conversation";\nimport {\n PromptInput,\n type PromptInputMessage,\n PromptInputSubmit,\n PromptInputTextarea,\n} from "@/components/ai-elements/prompt-input";\nimport { cn } from "@/lib/utils";\nimport { AgentMessage } from "./agent-message";\n\nconst AGENT_NAME = "__EVE_INIT_APP_NAME__";\n\ntype AgentStatus = ReturnType<typeof useEveAgent>["status"];\n\nexport function AgentChat() {\n const [cancellationError, setCancellationError] = useState<string>();\n const agent = useEveAgent();\n const isBusy = agent.status === "submitted" || agent.status === "streaming";\n const isEmpty = agent.data.messages.length === 0;\n const errorMessage = cancellationError ?? agent.error?.message;\n\n const requestCancellation = () => {\n setCancellationError(undefined);\n void agent.cancel().catch((error: unknown) => {\n setCancellationError(toErrorMessage(error));\n });\n };\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const text = message.text.trim();\n if ((text.length === 0 && message.files.length === 0) || isBusy) return;\n\n setCancellationError(undefined);\n\n if (message.files.length === 0) {\n await agent.send(text);\n return;\n }\n\n const parts: UserContent = [];\n if (text.length > 0) {\n parts.push({ text, type: "text" });\n }\n for (const file of message.files) {\n parts.push({\n data: file.url,\n filename: file.filename,\n mediaType: file.mediaType,\n type: "file",\n });\n }\n\n await agent.send(parts);\n };\n\n const composer = (\n <PromptInput onSubmit={handleSubmit}>\n <PromptInputTextarea placeholder="Send a message…" />\n <PromptInputSubmit onStop={requestCancellation} status={agent.status} />\n </PromptInput>\n );\n\n return (\n <main className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">\n {isEmpty ? null : (\n <header className="flex h-14 shrink-0 items-center justify-center gap-3 pl-4 pr-2">\n <span className="flex min-w-0 items-center gap-2">\n <span className="truncate text-muted-foreground text-sm">{AGENT_NAME}</span>\n <StatusDot status={agent.status} />\n </span>\n </header>\n )}\n\n {errorMessage ? (\n <div className="mx-auto w-full max-w-3xl shrink-0 px-4 pt-2 sm:px-6">\n <div className="flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5 text-sm">\n <AlertCircleIcon className="mt-0.5 size-4 shrink-0 text-destructive" />\n <div>\n <p className="font-medium">Request failed</p>\n <p className="mt-0.5 text-muted-foreground">{errorMessage}</p>\n </div>\n </div>\n </div>\n ) : null}\n\n {isEmpty ? null : (\n <Conversation className="min-h-0 flex-1">\n <ConversationContent className="mx-auto w-full max-w-3xl gap-6 px-4 py-6 sm:px-6">\n {agent.data.messages.map((message, index) => (\n <AgentMessage\n canRespond={!isBusy}\n isStreaming={\n agent.status === "streaming" && index === agent.data.messages.length - 1\n }\n key={message.id}\n message={message}\n onInputResponses={(inputResponses) => {\n setCancellationError(undefined);\n return agent.respond(inputResponses);\n }}\n />\n ))}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n )}\n\n <div\n className={cn(\n "mx-auto w-full px-4 sm:px-6",\n isEmpty\n ? "flex max-w-xl flex-1 flex-col items-center justify-center gap-8 pb-[10vh]"\n : "max-w-3xl shrink-0 pb-6",\n )}\n >\n {isEmpty ? (\n <div className="flex flex-col items-center gap-3 text-center">\n <h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1>\n </div>\n ) : null}\n <div className="w-full">{composer}</div>\n </div>\n </main>\n );\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : "Unable to cancel the response.";\n}\n\nfunction StatusDot({ status }: { readonly status: AgentStatus }) {\n const isLive = status === "submitted" || status === "streaming";\n const tone =\n status === "error"\n ? "bg-destructive"\n : isLive\n ? "bg-emerald-500"\n : status === "ready"\n ? "bg-muted-foreground"\n : "bg-muted-foreground/50";\n\n return (\n <span className="relative flex size-1">\n {isLive ? (\n <span\n className={cn(\n "absolute inline-flex size-full animate-ping rounded-full opacity-75",\n tone,\n )}\n />\n ) : null}\n <span className={cn("relative inline-flex size-1 rounded-full transition-colors", tone)} />\n </span>\n );\n}\n';
|
|
4
4
|
readonly "app/_components/agent-message.tsx": '"use client";\n\nimport type {\n EveAuthorizationPart,\n EveDynamicToolPart,\n EveMessage,\n EveMessagePart,\n} from "eve/react";\nimport {\n CheckCircleIcon,\n ExternalLinkIcon,\n FileIcon,\n ImageIcon,\n KeyRoundIcon,\n XCircleIcon,\n} from "lucide-react";\nimport { Message, MessageContent, MessageResponse } from "@/components/ai-elements/message";\nimport { Reasoning, ReasoningContent, ReasoningTrigger } from "@/components/ai-elements/reasoning";\nimport {\n Tool,\n ToolContent,\n ToolHeader,\n ToolInput,\n ToolOutput,\n} from "@/components/ai-elements/tool";\nimport { Button } from "@/components/ui/button";\nimport { cn } from "@/lib/utils";\n\nexport type AgentInputResponse = {\n readonly optionId?: string;\n readonly requestId: string;\n readonly text?: string;\n};\n\ntype EveFilePart = Extract<EveMessagePart, { type: "file" }>;\n\nexport function AgentMessage({\n canRespond,\n isStreaming,\n message,\n onInputResponses,\n}: {\n readonly canRespond: boolean;\n readonly isStreaming: boolean;\n readonly message: EveMessage;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n}) {\n const lastTextIndex = message.parts.reduce(\n (last, part, index) => (part.type === "text" ? index : last),\n -1,\n );\n\n return (\n <Message\n data-optimistic={message.metadata?.optimistic ? "true" : undefined}\n from={message.role}\n >\n <MessageContent>\n {message.parts.map((part, index) => (\n <AgentMessagePart\n canRespond={canRespond}\n key={partKey(part, index)}\n onInputResponses={onInputResponses}\n part={part}\n showCaret={isStreaming && message.role === "assistant" && index === lastTextIndex}\n />\n ))}\n </MessageContent>\n </Message>\n );\n}\n\nfunction AgentMessagePart({\n canRespond,\n onInputResponses,\n part,\n showCaret,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveMessagePart;\n readonly showCaret: boolean;\n}) {\n switch (part.type) {\n case "step-start":\n return null;\n case "text":\n return (\n <MessageResponse caret="block" isAnimating={showCaret}>\n {part.text}\n </MessageResponse>\n );\n case "reasoning":\n return (\n <Reasoning defaultOpen isStreaming={part.state === "streaming"}>\n <ReasoningTrigger />\n <ReasoningContent>{part.text}</ReasoningContent>\n </Reasoning>\n );\n case "file":\n return <AttachmentPart part={part} />;\n case "authorization":\n return <AuthorizationPrompt part={part} />;\n case "dynamic-tool":\n return (\n <Tool\n defaultOpen={part.state === "approval-requested" || part.state === "approval-responded"}\n >\n <ToolHeader\n state={part.state}\n title={part.toolName}\n toolName={part.toolName}\n type="dynamic-tool"\n />\n <ToolContent>\n <ToolInput input={part.input} />\n <InputRequestActions\n canRespond={canRespond}\n part={part}\n onInputResponses={onInputResponses}\n />\n <ToolOutput errorText={part.errorText} output={part.output} />\n </ToolContent>\n </Tool>\n );\n }\n}\n\nfunction AttachmentPart({ part }: { readonly part: EveFilePart }) {\n const label = part.filename ?? "Attachment";\n const detail = [part.mediaType, formatBytes(part.size)].filter(Boolean).join(" - ");\n const isImage = part.mediaType.startsWith("image/") && part.url !== undefined;\n const Icon = isImage ? ImageIcon : FileIcon;\n const body = (\n <span className="flex max-w-sm items-center gap-3 rounded-md border bg-background/60 p-2 text-sm">\n {isImage ? (\n <img alt={label} className="size-12 shrink-0 rounded-sm object-cover" src={part.url} />\n ) : (\n <span className="flex size-10 shrink-0 items-center justify-center rounded-sm bg-muted text-muted-foreground">\n <Icon className="size-4" />\n </span>\n )}\n <span className="min-w-0 flex-1">\n <span className="block truncate font-medium">{label}</span>\n {detail ? <span className="block truncate text-muted-foreground">{detail}</span> : null}\n </span>\n {part.url ? <ExternalLinkIcon className="size-4 shrink-0 text-muted-foreground" /> : null}\n </span>\n );\n\n return part.url ? (\n <a href={part.url} rel="noreferrer" target="_blank">\n {body}\n </a>\n ) : (\n body\n );\n}\n\nfunction AuthorizationPrompt({ part }: { readonly part: EveAuthorizationPart }) {\n const isAuthorized = part.state === "completed" && part.outcome === "authorized";\n const isCompleted = part.state === "completed";\n const Icon = isAuthorized ? CheckCircleIcon : isCompleted ? XCircleIcon : KeyRoundIcon;\n const instructions = part.authorization?.instructions;\n const shouldShowInstructions = instructions !== undefined && instructions !== part.description;\n\n return (\n <div\n className={cn(\n "space-y-3 rounded-md border p-3",\n isAuthorized\n ? "border-emerald-500/30 bg-emerald-500/5"\n : isCompleted\n ? "border-destructive/30 bg-destructive/5"\n : "border-blue-500/30 bg-blue-500/5",\n )}\n >\n <div className="flex items-start gap-3">\n <span\n className={cn(\n "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full",\n isAuthorized\n ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"\n : isCompleted\n ? "bg-destructive/10 text-destructive"\n : "bg-blue-500/10 text-blue-700 dark:text-blue-300",\n )}\n >\n <Icon className="size-4" />\n </span>\n <div className="min-w-0 flex-1 space-y-2">\n <p className="font-medium text-sm">{authorizationTitle(part)}</p>\n <p className="text-muted-foreground text-sm">{authorizationDescription(part)}</p>\n {shouldShowInstructions ? (\n <p className="text-muted-foreground text-sm">{instructions}</p>\n ) : null}\n {part.state === "required" && part.authorization?.userCode ? (\n <div className="flex flex-wrap items-center gap-2 text-sm">\n <span className="text-muted-foreground">Code</span>\n <code className="rounded-md bg-background px-2 py-1 font-mono">\n {part.authorization.userCode}\n </code>\n </div>\n ) : null}\n {part.state === "required" && part.authorization?.url ? (\n <Button asChild size="sm">\n <a href={part.authorization.url} rel="noreferrer" target="_blank">\n <ExternalLinkIcon className="size-4" />\n Sign in with {part.displayName}\n </a>\n </Button>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n\nfunction authorizationTitle(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return `Connect ${part.displayName}`;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected`;\n }\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}`;\n}\n\nfunction authorizationDescription(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return part.description;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected.`;\n }\n const tail = part.reason !== undefined ? ` (${part.reason})` : "";\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}${tail}.`;\n}\n\nfunction formatAuthorizationOutcome(outcome: NonNullable<EveAuthorizationPart["outcome"]>): string {\n switch (outcome) {\n case "authorized":\n return "authorized";\n case "declined":\n return "declined";\n case "failed":\n return "failed";\n case "timed-out":\n return "timed out";\n }\n}\n\nfunction formatBytes(size: number | undefined): string | undefined {\n if (size === undefined) {\n return undefined;\n }\n if (size < 1024) {\n return `${size} B`;\n }\n if (size < 1024 * 1024) {\n return `${(size / 1024).toFixed(1)} KB`;\n }\n return `${(size / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction InputRequestActions({\n canRespond,\n onInputResponses,\n part,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveDynamicToolPart;\n}) {\n const inputRequest = part.toolMetadata?.eve?.inputRequest;\n if (!inputRequest) {\n return null;\n }\n\n const inputResponse = part.toolMetadata?.eve?.inputResponse;\n const selectedOption = inputRequest.options?.find(\n (option) => option.id === inputResponse?.optionId,\n );\n\n return (\n <div className="space-y-3 rounded-md border border-yellow-500/30 bg-yellow-500/5 p-3">\n <p className="text-muted-foreground text-sm">{inputRequest.prompt}</p>\n {inputResponse ? (\n <p className="font-medium text-sm">\n Responded: {selectedOption?.label ?? inputResponse.text ?? inputResponse.optionId}\n </p>\n ) : (\n <div className="flex flex-wrap gap-2">\n {inputRequest.options?.map((option) => (\n <Button\n disabled={!canRespond}\n key={option.id}\n onClick={() => {\n void onInputResponses([\n {\n optionId: option.id,\n requestId: inputRequest.requestId,\n },\n ]);\n }}\n size="sm"\n type="button"\n variant={option.style === "danger" ? "destructive" : "default"}\n >\n {option.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction partKey(part: EveMessagePart, index: number): string {\n switch (part.type) {\n case "authorization":\n return `authorization:${part.turnId}:${part.stepIndex}:${part.name}`;\n case "dynamic-tool":\n return part.toolCallId;\n default:\n return `${part.type}:${index}`;\n }\n}\n';
|
|
5
5
|
readonly "app/globals.css": '@import "tailwindcss";\n@source "../node_modules/streamdown/dist/*.js";\n\n@theme inline {\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n --font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;\n --font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;\n}\n\n:root {\n color-scheme: light;\n /* Soft neutral page with white elevated surfaces so cards/composer pop. */\n --background: oklch(0.971 0 0);\n --foreground: oklch(0.16 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.16 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.16 0 0);\n --primary: oklch(0.19 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --secondary: oklch(0.94 0 0);\n --secondary-foreground: oklch(0.19 0 0);\n --muted: oklch(0.94 0 0);\n --muted-foreground: oklch(0.6 0 0);\n --accent: oklch(0.94 0 0);\n --accent-foreground: oklch(0.19 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --border: oklch(0.916 0 0);\n --input: oklch(0.916 0 0);\n --ring: oklch(0.708 0 0);\n --radius: 0.625rem;\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n color-scheme: dark;\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.205 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.269 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --border: oklch(1 0 0 / 10%);\n --input: oklch(1 0 0 / 15%);\n --ring: oklch(0.556 0 0);\n }\n}\n\n* {\n border-color: var(--border);\n}\n\nhtml {\n height: 100%;\n}\n\nbody {\n min-height: 100%;\n margin: 0;\n background: var(--background);\n font-family: var(--font-sans);\n}\n\nbutton,\ninput,\ntextarea {\n font: inherit;\n}\n';
|
|
6
6
|
readonly "app/layout.tsx": 'import type { Metadata } from "next";\nimport { Geist, Geist_Mono } from "next/font/google";\nimport type { ReactNode } from "react";\nimport { TooltipProvider } from "@/components/ui/tooltip";\nimport { cn } from "@/lib/utils";\nimport "./globals.css";\n\nconst sans = Geist({\n variable: "--font-sans",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nconst mono = Geist_Mono({\n variable: "--font-mono",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nexport const metadata: Metadata = {\n title: "__EVE_INIT_APP_NAME__",\n description: "A Next.js starter for eve agents with AI Elements.",\n};\n\nexport default function RootLayout({ children }: { readonly children: ReactNode }) {\n return (\n <html className={cn(sans.variable, mono.variable)} lang="en">\n <body>\n <TooltipProvider>{children}</TooltipProvider>\n </body>\n </html>\n );\n}\n';
|
|
@@ -16,10 +16,9 @@ export default eveChannel({
|
|
|
16
16
|
`,"app/_components/agent-chat.tsx":`"use client";
|
|
17
17
|
|
|
18
18
|
import type { UserContent } from "ai";
|
|
19
|
-
import { Client, type MessageStreamEvent } from "eve/client";
|
|
20
19
|
import { useEveAgent } from "eve/react";
|
|
21
20
|
import { AlertCircleIcon } from "lucide-react";
|
|
22
|
-
import {
|
|
21
|
+
import { useState } from "react";
|
|
23
22
|
import {
|
|
24
23
|
Conversation,
|
|
25
24
|
ConversationContent,
|
|
@@ -37,103 +36,26 @@ import { AgentMessage } from "./agent-message";
|
|
|
37
36
|
const AGENT_NAME = "__EVE_INIT_APP_NAME__";
|
|
38
37
|
|
|
39
38
|
type AgentStatus = ReturnType<typeof useEveAgent>["status"];
|
|
40
|
-
type CancellationState = "idle" | "requested" | "cancelling";
|
|
41
|
-
|
|
42
|
-
type Cancellation = {
|
|
43
|
-
requested: boolean;
|
|
44
|
-
sentTurnId?: string;
|
|
45
|
-
turnId?: string;
|
|
46
|
-
};
|
|
47
39
|
|
|
48
40
|
export function AgentChat() {
|
|
49
|
-
const [client] = useState(() => new Client({ host: "" }));
|
|
50
|
-
const sessionIdRef = useRef<string | undefined>(undefined);
|
|
51
|
-
const cancellationRef = useRef<Cancellation>({ requested: false });
|
|
52
41
|
const [cancellationError, setCancellationError] = useState<string>();
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
const cancelTurn = useCallback(
|
|
56
|
-
(turnId: string) => {
|
|
57
|
-
const cancellation = cancellationRef.current;
|
|
58
|
-
if (!cancellation.requested || cancellation.sentTurnId === turnId) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
cancellation.sentTurnId = turnId;
|
|
63
|
-
setCancellationState("cancelling");
|
|
64
|
-
|
|
65
|
-
const sessionId = sessionIdRef.current;
|
|
66
|
-
if (sessionId === undefined) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
void client.sessions
|
|
71
|
-
.attach(sessionId)
|
|
72
|
-
.cancel({ turnId })
|
|
73
|
-
.catch((error: unknown) => {
|
|
74
|
-
if (cancellationRef.current !== cancellation) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
cancellation.requested = false;
|
|
79
|
-
cancellation.sentTurnId = undefined;
|
|
80
|
-
setCancellationError(toErrorMessage(error));
|
|
81
|
-
setCancellationState("idle");
|
|
82
|
-
});
|
|
83
|
-
},
|
|
84
|
-
[client],
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const handleEvent = useCallback(
|
|
88
|
-
(event: MessageStreamEvent) => {
|
|
89
|
-
if (event.type !== "turn.started") {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const cancellation = cancellationRef.current;
|
|
94
|
-
cancellation.turnId = event.data.turnId;
|
|
95
|
-
cancelTurn(event.data.turnId);
|
|
96
|
-
},
|
|
97
|
-
[cancelTurn],
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const agent = useEveAgent({
|
|
101
|
-
onEvent: handleEvent,
|
|
102
|
-
onSessionChange(session) {
|
|
103
|
-
sessionIdRef.current = session?.sessionId;
|
|
104
|
-
},
|
|
105
|
-
});
|
|
42
|
+
const agent = useEveAgent();
|
|
106
43
|
const isBusy = agent.status === "submitted" || agent.status === "streaming";
|
|
107
44
|
const isEmpty = agent.data.messages.length === 0;
|
|
108
45
|
const errorMessage = cancellationError ?? agent.error?.message;
|
|
109
|
-
const submitStatus = isBusy && cancellationState !== "idle" ? "submitted" : agent.status;
|
|
110
|
-
|
|
111
|
-
const prepareTurn = () => {
|
|
112
|
-
cancellationRef.current = { requested: false };
|
|
113
|
-
setCancellationError(undefined);
|
|
114
|
-
setCancellationState("idle");
|
|
115
|
-
};
|
|
116
46
|
|
|
117
47
|
const requestCancellation = () => {
|
|
118
|
-
if (!isBusy || cancellationState !== "idle") {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const cancellation = cancellationRef.current;
|
|
123
|
-
cancellation.requested = true;
|
|
124
48
|
setCancellationError(undefined);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
cancelTurn(cancellation.turnId);
|
|
129
|
-
}
|
|
49
|
+
void agent.cancel().catch((error: unknown) => {
|
|
50
|
+
setCancellationError(toErrorMessage(error));
|
|
51
|
+
});
|
|
130
52
|
};
|
|
131
53
|
|
|
132
54
|
const handleSubmit = async (message: PromptInputMessage) => {
|
|
133
55
|
const text = message.text.trim();
|
|
134
56
|
if ((text.length === 0 && message.files.length === 0) || isBusy) return;
|
|
135
57
|
|
|
136
|
-
|
|
58
|
+
setCancellationError(undefined);
|
|
137
59
|
|
|
138
60
|
if (message.files.length === 0) {
|
|
139
61
|
await agent.send(text);
|
|
@@ -159,7 +81,7 @@ export function AgentChat() {
|
|
|
159
81
|
const composer = (
|
|
160
82
|
<PromptInput onSubmit={handleSubmit}>
|
|
161
83
|
<PromptInputTextarea placeholder="Send a message…" />
|
|
162
|
-
<PromptInputSubmit onStop={requestCancellation} status={
|
|
84
|
+
<PromptInputSubmit onStop={requestCancellation} status={agent.status} />
|
|
163
85
|
</PromptInput>
|
|
164
86
|
);
|
|
165
87
|
|
|
@@ -198,7 +120,7 @@ export function AgentChat() {
|
|
|
198
120
|
key={message.id}
|
|
199
121
|
message={message}
|
|
200
122
|
onInputResponses={(inputResponses) => {
|
|
201
|
-
|
|
123
|
+
setCancellationError(undefined);
|
|
202
124
|
return agent.respond(inputResponses);
|
|
203
125
|
}}
|
|
204
126
|
/>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}function bareToken(e){return`__${e}__`}const NODE_ENGINE_TOKEN=bareToken(`NODE_ENGINE`),TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[versionToken(`EVE_PACKAGE_DEPENDENCY`)]:{kind:`eve-version`},[NODE_ENGINE_TOKEN]:{kind:`eve-node-engine`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`VERCEL_CONNECT`)]:{kind:`catalog`,packageName:`@vercel/connect`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`TYPESCRIPT`)]:{kind:`catalog`,packageName:`typescript`},[versionToken(`TYPES_REACT`)]:{kind:`catalog`,packageName:`@types/react`},[versionToken(`TYPES_REACT_DOM`)]:{kind:`catalog`,packageName:`@types/react-dom`}},resolvedTokens=new Map;function findEvePackageRoot(){let o=dirname(realpathSync(fileURLToPath(import.meta.url)));for(;;){let i=join(o,`package.json`);if(existsSync(i)&&JSON.parse(readFileSync(i,`utf8`)).name===`eve`)return o;let a=dirname(o);if(a===o)return;o=a}}function findWorkspaceManifest(r){let i=r;for(;;){let r=join(i,`pnpm-workspace.yaml`);if(existsSync(r))return r;let a=dirname(i);if(a===i)return;i=a}}function readCatalogVersion(e,t){let n=readFileSync(e,`utf8`).split(/\r?\n/),i=!1;for(let e of n){if(/^catalog:\s*$/.test(e)){i=!0;continue}if(!i)continue;if(/^\S/.test(e))break;let n=e.match(/^\s+(?:"([^"]+)"|([\w@/.-]+)):\s*"([^"]+)"/);if(n&&(n[1]??n[2])===t)return n[3]}}function resolveTokenFromDevTree(e){let i=TOKEN_SOURCES[e];if(i!==void 0)try{let e=findEvePackageRoot();if(e===void 0||!existsSync(join(e,`scripts/stamp-version-tokens.mjs`)))return;if(i.kind===`eve-version`){let n=JSON.parse(readFileSync(join(e,`package.json`),`utf8`));return typeof n.version==`string`?n.version:void 0}if(i.kind===`eve-node-engine`){let n=JSON.parse(readFileSync(join(e,`package.json`),`utf8`)).engines?.node;return typeof n==`string`?n:void 0}let a=findWorkspaceManifest(e);return a===void 0?void 0:readCatalogVersion(a,i.packageName)}catch{return}}function resolveVersionToken(e,t){if(!t.startsWith(`__`))return t;let n=resolvedTokens.get(t);if(n!==void 0)return n;let r=resolveTokenFromDevTree(t);if(r===void 0)throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`);return resolvedTokens.set(t,r),r}export{resolveVersionToken};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isPathInside,workspacePatternForProject,workspacePatternsClaimProject}from"./workspace-glob.js";import{ensurePnpmWorkspaceIncludesProject,findAncestorPnpmWorkspaceRoot}from"../primitives/pm/pnpm.js";import{getPackageManagerStrategy}from"../primitives/pm/index.js";import{patchPackageJson}from"./update/package-json.js";import{readFile,writeFile}from"node:fs/promises";import{
|
|
1
|
+
import{isPathInside,workspacePatternForProject,workspacePatternsClaimProject}from"./workspace-glob.js";import{ensurePnpmWorkspaceIncludesProject,findAncestorPnpmWorkspaceRoot}from"../primitives/pm/pnpm.js";import{getPackageManagerStrategy}from"../primitives/pm/index.js";import{patchPackageJson}from"./update/package-json.js";import{readFile,writeFile}from"node:fs/promises";import{dirname,join,resolve}from"node:path";import{existsSync,readFileSync}from"node:fs";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function packageJsonWorkspacePatterns(e){let t=e.workspaces;return Array.isArray(t)?t.filter(e=>typeof e==`string`):!isJsonObject(t)||!Array.isArray(t.packages)?[]:t.packages.filter(e=>typeof e==`string`)}function readPackageJsonWorkspacePatterns(e){let t=JSON.parse(readFileSync(e,`utf8`));if(!isJsonObject(t))return;let n=packageJsonWorkspacePatterns(t);return n.length===0?void 0:n}function findAncestorPackageJsonWorkspaceRoot(e){let t=dirname(resolve(e));for(;;){let e=join(t,`package.json`);if(existsSync(e))try{if(readPackageJsonWorkspacePatterns(e)!==void 0)return t}catch{}let n=dirname(t);if(n===t)return;t=n}}function findClaimingPackageJsonWorkspaceRoot(e){let t=findAncestorPackageJsonWorkspaceRoot(e);if(t===void 0)return;let r;try{r=readPackageJsonWorkspacePatterns(join(t,`package.json`))}catch{return}return r!==void 0&&workspacePatternsClaimProject(r,t,e)?t:void 0}function findPackageManagerWorkspaceRoot(e,t){switch(e){case`pnpm`:return findAncestorPnpmWorkspaceRoot(t);case`bun`:case`npm`:case`yarn`:return findAncestorPackageJsonWorkspaceRoot(t)}}function isPackageManagerWorkspaceMember(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n!==void 0&&resolve(n)!==resolve(t)}function workspaceRootPackageJsonPath(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n===void 0?void 0:join(n,`package.json`)}async function ensurePackageJsonWorkspaceIncludesProject(e){let n=findAncestorPackageJsonWorkspaceRoot(e);if(n===void 0||resolve(n)===resolve(e)||findClaimingPackageJsonWorkspaceRoot(e)===n)return;let r=join(n,`package.json`),i=JSON.parse(await readFile(r,`utf8`)),a=workspacePatternForProject(n,e);if(Array.isArray(i.workspaces))i.workspaces=[...i.workspaces,a];else if(isJsonObject(i.workspaces)&&Array.isArray(i.workspaces.packages))i.workspaces={...i.workspaces,packages:[...i.workspaces.packages,a]};else return;return await writeFile(r,`${JSON.stringify(i,null,2)}\n`,`utf8`),r}async function ensurePackageManagerWorkspaceIncludesProject(e,t){switch(e){case`pnpm`:{let e=findAncestorPnpmWorkspaceRoot(t);return e===void 0?void 0:await ensurePnpmWorkspaceIncludesProject(t)===`written`?join(e,`pnpm-workspace.yaml`):void 0}case`bun`:case`npm`:case`yarn`:return ensurePackageJsonWorkspaceIncludesProject(t)}}function packageManagerRootOnlyPackageJsonPatch(e,t){let n={};if(t.nodeEngineRequirement!==void 0&&(n.nodeEngineRequirement=t.nodeEngineRequirement),t.aiPackageVersion!==void 0)switch(e){case`bun`:case`npm`:n.overrides={ai:t.aiPackageVersion};break;case`yarn`:n.resolutions={ai:t.aiPackageVersion};break;case`pnpm`:break}return n}async function patchWorkspaceRootPackageJson(e,t,n){if(!isPackageManagerWorkspaceMember(e,t))return{changed:!1};let r=workspaceRootPackageJsonPath(e,t);if(r===void 0||!existsSync(r))return{changed:!1};let i=await patchPackageJson(r,packageManagerRootOnlyPackageJsonPatch(e,n));return i.changed&&await n.onWorkspaceRootMutation?.({kind:`package-json`,nodeEngineOverride:i.nodeEngineOverride,path:r}),{...i,path:r}}async function applyPackageManagerWorkspaceConfiguration(t){let n=resolve(t.workspaceProbeRoot??t.projectRoot),r=t.packageManager===`pnpm`?void 0:await ensurePackageManagerWorkspaceIncludesProject(t.packageManager,n),i=await getPackageManagerStrategy(t.packageManager).applyProjectConfiguration(t.projectRoot,{workspaceProbeRoot:n}),o=[...r===void 0?[]:[r],...i.filesWritten],s=[...i.filesSkipped];for(let n of o)isPathInside(t.projectRoot,n)||await t.onWorkspaceRootMutation?.({kind:`workspace-config`,path:n});return{filesSkipped:s,filesWritten:o}}export{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson};
|
package/dist/src/svelte/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { type EveAgentStoreCallbacks, type EveAgentStoreSnapshot, type EveAgentS
|
|
|
3
3
|
import { type EveMessageData } from "#client/message-reducer.js";
|
|
4
4
|
import type { EveAgentReducer } from "#client/reducer.js";
|
|
5
5
|
import type { ClientSession } from "#client/session.js";
|
|
6
|
-
import type { ClientAuth, HeadersValue, RespondTurnOptions, SendTurnOptions, ClientSessionState } from "#client/types.js";
|
|
6
|
+
import type { CancelSessionResult, ClientAuth, HeadersValue, RespondTurnOptions, SendTurnOptions, ClientSessionState } from "#client/types.js";
|
|
7
7
|
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
8
8
|
export type { PrepareSend };
|
|
9
9
|
/**
|
|
@@ -26,6 +26,8 @@ export type UseEveAgentSnapshot<TData> = EveAgentStoreSnapshot<TData>;
|
|
|
26
26
|
* new events.
|
|
27
27
|
*/
|
|
28
28
|
export interface UseEveAgentReturn<TData> {
|
|
29
|
+
/** Request durable cancellation of the active turn while continuing to receive its events. */
|
|
30
|
+
readonly cancel: () => Promise<CancelSessionResult>;
|
|
29
31
|
/** Projected state built by reducing every stream event through the reducer. */
|
|
30
32
|
readonly data: TData;
|
|
31
33
|
/** Last transport-level error, or `undefined` when healthy. */
|
|
@@ -42,8 +44,6 @@ export interface UseEveAgentReturn<TData> {
|
|
|
42
44
|
readonly session: ClientSessionState | undefined;
|
|
43
45
|
/** Lifecycle phase: `"ready"` (idle), `"submitted"` (request sent, awaiting first event), `"streaming"` (events arriving), or `"error"`. */
|
|
44
46
|
readonly status: UseEveAgentStatus;
|
|
45
|
-
/** Abort the in-flight request. */
|
|
46
|
-
readonly stop: () => void;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* Configuration for a Svelte eve agent session.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type InstrumentationProviderDefinition } from "#harness/instrumentation/lifecycle.js";
|
|
2
2
|
import { type InstrumentationRuntime } from "#harness/instrumentation/runtime.js";
|
|
3
|
-
import type { CollectedOtel } from "#tracing/otel-declaration.js";
|
|
3
|
+
import type { CollectedOtel, RuntimeContextResolver } from "#tracing/otel-declaration.js";
|
|
4
4
|
/**
|
|
5
5
|
* Installs the process instrumentation runtime around a collected pipeline.
|
|
6
6
|
*
|
|
@@ -15,5 +15,6 @@ export declare function installInstrumentationRuntime(input: {
|
|
|
15
15
|
readonly collected: CollectedOtel;
|
|
16
16
|
readonly frameworkVersion: string;
|
|
17
17
|
readonly providers: readonly InstrumentationProviderDefinition[];
|
|
18
|
+
readonly runtimeContextResolvers?: readonly RuntimeContextResolver[];
|
|
18
19
|
readonly serviceName: string;
|
|
19
20
|
}): InstrumentationRuntime;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,formatError}from"#internal/logging.js";import{ContextAgentTraceStateStore}from"#tracing/agent-trace-context-store.js";import{registerInstrumentationRuntime}from"#harness/instrumentation/runtime.js";import{trace}from"#compiled/@opentelemetry/api/index.js";import{createInstrumentationHooks}from"#harness/instrumentation/lifecycle.js";import{hasSessionRelease}from"#tracing/local-traces.js";import{createAgentOtelInstrumentation}from"#tracing/agent-otel-provider.js";import{registerOtelPipeline}from"#tracing/otel-registration.js";const log=createLogger(`tracing.install-instrumentation-runtime`);function installInstrumentationRuntime(e){let t=[],a=[],o,s,c,runInContext=(e,t)=>t();if(e.collected.declared){o=registerOtelPipeline({pipeline:e.collected.pipeline,serviceName:e.serviceName});let r=createAgentOtelInstrumentation({frameworkVersion:e.frameworkVersion,idGenerator:o.idGenerator,recordInputs:e.collected.settings.recordInputs,recordOutputs:e.collected.settings.recordOutputs,stateStore:new ContextAgentTraceStateStore,tracer:trace.getTracer(`eve.agent`,e.frameworkVersion)});t.push({...r.hook,stateNamespace:`internal:otel`}),s=r.prepareSessionTrace,c=r.prepareTurnTrace,runInContext=r.runInContext;let i=e.collected.pipeline.spanProcessors.filter(isSpanProcessor).filter(hasSessionRelease);i.length>0&&a.push(sessionReleaseProvider(i))}let l=[...t,...e.providers,...a],u;return registerInstrumentationRuntime({forceFlush:()=>settleAll([...o===void 0?[]:[o.forceFlush],...l.map(e=>()=>e.flush?.())]),hooks:createInstrumentationHooks({parallel:e.providers,serialAfter:a,serialBefore:t}),otelSettings:e.collected.declared?e.collected.settings:void 0,prepareSessionTrace:s,prepareTurnTrace:c,runInContext,shutdown:()=>(u??=settleAll([...o===void 0?[]:[o.shutdown],...l.map(e=>()=>e.shutdown?.())]),u)})}function isSpanProcessor(e){return e!==`auto`}function sessionReleaseProvider(e){let release=async t=>{await Promise.all(e.map(e=>e.releaseSession(t.sessionId)))};return{events:{"session.completed":release,"session.failed":release},name:`eve.session-release`,stateNamespace:`internal:session-release`}}async function settleAll(e){let n=await Promise.allSettled(e.map(async e=>e()));for(let e of n)e.status===`rejected`&&log.warn(`instrumentation drain failed`,{error:formatError(e.reason)})}export{installInstrumentationRuntime};
|
|
1
|
+
import{createLogger,formatError}from"#internal/logging.js";import{ContextAgentTraceStateStore}from"#tracing/agent-trace-context-store.js";import{registerInstrumentationRuntime}from"#harness/instrumentation/runtime.js";import{trace}from"#compiled/@opentelemetry/api/index.js";import{createInstrumentationHooks}from"#harness/instrumentation/lifecycle.js";import{hasSessionRelease}from"#tracing/local-traces.js";import{createAgentOtelInstrumentation}from"#tracing/agent-otel-provider.js";import{registerOtelPipeline}from"#tracing/otel-registration.js";const log=createLogger(`tracing.install-instrumentation-runtime`);function installInstrumentationRuntime(e){let t=[],a=[],o,s,c,runInContext=(e,t)=>t();if(e.collected.declared){o=registerOtelPipeline({pipeline:e.collected.pipeline,serviceName:e.serviceName});let r=createAgentOtelInstrumentation({frameworkVersion:e.frameworkVersion,idGenerator:o.idGenerator,recordInputs:e.collected.settings.recordInputs,recordOutputs:e.collected.settings.recordOutputs,stateStore:new ContextAgentTraceStateStore,tracer:trace.getTracer(`eve.agent`,e.frameworkVersion)});t.push({...r.hook,stateNamespace:`internal:otel`}),s=r.prepareSessionTrace,c=r.prepareTurnTrace,runInContext=r.runInContext;let i=e.collected.pipeline.spanProcessors.filter(isSpanProcessor).filter(hasSessionRelease);i.length>0&&a.push(sessionReleaseProvider(i))}let l=[...t,...e.providers,...a],u;return registerInstrumentationRuntime({forceFlush:()=>settleAll([...o===void 0?[]:[o.forceFlush],...l.map(e=>()=>e.flush?.())]),hooks:createInstrumentationHooks({parallel:e.providers,serialAfter:a,serialBefore:t}),otelSettings:e.collected.declared?e.collected.settings:void 0,prepareSessionTrace:s,prepareTurnTrace:c,runtimeContextResolvers:e.runtimeContextResolvers,runInContext,shutdown:()=>(u??=settleAll([...o===void 0?[]:[o.shutdown],...l.map(e=>()=>e.shutdown?.())]),u)})}function isSpanProcessor(e){return e!==`auto`}function sessionReleaseProvider(e){let release=async t=>{await Promise.all(e.map(e=>e.releaseSession(t.sessionId)))};return{events:{"session.completed":release,"session.failed":release},name:`eve.session-release`,stateNamespace:`internal:session-release`}}async function settleAll(e){let n=await Promise.allSettled(e.map(async e=>e()));for(let e of n)e.status===`rejected`&&log.warn(`instrumentation drain failed`,{error:formatError(e.reason)})}export{installInstrumentationRuntime};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { PropagatorOrName, SamplerOrName, SpanExporter, SpanProcessor, SpanProcessorOrName } from "#compiled/@vercel/otel/index.js";
|
|
2
2
|
import { type InstrumentationProvider } from "#public/instrumentation/provider.js";
|
|
3
|
+
import type { InstrumentationRuntimeContextInput } from "#public/instrumentation/index.js";
|
|
4
|
+
import type { JsonObject } from "#shared/json.js";
|
|
3
5
|
import type { ResolvedContentOptions } from "#tracing/content-attributes.js";
|
|
4
6
|
/**
|
|
5
7
|
* The process-wide OpenTelemetry settings, declared by `otel()`.
|
|
@@ -8,9 +10,11 @@ import type { ResolvedContentOptions } from "#tracing/content-attributes.js";
|
|
|
8
10
|
* one tracer provider, so it has one resource, one sampler, and one propagator
|
|
9
11
|
* set. Destinations are the plural half and live in `otelIntegration()`.
|
|
10
12
|
*
|
|
11
|
-
* `contextManager`
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* `contextManager` is deliberately absent: eve's span nesting depends on it.
|
|
14
|
+
* `instrumentations` is accepted so providers can opt into Node auto-
|
|
15
|
+
* instrumentations (e.g. `@opentelemetry/auto-instrumentations-node`); the
|
|
16
|
+
* packages patch modules eve already imported, so their effects are limited
|
|
17
|
+
* to code loaded after registration.
|
|
14
18
|
*/
|
|
15
19
|
export interface OtelOptions {
|
|
16
20
|
/**
|
|
@@ -38,6 +42,15 @@ export interface OtelOptions {
|
|
|
38
42
|
readonly sampler?: SamplerOrName;
|
|
39
43
|
/** Composed into one propagator. All inject; the first to extract wins. */
|
|
40
44
|
readonly propagators?: readonly PropagatorOrName[];
|
|
45
|
+
/**
|
|
46
|
+
* OpenTelemetry `Instrumentation` instances passed through to
|
|
47
|
+
* `registerOTel`. Use them to patch Node.js built-ins (HTTP, DNS, fs, etc.)
|
|
48
|
+
* for automatic spans around outbound work. Disabled by default because eve
|
|
49
|
+
* already imports the model SDK before registration, so patching cannot
|
|
50
|
+
* reach it — but code loaded after registration (tool modules, connection
|
|
51
|
+
* clients) will be instrumented.
|
|
52
|
+
*/
|
|
53
|
+
readonly instrumentations?: readonly unknown[];
|
|
41
54
|
}
|
|
42
55
|
/**
|
|
43
56
|
* What one destination records of the conversation itself.
|
|
@@ -60,6 +73,17 @@ export interface OtelIntegrationOptions extends ContentOptions {
|
|
|
60
73
|
readonly spanProcessors?: readonly SpanProcessor[];
|
|
61
74
|
/** Wrapped in eve's batching processor and appended after `spanProcessors`. */
|
|
62
75
|
readonly traceExporter?: SpanExporter;
|
|
76
|
+
/**
|
|
77
|
+
* Contributes runtime context that the AI SDK merges into telemetry spans
|
|
78
|
+
* for each model call. Child spans inherit the values, so a destination can
|
|
79
|
+
* stamp channel or auth identity onto every span in the turn.
|
|
80
|
+
*
|
|
81
|
+
* Synchronous: the harness collects from every destination before the model
|
|
82
|
+
* call, so a return that is not a plain object is dropped (warning-only).
|
|
83
|
+
* Keys beginning with `eve.` are reserved and dropped. Return `undefined`
|
|
84
|
+
* to contribute nothing.
|
|
85
|
+
*/
|
|
86
|
+
readonly runtimeContext?: (input: InstrumentationRuntimeContextInput) => JsonObject | undefined;
|
|
63
87
|
}
|
|
64
88
|
declare const OTEL_DECLARATION: unique symbol;
|
|
65
89
|
declare const OTEL_INTEGRATION: unique symbol;
|
|
@@ -76,6 +100,7 @@ export interface OtelIntegration extends InstrumentationProvider {
|
|
|
76
100
|
readonly [OTEL_INTEGRATION]: true;
|
|
77
101
|
/** Resolved from `ContentOptions`, so the union does not re-apply defaults. */
|
|
78
102
|
readonly content: ResolvedContentOptions;
|
|
103
|
+
readonly runtimeContext?: (input: InstrumentationRuntimeContextInput) => JsonObject | undefined;
|
|
79
104
|
readonly spanProcessors: readonly SpanProcessorOrName[];
|
|
80
105
|
}
|
|
81
106
|
/**
|
|
@@ -105,6 +130,7 @@ export declare function isOtelDeclaration(value: unknown): value is OtelDeclarat
|
|
|
105
130
|
export declare function isOtelIntegration(value: unknown): value is OtelIntegration;
|
|
106
131
|
/** The one pipeline a process can register. @internal */
|
|
107
132
|
export interface OtelPipeline {
|
|
133
|
+
readonly instrumentations?: readonly unknown[];
|
|
108
134
|
readonly propagators?: readonly PropagatorOrName[];
|
|
109
135
|
readonly resource?: Readonly<Record<string, unknown>>;
|
|
110
136
|
readonly sampler?: SamplerOrName;
|
|
@@ -123,6 +149,8 @@ export interface OtelHarnessSettings {
|
|
|
123
149
|
readonly recordOutputs?: boolean;
|
|
124
150
|
}
|
|
125
151
|
/** @internal */
|
|
152
|
+
export type RuntimeContextResolver = (input: InstrumentationRuntimeContextInput) => JsonObject | undefined;
|
|
153
|
+
/** @internal */
|
|
126
154
|
export interface CollectedOtel {
|
|
127
155
|
/**
|
|
128
156
|
* Whether anything declared OpenTelemetry. False means eve should leave the
|
|
@@ -130,6 +158,7 @@ export interface CollectedOtel {
|
|
|
130
158
|
*/
|
|
131
159
|
readonly declared: boolean;
|
|
132
160
|
readonly pipeline: OtelPipeline;
|
|
161
|
+
readonly runtimeContextResolvers: readonly RuntimeContextResolver[];
|
|
133
162
|
readonly settings: OtelHarnessSettings;
|
|
134
163
|
}
|
|
135
164
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PROVIDER}from"#public/instrumentation/provider.js";import{batchSpanProcessor}from"#tracing/batch-span-processor.js";import{contentFilteringProcessor}from"#tracing/content-span-processor.js";import{vercelRuntimeSpanProcessor}from"#tracing/vercel-runtime-span-exporter.js";const OTEL_DECLARATION=Symbol.for(`eve.instrumentation.otel`),OTEL_INTEGRATION=Symbol.for(`eve.instrumentation.otel-integration`);function otel(t={}){return{[OTEL_DECLARATION]:!0,[PROVIDER]:!0,options:t}}function otelIntegration(r={}){let i={recordInputs:r.recordInputs===!0,recordOutputs:r.recordOutputs===!0},o=r.spanProcessors??[],s=r.traceExporter===void 0?o:[...o,batchSpanProcessor(r.traceExporter)];return{[OTEL_INTEGRATION]:!0,[PROVIDER]:!0,content:i,spanProcessors:i.recordInputs&&i.recordOutputs?s:s.map(e=>contentFilteringProcessor(e,i))}}function agentRunsIntegration(t={}){let i=resolveContentOptions(t);return{[OTEL_INTEGRATION]:!0,[PROVIDER]:!0,content:i,spanProcessors:i.recordInputs&&i.recordOutputs?[`auto`]:[contentFilteringProcessor(vercelRuntimeSpanProcessor(),i)]}}function resolveContentOptions(e){return{recordInputs:e.recordInputs===!0,recordOutputs:e.recordOutputs===!0}}function isOtelDeclaration(e){return typeof e==`object`&&!!e&&e[OTEL_DECLARATION]===!0}function isOtelIntegration(e){return typeof e==`object`&&!!e&&e[OTEL_INTEGRATION]===!0}function collectOtelPipeline(e){let t=[],n,r
|
|
1
|
+
import{PROVIDER}from"#public/instrumentation/provider.js";import{batchSpanProcessor}from"#tracing/batch-span-processor.js";import{contentFilteringProcessor}from"#tracing/content-span-processor.js";import{vercelRuntimeSpanProcessor}from"#tracing/vercel-runtime-span-exporter.js";const OTEL_DECLARATION=Symbol.for(`eve.instrumentation.otel`),OTEL_INTEGRATION=Symbol.for(`eve.instrumentation.otel-integration`);function otel(t={}){return{[OTEL_DECLARATION]:!0,[PROVIDER]:!0,options:t}}function otelIntegration(r={}){let i={recordInputs:r.recordInputs===!0,recordOutputs:r.recordOutputs===!0},o=r.spanProcessors??[],s=r.traceExporter===void 0?o:[...o,batchSpanProcessor(r.traceExporter)];return{[OTEL_INTEGRATION]:!0,[PROVIDER]:!0,content:i,runtimeContext:r.runtimeContext,spanProcessors:i.recordInputs&&i.recordOutputs?s:s.map(e=>contentFilteringProcessor(e,i))}}function agentRunsIntegration(t={}){let i=resolveContentOptions(t);return{[OTEL_INTEGRATION]:!0,[PROVIDER]:!0,content:i,spanProcessors:i.recordInputs&&i.recordOutputs?[`auto`]:[contentFilteringProcessor(vercelRuntimeSpanProcessor(),i)]}}function resolveContentOptions(e){return{recordInputs:e.recordInputs===!0,recordOutputs:e.recordOutputs===!0}}function isOtelDeclaration(e){return typeof e==`object`&&!!e&&e[OTEL_DECLARATION]===!0}function isOtelIntegration(e){return typeof e==`object`&&!!e&&e[OTEL_INTEGRATION]===!0}function collectOtelPipeline(e){let t=[],n=[],r,i=!1,a=!1,o=!1;for(let s of e){if(isOtelIntegration(s)){i=!0,a||=s.content.recordInputs,o||=s.content.recordOutputs,t.push(...s.spanProcessors),s.runtimeContext!==void 0&&n.push(s.runtimeContext);continue}if(isOtelDeclaration(s)){if(r!==void 0)throw Error("Instrumentation declares `otel()` more than once. One process has one OpenTelemetry tracer provider, so it has one resource, one sampler, and one propagator set — declare them in a single `otel()`.");i=!0,r=s}}let s=r?.options??{};return{declared:i,pipeline:{instrumentations:s.instrumentations,propagators:s.propagators,resource:s.resource,sampler:s.sampler,spanProcessors:t},runtimeContextResolvers:n,settings:{functionId:s.functionId,recordInputs:a,recordOutputs:o,traceChannelRequests:s.traceChannelRequests===!0}}}export{agentRunsIntegration,collectOtelPipeline,isOtelDeclaration,isOtelIntegration,otel,otelIntegration,resolveContentOptions};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{context,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";import{AgentSpanIdGenerator}from"#tracing/agent-span-id-generator.js";const REGISTRATION_SPAN_NAME=`eve.otel.registration`,REPLAY_DEDUPLICATION_LIMIT=1e5;var RegistrationMarkerPropagator=class{#e=!1;extract(e){return e}fields(){return[]}inject(){this.#e=!0}isInstalled(){return this.#e=!1,propagation.inject(context.active(),{},{set:()=>{}}),this.#e}},PrivateSpanFilteringProcessor=class{endedSpans=new Set;forwardedSpans=new Set;pendingByParent=new Map;processors;startedSpans=new Set;constructor(e){this.processors=e}async forceFlush(){await Promise.all(this.processors.map(e=>e.forceFlush()))}onEnd(e){if(isRegistrationSpan(e))return;let t=spanIdentity(e);if(t!==void 0){if(this.endedSpans.has(t))return;if(this.endedSpans.size>=REPLAY_DEDUPLICATION_LIMIT){let e=this.endedSpans.values().next().value;e!==void 0&&this.endedSpans.delete(e)}this.endedSpans.add(t)}let n=parentIdentity(e);if(n!==void 0&&this.startedSpans.has(n)&&!this.forwardedSpans.has(n)){let t=this.pendingByParent.get(n)??[];t.push(e),this.pendingByParent.set(n,t);return}this.forward(e,t)}onStart(e,t){if(isRegistrationSpan(e))return;let n=spanIdentity(e);n!==void 0&&addBounded(this.startedSpans,n);for(let n of this.processors)n.onStart(e,t)}async shutdown(){await Promise.all(this.processors.map(e=>e.shutdown()))}forward(e,t){for(let t of this.processors)t.onEnd(e);if(t===void 0)return;addBounded(this.forwardedSpans,t);let n=this.pendingByParent.get(t);if(n!==void 0){this.pendingByParent.delete(t);for(let e of n)this.forward(e,spanIdentity(e))}}};function registerOtelPipeline(e){let{pipeline:t}=e,n=new AgentSpanIdGenerator,i=new RegistrationMarkerPropagator,a={attributes:t.resource,autoDetectResources:!1,idGenerator:
|
|
1
|
+
import{createRequire}from"node:module";import{context,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";import{AgentSpanIdGenerator}from"#tracing/agent-span-id-generator.js";const REGISTRATION_SPAN_NAME=`eve.otel.registration`,REPLAY_DEDUPLICATION_LIMIT=1e5,require=createRequire(import.meta.url);var RegistrationMarkerPropagator=class{#e=!1;extract(e){return e}fields(){return[]}inject(){this.#e=!0}isInstalled(){return this.#e=!1,propagation.inject(context.active(),{},{set:()=>{}}),this.#e}},PrivateSpanFilteringProcessor=class{endedSpans=new Set;forwardedSpans=new Set;pendingByParent=new Map;processors;startedSpans=new Set;constructor(e){this.processors=e}async forceFlush(){await Promise.all(this.processors.map(e=>e.forceFlush()))}onEnd(e){if(isRegistrationSpan(e))return;let t=spanIdentity(e);if(t!==void 0){if(this.endedSpans.has(t))return;if(this.endedSpans.size>=REPLAY_DEDUPLICATION_LIMIT){let e=this.endedSpans.values().next().value;e!==void 0&&this.endedSpans.delete(e)}this.endedSpans.add(t)}let n=parentIdentity(e);if(n!==void 0&&this.startedSpans.has(n)&&!this.forwardedSpans.has(n)){let t=this.pendingByParent.get(n)??[];t.push(e),this.pendingByParent.set(n,t);return}this.forward(e,t)}onStart(e,t){if(isRegistrationSpan(e))return;let n=spanIdentity(e);n!==void 0&&addBounded(this.startedSpans,n);for(let n of this.processors)n.onStart(e,t)}async shutdown(){await Promise.all(this.processors.map(e=>e.shutdown()))}forward(e,t){for(let t of this.processors)t.onEnd(e);if(t===void 0)return;addBounded(this.forwardedSpans,t);let n=this.pendingByParent.get(t);if(n!==void 0){this.pendingByParent.delete(t);for(let e of n)this.forward(e,spanIdentity(e))}}};function registerOtelPipeline(e){let{pipeline:t}=e,n=captureOptionalPeerTracerProxy(),r=new AgentSpanIdGenerator,i=new RegistrationMarkerPropagator,a={attributes:t.resource,autoDetectResources:!1,idGenerator:r,instrumentations:t.instrumentations??[],propagators:[...t.propagators??[`none`],i],serviceName:e.serviceName,spanProcessors:t.spanProcessors.map(e=>isSpanProcessor(e)?new PrivateSpanFilteringProcessor([e]):e)};registerOTel(t.sampler===void 0?a:{...a,traceSampler:t.sampler});let o=globalTracerUses(r),s=i.isInstalled();if((!o||!s)&&rollbackRegistration({ownsPropagator:s,ownsTracer:o}),!o)throw Error("eve could not register OpenTelemetry because another runtime already owns the global tracer provider. Remove the other `registerOTel` call, or move its exporters into eve's `otelIntegration({ spanProcessors: [...] })`.");if(!s)throw Error("eve could not register OpenTelemetry because another runtime already owns the global propagator. Remove the other global propagator registration and declare propagators through eve's `otel()` instead.");let c=runtimeTracerProvider();if(typeof c.forceFlush!=`function`||typeof c.shutdown!=`function`)throw rollbackRegistration({ownsPropagator:s,ownsTracer:o}),Error(`The registered OpenTelemetry tracer provider has no lifecycle methods.`);return n?.setDelegate(c),{forceFlush:()=>c.forceFlush(),idGenerator:r,shutdown:()=>c.shutdown()}}function captureOptionalPeerTracerProxy(){try{let e=require("@opentelemetry/api"),t=e.trace.getTracerProvider();return t instanceof e.ProxyTracerProvider?t:void 0}catch{return}}function rollbackRegistration(e){if(e.ownsPropagator&&propagation.disable(),!e.ownsTracer)return;let t=runtimeTracerProvider();if(typeof t.shutdown==`function`)try{t.shutdown().catch(()=>{})}catch{}trace.disable()}function runtimeTracerProvider(){let e=trace.getTracerProvider();return e.getDelegate?.()??e}function globalTracerUses(e){let t=e.allocateSpanId();return e.withSpanId(t,()=>trace.getTracer(`eve.registration`).startSpan(REGISTRATION_SPAN_NAME)).spanContext().spanId===t}function isRegistrationSpan(e){return typeof e==`object`&&!!e&&`name`in e&&e.name===REGISTRATION_SPAN_NAME}function spanIdentity(e){if(typeof e!=`object`||!e||!(`spanContext`in e)||typeof e.spanContext!=`function`)return;let t=e.spanContext();return typeof t.traceId==`string`&&typeof t.spanId==`string`?`${t.traceId}:${t.spanId}`:void 0}function parentIdentity(e){if(typeof e!=`object`||!e||!(`parentSpanContext`in e))return;let t=e.parentSpanContext;return typeof t?.traceId==`string`&&typeof t.spanId==`string`?`${t.traceId}:${t.spanId}`:void 0}function addBounded(e,t){if(e.size>=REPLAY_DEDUPLICATION_LIMIT){let t=e.values().next().value;t!==void 0&&e.delete(t)}e.add(t)}function isSpanProcessor(e){return e!==`auto`}export{registerOtelPipeline};
|
package/dist/src/vue/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import type { EveAgentReducer } from "#client/reducer.js";
|
|
|
5
5
|
import type { ClientSession } from "#client/session.js";
|
|
6
6
|
import { type EveMessageData } from "#client/message-reducer.js";
|
|
7
7
|
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
8
|
-
import type { ClientAuth, HeadersValue, RespondTurnOptions, SendTurnOptions, ClientSessionState } from "#client/types.js";
|
|
8
|
+
import type { CancelSessionResult, ClientAuth, HeadersValue, RespondTurnOptions, SendTurnOptions, ClientSessionState } from "#client/types.js";
|
|
9
9
|
export type { PrepareSend };
|
|
10
10
|
/**
|
|
11
11
|
* Lifecycle phase of a `useEveAgent` session: `"ready"` (idle), `"submitted"`
|
|
@@ -25,6 +25,8 @@ export type UseEveAgentSnapshot<TData> = EveAgentStoreSnapshot<TData>;
|
|
|
25
25
|
* Reactive return value from `useEveAgent`.
|
|
26
26
|
*/
|
|
27
27
|
export interface UseEveAgentReturn<TData> {
|
|
28
|
+
/** Request durable cancellation of the active turn while continuing to receive its events. */
|
|
29
|
+
readonly cancel: () => Promise<CancelSessionResult>;
|
|
28
30
|
/** Projected state: the reducer folds every stream event into this value. */
|
|
29
31
|
readonly data: ComputedRef<TData>;
|
|
30
32
|
/** Last transport-level error, or `undefined` when healthy. */
|
|
@@ -41,8 +43,6 @@ export interface UseEveAgentReturn<TData> {
|
|
|
41
43
|
readonly session: ComputedRef<ClientSessionState | undefined>;
|
|
42
44
|
/** Lifecycle phase: `"ready"` (idle), `"submitted"` (request sent, awaiting first event), `"streaming"` (events arriving), or `"error"`. */
|
|
43
45
|
readonly status: ComputedRef<UseEveAgentStatus>;
|
|
44
|
-
/** Abort the in-flight request. */
|
|
45
|
-
readonly stop: () => void;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* Configuration for creating or binding a Vue eve agent session.
|
package/docs/channels/custom.mdx
CHANGED
|
@@ -7,7 +7,7 @@ When eve doesn't ship a channel for your surface, you build one. Custom channels
|
|
|
7
7
|
|
|
8
8
|
## File location and identity
|
|
9
9
|
|
|
10
|
-
Custom channels live in `agent/channels/` at the root agent. Local subagents do not declare channels today.
|
|
10
|
+
Custom channels live in `agent/channels/` at the root agent or in an [extension](../extensions) mounted there. Local subagents do not declare channels today.
|
|
11
11
|
|
|
12
12
|
The channel file stem becomes the channel id, so `agent/channels/internal-webhook.ts` is addressed as `internal-webhook`. Export the channel definition as the module's default export.
|
|
13
13
|
|
|
@@ -56,7 +56,7 @@ Then configure the public `https://…/eve/v1/discord` route as the application'
|
|
|
56
56
|
|
|
57
57
|
### Dispatch
|
|
58
58
|
|
|
59
|
-
`onCommand(ctx, interaction)` decides whether to dispatch and under what `auth`. Return `{ auth }` to proceed
|
|
59
|
+
`onCommand(ctx, interaction)` decides whether to dispatch and under what `auth`. Return `{ auth }` to proceed, `null` to drop the interaction, or `title` alongside `auth` to set the title when the dispatch starts a run. By default, auth comes from the invoking user. Event handlers receive `(eventData, channel, ctx)`, with Discord platform handles on `channel.discord`:
|
|
60
60
|
|
|
61
61
|
```ts
|
|
62
62
|
import { discordChannel } from "eve/channels/discord";
|
package/docs/channels/eve.mdx
CHANGED
|
@@ -160,8 +160,7 @@ export default eveChannel({
|
|
|
160
160
|
});
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
-
`onMessage` must return an auth result. A successful canonical eve HTTP message
|
|
164
|
-
always dispatches and therefore always produces or continues a session.
|
|
163
|
+
`onMessage` must return an auth result. Return `title` alongside `auth` to set the title when the dispatch starts a run. A successful canonical eve HTTP message always dispatches and therefore always produces or continues a session.
|
|
165
164
|
|
|
166
165
|
## Clients
|
|
167
166
|
|
package/docs/channels/github.mdx
CHANGED
|
@@ -66,7 +66,7 @@ Point the GitHub App webhook URL at `https://<deployment>/eve/v1/github`. For co
|
|
|
66
66
|
|
|
67
67
|
### Dispatch
|
|
68
68
|
|
|
69
|
-
Inbound hooks return `{ auth }` to dispatch, or `null` to ignore. Use `defaultGitHubAuth(ctx)` to derive auth from the actor.
|
|
69
|
+
Inbound hooks return `{ auth }` to dispatch, or `null` to ignore. Return `title` alongside `auth` to set the title when the dispatch starts a run. Use `defaultGitHubAuth(ctx)` to derive auth from the actor.
|
|
70
70
|
|
|
71
71
|
```ts
|
|
72
72
|
import { defaultGitHubAuth, githubChannel } from "eve/channels/github";
|
package/docs/channels/linear.mdx
CHANGED
|
@@ -99,7 +99,7 @@ Event handlers receive `channel.linear`, which exposes `createActivity`, `listAc
|
|
|
99
99
|
|
|
100
100
|
## Custom hooks
|
|
101
101
|
|
|
102
|
-
Return `{ auth }` to dispatch, or `null` to acknowledge without waking the agent.
|
|
102
|
+
Return `{ auth }` to dispatch, or `null` to acknowledge without waking the agent. Return `title` alongside `auth` to set the title when the dispatch starts a run.
|
|
103
103
|
|
|
104
104
|
```ts
|
|
105
105
|
import { defaultLinearAuth, linearChannel } from "eve/channels/linear";
|
|
@@ -36,7 +36,7 @@ Each channel has its own provider terms, data flow, auth model, and user-consent
|
|
|
36
36
|
|
|
37
37
|
## Where channels live
|
|
38
38
|
|
|
39
|
-
Channel files live under `agent/channels/` in the root agent. The file stem is the channel id: `agent/channels/intake.ts` is addressed as `intake`.
|
|
39
|
+
Channel files live under `agent/channels/` in the root agent or come from an [extension](../extensions) mounted there. The file stem is the channel id: `agent/channels/intake.ts` is addressed as `intake`. An extension mount prefixes its contributed channel IDs but does not change their route paths. Local subagents do not declare channels.
|
|
40
40
|
|
|
41
41
|
```text
|
|
42
42
|
agent/
|
package/docs/channels/photon.mdx
CHANGED
|
@@ -29,7 +29,7 @@ steers its replacement turn.
|
|
|
29
29
|
|
|
30
30
|
Set `turnPolicy: "queue"` when every response should finish before Photon starts the next message.
|
|
31
31
|
|
|
32
|
-
Customize inbound dispatch with `onMessage`. Return `null` to ignore a message:
|
|
32
|
+
Customize inbound dispatch with `onMessage`. Return `null` to ignore a message, or return `title` alongside `auth` to set the title when the dispatch starts a run:
|
|
33
33
|
|
|
34
34
|
```ts
|
|
35
35
|
export default photonIMessageChannel({
|
package/docs/channels/slack.mdx
CHANGED
|
@@ -125,7 +125,7 @@ Check the delivery path in order so you can identify where a Slack event stops:
|
|
|
125
125
|
|
|
126
126
|
### Message hooks
|
|
127
127
|
|
|
128
|
-
Message hooks return `{ auth }` to dispatch, `null` to drop, or `{ auth, context }` to inject background into history.
|
|
128
|
+
Message hooks return `{ auth }` to dispatch, `null` to drop, or `{ auth, context }` to inject background into history. Return `title` alongside `auth` to set the title when the dispatch starts a run. When omitted, the title continues to use the triggering message text.
|
|
129
129
|
|
|
130
130
|
- `onMessage(ctx, message)` handles Slack `message` events. eve drops messages authored by the installed app before this hook runs, preventing self-reply loops. Messages from other bots remain visible; check `message.author?.isBot` when those should also be ignored. `ctx.isBotMentioned()` and `ctx.isSubscribed()` support mention and active-thread policies.
|
|
131
131
|
- `onAppMention(ctx, message)` handles only `app_mention` and takes precedence over `onMessage`. Its default derives workspace-scoped auth and posts `Thinking…`.
|
package/docs/channels/teams.mdx
CHANGED
|
@@ -26,7 +26,7 @@ By default the channel mounts at `POST /eve/v1/teams`. Point your Azure Bot or T
|
|
|
26
26
|
|
|
27
27
|
### Dispatch
|
|
28
28
|
|
|
29
|
-
The default `onMessage` handles two cases: personal-chat messages, and channel or group-chat messages that mention the bot directly. Ambient resource-specific-consent messages are dropped unless you override it. Before dispatch, eve strips the mention, adds a `<teams_context>` block, and scopes channel and group threads by root activity id (`replyToId ?? id`).
|
|
29
|
+
The default `onMessage` handles two cases: personal-chat messages, and channel or group-chat messages that mention the bot directly. Ambient resource-specific-consent messages are dropped unless you override it. Return `title` alongside `auth` to set the title when the dispatch starts a run. Before dispatch, eve strips the mention, adds a `<teams_context>` block, and scopes channel and group threads by root activity id (`replyToId ?? id`).
|
|
30
30
|
|
|
31
31
|
For example, use the contextual `isSubscribed()` helper to continue active threads without requiring another mention:
|
|
32
32
|
|
|
@@ -39,7 +39,7 @@ In a private chat, text, captions, photos, and documents all go through. Groups
|
|
|
39
39
|
|
|
40
40
|
Forum topics carry `message_thread_id` in the continuation token, so each topic stays on its own thread.
|
|
41
41
|
|
|
42
|
-
To customize auth or filtering, override `onMessage`. Group privacy mode itself lives in BotFather, not here.
|
|
42
|
+
To customize auth or filtering, override `onMessage`. Return `title` alongside `auth` to set the title when the dispatch starts a run. Group privacy mode itself lives in BotFather, not here.
|
|
43
43
|
|
|
44
44
|
### Delivery
|
|
45
45
|
|
package/docs/channels/twilio.mdx
CHANGED
|
@@ -40,7 +40,7 @@ Point your Twilio number's Messaging webhook at `/messages` and Voice webhook at
|
|
|
40
40
|
export default twilioChannel({ allowFrom: ["+15551234567", "+15557654321"] });
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
`onText` and `onVoiceTranscription` decide dispatch and `auth`. Return `{ auth }` to proceed,
|
|
43
|
+
`onText` and `onVoiceTranscription` decide dispatch and `auth`. Return `{ auth }` to proceed, `null` to drop the message, or `title` alongside `auth` to set the title when the dispatch starts a run. `onVoice` fires the moment a call comes in. Return `null` to reject it, or return an object to override the spoken prompt, language, `<Say voice>`, and speech-recognition options.
|
|
44
44
|
|
|
45
45
|
```ts
|
|
46
46
|
export default twilioChannel({
|