

















@@ -3,6 +3,8 @@ import {
33testing as sessionBindingServiceTesting,
44registerSessionBindingAdapter,
55} from "../infra/outbound/session-binding-service.js";
6+import { setActivePluginRegistry } from "../plugins/runtime.js";
7+import { createChannelTestPluginBase, createTestRegistry } from "../test-utils/channel-plugins.js";
68import type { AgentInternalEvent } from "./internal-events.js";
79import type {
810EmbeddedPiQueueFailureReason,
@@ -23,6 +25,7 @@ import { resolveAnnounceOrigin } from "./subagent-announce-origin.js";
23252426afterEach(() => {
2527sessionBindingServiceTesting.resetSessionBindingAdaptersForTests();
28+setActivePluginRegistry(createTestRegistry());
2629testing.setDepsForTest();
2730});
2831@@ -135,6 +138,27 @@ function asMock(fn: unknown) {
135138return fn as ReturnType<typeof vi.fn>;
136139}
137140141+function registerDirectTargetTestChannel(channelId: string): void {
142+setActivePluginRegistry(
143+createTestRegistry([
144+{
145+pluginId: channelId,
146+source: "test",
147+plugin: {
148+ ...createChannelTestPluginBase({
149+id: channelId,
150+capabilities: { chatTypes: ["direct", "channel"] },
151+}),
152+messaging: {
153+inferTargetChatType: ({ to }: { to: string }) =>
154+to.startsWith("channel:") || to.startsWith("thread:") ? "channel" : "direct",
155+},
156+},
157+},
158+]),
159+);
160+}
161+138162function mockCallArg(fn: unknown, callIndex = 0, argIndex = 0) {
139163const call = asMock(fn).mock.calls[callIndex];
140164if (!call) {
@@ -979,6 +1003,59 @@ describe("deliverSubagentAnnouncement completion delivery", () => {
9791003);
9801004});
98110051006+it("directly delivers unprefixed direct targets recognized by the channel grammar", async () => {
1007+registerDirectTargetTestChannel("qa-channel");
1008+const callGateway = createGatewayMock({
1009+result: {
1010+payloads: [],
1011+},
1012+});
1013+const sendMessage = createSendMessageMock();
1014+1015+const result = await deliverSlackChannelAnnouncement({
1016+ callGateway,
1017+ sendMessage,
1018+sessionId: "requester-session-qa",
1019+isActive: false,
1020+expectsCompletionMessage: true,
1021+directIdempotencyKey: "announce-qa-fallback-empty",
1022+requesterSessionKey: "agent:qa:subagent-direct-fallback:1234",
1023+requesterOrigin: {
1024+channel: "qa-channel",
1025+to: "qa-operator",
1026+accountId: "default",
1027+},
1028+internalEvents: [
1029+{
1030+type: "task_completion",
1031+source: "subagent",
1032+childSessionKey: "agent:worker:subagent:child",
1033+childSessionId: "child-session-id",
1034+announceType: "subagent task",
1035+taskLabel: "qa direct completion smoke",
1036+status: "ok",
1037+statusLabel: "completed successfully",
1038+result: "child completion output",
1039+replyInstruction: "Summarize the result.",
1040+},
1041+],
1042+});
1043+1044+expectRecordFields(result, {
1045+delivered: true,
1046+path: "direct",
1047+});
1048+expect(sendMessage).toHaveBeenCalledWith(
1049+expect.objectContaining({
1050+channel: "qa-channel",
1051+accountId: "default",
1052+to: "qa-operator",
1053+content: "child completion output",
1054+idempotencyKey: "announce-qa-fallback-empty:text-direct",
1055+}),
1056+);
1057+});
1058+9821059it("directly delivers direct-message subagent text when the announce agent returns incomplete", async () => {
9831060const callGateway = vi.fn(async () => {
9841061throw new Error(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。