fix(wake): reject subagent session targets · openclaw/openclaw@528ab7e
Kaspre
·
2026-05-12
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -13,7 +13,7 @@ import type {
|
13 | 13 | } from "./service/state.js"; |
14 | 14 | import type { CronJob } from "./types.js"; |
15 | 15 | |
16 | | -type CronWakeResult = { ok: true } | { ok: false }; |
| 16 | +type CronWakeResult = { ok: true } | { ok: false; reason?: "unwakeable-session-key" }; |
17 | 17 | |
18 | 18 | export type CronServiceRunResult = CronRunResult | { ok: true; ran: false; reason: "invalid-spec" }; |
19 | 19 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -5,7 +5,7 @@ import {
|
5 | 5 | HEARTBEAT_SKIP_CRON_IN_PROGRESS, |
6 | 6 | isRetryableHeartbeatBusySkipReason, |
7 | 7 | } from "../../infra/heartbeat-wake.js"; |
8 | | -import { DEFAULT_AGENT_ID } from "../../routing/session-key.js"; |
| 8 | +import { DEFAULT_AGENT_ID, isSubagentSessionKey } from "../../routing/session-key.js"; |
9 | 9 | import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js"; |
10 | 10 | import { |
11 | 11 | completeTaskRunByRunId, |
@@ -1788,6 +1788,9 @@ export function wake(
|
1788 | 1788 | return { ok: false } as const; |
1789 | 1789 | } |
1790 | 1790 | const sessionKey = opts.sessionKey?.trim() || undefined; |
| 1791 | +if (sessionKey && isSubagentSessionKey(sessionKey)) { |
| 1792 | +return { ok: false, reason: "unwakeable-session-key" } as const; |
| 1793 | +} |
1791 | 1794 | state.deps.enqueueSystemEvent(text, sessionKey ? { sessionKey } : undefined); |
1792 | 1795 | if (opts.mode === "now") { |
1793 | 1796 | state.deps.requestHeartbeat({ |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -96,4 +96,17 @@ describe("wake (cron timer)", () => {
|
96 | 96 | reason: "wake", |
97 | 97 | }); |
98 | 98 | }); |
| 99 | + |
| 100 | +it("rejects subagent sessionKey targets without enqueueing or waking", () => { |
| 101 | +const { state, enqueueSystemEvent, requestHeartbeat } = createState(); |
| 102 | +expect( |
| 103 | +wake(state, { |
| 104 | +mode: "now", |
| 105 | +text: "ping", |
| 106 | +sessionKey: "agent:main:subagent:worker", |
| 107 | +}), |
| 108 | +).toEqual({ ok: false, reason: "unwakeable-session-key" }); |
| 109 | +expect(enqueueSystemEvent).not.toHaveBeenCalled(); |
| 110 | +expect(requestHeartbeat).not.toHaveBeenCalled(); |
| 111 | +}); |
99 | 112 | }); |
| Original file line number | Diff line number | Diff line change |
|---|
@@ -16,6 +16,7 @@ import {
|
16 | 16 | validateTargetProviderPrefix, |
17 | 17 | } from "../../infra/outbound/channel-target-prefix.js"; |
18 | 18 | import { listConfiguredAnnounceChannelIdsForConfig } from "../../plugins/channel-plugin-ids.js"; |
| 19 | +import { isSubagentSessionKey } from "../../routing/session-key.js"; |
19 | 20 | import { normalizeMessageChannel } from "../../utils/message-channel.js"; |
20 | 21 | import { |
21 | 22 | ErrorCodes, |
@@ -178,6 +179,14 @@ export const cronHandlers: GatewayRequestHandlers = {
|
178 | 179 | sessionKey?: string; |
179 | 180 | }; |
180 | 181 | const sessionKey = p.sessionKey?.trim() || undefined; |
| 182 | +if (sessionKey && isSubagentSessionKey(sessionKey)) { |
| 183 | +respond( |
| 184 | +false, |
| 185 | +undefined, |
| 186 | +errorShape(ErrorCodes.INVALID_REQUEST, "wake sessionKey cannot target a subagent session"), |
| 187 | +); |
| 188 | +return; |
| 189 | +} |
181 | 190 | const result = context.cron.wake({ |
182 | 191 | mode: p.mode, |
183 | 192 | text: p.text, |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -722,5 +722,15 @@ describe("cron method validation", () => {
|
722 | 722 | expect(context.cron.wake).not.toHaveBeenCalled(); |
723 | 723 | expect(respond).toHaveBeenCalledWith(false, undefined, expect.any(Object)); |
724 | 724 | }); |
| 725 | + |
| 726 | +it("rejects subagent sessionKey targets before enqueueing", async () => { |
| 727 | +const { context, respond } = await invokeWake({ |
| 728 | +mode: "now", |
| 729 | +text: "ping", |
| 730 | +sessionKey: "agent:main:subagent:worker", |
| 731 | +}); |
| 732 | +expect(context.cron.wake).not.toHaveBeenCalled(); |
| 733 | +expect(respond).toHaveBeenCalledWith(false, undefined, expect.any(Object)); |
| 734 | +}); |
725 | 735 | }); |
726 | 736 | }); |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。