Memory API
Prefix: /api/memory
This is the main server's browser and settings API for memory. It exposes recent-memory editing, memory feature toggles, character-memory renaming, and user-initiated cleanup of legacy storage. It is not a generic proxy for the process-local Memory Server API.
All routes are declared without a trailing slash. Write operations can return 409 while cloud storage is in maintenance or read-only mode.
Endpoint summary
| Method | Path | Purpose |
|---|---|---|
GET | /api/memory/recent_files | List logical recent-memory filenames |
GET | /api/memory/recent_file | Read one recent-memory file |
POST | /api/memory/recent_file/save | Replace one character's recent-memory history |
POST | /api/memory/update_catgirl_name | Compatibility alias for the full character rename transaction |
GET | /api/memory/review_config | Read the automatic recent-memory review toggle |
POST | /api/memory/review_config | Update the automatic recent-memory review toggle |
GET | /api/memory/powerful_memory_config | Read the powerful-memory toggle |
POST | /api/memory/powerful_memory_config | Update the powerful-memory toggle and run any required migration |
GET | /api/memory/legacy/scan | Scan user-visible legacy memory roots without changing them |
POST | /api/memory/legacy/purge | Delete explicitly selected entries from scanned legacy roots |
Recent memory files
The browser API retains the logical filename recent_<character>.json for compatibility. Current storage resolves that name to memory/<character>/recent.json; legacy flat files are still readable during migration.
GET /api/memory/recent_files
No parameters.
The route searches both the active and project memory roots, deduplicates logical filenames, and returns them in sorted order.
{
"files": ["recent_小天.json", "recent_小夜.json"]
}GET /api/memory/recent_file
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
filename | string | yes | Logical filename such as recent_小天.json; path separators and .. are rejected |
The content field is the file's UTF-8 JSON text, not a parsed message array.
{
"content": "[{\"type\":\"human\",\"data\":{...}}]",
"fingerprint": "b4c1000000000000000000000000000000000000000000000000000000000000",
"identity_token": "a7e3111111111111111111111111111111111111111111111111111111111111"
}fingerprint and identity_token are opaque snapshot tokens. A client that edits this content must retain both values and return them unchanged with the corresponding save request.
Errors use {"success": false, "error": "..."} with 400 for an invalid filename and 404 when the logical file cannot be resolved.
POST /api/memory/recent_file/save
Replaces the selected character's recent history and cancels any in-flight review for that character so the manual edit can take effect.
Request body
{
"filename": "recent_小天.json",
"fingerprint": "b4c1000000000000000000000000000000000000000000000000000000000000",
"identity_token": "a7e3111111111111111111111111111111111111111111111111111111111111",
"chat": [
{ "role": "human", "text": "Hello!" },
{ "role": "ai", "text": "Hi there!" }
]
}| Field | Type | Required | Description |
|---|---|---|---|
filename | string | yes | Must match recent_<character>.json; the character name is derived from this field |
fingerprint | string | yes | Opaque content token returned by the GET used to populate this edit |
identity_token | string | yes | Opaque file-identity token returned by the same GET |
chat | array | yes | Replacement history, up to 10,000 entries |
chat[].role | string | yes | Stored message type, normally human, ai, or system |
chat[].text | string | no | Message text; defaults to an empty string |
Each message is limited to 32,768 text characters and the request to 2,097,152 text characters in total. Unknown fields on a chat entry are not persisted.
Success:
{
"success": true,
"need_refresh": true,
"catgirl_name": "小天",
"fingerprint": "d8f2222222222222222222222222222222222222222222222222222222222222",
"identity_token": "a7e3111111111111111111111111111111111111111111111111111111111111"
}Validation failures return 400 with success: false. Missing snapshot tokens or a concurrent file/identity change returns 409; conflicts use code: "RECENT_FILE_CONFLICT" and include the current tokens. On conflict, GET the file again and merge the user's edits before saving. Do not replay the old chat merely with the returned tokens. A successful response returns the tokens for a subsequent edit. A storage failure returns success: false and an error field; cloud-storage maintenance is also reported as 409.
Character memory rename
POST /api/memory/update_catgirl_name
Compatibility alias for the canonical POST /api/characters/catgirl/{old_name}/rename transaction. It drains memory review/compression tasks, publishes the character rename, migrates all memory and card state, reloads the memory server, and rolls back on failure. A legacy follow-up call after that transaction already committed succeeds as an idempotent no-op.
{
"old_name": "旧名字",
"new_name": "新名字"
}Both fields are required strings. Historical old_name values may contain dots; new_name uses the current character-name rules and cannot be a reserved route name.
{
"success": true,
"memory_renamed": true,
"memory_server_reloaded": true
}An idempotent follow-up returns changed: false, already_renamed: true, and exists_after. This no-op is allowed only when configuration already contains the new name and the old storage is gone. If configuration was published but old storage remains, the route returns 409 instead of hiding a partial rename; repair it through the canonical character-management endpoint. Invalid or missing names return 400. The operation can also return 409 when storage is not writable.
Memory feature toggles
GET /api/memory/review_config
Returns whether automatic review and correction of recent memory is enabled. The default is true when the setting is absent.
{ "enabled": true }POST /api/memory/review_config
{ "enabled": false }The route persists recent_memory_auto_review in core_config.json.
{ "success": true, "enabled": false }Failures use {"success": false, "error": "..."}. Storage maintenance can return 409.
GET /api/memory/powerful_memory_config
Returns the powerful_memory_enabled setting. The default is true for existing installations without an explicit value.
{ "enabled": true }POST /api/memory/powerful_memory_config
{ "enabled": false }The powerful-memory switch controls the evidence-driven LLM paths, including signal analysis, merge-on-promotion, rebuttal checks, negative-target checks, fact deduplication, and persona corrections. The lightweight feedback path remains available when powerful memory is off.
An ON to OFF transition first asks the memory-server process to reset the age anchor on confirmed reflections. This prevents old confirmed entries from being promoted immediately by the time-driven fallback. The configuration is saved only after that migration succeeds.
Success:
{ "success": true, "enabled": false }Migration or persistence failure:
{ "success": false, "error": "migration HTTP 409" }Legacy memory cleanup
Legacy cleanup is an explicit two-step operation: scan first, then submit selected absolute paths. The scan never migrates or deletes data.
GET /api/memory/legacy/scan
No parameters.
The response identifies candidate roots outside the active runtime memory directory and describes each direct child. size_bytes is -1 when size calculation is unavailable or exceeds the safety scan limit.
{
"success": true,
"runtime_memory_dir": "C:\\...\\memory",
"legacy_roots": [
{
"root": "C:\\...\\old-root\\memory",
"source": "legacy_app_root",
"exists": true,
"entries": [
{
"name": "小天",
"path": "C:\\...\\old-root\\memory\\小天",
"is_dir": true,
"size_bytes": 12345,
"is_unlinked": false,
"runtime_has_same_name": true
}
]
}
],
"total_entries": 1,
"total_size_bytes": 12345
}Unexpected scan failures return 500 with success: false.
POST /api/memory/legacy/purge
This is destructive. Send only paths returned as entries by the latest scan.
{
"paths": [
"C:\\...\\old-root\\memory\\小天"
]
}paths must be a non-empty array of absolute paths. Every path must resolve strictly below a currently recognized legacy root. The route rejects relative paths, .. segments, the root directory itself, and the active runtime memory directory. Missing targets count as already removed, making retries idempotent.
Deletion is best-effort per entry. A successful request can therefore contain both removed and errors:
{
"success": true,
"removed": ["C:\\...\\old-root\\memory\\小天"],
"errors": [
{ "path": "C:\\...\\not-allowed", "error": "..." }
]
}Malformed bodies return 400; no recognized legacy roots returns 409; initialization failure returns 500.
