@openviking/openclaw-plugin 2026.8.7 → 2026.8.12
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/README.md +0 -5
- package/config.ts +1 -4
- package/dist/config.js +1 -4
- package/dist/index.js +0 -9
- package/dist/text-utils.js +1 -1
- package/index.ts +0 -10
- package/openclaw.plugin.json +3 -4
- package/package.json +1 -1
- package/registries/openviking-tools.ts +2 -6
- package/skills/ov-experience-memory/SKILL.md +110 -150
- package/text-utils.ts +1 -1
- package/dist/plugin/openviking-experience-tools.js +0 -105
- package/plugin/openviking-experience-tools.ts +0 -160
package/README.md
CHANGED
|
@@ -46,8 +46,6 @@ Once installed, the plugin provides these agent tools:
|
|
|
46
46
|
| `ov_read` | Read the full original content of one exact OpenViking URI |
|
|
47
47
|
| `ov_multi_read` | Read the full original content of multiple OpenViking URIs |
|
|
48
48
|
| `ov_list` | List OpenViking directories after search to inspect sibling chunks and overview files |
|
|
49
|
-
| `search_experience` | Search reusable execution experiences for the current OpenViking user |
|
|
50
|
-
| `read_experience` | Read one exact Experience returned by `search_experience` |
|
|
51
49
|
| `openviking_tool_result_read` | Restore the full original content of an externalized tool result |
|
|
52
50
|
| `openviking_tool_result_search` | Search inside an externalized tool result by keyword |
|
|
53
51
|
| `openviking_tool_result_list` | List externalized tool results in the current session |
|
|
@@ -250,8 +248,6 @@ Beyond automatic behavior, the plugin exposes these tools directly:
|
|
|
250
248
|
- `ov_read`: read one exact `viking://` URI returned by `ov_search` or `ov_list`
|
|
251
249
|
- `ov_multi_read`: read multiple exact `viking://` URIs, useful for an overview plus sibling chunks
|
|
252
250
|
- `ov_list`: list a hit's parent directory after `ov_search` to recover sibling chunks, `.overview.md`, and related split-document context
|
|
253
|
-
- `search_experience`: search reusable execution experiences for the current OpenViking user
|
|
254
|
-
- `read_experience`: read one exact Experience returned by `search_experience`
|
|
255
251
|
|
|
256
252
|
They serve different roles:
|
|
257
253
|
|
|
@@ -265,7 +261,6 @@ They serve different roles:
|
|
|
265
261
|
- `ov_read` turns a ranked hit into original evidence before answering precise documentation, codebase, configuration, or procedural questions
|
|
266
262
|
- `ov_multi_read` reads overview and sibling chunks together when a split document needs more context than a single hit
|
|
267
263
|
- `ov_list` complements `ov_search` when a ranked hit is only one chunk of a larger procedure or document
|
|
268
|
-
- `search_experience` and `read_experience` provide the exact tool-call contract used by the bundled Experience Memory skill and usage reporting
|
|
269
264
|
|
|
270
265
|
`ov_archive_expand` is especially important because `assemble()` normally returns archive summaries and indexes, not the full raw transcript.
|
|
271
266
|
|
package/config.ts
CHANGED
|
@@ -170,8 +170,6 @@ export const OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES = [
|
|
|
170
170
|
"ov_read",
|
|
171
171
|
"ov_multi_read",
|
|
172
172
|
"ov_list",
|
|
173
|
-
"search_experience",
|
|
174
|
-
"read_experience",
|
|
175
173
|
"memory_recall",
|
|
176
174
|
"ov_recall_trace",
|
|
177
175
|
"memory_store",
|
|
@@ -192,7 +190,6 @@ export const OPENVIKING_TOOL_GROUPS: Record<string, readonly OpenVikingToolName[
|
|
|
192
190
|
default: OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES,
|
|
193
191
|
memory: ["memory_recall", "memory_store", "memory_forget"],
|
|
194
192
|
resource_query: ["ov_search", "ov_read", "ov_multi_read", "ov_list"],
|
|
195
|
-
experience: ["search_experience", "read_experience"],
|
|
196
193
|
import: ["add_resource", "add_skill"],
|
|
197
194
|
recall_trace: ["ov_recall_trace"],
|
|
198
195
|
archive: ["ov_archive_search", "ov_archive_expand"],
|
|
@@ -951,7 +948,7 @@ export const memoryOpenVikingConfigSchema = {
|
|
|
951
948
|
enabledTools: {
|
|
952
949
|
label: "Enabled Tools",
|
|
953
950
|
placeholder: "default",
|
|
954
|
-
help: "Agent-visible tool allowlist. Accepts tool names or groups: default, all, memory, resource_query,
|
|
951
|
+
help: "Agent-visible tool allowlist. Accepts tool names or groups: default, all, memory, resource_query, import, recall_trace, archive, tool_result. add_resource also requires enableAddResourceTool=true.",
|
|
955
952
|
advanced: true,
|
|
956
953
|
},
|
|
957
954
|
disabledTools: {
|
package/dist/config.js
CHANGED
|
@@ -35,8 +35,6 @@ export const OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES = [
|
|
|
35
35
|
"ov_read",
|
|
36
36
|
"ov_multi_read",
|
|
37
37
|
"ov_list",
|
|
38
|
-
"search_experience",
|
|
39
|
-
"read_experience",
|
|
40
38
|
"memory_recall",
|
|
41
39
|
"ov_recall_trace",
|
|
42
40
|
"memory_store",
|
|
@@ -56,7 +54,6 @@ export const OPENVIKING_TOOL_GROUPS = {
|
|
|
56
54
|
default: OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES,
|
|
57
55
|
memory: ["memory_recall", "memory_store", "memory_forget"],
|
|
58
56
|
resource_query: ["ov_search", "ov_read", "ov_multi_read", "ov_list"],
|
|
59
|
-
experience: ["search_experience", "read_experience"],
|
|
60
57
|
import: ["add_resource", "add_skill"],
|
|
61
58
|
recall_trace: ["ov_recall_trace"],
|
|
62
59
|
archive: ["ov_archive_search", "ov_archive_expand"],
|
|
@@ -653,7 +650,7 @@ export const memoryOpenVikingConfigSchema = {
|
|
|
653
650
|
enabledTools: {
|
|
654
651
|
label: "Enabled Tools",
|
|
655
652
|
placeholder: "default",
|
|
656
|
-
help: "Agent-visible tool allowlist. Accepts tool names or groups: default, all, memory, resource_query,
|
|
653
|
+
help: "Agent-visible tool allowlist. Accepts tool names or groups: default, all, memory, resource_query, import, recall_trace, archive, tool_result. add_resource also requires enableAddResourceTool=true.",
|
|
657
654
|
advanced: true,
|
|
658
655
|
},
|
|
659
656
|
disabledTools: {
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,6 @@ import { registerOpenVikingCommands } from "./plugin/command-registration.js";
|
|
|
15
15
|
import { registerRecallTraceRoutes as registerRecallTraceRouteAdapters } from "./plugin/recall-trace-routes.js";
|
|
16
16
|
import { createOpenVikingService } from "./plugin/openviking-services.js";
|
|
17
17
|
import { registerOpenVikingArchiveTools } from "./plugin/openviking-archive-tools.js";
|
|
18
|
-
import { registerOpenVikingExperienceTools } from "./plugin/openviking-experience-tools.js";
|
|
19
18
|
import { createOpenVikingImportRuntime } from "./plugin/openviking-import-runtime.js";
|
|
20
19
|
import { registerOpenVikingImportTools } from "./plugin/openviking-import-tools.js";
|
|
21
20
|
import { registerOpenVikingLifecycleHooks } from "./plugin/openviking-lifecycle-hooks.js";
|
|
@@ -137,14 +136,6 @@ const contextEnginePlugin = {
|
|
|
137
136
|
isBypassedSession,
|
|
138
137
|
makeBypassedToolResult,
|
|
139
138
|
});
|
|
140
|
-
registerOpenVikingExperienceTools({
|
|
141
|
-
registerTool: registerOpenVikingTool,
|
|
142
|
-
getClient,
|
|
143
|
-
resolvePluginSessionRouting,
|
|
144
|
-
isBypassedSession,
|
|
145
|
-
makeBypassedToolResult,
|
|
146
|
-
userId: cfg.userId,
|
|
147
|
-
});
|
|
148
139
|
registerOpenVikingMemoryRecallTools({
|
|
149
140
|
registerTool: registerOpenVikingTool,
|
|
150
141
|
getClient,
|
package/dist/text-utils.js
CHANGED
package/index.ts
CHANGED
|
@@ -19,7 +19,6 @@ import { registerOpenVikingCommands } from "./plugin/command-registration.js";
|
|
|
19
19
|
import { registerRecallTraceRoutes as registerRecallTraceRouteAdapters } from "./plugin/recall-trace-routes.js";
|
|
20
20
|
import { createOpenVikingService } from "./plugin/openviking-services.js";
|
|
21
21
|
import { registerOpenVikingArchiveTools } from "./plugin/openviking-archive-tools.js";
|
|
22
|
-
import { registerOpenVikingExperienceTools } from "./plugin/openviking-experience-tools.js";
|
|
23
22
|
import { createOpenVikingImportRuntime } from "./plugin/openviking-import-runtime.js";
|
|
24
23
|
import { registerOpenVikingImportTools } from "./plugin/openviking-import-tools.js";
|
|
25
24
|
import { registerOpenVikingLifecycleHooks } from "./plugin/openviking-lifecycle-hooks.js";
|
|
@@ -281,15 +280,6 @@ const contextEnginePlugin = {
|
|
|
281
280
|
makeBypassedToolResult,
|
|
282
281
|
});
|
|
283
282
|
|
|
284
|
-
registerOpenVikingExperienceTools({
|
|
285
|
-
registerTool: registerOpenVikingTool,
|
|
286
|
-
getClient,
|
|
287
|
-
resolvePluginSessionRouting,
|
|
288
|
-
isBypassedSession,
|
|
289
|
-
makeBypassedToolResult,
|
|
290
|
-
userId: cfg.userId,
|
|
291
|
-
});
|
|
292
|
-
|
|
293
283
|
registerOpenVikingMemoryRecallTools({
|
|
294
284
|
registerTool: registerOpenVikingTool,
|
|
295
285
|
getClient,
|
package/openclaw.plugin.json
CHANGED
|
@@ -19,8 +19,6 @@
|
|
|
19
19
|
"ov_read",
|
|
20
20
|
"ov_multi_read",
|
|
21
21
|
"ov_list",
|
|
22
|
-
"search_experience",
|
|
23
|
-
"read_experience",
|
|
24
22
|
"memory_recall",
|
|
25
23
|
"ov_recall_trace",
|
|
26
24
|
"memory_store",
|
|
@@ -52,7 +50,8 @@
|
|
|
52
50
|
},
|
|
53
51
|
"skills": [
|
|
54
52
|
"./skills/install-openviking-memory",
|
|
55
|
-
"./skills/openviking-context-database"
|
|
53
|
+
"./skills/openviking-context-database",
|
|
54
|
+
"./skills/ov-experience-memory"
|
|
56
55
|
],
|
|
57
56
|
"setup": {
|
|
58
57
|
"providers": [
|
|
@@ -254,7 +253,7 @@
|
|
|
254
253
|
"enabledTools": {
|
|
255
254
|
"label": "Enabled Tools",
|
|
256
255
|
"placeholder": "default",
|
|
257
|
-
"help": "Agent-visible tool allowlist. Accepts tool names or groups: default, all, memory, resource_query,
|
|
256
|
+
"help": "Agent-visible tool allowlist. Accepts tool names or groups: default, all, memory, resource_query, import, recall_trace, archive, tool_result. add_resource also requires enableAddResourceTool=true.",
|
|
258
257
|
"advanced": true
|
|
259
258
|
},
|
|
260
259
|
"disabledTools": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openviking/openclaw-plugin",
|
|
3
|
-
"version": "2026.8.
|
|
3
|
+
"version": "2026.8.12",
|
|
4
4
|
"displayName": "OpenViking",
|
|
5
5
|
"description": "OpenClaw context-engine plugin — OpenViking AI memory, long-term memory, knowledge base, semantic search, RAG, context engine. 长期记忆 · 知识库 · 语义检索 · 上下文引擎",
|
|
6
6
|
"type": "module",
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export type OpenVikingToolGroup =
|
|
2
2
|
| "memory"
|
|
3
3
|
| "resource_query"
|
|
4
|
-
| "experience"
|
|
5
4
|
| "import"
|
|
6
5
|
| "recall_trace"
|
|
7
6
|
| "archive"
|
|
@@ -14,8 +13,6 @@ export type OpenVikingToolName =
|
|
|
14
13
|
| "ov_read"
|
|
15
14
|
| "ov_multi_read"
|
|
16
15
|
| "ov_list"
|
|
17
|
-
| "search_experience"
|
|
18
|
-
| "read_experience"
|
|
19
16
|
| "memory_recall"
|
|
20
17
|
| "ov_recall_trace"
|
|
21
18
|
| "memory_store"
|
|
@@ -47,8 +44,6 @@ export const OPENVIKING_TOOL_SPECS = [
|
|
|
47
44
|
{ name: "ov_read", group: "resource_query", defaultEnabled: true },
|
|
48
45
|
{ name: "ov_multi_read", group: "resource_query", defaultEnabled: true },
|
|
49
46
|
{ name: "ov_list", group: "resource_query", defaultEnabled: true },
|
|
50
|
-
{ name: "search_experience", group: "experience", defaultEnabled: true },
|
|
51
|
-
{ name: "read_experience", group: "experience", defaultEnabled: true },
|
|
52
47
|
{ name: "memory_recall", group: "memory", defaultEnabled: true },
|
|
53
48
|
{ name: "ov_recall_trace", group: "recall_trace", defaultEnabled: true },
|
|
54
49
|
{ name: "memory_store", group: "memory", defaultEnabled: true },
|
|
@@ -69,7 +64,6 @@ export const OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES = OPENVIKING_TOOL_SPECS
|
|
|
69
64
|
const OPENVIKING_TOOL_GROUP_ORDER: readonly OpenVikingToolGroup[] = [
|
|
70
65
|
"memory",
|
|
71
66
|
"resource_query",
|
|
72
|
-
"experience",
|
|
73
67
|
"import",
|
|
74
68
|
"recall_trace",
|
|
75
69
|
"archive",
|
|
@@ -79,6 +73,8 @@ const OPENVIKING_TOOL_GROUP_ORDER: readonly OpenVikingToolGroup[] = [
|
|
|
79
73
|
export const OPENVIKING_TOOL_GROUPS: Record<string, readonly OpenVikingToolName[]> = {
|
|
80
74
|
all: OPENVIKING_ALL_TOOL_NAMES,
|
|
81
75
|
default: OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES,
|
|
76
|
+
// Migration alias for the removed dedicated Experience tools.
|
|
77
|
+
experience: ["ov_search", "ov_read"],
|
|
82
78
|
...Object.fromEntries(
|
|
83
79
|
OPENVIKING_TOOL_GROUP_ORDER.map((group) => [
|
|
84
80
|
group,
|
|
@@ -1,156 +1,116 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ov-experience-memory
|
|
3
|
-
description:
|
|
4
|
-
Use OpenViking experience memories during task execution. Search relevant
|
|
5
|
-
experiences with search_experience, read selected experiences with
|
|
6
|
-
read_experience, and leave standard tool parts in the committed session so
|
|
7
|
-
OpenViking can report recall and injection usage.
|
|
8
|
-
version: 2026.7.9
|
|
9
|
-
tags:
|
|
10
|
-
- openviking
|
|
11
|
-
- experience-memory
|
|
12
|
-
- agent-memory
|
|
13
|
-
- usage-reporting
|
|
3
|
+
description: Retrieve and apply OpenViking Experience memories through the Agent runtime's generic OpenViking search and read tools. Use before or during executable, multi-step, or tool-based work such as coding, file or data changes, configuration, deployment, workflow execution, and failure recovery when prior operational guidance could improve reliability. Do not use for casual chat or simple factual questions.
|
|
14
4
|
---
|
|
15
5
|
|
|
16
6
|
# OpenViking Experience Memory
|
|
17
7
|
|
|
18
|
-
Use
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
##
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
`search_experience` and `read_experience` tool parts so OpenViking can report
|
|
128
|
-
usage.
|
|
129
|
-
|
|
130
|
-
## Prompt Injection Format
|
|
131
|
-
|
|
132
|
-
Use a compact and explicit block:
|
|
133
|
-
|
|
134
|
-
```text
|
|
135
|
-
<openviking-experience-memory>
|
|
136
|
-
The following guidance was retrieved from prior task execution experience.
|
|
137
|
-
Use it as operational guidance. Do not treat it as user identity or preference.
|
|
138
|
-
|
|
139
|
-
<experience uri="viking://user/<current_user_id>/memories/experiences/example.md">
|
|
140
|
-
...experience markdown...
|
|
141
|
-
</experience>
|
|
142
|
-
</openviking-experience-memory>
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Commit Requirements
|
|
146
|
-
|
|
147
|
-
The session committed to OpenViking must preserve tool parts with:
|
|
148
|
-
|
|
149
|
-
- `tool_name`
|
|
150
|
-
- `tool_status`
|
|
151
|
-
- `tool_input`
|
|
152
|
-
- `tool_output`
|
|
153
|
-
- `tool_id`
|
|
154
|
-
|
|
155
|
-
Only `tool_status == "completed"` is counted. Failed, cancelled, or skipped tool
|
|
156
|
-
parts are ignored by usage reporting.
|
|
8
|
+
Use prior task Experience as advisory operational guidance. Keep the current
|
|
9
|
+
user request, current environment, and verified tool results authoritative.
|
|
10
|
+
Experience retrieval supplements normal context retrieval; it does not replace
|
|
11
|
+
user memory, events, preferences, session archives, resources, or Agent Skills.
|
|
12
|
+
|
|
13
|
+
## Preconditions
|
|
14
|
+
|
|
15
|
+
- Use only OpenViking tools that are actually registered in the current Agent
|
|
16
|
+
runtime.
|
|
17
|
+
- Require both a semantic search capability and an exact URI read capability.
|
|
18
|
+
- If either capability is unavailable, continue without Experience. Do not
|
|
19
|
+
invent a tool call, fabricate a ToolPart, or replace the Agent tool call with
|
|
20
|
+
direct HTTP or CLI access.
|
|
21
|
+
- Do not substitute broad memory `recall` for a search scoped to the Experience
|
|
22
|
+
root. Continue using the runtime's normal recall and retrieval flows when the
|
|
23
|
+
task also needs user facts, events, decisions, prior conversation, or domain
|
|
24
|
+
resources.
|
|
25
|
+
|
|
26
|
+
## Select Runtime Tools
|
|
27
|
+
|
|
28
|
+
Choose the registered names that match the current runtime:
|
|
29
|
+
|
|
30
|
+
| Runtime | Search | Read |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| OpenViking MCP, Codex, Claude Code | `find` or `search` | `read` |
|
|
33
|
+
| OpenCode | `openviking_find` or `openviking_search` | `openviking_read` |
|
|
34
|
+
| OpenClaw | `ov_search` | `ov_read` or `ov_multi_read` |
|
|
35
|
+
|
|
36
|
+
The host may display MCP names with a namespace such as
|
|
37
|
+
`mcp__openviking__find`. Use the exact registered name and schema shown by the
|
|
38
|
+
runtime. Prefer `find` for a fast task-start lookup and `search` when session
|
|
39
|
+
context or deeper intent analysis is useful.
|
|
40
|
+
|
|
41
|
+
## Retrieval Workflow
|
|
42
|
+
|
|
43
|
+
1. Decide whether the request is an executable task. Retrieve Experience for
|
|
44
|
+
planning, tool use, environment changes, multi-step workflows, or recovery
|
|
45
|
+
from a failed attempt. Skip retrieval for casual conversation and simple
|
|
46
|
+
knowledge answers.
|
|
47
|
+
2. Build one concise query containing the task goal, domain object, intended
|
|
48
|
+
operation, and important constraints. After a failure, include the failed
|
|
49
|
+
operation and stable error signature.
|
|
50
|
+
3. Search only the current user's Experience root:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
viking://user/memories/experiences
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
For tools using MCP-style parameters, set `target_uri` to this root. For
|
|
57
|
+
OpenClaw `ov_search`, set `uri` to this root. Never hardcode `default`,
|
|
58
|
+
`test`, or another user ID.
|
|
59
|
+
4. Start with `limit=5` and the tool's normal score threshold. Judge results by
|
|
60
|
+
task, environment, preconditions, and likely effect; title similarity alone
|
|
61
|
+
is insufficient. If no result is relevant, continue without Experience and
|
|
62
|
+
do not broaden the search to unrelated memory directories.
|
|
63
|
+
5. Select only the one to three Experience files likely to change execution.
|
|
64
|
+
Require an exact file URI without a query or fragment. Ignore directories,
|
|
65
|
+
unrelated memory types, and sidecars such as `.abstract.md`, `.overview.md`,
|
|
66
|
+
and `.relations.json`.
|
|
67
|
+
6. Read every selected canonical `viking://.../memories/experiences/...` URI
|
|
68
|
+
with the runtime's OpenViking read tool. Search abstracts help selection but
|
|
69
|
+
are not a substitute for reading the Experience body.
|
|
70
|
+
7. Apply relevant steps and checks while executing the task. Do not repeat the
|
|
71
|
+
Experience verbatim to the user unless its content is directly needed in the
|
|
72
|
+
answer.
|
|
73
|
+
8. If execution fails for a materially new reason, perform at most one focused
|
|
74
|
+
follow-up search using the failure evidence, then read only newly relevant
|
|
75
|
+
Experience files.
|
|
76
|
+
|
|
77
|
+
## Applying Retrieved Experience
|
|
78
|
+
|
|
79
|
+
- Treat Experience as reusable procedure, not as a user profile, user intent,
|
|
80
|
+
security policy, or proof that an action succeeded.
|
|
81
|
+
- Follow priority in this order: system and developer instructions, current
|
|
82
|
+
user request, current environment and tool evidence, then Experience.
|
|
83
|
+
- Ignore stale, incompatible, unsafe, or conflicting guidance. Verify commands,
|
|
84
|
+
paths, APIs, versions, and destructive actions against the current task.
|
|
85
|
+
- Preserve confirmation requirements and permission boundaries. Prior success
|
|
86
|
+
never authorizes a destructive or external action in the current session.
|
|
87
|
+
- When multiple Experience files conflict, prefer the one whose preconditions
|
|
88
|
+
match the current environment; otherwise proceed conservatively and surface
|
|
89
|
+
the ambiguity when it affects the user.
|
|
90
|
+
|
|
91
|
+
## Session Evidence
|
|
92
|
+
|
|
93
|
+
Use real Agent tool calls so the committed OpenViking session retains their
|
|
94
|
+
ToolParts:
|
|
95
|
+
|
|
96
|
+
- A completed generic OpenViking `find`, `search`, or `list` result containing
|
|
97
|
+
an Experience URI records recall for that Experience.
|
|
98
|
+
- A completed generic OpenViking `read` or `multi_read` of an Experience URI
|
|
99
|
+
records injection and can associate the resulting trajectory with that
|
|
100
|
+
Experience.
|
|
101
|
+
- Failed, cancelled, or incomplete calls do not count.
|
|
102
|
+
|
|
103
|
+
Do not edit, summarize away, or synthesize these ToolParts before the session
|
|
104
|
+
is committed.
|
|
105
|
+
|
|
106
|
+
## Example
|
|
107
|
+
|
|
108
|
+
For a request to fix a deployment failure:
|
|
109
|
+
|
|
110
|
+
1. Search the Experience root with a query such as
|
|
111
|
+
`Kubernetes deployment image pull failure private registry`.
|
|
112
|
+
2. Read the most relevant exact Experience URI.
|
|
113
|
+
3. Check that its registry, credential, and rollout assumptions match the
|
|
114
|
+
current cluster.
|
|
115
|
+
4. Apply the compatible diagnostic steps, verify the live result, and continue
|
|
116
|
+
the user's task.
|
package/text-utils.ts
CHANGED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { Type } from "@sinclair/typebox";
|
|
2
|
-
const EXPERIENCE_TARGET_URI = "viking://user/memories/experiences/";
|
|
3
|
-
const DEFAULT_LIMIT = 5;
|
|
4
|
-
const MAX_LIMIT = 20;
|
|
5
|
-
const EXPERIENCE_SIDECAR_FILENAMES = new Set([".abstract.md", ".overview.md", ".relations.json"]);
|
|
6
|
-
function clampLimit(value) {
|
|
7
|
-
const parsed = Number.isFinite(Number(value)) ? Math.trunc(Number(value)) : DEFAULT_LIMIT;
|
|
8
|
-
return Math.max(1, Math.min(MAX_LIMIT, parsed));
|
|
9
|
-
}
|
|
10
|
-
function experienceRelativePath(uri) {
|
|
11
|
-
return uri.match(/^viking:\/\/user\/[^/]+\/memories\/experiences\/(.+)$/)?.[1] ?? "";
|
|
12
|
-
}
|
|
13
|
-
export function isCanonicalExperienceUri(uri, expectedUserId) {
|
|
14
|
-
const value = typeof uri === "string" ? uri.trim() : "";
|
|
15
|
-
if (!value || value.includes("?") || value.includes("#")) {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
const owner = value.match(/^viking:\/\/user\/([^/]+)\//)?.[1] ?? "";
|
|
19
|
-
if (expectedUserId?.trim() && owner !== expectedUserId.trim()) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
const relative = experienceRelativePath(value);
|
|
23
|
-
const segments = relative.split("/");
|
|
24
|
-
const basename = segments.at(-1) ?? "";
|
|
25
|
-
return Boolean(relative
|
|
26
|
-
&& segments.every((segment) => segment && segment !== "." && segment !== "..")
|
|
27
|
-
&& !EXPERIENCE_SIDECAR_FILENAMES.has(basename));
|
|
28
|
-
}
|
|
29
|
-
function titleFromUri(uri) {
|
|
30
|
-
const basename = uri.split("/").at(-1) ?? uri;
|
|
31
|
-
const title = basename.replace(/\.md$/i, "");
|
|
32
|
-
try {
|
|
33
|
-
return decodeURIComponent(title);
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
return title;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function jsonToolResult(payload) {
|
|
40
|
-
return {
|
|
41
|
-
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
export function registerOpenVikingExperienceTools(deps) {
|
|
45
|
-
deps.registerTool((ctx) => ({
|
|
46
|
-
name: "search_experience",
|
|
47
|
-
label: "Search Experience (OpenViking)",
|
|
48
|
-
description: "Search reusable task-execution experiences for the current OpenViking user. " +
|
|
49
|
-
"Use before executing operational or multi-step tasks, then call read_experience for selected results.",
|
|
50
|
-
parameters: Type.Object({
|
|
51
|
-
query: Type.String({ description: "Current task, situation, or execution problem to search for" }),
|
|
52
|
-
limit: Type.Optional(Type.Integer({
|
|
53
|
-
description: `Maximum results to return. Default: ${DEFAULT_LIMIT}; maximum: ${MAX_LIMIT}`,
|
|
54
|
-
minimum: 1,
|
|
55
|
-
maximum: MAX_LIMIT,
|
|
56
|
-
})),
|
|
57
|
-
}, { additionalProperties: false }),
|
|
58
|
-
async execute(_toolCallId, params) {
|
|
59
|
-
if (deps.isBypassedSession(ctx)) {
|
|
60
|
-
return deps.makeBypassedToolResult("search_experience");
|
|
61
|
-
}
|
|
62
|
-
const query = typeof params.query === "string" ? params.query.trim() : "";
|
|
63
|
-
if (!query) {
|
|
64
|
-
throw new Error("query is required");
|
|
65
|
-
}
|
|
66
|
-
const session = deps.resolvePluginSessionRouting(ctx);
|
|
67
|
-
const client = await deps.getClient();
|
|
68
|
-
const result = await client.find(query, {
|
|
69
|
-
targetUri: EXPERIENCE_TARGET_URI,
|
|
70
|
-
limit: clampLimit(params.limit),
|
|
71
|
-
}, session.actorPeerId);
|
|
72
|
-
const results = (result.memories ?? [])
|
|
73
|
-
.filter((item) => isCanonicalExperienceUri(item.uri, deps.userId))
|
|
74
|
-
.map((item) => ({
|
|
75
|
-
uri: item.uri,
|
|
76
|
-
title: titleFromUri(item.uri),
|
|
77
|
-
score: typeof item.score === "number" ? item.score : 0,
|
|
78
|
-
snippet: item.abstract || item.overview || "",
|
|
79
|
-
}));
|
|
80
|
-
return jsonToolResult({ results });
|
|
81
|
-
},
|
|
82
|
-
}), { name: "search_experience" });
|
|
83
|
-
deps.registerTool((ctx) => ({
|
|
84
|
-
name: "read_experience",
|
|
85
|
-
label: "Read Experience (OpenViking)",
|
|
86
|
-
description: "Read the complete Markdown body of one Experience returned by search_experience and use it as execution guidance.",
|
|
87
|
-
parameters: Type.Object({
|
|
88
|
-
uri: Type.String({ description: "Exact canonical Experience URI returned by search_experience" }),
|
|
89
|
-
}, { additionalProperties: false }),
|
|
90
|
-
async execute(_toolCallId, params) {
|
|
91
|
-
if (deps.isBypassedSession(ctx)) {
|
|
92
|
-
return deps.makeBypassedToolResult("read_experience");
|
|
93
|
-
}
|
|
94
|
-
const uri = typeof params.uri === "string" ? params.uri.trim() : "";
|
|
95
|
-
if (!isCanonicalExperienceUri(uri, deps.userId)) {
|
|
96
|
-
throw new Error("uri must be a canonical OpenViking Experience URI returned by search_experience");
|
|
97
|
-
}
|
|
98
|
-
const session = deps.resolvePluginSessionRouting(ctx);
|
|
99
|
-
const client = await deps.getClient();
|
|
100
|
-
const content = await client.read(uri, session.actorPeerId);
|
|
101
|
-
const text = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
102
|
-
return jsonToolResult({ uri, content: text });
|
|
103
|
-
},
|
|
104
|
-
}), { name: "read_experience" });
|
|
105
|
-
}
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { Type } from "@sinclair/typebox";
|
|
2
|
-
|
|
3
|
-
import type { FindResult } from "../client.js";
|
|
4
|
-
|
|
5
|
-
const EXPERIENCE_TARGET_URI = "viking://user/memories/experiences/";
|
|
6
|
-
const DEFAULT_LIMIT = 5;
|
|
7
|
-
const MAX_LIMIT = 20;
|
|
8
|
-
const EXPERIENCE_SIDECAR_FILENAMES = new Set([".abstract.md", ".overview.md", ".relations.json"]);
|
|
9
|
-
|
|
10
|
-
export type OpenVikingExperienceToolContext = {
|
|
11
|
-
sessionKey?: string;
|
|
12
|
-
sessionId?: string;
|
|
13
|
-
agentId?: string;
|
|
14
|
-
senderId?: string;
|
|
15
|
-
requesterSenderId?: string;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type OpenVikingExperienceSession = {
|
|
19
|
-
sessionId?: string;
|
|
20
|
-
sessionKey?: string;
|
|
21
|
-
ovSessionId?: string;
|
|
22
|
-
agentId: string;
|
|
23
|
-
actorPeerId?: string;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
type OpenVikingExperienceClient = {
|
|
27
|
-
find: (
|
|
28
|
-
query: string,
|
|
29
|
-
options: { targetUri: string; limit: number; scoreThreshold?: number },
|
|
30
|
-
actorPeerId?: string,
|
|
31
|
-
) => Promise<FindResult>;
|
|
32
|
-
read: (uri: string, actorPeerId?: string) => Promise<unknown>;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export type OpenVikingExperienceToolsDeps = {
|
|
36
|
-
registerTool: (toolOrFactory: unknown, opts: { name: string }) => void;
|
|
37
|
-
getClient: () => Promise<OpenVikingExperienceClient>;
|
|
38
|
-
resolvePluginSessionRouting: (ctx?: OpenVikingExperienceToolContext) => OpenVikingExperienceSession;
|
|
39
|
-
isBypassedSession: (ctx?: OpenVikingExperienceToolContext) => boolean;
|
|
40
|
-
makeBypassedToolResult: (toolName: string) => unknown;
|
|
41
|
-
userId?: string;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
function clampLimit(value: unknown): number {
|
|
45
|
-
const parsed = Number.isFinite(Number(value)) ? Math.trunc(Number(value)) : DEFAULT_LIMIT;
|
|
46
|
-
return Math.max(1, Math.min(MAX_LIMIT, parsed));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function experienceRelativePath(uri: string): string {
|
|
50
|
-
return uri.match(/^viking:\/\/user\/[^/]+\/memories\/experiences\/(.+)$/)?.[1] ?? "";
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function isCanonicalExperienceUri(uri: unknown, expectedUserId?: string): uri is string {
|
|
54
|
-
const value = typeof uri === "string" ? uri.trim() : "";
|
|
55
|
-
if (!value || value.includes("?") || value.includes("#")) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
const owner = value.match(/^viking:\/\/user\/([^/]+)\//)?.[1] ?? "";
|
|
59
|
-
if (expectedUserId?.trim() && owner !== expectedUserId.trim()) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
const relative = experienceRelativePath(value);
|
|
63
|
-
const segments = relative.split("/");
|
|
64
|
-
const basename = segments.at(-1) ?? "";
|
|
65
|
-
return Boolean(
|
|
66
|
-
relative
|
|
67
|
-
&& segments.every((segment) => segment && segment !== "." && segment !== "..")
|
|
68
|
-
&& !EXPERIENCE_SIDECAR_FILENAMES.has(basename)
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function titleFromUri(uri: string): string {
|
|
73
|
-
const basename = uri.split("/").at(-1) ?? uri;
|
|
74
|
-
const title = basename.replace(/\.md$/i, "");
|
|
75
|
-
try {
|
|
76
|
-
return decodeURIComponent(title);
|
|
77
|
-
} catch {
|
|
78
|
-
return title;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function jsonToolResult(payload: Record<string, unknown>): {
|
|
83
|
-
content: Array<{ type: "text"; text: string }>;
|
|
84
|
-
} {
|
|
85
|
-
return {
|
|
86
|
-
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function registerOpenVikingExperienceTools(deps: OpenVikingExperienceToolsDeps): void {
|
|
91
|
-
deps.registerTool(
|
|
92
|
-
(ctx: OpenVikingExperienceToolContext) => ({
|
|
93
|
-
name: "search_experience",
|
|
94
|
-
label: "Search Experience (OpenViking)",
|
|
95
|
-
description:
|
|
96
|
-
"Search reusable task-execution experiences for the current OpenViking user. " +
|
|
97
|
-
"Use before executing operational or multi-step tasks, then call read_experience for selected results.",
|
|
98
|
-
parameters: Type.Object({
|
|
99
|
-
query: Type.String({ description: "Current task, situation, or execution problem to search for" }),
|
|
100
|
-
limit: Type.Optional(Type.Integer({
|
|
101
|
-
description: `Maximum results to return. Default: ${DEFAULT_LIMIT}; maximum: ${MAX_LIMIT}`,
|
|
102
|
-
minimum: 1,
|
|
103
|
-
maximum: MAX_LIMIT,
|
|
104
|
-
})),
|
|
105
|
-
}, { additionalProperties: false }),
|
|
106
|
-
async execute(_toolCallId: string, params: Record<string, unknown>) {
|
|
107
|
-
if (deps.isBypassedSession(ctx)) {
|
|
108
|
-
return deps.makeBypassedToolResult("search_experience");
|
|
109
|
-
}
|
|
110
|
-
const query = typeof params.query === "string" ? params.query.trim() : "";
|
|
111
|
-
if (!query) {
|
|
112
|
-
throw new Error("query is required");
|
|
113
|
-
}
|
|
114
|
-
const session = deps.resolvePluginSessionRouting(ctx);
|
|
115
|
-
const client = await deps.getClient();
|
|
116
|
-
const result = await client.find(query, {
|
|
117
|
-
targetUri: EXPERIENCE_TARGET_URI,
|
|
118
|
-
limit: clampLimit(params.limit),
|
|
119
|
-
}, session.actorPeerId);
|
|
120
|
-
const results = (result.memories ?? [])
|
|
121
|
-
.filter((item) => isCanonicalExperienceUri(item.uri, deps.userId))
|
|
122
|
-
.map((item) => ({
|
|
123
|
-
uri: item.uri,
|
|
124
|
-
title: titleFromUri(item.uri),
|
|
125
|
-
score: typeof item.score === "number" ? item.score : 0,
|
|
126
|
-
snippet: item.abstract || item.overview || "",
|
|
127
|
-
}));
|
|
128
|
-
return jsonToolResult({ results });
|
|
129
|
-
},
|
|
130
|
-
}),
|
|
131
|
-
{ name: "search_experience" },
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
deps.registerTool(
|
|
135
|
-
(ctx: OpenVikingExperienceToolContext) => ({
|
|
136
|
-
name: "read_experience",
|
|
137
|
-
label: "Read Experience (OpenViking)",
|
|
138
|
-
description:
|
|
139
|
-
"Read the complete Markdown body of one Experience returned by search_experience and use it as execution guidance.",
|
|
140
|
-
parameters: Type.Object({
|
|
141
|
-
uri: Type.String({ description: "Exact canonical Experience URI returned by search_experience" }),
|
|
142
|
-
}, { additionalProperties: false }),
|
|
143
|
-
async execute(_toolCallId: string, params: Record<string, unknown>) {
|
|
144
|
-
if (deps.isBypassedSession(ctx)) {
|
|
145
|
-
return deps.makeBypassedToolResult("read_experience");
|
|
146
|
-
}
|
|
147
|
-
const uri = typeof params.uri === "string" ? params.uri.trim() : "";
|
|
148
|
-
if (!isCanonicalExperienceUri(uri, deps.userId)) {
|
|
149
|
-
throw new Error("uri must be a canonical OpenViking Experience URI returned by search_experience");
|
|
150
|
-
}
|
|
151
|
-
const session = deps.resolvePluginSessionRouting(ctx);
|
|
152
|
-
const client = await deps.getClient();
|
|
153
|
-
const content = await client.read(uri, session.actorPeerId);
|
|
154
|
-
const text = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
155
|
-
return jsonToolResult({ uri, content: text });
|
|
156
|
-
},
|
|
157
|
-
}),
|
|
158
|
-
{ name: "read_experience" },
|
|
159
|
-
);
|
|
160
|
-
}
|