eve 0.30.7 → 0.31.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 +36 -0
- package/README.md +5 -6
- package/dist/src/acp/adapter.d.ts +10 -4
- package/dist/src/acp/adapter.js +1 -1
- package/dist/src/channel/adapter-context.d.ts +1 -1
- package/dist/src/channel/adapter.d.ts +2 -4
- package/dist/src/channel/adapter.js +1 -1
- package/dist/src/channel/channel-address.d.ts +58 -0
- package/dist/src/channel/channel-address.js +1 -0
- package/dist/src/channel/channel-operations.d.ts +72 -0
- package/dist/src/channel/channel-operations.js +1 -0
- package/dist/src/channel/compiled-channel.d.ts +10 -6
- package/dist/src/channel/cross-channel-receive.d.ts +13 -25
- package/dist/src/channel/cross-channel-receive.js +2 -2
- package/dist/src/channel/receive-target.d.ts +1 -2
- package/dist/src/channel/routes.d.ts +21 -149
- package/dist/src/channel/schedule.d.ts +1 -1
- package/dist/src/channel/schedule.js +1 -1
- package/dist/src/channel/send-input.d.ts +6 -0
- package/dist/src/channel/send-input.js +1 -0
- package/dist/src/channel/session.d.ts +44 -30
- package/dist/src/channel/session.js +1 -1
- package/dist/src/channel/types.d.ts +8 -35
- package/dist/src/chunks/{use-eve-agent-k-XHfrJT.js → use-eve-agent-CF5D6jSV.js} +361 -367
- package/dist/src/chunks/{use-eve-agent-BXMIf5fR.js → use-eve-agent-DbYZLG0h.js} +364 -368
- package/dist/src/cli/commands/agent-prompt/build-and-verify.md +1 -2
- package/dist/src/cli/commands/channel-add-conflicts.js +1 -1
- package/dist/src/cli/commands/info.d.ts +1 -1
- package/dist/src/cli/commands/info.js +1 -1
- package/dist/src/cli/commands/registry-metadata.d.ts +15 -0
- package/dist/src/cli/commands/registry-metadata.js +1 -0
- package/dist/src/cli/commands/registry-package.d.ts +46 -0
- package/dist/src/cli/commands/registry-package.js +1 -0
- package/dist/src/cli/commands/registry.d.ts +1 -1
- package/dist/src/cli/commands/registry.js +4 -4
- package/dist/src/cli/dev/tui/runner.d.ts +1 -1
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/invoke/invoke.d.ts +1 -1
- package/dist/src/cli/invoke/invoke.js +1 -1
- package/dist/src/cli/invoke/result.d.ts +0 -11
- package/dist/src/cli/invoke/result.js +1 -1
- package/dist/src/client/client-error.d.ts +2 -0
- package/dist/src/client/client-error.js +1 -1
- package/dist/src/client/client.d.ts +7 -14
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/eve-agent-store.d.ts +4 -4
- package/dist/src/client/eve-agent-store.js +1 -1
- package/dist/src/client/index.d.ts +3 -2
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/message-reducer-types.d.ts +3 -0
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/client/message-response.d.ts +2 -7
- package/dist/src/client/message-response.js +1 -1
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session-controls.d.ts +29 -0
- package/dist/src/client/session-controls.js +1 -0
- package/dist/src/client/session-utils.d.ts +0 -20
- package/dist/src/client/session-utils.js +1 -1
- package/dist/src/client/session.d.ts +26 -90
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/sessions.d.ts +20 -0
- package/dist/src/client/sessions.js +1 -0
- package/dist/src/client/types.d.ts +26 -47
- package/dist/src/compiler/extension-compatibility.d.ts +10 -10
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/normalize-subagent.js +1 -1
- package/dist/src/evals/cli/eval-client.js +1 -1
- package/dist/src/evals/context.js +1 -1
- package/dist/src/evals/session.d.ts +7 -6
- package/dist/src/evals/session.js +1 -1
- package/dist/src/evals/types.d.ts +9 -9
- package/dist/src/execution/agent-handle-dispatch.js +1 -1
- package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/remote-agent-dispatch.d.ts +1 -3
- package/dist/src/execution/remote-agent-dispatch.js +1 -1
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/runtime-errors.d.ts +1 -1
- package/dist/src/execution/session-command-token.d.ts +2 -0
- package/dist/src/execution/session-command-token.js +1 -1
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/subagent-hitl-proxy.js +1 -1
- package/dist/src/execution/tool-auth.d.ts +1 -1
- package/dist/src/execution/tool-auth.js +1 -1
- package/dist/src/execution/turn-control-receiver.d.ts +2 -2
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/cancelled-turn-emission.d.ts +1 -1
- package/dist/src/harness/cancelled-turn-emission.js +1 -1
- package/dist/src/harness/emission-state.d.ts +25 -0
- package/dist/src/harness/emission-state.js +1 -0
- package/dist/src/harness/emission.d.ts +5 -37
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/handles/prompt.d.ts +22 -3
- package/dist/src/harness/handles/prompt.js +1 -1
- package/dist/src/harness/handles/store.d.ts +0 -5
- package/dist/src/harness/handles/store.js +1 -1
- package/dist/src/harness/ordered-stream-emitter.d.ts +3 -2
- package/dist/src/harness/ordered-stream-emitter.js +1 -1
- package/dist/src/harness/runtime-actions.js +1 -1
- package/dist/src/harness/session-limit-enforcement.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tools.d.ts +1 -1
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.d.ts +15 -0
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.js +1 -0
- package/dist/src/internal/nitro/dev-runtime-source-snapshot.d.ts +14 -2
- package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
- package/dist/src/internal/nitro/host/dev-server-http.js +1 -1
- package/dist/src/internal/nitro/routes/channel-dispatch.d.ts +2 -5
- package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
- package/dist/src/internal/nitro/routes/channel-route-context.d.ts +4 -3
- package/dist/src/internal/nitro/routes/channel-route-context.js +1 -1
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/protocol/cancel-turn.d.ts +9 -4
- package/dist/src/protocol/cancel-turn.js +1 -1
- package/dist/src/protocol/message.d.ts +27 -17
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/protocol/reset-session.d.ts +1 -1
- package/dist/src/protocol/routes.d.ts +27 -47
- package/dist/src/protocol/routes.js +1 -1
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +19 -21
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/discord/discordChannel.d.ts +5 -4
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/eve.d.ts +11 -10
- package/dist/src/public/channels/eve.js +1 -1
- package/dist/src/public/channels/github/dispatch.d.ts +8 -8
- package/dist/src/public/channels/github/dispatch.js +1 -1
- package/dist/src/public/channels/github/githubChannel.d.ts +4 -3
- package/dist/src/public/channels/github/githubChannel.js +1 -1
- package/dist/src/public/channels/github/pr-context.d.ts +1 -1
- package/dist/src/public/channels/index.d.ts +1 -1
- package/dist/src/public/channels/linear/linearChannel.d.ts +4 -3
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/slack/index.d.ts +1 -1
- package/dist/src/public/channels/slack/interactions.d.ts +3 -4
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/session-operations.d.ts +37 -0
- package/dist/src/public/channels/slack/session-operations.js +1 -0
- package/dist/src/public/channels/slack/slackChannel.d.ts +56 -74
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.d.ts +4 -3
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.d.ts +5 -4
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/channels/twilio/twilioChannel.d.ts +4 -3
- package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
- package/dist/src/public/definitions/callback-context.d.ts +1 -2
- package/dist/src/public/definitions/channel.d.ts +22 -86
- package/dist/src/public/definitions/channel.js +1 -1
- package/dist/src/public/definitions/hook.d.ts +1 -0
- package/dist/src/public/definitions/remote-agent.js +1 -1
- package/dist/src/public/definitions/schedule.d.ts +16 -16
- package/dist/src/public/definitions/tool.d.ts +5 -5
- package/dist/src/public/schedules/index.d.ts +1 -1
- package/dist/src/react/use-eve-agent.d.ts +7 -4
- package/dist/src/react/use-eve-agent.js +1 -1
- package/dist/src/runtime/agent/bootstrap-model-utils.d.ts +11 -0
- package/dist/src/runtime/agent/bootstrap-model-utils.js +1 -1
- package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
- package/dist/src/runtime/agent/mock-model-fixtures.js +2 -2
- package/dist/src/runtime/prompt/compose.js +1 -1
- package/dist/src/runtime/subagents/dynamic-remote-agent-config.js +1 -1
- package/dist/src/runtime/types.d.ts +2 -2
- package/dist/src/services/inspect-application.d.ts +1 -1
- package/dist/src/services/inspect-application.js +1 -1
- package/dist/src/setup/channel-add-conflicts.js +1 -1
- package/dist/src/setup/integrations/linear/setup.js +1 -1
- 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 +29 -17
- package/dist/src/shared/async-iterable.d.ts +2 -0
- package/dist/src/shared/async-iterable.js +1 -0
- package/dist/src/shared/channel-definition.d.ts +7 -7
- package/dist/src/shared/schedule-definition.d.ts +2 -2
- package/dist/src/shared/tool-definition.d.ts +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.d.ts +8 -5
- 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 +8 -5
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/README.md +6 -6
- package/docs/channels/chat-sdk.mdx +5 -6
- package/docs/channels/custom.mdx +116 -144
- package/docs/channels/discord.mdx +1 -1
- package/docs/channels/eve.mdx +76 -30
- package/docs/channels/github.mdx +1 -1
- package/docs/channels/linear.mdx +10 -10
- package/docs/channels/overview.mdx +2 -2
- package/docs/channels/slack.mdx +46 -15
- package/docs/channels/telegram.mdx +1 -1
- package/docs/channels/twilio.mdx +1 -1
- package/docs/concepts/default-harness.md +11 -3
- package/docs/concepts/execution-model-and-durability.mdx +17 -5
- package/docs/concepts/sessions-runs-and-streaming.md +45 -16
- package/docs/evals/cases.mdx +3 -3
- package/docs/evals/targets.mdx +1 -1
- package/docs/guides/auth-and-route-protection.md +2 -1
- package/docs/guides/client/continuations.mdx +50 -77
- package/docs/guides/client/messages.mdx +29 -33
- package/docs/guides/client/output-schema.mdx +7 -14
- package/docs/guides/client/overview.mdx +40 -11
- package/docs/guides/client/streaming.mdx +18 -23
- package/docs/guides/frontend/nuxt.mdx +1 -1
- package/docs/guides/frontend/overview.mdx +40 -36
- package/docs/guides/frontend/sveltekit.mdx +1 -1
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +19 -23
- package/docs/guides/frontend/use-eve-agent-vue.mdx +21 -25
- package/docs/guides/hooks.md +1 -1
- package/docs/guides/instrumentation.md +1 -1
- package/docs/install-integrations.mdx +4 -2
- package/docs/patterns/dynamic-scheduling.md +16 -15
- package/docs/reference/cli.md +4 -1
- package/docs/schedules.mdx +10 -11
- package/docs/subagents.mdx +1 -1
- package/docs/tools/human-in-the-loop.md +1 -1
- package/docs/tools/overview.mdx +26 -2
- package/docs/tutorial/ship-it.mdx +1 -1
- package/package.json +1 -1
- package/dist/src/channel/cancel.d.ts +0 -6
- package/dist/src/channel/cancel.js +0 -1
- package/dist/src/channel/clear-session.d.ts +0 -4
- package/dist/src/channel/clear-session.js +0 -1
- package/dist/src/channel/compact-session.d.ts +0 -4
- package/dist/src/channel/compact-session.js +0 -1
- package/dist/src/channel/reset-session.d.ts +0 -6
- package/dist/src/channel/reset-session.js +0 -1
- package/dist/src/channel/resolve-active-session.d.ts +0 -4
- package/dist/src/channel/resolve-active-session.js +0 -1
- package/dist/src/channel/send.d.ts +0 -6
- package/dist/src/channel/send.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.31.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 40b09e6: Replace continuation-token session APIs with fixed, ID-addressed handles and consistent channel-local operations. This is a breaking migration across the following public surfaces:
|
|
8
|
+
|
|
9
|
+
- TypeScript clients now use `client.sessions.create(input)` to start a session and `client.sessions.attach(sessionId)` to obtain a fixed handle; `client.session(...)` and continuation-token client state are removed.
|
|
10
|
+
- Client, eval, frontend, fixed-session, and Slack message delivery now use positional `send(message, options)`. HITL replies use the separate `respond(inputResponses, options)` method, and `message` and `inputResponses` are mutually exclusive.
|
|
11
|
+
- Custom channels use `from(address)` for channel-local operations, top-level `resolveSession(address)` to resolve the current owner, `attachSession(sessionId)` for an immutable session handle, and `to(channel, target)` for cross-channel delivery.
|
|
12
|
+
- Slack message and interaction hooks expose `ctx.send`, `ctx.respond`, `ctx.cancel`, `ctx.compact`, `ctx.clear`, `ctx.reset`, and `ctx.resolveSession`. For generic events, the target is passed in each operation's options; `ctx.receive` and `resolveActiveSession` are removed.
|
|
13
|
+
- Schedule handlers replace `receive(channel, { message, target, auth })` with `to(channel, target).send(message, { auth })`.
|
|
14
|
+
- Channel event session identity moves to `ctx.session.id`, while `session.failed` includes `sessionId` in its event data.
|
|
15
|
+
- The eve HTTP API keeps `POST /eve/v1/session` for creation and `POST /eve/v1/session/:sessionId` for follow-ups. Clear, compact, and reset move from continuation-token body routes to `POST /eve/v1/session/:sessionId/{clear,compact,reset}`; cancel and streaming remain ID-addressed.
|
|
16
|
+
- Session message and control bodies no longer accept or return continuation tokens. Accepted asynchronous work returns HTTP `202`; no-active operation results omit `sessionId`, and inactive follow-ups return HTTP `409` with `code: "session_not_active"`, available as `ClientError.code`.
|
|
17
|
+
- Canonical eve `onMessage` hooks can no longer drop an otherwise authorized delivery by returning `null`.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- 2054b9f: Agent-messaging `<agents>` listings are now announced as framework-injected user-role notes instead of assistant messages appended to history. This fixes parent resume failures on models that reject assistant-final requests (e.g. `This model does not support assistant message prefill` from Claude via AI Gateway) after a persistent child parks, keeps the announcement append-only so provider prompt caches stay warm, and the agent-messaging system prompt now declares the `[Agents]` note as framework-injected.
|
|
22
|
+
- 84c3dfc: Flush local development streaming response headers immediately so pending Workflow streams can be cancelled without accumulating listeners.
|
|
23
|
+
- b7a2a14: Dev runtime snapshots now mount workspace dependency packages in place
|
|
24
|
+
instead of copying them. Only roots that host runtime-hydrated authored
|
|
25
|
+
source — the app root, extension mount roots, and tsconfig path-alias
|
|
26
|
+
targets — are still copied, matching how installed dependencies already
|
|
27
|
+
resolved. In monorepos this removes the largest per-generation copy: a
|
|
28
|
+
workspace-linked framework package (hundreds of files and tens of
|
|
29
|
+
megabytes per rebuild) no longer lands under
|
|
30
|
+
`.eve/dev-runtime/snapshots/`.
|
|
31
|
+
|
|
32
|
+
## 0.30.8
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- e6f4808: Add a single `eve add linear` flow that installs and configures both the Linear Channel and Linear MCP connection.
|
|
37
|
+
- f51f866: Tools can now use async generators to stream preliminary output snapshots. eve publishes local snapshots as `action.partial` events before the final `action.result`, and the default client reducer exposes provisional output with `partial: true`.
|
|
38
|
+
|
|
3
39
|
## 0.30.7
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Unless you configure stricter controls, eve agents may operate with permissive s
|
|
|
27
27
|
- Durable message runs and follow-up turns
|
|
28
28
|
- Inspectable compiled artifacts under `.eve/`
|
|
29
29
|
- Per-agent sandbox with optional authored overrides
|
|
30
|
-
- A stable HTTP protocol
|
|
30
|
+
- A stable HTTP protocol built around immutable session IDs
|
|
31
31
|
- A runtime model that keeps channels, harnesses, and workflow execution separate
|
|
32
32
|
|
|
33
33
|
## Authored Directory
|
|
@@ -163,14 +163,13 @@ You do not need this section to author an eve agent — it documents the public
|
|
|
163
163
|
|
|
164
164
|
eve's internal split is:
|
|
165
165
|
|
|
166
|
-
- the **channel** normalizes inbound transport, applies auth and delivery policy, and owns
|
|
166
|
+
- the **channel** normalizes inbound transport, applies auth and delivery policy, and owns channel-local addresses
|
|
167
167
|
- the **harness** does one unit of AI work and returns `{ session, next }`
|
|
168
168
|
- the **runtime** persists state, follows `next`, streams events, and owns workflow primitives (`start()`, `resumeHook()`, `createHook()`, `getWritable()`)
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
- `sessionId` — runtime-owned handle for streaming and inspection
|
|
170
|
+
The public HTTP protocol exposes one immutable identifier: `sessionId`. Create a
|
|
171
|
+
session explicitly, then use that ID for follow-up messages, controls, streaming,
|
|
172
|
+
and inspection. Channel-local addresses remain behind authored channel APIs.
|
|
174
173
|
|
|
175
174
|
## Changelog
|
|
176
175
|
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { type AgentContext, type InitializeRequest, type InitializeResponse, type NewSessionRequest, type NewSessionResponse, type PromptRequest, type PromptResponse } from "#compiled/@agentclientprotocol/sdk/index.js";
|
|
2
|
-
import type { ClientOptions, SendTurnInput
|
|
2
|
+
import type { ClientOptions, SendTurnInput } from "#client/types.js";
|
|
3
3
|
import type { HandleMessageStreamEvent } from "#protocol/message.js";
|
|
4
|
+
import type { InputResponse } from "#runtime/input/types.js";
|
|
4
5
|
interface AdapterClientSession {
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
send(message: SendTurnInput["message"]): Promise<AsyncIterable<HandleMessageStreamEvent>>;
|
|
7
|
+
respond(inputResponses: readonly InputResponse[]): Promise<AsyncIterable<HandleMessageStreamEvent>>;
|
|
7
8
|
cancel(options?: {
|
|
8
9
|
turnId?: string;
|
|
9
10
|
}): Promise<unknown>;
|
|
10
11
|
reset(): Promise<unknown>;
|
|
11
12
|
}
|
|
12
13
|
interface AdapterClient {
|
|
13
|
-
|
|
14
|
+
readonly sessions: {
|
|
15
|
+
create(input: SendTurnInput): Promise<{
|
|
16
|
+
readonly response: AsyncIterable<HandleMessageStreamEvent>;
|
|
17
|
+
readonly session: AdapterClientSession;
|
|
18
|
+
}>;
|
|
19
|
+
};
|
|
14
20
|
}
|
|
15
21
|
/** Configuration for translating one ACP client connection to an eve server. */
|
|
16
22
|
export interface EveAcpAdapterOptions {
|
package/dist/src/acp/adapter.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{realpath}from"node:fs/promises";import{PROTOCOL_VERSION,RequestError,methods}from"#compiled/@agentclientprotocol/sdk/index.js";import{Client,ClientError}from"#client/index.js";const ANSWER_FIELD=`answer`,ERROR_CODE_EVE=-32002;var EveAcpAdapter=class{#e;#t;#n;#r=!1;#i=new Map;constructor(e){this.#t=e.eveVersion,this.#n=e.workspaceRoot,this.#e=e.client??new Client({auth:e.auth,headers:e.headers,host:e.serverUrl,
|
|
1
|
+
import{randomUUID}from"node:crypto";import{realpath}from"node:fs/promises";import{PROTOCOL_VERSION,RequestError,methods}from"#compiled/@agentclientprotocol/sdk/index.js";import{Client,ClientError}from"#client/index.js";const ANSWER_FIELD=`answer`,ERROR_CODE_EVE=-32002;var EveAcpAdapter=class{#e;#t;#n;#r=!1;#i=new Map;constructor(e){this.#t=e.eveVersion,this.#n=e.workspaceRoot,this.#e=e.client??new Client({auth:e.auth,headers:e.headers,host:e.serverUrl,redirect:`manual`})}initialize(e){return this.#r=e.clientCapabilities?.elicitation?.form!==void 0,{protocolVersion:PROTOCOL_VERSION,agentCapabilities:{loadSession:!1,promptCapabilities:{},sessionCapabilities:{close:{}}},agentInfo:{name:`eve`,title:`eve`,version:this.#t},authMethods:[]}}async newSession(t){if(t.mcpServers.length>0)throw unsupported(`Client-provided MCP servers are not supported by eve ACP mode.`);if((t.additionalDirectories?.length??0)>0)throw unsupported(`Additional workspace directories are not supported by eve ACP mode.`);if(this.#n!==void 0){let e=await normalizedRealpath(t.cwd,`session/new.cwd`),n=await normalizedRealpath(this.#n,`the eve application root`);if(e!==n)throw RequestError.invalidParams({cwd:t.cwd,workspaceRoot:n},`ACP cwd must be the eve application root`)}let n=randomUUID();return this.#i.set(n,{tools:new Map}),{sessionId:n}}async prompt(e,t,n){let i=this.#s(e.sessionId);if(i.active!==void 0)throw new RequestError(-32001,`ACP session ${e.sessionId} already has an active prompt.`);let a=promptContent(e);i.tools.clear();let o=Promise.withResolvers(),s={cancelRequested:!1,protocolCancelled:!1,outboundController:new AbortController,settled:o.promise,resolveSettled:o.resolve};i.active=s;let onProtocolCancel=()=>{s.protocolCancelled=!0,this.#o(i).catch(()=>void 0)};n.aborted?onProtocolCancel():n.addEventListener(`abort`,onProtocolCancel,{once:!0});try{if(s.protocolCancelled)throw RequestError.requestCancelled({sessionId:e.sessionId});let o={message:a};for(;;){let a;if(i.client===void 0){if(o.message===void 0)throw Error(`ACP session has not started.`);let e=await this.#e.sessions.create({...o,message:o.message});i.client=e.session,a=e.response}else a=o.inputResponses===void 0?await i.client.send(o.message):await i.client.respond(o.inputResponses);(s.cancelRequested||s.protocolCancelled)&&await this.#o(i);let c=[],l=!1,u,d;for await(let n of a){let r=`data`in n&&`turnId`in n.data?n.data.turnId:void 0;typeof r==`string`&&(s.turnId=r),n.type===`input.requested`&&c.push(...n.data.requests),n.type===`authorization.required`&&(d=unsupported(`Connection authorization cannot be completed through eve ACP mode.`)),n.type===`turn.cancelled`&&(l=!0),(n.type===`turn.failed`||n.type===`session.failed`)&&(u=n),await this.#c(e.sessionId,i,n,t)}if(s.protocolCancelled)throw RequestError.requestCancelled({sessionId:e.sessionId});if(l||s.cancelRequested)return{stopReason:`cancelled`};if(u!==void 0)throw eveFailure(u);if(d!==void 0)throw d;if(c.length===0)return{stopReason:`end_turn`};let f;try{f=await Promise.all(c.map(r=>this.#l(e.sessionId,i,r,t,n)))}catch(t){if(s.protocolCancelled)throw RequestError.requestCancelled({sessionId:e.sessionId});if(s.cancelRequested)return{stopReason:`cancelled`};throw t}if(s.protocolCancelled)throw RequestError.requestCancelled({sessionId:e.sessionId});if(s.cancelRequested)return{stopReason:`cancelled`};o={inputResponses:f}}}catch(e){throw acpRequestError(e)}finally{n.removeEventListener(`abort`,onProtocolCancel),i.tools.clear(),s.resolveSettled(),i.active===s&&(i.active=void 0)}}async cancel(e){let t=this.#i.get(e);t===void 0||t.active===void 0||(t.active.cancelRequested=!0,await this.#o(t))}async closeSession(e){let t=this.#s(e);this.#i.delete(e),await this.#a(t)}async close(){let e=[...this.#i.values()];this.#i.clear(),await Promise.allSettled(e.map(e=>this.#a(e)))}async#a(e){let t;if(e.active!==void 0){let n=e.active;n.cancelRequested=!0;try{await this.#o(e)}catch(e){t=e}await n.settled}try{await e.client?.reset()}catch(e){throw t===void 0?e:AggregateError([t,e],`Could not cancel or reset the eve session`)}if(t!==void 0)throw t}async#o(e){e.active?.outboundController.abort(),e.client!==void 0&&await e.client.cancel(e.active?.turnId===void 0?void 0:{turnId:e.active.turnId})}#s(e){let t=this.#i.get(e);if(t===void 0)throw RequestError.invalidParams({sessionId:e},`Unknown or closed ACP session`);return t}async#c(e,t,n,r){switch(n.type){case`message.appended`:await notifyUpdate(r,e,{sessionUpdate:`agent_message_chunk`,content:{type:`text`,text:n.data.messageDelta},messageId:`${n.data.turnId}:message:${n.data.stepIndex}`});return;case`reasoning.appended`:await notifyUpdate(r,e,{sessionUpdate:`agent_thought_chunk`,content:{type:`text`,text:n.data.reasoningDelta},messageId:`${n.data.turnId}:thought:${n.data.stepIndex}`});return;case`actions.requested`:for(let i of n.data.actions){let n=toolCallForAction(i);t.tools.set(i.callId,n),await notifyUpdate(r,e,{sessionUpdate:`tool_call`,...n})}return;case`action.result`:{let t=n.data.result,i=n.data.status!==`completed`||t.isError?`failed`:`completed`;await notifyUpdate(r,e,{sessionUpdate:`tool_call_update`,toolCallId:t.callId,status:i,content:[{type:`content`,content:{type:`text`,text:stringifyOutput(t.output)}}],rawOutput:t.output});return}default:return}}async#l(e,t,n,a,o){let c=AbortSignal.any([o,t.active.outboundController.signal]);if(n.display===`confirmation`){let o=`${n.requestId}:approve`,s=`${n.requestId}:deny`,l=t.tools.get(n.action.callId)??toolCallForAction(n.action),u=await a.request(methods.client.session.requestPermission,{sessionId:e,toolCall:l,options:[{kind:`allow_once`,name:`Approve`,optionId:o},{kind:`reject_once`,name:`Deny`,optionId:s}]},{cancellationSignal:c});if(u.outcome.outcome===`cancelled`)return this.#u(t),{requestId:n.requestId};if(u.outcome.optionId===o)return{requestId:n.requestId,optionId:`approve`};if(u.outcome.optionId===s)return{requestId:n.requestId,optionId:`deny`};throw RequestError.invalidParams({optionId:u.outcome.optionId},`Unknown ACP permission option`)}if(!this.#r)throw unsupported(`The ACP client does not support form elicitation required by this eve question.`);let l=elicitationProperty(n),u=await a.request(methods.client.elicitation.create,{mode:`form`,sessionId:e,message:n.prompt,requestedSchema:{type:`object`,properties:{[ANSWER_FIELD]:l},required:[ANSWER_FIELD]}},{cancellationSignal:c});if(u.action!==`accept`)return this.#u(t),{requestId:n.requestId};let d=u.content?.[ANSWER_FIELD];if(typeof d!=`string`)throw RequestError.invalidParams(u.content,`ACP elicitation response must contain a string answer`);if(n.display===`select`){if(!n.options?.some(e=>e.id===d))throw RequestError.invalidParams({answer:d},`Unknown eve question option`);return{requestId:n.requestId,optionId:d}}return{requestId:n.requestId,text:d}}#u(e){let t=e.active;t.cancelRequested=!0,t.outboundController.abort()}};async function normalizedRealpath(e,n){try{return await realpath(e)}catch(t){throw RequestError.invalidParams({path:e},`Could not resolve ${n}: ${errorMessage(t)}`)}}function promptContent(e){let t=e.prompt.map(e=>{if(e.type!==`text`)throw unsupported(`ACP prompt content type ${JSON.stringify(e.type)} is not supported.`);return{type:`text`,text:e.text}});if(t.every(e=>e.text.length===0))throw RequestError.invalidParams(e.prompt,`ACP prompt must contain at least one non-empty text block`);return t}function toolCallForAction(e){let t=e.kind===`tool-call`?e.toolName:e.kind===`load-skill`?`Load skill`:e.name;return{toolCallId:e.callId,title:t,kind:`other`,status:`pending`,rawInput:e.input}}function elicitationProperty(e){if(e.display===`select`&&e.allowFreeform!==!0&&e.options?.length)return{type:`string`,title:e.prompt,oneOf:e.options.map(e=>({const:e.id,title:e.label,description:e.description}))};if(e.display===`text`&&e.allowFreeform!==!1)return{type:`string`,title:e.prompt,minLength:1};throw unsupported(`This eve question shape cannot be represented by ACP form elicitation.`)}async function notifyUpdate(e,t,n){await e.notify(methods.client.session.update,{sessionId:t,update:n})}function stringifyOutput(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}function unsupported(e){return new RequestError(-32003,e)}function eveFailure(e){return new RequestError(ERROR_CODE_EVE,e.data.message,{code:e.data.code,details:e.data.details})}function acpRequestError(e){return e instanceof RequestError?e:e instanceof ClientError?new RequestError(ERROR_CODE_EVE,e.message,{httpStatus:e.status}):new RequestError(ERROR_CODE_EVE,errorMessage(e))}function errorMessage(e){return e instanceof Error?e.message:String(e)}export{EveAcpAdapter};
|
|
@@ -6,6 +6,6 @@ import type { ChannelAdapter, ChannelAdapterContext } from "#channel/adapter.js"
|
|
|
6
6
|
*
|
|
7
7
|
* Populates `session` with a live {@link SessionHandle} backed by the
|
|
8
8
|
* supplied accessor so handlers can read identity / auth and call
|
|
9
|
-
* `
|
|
9
|
+
* `session.continuation.rekey(...)` to re-key the parked session.
|
|
10
10
|
*/
|
|
11
11
|
export declare function buildAdapterContext<TCtx extends ChannelAdapterContext<any> = ChannelAdapterContext>(adapter: ChannelAdapter<TCtx>, accessor: ContextAccessor): TCtx;
|
|
@@ -14,7 +14,7 @@ import type { FetchFileResult, FetchFileFunction } from "#shared/channel-definit
|
|
|
14
14
|
* {@link ContextAccessor} that tools and providers use).
|
|
15
15
|
*
|
|
16
16
|
* `session` is a live handle to the current session — id, auth,
|
|
17
|
-
* continuation
|
|
17
|
+
* optional channel continuation address, including an imperative `rekey()`
|
|
18
18
|
* for channels that need to re-key the session mid-turn (e.g. Slack's
|
|
19
19
|
* auto-anchor on first post).
|
|
20
20
|
*/
|
|
@@ -148,9 +148,7 @@ export declare function defaultDeliverResult(payload: DeliverPayload): StepInput
|
|
|
148
148
|
export declare function getAdapterKind(adapter: ChannelAdapter): string;
|
|
149
149
|
/**
|
|
150
150
|
* Calls an adapter's event handler for a given event. Adapters perform side
|
|
151
|
-
* effects rather than transforming events
|
|
152
|
-
* runtime refreshes `session.waiting` with the live continuation token so a
|
|
153
|
-
* handler that re-keyed the session publishes the new resume handle.
|
|
151
|
+
* effects rather than transforming events.
|
|
154
152
|
*
|
|
155
153
|
* Throwing handlers are logged and swallowed so a downstream delivery
|
|
156
154
|
* failure does not corrupt the event stream write path.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";const log=createLogger(`channel.adapter`);function defaultDeliverResult(e){if(e.message!==void 0)return{inputResponses:e.inputResponses,message:e.message,context:e.context,outputSchema:e.outputSchema};if(e.inputResponses!==void 0&&e.inputResponses.length>0)return{inputResponses:e.inputResponses,context:e.context,outputSchema:e.outputSchema};if(e.context!==void 0&&e.context.length>0)return{context:e.context,outputSchema:e.outputSchema};if(e.outputSchema!==void 0)return{outputSchema:e.outputSchema}}function getAdapterKind(e){return e.kind}async function callAdapterEventHandler(e,n,r){let i=withWaitingContinuationToken(n,r),a=e[n.type];if(a!==void 0)try{await a(`data`in i?i.data:void 0,r)}catch(r){log.error(`adapter event handler threw — event swallowed`,{adapterKind:getAdapterKind(e),eventType:n.type,error:r})}return withWaitingContinuationToken(i,r)}function withWaitingContinuationToken(e,t){return e.type===`session.waiting`?{...e,data:{...e.data,continuationToken:t.session.continuation?.token??t.session.id}}:e}export{callAdapterEventHandler,defaultDeliverResult,getAdapterKind};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { UserContent } from "ai";
|
|
2
|
+
import type { ChannelAdapter } from "#channel/adapter.js";
|
|
3
|
+
import type { SendPayload } from "#channel/routes.js";
|
|
4
|
+
import { type Session } from "#channel/session.js";
|
|
5
|
+
import type { CancelTurnResult, ClearSessionResult, CompactSessionResult, ResetSessionResult, Runtime, SessionAuthContext, SessionCallback } from "#channel/types.js";
|
|
6
|
+
import type { RunMode } from "#shared/run-mode.js";
|
|
7
|
+
interface BaseChannelAddressDeliveryOptions {
|
|
8
|
+
readonly auth: SessionAuthContext | null;
|
|
9
|
+
readonly callback?: SessionCallback;
|
|
10
|
+
readonly initiatorAuth?: SessionAuthContext | null;
|
|
11
|
+
readonly mode?: RunMode;
|
|
12
|
+
readonly title?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Delivery options for a channel address whose continuation token is already bound. */
|
|
15
|
+
export type ChannelAddressDeliveryOptions<TState = undefined> = [TState] extends [undefined] ? BaseChannelAddressDeliveryOptions : BaseChannelAddressDeliveryOptions & {
|
|
16
|
+
readonly state?: TState;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Dynamic handle for whichever durable session currently owns one channel-local address.
|
|
20
|
+
* Only {@link send} may create a session when the address is unowned.
|
|
21
|
+
*/
|
|
22
|
+
export interface ChannelAddress<TState = undefined> {
|
|
23
|
+
readonly continuationToken: string;
|
|
24
|
+
deliver(input: SendPayload, options: ChannelAddressDeliveryOptions<TState>): Promise<Session>;
|
|
25
|
+
send(message: string | UserContent, options: ChannelAddressDeliveryOptions<TState>): Promise<Session>;
|
|
26
|
+
respond(inputResponses: SendPayload["inputResponses"], options: ChannelAddressDeliveryOptions<TState>): Promise<Session>;
|
|
27
|
+
cancel(options?: {
|
|
28
|
+
readonly turnId?: string;
|
|
29
|
+
}): Promise<CancelTurnResult>;
|
|
30
|
+
compact(): Promise<CompactSessionResult>;
|
|
31
|
+
clear(): Promise<ClearSessionResult>;
|
|
32
|
+
reset(options?: {
|
|
33
|
+
readonly reason?: string;
|
|
34
|
+
}): Promise<ResetSessionResult>;
|
|
35
|
+
resolveSession(): Promise<Session | undefined>;
|
|
36
|
+
}
|
|
37
|
+
/** Factory for binding a route-local continuation token to a {@link ChannelAddress}. */
|
|
38
|
+
export type ChannelAddressFn<TState = undefined> = (continuationToken: string) => ChannelAddress<TState>;
|
|
39
|
+
/** Creates one channel address backed by the runtime's continuation dispatch primitive. */
|
|
40
|
+
export declare function createChannelAddress<TState = undefined>(input: {
|
|
41
|
+
readonly adapter: ChannelAdapter<any>;
|
|
42
|
+
readonly channelName: string;
|
|
43
|
+
readonly continuationToken: string;
|
|
44
|
+
readonly metadata?: {
|
|
45
|
+
readonly requestId?: string;
|
|
46
|
+
};
|
|
47
|
+
readonly runtime: Runtime;
|
|
48
|
+
}): ChannelAddress<TState>;
|
|
49
|
+
/** Builds a request-scoped factory for channel addresses on one authored channel. */
|
|
50
|
+
export declare function createChannelAddressFn<TState = undefined>(input: {
|
|
51
|
+
readonly adapter: ChannelAdapter<any>;
|
|
52
|
+
readonly channelName: string;
|
|
53
|
+
readonly metadata?: {
|
|
54
|
+
readonly requestId?: string;
|
|
55
|
+
};
|
|
56
|
+
readonly runtime: Runtime;
|
|
57
|
+
}): ChannelAddressFn<TState>;
|
|
58
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createSession,sessionCallbackToTurnCaller}from"#channel/session.js";import{normalizeSendInput,serializeUrlFilePartsInMessage}from"#channel/send-input.js";import{isRuntimeSessionOwnershipConflictError}from"#execution/runtime-errors.js";import{isReservedSessionCommandToken}from"#execution/session-command-token.js";function createChannelAddress(r){let i=r.metadata??{},a=`${r.channelName}:${r.continuationToken}`;if(isReservedSessionCommandToken(a))throw Error(`Channel address "${a}" uses eve's reserved session namespace.`);return{continuationToken:r.continuationToken,async deliver(n,o){let s=normalizeSendInput(n),c=sessionCallbackToTurnCaller(o.callback),l={auth:o.auth,kind:`send`,payload:{...s,message:serializeUrlFilePartsInMessage(s.message)},requestId:i.requestId},u=c===void 0?l:{...l,caller:c},dispatch=async()=>{let t=await r.runtime.dispatchContinuation({command:u,continuationToken:a});return t.status===`accepted`?createSession(t.sessionId,r.runtime,i):void 0},d=await dispatch();if(d!==void 0)return d;if(s.inputResponses&&s.inputResponses.length>0)throw Error(`Cannot deliver inputResponses — the target session was not found via continuation token.`);let f=o.state,p={adapter:f===void 0?r.adapter:{...r.adapter,state:{...r.adapter.state,...f}},auth:o.auth,capabilities:o.mode===`task`?void 0:{requestInput:!0},callback:o.callback,channelName:r.channelName,continuationToken:a,initiatorAuth:o.initiatorAuth,input:{context:s.context,message:serializeUrlFilePartsInMessage(s.message)??``,outputSchema:s.outputSchema},mode:o.mode??`conversation`,requestId:i.requestId,title:o.title};try{return createSession((await r.runtime.createSession(p)).sessionId,r.runtime,i)}catch(e){if(!isRuntimeSessionOwnershipConflictError(e))throw e;let t=await dispatch();if(t!==void 0)return t;throw e}},async send(e,t){return await this.deliver({message:e},t)},async respond(e,t){if(e===void 0||e.length===0)throw Error(`respond() requires at least one input response.`);return await this.deliver({inputResponses:e},t)},async cancel(e){return await r.runtime.dispatchContinuation({command:{kind:`cancel`,turnId:e?.turnId},continuationToken:a})},async compact(){return await r.runtime.dispatchContinuation({command:{kind:`compact`},continuationToken:a})},async clear(){return await r.runtime.dispatchContinuation({command:{kind:`clear`},continuationToken:a})},async reset(e){return await r.runtime.dispatchContinuation({command:{kind:`reset`,reason:e?.reason},continuationToken:a})},async resolveSession(){let t=await r.runtime.resolveContinuation(a);return t===void 0?void 0:createSession(t.sessionId,r.runtime,i)}}}function createChannelAddressFn(e){return t=>createChannelAddress({...e,continuationToken:t})}export{createChannelAddress,createChannelAddressFn};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { UserContent } from "ai";
|
|
2
|
+
import type { ChannelAdapter } from "#channel/adapter.js";
|
|
3
|
+
import { type ChannelAddressDeliveryOptions } from "#channel/channel-address.js";
|
|
4
|
+
import type { SendPayload } from "#channel/routes.js";
|
|
5
|
+
import type { Session } from "#channel/session.js";
|
|
6
|
+
import type { CancelTurnResult, ClearSessionResult, CompactSessionResult, ResetSessionResult, Runtime, SessionAuthContext, SessionCallback } from "#channel/types.js";
|
|
7
|
+
import type { InputResponse } from "#runtime/input/types.js";
|
|
8
|
+
import type { JsonObject } from "#shared/json.js";
|
|
9
|
+
import type { RunMode } from "#shared/run-mode.js";
|
|
10
|
+
interface BaseChannelSendOptions {
|
|
11
|
+
readonly auth: SessionAuthContext | null;
|
|
12
|
+
readonly callback?: SessionCallback;
|
|
13
|
+
readonly context?: readonly string[];
|
|
14
|
+
readonly initiatorAuth?: SessionAuthContext | null;
|
|
15
|
+
readonly mode?: RunMode;
|
|
16
|
+
readonly outputSchema?: JsonObject;
|
|
17
|
+
readonly title?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Options for sending a message from a channel-local continuation address. */
|
|
20
|
+
export type ChannelSendOptions<TState = undefined> = [TState] extends [undefined] ? BaseChannelSendOptions : BaseChannelSendOptions & {
|
|
21
|
+
readonly state: TState;
|
|
22
|
+
};
|
|
23
|
+
interface BaseChannelRespondOptions {
|
|
24
|
+
readonly auth: SessionAuthContext | null;
|
|
25
|
+
readonly context?: readonly string[];
|
|
26
|
+
readonly outputSchema?: JsonObject;
|
|
27
|
+
}
|
|
28
|
+
/** Options for answering pending input requests at an existing continuation address. */
|
|
29
|
+
export type ChannelRespondOptions = BaseChannelRespondOptions;
|
|
30
|
+
/** Dynamic handle for whichever session currently owns one channel-local address. */
|
|
31
|
+
export interface ChannelSource<TState = undefined> {
|
|
32
|
+
/** Starts or resumes a turn with a user message. May create a session. */
|
|
33
|
+
send(message: string | UserContent, options: ChannelSendOptions<TState>): Promise<Session>;
|
|
34
|
+
/** Answers pending input requests. Never creates a session. */
|
|
35
|
+
respond(inputResponses: readonly InputResponse[], options: ChannelRespondOptions): Promise<Session>;
|
|
36
|
+
/** Cooperatively cancels the active turn without creating a session. */
|
|
37
|
+
cancel(options?: {
|
|
38
|
+
readonly turnId?: string;
|
|
39
|
+
}): Promise<CancelTurnResult>;
|
|
40
|
+
/** Queues context compaction without creating a session. */
|
|
41
|
+
compact(): Promise<CompactSessionResult>;
|
|
42
|
+
/** Clears model-message history without creating a session. */
|
|
43
|
+
clear(): Promise<ClearSessionResult>;
|
|
44
|
+
/** Retires the current owner without creating a replacement. */
|
|
45
|
+
reset(options?: {
|
|
46
|
+
readonly reason?: string;
|
|
47
|
+
}): Promise<ResetSessionResult>;
|
|
48
|
+
}
|
|
49
|
+
/** Binds a raw channel-local continuation address to its current-owner operations. */
|
|
50
|
+
export type ChannelFrom<TState = undefined> = (address: string) => ChannelSource<TState>;
|
|
51
|
+
/** Snapshots the session currently owning a channel-local continuation address. */
|
|
52
|
+
export type ChannelResolveSession = (address: string) => Promise<Session | undefined>;
|
|
53
|
+
/** Continuation operations passed to an authored channel's proactive `receive` hook. */
|
|
54
|
+
export interface ChannelReceiveContext<TState = undefined> {
|
|
55
|
+
readonly from: ChannelFrom<TState>;
|
|
56
|
+
readonly resolveSession: ChannelResolveSession;
|
|
57
|
+
}
|
|
58
|
+
export declare const INTERNAL_CHANNEL_DELIVER: unique symbol;
|
|
59
|
+
/** @internal Permissive transport delivery retained below public authoring surfaces. */
|
|
60
|
+
export interface InternalChannelSource<TState = undefined> extends ChannelSource<TState> {
|
|
61
|
+
[INTERNAL_CHANNEL_DELIVER](payload: SendPayload, options: ChannelAddressDeliveryOptions<TState>): Promise<Session>;
|
|
62
|
+
}
|
|
63
|
+
/** Creates request-scoped channel operations backed by continuation dispatch. */
|
|
64
|
+
export declare function createChannelOperations<TState = undefined>(input: {
|
|
65
|
+
readonly adapter: ChannelAdapter<any>;
|
|
66
|
+
readonly channelName: string;
|
|
67
|
+
readonly metadata?: {
|
|
68
|
+
readonly requestId?: string;
|
|
69
|
+
};
|
|
70
|
+
readonly runtime: Runtime;
|
|
71
|
+
}): ChannelReceiveContext<TState>;
|
|
72
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createChannelAddressFn}from"#channel/channel-address.js";const INTERNAL_CHANNEL_DELIVER=Symbol(`eve.internal.channel-deliver`);function createChannelOperations(n){let r=createChannelAddressFn(n);return{from(e){let n=r(e);return{async send(e,t){return await n.deliver({context:t.context,message:e,outputSchema:t.outputSchema},t)},async respond(e,t){if(e.length===0)throw Error(`respond() requires at least one input response.`);return await n.deliver({context:t.context,inputResponses:e,outputSchema:t.outputSchema},t)},async cancel(e){return await n.cancel(e)},async compact(){return await n.compact()},async clear(){return await n.clear()},async reset(e){return await n.reset(e)},async[INTERNAL_CHANNEL_DELIVER](e,t){return await n.deliver(e,t)}}},async resolveSession(e){return await r(e).resolveSession()}}}export{INTERNAL_CHANNEL_DELIVER,createChannelOperations};
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import type { ChannelAdapter } from "#channel/adapter.js";
|
|
2
|
+
import type { UserContent } from "ai";
|
|
3
|
+
import type { ChannelReceiveContext } from "#channel/channel-operations.js";
|
|
2
4
|
import type { NormalizedChannelCorsOptions } from "#channel/cors.js";
|
|
3
|
-
import type {
|
|
5
|
+
import type { TypedReceiveTarget } from "#channel/receive-target.js";
|
|
6
|
+
import type { RouteDefinition } from "#channel/routes.js";
|
|
4
7
|
import type { Session } from "#channel/session.js";
|
|
5
8
|
import type { SessionAuthContext } from "#channel/types.js";
|
|
6
9
|
export declare const CHANNEL_SENTINEL: "eve:channel";
|
|
7
|
-
|
|
10
|
+
/** Structural identity shared by public authored channels and compiled channels. */
|
|
11
|
+
export interface ChannelReference<TReceiveTarget = Record<string, unknown>> extends TypedReceiveTarget<TReceiveTarget> {
|
|
8
12
|
readonly __kind: typeof CHANNEL_SENTINEL;
|
|
13
|
+
}
|
|
14
|
+
export interface CompiledChannel<TState = undefined, TReceiveTarget = Record<string, unknown>, TMetadata extends Record<string, unknown> = Record<string, unknown>> extends ChannelReference<TReceiveTarget> {
|
|
9
15
|
readonly routes: readonly RouteDefinition<TState>[];
|
|
10
16
|
readonly adapter: ChannelAdapter<any>;
|
|
11
17
|
readonly cors?: NormalizedChannelCorsOptions;
|
|
12
18
|
readonly __metadata?: TMetadata;
|
|
13
19
|
readonly receive?: (input: {
|
|
14
|
-
readonly message: string;
|
|
20
|
+
readonly message: string | UserContent;
|
|
15
21
|
readonly target: Readonly<TReceiveTarget>;
|
|
16
22
|
readonly auth: SessionAuthContext | null;
|
|
17
|
-
},
|
|
18
|
-
send: SendFn<TState>;
|
|
19
|
-
}) => Promise<Session>;
|
|
23
|
+
}, ctx: ChannelReceiveContext<TState>) => Promise<Session>;
|
|
20
24
|
}
|
|
21
25
|
export declare function isCompiledChannel(value: unknown): value is CompiledChannel;
|
|
22
26
|
export declare function getChannelInstrumentationKind(value: unknown): string | undefined;
|
|
@@ -1,28 +1,22 @@
|
|
|
1
1
|
import type { UserContent } from "ai";
|
|
2
2
|
import type { ChannelAdapter } from "#channel/adapter.js";
|
|
3
|
-
import { type CompiledChannel } from "#channel/compiled-channel.js";
|
|
3
|
+
import { type ChannelReference, type CompiledChannel } from "#channel/compiled-channel.js";
|
|
4
4
|
import type { InferReceiveTarget } from "#channel/receive-target.js";
|
|
5
5
|
import type { Session } from "#channel/session.js";
|
|
6
6
|
import type { Runtime, SessionAuthContext } from "#channel/types.js";
|
|
7
7
|
import type { ResolvedChannelDefinition } from "#runtime/types.js";
|
|
8
8
|
/**
|
|
9
|
-
* Options
|
|
10
|
-
* argument of a channel's authored `receive(input, { send })` hook —
|
|
11
|
-
* the runtime constructs `send` internally so route-handler callers
|
|
12
|
-
* only supply the platform target, payload, and auth.
|
|
9
|
+
* Options for sending a message to a channel selected with `ctx.to(...)`.
|
|
13
10
|
*/
|
|
14
|
-
export interface
|
|
15
|
-
readonly message: string | UserContent;
|
|
16
|
-
readonly target: TTarget;
|
|
11
|
+
export interface CrossChannelSendOptions {
|
|
17
12
|
readonly auth: SessionAuthContext | null;
|
|
18
13
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export type CrossChannelReceiveFn = <TChannel>(channel: TChannel, options: CrossChannelReceiveOptions<InferReceiveTarget<TChannel>>) => Promise<Session>;
|
|
14
|
+
/** Message delivery bound to one channel-specific proactive target. */
|
|
15
|
+
export interface CrossChannelTargetHandle {
|
|
16
|
+
send(message: string | UserContent, options: CrossChannelSendOptions): Promise<Session>;
|
|
17
|
+
}
|
|
18
|
+
/** Selects another authored channel and one of its proactive targets. */
|
|
19
|
+
export type CrossChannelToFn = <TChannel extends ChannelReference>(channel: TChannel, target: InferReceiveTarget<TChannel>) => CrossChannelTargetHandle;
|
|
26
20
|
/**
|
|
27
21
|
* Channel record consumed by the receiver — keeps the public-facing
|
|
28
22
|
* `definition` reference so callers can identify a target by value
|
|
@@ -43,17 +37,14 @@ export interface CrossChannelTarget {
|
|
|
43
37
|
*/
|
|
44
38
|
export declare function toCrossChannelTargets(channels: readonly ResolvedChannelDefinition[]): readonly CrossChannelTarget[];
|
|
45
39
|
/**
|
|
46
|
-
* Builds the `
|
|
47
|
-
* closure resolves the target channel by reference identity against
|
|
48
|
-
* the request-scoped channel bundle, then delegates to the target's
|
|
49
|
-
* authored `receive` hook with a per-target `send` factory.
|
|
40
|
+
* Builds the `ctx.to(channel, target)` closure used by route and schedule handlers.
|
|
50
41
|
*/
|
|
51
|
-
export declare function
|
|
42
|
+
export declare function createCrossChannelToFn(runtime: Runtime, channels: readonly CrossChannelTarget[]): CrossChannelToFn;
|
|
52
43
|
interface InvokeChannelReceiveInput {
|
|
53
44
|
readonly runtime: Runtime;
|
|
54
45
|
readonly target: Pick<CrossChannelTarget, "name" | "receive" | "adapter">;
|
|
55
46
|
readonly input: {
|
|
56
|
-
readonly message: string;
|
|
47
|
+
readonly message: string | UserContent;
|
|
57
48
|
readonly target: Readonly<Record<string, unknown>>;
|
|
58
49
|
readonly auth: SessionAuthContext | null;
|
|
59
50
|
};
|
|
@@ -61,10 +52,7 @@ interface InvokeChannelReceiveInput {
|
|
|
61
52
|
readonly describeMissingAdapter: () => string;
|
|
62
53
|
}
|
|
63
54
|
/**
|
|
64
|
-
* Shared `receive(input,
|
|
65
|
-
* handler cross-channel surface and the schedule dispatcher. Owns the
|
|
66
|
-
* receive/adapter precondition checks and the per-target `send`
|
|
67
|
-
* factory so both call sites stay byte-identical.
|
|
55
|
+
* Shared authored `receive(input, ctx)` invocation used by route and schedule delivery.
|
|
68
56
|
*/
|
|
69
57
|
export declare function invokeChannelReceive(args: InvokeChannelReceiveInput): Promise<Session>;
|
|
70
58
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)}export{
|
|
1
|
+
import{createChannelOperations}from"#channel/channel-operations.js";import{isCompiledChannel}from"#channel/compiled-channel.js";function toCrossChannelTargets(e){return e.flatMap(e=>e.definition===void 0?[]:[{name:e.name,definition:e.definition,receive:e.receive,adapter:e.adapter}])}function createCrossChannelToFn(e,t){return(n,r)=>{let i=resolveTargetByReference(n,t);return{async send(t,n){return await invokeChannelReceive({runtime:e,target:i,input:{message:t,target:r,auth:n.auth},describeMissingReceive:()=>`ctx.to(): channel "${i.name}" does not implement receive(). Declare a receive hook on the channel to accept cross-channel sessions.`,describeMissingAdapter:()=>`ctx.to(): channel "${i.name}" has no adapter — cannot build ctx.from().`})}}}}async function invokeChannelReceive(t){if(!t.target.receive)throw Error(t.describeMissingReceive());if(!t.target.adapter)throw Error(t.describeMissingAdapter());let n=createChannelOperations({adapter:t.target.adapter,channelName:t.target.name,runtime:t.runtime});return await t.target.receive(t.input,n)}function resolveTargetByReference(e,t){for(let n of t)if(n.definition===e)return n;let n=resolveTargetByRouteFingerprint(e,t);if(n!==null)return n;throw Error(`ctx.to(): the channel passed as the first argument is not registered in this agent's channels/. Import the channel module's default export from agent/channels/<name>.ts and pass that value.`)}function resolveTargetByRouteFingerprint(e,n){if(!isCompiledChannel(e))return null;let r=createRouteFingerprint(e);if(r===null)return null;let i=new Map;for(let e of n)createRouteFingerprint(e.definition)===r&&i.set(e.name,e);if(i.size===1)return[...i.values()][0];if(i.size>1)throw Error(`ctx.to(): the channel passed as the first argument matches multiple registered channels by route shape. Import a channel with a unique route set from agent/channels/<name>.ts before passing it to ctx.to().`);return null}function createRouteFingerprint(e){return e.routes.length===0?null:e.routes.map(e=>`${e.method.toUpperCase()} ${e.path}`).sort().join(`
|
|
2
|
+
`)}export{createCrossChannelToFn,invokeChannelReceive,toCrossChannelTargets};
|
|
@@ -2,8 +2,7 @@ declare const receiveTargetMarker: unique symbol;
|
|
|
2
2
|
/**
|
|
3
3
|
* Structural marker that channel factories (e.g. `slackChannel`,
|
|
4
4
|
* `twilioChannel`) add to declare the target type their `receive()` accepts.
|
|
5
|
-
* `
|
|
6
|
-
* `args.receive(channel, ...)` read this marker to infer typed targets
|
|
5
|
+
* `ctx.to(channel, target)` helpers read this marker to infer typed targets
|
|
7
6
|
* from a plain channel import.
|
|
8
7
|
*/
|
|
9
8
|
export interface TypedReceiveTarget<TTarget = Record<string, unknown>> {
|