Skip to content

Commit a2cc063

Browse files
committed
fix: use session origin provider in subagent queue routing
1 parent 6e5bc56 commit a2cc063

2 files changed

Lines changed: 65 additions & 8 deletions

File tree

src/agents/subagent-announce-delivery.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ async function maybeQueueSubagentAnnounce(params: {
382382

383383
const queueSettings = resolveQueueSettings({
384384
cfg,
385-
channel: entry?.channel ?? entry?.lastChannel,
385+
channel: entry?.channel ?? entry?.lastChannel ?? entry?.origin?.provider,
386386
sessionEntry: entry,
387387
});
388388
const isActive = isEmbeddedPiRunActive(sessionId);

src/agents/subagent-announce.test.ts

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@ const resolveStorePathMock = vi.fn((_store: unknown, _options: unknown) => "/tmp
1313
const resolveMainSessionKeyMock = vi.fn((_cfg: unknown) => "agent:main:main");
1414
const readLatestAssistantReplyMock = vi.fn(async (_params?: unknown) => "raw subagent reply");
1515
const isEmbeddedPiRunActiveMock = vi.fn((_sessionId: string) => false);
16+
const queueEmbeddedPiMessageMock = vi.fn((_sessionId: string, _text: string) => false);
1617
const waitForEmbeddedPiRunEndMock = vi.fn(async (_sessionId: string, _timeoutMs?: number) => true);
18+
let mockConfig: Record<string, unknown> = {
19+
session: {
20+
mainKey: "main",
21+
scope: "per-sender",
22+
},
23+
};
1724

1825
const { subagentRegistryRuntimeMock } = vi.hoisted(() => ({
1926
subagentRegistryRuntimeMock: {
@@ -32,12 +39,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
3239
const actual = await importOriginal<typeof import("../config/config.js")>();
3340
return {
3441
...actual,
35-
loadConfig: () => ({
36-
session: {
37-
mainKey: "main",
38-
scope: "per-sender",
39-
},
40-
}),
42+
loadConfig: () => mockConfig,
4143
};
4244
});
4345

@@ -62,7 +64,8 @@ vi.mock("./pi-embedded.js", async (importOriginal) => {
6264
return {
6365
...actual,
6466
isEmbeddedPiRunActive: (sessionId: string) => isEmbeddedPiRunActiveMock(sessionId),
65-
queueEmbeddedPiMessage: () => false,
67+
queueEmbeddedPiMessage: (sessionId: string, text: string) =>
68+
queueEmbeddedPiMessageMock(sessionId, text),
6669
waitForEmbeddedPiRunEnd: (sessionId: string, timeoutMs?: number) =>
6770
waitForEmbeddedPiRunEndMock(sessionId, timeoutMs),
6871
};
@@ -120,7 +123,14 @@ describe("subagent announce seam flow", () => {
120123
resolveMainSessionKeyMock.mockReset().mockImplementation(() => "agent:main:main");
121124
readLatestAssistantReplyMock.mockReset().mockResolvedValue("raw subagent reply");
122125
isEmbeddedPiRunActiveMock.mockReset().mockReturnValue(false);
126+
queueEmbeddedPiMessageMock.mockReset().mockReturnValue(false);
123127
waitForEmbeddedPiRunEndMock.mockReset().mockResolvedValue(true);
128+
mockConfig = {
129+
session: {
130+
mainKey: "main",
131+
scope: "per-sender",
132+
},
133+
};
124134
subagentRegistryRuntimeMock.shouldIgnorePostCompletionAnnounceForSession.mockReset();
125135
subagentRegistryRuntimeMock.shouldIgnorePostCompletionAnnounceForSession.mockReturnValue(false);
126136
subagentRegistryRuntimeMock.isSubagentSessionRunActive.mockReset();
@@ -201,4 +211,51 @@ describe("subagent announce seam flow", () => {
201211
timeoutMs: 10_000,
202212
});
203213
});
214+
215+
it("uses origin.provider for channel-specific queue settings in active announce delivery", async () => {
216+
mockConfig = {
217+
session: {
218+
mainKey: "main",
219+
scope: "per-sender",
220+
},
221+
messages: {
222+
queue: {
223+
byChannel: {
224+
discord: "steer",
225+
},
226+
},
227+
},
228+
};
229+
loadSessionStoreMock.mockImplementation(() => ({
230+
"agent:main:main": {
231+
sessionId: "session-origin-provider-steer",
232+
updatedAt: Date.now(),
233+
origin: { provider: "discord" },
234+
},
235+
}));
236+
isEmbeddedPiRunActiveMock.mockReturnValue(true);
237+
queueEmbeddedPiMessageMock.mockReturnValue(true);
238+
239+
({ runSubagentAnnounceFlow } = await import("./subagent-announce.js"));
240+
const didAnnounce = await runSubagentAnnounceFlow({
241+
childSessionKey: "agent:main:subagent:test",
242+
childRunId: "run-origin-provider-steer",
243+
requesterSessionKey: "agent:main:main",
244+
requesterDisplayKey: "main",
245+
task: "do thing",
246+
timeoutMs: 10,
247+
cleanup: "keep",
248+
waitForCompletion: false,
249+
startedAt: 10,
250+
endedAt: 20,
251+
outcome: { status: "ok" },
252+
});
253+
254+
expect(didAnnounce).toBe(true);
255+
expect(queueEmbeddedPiMessageMock).toHaveBeenCalledWith(
256+
"session-origin-provider-steer",
257+
expect.stringContaining("[Internal task completion event]"),
258+
);
259+
expect(agentSpy).not.toHaveBeenCalled();
260+
});
204261
});

0 commit comments

Comments
 (0)