# session-store

Unified session and message access across AI agent tools

## Installation

### From DevPi (private registry)

```bash
uv add session-store
```

> Requires the DevPi index to be configured in `~/.config/uv/uv.toml`:
> ```toml
> index-strategy = "unsafe-best-match"
>
> [[index]]
> name = "devpi"
> url = "https://pypi.registry.hochguertel.work/root/dev/+simple/"
> ```

### From source (monorepo)

```bash
git clone https://pastoral-oyster.pikapod.net/tools/ai-session-tools.git
cd ai-session-tools
uv sync --all-packages
```

## Usage

`SessionStore` is the client-facing facade. It composes the per-tool adapters
(`devin-session`, `opencode-session`, `copilot-session`) so downstream
consumers only need to talk to `session-store`.

```python
from session_store import SessionStore

store = SessionStore()

# List sessions from all tools (merged, most recent first)
all_sessions = store.list_sessions()

# List sessions from Devin only
devin_sessions = store.list_sessions(tool="devin")

# Load a specific session's messages
session = store.get_session("plum-produce", tool="devin")
for msg in session.messages:
    print(f"[{msg.role}] {msg.content[:80]}")

# Select a specific message by expression
msg = store.select_message("latest", session_id="plum-produce", tool="devin")
msg = store.select_message("HEAD~3", session_id="plum-produce", tool="devin")
msg = store.select_message("search:naming", session_id="plum-produce", tool="devin")

# Auto-detect tool and session, then select latest message
msg = store.select_message("latest")  # auto-detects tool + session

# Auto-detect just the tool
tool = store.detect_tool()  # "devin"

# Auto-detect session for a specific tool
session_id = store.detect_session(tool="devin", cwd="/root/tools/ai-session-tools")
```

Supported target expressions for `select_message`:

| Expression      | Meaning                                              |
|-----------------|------------------------------------------------------|
| `latest`        | Most recent assistant message                        |
| `HEAD`          | Alias for `latest`                                   |
| `HEAD~N`        | Nth message before the latest (1-based)              |
| `<number>`      | 1-based index into filtered assistant messages       |
| `first`         | First assistant message in the session               |
| `search:<text>` | First assistant message containing the text          |

## Development

```bash
# Run tests
uv run pytest libs/session-store/tests/

# Lint
uv run ruff check libs/session-store/

# Type check
uv run mypy
```

## License

MIT
