mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-03 09:24:08 +00:00
fix(sqlite): align rebased runtime surfaces
This commit is contained in:
@@ -8255,7 +8255,7 @@ describe("runCodexAppServerAttempt", () => {
|
||||
expect(llmInput).toHaveBeenCalledTimes(1);
|
||||
expect(llmOutput).toHaveBeenCalledTimes(1);
|
||||
expect(agentEnd).toHaveBeenCalledTimes(1);
|
||||
const [llmOutputPayload] = mockCall(llmOutput, "llm_output") as [
|
||||
const [llmOutputPayload] = llmOutput.mock.calls[0] as [
|
||||
{
|
||||
assistantTexts?: string[];
|
||||
harnessId?: string;
|
||||
@@ -8273,8 +8273,8 @@ describe("runCodexAppServerAttempt", () => {
|
||||
expect(llmOutputPayload.resolvedRef).toBe("codex/gpt-5.4-codex");
|
||||
expect(llmOutputPayload.harnessId).toBe("codex");
|
||||
expect(llmOutputPayload.runId).toBe("run-1");
|
||||
expect(llmOutputPayload.sessionId).toBe("session-1");
|
||||
const [agentEndPayload] = mockCall(agentEnd, "agent_end") as [
|
||||
expect(llmOutputPayload.sessionId).toBe(sessionId);
|
||||
const [agentEndPayload] = agentEnd.mock.calls[0] as [
|
||||
{ error?: string; messages?: Array<{ role?: string }>; success?: boolean },
|
||||
unknown,
|
||||
];
|
||||
|
||||
@@ -74,7 +74,7 @@ import {
|
||||
import { resolveSlackThreadTargets } from "../../threading.js";
|
||||
import type { SlackMessageEvent } from "../../types.js";
|
||||
import { normalizeSlackAllowOwnerEntry } from "../allow-list.js";
|
||||
import { resolveStorePath, updateLastRoute } from "../config.runtime.js";
|
||||
import { updateLastRoute } from "../config.runtime.js";
|
||||
import { recordInboundSession } from "../conversation.runtime.js";
|
||||
import { escapeSlackMrkdwn } from "../mrkdwn.js";
|
||||
import {
|
||||
@@ -359,10 +359,6 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
: undefined;
|
||||
|
||||
if (prepared.isDirectMessage) {
|
||||
const sessionCfg = cfg.session;
|
||||
const storePath = resolveStorePath(sessionCfg?.store, {
|
||||
agentId: route.agentId,
|
||||
});
|
||||
const pinnedMainDmOwner = resolvePinnedMainDmOwnerFromAllowlist({
|
||||
dmScope: cfg.session?.dmScope,
|
||||
allowFrom: ctx.allowFrom,
|
||||
@@ -384,7 +380,7 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
);
|
||||
} else {
|
||||
await updateLastRoute({
|
||||
storePath,
|
||||
agentId: route.agentId,
|
||||
sessionKey: inboundLastRouteSessionKey,
|
||||
deliveryContext: {
|
||||
channel: "slack",
|
||||
|
||||
@@ -1469,7 +1469,6 @@ export async function runEmbeddedAgent(
|
||||
durationMs: Date.now() - started,
|
||||
agentMeta: buildErrorAgentMeta({
|
||||
sessionId: activeSessionId,
|
||||
sessionFile: activeSessionFile,
|
||||
provider,
|
||||
model: model.id,
|
||||
contextTokens: ctxInfo.tokens,
|
||||
@@ -1795,7 +1794,6 @@ export async function runEmbeddedAgent(
|
||||
durationMs: Date.now() - started,
|
||||
agentMeta: buildErrorAgentMeta({
|
||||
sessionId: activeSessionId,
|
||||
sessionFile: activeSessionFile,
|
||||
provider,
|
||||
model: model.id,
|
||||
contextTokens: ctxInfo.tokens,
|
||||
@@ -2324,7 +2322,6 @@ export async function runEmbeddedAgent(
|
||||
durationMs: Date.now() - started,
|
||||
agentMeta: buildErrorAgentMeta({
|
||||
sessionId: sessionIdUsed,
|
||||
sessionFile: activeSessionFile,
|
||||
provider,
|
||||
model: model.id,
|
||||
contextTokens: ctxInfo.tokens,
|
||||
@@ -2357,7 +2354,6 @@ export async function runEmbeddedAgent(
|
||||
durationMs: Date.now() - started,
|
||||
agentMeta: buildErrorAgentMeta({
|
||||
sessionId: sessionIdUsed,
|
||||
sessionFile: activeSessionFile,
|
||||
provider,
|
||||
model: model.id,
|
||||
contextTokens: ctxInfo.tokens,
|
||||
@@ -2448,7 +2444,6 @@ export async function runEmbeddedAgent(
|
||||
durationMs: Date.now() - started,
|
||||
agentMeta: buildErrorAgentMeta({
|
||||
sessionId: sessionIdUsed,
|
||||
sessionFile: activeSessionFile,
|
||||
provider,
|
||||
model: model.id,
|
||||
contextTokens: ctxInfo.tokens,
|
||||
@@ -2489,7 +2484,6 @@ export async function runEmbeddedAgent(
|
||||
durationMs: Date.now() - started,
|
||||
agentMeta: buildErrorAgentMeta({
|
||||
sessionId: sessionIdUsed,
|
||||
sessionFile: activeSessionFile,
|
||||
provider,
|
||||
model: model.id,
|
||||
contextTokens: ctxInfo.tokens,
|
||||
|
||||
@@ -114,6 +114,21 @@ async function resolveQueueEmbeddedAgentMessageOutcome(
|
||||
);
|
||||
}
|
||||
|
||||
async function runAnnounceAgentCall(params: {
|
||||
agentParams: Record<string, unknown>;
|
||||
expectFinal?: boolean;
|
||||
timeoutMs?: number;
|
||||
}): Promise<unknown> {
|
||||
return await subagentAnnounceDeliveryDeps.dispatchGatewayMethodInProcess(
|
||||
"agent",
|
||||
params.agentParams,
|
||||
{
|
||||
expectFinal: params.expectFinal,
|
||||
timeoutMs: params.timeoutMs,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function formatQueueWakeFailureError(
|
||||
fallback: string,
|
||||
outcome: EmbeddedAgentQueueMessageOutcome,
|
||||
|
||||
@@ -74,6 +74,9 @@ function inferCompletionChatTypeFromTarget(to: string | undefined): CompletionCh
|
||||
if (normalized.startsWith("group:")) {
|
||||
return "group";
|
||||
}
|
||||
if (normalized.endsWith("@g.us")) {
|
||||
return "group";
|
||||
}
|
||||
if (normalized.startsWith("channel:") || normalized.startsWith("thread:")) {
|
||||
return "channel";
|
||||
}
|
||||
|
||||
@@ -2794,10 +2794,6 @@ async function updateCommandInternal(opts: UpdateCommandOptions): Promise<void>
|
||||
if (timeoutMs === null) {
|
||||
return;
|
||||
}
|
||||
if (opts.dryRun !== true) {
|
||||
await disableCurrentOpenClawUpdateLaunchdJob().catch(() => undefined);
|
||||
assertConfigWriteAllowedInCurrentMode();
|
||||
}
|
||||
const updateStepTimeoutMs = timeoutMs ?? DEFAULT_UPDATE_STEP_TIMEOUT_MS;
|
||||
|
||||
let root = await resolveUpdateRoot();
|
||||
@@ -2910,6 +2906,10 @@ async function updateCommandInternal(opts: UpdateCommandOptions): Promise<void>
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
}
|
||||
if (opts.dryRun !== true) {
|
||||
await disableCurrentOpenClawUpdateLaunchdJob().catch(() => undefined);
|
||||
assertConfigWriteAllowedInCurrentMode();
|
||||
}
|
||||
|
||||
const installKind = updateStatus.installKind;
|
||||
const switchToGit = requestedChannel === "dev" && installKind !== "git";
|
||||
|
||||
@@ -105,6 +105,13 @@ function requirePersistedJob(jobs: Array<Record<string, unknown>>, index: number
|
||||
return job;
|
||||
}
|
||||
|
||||
function requireRecord(value: unknown, label: string): Record<string, unknown> {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
throw new Error(`expected ${label}`);
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function expectNoteContaining(message: string, title: string): void {
|
||||
expect(
|
||||
noteMock.mock.calls.some(
|
||||
@@ -174,7 +181,7 @@ describe("maybeRepairLegacyCronStore", () => {
|
||||
state: {},
|
||||
},
|
||||
]);
|
||||
const prompter = makePrompter(true);
|
||||
const prompter = makePrompter(false);
|
||||
|
||||
await maybeRepairLegacyCronStore({
|
||||
cfg: {
|
||||
@@ -189,7 +196,7 @@ describe("maybeRepairLegacyCronStore", () => {
|
||||
prompter,
|
||||
});
|
||||
|
||||
expect(prompter.confirm).not.toHaveBeenCalled();
|
||||
expect(prompter.confirm).toHaveBeenCalledOnce();
|
||||
expectNoteContaining("Cron model overrides detected", "Cron");
|
||||
expectNoteContaining("2 jobs set `payload.model`", "Cron");
|
||||
expectNoteContaining("Provider namespaces: anthropic=1, openai=1", "Cron");
|
||||
|
||||
@@ -357,7 +357,7 @@ export async function maybeRepairLegacyCronStore(params: {
|
||||
if (rawJobs.length === 0 && !hasLegacyStoreFile && !hasLegacyStateSidecar && !hasLegacyRunLogs) {
|
||||
return;
|
||||
}
|
||||
noteCronModelOverrides({ cfg: params.cfg, jobs: rawJobs, storePath });
|
||||
noteCronModelOverrides({ cfg: params.cfg, jobs: rawJobs, storePath: legacyStorePath });
|
||||
|
||||
const normalized = normalizeStoredCronJobs(rawJobs);
|
||||
const legacyWebhook = normalizeOptionalString(params.cfg.cron?.webhook);
|
||||
|
||||
@@ -9,8 +9,6 @@ import {
|
||||
makeJob,
|
||||
seedCronSessionRows,
|
||||
seedMainRouteSession,
|
||||
writeSessionStore,
|
||||
writeSessionStoreEntries,
|
||||
} from "./isolated-agent.test-harness.js";
|
||||
import {
|
||||
DEFAULT_AGENT_TURN_PAYLOAD,
|
||||
@@ -25,8 +23,7 @@ import { setupRunCronIsolatedAgentTurnSuite } from "./isolated-agent/run.suite-h
|
||||
import {
|
||||
dispatchCronDeliveryMock,
|
||||
mockRunCronFallbackPassthrough,
|
||||
runEmbeddedAgentMock,
|
||||
updateSessionStoreMock,
|
||||
runEmbeddedPiAgentMock,
|
||||
} from "./isolated-agent/run.test-harness.js";
|
||||
import { normalizeCronJobCreate } from "./normalize.js";
|
||||
import type { CronJob } from "./types.js";
|
||||
@@ -158,12 +155,9 @@ describe("runCronIsolatedAgentTurn session identity", () => {
|
||||
await withTempHome(async (home) => {
|
||||
const deps = makeDeps();
|
||||
const boundSessionKey = "agent:main:telegram:direct:42";
|
||||
const originalSessionFile = path.join(home, "bound-session.jsonl");
|
||||
const rotatedSessionFile = path.join(home, "bound-session-rotated.jsonl");
|
||||
const storePath = await writeSessionStoreEntries(home, {
|
||||
await seedCronSessionRows(home, {
|
||||
[boundSessionKey]: {
|
||||
sessionId: "bound-session",
|
||||
sessionFile: originalSessionFile,
|
||||
updatedAt: Date.now(),
|
||||
lastInteractionAt: Date.now() - 1_000,
|
||||
systemSent: true,
|
||||
@@ -175,7 +169,6 @@ describe("runCronIsolatedAgentTurn session identity", () => {
|
||||
durationMs: 5,
|
||||
agentMeta: {
|
||||
sessionId: "bound-session-rotated",
|
||||
sessionFile: rotatedSessionFile,
|
||||
provider: "anthropic",
|
||||
model: "claude-opus-4-6",
|
||||
compactionCount: 1,
|
||||
@@ -183,12 +176,6 @@ describe("runCronIsolatedAgentTurn session identity", () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
updateSessionStoreMock.mockImplementation(async (targetStorePath, update) => {
|
||||
const raw = await fs.readFile(targetStorePath, "utf-8");
|
||||
const store = JSON.parse(raw) as Record<string, SessionEntry>;
|
||||
update(store);
|
||||
await fs.writeFile(targetStorePath, JSON.stringify(store, null, 2), "utf-8");
|
||||
});
|
||||
const currentBoundJob = normalizeCronJobCreate(
|
||||
{
|
||||
...makeJob(DEFAULT_AGENT_TURN_PAYLOAD),
|
||||
@@ -199,7 +186,7 @@ describe("runCronIsolatedAgentTurn session identity", () => {
|
||||
) as CronJob;
|
||||
|
||||
const res = await runCronIsolatedAgentTurn({
|
||||
cfg: makeCfg(home, storePath),
|
||||
cfg: makeCfg(home),
|
||||
deps,
|
||||
job: currentBoundJob,
|
||||
message: DEFAULT_MESSAGE,
|
||||
@@ -213,14 +200,10 @@ describe("runCronIsolatedAgentTurn session identity", () => {
|
||||
expect.objectContaining({ sessionId: "bound-session-rotated" }),
|
||||
);
|
||||
|
||||
const finalPersist = updateSessionStoreMock.mock.calls.at(-1);
|
||||
expect(finalPersist?.[0]).toBe(storePath);
|
||||
const persistedStore: Record<string, { [key: string]: unknown }> = {};
|
||||
(finalPersist?.[1] as (store: typeof persistedStore) => void)(persistedStore);
|
||||
expect(persistedStore[boundSessionKey]).toEqual(
|
||||
const persisted = await readSessionEntry("main", boundSessionKey);
|
||||
expect(persisted).toEqual(
|
||||
expect.objectContaining({
|
||||
sessionId: "bound-session-rotated",
|
||||
sessionFile: rotatedSessionFile,
|
||||
usageFamilyKey: boundSessionKey,
|
||||
usageFamilySessionIds: ["bound-session", "bound-session-rotated"],
|
||||
}),
|
||||
|
||||
@@ -171,7 +171,6 @@ describe("createPersistCronSessionEntry", () => {
|
||||
const cronSession = makeCronSession(
|
||||
makeSessionEntry({
|
||||
sessionId: "bound-session",
|
||||
sessionFile: "/tmp/bound-session.jsonl",
|
||||
}),
|
||||
);
|
||||
const changed = adoptCronRunSessionMetadata({
|
||||
@@ -179,37 +178,31 @@ describe("createPersistCronSessionEntry", () => {
|
||||
sessionKey: "agent:main:telegram:direct:42",
|
||||
runMeta: {
|
||||
sessionId: "bound-session-rotated",
|
||||
sessionFile: "/tmp/bound-session-rotated.jsonl",
|
||||
},
|
||||
});
|
||||
const updateSessionStore = vi.fn(
|
||||
async (_storePath, update: (store: Record<string, SessionEntry>) => void) => {
|
||||
const store: Record<string, SessionEntry> = {};
|
||||
update(store);
|
||||
expect(store["agent:main:telegram:direct:42"]).toEqual({
|
||||
sessionId: "bound-session-rotated",
|
||||
sessionFile: "/tmp/bound-session-rotated.jsonl",
|
||||
usageFamilyKey: "agent:main:telegram:direct:42",
|
||||
usageFamilySessionIds: ["bound-session", "bound-session-rotated"],
|
||||
updatedAt: 1000,
|
||||
systemSent: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
const persistSessionRow = vi.fn(async (sessionKey: string, entry: SessionEntry) => {
|
||||
expect(sessionKey).toBe("agent:main:telegram:direct:42");
|
||||
expect(entry).toEqual({
|
||||
sessionId: "bound-session-rotated",
|
||||
usageFamilyKey: "agent:main:telegram:direct:42",
|
||||
usageFamilySessionIds: ["bound-session", "bound-session-rotated"],
|
||||
updatedAt: 1000,
|
||||
systemSent: true,
|
||||
});
|
||||
});
|
||||
|
||||
expect(changed).toBe(true);
|
||||
const persist = createPersistCronSessionEntry({
|
||||
isFastTestEnv: false,
|
||||
cronSession,
|
||||
agentSessionKey: "agent:main:telegram:direct:42",
|
||||
updateSessionStore,
|
||||
persistSessionRow,
|
||||
});
|
||||
|
||||
await persist();
|
||||
|
||||
expect(cronSession.store["agent:main:telegram:direct:42"]).toEqual({
|
||||
sessionId: "bound-session-rotated",
|
||||
sessionFile: "/tmp/bound-session-rotated.jsonl",
|
||||
usageFamilyKey: "agent:main:telegram:direct:42",
|
||||
usageFamilySessionIds: ["bound-session", "bound-session-rotated"],
|
||||
updatedAt: 1000,
|
||||
|
||||
@@ -73,18 +73,16 @@ export function adoptCronRunSessionMetadata(params: {
|
||||
sessionKey: string;
|
||||
runMeta?: {
|
||||
sessionId?: string;
|
||||
sessionFile?: string;
|
||||
};
|
||||
}): boolean {
|
||||
const nextSessionId = normalizeSessionField(params.runMeta?.sessionId);
|
||||
const nextSessionFile = normalizeSessionField(params.runMeta?.sessionFile);
|
||||
if (!nextSessionFile) {
|
||||
if (!nextSessionId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let changed = false;
|
||||
const previousSessionId = params.entry.sessionId;
|
||||
if (nextSessionId && nextSessionId !== previousSessionId) {
|
||||
if (nextSessionId !== previousSessionId) {
|
||||
params.entry.sessionId = nextSessionId;
|
||||
params.entry.usageFamilyKey = params.entry.usageFamilyKey ?? params.sessionKey;
|
||||
params.entry.usageFamilySessionIds = Array.from(
|
||||
@@ -97,11 +95,6 @@ export function adoptCronRunSessionMetadata(params: {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (nextSessionFile !== params.entry.sessionFile) {
|
||||
params.entry.sessionFile = nextSessionFile;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user