@openviking/openclaw-plugin 2026.6.2 → 2026.6.17-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL-AGENT.md +4 -4
- package/INSTALL-ZH.md +68 -8
- package/INSTALL.md +12 -8
- package/README.md +45 -35
- package/adapters/http-transport.ts +3 -0
- package/adapters/resource-packager.ts +141 -0
- package/auto-recall.ts +258 -27
- package/client.ts +201 -177
- package/commands/setup.ts +200 -33
- package/config/feature-gates.json +10 -0
- package/config.ts +428 -85
- package/context-engine.ts +71 -1402
- package/dist/adapters/http-transport.js +1 -0
- package/dist/adapters/resource-packager.js +114 -0
- package/dist/auto-recall.js +201 -25
- package/dist/client.js +125 -161
- package/dist/commands/setup.js +170 -32
- package/dist/config.js +285 -64
- package/dist/context-engine.js +62 -1173
- package/dist/index.js +209 -1489
- package/dist/memory-ranking.js +35 -12
- package/dist/plugin/command-registration.js +5 -0
- package/dist/plugin/openviking-archive-tools.js +210 -0
- package/dist/plugin/openviking-bypass-runtime.js +8 -0
- package/dist/plugin/openviking-client-runtime.js +28 -0
- package/dist/plugin/openviking-command-args.js +146 -0
- package/dist/plugin/openviking-command-definitions.js +206 -0
- package/dist/plugin/openviking-context-engine-ref.js +11 -0
- package/dist/plugin/openviking-context-engine-registration.js +23 -0
- package/dist/plugin/openviking-feature-gates.js +250 -0
- package/dist/plugin/openviking-import-runtime.js +50 -0
- package/dist/plugin/openviking-import-tools.js +86 -0
- package/dist/plugin/openviking-lifecycle-hooks.js +33 -0
- package/dist/plugin/openviking-memory-recall-tools.js +233 -0
- package/dist/plugin/openviking-memory-tools.js +199 -0
- package/dist/plugin/openviking-query-config-command.js +203 -0
- package/dist/plugin/openviking-query-runtime.js +367 -0
- package/dist/plugin/openviking-query-tools.js +91 -0
- package/dist/plugin/openviking-recall-trace-runtime.js +387 -0
- package/dist/plugin/openviking-recall-trace-tools.js +38 -0
- package/dist/plugin/openviking-runtime-state.js +26 -0
- package/dist/plugin/openviking-runtime-utils.js +62 -0
- package/dist/plugin/openviking-services.js +20 -0
- package/dist/plugin/openviking-session-routing-runtime.js +61 -0
- package/dist/plugin/openviking-tool-result-tools.js +268 -0
- package/dist/plugin/recall-trace-routes.js +77 -0
- package/dist/plugin/tool-registration.js +23 -0
- package/dist/process-manager.js +1 -1
- package/dist/query-config.js +336 -0
- package/dist/recall-trace.js +309 -0
- package/dist/registries/recall-resource-types.js +58 -0
- package/dist/routing/identity-routing.js +152 -0
- package/dist/routing/memory-uri.js +7 -0
- package/dist/services/context-lifecycle-service.js +847 -0
- package/dist/services/context-message-adapter.js +340 -0
- package/dist/session-transcript-repair.js +0 -1
- package/dist/text-utils.js +14 -31
- package/index.ts +271 -1873
- package/install-manifest.json +10 -1
- package/memory-ranking.ts +46 -10
- package/openclaw.plugin.json +198 -36
- package/package.json +14 -4
- package/plugin/command-registration.ts +34 -0
- package/plugin/openviking-archive-tools.ts +301 -0
- package/plugin/openviking-bypass-runtime.ts +26 -0
- package/plugin/openviking-client-runtime.ts +74 -0
- package/plugin/openviking-command-args.ts +187 -0
- package/plugin/openviking-command-definitions.ts +294 -0
- package/plugin/openviking-context-engine-ref.ts +16 -0
- package/plugin/openviking-context-engine-registration.ts +97 -0
- package/plugin/openviking-feature-gates.ts +335 -0
- package/plugin/openviking-import-runtime.ts +105 -0
- package/plugin/openviking-import-tools.ts +133 -0
- package/plugin/openviking-lifecycle-hooks.ts +65 -0
- package/plugin/openviking-memory-recall-tools.ts +368 -0
- package/plugin/openviking-memory-tools.ts +299 -0
- package/plugin/openviking-query-config-command.ts +230 -0
- package/plugin/openviking-query-formatters.ts +108 -0
- package/plugin/openviking-query-runtime.ts +476 -0
- package/plugin/openviking-query-tools.ts +161 -0
- package/plugin/openviking-recall-trace-runtime.ts +482 -0
- package/plugin/openviking-recall-trace-tools.ts +99 -0
- package/plugin/openviking-runtime-state.ts +52 -0
- package/plugin/openviking-runtime-utils.ts +67 -0
- package/plugin/openviking-services.ts +49 -0
- package/plugin/openviking-session-routing-runtime.ts +105 -0
- package/plugin/openviking-tool-result-tools.ts +397 -0
- package/plugin/recall-trace-routes.ts +133 -0
- package/plugin/tool-registration.ts +51 -0
- package/process-manager.ts +1 -1
- package/query-config.ts +400 -0
- package/recall-trace.ts +442 -0
- package/registries/openviking-tools.ts +84 -0
- package/registries/recall-resource-types.ts +74 -0
- package/routing/identity-routing.ts +210 -0
- package/routing/memory-uri.ts +8 -0
- package/services/context-lifecycle-service.ts +1209 -0
- package/services/context-message-adapter.ts +375 -0
- package/services/setup/config-writer.ts +125 -0
- package/services/setup/exit-utils.ts +5 -0
- package/services/setup/package-metadata.ts +56 -0
- package/services/setup/probe-service.ts +143 -0
- package/services/setup/setup-flow.ts +306 -0
- package/services/setup/version-compatibility.ts +41 -0
- package/session-transcript-repair.ts +0 -2
- package/skills/install-openviking-memory/SKILL.md +123 -50
- package/skills/openviking-context-database/SKILL.md +286 -0
- package/text-utils.ts +15 -34
package/INSTALL-AGENT.md
CHANGED
|
@@ -99,7 +99,7 @@ openclaw openviking setup \
|
|
|
99
99
|
Custom agent routing prefix (optional; only when the user explicitly requests a prefix):
|
|
100
100
|
|
|
101
101
|
```bash
|
|
102
|
-
openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --
|
|
102
|
+
openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --peer-prefix <PREFIX> --json
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
Slot replacement retry, only after user approval:
|
|
@@ -139,7 +139,7 @@ Also inspect:
|
|
|
139
139
|
| `health.version` | Records server version |
|
|
140
140
|
| `health.compatibility` | Determines whether to warn |
|
|
141
141
|
| `config.hasApiKey` | Confirms whether an API key was saved |
|
|
142
|
-
| `config.
|
|
142
|
+
| `config.peer_prefix` | Confirms configured peer prefix when present |
|
|
143
143
|
|
|
144
144
|
## Environment Detection
|
|
145
145
|
|
|
@@ -267,7 +267,7 @@ Core fields:
|
|
|
267
267
|
| `mode` | Legacy compatibility field. Expected value: `remote`. |
|
|
268
268
|
| `baseUrl` | OpenViking HTTP endpoint |
|
|
269
269
|
| `apiKey` | OpenViking API key |
|
|
270
|
-
| `
|
|
270
|
+
| `peer_prefix` | Optional; prefix for OpenClaw agent IDs when set. Interactive setup accepts only letters, digits, `_`, and `-`. If unset, the plugin follows session agent IDs. |
|
|
271
271
|
| `accountId` | Required for root API keys |
|
|
272
272
|
| `userId` | Required for root API keys |
|
|
273
273
|
|
|
@@ -329,7 +329,7 @@ Existing config fields are preserved during migration. The new plugin reads old
|
|
|
329
329
|
|
|
330
330
|
- `baseUrl`
|
|
331
331
|
- `apiKey`
|
|
332
|
-
- `
|
|
332
|
+
- `peer_prefix`: optional; interactive setup accepts only letters, digits, `_`, and `-`
|
|
333
333
|
|
|
334
334
|
## Backup Path: ov-install
|
|
335
335
|
|
package/INSTALL-ZH.md
CHANGED
|
@@ -46,6 +46,62 @@ node -v
|
|
|
46
46
|
openclaw --version
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
## 火山 OpenViking Service 一键接入
|
|
50
|
+
|
|
51
|
+
如果你使用的是火山控制台创建的 OpenViking Service 库,不需要启动本地 `openviking-server`。从控制台复制 OpenViking Service 的 server url、API Key,并按需配置 peer 标识:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
OPENVIKING_BASE_URL="https://api.vikingdb.cn-beijing.volces.com/openviking" \
|
|
55
|
+
OPENVIKING_API_KEY="<your-openviking-service-api-key>" \
|
|
56
|
+
bash scripts/install.sh --json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
这条命令会完成:
|
|
60
|
+
|
|
61
|
+
- 默认从 TOS `latest` 安装 OpenViking 插件。
|
|
62
|
+
- 写入 `$OPENCLAW_STATE_DIR/openviking.env`,默认是 `~/.openclaw/openviking.env`,权限为 `0600`。
|
|
63
|
+
- 调用 `openclaw openviking setup --base-url ... --api-key ...` 写入插件配置。
|
|
64
|
+
- 重启 `openclaw gateway`。
|
|
65
|
+
- 执行 `openclaw openviking status --json` 和 `openclaw config get plugins.slots.contextEngine` 验证。
|
|
66
|
+
|
|
67
|
+
如果需要把 OpenClaw assistant 说话人写成独立 `peer_id`,并让数据面 recall/search 使用对应 actor peer 视图,可以额外传:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
OPENVIKING_BASE_URL="https://api.vikingdb.cn-beijing.volces.com/openviking" \
|
|
71
|
+
OPENVIKING_API_KEY="<your-openviking-service-api-key>" \
|
|
72
|
+
OPENVIKING_PEER_ROLE="assistant" \
|
|
73
|
+
OPENVIKING_PEER_PREFIX="openclaw-prod" \
|
|
74
|
+
bash scripts/install.sh --json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
如果使用 root key 或可信服务身份,补充租户信息:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
OPENVIKING_BASE_URL="https://api.vikingdb.cn-beijing.volces.com/openviking" \
|
|
81
|
+
OPENVIKING_API_KEY="<root-key>" \
|
|
82
|
+
OPENVIKING_ACCOUNT_ID="<account-id>" \
|
|
83
|
+
OPENVIKING_USER_ID="<user-id>" \
|
|
84
|
+
bash scripts/install.sh --json
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
离线下载包安装:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
sh build.sh
|
|
91
|
+
OPENVIKING_BASE_URL="https://api.vikingdb.cn-beijing.volces.com/openviking" \
|
|
92
|
+
OPENVIKING_API_KEY="<your-openviking-service-api-key>" \
|
|
93
|
+
OPENVIKING_PEER_ROLE="assistant" \
|
|
94
|
+
OPENVIKING_PEER_PREFIX="openclaw-prod" \
|
|
95
|
+
bash output/install.sh --source tarball --tarball output/openviking.tgz --json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
接入后,在火山 OpenViking Service 控制台检查:
|
|
99
|
+
|
|
100
|
+
- 发送一轮 OpenClaw 对话后,`Session` 下出现原始会话。
|
|
101
|
+
- 触发 `/compact` 或等待 commit 后,`User/memories` 出现长期记忆。
|
|
102
|
+
- 如果配置了 `peer_role=assistant`,数据面 recall/search 会携带对应 `X-OpenViking-Actor-Peer`,session message 仍用 body `peer_id` 做消息归因。
|
|
103
|
+
- 通过手动 `/add-resource` 导入文档、URL 或目录后,`Resources` 下出现对应知识,并可做目录递归检索。Agent 可见的 `add_resource` 工具默认禁用,只有显式设置 `enableAddResourceTool=true` 后才暴露。
|
|
104
|
+
|
|
49
105
|
## 启动 OpenViking Server
|
|
50
106
|
|
|
51
107
|
如果 OpenViking 和 OpenClaw 在同一台机器上,最短流程是:
|
|
@@ -141,10 +197,10 @@ openclaw openviking setup \
|
|
|
141
197
|
openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --force-slot --json
|
|
142
198
|
```
|
|
143
199
|
|
|
144
|
-
|
|
200
|
+
如需给默认 assistant peer 路由增加前缀,可以额外传:
|
|
145
201
|
|
|
146
202
|
```bash
|
|
147
|
-
openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --
|
|
203
|
+
openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --peer-role assistant --peer-prefix <PREFIX> --json
|
|
148
204
|
```
|
|
149
205
|
|
|
150
206
|
### 3. 重启 OpenClaw Gateway
|
|
@@ -205,7 +261,8 @@ plugins.entries.openviking.config
|
|
|
205
261
|
| `mode` | `remote` | 兼容旧配置的字段。当前只支持 remote。 |
|
|
206
262
|
| `baseUrl` | `http://127.0.0.1:1933` | OpenViking HTTP 地址 |
|
|
207
263
|
| `apiKey` | 空 | OpenViking API key |
|
|
208
|
-
| `
|
|
264
|
+
| `peer_role` | `assistant` | Peer 身份模式:`none`、`assistant` 或 `person`。Session message 使用 body `peer_id`;数据面 recall/search 使用 `X-OpenViking-Actor-Peer`。 |
|
|
265
|
+
| `peer_prefix` | 空 | `peer_role=assistant` 时 assistant `peer_id` / actor peer 值的可选前缀。 |
|
|
209
266
|
| `accountId` | 空 | 使用 root API key 时需要 |
|
|
210
267
|
| `userId` | 空 | 使用 root API key 时需要 |
|
|
211
268
|
|
|
@@ -229,14 +286,16 @@ openclaw config get plugins.entries.openviking.config
|
|
|
229
286
|
| --- | --- | --- |
|
|
230
287
|
| `baseUrl` | `http://127.0.0.1:1933` | 远端 OpenViking 服务地址 |
|
|
231
288
|
| `apiKey` | 空 | 远端 OpenViking API Key;服务端未开启认证时可不填 |
|
|
232
|
-
| `
|
|
289
|
+
| `peer_role` | `assistant` | Peer 身份模式:`none`、`assistant` 或 `person`;session message 使用 body `peer_id`,数据面 recall/search 使用 `X-OpenViking-Actor-Peer` |
|
|
290
|
+
| `peer_prefix` | 空 | `peer_role=assistant` 时 assistant `peer_id` / actor peer 值的可选前缀 |
|
|
233
291
|
|
|
234
292
|
常见设置:
|
|
235
293
|
|
|
236
294
|
```bash
|
|
237
295
|
openclaw config set plugins.entries.openviking.config.baseUrl http://your-server:1933
|
|
238
296
|
openclaw config set plugins.entries.openviking.config.apiKey your-api-key
|
|
239
|
-
openclaw config set plugins.entries.openviking.config.
|
|
297
|
+
openclaw config set plugins.entries.openviking.config.peer_role assistant
|
|
298
|
+
openclaw config set plugins.entries.openviking.config.peer_prefix your-prefix
|
|
240
299
|
```
|
|
241
300
|
|
|
242
301
|
## 升级
|
|
@@ -289,7 +348,8 @@ ov-install
|
|
|
289
348
|
| `--current-version` | 查看 helper 记录的当前版本 |
|
|
290
349
|
| `--base-url URL` | OpenViking 服务器地址(启用非交互模式) |
|
|
291
350
|
| `--api-key KEY` | OpenViking API key |
|
|
292
|
-
| `--
|
|
351
|
+
| `--peer-role ROLE` | Peer role:`none`、`assistant` 或 `person` |
|
|
352
|
+
| `--peer-prefix PREFIX` | assistant `peer_id` / actor peer 值的前缀 |
|
|
293
353
|
| `--update` | 更新 helper 管理的安装 |
|
|
294
354
|
|
|
295
355
|
面向用户的安装,请先使用 `openclaw plugins install clawhub:@openviking/openclaw-plugin`。只有作为备用路径时才选择 `ov-install`。
|
|
@@ -315,7 +375,7 @@ openclaw gateway restart
|
|
|
315
375
|
openclaw openviking status --json
|
|
316
376
|
```
|
|
317
377
|
|
|
318
|
-
已有的配置字段(`baseUrl`、`apiKey`、`
|
|
378
|
+
已有的配置字段(`baseUrl`、`apiKey`、`peer_role`、`peer_prefix` 等)会保留。
|
|
319
379
|
|
|
320
380
|
### 旧插件 ID(memory-openviking,版本 < 0.3.x)
|
|
321
381
|
|
|
@@ -342,4 +402,4 @@ openclaw openviking status --json
|
|
|
342
402
|
bash examples/openclaw-plugin/upgrade_scripts/cleanup-memory-openviking.sh
|
|
343
403
|
```
|
|
344
404
|
|
|
345
|
-
另见:[INSTALL.md](./INSTALL.md)
|
|
405
|
+
另见:[INSTALL.md](./INSTALL.md)、[INSTALL-AGENT.md](./INSTALL-AGENT.md) 和 [docs/openviking-tos-install-guide.md](./docs/openviking-tos-install-guide.md)。
|
package/INSTALL.md
CHANGED
|
@@ -141,10 +141,10 @@ If another context engine already owns the slot, setup will not replace it by de
|
|
|
141
141
|
openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --force-slot --json
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
If you
|
|
144
|
+
If you want assistant messages to carry a prefixed `peer_id` and data-plane recall/search requests to use the matching actor peer view, pass a prefix explicitly:
|
|
145
145
|
|
|
146
146
|
```bash
|
|
147
|
-
openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --
|
|
147
|
+
openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --peer-role assistant --peer-prefix <PREFIX> --json
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
### 3. Restart OpenClaw Gateway
|
|
@@ -205,7 +205,8 @@ Core fields:
|
|
|
205
205
|
| `mode` | `remote` | Legacy compatibility field. Only remote mode is supported. |
|
|
206
206
|
| `baseUrl` | `http://127.0.0.1:1933` | OpenViking HTTP endpoint |
|
|
207
207
|
| `apiKey` | empty | OpenViking API key |
|
|
208
|
-
| `
|
|
208
|
+
| `peer_role` | `assistant` | Peer identity mode: `none`, `assistant`, or `person`. Session messages use body `peer_id`; data-plane recall/search uses `X-OpenViking-Actor-Peer`. |
|
|
209
|
+
| `peer_prefix` | empty | Optional prefix for assistant `peer_id` / actor peer values when `peer_role=assistant`. |
|
|
209
210
|
| `accountId` | empty | Required when using a root API key |
|
|
210
211
|
| `userId` | empty | Required when using a root API key |
|
|
211
212
|
|
|
@@ -271,7 +272,8 @@ Useful backup/source flags:
|
|
|
271
272
|
| `--current-version` | Print the version tracked by the helper |
|
|
272
273
|
| `--base-url URL` | OpenViking server URL (enables non-interactive mode) |
|
|
273
274
|
| `--api-key KEY` | OpenViking API key |
|
|
274
|
-
| `--
|
|
275
|
+
| `--peer-role ROLE` | Peer role: `none`, `assistant`, or `person` |
|
|
276
|
+
| `--peer-prefix PREFIX` | Prefix for assistant `peer_id` / actor peer values |
|
|
275
277
|
| `--update` | Update an existing helper-managed install |
|
|
276
278
|
|
|
277
279
|
For user-facing installs, use `openclaw plugins install clawhub:@openviking/openclaw-plugin` first. Choose `ov-install` only as the backup path.
|
|
@@ -297,7 +299,7 @@ openclaw gateway restart
|
|
|
297
299
|
openclaw openviking status --json
|
|
298
300
|
```
|
|
299
301
|
|
|
300
|
-
Your existing config fields
|
|
302
|
+
Your existing config fields such as `baseUrl`, `apiKey`, `peer_role`, and `peer_prefix` are preserved.
|
|
301
303
|
|
|
302
304
|
The plugin configuration lives under `plugins.entries.openviking.config`.
|
|
303
305
|
|
|
@@ -315,14 +317,16 @@ The plugin connects to an existing remote OpenViking server.
|
|
|
315
317
|
| --- | --- | --- |
|
|
316
318
|
| `baseUrl` | `http://127.0.0.1:1933` | Remote OpenViking HTTP endpoint |
|
|
317
319
|
| `apiKey` | empty | Optional OpenViking API key |
|
|
318
|
-
| `
|
|
320
|
+
| `peer_role` | `assistant` | Peer identity mode: `none`, `assistant`, or `person`; session messages use body `peer_id`, while data-plane recall/search uses `X-OpenViking-Actor-Peer` |
|
|
321
|
+
| `peer_prefix` | empty | Optional prefix for assistant `peer_id` / actor peer values when `peer_role=assistant` |
|
|
319
322
|
|
|
320
323
|
Common settings:
|
|
321
324
|
|
|
322
325
|
```bash
|
|
323
326
|
openclaw config set plugins.entries.openviking.config.baseUrl http://your-server:1933
|
|
324
327
|
openclaw config set plugins.entries.openviking.config.apiKey your-api-key
|
|
325
|
-
openclaw config set plugins.entries.openviking.config.
|
|
328
|
+
openclaw config set plugins.entries.openviking.config.peer_role assistant
|
|
329
|
+
openclaw config set plugins.entries.openviking.config.peer_prefix your-prefix
|
|
326
330
|
```
|
|
327
331
|
|
|
328
332
|
## Start
|
|
@@ -359,4 +363,4 @@ Or use the cleanup script:
|
|
|
359
363
|
bash examples/openclaw-plugin/upgrade_scripts/cleanup-memory-openviking.sh
|
|
360
364
|
```
|
|
361
365
|
|
|
362
|
-
See also: [INSTALL-ZH.md](./INSTALL-ZH.md)
|
|
366
|
+
See also: [INSTALL-ZH.md](./INSTALL-ZH.md), [INSTALL-AGENT.md](./INSTALL-AGENT.md), and [docs/openviking-tos-install-guide.md](./docs/openviking-tos-install-guide.md).
|
package/README.md
CHANGED
|
@@ -39,20 +39,26 @@ Once installed, the plugin provides these agent tools:
|
|
|
39
39
|
| `memory_forget` | Delete memories by URI or query |
|
|
40
40
|
| `ov_archive_search` | Search across archives by keyword |
|
|
41
41
|
| `ov_archive_expand` | Expand an archive back to raw messages |
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
42
|
+
| `ov_recall_trace` | Inspect why recall/search returned or injected specific results |
|
|
43
|
+
| `add_resource` | Import documents, URLs, or Git repos when explicitly enabled |
|
|
44
|
+
| `add_skill` | Import OpenViking skills |
|
|
44
45
|
| `ov_search` | Search imported resources and skills |
|
|
46
|
+
| `ov_read` | Read the full original content of one exact OpenViking URI |
|
|
47
|
+
| `ov_multi_read` | Read the full original content of multiple OpenViking URIs |
|
|
48
|
+
| `ov_list` | List OpenViking directories after search to inspect sibling chunks and overview files |
|
|
45
49
|
| `openviking_tool_result_read` | Restore the full original content of an externalized tool result |
|
|
46
50
|
| `openviking_tool_result_search` | Search inside an externalized tool result by keyword |
|
|
47
51
|
| `openviking_tool_result_list` | List externalized tool results in the current session |
|
|
48
52
|
|
|
53
|
+
`add_resource` is hidden from agents by default (`enableAddResourceTool=false`), while manual `/add-resource` remains available. Configure `recallTargetTypes` to choose default recall targets (`user`, `agent`, `resource`); legacy `recallResources=true` appends `resource` only when `recallTargetTypes` is unset.
|
|
54
|
+
|
|
49
55
|
## Data Flow & Privacy
|
|
50
56
|
|
|
51
57
|
- **What is sent**: User/assistant message text from each turn (after stripping injected memory blocks and metadata noise).
|
|
52
58
|
- **Where it goes**: Your configured OpenViking server (`baseUrl`). The plugin only sends data to that server; downstream model/provider data handling (embedding, VLM) depends on the server's configuration.
|
|
53
|
-
- **Storage**: All data lives on your OpenViking server under `viking://user
|
|
54
|
-
- **API Key**: Sent as `X-
|
|
55
|
-
- **Multi-tenant isolation**: Supports `accountId
|
|
59
|
+
- **Storage**: All data lives on your OpenViking server under `viking://user/*` (including `viking://user/sessions/*`) and `viking://resources/*`.
|
|
60
|
+
- **API Key**: Sent as `X-API-Key` header over your configured connection. Never logged or forwarded.
|
|
61
|
+
- **Multi-tenant isolation**: Supports `accountId` and `userId`. Optional `peer_role` / `peer_prefix` controls whether OpenClaw speakers are written as OpenViking `peer_id`.
|
|
56
62
|
|
|
57
63
|
## Verify
|
|
58
64
|
|
|
@@ -68,6 +74,11 @@ openclaw config get plugins.slots.contextEngine # should output: openviking
|
|
|
68
74
|
| [INSTALL.md](./INSTALL.md) | Full install, upgrade, and uninstall guide |
|
|
69
75
|
| [INSTALL-ZH.md](./INSTALL-ZH.md) | Chinese install guide |
|
|
70
76
|
| [INSTALL-AGENT.md](./INSTALL-AGENT.md) | Agent-oriented operator guide |
|
|
77
|
+
| [docs/openviking-tos-install-guide.md](./docs/openviking-tos-install-guide.md) | TOS release bundle publishing and installer guide |
|
|
78
|
+
| [docs/openviking-openclaw-plugin-guide.md](./docs/openviking-openclaw-plugin-guide.md) | Comprehensive Chinese guide for usage, configuration, debugging, testing, build, release, deployment, and rollback |
|
|
79
|
+
| [docs/openviking-websocket-rpc-api.md](./docs/openviking-websocket-rpc-api.md) | Gateway WebSocket RPC usage for OpenViking tools |
|
|
80
|
+
| [docs/openviking-runtime-query-config.md](./docs/openviking-runtime-query-config.md) | Runtime query config scopes, fields, and commands |
|
|
81
|
+
| [docs/openviking-install-package-contract.md](./docs/openviking-install-package-contract.md) | Package and install contract verification notes |
|
|
71
82
|
|
|
72
83
|
> **Plugin vs Skill**: This page is for `@openviking/openclaw-plugin` (the context-engine plugin). Do **not** use `clawhub install openviking` — that installs a different AgentSkill.
|
|
73
84
|
|
|
@@ -99,53 +110,45 @@ The diagram above reflects the current implementation boundary:
|
|
|
99
110
|
|
|
100
111
|
- OpenClaw remains the primary runtime on the left. The plugin does not take over agent execution.
|
|
101
112
|
- The middle layer combines hooks, the context engine, tools, and runtime management in one plugin registration.
|
|
102
|
-
- All HTTP traffic goes through `OpenVikingClient`, which centralizes
|
|
103
|
-
- The OpenViking service owns sessions, memories, archives, and Phase 2 extraction, with storage under `viking://user
|
|
113
|
+
- All HTTP traffic goes through `OpenVikingClient`, which centralizes tenant headers and routing logs.
|
|
114
|
+
- The OpenViking service owns sessions, memories, archives, and Phase 2 extraction, with storage under `viking://user/*` (including `viking://user/sessions/*`) and `viking://resources/*`.
|
|
104
115
|
|
|
105
116
|
That split lets OpenClaw stay focused on reasoning and orchestration while OpenViking becomes the source of truth for long-lived context.
|
|
106
117
|
|
|
107
118
|
## Identity and Routing
|
|
108
119
|
|
|
109
|
-
The plugin
|
|
120
|
+
The plugin keeps OpenClaw session identity in session and peer metadata. It does not send an OpenViking agent identity or create an agent namespace.
|
|
110
121
|
|
|
111
122
|
The main rules are:
|
|
112
123
|
|
|
113
124
|
- reuse `sessionId` directly when it is already a UUID
|
|
114
125
|
- prefer `sessionKey` when deriving a stable `ovSessionId`
|
|
115
126
|
- normalize unsafe path characters, or fall back to a stable SHA-256 when needed
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
127
|
+
- `peer_role=assistant` is the default and writes assistant messages with `peer_id=<sessionAgent>`; if `peer_prefix` is set, the value becomes `<peer_prefix>_<sessionAgent>`
|
|
128
|
+
- `peer_role=none` disables peer message attribution and actor-peer routing
|
|
129
|
+
- `peer_role=person` writes user messages with `peer_id` derived from OpenClaw sender identity; assistant messages do not get `peer_id`
|
|
130
|
+
- data-plane recall/search/read/import/delete sends the same resolved peer identity as `X-OpenViking-Actor-Peer` when `peer_role` is `assistant` or `person`
|
|
131
|
+
- when OpenClaw does not provide a session agent, use its default agent `main` for local session and assistant peer metadata
|
|
120
132
|
- only add `X-OpenViking-Account` / `X-OpenViking-User` when `accountId` / `userId` are explicitly configured
|
|
121
133
|
|
|
122
|
-
This matters because
|
|
134
|
+
This matters because OpenViking tenant identity is account/user-scoped, while OpenClaw agent identity is runtime metadata.
|
|
123
135
|
|
|
124
136
|
The recommended remote-mode configuration only needs:
|
|
125
137
|
|
|
126
138
|
- `baseUrl`
|
|
127
139
|
- `apiKey`
|
|
128
|
-
- `
|
|
140
|
+
- optionally `peer_role`
|
|
141
|
+
- optionally `peer_prefix` when `peer_role=assistant`
|
|
129
142
|
|
|
130
143
|
In this setup:
|
|
131
144
|
|
|
132
145
|
- `apiKey` should usually be a user key
|
|
146
|
+
- new installs default to `peer_role=assistant`
|
|
133
147
|
- `accountId` / `userId` are advanced options only when the deployment needs explicit identity headers, such as root-key or trusted-server flows
|
|
134
|
-
- `isolateUserScopeByAgent` / `isolateAgentScopeByUser` must match the server-side account namespace policy when using the PR #1356 canonical namespace model
|
|
135
|
-
- `agentScopeMode` is a deprecated compatibility alias for older hash-based routing and should only be used against older servers
|
|
136
|
-
|
|
137
|
-
### Canonical namespace policy
|
|
138
|
-
|
|
139
|
-
For OpenViking servers that include PR #1356, the plugin no longer treats agent or user scope as a locally computed hash. Instead it expands shorthand aliases into canonical URIs using the configured namespace policy:
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
- `viking://user/<user_id>/memories` when `isolateUserScopeByAgent=false`
|
|
143
|
-
- `viking://user/<user_id>/agent/<agent_id>/memories` when `isolateUserScopeByAgent=true`
|
|
144
|
-
- `viking://agent/memories`
|
|
145
|
-
- `viking://agent/<agent_id>/memories` when `isolateAgentScopeByUser=false`
|
|
146
|
-
- `viking://agent/<agent_id>/user/<user_id>/memories` when `isolateAgentScopeByUser=true`
|
|
149
|
+
### User namespace
|
|
147
150
|
|
|
148
|
-
The plugin
|
|
151
|
+
The plugin writes and searches user-scoped memory through `viking://user/...`; OpenViking resolves that alias from the request tenant and actor-peer context. Deprecated agent URI paths are not used by the plugin.
|
|
149
152
|
|
|
150
153
|
## assemble Recall Flow
|
|
151
154
|
|
|
@@ -161,9 +164,9 @@ During recall, the plugin:
|
|
|
161
164
|
1. Extracts query text from the latest user message.
|
|
162
165
|
2. Resolves the agent routing for the current `sessionId/sessionKey`.
|
|
163
166
|
3. Runs a quick availability precheck so model requests do not stall when OpenViking is unavailable.
|
|
164
|
-
4. Queries
|
|
167
|
+
4. Queries the configured `recallTargetTypes` (`user,agent` by default; optionally `resource`; use `ov_archive_search` and `ov_archive_expand` for session history).
|
|
165
168
|
5. Deduplicates, threshold-filters, reranks, and trims the results under a token budget.
|
|
166
|
-
6. Prepends the selected memories as a `<
|
|
169
|
+
6. Prepends the selected memories as a `## Long-term Memories` section inside `<openviking-context>` to the current user message; it does not append a standalone synthetic user message.
|
|
167
170
|
|
|
168
171
|
The reranking logic is not pure vector-score sorting. The current implementation also considers:
|
|
169
172
|
|
|
@@ -198,7 +201,7 @@ That means OpenClaw sees "compressed history summary + archive index + active me
|
|
|
198
201
|
- it slices only the newly added messages
|
|
199
202
|
- it keeps only `user` / `assistant` capture text
|
|
200
203
|
- it preserves `toolCall` / `toolResult` content in the serialized turn text
|
|
201
|
-
- it strips injected `<relevant-memories>` blocks and metadata noise before capture
|
|
204
|
+
- it strips injected `<openviking-context>` blocks, historical `<relevant-memories>` blocks, and metadata noise before capture
|
|
202
205
|
- it appends the sanitized turn text into the OpenViking session
|
|
203
206
|
|
|
204
207
|
After that, the plugin checks `pending_tokens`. Once the session crosses `commitTokenThreshold`, it triggers `commit(wait=false)`:
|
|
@@ -232,15 +235,19 @@ So `afterTurn()` is closer to "incremental append plus threshold-triggered async
|
|
|
232
235
|
|
|
233
236
|
## Tools and Expandability
|
|
234
237
|
|
|
235
|
-
Beyond automatic behavior, the plugin exposes
|
|
238
|
+
Beyond automatic behavior, the plugin exposes these tools directly:
|
|
236
239
|
|
|
237
240
|
- `memory_recall`: explicit long-term memory search
|
|
238
241
|
- `memory_store`: write explicit long-term facts into an OpenViking session and trigger commit
|
|
239
242
|
- `memory_forget`: delete by URI, or search first and remove a single strong match
|
|
240
243
|
- `ov_archive_expand`: expand a concrete archive back into raw messages
|
|
241
|
-
- `
|
|
242
|
-
- `
|
|
244
|
+
- `ov_recall_trace`: inspect recent recall/search trace records when `traceRecall` is enabled
|
|
245
|
+
- `add_resource`: import a document, directory, URL, or Git repository as an OpenViking resource when explicitly enabled
|
|
246
|
+
- `add_skill`: import or register an OpenViking skill
|
|
243
247
|
- `ov_search`: search OpenViking resources and skills, especially after importing them
|
|
248
|
+
- `ov_read`: read one exact `viking://` URI returned by `ov_search` or `ov_list`
|
|
249
|
+
- `ov_multi_read`: read multiple exact `viking://` URIs, useful for an overview plus sibling chunks
|
|
250
|
+
- `ov_list`: list a hit's parent directory after `ov_search` to recover sibling chunks, `.overview.md`, and related split-document context
|
|
244
251
|
|
|
245
252
|
They serve different roles:
|
|
246
253
|
|
|
@@ -251,6 +258,9 @@ They serve different roles:
|
|
|
251
258
|
- `add_resource` lets the agent save explicit document or repository import requests without asking the user to remember slash commands
|
|
252
259
|
- `add_skill` imports skills into OpenViking, while `add_resource` imports resources
|
|
253
260
|
- `ov_search` closes the loop after import by letting the user or agent confirm and consume resources and skills
|
|
261
|
+
- `ov_read` turns a ranked hit into original evidence before answering precise documentation, codebase, configuration, or procedural questions
|
|
262
|
+
- `ov_multi_read` reads overview and sibling chunks together when a split document needs more context than a single hit
|
|
263
|
+
- `ov_list` complements `ov_search` when a ranked hit is only one chunk of a larger procedure or document
|
|
254
264
|
|
|
255
265
|
`ov_archive_expand` is especially important because `assemble()` normally returns archive summaries and indexes, not the full raw transcript.
|
|
256
266
|
|
|
@@ -259,7 +269,7 @@ They serve different roles:
|
|
|
259
269
|
Resource and skill imports are intentionally separate because they land in different OpenViking namespaces and use different server APIs:
|
|
260
270
|
|
|
261
271
|
- resources go through `/api/v1/resources` and land under `viking://resources/...`
|
|
262
|
-
- skills go through `/api/v1/skills` and land under `viking://
|
|
272
|
+
- skills go through `/api/v1/skills` and land under `viking://user/skills/...`
|
|
263
273
|
|
|
264
274
|
The plugin also registers explicit slash commands for manual imports:
|
|
265
275
|
|
|
@@ -267,7 +277,7 @@ The plugin also registers explicit slash commands for manual imports:
|
|
|
267
277
|
/add-resource ./README.md --to viking://resources/openviking-readme --wait
|
|
268
278
|
/add-skill ./skills/install-openviking-memory --wait
|
|
269
279
|
/ov-search "OpenViking install" --uri viking://resources/openviking-readme
|
|
270
|
-
/ov-search "memory install skill" --uri viking://
|
|
280
|
+
/ov-search "memory install skill" --uri viking://user/skills
|
|
271
281
|
```
|
|
272
282
|
|
|
273
283
|
Resource import supports remote URLs, Git URLs, local files, local directories, and uploaded zip files. OpenViking's built-in parsers cover common documents and media such as Markdown, text, PDF, HTML, Word, PowerPoint, Excel, EPUB, images, audio, and video. Directory imports also accept common code, documentation, and config file extensions such as `.py`, `.js`, `.ts`, `.go`, `.rs`, `.java`, `.cpp`, `.json`, `.yaml`, `.toml`, `.csv`, `.rst`, `.proto`, `.tf`, and `.vue`.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { once } from "node:events";
|
|
3
|
+
import { createWriteStream } from "node:fs";
|
|
4
|
+
import { mkdtemp, readdir, readFile, rm, stat } from "node:fs/promises";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { basename, dirname, join, relative } from "node:path";
|
|
7
|
+
|
|
8
|
+
import { Zip, ZipDeflate } from "fflate";
|
|
9
|
+
|
|
10
|
+
const REMOTE_RESOURCE_PREFIXES = ["http://", "https://", "git@", "ssh://", "git://"];
|
|
11
|
+
|
|
12
|
+
export type PackagedResourceSource =
|
|
13
|
+
| { kind: "remote"; path: string }
|
|
14
|
+
| { kind: "upload"; uploadPath: string; sourceName?: string; cleanupPath?: string };
|
|
15
|
+
|
|
16
|
+
export type ResourcePackager = {
|
|
17
|
+
prepareResourceSource(pathOrUrl: string): Promise<PackagedResourceSource>;
|
|
18
|
+
prepareLocalUploadSource(path: string): Promise<PackagedResourceSource>;
|
|
19
|
+
createTempUploadBody(uploadPath: string): Promise<BodyInit>;
|
|
20
|
+
cleanup(source?: PackagedResourceSource): Promise<void>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function toBlobPart(value: Buffer): ArrayBuffer {
|
|
24
|
+
return value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength) as ArrayBuffer;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isRemoteResourceSource(source: string): boolean {
|
|
28
|
+
return REMOTE_RESOURCE_PREFIXES.some((prefix) => source.startsWith(prefix));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function cleanupUploadTempPath(path?: string): Promise<void> {
|
|
32
|
+
if (!path) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
await rm(path, { force: true }).catch(() => undefined);
|
|
36
|
+
await rm(dirname(path), { recursive: true, force: true }).catch(() => undefined);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function zipDirectoryForUpload(dirPath: string): Promise<string> {
|
|
40
|
+
const rootStats = await stat(dirPath);
|
|
41
|
+
if (!rootStats.isDirectory()) {
|
|
42
|
+
throw new Error(`Not a directory: ${dirPath}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const zipDir = await mkdtemp(join(tmpdir(), "openviking-openclaw-upload-"));
|
|
46
|
+
const zipPath = join(zipDir, `${basename(dirPath).replace(/[^a-zA-Z0-9._-]/g, "_")}-${randomUUID()}.zip`);
|
|
47
|
+
const output = createWriteStream(zipPath);
|
|
48
|
+
const outputClosed = once(output, "close");
|
|
49
|
+
const outputErrored = once(output, "error").then(([err]) => Promise.reject(err));
|
|
50
|
+
const zip = new Zip((err, chunk, final) => {
|
|
51
|
+
if (err) {
|
|
52
|
+
output.destroy(err);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (chunk?.length) {
|
|
56
|
+
output.write(Buffer.from(chunk));
|
|
57
|
+
}
|
|
58
|
+
if (final) {
|
|
59
|
+
output.end();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const walk = async (currentDir: string) => {
|
|
64
|
+
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
65
|
+
for (const entry of entries) {
|
|
66
|
+
const fullPath = join(currentDir, entry.name);
|
|
67
|
+
if (entry.isDirectory()) {
|
|
68
|
+
await walk(fullPath);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (!entry.isFile()) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const relPath = relative(dirPath, fullPath).split("\\").join("/");
|
|
75
|
+
if (!relPath || relPath.startsWith("../") || relPath.includes("/../")) {
|
|
76
|
+
throw new Error(`Unsafe relative path while zipping: ${relPath}`);
|
|
77
|
+
}
|
|
78
|
+
const file = new ZipDeflate(relPath);
|
|
79
|
+
zip.add(file);
|
|
80
|
+
file.push(new Uint8Array(await readFile(fullPath)), true);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
try {
|
|
84
|
+
await walk(dirPath);
|
|
85
|
+
zip.end();
|
|
86
|
+
await Promise.race([outputClosed, outputErrored]);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
zip.terminate();
|
|
89
|
+
output.destroy(err as Error);
|
|
90
|
+
await cleanupUploadTempPath(zipPath);
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
return zipPath;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function prepareLocalUploadSource(path: string, includeSourceName = false): Promise<PackagedResourceSource> {
|
|
97
|
+
const localStats = await stat(path);
|
|
98
|
+
if (localStats.isDirectory()) {
|
|
99
|
+
const uploadPath = await zipDirectoryForUpload(path);
|
|
100
|
+
return {
|
|
101
|
+
kind: "upload",
|
|
102
|
+
uploadPath,
|
|
103
|
+
cleanupPath: uploadPath,
|
|
104
|
+
...(includeSourceName ? { sourceName: basename(path) } : {}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (!localStats.isFile()) {
|
|
108
|
+
throw new Error(`Path is not a file or directory: ${path}`);
|
|
109
|
+
}
|
|
110
|
+
return { kind: "upload", uploadPath: path };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export const defaultResourcePackager: ResourcePackager = {
|
|
114
|
+
async prepareResourceSource(pathOrUrl: string): Promise<PackagedResourceSource> {
|
|
115
|
+
if (isRemoteResourceSource(pathOrUrl)) {
|
|
116
|
+
return { kind: "remote", path: pathOrUrl };
|
|
117
|
+
}
|
|
118
|
+
return prepareLocalUploadSource(pathOrUrl, true);
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
async prepareLocalUploadSource(path: string): Promise<PackagedResourceSource> {
|
|
122
|
+
return prepareLocalUploadSource(path, false);
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
async createTempUploadBody(uploadPath: string): Promise<BodyInit> {
|
|
126
|
+
const fileBytes = await readFile(uploadPath);
|
|
127
|
+
const form = new FormData();
|
|
128
|
+
form.append(
|
|
129
|
+
"file",
|
|
130
|
+
new Blob([toBlobPart(fileBytes)], { type: "application/octet-stream" }),
|
|
131
|
+
basename(uploadPath),
|
|
132
|
+
);
|
|
133
|
+
return form;
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
async cleanup(source?: PackagedResourceSource): Promise<void> {
|
|
137
|
+
if (source?.kind === "upload") {
|
|
138
|
+
await cleanupUploadTempPath(source.cleanupPath);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
};
|