mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix: avoid cron embedded lane deadlock
This commit is contained in:
@@ -35,12 +35,12 @@ function mockEmbeddedOk() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the provider and model from the last runEmbeddedPiAgent call.
|
||||
* Extract select fields from the last runEmbeddedPiAgent call.
|
||||
*/
|
||||
function lastEmbeddedCall(): { provider?: string; model?: string } {
|
||||
function lastEmbeddedCall(): { provider?: string; model?: string; lane?: string } {
|
||||
const calls = vi.mocked(runEmbeddedPiAgent).mock.calls;
|
||||
expect(calls.length).toBeGreaterThan(0);
|
||||
return calls.at(-1)?.[0] as { provider?: string; model?: string };
|
||||
return calls.at(-1)?.[0] as { provider?: string; model?: string; lane?: string };
|
||||
}
|
||||
|
||||
const DEFAULT_MESSAGE = "do it";
|
||||
@@ -106,6 +106,14 @@ describe("cron model formatting and precedence edge cases", () => {
|
||||
// ------ provider/model string splitting ------
|
||||
|
||||
describe("parseModelRef formatting", () => {
|
||||
it("moves nested embedded runs off the cron lane to avoid self-deadlock", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const { res, call } = await runTurn(home);
|
||||
expect(res.status).toBe("ok");
|
||||
expect(call.lane).toBe("nested");
|
||||
});
|
||||
});
|
||||
|
||||
it("splits standard provider/model", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const { res, call } = await runTurn(home, {
|
||||
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
import type { AgentDefaultsConfig } from "../../config/types.js";
|
||||
import { registerAgentRunContext } from "../../infra/agent-events.js";
|
||||
import { logWarn } from "../../logger.js";
|
||||
import { CommandLane } from "../../process/lanes.js";
|
||||
import { normalizeAgentId } from "../../routing/session-key.js";
|
||||
import {
|
||||
buildSafeExternalPrompt,
|
||||
@@ -197,6 +198,17 @@ function appendCronDeliveryInstruction(params: {
|
||||
return `${params.commandBody}\n\nReturn your summary as plain text; it will be delivered automatically. If the task explicitly calls for messaging a specific external recipient, note who/where it should go instead of sending it yourself.`.trim();
|
||||
}
|
||||
|
||||
function resolveCronEmbeddedAgentLane(lane?: string) {
|
||||
const trimmed = lane?.trim();
|
||||
// Cron jobs already execute inside the cron command lane. Reusing that same
|
||||
// lane for the nested embedded-agent run deadlocks: the outer cron task holds
|
||||
// the lane while the inner run waits to reacquire it.
|
||||
if (!trimmed || trimmed === "cron") {
|
||||
return CommandLane.Nested;
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
export async function runCronIsolatedAgentTurn(params: {
|
||||
cfg: OpenClawConfig;
|
||||
deps: CliDeps;
|
||||
@@ -610,7 +622,7 @@ export async function runCronIsolatedAgentTurn(params: {
|
||||
config: cfgWithAgentDefaults,
|
||||
skillsSnapshot,
|
||||
prompt: promptText,
|
||||
lane: params.lane ?? "cron",
|
||||
lane: resolveCronEmbeddedAgentLane(params.lane),
|
||||
provider: providerOverride,
|
||||
model: modelOverride,
|
||||
authProfileId,
|
||||
|
||||
Reference in New Issue
Block a user