Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
84a9423
feat(stage-tamagotchi,plugin-sdk,openviking-memory): add PluginHost c…
xiaobin83 May 15, 2026
a29ed99
feat(plugin-sdk): propagate ModuleConfigEnvelope through PluginStartO…
xiaobin83 May 24, 2026
f9fda3d
fix(stage-tamagotchi): reset conversationSessionId on chat cleanup
xiaobin83 May 24, 2026
151471f
fix(stage-tamagotchi): guard plugin IPC calls and derive session ID f…
xiaobin83 May 25, 2026
3b4d849
fix(stage-tamagotchi): revoke old asset sessions and clear loaded sta…
xiaobin83 May 25, 2026
0de89e3
feat(stage-tamagotchi): gate memory persistence to plugins that suppo…
xiaobin83 May 25, 2026
97c2600
refactor(stage-tamagotchi): remove queryContext Eventa layer, use dir…
xiaobin83 May 25, 2026
71b6199
fix(stage-tamagotchi): bound memory-context lookup latency before com…
xiaobin83 May 25, 2026
4b84892
feat(host): enforce manifest schema validation in setPluginConfig
xiaobin-tal May 26, 2026
1a5854c
fix(stage-tamagotchi): separate reload error handling from post-reloa…
xiaobin-tal May 26, 2026
8695cb2
fix(stage-tamagotchi): capture session metadata synchronously in onCh…
xiaobin-tal May 26, 2026
e79b499
refactor(stage-tamagotchi): use TypeError for config field type valid…
xiaobin83 May 26, 2026
bbe8862
fix(stage-tamagotchi): reject empty values for required secret fields…
xiaobin83 May 26, 2026
ddd06e9
fix: propagate sessionId and generation through stream event context
xiaobin83 May 26, 2026
db6d513
fix(stage-tamagotchi): preserve unsaved edits and reject invalid numb…
xiaobin83 May 26, 2026
e2954ec
fix(stage-ui): prefer snapshot generation in applyRemoteSnapshot
xiaobin83 May 26, 2026
1689ec8
chore: remove completed planning document
xiaobin83 May 26, 2026
d59db36
feat(openviking-memory): refactor saveConversation to add-accumulate-…
xiaobin83 May 27, 2026
e6cf0d3
feat(openviking-memory): add memory_recall tool, rename memory_save_t…
xiaobin83 May 27, 2026
03284c8
feat(openviking-memory): implement rankForInjection memory ranking st…
xiaobin83 May 27, 2026
5ba6a9e
docs(openviking-memory): remove outdated openclaw plugin implementati…
xiaobin83 May 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# OpenViking 长期记忆插件

基于 [OpenViking](https://openviking.ai) 的长期记忆系统插件,为 AIRI 提供记忆搜索、保存和删除功能。

## 功能

### 工具列表

- **搜索记忆**(`memory_search`):根据查询关键词搜索长期记忆。返回结果格式如下:

```json
[
{
"context_type": "memory",
"uri": "viking://user/default/memories/manual/1779530859829-dly184hl.md",
"level": 2,
"score": 0.6159865260124207,
"category": "",
"match_reason": "",
"relations": [],
"abstract": "1. 该文档是一份个人日程计划笔记...",
"overview": null
},
{
"context_type": "memory",
"uri": "viking://user/default/memories/manual/1779384773203-r0jq33bf.md",
"level": 2,
"score": 0.6076329350471497,
"category": "",
"match_reason": "",
"relations": [],
"abstract": "This document is a concise personal travel plan...",
"overview": null
}
]
```

每个结果字段说明:

| 字段 | 类型 | 说明 |
|------|------|------|
| `context_type` | `string` | 上下文类型,固定为 `memory` |
| `uri` | `string` | 记忆文件的 URI,可用于 `memory_read` 工具读取完整内容 |
| `level` | `number` | 层级(0-3),数字越大表示越相关 |
| `score` | `number` | 相关性评分(0-1),越高越匹配 |
| `category` | `string` | 分类标签 |
| `match_reason` | `string` | 匹配原因说明 |
| `relations` | `array` | 关联的其它记忆 URI 列表 |
| `abstract` | `string` | 记忆内容的摘要/概述 |
| `overview` | `string \| null` | 概览信息 |

- **读取记忆**(`memory_read`):根据 URI 读取一条记忆的完整内容
- **保存记忆**(`memory_save`):将重要信息保存到长期记忆
- **保存对话记录**(`memory_save_turn`):将一轮对话(用户消息 + 助手回复 + 工具调用)保存到长期记忆。此工具由系统自动触发,AI 助手不应主动调用。
- **召回记忆**(`memory_recall`):自动召回与当前对话相关的长期记忆,用于上下文注入。此工具由系统自动触发,AI 助手不应主动调用。
- **删除记忆**(`memory_delete`):删除指定的记忆条目

> `memory_recall` 和 `memory_save_turn` 为系统级工具,由框架在对话处理流程中自动调用,用于上下文注入和对话持久化。AI 助手不会在工具选择列表中看到它们,开发者也不应手动调用。

### Session 记忆处理

对话通过 `memory_save_turn` 保存到 Session 后,系统会按以下规则决定是否将对话内容转化为可检索的记忆:

- **短对话**(累计 pending tokens < 20,000):仅保存到 Session,不参与记忆搜索
- **长对话**(累计 pending tokens ≥ 20,000):自动提交并做 embedding 处理,之后可通过记忆注入(`memory_recall`)或 Agent 主动搜索(`memory_search`)找到

例如,一个持续数小时的长对话(如聊了一整晚)达到阈值后会被 embedding,后续用户提问时系统会自动召回相关记忆片段作为上下文注入。

## 安装

### 前提条件

- AIRI Stage Tamagotchi(Electron 桌面应用)
- OpenViking 服务(默认地址:`http://localhost:1933`)

### 安装步骤

1. **构建插件**

在插件目录下执行:

```bash
cd apps/stage-tamagotchi/src/main/services/airi/plugins/examples/openviking-memory
pnpm install
pnpm run pack
```

构建完成后会在当前目录生成 `openviking-memory.tar.gz` 打包文件。

2. **将插件复制到插件目录**

根据运行环境,将打包文件解压后的 `openviking-memory/` 目录复制到对应的插件目录。

**生产环境**(打包后的应用):

| 操作系统 | 插件目录 |
|----------|----------|
| **macOS** | `~/Library/Application Support/${appId}/plugins/v1/` |
| **Windows** | `%APPDATA%\\${appId}\\plugins\\v1\\` |
| **Linux** | `$XDG_CONFIG_HOME/${appId}/plugins/v1/` 或 `~/.config/${appId}/plugins/v1/` |

> `${appId}` 为 AIRI 应用的标识符(默认 `ai.moeru.airi`),具体值请参考应用配置。

**开发环境**(`pnpm dev`):

当使用 `electron-vite dev` 运行时,Electron 使用包名作为用户数据目录,插件目录为:

| 操作系统 | 插件目录 |
|----------|----------|
| **macOS** | `~/Library/Application Support/@proj-airi/stage-tamagotchi/plugins/v1/` |
| **Windows** | `%APPDATA%\\@proj-airi\\stage-tamagotchi\\plugins\\v1\\` |
| **Linux** | `~/.config/@proj-airi/stage-tamagotchi/plugins/v1/` |

3. **在插件管理器中启用**

- 打开 Stage Tamagotchi 的开发者工具页面(DevTools)
- 进入 **Plugin Host Inspector** 页面
- 点击 **Refresh** 刷新插件列表
- 找到 `openviking-memory` 插件
- 点击 **Enable** 启用
- 点击 **Load**(或 **Load Enabled**)加载插件

4. **配置插件**

插件加载后,在插件配置页面设置以下参数:

- **服务器地址**(`baseUrl`):OpenViking 服务的 base URL,默认为 `http://localhost:1933`
- **API 密钥**(`apiKey`):OpenViking 服务的 API 密钥(可选)

### 验证安装

加载成功后,AIRI 将获得以下工具能力:

- `memory_search` — 搜索长期记忆(Agent 主动调用)
- `memory_read` — 根据 URI 读取记忆完整内容(Agent 主动调用)
- `memory_save` — 保存记忆(Agent 主动调用)
- `memory_save_turn` — 保存对话记录(系统自动触发)
- `memory_recall` — 召回记忆(系统自动触发)
- `memory_delete` — 删除记忆(Agent 主动调用)

## 开发

### 目录结构

```
openviking-memory/
├── src/
│ ├── index.ts # 插件入口,注册工具
│ └── openviking.ts # OpenViking 客户端实现
├── scripts/
│ └── pack.mjs # 打包脚本
├── dist/
│ └── index.mjs # 编译后的插件入口(仅构建产物)
├── docs/
│ ├── Readme.zh-CN.md # 本文件
│ └── openclaw-plugin-implementation-analysis.md
├── plugin.airi.json # 插件清单(entrypoint: ./index.mjs)
├── tsdown.config.ts # 构建配置
└── package.json # 依赖与构建脚本
```

### 构建

```bash
pnpm run build # 使用 tsdown 编译 TypeScript
pnpm run pack # 构建并打包为 tar.gz
```

## 配置说明

| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `baseUrl` | `string` | 是 | `http://localhost:1933` | OpenViking 服务器地址 |
| `apiKey` | `secret` | 否 | `""` | API 密钥 |

## 许可

此插件为 AIRI 示例插件,仅供学习和参考使用。
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "openviking-memory",
"type": "module",
"version": "1.0.0",
"private": true,
"description": "OpenViking 长期记忆插件",
"scripts": {
"build": "tsdown",
"dev": "pnpm run build",
"pack": "pnpm run build && tar -czf dist/openviking-memory.tar.gz plugin.airi.json -C dist/dist index.mjs"
},
"dependencies": {
"@proj-airi/plugin-protocol": "workspace:*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"apiVersion": "v1",
"kind": "manifest.plugin.airi.moeru.ai",
"name": "openviking-memory",
"displayName": "OpenViking 长期记忆",
"description": "基于 OpenViking 的长期记忆系统,提供记忆搜索、保存和删除功能",
"version": "0.1.0",
"permissions": {
"apis": [
{
"key": "proj-airi:plugin-sdk:apis:client:tools:register",
"actions": ["invoke"]
}
],
"resources": [
{
"key": "proj-airi:plugin-sdk:resources:tools",
"actions": ["write"]
}
]
},
"config": {
"schema": {
"baseUrl": {
"type": "string",
"label": "OPENVIKING_BASE_URL",
"default": "http://localhost:1933",
"required": true
},
"apiKey": {
"type": "secret",
"label": "OPENVIKING_API_KEY",
"default": "",
"required": false
}
}
},
"entrypoints": {
"electron": "./index.mjs"
}
}
Loading