mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-24 08:01:12 +00:00
* feat(ui): create sessions from catalog headers * fix(ui): deduplicate catalog-owned sessions * fix(ui): preserve catalog session routing state * fix(ui): keep per-agent session creation in switcher * fix(anthropic): normalize runtime config snapshot * test(plugin-sdk): account for model runtime export * test(plugin-sdk): classify current deprecated surface * test(ui): follow agent chip menu trigger * fix(ui): bind catalog drafts to validated agent * fix(ui): resolve catalog targets from gateway * refactor(ui): split sidebar session helpers * chore(ci): complete LOC baseline migration * fix(ui): extract sidebar session catalog rendering * fix(anthropic): use provider-relative catalog model id * chore(ci): ratchet sidebar LOC baselines * test(ui): cover catalog draft retargeting * chore(plugin-sdk): refresh API baseline * style: format catalog session changes * fix(ui): retry catalog drafts after reconnect * fix(ui): back off catalog target retries * fix(ui): keep unresolved catalog drafts locked * fix(ui): gate catalog creation in core * fix(ui): keep catalog renderer private * style(ui): format catalog session target * chore(plugin-sdk): refresh API baseline * style(ui): format catalog group state * Merge latest origin/main CI fixes * fix(ui): preserve catalog session agent selection * fix(ui): preserve catalog session agent * chore(plugin-sdk): refresh API baseline * fix(ui): type catalog route data * chore(plugin-sdk): refresh API baseline * refactor(sessions): centralize transcript path archival * fix(ui): target expanded agent catalog sessions * fix(ui): scope catalog actions to expanded agent * docs(ui): clarify catalog loader fallback * fix(ui): scope catalog pagination to agent * test(ui): type sidebar lifecycle refresh * fix(anthropic): preserve node catalog bindings
103 lines
3.8 KiB
TypeScript
103 lines
3.8 KiB
TypeScript
import {
|
|
listAgentIds,
|
|
resolveAllowedModelRef,
|
|
resolveDefaultAgentId,
|
|
resolveDefaultModelForAgent,
|
|
} from "openclaw/plugin-sdk/agent-runtime";
|
|
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 { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
import {
|
|
CLAUDE_CLI_BACKEND_ID,
|
|
CLAUDE_CLI_CANONICAL_DEFAULT_MODEL_ID,
|
|
CLAUDE_CLI_CANONICAL_DEFAULT_MODEL_REF,
|
|
} 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): Map<string, string> {
|
|
const config = currentClaudeSessionCatalogConfig(api);
|
|
const defaultAgentId = resolveDefaultAgentId(config);
|
|
const agentIds = [
|
|
defaultAgentId,
|
|
...listAgentIds(config).filter((agentId) => agentId !== defaultAgentId),
|
|
];
|
|
const bound = new Map<string, string>();
|
|
for (const { sessionKey, entry } of agentIds.flatMap((agentId) =>
|
|
api.runtime.agent.session.listSessionEntries({ agentId }),
|
|
)) {
|
|
const source = boundClaudeSource(api.id, entry);
|
|
if (source) {
|
|
bound.set(adoptedSourceKey(source.hostId, source.threadId), sessionKey);
|
|
}
|
|
}
|
|
return bound;
|
|
}
|
|
|
|
export function resolveClaudeCatalogCreateSession(
|
|
api: OpenClawPluginApi,
|
|
requestedAgentId?: string,
|
|
): { model: string; agentRuntime: string } | undefined {
|
|
const config = currentClaudeSessionCatalogConfig(api);
|
|
const agentId = requestedAgentId ?? resolveDefaultAgentId(config);
|
|
const agentRuntime = resolveEffectiveAgentRuntime({
|
|
cfg: config,
|
|
provider: "anthropic",
|
|
modelId: CLAUDE_CLI_CANONICAL_DEFAULT_MODEL_ID,
|
|
agentId,
|
|
});
|
|
if (agentRuntime !== CLAUDE_CLI_BACKEND_ID) {
|
|
return undefined;
|
|
}
|
|
const defaultModel = resolveDefaultModelForAgent({ cfg: config, agentId });
|
|
const allowed = resolveAllowedModelRef({
|
|
cfg: config,
|
|
catalog: [],
|
|
raw: CLAUDE_CLI_CANONICAL_DEFAULT_MODEL_REF,
|
|
defaultProvider: defaultModel.provider,
|
|
defaultModel: defaultModel.model,
|
|
});
|
|
return "error" in allowed
|
|
? undefined
|
|
: {
|
|
model: CLAUDE_CLI_CANONICAL_DEFAULT_MODEL_REF,
|
|
agentRuntime: CLAUDE_CLI_BACKEND_ID,
|
|
};
|
|
}
|