Files
openclaw/extensions/anthropic/session-catalog-runtime.ts
Vincent Koc eba4487b3a improve(anthropic): reduce session catalog startup memory (#119619)
* perf(anthropic): lazy-load session catalog runtime

Punchcard-Session: coral-workshop-workshop-3f

* fix(anthropic): keep session catalog helpers private

Punchcard-Session: coral-workshop-workshop-3f

* docs(plugin-sdk): document catalog create target

Punchcard-Session: coral-workshop-workshop-3f

* fix(plugins): continue catalog target selection

Punchcard-Session: coral-workshop-workshop-3f
2026-08-06 00:28:56 +08:00

87 lines
3.2 KiB
TypeScript

import { resolveEffectiveAgentRuntime } from "openclaw/plugin-sdk/command-auth-native";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
import {
listSessionCatalogEntries,
type SessionCatalogEntrySnapshot,
} from "openclaw/plugin-sdk/session-catalog";
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
import { CLAUDE_CLI_BACKEND_ID, CLAUDE_CLI_ROUTE_PROBE_MODEL_IDS } from "./cli-constants.js";
import { adoptedSourceKey, CLAUDE_LOCAL_SESSION_HOST_ID } from "./session-catalog-adoption.js";
export function currentClaudeSessionCatalogConfig(api: OpenClawPluginApi): OpenClawConfig {
return (api.runtime.config?.current?.() ?? api.config ?? {}) as OpenClawConfig;
}
function boundClaudeSource(
pluginId: string,
entry: {
cliSessionBindings?: unknown;
execHost?: string;
execNode?: string;
pluginOwnerId?: string;
modelSelectionLocked?: boolean;
pluginExtensions?: unknown;
},
): { hostId: string; threadId: string } | undefined {
const anthropic = isRecord(entry.pluginExtensions) ? entry.pluginExtensions.anthropic : undefined;
const marker = isRecord(anthropic) ? anthropic.sessionCatalog : undefined;
const hostId =
isRecord(marker) && typeof marker.sourceHostId === "string"
? marker.sourceHostId
: entry.execHost === "node" && typeof entry.execNode === "string" && entry.execNode.trim()
? `node:${entry.execNode.trim()}`
: CLAUDE_LOCAL_SESSION_HOST_ID;
const bindings = isRecord(entry.cliSessionBindings) ? entry.cliSessionBindings : undefined;
const binding = bindings?.[CLAUDE_CLI_BACKEND_ID];
if (isRecord(binding) && typeof binding.sessionId === "string" && binding.sessionId) {
return { hostId, threadId: binding.sessionId };
}
if (entry.pluginOwnerId !== pluginId || entry.modelSelectionLocked !== true) {
return undefined;
}
return isRecord(marker) && typeof marker.sourceThreadId === "string"
? { hostId, threadId: marker.sourceThreadId }
: undefined;
}
export function listBoundClaudeSessions(
api: OpenClawPluginApi,
sessionEntries?: SessionCatalogEntrySnapshot,
): Map<string, string> {
const config = currentClaudeSessionCatalogConfig(api);
const bound = new Map<string, string>();
for (const { sessionKey, entry } of listSessionCatalogEntries({
config,
runtime: api.runtime,
sessionEntries,
})) {
const source = boundClaudeSource(api.id, entry);
if (source) {
bound.set(adoptedSourceKey(source.hostId, source.threadId), sessionKey);
}
}
return bound;
}
/**
* Resolve the Claude model an agent actually routes to the Claude CLI backend.
* Callers must not assume the current default is routed: existing configs pin
* older Claude models, and stamping the default onto their sessions would
* select a model the operator never routed or allowed.
*/
export function resolveClaudeCliRoutedModelId(
config: OpenClawConfig,
agentId: string,
): string | undefined {
return CLAUDE_CLI_ROUTE_PROBE_MODEL_IDS.find(
(modelId) =>
resolveEffectiveAgentRuntime({
cfg: config,
provider: "anthropic",
modelId,
agentId,
}) === CLAUDE_CLI_BACKEND_ID,
);
}