



















@@ -1,4 +1,5 @@
11import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2+import type { ChannelRuntimeSurface } from "../channels/plugins/channel-runtime-surface.types.js";
23import {
34type ChannelGatewayContext,
45type ChannelId,
@@ -11,6 +12,7 @@ import {
1112} from "../logging/subsystem.js";
1213import { createEmptyPluginRegistry, type PluginRegistry } from "../plugins/registry.js";
1314import { getActivePluginRegistry, setActivePluginRegistry } from "../plugins/runtime.js";
15+import { createChannelRuntimeContextRegistry } from "../plugins/runtime/channel-runtime-contexts.js";
1416import { createRuntimeChannel } from "../plugins/runtime/runtime-channel.js";
1517import type { PluginRuntime } from "../plugins/runtime/types.js";
1618import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js";
@@ -102,11 +104,17 @@ function createDeferred(): { promise: Promise<void>; resolve: () => void } {
102104return { promise, resolve: resolvePromise };
103105}
104106105-function installTestRegistry(...plugins: ChannelPlugin<TestAccount>[]) {
107+function installTestRegistry(
108+ ...plugins: Array<
109+ChannelPlugin<TestAccount> | { plugin: ChannelPlugin<TestAccount>; origin: string }
110+>
111+) {
106112const registry = createEmptyPluginRegistry();
107-for (const plugin of plugins) {
113+for (const candidate of plugins) {
114+const plugin = "plugin" in candidate ? candidate.plugin : candidate;
108115registry.channels.push({
109116pluginId: plugin.id,
117+ ...("origin" in candidate ? { origin: candidate.origin as never } : {}),
110118source: "test",
111119 plugin,
112120});
@@ -115,8 +123,9 @@ function installTestRegistry(...plugins: ChannelPlugin<TestAccount>[]) {
115123}
116124117125function createManager(options?: {
118-channelRuntime?: PluginRuntime["channel"];
119-resolveChannelRuntime?: () => PluginRuntime["channel"] | Promise<PluginRuntime["channel"]>;
126+channelRuntime?: ChannelRuntimeSurface;
127+resolveChannelRuntime?: () => ChannelRuntimeSurface | Promise<ChannelRuntimeSurface>;
128+resolveStartupChannelRuntime?: () => ChannelRuntimeSurface | Promise<ChannelRuntimeSurface>;
120129getRuntimeConfig?: () => Record<string, unknown>;
121130channelIds?: ChannelId[];
122131startupTrace?: { measure: <T>(name: string, run: () => T | Promise<T>) => Promise<T> };
@@ -138,6 +147,9 @@ function createManager(options?: {
138147 ...(options?.resolveChannelRuntime
139148 ? { resolveChannelRuntime: options.resolveChannelRuntime }
140149 : {}),
150+ ...(options?.resolveStartupChannelRuntime
151+ ? { resolveStartupChannelRuntime: options.resolveStartupChannelRuntime }
152+ : {}),
141153 ...(options?.startupTrace ? { startupTrace: options.startupTrace } : {}),
142154});
143155}
@@ -377,6 +389,56 @@ describe("server-channels auto restart", () => {
377389expect(ctx?.channelRuntime).not.toBe(channelRuntime);
378390});
379391392+it("uses a lightweight startup runtime for bundled channels", async () => {
393+const fullRuntime = {
394+ ...createRuntimeChannel(),
395+marker: "full-channel-runtime",
396+} as PluginRuntime["channel"] & { marker: string };
397+const startupRuntime = {
398+runtimeContexts: createChannelRuntimeContextRegistry(),
399+marker: "startup-channel-runtime",
400+};
401+const resolveChannelRuntime = vi.fn(() => fullRuntime);
402+const resolveStartupChannelRuntime = vi.fn(() => startupRuntime);
403+const startAccount = vi.fn(async (_ctx: ChannelGatewayContext<TestAccount>) => {});
404+405+installTestRegistry({ plugin: createTestPlugin({ startAccount }), origin: "bundled" });
406+const manager = createManager({ resolveChannelRuntime, resolveStartupChannelRuntime });
407+408+await manager.startChannels();
409+410+expect(resolveStartupChannelRuntime).toHaveBeenCalledTimes(1);
411+expect(resolveChannelRuntime).not.toHaveBeenCalled();
412+expect(startAccount).toHaveBeenCalledTimes(1);
413+const [ctx] = startAccount.mock.calls[0] ?? [];
414+expect(ctx?.channelRuntime).toMatchObject({ marker: "startup-channel-runtime" });
415+expect(ctx?.channelRuntime).not.toBe(startupRuntime);
416+});
417+418+it("keeps the full runtime path for non-bundled channels", async () => {
419+const fullRuntime = {
420+ ...createRuntimeChannel(),
421+marker: "full-channel-runtime",
422+} as PluginRuntime["channel"] & { marker: string };
423+const startupRuntime = {
424+runtimeContexts: createChannelRuntimeContextRegistry(),
425+marker: "startup-channel-runtime",
426+};
427+const resolveChannelRuntime = vi.fn(() => fullRuntime);
428+const resolveStartupChannelRuntime = vi.fn(() => startupRuntime);
429+const startAccount = vi.fn(async (_ctx: ChannelGatewayContext<TestAccount>) => {});
430+431+installTestRegistry({ plugin: createTestPlugin({ startAccount }), origin: "workspace" });
432+const manager = createManager({ resolveChannelRuntime, resolveStartupChannelRuntime });
433+434+await manager.startChannels();
435+436+expect(resolveStartupChannelRuntime).not.toHaveBeenCalled();
437+expect(resolveChannelRuntime).toHaveBeenCalledTimes(1);
438+const [ctx] = startAccount.mock.calls[0] ?? [];
439+expect(ctx?.channelRuntime).toMatchObject({ marker: "full-channel-runtime" });
440+});
441+380442it("does not resolve channelRuntime for disabled accounts", async () => {
381443const channelRuntime = createRuntimeChannel();
382444const resolveChannelRuntime = vi.fn(() => channelRuntime);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。