eve 0.29.2 → 0.29.4
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 +41 -0
- package/dist/src/acp/adapter.d.ts +43 -0
- package/dist/src/acp/adapter.js +1 -0
- package/dist/src/acp/line-limit.d.ts +3 -0
- package/dist/src/acp/line-limit.js +1 -0
- package/dist/src/acp/server.d.ts +24 -0
- package/dist/src/acp/server.js +1 -0
- package/dist/src/channel/types.d.ts +15 -0
- package/dist/src/chunks/{use-eve-agent-DaH3cf8K.js → use-eve-agent-8mofdZcO.js} +45 -10
- package/dist/src/chunks/{use-eve-agent-CyDt3Lny.js → use-eve-agent-bKJbH0k4.js} +45 -10
- package/dist/src/cli/acp/command.d.ts +22 -0
- package/dist/src/cli/acp/command.js +4 -0
- package/dist/src/cli/commands/agent-prompt/build-and-verify.md +4 -0
- package/dist/src/cli/commands/extension-init.js +1 -1
- package/dist/src/cli/commands/init-git.js +1 -1
- package/dist/src/cli/commands/init-repl.js +1 -1
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/integration-setup.d.ts +3 -7
- package/dist/src/cli/commands/integration-setup.js +1 -1
- package/dist/src/cli/commands/logs.js +2 -2
- package/dist/src/cli/commands/register-integration-commands.js +1 -1
- package/dist/src/cli/commands/register-registry-commands.js +1 -1
- package/dist/src/cli/commands/registry-project.js +1 -1
- package/dist/src/cli/commands/registry-setup-command.js +1 -1
- package/dist/src/cli/commands/registry.d.ts +15 -2
- package/dist/src/cli/commands/registry.js +1 -1
- package/dist/src/cli/commands/trace.d.ts +6 -23
- package/dist/src/cli/commands/trace.js +7 -5
- package/dist/src/cli/dev/command-options.d.ts +22 -0
- package/dist/src/cli/dev/diagnostic-dump.js +1 -1
- package/dist/src/cli/dev/diagnostic-sink.js +1 -1
- package/dist/src/cli/dev/local-server-cleanup.js +1 -1
- package/dist/src/cli/dev/local-server-process.js +1 -1
- package/dist/src/cli/dev/tui/blocks.js +1 -1
- package/dist/src/cli/dev/tui/clipboard.d.ts +17 -0
- package/dist/src/cli/dev/tui/clipboard.js +1 -0
- package/dist/src/cli/dev/tui/command-typeahead.js +1 -1
- package/dist/src/cli/dev/tui/prompt-commands.d.ts +3 -0
- package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
- package/dist/src/cli/dev/tui/remote-auth.d.ts +6 -3
- package/dist/src/cli/dev/tui/remote-auth.js +1 -1
- package/dist/src/cli/dev/tui/remote-connection-probe.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +6 -0
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/stream-format.d.ts +22 -0
- package/dist/src/cli/dev/tui/stream-format.js +2 -2
- package/dist/src/cli/dev/tui/terminal-background.d.ts +23 -0
- package/dist/src/cli/dev/tui/terminal-background.js +1 -0
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +3 -0
- package/dist/src/cli/dev/tui/terminal-renderer.js +12 -12
- package/dist/src/cli/dev/tui/test/mock-terminal.js +3 -3
- package/dist/src/cli/dev/tui/traces/trace-content.d.ts +35 -0
- package/dist/src/cli/dev/tui/traces/trace-content.js +2 -0
- package/dist/src/cli/dev/tui/traces/trace-conversation.d.ts +63 -0
- package/dist/src/cli/dev/tui/traces/trace-conversation.js +2 -0
- package/dist/src/cli/dev/tui/traces/trace-store.d.ts +27 -0
- package/dist/src/cli/dev/tui/traces/trace-store.js +1 -0
- package/dist/src/cli/dev/tui/traces/trace-surfaces.d.ts +40 -0
- package/dist/src/cli/dev/tui/traces/trace-surfaces.js +1 -0
- package/dist/src/cli/dev/tui/traces/trace-view.d.ts +55 -0
- package/dist/src/cli/dev/tui/traces/trace-view.js +2 -0
- package/dist/src/cli/dev/tui/traces/trace-viewer-session.d.ts +54 -0
- package/dist/src/cli/dev/tui/traces/trace-viewer-session.js +1 -0
- package/dist/src/cli/dev/tui/traces/trace-viewer-state.d.ts +110 -0
- package/dist/src/cli/dev/tui/traces/trace-viewer-state.js +1 -0
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/invoke/invoke.js +1 -1
- package/dist/src/cli/invoke/result.js +1 -1
- package/dist/src/cli/run.d.ts +3 -0
- package/dist/src/cli/run.js +3 -3
- package/dist/src/cli/ui/alt-screen.d.ts +42 -0
- package/dist/src/cli/ui/alt-screen.js +1 -0
- package/dist/src/cli/ui/terminal-text.d.ts +4 -3
- package/dist/src/cli/ui/terminal-text.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session.d.ts +15 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/types.d.ts +9 -0
- package/dist/src/compiled/.vendor-stamp.json +3 -1
- package/dist/src/compiled/@agentclientprotocol/sdk/LICENSE +191 -0
- package/dist/src/compiled/@agentclientprotocol/sdk/index.d.ts +1835 -0
- package/dist/src/compiled/@agentclientprotocol/sdk/index.js +65 -0
- package/dist/src/compiled/@agentclientprotocol/sdk/jsonrpc.d.ts +603 -0
- package/dist/src/compiled/@agentclientprotocol/sdk/schema/guards.gen.d.ts +199 -0
- package/dist/src/compiled/@agentclientprotocol/sdk/schema/index.d.ts +51 -0
- package/dist/src/compiled/@agentclientprotocol/sdk/schema/types.gen.d.ts +6118 -0
- package/dist/src/compiled/@agentclientprotocol/sdk/stream.d.ts +35 -0
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/LICENSE +21 -0
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/_spectrum-core.d.ts +3 -0
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/_spectrum-imessage.d.ts +2 -0
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.d.ts +496 -0
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +137 -0
- package/dist/src/compiled/@vercel/sandbox/index.js +13 -107
- package/dist/src/compiled/_chunks/node/auth-BS3UoyvT.js +2 -0
- package/dist/src/compiled/_chunks/node/compat-Dm2n85Mx.js +1 -0
- package/dist/src/compiled/_chunks/node/schemas-DtQwuPdM.js +65 -0
- package/dist/src/compiled/_chunks/node/undici-DWL_MYmT.js +95 -0
- package/dist/src/compiled/_chunks/node/version-Cztrk7z6.js +1 -0
- package/dist/src/compiled/shadcn-registry/index.js +461 -893
- package/dist/src/compiler/artifacts.js +1 -1
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/model-catalog.js +1 -1
- package/dist/src/compiler/normalize-sandbox.js +1 -1
- package/dist/src/compiler/workspace-resources.js +1 -1
- package/dist/src/context/keys.d.ts +3 -1
- package/dist/src/context/keys.js +1 -1
- package/dist/src/discover/project-source.js +1 -1
- package/dist/src/evals/cli/eval.js +2 -2
- package/dist/src/evals/loaders/json.js +1 -1
- package/dist/src/evals/loaders/yaml.js +1 -1
- package/dist/src/evals/runner/artifacts.js +1 -1
- package/dist/src/evals/runner/discover.js +1 -1
- package/dist/src/evals/runner/reporters/junit.js +1 -1
- package/dist/src/evals/session.js +1 -1
- package/dist/src/execution/delegated-parent-notification.js +1 -1
- package/dist/src/execution/delegated-parent-result.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker-cli.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker-templates.js +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash.js +1 -1
- package/dist/src/execution/sandbox/bindings/local-backend-utils.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-metadata.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-platform.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-templates.js +1 -1
- package/dist/src/execution/sandbox/development-cleanup.js +1 -1
- package/dist/src/execution/sandbox/glob-tool.js +3 -3
- package/dist/src/execution/sandbox/grep-tool.js +1 -1
- package/dist/src/execution/sandbox/read-file-tool.js +3 -3
- package/dist/src/execution/sandbox/require-sandbox.d.ts +3 -3
- package/dist/src/execution/sandbox/require-sandbox.js +1 -1
- package/dist/src/execution/sandbox/template-prewarm-lock.js +1 -1
- package/dist/src/execution/sandbox/write-file-tool.js +1 -1
- package/dist/src/execution/subagent-adapter-state.d.ts +39 -0
- package/dist/src/execution/subagent-adapter-state.js +1 -0
- package/dist/src/execution/subagent-adapter.d.ts +0 -34
- package/dist/src/execution/subagent-adapter.js +1 -1
- package/dist/src/execution/subagent-tool.d.ts +2 -1
- package/dist/src/execution/subagent-tool.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/attachment-staging.js +1 -1
- package/dist/src/harness/instrumentation-lifecycle.d.ts +18 -0
- package/dist/src/harness/instrumentation-native-events.d.ts +3 -1
- package/dist/src/harness/instrumentation-native-events.js +1 -1
- package/dist/src/harness/parent-lineage.d.ts +11 -0
- package/dist/src/harness/parent-lineage.js +1 -0
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/internal/application/build-profile.js +1 -1
- package/dist/src/internal/application/build-workspace.js +1 -1
- package/dist/src/internal/application/cache-metadata.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +8 -8
- package/dist/src/internal/application/optional-package-install.js +2 -2
- package/dist/src/internal/application/output-publication-artifacts.js +1 -1
- package/dist/src/internal/application/output-publication-journal.js +1 -1
- package/dist/src/internal/application/output-publication-lock.js +1 -1
- package/dist/src/internal/application/output-publication.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/production-compiler-artifacts.js +1 -1
- package/dist/src/internal/application/tsconfig-dependencies.js +1 -1
- package/dist/src/internal/authored-asset-import-plugin.js +1 -1
- package/dist/src/internal/authored-module-loader.js +3 -3
- package/dist/src/internal/authored-package-tsconfig-paths.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.js +1 -1
- 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/configure-nitro-routes.js +3 -3
- package/dist/src/internal/nitro/host/copy-host-middleware.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/cron-handler-route.js +1 -1
- package/dist/src/internal/nitro/host/dev-authored-rebuild-coordinator.js +1 -1
- package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
- package/dist/src/internal/nitro/host/dev-host-fingerprint.js +1 -1
- package/dist/src/internal/nitro/host/dev-host-workspace.js +1 -1
- package/dist/src/internal/nitro/host/dev-server-http.js +1 -1
- package/dist/src/internal/nitro/host/dev-server-state.js +1 -1
- package/dist/src/internal/nitro/host/dev-workspace-extensions.js +1 -1
- package/dist/src/internal/nitro/host/extension-build-config.js +1 -1
- package/dist/src/internal/nitro/host/extension-declarations.js +2 -2
- package/dist/src/internal/nitro/host/extension-distribution.js +3 -3
- package/dist/src/internal/nitro/host/extension-state-usage.js +1 -1
- package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.js +1 -1
- package/dist/src/internal/nitro/host/normalize-vercel-service-crons.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/types.d.ts +2 -0
- package/dist/src/internal/vercel/project-link.js +1 -1
- package/dist/src/internal/workflow/development-world-client.js +1 -1
- package/dist/src/internal/workflow-bundle/builder-support.js +6 -6
- package/dist/src/internal/workflow-bundle/builder.js +3 -3
- package/dist/src/internal/workflow-bundle/nitro-step-entry.js +2 -2
- package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
- package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +7 -0
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/discord/verify.js +1 -1
- package/dist/src/public/channels/github/auth.js +2 -2
- package/dist/src/public/channels/github/githubChannel.js +1 -1
- package/dist/src/public/channels/github/verify.js +1 -1
- package/dist/src/public/channels/linear/inbound.js +2 -2
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/linear/verify.js +1 -1
- package/dist/src/public/channels/photon/inboundContent.d.ts +4 -0
- package/dist/src/public/channels/photon/inboundContent.js +1 -0
- package/dist/src/public/channels/photon/index.d.ts +1 -0
- package/dist/src/public/channels/photon/index.js +1 -0
- package/dist/src/public/channels/photon/photonIMessageChannel.d.ts +54 -0
- package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -0
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/verify.js +1 -1
- package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
- package/dist/src/public/models/openai/chatgpt/auth.js +1 -1
- package/dist/src/public/next/server.js +2 -2
- package/dist/src/public/next/vercel-output-config.js +1 -1
- package/dist/src/public/nuxt/dev-server.js +1 -1
- package/dist/src/public/nuxt/vercel-services.js +1 -1
- package/dist/src/public/sveltekit/dev-server.js +1 -1
- package/dist/src/public/sveltekit/vercel-json.js +1 -1
- package/dist/src/runtime/channels/registry.js +1 -1
- package/dist/src/runtime/framework-tools/file-state.js +1 -1
- package/dist/src/runtime/framework-tools/glob.js +1 -1
- package/dist/src/runtime/framework-tools/grep.js +1 -1
- package/dist/src/runtime/framework-tools/read-file.js +1 -1
- package/dist/src/runtime/framework-tools/write-file.js +1 -1
- package/dist/src/runtime/sandbox/keys.js +1 -1
- package/dist/src/runtime/workspace/seed-files.js +1 -1
- package/dist/src/setup/boxes/detect-ai-gateway.js +1 -1
- package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
- package/dist/src/setup/connect-provisioning.d.ts +32 -0
- package/dist/src/setup/connect-provisioning.js +1 -0
- package/dist/src/setup/flows/login.js +1 -1
- package/dist/src/setup/flows/registry.js +1 -1
- package/dist/src/setup/index.d.ts +1 -0
- package/dist/src/setup/index.js +1 -1
- package/dist/src/setup/integrations/discord/api.d.ts +15 -0
- package/dist/src/setup/integrations/discord/api.js +1 -0
- package/dist/src/setup/integrations/discord/connect.d.ts +24 -0
- package/dist/src/setup/integrations/discord/connect.js +1 -0
- package/dist/src/setup/integrations/discord/setup.d.ts +19 -0
- package/dist/src/setup/integrations/discord/setup.js +8 -0
- package/dist/src/setup/integrations/photon/connect.d.ts +40 -0
- package/dist/src/setup/integrations/photon/connect.js +1 -0
- package/dist/src/setup/integrations/photon/management.d.ts +34 -0
- package/dist/src/setup/integrations/photon/management.js +1 -0
- package/dist/src/setup/integrations/photon/setup-flow.d.ts +39 -0
- package/dist/src/setup/integrations/photon/setup-flow.js +20 -0
- package/dist/src/setup/integrations/photon/setup.d.ts +3 -0
- package/dist/src/setup/integrations/photon/setup.js +1 -0
- package/dist/src/setup/integrations/registry.d.ts +6 -0
- package/dist/src/setup/integrations/registry.js +1 -0
- package/dist/src/setup/integrations/runner.d.ts +25 -0
- package/dist/src/setup/integrations/runner.js +1 -0
- package/dist/src/setup/integrations/{channels → shared}/environment.d.ts +3 -3
- package/dist/src/setup/integrations/shared/environment.js +1 -0
- package/dist/src/setup/integrations/shared/scaffold.d.ts +19 -0
- package/dist/src/setup/integrations/shared/scaffold.js +1 -0
- package/dist/src/setup/integrations/{channels → shared}/ui.d.ts +3 -3
- package/dist/src/setup/integrations/shared/ui.js +2 -0
- package/dist/src/setup/integrations/slack/setup.d.ts +16 -0
- package/dist/src/setup/integrations/slack/setup.js +1 -0
- package/dist/src/setup/integrations/types.d.ts +26 -0
- package/dist/src/setup/integrations/types.js +1 -0
- package/dist/src/setup/integrations/web/setup.d.ts +3 -0
- package/dist/src/setup/integrations/web/setup.js +1 -0
- package/dist/src/setup/package-manager.js +1 -1
- package/dist/src/setup/primitives/pm/pnpm.js +3 -3
- package/dist/src/setup/primitives/run-vercel.d.ts +2 -7
- package/dist/src/setup/primitives/run-vercel.js +1 -1
- package/dist/src/setup/project-resolution.js +1 -1
- package/dist/src/setup/prompter.js +1 -1
- package/dist/src/setup/registry-setup-client.d.ts +6 -2
- package/dist/src/setup/registry-setup-client.js +1 -1
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/extension.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +3 -10
- package/dist/src/setup/scaffold/files.js +1 -1
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/setup/scaffold/update/connections.js +1 -1
- package/dist/src/setup/scaffold/workspace-root.js +1 -1
- package/dist/src/setup/slack-connect-lifecycle.d.ts +2 -8
- package/dist/src/setup/slack-connect-lifecycle.js +1 -1
- package/dist/src/setup/state.d.ts +0 -12
- package/dist/src/setup/state.js +1 -1
- package/dist/src/setup/vercel-project-framework.js +1 -1
- package/dist/src/shared/guards.d.ts +2 -0
- package/dist/src/shared/guards.js +1 -1
- package/dist/src/shared/skill-package.js +1 -1
- package/dist/src/shared/skill-paths.d.ts +14 -4
- package/dist/src/shared/skill-paths.js +2 -2
- package/dist/src/shared/vercel-output-directory.js +1 -1
- package/dist/src/source-change/static-source-change.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tracing/agent-otel-content.d.ts +32 -0
- package/dist/src/tracing/agent-otel-content.js +4 -0
- package/dist/src/{harness → tracing}/agent-otel-provider.d.ts +10 -1
- package/dist/src/tracing/agent-otel-provider.js +2 -0
- package/dist/src/{harness → tracing}/agent-trace-context-store.d.ts +8 -1
- package/dist/src/tracing/agent-trace-context-store.js +1 -0
- package/dist/src/{harness → tracing}/agent-trace-span-processor.d.ts +5 -1
- package/dist/src/tracing/agent-trace-span-processor.js +1 -0
- package/dist/src/tracing/local-instrumentation-runtime.js +1 -0
- package/dist/src/tracing/local-trace-reader.d.ts +74 -0
- package/dist/src/tracing/local-trace-reader.js +1 -0
- package/dist/src/{harness → tracing}/local-trace-retention.js +1 -1
- package/dist/src/{harness → tracing}/local-trace-span-processor.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/chat-sdk.mdx +18 -1
- package/docs/channels/discord.mdx +30 -14
- package/docs/channels/meta.json +1 -0
- package/docs/channels/overview.mdx +1 -1
- package/docs/channels/photon.mdx +78 -0
- package/docs/concepts/default-harness.md +2 -0
- package/docs/guides/acp.md +91 -0
- package/docs/guides/client/streaming.mdx +24 -0
- package/docs/guides/dev-tui.md +20 -1
- package/docs/guides/instrumentation.md +8 -7
- package/docs/guides/meta.json +1 -0
- package/docs/reference/cli.md +12 -1
- package/docs/sandbox.mdx +1 -1
- package/package.json +8 -1
- package/dist/src/compiled/_chunks/node/auth-DMsLOrh7.js +0 -2
- package/dist/src/compiled/_chunks/node/version-BQBAL95V.js +0 -64
- package/dist/src/harness/agent-otel-provider.js +0 -1
- package/dist/src/harness/agent-trace-context-store.js +0 -1
- package/dist/src/harness/agent-trace-span-processor.js +0 -1
- package/dist/src/harness/local-instrumentation-runtime.js +0 -1
- package/dist/src/setup/integrations/channels/environment.js +0 -1
- package/dist/src/setup/integrations/channels/index.d.ts +0 -7
- package/dist/src/setup/integrations/channels/index.js +0 -1
- package/dist/src/setup/integrations/channels/runner.d.ts +0 -7
- package/dist/src/setup/integrations/channels/runner.js +0 -1
- package/dist/src/setup/integrations/channels/setup.d.ts +0 -130
- package/dist/src/setup/integrations/channels/setup.js +0 -2
- package/dist/src/setup/integrations/channels/slack.d.ts +0 -3
- package/dist/src/setup/integrations/channels/slack.js +0 -1
- package/dist/src/setup/integrations/channels/types.d.ts +0 -49
- package/dist/src/setup/integrations/channels/ui.js +0 -2
- package/dist/src/setup/integrations/channels/web.d.ts +0 -3
- package/dist/src/setup/integrations/channels/web.js +0 -1
- /package/dist/src/{setup/integrations/channels/types.js → cli/dev/command-options.js} +0 -0
- /package/dist/src/{harness → tracing}/local-instrumentation-runtime.d.ts +0 -0
- /package/dist/src/{harness → tracing}/local-trace-retention.d.ts +0 -0
- /package/dist/src/{harness → tracing}/local-trace-span-processor.d.ts +0 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { type SpanContext, type Tracer } from "#compiled/@opentelemetry/api/index.js";
|
|
2
2
|
import type { InstrumentationContextRunner, InstrumentationProviderDefinition, InstrumentationTurnTerminalEvent } from "#harness/instrumentation-lifecycle.js";
|
|
3
|
+
/** Sized so an ordinary session stays one trace and only an outsized one rolls. */
|
|
4
|
+
export declare const SESSION_WINDOW_TURN_LIMIT = 200;
|
|
3
5
|
export interface AgentSessionTraceState {
|
|
4
6
|
readonly agentName?: string;
|
|
5
7
|
readonly channelKind?: string;
|
|
6
8
|
readonly context: SpanContext;
|
|
7
|
-
readonly pendingStarted: boolean;
|
|
8
9
|
readonly rootSessionId: string;
|
|
10
|
+
readonly turnsInWindow: number;
|
|
11
|
+
readonly window: number;
|
|
9
12
|
}
|
|
10
13
|
export interface AgentTurnTraceState {
|
|
11
14
|
readonly context: SpanContext;
|
|
@@ -36,6 +39,12 @@ export declare class InMemoryAgentTraceStateStore implements AgentTraceStateStor
|
|
|
36
39
|
setTurn(sessionId: string, turnId: string, state: AgentTurnTraceState): void;
|
|
37
40
|
}
|
|
38
41
|
export interface AgentOtelInstrumentationInput {
|
|
42
|
+
/**
|
|
43
|
+
* Capture model prompts/responses and tool call inputs/outputs as span
|
|
44
|
+
* attributes. Content stays on the local machine — this provider only
|
|
45
|
+
* wires the dev-time local spool — but can be turned off per project.
|
|
46
|
+
*/
|
|
47
|
+
readonly captureContent?: boolean;
|
|
39
48
|
readonly frameworkVersion: string;
|
|
40
49
|
readonly stateStore: AgentTraceStateStore;
|
|
41
50
|
readonly tracer: Tracer;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{ROOT_CONTEXT,SpanStatusCode,context,trace}from"#compiled/@opentelemetry/api/index.js";import{contentAttribute,messagesContentAttribute,systemPromptAttribute,textContentAttribute,toolResultsContentAttribute}from"#tracing/agent-otel-content.js";const SESSION_WINDOW_TURN_LIMIT=200;var InMemoryAgentTraceStateStore=class{#e=new Map;#t=new Map;deleteSession(e){this.#e.delete(e)}deleteTurn(e,t){this.#t.delete(turnKey(e,t))}getSession(e){return this.#e.get(e)}getTurn(e,t){return this.#t.get(turnKey(e,t))}setSession(e,t){this.#e.set(e,t)}setTurn(e,t,n){this.#t.set(turnKey(e,t),n)}};function createAgentOtelInstrumentation(e){let t=e.captureContent??!0,l=new WeakMap,u=new WeakMap,onSessionStarted=async e=>{await ensureSessionContext(e)},onTurnStarted=async t=>{let n=advanceSessionWindow(t.sessionId,await ensureSessionContext({agentName:void 0,channelKind:void 0,parentTraceContext:t.parentTraceContext,rootSessionId:t.rootSessionId,sessionId:t.sessionId,type:`session.started`})),r=e.tracer.startSpan(`agent.turn`,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":n.agentName,...parentLineageAttributes(t.parentLineage),"agent.root.session.id":t.rootSessionId,"agent.session.id":t.sessionId,"agent.session.window":n.window,"agent.turn.id":t.turnId,"agent.turn.sequence":t.sequence}},contextFromSpanContext(n.context));r.addEvent(`turn.started`),await e.stateStore.setSession(t.sessionId,{...n,turnsInWindow:n.turnsInWindow+1}),await e.stateStore.setTurn(t.sessionId,t.turnId,{context:r.spanContext(),rootSessionId:t.rootSessionId,sequence:t.sequence}),r.end()},onAttemptStarted=async t=>{let n=await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId);if(n===void 0)return;let i=contextFromSpanContext(n.context),a=e.tracer.startSpan(`agent.step`,{attributes:{"agent.session.id":t.scope.sessionId,"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.root.session.id":t.scope.rootSessionId??t.scope.sessionId,"agent.step.attempt":t.scope.attemptIndex,"agent.step.index":t.scope.stepIndex,"agent.turn.id":t.scope.turnId,"agent.name":t.scope.functionId}},i);a.addEvent(`step.started`);let o=trace.setSpan(i,a),s=t.operation.operationId,c=e.tracer.startSpan(s,{attributes:{"gen_ai.operation.name":s,"gen_ai.provider.name":t.operation.provider,"gen_ai.request.model":t.operation.modelId}},o);u.set(t.scope,{operation:{context:trace.setSpan(o,c),name:s,span:c},step:{context:o,span:a}})},onAttemptTerminal=e=>{l.delete(e.scope);let t=u.get(e.scope);t!==void 0&&(t.step.span.addEvent(e.type===`attempt.completed`?`step.completed`:`step.failed`),e.type===`attempt.failed`&&(recordError(t.operation.span,e.error),recordError(t.step.span,e.error)),t.operation.span.end(),t.step.span.end(),u.delete(e.scope))},onTurnTerminal=async t=>{let n=await e.stateStore.getTurn(t.sessionId,t.turnId);n!==void 0&&await e.stateStore.setTurn(t.sessionId,t.turnId,{...n,terminal:{error:t.error,type:t.type}})},onSessionTransition=async t=>{if(t.turnId!==void 0){let n=await e.stateStore.getTurn(t.sessionId,t.turnId);if(n!==void 0){let r=e.tracer.startSpan(`agent.turn.terminal`,{attributes:{"agent.root.session.id":n.rootSessionId,"agent.session.id":t.sessionId,"agent.turn.id":t.turnId,"agent.turn.sequence":n.sequence}},contextFromSpanContext(n.context));n.terminal!==void 0&&(r.addEvent(n.terminal.type),n.terminal.type===`turn.failed`&&recordError(r,n.terminal.error)),r.addEvent(t.type),r.end(),await e.stateStore.deleteTurn(t.sessionId,t.turnId)}}(t.type===`session.completed`||t.type===`session.failed`)&&await e.stateStore.deleteSession(t.sessionId)},beforeModelCall=n=>{let i=u.get(n.scope);if(i===void 0)return;i.step.span.setAttribute(`agent.model.id`,n.source.modelId),i.step.span.setAttribute(`agent.model.provider`,n.source.provider);let s=e.tracer.startSpan(modelSpanName(i.operation.name),{attributes:{"gen_ai.operation.name":i.operation.name,"gen_ai.provider.name":n.source.provider,"gen_ai.request.model":n.source.modelId}},i.operation.context);if(t){let e=messagesContentAttribute(n.source.messages);e!==void 0&&s.setAttribute(`ai.prompt.messages`,e);let t=systemPromptAttribute(n.source.instructions);t!==void 0&&s.setAttribute(`ai.prompt.system`,t)}let c={context:trace.setSpan(i.operation.context,s),span:s};return getExecutionContexts(n.scope).models.set(n.id,c.context),c},afterModelCall=(e,n)=>{if(l.get(e.scope)?.models.delete(e.id),isSpanState(n)){if(e.type===`model.call.failed`)recordError(n.span,e.error);else{setUsage(n.span,e.source.usage);let r=u.get(e.scope);if(r!==void 0&&setUsage(r.step.span,e.source.usage),t){n.span.setAttribute(`ai.response.finish_reason`,e.source.finishReason);let t=textContentAttribute(e.source.content.filter(e=>e.type===`reasoning`).map(e=>e.text).filter(e=>e.trim().length>0).join(`
|
|
2
|
+
`));t!==void 0&&n.span.setAttribute(`ai.response.reasoning`,t);let r=textContentAttribute(e.source.content.filter(e=>e.type===`text`).map(e=>e.text).join(``));r!==void 0&&n.span.setAttribute(`ai.response.text`,r);let a=e.source.content.filter(e=>e.type===`tool-call`).map(e=>({input:e.input,toolName:e.toolName}));if(a.length>0){let e=contentAttribute(a,!1);e!==void 0&&n.span.setAttribute(`ai.response.tool_calls`,e)}let o=e.source.content.filter(e=>e.type===`tool-result`||e.type===`tool-error`).map(e=>e.type===`tool-result`?{input:e.input,output:e.output,toolName:e.toolName}:{error:errorText(e.error),input:e.input,toolName:e.toolName});if(o.length>0){let e=toolResultsContentAttribute(o);e!==void 0&&n.span.setAttribute(`ai.response.tool_results`,e)}}}n.span.end()}},beforeToolCall=n=>{let a=u.get(n.scope);if(a===void 0)return;let o=e.tracer.startSpan(`agent.action`,{attributes:{"agent.action.call_id":n.source.toolCall.toolCallId,"agent.action.kind":`tool`,"agent.action.name":n.source.toolCall.toolName,"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.root.session.id":n.scope.rootSessionId??n.scope.sessionId,"agent.session.id":n.scope.sessionId,"agent.step.attempt":n.scope.attemptIndex,"agent.step.index":n.scope.stepIndex,"agent.turn.id":n.scope.turnId}},a.step.context),s=trace.setSpan(a.step.context,o),c=e.tracer.startSpan(`ai.toolCall`,{attributes:{"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.call.id":n.source.toolCall.toolCallId,"gen_ai.tool.name":n.source.toolCall.toolName}},s);if(t){let e=contentAttribute(n.source.toolCall.input,!1);e!==void 0&&c.setAttribute(`gen_ai.tool.call.arguments`,e)}let l={context:trace.setSpan(s,c),span:o,toolSpan:c};return getExecutionContexts(n.scope).tools.set(n.id,l.context),l},afterToolCall=(e,n)=>{if(l.get(e.scope)?.tools.delete(e.id),isToolSpanState(n)){if(e.type===`tool.call.failed`)recordError(n.toolSpan,e.error),recordError(n.span,e.error);else if(e.source.toolOutput.type!==`tool-result`)recordError(n.toolSpan,e.source.toolOutput.error),recordError(n.span,e.source.toolOutput.error);else if(t){let t=contentAttribute(e.source.toolOutput.output,!1);t!==void 0&&n.toolSpan.setAttribute(`gen_ai.tool.call.result`,t)}n.toolSpan.end(),n.span.end()}},openSessionWindow=t=>{let n=e.tracer.startSpan(`agent.session`,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":t.agentName,"agent.root.session.id":t.rootSessionId,"agent.session.id":t.sessionId,"agent.session.window":t.index,...t.previousTraceId===void 0?{}:{"agent.session.window.previous.trace.id":t.previousTraceId}},root:!0});return n.addEvent(t.index===0?`session.started`:`session.window.opened`),n.end(),n.spanContext()},ensureSessionContext=async t=>{let n=await e.stateStore.getSession(t.sessionId);return n===void 0&&(n={agentName:t.agentName,channelKind:t.channelKind,context:t.parentTraceContext===void 0?openSessionWindow({agentName:t.agentName,index:0,rootSessionId:t.rootSessionId,sessionId:t.sessionId}):adoptedSpanContext(t.parentTraceContext),rootSessionId:t.rootSessionId,turnsInWindow:0,window:0},await e.stateStore.setSession(t.sessionId,n)),n},advanceSessionWindow=(e,t)=>{if(t.turnsInWindow<200)return t;let n=t.window+1;return{...t,context:openSessionWindow({agentName:t.agentName,index:n,previousTraceId:t.context.traceId,rootSessionId:t.rootSessionId,sessionId:e}),turnsInWindow:0,window:n}};return{hook:{events:{"attempt.completed":onAttemptTerminal,"attempt.failed":onAttemptTerminal,"attempt.metadata":e=>{let t=u.get(e.scope);if(t===void 0)return;let n=readGatewayCost(e.providerMetadata);if(n!==void 0)for(let[e,r]of Object.entries(n))t.step.span.setAttribute(e,r)},"attempt.started":onAttemptStarted,"model.call":{after:afterModelCall,before:beforeModelCall},"session.completed":onSessionTransition,"session.failed":onSessionTransition,"session.started":onSessionStarted,"session.waiting":onSessionTransition,"tool.call":{after:afterToolCall,before:beforeToolCall},"turn.cancelled":onTurnTerminal,"turn.completed":onTurnTerminal,"turn.failed":onTurnTerminal,"turn.started":onTurnStarted}},runInContext(e,t){let r=l.get(e.scope),i=e.type===`model.call`?r?.models.get(e.id):r?.tools.get(e.id);return i===void 0?t():context.with(i,t)}};function getExecutionContexts(e){let t=l.get(e);return t===void 0&&(t={models:new Map,tools:new Map},l.set(e,t)),t}}function turnKey(e,t){return`${e}:${t}`}function parentLineageAttributes(e){if(e===void 0)return{};let t={"agent.parent.call_id":e.callId,"agent.parent.session.id":e.sessionId,"agent.parent.turn.id":e.turnId};return e.subagentName!==void 0&&(t[`agent.subagent.name`]=e.subagentName),t}function adoptedSpanContext(e){return{isRemote:!1,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function contextFromSpanContext(t){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(t))}function readGatewayCost(e){let t=e.gateway;if(!isRecord(t))return;let n={},r=readUsd(t.cost);r!==void 0&&(n[`gen_ai.usage.cost`]=r);let i=readUsd(t.gatewayCost);i!==void 0&&(n[`gen_ai.usage.gateway_cost`]=i);let a=readUsd(t.inputInferenceCost);a!==void 0&&(n[`gen_ai.usage.input_cost`]=a);let o=readUsd(t.outputInferenceCost);return o!==void 0&&(n[`gen_ai.usage.output_cost`]=o),typeof t.generationId==`string`&&t.generationId.length>0&&(n[`gen_ai.generation.id`]=t.generationId),Object.keys(n).length===0?void 0:n}function readUsd(e){if(typeof e!=`string`)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function isSpanState(e){return typeof e==`object`&&!!e&&`context`in e&&`span`in e}function isToolSpanState(e){return isSpanState(e)&&`toolSpan`in e}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function modelSpanName(e){return e===`ai.generateText`?`ai.generateText.doGenerate`:`ai.streamText.doStream`}function setUsage(e,t){t.inputTokens!==void 0&&e.setAttribute(`agent.usage.input_tokens`,t.inputTokens),t.outputTokens!==void 0&&e.setAttribute(`agent.usage.output_tokens`,t.outputTokens);let n=t.inputTokenDetails;n?.cacheReadTokens!==void 0&&e.setAttribute(`gen_ai.usage.cache_read.input_tokens`,n.cacheReadTokens),n?.cacheWriteTokens!==void 0&&e.setAttribute(`gen_ai.usage.cache_creation.input_tokens`,n.cacheWriteTokens)}function errorText(e){return e instanceof Error?e.message:e}function recordError(e,n){n instanceof Error?(e.recordException(n),e.setStatus({code:SpanStatusCode.ERROR,message:n.message})):e.setStatus({code:SpanStatusCode.ERROR})}export{InMemoryAgentTraceStateStore,SESSION_WINDOW_TURN_LIMIT,createAgentOtelInstrumentation};
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SpanContext } from "#compiled/@opentelemetry/api/index.js";
|
|
2
|
+
import type { AgentSessionTraceState, AgentTraceStateStore, AgentTurnTraceState } from "#tracing/agent-otel-provider.js";
|
|
2
3
|
/** Keeps only framework trace state from an interrupted step's context changes. */
|
|
3
4
|
export declare function preserveSerializedAgentTraceState(original: Record<string, unknown>, interrupted: Record<string, unknown>): Record<string, unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* Reads a named session's trace window straight out of a serialized context,
|
|
7
|
+
* which {@link ContextAgentTraceStateStore} cannot do — its reads are scoped
|
|
8
|
+
* to the ambient session.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readSessionTraceContext(serializedContext: Readonly<Record<string, unknown>>, sessionId: string): SpanContext | undefined;
|
|
4
11
|
/** Durable trace state backed by eve's serialized Workflow context. */
|
|
5
12
|
export declare class ContextAgentTraceStateStore implements AgentTraceStateStore {
|
|
6
13
|
deleteSession(sessionId: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{contextStorage,loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";const AgentTraceContextKey=new ContextKey(`eve.harness.agentTrace`,{codec:{deserialize:deserializeState,serialize:serializeState}});function preserveSerializedAgentTraceState(e,t){let n=t[AgentTraceContextKey.name];return n===void 0?e:{...e,[AgentTraceContextKey.name]:n}}function readSessionTraceContext(e,t){let n=e[AgentTraceContextKey.name];if(n!==void 0)return deserializeState(n).sessions[t]?.context}var ContextAgentTraceStateStore=class{deleteSession(e){updateState(t=>{let n={...t.sessions};return delete n[e],{...t,sessions:n}})}deleteTurn(e,t){updateState(n=>{let r={...n.turns};return delete r[turnKey(e,t)],{...n,turns:r}})}getSession(t){return contextStorage.getStore()?.get(AgentTraceContextKey)?.sessions[t]}getTurn(t,n){return contextStorage.getStore()?.get(AgentTraceContextKey)?.turns[turnKey(t,n)]}setSession(e,t){updateState(n=>({...n,sessions:{...n.sessions,[e]:t}}))}setTurn(e,t,n){updateState(r=>({...r,turns:{...r.turns,[turnKey(e,t)]:n}}))}};function updateState(e){loadContext().set(AgentTraceContextKey,t=>e(t??{sessions:{},turns:{}}))}function turnKey(e,t){return`${e}\0${t}`}function serializeState(e){return{sessions:Object.fromEntries(Object.entries(e.sessions).map(([e,t])=>[e,{...t,context:serializeSpanContext(t.context)}])),turns:Object.fromEntries(Object.entries(e.turns).map(([e,t])=>[e,{...t,context:serializeSpanContext(t.context),terminal:t.terminal===void 0?void 0:{error:serializeError(t.terminal.error),type:t.terminal.type}}]))}}function deserializeState(e){return isRecord(e)?{sessions:deserializeRecord(e.sessions,e=>{if(!(!isRecord(e)||!isSpanContext(e.context)))return{agentName:typeof e.agentName==`string`?e.agentName:void 0,channelKind:typeof e.channelKind==`string`?e.channelKind:void 0,context:e.context,rootSessionId:typeof e.rootSessionId==`string`?e.rootSessionId:``,turnsInWindow:typeof e.turnsInWindow==`number`?e.turnsInWindow:0,window:typeof e.window==`number`?e.window:0}}),turns:deserializeRecord(e.turns,e=>{if(!(!isRecord(e)||!isSpanContext(e.context)))return{context:e.context,rootSessionId:typeof e.rootSessionId==`string`?e.rootSessionId:``,sequence:typeof e.sequence==`number`?e.sequence:0,terminal:deserializeTerminal(e.terminal)}})}:{sessions:{},turns:{}}}function deserializeRecord(e,t){if(!isRecord(e))return{};let n={};for(let[r,i]of Object.entries(e)){let e=t(i);e!==void 0&&(n[r]=e)}return n}function deserializeTerminal(e){if(!isRecord(e)||typeof e.type!=`string`)return;let t=e.type;if(isTurnTerminalType(t))return{error:deserializeError(e.error),type:t}}function serializeSpanContext(e){return{isRemote:e.isRemote,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function isSpanContext(e){return isRecord(e)&&typeof e.spanId==`string`&&typeof e.traceFlags==`number`&&typeof e.traceId==`string`}function serializeError(e){return e instanceof Error?{message:e.message,name:e.name,stack:e.stack}:void 0}function deserializeError(e){if(!isRecord(e)||typeof e.message!=`string`)return;let t=Error(e.message);return typeof e.name==`string`&&(t.name=e.name),typeof e.stack==`string`&&(t.stack=e.stack),t}function isTurnTerminalType(e){return e===`turn.cancelled`||e===`turn.completed`||e===`turn.failed`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{ContextAgentTraceStateStore,preserveSerializedAgentTraceState,readSessionTraceContext};
|
|
@@ -9,7 +9,11 @@ export declare class AgentTraceSpanProcessor implements SpanProcessor {
|
|
|
9
9
|
onEnd(span: unknown): void;
|
|
10
10
|
/** Trace ids whose session is still open, so retention never evicts them. */
|
|
11
11
|
activeTraceIds(): ReadonlySet<string>;
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Forgets every trace one root session owned, reporting whether it owned any.
|
|
14
|
+
* A subagent child owns none, so releasing one reports `false` and leaves the
|
|
15
|
+
* shared trace pinned until its root finishes.
|
|
16
|
+
*/
|
|
13
17
|
releaseSession(sessionId: string): boolean;
|
|
14
18
|
shutdown(): Promise<void>;
|
|
15
19
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var AgentTraceSpanProcessor=class{#e;#t=new Set;#n=new Map;#r=!1;constructor(e){this.#e=e}async forceFlush(){await Promise.all(this.#e.map(e=>e.forceFlush()))}isAttached(){return this.#r}onStart(e,t){if(this.#r=!0,!isSpanLike(e))return;let n=e.attributes[`agent.session.id`];if(typeof n==`string`){let t=e.attributes[`agent.root.session.id`],r=typeof t==`string`?t:n,i=e.spanContext().traceId;this.#t.add(i);let a=this.#n.get(r)??new Set;a.add(i),this.#n.set(r,a)}if(this.#i(e))for(let n of this.#e)n.onStart(e,t)}onEnd(e){if(!(!isSpanLike(e)||!this.#i(e)))for(let t of this.#e)t.onEnd(e)}activeTraceIds(){return this.#t}releaseSession(e){let t=this.#n.get(e);if(t===void 0)return!1;for(let e of t)this.#t.delete(e);return this.#n.delete(e),!0}async shutdown(){await Promise.all(this.#e.map(e=>e.shutdown()))}#i(e){return e.instrumentationScope?.name!==`workflow`&&this.#t.has(e.spanContext().traceId)}};function isSpanLike(e){return typeof e==`object`&&!!e&&`attributes`in e&&`spanContext`in e&&typeof e.spanContext==`function`}export{AgentTraceSpanProcessor};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ContextAgentTraceStateStore}from"#tracing/agent-trace-context-store.js";import{getInstrumentationRuntime,registerInstrumentationRuntime}from"#harness/instrumentation-runtime.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";import{createAgentOtelInstrumentation}from"#tracing/agent-otel-provider.js";import{AgentTraceSpanProcessor}from"#tracing/agent-trace-span-processor.js";import{createInstrumentationHooks}from"#harness/instrumentation-lifecycle.js";import{requestLocalTraceStorePrune,resolveLocalTraceRetentionSettings}from"#tracing/local-trace-retention.js";import{LocalTraceSpanProcessor}from"#tracing/local-trace-span-processor.js";function installLocalInstrumentationRuntime(t){let n=getInstrumentationRuntime();if(n!==void 0)return n;let r=resolveLocalTraceRetentionSettings(),i=new AgentTraceSpanProcessor(r.enabled?[new LocalTraceSpanProcessor(t.appRoot)]:[]);registerOTel({autoDetectResources:!1,instrumentations:[],propagators:[`none`],serviceName:t.serviceName,spanProcessors:[i]});let a=trace.getTracer(`eve.registration`).startSpan(`eve.otel.registration`),o=trace.setSpan(context.active(),a),s=context.with(o,()=>trace.getActiveSpan()===a);if(a.end(),!i.isAttached()||!s)throw Error(`eve could not register OpenTelemetry because another runtime already exists.`);let c=createAgentOtelInstrumentation({captureContent:process.env.EVE_TRACES_CONTENT!==`off`,frameworkVersion:t.frameworkVersion,stateStore:new ContextAgentTraceStateStore,tracer:trace.getTracer(`eve.agent`,t.frameworkVersion)}),l={events:{"session.completed":releaseSessionTrace,"session.failed":releaseSessionTrace}};return requestPrune(),registerInstrumentationRuntime({forceFlush:()=>i.forceFlush(),hooks:createInstrumentationHooks([c.hook,l]),runInContext:c.runInContext});async function releaseSessionTrace(e){await i.forceFlush(),i.releaseSession(e.sessionId)&&requestPrune()}function requestPrune(){r.enabled&&requestLocalTraceStorePrune({activeTraceIds:i.activeTraceIds(),appRoot:t.appRoot,maxAgeMs:r.maxAgeMs,maxTotalBytes:r.maxTotalBytes,retainCount:r.retainCount})}}export{installLocalInstrumentationRuntime};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the local trace spool written by {@link LocalTraceSpanProcessor}.
|
|
3
|
+
*
|
|
4
|
+
* The spool is the contract between the dev-time writer and every viewer
|
|
5
|
+
* (`eve traces`, the TUI trace viewer): one directory per trace under
|
|
6
|
+
* `.eve/traces/v1/<traceId>/segments/`, one immutable OTLP/JSON file per
|
|
7
|
+
* span. Parsing is defensive end to end — malformed or oversized segments
|
|
8
|
+
* are skipped so a partial write never breaks a view.
|
|
9
|
+
*/
|
|
10
|
+
export interface LocalTraceSpan {
|
|
11
|
+
readonly attributes: Readonly<Record<string, unknown>>;
|
|
12
|
+
readonly endTimeNs: bigint;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly parentSpanId?: string;
|
|
15
|
+
readonly scope?: string;
|
|
16
|
+
readonly spanId: string;
|
|
17
|
+
readonly startTimeNs: bigint;
|
|
18
|
+
readonly statusCode: number;
|
|
19
|
+
readonly traceId: string;
|
|
20
|
+
}
|
|
21
|
+
export interface LocalTrace {
|
|
22
|
+
readonly agentName?: string;
|
|
23
|
+
readonly endTimeNs: bigint;
|
|
24
|
+
/** Session that opened the trace, which is the one the list shows. */
|
|
25
|
+
readonly sessionId?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Every session recorded in the trace, opener first.
|
|
28
|
+
*
|
|
29
|
+
* A subagent child records into the window its parent had open, so one
|
|
30
|
+
* trace can hold several sessions and any of their ids resolves to it.
|
|
31
|
+
*/
|
|
32
|
+
readonly sessionIds: readonly string[];
|
|
33
|
+
readonly spans: readonly LocalTraceSpan[];
|
|
34
|
+
readonly startTimeNs: bigint;
|
|
35
|
+
readonly traceId: string;
|
|
36
|
+
/** Zero-based session window this trace holds, when the spans record one. */
|
|
37
|
+
readonly window?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Trace ids held by the spool, unordered. Empty when nothing has been written
|
|
41
|
+
* yet; any other read fault propagates.
|
|
42
|
+
*/
|
|
43
|
+
export declare function listLocalTraceIds(appRoot: string): Promise<string[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Instant one trace last received a span, or `undefined` once retention has
|
|
46
|
+
* pruned it. Reads the segments directory's mtime, so it stays cheap enough to
|
|
47
|
+
* poll a large spool without parsing any span.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readLocalTraceActivityMs(appRoot: string, traceId: string): Promise<number | undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* Segment file names of one trace in read order, or `undefined` when the trace
|
|
52
|
+
* is gone. Segments are immutable and named for their span, so the order is
|
|
53
|
+
* stable across reads and a caller can treat names it has seen as parsed.
|
|
54
|
+
*/
|
|
55
|
+
export declare function listLocalTraceSegments(appRoot: string, traceId: string): Promise<string[] | undefined>;
|
|
56
|
+
/**
|
|
57
|
+
* Spans held by one segment file. An oversized, unreadable, or malformed
|
|
58
|
+
* segment yields none, so a partial write never breaks a view.
|
|
59
|
+
*/
|
|
60
|
+
export declare function readLocalTraceSegment(appRoot: string, traceId: string, fileName: string): Promise<LocalTraceSpan[]>;
|
|
61
|
+
/** Reads valid local traces, newest first, while ignoring malformed segments. */
|
|
62
|
+
export declare function listLocalTraces(appRoot: string): Promise<LocalTrace[]>;
|
|
63
|
+
/** Sorts spans into timeline order: start, then end, then a stable tiebreak. */
|
|
64
|
+
export declare function compareLocalTraceSpans(left: LocalTraceSpan, right: LocalTraceSpan): number;
|
|
65
|
+
/** Builds a trace from already-parsed spans, deriving summary fields. */
|
|
66
|
+
export declare function assembleLocalTrace(traceId: string, spans: readonly LocalTraceSpan[]): LocalTrace;
|
|
67
|
+
/**
|
|
68
|
+
* Extracts short human-facing details from a span's structural attributes
|
|
69
|
+
* (turn id, step index/attempt, action kind/name, model id) for one-line
|
|
70
|
+
* span labels. Raw values — callers sanitize for their output surface.
|
|
71
|
+
*/
|
|
72
|
+
export declare function describeLocalTraceSpan(span: LocalTraceSpan): string[];
|
|
73
|
+
/** Parses one OTLP/JSON segment file into spans belonging to `expectedTraceId`. */
|
|
74
|
+
export declare function parseLocalTraceSegment(content: string, expectedTraceId: string): LocalTraceSpan[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readFile,readdir,stat}from"node:fs/promises";import{join}from"node:path";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#tracing/local-trace-span-processor.js";const TRACE_ID_PATTERN=/^[0-9a-f]{32}$/u,SPAN_FILE_PATTERN=/^[0-9a-f]{16}\.otlp\.json$/u;async function listLocalTraceIds(e){let n;try{n=await readdir(resolveLocalTraceSchemaDirectory(e),{withFileTypes:!0})}catch(e){if(isMissing(e))return[];throw e}return n.filter(e=>e.isDirectory()&&TRACE_ID_PATTERN.test(e.name)).map(e=>e.name)}async function readLocalTraceActivityMs(e,t){try{return(await stat(resolveLocalTraceSegmentsDirectory(e,t))).mtimeMs}catch(e){if(isMissing(e))return;throw e}}async function listLocalTraceSegments(e,n){let r;try{r=await readdir(resolveLocalTraceSegmentsDirectory(e,n),{withFileTypes:!0})}catch(e){if(isMissing(e))return;throw e}return r.filter(e=>e.isFile()&&SPAN_FILE_PATTERN.test(e.name)).map(e=>e.name).sort((e,t)=>e.localeCompare(t))}async function readLocalTraceSegment(t,i,o){let s=join(resolveLocalTraceSegmentsDirectory(t,i),o),c;try{if((await stat(s)).size>8388608)return[];c=await readFile(s,`utf8`)}catch{return[]}return parseLocalTraceSegment(c,i)}async function listLocalTraces(e){let t=[];for(let n of await listLocalTraceIds(e)){let r=await readLocalTrace(e,n).catch(()=>void 0);r!==void 0&&t.push(r)}return t.sort((e,t)=>e.startTimeNs===t.startTimeNs?e.traceId.localeCompare(t.traceId):e.startTimeNs>t.startTimeNs?-1:1)}async function readLocalTrace(e,t){let n=await listLocalTraceSegments(e,t);if(n===void 0)return;let r=new Map;for(let i of n)for(let n of await readLocalTraceSegment(e,t,i))r.has(n.spanId)||r.set(n.spanId,n);if(r.size!==0)return assembleLocalTrace(t,[...r.values()])}function compareLocalTraceSpans(e,t){return e.startTimeNs===t.startTimeNs?e.endTimeNs===t.endTimeNs?e.name.localeCompare(t.name)||e.spanId.localeCompare(t.spanId):e.endTimeNs<t.endTimeNs?-1:1:e.startTimeNs<t.startTimeNs?-1:1}function assembleLocalTrace(e,t){let n=[...t].sort(compareLocalTraceSpans),r=n.map(e=>e.attributes),i=distinctAttributes(r,`agent.session.id`);return{agentName:firstAttribute(r,`agent.name`),endTimeNs:n.reduce((e,t)=>t.endTimeNs>e?t.endTimeNs:e,0n),sessionId:i[0],sessionIds:i,spans:n,startTimeNs:n.reduce((e,t)=>t.startTimeNs<e?t.startTimeNs:e,n[0].startTimeNs),traceId:e,window:firstNumberAttribute(r,`agent.session.window`)}}function describeLocalTraceSpan(e){let t=[],n=stringSpanAttribute(e,`agent.turn.id`),r=valueSpanAttribute(e,`agent.step.index`),i=valueSpanAttribute(e,`agent.step.attempt`),a=stringSpanAttribute(e,`agent.action.kind`),o=stringSpanAttribute(e,`agent.action.name`),s=stringSpanAttribute(e,`agent.model.id`)??stringSpanAttribute(e,`gen_ai.request.model`);return e.name===`agent.turn`&&n!==void 0&&t.push(n),e.name===`agent.step`&&r!==void 0&&t.push(`step ${String(r)}${i===void 0?``:`, attempt ${String(i)}`}`),e.name===`agent.action`&&o!==void 0&&t.push(`${a??`action`}: ${o}`),s!==void 0&&e.name.includes(`do`)&&t.push(`model ${s}`),t}function parseLocalTraceSegment(e,t){try{let n=JSON.parse(e);if(!isRecord(n)||!Array.isArray(n.resourceSpans))return[];let r=[];for(let e of n.resourceSpans)if(!(!isRecord(e)||!Array.isArray(e.scopeSpans)))for(let n of e.scopeSpans){if(!isRecord(n)||!Array.isArray(n.spans))continue;let e=isRecord(n.scope)&&typeof n.scope.name==`string`?n.scope.name:void 0;for(let i of n.spans){let n=parseLocalTraceSpan(i,t,e);n!==void 0&&r.push(n)}}return r}catch{return[]}}function parseLocalTraceSpan(e,t,n){if(!isRecord(e)||e.traceId!==t||typeof e.spanId!=`string`||!/^[0-9a-f]{16}$/u.test(e.spanId)||typeof e.name!=`string`)return;let r=parseNanos(e.startTimeUnixNano),i=parseNanos(e.endTimeUnixNano);if(!(r===void 0||i===void 0||i<r))return{attributes:parseAttributes(e.attributes),endTimeNs:i,name:e.name,parentSpanId:typeof e.parentSpanId==`string`&&/^[0-9a-f]{16}$/u.test(e.parentSpanId)?e.parentSpanId:void 0,scope:n,spanId:e.spanId,startTimeNs:r,statusCode:parseStatusCode(e.status),traceId:t}}function parseAttributes(e){if(!Array.isArray(e))return{};let t={};for(let n of e){if(!isRecord(n)||typeof n.key!=`string`||!isRecord(n.value))continue;let e=parseAnyValue(n.value);e!==void 0&&(t[n.key]=e)}return t}function parseAnyValue(e){for(let t of[`stringValue`,`boolValue`,`intValue`,`doubleValue`])if(t in e)return e[t];if(isRecord(e.arrayValue)&&Array.isArray(e.arrayValue.values))return e.arrayValue.values.filter(isRecord).map(e=>parseAnyValue(e))}function parseNanos(e){if(!(typeof e!=`string`&&typeof e!=`number`))try{let t=BigInt(e);return t>=0n&&t<=18446744073709551615n?t:void 0}catch{return}}function parseStatusCode(e){return isRecord(e)?typeof e.code==`number`?e.code:e.code===`STATUS_CODE_ERROR`?2:0:0}function firstAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`string`&&e.length>0)return e}}function firstNumberAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`number`)return e;if(typeof e==`bigint`)return Number(e)}}function distinctAttributes(e,t){let n=new Set;for(let r of e){let e=r[t];typeof e==`string`&&e.length>0&&n.add(e)}return[...n]}function stringSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`?n:void 0}function valueSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`||typeof n==`number`?n:void 0}function isMissing(e){return e.code===`ENOENT`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{assembleLocalTrace,compareLocalTraceSpans,describeLocalTraceSpan,listLocalTraceIds,listLocalTraceSegments,listLocalTraces,parseLocalTraceSegment,readLocalTraceActivityMs,readLocalTraceSegment};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{
|
|
1
|
+
import{readdir,rm,stat}from"node:fs/promises";import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#tracing/local-trace-span-processor.js";const log=createLogger(`harness.local-trace-retention`),LOCAL_TRACE_QUIESCENCE_MS=300*1e3,LOCAL_TRACE_MAX_AGE_MS=10080*60*1e3,LOCAL_TRACE_MAX_TOTAL_BYTES=512*1024*1024;function resolveLocalTraceRetentionSettings(e=process.env){return{enabled:!isDisabled(e.EVE_TRACES),maxAgeMs:readBound(e,`EVE_TRACES_MAX_AGE_MS`,LOCAL_TRACE_MAX_AGE_MS),maxTotalBytes:readBound(e,`EVE_TRACES_MAX_TOTAL_BYTES`,LOCAL_TRACE_MAX_TOTAL_BYTES),retainCount:readBound(e,`EVE_TRACES_RETAIN_COUNT`,20)}}async function pruneLocalTraceStore(e){let n=e.now??Date.now(),r=clampBound(e.maxAgeMs??LOCAL_TRACE_MAX_AGE_MS),i=clampBound(e.maxTotalBytes??LOCAL_TRACE_MAX_TOTAL_BYTES),a=clampCount(e.retainCount??20),o=await readStoredTraces(e.appRoot,n),s=[...o].sort((e,t)=>t.modifiedAtMs-e.modifiedAtMs),c=new Set(s.slice(0,a===!1?0:a)),l=new Set,u=o.reduce((e,t)=>e+t.byteSize,0),d=0,f=0,p=0;for(let a of s.toReversed()){let o=n-a.modifiedAtMs,s=e.activeTraceIds.has(a.traceId)||c.has(a)||o<=LOCAL_TRACE_QUIESCENCE_MS?void 0:r!==!1&&o>r?`maxAgeMs`:i!==!1&&u>i?`maxTotalBytes`:void 0;if(s===void 0){p+=1;continue}await rm(a.path,{force:!0,recursive:!0}),u-=a.byteSize,d+=a.byteSize,f+=1,l.add(s)}return{reasons:[...l],reclaimedBytes:d,removedTraces:f,retainedTraces:p}}const pruneRequest={input:{activeTraceIds:new Set,appRoot:``},requested:!1,running:void 0};function requestLocalTraceStorePrune(e){pruneRequest.input=e,pruneRequest.requested=!0,pruneRequest.running===void 0&&startPruning()}function startPruning(){pruneRequest.running=(async()=>{for(;pruneRequest.requested;)pruneRequest.requested=!1,report(await pruneLocalTraceStore(pruneRequest.input))})().catch(e=>{log.warn(`local trace retention failed`,{error:formatError(e)})}).finally(()=>{pruneRequest.running=void 0,pruneRequest.requested&&startPruning()})}function report(e){e.removedTraces!==0&&log.info(`pruned local traces`,{reasons:e.reasons.join(`,`),reclaimedBytes:e.reclaimedBytes,removedTraces:e.removedTraces,retainedTraces:e.retainedTraces})}async function readStoredTraces(e,t){let n=resolveLocalTraceSchemaDirectory(e),r=await readDirectoryEntries(n);return r===void 0?[]:(await Promise.all(r.filter(e=>e.isDirectory()).map(async r=>{let i=join(n,r.name),o=resolveLocalTraceSegmentsDirectory(e,r.name);await reapAbandonedTemporaryFiles(o,t);let c=await directoryMtime(o)??await directoryMtime(i);if(c!==void 0)return{byteSize:await directorySize(i),modifiedAtMs:c,path:i,traceId:r.name}}))).filter(e=>e!==void 0)}async function reapAbandonedTemporaryFiles(e,r){let i=await readDirectoryEntries(e);if(i!==void 0)for(let o of i){if(!o.isFile()||!o.name.includes(`.tmp-`))continue;let i=join(e,o.name);try{if(r-(await stat(i)).mtimeMs<=LOCAL_TRACE_QUIESCENCE_MS)continue;await rm(i,{force:!0})}catch{}}}async function directoryMtime(e){try{return(await stat(e)).mtimeMs}catch{return}}async function directorySize(e){let t=await readDirectoryEntries(e);if(t===void 0)return 0;let r=0;for(let i of t){let t=join(e,i.name);if(i.isDirectory()){r+=await directorySize(t);continue}try{r+=(await stat(t)).size}catch{}}return r}async function readDirectoryEntries(t){try{return await readdir(t,{withFileTypes:!0})}catch(e){if(e instanceof Error&&`code`in e&&(e.code===`ENOENT`||e.code===`ENOTDIR`))return;throw e}}function isDisabled(e){if(e===void 0)return!1;let t=e.trim().toLowerCase();return t===`off`||t===`false`||t===`0`}function readBound(e,t,n){let r=e[t];if(r===void 0)return n;let i=r.trim().toLowerCase();if(i===`off`||i===`false`)return!1;let a=Number(i);return!Number.isFinite(a)||a<0?(log.warn(`ignoring invalid local trace retention value`,{fallback:n,name:t,value:r}),n):a}function clampBound(e){return e!==!1&&Math.max(0,e)}function clampCount(e){return e!==!1&&Math.max(0,Math.trunc(e))}export{pruneLocalTraceStore,requestLocalTraceStorePrune,resolveLocalTraceRetentionSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{
|
|
1
|
+
import{mkdir}from"node:fs/promises";import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{atomicWriteFile}from"#shared/atomic-write-file.js";import{JsonTraceSerializer}from"#compiled/@opentelemetry/otlp-transformer/index.js";const log=createLogger(`harness.local-trace-span-processor`);function resolveLocalTraceStoreDirectory(e){return join(e,`.eve`,`traces`)}function resolveLocalTraceSchemaDirectory(e){return join(resolveLocalTraceStoreDirectory(e),`v1`)}function resolveLocalTraceSegmentsDirectory(e,t){return join(resolveLocalTraceSchemaDirectory(e),t,`segments`)}var LocalTraceSpanProcessor=class{#e;#t=Promise.resolve();#n=!1;constructor(e){this.#e=e}forceFlush(){return this.#t}onStart(){}onEnd(t){if(!isReadableSpan(t))return;let{spanId:n,traceId:r}=t.spanContext();if(!isHexId(r,32)||!isHexId(n,16))return;let i=JsonTraceSerializer.serializeRequest([t]);i!==void 0&&(this.#t=this.#t.then(async()=>{let t=resolveLocalTraceSegmentsDirectory(this.#e,r);await mkdir(t,{recursive:!0}),await atomicWriteFile(join(t,`${n}.otlp.json`),i)}).catch(e=>{this.#n||(this.#n=!0,log.warn(`local trace persistence failed`,{error:formatError(e)}))}))}shutdown(){return this.forceFlush()}};function isReadableSpan(e){return typeof e==`object`&&!!e&&`attributes`in e&&`spanContext`in e&&typeof e.spanContext==`function`}function isHexId(e,t){return e.length===t&&/^[0-9a-f]+$/u.test(e)}export{LocalTraceSpanProcessor,resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory};
|
package/dist/src/vue/index.js
CHANGED
|
@@ -97,7 +97,24 @@ bot.onNewMention(async (thread, message) => {
|
|
|
97
97
|
});
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
`options` accepts `{ thread, auth?, title?, mode?, callback?, adapterName? }`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn.
|
|
100
|
+
`options` accepts `{ thread, auth?, title?, mode?, callback?, adapterName?, turnPolicy? }`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn.
|
|
101
|
+
|
|
102
|
+
### Experimental steering
|
|
103
|
+
|
|
104
|
+
By default, a message sent while an eve turn is active waits for the next turn. Pass `turnPolicy: "experimental-steer"` to cancel the active turn before sending the new message:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
bot.onSubscribedMessage(async (thread, message) => {
|
|
108
|
+
await send(message.text, {
|
|
109
|
+
thread,
|
|
110
|
+
turnPolicy: "experimental-steer",
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
This is cancellation-backed steering: the interrupted turn emits `turn.cancelled`, and the replacement message starts a new turn with a new turn ID. Partial output and completed side effects from the interrupted turn are not rolled back. If no turn is active, the message is sent normally. Use the default `turnPolicy: "queue"` when every turn should finish in order.
|
|
116
|
+
|
|
117
|
+
This policy controls overlapping eve turns. Chat SDK's separate `concurrency` option controls overlapping webhook handlers; use `concurrency: "concurrent"` when each inbound message should reach the experimental steering path immediately.
|
|
101
118
|
|
|
102
119
|
### Delivery
|
|
103
120
|
|
|
@@ -4,27 +4,43 @@ description: "Reach your agent from Discord HTTP Interactions, including slash c
|
|
|
4
4
|
type: integration
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The Discord channel wires your agent into Discord's HTTP Interactions, including slash and application commands, message components, and modal submissions. Discord enforces a three-second ACK deadline, so the channel
|
|
7
|
+
The Discord channel wires your agent into Discord's HTTP Interactions, including slash and application commands, message components, and modal submissions. Discord enforces a three-second ACK deadline, so the channel acknowledges the command right away and runs the eve work in the background. Credentials and inbound request verification run through [Vercel Connect](../guides/auth-and-route-protection), so Discord's bot token stays out of your environment and Connect verifies Discord's signature before forwarding an interaction to eve. See [Channels](./overview) for the contract this builds on.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Set up Discord
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
import { discordChannel } from "eve/channels/discord";
|
|
11
|
+
Run the guided setup from your eve project:
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
```bash
|
|
14
|
+
pnpm eve add channel/discord
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
The setup guides you through creating a Discord application and bot, then:
|
|
18
|
+
|
|
19
|
+
- validates the bot token;
|
|
20
|
+
- creates a Vercel Connect client and attaches `/eve/v1/discord` as its trigger destination;
|
|
21
|
+
- registers an application command with a required `message` option;
|
|
22
|
+
- configures the Discord application's Interactions Endpoint URL;
|
|
23
|
+
- scaffolds the channel with Connect-managed credentials; and
|
|
24
|
+
- prints the bot installation URL.
|
|
25
|
+
|
|
26
|
+
The command defaults to `/ask` with the description **Ask the eve agent**. You can edit both during setup. Discord global commands can take up to an hour to appear after registration.
|
|
27
|
+
|
|
28
|
+
The generated channel looks like this:
|
|
29
|
+
|
|
30
|
+
```ts title="agent/channels/discord.ts"
|
|
31
|
+
import { connectDiscordCredentials } from "@vercel/connect/eve";
|
|
32
|
+
import { discordChannel } from "eve/channels/discord";
|
|
33
|
+
|
|
34
|
+
export default discordChannel({
|
|
35
|
+
credentials: connectDiscordCredentials("discord/my-agent"),
|
|
36
|
+
});
|
|
21
37
|
```
|
|
22
38
|
|
|
23
|
-
|
|
39
|
+
The route is `POST /eve/v1/discord` by default. Connect resolves the application ID and bot token lazily and verifies forwarded interactions with same-project Vercel OIDC.
|
|
24
40
|
|
|
25
|
-
|
|
41
|
+
### Configure Discord manually
|
|
26
42
|
|
|
27
|
-
|
|
43
|
+
If you do not use the guided Connect setup, register a command with Discord's API or the Developer Portal. A string option named `message` lines up with eve's default prompt extraction:
|
|
28
44
|
|
|
29
45
|
```bash
|
|
30
46
|
curl -X PUT "https://discord.com/api/v10/applications/$DISCORD_APPLICATION_ID/commands" \
|
|
@@ -33,7 +49,7 @@ curl -X PUT "https://discord.com/api/v10/applications/$DISCORD_APPLICATION_ID/co
|
|
|
33
49
|
"options":[{"name":"message","description":"What should the agent do?","type":3,"required":true}]}]'
|
|
34
50
|
```
|
|
35
51
|
|
|
36
|
-
|
|
52
|
+
Then configure the public `https://…/eve/v1/discord` route as the application's Interactions Endpoint URL. Pass `credentials: { applicationId, botToken, publicKey }` to `discordChannel`, or set the corresponding `DISCORD_APPLICATION_ID`, `DISCORD_BOT_TOKEN`, and `DISCORD_PUBLIC_KEY` environment variables.
|
|
37
53
|
|
|
38
54
|
## How the channel handles messages
|
|
39
55
|
|
|
@@ -74,7 +90,7 @@ HITL renders as Discord components. Confirmations and options become buttons, `d
|
|
|
74
90
|
|
|
75
91
|
### Proactive sessions
|
|
76
92
|
|
|
77
|
-
Start a session without an inbound interaction through `receive(discord, { message, target, auth })` from a schedule `run` handler, or `args.receive(discord, ...)` from another channel. The proactive target shape is `{ channelId, conversationId?, initialMessage? }`. Either path needs `DISCORD_BOT_TOKEN`.
|
|
93
|
+
Start a session without an inbound interaction through `receive(discord, { message, target, auth })` from a schedule `run` handler, or `args.receive(discord, ...)` from another channel. The proactive target shape is `{ channelId, conversationId?, initialMessage? }`. Either path needs a bot token, supplied by Connect or `DISCORD_BOT_TOKEN`.
|
|
78
94
|
|
|
79
95
|
### Attachments
|
|
80
96
|
|
package/docs/channels/meta.json
CHANGED
|
@@ -28,7 +28,7 @@ agent/
|
|
|
28
28
|
intake.ts
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Install a
|
|
31
|
+
Install a channel from the registry with `eve add channel/photon-imessage`, `eve add channel/slack`, or `eve add channel/web`. You can also author the file by hand.
|
|
32
32
|
|
|
33
33
|
## The eve HTTP channel (default)
|
|
34
34
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Photon
|
|
3
|
+
description: Connect an eve agent to iMessage through Photon.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use `photonIMessageChannel` to receive and reply to iMessages through a Photon project.
|
|
7
|
+
|
|
8
|
+
Run `eve add channel/photon-imessage` to create or use a Photon project and register
|
|
9
|
+
your phone number. It then asks whether to configure Vercel Connect or portable
|
|
10
|
+
credentials. With Vercel Connect, eve creates the connector and configures
|
|
11
|
+
Photon’s webhook through Connect. The channel resolves credentials lazily when
|
|
12
|
+
the adapter first initializes:
|
|
13
|
+
|
|
14
|
+
```ts title="agent/channels/photon.ts"
|
|
15
|
+
import { connectPhotonCredentials } from "@vercel/connect/eve";
|
|
16
|
+
import { photonIMessageChannel } from "eve/channels/photon";
|
|
17
|
+
|
|
18
|
+
export default photonIMessageChannel({
|
|
19
|
+
credentials: connectPhotonCredentials("photon/my-agent"),
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The default webhook route is `/eve/v1/photon`. The channel verifies forwarded
|
|
24
|
+
webhooks with same-project Vercel OIDC by default, marks accepted messages as
|
|
25
|
+
read, and continues the same eve session for every message in an iMessage
|
|
26
|
+
conversation. A new accepted message cooperatively cancels an active turn and
|
|
27
|
+
steers its replacement turn.
|
|
28
|
+
|
|
29
|
+
Customize inbound dispatch with `onMessage`. Return `null` to ignore a message:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
export default photonIMessageChannel({
|
|
33
|
+
credentials: connectPhotonCredentials("photon/my-agent"),
|
|
34
|
+
onMessage(_ctx, message) {
|
|
35
|
+
if (message.author.isBot) return null;
|
|
36
|
+
return {
|
|
37
|
+
auth: null,
|
|
38
|
+
context: [`The sender is ${message.author.fullName}.`],
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Set `route` to override the webhook path or `webhookVerifier` to use a different
|
|
45
|
+
trusted-forwarder verifier.
|
|
46
|
+
|
|
47
|
+
## Other hosts
|
|
48
|
+
|
|
49
|
+
For a host without Vercel Connect, choose **Use portable credentials** during
|
|
50
|
+
`eve add channel/photon-imessage`. eve scaffolds the channel and writes
|
|
51
|
+
`IMESSAGE_PROJECT_ID` and `IMESSAGE_PROJECT_SECRET` to `.env.local`.
|
|
52
|
+
|
|
53
|
+
After deploying the agent:
|
|
54
|
+
|
|
55
|
+
1. Create a Photon webhook for your public `https://…/eve/v1/photon` URL.
|
|
56
|
+
2. Copy its signing secret into `IMESSAGE_WEBHOOK_SECRET`.
|
|
57
|
+
3. Set `IMESSAGE_PROJECT_ID`, `IMESSAGE_PROJECT_SECRET`, and
|
|
58
|
+
`IMESSAGE_WEBHOOK_SECRET` in the host’s encrypted environment variables.
|
|
59
|
+
|
|
60
|
+
To configure the channel by hand, use lazy environment-backed credentials:
|
|
61
|
+
|
|
62
|
+
```ts title="agent/channels/photon.ts"
|
|
63
|
+
import { photonIMessageChannel } from "eve/channels/photon";
|
|
64
|
+
|
|
65
|
+
export default photonIMessageChannel({
|
|
66
|
+
async credentials() {
|
|
67
|
+
const projectId = process.env.IMESSAGE_PROJECT_ID;
|
|
68
|
+
const projectSecret = process.env.IMESSAGE_PROJECT_SECRET;
|
|
69
|
+
if (!projectId || !projectSecret) throw new Error("Photon project credentials are required.");
|
|
70
|
+
return { projectId, projectSecret };
|
|
71
|
+
},
|
|
72
|
+
webhookSecret: process.env.IMESSAGE_WEBHOOK_SECRET,
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
For direct Photon webhooks, pass `webhookSecret` or set
|
|
77
|
+
`IMESSAGE_WEBHOOK_SECRET`; the signing secret takes precedence over the default
|
|
78
|
+
OIDC verifier.
|
|
@@ -41,6 +41,8 @@ The shell and file tools (`bash`, `read_file`, `write_file`, `glob`, `grep`) run
|
|
|
41
41
|
| `load_skill` | Pull an on-demand [skill](../skills)'s instructions into the current turn. Present only when the agent declares skills. | App runtime |
|
|
42
42
|
| `connection_search` | Discover tools across declared [connections](../connections); matched tools become directly callable. Present only when the agent declares connections. | App runtime |
|
|
43
43
|
|
|
44
|
+
The model-facing file tools accept absolute paths and paths beginning with `$HOME/`. eve resolves `$HOME` against the sandbox before invoking non-shell file operations, so packaged skill references such as `$HOME/.agents/skills/<skill>/references/...` work consistently across `read_file`, `write_file`, `glob`, and `grep`.
|
|
45
|
+
|
|
44
46
|
Notes:
|
|
45
47
|
|
|
46
48
|
- **`agent`** is available only in the root session. Its child uses the root's instructions, tools, connections, and sandbox, but starts with fresh conversation history and fresh [state](../guides/state). The child receives neither `agent` nor `Workflow`; declared subagents do not receive the built-in `agent` either. See [Subagents](../subagents).
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Use eve through ACP"
|
|
3
|
+
description: "Use local or deployed eve agents from Agent Client Protocol clients."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Agent Client Protocol (ACP) clients can launch an authored eve application as a local subprocess. eve serves stable ACP v1 over stdio while its normal development server remains the execution runtime.
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
eve acp
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Without a URL, the client starts one process from the eve application root. It supervises a local development server, and closing the ACP connection stops that owned server. To bridge ACP to a deployed eve agent, pass its URL:
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
eve acp https://agent.example.com
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
For a recognized Vercel deployment, eve verifies the exact origin and resolves a short-lived project-scoped OIDC token from the local Vercel session. If login or a Trusted Sources change is required, run `eve dev <url>` and complete `/vc:login` before launching ACP. `VERCEL_AUTOMATION_BYPASS_SECRET` remains available for deployments configured with a Protection Bypass for Automation token.
|
|
19
|
+
|
|
20
|
+
## Configure Zed
|
|
21
|
+
|
|
22
|
+
Open the eve application root as the Zed workspace. In **Agent Settings → External Agents**, add a custom agent:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"agent_servers": {
|
|
27
|
+
"eve-local": {
|
|
28
|
+
"type": "custom",
|
|
29
|
+
"command": "pnpm",
|
|
30
|
+
"args": ["exec", "eve", "acp"],
|
|
31
|
+
"env": {}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Use an absolute command path if Zed cannot find `pnpm` in its environment. The workspace must be the same directory as the eve application root; eve rejects a different `session/new.cwd` instead of running the wrong application.
|
|
38
|
+
|
|
39
|
+
Disable Zed project MCP servers for this agent. The initial eve adapter does not accept client-provided MCP servers.
|
|
40
|
+
|
|
41
|
+
## Supported behavior
|
|
42
|
+
|
|
43
|
+
ACP clients receive:
|
|
44
|
+
|
|
45
|
+
- streamed assistant text and reasoning;
|
|
46
|
+
- tool-call requests and results;
|
|
47
|
+
- one-time tool approval and denial requests;
|
|
48
|
+
- fixed-choice and freeform questions when the client supports ACP form elicitation;
|
|
49
|
+
- cooperative turn cancellation;
|
|
50
|
+
- independent concurrent ACP sessions;
|
|
51
|
+
- session closure and process cleanup.
|
|
52
|
+
|
|
53
|
+
Development rebuilds retain normal eve semantics. In-flight work stays pinned to its generation, and the next turn uses the newest successful generation.
|
|
54
|
+
|
|
55
|
+
## Security and capability limits
|
|
56
|
+
|
|
57
|
+
ACP mode does not give the agent access to the editor's host filesystem or terminal. `session/new.cwd` identifies the eve application being launched; it is not mounted into the agent sandbox.
|
|
58
|
+
|
|
59
|
+
The initial adapter does not support:
|
|
60
|
+
|
|
61
|
+
- a deployed ACP HTTP or WebSocket endpoint;
|
|
62
|
+
- ACP authentication (remote bridges use the deployed eve agent's existing HTTP authentication);
|
|
63
|
+
- ACP v2;
|
|
64
|
+
- client filesystem or terminal methods;
|
|
65
|
+
- client-provided MCP servers;
|
|
66
|
+
- images, audio, files, or embedded resources in prompts;
|
|
67
|
+
- session loading, listing, resumption, or durable ACP IDs across process restarts;
|
|
68
|
+
- ACP model or mode configuration.
|
|
69
|
+
|
|
70
|
+
The agent continues to use the connections, tools, credentials, and sandbox policy authored in the eve application. Prompt text and ACP metadata never establish an authenticated end-user principal.
|
|
71
|
+
|
|
72
|
+
## Diagnose a connection
|
|
73
|
+
|
|
74
|
+
ACP reserves stdout for newline-delimited JSON-RPC. eve sends compilation output, server logs, and diagnostics to stderr so they cannot corrupt the protocol stream.
|
|
75
|
+
|
|
76
|
+
For a quick headless smoke test, run an ACP client such as `acpx` from the application root. `acpx` launches the ACP process itself; do not start `eve acp` separately.
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
npx acpx@latest \
|
|
80
|
+
--agent 'pnpm exec eve acp' \
|
|
81
|
+
exec 'Reply with exactly: ACP works'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
When testing from the eve source checkout, use an authored fixture rather than the monorepo root, which does not provide an `eve` executable:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
cd apps/fixtures/weather-agent
|
|
88
|
+
npx acpx@latest --agent 'pnpm exec eve acp' exec 'Reply with exactly: ACP works'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If startup fails, inspect the ACP client's logs together with eve's stderr. A non-empty client MCP configuration, a mismatched working directory, and unsupported prompt content produce explicit protocol errors before model work begins.
|
|
@@ -180,6 +180,30 @@ Because a tail-relative cursor cannot be bounded, `follow: false` throws when co
|
|
|
180
180
|
|
|
181
181
|
`stream()` throws if the session has no `sessionId`, because there's no stream to attach to before the first send.
|
|
182
182
|
|
|
183
|
+
## Snapshot a session
|
|
184
|
+
|
|
185
|
+
Use `snapshot()` when you need the complete event prefix and its matching cursor
|
|
186
|
+
as one value, such as when hydrating a server-rendered chat:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
const session = client.session({ sessionId, streamIndex: 0 });
|
|
190
|
+
const snapshot = await session.snapshot();
|
|
191
|
+
|
|
192
|
+
// snapshot.events contains event indexes 0 through snapshot.session.streamIndex - 1.
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The read pins the durable tail when it opens, just like
|
|
196
|
+
`stream({ follow: false })`. Events written afterward are not included, and
|
|
197
|
+
`snapshot.session.streamIndex` is the exact index from which a live consumer can
|
|
198
|
+
continue. `snapshot()` always reads from index `0`; use a bounded stream directly
|
|
199
|
+
when you only need the unread suffix from an existing cursor.
|
|
200
|
+
|
|
201
|
+
Unlike `stream()`, `snapshot()` does not advance or reset the originating
|
|
202
|
+
`ClientSession`. Its returned session includes a continuation token only when
|
|
203
|
+
the captured prefix ends in `session.waiting`, or when completed sessions are
|
|
204
|
+
explicitly preserved by the client. Active and terminal snapshots remain
|
|
205
|
+
inspectable at their returned stream cursor but cannot accept another turn.
|
|
206
|
+
|
|
183
207
|
## Abort a request
|
|
184
208
|
|
|
185
209
|
Pass an `AbortSignal` to cancel the POST or stream. Aborting is local transport cancellation: turns are resumable across disconnects, so detaching never stops the server-side turn — it keeps running and remains attachable by index. To stop the turn itself, POST the session's [cancel route](../../channels/eve#routes) and watch the stream settle with `turn.cancelled` followed by `session.waiting`.
|