mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-11 12:58:34 +00:00
refactor: drop legacy cli session aliases
This commit is contained in:
@@ -218,8 +218,7 @@ type OverrideFieldClearedByDelete =
|
||||
| "authProfileOverrideCompactionCount"
|
||||
| "fallbackNoticeSelectedModel"
|
||||
| "fallbackNoticeActiveModel"
|
||||
| "fallbackNoticeReason"
|
||||
| "claudeCliSessionId";
|
||||
| "fallbackNoticeReason";
|
||||
|
||||
const OVERRIDE_FIELDS_CLEARED_BY_DELETE: OverrideFieldClearedByDelete[] = [
|
||||
"providerOverride",
|
||||
@@ -230,7 +229,6 @@ const OVERRIDE_FIELDS_CLEARED_BY_DELETE: OverrideFieldClearedByDelete[] = [
|
||||
"fallbackNoticeSelectedModel",
|
||||
"fallbackNoticeActiveModel",
|
||||
"fallbackNoticeReason",
|
||||
"claudeCliSessionId",
|
||||
];
|
||||
|
||||
const OVERRIDE_VALUE_MAX_LENGTH = 256;
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from "./cli-session.js";
|
||||
|
||||
describe("cli-session helpers", () => {
|
||||
it("persists binding metadata alongside legacy session ids", () => {
|
||||
it("persists binding metadata in the canonical CLI session binding", () => {
|
||||
const entry: SessionEntry = {
|
||||
sessionId: "openclaw-session",
|
||||
updatedAt: Date.now(),
|
||||
@@ -27,8 +27,6 @@ describe("cli-session helpers", () => {
|
||||
mcpResumeHash: "mcp-resume-hash",
|
||||
});
|
||||
|
||||
expect(entry.cliSessionIds?.["claude-cli"]).toBe("cli-session-1");
|
||||
expect(entry.claudeCliSessionId).toBe("cli-session-1");
|
||||
expect(getCliSessionBinding(entry, "claude-cli")).toEqual({
|
||||
sessionId: "cli-session-1",
|
||||
forceReuse: true,
|
||||
@@ -66,12 +64,11 @@ describe("cli-session helpers", () => {
|
||||
).toEqual({ sessionId: "cli-session-1" });
|
||||
});
|
||||
|
||||
it("keeps legacy bindings reusable until richer metadata is persisted", () => {
|
||||
it("keeps bindings reusable until richer metadata is persisted", () => {
|
||||
const entry: SessionEntry = {
|
||||
sessionId: "openclaw-session",
|
||||
updatedAt: Date.now(),
|
||||
cliSessionIds: { "claude-cli": "legacy-session" },
|
||||
claudeCliSessionId: "legacy-session",
|
||||
cliSessionBindings: { "claude-cli": { sessionId: "cli-session" } },
|
||||
};
|
||||
|
||||
expect(
|
||||
@@ -79,15 +76,14 @@ describe("cli-session helpers", () => {
|
||||
binding: getCliSessionBinding(entry, "claude-cli"),
|
||||
authEpochVersion: 2,
|
||||
}),
|
||||
).toEqual({ sessionId: "legacy-session" });
|
||||
).toEqual({ sessionId: "cli-session" });
|
||||
});
|
||||
|
||||
it("invalidates legacy bindings when auth, prompt, or MCP state changes", () => {
|
||||
it("invalidates bindings without matching metadata when auth, prompt, or MCP state changes", () => {
|
||||
const entry: SessionEntry = {
|
||||
sessionId: "openclaw-session",
|
||||
updatedAt: Date.now(),
|
||||
cliSessionIds: { "claude-cli": "legacy-session" },
|
||||
claudeCliSessionId: "legacy-session",
|
||||
cliSessionBindings: { "claude-cli": { sessionId: "cli-session" } },
|
||||
};
|
||||
const binding = getCliSessionBinding(entry, "claude-cli");
|
||||
|
||||
@@ -363,8 +359,6 @@ describe("cli-session helpers", () => {
|
||||
|
||||
clearAllCliSessions(entry);
|
||||
expect(entry.cliSessionBindings).toBeUndefined();
|
||||
expect(entry.cliSessionIds).toBeUndefined();
|
||||
expect(entry.claudeCliSessionId).toBeUndefined();
|
||||
});
|
||||
|
||||
it("hashes trimmed extra system prompts consistently", () => {
|
||||
|
||||
@@ -3,8 +3,6 @@ import type { CliSessionBinding, SessionEntry } from "../config/sessions.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { normalizeProviderId } from "./model-selection.js";
|
||||
|
||||
const CLAUDE_CLI_BACKEND_ID = "claude-cli";
|
||||
|
||||
export function hashCliSessionText(value: string | undefined): string | undefined {
|
||||
const trimmed = normalizeOptionalString(value);
|
||||
if (!trimmed) {
|
||||
@@ -35,17 +33,6 @@ export function getCliSessionBinding(
|
||||
mcpResumeHash: normalizeOptionalString(fromBindings?.mcpResumeHash),
|
||||
};
|
||||
}
|
||||
const fromMap = entry.cliSessionIds?.[normalized];
|
||||
const normalizedFromMap = normalizeOptionalString(fromMap);
|
||||
if (normalizedFromMap) {
|
||||
return { sessionId: normalizedFromMap };
|
||||
}
|
||||
if (normalized === CLAUDE_CLI_BACKEND_ID) {
|
||||
const legacy = normalizeOptionalString(entry.claudeCliSessionId);
|
||||
if (legacy) {
|
||||
return { sessionId: legacy };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -95,10 +82,6 @@ export function setCliSessionBinding(
|
||||
: {}),
|
||||
},
|
||||
};
|
||||
entry.cliSessionIds = { ...entry.cliSessionIds, [normalized]: trimmed };
|
||||
if (normalized === CLAUDE_CLI_BACKEND_ID) {
|
||||
entry.claudeCliSessionId = trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
export function clearCliSession(entry: SessionEntry, provider: string): void {
|
||||
@@ -108,20 +91,10 @@ export function clearCliSession(entry: SessionEntry, provider: string): void {
|
||||
delete next[normalized];
|
||||
entry.cliSessionBindings = Object.keys(next).length > 0 ? next : undefined;
|
||||
}
|
||||
if (entry.cliSessionIds?.[normalized] !== undefined) {
|
||||
const next = { ...entry.cliSessionIds };
|
||||
delete next[normalized];
|
||||
entry.cliSessionIds = Object.keys(next).length > 0 ? next : undefined;
|
||||
}
|
||||
if (normalized === CLAUDE_CLI_BACKEND_ID) {
|
||||
entry.claudeCliSessionId = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function clearAllCliSessions(entry: SessionEntry): void {
|
||||
entry.cliSessionBindings = undefined;
|
||||
entry.cliSessionIds = undefined;
|
||||
entry.claudeCliSessionId = undefined;
|
||||
}
|
||||
|
||||
export function resolveCliSessionReuse(params: {
|
||||
|
||||
@@ -206,8 +206,12 @@ describe("CLI attempt execution", () => {
|
||||
const sessionEntry: SessionEntry = {
|
||||
sessionId: "session-cli-123",
|
||||
updatedAt: Date.now(),
|
||||
cliSessionIds: { "claude-cli": "stale-cli-session" },
|
||||
claudeCliSessionId: "stale-legacy-session",
|
||||
cliSessionBindings: {
|
||||
"claude-cli": {
|
||||
sessionId: "stale-cli-session",
|
||||
authProfileId: "anthropic:claude-cli",
|
||||
},
|
||||
},
|
||||
};
|
||||
const sessionStore: Record<string, SessionEntry> = { [sessionKey]: sessionEntry };
|
||||
await writeStore(sessionStore);
|
||||
@@ -254,12 +258,10 @@ describe("CLI attempt execution", () => {
|
||||
expect(runCliAgentMock).toHaveBeenCalledTimes(2);
|
||||
expect(runCliAgentMock.mock.calls[0]?.[0]?.cliSessionId).toBe("stale-cli-session");
|
||||
expect(runCliAgentMock.mock.calls[1]?.[0]?.cliSessionId).toBeUndefined();
|
||||
expect(sessionStore[sessionKey]?.cliSessionIds?.["claude-cli"]).toBeUndefined();
|
||||
expect(sessionStore[sessionKey]?.claudeCliSessionId).toBeUndefined();
|
||||
expect(sessionStore[sessionKey]?.cliSessionBindings?.["claude-cli"]).toBeUndefined();
|
||||
|
||||
const persisted = readStore();
|
||||
expect(persisted[sessionKey]?.cliSessionIds?.["claude-cli"]).toBeUndefined();
|
||||
expect(persisted[sessionKey]?.claudeCliSessionId).toBeUndefined();
|
||||
expect(persisted[sessionKey]?.cliSessionBindings?.["claude-cli"]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not pass --resume when the stored Claude CLI transcript is missing", async () => {
|
||||
@@ -275,8 +277,6 @@ describe("CLI attempt execution", () => {
|
||||
authProfileId: "anthropic:claude-cli",
|
||||
},
|
||||
},
|
||||
cliSessionIds: { "claude-cli": "phantom-claude-session" },
|
||||
claudeCliSessionId: "phantom-claude-session",
|
||||
};
|
||||
const sessionStore: Record<string, SessionEntry> = { [sessionKey]: sessionEntry };
|
||||
await writeStore(sessionStore);
|
||||
@@ -294,13 +294,9 @@ describe("CLI attempt execution", () => {
|
||||
expect(runCliAgentMock.mock.calls[0]?.[0]?.cliSessionId).toBeUndefined();
|
||||
expect(runCliAgentMock.mock.calls[0]?.[0]?.cliSessionBinding).toBeUndefined();
|
||||
expect(sessionStore[sessionKey]?.cliSessionBindings?.["claude-cli"]).toBeUndefined();
|
||||
expect(sessionStore[sessionKey]?.cliSessionIds?.["claude-cli"]).toBeUndefined();
|
||||
expect(sessionStore[sessionKey]?.claudeCliSessionId).toBeUndefined();
|
||||
|
||||
const persisted = readStore();
|
||||
expect(persisted[sessionKey]?.cliSessionBindings?.["claude-cli"]).toBeUndefined();
|
||||
expect(persisted[sessionKey]?.cliSessionIds?.["claude-cli"]).toBeUndefined();
|
||||
expect(persisted[sessionKey]?.claudeCliSessionId).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps Claude CLI resume when the stored transcript has assistant content", async () => {
|
||||
@@ -330,8 +326,6 @@ describe("CLI attempt execution", () => {
|
||||
authProfileId: "anthropic:claude-cli",
|
||||
},
|
||||
},
|
||||
cliSessionIds: { "claude-cli": cliSessionId },
|
||||
claudeCliSessionId: cliSessionId,
|
||||
};
|
||||
const sessionStore: Record<string, SessionEntry> = { [sessionKey]: sessionEntry };
|
||||
await writeStore(sessionStore);
|
||||
@@ -351,8 +345,9 @@ describe("CLI attempt execution", () => {
|
||||
sessionId: cliSessionId,
|
||||
authProfileId: "anthropic:claude-cli",
|
||||
});
|
||||
expect(sessionStore[sessionKey]?.cliSessionIds?.["claude-cli"]).toBe(cliSessionId);
|
||||
expect(sessionStore[sessionKey]?.claudeCliSessionId).toBe(cliSessionId);
|
||||
expect(sessionStore[sessionKey]?.cliSessionBindings?.["claude-cli"]?.sessionId).toBe(
|
||||
cliSessionId,
|
||||
);
|
||||
});
|
||||
|
||||
it("passes session-bound OpenAI Codex auth profile to codex-cli aliases", async () => {
|
||||
|
||||
@@ -107,10 +107,6 @@ describe("runCliTurnCompactionLifecycle", () => {
|
||||
cliSessionBindings: {
|
||||
"claude-cli": { sessionId: "claude-session" },
|
||||
},
|
||||
cliSessionIds: {
|
||||
"claude-cli": "claude-session",
|
||||
},
|
||||
claudeCliSessionId: "claude-session",
|
||||
};
|
||||
const sessionStore: Record<string, SessionEntry> = { [sessionKey]: sessionEntry };
|
||||
upsertSessionEntry({ agentId: "main", sessionKey, entry: sessionEntry });
|
||||
@@ -170,8 +166,6 @@ describe("runCliTurnCompactionLifecycle", () => {
|
||||
);
|
||||
expect(updatedEntry?.compactionCount).toBe(1);
|
||||
expect(updatedEntry?.cliSessionBindings?.["claude-cli"]).toBeUndefined();
|
||||
expect(updatedEntry?.cliSessionIds?.["claude-cli"]).toBeUndefined();
|
||||
expect(updatedEntry?.claudeCliSessionId).toBeUndefined();
|
||||
});
|
||||
|
||||
it("initializes built-in context engines before resolving CLI compaction engine", async () => {
|
||||
|
||||
@@ -317,15 +317,11 @@ describe("updateSessionEntryAfterAgentRun", () => {
|
||||
expect(sessionStore[sessionKey]?.cliSessionBindings?.["claude-cli"]).toEqual({
|
||||
sessionId: "cli-session-123",
|
||||
});
|
||||
expect(sessionStore[sessionKey]?.cliSessionIds?.["claude-cli"]).toBe("cli-session-123");
|
||||
expect(sessionStore[sessionKey]?.claudeCliSessionId).toBe("cli-session-123");
|
||||
|
||||
const persisted = readMockSessionEntries(agentId);
|
||||
expect(persisted[sessionKey]?.cliSessionBindings?.["claude-cli"]).toEqual({
|
||||
sessionId: "cli-session-123",
|
||||
});
|
||||
expect(persisted[sessionKey]?.cliSessionIds?.["claude-cli"]).toBe("cli-session-123");
|
||||
expect(persisted[sessionKey]?.claudeCliSessionId).toBe("cli-session-123");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1163,11 +1159,6 @@ describe("clearCliSessionEntry", () => {
|
||||
sessionId: "codex-session-1",
|
||||
},
|
||||
},
|
||||
cliSessionIds: {
|
||||
"claude-cli": "claude-session-1",
|
||||
"codex-cli": "codex-session-1",
|
||||
},
|
||||
claudeCliSessionId: "claude-session-1",
|
||||
};
|
||||
const sessionStore: Record<string, SessionEntry> = { [sessionKey]: entry };
|
||||
await replaceMockSessionEntries(agentId, sessionStore);
|
||||
@@ -1182,9 +1173,6 @@ describe("clearCliSessionEntry", () => {
|
||||
expect(cleared?.cliSessionBindings?.["codex-cli"]).toEqual({
|
||||
sessionId: "codex-session-1",
|
||||
});
|
||||
expect(cleared?.cliSessionIds?.["claude-cli"]).toBeUndefined();
|
||||
expect(cleared?.cliSessionIds?.["codex-cli"]).toBe("codex-session-1");
|
||||
expect(cleared?.claudeCliSessionId).toBeUndefined();
|
||||
expect(sessionStore[sessionKey]).toEqual(cleared);
|
||||
|
||||
const persisted = readMockSessionEntries(agentId)[sessionKey];
|
||||
@@ -1192,9 +1180,6 @@ describe("clearCliSessionEntry", () => {
|
||||
expect(persisted?.cliSessionBindings?.["codex-cli"]).toEqual({
|
||||
sessionId: "codex-session-1",
|
||||
});
|
||||
expect(persisted?.cliSessionIds?.["claude-cli"]).toBeUndefined();
|
||||
expect(persisted?.cliSessionIds?.["codex-cli"]).toBe("codex-session-1");
|
||||
expect(persisted?.claudeCliSessionId).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1205,7 +1190,7 @@ describe("clearCliSessionEntry", () => {
|
||||
[existingKey]: {
|
||||
sessionId: "openclaw-session-1",
|
||||
updatedAt: 1,
|
||||
claudeCliSessionId: "claude-session-1",
|
||||
cliSessionBindings: { "claude-cli": { sessionId: "claude-session-1" } },
|
||||
},
|
||||
};
|
||||
await replaceMockSessionEntries(agentId, sessionStore);
|
||||
@@ -1217,10 +1202,12 @@ describe("clearCliSessionEntry", () => {
|
||||
});
|
||||
|
||||
expect(cleared).toBeUndefined();
|
||||
expect(sessionStore[existingKey]?.claudeCliSessionId).toBe("claude-session-1");
|
||||
expect(readMockSessionEntries(agentId)[existingKey]?.claudeCliSessionId).toBe(
|
||||
expect(sessionStore[existingKey]?.cliSessionBindings?.["claude-cli"]?.sessionId).toBe(
|
||||
"claude-session-1",
|
||||
);
|
||||
expect(
|
||||
readMockSessionEntries(agentId)[existingKey]?.cliSessionBindings?.["claude-cli"]?.sessionId,
|
||||
).toBe("claude-session-1");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -331,14 +331,12 @@ describe("handleCommands reset hooks", () => {
|
||||
params.sessionEntry = {
|
||||
sessionId: "session-1",
|
||||
updatedAt: Date.now(),
|
||||
cliSessionIds: { "claude-cli": "cli-session-1" },
|
||||
cliSessionBindings: {
|
||||
"claude-cli": {
|
||||
sessionId: "cli-session-1",
|
||||
extraSystemPromptHash: "prompt-hash",
|
||||
},
|
||||
},
|
||||
claudeCliSessionId: "cli-session-1",
|
||||
} as HandleCommandsParams["sessionEntry"];
|
||||
|
||||
const result = await maybeHandleResetCommand(params);
|
||||
@@ -351,9 +349,7 @@ describe("handleCommands reset hooks", () => {
|
||||
expect(params.command.resetHookTriggered).toBe(true);
|
||||
expect(params.command.softResetTriggered).toBe(true);
|
||||
expect(params.command.softResetTail).toBe("");
|
||||
expect(params.sessionEntry?.cliSessionIds).toBeUndefined();
|
||||
expect(params.sessionEntry?.cliSessionBindings).toBeUndefined();
|
||||
expect(params.sessionEntry?.claudeCliSessionId).toBeUndefined();
|
||||
expect(clearBootstrapSnapshotSpy).toHaveBeenCalledWith("agent:main:main");
|
||||
});
|
||||
|
||||
@@ -392,39 +388,31 @@ describe("handleCommands reset hooks", () => {
|
||||
params.sessionEntry = {
|
||||
sessionId: "session-direct",
|
||||
updatedAt: 1,
|
||||
cliSessionIds: { "claude-cli": "cli-session-direct" },
|
||||
cliSessionBindings: {
|
||||
"claude-cli": {
|
||||
sessionId: "cli-session-direct",
|
||||
extraSystemPromptHash: "prompt-hash-direct",
|
||||
},
|
||||
},
|
||||
claudeCliSessionId: "cli-session-direct",
|
||||
} as HandleCommandsParams["sessionEntry"];
|
||||
params.sessionStore = {
|
||||
[params.sessionKey]: {
|
||||
sessionId: "session-store",
|
||||
updatedAt: 2,
|
||||
cliSessionIds: { "claude-cli": "cli-session-store" },
|
||||
cliSessionBindings: {
|
||||
"claude-cli": {
|
||||
sessionId: "cli-session-store",
|
||||
extraSystemPromptHash: "prompt-hash-store",
|
||||
},
|
||||
},
|
||||
claudeCliSessionId: "cli-session-store",
|
||||
},
|
||||
} as Record<string, NonNullable<HandleCommandsParams["sessionEntry"]>>;
|
||||
|
||||
const result = await maybeHandleResetCommand(params);
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(params.sessionEntry?.cliSessionIds).toBeUndefined();
|
||||
expect(params.sessionEntry?.cliSessionBindings).toBeUndefined();
|
||||
expect(params.sessionEntry?.claudeCliSessionId).toBeUndefined();
|
||||
expect(params.sessionStore?.[params.sessionKey]?.cliSessionIds).toBeUndefined();
|
||||
expect(params.sessionStore?.[params.sessionKey]?.cliSessionBindings).toBeUndefined();
|
||||
expect(params.sessionStore?.[params.sessionKey]?.claudeCliSessionId).toBeUndefined();
|
||||
});
|
||||
|
||||
it("rejects soft reset for bound ACP sessions", async () => {
|
||||
|
||||
@@ -82,8 +82,6 @@ export async function maybeHandleResetCommand(
|
||||
clearAllCliSessions(next);
|
||||
return {
|
||||
cliSessionBindings: next.cliSessionBindings,
|
||||
cliSessionIds: next.cliSessionIds,
|
||||
claudeCliSessionId: next.claudeCliSessionId,
|
||||
updatedAt: now,
|
||||
lastInteractionAt: now,
|
||||
};
|
||||
|
||||
@@ -26,9 +26,7 @@ function applyCliSessionIdToSessionPatch(
|
||||
setCliSessionBinding(nextEntry, cliProvider, params.cliSessionBinding);
|
||||
return {
|
||||
...patch,
|
||||
cliSessionIds: nextEntry.cliSessionIds,
|
||||
cliSessionBindings: nextEntry.cliSessionBindings,
|
||||
claudeCliSessionId: nextEntry.claudeCliSessionId,
|
||||
};
|
||||
}
|
||||
if (params.cliSessionId && cliProvider) {
|
||||
@@ -36,9 +34,7 @@ function applyCliSessionIdToSessionPatch(
|
||||
setCliSessionId(nextEntry, cliProvider, params.cliSessionId);
|
||||
return {
|
||||
...patch,
|
||||
cliSessionIds: nextEntry.cliSessionIds,
|
||||
cliSessionBindings: nextEntry.cliSessionBindings,
|
||||
claudeCliSessionId: nextEntry.claudeCliSessionId,
|
||||
};
|
||||
}
|
||||
return patch;
|
||||
|
||||
@@ -2217,14 +2217,12 @@ describe("initSessionState preserves behavior overrides across /new and /reset",
|
||||
authProfileOverride: "20251001",
|
||||
authProfileOverrideSource: "user",
|
||||
authProfileOverrideCompactionCount: 2,
|
||||
cliSessionIds: { "claude-cli": "cli-session-123" },
|
||||
cliSessionBindings: {
|
||||
"claude-cli": {
|
||||
sessionId: "cli-session-123",
|
||||
authProfileId: "anthropic:default",
|
||||
},
|
||||
},
|
||||
claudeCliSessionId: "cli-session-123",
|
||||
} as const;
|
||||
const cases = [
|
||||
{
|
||||
@@ -2274,14 +2272,10 @@ describe("initSessionState preserves behavior overrides across /new and /reset",
|
||||
authProfileOverrideSource: overrides.authProfileOverrideSource,
|
||||
authProfileOverrideCompactionCount: overrides.authProfileOverrideCompactionCount,
|
||||
});
|
||||
expect(result.sessionEntry.cliSessionIds).toBeUndefined();
|
||||
expect(result.sessionEntry.cliSessionBindings).toBeUndefined();
|
||||
expect(result.sessionEntry.claudeCliSessionId).toBeUndefined();
|
||||
|
||||
const stored = readSessionRowsForFixtureTarget(sessionRowsTarget);
|
||||
expect(stored[sessionKey].cliSessionIds).toBeUndefined();
|
||||
expect(stored[sessionKey].cliSessionBindings).toBeUndefined();
|
||||
expect(stored[sessionKey].claudeCliSessionId).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2442,7 +2436,6 @@ describe("initSessionState preserves behavior overrides across /new and /reset",
|
||||
sessionKey,
|
||||
sessionId: existingSessionId,
|
||||
overrides: {
|
||||
cliSessionIds: { "claude-cli": "cli-session-1" },
|
||||
cliSessionBindings: {
|
||||
"claude-cli": {
|
||||
sessionId: "cli-session-1",
|
||||
@@ -2625,10 +2618,6 @@ describe("initSessionState preserves behavior overrides across /new and /reset",
|
||||
cliSessionBindings: {
|
||||
"claude-cli": cliBinding,
|
||||
},
|
||||
cliSessionIds: {
|
||||
"claude-cli": cliBinding.sessionId,
|
||||
},
|
||||
claudeCliSessionId: cliBinding.sessionId,
|
||||
},
|
||||
});
|
||||
replaceSqliteSessionTranscriptEvents({
|
||||
@@ -2961,7 +2950,6 @@ describe("persistSessionUsageUpdate", () => {
|
||||
const stored = readSessionRowsForFixtureTarget(sessionRowsTarget);
|
||||
expect(stored[sessionKey].totalTokens).toBe(32_000);
|
||||
expect(stored[sessionKey].totalTokensFresh).toBe(true);
|
||||
expect(stored[sessionKey].cliSessionIds?.["claude-cli"]).toBe("cli-session-1");
|
||||
expect(stored[sessionKey].cliSessionBindings?.["claude-cli"]).toEqual({
|
||||
sessionId: "cli-session-1",
|
||||
authProfileId: "anthropic:default",
|
||||
|
||||
@@ -615,9 +615,7 @@ export async function initSessionState(params: {
|
||||
persistedAuthProfileOverrideSource ?? baseEntry?.authProfileOverrideSource,
|
||||
authProfileOverrideCompactionCount:
|
||||
persistedAuthProfileOverrideCompactionCount ?? baseEntry?.authProfileOverrideCompactionCount,
|
||||
cliSessionIds: baseEntry?.cliSessionIds,
|
||||
cliSessionBindings: baseEntry?.cliSessionBindings,
|
||||
claudeCliSessionId: baseEntry?.claudeCliSessionId,
|
||||
label: persistedLabel ?? baseEntry?.label,
|
||||
spawnedBy: persistedSpawnedBy ?? baseEntry?.spawnedBy,
|
||||
spawnedWorkspaceDir: persistedSpawnedWorkspaceDir ?? baseEntry?.spawnedWorkspaceDir,
|
||||
|
||||
@@ -342,9 +342,7 @@ export type SessionEntry = {
|
||||
memoryFlushAt?: number;
|
||||
memoryFlushCompactionCount?: number;
|
||||
memoryFlushContextHash?: string;
|
||||
cliSessionIds?: Record<string, string>;
|
||||
cliSessionBindings?: Record<string, CliSessionBinding>;
|
||||
claudeCliSessionId?: string;
|
||||
label?: string;
|
||||
displayName?: string;
|
||||
channel?: string;
|
||||
|
||||
@@ -35,9 +35,7 @@ function toNonResumableCronSessionEntry(entry: SessionEntry): SessionEntry {
|
||||
delete next.sessionId;
|
||||
delete next.sessionStartedAt;
|
||||
delete next.lastInteractionAt;
|
||||
delete next.cliSessionIds;
|
||||
delete next.cliSessionBindings;
|
||||
delete next.claudeCliSessionId;
|
||||
return next as SessionEntry;
|
||||
}
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ describe("runCronIsolatedAgentTurn — skill filter", () => {
|
||||
systemSent: false,
|
||||
skillsSnapshot: undefined,
|
||||
// A stored CLI session ID that should NOT be reused on fresh runs.
|
||||
cliSessionIds: { "claude-cli": "prev-cli-session-abc" },
|
||||
cliSessionBindings: { "claude-cli": { sessionId: "prev-cli-session-abc" } },
|
||||
},
|
||||
systemSent: false,
|
||||
isNewSession: true,
|
||||
@@ -348,7 +348,7 @@ describe("runCronIsolatedAgentTurn — skill filter", () => {
|
||||
updatedAt: 0,
|
||||
systemSent: false,
|
||||
skillsSnapshot: undefined,
|
||||
cliSessionIds: { "claude-cli": "existing-cli-session-def" },
|
||||
cliSessionBindings: { "claude-cli": { sessionId: "existing-cli-session-def" } },
|
||||
},
|
||||
systemSent: false,
|
||||
isNewSession: false,
|
||||
|
||||
@@ -223,9 +223,7 @@ describe("resolveCronSession", () => {
|
||||
modelProvider: "anthropic",
|
||||
agentHarnessId: "claude-cli",
|
||||
agentRuntimeOverride: "claude-cli",
|
||||
cliSessionIds: { anthropic: "old-cli-session" },
|
||||
cliSessionBindings: {},
|
||||
claudeCliSessionId: "old-claude-session",
|
||||
cliSessionBindings: { anthropic: { sessionId: "old-cli-session" } },
|
||||
liveModelSwitchPending: true,
|
||||
fallbackNoticeSelectedModel: "anthropic/claude-opus-4-6",
|
||||
fallbackNoticeActiveModel: "anthropic/claude-sonnet-4-6",
|
||||
@@ -311,9 +309,7 @@ describe("resolveCronSession", () => {
|
||||
expect(result.sessionEntry.modelProvider).toBeUndefined();
|
||||
expect(result.sessionEntry.agentHarnessId).toBeUndefined();
|
||||
expect(result.sessionEntry.agentRuntimeOverride).toBeUndefined();
|
||||
expect(result.sessionEntry.cliSessionIds).toBeUndefined();
|
||||
expect(result.sessionEntry.cliSessionBindings).toBeUndefined();
|
||||
expect(result.sessionEntry.claudeCliSessionId).toBeUndefined();
|
||||
expect(result.sessionEntry.liveModelSwitchPending).toBeUndefined();
|
||||
expect(result.sessionEntry.fallbackNoticeSelectedModel).toBeUndefined();
|
||||
expect(result.sessionEntry.fallbackNoticeActiveModel).toBeUndefined();
|
||||
|
||||
@@ -49,18 +49,7 @@ function resolveClaudeProjectsDir(homeDir?: string): string {
|
||||
export function resolveClaudeCliBindingSessionId(
|
||||
entry: SessionEntry | undefined,
|
||||
): string | undefined {
|
||||
const bindingSessionId = normalizeOptionalString(
|
||||
entry?.cliSessionBindings?.[CLAUDE_CLI_PROVIDER]?.sessionId,
|
||||
);
|
||||
if (bindingSessionId) {
|
||||
return bindingSessionId;
|
||||
}
|
||||
const legacyMapSessionId = normalizeOptionalString(entry?.cliSessionIds?.[CLAUDE_CLI_PROVIDER]);
|
||||
if (legacyMapSessionId) {
|
||||
return legacyMapSessionId;
|
||||
}
|
||||
const legacyClaudeSessionId = normalizeOptionalString(entry?.claudeCliSessionId);
|
||||
return legacyClaudeSessionId || undefined;
|
||||
return normalizeOptionalString(entry?.cliSessionBindings?.[CLAUDE_CLI_PROVIDER]?.sessionId);
|
||||
}
|
||||
|
||||
function resolveFiniteNumber(value: unknown): number | undefined {
|
||||
|
||||
@@ -351,48 +351,6 @@ describe("cli session history", () => {
|
||||
expect(messages).toBe(localMessages);
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to legacy cliSessionIds when bindings are absent", async () => {
|
||||
await withClaudeProjectsDir(async ({ homeDir, sessionId }) => {
|
||||
const messages = augmentChatHistoryWithCliSessionImports({
|
||||
entry: {
|
||||
sessionId: "openclaw-session",
|
||||
updatedAt: Date.now(),
|
||||
cliSessionIds: {
|
||||
"claude-cli": sessionId,
|
||||
},
|
||||
},
|
||||
provider: "claude-cli",
|
||||
localMessages: [],
|
||||
homeDir,
|
||||
});
|
||||
expect(messages).toHaveLength(3);
|
||||
expectFields(messages[1], {
|
||||
role: "assistant",
|
||||
});
|
||||
expectFields(readRecord(messages[1])["__openclaw"], { cliSessionId: sessionId });
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to legacy claudeCliSessionId when newer fields are absent", async () => {
|
||||
await withClaudeProjectsDir(async ({ homeDir, sessionId }) => {
|
||||
const messages = augmentChatHistoryWithCliSessionImports({
|
||||
entry: {
|
||||
sessionId: "openclaw-session",
|
||||
updatedAt: Date.now(),
|
||||
claudeCliSessionId: sessionId,
|
||||
},
|
||||
provider: "claude-cli",
|
||||
localMessages: [],
|
||||
homeDir,
|
||||
});
|
||||
expect(messages).toHaveLength(3);
|
||||
expectFields(messages[0], {
|
||||
role: "user",
|
||||
});
|
||||
expectFields(readRecord(messages[0])["__openclaw"], { cliSessionId: sessionId });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("readClaudeCliFallbackSeed", () => {
|
||||
|
||||
@@ -868,18 +868,15 @@ describe("gateway agent handler", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves cliSessionIds from existing session entry", async () => {
|
||||
const existingCliSessionIds = { "claude-cli": "abc-123-def" };
|
||||
const existingClaudeCliSessionId = "abc-123-def";
|
||||
it("preserves CLI session bindings from existing session entry", async () => {
|
||||
const existingCliSessionBindings = { "claude-cli": { sessionId: "abc-123-def" } };
|
||||
|
||||
mockMainSessionEntry({
|
||||
cliSessionIds: existingCliSessionIds,
|
||||
claudeCliSessionId: existingClaudeCliSessionId,
|
||||
cliSessionBindings: existingCliSessionBindings,
|
||||
});
|
||||
|
||||
const capturedEntry = await runMainAgentAndCaptureEntry("test-idem");
|
||||
expect(capturedEntry.cliSessionIds).toEqual(existingCliSessionIds);
|
||||
expect(capturedEntry.claudeCliSessionId).toBe(existingClaudeCliSessionId);
|
||||
expect(capturedEntry.cliSessionBindings).toEqual(existingCliSessionBindings);
|
||||
});
|
||||
it("reactivates completed subagent sessions and broadcasts send updates", async () => {
|
||||
const childSessionKey = "agent:main:subagent:followup";
|
||||
@@ -2544,13 +2541,12 @@ describe("gateway agent handler", () => {
|
||||
expect(mocks.resolveVoiceWakeRouteByTrigger).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("handles missing cliSessionIds gracefully", async () => {
|
||||
it("handles missing CLI session bindings gracefully", async () => {
|
||||
mockMainSessionEntry({});
|
||||
|
||||
const capturedEntry = await runMainAgentAndCaptureEntry("test-idem-2");
|
||||
// Should be undefined, not cause an error
|
||||
expect(capturedEntry.cliSessionIds).toBeUndefined();
|
||||
expect(capturedEntry.claudeCliSessionId).toBeUndefined();
|
||||
expect(capturedEntry.cliSessionBindings).toBeUndefined();
|
||||
});
|
||||
it("leaves noncanonical main row cleanup to doctor when writing a canonical session entry", async () => {
|
||||
mocks.loadSessionEntry.mockReturnValue({
|
||||
|
||||
@@ -1103,9 +1103,7 @@ export const agentHandlers: GatewayRequestHandlers = {
|
||||
groupChannel: resolvedGroupChannel,
|
||||
space: resolvedGroupSpace,
|
||||
...(pluginOwnerId ? { pluginOwnerId } : {}),
|
||||
cliSessionIds: entry?.cliSessionIds,
|
||||
cliSessionBindings: entry?.cliSessionBindings,
|
||||
claudeCliSessionId: entry?.claudeCliSessionId,
|
||||
};
|
||||
sessionEntry = mergeSessionEntry(entry, nextEntryPatch);
|
||||
if (request.deliver === true) {
|
||||
|
||||
@@ -234,9 +234,6 @@ describe("gateway server agent", () => {
|
||||
updatedAt: Date.now(),
|
||||
modelProvider: "claude-cli",
|
||||
model: "claude-opus-4-6",
|
||||
cliSessionIds: {
|
||||
"claude-cli": "cli-session-123",
|
||||
},
|
||||
cliSessionBindings: {
|
||||
"claude-cli": {
|
||||
sessionId: "cli-session-123",
|
||||
@@ -245,7 +242,6 @@ describe("gateway server agent", () => {
|
||||
mcpResumeHash: "mcp-resume-hash",
|
||||
},
|
||||
},
|
||||
claudeCliSessionId: "cli-session-123",
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -267,10 +263,6 @@ describe("gateway server agent", () => {
|
||||
mcpResumeHash: "mcp-resume-hash",
|
||||
},
|
||||
});
|
||||
expect(stored?.cliSessionIds).toEqual({
|
||||
"claude-cli": "cli-session-123",
|
||||
});
|
||||
expect(stored?.claudeCliSessionId).toBe("cli-session-123");
|
||||
});
|
||||
|
||||
test("agent accepts built-in channel alias (imsg)", async () => {
|
||||
|
||||
@@ -266,9 +266,6 @@ test("sessions.reset preserves spawned session ownership metadata", async () =>
|
||||
execAsk: "on-miss",
|
||||
execNode: "mac-mini",
|
||||
displayName: "Ops Child",
|
||||
cliSessionIds: {
|
||||
"claude-cli": "cli-session-123",
|
||||
},
|
||||
cliSessionBindings: {
|
||||
"claude-cli": {
|
||||
sessionId: "cli-session-123",
|
||||
@@ -276,7 +273,6 @@ test("sessions.reset preserves spawned session ownership metadata", async () =>
|
||||
extraSystemPromptHash: "prompt-hash",
|
||||
},
|
||||
},
|
||||
claudeCliSessionId: "cli-session-123",
|
||||
deliveryContext: {
|
||||
channel: "discord",
|
||||
to: "discord:child",
|
||||
@@ -334,8 +330,6 @@ test("sessions.reset preserves spawned session ownership metadata", async () =>
|
||||
mcpConfigHash?: string;
|
||||
}
|
||||
>;
|
||||
cliSessionIds?: Record<string, string>;
|
||||
claudeCliSessionId?: string;
|
||||
deliveryContext?: {
|
||||
channel?: string;
|
||||
to?: string;
|
||||
@@ -388,10 +382,6 @@ test("sessions.reset preserves spawned session ownership metadata", async () =>
|
||||
extraSystemPromptHash: "prompt-hash",
|
||||
},
|
||||
});
|
||||
expect(reset.payload?.entry.cliSessionIds).toEqual({
|
||||
"claude-cli": "cli-session-123",
|
||||
});
|
||||
expect(reset.payload?.entry.claudeCliSessionId).toBe("cli-session-123");
|
||||
expect(reset.payload?.entry.deliveryContext).toEqual({
|
||||
channel: "discord",
|
||||
to: "discord:child",
|
||||
@@ -440,10 +430,6 @@ test("sessions.reset preserves spawned session ownership metadata", async () =>
|
||||
extraSystemPromptHash: "prompt-hash",
|
||||
},
|
||||
});
|
||||
expect(stored?.cliSessionIds).toEqual({
|
||||
"claude-cli": "cli-session-123",
|
||||
});
|
||||
expect(stored?.claudeCliSessionId).toBe("cli-session-123");
|
||||
expect(stored?.deliveryContext).toEqual({
|
||||
channel: "discord",
|
||||
to: "discord:child",
|
||||
|
||||
@@ -592,8 +592,6 @@ export async function performGatewaySessionReset(params: {
|
||||
origin: snapshotSessionOrigin(currentEntry),
|
||||
deliveryContext: currentEntry?.deliveryContext,
|
||||
cliSessionBindings: currentEntry?.cliSessionBindings,
|
||||
cliSessionIds: currentEntry?.cliSessionIds,
|
||||
claudeCliSessionId: currentEntry?.claudeCliSessionId,
|
||||
lastChannel: currentEntry?.lastChannel,
|
||||
lastTo: currentEntry?.lastTo,
|
||||
lastAccountId: currentEntry?.lastAccountId,
|
||||
|
||||
@@ -93,9 +93,7 @@ const SESSION_ENTRY_RESERVED_SLOT_KEY_LIST = [
|
||||
"memoryFlushAt",
|
||||
"memoryFlushCompactionCount",
|
||||
"memoryFlushContextHash",
|
||||
"cliSessionIds",
|
||||
"cliSessionBindings",
|
||||
"claudeCliSessionId",
|
||||
"label",
|
||||
"displayName",
|
||||
"channel",
|
||||
|
||||
Reference in New Issue
Block a user