Skip to content

Commit 36ff921

Browse files
committed
feat(openclaw-plugin): align agent routing and reduce default log noise; fix(system/status): align resolved user id
1 parent 8c57069 commit 36ff921

File tree

6 files changed

+670
-127
lines changed

6 files changed

+670
-127
lines changed

examples/openclaw-plugin/client.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,42 @@ export class OpenVikingClient {
142142
private readonly apiKey: string,
143143
private readonly defaultAgentId: string,
144144
private readonly timeoutMs: number,
145+
/** When set (or defaulted), sent so ROOT key can access tenant-scoped APIs. */
146+
private readonly accountId: string = "",
147+
private readonly userId: string = "",
148+
/** When set, logs routing for find + session writes (tenant headers + paths; never apiKey). */
149+
private readonly routingDebugLog?: (message: string) => void,
145150
) {}
146151

147152
getDefaultAgentId(): string {
148153
return this.defaultAgentId;
149154
}
150155

156+
private async emitRoutingDebug(
157+
label: string,
158+
detail: Record<string, unknown>,
159+
agentId?: string,
160+
): Promise<void> {
161+
if (!this.routingDebugLog) {
162+
return;
163+
}
164+
const effectiveAgentId = agentId ?? this.defaultAgentId;
165+
const identity = await this.getRuntimeIdentity(agentId);
166+
this.routingDebugLog(
167+
`openviking: ${label} ` +
168+
JSON.stringify({
169+
...detail,
170+
X_OpenViking_Agent: effectiveAgentId,
171+
X_OpenViking_Account: this.accountId.trim() || "default",
172+
X_OpenViking_User: this.userId.trim() || "default",
173+
resolved_user_id: identity.userId,
174+
session_vfs_hint: detail.sessionId
175+
? `viking://session/${identity.userId}/${String(detail.sessionId)}`
176+
: undefined,
177+
}),
178+
);
179+
}
180+
151181
private async request<T>(path: string, init: RequestInit = {}, agentId?: string): Promise<T> {
152182
const effectiveAgentId = agentId ?? this.defaultAgentId;
153183
const controller = new AbortController();
@@ -157,6 +187,8 @@ export class OpenVikingClient {
157187
if (this.apiKey) {
158188
headers.set("X-API-Key", this.apiKey);
159189
}
190+
headers.set("X-OpenViking-Account", this.accountId.trim() || "default");
191+
headers.set("X-OpenViking-User", this.userId.trim() || "default");
160192
if (effectiveAgentId) {
161193
headers.set("X-OpenViking-Agent", effectiveAgentId);
162194
}
@@ -311,6 +343,25 @@ export class OpenVikingClient {
311343
limit: options.limit,
312344
score_threshold: options.scoreThreshold,
313345
};
346+
const effectiveAgentId = agentId ?? this.defaultAgentId;
347+
const identity = await this.getRuntimeIdentity(agentId);
348+
this.routingDebugLog?.(
349+
`openviking: find POST ${this.baseUrl}/api/v1/search/find ` +
350+
JSON.stringify({
351+
X_OpenViking_Agent: effectiveAgentId,
352+
X_OpenViking_Account: this.accountId.trim() || "default",
353+
X_OpenViking_User: this.userId.trim() || "default",
354+
resolved_user_id: identity.userId,
355+
target_uri: normalizedTargetUri,
356+
target_uri_input: options.targetUri,
357+
query:
358+
query.length > 4000
359+
? `${query.slice(0, 4000)}…(+${query.length - 4000} more chars)`
360+
: query,
361+
limit: body.limit,
362+
score_threshold: body.score_threshold ?? null,
363+
}),
364+
);
314365
return this.request<FindResult>("/api/v1/search/find", {
315366
method: "POST",
316367
body: JSON.stringify(body),
@@ -326,6 +377,16 @@ export class OpenVikingClient {
326377
}
327378

328379
async addSessionMessage(sessionId: string, role: string, content: string, agentId?: string): Promise<void> {
380+
await this.emitRoutingDebug(
381+
"session message POST",
382+
{
383+
path: `/api/v1/sessions/${encodeURIComponent(sessionId)}/messages`,
384+
sessionId,
385+
role,
386+
contentChars: content.length,
387+
},
388+
agentId,
389+
);
329390
await this.request<{ session_id: string }>(
330391
`/api/v1/sessions/${encodeURIComponent(sessionId)}/messages`,
331392
{
@@ -368,6 +429,15 @@ export class OpenVikingClient {
368429
sessionId: string,
369430
options?: { wait?: boolean; timeoutMs?: number; agentId?: string },
370431
): Promise<CommitSessionResult> {
432+
await this.emitRoutingDebug(
433+
"session commit POST (archive + memory extraction)",
434+
{
435+
path: `/api/v1/sessions/${encodeURIComponent(sessionId)}/commit`,
436+
sessionId,
437+
wait: options?.wait ?? false,
438+
},
439+
options?.agentId,
440+
);
371441
const result = await this.request<CommitSessionResult>(
372442
`/api/v1/sessions/${encodeURIComponent(sessionId)}/commit`,
373443
{ method: "POST", body: JSON.stringify({}) },

examples/openclaw-plugin/config.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export type MemoryOpenVikingConfig = {
3232
* standard-diagnostics file writes) for assemble/afterTurn. Set false to disable.
3333
*/
3434
emitStandardDiagnostics?: boolean;
35+
/** When true, log tenant routing for semantic find and session writes (messages/commit) to the plugin logger. */
36+
logFindRequests?: boolean;
3537
};
3638

3739
const DEFAULT_BASE_URL = "http://127.0.0.1:1933";
@@ -84,6 +86,16 @@ function toNumber(value: unknown, fallback: number): number {
8486
return fallback;
8587
}
8688

89+
/** True when env is 1 / true / yes (case-insensitive). Used for debug flags without editing plugin JSON. */
90+
function envFlag(name: string): boolean {
91+
const v = process.env[name];
92+
if (v == null || v === "") {
93+
return false;
94+
}
95+
const t = String(v).trim().toLowerCase();
96+
return t === "1" || t === "true" || t === "yes";
97+
}
98+
8799
function assertAllowedKeys(value: Record<string, unknown>, allowed: string[], label: string) {
88100
const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
89101
if (unknown.length === 0) {
@@ -131,6 +143,7 @@ export const memoryOpenVikingConfigSchema = {
131143
"ingestReplyAssistMinSpeakerTurns",
132144
"ingestReplyAssistMinChars",
133145
"emitStandardDiagnostics",
146+
"logFindRequests",
134147
],
135148
"openviking config",
136149
);
@@ -219,6 +232,10 @@ export const memoryOpenVikingConfigSchema = {
219232
typeof cfg.emitStandardDiagnostics === "boolean"
220233
? cfg.emitStandardDiagnostics
221234
: DEFAULT_EMIT_STANDARD_DIAGNOSTICS,
235+
logFindRequests:
236+
cfg.logFindRequests === true ||
237+
envFlag("OPENVIKING_LOG_ROUTING") ||
238+
envFlag("OPENVIKING_DEBUG"),
222239
};
223240
},
224241
uiHints: {
@@ -245,7 +262,7 @@ export const memoryOpenVikingConfigSchema = {
245262
agentId: {
246263
label: "Agent ID",
247264
placeholder: "auto-generated",
248-
help: "Identifies this agent to OpenViking (sent as X-OpenViking-Agent header). Defaults to \"default\" if not set.",
265+
help: 'OpenViking X-OpenViking-Agent: non-default values combine with OpenClaw ctx.agentId as "<config>_<sessionAgent>" (then sanitized to [a-zA-Z0-9_-]). Use "default" to send only ctx.agentId.',
249266
},
250267
apiKey: {
251268
label: "OpenViking API Key",
@@ -338,6 +355,13 @@ export const memoryOpenVikingConfigSchema = {
338355
advanced: true,
339356
help: "When enabled, emit structured openviking: diag {...} lines for assemble and afterTurn. Disable to reduce log noise.",
340357
},
358+
logFindRequests: {
359+
label: "Log find requests",
360+
help:
361+
"Log tenant routing: POST /api/v1/search/find (query, target_uri) and session POST .../messages + .../commit (sessionId, X-OpenViking-*). Never logs apiKey. " +
362+
"Or set env OPENVIKING_LOG_ROUTING=1 or OPENVIKING_DEBUG=1 (no JSON edit). When on, local-mode OpenViking subprocess stderr is also logged at info.",
363+
advanced: true,
364+
},
341365
},
342366
};
343367

0 commit comments

Comments
 (0)