




















@@ -128,28 +128,33 @@ describe("outbound channel resolution", () => {
128128).toBe(plugin);
129129});
130130131-it("does not load registries while resolving outbound plugins", async () => {
131+it("bootstraps configured channel plugins when the active registry is missing the target", async () => {
132132const plugin = { id: "alpha" };
133133getLoadedChannelPluginMock.mockReturnValueOnce(undefined).mockReturnValueOnce(plugin);
134-const channelResolution = await importChannelResolution("no-bootstrap");
134+const channelResolution = await importChannelResolution("bootstrap-missing-target");
135135136136expect(
137137channelResolution.resolveOutboundChannelPlugin({
138138channel: "alpha",
139139cfg: { channels: {} } as never,
140+allowBootstrap: true,
140141}),
141142).toBe(plugin);
142-expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
143-144-getChannelPluginMock.mockReturnValue(undefined);
145-channelResolution.resolveOutboundChannelPlugin({
146-channel: "alpha",
147-cfg: { channels: {} } as never,
148-});
149-expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
143+expect(applyPluginAutoEnableMock).toHaveBeenCalledWith({ config: { channels: {} } });
144+expect(resolveRuntimePluginRegistryMock).toHaveBeenCalledWith(
145+expect.objectContaining({
146+config: { autoEnabled: true },
147+activationSourceConfig: { channels: {} },
148+autoEnabledReasons: {},
149+workspaceDir: "/tmp/workspace",
150+runtimeOptions: {
151+allowGatewaySubagentBinding: true,
152+},
153+}),
154+);
150155});
151156152-it("does not load when the active registry has other channels but not the requested one", async () => {
157+it("attempts activation when the active registry has other channels but not the requested one", async () => {
153158getLoadedChannelPluginMock.mockReturnValue(undefined);
154159getChannelPluginMock.mockReturnValue(undefined);
155160getActivePluginRegistryMock.mockReturnValue({
@@ -164,47 +169,80 @@ describe("outbound channel resolution", () => {
164169channelResolution.resolveOutboundChannelPlugin({
165170channel: "alpha",
166171cfg: { channels: {} } as never,
172+allowBootstrap: true,
167173}),
168174).toBeUndefined();
169-expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
175+expect(resolveRuntimePluginRegistryMock).toHaveBeenCalledTimes(1);
170176});
171177172178it("does not retry registry loads after a missing outbound plugin", async () => {
173179getChannelPluginMock.mockReturnValue(undefined);
174-resolveRuntimePluginRegistryMock.mockImplementationOnce(() => {
175-throw new Error("transient");
176-});
177180const channelResolution = await importChannelResolution("bootstrap-retry");
178181179182expect(
180183channelResolution.resolveOutboundChannelPlugin({
181184channel: "alpha",
182185cfg: { channels: {} } as never,
186+allowBootstrap: true,
183187}),
184188).toBeUndefined();
185189186190channelResolution.resolveOutboundChannelPlugin({
187191channel: "alpha",
188192cfg: { channels: {} } as never,
193+allowBootstrap: true,
189194});
190-expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
195+expect(resolveRuntimePluginRegistryMock).toHaveBeenCalledTimes(1);
191196});
192197193-it("does not load when the pinned channel registry version changes", async () => {
198+it("allows another activation attempt when the pinned channel registry version changes", async () => {
194199getChannelPluginMock.mockReturnValue(undefined);
195200const channelResolution = await importChannelResolution("channel-version-change");
196201197202channelResolution.resolveOutboundChannelPlugin({
198203channel: "alpha",
199204cfg: { channels: {} } as never,
205+allowBootstrap: true,
200206});
201-expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
207+expect(resolveRuntimePluginRegistryMock).toHaveBeenCalledTimes(1);
202208203209getActivePluginChannelRegistryVersionMock.mockReturnValue(2);
204210channelResolution.resolveOutboundChannelPlugin({
205211channel: "alpha",
206212cfg: { channels: {} } as never,
213+allowBootstrap: true,
207214});
215+expect(resolveRuntimePluginRegistryMock).toHaveBeenCalledTimes(2);
216+});
217+218+it("resolves message adapters through the activation-aware channel plugin path", async () => {
219+const message = { send: { text: vi.fn() } };
220+const plugin = { id: "alpha", message };
221+getLoadedChannelPluginMock.mockReturnValueOnce(undefined).mockReturnValueOnce(plugin);
222+const channelResolution = await importChannelResolution("message-adapter-bootstrap");
223+224+expect(
225+channelResolution.resolveOutboundChannelMessageAdapter({
226+channel: "alpha",
227+cfg: { channels: {} } as never,
228+allowBootstrap: true,
229+}),
230+).toBe(message);
231+expect(resolveRuntimePluginRegistryMock).toHaveBeenCalledTimes(1);
232+});
233+234+it("does not bootstrap by default for outbound hot-path resolution", async () => {
235+const plugin = { id: "alpha" };
236+getLoadedChannelPluginMock.mockReturnValue(undefined);
237+getChannelPluginMock.mockReturnValue(plugin);
238+const channelResolution = await importChannelResolution("no-bootstrap-default");
239+240+expect(
241+channelResolution.resolveOutboundChannelPlugin({
242+channel: "alpha",
243+cfg: { channels: {} } as never,
244+}),
245+).toBe(plugin);
208246expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
209247});
210248});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。