eve 0.81.1 → 0.82.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/src/channel/channel-address.d.ts +21 -2
- package/dist/src/channel/channel-address.js +1 -1
- package/dist/src/channel/channel-operations.d.ts +32 -1
- package/dist/src/channel/channel-operations.js +1 -1
- package/dist/src/channel/delivery-idempotency.d.ts +4 -0
- package/dist/src/channel/delivery-idempotency.js +1 -0
- package/dist/src/channel/routes.d.ts +6 -0
- package/dist/src/channel/session.d.ts +5 -0
- package/dist/src/channel/session.js +1 -1
- package/dist/src/channel/types.d.ts +14 -11
- package/dist/src/chunks/{use-eve-agent-Bp6nbhfV.js → use-eve-agent-DTu78IAF.js} +36 -0
- package/dist/src/chunks/{use-eve-agent-DLkjJIm3.js → use-eve-agent-DlznYwQk.js} +36 -0
- package/dist/src/cli/dev/command-options.d.ts +1 -0
- package/dist/src/cli/dev/diagnostic-dump.js +1 -1
- package/dist/src/cli/run.d.ts +1 -0
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/message-reducer-types.d.ts +7 -3
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/client/transcript-reducer.d.ts +6 -3
- package/dist/src/client/transcript-reducer.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +19 -18
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/load-binding-namespace.d.ts +2 -0
- package/dist/src/compiler/load-binding-namespace.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/module-lifecycle.d.ts +1 -1
- package/dist/src/compiler/module-lifecycle.js +1 -1
- package/dist/src/compiler/module-map.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/compiler/project-sources.d.ts +6 -0
- package/dist/src/compiler/project-sources.js +1 -1
- package/dist/src/context/keys.d.ts +2 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/evals/cli/eval-state-directory.d.ts +7 -0
- package/dist/src/evals/cli/eval-state-directory.js +1 -0
- package/dist/src/evals/cli/eval.js +2 -2
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/eve-channel/support.d.ts +2 -0
- package/dist/src/eve-channel/support.js +1 -1
- package/dist/src/eve-channel/types.d.ts +7 -0
- package/dist/src/execution/agent-sessions/context.d.ts +2 -13
- package/dist/src/execution/agent-sessions/context.js +1 -1
- package/dist/src/execution/agent-sessions/runtime-overrides.d.ts +5 -0
- package/dist/src/execution/agent-sessions/runtime-overrides.js +1 -0
- package/dist/src/execution/agent-sessions/session.d.ts +2 -2
- package/dist/src/execution/agent-sessions/session.js +1 -1
- package/dist/src/execution/agent-sessions/steps.d.ts +2 -0
- package/dist/src/execution/agent-sessions/steps.js +1 -1
- package/dist/src/execution/coordination-dispatch-shared.d.ts +5 -5
- package/dist/src/execution/coordination-dispatch-step.d.ts +17 -2
- package/dist/src/execution/coordination-dispatch-step.js +1 -1
- package/dist/src/execution/create-session-step.d.ts +5 -2
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/deliver-payloads.js +1 -1
- package/dist/src/execution/durable-session-store.d.ts +0 -1
- package/dist/src/execution/dynamic-connection-recovery.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/effective-agent-config.d.ts +8 -2
- package/dist/src/execution/effective-agent-config.js +1 -1
- package/dist/src/execution/install-workflow-deployment-id.d.ts +3 -0
- package/dist/src/execution/install-workflow-deployment-id.js +1 -0
- package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
- package/dist/src/execution/node-step.d.ts +1 -0
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/runtime-context.d.ts +2 -0
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/session/active-turn.js +1 -1
- package/dist/src/execution/session/admission.js +1 -1
- package/dist/src/execution/session/checkpoint-migrations.js +1 -1
- package/dist/src/execution/session/entry-input.d.ts +1 -3
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/finalization.js +1 -1
- package/dist/src/execution/session/handoff.d.ts +6 -9
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/input-queue.d.ts +5 -1
- package/dist/src/execution/session/input-queue.js +1 -1
- package/dist/src/execution/session/pending-history.d.ts +5 -0
- package/dist/src/execution/session/pending-history.js +1 -0
- package/dist/src/execution/session/pending-turn-state.js +1 -1
- package/dist/src/execution/session/program.d.ts +1 -1
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/timeout-control.d.ts +18 -4
- package/dist/src/execution/session/timeout-control.js +1 -1
- package/dist/src/execution/session/timeout.d.ts +1 -2
- package/dist/src/execution/session/timeout.js +1 -1
- package/dist/src/execution/session/turn-event-handler.js +1 -1
- package/dist/src/execution/session/turn-step-result.js +1 -1
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn-waiting-step.js +1 -1
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/session-inbox/protocol.js +1 -1
- package/dist/src/execution/session.d.ts +0 -12
- package/dist/src/execution/session.js +2 -2
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/tasks/model-step.js +1 -1
- package/dist/src/execution/tasks/start.d.ts +4 -4
- package/dist/src/execution/tasks/start.js +1 -1
- package/dist/src/execution/tasks/steps.js +1 -1
- package/dist/src/execution/terminate-child-sessions-step.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/tools/workflow/body.d.ts +2 -2
- package/dist/src/execution/workflow-runtime.d.ts +5 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/hitl/approvals.js +1 -1
- package/dist/src/harness/hitl/budget-request.d.ts +12 -6
- package/dist/src/harness/hitl/budget-request.js +1 -1
- package/dist/src/harness/hitl/budget.d.ts +7 -1
- package/dist/src/harness/hitl/budget.js +1 -1
- package/dist/src/harness/hitl/coordinator.js +1 -1
- package/dist/src/harness/hitl/delivery.d.ts +1 -1
- package/dist/src/harness/hitl/delivery.js +1 -1
- package/dist/src/harness/hitl/index.js +1 -1
- package/dist/src/harness/hitl/intake.d.ts +2 -2
- package/dist/src/harness/hitl/intake.js +1 -1
- package/dist/src/harness/messages.d.ts +5 -0
- package/dist/src/harness/messages.js +1 -1
- package/dist/src/harness/model-call/call.d.ts +2 -2
- package/dist/src/harness/model-call/request.d.ts +2 -2
- package/dist/src/harness/session-machine/transitions.d.ts +3 -1
- package/dist/src/harness/session-machine/transitions.js +1 -1
- package/dist/src/harness/step/context.d.ts +3 -0
- package/dist/src/harness/step/context.js +1 -1
- package/dist/src/harness/step/intake.d.ts +5 -2
- package/dist/src/harness/step/intake.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/turn-tag-state.d.ts +7 -26
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/harness/types.d.ts +10 -25
- package/dist/src/internal/application/build-profile.d.ts +3 -0
- package/dist/src/internal/application/build-profile.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +2 -2
- package/dist/src/internal/application/dev-environment.d.ts +13 -0
- package/dist/src/internal/application/dev-environment.js +1 -1
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/internal/authored-definition/core.js +1 -1
- package/dist/src/internal/authored-module-build-options.d.ts +7 -0
- package/dist/src/internal/authored-module-build-options.js +1 -0
- package/dist/src/internal/authored-module-graph.d.ts +13 -0
- package/dist/src/internal/authored-module-graph.js +1 -0
- package/dist/src/internal/authored-module-loader.d.ts +22 -1
- package/dist/src/internal/authored-module-loader.js +1 -3
- package/dist/src/internal/authored-module.d.ts +7 -0
- package/dist/src/internal/authored-module.js +1 -1
- package/dist/src/internal/authored-package-boundary.js +1 -1
- package/dist/src/internal/bundler/nitro-rolldown.d.ts +5 -1
- package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
- package/dist/src/internal/development-programmatic-source-loader.d.ts +1 -0
- package/dist/src/internal/development-programmatic-source-loader.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-generation-metadata.js +1 -1
- package/dist/src/internal/nitro/host/build-application.js +1 -1
- package/dist/src/internal/nitro/host/build-deployment-id.d.ts +8 -0
- package/dist/src/internal/nitro/host/build-deployment-id.js +1 -0
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/dev-server-state.js +1 -1
- package/dist/src/internal/nitro/host/skill-server-assets.js +1 -1
- package/dist/src/internal/nitro/host/stage-build-deployment-id.d.ts +2 -0
- package/dist/src/internal/nitro/host/stage-build-deployment-id.js +1 -0
- package/dist/src/internal/nitro/host/start-production-server.d.ts +1 -0
- package/dist/src/internal/nitro/host/start-production-server.js +3 -3
- package/dist/src/internal/nitro/routes/schedule-task.d.ts +3 -0
- package/dist/src/internal/nitro/routes/schedule-task.js +1 -1
- package/dist/src/internal/programmatic-source-loader.d.ts +1 -0
- package/dist/src/internal/programmatic-source-loader.js +1 -1
- package/dist/src/internal/schedules/disabled.d.ts +2 -0
- package/dist/src/internal/schedules/disabled.js +1 -0
- package/dist/src/internal/workflow/development-world-server.js +1 -1
- package/dist/src/internal/workflow/local-world-data-directory.d.ts +2 -1
- package/dist/src/internal/workflow/local-world-data-directory.js +1 -1
- package/dist/src/internal/workflow-bundle/builder.js +1 -1
- package/dist/src/protocol/message.d.ts +27 -1
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +13 -0
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/chat-sdk/fetch-message.d.ts +10 -0
- package/dist/src/public/channels/chat-sdk/fetch-message.js +1 -0
- package/dist/src/public/channels/chat-sdk/index.d.ts +1 -1
- package/dist/src/public/channels/chat-sdk/reply-context.d.ts +15 -0
- package/dist/src/public/channels/chat-sdk/reply-context.js +2 -0
- package/dist/src/public/channels/discord/discordChannel.d.ts +3 -0
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/github/dispatch.js +1 -1
- package/dist/src/public/channels/github/githubChannel.d.ts +3 -0
- package/dist/src/public/channels/imessage-tapbacks.d.ts +74 -0
- package/dist/src/public/channels/imessage-tapbacks.js +1 -0
- package/dist/src/public/channels/index.d.ts +2 -1
- package/dist/src/public/channels/index.js +1 -1
- package/dist/src/public/channels/linear/linearChannel.d.ts +3 -0
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/linq/inboundContent.d.ts +7 -0
- package/dist/src/public/channels/linq/inboundContent.js +1 -1
- package/dist/src/public/channels/linq/index.d.ts +1 -0
- package/dist/src/public/channels/linq/index.js +1 -1
- package/dist/src/public/channels/linq/linqChannel.d.ts +17 -1
- package/dist/src/public/channels/linq/linqChannel.js +1 -1
- package/dist/src/public/channels/photon/inboundContent.d.ts +7 -0
- package/dist/src/public/channels/photon/inboundContent.js +2 -1
- package/dist/src/public/channels/photon/index.d.ts +1 -0
- package/dist/src/public/channels/photon/index.js +1 -1
- package/dist/src/public/channels/photon/photonIMessageChannel.d.ts +17 -1
- package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -1
- package/dist/src/public/channels/slack/api.d.ts +6 -0
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/model-context.d.ts +7 -0
- package/dist/src/public/channels/slack/model-context.js +1 -1
- package/dist/src/public/channels/slack/reply-delivery.d.ts +5 -0
- package/dist/src/public/channels/slack/reply-delivery.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +17 -3
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -0
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.d.ts +3 -0
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/definitions/agent.d.ts +1 -1
- package/dist/src/public/definitions/channel.d.ts +2 -2
- package/dist/src/public/definitions/channel.js +1 -1
- package/dist/src/public/definitions/hook.d.ts +1 -0
- package/dist/src/public/index.d.ts +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/runtime/agent/resolve-model.d.ts +4 -0
- package/dist/src/runtime/agent/resolve-model.js +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
- package/dist/src/runtime/subagents/dynamic-agent-config.d.ts +2 -1
- package/dist/src/runtime/subagents/dynamic-agent-config.js +1 -1
- package/dist/src/runtime/types.d.ts +3 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/shared/agent-definition.d.ts +31 -42
- package/dist/src/shared/session-history.d.ts +22 -0
- package/dist/src/shared/session-history.js +1 -0
- package/dist/src/subagents/tool.d.ts +1 -3
- package/dist/src/subagents/tool.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/tools/workflow-definition.d.ts +14 -1
- package/dist/src/tracing/eve/conversation-context.d.ts +4 -1
- package/dist/src/tracing/eve/conversation-context.js +1 -1
- package/dist/src/tracing/eve/invoke-tool-span.js +1 -1
- package/dist/src/tracing/eve/operation-input.d.ts +0 -5
- package/dist/src/tracing/eve/operation-input.js +1 -1
- package/dist/src/tracing/eve/otel-registration.js +1 -1
- package/dist/src/tracing/eve/session.d.ts +3 -2
- package/dist/src/tracing/eve/session.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/agent-config.md +86 -65
- package/docs/channels/chat-sdk.mdx +6 -1
- package/docs/channels/custom.mdx +38 -6
- package/docs/channels/eve.mdx +46 -0
- package/docs/channels/linq.mdx +51 -0
- package/docs/channels/photon.mdx +64 -0
- package/docs/channels/slack.mdx +4 -2
- package/docs/concepts/built-in-tools.md +1 -1
- package/docs/concepts/execution-model-and-durability.mdx +12 -5
- package/docs/concepts/sessions-runs-and-streaming.md +9 -8
- package/docs/connections/overview.mdx +1 -1
- package/docs/experimental/dynamic-schedules.mdx +186 -0
- package/docs/experimental/meta.json +4 -0
- package/docs/guides/client/streaming.mdx +1 -0
- package/docs/guides/deployment/self-hosting.md +3 -0
- package/docs/guides/hooks.md +21 -1
- package/docs/memory/overview.mdx +2 -1
- package/docs/patterns/dynamic-scheduling.md +3 -1
- package/docs/reference/cli.md +14 -7
- package/docs/schedules.mdx +2 -0
- package/docs/subagents/index.mdx +2 -0
- package/docs/tools/overview.mdx +2 -1
- package/docs/tools/tasks-upgrade.md +12 -7
- package/docs/tools/tasks.md +10 -6
- package/docs/tools/workflows.mdx +36 -5
- package/docs/tutorial/connect-a-warehouse.mdx +1 -1
- package/docs/tutorial/run-analysis.mdx +1 -1
- package/package.json +1 -1
- package/dist/src/execution/run-session-limits.d.ts +0 -12
- package/dist/src/execution/run-session-limits.js +0 -1
- package/dist/src/harness/session-usage-limits.d.ts +0 -49
- package/dist/src/harness/session-usage-limits.js +0 -1
- package/dist/src/subagents/token-budget.d.ts +0 -15
- package/dist/src/subagents/token-budget.js +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { StandardJSONSchemaV1, StandardSchemaV1 } from "#compiled/@standard-schema/spec/index.js";
|
|
2
2
|
import type { ToolApproval } from "#approval/definition.js";
|
|
3
3
|
import type { MessageResult, SendTurnOptions } from "#client/types.js";
|
|
4
|
+
import type { AgentModelOptionsDefinition, AgentReasoningDefinition } from "#shared/agent-definition.js";
|
|
4
5
|
import type { JsonObject } from "#shared/json.js";
|
|
5
6
|
import { type PublicToolDefinition, type ToolContext, type ToolInputRequest, type ToolInputRequestOptions, type ToolInputResponse } from "#tools/definition.js";
|
|
6
7
|
import type { ToolModelOutput } from "#tools/model-output.js";
|
|
@@ -9,6 +10,18 @@ export type { WorkflowToolEntryPoint };
|
|
|
9
10
|
export interface WorkflowAgentMetadata {
|
|
10
11
|
readonly description: string;
|
|
11
12
|
}
|
|
13
|
+
/** A serializable model selection for a local `ctx.agent` session. */
|
|
14
|
+
export type AgentSessionModelSelection = string | {
|
|
15
|
+
readonly model: string;
|
|
16
|
+
readonly modelContextWindowTokens?: number;
|
|
17
|
+
readonly modelOptions?: AgentModelOptionsDefinition;
|
|
18
|
+
readonly reasoning?: AgentReasoningDefinition;
|
|
19
|
+
};
|
|
20
|
+
/** Options that bind to a `ctx.agent` session when it opens. */
|
|
21
|
+
export interface AgentSessionOptions {
|
|
22
|
+
/** Override the model for every turn in this local agent session. */
|
|
23
|
+
readonly model?: AgentSessionModelSelection;
|
|
24
|
+
}
|
|
12
25
|
/** Context capabilities available inside an authored `"use step"` helper. */
|
|
13
26
|
export type WorkflowStepToolContext = Pick<ToolContext, "abortSignal" | "callId" | "session" | "toolName" | "getToken" | "requireAuth">;
|
|
14
27
|
/** Options for one message to a `ctx.agent` session. */
|
|
@@ -54,7 +67,7 @@ export type WorkflowSharedContext = Pick<ToolContext, "session" | "toolName" | "
|
|
|
54
67
|
* Returns a new session with the agent of this invocation name. Nothing
|
|
55
68
|
* starts until the first `send`.
|
|
56
69
|
*/
|
|
57
|
-
agent(name: string): AgentSession;
|
|
70
|
+
agent(name: string, options?: AgentSessionOptions): AgentSession;
|
|
58
71
|
/** Metadata for agents callable by this workflow, including hidden agents. */
|
|
59
72
|
agents: Readonly<Record<string, WorkflowAgentMetadata>>;
|
|
60
73
|
/**
|
|
@@ -3,10 +3,13 @@ export declare function withConversationId(context: Context, conversationId: str
|
|
|
3
3
|
interface OperationConversation {
|
|
4
4
|
readonly rootSessionId?: string;
|
|
5
5
|
readonly sessionId: string;
|
|
6
|
+
readonly traceSessionId?: string;
|
|
6
7
|
}
|
|
8
|
+
export declare function traceSessionIdOf(scope: OperationConversation): string;
|
|
7
9
|
export declare function operationConversationId(input: OperationConversation): string;
|
|
8
|
-
export declare function
|
|
10
|
+
export declare function withOperationTraceContext(context: Context, input: OperationConversation): Context;
|
|
9
11
|
export declare function conversationIdFromContext(context: unknown): string | undefined;
|
|
12
|
+
export declare function traceSessionIdFromContext(context: unknown): string | undefined;
|
|
10
13
|
export declare function readConversationBaggage(value: string | null): string | undefined;
|
|
11
14
|
export declare function writeConversationBaggage(value: string | undefined, conversationId: string | undefined): string | undefined;
|
|
12
15
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readBaggageMember,replaceBaggageMember}from"#protocol/baggage.js";import{readConversationId,resolveConversationId}from"#shared/conversation-identity.js";import{createContextKey}from"#compiled/@opentelemetry/api/index.js";const BAGGAGE_KEY=`eve.conversation.id`,CONVERSATION_KEY=createContextKey(`eve.trace.conversation.id`);function withConversationId(e,t){return e.setValue(CONVERSATION_KEY,t)}function operationConversationId(e){return resolveConversationId(e.rootSessionId??e.sessionId)}function
|
|
1
|
+
import{readBaggageMember,replaceBaggageMember}from"#protocol/baggage.js";import{readConversationId,resolveConversationId}from"#shared/conversation-identity.js";import{createContextKey}from"#compiled/@opentelemetry/api/index.js";const BAGGAGE_KEY=`eve.conversation.id`,CONVERSATION_KEY=createContextKey(`eve.trace.conversation.id`),TRACE_SESSION_KEY=createContextKey(`eve.trace.session.id`);function withConversationId(e,t){return e.setValue(CONVERSATION_KEY,t)}function traceSessionIdOf(e){return e.traceSessionId??e.rootSessionId??e.sessionId}function operationConversationId(e){return resolveConversationId(e.rootSessionId??e.sessionId)}function withOperationTraceContext(e,t){return withConversationId(e,operationConversationId(t)).setValue(TRACE_SESSION_KEY,traceSessionIdOf(t))}function conversationIdFromContext(e){return readConversationId(readContextValue(e,CONVERSATION_KEY))}function traceSessionIdFromContext(e){let t=readContextValue(e,TRACE_SESSION_KEY);return typeof t==`string`&&t.length>0?t:void 0}function readContextValue(e,t){if(typeof e!=`object`||!e)return;let n=Reflect.get(e,`getValue`);if(typeof n==`function`)return Reflect.apply(n,e,[t])}function readConversationBaggage(e){let t=readBaggageMember(e,BAGGAGE_KEY);return typeof t==`string`?void 0:readConversationId(t.value)}function writeConversationBaggage(e,t){let n=readConversationId(t);return n===void 0?e:replaceBaggageMember(e,BAGGAGE_KEY,encodeURIComponent(n))}export{conversationIdFromContext,operationConversationId,readConversationBaggage,traceSessionIdFromContext,traceSessionIdOf,withConversationId,withOperationTraceContext,writeConversationBaggage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,formatError}from"#internal/logging.js";import{applyLiveDeliveryAudienceCeiling}from"#shared/forwarded-trace-policy.js";import{DIRECT_TOOL_CALL_ATTRIBUTE,DIRECT_TOOL_CALL_VALUE}from"#tracing/local/inspection.js";import{resolveInstrumentationEnvironment}from"#internal/application/dev-environment.js";import{operationConversationId}from"#tracing/eve/conversation-context.js";import{resolveTracePolicy}from"#shared/trace-policy.js";import{context}from"#compiled/@opentelemetry/api/index.js";import{buildConversationContext}from"#channel/conversation-context.js";import{markAgentTraceContext}from"#tracing/eve/agent-trace-context.js";import{toolCallIdempotencyKey}from"#instrumentation/lifecycle.js";import{contentAttribute,mcpLifecycle,withErrorContent}from"#compiled/@vercel/agent-runs/otel.js";import{otelTelemetry}from"#compiled/@vercel/agent-runs/index.js";import{getInstrumentationRuntime}from"#instrumentation/runtime-global.js";import{MCP_SERIALIZER}from"#tracing/eve/mcp.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveOutputMapping}from"#tracing/eve/profile.js";const log=createLogger(`invoke-tool`),agentTelemetry=()=>otelTelemetry({tracerName:`eve.agent`,mapping:eveOutputMapping()});async function withInvokeToolSpan(e,t){let n=withErrorContent(context.active(),!1);return await context.with(n,()=>traced(e,n,t))}async function traced(e,t,n){let r=getInstrumentationRuntime();if(r===void 0)return await n(silentObserver);let i=agentTelemetry(),a=buildConversationContext({adapter:e.origin?.adapter??{kind:`channel`},auth:e.auth,channelName:e.origin?.channelName},resolveInstrumentationEnvironment()),o=
|
|
1
|
+
import{createLogger,formatError}from"#internal/logging.js";import{applyLiveDeliveryAudienceCeiling}from"#shared/forwarded-trace-policy.js";import{DIRECT_TOOL_CALL_ATTRIBUTE,DIRECT_TOOL_CALL_VALUE}from"#tracing/local/inspection.js";import{resolveInstrumentationEnvironment}from"#internal/application/dev-environment.js";import{operationConversationId,withOperationTraceContext}from"#tracing/eve/conversation-context.js";import{resolveTracePolicy}from"#shared/trace-policy.js";import{context}from"#compiled/@opentelemetry/api/index.js";import{buildConversationContext}from"#channel/conversation-context.js";import{markAgentTraceContext}from"#tracing/eve/agent-trace-context.js";import{toolCallIdempotencyKey}from"#instrumentation/lifecycle.js";import{contentAttribute,mcpLifecycle,withErrorContent}from"#compiled/@vercel/agent-runs/otel.js";import{otelTelemetry}from"#compiled/@vercel/agent-runs/index.js";import{getInstrumentationRuntime}from"#instrumentation/runtime-global.js";import{MCP_SERIALIZER}from"#tracing/eve/mcp.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveOutputMapping}from"#tracing/eve/profile.js";const log=createLogger(`invoke-tool`),agentTelemetry=()=>otelTelemetry({tracerName:`eve.agent`,mapping:eveOutputMapping()});async function withInvokeToolSpan(e,t){let n=withErrorContent(context.active(),!1);return await context.with(n,()=>traced(e,n,t))}async function traced(e,t,n){let r=getInstrumentationRuntime();if(r===void 0)return await n(silentObserver);let i=agentTelemetry(),a=buildConversationContext({adapter:e.origin?.adapter??{kind:`channel`},auth:e.auth,channelName:e.origin?.channelName},resolveInstrumentationEnvironment()),o=r.hooks.forTrace?.({agentName:e.agentName,...a})??r.hooks,s={attemptId:e.callId,attemptIndex:0,channelAudience:a.audience,functionId:e.agentName,rootSessionId:e.sessionId,sessionId:e.sessionId,stepIndex:0,traceSessionId:e.sessionId,turnId:e.callId},c=toolCallEvents(o,s,e),l=r.otelSettings;if(l===void 0)return await n(c.observer(void 0));let u=resolveTracePolicy(l.tracePolicy,{agentName:e.agentName,...a},e=>log.warn(`tracePolicy threw; dropping the tool call's trace`,{error:formatError(e)}));if(u.action===`drop`)return await i.suppressed(()=>n(c.observer(void 0)));let d=applyLiveDeliveryAudienceCeiling({...u,recordInputs:l.recordInputs&&u.recordInputs,recordOutputs:l.recordOutputs&&u.recordOutputs},a.audience,void 0,a.environment),f=d.action===`record`&&d.recordInputs,p=d.action===`record`&&d.recordOutputs,m=`execute_tool ${e.toolName}`,h=withOperationTraceContext(withChannelAudience(t,a.audience),s),g={"agent.tool.is_framework":!1,"gen_ai.agent.name":e.agentName,"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.call.id":e.callId,"gen_ai.tool.name":e.toolName,"gen_ai.tool.type":`function`,[DIRECT_TOOL_CALL_ATTRIBUTE]:DIRECT_TOOL_CALL_VALUE,"operation.name":`execute_tool`,"resource.name":m,"agent.run.id":e.sessionId,"agent.trace.schema.version":4,"gen_ai.conversation.id":operationConversationId({sessionId:e.sessionId})};process.env.VERCEL_ENV!==void 0&&(g[`vercel.session_id`]=e.sessionId),e.origin!==void 0&&(g[`eve.channel.kind`]=a.channel.kind,g[`eve.channel.name`]=e.origin.channelName);let _=i.startSpan({type:`tool`,operationId:e.callId,name:m,kind:`INTERNAL`,attributes:g},{context:h}),v={emit:!0,recordInputs:f,recordOutputs:p},y=markAgentTraceContext(withErrorContent(h,p)),b=mcpLifecycle({serializer:MCP_SERIALIZER,...v,write:e=>setDefined(_,e),error:(e,t)=>_.fail(p?e:void 0,t)}),x,S=c.observer({failedWith:e=>{x={error:e}},recordInputs:f,span:_});try{let e=await i.run({type:`tool`,reference:_.reference,capture:v,mcp:b},()=>n(S),y);if(_.setAttribute(`eve.tool.outcome`,e.status),e.status===`completed`&&p){let t=contentAttribute(e.output);t!==void 0&&_.setAttribute(`gen_ai.tool.call.result`,t)}return e.status===`invalid-input`?_.fail(void 0,e.status):e.status===`failed`&&_.fail(p?x?.error:void 0,x===void 0?e.status:void 0),e}catch(e){throw _.fail(p?e:void 0),e}finally{_.end(),await r.forceFlush().catch(e=>{log.warn(`flushing a tool call's trace failed`,{error:formatError(e)})})}}const silentObserver={executed:async()=>{},executing:async()=>{},failedWith:()=>{}};function toolCallEvents(e,t,n){let r=e.capturesInputs??e.capturesContent,i=e.capturesOutputs??e.capturesContent,a=toolCallIdempotencyKey(t,n.callId,0);return{observer(o){return{async executing(i){if(o?.recordInputs){let e=contentAttribute(i);e!==void 0&&o.span.setAttribute(`gen_ai.tool.call.arguments`,e)}await e.publish(Object.freeze({callId:n.callId,idempotencyKey:a,input:r?i:void 0,scope:t,toolName:n.toolName,type:`tool.call.started`}))},async executed(n){o?.span.setAttribute(`gen_ai.execute_tool.duration`,n.durationMs/1e3);let r=n.type===`result`?i?{output:n.output,type:`result`}:{type:`result`}:i?{error:n.error,type:`error`}:{type:`error`};await e.publish(Object.freeze({durationMs:n.durationMs,idempotencyKey:a,output:Object.freeze(r),scope:t,type:`tool.call.completed`,outcome:n.type===`result`?`completed`:`failed`}))},failedWith(e){o?.failedWith(e)}}}}}function setDefined(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&e.setAttribute(n,r)}export{withInvokeToolSpan};
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import type { AgentTraceStateStore } from "#tracing/eve/agent-trace-state.js";
|
|
2
2
|
import { type AgentTelemetry, type AgentRun } from "#compiled/@vercel/agent-runs/index.js";
|
|
3
|
-
export declare function traceSessionIdOf(scope: {
|
|
4
|
-
readonly traceSessionId?: string;
|
|
5
|
-
readonly rootSessionId?: string;
|
|
6
|
-
readonly sessionId: string;
|
|
7
|
-
}): string;
|
|
8
3
|
export declare function checkpointContent(value: string | undefined): unknown;
|
|
9
4
|
/** Identity of one eve turn within the shared tracing library. */
|
|
10
5
|
export declare function eveTurnIdentity(input: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveConversationId}from"#shared/conversation-identity.js";import{createAgentRun}from"#compiled/@vercel/agent-runs/index.js";function
|
|
1
|
+
import{resolveConversationId}from"#shared/conversation-identity.js";import{createAgentRun}from"#compiled/@vercel/agent-runs/index.js";function checkpointContent(e){if(e!==void 0)try{return JSON.parse(e)}catch{return}}function eveTurnIdentity(e){return{conversationId:resolveConversationId(e.rootSessionId??e.sessionId),runId:e.sessionId,turnId:e.turnId}}function createEveTracing(e){return createAgentRun({telemetry:e.telemetry,checkpointer:{get:t=>e.stateStore.get(`checkpoint`,t),set:(t,n)=>e.stateStore.set(`checkpoint`,t,n),delete:t=>e.stateStore.delete(`checkpoint`,t)}})}export{checkpointContent,createEveTracing,eveTurnIdentity};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire}from"node:module";import{conversationIdFromContext}from"#tracing/eve/conversation-context.js";import{SpanKind,context,metrics,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{invocationName}from"#compiled/@vercel/agent-runs/otel.js";import{AgentSpanIdGenerator}from"#compiled/@vercel/agent-runs/index.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";const REGISTRATION_SPAN_NAME=`eve.otel.registration`,REPLAY_DEDUPLICATION_LIMIT=1e5,REPLAY_DEDUPLICATION_KEY=Symbol.for(`eve.otel.replay-deduplication`),require=createRequire(import.meta.url),replayDeduplicationGlobal=globalThis;var RegistrationMarkerPropagator=class{#e=!1;extract(e){return e}fields(){return[]}inject(){this.#e=!0}isInstalled(){return this.#e=!1,propagation.inject(context.active(),{},{set:()=>{}}),this.#e}},PrivateSpanFilteringProcessor=class{endedSpans;forwardedSpans=new Set;pendingByParent=new Map;pendingSpanCount=0;processors;startedSpans=new Set;constructor(e,t){this.processors=e,this.endedSpans=t}async forceFlush(){this.drainPendingSpans(),await Promise.all(this.processors.map(e=>e.forceFlush()))}onEnd(e){if(isRegistrationSpan(e))return;let t=spanIdentity(e);if(t!==void 0){if(this.endedSpans.has(t))return;if(this.endedSpans.size>=REPLAY_DEDUPLICATION_LIMIT){let e=this.endedSpans.values().next().value;e!==void 0&&this.endedSpans.delete(e)}this.endedSpans.add(t)}let n=parentIdentity(e);if(n!==void 0&&this.startedSpans.has(n)&&!this.forwardedSpans.has(n)){let t=this.pendingByParent.get(n)??[];t.push(e),this.pendingByParent.set(n,t),this.pendingSpanCount+=1,this.pendingSpanCount>1e4&&this.releaseOldestPendingParent();return}this.forward(e,t)}onStart(e,t){if(isRegistrationSpan(e))return;let n=conversationIdFromContext(t);
|
|
1
|
+
import{createRequire}from"node:module";import{conversationIdFromContext,traceSessionIdFromContext}from"#tracing/eve/conversation-context.js";import{SpanKind,context,metrics,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{invocationName}from"#compiled/@vercel/agent-runs/otel.js";import{AgentSpanIdGenerator}from"#compiled/@vercel/agent-runs/index.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";const REGISTRATION_SPAN_NAME=`eve.otel.registration`,REPLAY_DEDUPLICATION_LIMIT=1e5,REPLAY_DEDUPLICATION_KEY=Symbol.for(`eve.otel.replay-deduplication`),require=createRequire(import.meta.url),replayDeduplicationGlobal=globalThis;var RegistrationMarkerPropagator=class{#e=!1;extract(e){return e}fields(){return[]}inject(){this.#e=!0}isInstalled(){return this.#e=!1,propagation.inject(context.active(),{},{set:()=>{}}),this.#e}},PrivateSpanFilteringProcessor=class{endedSpans;forwardedSpans=new Set;pendingByParent=new Map;pendingSpanCount=0;processors;startedSpans=new Set;constructor(e,t){this.processors=e,this.endedSpans=t}async forceFlush(){this.drainPendingSpans(),await Promise.all(this.processors.map(e=>e.forceFlush()))}onEnd(e){if(isRegistrationSpan(e))return;let t=spanIdentity(e);if(t!==void 0){if(this.endedSpans.has(t))return;if(this.endedSpans.size>=REPLAY_DEDUPLICATION_LIMIT){let e=this.endedSpans.values().next().value;e!==void 0&&this.endedSpans.delete(e)}this.endedSpans.add(t)}let n=parentIdentity(e);if(n!==void 0&&this.startedSpans.has(n)&&!this.forwardedSpans.has(n)){let t=this.pendingByParent.get(n)??[];t.push(e),this.pendingByParent.set(n,t),this.pendingSpanCount+=1,this.pendingSpanCount>1e4&&this.releaseOldestPendingParent();return}this.forward(e,t)}onStart(e,t){if(isRegistrationSpan(e))return;let n=e,r=conversationIdFromContext(t);r!==void 0&&n.attributes?.[`gen_ai.conversation.id`]===void 0&&n.setAttribute(`gen_ai.conversation.id`,r);let i=traceSessionIdFromContext(t);process.env.VERCEL_ENV!==void 0&&i!==void 0&&n.attributes?.[`vercel.session_id`]===void 0&&n.setAttribute(`vercel.session_id`,i);let a=spanIdentity(e);a!==void 0&&addBounded(this.startedSpans,a);for(let n of this.processors)n.onStart(e,t)}async shutdown(){this.drainPendingSpans(),await Promise.all(this.processors.map(e=>e.shutdown()))}drainPendingSpans(){for(;this.pendingByParent.size>0;)this.releaseOldestPendingParent()}releaseOldestPendingParent(){let e=this.pendingByParent.keys().next().value;e!==void 0&&this.releaseChildren(e)}releaseChildren(e){let t=this.pendingByParent.get(e);if(t!==void 0){this.pendingByParent.delete(e),this.pendingSpanCount-=t.length;for(let e of t)this.forward(e,spanIdentity(e))}}forward(e,t){for(let t of this.processors)t.onEnd(e);t!==void 0&&(addBounded(this.forwardedSpans,t),this.releaseChildren(t))}};function registerOtelPipeline(e){let t=e.otel,n=captureOptionalPeerTracerProxy(),r=new AgentSpanIdGenerator,i=new RegistrationMarkerPropagator,a=privateSpanProcessors(t.spanProcessors),o={attributes:t.resource,autoDetectResources:!1,idGenerator:r,instrumentations:t.instrumentations??[],metricReaders:t.metricReaders,propagators:[...t.propagators??[`auto`],i],serviceName:e.serviceName,spanProcessors:a};registerOTel(t.sampler===void 0?o:{...o,traceSampler:t.sampler});let s=globalTracerUses(r),c=i.isInstalled();if((!s||!c)&&rollbackRegistration({ownsPropagator:c,ownsTracer:s}),!s)throw Error("eve could not register OpenTelemetry because another runtime already owns the global tracer provider. Remove the other `registerOTel` call, or move its exporters into eve's `otelIntegration({ spanProcessors: [...] })`.");if(!c)throw Error("eve could not register OpenTelemetry because another runtime already owns the global propagator. Remove the other global propagator registration and declare propagators through eve's `otel()` instead.");let l=runtimeTracerProvider();if(typeof l.forceFlush!=`function`||typeof l.shutdown!=`function`)throw rollbackRegistration({ownsPropagator:c,ownsTracer:s}),Error(`The registered OpenTelemetry tracer provider has no lifecycle methods.`);n?.setDelegate(l);let u=runtimeMeterProvider();return{provider:trace.getTracerProvider(),forceFlush:async()=>{await Promise.all([l.forceFlush(),u.forceFlush?.()])},idGenerator:r,samplesTrace:(e,t)=>samplerAdmitsTrace(r,e,t),shutdown:async()=>{disableInstrumentations(t.instrumentations),await Promise.all([l.shutdown(),u.shutdown?.()])}}}function privateSpanProcessors(e){let t=e.filter(isSpanProcessor);if(t.length===0)return[...e];let n=new PrivateSpanFilteringProcessor(t,replayDeduplicationRegistry()),r=[],i=!1;for(let t of e){if(!isSpanProcessor(t)){r.push(t);continue}i||(i=!0,r.push(n))}return r}function replayDeduplicationRegistry(){let e=replayDeduplicationGlobal[REPLAY_DEDUPLICATION_KEY];if(e!==void 0)return e;let t=new Set;return replayDeduplicationGlobal[REPLAY_DEDUPLICATION_KEY]=t,t}const registerOtel=registerOtelPipeline;function samplerAdmitsTrace(e,t,n={name:invocationName(void 0)}){return(e.withTraceId(t,()=>trace.getTracer(`eve.registration`).startSpan(n.name,{attributes:n.attributes,kind:SpanKind.INTERNAL,root:!0})).spanContext().traceFlags&1)==1}function rollbackRegistration(e){if(e.ownsPropagator&&propagation.disable(),!e.ownsTracer)return;let t=runtimeTracerProvider();if(typeof t.shutdown==`function`)try{t.shutdown().catch(()=>{})}catch{}trace.disable()}function runtimeTracerProvider(){let e=trace.getTracerProvider();return e.getDelegate?.()??e}function runtimeMeterProvider(){let e=metrics.getMeterProvider();return{forceFlush:typeof e?.forceFlush==`function`?()=>e.forceFlush():void 0,shutdown:typeof e?.shutdown==`function`?()=>e.shutdown():void 0}}function disableInstrumentations(e){for(let t of e??[]){let e=t?.disable;if(typeof e==`function`)try{e.call(t)}catch{}}}function globalTracerUses(e){let t=e.allocateSpanId();return e.withSpanId(t,()=>trace.getTracer(`eve.registration`).startSpan(REGISTRATION_SPAN_NAME)).spanContext().spanId===t}function isRegistrationSpan(e){return typeof e==`object`&&!!e&&(`name`in e&&e.name===REGISTRATION_SPAN_NAME||`instrumentationScope`in e&&e.instrumentationScope?.name===`eve.registration`)}function spanIdentity(e){if(typeof e!=`object`||!e||!(`spanContext`in e)||typeof e.spanContext!=`function`)return;let t=e.spanContext();return typeof t.traceId==`string`&&typeof t.spanId==`string`?`${t.traceId}:${t.spanId}`:void 0}function parentIdentity(e){if(typeof e!=`object`||!e||!(`parentSpanContext`in e))return;let t=e.parentSpanContext;return typeof t?.traceId==`string`&&typeof t.spanId==`string`?`${t.traceId}:${t.spanId}`:void 0}function addBounded(e,t){if(e.size>=REPLAY_DEDUPLICATION_LIMIT){let t=e.values().next().value;t!==void 0&&e.delete(t)}e.add(t)}function isSpanProcessor(e){return e!==`auto`}function captureOptionalPeerTracerProxy(){try{let e=require("@opentelemetry/api"),t=e.trace.getTracerProvider();return t instanceof e.ProxyTracerProvider?t:void 0}catch{return}}export{registerOtel,registerOtelPipeline};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type { Context } from "#compiled/@opentelemetry/api/index.js";
|
|
1
2
|
import { type InstrumentationSessionStartedEvent, type InstrumentationTraceSeed, type InstrumentationTurnStartedEvent, type InstrumentationTurnTerminalEvent, type InstrumentationSessionTransitionEvent } from "#instrumentation/lifecycle.js";
|
|
2
3
|
import type { TraceCapturePolicy } from "#tracing/eve/otel-declaration.js";
|
|
3
4
|
import type { AgentSessionTraceState, AgentTraceStateStore } from "#tracing/eve/agent-trace-state.js";
|
|
4
5
|
import type { createEveCapturePolicy } from "#tracing/eve/policy.js";
|
|
5
6
|
import type { ConversationEnvironment } from "#shared/conversation-context.js";
|
|
6
|
-
import type { AgentSpanIdGenerator, AgentRun,
|
|
7
|
+
import type { AgentSpanIdGenerator, AgentRun, TurnOperation } from "#compiled/@vercel/agent-runs/index.js";
|
|
7
8
|
interface EveSessionTracingInput {
|
|
8
9
|
readonly tracing: AgentRun;
|
|
9
10
|
readonly idGenerator: AgentSpanIdGenerator;
|
|
@@ -19,7 +20,7 @@ interface EveSessionTracing {
|
|
|
19
20
|
readonly prepareSessionTrace: (event: InstrumentationSessionStartedEvent) => Promise<InstrumentationTraceSeed>;
|
|
20
21
|
readonly prepareTurnTrace: (event: InstrumentationTurnStartedEvent) => Promise<InstrumentationTraceSeed>;
|
|
21
22
|
/** Hydrates a turn this process or an earlier one started. */
|
|
22
|
-
turnFor(sessionId: string, turnId: string, context?:
|
|
23
|
+
turnFor(sessionId: string, turnId: string, context?: Context): Promise<TurnOperation | undefined>;
|
|
23
24
|
/** Whether the trace policy dropped this turn, so its work must not record spans. */
|
|
24
25
|
dropped(sessionId: string, turnId: string): Promise<boolean>;
|
|
25
26
|
turnTerminal(event: InstrumentationTurnTerminalEvent): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{normalizeChannelAudience}from"#shared/channel-audience.js";import{normalizeInstrumentationChannelKind}from"#internal/instrumentation.js";import{
|
|
1
|
+
import{normalizeChannelAudience}from"#shared/channel-audience.js";import{normalizeInstrumentationChannelKind}from"#internal/instrumentation.js";import{traceSessionIdOf,withOperationTraceContext}from"#tracing/eve/conversation-context.js";import{isSampledTrace,resolveTracePolicy,resolveTracePolicyDecision}from"#shared/trace-policy.js";import{ROOT_CONTEXT}from"#compiled/@opentelemetry/api/index.js";import"#instrumentation/lifecycle.js";import{readInstrumentationDecision}from"#shared/instrumentation-decision.js";import{applyPrincipalTraceDecision}from"#instrumentation/principal-summary.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveTurnIdentity}from"#tracing/eve/operation-input.js";import{eveActivationMetadata}from"#tracing/eve/metadata.js";function createEveSessionTracing(e){let ensureSessionContext=async t=>{let n=await e.stateStore.get(`session`,t.sessionId);if(n===void 0){let r=normalizeChannelAudience(t.channelAudience),i=resolveSessionTraceDecision(t,r,e.environment,e.tracePolicy);n={agentName:t.agentName,channelAudience:r,channelKind:t.channelKind,channelType:t.channelType,decision:i,context:initialSessionContext(e,t,i),parentLineage:t.parentLineage,rootSessionId:t.rootSessionId,traceSessionId:traceSessionIdOf(t),scheduleId:t.scheduleId,title:t.title},await e.stateStore.set(`session`,t.sessionId,n)}return n},prepareSessionTrace=async e=>{let t=await ensureSessionContext(e);return portableSpanContext(t.context,t.decision)},turnKey=(e,t)=>JSON.stringify([e,t]);async function turnFor(t,n,r){let i=await e.stateStore.get(`turn`,turnKey(t,n));if(i===void 0||!isSampledTrace(i.context))return;let a=await e.stateStore.get(`session`,t);return e.tracing.resume({identity:eveTurnIdentity({sessionId:t,rootSessionId:i.rootSessionId,turnId:n}),context:withOperationTraceContext(r??withChannelAudience(ROOT_CONTEXT,a?.channelAudience),{sessionId:t,...i})})}async function dropped(t,n){let r=await e.stateStore.get(`turn`,turnKey(t,n));return r!==void 0&&!isSampledTrace(r.context)}let prepareTurnTrace=async t=>{let n=await e.stateStore.get(`turn`,turnKey(t.sessionId,t.turnId));if(n!==void 0){let r=await e.stateStore.get(`session`,t.sessionId);return portableSpanContext(n.context,r?.decision)}let r=await ensureSessionContext(t),i=t.sequence===0,a=i?t.parentTraceContext:void 0,o=r.decision?.action===`record`,s=a!==void 0&&!(`isRemote`in a&&a.isRemote===!0),c=i?{...r.context,traceId:s?a.traceId:r.context.traceId,isRemote:!1}:{traceId:e.idGenerator.deriveTraceId(`turn:${t.idempotencyKey}`),spanId:e.idGenerator.deriveSpanId(`turn:${t.idempotencyKey}`),traceFlags:+!!o,isRemote:!1},l=r.agentName??(t.parentLineage??r.parentLineage)?.subagentName,u={agentName:l,caller:a===void 0?void 0:adoptedSpanContext(a),context:c,currentPrincipal:applyPrincipalTraceDecision(t.currentPrincipal,r.decision),initiatorPrincipal:applyPrincipalTraceDecision(t.initiatorPrincipal,r.decision),parentLineage:t.parentLineage??r.parentLineage,rootSessionId:t.rootSessionId,traceSessionId:traceSessionIdOf(t),sequence:t.sequence,startTimeMs:Date.now(),subagentName:(t.parentLineage??r.parentLineage)?.subagentName};if(isSampledTrace(c)){let n=await e.tracing.turn({...eveActivationMetadata({session:r,turn:u,sessionId:t.sessionId}),agentName:l,identity:eveTurnIdentity({...t,sessionId:t.sessionId}),framework:{name:`eve`,version:e.frameworkVersion},capture:{emit:!0,...await e.capturePolicy.forOperation(t)},reference:c,parent:s?adoptedSpanContext(a):void 0,links:activationLinks(u),startTimeMs:u.startTimeMs,context:hostContext(r.channelAudience,t)});u={...u,context:{...c,traceFlags:n.reference.traceFlags}}}return await e.stateStore.set(`turn`,turnKey(t.sessionId,t.turnId),u),portableSpanContext(u.context,r.decision)};async function recordTerminal(t,n,r,i){await e.stateStore.update(`turn`,turnKey(t,n),e=>({...e,terminal:r.outcome===`failed`?{outcome:`failed`,errorName:i instanceof Error?i.name:void 0,errorMessage:i instanceof Error?i.message:void 0}:r}))}return{ensureSessionContext,prepareSessionTrace,prepareTurnTrace,turnFor,dropped,async turnTerminal(e){await recordTerminal(e.sessionId,e.turnId,{outcome:e.type===`turn.failed`?`failed`:e.type===`turn.cancelled`?`cancelled`:`completed`},e.type===`turn.failed`?e.error:void 0)},async sessionTransition(t){if(t.turnId===void 0)return;t.type===`session.failed`&&await recordTerminal(t.sessionId,t.turnId,{outcome:`failed`},t.error);let n=await e.stateStore.get(`turn`,turnKey(t.sessionId,t.turnId));if(n===void 0)return;let r=await e.stateStore.get(`session`,t.sessionId),i=await turnFor(t.sessionId,t.turnId);if(i!==void 0){let e=eveActivationMetadata({session:r,turn:n,sessionId:t.sessionId});i.attributes(e.attributes??{}),i.links(activationLinks(n)??[]);let a=n.terminal;if(a===void 0)await i.complete({outcomeUnknown:!0});else if(a.outcome===`failed`){let e=Error(a.errorMessage);e.name=a.errorName??`Error`,await i.complete({outcome:`failed`,failed:!0,error:e,errorType:a.errorName})}else await i.complete({outcome:a.outcome})}await e.stateStore.delete(`turn`,turnKey(t.sessionId,t.turnId))}}}function hostContext(e,t){return withOperationTraceContext(withChannelAudience(ROOT_CONTEXT,e),t)}function activationLinks(e){let t=[];return e.caller?.isRemote===!0&&t.push({context:e.caller,relationship:`agent.dispatch`}),e.channelDelivery?.requestTraceContext!==void 0&&t.push({context:e.channelDelivery.requestTraceContext,relationship:`channel.request`}),t.length===0?void 0:t}function portableSpanContext(e,t){return{decision:t,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function adoptedSpanContext(e){return{isRemote:`isRemote`in e&&e.isRemote===!0,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function initialSessionContext(e,t,n){let r=t.traceSeed;if(r!==void 0)return{...adoptedSpanContext(r),traceFlags:n.action===`drop`?0:r.traceFlags};let i=`session:${t.sessionId}`,a=t.parentTraceContext;return{traceId:a!==void 0&&!(`isRemote`in a&&a.isRemote===!0)?a.traceId:e.idGenerator.deriveTraceId(i),spanId:e.idGenerator.deriveSpanId(i),traceFlags:+(n.action===`record`)}}function resolveSessionTraceDecision(e,t,n,r){let i={audience:t,environment:n};return e.parentTraceContext!==void 0&&!isSampledTrace(e.parentTraceContext)?{action:`drop`}:e.traceSeed?.decision===void 0?e.traceSeed===void 0?e.parentTraceContext===void 0?e.agentName===void 0?r===void 0?resolveTracePolicyDecision(!0,i):{action:`drop`}:resolveTracePolicy(r,{agentName:e.agentName,audience:t,channel:{kind:normalizeInstrumentationChannelKind(e.channelKind??e.channelType)},environment:n,principalType:`unknown`}):resolveTracePolicyDecision(isSampledTrace(e.parentTraceContext),i):resolveTracePolicyDecision(isSampledTrace(e.traceSeed),i):readInstrumentationDecision(e.traceSeed.decision)??{action:`drop`}}export{createEveSessionTracing};
|
package/dist/src/vue/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-
|
|
1
|
+
import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-DTu78IAF.js";
|
|
2
2
|
|
|
3
3
|
//#region src/client/tool-call-state.ts
|
|
4
4
|
function toolCallState(conversation, callId, options = {}) {
|
package/docs/agent-config.md
CHANGED
|
@@ -3,7 +3,7 @@ title: "Agent Configuration"
|
|
|
3
3
|
description: "Configure an eve agent's model, reasoning effort, compaction, limits, and runtime behavior in agent.ts."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
An eve app
|
|
6
|
+
An eve app's root agent uses files under `agent/` by default; a [flat layout](./reference/agent-files#flat-layout) places them directly in the app root instead. Its optional `agent.ts` calls `defineAgent` (from `eve`) when you need to configure the model or other runtime behavior. Declared [subagents](./subagents) have their own `agent.ts` and capabilities; this page covers the configuration shared by root agents and subagents.
|
|
7
7
|
|
|
8
8
|
## Set the model
|
|
9
9
|
|
|
@@ -137,7 +137,7 @@ export default defineAgent({
|
|
|
137
137
|
starting points on Ollama.
|
|
138
138
|
- **Usage.** `includeUsage: true` lets token usage reach eve's
|
|
139
139
|
[session limits](#runtime-limits). Local models report no cost, so
|
|
140
|
-
`
|
|
140
|
+
`costUsd` stays unset in a `sessionUsage` check.
|
|
141
141
|
- **Other servers.** Change `baseURL`, for example to
|
|
142
142
|
`http://localhost:1234/v1` for LM Studio. Pass `apiKey` for a remote
|
|
143
143
|
OpenAI-compatible server that requires one.
|
|
@@ -262,45 +262,88 @@ See [Default harness](./concepts/default-harness#compaction) for how the loop ap
|
|
|
262
262
|
|
|
263
263
|
## Runtime limits
|
|
264
264
|
|
|
265
|
-
Use `limits` for framework-owned runtime caps.
|
|
266
|
-
current durable session
|
|
267
|
-
|
|
265
|
+
Use `limits` for framework-owned runtime caps. `sessionUsage` decides when the
|
|
266
|
+
current durable session must stop starting model calls. It receives the
|
|
267
|
+
session's usage and returns `true` when the limit is reached:
|
|
268
268
|
|
|
269
269
|
```ts title="agent/agent.ts"
|
|
270
270
|
export default defineAgent({
|
|
271
271
|
model: "anthropic/claude-opus-5.5",
|
|
272
272
|
limits: {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
273
|
+
sessionUsage: ({ window }) =>
|
|
274
|
+
window.inputTokens - window.cacheReadTokens >= 200_000 ||
|
|
275
|
+
window.outputTokens >= 20_000 ||
|
|
276
|
+
(window.costUsd ?? 0) >= 1.5,
|
|
276
277
|
sessionTimeoutMs: 7 * 24 * 60 * 60 * 1_000,
|
|
277
278
|
},
|
|
278
279
|
});
|
|
279
280
|
```
|
|
280
281
|
|
|
281
|
-
`sessionTimeoutMs` sets
|
|
282
|
-
sessions. It defaults to 30 days
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
282
|
+
`sessionTimeoutMs` sets how long a session may sit idle before eve completes it,
|
|
283
|
+
for every session, including delegated sessions. It defaults to 30 days. The
|
|
284
|
+
idle window starts at creation and restarts each time a turn settles, including
|
|
285
|
+
turns that answer a message, clear or compact the context, or end in
|
|
286
|
+
cancellation. A session never expires while a turn is open, including a turn
|
|
287
|
+
held open while its [tasks](./tools/tasks) work or while it waits for a person
|
|
288
|
+
to answer; the window restarts when that turn settles. Process restarts do not
|
|
289
|
+
change the window. When the window elapses, eve emits `session.completed` and
|
|
290
|
+
releases every continuation address; the next qualifying channel message starts
|
|
291
|
+
fresh. To carry an earlier conversation into the fresh session, pass it as
|
|
292
|
+
[prior history](./channels/eve#start-from-prior-history). Set it to `false` to
|
|
293
|
+
disable the timeout. Session expiration follows
|
|
294
|
+
[run-data retention](#run-data-retention); a zero-retention session loses its
|
|
295
|
+
stored payloads when it ends.
|
|
296
|
+
|
|
297
|
+
`sessionUsage` gets two usage records with `inputTokens`, `outputTokens`,
|
|
298
|
+
`cacheReadTokens`, `cacheWriteTokens`, and `costUsd`: `total` is everything
|
|
299
|
+
the session has spent, and `window` is what it spent since the last approved
|
|
300
|
+
continuation. `inputTokens` includes cache reads and writes. Subtract
|
|
301
|
+
`cacheReadTokens` to count only new input; cache reads are the history a
|
|
302
|
+
provider replays from its prompt cache on every step. `costUsd` is the model
|
|
303
|
+
token cost in US dollars that AI Gateway reports with each step, not tool or
|
|
304
|
+
infrastructure spend; it is unset when no step reported a cost.
|
|
305
|
+
|
|
306
|
+
When `sessionUsage` is omitted, the limit is `40_000_000` new input tokens per
|
|
307
|
+
window:
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
({ window }) => window.inputTokens - window.cacheReadTokens >= 40_000_000;
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
`sessionUsage` can raise its threshold after each approval. This limit asks
|
|
314
|
+
at 20,000 new input tokens, then at 40,000, 80,000, and so on:
|
|
315
|
+
|
|
316
|
+
```ts title="agent/agent.ts"
|
|
317
|
+
export default defineAgent({
|
|
318
|
+
model: "anthropic/claude-opus-5.5",
|
|
319
|
+
limits: {
|
|
320
|
+
sessionUsage: ({ total, window }) => {
|
|
321
|
+
const used = total.inputTokens - total.cacheReadTokens;
|
|
322
|
+
// Usage when the last continuation was approved; 0 before the first.
|
|
323
|
+
const approvedAt = used - (window.inputTokens - window.cacheReadTokens);
|
|
324
|
+
// Double past it, so each approval allows twice the usage before the next prompt.
|
|
325
|
+
let next = 20_000;
|
|
326
|
+
while (next <= approvedAt) next *= 2;
|
|
327
|
+
return used >= next;
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Set `sessionUsage: () => false` to leave sessions uncapped; `sessionUsage:
|
|
334
|
+
false` is not accepted. eve calls `sessionUsage` before each model call once
|
|
335
|
+
the window has usage. The model call that crosses a limit is allowed to finish
|
|
336
|
+
because exact usage arrives after the call completes. Before the next model
|
|
337
|
+
call, eve pauses the turn (`turn.waiting`) and sends a deterministic
|
|
338
|
+
continuation prompt with two options: **Continue** starts a new window and
|
|
339
|
+
resumes the same turn, and **Stop** cancels the in-flight turn through the
|
|
340
|
+
standard cancellation path (`turn.cancelled` → `session.waiting`). Stop is a
|
|
341
|
+
user decision, not an error. The session stays resumable; because it is still
|
|
342
|
+
over budget after Stop, the next message raises a new prompt. Declining a
|
|
300
343
|
delegated child's prompt cancels the root turn, which cascades to the whole
|
|
301
|
-
delegation tree
|
|
302
|
-
could retry
|
|
303
|
-
|
|
344
|
+
delegation tree, so the delegating parent never receives an error result it
|
|
345
|
+
could retry. A reply that answers neither option is queued while the existing
|
|
346
|
+
prompt stays pending; eve does not raise another
|
|
304
347
|
copy or start another turn. The reply is received (`message.received`) and
|
|
305
348
|
processed in the held turn once the budget is granted.
|
|
306
349
|
|
|
@@ -312,44 +355,22 @@ turn or duplicate the prompt.
|
|
|
312
355
|
|
|
313
356
|
Sessions that cannot request input from a human, such as markdown schedules and
|
|
314
357
|
delegated runs without input proxying, skip the prompt and fail the next model
|
|
315
|
-
call with `
|
|
316
|
-
`
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
step; AI Gateway supplies this value, while model steps without reported cost
|
|
326
|
-
do not add to the limit. Set any usage limit to `false` to uncap that axis.
|
|
327
|
-
|
|
328
|
-
Delegated subagent sessions have no fixed default. Each child receives a share
|
|
329
|
-
of the delegating parent's remaining quota when it starts: the remainder in
|
|
330
|
-
the current budget window split evenly across the agent tasks that one model
|
|
331
|
-
step starts. A session that a workflow tool opens with `ctx.agent` receives
|
|
332
|
-
the share of the model step that called the tool, or the whole remainder when
|
|
333
|
-
that step starts no agent tasks; eve does not divide that share among several
|
|
334
|
-
sessions one call opens. A child keeps its grant for its whole session,
|
|
335
|
-
including turns that later calls with `taskId` start. Remote agent tasks count
|
|
336
|
-
toward the split but receive no grant: they run under their own deployment's
|
|
337
|
-
limits.
|
|
338
|
-
|
|
339
|
-
A child's usage, including what the child's own subagents spent, counts
|
|
340
|
-
against the parent's quota. An agent task's usage counts with each reply it
|
|
358
|
+
call with `SESSION_USAGE_LIMIT_REACHED`. Its details carry the `total` and
|
|
359
|
+
`window` usage the check saw.
|
|
360
|
+
|
|
361
|
+
Each subagent session checks its own usage against its own `sessionUsage`, or
|
|
362
|
+
the root agent's when it authors none. A dynamic subagent can't select
|
|
363
|
+
`sessionUsage` at runtime and always uses the root agent's. Remote agents run
|
|
364
|
+
under their own deployment's limits.
|
|
365
|
+
|
|
366
|
+
A child's usage, including what the child's own subagents spent, also counts
|
|
367
|
+
in the parent's usage. An agent task's usage counts with each reply it
|
|
341
368
|
sends. A turn it doesn't reply to, such as one a cancel stopped, counts with
|
|
342
369
|
the next reply, or when the turn ends if no call waits for a reply. Sessions
|
|
343
370
|
that any other `serve` workflow tool opens with `ctx.agent` count the same
|
|
344
371
|
way; those of an `execute` or `task` tool count when the tool finishes. Remote
|
|
345
|
-
agents' reported usage counts the same way
|
|
346
|
-
|
|
347
|
-
spend. Token-cost budgets follow the same rules, including splitting the
|
|
348
|
-
remaining US-dollar budget and adding child cost back to the parent. Approving
|
|
349
|
-
a continuation opens a fresh parent window for later child grants without
|
|
350
|
-
erasing lifetime usage. An authored child limit applies only when it is
|
|
351
|
-
tighter than the parent's grant; an uncapped parent delegates uncapped
|
|
352
|
-
children.
|
|
372
|
+
agents' reported usage counts the same way, cost included. Approving a
|
|
373
|
+
continuation starts a new window without erasing `total`.
|
|
353
374
|
|
|
354
375
|
Some delegated usage doesn't count against the parent: a `ctx.agent` turn
|
|
355
376
|
still running when its workflow tool finishes or is cancelled; the `ctx.agent`
|
|
@@ -496,7 +517,7 @@ keeps the data. Confirm support with your World provider. See
|
|
|
496
517
|
| -------------- | ------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
497
518
|
| `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
|
|
498
519
|
| `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call, and [`promptCache`](#prompt-caching) settings. |
|
|
499
|
-
| `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. Sessions complete after 30 days by default; usage-limit defaults and inheritance are described above. Set a limit to `false` to disable it.
|
|
520
|
+
| `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. Sessions complete after 30 idle days by default; usage-limit defaults and inheritance are described above. Set a limit to `false` to disable it. |
|
|
500
521
|
| `experimental` | `AgentExperimentalDefinition` | unset | Unstable opt-ins. `workflow.world` selects the Workflow world package on the root agent; `workflow.modelCallsPerStep` batches sequential model calls into a wider replay unit; `workflow.retention` controls how long the durable runtime keeps run data. |
|
|
501
522
|
| `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
|
|
502
523
|
| `tool` | `boolean \| "deferred"` | `true` | Exposes this agent to its parent model as a tool. `"deferred"` keeps it out of the model's tool list; the model finds it with `eve__search` and calls it with `eve__tool`. On the root agent, controls the built-in `agent` tool. A subagent with `tool: false` remains callable from authored workflow tools through `ctx.agent()`. |
|
|
@@ -53,6 +53,11 @@ export default channel;
|
|
|
53
53
|
|
|
54
54
|
`adapters` is a map of adapter name to adapter instance; each entry mounts its own webhook (see below). `state` takes any Chat SDK state adapter: `createMemoryState()` is fine for local development, but use a durable adapter (Redis, Upstash, etc.) in production so thread subscriptions and inbound deduplication survive restarts. `send` accepts a plain string or an AI SDK `UserContent` array, and must be called from inside a Chat SDK handler — it dispatches the turn on the webhook that is currently running.
|
|
55
55
|
|
|
56
|
+
Pass `idempotencyKey: message.id` to `send` to prevent duplicate agent input
|
|
57
|
+
within the session's [recent-key window](./custom#retried-deliveries). Chat SDK's
|
|
58
|
+
separate duplicate check can mark a message as seen before eve accepts it, so
|
|
59
|
+
a shared state adapter alone does not guarantee delivery.
|
|
60
|
+
|
|
56
61
|
Deploy once the channel file is in place:
|
|
57
62
|
|
|
58
63
|
```bash
|
|
@@ -104,7 +109,7 @@ bot.onNewMention(async (thread, message) => {
|
|
|
104
109
|
});
|
|
105
110
|
```
|
|
106
111
|
|
|
107
|
-
`options` accepts `thread` and `adapterName`, plus the channel send options `auth`, `context`, `outputSchema`, `title`, `callback`, and `
|
|
112
|
+
`options` accepts `thread` and `adapterName`, plus the channel send options `auth`, `context`, `outputSchema`, `title`, `callback`, `turnPolicy`, and `idempotencyKey`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn. `auth` defaults to `null`.
|
|
108
113
|
|
|
109
114
|
To answer pending input requests from a handler you render yourself, call `respond(inputResponses, { thread, auth?, context? })`. Like a channel's `respond()`, it never creates a session. This example answers a custom button whose `value` carries the eve request id:
|
|
110
115
|
|
package/docs/channels/custom.mdx
CHANGED
|
@@ -104,11 +104,11 @@ part of the authored channel API.
|
|
|
104
104
|
## Channel operations and session handles
|
|
105
105
|
|
|
106
106
|
Channel operations are dynamic: every call targets whichever session currently
|
|
107
|
-
owns the address.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
message to
|
|
111
|
-
|
|
107
|
+
owns the address. `create()` and `send()` can create a session when the address is unowned.
|
|
108
|
+
Without an [idempotency key](#retried-deliveries), a new session's handle can
|
|
109
|
+
return before it claims the address. If another send wins the address, eve
|
|
110
|
+
forwards the message to that session. Call `resolveSession(address)` after
|
|
111
|
+
startup to get the winning session's handle.
|
|
112
112
|
|
|
113
113
|
```ts
|
|
114
114
|
const source = from(threadId);
|
|
@@ -206,6 +206,38 @@ Attaching does no lookup. The first operation reports whether the ID is active.
|
|
|
206
206
|
Call `resolveSession(address)` only when you explicitly need to snapshot an
|
|
207
207
|
address's current owner as a fixed handle.
|
|
208
208
|
|
|
209
|
+
## Retried deliveries
|
|
210
|
+
|
|
211
|
+
After verifying a webhook, pass its stable event ID as `idempotencyKey`. Reuse the key
|
|
212
|
+
when retrying a failed or timed-out send:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
const session = await from(conversationId).send(message, {
|
|
216
|
+
auth,
|
|
217
|
+
idempotencyKey: providerEventId,
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Channel and fixed-session `send()` and `respond()` calls accept this option,
|
|
222
|
+
as does the Chat SDK bridge. Keys must contain 1–256 characters and identify one
|
|
223
|
+
delivery. Prefix IDs with the provider or event type if they can overlap.
|
|
224
|
+
Reusing a retained key ignores the new input, even if the message changed.
|
|
225
|
+
|
|
226
|
+
Each session remembers its last 1,024 distinct keys. Retries do not extend
|
|
227
|
+
retention and can run again after eviction. Aliases share this window; replay
|
|
228
|
+
and owner handoffs preserve it. Other sessions have separate windows, including
|
|
229
|
+
those created after reset, expiration, or replacement. Replicas must share the
|
|
230
|
+
same durable Workflow World.
|
|
231
|
+
|
|
232
|
+
A known duplicate does not interrupt generation, call `deliver`, or start a
|
|
233
|
+
turn. A keyed send that creates a session waits up to 30 seconds for the winning
|
|
234
|
+
session's handle. Sends to existing sessions return after eve stores the
|
|
235
|
+
delivery, without waiting for a turn or reporting whether it was a duplicate.
|
|
236
|
+
|
|
237
|
+
Await `send()` before acknowledging a webhook when the provider allows it.
|
|
238
|
+
Acknowledging sooner can lose work. This does not make tool calls, outbound
|
|
239
|
+
posts, or work done before `send()` exactly once.
|
|
240
|
+
|
|
209
241
|
## Wrap an existing channel's routes
|
|
210
242
|
|
|
211
243
|
A channel value can be spread into a new object with replaced `routes`. eve keeps the channel's adapter, events, and build metadata (such as the Slack app manifest) on the spread copy, so `{ ...channel, routes }` compiles and runs like the original.
|
|
@@ -374,7 +406,7 @@ Before sending:
|
|
|
374
406
|
|
|
375
407
|
- Verify the provider's signature and validate the payload, including size limits. Derive `event.source` from the verified sender, not an untrusted payload field.
|
|
376
408
|
- Filter out events that should not reach the agent.
|
|
377
|
-
- Deduplicate
|
|
409
|
+
- Deduplicate retries in your application unless the destination's `receive` hook passes a [delivery key](#retried-deliveries) to `from(address).send()`.
|
|
378
410
|
|
|
379
411
|
The supplied `auth` identifies who started the session, available to tools and event handlers as `session.auth.initiator`.
|
|
380
412
|
|
package/docs/channels/eve.mdx
CHANGED
|
@@ -368,6 +368,52 @@ export default eveChannel({
|
|
|
368
368
|
- eve labels client-supplied entries `Client context:` for the model. Returned context is sent without the label.
|
|
369
369
|
- `onMessage` runs only for requests with a message. An input response keeps the context its request sent.
|
|
370
370
|
|
|
371
|
+
### Start from prior history
|
|
372
|
+
|
|
373
|
+
Pass `history` to bring in conversation eve did not produce, such as a transcript your app stored, a conversation moving from another system, or a branch of an earlier exchange. The model sees each entry as a real user or assistant turn, not as a transcript inside one message.
|
|
374
|
+
|
|
375
|
+
Create a session that starts from stored history and waits for its first message with `create()` on a channel address. No turn runs until a message arrives:
|
|
376
|
+
|
|
377
|
+
```ts title="agent/channels/app.ts"
|
|
378
|
+
import { defineChannel, POST } from "eve/channels";
|
|
379
|
+
|
|
380
|
+
export default defineChannel({
|
|
381
|
+
routes: [
|
|
382
|
+
POST("/conversations/:id/session", async (req, { from, params }) => {
|
|
383
|
+
const auth = await authenticate(req);
|
|
384
|
+
// Load only conversations this caller may read.
|
|
385
|
+
const conversation = await db.conversations.findForUser(params.id!, auth);
|
|
386
|
+
const { created, session } = await from(`conversation:${conversation.id}`).create({
|
|
387
|
+
auth,
|
|
388
|
+
history: conversation.messages.map((message) => ({
|
|
389
|
+
id: message.id,
|
|
390
|
+
role: message.role, // "user" | "assistant"
|
|
391
|
+
text: message.body,
|
|
392
|
+
})),
|
|
393
|
+
});
|
|
394
|
+
if (!created) {
|
|
395
|
+
return Response.json({ error: "Conversation already has a session." }, { status: 409 });
|
|
396
|
+
}
|
|
397
|
+
return Response.json({ sessionId: session.id });
|
|
398
|
+
}),
|
|
399
|
+
],
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
The client then resumes that session by id, for example with `useEveAgent({ initialSession: { sessionId, streamIndex: 0 }, resume: true })`. `created` is `false` when a session already owned the address, or another `create()` or `send()` claimed it first. That session comes back unchanged and your `history` was not added, so check `created` before treating the session as seeded. Use a new address for each new conversation or branch.
|
|
404
|
+
|
|
405
|
+
When the session at the address is [stranded](../concepts/execution-model-and-durability#stranded-sessions), `create()` throws `SessionStrandedError` instead of replacing it, because that session may hold the conversation you meant to import. Call `reset()` on the address, then `create()` again.
|
|
406
|
+
|
|
407
|
+
`create()` returns once the new session claims its address, so a `send()` right after it reaches that session. It throws if no session claims the address within 15 seconds.
|
|
408
|
+
|
|
409
|
+
`send()` accepts the same `history` option. The entries are added right before that message and its `context`, whether the send creates the session or continues it. The eve channel's `onMessage` can return `history` the same way. It applies to every message it is returned for, so return it only when the message should carry those turns.
|
|
410
|
+
|
|
411
|
+
Each entry has a `role` of `"user"` or `"assistant"`, non-empty `text`, and an optional `id` that is unique within the call. Invalid history throws an `InvalidSessionHistoryError`, exported from `eve/channels`, that names the entry and the rule it broke. eve doesn't cap how many entries or how much text one call carries. Your route decides how much stored conversation to load, so trim long conversations there, for example to the newest messages. Tool calls, files, and reasoning are not supported.
|
|
412
|
+
|
|
413
|
+
eve never accepts `history` from a client request body. Resolve it on the server and authorize the caller against the stored conversation.
|
|
414
|
+
|
|
415
|
+
The stream publishes added entries in `history.imported`, right before the `message.received` of the turn they join. Each event message has the same `role`, `text`, and `id` you passed. `transcriptReducer()` from `eve/client` includes them, so its `{ role, text }` messages can be passed straight back as `history` to branch a session. The default client reducer renders them ahead of that turn's message with `metadata.imported` set and your `id` in `metadata.historyId`, so you can rejoin your own annotations. Message ids stay unique even when a later call reuses an `id`. After that, the entries are ordinary history: compaction, `clear()`, and handoffs treat them like any other turn.
|
|
416
|
+
|
|
371
417
|
## Clients
|
|
372
418
|
|
|
373
419
|
The browser side of this API lives in the [Frontend](../guides/frontend/overview) docs, where `useEveAgent` drives the eve channel from React UI.
|