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