eve 0.69.0 → 0.70.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/dist/src/acp/adapter.js +1 -1
- package/dist/src/channel/task-card.d.ts +3 -3
- package/dist/src/channel/task-card.js +1 -1
- package/dist/src/channel/types.d.ts +18 -0
- package/dist/src/chunks/{use-eve-agent-Dab2MnT2.js → use-eve-agent-CJQeE7-t.js} +1873 -1236
- package/dist/src/chunks/{use-eve-agent-D_5129A9.js → use-eve-agent-DdemtY6C.js} +1874 -1234
- package/dist/src/cli/dev/command.js +1 -1
- package/dist/src/cli/dev/console-records-preload.d.ts +1 -0
- package/dist/src/cli/dev/console-records-preload.js +1 -0
- package/dist/src/cli/dev/console-records.d.ts +17 -0
- package/dist/src/cli/dev/console-records.js +3 -0
- package/dist/src/cli/dev/diagnostic-sink.d.ts +1 -0
- package/dist/src/cli/dev/local-server-process.js +1 -1
- package/dist/src/cli/dev/tui/blocks.d.ts +2 -1
- package/dist/src/cli/dev/tui/blocks.js +3 -3
- package/dist/src/cli/dev/tui/conversation-view.d.ts +54 -0
- package/dist/src/cli/dev/tui/conversation-view.js +1 -0
- package/dist/src/cli/dev/tui/flow-drawer.d.ts +5 -2
- package/dist/src/cli/dev/tui/flow-drawer.js +1 -1
- package/dist/src/cli/dev/tui/log-display-mode.d.ts +4 -10
- package/dist/src/cli/dev/tui/log-display-mode.js +1 -1
- package/dist/src/cli/dev/tui/message-queue.d.ts +7 -63
- package/dist/src/cli/dev/tui/message-queue.js +3 -1
- package/dist/src/cli/dev/tui/prompt-commands.d.ts +7 -7
- package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
- package/dist/src/cli/dev/tui/question-panel.d.ts +3 -1
- package/dist/src/cli/dev/tui/question-panel.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +58 -195
- package/dist/src/cli/dev/tui/runner.js +3 -3
- package/dist/src/cli/dev/tui/task-activity.d.ts +11 -24
- package/dist/src/cli/dev/tui/task-activity.js +1 -1
- package/dist/src/cli/dev/tui/task-records.d.ts +17 -0
- package/dist/src/cli/dev/tui/task-records.js +1 -0
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +15 -37
- package/dist/src/cli/dev/tui/terminal-renderer.js +10 -13
- package/dist/src/cli/dev/tui/terminal-tool-part.d.ts +2 -0
- package/dist/src/cli/dev/tui/terminal-tool-part.js +1 -0
- package/dist/src/cli/dev/tui/test/fake-eve-server.d.ts +34 -0
- package/dist/src/cli/dev/tui/test/fake-eve-server.js +1 -0
- package/dist/src/cli/dev/tui/test/index.d.ts +1 -0
- package/dist/src/cli/dev/tui/test/index.js +1 -1
- package/dist/src/cli/dev/tui/tool-block-groups.js +1 -1
- package/dist/src/cli/dev/tui/tool-presentation.d.ts +1 -0
- package/dist/src/cli/dev/tui/tool-presentation.js +1 -1
- package/dist/src/cli/dev/tui/tool-rows.d.ts +1 -0
- package/dist/src/cli/dev/tui/tool-rows.js +2 -2
- package/dist/src/cli/dev/tui/transcript-parts.d.ts +81 -0
- package/dist/src/cli/dev/tui/transcript-parts.js +3 -0
- package/dist/src/cli/dev/tui/transcript.d.ts +47 -0
- package/dist/src/cli/dev/tui/transcript.js +1 -0
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/dev/tui/turn-clock.d.ts +11 -26
- package/dist/src/cli/dev/tui/turn-clock.js +1 -1
- package/dist/src/cli/dev/tui/types.d.ts +2 -4
- package/dist/src/cli/dev/ui-options.js +1 -1
- package/dist/src/client/agent-stream-follower.d.ts +26 -0
- package/dist/src/client/agent-stream-follower.js +1 -0
- package/dist/src/client/authorization-message-parts.js +1 -1
- package/dist/src/client/conversation-client.d.ts +40 -0
- package/dist/src/client/conversation-client.js +1 -0
- package/dist/src/client/conversation-reducer.d.ts +29 -0
- package/dist/src/client/conversation-reducer.js +1 -0
- package/dist/src/client/conversation-state.d.ts +110 -0
- package/dist/src/client/conversation-state.js +1 -0
- package/dist/src/client/eve-agent-projection.d.ts +24 -7
- package/dist/src/client/eve-agent-projection.js +1 -1
- package/dist/src/client/eve-agent-store-helpers.d.ts +21 -2
- package/dist/src/client/eve-agent-store-helpers.js +2 -2
- package/dist/src/client/eve-agent-store-state.d.ts +15 -3
- package/dist/src/client/eve-agent-store.d.ts +10 -1
- package/dist/src/client/eve-agent-store.js +1 -1
- package/dist/src/client/index.d.ts +4 -1
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/message-reducer-primitives.d.ts +1 -2
- package/dist/src/client/message-reducer-primitives.js +1 -1
- package/dist/src/client/message-reducer-types.d.ts +9 -2
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/client/message-response.js +1 -1
- package/dist/src/client/message-run-parts.d.ts +10 -6
- package/dist/src/client/message-run-parts.js +1 -1
- package/dist/src/client/optimistic-message-submissions.d.ts +6 -4
- package/dist/src/client/optimistic-message-submissions.js +1 -1
- package/dist/src/client/reducer.d.ts +5 -1
- package/dist/src/client/session-turn-dispatch.d.ts +15 -0
- package/dist/src/client/session-turn-dispatch.js +1 -0
- package/dist/src/client/session-utils.d.ts +27 -10
- package/dist/src/client/session-utils.js +1 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/types.d.ts +2 -1
- package/dist/src/compiled/.vendor-stamp.json +2 -2
- package/dist/src/compiled/{gray-matter → js-yaml}/LICENSE +2 -2
- package/dist/src/compiled/js-yaml/index.d.ts +12 -0
- package/dist/src/compiled/js-yaml/index.js +34 -0
- package/dist/src/compiler/extension-compatibility.d.ts +18 -18
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/load-binding-namespace.js +1 -1
- package/dist/src/context/keys.d.ts +5 -2
- package/dist/src/context/keys.js +1 -1
- package/dist/src/context/provider.d.ts +5 -9
- package/dist/src/context/run-step.d.ts +4 -4
- package/dist/src/context/run-step.js +1 -1
- package/dist/src/context/serialize.d.ts +5 -1
- package/dist/src/context/serialize.js +1 -1
- package/dist/src/evals/loaders/yaml.js +1 -1
- package/dist/src/evals/runner/derive-run-facts.js +1 -1
- package/dist/src/evals/runner/execute-task.js +1 -1
- package/dist/src/evals/session.js +2 -2
- package/dist/src/evals/types.d.ts +16 -0
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/execution/agent-sessions/context.d.ts +4 -2
- package/dist/src/execution/agent-sessions/context.js +1 -1
- package/dist/src/execution/agent-sessions/steps.js +1 -1
- package/dist/src/execution/cancelled-model-call-batch.js +1 -1
- package/dist/src/execution/coordination-dispatch-shared.d.ts +6 -4
- package/dist/src/execution/coordination-dispatch-shared.js +1 -1
- package/dist/src/execution/create-session-step.d.ts +4 -2
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/durable-session-store.d.ts +10 -4
- package/dist/src/execution/durable-session-store.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/legacy-remote-agent/protocol.d.ts +8 -0
- package/dist/src/execution/legacy-remote-agent/protocol.js +1 -1
- package/dist/src/execution/legacy-session/completion-step.d.ts +2 -0
- package/dist/src/execution/legacy-session/completion-step.js +1 -1
- package/dist/src/execution/legacy-session/interrupt-step.js +1 -1
- package/dist/src/execution/legacy-session/prepare-step.d.ts +1 -0
- package/dist/src/execution/legacy-session/prepare-step.js +1 -1
- package/dist/src/execution/legacy-session/snapshot.d.ts +8 -4
- package/dist/src/execution/legacy-session/snapshot.js +1 -1
- package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
- package/dist/src/execution/proxied-deliver-step.js +1 -1
- package/dist/src/execution/publish-session-events.d.ts +27 -7
- package/dist/src/execution/publish-session-events.js +1 -1
- package/dist/src/execution/reconcile-session-continuation-token.d.ts +2 -2
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/session/active-turn.d.ts +97 -0
- package/dist/src/execution/session/active-turn.js +1 -0
- package/dist/src/execution/session/checkpoint-migrations.d.ts +23 -0
- package/dist/src/execution/session/checkpoint-migrations.js +1 -0
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/finalization.js +1 -1
- package/dist/src/execution/session/handoff-steps.d.ts +24 -5
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/handoff.d.ts +10 -6
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/input-queue.d.ts +19 -13
- package/dist/src/execution/session/input-queue.js +1 -1
- package/dist/src/execution/session/next-input.d.ts +2 -10
- package/dist/src/execution/session/next-input.js +1 -1
- package/dist/src/execution/session/pending-turn-state.d.ts +2 -0
- package/dist/src/execution/session/pending-turn-state.js +1 -1
- package/dist/src/execution/session/program.d.ts +2 -0
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/state-cursor.d.ts +22 -16
- package/dist/src/execution/session/state-cursor.js +1 -1
- package/dist/src/execution/session/state-delta.d.ts +8 -1
- package/dist/src/execution/session/state-delta.js +1 -1
- package/dist/src/execution/session/turn-event-handler.js +1 -1
- package/dist/src/execution/session/turn-step-result.js +1 -1
- package/dist/src/execution/session/turn-step-types.d.ts +20 -4
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn-waiting-step.js +1 -1
- package/dist/src/execution/session/turn.d.ts +22 -3
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/session.d.ts +5 -5
- package/dist/src/execution/session.js +2 -2
- package/dist/src/execution/settle-cancelled-turn-step.d.ts +5 -4
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/tasks/start.d.ts +2 -2
- package/dist/src/execution/tasks/task-id-input.d.ts +1 -1
- package/dist/src/execution/tasks/task-id-input.js +1 -1
- package/dist/src/execution/terminal-session-completion-step.d.ts +2 -0
- package/dist/src/execution/terminal-session-completion-step.js +1 -1
- package/dist/src/execution/terminal-session-failure-step.d.ts +2 -0
- package/dist/src/execution/terminal-session-failure-step.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/tools/connection-target.d.ts +5 -0
- package/dist/src/execution/tools/connection-target.js +1 -1
- package/dist/src/execution/tools/connection-tools.js +2 -2
- package/dist/src/execution/tools/workflow/start.d.ts +3 -3
- package/dist/src/harness/authorization.d.ts +15 -2
- package/dist/src/harness/authorization.js +1 -1
- package/dist/src/harness/cancelled-turn-emission.d.ts +2 -1
- package/dist/src/harness/cancelled-turn-emission.js +1 -1
- package/dist/src/harness/coordination.d.ts +5 -3
- package/dist/src/harness/emission.d.ts +5 -2
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/held-requests.d.ts +18 -0
- package/dist/src/harness/held-requests.js +1 -0
- package/dist/src/harness/hitl/approval-input-requests.d.ts +16 -0
- package/dist/src/harness/hitl/approval-input-requests.js +1 -1
- package/dist/src/harness/input-extraction.js +1 -1
- package/dist/src/harness/input-requests.d.ts +0 -4
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/model-call-error.js +1 -1
- package/dist/src/harness/proxy-input-requests.d.ts +4 -4
- package/dist/src/harness/session-limit-enforcement.js +1 -1
- package/dist/src/harness/stale-input-responses.js +1 -1
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/harness/turn-tag-state.d.ts +2 -0
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/harness/types.d.ts +23 -11
- package/dist/src/instrumentation/channel-delivery.d.ts +1 -0
- package/dist/src/instrumentation/channel-delivery.js +1 -1
- package/dist/src/instrumentation/lifecycle.d.ts +4 -0
- package/dist/src/instrumentation/memory.d.ts +2 -0
- package/dist/src/instrumentation/memory.js +1 -1
- package/dist/src/instrumentation/native-events.d.ts +1 -0
- package/dist/src/instrumentation/native-events.js +1 -1
- package/dist/src/instrumentation/runtime.d.ts +4 -3
- package/dist/src/instrumentation/runtime.js +1 -1
- package/dist/src/instrumentation/session-init.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-module-loader.d.ts +14 -6
- package/dist/src/internal/authored-module-loader.js +1 -1
- package/dist/src/internal/authored-package-boundary.d.ts +1 -1
- package/dist/src/internal/authored-package-boundary.js +1 -1
- package/dist/src/internal/bundler/extension-mount-plugin.js +1 -1
- package/dist/src/internal/helpers/frontmatter.d.ts +24 -0
- package/dist/src/internal/helpers/frontmatter.js +1 -0
- package/dist/src/internal/helpers/markdown.js +1 -3
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/nitro-bundler-config.js +1 -1
- package/dist/src/internal/node-esm-compat-banner.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-remote-agent-transform.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.d.ts +27 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +2 -2
- package/dist/src/protocol/message.d.ts +41 -3
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/channels/slack/action-status.d.ts +2 -2
- package/dist/src/public/channels/slack/action-status.js +1 -1
- package/dist/src/public/channels/slack/approval-cards.d.ts +15 -0
- package/dist/src/public/channels/slack/approval-cards.js +2 -0
- package/dist/src/public/channels/slack/auth.d.ts +2 -0
- package/dist/src/public/channels/slack/auth.js +1 -1
- package/dist/src/public/channels/slack/connections.d.ts +15 -11
- package/dist/src/public/channels/slack/connections.js +1 -1
- package/dist/src/public/channels/slack/defaults.d.ts +1 -15
- package/dist/src/public/channels/slack/defaults.js +3 -4
- package/dist/src/public/channels/slack/hitl.js +1 -1
- package/dist/src/public/channels/slack/inbound.d.ts +10 -2
- package/dist/src/public/channels/slack/inbound.js +1 -1
- package/dist/src/public/channels/slack/index.d.ts +2 -0
- package/dist/src/public/channels/slack/index.js +1 -1
- package/dist/src/public/channels/slack/input-response.js +1 -1
- package/dist/src/public/channels/slack/interaction-cards.js +1 -1
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/limits.d.ts +5 -3
- package/dist/src/public/channels/slack/private-approval-delivery.js +1 -1
- package/dist/src/public/channels/slack/renderers.d.ts +1 -1
- package/dist/src/public/channels/slack/renderers.js +1 -1
- package/dist/src/public/channels/slack/reply-delivery.d.ts +72 -0
- package/dist/src/public/channels/slack/reply-delivery.js +1 -0
- package/dist/src/public/channels/slack/sign-in-cancel.d.ts +20 -0
- package/dist/src/public/channels/slack/sign-in-cancel.js +1 -0
- package/dist/src/public/channels/slack/slackChannel.d.ts +15 -0
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/slack/task-card.js +1 -1
- package/dist/src/public/channels/teams/defaults.d.ts +1 -1
- package/dist/src/public/channels/teams/defaults.js +2 -2
- package/dist/src/public/definitions/channel.d.ts +1 -0
- package/dist/src/public/definitions/channel.js +1 -1
- package/dist/src/public/definitions/state.d.ts +2 -0
- package/dist/src/public/definitions/state.js +1 -1
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/next/server.d.ts +2 -0
- package/dist/src/public/next/server.js +1 -2
- package/dist/src/public/nuxt/module.d.ts +6 -0
- package/dist/src/public/nuxt/module.js +1 -1
- package/dist/src/react/index.d.ts +3 -0
- package/dist/src/react/index.js +1 -1
- package/dist/src/react/use-eve-agent.d.ts +7 -5
- package/dist/src/react/use-eve-agent.js +1 -1
- package/dist/src/runtime/connections/openapi-spec.d.ts +1 -4
- package/dist/src/runtime/connections/openapi-spec.js +1 -1
- package/dist/src/runtime/connections/scoped-authorization.d.ts +2 -0
- package/dist/src/runtime/connections/scoped-authorization.js +1 -1
- package/dist/src/setup/boxes/deploy-project.js +1 -1
- package/dist/src/setup/integrations/web/setup.js +6 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +5 -5
- package/dist/src/setup/scaffold/create/web-template.js +61 -35
- package/dist/src/setup/vercel-project-framework.js +1 -1
- package/dist/src/shared/display-name.d.ts +15 -0
- package/dist/src/shared/display-name.js +1 -0
- package/dist/src/shared/framework-eve-server.d.ts +43 -0
- package/dist/src/shared/framework-eve-server.js +2 -0
- package/dist/src/shared/token-usage.d.ts +2 -0
- package/dist/src/shared/token-usage.js +1 -1
- package/dist/src/shared/trace-root.d.ts +8 -0
- package/dist/src/shared/trace-root.js +1 -0
- package/dist/src/subagents/callback-route.js +1 -1
- package/dist/src/subagents/hitl-proxy.d.ts +3 -3
- package/dist/src/subagents/hitl-proxy.js +1 -1
- package/dist/src/subagents/invocation.d.ts +3 -1
- package/dist/src/subagents/parent-notification.d.ts +7 -7
- package/dist/src/subagents/parent-notification.js +1 -1
- package/dist/src/subagents/tool.js +1 -1
- package/dist/src/svelte/index.d.ts +3 -0
- package/dist/src/svelte/index.js +2 -2
- package/dist/src/svelte/use-eve-agent.d.ts +7 -4
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/load-skill.js +1 -1
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/tracing/agent-action-instrumentation.js +1 -1
- package/dist/src/tracing/agent-approval-instrumentation.js +1 -1
- package/dist/src/tracing/agent-memory-instrumentation.js +1 -1
- package/dist/src/tracing/agent-otel-attributes.d.ts +6 -0
- package/dist/src/tracing/agent-otel-attributes.js +1 -1
- package/dist/src/tracing/agent-otel-provider.js +2 -2
- package/dist/src/tracing/agent-otel-runtime-context.d.ts +1 -1
- package/dist/src/tracing/agent-otel-runtime-context.js +1 -1
- package/dist/src/tracing/agent-otel-session-context.js +1 -1
- package/dist/src/tracing/agent-span-contract.js +1 -1
- package/dist/src/tracing/agent-tool-instrumentation.js +1 -1
- package/dist/src/tracing/agent-trace-context-codec.d.ts +4 -0
- package/dist/src/tracing/agent-trace-context-codec.js +1 -1
- package/dist/src/tracing/agent-trace-span-processor.js +1 -1
- package/dist/src/tracing/agent-trace-state.d.ts +3 -0
- package/dist/src/tracing/conversation-context.d.ts +10 -0
- package/dist/src/tracing/conversation-context.js +1 -1
- package/dist/src/tracing/otel-registration.js +1 -1
- package/dist/src/vue/index.d.ts +3 -0
- package/dist/src/vue/index.js +2 -2
- package/dist/src/vue/use-eve-agent.d.ts +7 -3
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/slack.mdx +60 -13
- package/docs/concepts/built-in-tools.md +3 -2
- package/docs/concepts/execution-model-and-durability.mdx +3 -1
- package/docs/concepts/sessions-runs-and-streaming.md +4 -4
- package/docs/connections/overview.mdx +9 -3
- package/docs/evals/reporters.mdx +4 -0
- package/docs/extensions.md +15 -3
- package/docs/guides/client/streaming.mdx +7 -6
- package/docs/guides/deployment/vercel.mdx +2 -1
- package/docs/guides/dev-tui.md +17 -17
- package/docs/guides/dynamic-capabilities.md +1 -1
- package/docs/guides/frontend/nuxt.mdx +24 -4
- package/docs/guides/frontend/overview.mdx +44 -38
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +4 -10
- package/docs/guides/frontend/use-eve-agent-vue.mdx +4 -10
- package/docs/guides/instrumentation/otel.mdx +24 -6
- package/docs/guides/remote-agents.md +26 -8
- package/docs/reference/cli.md +4 -4
- package/docs/tools/human-in-the-loop.md +4 -4
- package/docs/tools/overview.mdx +1 -1
- package/docs/tools/tasks.md +8 -8
- package/package.json +2 -2
- package/dist/src/cli/dev/tui/steering-stream.d.ts +0 -15
- package/dist/src/cli/dev/tui/steering-stream.js +0 -1
- package/dist/src/cli/dev/tui/subagent-pump.d.ts +0 -134
- package/dist/src/cli/dev/tui/subagent-pump.js +0 -1
- package/dist/src/compiled/gray-matter/index.d.ts +0 -62
- package/dist/src/compiled/gray-matter/index.js +0 -48
- package/dist/src/internal/helpers/gray-matter.d.ts +0 -25
- package/dist/src/internal/helpers/gray-matter.js +0 -1
- package/dist/src/public/nuxt/dev-server.d.ts +0 -25
- package/dist/src/public/nuxt/dev-server.js +0 -1
|
@@ -684,28 +684,22 @@ function isTurnFailureEvent(event) {
|
|
|
684
684
|
//#endregion
|
|
685
685
|
//#region src/client/session-utils.ts
|
|
686
686
|
function summarizeTurnEvents(events) {
|
|
687
|
+
const segment = new TurnSegment();
|
|
687
688
|
let boundary;
|
|
688
689
|
let failure;
|
|
689
690
|
let message;
|
|
690
|
-
const inputRequests = [];
|
|
691
|
-
const pendingInputRequests = /* @__PURE__ */ new Set();
|
|
692
|
-
const pendingAuthorizations = /* @__PURE__ */ new Map();
|
|
693
691
|
for (const event of events) {
|
|
694
|
-
|
|
695
|
-
if (isTurnSegmentBoundary(event, pendingInputRequests)) boundary = event;
|
|
692
|
+
if (segment.observe(event)) boundary = event;
|
|
696
693
|
if (isTurnFailureEvent(event)) failure = event;
|
|
697
694
|
if (isFinalMessageCompleted(event)) message = event.data.message ?? void 0;
|
|
698
695
|
if (event.type === "turn.waiting") message = void 0;
|
|
699
|
-
if (event.type === "input.requested") inputRequests.push(...event.data.requests);
|
|
700
|
-
if (event.type === "authorization.required") pendingAuthorizations.set(event.data.name, event.data);
|
|
701
|
-
if (event.type === "authorization.completed") pendingAuthorizations.delete(event.data.name);
|
|
702
696
|
}
|
|
703
697
|
return {
|
|
704
698
|
boundary,
|
|
705
699
|
failure,
|
|
706
|
-
inputRequests,
|
|
700
|
+
inputRequests: segment.inputRequests,
|
|
707
701
|
message,
|
|
708
|
-
pendingAuthorizations:
|
|
702
|
+
pendingAuthorizations: segment.pendingAuthorizations,
|
|
709
703
|
status: summarizeBoundaryStatus(boundary)
|
|
710
704
|
};
|
|
711
705
|
}
|
|
@@ -714,20 +708,50 @@ function summarizeBoundaryStatus(boundary) {
|
|
|
714
708
|
if (boundary?.type === "session.failed") return "failed";
|
|
715
709
|
return "completed";
|
|
716
710
|
}
|
|
717
|
-
function
|
|
718
|
-
if (event.type === "turn.waiting") return
|
|
719
|
-
return isCurrentTurnBoundaryEvent(event);
|
|
720
|
-
}
|
|
721
|
-
function updatePendingInputRequests(pending, event) {
|
|
722
|
-
if (event.type === "input.requested") for (const request of event.data.requests) pending.add(request.requestId);
|
|
723
|
-
else if (event.type === "input.resolved") for (const resolution of event.data.resolutions) pending.delete(resolution.requestId);
|
|
711
|
+
function endsTurnSegment(event, open) {
|
|
712
|
+
if (event.type === "turn.waiting") return open.requests || event.data.on === "input" && !open.callbacks;
|
|
713
|
+
return isCurrentTurnBoundaryEvent(event) && (event.type !== "session.waiting" || !open.callbacks);
|
|
724
714
|
}
|
|
715
|
+
var TurnSegment = class {
|
|
716
|
+
#authorizations = /* @__PURE__ */ new Map();
|
|
717
|
+
#followCallbacks;
|
|
718
|
+
#requests = /* @__PURE__ */ new Map();
|
|
719
|
+
constructor(options = {}) {
|
|
720
|
+
this.#followCallbacks = options.followCallbacks === true;
|
|
721
|
+
}
|
|
722
|
+
get inputRequests() {
|
|
723
|
+
return [...this.#requests.values()];
|
|
724
|
+
}
|
|
725
|
+
get pendingAuthorizations() {
|
|
726
|
+
return [...this.#authorizations.values()];
|
|
727
|
+
}
|
|
728
|
+
observe(event) {
|
|
729
|
+
switch (event.type) {
|
|
730
|
+
case "input.requested":
|
|
731
|
+
for (const request of event.data.requests) this.#requests.set(request.requestId, request);
|
|
732
|
+
break;
|
|
733
|
+
case "approval.settled":
|
|
734
|
+
this.#requests.delete(event.data.requestId);
|
|
735
|
+
break;
|
|
736
|
+
case "input.resolved":
|
|
737
|
+
for (const resolution of event.data.resolutions) this.#requests.delete(resolution.requestId);
|
|
738
|
+
break;
|
|
739
|
+
case "authorization.required":
|
|
740
|
+
this.#authorizations.set(authorizationKey(event.data), event.data);
|
|
741
|
+
break;
|
|
742
|
+
case "authorization.completed": this.#authorizations.delete(authorizationKey(event.data));
|
|
743
|
+
}
|
|
744
|
+
return endsTurnSegment(event, {
|
|
745
|
+
callbacks: this.#followCallbacks && [...this.#authorizations.values()].some((authorization) => authorization.webhookUrl !== void 0),
|
|
746
|
+
requests: this.#requests.size > 0
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
};
|
|
725
750
|
function isFinalMessageCompleted(event) {
|
|
726
751
|
return event.type === "message.completed" && event.data.finishReason !== "tool-calls";
|
|
727
752
|
}
|
|
728
|
-
function
|
|
729
|
-
|
|
730
|
-
else if (event.type === "authorization.completed") pending.delete(event.data.name);
|
|
753
|
+
function authorizationKey(data) {
|
|
754
|
+
return data.attemptId === void 0 ? `name:${data.name}` : `attempt:${data.attemptId}`;
|
|
731
755
|
}
|
|
732
756
|
|
|
733
757
|
//#endregion
|
|
@@ -1890,8 +1914,7 @@ var ClientSession = class ClientSession {
|
|
|
1890
1914
|
let eventCount = 0;
|
|
1891
1915
|
let started = deliveryId === void 0;
|
|
1892
1916
|
let reachedBoundary = false;
|
|
1893
|
-
const
|
|
1894
|
-
const pendingInputRequests = /* @__PURE__ */ new Set();
|
|
1917
|
+
const segment = new TurnSegment({ followCallbacks: true });
|
|
1895
1918
|
try {
|
|
1896
1919
|
for await (const event of source ?? this.#readStream({
|
|
1897
1920
|
headers: input.headers,
|
|
@@ -1909,9 +1932,7 @@ var ClientSession = class ClientSession {
|
|
|
1909
1932
|
if (!terminal && event.meta?.deliveryIds !== void 0 && !matches) continue;
|
|
1910
1933
|
started = true;
|
|
1911
1934
|
}
|
|
1912
|
-
|
|
1913
|
-
updatePendingInputRequests(pendingInputRequests, event);
|
|
1914
|
-
reachedBoundary = isTurnSegmentBoundary(event, pendingInputRequests) && (event.type !== "session.waiting" || pendingAuthorizations.size === 0);
|
|
1935
|
+
reachedBoundary = segment.observe(event);
|
|
1915
1936
|
yield event;
|
|
1916
1937
|
if (reachedBoundary) break;
|
|
1917
1938
|
}
|
|
@@ -2176,117 +2197,6 @@ function withRedirectPolicy(init, redirect) {
|
|
|
2176
2197
|
};
|
|
2177
2198
|
}
|
|
2178
2199
|
|
|
2179
|
-
//#endregion
|
|
2180
|
-
//#region src/client/session-event-stream.ts
|
|
2181
|
-
var SessionEventStream = class {
|
|
2182
|
-
#controller = new AbortController();
|
|
2183
|
-
#readers = /* @__PURE__ */ new Set();
|
|
2184
|
-
#caughtUp = Promise.withResolvers();
|
|
2185
|
-
caughtUp = this.#caughtUp.promise;
|
|
2186
|
-
#ended = false;
|
|
2187
|
-
#error;
|
|
2188
|
-
#headers;
|
|
2189
|
-
#reconnectPolicy;
|
|
2190
|
-
constructor(session, options) {
|
|
2191
|
-
this.setOptions(options);
|
|
2192
|
-
this.caughtUp.catch(() => {});
|
|
2193
|
-
if (!options.catchUp) this.#caughtUp.resolve();
|
|
2194
|
-
(async () => {
|
|
2195
|
-
try {
|
|
2196
|
-
for await (const event of followClientSession(session, {
|
|
2197
|
-
signal: this.#controller.signal,
|
|
2198
|
-
resolveHeaders: () => this.#headers,
|
|
2199
|
-
resolveReconnectPolicy: () => this.#reconnectPolicy,
|
|
2200
|
-
startIndex: options.startIndex,
|
|
2201
|
-
onCaughtUp: options.catchUp ? () => this.#caughtUp.resolve() : void 0
|
|
2202
|
-
})) {
|
|
2203
|
-
if (this.#controller.signal.aborted) return;
|
|
2204
|
-
options.onEvent(event);
|
|
2205
|
-
for (const reader of this.#readers) reader.push(event);
|
|
2206
|
-
if (event.type === "session.completed" || event.type === "session.failed") break;
|
|
2207
|
-
}
|
|
2208
|
-
this.#caughtUp.resolve();
|
|
2209
|
-
this.#finish();
|
|
2210
|
-
} catch (error) {
|
|
2211
|
-
this.#caughtUp.reject(error);
|
|
2212
|
-
this.#finish(error);
|
|
2213
|
-
if (!this.#controller.signal.aborted) options.onError(error);
|
|
2214
|
-
}
|
|
2215
|
-
})();
|
|
2216
|
-
}
|
|
2217
|
-
subscribe(signal) {
|
|
2218
|
-
const reader = new SessionEventReader(() => this.#readers.delete(reader), signal);
|
|
2219
|
-
if (this.#ended) reader.end(this.#error);
|
|
2220
|
-
else this.#readers.add(reader);
|
|
2221
|
-
return reader;
|
|
2222
|
-
}
|
|
2223
|
-
get ended() {
|
|
2224
|
-
return this.#ended;
|
|
2225
|
-
}
|
|
2226
|
-
setOptions(options) {
|
|
2227
|
-
if ("headers" in options) this.#headers = options.headers;
|
|
2228
|
-
if ("streamReconnectPolicy" in options) this.#reconnectPolicy = options.streamReconnectPolicy;
|
|
2229
|
-
}
|
|
2230
|
-
close() {
|
|
2231
|
-
const error = new DOMException("Session stream was detached.", "AbortError");
|
|
2232
|
-
this.#controller.abort(error);
|
|
2233
|
-
this.#caughtUp.reject(error);
|
|
2234
|
-
this.#finish(error);
|
|
2235
|
-
}
|
|
2236
|
-
#finish(error) {
|
|
2237
|
-
if (this.#ended) return;
|
|
2238
|
-
this.#ended = true;
|
|
2239
|
-
this.#error = error;
|
|
2240
|
-
for (const reader of this.#readers) reader.end(error);
|
|
2241
|
-
}
|
|
2242
|
-
};
|
|
2243
|
-
var SessionEventReader = class {
|
|
2244
|
-
#events = [];
|
|
2245
|
-
#wake = Promise.withResolvers();
|
|
2246
|
-
#ended = false;
|
|
2247
|
-
#error;
|
|
2248
|
-
#dispose;
|
|
2249
|
-
constructor(unsubscribe, signal) {
|
|
2250
|
-
const abort = () => this.end(signal?.reason);
|
|
2251
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
2252
|
-
this.#dispose = () => {
|
|
2253
|
-
signal?.removeEventListener("abort", abort);
|
|
2254
|
-
unsubscribe();
|
|
2255
|
-
};
|
|
2256
|
-
if (signal?.aborted) abort();
|
|
2257
|
-
}
|
|
2258
|
-
push(event) {
|
|
2259
|
-
if (this.#ended) return;
|
|
2260
|
-
this.#events.push(event);
|
|
2261
|
-
this.#wake.resolve();
|
|
2262
|
-
}
|
|
2263
|
-
end(error) {
|
|
2264
|
-
if (this.#ended) return;
|
|
2265
|
-
this.#ended = true;
|
|
2266
|
-
this.#error = error;
|
|
2267
|
-
this.#wake.resolve();
|
|
2268
|
-
}
|
|
2269
|
-
[Symbol.dispose]() {
|
|
2270
|
-
this.end();
|
|
2271
|
-
this.#events = [];
|
|
2272
|
-
this.#dispose();
|
|
2273
|
-
}
|
|
2274
|
-
discard() {
|
|
2275
|
-
this.#events = [];
|
|
2276
|
-
}
|
|
2277
|
-
async *[Symbol.asyncIterator]() {
|
|
2278
|
-
for (;;) {
|
|
2279
|
-
while (this.#events.length > 0) yield this.#events.shift();
|
|
2280
|
-
if (this.#ended) {
|
|
2281
|
-
if (this.#error !== void 0) throw this.#error;
|
|
2282
|
-
return;
|
|
2283
|
-
}
|
|
2284
|
-
this.#wake = Promise.withResolvers();
|
|
2285
|
-
await this.#wake.promise;
|
|
2286
|
-
}
|
|
2287
|
-
}
|
|
2288
|
-
};
|
|
2289
|
-
|
|
2290
2200
|
//#endregion
|
|
2291
2201
|
//#region src/client/eve-agent-projection.ts
|
|
2292
2202
|
var EveAgentProjection = class {
|
|
@@ -2295,18 +2205,21 @@ var EveAgentProjection = class {
|
|
|
2295
2205
|
#data;
|
|
2296
2206
|
constructor(reducer, events) {
|
|
2297
2207
|
this.#reducer = reducer;
|
|
2298
|
-
this.#events = events;
|
|
2208
|
+
this.#events = [...events];
|
|
2299
2209
|
this.#data = this.#reduce();
|
|
2300
2210
|
}
|
|
2301
2211
|
get data() {
|
|
2302
2212
|
return this.#data;
|
|
2303
2213
|
}
|
|
2214
|
+
get reducer() {
|
|
2215
|
+
return this.#reducer;
|
|
2216
|
+
}
|
|
2304
2217
|
reset() {
|
|
2305
2218
|
this.#events = [];
|
|
2306
2219
|
this.#data = this.#reducer.initial();
|
|
2307
2220
|
}
|
|
2308
2221
|
append(event) {
|
|
2309
|
-
this.#events
|
|
2222
|
+
this.#events.push(event);
|
|
2310
2223
|
this.#data = this.#reducer.reduce(this.#data, event);
|
|
2311
2224
|
}
|
|
2312
2225
|
remove(predicate) {
|
|
@@ -2315,7 +2228,8 @@ var EveAgentProjection = class {
|
|
|
2315
2228
|
}
|
|
2316
2229
|
replace(predicate, replacement) {
|
|
2317
2230
|
const index = this.#events.findIndex(predicate);
|
|
2318
|
-
|
|
2231
|
+
if (index === -1) this.#events.push(replacement);
|
|
2232
|
+
else this.#events[index] = replacement;
|
|
2319
2233
|
this.#data = this.#reduce();
|
|
2320
2234
|
}
|
|
2321
2235
|
#reduce() {
|
|
@@ -2325,18 +2239,68 @@ var EveAgentProjection = class {
|
|
|
2325
2239
|
}
|
|
2326
2240
|
};
|
|
2327
2241
|
|
|
2242
|
+
//#endregion
|
|
2243
|
+
//#region src/client/conversation-state.ts
|
|
2244
|
+
function openConversationInputs(state) {
|
|
2245
|
+
return Object.values(state.inputs).filter((input) => input.status === "open");
|
|
2246
|
+
}
|
|
2247
|
+
function conversationAuthorizations(state) {
|
|
2248
|
+
return state.messages.flatMap((message) => message.role === "assistant" ? message.parts.filter((part) => part.type === "authorization") : []);
|
|
2249
|
+
}
|
|
2250
|
+
function hasPendingAuthorizations(state) {
|
|
2251
|
+
return conversationAuthorizations(state).some((part) => part.state === "required" && part.awaitsCallback === true);
|
|
2252
|
+
}
|
|
2253
|
+
function agentToolTask(state, agent) {
|
|
2254
|
+
const task = agent.taskId === void 0 ? void 0 : state.tasks[agent.taskId];
|
|
2255
|
+
return task?.kind === "agent" ? task : void 0;
|
|
2256
|
+
}
|
|
2257
|
+
function isAgentSessionCaughtUp(state, agent) {
|
|
2258
|
+
if (agent.observation.status !== "following" && agent.observation.status !== "idle") return false;
|
|
2259
|
+
const task = agentToolTask(state, agent);
|
|
2260
|
+
if (task === void 0) return false;
|
|
2261
|
+
const calls = Object.values(task.calls);
|
|
2262
|
+
if (calls.some((call) => call.status === "working")) return false;
|
|
2263
|
+
const child = agent.observation.conversation;
|
|
2264
|
+
if (child.activeTurnId !== void 0) return false;
|
|
2265
|
+
if (Object.values(child.inputs).some((input) => input.status !== "settled")) return false;
|
|
2266
|
+
if (hasPendingAuthorizations(child)) return false;
|
|
2267
|
+
return child.messages.filter((message) => message.role === "user").length >= calls.filter((call) => call.status === "completed").length;
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2328
2270
|
//#endregion
|
|
2329
2271
|
//#region src/client/eve-agent-store-helpers.ts
|
|
2330
|
-
function
|
|
2272
|
+
function activeTurnForOptimisticFollowUp(events) {
|
|
2273
|
+
const lastTurn = events.findLast((event) => event.type === "turn.started" || event.type === "turn.completed" || event.type === "turn.failed" || event.type === "turn.cancelled" || isCurrentTurnBoundaryEvent(event));
|
|
2274
|
+
return lastTurn?.type === "turn.started" ? lastTurn.data.turnId : void 0;
|
|
2275
|
+
}
|
|
2276
|
+
function isResponseBoundary(event, conversation) {
|
|
2277
|
+
return endsTurnSegment(event, {
|
|
2278
|
+
callbacks: hasPendingAuthorizations(conversation),
|
|
2279
|
+
requests: Object.values(conversation.inputs).some((input) => input.status !== "settled")
|
|
2280
|
+
});
|
|
2281
|
+
}
|
|
2282
|
+
function settledStatus(error, conversation) {
|
|
2283
|
+
if (error !== void 0) return "error";
|
|
2284
|
+
return conversation.activeTurnId === void 0 ? "ready" : "streaming";
|
|
2285
|
+
}
|
|
2286
|
+
function isSettledSessionTail(events, conversation) {
|
|
2331
2287
|
const tail = events.at(-1);
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
for (const
|
|
2336
|
-
|
|
2337
|
-
|
|
2288
|
+
return tail !== void 0 && isResponseBoundary(tail, conversation);
|
|
2289
|
+
}
|
|
2290
|
+
function assertAnswerable(input, conversation) {
|
|
2291
|
+
for (const { requestId } of input.inputResponses ?? []) {
|
|
2292
|
+
const status = conversation.inputs[requestId]?.status;
|
|
2293
|
+
if (status !== void 0 && status !== "open") throw new Error(`Input request ${requestId} was already answered.`);
|
|
2338
2294
|
}
|
|
2339
|
-
|
|
2295
|
+
}
|
|
2296
|
+
function assertInFlightFollowUp(input) {
|
|
2297
|
+
if (input.inputResponses !== void 0) return;
|
|
2298
|
+
if (input.message === void 0 || input.turnPolicy !== "steer") throw new Error("eve session is already processing a turn. Send a message with turnPolicy: \"steer\" to guide it at the next boundary, or answer an open input request.");
|
|
2299
|
+
}
|
|
2300
|
+
function validateFollowUp(input) {
|
|
2301
|
+
assertExclusiveTurnInput(input);
|
|
2302
|
+
assertInFlightFollowUp(input);
|
|
2303
|
+
return input;
|
|
2340
2304
|
}
|
|
2341
2305
|
function assertExclusiveTurnInput(input) {
|
|
2342
2306
|
if (input.message !== void 0 === (input.inputResponses !== void 0)) throw new Error("A turn requires exactly one of message or inputResponses.");
|
|
@@ -2385,16 +2349,25 @@ function createActiveTurn(cancel) {
|
|
|
2385
2349
|
};
|
|
2386
2350
|
return turn;
|
|
2387
2351
|
}
|
|
2352
|
+
function countFollowUpDeliveries(turn, reconciliation) {
|
|
2353
|
+
let followed = 0;
|
|
2354
|
+
for (const id of reconciliation.ids) if (turn.followUpSubmissionIds.delete(id)) followed += 1;
|
|
2355
|
+
if (followed === 0) return;
|
|
2356
|
+
if (reconciliation.alreadyProjected) turn.receivedFollowUps += followed;
|
|
2357
|
+
else {
|
|
2358
|
+
const previous = turn.receivedFollowUpEvents.get(reconciliation.event) ?? 0;
|
|
2359
|
+
turn.receivedFollowUpEvents.set(reconciliation.event, previous + followed);
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2388
2362
|
async function followSteeredTurns(turn, events, isActive) {
|
|
2389
2363
|
while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
|
|
2390
2364
|
if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
|
|
2391
|
-
const
|
|
2365
|
+
const segment = new TurnSegment({ followCallbacks: true });
|
|
2392
2366
|
for await (const event of events) {
|
|
2393
2367
|
if (!isActive()) return;
|
|
2394
2368
|
turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
|
|
2395
2369
|
turn.receivedFollowUpEvents.delete(event);
|
|
2396
|
-
|
|
2397
|
-
if (isTurnSegmentBoundary(event, pendingInputRequests)) {
|
|
2370
|
+
if (segment.observe(event)) {
|
|
2398
2371
|
while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
|
|
2399
2372
|
if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
|
|
2400
2373
|
}
|
|
@@ -2417,43 +2390,52 @@ async function waitWithSignal(promise, signal) {
|
|
|
2417
2390
|
//#region src/client/optimistic-message-submissions.ts
|
|
2418
2391
|
var OptimisticMessageSubmissions = class {
|
|
2419
2392
|
#optimistic;
|
|
2420
|
-
#
|
|
2393
|
+
#projections;
|
|
2421
2394
|
#pending = [];
|
|
2422
|
-
constructor(
|
|
2423
|
-
this.#
|
|
2395
|
+
constructor(projections, optimistic) {
|
|
2396
|
+
this.#projections = projections;
|
|
2424
2397
|
this.#optimistic = optimistic;
|
|
2425
2398
|
}
|
|
2426
2399
|
reset() {
|
|
2427
2400
|
this.#pending = [];
|
|
2428
2401
|
}
|
|
2429
|
-
submit(input, eventStartIndex) {
|
|
2402
|
+
submit(input, eventStartIndex, turnId) {
|
|
2430
2403
|
if (input.message === void 0) return void 0;
|
|
2431
2404
|
const pending = {
|
|
2432
2405
|
createdAt: Date.now(),
|
|
2433
2406
|
eventStartIndex,
|
|
2434
2407
|
id: createSubmissionId(),
|
|
2435
2408
|
message: summarizeUserContent(input.message),
|
|
2409
|
+
turnId,
|
|
2436
2410
|
requiresDeliveryId: true
|
|
2437
2411
|
};
|
|
2438
2412
|
this.#pending = [...this.#pending, pending];
|
|
2439
|
-
if (this.#optimistic) this.#projection.append({
|
|
2413
|
+
if (this.#optimistic) for (const projection of this.#projections) projection.append({
|
|
2440
2414
|
data: {
|
|
2441
2415
|
createdAt: pending.createdAt,
|
|
2442
2416
|
message: pending.message,
|
|
2443
|
-
submissionId: pending.id
|
|
2417
|
+
submissionId: pending.id,
|
|
2418
|
+
turnId
|
|
2444
2419
|
},
|
|
2445
2420
|
type: "client.message.submitted"
|
|
2446
2421
|
});
|
|
2447
2422
|
return pending.id;
|
|
2448
2423
|
}
|
|
2424
|
+
resubmit(submissionId, input) {
|
|
2425
|
+
const pending = this.#pending.find((candidate) => candidate.id === submissionId);
|
|
2426
|
+
const message = input.message === void 0 ? void 0 : summarizeUserContent(input.message);
|
|
2427
|
+
if (pending?.message === message) return submissionId;
|
|
2428
|
+
if (pending !== void 0) this.#withdraw([pending.id]);
|
|
2429
|
+
return this.submit(input, pending?.eventStartIndex ?? 0, pending?.turnId);
|
|
2430
|
+
}
|
|
2449
2431
|
apply(event) {
|
|
2450
2432
|
if (event.type !== "message.received") {
|
|
2451
|
-
this.#projection.append(event);
|
|
2433
|
+
for (const projection of this.#projections) projection.append(event);
|
|
2452
2434
|
return;
|
|
2453
2435
|
}
|
|
2454
2436
|
const matching = this.#matching(event);
|
|
2455
2437
|
if (matching.length === 0) {
|
|
2456
|
-
this.#projection.append(event);
|
|
2438
|
+
for (const projection of this.#projections) projection.append(event);
|
|
2457
2439
|
return;
|
|
2458
2440
|
}
|
|
2459
2441
|
return this.#reconcile(matching, event, false);
|
|
@@ -2477,12 +2459,13 @@ var OptimisticMessageSubmissions = class {
|
|
|
2477
2459
|
const pending = submissionId === void 0 ? this.#pending[0] : this.#pending.find((candidate) => candidate.id === submissionId);
|
|
2478
2460
|
if (pending === void 0) return;
|
|
2479
2461
|
this.#pending = this.#pending.filter((candidate) => candidate.id !== pending.id);
|
|
2480
|
-
this.#projection.replace((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
|
|
2462
|
+
for (const projection of this.#projections) projection.replace((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
|
|
2481
2463
|
data: {
|
|
2482
2464
|
createdAt: pending.createdAt,
|
|
2483
2465
|
error: { message: error.message },
|
|
2484
2466
|
message: pending.message,
|
|
2485
|
-
submissionId: pending.id
|
|
2467
|
+
submissionId: pending.id,
|
|
2468
|
+
turnId: pending.turnId
|
|
2486
2469
|
},
|
|
2487
2470
|
type: "client.message.failed"
|
|
2488
2471
|
});
|
|
@@ -2495,1188 +2478,1840 @@ var OptimisticMessageSubmissions = class {
|
|
|
2495
2478
|
}
|
|
2496
2479
|
#reconcile(submissions, event, alreadyProjected) {
|
|
2497
2480
|
const ids = submissions.map((pending) => pending.id);
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
if (alreadyProjected) this.#projection.remove((candidate) => candidate.type === "client.message.submitted" && idSet.has(candidate.data.submissionId));
|
|
2501
|
-
else {
|
|
2502
|
-
this.#projection.replace((candidate) => candidate.type === "client.message.submitted" && candidate.data.submissionId === ids[0], event);
|
|
2503
|
-
this.#projection.remove((candidate) => candidate.type === "client.message.submitted" && idSet.has(candidate.data.submissionId));
|
|
2504
|
-
}
|
|
2481
|
+
this.#withdraw(ids);
|
|
2482
|
+
if (!alreadyProjected) for (const projection of this.#projections) projection.append(event);
|
|
2505
2483
|
return {
|
|
2506
2484
|
alreadyProjected,
|
|
2507
2485
|
event,
|
|
2508
2486
|
ids
|
|
2509
2487
|
};
|
|
2510
2488
|
}
|
|
2489
|
+
#withdraw(ids) {
|
|
2490
|
+
const idSet = new Set(ids);
|
|
2491
|
+
this.#pending = this.#pending.filter((pending) => !idSet.has(pending.id));
|
|
2492
|
+
for (const projection of this.#projections) projection.remove((candidate) => candidate.type === "client.message.submitted" && idSet.has(candidate.data.submissionId));
|
|
2493
|
+
}
|
|
2511
2494
|
};
|
|
2512
2495
|
|
|
2513
2496
|
//#endregion
|
|
2514
|
-
//#region src/
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2497
|
+
//#region src/client/agent-stream-follower.ts
|
|
2498
|
+
const agentStreamReconnectPolicy = {
|
|
2499
|
+
streamIdleReconnectPolicy: { maxAttempts: Infinity },
|
|
2500
|
+
streamOpenReconnectPolicy: { maxAttempts: Infinity }
|
|
2501
|
+
};
|
|
2502
|
+
var AgentStreamFollower = class {
|
|
2503
|
+
#options;
|
|
2504
|
+
#started = /* @__PURE__ */ new Map();
|
|
2505
|
+
#controllers = /* @__PURE__ */ new Map();
|
|
2506
|
+
#failed = /* @__PURE__ */ new Set();
|
|
2507
|
+
#disposed = false;
|
|
2508
|
+
constructor(options) {
|
|
2509
|
+
this.#options = options;
|
|
2510
|
+
}
|
|
2511
|
+
acceptParentEvent(event) {
|
|
2512
|
+
if (event.type === "agent.started") this.#started.set(event.data.sessionId, event);
|
|
2513
|
+
}
|
|
2514
|
+
reconcile() {
|
|
2515
|
+
if (this.#disposed) return;
|
|
2516
|
+
const state = this.#options.getState();
|
|
2517
|
+
for (const agent of Object.values(state.agents)) {
|
|
2518
|
+
if (agentToolTask(state, agent) === void 0) continue;
|
|
2519
|
+
const controller = this.#controllers.get(agent.sessionId);
|
|
2520
|
+
const caughtUp = isAgentSessionCaughtUp(state, agent);
|
|
2521
|
+
if (controller !== void 0 && caughtUp) {
|
|
2522
|
+
this.#controllers.delete(agent.sessionId);
|
|
2523
|
+
controller.abort();
|
|
2524
|
+
this.#options.onIdle(agent.sessionId);
|
|
2525
|
+
} else if (controller === void 0 && !caughtUp && !this.#failed.has(agent.sessionId)) this.#follow(agent.sessionId);
|
|
2527
2526
|
}
|
|
2528
|
-
};
|
|
2529
|
-
}
|
|
2530
|
-
|
|
2531
|
-
//#endregion
|
|
2532
|
-
//#region src/client/eve-agent-store.ts
|
|
2533
|
-
const detachStore = Symbol("detachEveAgentStore");
|
|
2534
|
-
const attachStore = Symbol("attachEveAgentStore");
|
|
2535
|
-
var EveAgentStore = class {
|
|
2536
|
-
#client;
|
|
2537
|
-
#autoPrewarm;
|
|
2538
|
-
#attached = false;
|
|
2539
|
-
#stream;
|
|
2540
|
-
#pendingAuthorizations = /* @__PURE__ */ new Set();
|
|
2541
|
-
#pendingInputRequests = /* @__PURE__ */ new Set();
|
|
2542
|
-
#externalSession;
|
|
2543
|
-
#optimistic;
|
|
2544
|
-
#projection;
|
|
2545
|
-
#subscribers = /* @__PURE__ */ new Set();
|
|
2546
|
-
#seenEvents = createEventDeduper();
|
|
2547
|
-
#activeTurn;
|
|
2548
|
-
#callbacks = {};
|
|
2549
|
-
#error;
|
|
2550
|
-
#events;
|
|
2551
|
-
#messageSubmissions;
|
|
2552
|
-
#prewarmGeneration = 0;
|
|
2553
|
-
#prewarmPromise;
|
|
2554
|
-
#prewarmController;
|
|
2555
|
-
#resumePromise;
|
|
2556
|
-
#session;
|
|
2557
|
-
#snapshot;
|
|
2558
|
-
#status = "ready";
|
|
2559
|
-
constructor(init) {
|
|
2560
|
-
this.#autoPrewarm = init.prewarm ?? false;
|
|
2561
|
-
this.#externalSession = init.session !== void 0;
|
|
2562
|
-
this.#client = this.#externalSession ? void 0 : new Client({
|
|
2563
|
-
auth: init.auth,
|
|
2564
|
-
headers: init.headers,
|
|
2565
|
-
host: init.host ?? ""
|
|
2566
|
-
});
|
|
2567
|
-
const initialEvents = [];
|
|
2568
|
-
for (const event of init.initialEvents ?? []) {
|
|
2569
|
-
if (this.#seenEvents.admit(event)) initialEvents.push(event);
|
|
2570
|
-
this.#trackPendingRequests(event);
|
|
2571
|
-
}
|
|
2572
|
-
this.#events = initialEvents;
|
|
2573
|
-
this.#projection = new EveAgentProjection(init.reducer, this.#events);
|
|
2574
|
-
this.#optimistic = init.optimistic ?? true;
|
|
2575
|
-
this.#messageSubmissions = new OptimisticMessageSubmissions(this.#projection, this.#optimistic);
|
|
2576
|
-
this.#session = init.session ?? (init.initialSession === void 0 ? void 0 : this.#client?.sessions.attach(init.initialSession.sessionId, { streamIndex: init.initialSession.streamIndex }));
|
|
2577
|
-
this.#snapshot = this.#createSnapshot();
|
|
2578
|
-
}
|
|
2579
|
-
get snapshot() {
|
|
2580
|
-
return this.#snapshot;
|
|
2581
2527
|
}
|
|
2582
|
-
|
|
2583
|
-
this.#
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
this.#subscribers.add(callback);
|
|
2587
|
-
return () => {
|
|
2588
|
-
this.#subscribers.delete(callback);
|
|
2589
|
-
};
|
|
2528
|
+
abortAll() {
|
|
2529
|
+
this.#disposed = true;
|
|
2530
|
+
for (const controller of this.#controllers.values()) controller.abort();
|
|
2531
|
+
this.#controllers.clear();
|
|
2590
2532
|
}
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
if (
|
|
2594
|
-
if (this.#activeTurn !== void 0) return this.#activeTurn.response.then((response) => {
|
|
2595
|
-
if (response === void 0) throw this.#error ?? new DOMException("Session creation was aborted.", "AbortError");
|
|
2596
|
-
});
|
|
2597
|
-
const client = this.#client;
|
|
2598
|
-
if (client === void 0) return Promise.reject(/* @__PURE__ */ new Error("This eve agent store does not own a session client."));
|
|
2599
|
-
const generation = this.#prewarmGeneration;
|
|
2533
|
+
#follow(sessionId) {
|
|
2534
|
+
const started = this.#started.get(sessionId);
|
|
2535
|
+
if (started === void 0) return;
|
|
2600
2536
|
const controller = new AbortController();
|
|
2601
|
-
this.#
|
|
2602
|
-
|
|
2537
|
+
this.#controllers.set(sessionId, controller);
|
|
2538
|
+
this.#options.onFollowing(sessionId);
|
|
2539
|
+
const { cursors } = this.#options;
|
|
2540
|
+
(async () => {
|
|
2541
|
+
let cursor = cursors.get(sessionId) ?? 0;
|
|
2603
2542
|
try {
|
|
2604
|
-
const
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) {
|
|
2614
|
-
this.#error = toError(error);
|
|
2615
|
-
this.#status = "error";
|
|
2616
|
-
this.#callbacks.onError?.(this.#error);
|
|
2617
|
-
this.#publish();
|
|
2543
|
+
for await (const event of this.#options.session.agent(started).stream({
|
|
2544
|
+
signal: controller.signal,
|
|
2545
|
+
startIndex: cursor,
|
|
2546
|
+
streamReconnectPolicy: agentStreamReconnectPolicy
|
|
2547
|
+
})) {
|
|
2548
|
+
if (controller.signal.aborted) return;
|
|
2549
|
+
cursors.set(sessionId, ++cursor);
|
|
2550
|
+
this.#options.onEvent(sessionId, event);
|
|
2551
|
+
this.reconcile();
|
|
2618
2552
|
}
|
|
2619
|
-
|
|
2620
|
-
|
|
2553
|
+
} catch {}
|
|
2554
|
+
if (controller.signal.aborted || this.#controllers.get(sessionId) !== controller) return;
|
|
2555
|
+
this.#controllers.delete(sessionId);
|
|
2556
|
+
this.#failed.add(sessionId);
|
|
2557
|
+
this.#options.onUnavailable(sessionId);
|
|
2621
2558
|
})();
|
|
2622
|
-
this.#prewarmPromise = promise;
|
|
2623
|
-
const clear = () => {
|
|
2624
|
-
if (this.#prewarmPromise === promise) {
|
|
2625
|
-
this.#prewarmPromise = void 0;
|
|
2626
|
-
this.#prewarmController = void 0;
|
|
2627
|
-
}
|
|
2628
|
-
};
|
|
2629
|
-
promise.then(clear, clear);
|
|
2630
|
-
return promise;
|
|
2631
|
-
}
|
|
2632
|
-
async send(input) {
|
|
2633
|
-
return await this.#submit(input, this.#callbacks.prepareSend);
|
|
2634
2559
|
}
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2560
|
+
};
|
|
2561
|
+
|
|
2562
|
+
//#endregion
|
|
2563
|
+
//#region src/client/authorization-message-parts.ts
|
|
2564
|
+
function createAuthorizationRequiredPart(event) {
|
|
2565
|
+
const displayName = event.data.authorization?.displayName ?? formatAuthorizationDisplayName(event.data.name);
|
|
2566
|
+
const part = {
|
|
2567
|
+
authorization: event.data.authorization,
|
|
2568
|
+
description: normalizeAuthorizationDescription(event.data.description, event.data.name, displayName),
|
|
2569
|
+
displayName,
|
|
2570
|
+
name: event.data.name,
|
|
2571
|
+
state: "required",
|
|
2572
|
+
stepIndex: event.data.stepIndex,
|
|
2573
|
+
turnId: event.data.turnId,
|
|
2574
|
+
type: "authorization"
|
|
2575
|
+
};
|
|
2576
|
+
if (event.data.attemptId !== void 0) part.attemptId = event.data.attemptId;
|
|
2577
|
+
if (event.data.webhookUrl !== void 0) part.awaitsCallback = true;
|
|
2578
|
+
return part;
|
|
2579
|
+
}
|
|
2580
|
+
function createAuthorizationCompletedPart(event, existing) {
|
|
2581
|
+
const displayName = event.data.authorization?.displayName ?? existing?.displayName ?? formatAuthorizationDisplayName(event.data.name);
|
|
2582
|
+
const part = {
|
|
2583
|
+
authorization: existing?.authorization || event.data.authorization ? {
|
|
2584
|
+
...existing?.authorization,
|
|
2585
|
+
...event.data.authorization
|
|
2586
|
+
} : void 0,
|
|
2587
|
+
description: existing?.description ?? buildCompletedAuthorizationDescription(displayName, event.data.outcome, event.data.reason),
|
|
2588
|
+
displayName,
|
|
2589
|
+
name: event.data.name,
|
|
2590
|
+
outcome: event.data.outcome,
|
|
2591
|
+
state: "completed",
|
|
2592
|
+
stepIndex: existing?.stepIndex ?? event.data.stepIndex,
|
|
2593
|
+
turnId: existing?.turnId ?? event.data.turnId,
|
|
2594
|
+
type: "authorization"
|
|
2595
|
+
};
|
|
2596
|
+
const attemptId = event.data.attemptId ?? existing?.attemptId;
|
|
2597
|
+
if (attemptId !== void 0) part.attemptId = attemptId;
|
|
2598
|
+
if (existing?.awaitsCallback) part.awaitsCallback = true;
|
|
2599
|
+
if (event.data.reason !== void 0) part.reason = event.data.reason;
|
|
2600
|
+
return part;
|
|
2601
|
+
}
|
|
2602
|
+
function buildCompletedAuthorizationDescription(displayName, outcome, reason) {
|
|
2603
|
+
if (outcome === "authorized") return `${displayName} connected.`;
|
|
2604
|
+
return `${displayName} authorization ${outcome}${reason !== void 0 ? ` (${reason})` : ""}.`;
|
|
2605
|
+
}
|
|
2606
|
+
function normalizeAuthorizationDescription(description, name, displayName) {
|
|
2607
|
+
if (description === `Authorization required for ${name}`) return `Authorization required for ${displayName}`;
|
|
2608
|
+
return description;
|
|
2609
|
+
}
|
|
2610
|
+
function formatAuthorizationDisplayName(name) {
|
|
2611
|
+
if (name.length === 0) return name;
|
|
2612
|
+
return `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
//#endregion
|
|
2616
|
+
//#region src/shared/action-request-name.ts
|
|
2617
|
+
function actionRequestName(action) {
|
|
2618
|
+
switch (action.kind) {
|
|
2619
|
+
case "load-skill": return "load_skill";
|
|
2620
|
+
case "subagent-call": return action.subagentName;
|
|
2621
|
+
case "remote-agent-call": return action.remoteAgentName;
|
|
2622
|
+
case "tool-call":
|
|
2623
|
+
case "workflow-tool-call": return action.toolName;
|
|
2688
2624
|
}
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
//#endregion
|
|
2628
|
+
//#region src/client/message-action-parts.ts
|
|
2629
|
+
function toMessageInputRequest(request) {
|
|
2630
|
+
return {
|
|
2631
|
+
allowFreeform: request.allowFreeform,
|
|
2632
|
+
display: request.display,
|
|
2633
|
+
kind: request.kind,
|
|
2634
|
+
options: request.options,
|
|
2635
|
+
prompt: request.prompt,
|
|
2636
|
+
requestId: request.requestId
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
function createToolMetadata(descriptor, extra) {
|
|
2640
|
+
return { eve: {
|
|
2641
|
+
inputRequest: extra?.inputRequest,
|
|
2642
|
+
kind: descriptor.kind,
|
|
2643
|
+
name: descriptor.name
|
|
2644
|
+
} };
|
|
2645
|
+
}
|
|
2646
|
+
function mergeToolMetadata(current, next) {
|
|
2647
|
+
const kind = next.eve?.kind ?? current?.eve?.kind ?? "unknown";
|
|
2648
|
+
const name = next.eve?.name ?? current?.eve?.name ?? "unknown";
|
|
2649
|
+
return { eve: {
|
|
2650
|
+
...current?.eve,
|
|
2651
|
+
...next.eve,
|
|
2652
|
+
inputRequest: next.eve?.inputRequest ?? current?.eve?.inputRequest,
|
|
2653
|
+
inputResponse: next.eve?.inputResponse ?? current?.eve?.inputResponse,
|
|
2654
|
+
kind,
|
|
2655
|
+
name
|
|
2656
|
+
} };
|
|
2657
|
+
}
|
|
2658
|
+
function approvedApproval(part) {
|
|
2659
|
+
if (!part?.approval?.id) return;
|
|
2660
|
+
return {
|
|
2661
|
+
approved: true,
|
|
2662
|
+
id: part.approval.id,
|
|
2663
|
+
isAutomatic: part.approval.isAutomatic,
|
|
2664
|
+
reason: part.approval.reason
|
|
2665
|
+
};
|
|
2666
|
+
}
|
|
2667
|
+
function normalizeActionRequest(action) {
|
|
2668
|
+
const name = actionRequestName(action);
|
|
2669
|
+
switch (action.kind) {
|
|
2670
|
+
case "load-skill": return {
|
|
2671
|
+
kind: "load-skill",
|
|
2672
|
+
name,
|
|
2673
|
+
toolName: "eve:load-skill"
|
|
2674
|
+
};
|
|
2675
|
+
case "tool-call":
|
|
2676
|
+
case "workflow-tool-call": return {
|
|
2677
|
+
kind: "tool-call",
|
|
2678
|
+
name,
|
|
2679
|
+
toolName: name
|
|
2680
|
+
};
|
|
2681
|
+
case "subagent-call":
|
|
2682
|
+
case "remote-agent-call": return {
|
|
2683
|
+
kind: "subagent-call",
|
|
2684
|
+
name,
|
|
2685
|
+
toolName: `eve:subagent:${name}`
|
|
2695
2686
|
};
|
|
2696
|
-
promise.then(clear, clear);
|
|
2697
|
-
return promise;
|
|
2698
|
-
}
|
|
2699
|
-
async #resume() {
|
|
2700
|
-
if (this.#status === "resuming" || this.#status === "streaming" || this.#status === "submitted") throw new Error("eve session is already processing a turn.");
|
|
2701
|
-
if (this.#session === void 0) throw new Error("An eve session is required before resuming.");
|
|
2702
|
-
const session = this.#session;
|
|
2703
|
-
const turn = createActiveTurn(() => session.cancel());
|
|
2704
|
-
this.#activeTurn = turn;
|
|
2705
|
-
turn.resolveResponse(void 0);
|
|
2706
|
-
this.#error = void 0;
|
|
2707
|
-
this.#status = "resuming";
|
|
2708
|
-
this.#publish();
|
|
2709
|
-
let reader;
|
|
2710
|
-
try {
|
|
2711
|
-
const stream = this.#ensureStream({
|
|
2712
|
-
catchUp: true,
|
|
2713
|
-
startIndex: this.#events.length === session.state.streamIndex ? session.state.streamIndex : 0
|
|
2714
|
-
});
|
|
2715
|
-
reader = stream.subscribe(turn.abortController.signal);
|
|
2716
|
-
await stream.caughtUp;
|
|
2717
|
-
if (!this.#isActiveTurn(turn)) return;
|
|
2718
|
-
reader.discard();
|
|
2719
|
-
const tail = this.#events.at(-1);
|
|
2720
|
-
if (tail !== void 0) this.#applyTerminalStreamFailure(tail);
|
|
2721
|
-
if (tail !== void 0 && this.#error === void 0 && !isSettledSessionTail(this.#events)) {
|
|
2722
|
-
this.#status = "streaming";
|
|
2723
|
-
this.#publish();
|
|
2724
|
-
for await (const event of reader) {
|
|
2725
|
-
if (!this.#isActiveTurn(turn)) return;
|
|
2726
|
-
turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
|
|
2727
|
-
turn.receivedFollowUpEvents.delete(event);
|
|
2728
|
-
if (this.#isSettledAt(event)) break;
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
|
|
2732
|
-
if (this.#isActiveTurn(turn)) this.#status = this.#error === void 0 ? "ready" : "error";
|
|
2733
|
-
} catch (error) {
|
|
2734
|
-
if (!this.#isActiveTurn(turn)) return;
|
|
2735
|
-
if (isAbortError(error)) this.#status = "ready";
|
|
2736
|
-
else {
|
|
2737
|
-
this.#error = toError(error);
|
|
2738
|
-
this.#status = "error";
|
|
2739
|
-
this.#callbacks.onError?.(this.#error);
|
|
2740
|
-
}
|
|
2741
|
-
} finally {
|
|
2742
|
-
reader?.[Symbol.dispose]();
|
|
2743
|
-
this.#finishTurn(turn);
|
|
2744
|
-
}
|
|
2745
|
-
}
|
|
2746
|
-
cancel() {
|
|
2747
|
-
const turn = this.#activeTurn;
|
|
2748
|
-
if (turn === void 0) return this.#status === "streaming" && this.#session !== void 0 ? this.#session.cancel() : Promise.resolve({ status: "no_active_turn" });
|
|
2749
|
-
return turn.cancel();
|
|
2750
|
-
}
|
|
2751
|
-
[attachStore]() {
|
|
2752
|
-
this.#attached = true;
|
|
2753
|
-
if (this.#autoPrewarm && this.#session === void 0) this.prewarm().catch(() => {});
|
|
2754
2687
|
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2688
|
+
}
|
|
2689
|
+
function normalizeActionResult(result) {
|
|
2690
|
+
switch (result.kind) {
|
|
2691
|
+
case "load-skill-result": return {
|
|
2692
|
+
kind: "load-skill",
|
|
2693
|
+
name: result.name ?? "load_skill",
|
|
2694
|
+
toolName: "eve:load-skill"
|
|
2695
|
+
};
|
|
2696
|
+
case "tool-result": return {
|
|
2697
|
+
kind: "tool-call",
|
|
2698
|
+
name: result.toolName,
|
|
2699
|
+
toolName: result.toolName
|
|
2700
|
+
};
|
|
2701
|
+
case "subagent-result": return {
|
|
2702
|
+
kind: "subagent-call",
|
|
2703
|
+
name: result.subagentName,
|
|
2704
|
+
toolName: `eve:subagent:${result.subagentName}`
|
|
2705
|
+
};
|
|
2762
2706
|
}
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
turn?.resolveResponse(void 0);
|
|
2771
|
-
turn?.resolveCompletion();
|
|
2772
|
-
turn?.abortController.abort();
|
|
2773
|
-
this.#resetPrewarm();
|
|
2774
|
-
this.#resumePromise = void 0;
|
|
2775
|
-
if (!this.#externalSession) this.#session = void 0;
|
|
2776
|
-
this.#events = [];
|
|
2777
|
-
this.#seenEvents = createEventDeduper();
|
|
2778
|
-
this.#messageSubmissions.reset();
|
|
2779
|
-
this.#projection.reset();
|
|
2780
|
-
this.#error = void 0;
|
|
2781
|
-
this.#status = "ready";
|
|
2782
|
-
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
2783
|
-
this.#publish();
|
|
2784
|
-
if (this.#autoPrewarm && this.#attached) this.prewarm().catch(() => {});
|
|
2707
|
+
}
|
|
2708
|
+
function stringifyUnknown(value) {
|
|
2709
|
+
if (typeof value === "string") return value;
|
|
2710
|
+
try {
|
|
2711
|
+
return JSON.stringify(value);
|
|
2712
|
+
} catch {
|
|
2713
|
+
return "Action failed.";
|
|
2785
2714
|
}
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
} catch (error) {
|
|
2816
|
-
if (this.#isActiveTurn(turn)) {
|
|
2817
|
-
this.#messageSubmissions.fail(toError(error), submissionId);
|
|
2818
|
-
this.#publish();
|
|
2819
|
-
}
|
|
2820
|
-
throw error;
|
|
2821
|
-
} finally {
|
|
2822
|
-
turn.followUpDispatches.delete(dispatch);
|
|
2823
|
-
}
|
|
2824
|
-
})();
|
|
2825
|
-
turn.followUpDispatches.add(dispatch);
|
|
2826
|
-
await dispatch;
|
|
2827
|
-
await turn.completion;
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
//#endregion
|
|
2718
|
+
//#region src/client/message-reducer-primitives.ts
|
|
2719
|
+
function projectReceivedParts(parts, message) {
|
|
2720
|
+
return parts?.map((part) => part.type === "text" ? {
|
|
2721
|
+
state: "done",
|
|
2722
|
+
text: part.text,
|
|
2723
|
+
type: "text"
|
|
2724
|
+
} : {
|
|
2725
|
+
filename: part.filename,
|
|
2726
|
+
mediaType: part.mediaType,
|
|
2727
|
+
size: part.size,
|
|
2728
|
+
type: "file",
|
|
2729
|
+
url: part.url
|
|
2730
|
+
}) ?? [{
|
|
2731
|
+
state: "done",
|
|
2732
|
+
text: message,
|
|
2733
|
+
type: "text"
|
|
2734
|
+
}];
|
|
2735
|
+
}
|
|
2736
|
+
function partKey(part) {
|
|
2737
|
+
switch (part.type) {
|
|
2738
|
+
case "text": return `text:${part.stepIndex ?? 0}`;
|
|
2739
|
+
case "reasoning": return `reasoning:${part.stepIndex ?? 0}`;
|
|
2740
|
+
case "file": return `file:${part.stepIndex ?? 0}:${part.filename ?? part.url ?? part.mediaType}`;
|
|
2741
|
+
case "step-start": return "step-start";
|
|
2742
|
+
case "authorization": return part.attemptId === void 0 ? `authorization:${part.turnId}:${part.stepIndex}:${part.name}` : `authorization:${part.attemptId}`;
|
|
2743
|
+
case "dynamic-tool": return `dynamic-tool:${part.toolCallId}`;
|
|
2828
2744
|
}
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2745
|
+
}
|
|
2746
|
+
function upsertMessage(data, next, beforeAssistantTurnId) {
|
|
2747
|
+
const index = data.messages.findIndex((message) => message.id === next.id);
|
|
2748
|
+
if (index !== -1) return {
|
|
2749
|
+
...data,
|
|
2750
|
+
messages: [
|
|
2751
|
+
...data.messages.slice(0, index),
|
|
2752
|
+
next,
|
|
2753
|
+
...data.messages.slice(index + 1)
|
|
2754
|
+
]
|
|
2755
|
+
};
|
|
2756
|
+
const before = beforeAssistantTurnId === void 0 ? -1 : data.messages.findIndex((message) => message.role === "assistant" && message.metadata?.turnId === beforeAssistantTurnId);
|
|
2757
|
+
if (before === -1) return {
|
|
2758
|
+
...data,
|
|
2759
|
+
messages: [...data.messages, next]
|
|
2760
|
+
};
|
|
2761
|
+
return {
|
|
2762
|
+
...data,
|
|
2763
|
+
messages: [
|
|
2764
|
+
...data.messages.slice(0, before),
|
|
2765
|
+
next,
|
|
2766
|
+
...data.messages.slice(before)
|
|
2767
|
+
]
|
|
2768
|
+
};
|
|
2769
|
+
}
|
|
2770
|
+
function optimisticUserMessageId(submissionId) {
|
|
2771
|
+
return `optimistic:${submissionId}:user`;
|
|
2772
|
+
}
|
|
2773
|
+
|
|
2774
|
+
//#endregion
|
|
2775
|
+
//#region src/client/message-run-parts.ts
|
|
2776
|
+
function transition(message, input) {
|
|
2777
|
+
const index = message.parts.findLastIndex((part) => part.type === input.type && part.stepIndex === input.stepIndex);
|
|
2778
|
+
const previous = index === -1 ? void 0 : message.parts[index];
|
|
2779
|
+
if (input.kind === "append" && !input.delta) return message;
|
|
2780
|
+
const current = previous?.state === "streaming" ? previous : void 0;
|
|
2781
|
+
const part = {
|
|
2782
|
+
id: current?.id ?? input.id ?? `${message.id}:${input.type}:${message.parts.length}`,
|
|
2783
|
+
state: input.kind === "append" ? "streaming" : "done",
|
|
2784
|
+
stepIndex: input.stepIndex,
|
|
2785
|
+
text: input.kind === "append" ? (current?.text ?? "") + input.delta : input.text,
|
|
2786
|
+
type: input.type
|
|
2787
|
+
};
|
|
2788
|
+
const parts = current ? [
|
|
2789
|
+
...message.parts.slice(0, index),
|
|
2790
|
+
part,
|
|
2791
|
+
...message.parts.slice(index + 1)
|
|
2792
|
+
] : [...message.parts, part];
|
|
2793
|
+
return {
|
|
2794
|
+
...message,
|
|
2795
|
+
metadata: {
|
|
2796
|
+
...message.metadata,
|
|
2797
|
+
status: input.type === "text" && part.state === "done" ? "complete" : "streaming"
|
|
2798
|
+
},
|
|
2799
|
+
parts
|
|
2800
|
+
};
|
|
2801
|
+
}
|
|
2802
|
+
const messageRun = { transition };
|
|
2803
|
+
|
|
2804
|
+
//#endregion
|
|
2805
|
+
//#region src/client/message-task-parts.ts
|
|
2806
|
+
function createSettledTaskPart(existing, event) {
|
|
2807
|
+
const settledPartBase = {
|
|
2808
|
+
approval: approvedApproval(existing),
|
|
2809
|
+
input: existing.input,
|
|
2810
|
+
stepIndex: existing.stepIndex,
|
|
2811
|
+
toolCallId: existing.toolCallId,
|
|
2812
|
+
toolMetadata: existing.toolMetadata,
|
|
2813
|
+
toolName: existing.toolName,
|
|
2814
|
+
type: "dynamic-tool"
|
|
2815
|
+
};
|
|
2816
|
+
switch (event.data.status) {
|
|
2817
|
+
case "completed": return {
|
|
2818
|
+
...settledPartBase,
|
|
2819
|
+
output: event.data.output,
|
|
2820
|
+
state: "output-available"
|
|
2833
2821
|
};
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2822
|
+
case "failed": return {
|
|
2823
|
+
...settledPartBase,
|
|
2824
|
+
errorText: event.data.error?.message ?? "Task failed.",
|
|
2825
|
+
state: "output-error"
|
|
2826
|
+
};
|
|
2827
|
+
case "cancelled": return {
|
|
2828
|
+
...settledPartBase,
|
|
2829
|
+
errorText: "Task was cancelled.",
|
|
2830
|
+
state: "output-error"
|
|
2831
|
+
};
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
//#endregion
|
|
2836
|
+
//#region src/client/message-reducer.ts
|
|
2837
|
+
function receivedMessageEventId(event) {
|
|
2838
|
+
return event.meta.id ?? `${event.data.turnId}:${event.data.sequence}`;
|
|
2839
|
+
}
|
|
2840
|
+
function defaultMessageReducer() {
|
|
2841
|
+
return {
|
|
2842
|
+
initial() {
|
|
2843
|
+
return { messages: [] };
|
|
2844
|
+
},
|
|
2845
|
+
reduce(data, event) {
|
|
2846
|
+
return reduceMessageData(data, event);
|
|
2839
2847
|
}
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2848
|
+
};
|
|
2849
|
+
}
|
|
2850
|
+
function reduceMessageData(data, event) {
|
|
2851
|
+
switch (event.type) {
|
|
2852
|
+
case "client.message.submitted":
|
|
2853
|
+
case "client.message.failed": return upsertMessage(data, {
|
|
2854
|
+
id: optimisticUserMessageId(event.data.submissionId),
|
|
2855
|
+
metadata: {
|
|
2856
|
+
optimistic: true,
|
|
2857
|
+
status: event.type === "client.message.failed" ? "failed" : "submitted"
|
|
2858
|
+
},
|
|
2859
|
+
parts: [{
|
|
2860
|
+
type: "text",
|
|
2861
|
+
text: event.data.message
|
|
2862
|
+
}],
|
|
2863
|
+
role: "user"
|
|
2864
|
+
}, event.data.turnId);
|
|
2865
|
+
case "input.resolved": {
|
|
2866
|
+
let next = data;
|
|
2867
|
+
for (const resolution of event.data.resolutions) next = resolveInputRequest(next, resolution);
|
|
2868
|
+
return next;
|
|
2869
|
+
}
|
|
2870
|
+
case "message.received": return upsertMessage(data, {
|
|
2871
|
+
id: `${receivedMessageEventId(event)}:user`,
|
|
2872
|
+
metadata: {
|
|
2873
|
+
status: "complete",
|
|
2874
|
+
turnId: event.data.turnId
|
|
2875
|
+
},
|
|
2876
|
+
parts: projectReceivedParts(event.data.parts, event.data.message),
|
|
2877
|
+
role: "user"
|
|
2878
|
+
}, event.data.turnId);
|
|
2879
|
+
case "step.started": return updateAssistantMessage(data, event.data.turnId, (message) => ensureStepStartPart(message, event.data.stepIndex));
|
|
2880
|
+
case "step.completed":
|
|
2881
|
+
if (data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === event.data.turnId) === void 0) return data;
|
|
2882
|
+
return updateAssistantMessage(data, event.data.turnId, (message) => ({
|
|
2883
|
+
...message,
|
|
2884
|
+
parts: closeStreamingRuns(message.parts, event.data.stepIndex)
|
|
2885
|
+
}));
|
|
2886
|
+
case "reasoning.appended": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.transition(ensureStepStartPart(message, event.data.stepIndex), {
|
|
2887
|
+
kind: "append",
|
|
2888
|
+
delta: event.data.reasoningDelta,
|
|
2889
|
+
id: event.meta?.id,
|
|
2890
|
+
stepIndex: event.data.stepIndex,
|
|
2891
|
+
type: "reasoning"
|
|
2892
|
+
}));
|
|
2893
|
+
case "reasoning.completed": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.transition(ensureStepStartPart(message, event.data.stepIndex), {
|
|
2894
|
+
kind: "complete",
|
|
2895
|
+
stepIndex: event.data.stepIndex,
|
|
2896
|
+
text: event.data.reasoning,
|
|
2897
|
+
id: event.meta?.id,
|
|
2898
|
+
type: "reasoning"
|
|
2899
|
+
}));
|
|
2900
|
+
case "action.input.appended": {
|
|
2901
|
+
const existing = findToolPart(data, event.data.callId);
|
|
2902
|
+
if (existing !== void 0 && existing.state !== "input-streaming") return data;
|
|
2903
|
+
const nextPart = {
|
|
2904
|
+
input: void 0,
|
|
2905
|
+
inputText: (existing?.state === "input-streaming" ? existing.inputText : "") + event.data.inputTextDelta,
|
|
2906
|
+
state: "input-streaming",
|
|
2907
|
+
stepIndex: event.data.stepIndex,
|
|
2908
|
+
toolCallId: event.data.callId,
|
|
2909
|
+
toolMetadata: existing?.toolMetadata ?? { eve: {
|
|
2910
|
+
kind: "unknown",
|
|
2911
|
+
name: event.data.toolName
|
|
2912
|
+
} },
|
|
2913
|
+
toolName: event.data.toolName,
|
|
2914
|
+
type: "dynamic-tool"
|
|
2854
2915
|
};
|
|
2916
|
+
return upsertToolPart(data, event.data.turnId, event.data.stepIndex, nextPart);
|
|
2855
2917
|
}
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
const
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2918
|
+
case "actions.requested": {
|
|
2919
|
+
let next = data;
|
|
2920
|
+
for (const action of event.data.actions) {
|
|
2921
|
+
const existing = findToolPart(next, action.callId);
|
|
2922
|
+
if (existing !== void 0 && existing.state !== "input-streaming") continue;
|
|
2923
|
+
const descriptor = normalizeActionRequest(action);
|
|
2924
|
+
next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
|
|
2925
|
+
input: "input" in action ? action.input : void 0,
|
|
2926
|
+
state: "input-available",
|
|
2927
|
+
stepIndex: event.data.stepIndex,
|
|
2928
|
+
toolCallId: action.callId,
|
|
2929
|
+
toolMetadata: createToolMetadata(descriptor),
|
|
2930
|
+
toolName: descriptor.toolName,
|
|
2931
|
+
type: "dynamic-tool"
|
|
2932
|
+
}));
|
|
2864
2933
|
}
|
|
2865
|
-
|
|
2866
|
-
return {
|
|
2867
|
-
response: await this.#session.respond(inputResponses, options),
|
|
2868
|
-
reader
|
|
2869
|
-
};
|
|
2870
|
-
} catch (error) {
|
|
2871
|
-
reader[Symbol.dispose]();
|
|
2872
|
-
throw error;
|
|
2934
|
+
return next;
|
|
2873
2935
|
}
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2936
|
+
case "input.requested": {
|
|
2937
|
+
let next = data;
|
|
2938
|
+
for (const request of event.data.requests) {
|
|
2939
|
+
const existing = findToolPart(next, request.action.callId);
|
|
2940
|
+
if (existing?.approval?.id === request.requestId || existing !== void 0 && isSettledToolPart(existing)) continue;
|
|
2941
|
+
const descriptor = normalizeActionRequest(request.action);
|
|
2942
|
+
next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
|
|
2943
|
+
approval: { id: request.requestId },
|
|
2944
|
+
input: request.action.input,
|
|
2945
|
+
state: "approval-requested",
|
|
2946
|
+
stepIndex: event.data.stepIndex,
|
|
2947
|
+
toolCallId: request.action.callId,
|
|
2948
|
+
toolMetadata: createToolMetadata(descriptor, { inputRequest: toMessageInputRequest(request) }),
|
|
2949
|
+
toolName: descriptor.toolName,
|
|
2950
|
+
type: "dynamic-tool"
|
|
2951
|
+
}));
|
|
2952
|
+
}
|
|
2953
|
+
return next;
|
|
2879
2954
|
}
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2955
|
+
case "approval.candidate": return data;
|
|
2956
|
+
case "approval.settled": {
|
|
2957
|
+
const existing = findToolPartByApprovalId(data, event.data.requestId);
|
|
2958
|
+
if (existing === void 0) return data;
|
|
2959
|
+
if (event.data.outcome === "approved") {
|
|
2960
|
+
const approval = {
|
|
2961
|
+
approved: true,
|
|
2962
|
+
id: event.data.requestId,
|
|
2963
|
+
reason: void 0
|
|
2964
|
+
};
|
|
2965
|
+
return updateToolPart(data, existing.toolCallId, existing.state === "output-available" ? {
|
|
2966
|
+
...existing,
|
|
2967
|
+
approval
|
|
2968
|
+
} : {
|
|
2969
|
+
...toolPartIdentity(existing),
|
|
2970
|
+
approval,
|
|
2971
|
+
state: "approval-responded"
|
|
2972
|
+
});
|
|
2896
2973
|
}
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
if (!this.#isActiveTurn(turn)) return;
|
|
2908
|
-
turn.resolveResponse(void 0);
|
|
2909
|
-
this.#activeTurn = void 0;
|
|
2910
|
-
try {
|
|
2911
|
-
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
2912
|
-
this.#publish();
|
|
2913
|
-
this.#callbacks.onFinish?.(this.#snapshot);
|
|
2914
|
-
} finally {
|
|
2915
|
-
turn.resolveCompletion();
|
|
2974
|
+
if (existing.state === "output-available") return data;
|
|
2975
|
+
return updateToolPart(data, existing.toolCallId, {
|
|
2976
|
+
...toolPartIdentity(existing),
|
|
2977
|
+
approval: {
|
|
2978
|
+
approved: false,
|
|
2979
|
+
id: event.data.requestId,
|
|
2980
|
+
reason: "Tool execution was cancelled."
|
|
2981
|
+
},
|
|
2982
|
+
state: "output-denied"
|
|
2983
|
+
});
|
|
2916
2984
|
}
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
if (
|
|
2985
|
+
case "action.result": {
|
|
2986
|
+
const descriptor = normalizeActionResult(event.data.result);
|
|
2987
|
+
const existing = findToolPart(data, event.data.result.callId);
|
|
2988
|
+
const denied = event.data.status === "rejected" || event.data.error?.code === "TOOL_EXECUTION_DENIED";
|
|
2989
|
+
const failed = event.data.status === "failed" && !denied;
|
|
2990
|
+
const approvalId = existing?.approval?.id ?? event.data.result.callId;
|
|
2991
|
+
const toolMetadata = mergeToolMetadata(existing?.toolMetadata, createToolMetadata(descriptor));
|
|
2992
|
+
const resultPartBase = {
|
|
2993
|
+
input: existing?.input,
|
|
2994
|
+
stepIndex: event.data.stepIndex,
|
|
2995
|
+
toolCallId: event.data.result.callId,
|
|
2996
|
+
toolMetadata,
|
|
2997
|
+
toolName: existing?.toolName ?? descriptor.toolName,
|
|
2998
|
+
type: "dynamic-tool"
|
|
2999
|
+
};
|
|
3000
|
+
let nextPart;
|
|
3001
|
+
if (denied) nextPart = {
|
|
3002
|
+
...resultPartBase,
|
|
3003
|
+
approval: {
|
|
3004
|
+
approved: false,
|
|
3005
|
+
id: approvalId,
|
|
3006
|
+
reason: event.data.error?.message
|
|
3007
|
+
},
|
|
3008
|
+
state: "output-denied"
|
|
3009
|
+
};
|
|
3010
|
+
else if (failed) nextPart = {
|
|
3011
|
+
...resultPartBase,
|
|
3012
|
+
approval: approvedApproval(existing),
|
|
3013
|
+
errorText: event.data.error?.message ?? stringifyUnknown(event.data.result.output),
|
|
3014
|
+
state: "output-error"
|
|
3015
|
+
};
|
|
3016
|
+
else nextPart = {
|
|
3017
|
+
...resultPartBase,
|
|
3018
|
+
approval: approvedApproval(existing),
|
|
3019
|
+
output: event.data.result.output,
|
|
3020
|
+
state: "output-available"
|
|
3021
|
+
};
|
|
3022
|
+
return upsertToolPart(data, event.data.turnId, event.data.stepIndex, nextPart);
|
|
2943
3023
|
}
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
else {
|
|
2962
|
-
const previous = this.#activeTurn.receivedFollowUpEvents.get(reconciliation.event) ?? 0;
|
|
2963
|
-
this.#activeTurn.receivedFollowUpEvents.set(reconciliation.event, previous + followed);
|
|
2964
|
-
}
|
|
3024
|
+
case "action.partial": {
|
|
3025
|
+
const existing = findToolPart(data, event.data.result.callId);
|
|
3026
|
+
if (existing !== void 0 && isSettledToolPart(existing)) return data;
|
|
3027
|
+
const descriptor = normalizeActionResult(event.data.result);
|
|
3028
|
+
const nextPart = {
|
|
3029
|
+
approval: approvedApproval(existing),
|
|
3030
|
+
input: existing?.input,
|
|
3031
|
+
output: event.data.result.output,
|
|
3032
|
+
partial: true,
|
|
3033
|
+
state: "output-available",
|
|
3034
|
+
stepIndex: event.data.stepIndex,
|
|
3035
|
+
toolCallId: event.data.result.callId,
|
|
3036
|
+
toolMetadata: mergeToolMetadata(existing?.toolMetadata, createToolMetadata(descriptor)),
|
|
3037
|
+
toolName: existing?.toolName ?? descriptor.toolName,
|
|
3038
|
+
type: "dynamic-tool"
|
|
3039
|
+
};
|
|
3040
|
+
return upsertToolPart(data, event.data.turnId, event.data.stepIndex, nextPart);
|
|
2965
3041
|
}
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
if (error === void 0) return;
|
|
2971
|
-
this.#status = "error";
|
|
2972
|
-
this.#messageSubmissions.failAll(error);
|
|
2973
|
-
if (this.#error === void 0) {
|
|
2974
|
-
this.#error = error;
|
|
2975
|
-
this.#callbacks.onError?.(error);
|
|
3042
|
+
case "task.settled": {
|
|
3043
|
+
const existing = findToolPart(data, event.data.callId);
|
|
3044
|
+
if (existing === void 0) return data;
|
|
3045
|
+
return replaceToolPart(data, createSettledTaskPart(existing, event));
|
|
2976
3046
|
}
|
|
3047
|
+
case "authorization.required": return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), createAuthorizationRequiredPart(event)));
|
|
3048
|
+
case "authorization.completed": return completeAuthorization(data, event);
|
|
3049
|
+
case "message.appended": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.transition(ensureStepStartPart(message, event.data.stepIndex), {
|
|
3050
|
+
kind: "append",
|
|
3051
|
+
delta: event.data.messageDelta,
|
|
3052
|
+
id: event.meta?.id,
|
|
3053
|
+
stepIndex: event.data.stepIndex,
|
|
3054
|
+
type: "text"
|
|
3055
|
+
}));
|
|
3056
|
+
case "message.completed": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.transition(ensureStepStartPart(message, event.data.stepIndex), {
|
|
3057
|
+
kind: "complete",
|
|
3058
|
+
stepIndex: event.data.stepIndex,
|
|
3059
|
+
text: event.data.message,
|
|
3060
|
+
id: event.meta?.id,
|
|
3061
|
+
type: "text"
|
|
3062
|
+
}));
|
|
3063
|
+
case "result.completed": return updateAssistantMessage(data, event.data.turnId, (message) => ({
|
|
3064
|
+
...message,
|
|
3065
|
+
metadata: {
|
|
3066
|
+
...message.metadata,
|
|
3067
|
+
result: event.data.result
|
|
3068
|
+
}
|
|
3069
|
+
}));
|
|
3070
|
+
case "turn.completed": return updateAssistantMessage(data, event.data.turnId, (message) => ({
|
|
3071
|
+
...message,
|
|
3072
|
+
metadata: {
|
|
3073
|
+
...message.metadata,
|
|
3074
|
+
status: "complete"
|
|
3075
|
+
},
|
|
3076
|
+
parts: removeStreamingToolParts(closeStreamingRuns(message.parts))
|
|
3077
|
+
}));
|
|
3078
|
+
case "turn.cancelled": return updateAssistantMessage(data, event.data.turnId, (message) => ({
|
|
3079
|
+
...message,
|
|
3080
|
+
metadata: {
|
|
3081
|
+
...message.metadata,
|
|
3082
|
+
status: "complete"
|
|
3083
|
+
},
|
|
3084
|
+
parts: removeStreamingToolParts(closeStreamingRuns(message.parts))
|
|
3085
|
+
}));
|
|
3086
|
+
case "turn.failed":
|
|
3087
|
+
if (data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === event.data.turnId) === void 0) return data;
|
|
3088
|
+
return updateAssistantMessage(data, event.data.turnId, (message) => ({
|
|
3089
|
+
...message,
|
|
3090
|
+
metadata: {
|
|
3091
|
+
...message.metadata,
|
|
3092
|
+
status: "complete"
|
|
3093
|
+
},
|
|
3094
|
+
parts: removeStreamingToolParts(closeStreamingRuns(message.parts))
|
|
3095
|
+
}));
|
|
3096
|
+
case "session.failed": return data;
|
|
3097
|
+
default: return data;
|
|
2977
3098
|
}
|
|
2978
|
-
#createSnapshot() {
|
|
2979
|
-
return {
|
|
2980
|
-
data: this.#projection.data,
|
|
2981
|
-
error: this.#error,
|
|
2982
|
-
events: this.#events,
|
|
2983
|
-
session: this.#session?.state,
|
|
2984
|
-
status: this.#status
|
|
2985
|
-
};
|
|
2986
|
-
}
|
|
2987
|
-
#publish() {
|
|
2988
|
-
this.#snapshot = this.#createSnapshot();
|
|
2989
|
-
for (const subscriber of this.#subscribers) subscriber();
|
|
2990
|
-
}
|
|
2991
|
-
};
|
|
2992
|
-
function detachEveAgentStore(store) {
|
|
2993
|
-
store[detachStore]();
|
|
2994
3099
|
}
|
|
2995
|
-
function
|
|
2996
|
-
|
|
3100
|
+
function closeStreamingRuns(parts, stepIndex) {
|
|
3101
|
+
return parts.map((part) => (part.type === "text" || part.type === "reasoning") && part.state === "streaming" && (stepIndex === void 0 || part.stepIndex === stepIndex) ? {
|
|
3102
|
+
...part,
|
|
3103
|
+
state: "done"
|
|
3104
|
+
} : part);
|
|
2997
3105
|
}
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
//#region src/client/agent-host.ts
|
|
3001
|
-
const AGENT_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
|
|
3002
|
-
const EVE_NAMED_AGENT_ROUTE_PREFIX = "/eve";
|
|
3003
|
-
function resolveEveAgentHost(input) {
|
|
3004
|
-
if (input.agent === void 0) return input.host ?? "";
|
|
3005
|
-
if (input.host !== void 0) throw new Error("useEveAgent cannot combine agent and host. Use one target option.");
|
|
3006
|
-
assertValidAgentName(input.agent);
|
|
3007
|
-
return `${EVE_NAMED_AGENT_ROUTE_PREFIX}/${input.agent}`;
|
|
3106
|
+
function removeStreamingToolParts(parts) {
|
|
3107
|
+
return parts.filter((part) => part.type !== "dynamic-tool" || part.state !== "input-streaming");
|
|
3008
3108
|
}
|
|
3009
|
-
function
|
|
3010
|
-
|
|
3109
|
+
function respondToInputRequest(data, response) {
|
|
3110
|
+
const existing = findToolPartByApprovalId(data, response.requestId);
|
|
3111
|
+
if (!existing) return data;
|
|
3112
|
+
const approval = { id: response.requestId };
|
|
3113
|
+
if (response.text !== void 0) approval.reason = response.text;
|
|
3114
|
+
const toolMetadata = mergeToolMetadata(existing.toolMetadata, { eve: {
|
|
3115
|
+
inputResponse: response,
|
|
3116
|
+
kind: existing.toolMetadata?.eve?.kind ?? "unknown",
|
|
3117
|
+
name: existing.toolMetadata?.eve?.name ?? existing.toolName
|
|
3118
|
+
} });
|
|
3119
|
+
return updateToolPart(data, existing.toolCallId, existing.state === "output-available" ? {
|
|
3120
|
+
...existing,
|
|
3121
|
+
approval: {
|
|
3122
|
+
...approval,
|
|
3123
|
+
approved: true
|
|
3124
|
+
},
|
|
3125
|
+
toolMetadata
|
|
3126
|
+
} : {
|
|
3127
|
+
...toolPartIdentity(existing),
|
|
3128
|
+
approval,
|
|
3129
|
+
state: "approval-responded",
|
|
3130
|
+
toolMetadata
|
|
3131
|
+
});
|
|
3011
3132
|
}
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3133
|
+
function resolveInputRequest(data, resolution) {
|
|
3134
|
+
if (resolution.response !== void 0) return findToolPartByApprovalId(data, resolution.requestId)?.approval?.approved === void 0 ? respondToInputRequest(data, resolution.response) : data;
|
|
3135
|
+
const existing = findToolPartByApprovalId(data, resolution.requestId);
|
|
3136
|
+
if (!existing) return data;
|
|
3137
|
+
return updateToolPart(data, existing.toolCallId, {
|
|
3138
|
+
...toolPartIdentity(existing),
|
|
3139
|
+
output: { status: resolution.outcome },
|
|
3140
|
+
state: "output-available"
|
|
3141
|
+
});
|
|
3142
|
+
}
|
|
3143
|
+
function toolPartIdentity(part) {
|
|
3017
3144
|
return {
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
turnId: event.data.turnId,
|
|
3025
|
-
type: "authorization"
|
|
3145
|
+
input: part.input,
|
|
3146
|
+
stepIndex: part.stepIndex,
|
|
3147
|
+
toolCallId: part.toolCallId,
|
|
3148
|
+
toolMetadata: part.toolMetadata,
|
|
3149
|
+
toolName: part.toolName,
|
|
3150
|
+
type: part.type
|
|
3026
3151
|
};
|
|
3027
3152
|
}
|
|
3028
|
-
function
|
|
3029
|
-
const
|
|
3153
|
+
function updateAssistantMessage(data, turnId, update) {
|
|
3154
|
+
const message = data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === turnId) ?? createAssistantMessage(turnId);
|
|
3155
|
+
return upsertMessage(data, update(message));
|
|
3156
|
+
}
|
|
3157
|
+
function createAssistantMessage(turnId) {
|
|
3030
3158
|
return {
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
outcome: event.data.outcome,
|
|
3039
|
-
reason: event.data.reason,
|
|
3040
|
-
state: "completed",
|
|
3041
|
-
stepIndex: existing?.stepIndex ?? event.data.stepIndex,
|
|
3042
|
-
turnId: existing?.turnId ?? event.data.turnId,
|
|
3043
|
-
type: "authorization"
|
|
3159
|
+
id: `${turnId}:assistant`,
|
|
3160
|
+
metadata: {
|
|
3161
|
+
status: "streaming",
|
|
3162
|
+
turnId
|
|
3163
|
+
},
|
|
3164
|
+
parts: [],
|
|
3165
|
+
role: "assistant"
|
|
3044
3166
|
};
|
|
3045
3167
|
}
|
|
3046
|
-
function
|
|
3047
|
-
|
|
3048
|
-
|
|
3168
|
+
function ensureStepStartPart(message, stepIndex) {
|
|
3169
|
+
const stepStartCount = message.parts.filter((part) => part.type === "step-start").length;
|
|
3170
|
+
if (stepStartCount > stepIndex) return message;
|
|
3171
|
+
const missingCount = stepIndex - stepStartCount + 1;
|
|
3172
|
+
return {
|
|
3173
|
+
...message,
|
|
3174
|
+
parts: [...message.parts, ...Array.from({ length: missingCount }, () => ({ type: "step-start" }))]
|
|
3175
|
+
};
|
|
3049
3176
|
}
|
|
3050
|
-
function
|
|
3051
|
-
|
|
3052
|
-
|
|
3177
|
+
function upsertPart(message, next) {
|
|
3178
|
+
const index = message.parts.findIndex((part) => partKey(part) === partKey(next));
|
|
3179
|
+
const parts = index === -1 ? [...message.parts, next] : [
|
|
3180
|
+
...message.parts.slice(0, index),
|
|
3181
|
+
next,
|
|
3182
|
+
...message.parts.slice(index + 1)
|
|
3183
|
+
];
|
|
3184
|
+
return {
|
|
3185
|
+
...message,
|
|
3186
|
+
metadata: {
|
|
3187
|
+
...message.metadata,
|
|
3188
|
+
status: next.type === "text" && next.state === "done" ? "complete" : "streaming"
|
|
3189
|
+
},
|
|
3190
|
+
parts
|
|
3191
|
+
};
|
|
3053
3192
|
}
|
|
3054
|
-
function
|
|
3055
|
-
|
|
3056
|
-
return
|
|
3193
|
+
function upsertToolPart(data, turnId, stepIndex, part) {
|
|
3194
|
+
const updated = updateToolPart(data, part.toolCallId, part);
|
|
3195
|
+
return updated !== data ? updated : updateAssistantMessage(data, turnId, (message) => upsertPart(ensureStepStartPart(message, stepIndex), part));
|
|
3057
3196
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3197
|
+
function updateToolPart(data, toolCallId, next) {
|
|
3198
|
+
const message = data.messages.find((candidate) => candidate.role === "assistant" && candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === toolCallId));
|
|
3199
|
+
if (!message) return data;
|
|
3200
|
+
return upsertMessage(data, upsertPart(message, next));
|
|
3201
|
+
}
|
|
3202
|
+
function replaceToolPart(data, next) {
|
|
3203
|
+
const message = data.messages.find((candidate) => candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === next.toolCallId));
|
|
3204
|
+
if (message === void 0) return data;
|
|
3205
|
+
return upsertMessage(data, {
|
|
3206
|
+
...message,
|
|
3207
|
+
parts: message.parts.map((part) => partKey(part) === partKey(next) ? next : part)
|
|
3208
|
+
});
|
|
3209
|
+
}
|
|
3210
|
+
function completeAuthorization(data, event) {
|
|
3211
|
+
const existing = findPendingAuthorizationPart(data, event.data.name, event.data.attemptId);
|
|
3212
|
+
const next = createAuthorizationCompletedPart(event, existing);
|
|
3213
|
+
return updateAssistantMessage(data, existing?.turnId ?? event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, next.stepIndex), next));
|
|
3214
|
+
}
|
|
3215
|
+
function findToolPart(data, toolCallId) {
|
|
3216
|
+
for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.toolCallId === toolCallId) return part;
|
|
3217
|
+
}
|
|
3218
|
+
function isSettledToolPart(part) {
|
|
3219
|
+
return part.state === "output-denied" || part.state === "output-error" || part.state === "output-available" && part.partial !== true;
|
|
3220
|
+
}
|
|
3221
|
+
function findPendingAuthorizationPart(data, name, attemptId) {
|
|
3222
|
+
for (let messageIndex = data.messages.length - 1; messageIndex >= 0; messageIndex -= 1) {
|
|
3223
|
+
const message = data.messages[messageIndex];
|
|
3224
|
+
if (message?.role !== "assistant") continue;
|
|
3225
|
+
for (let partIndex = message.parts.length - 1; partIndex >= 0; partIndex -= 1) {
|
|
3226
|
+
const part = message.parts[partIndex];
|
|
3227
|
+
if (part?.type === "authorization" && part.state === "required" && (attemptId === void 0 ? part.attemptId === void 0 && part.name === name : part.attemptId === attemptId)) return part;
|
|
3228
|
+
}
|
|
3068
3229
|
}
|
|
3069
3230
|
}
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
//#region src/client/message-action-parts.ts
|
|
3073
|
-
function toMessageInputRequest(request) {
|
|
3074
|
-
return {
|
|
3075
|
-
allowFreeform: request.allowFreeform,
|
|
3076
|
-
display: request.display,
|
|
3077
|
-
kind: request.kind,
|
|
3078
|
-
options: request.options,
|
|
3079
|
-
prompt: request.prompt,
|
|
3080
|
-
requestId: request.requestId
|
|
3081
|
-
};
|
|
3231
|
+
function findToolPartByApprovalId(data, approvalId) {
|
|
3232
|
+
for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.approval?.id === approvalId) return part;
|
|
3082
3233
|
}
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3234
|
+
|
|
3235
|
+
//#endregion
|
|
3236
|
+
//#region src/client/conversation-reducer.ts
|
|
3237
|
+
function initialConversationState() {
|
|
3238
|
+
return {
|
|
3239
|
+
messages: [],
|
|
3240
|
+
turns: {},
|
|
3241
|
+
inputs: {},
|
|
3242
|
+
tasks: {},
|
|
3243
|
+
agents: {}
|
|
3244
|
+
};
|
|
3089
3245
|
}
|
|
3090
|
-
function
|
|
3091
|
-
const
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
...
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
}
|
|
3246
|
+
function updateTurn(state, turnId, update) {
|
|
3247
|
+
const turn = state.turns[turnId];
|
|
3248
|
+
if (turn === void 0) return state;
|
|
3249
|
+
const next = update(turn);
|
|
3250
|
+
return next === turn ? state : {
|
|
3251
|
+
...state,
|
|
3252
|
+
turns: {
|
|
3253
|
+
...state.turns,
|
|
3254
|
+
[turnId]: next
|
|
3255
|
+
}
|
|
3256
|
+
};
|
|
3101
3257
|
}
|
|
3102
|
-
function
|
|
3103
|
-
|
|
3258
|
+
function updateTask(state, taskId, update) {
|
|
3259
|
+
const task = state.tasks[taskId];
|
|
3260
|
+
if (task === void 0) return state;
|
|
3261
|
+
const next = update(task);
|
|
3262
|
+
return next === task ? state : {
|
|
3263
|
+
...state,
|
|
3264
|
+
tasks: {
|
|
3265
|
+
...state.tasks,
|
|
3266
|
+
[taskId]: next
|
|
3267
|
+
}
|
|
3268
|
+
};
|
|
3269
|
+
}
|
|
3270
|
+
function updateObservation(state, sessionId, update) {
|
|
3271
|
+
const agent = state.agents[sessionId];
|
|
3272
|
+
if (agent === void 0) return state;
|
|
3273
|
+
const observation = update(agent.observation);
|
|
3274
|
+
if (observation === agent.observation) return state;
|
|
3104
3275
|
return {
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3276
|
+
...state,
|
|
3277
|
+
agents: {
|
|
3278
|
+
...state.agents,
|
|
3279
|
+
[sessionId]: {
|
|
3280
|
+
...agent,
|
|
3281
|
+
observation
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3109
3284
|
};
|
|
3110
3285
|
}
|
|
3111
|
-
function
|
|
3112
|
-
|
|
3113
|
-
switch (action.kind) {
|
|
3114
|
-
case "load-skill": return {
|
|
3115
|
-
kind: "load-skill",
|
|
3116
|
-
name,
|
|
3117
|
-
toolName: "eve:load-skill"
|
|
3118
|
-
};
|
|
3119
|
-
case "tool-call":
|
|
3120
|
-
case "workflow-tool-call": return {
|
|
3121
|
-
kind: "tool-call",
|
|
3122
|
-
name,
|
|
3123
|
-
toolName: name
|
|
3124
|
-
};
|
|
3125
|
-
case "subagent-call":
|
|
3126
|
-
case "remote-agent-call": return {
|
|
3127
|
-
kind: "subagent-call",
|
|
3128
|
-
name,
|
|
3129
|
-
toolName: `eve:subagent:${name}`
|
|
3130
|
-
};
|
|
3131
|
-
}
|
|
3286
|
+
function observedConversation(observation) {
|
|
3287
|
+
return observation.status === "not-followed" ? void 0 : observation.conversation;
|
|
3132
3288
|
}
|
|
3133
|
-
function
|
|
3134
|
-
switch (
|
|
3135
|
-
case "
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3289
|
+
function reduceConversationLifecycle(state, event) {
|
|
3290
|
+
switch (event.type) {
|
|
3291
|
+
case "turn.started": return {
|
|
3292
|
+
...state,
|
|
3293
|
+
activeTurnId: event.data.turnId,
|
|
3294
|
+
turns: {
|
|
3295
|
+
...state.turns,
|
|
3296
|
+
[event.data.turnId]: {
|
|
3297
|
+
turnId: event.data.turnId,
|
|
3298
|
+
status: "active"
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3144
3301
|
};
|
|
3145
|
-
case "
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3302
|
+
case "turn.waiting": return updateTurn(state, event.data.turnId, (turn) => turn.status === "active" && !turn.waiting ? {
|
|
3303
|
+
...turn,
|
|
3304
|
+
waiting: true
|
|
3305
|
+
} : turn);
|
|
3306
|
+
case "step.started": return updateTurn(state, event.data.turnId, (turn) => turn.waiting ? {
|
|
3307
|
+
turnId: turn.turnId,
|
|
3308
|
+
status: turn.status
|
|
3309
|
+
} : turn);
|
|
3310
|
+
case "turn.completed":
|
|
3311
|
+
case "turn.cancelled":
|
|
3312
|
+
case "turn.failed": {
|
|
3313
|
+
const { turnId } = event.data;
|
|
3314
|
+
return {
|
|
3315
|
+
...state,
|
|
3316
|
+
activeTurnId: state.activeTurnId === turnId ? void 0 : state.activeTurnId,
|
|
3317
|
+
turns: {
|
|
3318
|
+
...state.turns,
|
|
3319
|
+
[turnId]: {
|
|
3320
|
+
turnId,
|
|
3321
|
+
status: event.type === "turn.completed" ? "completed" : event.type === "turn.failed" ? "failed" : "cancelled"
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
};
|
|
3325
|
+
}
|
|
3326
|
+
case "session.waiting":
|
|
3327
|
+
case "session.completed":
|
|
3328
|
+
case "session.failed": return state.activeTurnId === void 0 ? state : {
|
|
3329
|
+
...state,
|
|
3330
|
+
activeTurnId: void 0
|
|
3149
3331
|
};
|
|
3332
|
+
case "task.started": {
|
|
3333
|
+
const { callId, kind, name, taskId, turnId } = event.data;
|
|
3334
|
+
const task = state.tasks[taskId] ?? {
|
|
3335
|
+
taskId,
|
|
3336
|
+
name,
|
|
3337
|
+
kind,
|
|
3338
|
+
calls: {}
|
|
3339
|
+
};
|
|
3340
|
+
if (task.calls[callId] !== void 0) return state;
|
|
3341
|
+
return {
|
|
3342
|
+
...state,
|
|
3343
|
+
tasks: {
|
|
3344
|
+
...state.tasks,
|
|
3345
|
+
[taskId]: {
|
|
3346
|
+
...task,
|
|
3347
|
+
calls: {
|
|
3348
|
+
...task.calls,
|
|
3349
|
+
[callId]: {
|
|
3350
|
+
callId,
|
|
3351
|
+
turnId,
|
|
3352
|
+
status: "working"
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
}
|
|
3357
|
+
};
|
|
3358
|
+
}
|
|
3359
|
+
case "task.settled": {
|
|
3360
|
+
const { callId, error, output, status, taskId } = event.data;
|
|
3361
|
+
return updateTask(state, taskId, (task) => {
|
|
3362
|
+
const call = task.calls[callId];
|
|
3363
|
+
if (call === void 0 || call.status !== "working") return task;
|
|
3364
|
+
const settled = {
|
|
3365
|
+
callId,
|
|
3366
|
+
turnId: call.turnId,
|
|
3367
|
+
status
|
|
3368
|
+
};
|
|
3369
|
+
return {
|
|
3370
|
+
...task,
|
|
3371
|
+
calls: {
|
|
3372
|
+
...task.calls,
|
|
3373
|
+
[callId]: status === "completed" && output !== void 0 ? {
|
|
3374
|
+
...settled,
|
|
3375
|
+
output
|
|
3376
|
+
} : status === "failed" && error !== void 0 ? {
|
|
3377
|
+
...settled,
|
|
3378
|
+
error
|
|
3379
|
+
} : settled
|
|
3380
|
+
}
|
|
3381
|
+
};
|
|
3382
|
+
});
|
|
3383
|
+
}
|
|
3384
|
+
case "agent.started": {
|
|
3385
|
+
const { callId, name, sessionId, taskId, turnId } = event.data;
|
|
3386
|
+
if (state.agents[sessionId] !== void 0) return state;
|
|
3387
|
+
const agent = {
|
|
3388
|
+
sessionId,
|
|
3389
|
+
name,
|
|
3390
|
+
callId,
|
|
3391
|
+
turnId,
|
|
3392
|
+
observation: { status: "not-followed" }
|
|
3393
|
+
};
|
|
3394
|
+
if (taskId !== void 0) agent.taskId = taskId;
|
|
3395
|
+
return {
|
|
3396
|
+
...state,
|
|
3397
|
+
agents: {
|
|
3398
|
+
...state.agents,
|
|
3399
|
+
[sessionId]: agent
|
|
3400
|
+
}
|
|
3401
|
+
};
|
|
3402
|
+
}
|
|
3403
|
+
case "input.requested": {
|
|
3404
|
+
const inputs = { ...state.inputs };
|
|
3405
|
+
for (const request of event.data.requests) {
|
|
3406
|
+
if (inputs[request.requestId] !== void 0) continue;
|
|
3407
|
+
const input = {
|
|
3408
|
+
request,
|
|
3409
|
+
turnId: event.data.turnId,
|
|
3410
|
+
stepIndex: event.data.stepIndex,
|
|
3411
|
+
status: "open"
|
|
3412
|
+
};
|
|
3413
|
+
if (event.data.taskId !== void 0) input.taskId = event.data.taskId;
|
|
3414
|
+
inputs[request.requestId] = input;
|
|
3415
|
+
}
|
|
3416
|
+
return {
|
|
3417
|
+
...state,
|
|
3418
|
+
inputs
|
|
3419
|
+
};
|
|
3420
|
+
}
|
|
3421
|
+
case "client.input.responded": {
|
|
3422
|
+
const inputs = { ...state.inputs };
|
|
3423
|
+
for (const response of event.data.responses) {
|
|
3424
|
+
const current = inputs[response.requestId];
|
|
3425
|
+
if (current?.status !== "open") continue;
|
|
3426
|
+
inputs[response.requestId] = {
|
|
3427
|
+
...current,
|
|
3428
|
+
response,
|
|
3429
|
+
status: "responded"
|
|
3430
|
+
};
|
|
3431
|
+
}
|
|
3432
|
+
return {
|
|
3433
|
+
...state,
|
|
3434
|
+
inputs
|
|
3435
|
+
};
|
|
3436
|
+
}
|
|
3437
|
+
case "approval.candidate": {
|
|
3438
|
+
const current = state.inputs[event.data.requestId];
|
|
3439
|
+
if (current === void 0 || current.status === "settled") return state;
|
|
3440
|
+
if (event.data.outcome === "pending") return state;
|
|
3441
|
+
return {
|
|
3442
|
+
...state,
|
|
3443
|
+
inputs: {
|
|
3444
|
+
...state.inputs,
|
|
3445
|
+
[event.data.requestId]: {
|
|
3446
|
+
...current,
|
|
3447
|
+
status: "open",
|
|
3448
|
+
response: void 0
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3451
|
+
};
|
|
3452
|
+
}
|
|
3453
|
+
case "approval.settled": {
|
|
3454
|
+
const current = state.inputs[event.data.requestId];
|
|
3455
|
+
if (current === void 0 || current.status === "settled") return state;
|
|
3456
|
+
return {
|
|
3457
|
+
...state,
|
|
3458
|
+
inputs: {
|
|
3459
|
+
...state.inputs,
|
|
3460
|
+
[event.data.requestId]: {
|
|
3461
|
+
...current,
|
|
3462
|
+
status: "settled",
|
|
3463
|
+
outcome: event.data.outcome
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
};
|
|
3467
|
+
}
|
|
3468
|
+
case "input.resolved": {
|
|
3469
|
+
const inputs = { ...state.inputs };
|
|
3470
|
+
for (const resolution of event.data.resolutions) {
|
|
3471
|
+
const current = inputs[resolution.requestId];
|
|
3472
|
+
if (current === void 0 || current.status === "settled") continue;
|
|
3473
|
+
inputs[resolution.requestId] = {
|
|
3474
|
+
...current,
|
|
3475
|
+
status: "settled",
|
|
3476
|
+
outcome: resolution.outcome,
|
|
3477
|
+
response: resolution.response ?? current.response
|
|
3478
|
+
};
|
|
3479
|
+
}
|
|
3480
|
+
return {
|
|
3481
|
+
...state,
|
|
3482
|
+
inputs
|
|
3483
|
+
};
|
|
3484
|
+
}
|
|
3485
|
+
default: return state;
|
|
3150
3486
|
}
|
|
3151
3487
|
}
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
return
|
|
3156
|
-
|
|
3157
|
-
|
|
3488
|
+
const messageReducer = defaultMessageReducer();
|
|
3489
|
+
function reduceConversation(state, event) {
|
|
3490
|
+
switch (event.type) {
|
|
3491
|
+
case "client.agent.following": return updateObservation(state, event.data.sessionId, (observation) => observation.status === "following" ? observation : {
|
|
3492
|
+
status: "following",
|
|
3493
|
+
conversation: observedConversation(observation) ?? initialConversationState()
|
|
3494
|
+
});
|
|
3495
|
+
case "client.agent.observed": return updateObservation(state, event.data.sessionId, (observation) => observation.status === "following" ? {
|
|
3496
|
+
status: "following",
|
|
3497
|
+
conversation: reduceConversation(observation.conversation, event.data.event)
|
|
3498
|
+
} : observation);
|
|
3499
|
+
case "client.agent.idle": return updateObservation(state, event.data.sessionId, (observation) => observation.status === "following" ? {
|
|
3500
|
+
status: "idle",
|
|
3501
|
+
conversation: observation.conversation
|
|
3502
|
+
} : observation);
|
|
3503
|
+
case "client.agent.unavailable": return updateObservation(state, event.data.sessionId, (observation) => {
|
|
3504
|
+
const conversation = observedConversation(observation);
|
|
3505
|
+
return conversation === void 0 ? { status: "unavailable" } : {
|
|
3506
|
+
status: "unavailable",
|
|
3507
|
+
conversation
|
|
3508
|
+
};
|
|
3509
|
+
});
|
|
3510
|
+
default: {
|
|
3511
|
+
const projected = messageReducer.reduce(state, event);
|
|
3512
|
+
return reduceConversationLifecycle({
|
|
3513
|
+
...state,
|
|
3514
|
+
...projected
|
|
3515
|
+
}, event);
|
|
3516
|
+
}
|
|
3158
3517
|
}
|
|
3159
3518
|
}
|
|
3519
|
+
const canonicalConversationReducer = {
|
|
3520
|
+
initial: initialConversationState,
|
|
3521
|
+
reduce: reduceConversation
|
|
3522
|
+
};
|
|
3523
|
+
const conversationReducer = canonicalConversationReducer;
|
|
3160
3524
|
|
|
3161
3525
|
//#endregion
|
|
3162
|
-
//#region src/
|
|
3163
|
-
function
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
type: "text"
|
|
3178
|
-
}];
|
|
3526
|
+
//#region src/protocol/event-dedupe.ts
|
|
3527
|
+
function createEventDeduper() {
|
|
3528
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3529
|
+
return {
|
|
3530
|
+
admit(event) {
|
|
3531
|
+
const id = event.meta?.id;
|
|
3532
|
+
if (id === void 0) return true;
|
|
3533
|
+
if (seen.has(id)) return false;
|
|
3534
|
+
seen.add(id);
|
|
3535
|
+
return true;
|
|
3536
|
+
},
|
|
3537
|
+
get size() {
|
|
3538
|
+
return seen.size;
|
|
3539
|
+
}
|
|
3540
|
+
};
|
|
3179
3541
|
}
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3542
|
+
|
|
3543
|
+
//#endregion
|
|
3544
|
+
//#region src/client/session-event-stream.ts
|
|
3545
|
+
var SessionEventStream = class {
|
|
3546
|
+
#controller = new AbortController();
|
|
3547
|
+
#readers = /* @__PURE__ */ new Set();
|
|
3548
|
+
#caughtUp = Promise.withResolvers();
|
|
3549
|
+
caughtUp = this.#caughtUp.promise;
|
|
3550
|
+
#ended = false;
|
|
3551
|
+
#error;
|
|
3552
|
+
#headers;
|
|
3553
|
+
#reconnectPolicy;
|
|
3554
|
+
constructor(session, options) {
|
|
3555
|
+
this.setOptions(options);
|
|
3556
|
+
this.caughtUp.catch(() => {});
|
|
3557
|
+
if (!options.catchUp) this.#caughtUp.resolve();
|
|
3558
|
+
(async () => {
|
|
3559
|
+
try {
|
|
3560
|
+
for await (const event of followClientSession(session, {
|
|
3561
|
+
signal: this.#controller.signal,
|
|
3562
|
+
resolveHeaders: () => this.#headers,
|
|
3563
|
+
resolveReconnectPolicy: () => this.#reconnectPolicy,
|
|
3564
|
+
startIndex: options.startIndex,
|
|
3565
|
+
onCaughtUp: options.catchUp ? () => this.#caughtUp.resolve() : void 0
|
|
3566
|
+
})) {
|
|
3567
|
+
if (this.#controller.signal.aborted) return;
|
|
3568
|
+
options.onEvent(event);
|
|
3569
|
+
for (const reader of this.#readers) reader.push(event);
|
|
3570
|
+
if (event.type === "session.completed" || event.type === "session.failed") break;
|
|
3571
|
+
}
|
|
3572
|
+
this.#caughtUp.resolve();
|
|
3573
|
+
this.#finish();
|
|
3574
|
+
} catch (error) {
|
|
3575
|
+
this.#caughtUp.reject(error);
|
|
3576
|
+
this.#finish(error);
|
|
3577
|
+
if (!this.#controller.signal.aborted) options.onError(error);
|
|
3578
|
+
}
|
|
3579
|
+
})();
|
|
3580
|
+
}
|
|
3581
|
+
subscribe(signal) {
|
|
3582
|
+
const reader = new SessionEventReader(() => this.#readers.delete(reader), signal);
|
|
3583
|
+
if (this.#ended) reader.end(this.#error);
|
|
3584
|
+
else this.#readers.add(reader);
|
|
3585
|
+
return reader;
|
|
3586
|
+
}
|
|
3587
|
+
get ended() {
|
|
3588
|
+
return this.#ended;
|
|
3589
|
+
}
|
|
3590
|
+
setOptions(options) {
|
|
3591
|
+
if ("headers" in options) this.#headers = options.headers;
|
|
3592
|
+
if ("streamReconnectPolicy" in options) this.#reconnectPolicy = options.streamReconnectPolicy;
|
|
3593
|
+
}
|
|
3594
|
+
close() {
|
|
3595
|
+
const error = new DOMException("Session stream was detached.", "AbortError");
|
|
3596
|
+
this.#controller.abort(error);
|
|
3597
|
+
this.#caughtUp.reject(error);
|
|
3598
|
+
this.#finish(error);
|
|
3599
|
+
}
|
|
3600
|
+
#finish(error) {
|
|
3601
|
+
if (this.#ended) return;
|
|
3602
|
+
this.#ended = true;
|
|
3603
|
+
this.#error = error;
|
|
3604
|
+
for (const reader of this.#readers) reader.end(error);
|
|
3605
|
+
}
|
|
3606
|
+
};
|
|
3607
|
+
var SessionEventReader = class {
|
|
3608
|
+
#events = [];
|
|
3609
|
+
#wake = Promise.withResolvers();
|
|
3610
|
+
#ended = false;
|
|
3611
|
+
#error;
|
|
3612
|
+
#dispose;
|
|
3613
|
+
constructor(unsubscribe, signal) {
|
|
3614
|
+
const abort = () => this.end(signal?.reason);
|
|
3615
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
3616
|
+
this.#dispose = () => {
|
|
3617
|
+
signal?.removeEventListener("abort", abort);
|
|
3618
|
+
unsubscribe();
|
|
3619
|
+
};
|
|
3620
|
+
if (signal?.aborted) abort();
|
|
3621
|
+
}
|
|
3622
|
+
push(event) {
|
|
3623
|
+
if (this.#ended) return;
|
|
3624
|
+
this.#events.push(event);
|
|
3625
|
+
this.#wake.resolve();
|
|
3626
|
+
}
|
|
3627
|
+
end(error) {
|
|
3628
|
+
if (this.#ended) return;
|
|
3629
|
+
this.#ended = true;
|
|
3630
|
+
this.#error = error;
|
|
3631
|
+
this.#wake.resolve();
|
|
3632
|
+
}
|
|
3633
|
+
[Symbol.dispose]() {
|
|
3634
|
+
this.end();
|
|
3635
|
+
this.#events = [];
|
|
3636
|
+
this.#dispose();
|
|
3188
3637
|
}
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
}
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
...message,
|
|
3205
|
-
parts: message.parts.filter((part) => part.type !== "dynamic-tool" || part.state !== "input-streaming")
|
|
3206
|
-
});
|
|
3207
|
-
}
|
|
3208
|
-
function optimisticUserMessageId(submissionId) {
|
|
3209
|
-
return `optimistic:${submissionId}:user`;
|
|
3210
|
-
}
|
|
3638
|
+
discard() {
|
|
3639
|
+
this.#events = [];
|
|
3640
|
+
}
|
|
3641
|
+
async *[Symbol.asyncIterator]() {
|
|
3642
|
+
for (;;) {
|
|
3643
|
+
while (this.#events.length > 0) yield this.#events.shift();
|
|
3644
|
+
if (this.#ended) {
|
|
3645
|
+
if (this.#error !== void 0) throw this.#error;
|
|
3646
|
+
return;
|
|
3647
|
+
}
|
|
3648
|
+
this.#wake = Promise.withResolvers();
|
|
3649
|
+
await this.#wake.promise;
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
};
|
|
3211
3653
|
|
|
3212
3654
|
//#endregion
|
|
3213
|
-
//#region src/client/
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3655
|
+
//#region src/client/conversation-client.ts
|
|
3656
|
+
var ConversationClient = class {
|
|
3657
|
+
projection;
|
|
3658
|
+
#conversation;
|
|
3659
|
+
#cursors = /* @__PURE__ */ new Map();
|
|
3660
|
+
#seenEvents = createEventDeduper();
|
|
3661
|
+
#follower;
|
|
3662
|
+
#stream;
|
|
3663
|
+
#onChange;
|
|
3664
|
+
#onConversationChange;
|
|
3665
|
+
constructor(projection, onChange, onConversationChange) {
|
|
3666
|
+
this.projection = projection;
|
|
3667
|
+
this.#conversation = projection.reducer === conversationReducer ? projection : new EveAgentProjection(canonicalConversationReducer, []);
|
|
3668
|
+
this.#onChange = onChange;
|
|
3669
|
+
this.#onConversationChange = onConversationChange;
|
|
3227
3670
|
}
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3671
|
+
get data() {
|
|
3672
|
+
return this.projection.data;
|
|
3673
|
+
}
|
|
3674
|
+
get conversation() {
|
|
3675
|
+
return this.#conversation.data;
|
|
3676
|
+
}
|
|
3677
|
+
get projections() {
|
|
3678
|
+
return this.#conversation === this.projection ? [this.projection] : [this.#conversation, this.projection];
|
|
3679
|
+
}
|
|
3680
|
+
get following() {
|
|
3681
|
+
return this.#follower !== void 0;
|
|
3682
|
+
}
|
|
3683
|
+
append(event) {
|
|
3684
|
+
const previous = this.data;
|
|
3685
|
+
const previousConversation = this.conversation;
|
|
3686
|
+
this.#appendRoot(event);
|
|
3687
|
+
if (previous !== this.data) this.#onChange(this.data, previous);
|
|
3688
|
+
else if (previousConversation !== this.conversation) this.#onConversationChange?.(this.conversation, previousConversation);
|
|
3689
|
+
}
|
|
3690
|
+
projectResponses(responses) {
|
|
3691
|
+
if (!responses?.length) return void 0;
|
|
3692
|
+
const event = {
|
|
3693
|
+
data: {
|
|
3694
|
+
createdAt: Date.now(),
|
|
3695
|
+
responses
|
|
3696
|
+
},
|
|
3697
|
+
type: "client.input.responded"
|
|
3698
|
+
};
|
|
3699
|
+
this.append(event);
|
|
3700
|
+
return () => this.#retract(event);
|
|
3701
|
+
}
|
|
3702
|
+
replaceResponses(retract, input) {
|
|
3703
|
+
retract?.();
|
|
3704
|
+
assertAnswerable(input, this.conversation);
|
|
3705
|
+
return this.projectResponses(input.inputResponses);
|
|
3706
|
+
}
|
|
3707
|
+
#retract(event) {
|
|
3708
|
+
const previous = this.data;
|
|
3709
|
+
const previousConversation = this.conversation;
|
|
3710
|
+
for (const projection of this.projections) projection.remove((entry) => entry === event);
|
|
3711
|
+
if (previous !== this.data) this.#onChange(this.data, previous);
|
|
3712
|
+
else if (previousConversation !== this.conversation) this.#onConversationChange?.(this.conversation, previousConversation);
|
|
3713
|
+
}
|
|
3714
|
+
observe(event, options = {}) {
|
|
3715
|
+
if (!this.#seenEvents.admit(event)) return false;
|
|
3716
|
+
options.onAccepted?.(event);
|
|
3717
|
+
const previous = this.data;
|
|
3718
|
+
const previousConversation = this.conversation;
|
|
3719
|
+
if (options.project) options.project(event);
|
|
3720
|
+
else this.#appendRoot(event);
|
|
3721
|
+
if (options.notify !== false) {
|
|
3722
|
+
if (previous !== this.data) this.#onChange(this.data, previous);
|
|
3723
|
+
else if (previousConversation !== this.conversation) this.#onConversationChange?.(this.conversation, previousConversation);
|
|
3236
3724
|
}
|
|
3725
|
+
this.#follower?.acceptParentEvent(event);
|
|
3726
|
+
this.#follower?.reconcile();
|
|
3727
|
+
return true;
|
|
3728
|
+
}
|
|
3729
|
+
hydrate(event) {
|
|
3730
|
+
if (!this.#seenEvents.admit(event)) return false;
|
|
3731
|
+
this.#appendRoot(event);
|
|
3732
|
+
return true;
|
|
3733
|
+
}
|
|
3734
|
+
follow(session, events = []) {
|
|
3735
|
+
this.#follower?.abortAll();
|
|
3736
|
+
const follower = new AgentStreamFollower({
|
|
3737
|
+
session,
|
|
3738
|
+
cursors: this.#cursors,
|
|
3739
|
+
getState: () => this.conversation,
|
|
3740
|
+
onFollowing: (sessionId) => this.#appendChild({
|
|
3741
|
+
type: "client.agent.following",
|
|
3742
|
+
data: { sessionId }
|
|
3743
|
+
}),
|
|
3744
|
+
onEvent: (sessionId, event) => this.#appendChild({
|
|
3745
|
+
type: "client.agent.observed",
|
|
3746
|
+
data: {
|
|
3747
|
+
sessionId,
|
|
3748
|
+
event
|
|
3749
|
+
}
|
|
3750
|
+
}),
|
|
3751
|
+
onIdle: (sessionId) => this.#appendChild({
|
|
3752
|
+
type: "client.agent.idle",
|
|
3753
|
+
data: { sessionId }
|
|
3754
|
+
}),
|
|
3755
|
+
onUnavailable: (sessionId) => this.#appendChild({
|
|
3756
|
+
type: "client.agent.unavailable",
|
|
3757
|
+
data: { sessionId }
|
|
3758
|
+
})
|
|
3759
|
+
});
|
|
3760
|
+
this.#follower = follower;
|
|
3761
|
+
for (const event of events) follower.acceptParentEvent(event);
|
|
3762
|
+
follower.reconcile();
|
|
3763
|
+
}
|
|
3764
|
+
#appendRoot(event) {
|
|
3765
|
+
for (const projection of this.projections) projection.append(event);
|
|
3766
|
+
}
|
|
3767
|
+
#appendChild(event) {
|
|
3768
|
+
const previous = this.data;
|
|
3769
|
+
const previousConversation = this.conversation;
|
|
3770
|
+
this.#conversation.append(event);
|
|
3771
|
+
if (previous !== this.data) this.#onChange(this.data, previous);
|
|
3772
|
+
else if (previousConversation !== this.conversation) this.#onConversationChange?.(this.conversation, previousConversation);
|
|
3773
|
+
}
|
|
3774
|
+
stream(session, options) {
|
|
3775
|
+
if (this.#stream !== void 0 && !this.#stream.ended) {
|
|
3776
|
+
this.#stream.setOptions(options);
|
|
3777
|
+
return this.#stream;
|
|
3778
|
+
}
|
|
3779
|
+
this.#stream = new SessionEventStream(session, options);
|
|
3780
|
+
return this.#stream;
|
|
3781
|
+
}
|
|
3782
|
+
stop() {
|
|
3783
|
+
this.#follower?.abortAll();
|
|
3784
|
+
this.#follower = void 0;
|
|
3785
|
+
this.#stream?.close();
|
|
3786
|
+
this.#stream = void 0;
|
|
3787
|
+
}
|
|
3788
|
+
reset() {
|
|
3789
|
+
this.stop();
|
|
3790
|
+
this.#cursors.clear();
|
|
3791
|
+
this.#seenEvents = createEventDeduper();
|
|
3792
|
+
for (const projection of this.projections) projection.reset();
|
|
3237
3793
|
}
|
|
3238
|
-
const parts = lastIndex !== -1 && message.parts[lastIndex].state === "streaming" ? [
|
|
3239
|
-
...message.parts.slice(0, lastIndex),
|
|
3240
|
-
next,
|
|
3241
|
-
...message.parts.slice(lastIndex + 1)
|
|
3242
|
-
] : [...message.parts, next];
|
|
3243
|
-
return {
|
|
3244
|
-
...message,
|
|
3245
|
-
metadata: {
|
|
3246
|
-
...message.metadata,
|
|
3247
|
-
status: next.type === "text" && next.state === "done" ? "complete" : "streaming"
|
|
3248
|
-
},
|
|
3249
|
-
parts
|
|
3250
|
-
};
|
|
3251
|
-
}
|
|
3252
|
-
const messageRun = {
|
|
3253
|
-
append,
|
|
3254
|
-
upsert
|
|
3255
3794
|
};
|
|
3256
3795
|
|
|
3257
3796
|
//#endregion
|
|
3258
|
-
//#region src/client/
|
|
3259
|
-
function
|
|
3260
|
-
const
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
output: event.data.output,
|
|
3273
|
-
state: "output-available"
|
|
3274
|
-
};
|
|
3275
|
-
case "failed": return {
|
|
3276
|
-
...settledPartBase,
|
|
3277
|
-
errorText: event.data.error?.message ?? "Task failed.",
|
|
3278
|
-
state: "output-error"
|
|
3797
|
+
//#region src/client/session-turn-dispatch.ts
|
|
3798
|
+
async function dispatchSessionTurn(input) {
|
|
3799
|
+
const { client, session, turn, beforeSend } = input;
|
|
3800
|
+
if (session === void 0) {
|
|
3801
|
+
if (client === void 0) throw new Error("An external eve session is required before sending.");
|
|
3802
|
+
if (turn.message === void 0) throw new Error("Cannot answer an input request before the session starts.");
|
|
3803
|
+
const created = await client.sessions.create({
|
|
3804
|
+
...turn,
|
|
3805
|
+
message: turn.message
|
|
3806
|
+
});
|
|
3807
|
+
turn.signal?.throwIfAborted();
|
|
3808
|
+
return {
|
|
3809
|
+
...created,
|
|
3810
|
+
created: true
|
|
3279
3811
|
};
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3812
|
+
}
|
|
3813
|
+
beforeSend?.();
|
|
3814
|
+
if (turn.inputResponses === void 0) {
|
|
3815
|
+
const { message, ...options } = turn;
|
|
3816
|
+
return {
|
|
3817
|
+
session,
|
|
3818
|
+
response: await session.send(message, options),
|
|
3819
|
+
created: false
|
|
3284
3820
|
};
|
|
3285
3821
|
}
|
|
3286
|
-
}
|
|
3287
|
-
|
|
3288
|
-
//#endregion
|
|
3289
|
-
//#region src/client/message-reducer.ts
|
|
3290
|
-
function receivedMessageEventId(event) {
|
|
3291
|
-
return event.meta.id ?? `${event.data.turnId}:${event.data.sequence}`;
|
|
3292
|
-
}
|
|
3293
|
-
function defaultMessageReducer() {
|
|
3822
|
+
const { inputResponses, ...options } = turn;
|
|
3294
3823
|
return {
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
reduce(data, event) {
|
|
3299
|
-
return reduceMessageData(data, event);
|
|
3300
|
-
}
|
|
3824
|
+
session,
|
|
3825
|
+
response: await session.respond(inputResponses, options),
|
|
3826
|
+
created: false
|
|
3301
3827
|
};
|
|
3302
3828
|
}
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3829
|
+
|
|
3830
|
+
//#endregion
|
|
3831
|
+
//#region src/client/eve-agent-store.ts
|
|
3832
|
+
const detachStore = Symbol("detachEveAgentStore");
|
|
3833
|
+
const attachStore = Symbol("attachEveAgentStore");
|
|
3834
|
+
var EveAgentStore = class {
|
|
3835
|
+
#client;
|
|
3836
|
+
#autoPrewarm;
|
|
3837
|
+
#attached = false;
|
|
3838
|
+
#conversationClient;
|
|
3839
|
+
#followChildStreams;
|
|
3840
|
+
#externalSession;
|
|
3841
|
+
#subscribers = /* @__PURE__ */ new Set();
|
|
3842
|
+
#activeTurn;
|
|
3843
|
+
#callbacks = {};
|
|
3844
|
+
#error;
|
|
3845
|
+
#events;
|
|
3846
|
+
#messageSubmissions;
|
|
3847
|
+
#prewarmGeneration = 0;
|
|
3848
|
+
#prewarmPromise;
|
|
3849
|
+
#prewarmController;
|
|
3850
|
+
#resumePromise;
|
|
3851
|
+
#session;
|
|
3852
|
+
#snapshot;
|
|
3853
|
+
#status = "ready";
|
|
3854
|
+
constructor(init) {
|
|
3855
|
+
this.#autoPrewarm = init.prewarm ?? false;
|
|
3856
|
+
this.#followChildStreams = init.followSubagents ?? false;
|
|
3857
|
+
this.#externalSession = init.session !== void 0;
|
|
3858
|
+
this.#client = this.#externalSession ? void 0 : init.client ?? new Client({
|
|
3859
|
+
auth: init.auth,
|
|
3860
|
+
headers: init.headers,
|
|
3861
|
+
host: init.host ?? ""
|
|
3328
3862
|
});
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3863
|
+
this.#conversationClient = new ConversationClient(new EveAgentProjection(init.reducer, []), () => this.#publish(), () => this.#publish());
|
|
3864
|
+
this.#events = (init.initialEvents ?? []).filter((event) => this.#conversationClient.hydrate(event));
|
|
3865
|
+
this.#messageSubmissions = new OptimisticMessageSubmissions(this.#conversationClient.projections, init.optimistic ?? true);
|
|
3866
|
+
this.#session = init.session ?? (init.initialSession === void 0 ? void 0 : this.#client?.sessions.attach(init.initialSession.sessionId, { streamIndex: init.initialSession.streamIndex }));
|
|
3867
|
+
this.#snapshot = this.#createSnapshot();
|
|
3868
|
+
}
|
|
3869
|
+
get snapshot() {
|
|
3870
|
+
return this.#snapshot;
|
|
3871
|
+
}
|
|
3872
|
+
setCallbacks(callbacks) {
|
|
3873
|
+
this.#callbacks = callbacks;
|
|
3874
|
+
}
|
|
3875
|
+
subscribe(callback) {
|
|
3876
|
+
this.#subscribers.add(callback);
|
|
3877
|
+
return () => void this.#subscribers.delete(callback);
|
|
3878
|
+
}
|
|
3879
|
+
prewarm() {
|
|
3880
|
+
if (this.#prewarmPromise !== void 0) return this.#prewarmPromise;
|
|
3881
|
+
if (this.#session !== void 0 || this.#externalSession) return Promise.resolve();
|
|
3882
|
+
if (this.#activeTurn !== void 0) return this.#activeTurn.response.then((response) => {
|
|
3883
|
+
if (response === void 0) throw this.#error ?? new DOMException("Session creation was aborted.", "AbortError");
|
|
3342
3884
|
});
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
name: event.data.toolName
|
|
3367
|
-
} },
|
|
3368
|
-
toolName: event.data.toolName,
|
|
3369
|
-
type: "dynamic-tool"
|
|
3370
|
-
};
|
|
3371
|
-
if (existing !== void 0) return updateToolPart(data, event.data.callId, nextPart);
|
|
3372
|
-
return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), nextPart));
|
|
3373
|
-
}
|
|
3374
|
-
case "actions.requested": {
|
|
3375
|
-
let next = data;
|
|
3376
|
-
for (const action of event.data.actions) {
|
|
3377
|
-
const descriptor = normalizeActionRequest(action);
|
|
3378
|
-
next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
|
|
3379
|
-
input: "input" in action ? action.input : void 0,
|
|
3380
|
-
state: "input-available",
|
|
3381
|
-
stepIndex: event.data.stepIndex,
|
|
3382
|
-
toolCallId: action.callId,
|
|
3383
|
-
toolMetadata: createToolMetadata(descriptor),
|
|
3384
|
-
toolName: descriptor.toolName,
|
|
3385
|
-
type: "dynamic-tool"
|
|
3386
|
-
}));
|
|
3885
|
+
const client = this.#client;
|
|
3886
|
+
if (client === void 0) return Promise.reject(/* @__PURE__ */ new Error("This eve agent store does not own a session client."));
|
|
3887
|
+
const generation = this.#prewarmGeneration;
|
|
3888
|
+
const controller = new AbortController();
|
|
3889
|
+
this.#prewarmController = controller;
|
|
3890
|
+
const promise = (async () => {
|
|
3891
|
+
try {
|
|
3892
|
+
const created = await client.sessions.create({ signal: controller.signal });
|
|
3893
|
+
if (generation !== this.#prewarmGeneration) return;
|
|
3894
|
+
this.#error = void 0;
|
|
3895
|
+
if (this.#status === "error") this.#status = "ready";
|
|
3896
|
+
this.#adoptSession(created.session);
|
|
3897
|
+
this.#ensureStream();
|
|
3898
|
+
} catch (error) {
|
|
3899
|
+
if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) this.#fail(error);
|
|
3900
|
+
throw error;
|
|
3901
|
+
}
|
|
3902
|
+
})();
|
|
3903
|
+
this.#prewarmPromise = promise;
|
|
3904
|
+
const clear = () => {
|
|
3905
|
+
if (this.#prewarmPromise === promise) {
|
|
3906
|
+
this.#prewarmPromise = void 0;
|
|
3907
|
+
this.#prewarmController = void 0;
|
|
3387
3908
|
}
|
|
3388
|
-
|
|
3909
|
+
};
|
|
3910
|
+
promise.then(clear, clear);
|
|
3911
|
+
return promise;
|
|
3912
|
+
}
|
|
3913
|
+
async send(input) {
|
|
3914
|
+
return await this.#submit(input, this.#callbacks.prepareSend);
|
|
3915
|
+
}
|
|
3916
|
+
async #submit(input, prepareSend) {
|
|
3917
|
+
assertAnswerable(input, this.#conversationClient.conversation);
|
|
3918
|
+
if (this.#activeTurn !== void 0) {
|
|
3919
|
+
if (this.#status === "resuming") throw new Error("eve session is resuming.");
|
|
3920
|
+
return await this.#sendFollowUp(this.#activeTurn, input, prepareSend);
|
|
3389
3921
|
}
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3922
|
+
const turn = createActiveTurn((turn) => turn.acceptedFollowUps > 0 && this.#session !== void 0 ? this.#session.cancel() : turn.response.then((response) => response === void 0 ? { status: "no_active_turn" } : response.cancel()));
|
|
3923
|
+
this.#activeTurn = turn;
|
|
3924
|
+
this.#error = void 0;
|
|
3925
|
+
this.#status = "submitted";
|
|
3926
|
+
let reader;
|
|
3927
|
+
let submissionId;
|
|
3928
|
+
let retractResponses;
|
|
3929
|
+
try {
|
|
3930
|
+
assertExclusiveTurnInput(input);
|
|
3931
|
+
submissionId = this.#messageSubmissions.submit(input, this.#events.length);
|
|
3932
|
+
retractResponses = this.#conversationClient.projectResponses(input.inputResponses);
|
|
3933
|
+
this.#publish();
|
|
3934
|
+
const preparedInput = await (prepareSend === void 0 ? input : waitWithSignal(Promise.resolve(prepareSend(input)), createAbortSignal(input.signal, turn.abortController.signal)));
|
|
3935
|
+
assertExclusiveTurnInput(preparedInput);
|
|
3936
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
3937
|
+
if (preparedInput !== input) {
|
|
3938
|
+
submissionId = this.#messageSubmissions.resubmit(submissionId, preparedInput);
|
|
3939
|
+
retractResponses = this.#conversationClient.replaceResponses(retractResponses, preparedInput);
|
|
3940
|
+
this.#publish();
|
|
3404
3941
|
}
|
|
3405
|
-
|
|
3942
|
+
const turnInput = {
|
|
3943
|
+
...preparedInput,
|
|
3944
|
+
signal: createAbortSignal(preparedInput.signal, turn.abortController.signal)
|
|
3945
|
+
};
|
|
3946
|
+
const dispatched = await this.#dispatchTurn(turnInput);
|
|
3947
|
+
retractResponses = void 0;
|
|
3948
|
+
const response = dispatched.response;
|
|
3949
|
+
reader = dispatched.reader;
|
|
3950
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
3951
|
+
turn.resolveResponse(response);
|
|
3952
|
+
this.#correlate(submissionId, response);
|
|
3953
|
+
for await (const event of consumeMessageResponse(response, reader)) {
|
|
3954
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
3955
|
+
turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
|
|
3956
|
+
turn.receivedFollowUpEvents.delete(event);
|
|
3957
|
+
}
|
|
3958
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
3959
|
+
await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
|
|
3960
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
3961
|
+
this.#status = settledStatus(this.#error, this.#conversationClient.conversation);
|
|
3962
|
+
} catch (error) {
|
|
3963
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
3964
|
+
retractResponses?.();
|
|
3965
|
+
if (isAbortError(error)) {
|
|
3966
|
+
this.#status = "ready";
|
|
3967
|
+
this.#messageSubmissions.fail(toError(error), submissionId);
|
|
3968
|
+
} else {
|
|
3969
|
+
const reported = this.#error !== void 0;
|
|
3970
|
+
this.#error ??= toError(error);
|
|
3971
|
+
this.#status = "error";
|
|
3972
|
+
this.#messageSubmissions.fail(this.#error, submissionId);
|
|
3973
|
+
if (!reported) this.#callbacks.onError?.(this.#error);
|
|
3974
|
+
}
|
|
3975
|
+
} finally {
|
|
3976
|
+
reader?.[Symbol.dispose]();
|
|
3977
|
+
this.#finishTurn(turn);
|
|
3406
3978
|
}
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
state:
|
|
3433
|
-
stepIndex: existing.stepIndex,
|
|
3434
|
-
toolCallId: existing.toolCallId,
|
|
3435
|
-
toolMetadata: existing.toolMetadata,
|
|
3436
|
-
toolName: existing.toolName,
|
|
3437
|
-
type: "dynamic-tool"
|
|
3979
|
+
}
|
|
3980
|
+
resume() {
|
|
3981
|
+
if (this.#resumePromise !== void 0) return this.#resumePromise;
|
|
3982
|
+
const promise = this.#resume();
|
|
3983
|
+
this.#resumePromise = promise;
|
|
3984
|
+
const clear = () => {
|
|
3985
|
+
if (this.#resumePromise === promise) this.#resumePromise = void 0;
|
|
3986
|
+
};
|
|
3987
|
+
promise.then(clear, clear);
|
|
3988
|
+
return promise;
|
|
3989
|
+
}
|
|
3990
|
+
async #resume() {
|
|
3991
|
+
if (this.#status !== "ready" && this.#status !== "error") throw new Error("eve session is already processing a turn.");
|
|
3992
|
+
if (this.#session === void 0) throw new Error("An eve session is required before resuming.");
|
|
3993
|
+
const session = this.#session;
|
|
3994
|
+
const turn = createActiveTurn(() => session.cancel());
|
|
3995
|
+
this.#activeTurn = turn;
|
|
3996
|
+
turn.resolveResponse(void 0);
|
|
3997
|
+
this.#error = void 0;
|
|
3998
|
+
this.#status = "resuming";
|
|
3999
|
+
this.#publish();
|
|
4000
|
+
let reader;
|
|
4001
|
+
try {
|
|
4002
|
+
const stream = this.#ensureStream({
|
|
4003
|
+
catchUp: true,
|
|
4004
|
+
startIndex: this.#events.length === session.state.streamIndex ? session.state.streamIndex : 0
|
|
3438
4005
|
});
|
|
4006
|
+
reader = stream.subscribe(turn.abortController.signal);
|
|
4007
|
+
await stream.caughtUp;
|
|
4008
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
4009
|
+
reader.discard();
|
|
4010
|
+
const tail = this.#events.at(-1);
|
|
4011
|
+
if (tail !== void 0) this.#applyTerminalStreamFailure(tail);
|
|
4012
|
+
if (tail && !this.#error && !isSettledSessionTail(this.#events, this.#conversationClient.conversation)) {
|
|
4013
|
+
this.#status = "streaming";
|
|
4014
|
+
this.#publish();
|
|
4015
|
+
for await (const event of reader) {
|
|
4016
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
4017
|
+
turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
|
|
4018
|
+
turn.receivedFollowUpEvents.delete(event);
|
|
4019
|
+
if (isResponseBoundary(event, this.#conversationClient.conversation)) break;
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
|
|
4023
|
+
if (this.#isActiveTurn(turn)) this.#status = settledStatus(this.#error, this.#conversationClient.conversation);
|
|
4024
|
+
} catch (error) {
|
|
4025
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
4026
|
+
if (isAbortError(error)) this.#status = "ready";
|
|
4027
|
+
else {
|
|
4028
|
+
this.#error = toError(error);
|
|
4029
|
+
this.#status = "error";
|
|
4030
|
+
this.#callbacks.onError?.(this.#error);
|
|
4031
|
+
}
|
|
4032
|
+
} finally {
|
|
4033
|
+
reader?.[Symbol.dispose]();
|
|
4034
|
+
this.#finishTurn(turn);
|
|
3439
4035
|
}
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
4036
|
+
}
|
|
4037
|
+
cancel() {
|
|
4038
|
+
const turn = this.#activeTurn;
|
|
4039
|
+
if (turn === void 0) return this.#status === "streaming" && this.#session !== void 0 ? this.#session.cancel() : Promise.resolve({ status: "no_active_turn" });
|
|
4040
|
+
return turn.cancel();
|
|
4041
|
+
}
|
|
4042
|
+
async compact() {
|
|
4043
|
+
return await this.#session?.compact() ?? { status: "no_active_session" };
|
|
4044
|
+
}
|
|
4045
|
+
async clear() {
|
|
4046
|
+
return await this.#session?.clear() ?? { status: "no_active_session" };
|
|
4047
|
+
}
|
|
4048
|
+
async retire() {
|
|
4049
|
+
if (this.#externalSession) throw new Error("retire() needs a store-owned session. Call reset() on the session you supplied, then create a new store for the next session.");
|
|
4050
|
+
const result = await this.#session?.reset() ?? { status: "no_active_session" };
|
|
4051
|
+
this.reset();
|
|
4052
|
+
return result;
|
|
4053
|
+
}
|
|
4054
|
+
[attachStore]() {
|
|
4055
|
+
this.#attached = true;
|
|
4056
|
+
if (this.#followChildStreams && !this.#conversationClient.following) this.#followSubagents();
|
|
4057
|
+
if (this.#autoPrewarm && this.#session === void 0) this.prewarm().catch(() => {});
|
|
4058
|
+
}
|
|
4059
|
+
[detachStore]() {
|
|
4060
|
+
this.#attached = false;
|
|
4061
|
+
this.#conversationClient.stop();
|
|
4062
|
+
this.#activeTurn?.abortController.abort();
|
|
4063
|
+
this.#resetPrewarm();
|
|
4064
|
+
this.#resumePromise = void 0;
|
|
4065
|
+
}
|
|
4066
|
+
reset() {
|
|
4067
|
+
this.#conversationClient.stop();
|
|
4068
|
+
const turn = this.#activeTurn;
|
|
4069
|
+
this.#activeTurn = void 0;
|
|
4070
|
+
turn?.resolveResponse(void 0);
|
|
4071
|
+
turn?.resolveCompletion();
|
|
4072
|
+
turn?.abortController.abort();
|
|
4073
|
+
this.#resetPrewarm();
|
|
4074
|
+
this.#resumePromise = void 0;
|
|
4075
|
+
if (!this.#externalSession) this.#session = void 0;
|
|
4076
|
+
this.#events = [];
|
|
4077
|
+
this.#conversationClient.reset();
|
|
4078
|
+
this.#messageSubmissions.reset();
|
|
4079
|
+
if (this.#followChildStreams && this.#attached) this.#followSubagents();
|
|
4080
|
+
this.#error = void 0;
|
|
4081
|
+
this.#status = "ready";
|
|
4082
|
+
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
4083
|
+
this.#publish();
|
|
4084
|
+
if (this.#autoPrewarm && this.#attached) this.prewarm().catch(() => {});
|
|
4085
|
+
}
|
|
4086
|
+
async #sendFollowUp(turn, input, prepareSend) {
|
|
4087
|
+
assertInFlightFollowUp(input);
|
|
4088
|
+
const generation = this.#prewarmGeneration;
|
|
4089
|
+
const signal = createAbortSignal(input.signal, turn.abortController.signal);
|
|
4090
|
+
let retractResponses = this.#conversationClient.projectResponses(input.inputResponses);
|
|
4091
|
+
const preparedInput = await waitWithSignal(Promise.resolve(prepareSend?.(input)), signal).then((prepared) => {
|
|
4092
|
+
const next = validateFollowUp(prepared ?? input);
|
|
4093
|
+
if (next === input) return next;
|
|
4094
|
+
retractResponses = this.#conversationClient.replaceResponses(retractResponses, next);
|
|
4095
|
+
return next;
|
|
4096
|
+
}).catch((error) => {
|
|
4097
|
+
retractResponses?.();
|
|
4098
|
+
throw error;
|
|
4099
|
+
});
|
|
4100
|
+
if (generation !== this.#prewarmGeneration) return;
|
|
4101
|
+
if (!this.#isActiveTurn(turn)) {
|
|
4102
|
+
retractResponses?.();
|
|
4103
|
+
return await this.#submit(preparedInput);
|
|
4104
|
+
}
|
|
4105
|
+
const submissionId = this.#messageSubmissions.submit(preparedInput, this.#events.length, activeTurnForOptimisticFollowUp(this.#events));
|
|
4106
|
+
if (submissionId !== void 0) turn.followUpSubmissionIds.add(submissionId);
|
|
4107
|
+
this.#publish();
|
|
4108
|
+
let dispatch;
|
|
4109
|
+
dispatch = (async () => {
|
|
4110
|
+
try {
|
|
4111
|
+
const signal = createAbortSignal(preparedInput.signal, turn.abortController.signal);
|
|
4112
|
+
await waitWithSignal(turn.response, signal);
|
|
4113
|
+
if (!this.#isActiveTurn(turn) || this.#session === void 0) throw new Error("The active eve turn ended before the follow-up could be sent.");
|
|
4114
|
+
this.#ensureStream({
|
|
4115
|
+
headers: preparedInput.headers,
|
|
4116
|
+
streamReconnectPolicy: preparedInput.streamReconnectPolicy
|
|
4117
|
+
});
|
|
4118
|
+
const response = (await dispatchSessionTurn({
|
|
4119
|
+
session: this.#session,
|
|
4120
|
+
turn: {
|
|
4121
|
+
...preparedInput,
|
|
4122
|
+
signal
|
|
4123
|
+
}
|
|
4124
|
+
})).response;
|
|
4125
|
+
retractResponses = void 0;
|
|
4126
|
+
if (preparedInput.message === void 0) return;
|
|
4127
|
+
turn.acceptedFollowUps += 1;
|
|
4128
|
+
this.#correlate(submissionId, response);
|
|
4129
|
+
} catch (error) {
|
|
4130
|
+
if (this.#isActiveTurn(turn)) {
|
|
4131
|
+
this.#messageSubmissions.fail(toError(error), submissionId);
|
|
4132
|
+
retractResponses?.();
|
|
4133
|
+
this.#publish();
|
|
4134
|
+
}
|
|
4135
|
+
throw error;
|
|
4136
|
+
} finally {
|
|
4137
|
+
turn.followUpDispatches.delete(dispatch);
|
|
4138
|
+
}
|
|
4139
|
+
})();
|
|
4140
|
+
turn.followUpDispatches.add(dispatch);
|
|
4141
|
+
await dispatch;
|
|
4142
|
+
await turn.completion;
|
|
4143
|
+
}
|
|
4144
|
+
async #dispatchTurn(input) {
|
|
4145
|
+
const streamOptions = {
|
|
4146
|
+
headers: input.headers,
|
|
4147
|
+
streamReconnectPolicy: input.streamReconnectPolicy
|
|
4148
|
+
};
|
|
4149
|
+
if (this.#prewarmPromise !== void 0) {
|
|
4150
|
+
await waitWithSignal(this.#prewarmPromise.catch((error) => {
|
|
4151
|
+
if (this.#session !== void 0) throw error;
|
|
4152
|
+
}), input.signal);
|
|
4153
|
+
input.signal?.throwIfAborted();
|
|
3479
4154
|
}
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
const
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
4155
|
+
const session = this.#session;
|
|
4156
|
+
let reader;
|
|
4157
|
+
try {
|
|
4158
|
+
const dispatched = await dispatchSessionTurn({
|
|
4159
|
+
client: this.#client,
|
|
4160
|
+
session,
|
|
4161
|
+
turn: input,
|
|
4162
|
+
beforeSend: () => {
|
|
4163
|
+
reader = this.#ensureStream(streamOptions).subscribe(input.signal);
|
|
4164
|
+
}
|
|
4165
|
+
});
|
|
4166
|
+
if (dispatched.created) {
|
|
4167
|
+
this.#adoptSession(dispatched.session);
|
|
4168
|
+
reader = this.#ensureStream(streamOptions).subscribe(input.signal);
|
|
4169
|
+
}
|
|
4170
|
+
return {
|
|
4171
|
+
response: dispatched.response,
|
|
4172
|
+
reader
|
|
3495
4173
|
};
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
case "task.settled": {
|
|
3500
|
-
const existing = findToolPart(data, event.data.callId);
|
|
3501
|
-
if (existing === void 0) return data;
|
|
3502
|
-
return replaceToolPart(data, createSettledTaskPart(existing, event));
|
|
4174
|
+
} catch (error) {
|
|
4175
|
+
reader?.[Symbol.dispose]();
|
|
4176
|
+
throw error;
|
|
3503
4177
|
}
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
}
|
|
4178
|
+
}
|
|
4179
|
+
#ensureStream(options = {}) {
|
|
4180
|
+
if (this.#session === void 0) throw new Error("A session is required before opening its stream.");
|
|
4181
|
+
const generation = this.#prewarmGeneration;
|
|
4182
|
+
if (this.#followChildStreams && !this.#conversationClient.following) this.#followSubagents();
|
|
4183
|
+
return this.#conversationClient.stream(this.#session, {
|
|
4184
|
+
...options,
|
|
4185
|
+
onEvent: (event) => {
|
|
4186
|
+
if (generation === this.#prewarmGeneration) this.#acceptServerEvent(event);
|
|
4187
|
+
},
|
|
4188
|
+
onError: (error) => {
|
|
4189
|
+
if (generation !== this.#prewarmGeneration || this.#activeTurn !== void 0) return;
|
|
4190
|
+
this.#fail(error);
|
|
4191
|
+
}
|
|
3518
4192
|
});
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
4193
|
+
}
|
|
4194
|
+
#adoptSession(session) {
|
|
4195
|
+
this.#session = session;
|
|
4196
|
+
if (this.#followChildStreams && this.#attached) this.#followSubagents();
|
|
4197
|
+
this.#callbacks.onSessionChange?.(session.state);
|
|
4198
|
+
this.#publish();
|
|
4199
|
+
}
|
|
4200
|
+
#fail(error) {
|
|
4201
|
+
this.#error = toError(error);
|
|
4202
|
+
this.#status = "error";
|
|
4203
|
+
this.#callbacks.onError?.(this.#error);
|
|
4204
|
+
this.#publish();
|
|
4205
|
+
}
|
|
4206
|
+
#followSubagents() {
|
|
4207
|
+
if (this.#session) this.#conversationClient.follow(this.#session, this.#events);
|
|
4208
|
+
}
|
|
4209
|
+
#resetPrewarm() {
|
|
4210
|
+
this.#prewarmGeneration += 1;
|
|
4211
|
+
this.#prewarmController?.abort();
|
|
4212
|
+
this.#prewarmController = void 0;
|
|
4213
|
+
this.#prewarmPromise = void 0;
|
|
4214
|
+
}
|
|
4215
|
+
#finishTurn(turn) {
|
|
4216
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
4217
|
+
turn.resolveResponse(void 0);
|
|
4218
|
+
this.#activeTurn = void 0;
|
|
4219
|
+
try {
|
|
4220
|
+
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
4221
|
+
this.#publish();
|
|
4222
|
+
this.#callbacks.onFinish?.(this.#snapshot);
|
|
4223
|
+
} finally {
|
|
4224
|
+
turn.resolveCompletion();
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
#isActiveTurn(turn) {
|
|
4228
|
+
return this.#activeTurn === turn;
|
|
4229
|
+
}
|
|
4230
|
+
#acceptServerEvent(event) {
|
|
4231
|
+
const wasStreaming = this.#status === "streaming";
|
|
4232
|
+
if (!this.#conversationClient.observe(event, {
|
|
4233
|
+
onAccepted: () => {
|
|
4234
|
+
this.#events = [...this.#events, event];
|
|
3525
4235
|
},
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
case "turn.cancelled": return updateAssistantMessage(data, event.data.turnId, (message) => ({
|
|
3529
|
-
...message,
|
|
3530
|
-
metadata: {
|
|
3531
|
-
...message.metadata,
|
|
3532
|
-
status: "complete"
|
|
4236
|
+
project: (accepted) => {
|
|
4237
|
+
this.#handleReconciliation(this.#messageSubmissions.apply(accepted));
|
|
3533
4238
|
},
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
}
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
4239
|
+
notify: false
|
|
4240
|
+
})) return false;
|
|
4241
|
+
this.#callbacks.onEvent?.(event);
|
|
4242
|
+
this.#applyTerminalStreamFailure(event);
|
|
4243
|
+
const { conversation } = this.#conversationClient;
|
|
4244
|
+
const settled = isSettledSessionTail(this.#events, conversation) && conversation.activeTurnId === void 0;
|
|
4245
|
+
if (this.#status !== "resuming" && this.#error === void 0) {
|
|
4246
|
+
if ("data" in event && event.data !== void 0 && "turnId" in event.data) this.#status = "streaming";
|
|
4247
|
+
if (this.#activeTurn === void 0 && settled) this.#status = "ready";
|
|
4248
|
+
}
|
|
4249
|
+
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
4250
|
+
if (this.#status !== "resuming") this.#publish();
|
|
4251
|
+
if (this.#activeTurn === void 0 && wasStreaming && settled) this.#callbacks.onFinish?.(this.#snapshot);
|
|
4252
|
+
return true;
|
|
3542
4253
|
}
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
name: existing.toolMetadata?.eve?.name ?? existing.toolName
|
|
3562
|
-
} }),
|
|
3563
|
-
toolName: existing.toolName,
|
|
3564
|
-
type: "dynamic-tool"
|
|
3565
|
-
});
|
|
3566
|
-
}
|
|
3567
|
-
function resolveInputRequest(data, resolution) {
|
|
3568
|
-
if (resolution.response !== void 0) return respondToInputRequest(data, resolution.response);
|
|
3569
|
-
const existing = findToolPartByApprovalId(data, resolution.requestId);
|
|
3570
|
-
if (!existing) return data;
|
|
3571
|
-
return updateToolPart(data, existing.toolCallId, {
|
|
3572
|
-
input: existing.input,
|
|
3573
|
-
output: { status: resolution.outcome },
|
|
3574
|
-
state: "output-available",
|
|
3575
|
-
stepIndex: existing.stepIndex,
|
|
3576
|
-
toolCallId: existing.toolCallId,
|
|
3577
|
-
toolMetadata: existing.toolMetadata,
|
|
3578
|
-
toolName: existing.toolName,
|
|
3579
|
-
type: "dynamic-tool"
|
|
3580
|
-
});
|
|
3581
|
-
}
|
|
3582
|
-
function updateAssistantMessage(data, turnId, update) {
|
|
3583
|
-
const message = data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === turnId) ?? createAssistantMessage(turnId);
|
|
3584
|
-
return upsertMessage(data, update(message));
|
|
3585
|
-
}
|
|
3586
|
-
function updateAssistantMetadata(data, turnId, metadata) {
|
|
3587
|
-
return updateAssistantMessage(data, turnId, (message) => ({
|
|
3588
|
-
...message,
|
|
3589
|
-
metadata: {
|
|
3590
|
-
...message.metadata,
|
|
3591
|
-
...metadata
|
|
4254
|
+
#correlate(submissionId, response) {
|
|
4255
|
+
const deliveryId = getMessageResponseDeliveryId(response);
|
|
4256
|
+
const reconciled = this.#messageSubmissions.correlate(submissionId, deliveryId, this.#events);
|
|
4257
|
+
if (this.#handleReconciliation(reconciled)) this.#publish();
|
|
4258
|
+
}
|
|
4259
|
+
#handleReconciliation(reconciliation) {
|
|
4260
|
+
if (reconciliation === void 0) return false;
|
|
4261
|
+
if (this.#activeTurn !== void 0) countFollowUpDeliveries(this.#activeTurn, reconciliation);
|
|
4262
|
+
return true;
|
|
4263
|
+
}
|
|
4264
|
+
#applyTerminalStreamFailure(event) {
|
|
4265
|
+
const error = toTerminalStreamFailureError(event);
|
|
4266
|
+
if (error === void 0) return;
|
|
4267
|
+
this.#status = "error";
|
|
4268
|
+
this.#messageSubmissions.failAll(error);
|
|
4269
|
+
if (this.#error === void 0) {
|
|
4270
|
+
this.#error = error;
|
|
4271
|
+
this.#callbacks.onError?.(error);
|
|
3592
4272
|
}
|
|
3593
|
-
}
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
...message,
|
|
3612
|
-
parts: [...message.parts, ...Array.from({ length: missingCount }, () => ({ type: "step-start" }))]
|
|
3613
|
-
};
|
|
3614
|
-
}
|
|
3615
|
-
function upsertPart(message, next) {
|
|
3616
|
-
const index = message.parts.findIndex((part) => partKey(part) === partKey(next));
|
|
3617
|
-
const parts = index === -1 ? [...message.parts, next] : [
|
|
3618
|
-
...message.parts.slice(0, index),
|
|
3619
|
-
next,
|
|
3620
|
-
...message.parts.slice(index + 1)
|
|
3621
|
-
];
|
|
3622
|
-
return {
|
|
3623
|
-
...message,
|
|
3624
|
-
metadata: {
|
|
3625
|
-
...message.metadata,
|
|
3626
|
-
status: next.type === "text" && next.state === "done" ? "complete" : "streaming"
|
|
3627
|
-
},
|
|
3628
|
-
parts
|
|
3629
|
-
};
|
|
3630
|
-
}
|
|
3631
|
-
function updateToolPart(data, toolCallId, next) {
|
|
3632
|
-
const message = data.messages.find((candidate) => candidate.role === "assistant" && candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === toolCallId));
|
|
3633
|
-
if (!message) return data;
|
|
3634
|
-
return upsertMessage(data, upsertPart(message, next));
|
|
3635
|
-
}
|
|
3636
|
-
function replaceToolPart(data, next) {
|
|
3637
|
-
const message = data.messages.find((candidate) => candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === next.toolCallId));
|
|
3638
|
-
if (message === void 0) return data;
|
|
3639
|
-
return upsertMessage(data, {
|
|
3640
|
-
...message,
|
|
3641
|
-
parts: message.parts.map((part) => partKey(part) === partKey(next) ? next : part)
|
|
3642
|
-
});
|
|
3643
|
-
}
|
|
3644
|
-
function completeAuthorization(data, event) {
|
|
3645
|
-
const existing = findLatestPendingAuthorizationPart(data, event.data.name);
|
|
3646
|
-
const next = createAuthorizationCompletedPart(event, existing);
|
|
3647
|
-
if (existing !== void 0) return updateAuthorizationPart(data, existing, next);
|
|
3648
|
-
return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), next));
|
|
3649
|
-
}
|
|
3650
|
-
function updateAuthorizationPart(data, existing, next) {
|
|
3651
|
-
const message = data.messages.find((candidate) => candidate.role === "assistant" && candidate.parts.some((part) => part === existing));
|
|
3652
|
-
if (!message) return data;
|
|
3653
|
-
return upsertMessage(data, upsertPart(message, next));
|
|
3654
|
-
}
|
|
3655
|
-
function findToolPart(data, toolCallId) {
|
|
3656
|
-
for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.toolCallId === toolCallId) return part;
|
|
4273
|
+
}
|
|
4274
|
+
#createSnapshot() {
|
|
4275
|
+
return {
|
|
4276
|
+
data: this.#conversationClient.data,
|
|
4277
|
+
conversation: this.#conversationClient.conversation,
|
|
4278
|
+
error: this.#error,
|
|
4279
|
+
events: this.#events,
|
|
4280
|
+
session: this.#session?.state,
|
|
4281
|
+
status: this.#status
|
|
4282
|
+
};
|
|
4283
|
+
}
|
|
4284
|
+
#publish() {
|
|
4285
|
+
this.#snapshot = this.#createSnapshot();
|
|
4286
|
+
for (const subscriber of this.#subscribers) subscriber();
|
|
4287
|
+
}
|
|
4288
|
+
};
|
|
4289
|
+
function detachEveAgentStore(store) {
|
|
4290
|
+
store[detachStore]();
|
|
3657
4291
|
}
|
|
3658
|
-
function
|
|
3659
|
-
|
|
4292
|
+
function attachEveAgentStore(store) {
|
|
4293
|
+
store[attachStore]();
|
|
3660
4294
|
}
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
4295
|
+
|
|
4296
|
+
//#endregion
|
|
4297
|
+
//#region src/client/agent-host.ts
|
|
4298
|
+
const AGENT_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
|
|
4299
|
+
const EVE_NAMED_AGENT_ROUTE_PREFIX = "/eve";
|
|
4300
|
+
function resolveEveAgentHost(input) {
|
|
4301
|
+
if (input.agent === void 0) return input.host ?? "";
|
|
4302
|
+
if (input.host !== void 0) throw new Error("useEveAgent cannot combine agent and host. Use one target option.");
|
|
4303
|
+
assertValidAgentName(input.agent);
|
|
4304
|
+
return `${EVE_NAMED_AGENT_ROUTE_PREFIX}/${input.agent}`;
|
|
3670
4305
|
}
|
|
3671
|
-
function
|
|
3672
|
-
|
|
4306
|
+
function assertValidAgentName(name) {
|
|
4307
|
+
if (!AGENT_NAME_PATTERN.test(name)) throw new Error(`eve agent name ${JSON.stringify(name)} is invalid. Use lowercase letters, numbers, underscores, or hyphens, starting with a letter or number.`);
|
|
3673
4308
|
}
|
|
3674
4309
|
|
|
3675
4310
|
//#endregion
|
|
3676
4311
|
//#region src/vue/use-eve-agent.ts
|
|
3677
4312
|
function useEveAgent(options = {}) {
|
|
3678
4313
|
if (options.resume && options.initialSession === void 0 && options.session === void 0) throw new Error("useEveAgent({ resume: true }) requires initialSession or session.");
|
|
3679
|
-
const reducer = options.reducer ??
|
|
4314
|
+
const reducer = options.reducer ?? conversationReducer;
|
|
3680
4315
|
const store = new EveAgentStore({
|
|
3681
4316
|
auth: options.auth,
|
|
3682
4317
|
headers: options.headers,
|
|
@@ -3687,6 +4322,7 @@ function useEveAgent(options = {}) {
|
|
|
3687
4322
|
initialEvents: options.initialEvents,
|
|
3688
4323
|
initialSession: options.initialSession,
|
|
3689
4324
|
optimistic: options.optimistic,
|
|
4325
|
+
followSubagents: options.followSubagents,
|
|
3690
4326
|
prewarm: options.prewarm,
|
|
3691
4327
|
reducer,
|
|
3692
4328
|
session: options.session
|
|
@@ -3713,6 +4349,7 @@ function useEveAgent(options = {}) {
|
|
|
3713
4349
|
return {
|
|
3714
4350
|
cancel: () => store.cancel(),
|
|
3715
4351
|
data: computed(() => snapshot.value.data),
|
|
4352
|
+
conversation: computed(() => snapshot.value.conversation),
|
|
3716
4353
|
error: computed(() => snapshot.value.error),
|
|
3717
4354
|
events: computed(() => snapshot.value.events),
|
|
3718
4355
|
prewarm: () => store.prewarm(),
|
|
@@ -3732,4 +4369,4 @@ function useEveAgent(options = {}) {
|
|
|
3732
4369
|
}
|
|
3733
4370
|
|
|
3734
4371
|
//#endregion
|
|
3735
|
-
export {
|
|
4372
|
+
export { openConversationInputs as i, conversationReducer as n, defaultMessageReducer as r, useEveAgent as t };
|