@openviking/openclaw-plugin 2026.6.2 → 2026.6.17-dev.1

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.
Files changed (108) hide show
  1. package/INSTALL-AGENT.md +4 -4
  2. package/INSTALL-ZH.md +68 -8
  3. package/INSTALL.md +12 -8
  4. package/README.md +45 -35
  5. package/adapters/http-transport.ts +3 -0
  6. package/adapters/resource-packager.ts +141 -0
  7. package/auto-recall.ts +258 -27
  8. package/client.ts +201 -177
  9. package/commands/setup.ts +200 -33
  10. package/config/feature-gates.json +10 -0
  11. package/config.ts +428 -85
  12. package/context-engine.ts +71 -1402
  13. package/dist/adapters/http-transport.js +1 -0
  14. package/dist/adapters/resource-packager.js +114 -0
  15. package/dist/auto-recall.js +201 -25
  16. package/dist/client.js +125 -161
  17. package/dist/commands/setup.js +170 -32
  18. package/dist/config.js +285 -64
  19. package/dist/context-engine.js +62 -1173
  20. package/dist/index.js +209 -1489
  21. package/dist/memory-ranking.js +35 -12
  22. package/dist/plugin/command-registration.js +5 -0
  23. package/dist/plugin/openviking-archive-tools.js +210 -0
  24. package/dist/plugin/openviking-bypass-runtime.js +8 -0
  25. package/dist/plugin/openviking-client-runtime.js +28 -0
  26. package/dist/plugin/openviking-command-args.js +146 -0
  27. package/dist/plugin/openviking-command-definitions.js +206 -0
  28. package/dist/plugin/openviking-context-engine-ref.js +11 -0
  29. package/dist/plugin/openviking-context-engine-registration.js +23 -0
  30. package/dist/plugin/openviking-feature-gates.js +250 -0
  31. package/dist/plugin/openviking-import-runtime.js +50 -0
  32. package/dist/plugin/openviking-import-tools.js +86 -0
  33. package/dist/plugin/openviking-lifecycle-hooks.js +33 -0
  34. package/dist/plugin/openviking-memory-recall-tools.js +233 -0
  35. package/dist/plugin/openviking-memory-tools.js +199 -0
  36. package/dist/plugin/openviking-query-config-command.js +203 -0
  37. package/dist/plugin/openviking-query-runtime.js +367 -0
  38. package/dist/plugin/openviking-query-tools.js +91 -0
  39. package/dist/plugin/openviking-recall-trace-runtime.js +387 -0
  40. package/dist/plugin/openviking-recall-trace-tools.js +38 -0
  41. package/dist/plugin/openviking-runtime-state.js +26 -0
  42. package/dist/plugin/openviking-runtime-utils.js +62 -0
  43. package/dist/plugin/openviking-services.js +20 -0
  44. package/dist/plugin/openviking-session-routing-runtime.js +61 -0
  45. package/dist/plugin/openviking-tool-result-tools.js +268 -0
  46. package/dist/plugin/recall-trace-routes.js +77 -0
  47. package/dist/plugin/tool-registration.js +23 -0
  48. package/dist/process-manager.js +1 -1
  49. package/dist/query-config.js +336 -0
  50. package/dist/recall-trace.js +309 -0
  51. package/dist/registries/recall-resource-types.js +58 -0
  52. package/dist/routing/identity-routing.js +152 -0
  53. package/dist/routing/memory-uri.js +7 -0
  54. package/dist/services/context-lifecycle-service.js +847 -0
  55. package/dist/services/context-message-adapter.js +340 -0
  56. package/dist/session-transcript-repair.js +0 -1
  57. package/dist/text-utils.js +14 -31
  58. package/index.ts +271 -1873
  59. package/install-manifest.json +10 -1
  60. package/memory-ranking.ts +46 -10
  61. package/openclaw.plugin.json +198 -36
  62. package/package.json +14 -4
  63. package/plugin/command-registration.ts +34 -0
  64. package/plugin/openviking-archive-tools.ts +301 -0
  65. package/plugin/openviking-bypass-runtime.ts +26 -0
  66. package/plugin/openviking-client-runtime.ts +74 -0
  67. package/plugin/openviking-command-args.ts +187 -0
  68. package/plugin/openviking-command-definitions.ts +294 -0
  69. package/plugin/openviking-context-engine-ref.ts +16 -0
  70. package/plugin/openviking-context-engine-registration.ts +97 -0
  71. package/plugin/openviking-feature-gates.ts +335 -0
  72. package/plugin/openviking-import-runtime.ts +105 -0
  73. package/plugin/openviking-import-tools.ts +133 -0
  74. package/plugin/openviking-lifecycle-hooks.ts +65 -0
  75. package/plugin/openviking-memory-recall-tools.ts +368 -0
  76. package/plugin/openviking-memory-tools.ts +299 -0
  77. package/plugin/openviking-query-config-command.ts +230 -0
  78. package/plugin/openviking-query-formatters.ts +108 -0
  79. package/plugin/openviking-query-runtime.ts +476 -0
  80. package/plugin/openviking-query-tools.ts +161 -0
  81. package/plugin/openviking-recall-trace-runtime.ts +482 -0
  82. package/plugin/openviking-recall-trace-tools.ts +99 -0
  83. package/plugin/openviking-runtime-state.ts +52 -0
  84. package/plugin/openviking-runtime-utils.ts +67 -0
  85. package/plugin/openviking-services.ts +49 -0
  86. package/plugin/openviking-session-routing-runtime.ts +105 -0
  87. package/plugin/openviking-tool-result-tools.ts +397 -0
  88. package/plugin/recall-trace-routes.ts +133 -0
  89. package/plugin/tool-registration.ts +51 -0
  90. package/process-manager.ts +1 -1
  91. package/query-config.ts +400 -0
  92. package/recall-trace.ts +442 -0
  93. package/registries/openviking-tools.ts +84 -0
  94. package/registries/recall-resource-types.ts +74 -0
  95. package/routing/identity-routing.ts +210 -0
  96. package/routing/memory-uri.ts +8 -0
  97. package/services/context-lifecycle-service.ts +1209 -0
  98. package/services/context-message-adapter.ts +375 -0
  99. package/services/setup/config-writer.ts +125 -0
  100. package/services/setup/exit-utils.ts +5 -0
  101. package/services/setup/package-metadata.ts +56 -0
  102. package/services/setup/probe-service.ts +143 -0
  103. package/services/setup/setup-flow.ts +306 -0
  104. package/services/setup/version-compatibility.ts +41 -0
  105. package/session-transcript-repair.ts +0 -2
  106. package/skills/install-openviking-memory/SKILL.md +123 -50
  107. package/skills/openviking-context-database/SKILL.md +286 -0
  108. 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> --agent-prefix <PREFIX> --json
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.agent_prefix` | Confirms configured agent prefix when present |
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
- | `agent_prefix` | Optional; prefix for OpenClaw agent IDs when set. Interactive setup accepts only letters, digits, `_`, and `-`. If unset, the plugin follows session agent IDs. |
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
- - `agent_prefix`: optional; interactive setup accepts only letters, digits, `_`, and `-`
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
- 如需自定义 agent 路由前缀(可选;多数用户留空即可):
200
+ 如需给默认 assistant peer 路由增加前缀,可以额外传:
145
201
 
146
202
  ```bash
147
- openclaw openviking setup --base-url <OPENVIKING_URL> --api-key <API_KEY> --agent-prefix <PREFIX> --json
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
- | `agent_prefix` | 空 | OpenClaw agent ID 的可选前缀;若没有 agent ID,插件使用 `main`。交互式配置只接受字母、数字、`_` 和 `-`。 |
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
- | `agent_prefix` | 空 | OpenClaw agent ID 的可选前缀;如果拿不到 agent ID,插件使用 `main`。交互式配置只接受字母、数字、`_` 和 `-` |
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.agent_prefix your-prefix
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
- | `--agent-prefix PREFIX` | Agent 路由前缀 |
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`、`agentId` 等)会保留。新版本在运行时兼容读取旧字段名,无需手动修改配置。
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) 和 [INSTALL-AGENT.md](./INSTALL-AGENT.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 need a custom agent routing prefix (optional; most users leave this empty):
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> --agent-prefix <PREFIX> --json
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
- | `agent_prefix` | empty | Optional prefix for OpenClaw agent IDs. If no agent ID is available, the plugin uses `main`. Interactive setup accepts only letters, digits, `_`, and `-`. |
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
- | `--agent-prefix PREFIX` | Agent routing prefix |
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 (`baseUrl`, `apiKey`, `agentId`, etc.) are preserved. The new plugin version reads old field names at runtime — no manual config edits needed.
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
- | `agent_prefix` | empty | Optional prefix for OpenClaw agent IDs. If no agent ID is available, the plugin uses `main`. Interactive setup accepts only letters, digits, `_`, and `-` |
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.agent_prefix your-prefix
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) and [INSTALL-AGENT.md](./INSTALL-AGENT.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
- | `add_resource` | Import documents, URLs, or Git repos |
43
- | `add_skill` | Import agent skills |
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/*`, `viking://agent/*`, and `viking://session/*`.
54
- - **API Key**: Sent as `X-OpenViking-Key` header over your configured connection. Never logged or forwarded.
55
- - **Multi-tenant isolation**: Supports `accountId`, `userId`, and `agent_prefix` for per-tenant scoping.
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 `X-OpenViking-*` headers and routing logs.
103
- - The OpenViking service owns sessions, memories, archives, and Phase 2 extraction, with storage under `viking://user/*`, `viking://agent/*`, and `viking://session/*`.
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 does not send one fixed agent ID to OpenViking. It tries to keep OpenClaw session identity and OpenViking routing aligned.
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
- - resolve `X-OpenViking-Agent` per session, not per process
117
- - when `plugins.entries.openviking.config.agent_prefix` is non-empty, prefix the session agent as `<agent_prefix>_<sessionAgent>`
118
- - when OpenClaw does not provide a session agent, use its default agent `main`
119
- - send `X-OpenViking-Agent` on OpenViking requests, including startup health checks
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 the plugin is built to support multi-agent and multi-session OpenClaw usage without mixing memories across sessions.
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
- - `agent_prefix`
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
- - `viking://user/memories`
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 cannot auto-discover this policy today because `/api/v1/system/status` does not expose it. Configure the two booleans explicitly so they stay aligned with the server-side account policy.
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 both `viking://user/memories` and `viking://agent/memories` in parallel.
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 `<relevant-memories>` block to the current user message; it does not append a standalone synthetic user message.
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 seven tools directly:
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
- - `add_resource`: import a document, directory, URL, or Git repository as an OpenViking resource
242
- - `add_skill`: import or register an OpenViking agent skill
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://agent/skills/...`
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://agent/skills
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,3 @@
1
+ export type HttpTransport = (url: string, init: RequestInit) => Promise<Response>;
2
+
3
+ export const defaultHttpTransport: HttpTransport = (url, init) => fetch(url, init);
@@ -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
+ };