Metadata-Version: 2.4
Name: vvz-agent-memory
Version: 1.7.46
Summary: Agent dialogue memory for the vvz prompt contract: AI Logger, with a local .agent-memory/ file store while the logger is unreachable
Author-email: Vasiliy Zdanovskiy <vasilyvz@gmail.com>
License-Expression: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: ailogger-client>=0.1.17
Requires-Dist: embed-client>=4.0.24

# vvz-agent-memory

`agent-memory` is how agents of a `file_access: local` project under the vvz prompt contract write
and read their dialogue messages. It wraps the published `ailogger-client`:

- while the AI Logger is reachable, every call goes to the logger;
- while it is unreachable (connection refused, connect timeout, DNS or transport failure, twice),
  a write goes to `.agent-memory/<session_id>/` in the project root;
- `agent-memory import` later moves those messages into the logger with their original
  `message_id` and time (`messages_import`, `occurred_at`), and moves the imported files to
  `.agent-memory/.imported/`.

The package version equals the contract version (`1.7.46` serves contract `v1.7.46`).

## The file store

One message is two files side by side; the name sorts by time (UTC):

```
.agent-memory/<session_id>/2026-10-01T13.57.45.123-<UUID4>.msg   the message (JSON, logger fields + relations)
.agent-memory/<session_id>/2026-10-01T13.57.45.123-<UUID4>.emb   its vector: {message_id, model, dimension, embedding}
```

The vector comes from the fleet embedding service through `embed_client`, with the logger's own
model (`BAAI/bge-m3`, 1024), so the closeness group works locally and survives the import. When the
embedder is down too, the `.msg` is written alone and `agent-memory embed` fills the `.emb` later.

Files are created once and never edited. There are no locks: the sequence number of a file message
is the count of messages already in the session, and references are resolved by `message_id`.
The directory must exist and be ignored by git (the prompt deployment does both); otherwise the
store is unavailable and nothing is written.

## Configuration

One JSON document: `--config`, else `$AGENT_MEMORY_CONFIG`, else
`~/.config/vvz-agent-memory/config.json`. Sections `ailogger_client`, `embedding_client` (the fleet
client shape: `protocol`, `server.host/port`, `client.timeout`, `ssl.cert/key/ca/check_hostname`,
`auth.token/token_header`) and `embedding_model` (`model`, `dimension`). Relative paths resolve
against the document's directory.

```
agent-memory config generate --output ~/.config/vvz-agent-memory/config.json \
  --logger-host 192.168.254.26 --embed-host 192.168.254.26 \
  --logger-cert client.crt --logger-key client.key --logger-ca ca.crt
agent-memory config validate
```

## Commands

Every command prints one JSON object: `{"success": true, "store": "logger|file|both", "data": …}`
in the logger's own data shape, or `{"success": false, "error": {"code", "message"}}`.
`--store auto|logger|file` (default `auto`) selects the side.

| Command | Logger call | File store |
|---|---|---|
| `write` | `append_message` | new `.msg` + `.emb` |
| `read --session-id --message-id [--sequence-number]` | `messages_read` block 1 (`message_get` finds the number) | the file ending in the id |
| `preview --session-id --sender-identity` | `messages_read` mode preview | files of that sender; both sides merged |
| `working-set --session-id (--anchor-message-id \| --anchor-text)` | `working_set` | last N up to the anchor + top M by cosine |
| `relations --session-id` | `relations_read` | relations of the files; both sides merged |
| `embed [--session-id]` | — | missing `.emb` files |
| `import [--session-id] [--batch-size] [--keep]` | `messages_import` | moved to `.imported/` after success |
| `config generate \| validate` | — | — |

Exit codes: 0 success; 1 logger refused or failed (or an import item failed); 2 usage; 3 file store
unavailable; 4 logger unreachable with no fallback; 5 not found; 6 configuration invalid;
7 embedding unavailable where a vector is required.

## Verification

`python -m pipeline` in this directory runs every check against the live logger and embedder;
`python -m pipeline <name>` runs one; `python -m pipeline --list` lists them.
