# OpenViking Pi Agent Extension

Chinese version: [README.md](README.md)

This is an OpenViking extension for `pi-coding-agent`. It follows the behavior of the OpenViking `examples/opencode-plugin` implementation and adapts it to Pi's extension API for tools, context injection, session events, and runtime UI status.

## Features

- Injects indexed `viking://resources/` repositories into the system prompt before each agent run.
- Auto-recalls relevant long-term memories and appends them to the latest user message in a `<relevant-memories>` block.
- Maps each Pi session to an OpenViking session and syncs user/assistant text messages.
- Supports manual `memcommit` and periodic background commits for OpenViking memory extraction.
- Registers OpenViking tools: `memsearch`, `memfind`, `memread`, `membrowse`, `memcommit`, `memgrep`, `memglob`, `memadd`, `meadd`, `memremove`, and `memqueue`.
- Supports `memadd` for remote URLs and local files. Local files are uploaded through `POST /api/v1/resources/temp_upload` before being added with `POST /api/v1/resources`.

## File Layout

```text
examples/extensions/openviking/
├── index.ts
├── README.md
├── README.en.md
└── lib/
    ├── config.ts
    ├── http.ts
    ├── memadd-local.ts
    ├── memory-recall.ts
    ├── repo-context.ts
    ├── runtime.ts
    ├── session-sync.ts
    └── tools.ts
```

## Configuration

The extension looks for configuration files in this order:

1. The path pointed to by `OPENVIKING_PLUGIN_CONFIG`
2. Current project `.pi/openviking-config.json`
3. User-level Pi config `~/.pi/agent/openviking-config.json`
4. Extension root `openviking-config.json`

Example:

```json
{
  "endpoint": "http://localhost:1933",
  "apiKey": "",
  "account": "",
  "user": "",
  "agentId": "",
  "enabled": true,
  "timeoutMs": 30000,
  "runtime": {
    "autoStartServer": false,
    "dataDir": ""
  },
  "repoContext": {
    "enabled": true,
    "cacheTtlMs": 60000
  },
  "autoCommit": {
    "enabled": true,
    "intervalMinutes": 10
  },
  "autoRecall": {
    "enabled": true,
    "limit": 6,
    "scoreThreshold": 0.15,
    "maxContentChars": 500,
    "preferAbstract": true,
    "tokenBudget": 2000
  }
}
```

`OPENVIKING_API_KEY`, `OPENVIKING_ACCOUNT`, `OPENVIKING_USER`, and `OPENVIKING_AGENT_ID` override the same fields from the config file.

Do not publish real credentials. If this extension is packaged for npm, publish an example config such as `openviking-config.example.json` and ask users to create their own `~/.pi/agent/openviking-config.json` or project-local `.pi/openviking-config.json`.

By default, runtime data is stored in `~/.pi/agent/openviking/`:

- `openviking-memory.log`
- `openviking-session-map.json`
- `openviking-server.log`, only when `runtime.autoStartServer=true`

## Usage

Start OpenViking first:

```bash
openviking-server --config ~/.openviking/ov.conf
```

After publishing to npm, regular users should install it through Pi's package mechanism:

```bash
pi install npm:@tanyouqing/pi-openviking
```

For a temporary one-off run:

```bash
pi -e npm:@tanyouqing/pi-openviking
```

Regular users do not need to run `npm install @tanyouqing/pi-openviking` directly. A plain `npm install` only installs the package into the current Node project; it does not update Pi's package settings and Pi will not auto-load the extension from there.

For local development, load the extension by path:

```bash
pi --extension ~\your_directory\openviking\index.ts
```

You can also copy the full `openviking/` directory into the user extensions directory:

```bash
mkdir "%USERPROFILE%\.pi\agent\extensions\openviking"
xcopy /E /I download_dir\openviking "%USERPROFILE%\.pi\agent\extensions\openviking"
pi
```

## Tools

| Tool          | Purpose                                                                                                          |
| ------------- | ---------------------------------------------------------------------------------------------------------------- |
| `memsearch` | Semantic search across memories, resources, and skills. Uses deep search for complex queries or mapped sessions. |
| `memfind`   | Fast semantic search through `/api/v1/search/find`.                                                            |
| `memread`   | Read a `viking://` URI with `auto`, `abstract`, `overview`, or `read` level.                           |
| `membrowse` | Browse OpenViking filesystem paths with `list`, `tree`, or `stat`.                                         |
| `memcommit` | Commit the current Pi session to OpenViking and trigger memory extraction.                                       |
| `memgrep`   | Search exact symbols, class names, function names, error strings, or known keywords.                             |
| `memglob`   | Enumerate files by glob pattern, such as `**/*.ts` or `**/README.md`.                                        |
| `memadd`    | Add a remote URL or local file under `viking://resources/`.                                                    |
| `meadd`     | Compatibility alias for `memadd`.                                                                              |
| `memremove` | Remove a `viking://` resource. Requires `confirm: true`.                                                     |
| `memqueue`  | Show observer queue status.                                                                                      |

## Examples

Add a remote document:

```text
memadd path="https://example.com/spec.md" to="viking://resources/spec.md"
```

Add a local file:

```text
memadd path="./docs/notes.md" parent="viking://resources/" reason="project notes"
```

Search by symbol:

```text
memgrep pattern="createMemorySessionManager" uri="viking://resources/pi-agent/"
```

List matching files:

```text
memglob pattern="**/*.ts" uri="viking://resources/OpenViking/"
```

Commit the current conversation for memory extraction:

```text
memcommit
```

## Implementation Notes

- `index.ts` binds Pi lifecycle events: `session_start`, `session_tree`, `before_agent_start`, `context`, `message_end`, and `session_shutdown`.
- `repo-context.ts` caches indexed repository context and formats the system prompt block.
- `memory-recall.ts` performs recall, ranking, deduplication, and context injection.
- `session-sync.ts` handles Pi session to OpenViking session mapping, message sync, background commits, and persistence.
- `tools.ts` registers the middleware tools and converts Pi tool arguments into OpenViking HTTP requests.
- `memadd-local.ts` resolves local files, uploads temporary resources, and adds resources.
