@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/dist/client.js CHANGED
@@ -5,6 +5,11 @@ import { mkdtemp, readdir, readFile, rm, stat } from "node:fs/promises";
5
5
  import { tmpdir } from "node:os";
6
6
  import { basename, dirname, join, relative } from "node:path";
7
7
  import { Zip, ZipDeflate } from "fflate";
8
+ import { defaultHttpTransport } from "./adapters/http-transport.js";
9
+ import { defaultResourcePackager, } from "./adapters/resource-packager.js";
10
+ function userSessionUri(sessionId) {
11
+ return `viking://user/sessions/${encodeURIComponent(sessionId)}`;
12
+ }
8
13
  const DEFAULT_WAIT_REQUEST_TIMEOUT_MS = 120_000;
9
14
  export const DEFAULT_PHASE2_POLL_TIMEOUT_MS = 300_000;
10
15
  const WAIT_REQUEST_TIMEOUT_BUFFER_MS = 5_000;
@@ -12,18 +17,8 @@ function sleep(ms) {
12
17
  return new Promise((resolve) => setTimeout(resolve, ms));
13
18
  }
14
19
  const MEMORY_URI_PATTERNS = [
15
- /^viking:\/\/user\/(?:[^/]+(?:\/agent\/[^/]+)?\/)?memories(?:\/|$)/,
16
- /^viking:\/\/agent\/(?:[^/]+(?:\/user\/[^/]+)?\/)?memories(?:\/|$)/,
20
+ /^viking:\/\/user\/(?:[^/]+\/)?memories(?:\/|$)/,
17
21
  ];
18
- const USER_STRUCTURE_DIRS = new Set(["memories", "profile.md", ".abstract.md", ".overview.md"]);
19
- const AGENT_STRUCTURE_DIRS = new Set([
20
- "memories",
21
- "skills",
22
- "instructions",
23
- "workspaces",
24
- ".abstract.md",
25
- ".overview.md",
26
- ]);
27
22
  const REMOTE_RESOURCE_PREFIXES = ["http://", "https://", "git@", "ssh://", "git://"];
28
23
  export function isMemoryUri(uri) {
29
24
  return MEMORY_URI_PATTERNS.some((pattern) => pattern.test(uri));
@@ -55,14 +50,15 @@ export class OpenVikingClient {
55
50
  accountId;
56
51
  userId;
57
52
  routingDebugLog;
58
- isolateUserScopeByAgent;
59
- isolateAgentScopeByUser;
60
- identityCache = new Map();
53
+ transport;
54
+ now;
55
+ sleep;
56
+ resourcePackager;
61
57
  constructor(baseUrl, apiKey, defaultAgentId, timeoutMs,
62
58
  /** When set, sent so ROOT keys or trusted deployments can select tenant identity. */
63
59
  accountId = "", userId = "",
64
60
  /** When set, logs routing for find + session writes (tenant headers + paths; never apiKey). */
65
- routingDebugLog, isolateUserScopeByAgent = false, isolateAgentScopeByUser = true) {
61
+ routingDebugLog, optionsOrLegacyUserScope = {}, _legacyAgentScope, legacyOptions) {
66
62
  this.baseUrl = baseUrl;
67
63
  this.apiKey = apiKey;
68
64
  this.defaultAgentId = defaultAgentId;
@@ -70,23 +66,17 @@ export class OpenVikingClient {
70
66
  this.accountId = accountId;
71
67
  this.userId = userId;
72
68
  this.routingDebugLog = routingDebugLog;
73
- this.isolateUserScopeByAgent = isolateUserScopeByAgent;
74
- this.isolateAgentScopeByUser = isolateAgentScopeByUser;
69
+ const options = typeof optionsOrLegacyUserScope === "object" && optionsOrLegacyUserScope !== null
70
+ ? optionsOrLegacyUserScope
71
+ : (legacyOptions ?? {});
72
+ this.transport = options.transport ?? defaultHttpTransport;
73
+ this.now = options.now ?? Date.now;
74
+ this.sleep = options.sleep ?? sleep;
75
+ this.resourcePackager = options.resourcePackager ?? defaultResourcePackager;
75
76
  }
76
77
  getDefaultAgentId() {
77
78
  return this.defaultAgentId;
78
79
  }
79
- resolveEffectiveAgentId(agentId) {
80
- const explicit = agentId?.trim();
81
- if (explicit) {
82
- return explicit;
83
- }
84
- const prefix = this.defaultAgentId.trim();
85
- return prefix ? `${prefix}_main` : "main";
86
- }
87
- async getResolvedIdentity(agentId) {
88
- return this.getRuntimeIdentity(agentId);
89
- }
90
80
  resolveTenantHeaders() {
91
81
  const apiKey = this.apiKey.trim();
92
82
  const accountId = this.accountId.trim();
@@ -97,27 +87,32 @@ export class OpenVikingClient {
97
87
  ...(userId ? { userId } : {}),
98
88
  };
99
89
  }
100
- async emitRoutingDebug(label, detail, agentId) {
90
+ resolveActorPeerHeader(actorPeerId) {
91
+ const value = actorPeerId?.trim();
92
+ return value || undefined;
93
+ }
94
+ resolveDefaultActorPeerHeader() {
95
+ const peerPrefix = this.defaultAgentId.trim();
96
+ return peerPrefix ? `${peerPrefix}_main` : "main";
97
+ }
98
+ async emitRoutingDebug(label, detail, actorPeerId) {
101
99
  if (!this.routingDebugLog) {
102
100
  return;
103
101
  }
104
- const effectiveAgentId = this.resolveEffectiveAgentId(agentId);
105
- const identity = await this.getRuntimeIdentity(agentId);
106
102
  const tenantHeaders = this.resolveTenantHeaders();
103
+ const actorPeerHeader = this.resolveActorPeerHeader(actorPeerId);
107
104
  this.routingDebugLog(`openviking: ${label} ` +
108
105
  JSON.stringify({
109
106
  ...detail,
110
- X_OpenViking_Agent: effectiveAgentId,
111
107
  X_OpenViking_Account: tenantHeaders.accountId ?? null,
112
108
  X_OpenViking_User: tenantHeaders.userId ?? null,
113
- resolved_user_id: identity.userId,
109
+ X_OpenViking_Actor_Peer: actorPeerHeader ?? null,
114
110
  session_vfs_hint: detail.sessionId
115
- ? `viking://session/${String(detail.sessionId)}`
111
+ ? userSessionUri(String(detail.sessionId))
116
112
  : undefined,
117
113
  }));
118
114
  }
119
- async request(path, init = {}, agentId, requestTimeoutMs) {
120
- const effectiveAgentId = this.resolveEffectiveAgentId(agentId);
115
+ async request(path, init = {}, requestTimeoutMs, actorPeerId) {
121
116
  const controller = new AbortController();
122
117
  const timer = setTimeout(() => controller.abort(), requestTimeoutMs ?? this.timeoutMs);
123
118
  try {
@@ -132,13 +127,14 @@ export class OpenVikingClient {
132
127
  if (tenantHeaders.userId) {
133
128
  headers.set("X-OpenViking-User", tenantHeaders.userId);
134
129
  }
135
- if (effectiveAgentId) {
136
- headers.set("X-OpenViking-Agent", effectiveAgentId);
130
+ const actorPeerHeader = this.resolveActorPeerHeader(actorPeerId);
131
+ if (actorPeerHeader) {
132
+ headers.set("X-OpenViking-Actor-Peer", actorPeerHeader);
137
133
  }
138
134
  if (init.body && !(init.body instanceof FormData) && !headers.has("Content-Type")) {
139
135
  headers.set("Content-Type", "application/json");
140
136
  }
141
- const response = await fetch(`${this.baseUrl}${path}`, {
137
+ const response = await this.transport(`${this.baseUrl}${path}`, {
142
138
  ...init,
143
139
  headers,
144
140
  signal: controller.signal,
@@ -155,97 +151,78 @@ export class OpenVikingClient {
155
151
  clearTimeout(timer);
156
152
  }
157
153
  }
158
- async healthCheck(agentId, requestTimeoutMs) {
159
- await this.request("/health", {}, agentId, requestTimeoutMs);
154
+ async healthCheck(requestTimeoutMs, actorPeerId) {
155
+ await this.request("/health", {}, requestTimeoutMs, actorPeerId ?? this.resolveDefaultActorPeerHeader());
160
156
  }
161
- async getRuntimeIdentity(agentId) {
162
- const effectiveAgentId = this.resolveEffectiveAgentId(agentId);
163
- const cached = this.identityCache.get(effectiveAgentId);
164
- if (cached) {
165
- return cached;
166
- }
167
- const fallback = { userId: "default", agentId: effectiveAgentId };
168
- try {
169
- const status = await this.request("/api/v1/system/status", {}, agentId);
170
- const userId = typeof status.user === "string" && status.user.trim() ? status.user.trim() : "default";
171
- const identity = { userId, agentId: effectiveAgentId };
172
- this.identityCache.set(effectiveAgentId, identity);
173
- return identity;
174
- }
175
- catch {
176
- this.identityCache.set(effectiveAgentId, fallback);
177
- return fallback;
157
+ async createSession(sessionId, options) {
158
+ const body = { session_id: sessionId };
159
+ if (options?.memoryPolicy) {
160
+ body.memory_policy = options.memoryPolicy;
178
161
  }
162
+ return this.request("/api/v1/sessions", { method: "POST", body: JSON.stringify(body) });
179
163
  }
180
- async buildCanonicalRoot(scope, agentId) {
181
- const identity = await this.getRuntimeIdentity(agentId);
182
- if (scope === "user") {
183
- const root = this.isolateUserScopeByAgent
184
- ? `viking://user/${identity.userId}/agent/${identity.agentId}`
185
- : `viking://user/${identity.userId}`;
186
- return root;
187
- }
188
- const root = this.isolateAgentScopeByUser
189
- ? `viking://agent/${identity.agentId}/user/${identity.userId}`
190
- : `viking://agent/${identity.agentId}`;
191
- return root;
192
- }
193
- async normalizeTargetUri(targetUri, agentId) {
194
- const trimmed = targetUri.trim().replace(/\/+$/, "");
195
- const match = trimmed.match(/^viking:\/\/(user|agent)(?:\/(.*))?$/);
196
- if (!match) {
197
- return trimmed;
198
- }
199
- const scope = match[1];
200
- const rawRest = (match[2] ?? "").trim();
201
- if (!rawRest) {
202
- return trimmed;
203
- }
204
- const parts = rawRest.split("/").filter(Boolean);
205
- if (parts.length === 0) {
206
- return trimmed;
164
+ async ensureSession(sessionId, options) {
165
+ try {
166
+ await this.createSession(sessionId, options);
167
+ return true;
207
168
  }
208
- const reservedDirs = scope === "user" ? USER_STRUCTURE_DIRS : AGENT_STRUCTURE_DIRS;
209
- if (!reservedDirs.has(parts[0])) {
210
- return trimmed;
169
+ catch (err) {
170
+ const message = err instanceof Error ? err.message : String(err);
171
+ if (message.includes("[ALREADY_EXISTS]")) {
172
+ return false;
173
+ }
174
+ throw err;
211
175
  }
212
- const root = await this.buildCanonicalRoot(scope, agentId);
213
- return `${root}/${parts.join("/")}`;
214
176
  }
215
- async find(query, options, agentId) {
216
- const normalizedTargetUri = await this.normalizeTargetUri(options.targetUri, agentId);
177
+ async find(query, options, legacyActorPeerId) {
178
+ const targetUri = options.targetUri?.trim().replace(/\/+$/, "") ?? "";
217
179
  const body = {
218
180
  query,
219
- target_uri: normalizedTargetUri,
220
181
  limit: options.limit,
221
182
  score_threshold: options.scoreThreshold,
183
+ context_type: options.contextType,
222
184
  };
223
- const effectiveAgentId = this.resolveEffectiveAgentId(agentId);
224
- const identity = await this.getRuntimeIdentity(agentId);
185
+ if (targetUri) {
186
+ body.target_uri = targetUri;
187
+ }
188
+ const actorPeerId = this.resolveActorPeerHeader(options.actorPeerId ?? legacyActorPeerId);
225
189
  const tenantHeaders = this.resolveTenantHeaders();
226
190
  this.routingDebugLog?.(`openviking: find POST ${this.baseUrl}/api/v1/search/find ` +
227
191
  JSON.stringify({
228
- X_OpenViking_Agent: effectiveAgentId,
229
192
  X_OpenViking_Account: tenantHeaders.accountId ?? null,
230
193
  X_OpenViking_User: tenantHeaders.userId ?? null,
231
- resolved_user_id: identity.userId,
232
- target_uri: normalizedTargetUri,
194
+ X_OpenViking_Actor_Peer: actorPeerId ?? null,
195
+ target_uri: targetUri || null,
233
196
  target_uri_input: options.targetUri,
234
197
  query: query.length > 4000
235
198
  ? `${query.slice(0, 4000)}…(+${query.length - 4000} more chars)`
236
199
  : query,
237
200
  limit: body.limit,
238
201
  score_threshold: body.score_threshold ?? null,
202
+ context_type: body.context_type ?? null,
239
203
  }));
240
204
  return this.request("/api/v1/search/find", {
241
205
  method: "POST",
242
206
  body: JSON.stringify(body),
243
- }, agentId);
207
+ }, undefined, actorPeerId);
244
208
  }
245
- async read(uri, agentId) {
246
- return this.request(`/api/v1/content/read?uri=${encodeURIComponent(uri)}`, {}, agentId);
209
+ async read(uri, actorPeerId) {
210
+ return this.request(`/api/v1/content/read?uri=${encodeURIComponent(uri)}`, {}, undefined, actorPeerId);
247
211
  }
248
- async readToolResult(sessionId, toolResultId, options, agentId) {
212
+ async list(uri, options) {
213
+ const normalizedUri = uri.trim().replace(/\/+$/, "");
214
+ const params = new URLSearchParams({
215
+ uri: normalizedUri,
216
+ recursive: String(options?.recursive ?? false),
217
+ simple: String(options?.simple ?? false),
218
+ output: options?.output ?? "agent",
219
+ abs_limit: String(options?.absLimit ?? 256),
220
+ show_all_hidden: String(options?.showAllHidden ?? false),
221
+ node_limit: String(options?.nodeLimit ?? 1000),
222
+ });
223
+ return this.request(`/api/v1/fs/ls?${params.toString()}`, {}, undefined, options?.actorPeerId);
224
+ }
225
+ async readToolResult(sessionId, toolResultId, options) {
249
226
  const params = new URLSearchParams();
250
227
  if (options?.offset !== undefined)
251
228
  params.set("offset", String(options.offset));
@@ -255,31 +232,29 @@ export class OpenVikingClient {
255
232
  params.set("include_metadata", String(options.includeMetadata));
256
233
  }
257
234
  const query = params.toString();
258
- return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/tool-results/${encodeURIComponent(toolResultId)}${query ? `?${query}` : ""}`, {}, agentId);
235
+ return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/tool-results/${encodeURIComponent(toolResultId)}${query ? `?${query}` : ""}`, {});
259
236
  }
260
- async searchToolResult(sessionId, toolResultId, queryText, options, agentId) {
237
+ async searchToolResult(sessionId, toolResultId, queryText, options) {
261
238
  const params = new URLSearchParams({ q: queryText });
262
239
  if (options?.limit !== undefined)
263
240
  params.set("limit", String(options.limit));
264
241
  if (options?.contextChars !== undefined) {
265
242
  params.set("context_chars", String(options.contextChars));
266
243
  }
267
- return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/tool-results/${encodeURIComponent(toolResultId)}/search?${params.toString()}`, {}, agentId);
244
+ return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/tool-results/${encodeURIComponent(toolResultId)}/search?${params.toString()}`, {});
268
245
  }
269
- async listToolResults(sessionId, options, agentId) {
246
+ async listToolResults(sessionId, options) {
270
247
  const params = new URLSearchParams();
271
248
  if (options?.toolName)
272
249
  params.set("tool_name", options.toolName);
273
250
  if (options?.limit !== undefined)
274
251
  params.set("limit", String(options.limit));
275
252
  const query = params.toString();
276
- return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/tool-results${query ? `?${query}` : ""}`, {}, agentId);
253
+ return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/tool-results${query ? `?${query}` : ""}`, {});
277
254
  }
278
- async uploadTempFile(filePath, agentId) {
279
- const fileBytes = await readFile(filePath);
280
- const form = new FormData();
281
- form.append("file", new Blob([toBlobPart(fileBytes)], { type: "application/octet-stream" }), basename(filePath));
282
- const result = await this.request("/api/v1/resources/temp_upload", { method: "POST", body: form }, agentId);
255
+ async uploadTempFile(filePath, actorPeerId) {
256
+ const form = await this.resourcePackager.createTempUploadBody(filePath);
257
+ const result = await this.request("/api/v1/resources/temp_upload", { method: "POST", body: form }, undefined, actorPeerId);
283
258
  if (!result.temp_file_id) {
284
259
  throw new Error("OpenViking temp upload did not return temp_file_id");
285
260
  }
@@ -340,7 +315,7 @@ export class OpenVikingClient {
340
315
  }
341
316
  return zipPath;
342
317
  }
343
- async addResource(input, agentId) {
318
+ async addResource(input, actorPeerId) {
344
319
  const pathOrUrl = input.pathOrUrl.trim();
345
320
  if (!pathOrUrl) {
346
321
  throw new Error("pathOrUrl is required");
@@ -363,32 +338,26 @@ export class OpenVikingClient {
363
338
  if (typeof input.preserveStructure === "boolean") {
364
339
  body.preserve_structure = input.preserveStructure;
365
340
  }
366
- let cleanupPath;
341
+ let packagedSource;
367
342
  const requestTimeoutMs = input.wait ? resolveWaitRequestTimeoutMs(this.timeoutMs, input.timeout) : undefined;
368
343
  try {
369
- if (isRemoteResourceSource(pathOrUrl)) {
370
- body.path = pathOrUrl;
344
+ packagedSource = await this.resourcePackager.prepareResourceSource(pathOrUrl);
345
+ if (packagedSource.kind === "remote") {
346
+ body.path = packagedSource.path;
371
347
  }
372
348
  else {
373
- const localStats = await stat(pathOrUrl);
374
- let uploadPath = pathOrUrl;
375
- if (localStats.isDirectory()) {
376
- uploadPath = await this.zipDirectoryForUpload(pathOrUrl);
377
- cleanupPath = uploadPath;
378
- body.source_name = basename(pathOrUrl);
379
- }
380
- else if (!localStats.isFile()) {
381
- throw new Error(`Path is not a file or directory: ${pathOrUrl}`);
349
+ if (packagedSource.sourceName) {
350
+ body.source_name = packagedSource.sourceName;
382
351
  }
383
- body.temp_file_id = await this.uploadTempFile(uploadPath, agentId);
352
+ body.temp_file_id = await this.uploadTempFile(packagedSource.uploadPath, actorPeerId);
384
353
  }
385
- return this.request("/api/v1/resources", { method: "POST", body: JSON.stringify(body) }, agentId, requestTimeoutMs);
354
+ return this.request("/api/v1/resources", { method: "POST", body: JSON.stringify(body) }, requestTimeoutMs, actorPeerId);
386
355
  }
387
356
  finally {
388
- await cleanupUploadTempPath(cleanupPath);
357
+ await this.resourcePackager.cleanup(packagedSource);
389
358
  }
390
359
  }
391
- async addSkill(input, agentId) {
360
+ async addSkill(input, actorPeerId) {
392
361
  const hasPath = typeof input.path === "string" && input.path.trim().length > 0;
393
362
  const hasData = input.data !== undefined && input.data !== null;
394
363
  if (hasPath === hasData) {
@@ -398,32 +367,27 @@ export class OpenVikingClient {
398
367
  wait: input.wait ?? false,
399
368
  timeout: input.timeout,
400
369
  };
401
- let cleanupPath;
370
+ let packagedSource;
402
371
  const requestTimeoutMs = input.wait ? resolveWaitRequestTimeoutMs(this.timeoutMs, input.timeout) : undefined;
403
372
  try {
404
373
  if (hasPath) {
405
374
  const skillPath = input.path.trim();
406
- const localStats = await stat(skillPath);
407
- let uploadPath = skillPath;
408
- if (localStats.isDirectory()) {
409
- uploadPath = await this.zipDirectoryForUpload(skillPath);
410
- cleanupPath = uploadPath;
411
- }
412
- else if (!localStats.isFile()) {
375
+ packagedSource = await this.resourcePackager.prepareLocalUploadSource(skillPath);
376
+ if (packagedSource.kind !== "upload") {
413
377
  throw new Error(`Path is not a file or directory: ${skillPath}`);
414
378
  }
415
- body.temp_file_id = await this.uploadTempFile(uploadPath, agentId);
379
+ body.temp_file_id = await this.uploadTempFile(packagedSource.uploadPath, actorPeerId);
416
380
  }
417
381
  else {
418
382
  body.data = input.data;
419
383
  }
420
- return this.request("/api/v1/skills", { method: "POST", body: JSON.stringify(body) }, agentId, requestTimeoutMs);
384
+ return this.request("/api/v1/skills", { method: "POST", body: JSON.stringify(body) }, requestTimeoutMs, actorPeerId);
421
385
  }
422
386
  finally {
423
- await cleanupUploadTempPath(cleanupPath);
387
+ await this.resourcePackager.cleanup(packagedSource);
424
388
  }
425
389
  }
426
- async addSessionMessage(sessionId, role, parts, agentId, createdAt, roleId) {
390
+ async addSessionMessage(sessionId, role, parts, actorPeerId, createdAt, roleId) {
427
391
  const body = { role, parts };
428
392
  if (createdAt) {
429
393
  body.created_at = createdAt;
@@ -438,15 +402,15 @@ export class OpenVikingClient {
438
402
  role_id: roleId ?? null,
439
403
  partCount: parts.length,
440
404
  created_at: createdAt ?? null,
441
- }, agentId);
405
+ }, actorPeerId);
442
406
  await this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/messages`, {
443
407
  method: "POST",
444
408
  body: JSON.stringify(body),
445
- }, agentId);
409
+ }, undefined, actorPeerId);
446
410
  }
447
411
  /** GET session — server auto-creates if absent; returns session meta including message stats and token usage. */
448
- async getSession(sessionId, agentId) {
449
- return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}`, { method: "GET" }, agentId);
412
+ async getSession(sessionId, actorPeerId) {
413
+ return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}`, { method: "GET" }, undefined, actorPeerId);
450
414
  }
451
415
  /**
452
416
  * Commit a session: archive (Phase 1) and extract memories (Phase 2).
@@ -469,15 +433,15 @@ export class OpenVikingClient {
469
433
  if (keepRecentCount > 0) {
470
434
  body.keep_recent_count = keepRecentCount;
471
435
  }
472
- const result = await this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/commit`, { method: "POST", body: JSON.stringify(body) }, options?.agentId);
436
+ const result = await this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/commit`, { method: "POST", body: JSON.stringify(body) }, undefined, options?.agentId);
473
437
  if (!options?.wait || !result.task_id) {
474
438
  return result;
475
439
  }
476
440
  // Client-side poll until Phase 2 finishes
477
- const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_PHASE2_POLL_TIMEOUT_MS);
441
+ const deadline = this.now() + (options.timeoutMs ?? DEFAULT_PHASE2_POLL_TIMEOUT_MS);
478
442
  const pollInterval = 500;
479
- while (Date.now() < deadline) {
480
- await sleep(pollInterval);
443
+ while (this.now() < deadline) {
444
+ await this.sleep(pollInterval);
481
445
  const task = await this.getTask(result.task_id, options.agentId).catch(() => null);
482
446
  if (!task)
483
447
  break;
@@ -498,17 +462,17 @@ export class OpenVikingClient {
498
462
  return result;
499
463
  }
500
464
  /** Poll a background task by ID. */
501
- async getTask(taskId, agentId) {
502
- return this.request(`/api/v1/tasks/${encodeURIComponent(taskId)}`, { method: "GET" }, agentId);
465
+ async getTask(taskId, actorPeerId) {
466
+ return this.request(`/api/v1/tasks/${encodeURIComponent(taskId)}`, { method: "GET" }, undefined, actorPeerId);
503
467
  }
504
- async getSessionContext(sessionId, tokenBudget = 128_000, agentId) {
505
- return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/context?token_budget=${tokenBudget}`, { method: "GET" }, agentId);
468
+ async getSessionContext(sessionId, tokenBudget = 128_000, actorPeerId) {
469
+ return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/context?token_budget=${tokenBudget}`, { method: "GET" }, undefined, actorPeerId);
506
470
  }
507
- async getSessionArchive(sessionId, archiveId, agentId) {
508
- return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/archives/${encodeURIComponent(archiveId)}`, { method: "GET" }, agentId);
471
+ async getSessionArchive(sessionId, archiveId, actorPeerId) {
472
+ return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/archives/${encodeURIComponent(archiveId)}`, { method: "GET" }, undefined, actorPeerId);
509
473
  }
510
474
  async grepSessionArchives(sessionId, pattern, options = {}) {
511
- const baseUri = `viking://session/${sessionId}/history`;
475
+ const baseUri = `${userSessionUri(sessionId)}/history`;
512
476
  const uri = options.archiveId ? `${baseUri}/${options.archiveId}` : baseUri;
513
477
  return this.request("/api/v1/search/grep", {
514
478
  method: "POST",
@@ -519,14 +483,14 @@ export class OpenVikingClient {
519
483
  ...(options.nodeLimit !== undefined ? { node_limit: options.nodeLimit } : {}),
520
484
  ...(options.levelLimit !== undefined ? { level_limit: options.levelLimit } : {}),
521
485
  }),
522
- }, options.agentId);
486
+ });
523
487
  }
524
- async deleteSession(sessionId, agentId) {
525
- await this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}`, { method: "DELETE" }, agentId);
488
+ async deleteSession(sessionId) {
489
+ await this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}`, { method: "DELETE" });
526
490
  }
527
- async deleteUri(uri, agentId) {
491
+ async deleteUri(uri, actorPeerId) {
528
492
  await this.request(`/api/v1/fs?uri=${encodeURIComponent(uri)}&recursive=false`, {
529
493
  method: "DELETE",
530
- }, agentId);
494
+ }, undefined, actorPeerId);
531
495
  }
532
496
  }