@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.
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/config.ts CHANGED
@@ -1,31 +1,25 @@
1
+ import { homedir } from "node:os";
2
+
1
3
  import { getEnv } from "./runtime-utils.js";
2
4
 
3
5
  export type MemoryOpenVikingConfig = {
4
6
  mode?: "remote";
5
7
  baseUrl?: string;
6
- agent_prefix?: string;
8
+ peer_role?: "none" | "assistant" | "person";
9
+ peer_prefix?: string;
7
10
  apiKey?: string;
8
11
  /** Advanced option. Only needed when explicitly sending tenant identity headers. With a user key the server derives identity from the key. */
9
12
  accountId?: string;
10
13
  /** Advanced option. Only needed when explicitly sending tenant identity headers. */
11
14
  userId?: string;
12
- /**
13
- * Canonical namespace policy. Must match the server-side account namespace
14
- * policy because current /system/status does not expose it.
15
- */
16
- isolateUserScopeByAgent?: boolean;
17
- isolateAgentScopeByUser?: boolean;
18
- /**
19
- * Deprecated compatibility alias for older hash-based agent space behavior.
20
- * Prefer isolateUserScopeByAgent / isolateAgentScopeByUser.
21
- */
22
- agentScopeMode?: "user_agent" | "agent";
23
15
  targetUri?: string;
24
16
  timeoutMs?: number;
25
17
  autoCapture?: boolean;
26
18
  captureMode?: "semantic" | "keyword";
27
19
  captureMaxLength?: number;
28
20
  autoRecall?: boolean;
21
+ /** Outer time budget for the whole auto-recall flow, including search, ranking, and reads. */
22
+ autoRecallTimeoutMs?: number;
29
23
  /** Include resources in auto-recall and default memory_recall search. Default false. */
30
24
  recallResources?: boolean;
31
25
  recallLimit?: number;
@@ -53,6 +47,55 @@ export type MemoryOpenVikingConfig = {
53
47
  emitStandardDiagnostics?: boolean;
54
48
  /** When true, log tenant routing for semantic find and session writes (messages/commit) to the plugin logger. */
55
49
  logFindRequests?: boolean;
50
+ /** Enable recall trace recording. Default false. */
51
+ traceRecall?: boolean;
52
+ /** Persist recall traces to local JSONL files. Default false. */
53
+ traceRecallPersist?: boolean;
54
+ /** Directory for JSONL recall trace files. */
55
+ traceRecallDir?: string;
56
+ /** Number of days to retain persisted trace files. */
57
+ traceRecallRetentionDays?: number;
58
+ /** Number of recent persisted days to preload on startup. */
59
+ traceRecallLoadRecentDays?: number;
60
+ /** Maximum in-memory recall trace entries. */
61
+ traceRecallMaxEntries?: number;
62
+ /** Maximum candidate results stored per search in trace. */
63
+ traceRecallMaxResultsPerSearch?: number;
64
+ /** Preview character limit for persisted trace summaries. */
65
+ traceRecallPreviewChars?: number;
66
+ /** Maximum query characters preserved in trace. */
67
+ traceRecallQueryMaxChars?: number;
68
+ /** Maximum days to scan when querying persisted traces without explicit time bounds. */
69
+ traceRecallQueryMaxDays?: number;
70
+ /** Whether trace queries include full content by default. */
71
+ traceRecallIncludeContentByDefault?: boolean;
72
+ /** Whether raw user text preview may be persisted. Default false. */
73
+ traceRecallIncludeRawUserPreview?: boolean;
74
+ /** Auto-recall target resource types. Empty means the backward-compatible memory recall set. */
75
+ recallTargetTypes?: Array<"resource" | "user" | "agent"> | string;
76
+ /** Agent-visible add_resource tool is disabled by default; manual /add-resource remains available. */
77
+ enableAddResourceTool?: boolean;
78
+ /** Agent-visible tool allowlist. Supports exact tool names or groups such as "memory" and "resource_query". */
79
+ enabledTools?: string[] | string;
80
+ /** Agent-visible tool blocklist applied after enabledTools. Supports exact tool names or groups. */
81
+ disabledTools?: string[] | string;
82
+ /** Optional JSON file path for runtime query config overrides. Empty means in-memory only. */
83
+ runtimeQueryConfigPath?: string;
84
+ agentExperience?: {
85
+ enabled?: boolean;
86
+ recallLimit?: number;
87
+ scoreThreshold?: number;
88
+ maxInjectedChars?: number;
89
+ minQueryChars?: number;
90
+ };
91
+ };
92
+
93
+ /** Runtime config after memoryOpenVikingConfigSchema.parse() has applied defaults. */
94
+ export type ParsedMemoryOpenVikingConfig = Required<
95
+ Omit<MemoryOpenVikingConfig, "agentExperience" | "recallTargetTypes">
96
+ > & {
97
+ agentExperience: Required<NonNullable<MemoryOpenVikingConfig["agentExperience"]>>;
98
+ recallTargetTypes: Array<"resource" | "user" | "agent">;
56
99
  };
57
100
 
58
101
  const DEFAULT_BASE_URL = "http://127.0.0.1:1933";
@@ -60,6 +103,7 @@ const DEFAULT_TARGET_URI = "viking://user/memories";
60
103
  const DEFAULT_TIMEOUT_MS = 15000;
61
104
  const DEFAULT_CAPTURE_MODE = "semantic";
62
105
  const DEFAULT_CAPTURE_MAX_LENGTH = 24000;
106
+ const DEFAULT_AUTO_RECALL_TIMEOUT_MS = 5000;
63
107
  const DEFAULT_RECALL_LIMIT = 6;
64
108
  const DEFAULT_RECALL_SCORE_THRESHOLD = 0.15;
65
109
  const DEFAULT_RECALL_MAX_CONTENT_CHARS = 5000;
@@ -69,14 +113,83 @@ const DEFAULT_COMMIT_TOKEN_THRESHOLD = 20000;
69
113
  const DEFAULT_COMMIT_KEEP_RECENT_COUNT = 10;
70
114
  const DEFAULT_BYPASS_SESSION_PATTERNS: string[] = [];
71
115
  const DEFAULT_EMIT_STANDARD_DIAGNOSTICS = false;
72
- const DEFAULT_AGENT_PREFIX = "";
116
+ const DEFAULT_PEER_ROLE = "assistant" as const;
117
+ const DEFAULT_PEER_PREFIX = "";
118
+ const DEFAULT_TRACE_RECALL_DIR = "~/.openclaw/openviking/recall-traces";
119
+ const DEFAULT_TRACE_RECALL_RETENTION_DAYS = 14;
120
+ const DEFAULT_TRACE_RECALL_LOAD_RECENT_DAYS = 2;
121
+ const DEFAULT_TRACE_RECALL_MAX_ENTRIES = 1000;
122
+ const DEFAULT_TRACE_RECALL_MAX_RESULTS_PER_SEARCH = 20;
123
+ const DEFAULT_TRACE_RECALL_PREVIEW_CHARS = 240;
124
+ const DEFAULT_TRACE_RECALL_QUERY_MAX_CHARS = 4000;
125
+ const DEFAULT_TRACE_RECALL_QUERY_MAX_DAYS = 14;
126
+ const ALLOWED_RECALL_TARGET_TYPES = ["resource", "user", "agent"] as const;
127
+ const DEFAULT_RECALL_TARGET_TYPES = ["user", "agent"] as const;
128
+ type RecallTargetType = typeof ALLOWED_RECALL_TARGET_TYPES[number];
129
+ export const OPENVIKING_ADD_RESOURCE_TOOL_NAME = "add_resource" as const;
130
+ export const OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES = [
131
+ "add_skill",
132
+ "ov_search",
133
+ "ov_read",
134
+ "ov_multi_read",
135
+ "ov_list",
136
+ "memory_recall",
137
+ "ov_recall_trace",
138
+ "memory_store",
139
+ "memory_forget",
140
+ "ov_archive_search",
141
+ "ov_archive_expand",
142
+ "openviking_tool_result_read",
143
+ "openviking_tool_result_search",
144
+ "openviking_tool_result_list",
145
+ ] as const;
146
+ export const OPENVIKING_ALL_TOOL_NAMES = [
147
+ OPENVIKING_ADD_RESOURCE_TOOL_NAME,
148
+ ...OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES,
149
+ ] as const;
150
+ export type OpenVikingToolName = typeof OPENVIKING_ALL_TOOL_NAMES[number];
151
+ export const OPENVIKING_TOOL_GROUPS: Record<string, readonly OpenVikingToolName[]> = {
152
+ all: OPENVIKING_ALL_TOOL_NAMES,
153
+ default: OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES,
154
+ memory: ["memory_recall", "memory_store", "memory_forget"],
155
+ resource_query: ["ov_search", "ov_read", "ov_multi_read", "ov_list"],
156
+ import: ["add_resource", "add_skill"],
157
+ recall_trace: ["ov_recall_trace"],
158
+ archive: ["ov_archive_search", "ov_archive_expand"],
159
+ tool_result: [
160
+ "openviking_tool_result_read",
161
+ "openviking_tool_result_search",
162
+ "openviking_tool_result_list",
163
+ ],
164
+ };
165
+ const DEFAULT_AGENT_EXPERIENCE = {
166
+ enabled: false,
167
+ recallLimit: 3,
168
+ scoreThreshold: 0.35,
169
+ maxInjectedChars: 6000,
170
+ minQueryChars: 12,
171
+ };
73
172
 
74
- function resolveAgentPrefix(configured: unknown): string {
173
+ function resolvePeerPrefix(configured: unknown): string {
75
174
  if (typeof configured === "string" && configured.trim()) {
76
175
  const trimmed = configured.trim();
77
- return trimmed === "default" ? DEFAULT_AGENT_PREFIX : trimmed;
176
+ return trimmed === "default" ? DEFAULT_PEER_PREFIX : trimmed;
177
+ }
178
+ return DEFAULT_PEER_PREFIX;
179
+ }
180
+
181
+ function resolvePeerRole(configured: unknown) {
182
+ if (typeof configured === "string") {
183
+ const role = configured.trim().toLowerCase();
184
+ if (role === "none" || role === "assistant" || role === "person") {
185
+ return role;
186
+ }
187
+ throw new Error(`openviking peer_role must be "none", "assistant", or "person"`);
78
188
  }
79
- return DEFAULT_AGENT_PREFIX;
189
+ if (configured !== undefined) {
190
+ throw new Error(`openviking peer_role must be "none", "assistant", or "person"`);
191
+ }
192
+ return DEFAULT_PEER_ROLE;
80
193
  }
81
194
 
82
195
  function resolveEnvVars(value: string): string {
@@ -89,6 +202,16 @@ function resolveEnvVars(value: string): string {
89
202
  });
90
203
  }
91
204
 
205
+ function expandHomeDir(value: string): string {
206
+ if (value === "~") {
207
+ return homedir();
208
+ }
209
+ if (value.startsWith("~/")) {
210
+ return `${homedir()}${value.slice(1)}`;
211
+ }
212
+ return value;
213
+ }
214
+
92
215
  function toNumber(value: unknown, fallback: number): number {
93
216
  if (typeof value === "number" && Number.isFinite(value)) {
94
217
  return value;
@@ -118,6 +241,101 @@ function toStringArray(value: unknown, fallback: string[]): string[] {
118
241
  return fallback;
119
242
  }
120
243
 
244
+ function toIntegerInRange(value: unknown, fallback: number, min: number, max: number): number {
245
+ return Math.max(min, Math.min(max, Math.floor(toNumber(value, fallback))));
246
+ }
247
+
248
+ function normalizeRecallTargetTypes(value: unknown, includeResources = false): RecallTargetType[] {
249
+ const entries = toStringArray(value, [...DEFAULT_RECALL_TARGET_TYPES]);
250
+ const seen = new Set<RecallTargetType>();
251
+ const normalized: RecallTargetType[] = [];
252
+ const unknown: string[] = [];
253
+
254
+ for (const entry of entries) {
255
+ if ((ALLOWED_RECALL_TARGET_TYPES as readonly string[]).includes(entry)) {
256
+ const typed = entry as RecallTargetType;
257
+ if (!seen.has(typed)) {
258
+ seen.add(typed);
259
+ normalized.push(typed);
260
+ }
261
+ } else {
262
+ unknown.push(entry);
263
+ }
264
+ }
265
+
266
+ if (unknown.length > 0) {
267
+ throw new Error(`openviking recallTargetTypes contains unknown resource types: ${unknown.join(", ")}`);
268
+ }
269
+
270
+ const result = normalized.length > 0 ? normalized : [...DEFAULT_RECALL_TARGET_TYPES];
271
+ if (includeResources && !seen.has("resource")) {
272
+ result.push("resource");
273
+ }
274
+ return result;
275
+ }
276
+
277
+ function toRecord(value: unknown): Record<string, unknown> {
278
+ return value && typeof value === "object" && !Array.isArray(value)
279
+ ? value as Record<string, unknown>
280
+ : {};
281
+ }
282
+
283
+ function expandToolSelectors(value: unknown, fallback: string[], label: string): OpenVikingToolName[] {
284
+ const entries = toStringArray(value, fallback);
285
+ const seen = new Set<OpenVikingToolName>();
286
+ const normalized: OpenVikingToolName[] = [];
287
+ const unknown: string[] = [];
288
+
289
+ for (const rawEntry of entries) {
290
+ const entry = rawEntry.trim();
291
+ const group = OPENVIKING_TOOL_GROUPS[entry];
292
+ const tools = group ??
293
+ ((OPENVIKING_ALL_TOOL_NAMES as readonly string[]).includes(entry)
294
+ ? [entry as OpenVikingToolName]
295
+ : undefined);
296
+ if (!tools) {
297
+ unknown.push(entry);
298
+ continue;
299
+ }
300
+ for (const tool of tools) {
301
+ if (!seen.has(tool)) {
302
+ seen.add(tool);
303
+ normalized.push(tool);
304
+ }
305
+ }
306
+ }
307
+
308
+ if (unknown.length > 0) {
309
+ throw new Error(`openviking ${label} contains unknown tool selectors: ${unknown.join(", ")}`);
310
+ }
311
+ return normalized;
312
+ }
313
+
314
+ function normalizeEnabledTools(cfg: Record<string, unknown>): {
315
+ enabledTools: OpenVikingToolName[];
316
+ disabledTools: OpenVikingToolName[];
317
+ } {
318
+ const enableAddResourceTool = cfg.enableAddResourceTool === true;
319
+ const defaultTools = enableAddResourceTool
320
+ ? [OPENVIKING_ADD_RESOURCE_TOOL_NAME, ...OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES]
321
+ : [...OPENVIKING_DEFAULT_ENABLED_TOOL_NAMES];
322
+ const selected = expandToolSelectors(cfg.enabledTools, defaultTools, "enabledTools");
323
+ const disabled = expandToolSelectors(cfg.disabledTools, [], "disabledTools");
324
+ const disabledSet = new Set(disabled);
325
+ if (!enableAddResourceTool) {
326
+ disabledSet.add(OPENVIKING_ADD_RESOURCE_TOOL_NAME);
327
+ }
328
+ const enabledTools = selected.filter((tool) =>
329
+ !disabledSet.has(tool) &&
330
+ (tool !== OPENVIKING_ADD_RESOURCE_TOOL_NAME || enableAddResourceTool)
331
+ );
332
+
333
+ return {
334
+ enabledTools,
335
+ disabledTools: Array.from(disabledSet),
336
+ };
337
+ }
338
+
121
339
  /** True when env is 1 / true / yes (case-insensitive). Used for debug flags without editing plugin JSON. */
122
340
  function envFlag(name: string): boolean {
123
341
  const v = getEnv(name);
@@ -145,37 +363,29 @@ function resolveDefaultBaseUrl(): string {
145
363
  }
146
364
 
147
365
  export const memoryOpenVikingConfigSchema = {
148
- parse(value: unknown): Required<MemoryOpenVikingConfig> {
366
+ parse(value: unknown): ParsedMemoryOpenVikingConfig {
149
367
  if (!value || typeof value !== "object" || Array.isArray(value)) {
150
368
  value = {};
151
369
  }
152
370
  const cfg = value as Record<string, unknown>;
153
- if ("agentId" in cfg) {
154
- if (!("agent_prefix" in cfg)) {
155
- cfg.agent_prefix = cfg.agentId;
156
- }
157
- delete cfg.agentId;
158
- }
159
371
  assertAllowedKeys(
160
372
  cfg,
161
373
  [
162
374
  "mode",
163
375
  "baseUrl",
164
- "agent_prefix",
165
- "agentId",
376
+ "peer_role",
377
+ "peer_prefix",
166
378
  "serverAuthMode",
167
379
  "apiKey",
168
380
  "accountId",
169
381
  "userId",
170
- "isolateUserScopeByAgent",
171
- "isolateAgentScopeByUser",
172
- "agentScopeMode",
173
382
  "targetUri",
174
383
  "timeoutMs",
175
384
  "autoCapture",
176
385
  "captureMode",
177
386
  "captureMaxLength",
178
387
  "autoRecall",
388
+ "autoRecallTimeoutMs",
179
389
  "recallResources",
180
390
  "recallLimit",
181
391
  "recallScoreThreshold",
@@ -192,11 +402,37 @@ export const memoryOpenVikingConfigSchema = {
192
402
  "ingestReplyAssistIgnoreSessionPatterns",
193
403
  "emitStandardDiagnostics",
194
404
  "logFindRequests",
405
+ "traceRecall",
406
+ "traceRecallPersist",
407
+ "traceRecallDir",
408
+ "traceRecallRetentionDays",
409
+ "traceRecallLoadRecentDays",
410
+ "traceRecallMaxEntries",
411
+ "traceRecallMaxResultsPerSearch",
412
+ "traceRecallPreviewChars",
413
+ "traceRecallQueryMaxChars",
414
+ "traceRecallQueryMaxDays",
415
+ "traceRecallIncludeContentByDefault",
416
+ "traceRecallIncludeRawUserPreview",
417
+ "recallTargetTypes",
418
+ "enableAddResourceTool",
419
+ "enabledTools",
420
+ "disabledTools",
421
+ "runtimeQueryConfigPath",
422
+ "agentExperience",
195
423
  ],
196
424
  "openviking config",
197
425
  );
426
+ const agentExperienceRaw = toRecord(cfg.agentExperience);
427
+ assertAllowedKeys(
428
+ agentExperienceRaw,
429
+ ["enabled", "recallLimit", "scoreThreshold", "maxInjectedChars", "minQueryChars"],
430
+ "openviking config agentExperience",
431
+ );
198
432
 
199
433
  const mode = "remote" as const;
434
+ const peerRole = resolvePeerRole(cfg.peer_role);
435
+ const peerPrefix = resolvePeerPrefix(cfg.peer_prefix);
200
436
  const rawBaseUrl = typeof cfg.baseUrl === "string" ? cfg.baseUrl : resolveDefaultBaseUrl();
201
437
  const resolvedBaseUrl = resolveEnvVars(rawBaseUrl).replace(/\/+$/, "");
202
438
  const rawApiKey = typeof cfg.apiKey === "string" ? cfg.apiKey : getEnv("OPENVIKING_API_KEY");
@@ -218,37 +454,6 @@ export const memoryOpenVikingConfigSchema = {
218
454
  ? cfg.userId.trim()
219
455
  : (getEnv("OPENVIKING_USER_ID")?.trim() || "");
220
456
 
221
- const hasExplicitAgentScopeMode =
222
- typeof cfg.agentScopeMode === "string" || getEnv("OPENVIKING_AGENT_SCOPE_MODE") !== undefined;
223
- const rawAgentScope = cfg.agentScopeMode ?? getEnv("OPENVIKING_AGENT_SCOPE_MODE");
224
- const agentScopeMode =
225
- rawAgentScope === "user_agent" ? "user_agent" as const : "agent" as const;
226
- const explicitIsolateUserScopeByAgent =
227
- typeof cfg.isolateUserScopeByAgent === "boolean"
228
- ? cfg.isolateUserScopeByAgent
229
- : undefined;
230
- const explicitIsolateAgentScopeByUser =
231
- typeof cfg.isolateAgentScopeByUser === "boolean"
232
- ? cfg.isolateAgentScopeByUser
233
- : undefined;
234
- const envIsolateUserScopeByAgent =
235
- explicitIsolateUserScopeByAgent === undefined &&
236
- getEnv("OPENVIKING_ISOLATE_USER_SCOPE_BY_AGENT") !== undefined
237
- ? envFlag("OPENVIKING_ISOLATE_USER_SCOPE_BY_AGENT")
238
- : undefined;
239
- const envIsolateAgentScopeByUser =
240
- explicitIsolateAgentScopeByUser === undefined &&
241
- getEnv("OPENVIKING_ISOLATE_AGENT_SCOPE_BY_USER") !== undefined
242
- ? envFlag("OPENVIKING_ISOLATE_AGENT_SCOPE_BY_USER")
243
- : undefined;
244
- const isolateUserScopeByAgent =
245
- explicitIsolateUserScopeByAgent ??
246
- envIsolateUserScopeByAgent ??
247
- false;
248
- const isolateAgentScopeByUser =
249
- explicitIsolateAgentScopeByUser ??
250
- envIsolateAgentScopeByUser ??
251
- (hasExplicitAgentScopeMode && agentScopeMode === "user_agent" ? true : false);
252
457
  const recallMaxInjectedChars = Math.max(
253
458
  100,
254
459
  Math.min(
@@ -261,17 +466,21 @@ export const memoryOpenVikingConfigSchema = {
261
466
  ),
262
467
  ),
263
468
  );
469
+ const recallResources = cfg.recallResources === true || envFlag("OPENVIKING_RECALL_RESOURCES");
470
+ const recallTargetTypes = normalizeRecallTargetTypes(
471
+ cfg.recallTargetTypes,
472
+ !("recallTargetTypes" in cfg) && recallResources,
473
+ );
474
+ const { enabledTools, disabledTools } = normalizeEnabledTools(cfg);
264
475
 
265
476
  return {
266
477
  mode,
267
478
  baseUrl: resolvedBaseUrl,
268
- agent_prefix: resolveAgentPrefix(cfg.agent_prefix),
479
+ peer_role: peerRole,
480
+ peer_prefix: peerPrefix,
269
481
  apiKey: rawApiKey ? resolveEnvVars(rawApiKey) : "",
270
482
  accountId,
271
483
  userId,
272
- isolateUserScopeByAgent,
273
- isolateAgentScopeByUser,
274
- agentScopeMode,
275
484
  targetUri: typeof cfg.targetUri === "string" ? cfg.targetUri : DEFAULT_TARGET_URI,
276
485
  timeoutMs: Math.max(1000, Math.floor(toNumber(cfg.timeoutMs, DEFAULT_TIMEOUT_MS))),
277
486
  autoCapture: cfg.autoCapture !== false,
@@ -281,7 +490,11 @@ export const memoryOpenVikingConfigSchema = {
281
490
  Math.min(200_000, Math.floor(toNumber(cfg.captureMaxLength, DEFAULT_CAPTURE_MAX_LENGTH))),
282
491
  ),
283
492
  autoRecall: cfg.autoRecall !== false,
284
- recallResources: cfg.recallResources === true || envFlag("OPENVIKING_RECALL_RESOURCES"),
493
+ autoRecallTimeoutMs: Math.max(
494
+ 1000,
495
+ Math.min(300_000, Math.floor(toNumber(cfg.autoRecallTimeoutMs, DEFAULT_AUTO_RECALL_TIMEOUT_MS))),
496
+ ),
497
+ recallResources,
285
498
  recallLimit: Math.max(1, Math.floor(toNumber(cfg.recallLimit, DEFAULT_RECALL_LIMIT))),
286
499
  recallScoreThreshold: Math.min(
287
500
  1,
@@ -323,6 +536,95 @@ export const memoryOpenVikingConfigSchema = {
323
536
  cfg.logFindRequests === true ||
324
537
  envFlag("OPENVIKING_LOG_ROUTING") ||
325
538
  envFlag("OPENVIKING_DEBUG"),
539
+ traceRecall: cfg.traceRecall === true,
540
+ traceRecallPersist: cfg.traceRecallPersist === true,
541
+ traceRecallDir:
542
+ typeof cfg.traceRecallDir === "string" && cfg.traceRecallDir.trim()
543
+ ? expandHomeDir(cfg.traceRecallDir.trim())
544
+ : expandHomeDir(DEFAULT_TRACE_RECALL_DIR),
545
+ traceRecallRetentionDays: toIntegerInRange(
546
+ cfg.traceRecallRetentionDays,
547
+ DEFAULT_TRACE_RECALL_RETENTION_DAYS,
548
+ 1,
549
+ 3650,
550
+ ),
551
+ traceRecallLoadRecentDays: toIntegerInRange(
552
+ cfg.traceRecallLoadRecentDays,
553
+ DEFAULT_TRACE_RECALL_LOAD_RECENT_DAYS,
554
+ 0,
555
+ 3650,
556
+ ),
557
+ traceRecallMaxEntries: toIntegerInRange(
558
+ cfg.traceRecallMaxEntries,
559
+ DEFAULT_TRACE_RECALL_MAX_ENTRIES,
560
+ 1,
561
+ 1_000_000,
562
+ ),
563
+ traceRecallMaxResultsPerSearch: toIntegerInRange(
564
+ cfg.traceRecallMaxResultsPerSearch,
565
+ DEFAULT_TRACE_RECALL_MAX_RESULTS_PER_SEARCH,
566
+ 1,
567
+ 1_000,
568
+ ),
569
+ traceRecallPreviewChars: toIntegerInRange(
570
+ cfg.traceRecallPreviewChars,
571
+ DEFAULT_TRACE_RECALL_PREVIEW_CHARS,
572
+ 20,
573
+ 10_000,
574
+ ),
575
+ traceRecallQueryMaxChars: toIntegerInRange(
576
+ cfg.traceRecallQueryMaxChars,
577
+ DEFAULT_TRACE_RECALL_QUERY_MAX_CHARS,
578
+ 200,
579
+ 200_000,
580
+ ),
581
+ traceRecallQueryMaxDays: toIntegerInRange(
582
+ cfg.traceRecallQueryMaxDays,
583
+ DEFAULT_TRACE_RECALL_QUERY_MAX_DAYS,
584
+ 1,
585
+ 3650,
586
+ ),
587
+ traceRecallIncludeContentByDefault: cfg.traceRecallIncludeContentByDefault === true,
588
+ traceRecallIncludeRawUserPreview: cfg.traceRecallIncludeRawUserPreview === true,
589
+ recallTargetTypes,
590
+ enableAddResourceTool: cfg.enableAddResourceTool === true,
591
+ enabledTools,
592
+ disabledTools,
593
+ runtimeQueryConfigPath:
594
+ typeof cfg.runtimeQueryConfigPath === "string" && cfg.runtimeQueryConfigPath.trim()
595
+ ? expandHomeDir(cfg.runtimeQueryConfigPath.trim())
596
+ : "",
597
+ agentExperience: {
598
+ enabled:
599
+ typeof agentExperienceRaw.enabled === "boolean"
600
+ ? agentExperienceRaw.enabled
601
+ : DEFAULT_AGENT_EXPERIENCE.enabled,
602
+ recallLimit: Math.max(
603
+ 1,
604
+ Math.min(
605
+ 10,
606
+ Math.floor(toNumber(agentExperienceRaw.recallLimit, DEFAULT_AGENT_EXPERIENCE.recallLimit)),
607
+ ),
608
+ ),
609
+ scoreThreshold: Math.min(
610
+ 1,
611
+ Math.max(0, toNumber(agentExperienceRaw.scoreThreshold, DEFAULT_AGENT_EXPERIENCE.scoreThreshold)),
612
+ ),
613
+ maxInjectedChars: Math.max(
614
+ 500,
615
+ Math.min(
616
+ 50_000,
617
+ Math.floor(toNumber(agentExperienceRaw.maxInjectedChars, DEFAULT_AGENT_EXPERIENCE.maxInjectedChars)),
618
+ ),
619
+ ),
620
+ minQueryChars: Math.max(
621
+ 1,
622
+ Math.min(
623
+ 500,
624
+ Math.floor(toNumber(agentExperienceRaw.minQueryChars, DEFAULT_AGENT_EXPERIENCE.minQueryChars)),
625
+ ),
626
+ ),
627
+ },
326
628
  };
327
629
  },
328
630
  uiHints: {
@@ -331,10 +633,15 @@ export const memoryOpenVikingConfigSchema = {
331
633
  placeholder: DEFAULT_BASE_URL,
332
634
  help: "HTTP URL when mode is remote (or use ${OPENVIKING_BASE_URL})",
333
635
  },
334
- agent_prefix: {
335
- label: "Agent Prefix",
636
+ peer_role: {
637
+ label: "Peer Role",
638
+ placeholder: DEFAULT_PEER_ROLE,
639
+ help: 'Controls which session messages get peer_id: "none", "assistant", or "person".',
640
+ },
641
+ peer_prefix: {
642
+ label: "Peer Prefix",
336
643
  placeholder: "optional-prefix",
337
- help: 'Optional prefix for OpenViking X-OpenViking-Agent. Empty means use OpenClaw ctx.agentId directly. Non-empty values are prepended as "<prefix>_<ctx.agentId>" (sanitized to [a-zA-Z0-9_-]). If ctx.agentId is unavailable, OpenClaw default agent "main" is used.',
644
+ help: "Optional prefix applied to assistant peer_id values derived from OpenClaw runtime agent IDs.",
338
645
  },
339
646
  apiKey: {
340
647
  label: "OpenViking API Key",
@@ -354,24 +661,6 @@ export const memoryOpenVikingConfigSchema = {
354
661
  help: "Advanced option. Tenant user ID. Only needed when explicitly sending identity headers.",
355
662
  advanced: true,
356
663
  },
357
- isolateUserScopeByAgent: {
358
- label: "Isolate User Scope By Agent",
359
- placeholder: "false",
360
- help: "Canonical namespace policy. false (default): user alias expands to viking://user/<user_id>/... . true: expands to viking://user/<user_id>/agent/<agent_id>/... . Must match the server-side account namespace policy.",
361
- advanced: true,
362
- },
363
- isolateAgentScopeByUser: {
364
- label: "Isolate Agent Scope By User",
365
- placeholder: "false",
366
- help: "Canonical namespace policy. false (default): agent alias expands to viking://agent/<agent_id>/... . true: expands to viking://agent/<agent_id>/user/<user_id>/... . Must match the server-side account namespace policy.",
367
- advanced: true,
368
- },
369
- agentScopeMode: {
370
- label: "Deprecated Agent Scope Mode",
371
- placeholder: "agent",
372
- help: 'Deprecated compatibility alias for older routing behavior. Prefer isolateUserScopeByAgent / isolateAgentScopeByUser. Mapping: explicit "user_agent" => false/true, explicit "agent" => false/false. When fully unset, the plugin defaults to false/false to match the current server-side default policy.',
373
- advanced: true,
374
- },
375
664
  targetUri: {
376
665
  label: "Search Target URI",
377
666
  placeholder: DEFAULT_TARGET_URI,
@@ -402,11 +691,23 @@ export const memoryOpenVikingConfigSchema = {
402
691
  label: "Auto-Recall",
403
692
  help: "Inject relevant OpenViking memories into agent context",
404
693
  },
694
+ autoRecallTimeoutMs: {
695
+ label: "Auto-Recall Timeout (ms)",
696
+ placeholder: String(DEFAULT_AUTO_RECALL_TIMEOUT_MS),
697
+ advanced: true,
698
+ help: "Outer time budget for the whole auto-recall flow, including search, ranking, and memory reads.",
699
+ },
405
700
  recallResources: {
406
701
  label: "Recall Resources",
407
702
  help: "Include resources (viking://resources) in auto-recall and default memory_recall search. Enables account-level shared knowledge retrieval.",
408
703
  advanced: true,
409
704
  },
705
+ recallTargetTypes: {
706
+ label: "Recall Target Types",
707
+ placeholder: "user,agent",
708
+ help: "Comma-separated auto-recall and default memory_recall targets: user, agent, resource. Session history is available through ov_archive_search and ov_archive_expand.",
709
+ advanced: true,
710
+ },
410
711
  recallLimit: {
411
712
  label: "Recall Limit",
412
713
  placeholder: String(DEFAULT_RECALL_LIMIT),
@@ -472,5 +773,47 @@ export const memoryOpenVikingConfigSchema = {
472
773
  "Or set env OPENVIKING_LOG_ROUTING=1 or OPENVIKING_DEBUG=1 (no JSON edit).",
473
774
  advanced: true,
474
775
  },
776
+ traceRecall: {
777
+ label: "Trace Recall",
778
+ placeholder: "false",
779
+ help: "Enable best-effort recall trace recording for debugging recall and search decisions.",
780
+ advanced: true,
781
+ },
782
+ traceRecallPersist: {
783
+ label: "Persist Recall Trace",
784
+ placeholder: "false",
785
+ help: "Persist recall traces to local JSONL files. Disabled by default.",
786
+ advanced: true,
787
+ },
788
+ traceRecallDir: {
789
+ label: "Recall Trace Directory",
790
+ placeholder: DEFAULT_TRACE_RECALL_DIR,
791
+ help: "Directory for persisted recall trace JSONL files.",
792
+ advanced: true,
793
+ },
794
+ enableAddResourceTool: {
795
+ label: "Enable Add Resource Tool",
796
+ placeholder: "false",
797
+ help: "Disabled by default so search and read flows cannot call add_resource. Set true only when agents should import resources; manual /add-resource remains available.",
798
+ advanced: true,
799
+ },
800
+ enabledTools: {
801
+ label: "Enabled Tools",
802
+ placeholder: "default",
803
+ 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.",
804
+ advanced: true,
805
+ },
806
+ disabledTools: {
807
+ label: "Disabled Tools",
808
+ placeholder: "memory",
809
+ help: "Agent-visible tool blocklist applied after enabledTools. Accepts the same tool names or groups.",
810
+ advanced: true,
811
+ },
812
+ runtimeQueryConfigPath: {
813
+ label: "Runtime Query Config Path",
814
+ placeholder: "~/.openclaw/openviking/runtime-query-config.json",
815
+ help: "Optional JSON file for /ov-query-config runtime overrides. Empty keeps overrides in memory only.",
816
+ advanced: true,
817
+ },
475
818
  },
476
819
  };