[wrangler] Add agent_memory binding support and namespace commands#13610
[wrangler] Add agent_memory binding support and namespace commands#13610petebacondarwin wants to merge 33 commits intomainfrom
Conversation
🦋 Changeset detectedLatest commit: 1ac68c8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
UnknownError: ProviderInitError |
|
@petebacondarwin Bonk workflow failed. Check the logs for details. View workflow run · To retry, trigger Bonk again. |
create-cloudflare
@cloudflare/kv-asset-handler
miniflare
@cloudflare/pages-shared
@cloudflare/unenv-preset
@cloudflare/vite-plugin
@cloudflare/vitest-pool-workers
@cloudflare/workers-editor-shared
@cloudflare/workers-utils
wrangler
commit: |
|
Codeowners approval required for this PR:
Show detailed file reviewers
|
penalosa
left a comment
There was a problem hiding this comment.
Initial pass. My main concern at this stage is the agentmemory/agent_memory/agent_memory_namespace naming confusion
|
Looks this doesn't include the new OAuth permissions. |
|
Not completely sure how "remote" bindings are implemented, but they don't seem to work. |
|
As for naming, you make good points on the consistency. Since we are not constrained by agent week deadlines, we are going to make changes to center on using "agent-memory" in the naming. (and "agent_memory", as necessary). |
79346fe to
230fe18
Compare
|
✅ All changesets look good |
|
Marking as draft while @oliy works through some backend updates (e.g. around the agentmemory/agent-memory/agent_memory naming etc) |
6ffd5a4 to
181d5f5
Compare
|
Codeowners approval required for this PR:
Show detailed file reviewers
|
779c979 to
dd9bf72
Compare
There was a problem hiding this comment.
Devin Review found 1 new potential issue.
🐛 1 issue in files not directly in the diff
🐛 Missing agent_memory in pickRemoteBindings causes binding to be silently dropped during wrangler dev (packages/wrangler/src/api/remoteBindings/index.ts:42-48)
agent_memory is an always-remote binding (confirmed by the changeset description, the miniflare plugin calling warnOrError("agent_memory", memory.remote, "always-remote") at packages/wrangler/src/dev/miniflare/index.ts:637, and by the miniflare plugin only implementing remote proxy). However, the pickRemoteBindings function at packages/wrangler/src/api/remoteBindings/index.ts:18-52 does not include agent_memory in its list of always-remote types. Every other always-remote binding (ai, media, artifacts, vpc_service, vpc_network, ai_search_namespace, ai_search) is explicitly listed. Without this, an agent_memory binding will only be picked for the remote proxy session if the user explicitly sets remote: true in their config. Since remote is optional (remote?: boolean in packages/workers-utils/src/config/environment.ts:1069), most users won't set it, causing the binding to silently not work during local development.
View 19 additional findings in Devin Review.
…_memory binding Add agent_memory to wrangler types generation so running `wrangler types` produces typed AgentMemory bindings. Fix config-diffs to strip the remote field when comparing local vs remote configs. Fix print-bindings to correctly display inherited agent_memory bindings. Add comprehensive tests: config validation (7 tests), provisioning (3 tests), deploy binding payload (1 test), and update type generation snapshots.
- Reformat changeset example JSONC (tabs + trailing commas, per oxfmt). - Mark Plugin and RemoteProxyConnectionString as type-only imports in the miniflare agent-memory plugin to satisfy consistent-type-imports. - Update provision tests to use agent_memory_namespace (the actual metadata binding type) instead of agent_memory.
The upload form emits type "agent_memory_namespace" for agent memory bindings, but the deploy/bindings test was asserting on "agent_memory", causing the toEqual(arrayContaining(...)) check to fail.
- Rename emitted ambient type AgentMemory to AgentMemoryNamespace to match the type declared in workerd (cloudflare/workerd#6628) and follow the AiSearchNamespace precedent. - Consolidate the AgentMemoryNamespace interface by importing it from agent-memory/client.ts in agent-memory/provisioning.ts instead of redeclaring a narrower shape there. - Split agent-memory/client.ts into two layers: low-level helpers that take (complianceConfig, accountId, ...) and high-level wrappers that resolve auth via requireAuth. agent-memory/provisioning.ts now delegates to the low-level helpers, removing the duplicated fetch calls. - Reorder the agent_memory block in deploy/config-diffs.ts so it sits alongside the related ai_search blocks.
Matches the dominant pattern in the wrangler codebase (ai-search.ts, pipelines/client.ts, vectorize/client.ts, etc.); fetchResult<null> was just a style nit. No behavior change.
- wrangler agent-memory namespace create: add --json flag and switch the text output to logger.table, matching the list/get commands. - Add TODO on agent-memory/client.ts pointing at the migration to the Cloudflare TypeScript SDK once it exposes /agentmemory endpoints (same situation as ai-search).
Catch the predictable client-side API errors from the agent-memory namespace commands and rethrow them as UserError with friendly messages so they do not get reported to Sentry: - get/delete on an unknown namespace (404) now explains the namespace was not found and suggests running `namespace list`. - create with an invalid or duplicate name (400/409/422) now surfaces the server's validation message wrapped in a UserError.
Wrap startRemoteProxySession() in retry() to handle transient Cloudflare API 5xx (most commonly edge-preview returning 500), which has been blocking shard 3 of this PR consistently for 2+ days. Test-only change; no runtime behaviour modified. Refs: #13831
Boot the remote proxy session in beforeAll with only the first test case's bindings, then call updateBindings inside each `it` to install that test case's bindings. Previously every test case's bindings were merged into a single startRemoteProxySession call, causing the boot to time out as the suite grew. The new flow makes the boot smaller and attributes any per-binding boot failure to the test that owns that binding rather than to an opaque beforeAll timeout. Also drop the retry wrapper around startRemoteProxySession in both the main and mTLS describe blocks.
The agent-memory worker binding API uses `getProfile()` (not `getContext()`), and the result's text field is `profile` (not `context`). Update the test worker and assertion to match.
DevEnv extends EventEmitter and routes events between controllers via its internal `dispatch()` method. Re-emit `reloadComplete` events on the EventEmitter so external callers (in the next commit, `RemoteProxySession.updateBindings`) can wait for a remote upload to finish. Other event types stay internal for now.
… to complete Previously `updateBindings` resolved as soon as `worker.patchConfig` dispatched the configUpdate event, long before the remote worker had been re-uploaded with the new bindings and the local proxy worker had unpaused. Callers issuing requests immediately after `updateBindings` could see flaky failures (typically "WebSocket connection failed" for JSRPC bindings like service bindings or dispatch namespaces) because the local proxy worker was still in its paused state during the reload window. `updateBindings` now subscribes to the `reloadComplete` event before calling `patchConfig`, then awaits either that event (success) or the DevEnv `error` event (non-recoverable failure). After reload it also drains the local proxy worker's runtime-message mutex so the "play" message that resumes the proxy has been delivered, mirroring what `worker.fetch` already does.
…estart The remote-runtime tail-logs WebSocket (`#activeTail` in `RemoteRuntimeController`) is constructed with `signal: this.#abortController.signal`. The `ws` package wires that signal to the underlying HTTP upgrade request via Node's `addAbortSignal()` helper, so when `onBundleStart` aborts the controller to cancel in-flight preview-session operations, the WebSocket's request is destroyed with `AbortError` and emits an `error` event. Only a `message` listener was attached at construction, so the `error` had no handler and propagated as an unhandled exception — visible in e2e runs as a trailing "Unhandled Errors / Uncaught Exception" in the test report. Attach an `error` listener at WebSocket construction that ignores errors (debug-logged), matching the safeguards already present on the `terminate` paths in `#previewToken` and `teardown()`. This covers the window between WebSocket construction and the next `terminate`, plus any transient network errors during normal operation.
9217cf8 to
356ed2c
Compare
…ng events.once() Address PR feedback to use `node:events`'s `events.once()` helper, which resolves on the named event and rejects on `error`, instead of hand-rolling a Promise with cross-cleanup listeners. Same behavior, fewer lines, matches the existing convention used elsewhere in wrangler (`dev.ts`, `pages/dev.ts`, `api/dev.ts`, `ProxyController.ts`, `check/commands.ts`).
Add support for Cloudflare's Agent Memory service in Wrangler and Miniflare.
This PR adds a new
agent_memorybinding type plus a set ofwrangler agent-memory namespacecommands for managing Agent Memory namespaces. The binding is remote-only — Workers always proxy to the live Cloudflare API duringwrangler devrather than being simulated locally — and Wrangler will provision missing namespaces automatically at deploy time.What's included
agent_memorybinding (wrangler + miniflare, minor)agent_memoryconfig section inwrangler.json:{ "agent_memory": [ { "binding": "MY_MEMORY", "namespace": "my-namespace" } ] }workers-utils(non-inheritable).packages/miniflare/src/plugins/agent-memory/) wires the binding through the standard remote-proxy machinery sowrangler devreaches the live Agent Memory API.startDevWorker, deploy paths,print-bindings, config-diffs, andworker-upload-formall updated to recognise the binding.wrangler deployif the named namespace doesn't exist.wrangler typesemits typedagent_memory_namespacebindings on the generatedEnvinterface.wrangler agent-memory namespacecommands (wrangler, minor)All commands are flagged as open beta and emit a warning on use. User-facing API errors are wrapped as
UserErrorso they get clean output instead of stack traces.OAuth scope
agent-memory:writeto Wrangler's default login scopes sowrangler loginrequests the permissions needed to provision and manage Agent Memory namespaces.Tests
packages/wrangler/e2e/agent-memory.test.tsexercisescreate→list(default +--json) →get→delete.miniflare-remote-resources.test.tsvalidates the binding works end-to-end via the remote proxy.packages/wrangler/src/__tests__/agent-memory.test.tscover the client, command parsing, and provisioning logic.print-bindings,provision,deploy/bindings,whoami(new OAuth scope), andnormalize-and-validate-config.A picture of a cute animal (not mandatory, but encouraged)