fix(cron): restore owner-only tools for isolated runs

This commit is contained in:
Peter Steinberger 2026-03-09 05:48:52 +00:00 committed by Vincent Koc
parent cc919d3856
commit 0d607942d5
3 changed files with 63 additions and 0 deletions

View File

@ -64,6 +64,7 @@ Docs: https://docs.openclaw.ai
- Matrix/DM routing: add safer fallback detection for broken `m.direct` homeservers, honor explicit room bindings over DM classification, and preserve room-bound agent selection for Matrix DM rooms. (#19736) Thanks @derbronko.
- Cron/Telegram announce delivery: route text-only announce jobs through the real outbound adapters after finalizing descendant output so plain Telegram targets no longer report `delivered: true` when no message actually reached Telegram. (#40575) thanks @obviyus.
- Gateway/restart timeout recovery: exit non-zero when restart-triggered shutdown drains time out so launchd/systemd restart the gateway instead of treating the failed restart as a clean stop. Landed from contributor PR #40380 by @dsantoreis. Thanks @dsantoreis.
- Cron/owner-only tools: pass trusted isolated cron runs into the embedded agent with owner context so `cron`/`gateway` tooling remains available after the owner-auth hardening narrowed direct-message ownership inference.
## 2026.3.7

View File

@ -0,0 +1,59 @@
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
clearFastTestEnv,
loadRunCronIsolatedAgentTurn,
resetRunCronIsolatedAgentTurnHarness,
resolveDeliveryTargetMock,
restoreFastTestEnv,
runEmbeddedPiAgentMock,
runWithModelFallbackMock,
} from "./run.test-harness.js";
const runCronIsolatedAgentTurn = await loadRunCronIsolatedAgentTurn();
function makeParams() {
return {
cfg: {},
deps: {} as never,
job: {
id: "owner-auth",
name: "Owner Auth",
schedule: { kind: "every", everyMs: 60_000 },
sessionTarget: "isolated",
payload: { kind: "agentTurn", message: "check owner tools" },
delivery: { mode: "none" },
} as never,
message: "check owner tools",
sessionKey: "cron:owner-auth",
};
}
describe("runCronIsolatedAgentTurn owner auth", () => {
let previousFastTestEnv: string | undefined;
beforeEach(() => {
previousFastTestEnv = clearFastTestEnv();
resetRunCronIsolatedAgentTurnHarness();
resolveDeliveryTargetMock.mockResolvedValue({
channel: "telegram",
to: "123",
accountId: undefined,
error: undefined,
});
runWithModelFallbackMock.mockImplementation(async ({ provider, model, run }) => {
const result = await run(provider, model);
return { result, provider, model, attempts: [] };
});
});
afterEach(() => {
restoreFastTestEnv(previousFastTestEnv);
});
it("passes senderIsOwner=true to isolated cron agent runs", async () => {
await runCronIsolatedAgentTurn(makeParams());
expect(runEmbeddedPiAgentMock).toHaveBeenCalledTimes(1);
expect(runEmbeddedPiAgentMock.mock.calls[0]?.[0]?.senderIsOwner).toBe(true);
});
});

View File

@ -588,6 +588,9 @@ export async function runCronIsolatedAgentTurn(params: {
sessionKey: agentSessionKey,
agentId,
trigger: "cron",
// Cron jobs are trusted local automation, so isolated runs should
// inherit owner-only tooling like local `openclaw agent` runs.
senderIsOwner: true,
messageChannel,
agentAccountId: resolvedDelivery.accountId,
sessionFile,