






















@@ -1497,6 +1497,7 @@ describe("gateway server cron", () => {
14971497const notifyBody = notifyCall.body;
14981498expect(notifyBody.action).toBe("finished");
14991499expect(notifyBody.jobId).toBe(notifyJobId);
1500+expect(notifyBody.summary).toBe("send webhook");
1500150115011502const legacyFinished = waitForCronEvent(
15021503ws,
@@ -1532,6 +1533,7 @@ describe("gateway server cron", () => {
15321533expect(completionCall.init.headers?.Authorization).toBe("Bearer cron-webhook-token");
15331534expect(completionCall.body.action).toBe("finished");
15341535expect(completionCall.body.jobId).toBe(completionJobId);
1536+expect(completionCall.body.summary).toBe("ok");
1535153715361538const silentRes = await rpcReq(ws, "cron.add", {
15371539name: "webhook disabled",
@@ -1628,6 +1630,110 @@ describe("gateway server cron", () => {
16281630}
16291631}, 60_000);
163016321633+test("omits raw summaries from failed cron webhook payloads", async () => {
1634+const { prevSkipCron } = await setupCronTestRun({
1635+tempPrefix: "openclaw-gw-cron-webhook-failure-summary-",
1636+cronEnabled: false,
1637+});
1638+1639+await writeCronConfig({
1640+cron: {
1641+webhookToken: "cron-webhook-token",
1642+},
1643+});
1644+1645+fetchWithSsrFGuardMock.mockClear();
1646+const { server, ws } = await startServerWithClient();
1647+await connectOk(ws);
1648+1649+try {
1650+const rawSummary = [
1651+"stdout:",
1652+"To sign in, use a web browser to open https://microsoft.com/devicelogin",
1653+"and enter the code ABCD-1234 to authenticate.",
1654+].join("\n");
1655+cronIsolatedRun.mockResolvedValueOnce({
1656+status: "error",
1657+error: "command exited with code 7",
1658+summary: rawSummary,
1659+diagnostics: {
1660+summary: rawSummary,
1661+entries: [
1662+{
1663+ts: 123,
1664+source: "exec",
1665+severity: "error",
1666+message: rawSummary,
1667+},
1668+],
1669+},
1670+});
1671+const directJobId = await addWebhookCronJob({
1672+ ws,
1673+name: "failed direct webhook",
1674+sessionTarget: "isolated",
1675+delivery: { mode: "webhook", to: "https://example.invalid/failed-direct" },
1676+});
1677+await runCronJobAndWaitForFinished(ws, directJobId);
1678+const directCall = getWebhookCall(0);
1679+expect(directCall.url).toBe("https://example.invalid/failed-direct");
1680+expect(directCall.init.headers?.Authorization).toBe("Bearer cron-webhook-token");
1681+expect(directCall.body).toMatchObject({
1682+action: "finished",
1683+jobId: directJobId,
1684+status: "error",
1685+error: "command exited with code 7",
1686+});
1687+expect(directCall.body).not.toHaveProperty("summary");
1688+expect(directCall.body).not.toHaveProperty("diagnostics");
1689+expect(JSON.stringify(directCall.body)).not.toContain("ABCD-1234");
1690+1691+const completionSummary = `${rawSummary}\nstderr:\nSECRET_TOKEN=super-secret-value`;
1692+cronIsolatedRun.mockResolvedValueOnce({
1693+status: "error",
1694+error: "command exited with code 9",
1695+summary: completionSummary,
1696+diagnostics: {
1697+summary: completionSummary,
1698+entries: [
1699+{
1700+ts: 456,
1701+source: "exec",
1702+severity: "error",
1703+message: completionSummary,
1704+},
1705+],
1706+},
1707+});
1708+const completionJobId = await addWebhookCronJob({
1709+ ws,
1710+name: "failed completion webhook",
1711+sessionTarget: "isolated",
1712+delivery: {
1713+mode: "announce",
1714+completionDestination: {
1715+mode: "webhook",
1716+to: "https://example.invalid/failed-completion",
1717+},
1718+},
1719+});
1720+await runCronJobAndWaitForFinished(ws, completionJobId);
1721+const completionCall = getWebhookCall(1);
1722+expect(completionCall.url).toBe("https://example.invalid/failed-completion");
1723+expect(completionCall.body).toMatchObject({
1724+action: "finished",
1725+jobId: completionJobId,
1726+status: "error",
1727+error: "command exited with code 9",
1728+});
1729+expect(completionCall.body).not.toHaveProperty("summary");
1730+expect(completionCall.body).not.toHaveProperty("diagnostics");
1731+expect(JSON.stringify(completionCall.body)).not.toContain("SECRET_TOKEN");
1732+} finally {
1733+await cleanupCronTestRun({ ws, server, prevSkipCron });
1734+}
1735+}, 45_000);
1736+16311737test("falls back to the primary delivery channel on job failure and preserves sessionKey", async () => {
16321738const { prevSkipCron } = await setupCronTestRun({
16331739tempPrefix: "openclaw-gw-cron-failure-primary-fallback-",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。