openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
116 lines (115 loc) • 5.83 kB
JavaScript
import { s as createSessionCatalogAdoptionCoordinator } from "./session-catalog-C5rciJKU.js";
import { a as CLAUDE_CLI_DEFAULT_MODEL_REF, t as CLAUDE_CLI_BACKEND_ID } from "./cli-constants-Dsp5krT8.js";
import { t as resolveClaudeCatalogHomeDir } from "./session-catalog-home-DC4c4SgQ.js";
import { o as ClaudeCatalogParamsError, s as isResumableClaudeSource } from "./session-catalog-shared-CiyzxK6Y.js";
import { s as gatewayClaudeScanOptions } from "./session-catalog-scan-4wxzSKEc.js";
import { n as adoptedSessionKey, r as adoptedSourceKey } from "./session-catalog-adoption-C3d_naEs.js";
import { t as listClaudeSessions } from "./session-catalog-discovery-DrNiZpI6.js";
import { t as importClaudeHistory } from "./session-catalog-history-CkrJNYvT.js";
import { a as readClaudeSessionTranscript, i as readBoundedClaudeHistory, s as resolveNodeClaudeRecord } from "./session-catalog-listing-Dv8GSksb.js";
import { n as listBoundClaudeSessions, r as resolveClaudeCliRoutedModelId, t as currentClaudeSessionCatalogConfig } from "./session-catalog-runtime-ClnpB6gi.js";
import { n as linkContinued } from "./session-upstream-activity-DYZ56t0D.js";
import fs from "node:fs/promises";
//#region extensions/anthropic/session-catalog-continue.ts
const continueClaudeAdoption = createSessionCatalogAdoptionCoordinator();
async function continueClaudeSession(api, agentId, hostId, threadId, allowProcessHomeFallback) {
const scanOptions = gatewayClaudeScanOptions(allowProcessHomeFallback);
const sourceKey = adoptedSourceKey(hostId, threadId);
const operationKey = `${agentId}\0${sourceKey}`;
const linkSession = async (sessionKey, history) => await linkContinued({
sessionKey,
hostId,
threadId,
...history ? { history } : {},
listLocalSessions: () => listClaudeSessions(resolveClaudeCatalogHomeDir(), scanOptions),
readRemote: async () => (await readClaudeSessionTranscript({
runtime: api.runtime,
hostId,
threadId,
limit: 1,
allowProcessHomeFallback
})).items
});
const existing = listBoundClaudeSessions(api, agentId).get(sourceKey);
if (existing) return await linkSession(existing);
let history;
return await continueClaudeAdoption({
sourceKey: operationKey,
findExisting: () => listBoundClaudeSessions(api, agentId).get(sourceKey),
create: async () => {
let nodeId;
let record;
if (hostId === "gateway:local") {
record = (await listClaudeSessions(resolveClaudeCatalogHomeDir(), scanOptions)).find((candidate) => candidate.threadId === threadId);
if (!record || !isResumableClaudeSource(record.source)) throw new ClaudeCatalogParamsError("only local Claude Code sessions can be continued");
} else if (hostId.startsWith("node:")) {
nodeId = hostId.slice(5);
if (!(await api.runtime.nodes.list()).nodes.find((candidate) => candidate.nodeId === nodeId && candidate.connected === true && candidate.commands?.includes("anthropic.claude.sessions.list.v1") && candidate.commands.includes("anthropic.claude.sessions.read.v1") && candidate.commands.includes("agent.cli.claude.run.v1") && candidate.invocableCommands?.includes("anthropic.claude.sessions.list.v1") === true && candidate.invocableCommands.includes("anthropic.claude.sessions.read.v1") && candidate.invocableCommands.includes("agent.cli.claude.run.v1"))) throw new ClaudeCatalogParamsError("paired node does not permit Claude CLI session continuation");
record = await resolveNodeClaudeRecord({
runtime: api.runtime,
nodeId,
threadId
});
if (!record || record.source !== "claude-cli") throw new ClaudeCatalogParamsError("only Claude CLI sessions can be continued");
} else throw new ClaudeCatalogParamsError("hostId is invalid");
if (hostId === "gateway:local") {
if (!(await fs.stat(record.filePath).catch(() => void 0))?.isFile()) throw new ClaudeCatalogParamsError("Claude session transcript is unavailable");
}
const loadedHistory = await readBoundedClaudeHistory({
runtime: api.runtime,
hostId,
threadId,
allowProcessHomeFallback
});
history = loadedHistory;
const config = currentClaudeSessionCatalogConfig(api);
const adoptingAgentId = agentId;
const model = resolveClaudeCliRoutedModelId(config, adoptingAgentId) ?? CLAUDE_CLI_DEFAULT_MODEL_REF.slice(`claude-cli/`.length);
const marker = {
sourceThreadId: threadId,
...hostId !== "gateway:local" ? { sourceHostId: hostId } : {}
};
return { sessionKey: (await api.runtime.agent.session.createSessionEntry({
cfg: config,
key: adoptedSessionKey(hostId, threadId),
agentId: adoptingAgentId,
recoverMatchingInitialEntry: true,
...record.name ? { displayName: record.name } : {},
...record.cwd ? { spawnedCwd: record.cwd } : {},
...nodeId ? {
execNode: nodeId,
...record.cwd ? { execCwd: record.cwd } : {}
} : {},
initialEntry: {
...record.color ? { color: record.color } : {},
cliBackendId: CLAUDE_CLI_BACKEND_ID,
model,
modelSelectionLocked: true,
pluginOwnerId: api.id,
cliSessionBinding: {
sessionId: threadId,
forceReuse: true,
forkNextResume: true
},
pluginExtensions: { anthropic: { sessionCatalog: marker } }
},
afterCreate: async (entry) => {
await importClaudeHistory({
items: loadedHistory,
threadId,
sessionId: entry.sessionId,
sessionKey: entry.key,
agentId: entry.agentId,
storePath: api.runtime.agent.session.resolveStorePath(config.session?.store, { agentId: entry.agentId }),
...record.cwd ? { cwd: record.cwd } : {},
config
});
return { pluginExtensions: { anthropic: { sessionCatalog: marker } } };
}
})).key };
},
complete: async (continued) => await linkSession(continued.sessionKey, history)
});
}
//#endregion
export { continueClaudeSession as t };