Media: keep inbound roots on media contracts

This commit is contained in:
Gustavo Madeira Santana
2026-04-17 14:41:37 -04:00
parent bb5d9948c2
commit 8747351383
2 changed files with 32 additions and 80 deletions

View File

@@ -5,12 +5,8 @@ import type { OpenClawConfig } from "../config/types.js";
const publicSurfaceLoaderMocks = vi.hoisted(() => ({
loadBundledPluginPublicArtifactModuleSync: vi.fn(),
}));
const bootstrapRegistryMocks = vi.hoisted(() => ({
getBootstrapChannelPlugin: vi.fn(),
}));
vi.mock("../plugins/public-surface-loader.js", () => publicSurfaceLoaderMocks);
vi.mock("../channels/plugins/bootstrap-registry.js", () => bootstrapRegistryMocks);
import {
resolveChannelInboundAttachmentRoots,
@@ -40,7 +36,6 @@ function createContext(provider: string, accountId = "work"): MsgContext {
beforeEach(() => {
publicSurfaceLoaderMocks.loadBundledPluginPublicArtifactModuleSync.mockReset();
bootstrapRegistryMocks.getBootstrapChannelPlugin.mockReset();
});
describe("channel inbound roots fast path", () => {
@@ -73,7 +68,6 @@ describe("channel inbound roots fast path", () => {
ctx: createContext("imessage"),
}),
).toEqual(["/remote/work"]);
expect(bootstrapRegistryMocks.getBootstrapChannelPlugin).not.toHaveBeenCalled();
expect(publicSurfaceLoaderMocks.loadBundledPluginPublicArtifactModuleSync).toHaveBeenCalledWith(
{
dirName: "imessage",
@@ -82,14 +76,9 @@ describe("channel inbound roots fast path", () => {
);
});
it("falls back to generic contract artifacts before full channel bootstrap", () => {
it("does not load broad generic contract artifacts on the media-root path", () => {
publicSurfaceLoaderMocks.loadBundledPluginPublicArtifactModuleSync.mockImplementation(
({ artifactBasename, dirName }: { artifactBasename: string; dirName: string }) => {
if (dirName === "legacy-channel" && artifactBasename === "contract-api.js") {
return {
resolveRemoteInboundAttachmentRoots: () => ["/legacy-remote"],
};
}
throw unableToResolve(dirName, artifactBasename);
},
);
@@ -97,46 +86,26 @@ describe("channel inbound roots fast path", () => {
expect(
resolveChannelRemoteInboundAttachmentRoots({
cfg,
ctx: createContext("legacy-channel"),
ctx: createContext("whatsapp"),
}),
).toEqual(["/legacy-remote"]);
expect(bootstrapRegistryMocks.getBootstrapChannelPlugin).not.toHaveBeenCalled();
).toBeUndefined();
expect(publicSurfaceLoaderMocks.loadBundledPluginPublicArtifactModuleSync).toHaveBeenCalledWith(
{
dirName: "legacy-channel",
dirName: "whatsapp",
artifactBasename: "media-contract-api.js",
},
);
expect(publicSurfaceLoaderMocks.loadBundledPluginPublicArtifactModuleSync).toHaveBeenCalledWith(
{
dirName: "legacy-channel",
artifactBasename: "contract-api.js",
},
);
});
it("uses channel bootstrap when no public root contract exists", () => {
publicSurfaceLoaderMocks.loadBundledPluginPublicArtifactModuleSync.mockImplementation(
({ artifactBasename, dirName }: { artifactBasename: string; dirName: string }) => {
throw unableToResolve(dirName, artifactBasename);
},
);
bootstrapRegistryMocks.getBootstrapChannelPlugin.mockReturnValue({
messaging: {
resolveRemoteInboundAttachmentRoots: ({ accountId }: { accountId?: string }) => [
`/bootstrap/${accountId}`,
],
},
});
expect(
resolveChannelRemoteInboundAttachmentRoots({
cfg,
ctx: createContext("bootstrap-channel"),
}),
).toEqual(["/bootstrap/work"]);
expect(bootstrapRegistryMocks.getBootstrapChannelPlugin).toHaveBeenCalledWith(
"bootstrap-channel",
);
publicSurfaceLoaderMocks.loadBundledPluginPublicArtifactModuleSync,
).not.toHaveBeenCalledWith({
dirName: "whatsapp",
artifactBasename: "contract-api.js",
});
expect(
publicSurfaceLoaderMocks.loadBundledPluginPublicArtifactModuleSync,
).not.toHaveBeenCalledWith({
dirName: "whatsapp",
artifactBasename: "index.js",
});
});
});

View File

@@ -1,5 +1,4 @@
import type { MsgContext } from "../auto-reply/templating.js";
import { getBootstrapChannelPlugin } from "../channels/plugins/bootstrap-registry.js";
import type { OpenClawConfig } from "../config/types.js";
import { loadBundledPluginPublicArtifactModuleSync } from "../plugins/public-surface-loader.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
@@ -31,23 +30,23 @@ function loadChannelMediaContractApi(
return mediaContractApiByResolver.get(cacheKey) ?? undefined;
}
for (const artifactBasename of ["media-contract-api.js", "contract-api.js"]) {
try {
const loaded = loadBundledPluginPublicArtifactModuleSync<ChannelMediaContractApi>({
dirName: channelId,
artifactBasename,
});
if (typeof loaded[resolver] === "function") {
mediaContractApiByResolver.set(cacheKey, loaded);
return loaded;
}
} catch (error) {
if (
try {
const loaded = loadBundledPluginPublicArtifactModuleSync<ChannelMediaContractApi>({
dirName: channelId,
artifactBasename: "media-contract-api.js",
});
if (typeof loaded[resolver] === "function") {
mediaContractApiByResolver.set(cacheKey, loaded);
return loaded;
}
} catch (error) {
if (
!(
error instanceof Error &&
error.message.startsWith("Unable to resolve bundled plugin public surface ")
) {
continue;
}
)
) {
throw error;
}
}
@@ -66,14 +65,6 @@ function findChannelMediaContractApi(
return loadChannelMediaContractApi(normalized, resolver);
}
function findChannelMessagingAdapter(channelId?: string | null) {
const normalized = normalizeOptionalLowercaseString(channelId);
if (!normalized) {
return undefined;
}
return getBootstrapChannelPlugin(normalized)?.messaging;
}
export function resolveChannelInboundAttachmentRoots(params: {
cfg: OpenClawConfig;
ctx: MsgContext;
@@ -88,11 +79,7 @@ export function resolveChannelInboundAttachmentRoots(params: {
accountId: params.ctx.AccountId,
});
}
const messaging = findChannelMessagingAdapter(params.ctx.Surface ?? params.ctx.Provider);
return messaging?.resolveInboundAttachmentRoots?.({
cfg: params.cfg,
accountId: params.ctx.AccountId,
});
return undefined;
}
export function resolveChannelRemoteInboundAttachmentRoots(params: {
@@ -109,9 +96,5 @@ export function resolveChannelRemoteInboundAttachmentRoots(params: {
accountId: params.ctx.AccountId,
});
}
const messaging = findChannelMessagingAdapter(params.ctx.Surface ?? params.ctx.Provider);
return messaging?.resolveRemoteInboundAttachmentRoots?.({
cfg: params.cfg,
accountId: params.ctx.AccountId,
});
return undefined;
}