Skip to content

Commit 230cf7f

Browse files
committed
fix(cron): keep isolated delivery on runtime snapshot
1 parent 9b9d897 commit 230cf7f

2 files changed

Lines changed: 72 additions & 6 deletions

File tree

src/cron/isolated-agent.direct-delivery-core-channels.test.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import "./isolated-agent.mocks.js";
2-
import { beforeEach, describe, expect, it } from "vitest";
2+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
33
import { runSubagentAnnounceFlow } from "../agents/subagent-announce.js";
44
import type { ChannelOutboundAdapter, ChannelOutboundContext } from "../channels/plugins/types.js";
55
import type { CliDeps } from "../cli/deps.js";
6+
import { clearRuntimeConfigSnapshot, setRuntimeConfigSnapshot } from "../config/config.js";
67
import { resolveOutboundSendDep } from "../infra/outbound/send-deps.js";
78
import { setActivePluginRegistry } from "../plugins/runtime.js";
89
import { createOutboundTestPlugin, createTestRegistry } from "../test-utils/channel-plugins.js";
@@ -297,6 +298,10 @@ describe("runCronIsolatedAgentTurn core-channel direct delivery", () => {
297298
);
298299
});
299300

301+
afterEach(() => {
302+
clearRuntimeConfigSnapshot();
303+
});
304+
300305
for (const testCase of CASES) {
301306
it(`routes ${testCase.name} text-only announce delivery through the outbound adapter`, async () => {
302307
await expectCoreChannelAnnounceDelivery({
@@ -316,6 +321,51 @@ describe("runCronIsolatedAgentTurn core-channel direct delivery", () => {
316321
});
317322

318323
if (testCase.channel === "discord") {
324+
it("keeps isolated Discord delivery on the active runtime snapshot after agent-default derivation", async () => {
325+
await withTempCronHome(async (home) => {
326+
const storePath = await writeSessionStore(home, { lastProvider: "webchat", lastTo: "" });
327+
const sourceCfg = makeCfg(home, storePath, {
328+
channels: {
329+
discord: {
330+
accounts: {
331+
default: {
332+
token: { provider: "default", source: "env", id: "DISCORD_BOT_TOKEN" },
333+
},
334+
},
335+
},
336+
},
337+
});
338+
const runtimeCfg = makeCfg(home, storePath, {
339+
channels: {
340+
discord: {
341+
accounts: { default: { token: "resolved-discord-token" } },
342+
},
343+
},
344+
});
345+
setRuntimeConfigSnapshot(runtimeCfg, sourceCfg);
346+
const deps = createCliDeps();
347+
mockAgentPayloads([{ text: "hello from cron" }]);
348+
349+
const res = await runExplicitAnnounceTurn({
350+
cfg: sourceCfg,
351+
deps,
352+
channel: "discord",
353+
to: testCase.to,
354+
});
355+
356+
expect(res.status).toBe("ok");
357+
expect(res.delivered).toBe(true);
358+
expect(deps.sendMessageDiscord).toHaveBeenCalledTimes(1);
359+
expect(deps.sendMessageDiscord).toHaveBeenCalledWith(
360+
testCase.expectedTo,
361+
"hello from cron",
362+
expect.objectContaining({
363+
cfg: expect.objectContaining({ channels: runtimeCfg.channels }),
364+
}),
365+
);
366+
});
367+
});
368+
319369
it("collapses Discord text-only announce delivery to the final assistant text", async () => {
320370
await expectCoreChannelAnnounceDelivery({
321371
testCase,

src/cron/isolated-agent/run.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import { retireSessionMcpRuntime } from "../../agents/pi-bundle-mcp-tools.js";
55
import type { SkillSnapshot } from "../../agents/skills.js";
66
import type { ThinkLevel } from "../../auto-reply/thinking.js";
77
import type { CliDeps } from "../../cli/outbound-send-deps.js";
8+
import {
9+
getRuntimeConfigSnapshot,
10+
getRuntimeConfigSourceSnapshot,
11+
selectApplicableRuntimeConfig,
12+
} from "../../config/config.js";
813
import type { AgentDefaultsConfig } from "../../config/types.agent-defaults.js";
914
import type { OpenClawConfig } from "../../config/types.openclaw.js";
1015
import { clearAgentRunContext } from "../../infra/agent-events.js";
@@ -484,12 +489,23 @@ type CronPreparationResult =
484489
| { ok: true; context: PreparedCronRunContext }
485490
| { ok: false; result: RunCronAgentTurnResult };
486491

492+
function resolveCronActiveRuntimeConfig(cfg: OpenClawConfig): OpenClawConfig {
493+
return (
494+
selectApplicableRuntimeConfig({
495+
inputConfig: cfg,
496+
runtimeConfig: getRuntimeConfigSnapshot(),
497+
runtimeSourceConfig: getRuntimeConfigSourceSnapshot(),
498+
}) ?? cfg
499+
);
500+
}
501+
487502
async function prepareCronRunContext(params: {
488503
input: RunCronAgentTurnParams;
489504
isFastTestEnv: boolean;
490505
}): Promise<CronPreparationResult> {
491506
const { input } = params;
492-
const defaultAgentId = resolveDefaultAgentId(input.cfg);
507+
const runtimeCfg = resolveCronActiveRuntimeConfig(input.cfg);
508+
const defaultAgentId = resolveDefaultAgentId(runtimeCfg);
493509
const requestedAgentId =
494510
typeof input.agentId === "string" && input.agentId.trim()
495511
? input.agentId
@@ -498,16 +514,16 @@ async function prepareCronRunContext(params: {
498514
: undefined;
499515
const normalizedRequested = requestedAgentId ? normalizeAgentId(requestedAgentId) : undefined;
500516
const agentConfigOverride = normalizedRequested
501-
? resolveAgentConfig(input.cfg, normalizedRequested)
517+
? resolveAgentConfig(runtimeCfg, normalizedRequested)
502518
: undefined;
503519
const agentId = normalizedRequested ?? defaultAgentId;
504520
const agentCfg: AgentDefaultsConfig = buildCronAgentDefaultsConfig({
505-
defaults: input.cfg.agents?.defaults,
521+
defaults: runtimeCfg.agents?.defaults,
506522
agentConfigOverride,
507523
});
508524
const cfgWithAgentDefaults: OpenClawConfig = {
509-
...input.cfg,
510-
agents: Object.assign({}, input.cfg.agents, { defaults: agentCfg }),
525+
...runtimeCfg,
526+
agents: Object.assign({}, runtimeCfg.agents, { defaults: agentCfg }),
511527
};
512528
let catalog: Awaited<ReturnType<CronModelCatalogRuntime["loadModelCatalog"]>> | undefined;
513529
const loadCatalog = async () => {

0 commit comments

Comments
 (0)