mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-08 00:32:55 +00:00
* fix restart sentinel internal continuations * update gateway prompt snapshots * stabilize sandbox browser audit timer tests * drive sandbox audit timeouts deterministically * drive gh-read timeout tests deterministically * drive label-open-issues timeout tests deterministically * document deterministic timeout test timers * test: preserve deterministic timer setup after rebase
114 lines
3.9 KiB
TypeScript
114 lines
3.9 KiB
TypeScript
import type { SourceReplyDeliveryMode } from "../auto-reply/get-reply-options.types.js";
|
|
import type { InboundEventKind } from "../channels/inbound-event/kind.js";
|
|
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
|
import {
|
|
buildMcpToolSchema,
|
|
type McpLoopbackTool,
|
|
type McpToolSchemaEntry,
|
|
} from "./mcp-http.schema.js";
|
|
import { resolveGatewayScopedTools } from "./tool-resolution.js";
|
|
|
|
const TOOL_CACHE_TTL_MS = 30_000;
|
|
const NATIVE_TOOL_EXCLUDE = new Set(["read", "write", "edit", "apply_patch", "exec", "process"]);
|
|
|
|
type CachedScopedTools = {
|
|
agentId: string | undefined;
|
|
tools: McpLoopbackTool[];
|
|
toolSchema: McpToolSchemaEntry[];
|
|
configRef: OpenClawConfig;
|
|
time: number;
|
|
};
|
|
|
|
export function resolveMcpLoopbackScopedTools(params: {
|
|
cfg: OpenClawConfig;
|
|
sessionKey: string;
|
|
messageProvider: string | undefined;
|
|
currentChannelId: string | undefined;
|
|
currentThreadTs: string | undefined;
|
|
currentMessageId: string | number | undefined;
|
|
accountId: string | undefined;
|
|
inboundEventKind: InboundEventKind | undefined;
|
|
sourceReplyDeliveryMode: SourceReplyDeliveryMode | undefined;
|
|
senderIsOwner: boolean | undefined;
|
|
}): { agentId: string | undefined; tools: McpLoopbackTool[] } {
|
|
const scoped = resolveGatewayScopedTools({
|
|
cfg: params.cfg,
|
|
sessionKey: params.sessionKey,
|
|
messageProvider: params.messageProvider,
|
|
currentChannelId: params.currentChannelId,
|
|
currentThreadTs: params.currentThreadTs,
|
|
currentMessageId: params.currentMessageId,
|
|
accountId: params.accountId,
|
|
inboundEventKind: params.inboundEventKind,
|
|
sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
|
|
senderIsOwner: params.senderIsOwner,
|
|
surface: "loopback",
|
|
excludeToolNames: NATIVE_TOOL_EXCLUDE,
|
|
});
|
|
return {
|
|
agentId: scoped.agentId,
|
|
tools: scoped.tools,
|
|
};
|
|
}
|
|
|
|
export class McpLoopbackToolCache {
|
|
#entries = new Map<string, CachedScopedTools>();
|
|
|
|
resolve(params: {
|
|
cfg: OpenClawConfig;
|
|
sessionKey: string;
|
|
messageProvider: string | undefined;
|
|
currentChannelId: string | undefined;
|
|
currentThreadTs: string | undefined;
|
|
currentMessageId: string | number | undefined;
|
|
accountId: string | undefined;
|
|
inboundEventKind: InboundEventKind | undefined;
|
|
sourceReplyDeliveryMode: SourceReplyDeliveryMode | undefined;
|
|
senderIsOwner: boolean | undefined;
|
|
}): CachedScopedTools {
|
|
const cacheKey = [
|
|
params.sessionKey,
|
|
params.messageProvider ?? "",
|
|
params.currentChannelId ?? "",
|
|
params.currentThreadTs ?? "",
|
|
params.currentMessageId != null ? String(params.currentMessageId) : "",
|
|
params.accountId ?? "",
|
|
params.inboundEventKind ?? "",
|
|
params.sourceReplyDeliveryMode ?? "",
|
|
params.senderIsOwner === true ? "owner" : "non-owner",
|
|
].join("\u0000");
|
|
const now = Date.now();
|
|
const cached = this.#entries.get(cacheKey);
|
|
if (cached && cached.configRef === params.cfg && now - cached.time < TOOL_CACHE_TTL_MS) {
|
|
return cached;
|
|
}
|
|
|
|
const next = resolveMcpLoopbackScopedTools({
|
|
cfg: params.cfg,
|
|
sessionKey: params.sessionKey,
|
|
messageProvider: params.messageProvider,
|
|
currentChannelId: params.currentChannelId,
|
|
currentThreadTs: params.currentThreadTs,
|
|
currentMessageId: params.currentMessageId,
|
|
accountId: params.accountId,
|
|
inboundEventKind: params.inboundEventKind,
|
|
sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
|
|
senderIsOwner: params.senderIsOwner,
|
|
});
|
|
const nextEntry: CachedScopedTools = {
|
|
agentId: next.agentId,
|
|
tools: next.tools,
|
|
toolSchema: buildMcpToolSchema(next.tools),
|
|
configRef: params.cfg,
|
|
time: now,
|
|
};
|
|
this.#entries.set(cacheKey, nextEntry);
|
|
for (const [key, entry] of this.#entries) {
|
|
if (now - entry.time >= TOOL_CACHE_TTL_MS) {
|
|
this.#entries.delete(key);
|
|
}
|
|
}
|
|
return nextEntry;
|
|
}
|
|
}
|