UNPKG

eve

Version:

Filesystem-first framework for durable backend AI agents that run anywhere.

157 lines (113 loc) 4.89 kB
--- title: "Messages" description: "Send text, full turn payloads, client context, attachments, and HITL responses with eve/client." --- `ClientSession` sends one turn at a time. A fresh session starts on the first send; later sends continue the same conversation as long as the previous turn left the session waiting. ## Send text Pass a string to `send()` for plain text: ```ts import { Client } from "eve/client"; const client = new Client({ host: "http://127.0.0.1:3000" }); const session = client.session(); const response = await session.send("What is the weather in Brooklyn?"); // Metadata is available as soon as the POST succeeds. console.log(response.sessionId, response.continuationToken); const result = await response.result(); console.log(result.status, result.message); ``` `response.result()` consumes the event stream and returns a `MessageResult`: | Field | Meaning | | ----------- | ------------------------------------------------------------------------------ | | `message` | Final assistant text for the turn, when one completed. | | `status` | `"waiting"`, `"completed"`, or `"failed"`. | | `events` | All stream events observed during the turn. | | `sessionId` | Session ID for streaming and inspection. | | `data` | Structured output when the turn requested an [output schema](./output-schema). | When the stream includes `session.failed`, the turn returns `status: "failed"` rather than throwing. Transport and route errors throw `ClientError`. ## Send a full turn payload Use `send()` when you need more than plain text: ```ts const response = await session.send({ message: "What should I do on this screen?", clientContext: { route: "/billing", plan: "pro", seatsUsed: 4, }, }); await response.result(); ``` `clientContext` is one-turn context for the next model call. Strings become user-role context messages, arrays of strings become multiple context messages, and objects are JSON-serialized into one context message. It isn't persisted to durable session history and doesn't dispatch a turn by itself. ## Send attachments `send()` accepts AI SDK `UserContent`, so a message can mix text and file parts: ```ts const response = await session.send({ message: [ { type: "text", text: "Summarize this report." }, { type: "file", data: reportDataUrl, mediaType: "application/pdf", filename: "report.pdf", }, ], }); await response.result(); ``` For local files, read the file and send a base64 `data:` URL: ```ts import { readFile } from "node:fs/promises"; const bytes = await readFile("report.pdf"); const reportDataUrl = `data:application/pdf;base64,${bytes.toString("base64")}`; const response = await session.send({ message: [ { type: "text", text: "Summarize this report." }, { type: "file", data: reportDataUrl, mediaType: "application/pdf", filename: "report.pdf", }, ], }); await response.result(); ``` The stream confirms the turn with `message.received`. Its `data.message` remains the flattened summary for compatibility, and `data.parts` contains structured text and file metadata for clients that render attachments. File parts never include raw bytes or internal sandbox paths. ## Answer human input requests Tools can pause for approval or ask the user a question. The stream emits `input.requested` with one or more requests. Reply through the same session with `inputResponses`: ```ts import type { InputRequest } from "eve/client"; let pendingRequests: readonly InputRequest[] = []; const response = await session.send("Run the deployment checks."); for await (const event of response) { if (event.type === "input.requested") { pendingRequests = event.data.requests; } } const resumed = await session.send({ inputResponses: pendingRequests.map((request) => ({ requestId: request.requestId, optionId: "approve", })), }); await resumed.result(); ``` You can send `message`, `inputResponses`, and `clientContext` together when the resumed turn needs both a human answer and follow-up text. ## Single-use responses `MessageResponse` is single-use. Either aggregate it: ```ts const result = await response.result(); ``` Or stream it: ```ts for await (const event of response) { console.log(event.type); } ``` Don't do both on the same response. Once the stream is consumed, the `ClientSession` advances its cursor for the next turn. ## What to read next - [Continuations](./continuations): how the session cursor advances - [Streaming](./streaming): handle events live instead of using `result()` - [Tools](../../tools): configure approvals and question prompts