eve 0.45.0 → 0.45.2
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 +21 -0
- package/dist/src/chunks/{use-eve-agent-OtHRoxIS.js → use-eve-agent-BH7Z6SDu.js} +13 -1
- package/dist/src/chunks/{use-eve-agent-C46Kan_I.js → use-eve-agent-DI2j5XK8.js} +13 -1
- package/dist/src/cli/commands/integration-connect.d.ts +2 -0
- package/dist/src/cli/commands/integration-connect.js +1 -1
- package/dist/src/cli/commands/register-integration-commands.js +1 -1
- package/dist/src/client/agent-info-schema.d.ts +191 -2
- package/dist/src/client/agent-info-schema.js +1 -1
- package/dist/src/client/types.d.ts +1 -1
- package/dist/src/compiled/.vendor-stamp.json +2 -1
- package/dist/src/compiled/@vercel/blob/client.d.ts +487 -0
- package/dist/src/compiled/@vercel/blob/create-folder-BM6BTlko.d.ts +471 -0
- package/dist/src/compiled/@vercel/blob/index.d.ts +573 -0
- package/dist/src/compiled/@vercel/blob/index.js +43 -0
- package/dist/src/compiled/@vercel/blob/license.md +201 -0
- package/dist/src/compiler/extension-compatibility.d.ts +4 -4
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/load-binding-namespace.js +1 -1
- package/dist/src/compiler/manifest.d.ts +10 -0
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/model-catalog.d.ts +1 -1
- package/dist/src/compiler/model-catalog.js +1 -1
- package/dist/src/compiler/module-map.js +1 -1
- package/dist/src/compiler/normalize-helpers.d.ts +2 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/compiler/normalize-memory.d.ts +5 -0
- package/dist/src/compiler/normalize-memory.js +1 -0
- package/dist/src/compiler/normalize-tool.js +1 -1
- package/dist/src/compiler/project-sources.d.ts +3 -4
- package/dist/src/compiler/project-sources.js +1 -1
- package/dist/src/compiler/source-graph.d.ts +2 -0
- package/dist/src/compiler/source-graph.js +1 -1
- package/dist/src/compiler/validate-artifact.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.d.ts +8 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +25 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/context/memory-event-lifecycle.d.ts +13 -0
- package/dist/src/context/memory-event-lifecycle.js +1 -0
- package/dist/src/context/memory-lifecycle.d.ts +52 -0
- package/dist/src/context/memory-lifecycle.js +1 -0
- package/dist/src/context/memory-tools.d.ts +12 -0
- package/dist/src/context/memory-tools.js +1 -0
- package/dist/src/discover/discover-agent.js +1 -1
- package/dist/src/discover/discover-subagent.js +1 -1
- package/dist/src/discover/extensions.d.ts +6 -0
- package/dist/src/discover/extensions.js +1 -1
- package/dist/src/discover/filesystem.d.ts +2 -2
- package/dist/src/discover/filesystem.js +1 -1
- package/dist/src/discover/manifest.d.ts +6 -1
- package/dist/src/discover/manifest.js +1 -1
- package/dist/src/discover/memory.d.ts +14 -0
- package/dist/src/discover/memory.js +1 -0
- package/dist/src/discover/project.js +1 -1
- package/dist/src/evals/cli/eval.js +1 -1
- package/dist/src/evals/target.js +1 -1
- package/dist/src/execution/history-view.d.ts +2 -2
- package/dist/src/execution/history-view.js +1 -1
- package/dist/src/execution/tools/connection-search.js +2 -2
- package/dist/src/execution/workflow-steps.d.ts +1 -3
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/framework/sources/modules/memory-wrapper.d.ts +2 -0
- package/dist/src/framework/sources/modules/memory-wrapper.js +1 -0
- package/dist/src/framework/sources/registry.d.ts +1 -0
- package/dist/src/framework/sources/registry.js +1 -1
- package/dist/src/harness/emission.d.ts +1 -1
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/hitl/approval-prompt.d.ts +2 -0
- package/dist/src/harness/hitl/approval-prompt.js +3 -2
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +4 -2
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/memory.d.ts +2 -0
- package/dist/src/internal/authored-definition/memory.js +1 -0
- package/dist/src/internal/authored-definition/schema-backed.d.ts +1 -0
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/internal/authored-module-map-loader.js +1 -1
- package/dist/src/internal/dynamic-tool-rebind.d.ts +3 -0
- package/dist/src/internal/dynamic-tool-rebind.js +1 -0
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
- package/dist/src/internal/nitro/routes/index.js +1 -0
- package/dist/src/internal/programmatic-source-loader.d.ts +1 -0
- package/dist/src/internal/programmatic-source-loader.js +1 -1
- package/dist/src/internal/workflow/development-world-server.js +1 -1
- package/dist/src/internal/workflow/local-world-delivery-timeouts.d.ts +7 -0
- package/dist/src/internal/workflow/local-world-delivery-timeouts.js +1 -0
- package/dist/src/public/memory/file/backend.d.ts +37 -0
- package/dist/src/public/memory/file/backend.js +1 -0
- package/dist/src/public/memory/file/backends/default.d.ts +7 -0
- package/dist/src/public/memory/file/backends/default.js +1 -0
- package/dist/src/public/memory/file/backends/in-memory.d.ts +6 -0
- package/dist/src/public/memory/file/backends/in-memory.js +1 -0
- package/dist/src/public/memory/file/backends/lazy.d.ts +3 -0
- package/dist/src/public/memory/file/backends/lazy.js +1 -0
- package/dist/src/public/memory/file/backends/vercel-blob.d.ts +14 -0
- package/dist/src/public/memory/file/backends/vercel-blob.js +1 -0
- package/dist/src/public/memory/file/index.d.ts +3 -0
- package/dist/src/public/memory/file/index.js +1 -0
- package/dist/src/public/memory/file/provider.d.ts +14 -0
- package/dist/src/public/memory/file/provider.js +6 -0
- package/dist/src/public/memory/file/vercel.d.ts +1 -0
- package/dist/src/public/memory/file/vercel.js +1 -0
- package/dist/src/public/memory/index.d.ts +117 -0
- package/dist/src/public/memory/index.js +1 -0
- package/dist/src/public/memory/scope.d.ts +2 -0
- package/dist/src/public/memory/scope.js +1 -0
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/runtime/resolve-dynamic-tool.d.ts +1 -0
- package/dist/src/runtime/resolve-dynamic-tool.js +1 -1
- package/dist/src/runtime/resolve-memory.d.ts +4 -0
- package/dist/src/runtime/resolve-memory.js +1 -0
- package/dist/src/runtime/types.d.ts +7 -0
- package/dist/src/setup/connection-connector.d.ts +2 -0
- package/dist/src/setup/connection-connector.js +1 -1
- package/dist/src/setup/integrations/linq/connect.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +2 -0
- package/dist/src/setup/scaffold/create/web-template.js +28 -0
- package/dist/src/shared/memory-definition.d.ts +2 -0
- package/dist/src/shared/memory-definition.js +1 -0
- package/dist/src/shared/memory-state.d.ts +55 -0
- package/dist/src/shared/memory-state.js +1 -0
- package/dist/src/svelte/index.js +1 -1
- 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.js +1 -1
- package/docs/channels/eve.mdx +1 -1
- package/docs/concepts/context-control.md +7 -0
- package/docs/concepts/default-harness.md +8 -0
- package/docs/concepts/sessions-runs-and-streaming.md +3 -3
- package/docs/concepts/state.md +8 -1
- package/docs/extensions.md +6 -2
- package/docs/guides/client/overview.mdx +2 -2
- package/docs/guides/dynamic-capabilities.md +3 -2
- package/docs/memory.md +320 -0
- package/docs/meta.json +1 -0
- package/docs/patterns/multi-tenant-memory.md +108 -136
- package/docs/reference/typescript-api.md +5 -0
- package/package.json +22 -1
package/dist/src/vue/index.js
CHANGED
package/docs/channels/eve.mdx
CHANGED
|
@@ -34,7 +34,7 @@ The default eve channel inspects the agent, creates sessions, accepts callbacks
|
|
|
34
34
|
|
|
35
35
|
The session routes use only durable session IDs. Create a session explicitly, then put its returned ID in every follow-up, control, and stream path.
|
|
36
36
|
|
|
37
|
-
`GET /eve/v1/health` is public and returns `{ ok: true, status: "ready", workflowId: string }`. `GET /eve/v1/info` uses the channel's auth policy and returns agent-info version
|
|
37
|
+
`GET /eve/v1/health` is public and returns `{ ok: true, status: "ready", workflowId: string }`. `GET /eve/v1/info` uses the channel's auth policy and returns agent-info version 4. The TypeScript client validates both successful payloads: malformed health JSON throws `HealthResponseError`, malformed inspection JSON throws `AgentInfoResponseError`, and a non-success response from either route throws `ClientError`.
|
|
38
38
|
|
|
39
39
|
### Start and continue a session
|
|
40
40
|
|
|
@@ -16,6 +16,7 @@ Control context by putting information in the narrowest surface that needs it. K
|
|
|
16
16
|
| Files or command execution | The [sandbox workspace](../sandbox) | A workspace hint, then files and command output the model requests through tools |
|
|
17
17
|
| A specialist with a separate prompt and capabilities | A [subagent](../subagents) | Only the subagent's final result in the parent context |
|
|
18
18
|
| Instructions or capabilities that vary by caller | A [dynamic capability](../guides/dynamic-capabilities) | The values resolved for the active session |
|
|
19
|
+
| Scoped context retrieved from cross-session storage | [Memory](../memory) | Attributed user-role messages recalled before the current delivery |
|
|
19
20
|
|
|
20
21
|
## Base identity with `instructions.md`
|
|
21
22
|
|
|
@@ -59,6 +60,11 @@ See [Dynamic capabilities](../guides/dynamic-capabilities) for the resolver API,
|
|
|
59
60
|
|
|
60
61
|
User-role instructions follow the normal history lifecycle. Compaction can summarize them, and clear removes them without rerunning their static definitions or dynamic resolvers. System-role instructions remain outside history and continue to apply after either operation.
|
|
61
62
|
|
|
63
|
+
Recalled memory also uses user-role messages, but eve keeps their attribution
|
|
64
|
+
separate. Compaction excludes them from the summary, preserves their canonical
|
|
65
|
+
records, and recalls again after the checkpoint. Clear removes those session
|
|
66
|
+
records without deleting the provider's external data.
|
|
67
|
+
|
|
62
68
|
## What to read next
|
|
63
69
|
|
|
64
70
|
- [Instructions](../instructions): author the always-on system prompt.
|
|
@@ -66,3 +72,4 @@ User-role instructions follow the normal history lifecycle. Compaction can summa
|
|
|
66
72
|
- [Sandbox](../sandbox): give the model files and command execution.
|
|
67
73
|
- [Subagents](../subagents): isolate specialist work.
|
|
68
74
|
- [Dynamic capabilities](../guides/dynamic-capabilities): vary context and capabilities by session.
|
|
75
|
+
- [Memory](../memory): retrieve scoped context from storage that outlives a session.
|
|
@@ -20,6 +20,11 @@ export default defineAgent({
|
|
|
20
20
|
|
|
21
21
|
Compaction also preserves the framework's own tool state automatically. It resets read-before-write tracking (so a write afterward re-reads the file whose read evidence was summarized away) and re-injects the active todo list, so the model keeps its task list across the summary. There is no per-tool hook to configure.
|
|
22
22
|
|
|
23
|
+
First-class [memory](../memory) participates in a separate lifecycle. eve asks
|
|
24
|
+
providers to capture before compaction, excludes attributed recalled records
|
|
25
|
+
from the summarizer, keeps their canonical latest values, and recalls again
|
|
26
|
+
after the checkpoint.
|
|
27
|
+
|
|
23
28
|
Clients and channels can also request compaction between turns. Call
|
|
24
29
|
`ClientSession.compact()`, a channel route's `compact(address)`, or
|
|
25
30
|
`attachSession(sessionId).compact()`. The request does not append a user message;
|
|
@@ -30,6 +35,8 @@ events as automatic compaction, followed by `session.waiting`.
|
|
|
30
35
|
To discard model-message history instead of summarizing it, call the corresponding
|
|
31
36
|
`clear()` method on any of those handles. Clearing preserves the session identity,
|
|
32
37
|
system prompt, configured tools and skills, durable state, limits, and sandbox.
|
|
38
|
+
It removes recalled memory records and framework memory bookkeeping, but it
|
|
39
|
+
does not delete data from a memory provider's external store.
|
|
33
40
|
Its stream boundary is `context.cleared` followed by `session.waiting`.
|
|
34
41
|
|
|
35
42
|
## What to read next
|
|
@@ -37,3 +44,4 @@ Its stream boundary is `context.cleared` followed by `session.waiting`.
|
|
|
37
44
|
- [Built-in tools](./built-in-tools): review the default and opt-in framework tools and configure the model-facing tool set
|
|
38
45
|
- [Execution model and durability](./execution-model-and-durability): understand how turns checkpoint and resume
|
|
39
46
|
- [Context control](./context-control): choose what the model sees and when
|
|
47
|
+
- [Memory](../memory): connect scoped, cross-session context to the harness lifecycle
|
|
@@ -201,9 +201,9 @@ curl -X POST http://127.0.0.1:2000/eve/v1/session/<sessionId>/reset \
|
|
|
201
201
|
-d '{"reason":"Start over"}'
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
Compaction summarizes context without adding a user message. User-role instructions are ordinary history and may be represented by the summary; system-role instructions remain outside it. If a turn is active, eve queues the request until that turn settles. A successful compaction emits `compaction.requested` and `compaction.completed`, followed by `session.waiting`; if summarization fails, the session returns to waiting with its previous history.
|
|
204
|
+
Compaction summarizes context without adding a user message. User-role instructions are ordinary history and may be represented by the summary; system-role instructions remain outside it. Attributed [memory](../memory) records are excluded from the summary, canonicalized, and recalled again after the checkpoint. If a turn is active, eve queues the request until that turn settles. A successful compaction emits `compaction.requested` and `compaction.completed`, followed by `session.waiting`; if summarization fails before a checkpoint, the session returns to waiting with its previous history.
|
|
205
205
|
|
|
206
|
-
Clear removes model-message history in place, including static and dynamic user-role instructions, while preserving the session identity, system-role instructions, tools, skills, durable state, limits, and sandbox. It does not rerun instruction definitions or resolvers. It emits `context.cleared` followed by `session.waiting`.
|
|
206
|
+
Clear removes model-message history in place, including static and dynamic user-role instructions and recalled memory records, while preserving the session identity, system-role instructions, tools, skills, application-defined durable state, limits, and sandbox. It clears framework memory locks and replay bookkeeping but does not delete data from a provider's external store. It does not rerun instruction definitions or resolvers. It emits `context.cleared` followed by `session.waiting`.
|
|
207
207
|
|
|
208
208
|
Reset terminally retires the exact session ID. A reset ID never becomes a new session; create another session explicitly for a fresh conversation. Compact, clear, and reset return `"no_active_session"` when the target is already inactive.
|
|
209
209
|
|
|
@@ -244,7 +244,7 @@ Start with the [Client SDK](../guides/client/overview) guide. It covers basic us
|
|
|
244
244
|
|
|
245
245
|
## Inspect the agent over HTTP
|
|
246
246
|
|
|
247
|
-
`GET /eve/v1/info` returns agent-info version
|
|
247
|
+
`GET /eve/v1/info` returns agent-info version 4, a JSON inspection snapshot of the effective compiled agent. It reports the selected config; active tools, instructions, memory slots, skills, channels, schedules, sandbox, connections, hooks, and instrumentation with explicit source ownership; dynamic resolvers separately from their session-specific output; local and remote agents in separate collections; prepared built-in effects; and shadowed or disabled source diagnostics. Memory tool wrappers include their selected memory-source dependency. Channel routes appear in the same effective order used by the HTTP host. Static instructions remain an ordered array whose entries expose `content` and `role`.
|
|
248
248
|
|
|
249
249
|
The info route belongs to the selected `channels/eve.ts` source and uses its resolved auth policy. Without an authored replacement, eve selects the default channel source with Vercel OIDC, local development access, and the production placeholder. Replacing or disabling that source replaces or removes the info route too; no native fallback serves it.
|
|
250
250
|
|
package/docs/concepts/state.md
CHANGED
|
@@ -69,7 +69,13 @@ Every [subagent](../subagents) starts with its own fresh state, whether it's a b
|
|
|
69
69
|
|
|
70
70
|
## State vs. connection-side storage
|
|
71
71
|
|
|
72
|
-
`defineState` holds conversation-scoped working memory that lives and dies with
|
|
72
|
+
`defineState` holds conversation-scoped working memory that lives and dies with
|
|
73
|
+
the session, including counters, the current plan, and what the user has told
|
|
74
|
+
you this conversation. It is the agent's short-term memory, persisted durably
|
|
75
|
+
for the life of the session. For context that must outlive a session, connect a
|
|
76
|
+
first-class [memory provider](../memory) to your own application store. Use a
|
|
77
|
+
general [connection](../connections) instead when the data should be queried
|
|
78
|
+
only through explicit model tool calls rather than recalled automatically.
|
|
73
79
|
|
|
74
80
|
## What to read next
|
|
75
81
|
|
|
@@ -77,3 +83,4 @@ Every [subagent](../subagents) starts with its own fresh state, whether it's a b
|
|
|
77
83
|
- How step durability works → [Execution model & durability](../concepts/execution-model-and-durability)
|
|
78
84
|
- The `ctx` accessors available alongside state → [TypeScript API Reference](../reference/typescript-api)
|
|
79
85
|
- Tenant-scoped long-term memory in your own store → [Multi-tenant memory](../patterns/multi-tenant-memory)
|
|
86
|
+
- First-class recall, capture, and provider tools → [Memory](../memory)
|
package/docs/extensions.md
CHANGED
|
@@ -7,7 +7,7 @@ Extensions package eve tools, channels, connections, skills, schedules, subagent
|
|
|
7
7
|
|
|
8
8
|
Ready-made extensions can also be distributed through an eve integration registry. See [Add Integrations](./install-integrations) to discover and add one with `eve add`; this page explains how extension packages are authored, mounted, configured, and overridden.
|
|
9
9
|
|
|
10
|
-
This enables sharing many different capability sets. A browser extension might include several tools for navigating a site. A
|
|
10
|
+
This enables sharing many different capability sets. A browser extension might include several tools for navigating a site. A self-improving extension could pair hooks with dynamic instructions.
|
|
11
11
|
|
|
12
12
|
## Author: create an extension
|
|
13
13
|
|
|
@@ -43,7 +43,11 @@ Each listed slot accepts the same authored forms as its agent counterpart. Stati
|
|
|
43
43
|
|
|
44
44
|
Names come from paths, so call the tool `search`, not `crm_search`; the consumer's mount adds the `crm__` prefix. The same prefix applies to channel, schedule, and parent-visible subagent IDs, while channel route paths and schedule cron expressions stay unchanged. Keep shared code in `extension/lib/`.
|
|
45
45
|
|
|
46
|
-
The extension root cannot declare agent configuration,
|
|
46
|
+
The extension root cannot declare agent configuration, instrumentation,
|
|
47
|
+
[memory](./memory), a sandbox, or nested extensions. Those agent-level concerns
|
|
48
|
+
belong to the consuming application. A subagent contributed under
|
|
49
|
+
`extension/subagents/` owns its own agent configuration, memory, and sandbox
|
|
50
|
+
like any other [declared subagent](./subagents).
|
|
47
51
|
|
|
48
52
|
### Add configuration and contributions
|
|
49
53
|
|
|
@@ -34,14 +34,14 @@ The client requires the successful response to match `{ ok: true, status: "ready
|
|
|
34
34
|
|
|
35
35
|
## Inspect an agent
|
|
36
36
|
|
|
37
|
-
Use `info()` to inspect an agent. The client requires the complete agent-info version
|
|
37
|
+
Use `info()` to inspect an agent. The client requires the complete agent-info version 4 response before returning it:
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
40
|
const info = await client.info();
|
|
41
41
|
console.log(info.agent.name, info.agent.model.id);
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Version
|
|
44
|
+
Version 4 separates active static definitions from dynamic resolvers, includes binding-backed source ownership and composition history, reports first-class memory slots and their provider-tool wrapper dependencies, reports local and remote agents separately, and returns the exact compiled channel route order. A non-success response throws `ClientError`; invalid JSON, an earlier schema version, duplicate identities, inconsistent totals, or mismatched source provenance throws `AgentInfoResponseError`.
|
|
45
45
|
|
|
46
46
|
## Authentication
|
|
47
47
|
|
|
@@ -166,7 +166,7 @@ Write callback properties as inline function expressions, arrows, method shortha
|
|
|
166
166
|
|
|
167
167
|
Closure values must be JSON-serializable. Plain objects, arrays, strings, finite numbers, booleans, and `null` are supported; `undefined` object properties are omitted. Functions, class instances, `Date`, `Map`, symbols, non-finite numbers, and cyclic values fail resolution with the tool name and callback phase instead of being serialized lossily.
|
|
168
168
|
|
|
169
|
-
Call expressions such as `execute: makeExecutor()` are not transformed. Put the callback body directly in `defineTool()` inside an authored module; eve-provided factories may also supply pre-registered callbacks. eve rejects a dynamic tool if any present callback lacks durable metadata.
|
|
169
|
+
Call expressions such as `execute: makeExecutor()` are not transformed. Put the callback body directly in `defineTool()` inside an authored module; eve-provided factories, including [memory provider tools](../memory), may also supply pre-registered callbacks. eve rejects a dynamic tool if any present callback lacks durable metadata.
|
|
170
170
|
|
|
171
171
|
### Identity and redeploys
|
|
172
172
|
|
|
@@ -174,7 +174,7 @@ A parked call binds to its callback by **tool name and phase** — the same iden
|
|
|
174
174
|
|
|
175
175
|
- Editing a callback body (or anything else that does not change tool names) is safe: replaying a parked call runs the latest deployed code with the closure values snapshotted when the call was made.
|
|
176
176
|
- If a persisted callback has no registered implementation (fresh process after a crash, or after a redeploy), eve re-runs `session.started` resolvers once to rebind it, then replays.
|
|
177
|
-
- If the tool no longer exists under that name, replay fails closed with an explicit error instead of invoking something else.
|
|
177
|
+
- If the tool no longer exists under that name, replay fails closed with an explicit error instead of invoking something else. Ordinary turn-scoped and step-scoped tools are not rebound; a parked call to a missing one errors. Framework-provided resolvers such as memory provider-tool wrappers opt into the same generic missing-callback rebind while preserving their locked scope.
|
|
178
178
|
|
|
179
179
|
### Naming
|
|
180
180
|
|
|
@@ -312,3 +312,4 @@ Dynamic system content that changes frequently can reduce provider prompt-cache
|
|
|
312
312
|
- The built-in tools and how to override them → [Built-in tools](../concepts/built-in-tools)
|
|
313
313
|
- Authenticate a tool or connection to an external service → [Auth & route protection](./auth-and-route-protection)
|
|
314
314
|
- Durable per-session memory for resolvers to read → [State](../concepts/state)
|
|
315
|
+
- Cross-session recall and provider-generated tools → [Memory](../memory)
|
package/docs/memory.md
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Memory"
|
|
3
|
+
description: "Recall and capture scoped, cross-session context with built-in or custom eve memory providers."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Memory connects an agent to application-owned storage that can outlive one
|
|
7
|
+
session. A provider recalls relevant context before a turn, can capture the
|
|
8
|
+
settled conversation afterward, and can expose tools that operate on the same
|
|
9
|
+
locked scope.
|
|
10
|
+
|
|
11
|
+
eve owns the lifecycle and model-facing history. A provider owns storage,
|
|
12
|
+
retrieval, retention, and deletion. Use the built-in bounded file provider for
|
|
13
|
+
model-maintained facts, or implement a provider for application-specific
|
|
14
|
+
retrieval and capture.
|
|
15
|
+
|
|
16
|
+
## Use file memory
|
|
17
|
+
|
|
18
|
+
`fileMemory()` keeps one indexed document for each resolved scope and gives the
|
|
19
|
+
model `save_memory` and `remove_memory` tools. It recalls the document before
|
|
20
|
+
each turn and after compaction, but does not automatically extract facts from
|
|
21
|
+
the conversation.
|
|
22
|
+
|
|
23
|
+
```ts title="agent/memory/profile.ts"
|
|
24
|
+
import { defineMemory } from "eve/memory";
|
|
25
|
+
import { byPrincipal } from "eve/memory/scope";
|
|
26
|
+
import { fileMemory } from "eve/memory/file";
|
|
27
|
+
|
|
28
|
+
export default defineMemory({
|
|
29
|
+
description: "Remember stable facts and preferences about the caller.",
|
|
30
|
+
provider: fileMemory(),
|
|
31
|
+
scope: byPrincipal,
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The `profile` slot exposes `profile__save_memory` and
|
|
36
|
+
`profile__remove_memory`. Saved entries are normalized, assigned permanent
|
|
37
|
+
numeric indexes, and recalled as one stable keyed message. Removing an entry
|
|
38
|
+
replaces the previous recalled document at the next boundary, including when
|
|
39
|
+
the final entry is removed, so stale content does not remain in model context.
|
|
40
|
+
|
|
41
|
+
The provider rejects rather than truncates or evicts data. `maxCharacters`
|
|
42
|
+
defaults to 4,000 characters and caps the exact recalled message, including
|
|
43
|
+
its heading, removal guidance, indexes, separators, and saved text.
|
|
44
|
+
`save_memory` rejects an entry when the resulting message would exceed that
|
|
45
|
+
limit. Each normalized entry can contain up to 2,048 UTF-8 bytes, and the
|
|
46
|
+
stored document can contain up to 65,536 bytes:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
provider: fileMemory({ maxCharacters: 8_000 });
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Choose a file backend
|
|
53
|
+
|
|
54
|
+
With no `backend`, `fileMemory()` selects storage lazily:
|
|
55
|
+
|
|
56
|
+
| Environment | Backend |
|
|
57
|
+
| ----------------------------------------------------------------- | ---------------------------------------- |
|
|
58
|
+
| Vercel with Blob credentials (token, or attached store with OIDC) | Private Vercel Blob |
|
|
59
|
+
| Vercel without Blob configuration | Error asking you to attach a Blob store |
|
|
60
|
+
| `eve dev` | Shared process-local in-memory storage |
|
|
61
|
+
| Every other environment | Error asking you for an explicit backend |
|
|
62
|
+
|
|
63
|
+
`NODE_ENV=development` alone does not select in-memory storage, and a Blob
|
|
64
|
+
token outside Vercel does not select Blob. For tests, pass a fresh in-memory
|
|
65
|
+
backend explicitly:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { fileMemory, inMemory } from "eve/memory/file";
|
|
69
|
+
|
|
70
|
+
provider: fileMemory({ backend: inMemory() });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`inMemory()` loses its contents when its backend instance or process is
|
|
74
|
+
replaced. For another durable store, implement `MemoryDocumentBackend` from
|
|
75
|
+
`eve/memory/file`. Its `write()` method conditionally replaces the complete
|
|
76
|
+
document and must throw `MemoryDocumentConflictError` when `expectedVersion`
|
|
77
|
+
is stale. Use `vercelBlob()` from `eve/memory/file/vercel` when you want to
|
|
78
|
+
configure Vercel Blob credentials or an object prefix explicitly.
|
|
79
|
+
|
|
80
|
+
## Add a memory slot
|
|
81
|
+
|
|
82
|
+
Create `agent/memory.ts` for one slot named `memory`, or use
|
|
83
|
+
`agent/memory/<slot>.ts` for named slots. These forms are mutually exclusive.
|
|
84
|
+
|
|
85
|
+
```ts title="agent/memory/profile.ts"
|
|
86
|
+
import { defineMemory, type MemoryOperationContext } from "eve/memory";
|
|
87
|
+
import { byPrincipal } from "eve/memory/scope";
|
|
88
|
+
import { defineTool } from "eve/tools";
|
|
89
|
+
import { z } from "zod";
|
|
90
|
+
import { profileStore } from "../lib/profile-store";
|
|
91
|
+
|
|
92
|
+
async function recallProfile(ctx: MemoryOperationContext) {
|
|
93
|
+
const profile = await profileStore.get(ctx.memory.scope.key);
|
|
94
|
+
if (profile === null) return null;
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
messages: [{ id: "profile", content: JSON.stringify(profile) }],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export default defineMemory({
|
|
102
|
+
description: "Manage durable facts and preferences for the current caller.",
|
|
103
|
+
scope: byPrincipal,
|
|
104
|
+
provider: {
|
|
105
|
+
recall: {
|
|
106
|
+
"turn.started": recallProfile,
|
|
107
|
+
"compaction.completed": recallProfile,
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
capture: {
|
|
111
|
+
async "turn.completed"(ctx) {
|
|
112
|
+
await profileStore.observe(ctx.memory.scope.key, ctx.messages, {
|
|
113
|
+
operationId: ctx.operationId,
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
async tools(ctx) {
|
|
119
|
+
return {
|
|
120
|
+
save: defineTool({
|
|
121
|
+
description: "Save one durable profile fact.",
|
|
122
|
+
inputSchema: z.object({ key: z.string(), value: z.string() }),
|
|
123
|
+
async execute(input) {
|
|
124
|
+
await profileStore.put(ctx.memory.scope.key, input);
|
|
125
|
+
return { saved: true };
|
|
126
|
+
},
|
|
127
|
+
}),
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The filename is the slot name. The provider tool above is exposed as
|
|
135
|
+
`profile__save`; the slot description is prepended to the tool description.
|
|
136
|
+
Provider tools are ordinary `defineTool()` values, so schemas, approvals, and
|
|
137
|
+
`toModelOutput` work normally. Their callbacks remain replayable after a
|
|
138
|
+
process restart or deployment.
|
|
139
|
+
|
|
140
|
+
Use `defineMemoryProvider()` when several slots share one provider or when you
|
|
141
|
+
want its contract checked separately:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { defineMemoryProvider, type MemoryOperationContext } from "eve/memory";
|
|
145
|
+
|
|
146
|
+
async function recall(ctx: MemoryOperationContext) {
|
|
147
|
+
return await recallFromStore(ctx.memory.scope.key, ctx.messages);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export const provider = defineMemoryProvider({
|
|
151
|
+
recall: {
|
|
152
|
+
"turn.started": recall,
|
|
153
|
+
"compaction.completed": recall,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Choose a scope
|
|
159
|
+
|
|
160
|
+
`scope` decides who or what shares memory. Set it to a string or `null`, or use
|
|
161
|
+
a resolver that returns a string, a tuple of strings, or `null`. Resolve tenant
|
|
162
|
+
and caller identity from trusted authentication or channel metadata, never from
|
|
163
|
+
model input:
|
|
164
|
+
|
|
165
|
+
```ts title="agent/memory/account.ts"
|
|
166
|
+
import { defineMemory } from "eve/memory";
|
|
167
|
+
|
|
168
|
+
export default defineMemory({
|
|
169
|
+
scope: (ctx) => {
|
|
170
|
+
const caller = ctx.session.auth.current;
|
|
171
|
+
const tenantId = caller?.attributes.tenantId;
|
|
172
|
+
|
|
173
|
+
if (caller?.principalType !== "user" || typeof tenantId !== "string") {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return [tenantId, caller.principalId];
|
|
178
|
+
},
|
|
179
|
+
provider,
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Returning `null` disables the slot for that operation. eve does not call its
|
|
184
|
+
namespace resolver, provider, or tools, and it never falls back to a shared
|
|
185
|
+
scope. In `eve dev`, a diagnostic names the disabled slot and the resolver
|
|
186
|
+
that returned `null`, without logging the resolved value.
|
|
187
|
+
|
|
188
|
+
`byPrincipal` uses `auth.current`. It disables memory for anonymous and runtime
|
|
189
|
+
principals and returns the shared `local-dev` scope during local development.
|
|
190
|
+
Use a custom resolver when the boundary also needs a tenant, channel, or
|
|
191
|
+
conversation identifier.
|
|
192
|
+
|
|
193
|
+
eve validates the namespace and scope, then gives the provider:
|
|
194
|
+
|
|
195
|
+
- `memory.scope.key`: a versioned, opaque digest for storage lookup;
|
|
196
|
+
- `memory.scope.namespace`: the resolved namespace;
|
|
197
|
+
- `memory.scope.value`: the resolved string or tuple;
|
|
198
|
+
- `memory.slot`: the path-derived slot name.
|
|
199
|
+
|
|
200
|
+
Use `memory.scope.key` as the provider partition key. It preserves tuple
|
|
201
|
+
boundaries and does not persist raw scope components in eve's durable
|
|
202
|
+
attribution.
|
|
203
|
+
|
|
204
|
+
## Choose a namespace
|
|
205
|
+
|
|
206
|
+
The namespace separates an application's memory domains before scope is
|
|
207
|
+
applied. Omit `namespace` for `defaultNamespace`, which includes the graph
|
|
208
|
+
node and slot plus a deployment-aware identity:
|
|
209
|
+
|
|
210
|
+
- production and other Vercel environments use the project and environment;
|
|
211
|
+
- Preview also uses the branch or deployment identity;
|
|
212
|
+
- local development uses a digest of the application root, never the raw path.
|
|
213
|
+
|
|
214
|
+
Redeployments keep the same production namespace. Preview branches do not
|
|
215
|
+
share memory accidentally. Set a string or resolver for an explicit domain:
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
export default defineMemory({
|
|
219
|
+
namespace: "acme-support-v1",
|
|
220
|
+
scope: byPrincipal,
|
|
221
|
+
provider,
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
A custom namespace is complete; eve adds no hidden suffix. Returning `null`
|
|
226
|
+
disables the slot. Scope resolves first, so a disabled scope never invokes the
|
|
227
|
+
namespace resolver.
|
|
228
|
+
|
|
229
|
+
## Recall behavior
|
|
230
|
+
|
|
231
|
+
Register recall handlers under their lifecycle keys. `"turn.started"` is
|
|
232
|
+
required and runs before the model. `"compaction.completed"` is optional and
|
|
233
|
+
runs after a compaction checkpoint. A recall handler returns `{ messages }`,
|
|
234
|
+
`null`, or `undefined`. Each recalled item becomes an untrusted user-role
|
|
235
|
+
message; provider content is never promoted to system instructions.
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
return {
|
|
239
|
+
messages: [
|
|
240
|
+
{ id: "preferred-language", content: "The user prefers Spanish." },
|
|
241
|
+
{ content: "A relevant note without a stable identity." },
|
|
242
|
+
],
|
|
243
|
+
};
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Use stable `id` values for replaceable facts. A later item with the same ID in
|
|
247
|
+
the same slot, namespace, and scope supersedes the earlier value. An identical
|
|
248
|
+
value is a no-op. Items without IDs accumulate, even when their content is
|
|
249
|
+
identical. Omitting an earlier item from a later result does not delete it.
|
|
250
|
+
|
|
251
|
+
All active slots lock their scopes before any recall runs. They see the same
|
|
252
|
+
pre-recall history, and eve commits their validated results atomically. Each
|
|
253
|
+
call receives a stable `operationId`; use it as an idempotency key for writes
|
|
254
|
+
performed by capture handlers.
|
|
255
|
+
|
|
256
|
+
The default `visibility: "scope"` hides a slot's prior recalled records when
|
|
257
|
+
its scope changes. Set `visibility: "session"` only when those records are
|
|
258
|
+
safe to retain for the rest of the session across scope changes. Namespace
|
|
259
|
+
and slot boundaries still apply.
|
|
260
|
+
|
|
261
|
+
## Lifecycle and compaction
|
|
262
|
+
|
|
263
|
+
| Phase | Provider handler | Context |
|
|
264
|
+
| ---------------------- | --------------------------------- | ---------------------------------------------------------- |
|
|
265
|
+
| `turn.started` | `recall["turn.started"]` | History before recall; current delivery is in `turn.input` |
|
|
266
|
+
| `turn.completed` | `capture["turn.completed"]` | Settled, projected history after a successful turn |
|
|
267
|
+
| `compaction.requested` | `capture["compaction.requested"]` | Projected history before the checkpoint changes |
|
|
268
|
+
| `compaction.completed` | `recall["compaction.completed"]` | The checkpoint plus canonical recalled records |
|
|
269
|
+
|
|
270
|
+
Compaction excludes recalled records from the summarizer, preserves only the
|
|
271
|
+
latest keyed values plus unkeyed values, then recalls again against the new
|
|
272
|
+
checkpoint. This keeps provider context attributable and prevents a summary
|
|
273
|
+
from turning it into ordinary conversation history.
|
|
274
|
+
|
|
275
|
+
If raw superseded records exceed 512 entries or 256 KiB, eve can canonicalize
|
|
276
|
+
them without waiting for the normal token threshold. This folds superseded
|
|
277
|
+
records without changing the provider's external storage.
|
|
278
|
+
|
|
279
|
+
`clear()` removes conversation history, recalled records, locked scopes, and
|
|
280
|
+
memory replay bookkeeping from the session. It does not delete data in the
|
|
281
|
+
provider's external store. A later turn can recall that data again.
|
|
282
|
+
|
|
283
|
+
## Failure behavior
|
|
284
|
+
|
|
285
|
+
- A throwing or invalid turn-start recall fails before the model call. No
|
|
286
|
+
slot's recall results are committed.
|
|
287
|
+
- A pre-compaction capture failure leaves history unchanged.
|
|
288
|
+
- A post-compaction recall failure fails an automatic turn. Standalone
|
|
289
|
+
compaction reports a diagnostic and returns the session to waiting because
|
|
290
|
+
the checkpoint has already been written.
|
|
291
|
+
- An invalid or throwing `tools()` result is diagnosed and omitted for that
|
|
292
|
+
turn.
|
|
293
|
+
- A completed-turn capture failure is diagnosed after the response and does
|
|
294
|
+
not rewrite the completed turn.
|
|
295
|
+
|
|
296
|
+
Keep provider operations idempotent, enforce backend size and retention
|
|
297
|
+
policies, and treat recalled content as user-controlled data.
|
|
298
|
+
|
|
299
|
+
## Limits and overrides
|
|
300
|
+
|
|
301
|
+
Namespaces, scope components, and provider item IDs are limited to 1,024 UTF-8
|
|
302
|
+
bytes. Scope tuples accept at most 16 non-empty components, and the combined
|
|
303
|
+
canonical namespace and scope input is limited to 4,096 bytes. Provider tool
|
|
304
|
+
names must satisfy the normal tool-name grammar after the `<slot>__` prefix is
|
|
305
|
+
added.
|
|
306
|
+
|
|
307
|
+
An application-owned `agent/tools/<slot>.ts` replaces the generated
|
|
308
|
+
provider-tool wrapper; export `disableTool()` there to remove it. Extensions
|
|
309
|
+
cannot contribute memory slots because scope and lifecycle ownership remain
|
|
310
|
+
with the consuming agent or subagent.
|
|
311
|
+
|
|
312
|
+
## What to read next
|
|
313
|
+
|
|
314
|
+
- [Multi-tenant memory](./patterns/multi-tenant-memory): define a tenant and
|
|
315
|
+
caller scope for an application store.
|
|
316
|
+
- [State](./concepts/state): keep durable working data inside one session.
|
|
317
|
+
- [Default harness](./concepts/default-harness): understand compaction and
|
|
318
|
+
context controls.
|
|
319
|
+
- [Dynamic capabilities](./guides/dynamic-capabilities): understand the
|
|
320
|
+
ordinary dynamic-tool lifecycle used by provider tools.
|