Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/walm-115-sdk-delete-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@mysten-incubation/memwal": patch
---

Add memory deletion + listing to the SDK: `clearNamespace(namespace)`, `forget(id)`, and `list(namespace, { limit, cursor })`.

- `clearNamespace` soft-deletes every memory in a namespace so it stops surfacing in `recall()` — the reset primitive for iteration/dev loops (replaces namespace rotation).
- `forget` soft-deletes a single memory by the `id` returned from `list()` (per-memory; identical-text memories stored separately are unaffected).
- `list` enumerates a namespace as metadata only (id, blob_id, created_at, importance — no decrypted text), cursor-paginated via `has_more` / `next_cursor`.

Soft-delete clears *retrievability*, not the underlying Walrus blob (user-owned, persists until on-chain deletion / storage-epoch expiry). All owner-scoped.
39 changes: 39 additions & 0 deletions docs/python-sdk/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,45 @@ Rebuild missing indexed entries for one namespace from Walrus. Incremental.
RestoreResult(restored: int, skipped: int, total: int, namespace: str, owner: str)
```

### `clear_namespace(namespace) -> ClearNamespaceResult`

Soft-delete every memory in a namespace so it stops surfacing in `recall` — the reset primitive. Clears retrievability; the Walrus blob is user-owned and persists (un-recallable, not erased). Owner-scoped; namespace matched exactly.

- `cleared` is the count newly soft-deleted; `0` is a safe no-op (already empty/cleared)

```python
ClearNamespaceResult(cleared: int, namespace: str, owner: str)
```

### `list(namespace, limit=50, cursor=None) -> ListResult`

Enumerate the memories in a namespace — metadata only (no decrypted text), newest first, decrypt-free. Each item's `id` is the handle for `forget`. Use `recall` to read content.

- `limit` defaults to `50` (capped 1–500); omit `cursor` for the first page
- Paginate: when `has_more` is `True`, pass `next_cursor` back as `cursor`
- `returned` is this page's size, not the namespace total

```python
ListResult(
memories: list[MemoryListItem], # MemoryListItem(id, blob_id, created_at, importance)
returned: int,
has_more: bool,
next_cursor: Optional[str],
namespace: str,
owner: str,
)
```

### `forget(memory_id) -> ForgetResult`

Soft-delete a single memory by its `id` (from `list`). An identical-text memory stored separately is unaffected (per-memory). Owner-scoped.

- `forgotten` is `1` on success; `0` is a safe no-op (not found / not yours / already gone)

```python
ForgetResult(forgotten: int, id: str, owner: str)
```

### `health() -> HealthResult`

Check relayer health. No authentication. Raises `MemWalError` on non-200.
Expand Down
85 changes: 85 additions & 0 deletions docs/relayer/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,88 @@ Rebuild missing vector entries for one namespace. Queries onchain blobs by owner
"owner": "0x..."
}
```

### `POST /api/clear-namespace`

Soft-delete every memory in one namespace. The memories immediately stop appearing in `recall`; the underlying Walrus blobs are user-owned and persist (this clears retrievability, not the blob). Owner-scoped.

**Request:**

```json
{
"namespace": "demo"
}
```

**Response:**

```json
{
"cleared": 12,
"namespace": "demo",
"owner": "0x..."
}
```

`cleared` is the number of memories newly soft-deleted; `0` is a safe no-op (already empty/cleared).

### `POST /api/list`

Enumerate the live memories in one namespace, newest first. Metadata only — no decrypted text — so it is cheap to call for auditing. Each item's `id` is the handle for `/api/memories/forget`. Owner-scoped; soft-deleted memories are omitted.

**Request:**

```json
{
"namespace": "demo",
"limit": 50,
"cursor": "<next_cursor from a previous response, omit for the first page>"
}
```

`limit` defaults to `50` (clamped to 1–500). Omit `cursor` for the first page.

**Response:**

```json
{
"memories": [
{
"id": "uuid",
"blob_id": "walrus-blob-id",
"created_at": "2026-06-18T12:00:00+00:00",
"importance": 0.5
}
],
"returned": 1,
"has_more": false,
"namespace": "demo",
"owner": "0x..."
}
```

`returned` is this page's size (not the namespace total). When `has_more` is `true`, the response also includes a `next_cursor`; pass it back as `cursor` to fetch the next page.

### `POST /api/memories/forget`

Soft-delete a single memory by its `id` (from `/api/list`). The memory stops appearing in `recall`; an identical-text memory stored separately is unaffected (deletion is per-memory). Owner-scoped.

**Request:**

```json
{
"id": "uuid"
}
```

**Response:**

```json
{
"forgotten": 1,
"id": "uuid",
"owner": "0x..."
}
```

`forgotten` is `1` on success, `0` if the id was not found, is not the caller's, or was already forgotten (all safe no-ops).
48 changes: 48 additions & 0 deletions docs/sdk/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,54 @@ Rebuild missing indexed entries for one namespace from Walrus. Incremental — o
}
```

### `clearNamespace(namespace): Promise<ClearNamespaceResult>`

Soft-delete every memory in a namespace so it stops surfacing in `recall()` — the reset primitive for iteration/dev loops. Soft-delete clears *retrievability*; the Walrus blob is user-owned and persists (un-recallable, not erased). Owner-scoped; namespace matched exactly.

**Returns:**

```ts
{
cleared: number; // Memories newly cleared (0 = safe no-op, already empty/cleared)
namespace: string;
owner: string;
}
```

### `list(namespace, opts?): Promise<ListResult>`

Enumerate the memories in a namespace — metadata only (id, blob_id, created_at, importance), newest first. Decrypt-free, so cheap to call for auditing. Each item's `id` is the handle for `forget()`. Use `recall()` to read content.

- `opts` is `{ limit?, cursor? }` (a bare `number` is accepted as `limit`); `limit` defaults to `50`, capped 1–500.
- Paginate: when `has_more` is `true`, pass `next_cursor` back as `opts.cursor`.

**Returns:**

```ts
{
memories: { id: string; blob_id: string; created_at: string; importance: number }[];
returned: number; // This page's size (NOT the namespace total)
has_more: boolean;
next_cursor?: string; // Pass back as opts.cursor for the next page
namespace: string;
owner: string;
}
```

### `forget(id): Promise<ForgetResult>`

Soft-delete a single memory by its `id` (from `list()`). An identical-text memory stored separately is unaffected (deletion is per-memory). Like `clearNamespace`, clears retrievability, not the blob. Owner-scoped.

**Returns:**

```ts
{
forgotten: number; // 1 on success; 0 = safe no-op (not found / not yours / already gone)
id: string;
owner: string;
}
```

### `health(): Promise<HealthResult>`

Check relayer health. Does not require authentication.
Expand Down
4 changes: 2 additions & 2 deletions docs/sdk/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Use this first.

- relayer-backed
- best path for most teams
- main methods: `remember`, `recall`, `analyze`, `restore`, `health`
- main methods: `remember`, `recall`, `analyze`, `restore`, `clearNamespace`, `list`, `forget`, `health`

```ts
import { MemWal } from "@mysten-incubation/memwal";
Expand Down Expand Up @@ -67,7 +67,7 @@ memwal = MemWal.create(
)
```

Main methods: `remember`, `recall`, `analyze`, `ask`, `restore`, `health`
Main methods: `remember`, `recall`, `analyze`, `ask`, `restore`, `clear_namespace`, `list`, `forget`, `health`

Middleware: `with_memwal_langchain`, `with_memwal_openai`

Expand Down
11 changes: 11 additions & 0 deletions packages/mcp/src/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ const NAMESPACE_TOOLS = new Set([
"memwal_recall",
"memwal_analyze",
"memwal_restore",
// soft-delete: clears a namespace's memories from recall. Like restore,
// its upstream schema requires `namespace`; registered here so a
// configured default is injected when the agent omits one. (The tool
// DEFINITION itself lives in the MCP sidecar.)
"memwal_clear_namespace",
// list a namespace's memories (metadata + per-row id, for auditing /
// feeding memwal_forget). Namespace-scoped → default injection applies.
"memwal_list",
// NOTE: memwal_forget is intentionally NOT here — it takes a memory `id`,
// not a `namespace`, so there's nothing to inject. (Tool DEFINITION for
// both lives in the MCP sidecar.)
]);

/**
Expand Down
8 changes: 8 additions & 0 deletions packages/python-sdk-memwal/memwal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
RememberManualResult,
RememberResult,
RestoreResult,
ClearNamespaceResult,
MemoryListItem,
ListResult,
ForgetResult,
ScoringWeights,
)
from .utils import delegate_key_to_public_key, delegate_key_to_sui_address
Expand Down Expand Up @@ -108,6 +112,10 @@
"AnalyzedFact",
"HealthResult",
"RestoreResult",
"ClearNamespaceResult",
"MemoryListItem",
"ListResult",
"ForgetResult",
"ScoringWeights",
"RememberManualOptions",
"RememberManualResult",
Expand Down
Loading
Loading