eve 0.27.13 → 0.28.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 +19 -0
- package/dist/src/channel/adapter.d.ts +5 -5
- package/dist/src/channel/session.d.ts +2 -2
- package/dist/src/channel/types.d.ts +10 -6
- package/dist/src/chunks/{use-eve-agent-CsSQOKnp.js → use-eve-agent-CZkX_ZTT.js} +90 -1
- package/dist/src/chunks/{use-eve-agent-CWYe-vqE.js → use-eve-agent-hdPX68_i.js} +90 -1
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/subagent-pump.d.ts +8 -2
- package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
- package/dist/src/cli/invoke/result.d.ts +15 -0
- package/dist/src/cli/invoke/result.js +1 -1
- package/dist/src/client/eve-agent-store.d.ts +7 -4
- package/dist/src/client/eve-agent-store.js +1 -1
- package/dist/src/client/index.d.ts +3 -3
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/message-action-parts.js +1 -1
- package/dist/src/client/message-reducer-types.d.ts +5 -3
- package/dist/src/client/message-response.d.ts +4 -4
- package/dist/src/client/ndjson.d.ts +3 -3
- package/dist/src/client/open-stream.d.ts +2 -2
- package/dist/src/client/output-schema.d.ts +2 -2
- package/dist/src/client/reducer.d.ts +2 -2
- package/dist/src/client/session-utils.d.ts +5 -5
- package/dist/src/client/session.d.ts +2 -2
- package/dist/src/client/types.d.ts +2 -2
- package/dist/src/compiler/compile-from-memory.d.ts +1 -0
- package/dist/src/compiler/extension-compatibility.d.ts +8 -8
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/manifest.d.ts +2 -2
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/context/dynamic-instruction-lifecycle.d.ts +2 -2
- package/dist/src/context/dynamic-model-lifecycle.d.ts +2 -2
- package/dist/src/context/dynamic-skill-lifecycle.d.ts +2 -2
- package/dist/src/context/dynamic-tool-lifecycle.d.ts +2 -2
- package/dist/src/context/hook-lifecycle.d.ts +2 -2
- package/dist/src/evals/assertions/run.d.ts +3 -3
- package/dist/src/evals/match.d.ts +4 -4
- package/dist/src/evals/runner/derive-run-facts.d.ts +2 -2
- package/dist/src/evals/session.d.ts +3 -3
- package/dist/src/evals/types.d.ts +12 -12
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/route-child-delivery.d.ts +4 -3
- package/dist/src/execution/route-child-delivery.js +1 -1
- package/dist/src/execution/session-delivery-hook.d.ts +1 -0
- package/dist/src/execution/session-delivery-hook.js +1 -1
- package/dist/src/execution/session-timeout-control.d.ts +9 -0
- package/dist/src/execution/session-timeout-control.js +1 -0
- package/dist/src/execution/session-timeout-steps.d.ts +13 -0
- package/dist/src/execution/session-timeout-steps.js +1 -0
- package/dist/src/execution/session-timeout-workflow.d.ts +6 -0
- package/dist/src/execution/session-timeout-workflow.js +1 -0
- package/dist/src/execution/session-timeout.d.ts +2 -0
- package/dist/src/execution/session-timeout.js +1 -0
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/subagent-event-proxy-step.js +1 -1
- package/dist/src/execution/subagent-hitl-proxy.d.ts +5 -1
- package/dist/src/execution/subagent-hitl-proxy.js +1 -1
- package/dist/src/execution/terminal-session-completion-step.d.ts +5 -0
- package/dist/src/execution/terminal-session-completion-step.js +1 -0
- package/dist/src/execution/terminal-session-failure-step.js +1 -1
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-entry.d.ts +1 -0
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +4 -0
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-steps.d.ts +5 -2
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/agent-otel-provider.js +1 -1
- package/dist/src/harness/ai-sdk-hook-bridge.js +1 -1
- package/dist/src/harness/input-extraction.js +1 -1
- package/dist/src/harness/input-request-class.d.ts +23 -0
- package/dist/src/harness/input-request-class.js +1 -0
- package/dist/src/harness/input-requests.d.ts +20 -9
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/instrumentation-lifecycle.d.ts +12 -1
- package/dist/src/harness/proxy-input-requests.d.ts +10 -4
- package/dist/src/harness/proxy-input-requests.js +1 -1
- package/dist/src/harness/session-limit-continuation.d.ts +0 -11
- package/dist/src/harness/session-limit-continuation.js +1 -1
- package/dist/src/harness/session-limit-enforcement.d.ts +3 -2
- package/dist/src/harness/session-limit-enforcement.js +1 -1
- package/dist/src/harness/session-token-limits.d.ts +41 -0
- package/dist/src/harness/session-token-limits.js +1 -0
- package/dist/src/harness/stale-input-responses.js +1 -1
- package/dist/src/harness/subagent-token-budget.d.ts +6 -4
- package/dist/src/harness/subagent-token-budget.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/turn-tag-state.d.ts +26 -17
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/harness/types.d.ts +4 -4
- package/dist/src/harness/workflow-lifecycle.d.ts +2 -2
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/core.js +1 -1
- package/dist/src/internal/workflow-bundle/workflow-core-shim.d.ts +1 -1
- package/dist/src/internal/workflow-bundle/workflow-core-shim.js +1 -1
- package/dist/src/protocol/event-dedupe.d.ts +25 -0
- package/dist/src/protocol/event-dedupe.js +1 -0
- package/dist/src/protocol/event-id.d.ts +16 -0
- package/dist/src/protocol/event-id.js +1 -0
- package/dist/src/protocol/message.d.ts +39 -23
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/channels/discord/discordChannel.d.ts +3 -3
- package/dist/src/public/channels/github/githubChannel.d.ts +3 -3
- package/dist/src/public/channels/linear/linearChannel.d.ts +3 -3
- package/dist/src/public/channels/slack/hitl.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +3 -3
- package/dist/src/public/channels/teams/hitl.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -3
- package/dist/src/public/channels/telegram/telegramChannel.d.ts +3 -3
- package/dist/src/public/channels/twilio/twilioChannel.d.ts +3 -3
- package/dist/src/public/definitions/channel.d.ts +4 -4
- package/dist/src/public/definitions/hook.d.ts +2 -2
- package/dist/src/react/use-eve-agent.d.ts +3 -2
- package/dist/src/runtime/framework-tools/ask-question.js +1 -1
- package/dist/src/runtime/hooks/registry.d.ts +2 -2
- package/dist/src/runtime/input/types.d.ts +19 -4
- package/dist/src/runtime/input/types.js +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/runtime/types.d.ts +2 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +2 -2
- package/dist/src/shared/agent-definition.d.ts +12 -0
- package/dist/src/shared/dynamic-tool-definition.d.ts +2 -2
- package/dist/src/shared/ulid.d.ts +39 -0
- package/dist/src/shared/ulid.js +1 -0
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.d.ts +4 -4
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.d.ts +4 -4
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/agent-config.md +28 -16
- package/docs/concepts/execution-model-and-durability.mdx +1 -1
- package/docs/concepts/sessions-runs-and-streaming.md +61 -0
- package/docs/guides/client/streaming.mdx +9 -3
- package/docs/guides/frontend/overview.mdx +4 -2
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +1 -1
- package/docs/guides/frontend/use-eve-agent-vue.mdx +10 -10
- package/docs/guides/hooks.md +40 -2
- package/docs/guides/instrumentation.md +4 -0
- package/docs/tools/human-in-the-loop.md +5 -0
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { SessionAuthContext } from "#channel/types.js";
|
|
2
2
|
import type { SessionContext } from "#public/definitions/callback-context.js";
|
|
3
3
|
import type { ChannelSessionOps } from "#public/definitions/channel.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
|
|
5
5
|
import { type TwilioApiOptions, type TwilioApiResponse, type TwilioCredentials } from "#public/channels/twilio/api.js";
|
|
6
6
|
import { type TwilioTextMessage, type TwilioVoiceCall, type TwilioVoiceTranscription } from "#public/channels/twilio/inbound.js";
|
|
7
7
|
import { type TwilioAuthToken, type TwilioWebhookUrl } from "#public/channels/twilio/verify.js";
|
|
8
8
|
import { type Channel } from "#public/definitions/channel.js";
|
|
9
|
-
type EventData<T extends
|
|
9
|
+
type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
|
|
10
10
|
type: T;
|
|
11
11
|
}> extends {
|
|
12
12
|
data: infer D;
|
|
@@ -82,7 +82,7 @@ export interface TwilioVoiceResult {
|
|
|
82
82
|
}
|
|
83
83
|
/** Sync or async {@link TwilioVoiceResult}. */
|
|
84
84
|
export type TwilioVoiceResultOrPromise = TwilioVoiceResult | null | undefined | Promise<TwilioVoiceResult | null | undefined>;
|
|
85
|
-
type TwilioEventHandler<T extends
|
|
85
|
+
type TwilioEventHandler<T extends UnstampedMessageStreamEvent["type"]> = (data: EventData<T>, channel: TwilioEventContext, ctx: SessionContext) => void | Promise<void>;
|
|
86
86
|
type TwilioSessionFailedHandler = (data: EventData<"session.failed">, channel: TwilioEventContext) => void | Promise<void>;
|
|
87
87
|
/** Event handlers supported by `twilioChannel({ events })`. */
|
|
88
88
|
export interface TwilioChannelEvents {
|
|
@@ -4,7 +4,7 @@ import type { TypedReceiveTarget } from "#channel/receive-target.js";
|
|
|
4
4
|
import type { RouteDefinition, SendFn } from "#channel/routes.js";
|
|
5
5
|
import type { Session } from "#channel/session.js";
|
|
6
6
|
import type { CancelTurnInput, CancelTurnResult, DeliverInput, GetEventStreamOptions, RunHandle, RunInput } from "#channel/types.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type { UnstampedMessageStreamEvent, MessageStreamEvent } from "#protocol/message.js";
|
|
8
8
|
import type { SessionContext } from "#public/definitions/callback-context.js";
|
|
9
9
|
import type { GenericChannelDefinition, GenericReceiveInput } from "#shared/channel-definition.js";
|
|
10
10
|
declare const CHANNEL_METADATA_TYPE: unique symbol;
|
|
@@ -120,7 +120,7 @@ export interface Agent {
|
|
|
120
120
|
* at the latest event). The framework HTTP session-stream route forwards
|
|
121
121
|
* the `startIndex` query parameter unchanged.
|
|
122
122
|
*/
|
|
123
|
-
getEventStream(sessionId: string, options?: GetEventStreamOptions): Promise<ReadableStream<
|
|
123
|
+
getEventStream(sessionId: string, options?: GetEventStreamOptions): Promise<ReadableStream<MessageStreamEvent>>;
|
|
124
124
|
}
|
|
125
125
|
/**
|
|
126
126
|
* Marker discriminator written into every {@link DisabledRouteSentinel}.
|
|
@@ -146,7 +146,7 @@ export declare function disableRoute(): DisabledRouteSentinel;
|
|
|
146
146
|
* produced by {@link disableRoute}.
|
|
147
147
|
*/
|
|
148
148
|
export declare function isDisabledRouteSentinel(value: unknown): value is DisabledRouteSentinel;
|
|
149
|
-
type EventData<T extends
|
|
149
|
+
type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
|
|
150
150
|
type: T;
|
|
151
151
|
}> extends {
|
|
152
152
|
data: infer D;
|
|
@@ -163,7 +163,7 @@ export interface ChannelSessionOps {
|
|
|
163
163
|
* {@link ChannelSessionOps}.
|
|
164
164
|
*/
|
|
165
165
|
export type ChannelContext<TCtx> = TCtx & ChannelSessionOps;
|
|
166
|
-
type ChannelEventHandler<T extends
|
|
166
|
+
type ChannelEventHandler<T extends UnstampedMessageStreamEvent["type"], TCtx> = (data: EventData<T>, channel: ChannelContext<TCtx>, ctx: SessionContext) => void | Promise<void>;
|
|
167
167
|
type ChannelSessionFailedHandler<TCtx> = (data: EventData<"session.failed">, channel: ChannelContext<TCtx>) => void | Promise<void>;
|
|
168
168
|
/**
|
|
169
169
|
* Optional handlers keyed by session lifecycle event name. Each handler receives
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MessageStreamEvent } from "../../protocol/message.js";
|
|
2
2
|
import type { SessionContext } from "./callback-context.js";
|
|
3
3
|
import type { ExactDefinition } from "./exact.js";
|
|
4
|
-
type ProtocolEvent<TType extends
|
|
4
|
+
type ProtocolEvent<TType extends MessageStreamEvent["type"]> = Extract<MessageStreamEvent, {
|
|
5
5
|
type: TType;
|
|
6
6
|
}>;
|
|
7
7
|
/**
|
|
@@ -2,7 +2,7 @@ import { type EveAgentStoreCallbacks, type EveAgentStoreSnapshot, type EveAgentS
|
|
|
2
2
|
import type { EveAgentReducer } from "#client/reducer.js";
|
|
3
3
|
import type { ClientSession } from "#client/session.js";
|
|
4
4
|
import { type EveMessageData } from "#client/message-reducer.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
6
6
|
import type { ClientAuth, HeadersValue, SendTurnPayload, SessionState } from "#client/types.js";
|
|
7
7
|
export type { PrepareSend };
|
|
8
8
|
/**
|
|
@@ -61,7 +61,8 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
|
|
|
61
61
|
* @default ""
|
|
62
62
|
*/
|
|
63
63
|
readonly host?: string;
|
|
64
|
-
|
|
64
|
+
/** Ordered prefix of the session stream used to rehydrate projected state. */
|
|
65
|
+
readonly initialEvents?: readonly MessageStreamEvent[];
|
|
65
66
|
readonly initialSession?: SessionState;
|
|
66
67
|
/**
|
|
67
68
|
* Project submitted user messages before eve confirms them with a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{inputRequestSchema}from"#runtime/input/types.js";const ASK_QUESTION_TOOL_NAME=`ask_question`,ASK_QUESTION_INPUT_SCHEMA=inputRequestSchema.omit({action:!0,display:!0,requestId:!0}),ASK_QUESTION_OUTPUT_SCHEMA=z.object({optionId:z.string().optional(),status:z.enum([`answered`,`ignored`]),text:z.string().optional()}).strict(),ASK_QUESTION_TOOL_DEFINITION={description:`Ask the user a question and wait for their response before continuing. Use this when you need clarification or a choice from the user.`,inputSchema:ASK_QUESTION_INPUT_SCHEMA,logicalPath:`eve:framework/ask-question`,name:ASK_QUESTION_TOOL_NAME,outputSchema:ASK_QUESTION_OUTPUT_SCHEMA,sourceId:`eve:ask-question-tool`,sourceKind:`module`};export{ASK_QUESTION_INPUT_SCHEMA,ASK_QUESTION_OUTPUT_SCHEMA,ASK_QUESTION_TOOL_DEFINITION,ASK_QUESTION_TOOL_NAME};
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{inputRequestSchema}from"#runtime/input/types.js";const ASK_QUESTION_TOOL_NAME=`ask_question`,ASK_QUESTION_INPUT_SCHEMA=inputRequestSchema.omit({action:!0,display:!0,kind:!0,requestId:!0}),ASK_QUESTION_OUTPUT_SCHEMA=z.object({optionId:z.string().optional(),status:z.enum([`answered`,`ignored`]),text:z.string().optional()}).strict(),ASK_QUESTION_TOOL_DEFINITION={description:`Ask the user a question and wait for their response before continuing. Use this when you need clarification or a choice from the user.`,inputSchema:ASK_QUESTION_INPUT_SCHEMA,logicalPath:`eve:framework/ask-question`,name:ASK_QUESTION_TOOL_NAME,outputSchema:ASK_QUESTION_OUTPUT_SCHEMA,sourceId:`eve:ask-question-tool`,sourceKind:`module`};export{ASK_QUESTION_INPUT_SCHEMA,ASK_QUESTION_OUTPUT_SCHEMA,ASK_QUESTION_TOOL_DEFINITION,ASK_QUESTION_TOOL_NAME};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
2
2
|
import type { StreamEventHook } from "../../public/definitions/hook.js";
|
|
3
3
|
import type { ResolvedHookDefinition } from "../types.js";
|
|
4
4
|
/**
|
|
@@ -9,7 +9,7 @@ import type { ResolvedHookDefinition } from "../types.js";
|
|
|
9
9
|
*/
|
|
10
10
|
interface RuntimeStreamEventHookEntry {
|
|
11
11
|
readonly slug: string;
|
|
12
|
-
readonly handler: StreamEventHook<
|
|
12
|
+
readonly handler: StreamEventHook<MessageStreamEvent>;
|
|
13
13
|
readonly eventType: string;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
@@ -20,11 +20,21 @@ export declare const inputOptionSchema: z.ZodObject<{
|
|
|
20
20
|
}>>;
|
|
21
21
|
}, z.core.$strict>;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
* user input before continuing.
|
|
23
|
+
* Framework-owned source of an input request.
|
|
25
24
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* Consumers use this discriminator for behavior. The action tool name and
|
|
26
|
+
* request id are presentation and identity fields, not request semantics.
|
|
27
|
+
*/
|
|
28
|
+
export type InputRequestKind = z.infer<typeof inputRequestKindSchema>;
|
|
29
|
+
/** Zod schema for the framework-owned source of an input request. */
|
|
30
|
+
export declare const inputRequestKindSchema: z.ZodEnum<{
|
|
31
|
+
question: "question";
|
|
32
|
+
"session-limit": "session-limit";
|
|
33
|
+
"tool-approval": "tool-approval";
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Unified input request surfaced to the client when the agent needs user
|
|
37
|
+
* input before continuing.
|
|
28
38
|
*/
|
|
29
39
|
export type InputRequest = z.infer<typeof inputRequestSchema>;
|
|
30
40
|
/**
|
|
@@ -43,6 +53,11 @@ export declare const inputRequestSchema: z.ZodObject<{
|
|
|
43
53
|
select: "select";
|
|
44
54
|
text: "text";
|
|
45
55
|
}>>;
|
|
56
|
+
kind: z.ZodEnum<{
|
|
57
|
+
question: "question";
|
|
58
|
+
"session-limit": "session-limit";
|
|
59
|
+
"tool-approval": "tool-approval";
|
|
60
|
+
}>;
|
|
46
61
|
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
47
62
|
description: z.ZodOptional<z.ZodString>;
|
|
48
63
|
id: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{runtimeToolCallActionRequestSchema}from"#runtime/actions/types.js";const inputOptionSchema=z.object({description:z.string().describe(`Optional additional context for this option.`).optional(),id:z.string().describe(`Stable identifier for the option.`),label:z.string().describe(`User-facing label for the option.`),style:z.enum([`primary`,`danger`,`default`]).describe(`Visual treatment hint for the option.`).optional()}).strict(),inputRequestSchema=z.object({action:runtimeToolCallActionRequestSchema,allowFreeform:z.boolean().describe(`Whether the user may answer with freeform text instead of selecting one of the provided options.`).optional(),display:z.enum([`confirmation`,`select`,`text`]).describe(`Rendering hint: the channel uses this to pick a UX treatment.`).optional(),options:z.array(inputOptionSchema).describe(`Selectable answer options to present to the user.`).optional(),prompt:z.string().describe(`The prompt to present to the user.`),requestId:z.string().describe(`Stable identifier for this request.`)}).strict(),inputResponseSchema=z.object({optionId:z.string().optional(),requestId:z.string(),text:z.string().optional()}).strict();function isInputRequest(e){return inputRequestSchema.safeParse(e).success}function isInputResponse(e){return inputResponseSchema.safeParse(e).success}export{inputOptionSchema,inputRequestSchema,inputResponseSchema,isInputRequest,isInputResponse};
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{runtimeToolCallActionRequestSchema}from"#runtime/actions/types.js";const inputOptionSchema=z.object({description:z.string().describe(`Optional additional context for this option.`).optional(),id:z.string().describe(`Stable identifier for the option.`),label:z.string().describe(`User-facing label for the option.`),style:z.enum([`primary`,`danger`,`default`]).describe(`Visual treatment hint for the option.`).optional()}).strict(),inputRequestKindSchema=z.enum([`question`,`session-limit`,`tool-approval`]),inputRequestSchema=z.object({action:runtimeToolCallActionRequestSchema,allowFreeform:z.boolean().describe(`Whether the user may answer with freeform text instead of selecting one of the provided options.`).optional(),display:z.enum([`confirmation`,`select`,`text`]).describe(`Rendering hint: the channel uses this to pick a UX treatment.`).optional(),kind:inputRequestKindSchema.describe(`Framework-owned request source used to resolve, route, and render the response.`),options:z.array(inputOptionSchema).describe(`Selectable answer options to present to the user.`).optional(),prompt:z.string().describe(`The prompt to present to the user.`),requestId:z.string().describe(`Stable identifier for this request.`)}).strict(),inputResponseSchema=z.object({optionId:z.string().optional(),requestId:z.string(),text:z.string().optional()}).strict();function isInputRequest(e){return inputRequestSchema.safeParse(e).success}function isInputResponse(e){return inputResponseSchema.safeParse(e).success}export{inputOptionSchema,inputRequestKindSchema,inputRequestSchema,inputResponseSchema,isInputRequest,isInputResponse};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicInstructionsDefinition}from"#runtime/resolve-dynamic-instructions.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all((e.manifest.dynamicInstructions??[]).map(t=>resolveDynamicInstructionsDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),u=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),d=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),f=createResolvedInstructionsDefinition(e.manifest.instructions),p=e.manifest.workspaceResourceRoot,m={channels:r,config:createResolvedAgentConfig(e.manifest),connections:u,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],workflowTool:e.manifest.workflowTool===void 0?void 0:{maxSubagents:e.manifest.workflowTool.maxSubagents},dynamicInstructionsResolvers:o,dynamicSkillResolvers:s,dynamicToolResolvers:c,hooks:l,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:d,workspaceResourceRoot:p,skills:t,tools:a,workspaceSpec:{rootEntries:[...p.rootEntries]}};return f===void 0?m:{...m,instructions:f}}function createResolvedInstructionsDefinition(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.dynamicModel!==void 0&&(n.dynamicModel={...createResolvedModuleSourceRef(e.config.dynamicModel),eventNames:[...e.config.dynamicModel.eventNames]}),e.config.experimental!==void 0&&(n.experimental={workflow:e.config.experimental.workflow===void 0?void 0:{world:e.config.experimental.workflow.world}}),e.config.outputSchema!==void 0&&(n.outputSchema=e.config.outputSchema),e.config.reasoning!==void 0&&(n.reasoning=e.config.reasoning),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),e.config.limits!==void 0&&(n.limits={maxInputTokensPerSession:e.config.limits.maxInputTokensPerSession,maxOutputTokensPerSession:e.config.limits.maxOutputTokensPerSession}),n}export{ResolveAgentError,resolveAgent};
|
|
1
|
+
import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicInstructionsDefinition}from"#runtime/resolve-dynamic-instructions.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all((e.manifest.dynamicInstructions??[]).map(t=>resolveDynamicInstructionsDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),u=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),d=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),f=createResolvedInstructionsDefinition(e.manifest.instructions),p=e.manifest.workspaceResourceRoot,m={channels:r,config:createResolvedAgentConfig(e.manifest),connections:u,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],workflowTool:e.manifest.workflowTool===void 0?void 0:{maxSubagents:e.manifest.workflowTool.maxSubagents},dynamicInstructionsResolvers:o,dynamicSkillResolvers:s,dynamicToolResolvers:c,hooks:l,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:d,workspaceResourceRoot:p,skills:t,tools:a,workspaceSpec:{rootEntries:[...p.rootEntries]}};return f===void 0?m:{...m,instructions:f}}function createResolvedInstructionsDefinition(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.dynamicModel!==void 0&&(n.dynamicModel={...createResolvedModuleSourceRef(e.config.dynamicModel),eventNames:[...e.config.dynamicModel.eventNames]}),e.config.experimental!==void 0&&(n.experimental={workflow:e.config.experimental.workflow===void 0?void 0:{world:e.config.experimental.workflow.world}}),e.config.outputSchema!==void 0&&(n.outputSchema=e.config.outputSchema),e.config.reasoning!==void 0&&(n.reasoning=e.config.reasoning),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),e.config.limits!==void 0&&(n.limits={maxInputTokensPerSession:e.config.limits.maxInputTokensPerSession,maxOutputTokensPerSession:e.config.limits.maxOutputTokensPerSession,sessionTimeoutMs:e.config.limits.sessionTimeoutMs}),n}export{ResolveAgentError,resolveAgent};
|
|
@@ -3,7 +3,7 @@ import type { CompiledChannel } from "#channel/compiled-channel.js";
|
|
|
3
3
|
import type { NormalizedChannelCorsOptions } from "#channel/cors.js";
|
|
4
4
|
import type { HeadersValue } from "#client/types.js";
|
|
5
5
|
import type { DiscoverDiagnosticsSummary } from "#discover/diagnostics.js";
|
|
6
|
-
import type {
|
|
6
|
+
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
7
7
|
import type { ChannelRouteMethod, RouteContext } from "#public/definitions/channel.js";
|
|
8
8
|
import type { RouteHandler, WebSocketRouteHandler } from "#channel/routes.js";
|
|
9
9
|
import type { OutboundAuthFn } from "#public/agents/auth.js";
|
|
@@ -178,7 +178,7 @@ export interface ResolvedHookDefinition extends ResolvedModuleSourceRef {
|
|
|
178
178
|
* wildcard if declared. Unknown keys are accepted at resolve time
|
|
179
179
|
* and ignored at dispatch time.
|
|
180
180
|
*/
|
|
181
|
-
readonly events: Readonly<Record<string, StreamEventHook<
|
|
181
|
+
readonly events: Readonly<Record<string, StreamEventHook<MessageStreamEvent>>>;
|
|
182
182
|
}
|
|
183
183
|
/**
|
|
184
184
|
* Runtime-owned authored channel definition resolved from the compiled
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.28.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
|
|
2
2
|
|
|
3
3
|
export default defineAgent({
|
|
4
4
|
model: "__EVE_INIT_MODEL__",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const WEB_APP_TEMPLATE_FILES: {
|
|
2
2
|
readonly "agent/channels/eve.ts": 'import { eveChannel } from "eve/channels/eve";\nimport { localDev, placeholderAuth, vercelOidc } from "eve/channels/auth";\n\nexport default eveChannel({\n auth: [\n // Lets the eve TUI and your Vercel deployments reach the deployed agent.\n vercelOidc(),\n // Open on localhost for `eve dev` and the REPL; ignored in production.\n localDev(),\n // This placeholder will not allow browser requests in production.\n // Replace it with your app\'s auth provider, like Auth.js or Clerk,\n // or use none() for a public demo.\n placeholderAuth(),\n ],\n});\n';
|
|
3
|
-
readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport type { UserContent } from "ai";\nimport { Client, type
|
|
3
|
+
readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport type { UserContent } from "ai";\nimport { Client, type MessageStreamEvent } from "eve/client";\nimport { useEveAgent } from "eve/react";\nimport { AlertCircleIcon } from "lucide-react";\nimport { useCallback, useRef, useState } from "react";\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from "@/components/ai-elements/conversation";\nimport {\n PromptInput,\n type PromptInputMessage,\n PromptInputSubmit,\n PromptInputTextarea,\n} from "@/components/ai-elements/prompt-input";\nimport { cn } from "@/lib/utils";\nimport { AgentMessage } from "./agent-message";\n\nconst AGENT_NAME = "__EVE_INIT_APP_NAME__";\n\ntype AgentStatus = ReturnType<typeof useEveAgent>["status"];\ntype CancellationState = "idle" | "requested" | "cancelling";\n\ntype Cancellation = {\n requested: boolean;\n sentTurnId?: string;\n turnId?: string;\n};\n\nexport function AgentChat() {\n const [session] = useState(() =>\n new Client({ host: "", preserveCompletedSessions: true }).session(),\n );\n const cancellationRef = useRef<Cancellation>({ requested: false });\n const [cancellationError, setCancellationError] = useState<string>();\n const [cancellationState, setCancellationState] = useState<CancellationState>("idle");\n\n const cancelTurn = useCallback(\n (turnId: string) => {\n const cancellation = cancellationRef.current;\n if (!cancellation.requested || cancellation.sentTurnId === turnId) {\n return;\n }\n\n cancellation.sentTurnId = turnId;\n setCancellationState("cancelling");\n\n void session.cancel({ turnId }).catch((error: unknown) => {\n if (cancellationRef.current !== cancellation) {\n return;\n }\n\n cancellation.requested = false;\n cancellation.sentTurnId = undefined;\n setCancellationError(toErrorMessage(error));\n setCancellationState("idle");\n });\n },\n [session],\n );\n\n const handleEvent = useCallback(\n (event: MessageStreamEvent) => {\n if (event.type !== "turn.started") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.turnId = event.data.turnId;\n cancelTurn(event.data.turnId);\n },\n [cancelTurn],\n );\n\n const agent = useEveAgent({ onEvent: handleEvent, session });\n const isBusy = agent.status === "submitted" || agent.status === "streaming";\n const isEmpty = agent.data.messages.length === 0;\n const errorMessage = cancellationError ?? agent.error?.message;\n const submitStatus = isBusy && cancellationState !== "idle" ? "submitted" : agent.status;\n\n const prepareTurn = () => {\n cancellationRef.current = { requested: false };\n setCancellationError(undefined);\n setCancellationState("idle");\n };\n\n const requestCancellation = () => {\n if (!isBusy || cancellationState !== "idle") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.requested = true;\n setCancellationError(undefined);\n setCancellationState("requested");\n\n if (cancellation.turnId !== undefined) {\n cancelTurn(cancellation.turnId);\n }\n };\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const text = message.text.trim();\n if ((text.length === 0 && message.files.length === 0) || isBusy) return;\n\n prepareTurn();\n\n if (message.files.length === 0) {\n await agent.send({ message: text });\n return;\n }\n\n const parts: UserContent = [];\n if (text.length > 0) {\n parts.push({ text, type: "text" });\n }\n for (const file of message.files) {\n parts.push({\n data: file.url,\n filename: file.filename,\n mediaType: file.mediaType,\n type: "file",\n });\n }\n\n await agent.send({ message: parts });\n };\n\n const composer = (\n <PromptInput onSubmit={handleSubmit}>\n <PromptInputTextarea placeholder="Send a message…" />\n <PromptInputSubmit onStop={requestCancellation} status={submitStatus} />\n </PromptInput>\n );\n\n return (\n <main className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">\n {isEmpty ? null : (\n <header className="flex h-14 shrink-0 items-center justify-center gap-3 pl-4 pr-2">\n <span className="flex min-w-0 items-center gap-2">\n <span className="truncate text-muted-foreground text-sm">{AGENT_NAME}</span>\n <StatusDot status={agent.status} />\n </span>\n </header>\n )}\n\n {errorMessage ? (\n <div className="mx-auto w-full max-w-3xl shrink-0 px-4 pt-2 sm:px-6">\n <div className="flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5 text-sm">\n <AlertCircleIcon className="mt-0.5 size-4 shrink-0 text-destructive" />\n <div>\n <p className="font-medium">Request failed</p>\n <p className="mt-0.5 text-muted-foreground">{errorMessage}</p>\n </div>\n </div>\n </div>\n ) : null}\n\n {isEmpty ? null : (\n <Conversation className="min-h-0 flex-1">\n <ConversationContent className="mx-auto w-full max-w-3xl gap-6 px-4 py-6 sm:px-6">\n {agent.data.messages.map((message, index) => (\n <AgentMessage\n canRespond={!isBusy}\n isStreaming={\n agent.status === "streaming" && index === agent.data.messages.length - 1\n }\n key={message.id}\n message={message}\n onInputResponses={(inputResponses) => {\n prepareTurn();\n return agent.send({ inputResponses });\n }}\n />\n ))}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n )}\n\n <div\n className={cn(\n "mx-auto w-full px-4 sm:px-6",\n isEmpty\n ? "flex max-w-xl flex-1 flex-col items-center justify-center gap-8 pb-[10vh]"\n : "max-w-3xl shrink-0 pb-6",\n )}\n >\n {isEmpty ? (\n <div className="flex flex-col items-center gap-3 text-center">\n <h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1>\n </div>\n ) : null}\n <div className="w-full">{composer}</div>\n </div>\n </main>\n );\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : "Unable to cancel the response.";\n}\n\nfunction StatusDot({ status }: { readonly status: AgentStatus }) {\n const isLive = status === "submitted" || status === "streaming";\n const tone =\n status === "error"\n ? "bg-destructive"\n : isLive\n ? "bg-emerald-500"\n : status === "ready"\n ? "bg-muted-foreground"\n : "bg-muted-foreground/50";\n\n return (\n <span className="relative flex size-1">\n {isLive ? (\n <span\n className={cn(\n "absolute inline-flex size-full animate-ping rounded-full opacity-75",\n tone,\n )}\n />\n ) : null}\n <span className={cn("relative inline-flex size-1 rounded-full transition-colors", tone)} />\n </span>\n );\n}\n';
|
|
4
4
|
readonly "app/_components/agent-message.tsx": '"use client";\n\nimport type {\n EveAuthorizationPart,\n EveDynamicToolPart,\n EveMessage,\n EveMessagePart,\n} from "eve/react";\nimport {\n CheckCircleIcon,\n ExternalLinkIcon,\n FileIcon,\n ImageIcon,\n KeyRoundIcon,\n XCircleIcon,\n} from "lucide-react";\nimport { Message, MessageContent, MessageResponse } from "@/components/ai-elements/message";\nimport { Reasoning, ReasoningContent, ReasoningTrigger } from "@/components/ai-elements/reasoning";\nimport {\n Tool,\n ToolContent,\n ToolHeader,\n ToolInput,\n ToolOutput,\n} from "@/components/ai-elements/tool";\nimport { Button } from "@/components/ui/button";\nimport { cn } from "@/lib/utils";\n\nexport type AgentInputResponse = {\n readonly optionId?: string;\n readonly requestId: string;\n readonly text?: string;\n};\n\ntype EveFilePart = Extract<EveMessagePart, { type: "file" }>;\n\nexport function AgentMessage({\n canRespond,\n isStreaming,\n message,\n onInputResponses,\n}: {\n readonly canRespond: boolean;\n readonly isStreaming: boolean;\n readonly message: EveMessage;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n}) {\n const lastTextIndex = message.parts.reduce(\n (last, part, index) => (part.type === "text" ? index : last),\n -1,\n );\n\n return (\n <Message\n data-optimistic={message.metadata?.optimistic ? "true" : undefined}\n from={message.role}\n >\n <MessageContent>\n {message.parts.map((part, index) => (\n <AgentMessagePart\n canRespond={canRespond}\n key={partKey(part, index)}\n onInputResponses={onInputResponses}\n part={part}\n showCaret={isStreaming && message.role === "assistant" && index === lastTextIndex}\n />\n ))}\n </MessageContent>\n </Message>\n );\n}\n\nfunction AgentMessagePart({\n canRespond,\n onInputResponses,\n part,\n showCaret,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveMessagePart;\n readonly showCaret: boolean;\n}) {\n switch (part.type) {\n case "step-start":\n return null;\n case "text":\n return (\n <MessageResponse caret="block" isAnimating={showCaret}>\n {part.text}\n </MessageResponse>\n );\n case "reasoning":\n return (\n <Reasoning defaultOpen isStreaming={part.state === "streaming"}>\n <ReasoningTrigger />\n <ReasoningContent>{part.text}</ReasoningContent>\n </Reasoning>\n );\n case "file":\n return <AttachmentPart part={part} />;\n case "authorization":\n return <AuthorizationPrompt part={part} />;\n case "dynamic-tool":\n return (\n <Tool\n defaultOpen={part.state === "approval-requested" || part.state === "approval-responded"}\n >\n <ToolHeader\n state={part.state}\n title={part.toolName}\n toolName={part.toolName}\n type="dynamic-tool"\n />\n <ToolContent>\n <ToolInput input={part.input} />\n <InputRequestActions\n canRespond={canRespond}\n part={part}\n onInputResponses={onInputResponses}\n />\n <ToolOutput errorText={part.errorText} output={part.output} />\n </ToolContent>\n </Tool>\n );\n }\n}\n\nfunction AttachmentPart({ part }: { readonly part: EveFilePart }) {\n const label = part.filename ?? "Attachment";\n const detail = [part.mediaType, formatBytes(part.size)].filter(Boolean).join(" - ");\n const isImage = part.mediaType.startsWith("image/") && part.url !== undefined;\n const Icon = isImage ? ImageIcon : FileIcon;\n const body = (\n <span className="flex max-w-sm items-center gap-3 rounded-md border bg-background/60 p-2 text-sm">\n {isImage ? (\n <img alt={label} className="size-12 shrink-0 rounded-sm object-cover" src={part.url} />\n ) : (\n <span className="flex size-10 shrink-0 items-center justify-center rounded-sm bg-muted text-muted-foreground">\n <Icon className="size-4" />\n </span>\n )}\n <span className="min-w-0 flex-1">\n <span className="block truncate font-medium">{label}</span>\n {detail ? <span className="block truncate text-muted-foreground">{detail}</span> : null}\n </span>\n {part.url ? <ExternalLinkIcon className="size-4 shrink-0 text-muted-foreground" /> : null}\n </span>\n );\n\n return part.url ? (\n <a href={part.url} rel="noreferrer" target="_blank">\n {body}\n </a>\n ) : (\n body\n );\n}\n\nfunction AuthorizationPrompt({ part }: { readonly part: EveAuthorizationPart }) {\n const isAuthorized = part.state === "completed" && part.outcome === "authorized";\n const isCompleted = part.state === "completed";\n const Icon = isAuthorized ? CheckCircleIcon : isCompleted ? XCircleIcon : KeyRoundIcon;\n const instructions = part.authorization?.instructions;\n const shouldShowInstructions = instructions !== undefined && instructions !== part.description;\n\n return (\n <div\n className={cn(\n "space-y-3 rounded-md border p-3",\n isAuthorized\n ? "border-emerald-500/30 bg-emerald-500/5"\n : isCompleted\n ? "border-destructive/30 bg-destructive/5"\n : "border-blue-500/30 bg-blue-500/5",\n )}\n >\n <div className="flex items-start gap-3">\n <span\n className={cn(\n "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full",\n isAuthorized\n ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"\n : isCompleted\n ? "bg-destructive/10 text-destructive"\n : "bg-blue-500/10 text-blue-700 dark:text-blue-300",\n )}\n >\n <Icon className="size-4" />\n </span>\n <div className="min-w-0 flex-1 space-y-2">\n <p className="font-medium text-sm">{authorizationTitle(part)}</p>\n <p className="text-muted-foreground text-sm">{authorizationDescription(part)}</p>\n {shouldShowInstructions ? (\n <p className="text-muted-foreground text-sm">{instructions}</p>\n ) : null}\n {part.state === "required" && part.authorization?.userCode ? (\n <div className="flex flex-wrap items-center gap-2 text-sm">\n <span className="text-muted-foreground">Code</span>\n <code className="rounded-md bg-background px-2 py-1 font-mono">\n {part.authorization.userCode}\n </code>\n </div>\n ) : null}\n {part.state === "required" && part.authorization?.url ? (\n <Button asChild size="sm">\n <a href={part.authorization.url} rel="noreferrer" target="_blank">\n <ExternalLinkIcon className="size-4" />\n Sign in with {part.displayName}\n </a>\n </Button>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n\nfunction authorizationTitle(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return `Connect ${part.displayName}`;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected`;\n }\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}`;\n}\n\nfunction authorizationDescription(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return part.description;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected.`;\n }\n const tail = part.reason !== undefined ? ` (${part.reason})` : "";\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}${tail}.`;\n}\n\nfunction formatAuthorizationOutcome(outcome: NonNullable<EveAuthorizationPart["outcome"]>): string {\n switch (outcome) {\n case "authorized":\n return "authorized";\n case "declined":\n return "declined";\n case "failed":\n return "failed";\n case "timed-out":\n return "timed out";\n }\n}\n\nfunction formatBytes(size: number | undefined): string | undefined {\n if (size === undefined) {\n return undefined;\n }\n if (size < 1024) {\n return `${size} B`;\n }\n if (size < 1024 * 1024) {\n return `${(size / 1024).toFixed(1)} KB`;\n }\n return `${(size / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction InputRequestActions({\n canRespond,\n onInputResponses,\n part,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveDynamicToolPart;\n}) {\n const inputRequest = part.toolMetadata?.eve?.inputRequest;\n if (!inputRequest) {\n return null;\n }\n\n const inputResponse = part.toolMetadata?.eve?.inputResponse;\n const selectedOption = inputRequest.options?.find(\n (option) => option.id === inputResponse?.optionId,\n );\n\n return (\n <div className="space-y-3 rounded-md border border-yellow-500/30 bg-yellow-500/5 p-3">\n <p className="text-muted-foreground text-sm">{inputRequest.prompt}</p>\n {inputResponse ? (\n <p className="font-medium text-sm">\n Responded: {selectedOption?.label ?? inputResponse.text ?? inputResponse.optionId}\n </p>\n ) : (\n <div className="flex flex-wrap gap-2">\n {inputRequest.options?.map((option) => (\n <Button\n disabled={!canRespond}\n key={option.id}\n onClick={() => {\n void onInputResponses([\n {\n optionId: option.id,\n requestId: inputRequest.requestId,\n },\n ]);\n }}\n size="sm"\n type="button"\n variant={option.style === "danger" ? "destructive" : "default"}\n >\n {option.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction partKey(part: EveMessagePart, index: number): string {\n switch (part.type) {\n case "authorization":\n return `authorization:${part.turnId}:${part.stepIndex}:${part.name}`;\n case "dynamic-tool":\n return part.toolCallId;\n default:\n return `${part.type}:${index}`;\n }\n}\n';
|
|
5
5
|
readonly "app/globals.css": '@import "tailwindcss";\n@source "../node_modules/streamdown/dist/*.js";\n\n@theme inline {\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n --font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;\n --font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;\n}\n\n:root {\n color-scheme: light;\n /* Soft neutral page with white elevated surfaces so cards/composer pop. */\n --background: oklch(0.971 0 0);\n --foreground: oklch(0.16 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.16 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.16 0 0);\n --primary: oklch(0.19 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --secondary: oklch(0.94 0 0);\n --secondary-foreground: oklch(0.19 0 0);\n --muted: oklch(0.94 0 0);\n --muted-foreground: oklch(0.6 0 0);\n --accent: oklch(0.94 0 0);\n --accent-foreground: oklch(0.19 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --border: oklch(0.916 0 0);\n --input: oklch(0.916 0 0);\n --ring: oklch(0.708 0 0);\n --radius: 0.625rem;\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n color-scheme: dark;\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.205 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.269 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --border: oklch(1 0 0 / 10%);\n --input: oklch(1 0 0 / 15%);\n --ring: oklch(0.556 0 0);\n }\n}\n\n* {\n border-color: var(--border);\n}\n\nhtml {\n height: 100%;\n}\n\nbody {\n min-height: 100%;\n margin: 0;\n background: var(--background);\n font-family: var(--font-sans);\n}\n\nbutton,\ninput,\ntextarea {\n font: inherit;\n}\n';
|
|
6
6
|
readonly "app/layout.tsx": 'import type { Metadata } from "next";\nimport { Geist, Geist_Mono } from "next/font/google";\nimport type { ReactNode } from "react";\nimport { TooltipProvider } from "@/components/ui/tooltip";\nimport { cn } from "@/lib/utils";\nimport "./globals.css";\n\nconst sans = Geist({\n variable: "--font-sans",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nconst mono = Geist_Mono({\n variable: "--font-mono",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nexport const metadata: Metadata = {\n title: "__EVE_INIT_APP_NAME__",\n description: "A Next.js starter for eve agents with AI Elements.",\n};\n\nexport default function RootLayout({ children }: { readonly children: ReactNode }) {\n return (\n <html className={cn(sans.variable, mono.variable)} lang="en">\n <body>\n <TooltipProvider>{children}</TooltipProvider>\n </body>\n </html>\n );\n}\n';
|
|
@@ -16,7 +16,7 @@ export default eveChannel({
|
|
|
16
16
|
`,"app/_components/agent-chat.tsx":`"use client";
|
|
17
17
|
|
|
18
18
|
import type { UserContent } from "ai";
|
|
19
|
-
import { Client, type
|
|
19
|
+
import { Client, type MessageStreamEvent } from "eve/client";
|
|
20
20
|
import { useEveAgent } from "eve/react";
|
|
21
21
|
import { AlertCircleIcon } from "lucide-react";
|
|
22
22
|
import { useCallback, useRef, useState } from "react";
|
|
@@ -78,7 +78,7 @@ export function AgentChat() {
|
|
|
78
78
|
);
|
|
79
79
|
|
|
80
80
|
const handleEvent = useCallback(
|
|
81
|
-
(event:
|
|
81
|
+
(event: MessageStreamEvent) => {
|
|
82
82
|
if (event.type !== "turn.started") {
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
@@ -119,6 +119,18 @@ export interface PublicAgentCompactionDefinition {
|
|
|
119
119
|
* Configures framework-owned runtime limits for this agent's runs.
|
|
120
120
|
*/
|
|
121
121
|
export interface AgentLimitsDefinition {
|
|
122
|
+
/**
|
|
123
|
+
* Maximum lifetime of one durable session, in milliseconds.
|
|
124
|
+
*
|
|
125
|
+
* The deadline starts when the session is created and survives process
|
|
126
|
+
* restarts and redeployments. If it elapses during an active turn, eve lets
|
|
127
|
+
* that turn settle before completing the session normally.
|
|
128
|
+
*
|
|
129
|
+
* `false` disables the timeout.
|
|
130
|
+
*
|
|
131
|
+
* @default 2_592_000_000 (30 days)
|
|
132
|
+
*/
|
|
133
|
+
readonly sessionTimeoutMs?: number | false;
|
|
122
134
|
/**
|
|
123
135
|
* Maximum provider-reported input tokens accumulated by one durable session.
|
|
124
136
|
*
|
|
@@ -3,13 +3,13 @@ import type { PublicToolInputSchema, PublicToolOutputSchema, ToolModelOutput } f
|
|
|
3
3
|
import type { Approval } from "#public/definitions/approval.js";
|
|
4
4
|
import type { ToolContext } from "#public/definitions/tool.js";
|
|
5
5
|
import type { SessionAuth } from "#context/keys.js";
|
|
6
|
-
import type {
|
|
6
|
+
import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
|
|
7
7
|
/**
|
|
8
8
|
* Stream event types allowed for dynamic tool resolvers. Dispatch
|
|
9
9
|
* supports any event; this extract restricts the public surface until
|
|
10
10
|
* more events are validated.
|
|
11
11
|
*/
|
|
12
|
-
export type DynamicToolEventName = Extract<
|
|
12
|
+
export type DynamicToolEventName = Extract<UnstampedMessageStreamEvent["type"], "session.started" | "turn.started" | "step.started">;
|
|
13
13
|
export declare const ALLOWED_DYNAMIC_TOOL_EVENTS: ReadonlySet<string>;
|
|
14
14
|
/**
|
|
15
15
|
* Instructions and skills are restricted to session/turn boundaries.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ULID-compatible generation, vendored rather than taken from npm: the
|
|
3
|
+
* `ulid` package's Node build hard-imports `node:crypto`, and this module is
|
|
4
|
+
* bundled into browser clients, the Nitro server, and the workflow step
|
|
5
|
+
* sandbox. `ulid.test.ts` pins the encoding against the reference
|
|
6
|
+
* implementation's golden vectors.
|
|
7
|
+
*/
|
|
8
|
+
/** Character count of a ULID: a 10-char timestamp then a 16-char random tail. */
|
|
9
|
+
export declare const ULID_LENGTH: number;
|
|
10
|
+
/** Mints one ULID. See {@link createUlidFactory}. */
|
|
11
|
+
export type UlidFactory = () => string;
|
|
12
|
+
/**
|
|
13
|
+
* Creates an independent ULID generator with its own monotonic state.
|
|
14
|
+
*
|
|
15
|
+
* Prefer {@link createUlid} unless a caller needs a sequence that unrelated
|
|
16
|
+
* code cannot perturb. Ids sort in the order one generator produced them:
|
|
17
|
+
* those minted within a millisecond increment the random tail, and a
|
|
18
|
+
* backwards clock pins to the last millisecond observed.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createUlidFactory(): UlidFactory;
|
|
21
|
+
/**
|
|
22
|
+
* Mints a ULID from the process-wide generator: a 48-bit millisecond
|
|
23
|
+
* timestamp then 80 bits of randomness, in Crockford base32.
|
|
24
|
+
*
|
|
25
|
+
* Ids lead with their timestamp, so they are broadly time-ordered. Ordering
|
|
26
|
+
* holds within one process only — separate processes have independent clocks
|
|
27
|
+
* and random tails — so a ULID is not a lossless pagination cursor.
|
|
28
|
+
*
|
|
29
|
+
* Throws when the clock is outside the 48-bit timestamp range or Web Crypto
|
|
30
|
+
* is unavailable rather than weakening the randomness.
|
|
31
|
+
*/
|
|
32
|
+
export declare const createUlid: UlidFactory;
|
|
33
|
+
/**
|
|
34
|
+
* Returns true when `value` is shaped like a ULID: {@link ULID_LENGTH}
|
|
35
|
+
* characters drawn from the Crockford base32 alphabet.
|
|
36
|
+
*
|
|
37
|
+
* Shape-only — this does not prove the value was minted here.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isUlid(value: string): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const ENCODING=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,TIME_MAX=2**48-1,ULID_LENGTH=26;function createUlidFactory(){let e=-1,n=new Uint8Array(10);return function(){let r=Date.now();if(!Number.isInteger(r)||r<0||r>TIME_MAX)throw Error(`Cannot mint a ULID: timestamp must be an integer from 0 to ${TIME_MAX}.`);if(r>e)e=r,randomFill(n);else if(!incrementRandom(n)){if(e===TIME_MAX)throw Error(`Cannot mint a ULID: random component overflowed at the maximum timestamp.`);e+=1,randomFill(n)}return`${encodeTime(e)}${encodeRandom(n)}`}}const createUlid=createUlidFactory();function isUlid(t){if(t.length!==26||ENCODING.indexOf(t[0]??``)>7)return!1;for(let n of t)if(!ENCODING.includes(n))return!1;return!0}function randomFill(e){let t=globalThis.crypto;if(typeof t?.getRandomValues!=`function`)throw Error(`Cannot mint a ULID: globalThis.crypto.getRandomValues is unavailable.`);t.getRandomValues(e)}function encodeTime(t){let n=t,r=``;for(let t=0;t<10;t+=1)r=ENCODING[n%32]+r,n=Math.floor(n/32);return r}function encodeRandom(t){let n=0,r=0,i=``;for(let a of t){for(n=n<<8|a,r+=8;r>=5;)r-=5,i+=ENCODING[n>>>r&31];n&=(1<<r)-1}return i}function incrementRandom(e){for(let t=e.length-1;t>=0;--t){let n=e[t]??0;if(n<255)return e[t]=n+1,e.fill(0,t+1),!0}return!1}export{ULID_LENGTH,createUlid,createUlidFactory,isUlid};
|
package/dist/src/svelte/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { type EveMessageData } from "#client/message-reducer.js";
|
|
|
3
3
|
import type { EveAgentReducer } from "#client/reducer.js";
|
|
4
4
|
import type { ClientSession } from "#client/session.js";
|
|
5
5
|
import type { ClientAuth, HeadersValue, SendTurnPayload, SessionState } from "#client/types.js";
|
|
6
|
-
import type {
|
|
6
|
+
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
7
7
|
export type { PrepareSend };
|
|
8
8
|
/**
|
|
9
9
|
* Session lifecycle phase: `"ready"` (idle), `"submitted"` (request sent,
|
|
@@ -30,7 +30,7 @@ export interface UseEveAgentReturn<TData> {
|
|
|
30
30
|
/** Last transport-level error, or `undefined` when healthy. */
|
|
31
31
|
readonly error: Error | undefined;
|
|
32
32
|
/** Raw server events received during this session (authoritative stream). */
|
|
33
|
-
readonly events: readonly
|
|
33
|
+
readonly events: readonly MessageStreamEvent[];
|
|
34
34
|
/** Clear all state and start a new session. */
|
|
35
35
|
readonly reset: () => void;
|
|
36
36
|
/** Send a turn with full structured input (message, attachments, input responses). */
|
|
@@ -76,8 +76,8 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
|
|
|
76
76
|
* @default ""
|
|
77
77
|
*/
|
|
78
78
|
readonly host?: string;
|
|
79
|
-
/**
|
|
80
|
-
readonly initialEvents?: readonly
|
|
79
|
+
/** Ordered prefix of the session stream used to rehydrate projected state. */
|
|
80
|
+
readonly initialEvents?: readonly MessageStreamEvent[];
|
|
81
81
|
/** Seed session identity and stream cursor for resuming a prior conversation. */
|
|
82
82
|
readonly initialSession?: SessionState;
|
|
83
83
|
/**
|
package/dist/src/vue/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { type EveAgentStoreCallbacks, type EveAgentStoreSnapshot, type EveAgentS
|
|
|
3
3
|
import type { EveAgentReducer } from "#client/reducer.js";
|
|
4
4
|
import type { ClientSession } from "#client/session.js";
|
|
5
5
|
import { type EveMessageData } from "#client/message-reducer.js";
|
|
6
|
-
import type {
|
|
6
|
+
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
7
7
|
import type { ClientAuth, HeadersValue, SendTurnPayload, SessionState } from "#client/types.js";
|
|
8
8
|
export type { PrepareSend };
|
|
9
9
|
/**
|
|
@@ -29,7 +29,7 @@ export interface UseEveAgentReturn<TData> {
|
|
|
29
29
|
/** Last transport-level error, or `undefined` when healthy. */
|
|
30
30
|
readonly error: ComputedRef<Error | undefined>;
|
|
31
31
|
/** Raw server events from this session (authoritative stream). */
|
|
32
|
-
readonly events: ComputedRef<readonly
|
|
32
|
+
readonly events: ComputedRef<readonly MessageStreamEvent[]>;
|
|
33
33
|
/** Clear all state and start a new session. */
|
|
34
34
|
readonly reset: () => void;
|
|
35
35
|
/** Send a turn with full structured input (message, attachments, input responses). */
|
|
@@ -75,8 +75,8 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
|
|
|
75
75
|
* @default ""
|
|
76
76
|
*/
|
|
77
77
|
readonly host?: string;
|
|
78
|
-
/**
|
|
79
|
-
readonly initialEvents?: readonly
|
|
78
|
+
/** Ordered prefix of the session stream used to rehydrate projected state. */
|
|
79
|
+
readonly initialEvents?: readonly MessageStreamEvent[];
|
|
80
80
|
/** Prior session cursor to resume from on mount. */
|
|
81
81
|
readonly initialSession?: SessionState;
|
|
82
82
|
/**
|
package/docs/agent-config.md
CHANGED
|
@@ -131,10 +131,18 @@ export default defineAgent({
|
|
|
131
131
|
limits: {
|
|
132
132
|
maxInputTokensPerSession: 200_000,
|
|
133
133
|
maxOutputTokensPerSession: 20_000,
|
|
134
|
+
sessionTimeoutMs: 7 * 24 * 60 * 60 * 1_000,
|
|
134
135
|
},
|
|
135
136
|
});
|
|
136
137
|
```
|
|
137
138
|
|
|
139
|
+
`sessionTimeoutMs` sets an absolute lifetime for every session, including
|
|
140
|
+
delegated sessions. It defaults to 30 days, starts at creation, and survives
|
|
141
|
+
restarts and redeployments. At the deadline, eve lets an active turn settle,
|
|
142
|
+
then emits `session.completed` and releases the continuation; the next
|
|
143
|
+
qualifying channel message starts fresh. Set it to `false` to disable the
|
|
144
|
+
timeout. Expiration does not delete stored session data.
|
|
145
|
+
|
|
138
146
|
Input and output budgets are checked independently. The model call that crosses
|
|
139
147
|
either limit is allowed to finish because providers only report exact token
|
|
140
148
|
usage after a call completes. Before the next model call, eve pauses the
|
|
@@ -147,12 +155,14 @@ still over budget, the next message re-raises the prompt. Declining a
|
|
|
147
155
|
delegated child's prompt cancels the root turn, which cascades to the whole
|
|
148
156
|
delegation tree — the delegating parent never receives an error result it
|
|
149
157
|
could retry against a fresh quota share. A reply that answers neither option
|
|
150
|
-
|
|
151
|
-
budget is granted.
|
|
158
|
+
is queued while the existing prompt stays pending; eve does not raise another
|
|
159
|
+
copy. The reply is processed once the budget is granted.
|
|
152
160
|
|
|
153
161
|
Sessions that cannot reach a human — task-mode runs such as schedules and
|
|
154
162
|
subagents without input proxying — skip the prompt and fail the next model
|
|
155
|
-
call with `SESSION_TOKEN_LIMIT_REACHED`.
|
|
163
|
+
call with `SESSION_TOKEN_LIMIT_REACHED`. A delegated task with no inherited
|
|
164
|
+
quota also fails instead of raising a continuation prompt that could only
|
|
165
|
+
grant another zero-token window.
|
|
156
166
|
|
|
157
167
|
When `maxInputTokensPerSession` is omitted, root sessions apply a default
|
|
158
168
|
input budget of `40_000_000` provider-reported input tokens.
|
|
@@ -161,11 +171,13 @@ to `false` uncaps that axis — the session never stops on it.
|
|
|
161
171
|
|
|
162
172
|
Delegated subagent sessions have no fixed default. Each child receives a
|
|
163
173
|
share of the delegating parent's remaining quota at dispatch time — the
|
|
164
|
-
remainder
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
174
|
+
remainder in the current budget window split evenly across the batch's local
|
|
175
|
+
subagent calls — and a completed child's usage counts against the parent's
|
|
176
|
+
quota, so a delegation tree can never outspend the budget configured at its
|
|
177
|
+
root. Approving a continuation opens a fresh parent window for later child
|
|
178
|
+
grants without erasing lifetime usage. An authored child limit applies only
|
|
179
|
+
when it is tighter than the parent's grant; an uncapped parent delegates
|
|
180
|
+
uncapped children.
|
|
169
181
|
|
|
170
182
|
## Workflow world
|
|
171
183
|
|
|
@@ -208,14 +220,14 @@ installed package must stay external in hosted output, list it in
|
|
|
208
220
|
|
|
209
221
|
`defineAgent` takes a few more fields, all optional. For the exported types, see the [TypeScript API](./reference/typescript-api).
|
|
210
222
|
|
|
211
|
-
| Field | Type | Default | Description
|
|
212
|
-
| -------------- | --------------------------------------- | ---------------- |
|
|
213
|
-
| `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls.
|
|
214
|
-
| `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call.
|
|
215
|
-
| `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits.
|
|
216
|
-
| `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent.
|
|
217
|
-
| `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema.
|
|
218
|
-
| `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.
|
|
223
|
+
| Field | Type | Default | Description |
|
|
224
|
+
| -------------- | --------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
225
|
+
| `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
|
|
226
|
+
| `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call. |
|
|
227
|
+
| `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. Sessions complete after 30 days by default; token-limit defaults and inheritance are described above. Set a limit to `false` to disable it. |
|
|
228
|
+
| `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent. |
|
|
229
|
+
| `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema. |
|
|
230
|
+
| `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. |
|
|
219
231
|
|
|
220
232
|
`externalDependencies` is a packaging control only. It keeps selected packages as runtime dependencies in the hosted output; it does not authorize, configure, or review any third-party service those packages may call.
|
|
221
233
|
|
|
@@ -56,7 +56,7 @@ Provider keys, tool secrets, and MCP, OpenAPI, and connection credentials stay i
|
|
|
56
56
|
|
|
57
57
|
## Resuming after a crash
|
|
58
58
|
|
|
59
|
-
Crash the process, hit a timeout, or redeploy mid-turn, and the run picks up from the last completed step rather than replaying the whole turn. Completed steps never re-run; eve replays the recorded result. A step interrupted mid-execution re-runs, so make non-idempotent side effects like charges or emails idempotent, or gate them with approval.
|
|
59
|
+
Crash the process, hit a timeout, or redeploy mid-turn, and the run picks up from the last completed step rather than replaying the whole turn. Completed steps never re-run; eve replays the recorded result. A step interrupted mid-execution re-runs, so make non-idempotent side effects like charges or emails idempotent, or gate them with approval. Whatever that step already wrote to the session stream stays there, and the re-run emits its events again under new ids, so a stream consumer sees both attempts — see [the event envelope](./sessions-runs-and-streaming#the-event-envelope).
|
|
60
60
|
|
|
61
61
|
There's nothing to configure. eve owns the workflow lifecycle, and sessions are durable by default.
|
|
62
62
|
|