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.
Files changed (141) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/src/chunks/{use-eve-agent-OtHRoxIS.js → use-eve-agent-BH7Z6SDu.js} +13 -1
  3. package/dist/src/chunks/{use-eve-agent-C46Kan_I.js → use-eve-agent-DI2j5XK8.js} +13 -1
  4. package/dist/src/cli/commands/integration-connect.d.ts +2 -0
  5. package/dist/src/cli/commands/integration-connect.js +1 -1
  6. package/dist/src/cli/commands/register-integration-commands.js +1 -1
  7. package/dist/src/client/agent-info-schema.d.ts +191 -2
  8. package/dist/src/client/agent-info-schema.js +1 -1
  9. package/dist/src/client/types.d.ts +1 -1
  10. package/dist/src/compiled/.vendor-stamp.json +2 -1
  11. package/dist/src/compiled/@vercel/blob/client.d.ts +487 -0
  12. package/dist/src/compiled/@vercel/blob/create-folder-BM6BTlko.d.ts +471 -0
  13. package/dist/src/compiled/@vercel/blob/index.d.ts +573 -0
  14. package/dist/src/compiled/@vercel/blob/index.js +43 -0
  15. package/dist/src/compiled/@vercel/blob/license.md +201 -0
  16. package/dist/src/compiler/extension-compatibility.d.ts +4 -4
  17. package/dist/src/compiler/extension-compatibility.js +1 -1
  18. package/dist/src/compiler/load-binding-namespace.js +1 -1
  19. package/dist/src/compiler/manifest.d.ts +10 -0
  20. package/dist/src/compiler/manifest.js +1 -1
  21. package/dist/src/compiler/model-catalog.d.ts +1 -1
  22. package/dist/src/compiler/model-catalog.js +1 -1
  23. package/dist/src/compiler/module-map.js +1 -1
  24. package/dist/src/compiler/normalize-helpers.d.ts +2 -1
  25. package/dist/src/compiler/normalize-manifest.js +1 -1
  26. package/dist/src/compiler/normalize-memory.d.ts +5 -0
  27. package/dist/src/compiler/normalize-memory.js +1 -0
  28. package/dist/src/compiler/normalize-tool.js +1 -1
  29. package/dist/src/compiler/project-sources.d.ts +3 -4
  30. package/dist/src/compiler/project-sources.js +1 -1
  31. package/dist/src/compiler/source-graph.d.ts +2 -0
  32. package/dist/src/compiler/source-graph.js +1 -1
  33. package/dist/src/compiler/validate-artifact.js +1 -1
  34. package/dist/src/context/dynamic-tool-lifecycle.d.ts +8 -1
  35. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  36. package/dist/src/context/keys.d.ts +25 -0
  37. package/dist/src/context/keys.js +1 -1
  38. package/dist/src/context/memory-event-lifecycle.d.ts +13 -0
  39. package/dist/src/context/memory-event-lifecycle.js +1 -0
  40. package/dist/src/context/memory-lifecycle.d.ts +52 -0
  41. package/dist/src/context/memory-lifecycle.js +1 -0
  42. package/dist/src/context/memory-tools.d.ts +12 -0
  43. package/dist/src/context/memory-tools.js +1 -0
  44. package/dist/src/discover/discover-agent.js +1 -1
  45. package/dist/src/discover/discover-subagent.js +1 -1
  46. package/dist/src/discover/extensions.d.ts +6 -0
  47. package/dist/src/discover/extensions.js +1 -1
  48. package/dist/src/discover/filesystem.d.ts +2 -2
  49. package/dist/src/discover/filesystem.js +1 -1
  50. package/dist/src/discover/manifest.d.ts +6 -1
  51. package/dist/src/discover/manifest.js +1 -1
  52. package/dist/src/discover/memory.d.ts +14 -0
  53. package/dist/src/discover/memory.js +1 -0
  54. package/dist/src/discover/project.js +1 -1
  55. package/dist/src/evals/cli/eval.js +1 -1
  56. package/dist/src/evals/target.js +1 -1
  57. package/dist/src/execution/history-view.d.ts +2 -2
  58. package/dist/src/execution/history-view.js +1 -1
  59. package/dist/src/execution/tools/connection-search.js +2 -2
  60. package/dist/src/execution/workflow-steps.d.ts +1 -3
  61. package/dist/src/execution/workflow-steps.js +1 -1
  62. package/dist/src/framework/sources/modules/memory-wrapper.d.ts +2 -0
  63. package/dist/src/framework/sources/modules/memory-wrapper.js +1 -0
  64. package/dist/src/framework/sources/registry.d.ts +1 -0
  65. package/dist/src/framework/sources/registry.js +1 -1
  66. package/dist/src/harness/emission.d.ts +1 -1
  67. package/dist/src/harness/emission.js +1 -1
  68. package/dist/src/harness/hitl/approval-prompt.d.ts +2 -0
  69. package/dist/src/harness/hitl/approval-prompt.js +3 -2
  70. package/dist/src/harness/tool-loop.js +2 -2
  71. package/dist/src/harness/tools.js +1 -1
  72. package/dist/src/internal/application/compiled-artifacts.js +4 -2
  73. package/dist/src/internal/application/package.js +1 -1
  74. package/dist/src/internal/authored-definition/memory.d.ts +2 -0
  75. package/dist/src/internal/authored-definition/memory.js +1 -0
  76. package/dist/src/internal/authored-definition/schema-backed.d.ts +1 -0
  77. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  78. package/dist/src/internal/authored-module-map-loader.js +1 -1
  79. package/dist/src/internal/dynamic-tool-rebind.d.ts +3 -0
  80. package/dist/src/internal/dynamic-tool-rebind.js +1 -0
  81. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +1 -1
  82. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  83. package/dist/src/internal/nitro/routes/index.js +1 -0
  84. package/dist/src/internal/programmatic-source-loader.d.ts +1 -0
  85. package/dist/src/internal/programmatic-source-loader.js +1 -1
  86. package/dist/src/internal/workflow/development-world-server.js +1 -1
  87. package/dist/src/internal/workflow/local-world-delivery-timeouts.d.ts +7 -0
  88. package/dist/src/internal/workflow/local-world-delivery-timeouts.js +1 -0
  89. package/dist/src/public/memory/file/backend.d.ts +37 -0
  90. package/dist/src/public/memory/file/backend.js +1 -0
  91. package/dist/src/public/memory/file/backends/default.d.ts +7 -0
  92. package/dist/src/public/memory/file/backends/default.js +1 -0
  93. package/dist/src/public/memory/file/backends/in-memory.d.ts +6 -0
  94. package/dist/src/public/memory/file/backends/in-memory.js +1 -0
  95. package/dist/src/public/memory/file/backends/lazy.d.ts +3 -0
  96. package/dist/src/public/memory/file/backends/lazy.js +1 -0
  97. package/dist/src/public/memory/file/backends/vercel-blob.d.ts +14 -0
  98. package/dist/src/public/memory/file/backends/vercel-blob.js +1 -0
  99. package/dist/src/public/memory/file/index.d.ts +3 -0
  100. package/dist/src/public/memory/file/index.js +1 -0
  101. package/dist/src/public/memory/file/provider.d.ts +14 -0
  102. package/dist/src/public/memory/file/provider.js +6 -0
  103. package/dist/src/public/memory/file/vercel.d.ts +1 -0
  104. package/dist/src/public/memory/file/vercel.js +1 -0
  105. package/dist/src/public/memory/index.d.ts +117 -0
  106. package/dist/src/public/memory/index.js +1 -0
  107. package/dist/src/public/memory/scope.d.ts +2 -0
  108. package/dist/src/public/memory/scope.js +1 -0
  109. package/dist/src/runtime/resolve-agent.js +1 -1
  110. package/dist/src/runtime/resolve-dynamic-tool.d.ts +1 -0
  111. package/dist/src/runtime/resolve-dynamic-tool.js +1 -1
  112. package/dist/src/runtime/resolve-memory.d.ts +4 -0
  113. package/dist/src/runtime/resolve-memory.js +1 -0
  114. package/dist/src/runtime/types.d.ts +7 -0
  115. package/dist/src/setup/connection-connector.d.ts +2 -0
  116. package/dist/src/setup/connection-connector.js +1 -1
  117. package/dist/src/setup/integrations/linq/connect.js +1 -1
  118. package/dist/src/setup/scaffold/create/project.js +1 -1
  119. package/dist/src/setup/scaffold/create/web-template.d.ts +2 -0
  120. package/dist/src/setup/scaffold/create/web-template.js +28 -0
  121. package/dist/src/shared/memory-definition.d.ts +2 -0
  122. package/dist/src/shared/memory-definition.js +1 -0
  123. package/dist/src/shared/memory-state.d.ts +55 -0
  124. package/dist/src/shared/memory-state.js +1 -0
  125. package/dist/src/svelte/index.js +1 -1
  126. package/dist/src/svelte/use-eve-agent.js +1 -1
  127. package/dist/src/vue/index.js +1 -1
  128. package/dist/src/vue/use-eve-agent.js +1 -1
  129. package/docs/channels/eve.mdx +1 -1
  130. package/docs/concepts/context-control.md +7 -0
  131. package/docs/concepts/default-harness.md +8 -0
  132. package/docs/concepts/sessions-runs-and-streaming.md +3 -3
  133. package/docs/concepts/state.md +8 -1
  134. package/docs/extensions.md +6 -2
  135. package/docs/guides/client/overview.mdx +2 -2
  136. package/docs/guides/dynamic-capabilities.md +3 -2
  137. package/docs/memory.md +320 -0
  138. package/docs/meta.json +1 -0
  139. package/docs/patterns/multi-tenant-memory.md +108 -136
  140. package/docs/reference/typescript-api.md +5 -0
  141. package/package.json +22 -1
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-OtHRoxIS.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-BH7Z6SDu.js";
2
2
 
3
3
  export { useEveAgent };
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-C46Kan_I.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-DI2j5XK8.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-C46Kan_I.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-DI2j5XK8.js";
2
2
 
3
3
  export { useEveAgent };
@@ -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 3. 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`.
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 3, a JSON inspection snapshot of the effective compiled agent. It reports the selected config; active tools, instructions, 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. 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`.
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
 
@@ -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 the session, including counters, the current plan, and what the user has told you this conversation. It is the agent's short-term memory, persisted durably for the life of the session. Anything that has to outlive the session, be shared across sessions or users, or be queried independently of a turn belongs in an external store. Start with a packaged memory provider from the [integration gallery](/integrations) using the Memory filter, a general [connection](../connections), or your own database.
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)
@@ -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 memory extension could use hooks to capture context and tools to recall it. A self-improving extension could pair hooks with dynamic instructions.
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, a sandbox, or nested extensions. A subagent contributed under `extension/subagents/` owns its own agent configuration and sandbox like any other [declared subagent](./subagents).
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 3 response before returning it:
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 3 separates active static definitions from dynamic resolvers, includes binding-backed source ownership and composition history, 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`.
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. Turn-scoped and step-scoped tools are not rebound; a parked call to a missing one errors.
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.
package/docs/meta.json CHANGED
@@ -6,6 +6,7 @@
6
6
  "---Build---",
7
7
  "agent-config",
8
8
  "instructions",
9
+ "memory",
9
10
  "tools",
10
11
  "connections",
11
12
  "channels",