# loves0ph1e/astrbot_plugin_readingsteiner architecture

> Architecture diagram of the GitHub repository loves0ph1e/astrbot_plugin_readingsteiner, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/loves0ph1e/astrbot_plugin_readingsteiner
- Repository: https://github.com/loves0ph1e/astrbot_plugin_readingsteiner

## Overview

1. **What this repo is**
   - `astrbot_plugin_readingsteiner` is a Python plugin for AstrBot that adds long-term memory by delegating persistence and retrieval to an external **EverOS** memory service.
   - The plugin itself does not store the full memory engine; it acts as an integration layer inside the AstrBot runtime.

2. **Top-level boundary**
   - **Inside this repo:** AstrBot plugin logic, command handling, memory injection/archiving, identity resolution, filtering, and prompt synthesis.
   - **Outside this repo:** the EverOS service, which is deployed separately and accessed over HTTP via `core/everos_client.py`.
   - The `deploy/` directory packages the EverOS side with Docker/Docker Compose; it is a sibling operational component, not embedded in the plugin process.

3. **Main runtime flow**
   - The plugin works on two hooks around each conversation turn:
     - **Pre-request injection:** fetch stable user profile + related memories and inject them into the model prompt.
     - **Post-response archiving:** write the new turn back to EverOS so the user’s profile and episodic memory can evolve.
   - This makes memory behavior symmetric: read before generation, write after generation.

4. **Identity and isolation layer**
   - `core/identity.py` is the key boundary for user/session identification.
   - The system treats the **real sender identity** as authoritative; memory is keyed by that identity, not by the model’s interpretation.
   - The README’s “hard isolation” means this layer prevents cross-user memory mixing, especially in multi-user or group chat settings.

5. **Memory injection subsystem**
   - `core/injection.py` and related modules assemble the context inserted into the LLM request.
   - Injection combines:
     - a **persistent profile** for the current user,
     - **top-k relevant scene memories** from recent/history search,
     - optional filtering based on group-chat privacy rules.
   - `core/visibility.py` and config flags like `group_public_only` decide what is safe to expose in group contexts.

6. **Memory synthesis and representation**
   - `core/synthesis.py` turns raw memory data into the readable Chinese structure described in the README: overall impression, explicit facts, implicit traits.
   - `core/relationship.py`, `core/profile_quality.py`, and `core/constants.py` suggest the repo models memory not just as blobs, but as structured user-state plus relationship/quality metadata.
   - This is important architecturally: the plugin is not a plain vector-recall wrapper; it is a **profile-centric memory layer**.

7. **Archiving subsystem**
   - `core/archiving.py` handles writing conversation turns back to EverOS.
   - The archive strategy is configurable (`auto`, `every_turn`, `manual`), so the write path can be event-driven or explicitly triggered.
   - This write path is what lets EverOS incrementally update the user profile and memory graph over time.

8. **Forget / suppression path**
   - `core/forget.py` implements “forgetting” as **read-path suppression**, not physical deletion.
   - That distinction is architectural: the plugin can stop injecting or recalling specific memories, but the underlying EverOS data remains unless removed on the EverOS side.
   - The repo therefore supports reversible opt-out behavior without needing disk-level access to the memory service.

9. **Command and tool surfaces**
   - `commands/handlers.py` exposes user/admin commands like flush, status, search, quality, and forget.
   - The README also mentions optional LLM tools (`epk_recall`, `epk_remember`), which means the plugin has both **human control commands** and **model-invoked memory tools**.
   - These are separate access paths into the same memory subsystem, but both still depend on identity from the real message event.

10. **Operational resilience**
   - The architecture is explicitly fail-soft: if EverOS is unreachable, the plugin logs the issue and lets normal chat continue.
   - That means memory is an enhancement, not a hard dependency for core dialogue.
   - The eventual-consistency note in the README also matters: archive and later search may not be immediately in sync.

11. **Configuration and packaging**
   - `_conf_schema.json` is the plugin’s configuration contract for AstrBot’s UI/config system.
   - `main.py` is the integration entrypoint, while `metadata.yaml` and `pyproject.toml` define plugin/package metadata.
   - The `deploy/` folder contains the operational packaging for EverOS, including environment defaults and container orchestration.

12. **Test coverage implies the subsystem map**
   - The tests mirror the architecture: identity, injection, archiving, forgetting, visibility, synthesis, profile quality, EverOS client, and command handling.
   - That strongly suggests the repo is organized around distinct functional boundaries rather than one monolithic plugin file.

13. **Diagramming hint**
   - A correct architecture diagram should show:
     - AstrBot message/event stream entering the plugin,
     - identity extraction as the first gate,
     - pre-generation injection from EverOS into the prompt,
     - post-generation archiving back to EverOS,
     - command/tool side channels into the same memory engine,
     - and a separate deployment boundary for the EverOS service.

Main entry points: [`core/injection.py`](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/injection.py) (Injection), [`main.py`](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/main.py) (Entry), [`core/everos_client.py`](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/everos_client.py) (EverOS Client), [`core/identity.py`](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/identity.py) (Identity)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Plugin Runtime"]
  node_main["Entry<br/>[main.py]"]
  node_identity["Identity<br/>user/session gate<br/>[identity.py]"]
  node_injection["Injection<br/>prompt assembler<br/>[injection.py]"]
  node_archiving["Archiver<br/>write path<br/>[archiving.py]"]
  node_forget["Forget<br/>read filter<br/>[forget.py]"]
  node_visibility["Visibility<br/>privacy rules<br/>[visibility.py]"]
  node_synthesis["Synthesis<br/>profile formatter<br/>[synthesis.py]"]
  node_profile_quality["Quality<br/>profile metadata<br/>[profile_quality.py]"]
  node_relationship["Relationship<br/>memory metadata<br/>[relationship.py]"]
  node_constants["Constants<br/>shared schema<br/>[constants.py]"]
  node_everos_client["EverOS Client<br/>http client<br/>[everos_client.py]"]
  node_config["Config<br/>plugin schema<br/>[_conf_schema.json]"]
  node_metadata["Metadata<br/>package manifest<br/>[metadata.yaml]"]
end

subgraph group_controls["Controls"]
  node_commands["Commands<br/>admin/user interface<br/>[handlers.py]"]
  node_tools["Tools"]
end

subgraph group_deploy["Deployment"]
  node_deploy_stack[("Deploy<br/>service packaging<br/>[docker-compose.yml]")]
  node_everos_service[("EverOS<br/>external memory service")]
end

node_astrbot_runtime(("AstrBot<br/>host runtime"))

node_astrbot_runtime -->|"loads"| node_main
node_main -->|"gate"| node_identity
node_main -->|"pre-turn"| node_injection
node_main -->|"post-turn"| node_archiving
node_main -->|"admin path"| node_commands
node_main -->|"tool path"| node_tools
node_identity -->|"scope"| node_injection
node_identity -->|"owner"| node_archiving
node_identity -->|"scope"| node_forget
node_injection -->|"filter"| node_visibility
node_injection -->|"format"| node_synthesis
node_injection -->|"annotate"| node_profile_quality
node_injection -->|"enrich"| node_relationship
node_injection -->|"rules"| node_constants
node_injection -->|"retrieve"| node_everos_client
node_archiving -->|"write"| node_everos_client
node_forget -->|"suppress"| node_everos_client
node_commands -->|"auth"| node_identity
node_commands -->|"query"| node_everos_client
node_commands -->|"forget"| node_forget
node_tools -->|"recall/remember"| node_everos_client
node_config -->|"configure"| node_main
node_metadata -->|"package"| node_main
node_deploy_stack -->|"runs"| node_everos_service
node_everos_client -->|"http"| node_everos_service

click node_main "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/main.py"
click node_identity "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/identity.py"
click node_injection "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/injection.py"
click node_archiving "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/archiving.py"
click node_forget "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/forget.py"
click node_visibility "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/visibility.py"
click node_synthesis "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/synthesis.py"
click node_profile_quality "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/profile_quality.py"
click node_relationship "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/relationship.py"
click node_constants "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/constants.py"
click node_everos_client "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/everos_client.py"
click node_commands "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/commands/handlers.py"
click node_config "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/_conf_schema.json"
click node_metadata "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/metadata.yaml"
click node_deploy_stack "https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/deploy/docker-compose.yml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main,node_identity,node_injection,node_archiving,node_forget,node_visibility,node_synthesis,node_profile_quality,node_relationship,node_constants,node_everos_client,node_config,node_metadata toneBlue
class node_commands,node_tools toneAmber
class node_deploy_stack,node_everos_service toneMint
class node_astrbot_runtime toneNeutral
```

## Components

### Plugin Runtime

AstrBot plugin components that identify users, inject memory, and archive turns.

- [Entry](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/main.py): plugin entrypoint · Initializes the plugin integration and wires the runtime hooks. · `main.py`
- [Identity](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/identity.py): user/session gate · Resolves the real sender identity and anchors memory isolation. · `core/identity.py`
- [Injection](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/injection.py): prompt assembler · Builds pre-generation memory context for the model prompt. · `core/injection.py`
- [Archiver](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/archiving.py): write path · Sends conversation turns back for long-term memory updates. · `core/archiving.py`
- [Forget](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/forget.py): read filter · Suppresses selected memories from recall without deleting upstream data. · `core/forget.py`
- [Visibility](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/visibility.py): privacy rules · Determines what memory is safe to expose, especially in groups. · `core/visibility.py`
- [Synthesis](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/synthesis.py): profile formatter · Turns raw memory into readable profile and impression text. · `core/synthesis.py`
- [Quality](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/profile_quality.py): profile metadata · Scores or annotates profile confidence and state quality. · `core/profile_quality.py`
- [Relationship](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/relationship.py): memory metadata · Tracks relationship-oriented structure around the user profile. · `core/relationship.py`
- [Constants](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/constants.py): shared schema · Holds shared labels, limits, and memory structure constants. · `core/constants.py`
- [EverOS Client](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/core/everos_client.py): http client · Talks to the external EverOS memory service over HTTP. · `core/everos_client.py`
- [Config](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/_conf_schema.json): plugin schema · AstrBot configuration contract for runtime behavior and privacy flags. · `_conf_schema.json`
- [Metadata](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/metadata.yaml): package manifest · Plugin package metadata and distribution settings. · `metadata.yaml`

### Controls

Human and tool-facing command surfaces for inspecting or changing memory behavior.

- [Commands](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/commands/handlers.py): admin/user interface · Exposes flush, status, search, quality, and forget commands. · `commands/handlers.py`
- **Tools**: llm tools · Model-invoked recall and remember actions that reach the same memory engine.

### Deployment

Operational packaging for the external EverOS service.

- [Deploy](https://github.com/loves0ph1e/astrbot_plugin_readingsteiner/blob/main/deploy/docker-compose.yml): service packaging · Docker-based packaging for the separately deployed EverOS service. · `deploy/docker-compose.yml`
- **EverOS**: external memory service · Separate persistence and retrieval backend used by the plugin.

### Other components

- **AstrBot**: host runtime · External chat runtime that loads the plugin and emits message events.

## Connections

- AstrBot → Entry: loads · AstrBot loads the plugin entrypoint and starts hook wiring.
- Entry → Identity: gate · Every turn is keyed by the authoritative sender identity.
- Entry → Injection: pre-turn · Pre-generation hook assembles memory context before the model is called.
- Entry → Archiver: post-turn · Post-generation hook archives the completed exchange.
- Entry → Commands: admin path · Registers command handlers for memory inspection and control.
- Entry → Tools: tool path · Optional model tools access the same memory subsystem.
- Identity → Injection: scope · Identity resolution scopes which memories may be retrieved.
- Identity → Archiver: owner · Archiving writes back under the real sender identity.
- Identity → Forget: scope · Forget operations are also anchored to the resolved identity.
- Injection → Visibility: filter · Filters what can be exposed in the current conversation context.
- Injection → Synthesis: format · Builds readable profile text from structured memory data.
- Injection → Quality: annotate · Includes quality or confidence signals when composing context.
- Injection → Relationship: enrich · Pulls relationship-aware state into the injected memory view.
- Injection → Constants: rules · Uses shared limits and schema constants while assembling context.
- Injection → EverOS Client: retrieve · Fetches profile and relevant memories from EverOS.
- Archiver → EverOS Client: write · Sends new conversation turns to EverOS for persistence.
- Forget → EverOS Client: suppress · Applies read-path suppression against retrieved memories.
- Commands → Identity: auth · Command behavior follows the same sender identity boundary.
- Commands → EverOS Client: query · Status, search, and quality commands inspect the remote memory store.
- Commands → Forget: forget · User/admin commands can mark memories hidden from recall.
- Tools → EverOS Client: recall/remember · LLM tools invoke the same memory backend through the client.
- Config → Entry: configure · Configuration flags shape runtime behavior and privacy policy.
- Metadata → Entry: package · Package metadata defines how the plugin is distributed and loaded.
- Deploy → EverOS: runs · Deployment assets package the external EverOS service stack.
- EverOS Client → EverOS: http · The plugin communicates with EverOS over HTTP.
