mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-26 20:49:31 +00:00
fix(web): keep agent search runtime-first
This commit is contained in:
@@ -35,20 +35,10 @@ type RunWebSearchParams = {
|
||||
};
|
||||
};
|
||||
|
||||
type ProviderResolutionParams = {
|
||||
value?: string;
|
||||
};
|
||||
|
||||
function firstRunWebSearchParams(): RunWebSearchParams | undefined {
|
||||
return mocks.runWebSearch.mock.calls[0]?.[0] as RunWebSearchParams | undefined;
|
||||
}
|
||||
|
||||
function firstProviderResolutionParams(): ProviderResolutionParams | undefined {
|
||||
return mocks.resolveManifestContractOwnerPluginId.mock.calls[0]?.[0] as
|
||||
| ProviderResolutionParams
|
||||
| undefined;
|
||||
}
|
||||
|
||||
describe("web_search late-bound runtime fallback", () => {
|
||||
beforeEach(() => {
|
||||
mocks.runWebSearch.mockReset();
|
||||
@@ -106,7 +96,7 @@ describe("web_search late-bound runtime fallback", () => {
|
||||
|
||||
await tool?.execute("call-search", { query: "openclaw" }, undefined);
|
||||
|
||||
expect(firstProviderResolutionParams()?.value).toBe("brave");
|
||||
expect(mocks.resolveManifestContractOwnerPluginId).not.toHaveBeenCalled();
|
||||
expect(firstRunWebSearchParams()?.preferRuntimeProviders).toBe(true);
|
||||
});
|
||||
|
||||
@@ -122,7 +112,7 @@ describe("web_search late-bound runtime fallback", () => {
|
||||
expect(firstRunWebSearchParams()?.preferRuntimeProviders).toBe(true);
|
||||
});
|
||||
|
||||
it("does not prefer runtime providers when the configured provider is a bundled manifest owner", async () => {
|
||||
it("keeps runtime provider discovery enabled when configured search provider has a manifest owner", async () => {
|
||||
mocks.resolveManifestContractOwnerPluginId.mockReturnValue("openclaw-bundled-brave");
|
||||
const config = {
|
||||
tools: { web: { search: { provider: "brave" } } },
|
||||
@@ -134,7 +124,8 @@ describe("web_search late-bound runtime fallback", () => {
|
||||
|
||||
await tool?.execute("call-search", { query: "openclaw" }, undefined);
|
||||
|
||||
expect(firstRunWebSearchParams()?.preferRuntimeProviders).toBe(false);
|
||||
expect(mocks.resolveManifestContractOwnerPluginId).not.toHaveBeenCalled();
|
||||
expect(firstRunWebSearchParams()?.preferRuntimeProviders).toBe(true);
|
||||
});
|
||||
|
||||
it("prefers active runtime metadata over options.runtimeWebSearch when present", async () => {
|
||||
|
||||
@@ -78,11 +78,8 @@ describe("web tool runtime context", () => {
|
||||
|
||||
expect(resolved.config).toBe(runtimeConfig);
|
||||
expect(resolved.runtimeWebSearch?.selectedProvider).toBe("perplexity");
|
||||
const ownerLookup = latestOwnerLookupParams();
|
||||
expect(ownerLookup.contract).toBe("webSearchProviders");
|
||||
expect(ownerLookup.value).toBe("perplexity");
|
||||
expect(ownerLookup).not.toHaveProperty("origin");
|
||||
expect(ownerLookup.config).toBe(runtimeConfig);
|
||||
expect(resolved.preferRuntimeProviders).toBe(true);
|
||||
expect(mocks.resolveManifestContractOwnerPluginId).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("falls back to captured search config and runtime metadata when active globals are missing", async () => {
|
||||
@@ -104,28 +101,20 @@ describe("web tool runtime context", () => {
|
||||
|
||||
expect(resolved.config).toBe(capturedConfig);
|
||||
expect(resolved.runtimeWebSearch?.selectedProvider).toBe("brave");
|
||||
const ownerLookup = latestOwnerLookupParams();
|
||||
expect(ownerLookup.contract).toBe("webSearchProviders");
|
||||
expect(ownerLookup.value).toBe("brave");
|
||||
expect(ownerLookup).not.toHaveProperty("origin");
|
||||
expect(ownerLookup.config).toBe(capturedConfig);
|
||||
expect(resolved.preferRuntimeProviders).toBe(true);
|
||||
expect(mocks.resolveManifestContractOwnerPluginId).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses configured provider ids when runtime metadata is absent", () => {
|
||||
resolveWebSearchToolRuntimeContext({
|
||||
it("keeps search runtime discovery enabled when runtime metadata is absent", () => {
|
||||
const resolved = resolveWebSearchToolRuntimeContext({
|
||||
config: { tools: { web: { search: { provider: "Brave" } } } },
|
||||
});
|
||||
|
||||
const ownerLookup = latestOwnerLookupParams();
|
||||
expect(ownerLookup.contract).toBe("webSearchProviders");
|
||||
expect(ownerLookup.value).toBe("brave");
|
||||
expect(ownerLookup).not.toHaveProperty("origin");
|
||||
expect(ownerLookup.config).toEqual({
|
||||
tools: { web: { search: { provider: "Brave" } } },
|
||||
});
|
||||
expect(resolved.preferRuntimeProviders).toBe(true);
|
||||
expect(mocks.resolveManifestContractOwnerPluginId).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("treats resolved global provider owners as explicit selections", async () => {
|
||||
it("keeps search runtime discovery enabled for manifest-owned configured providers", async () => {
|
||||
mocks.resolveManifestContractOwnerPluginId.mockReturnValue("brave");
|
||||
const { resolveWebSearchToolRuntimeContext: resolveWebSearchToolRuntimeContextLocal } =
|
||||
await import("./web-tool-runtime-context.js");
|
||||
@@ -134,10 +123,8 @@ describe("web tool runtime context", () => {
|
||||
config: { tools: { web: { search: { provider: "brave" } } } },
|
||||
});
|
||||
|
||||
expect(resolved.preferRuntimeProviders).toBe(false);
|
||||
expect(mocks.resolveManifestContractOwnerPluginId.mock.calls.at(-1)?.[0]).not.toHaveProperty(
|
||||
"origin",
|
||||
);
|
||||
expect(resolved.preferRuntimeProviders).toBe(true);
|
||||
expect(mocks.resolveManifestContractOwnerPluginId).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("keeps runtime providers disabled for bundled fetch owners", async () => {
|
||||
|
||||
@@ -16,8 +16,6 @@ type WebProviderKind = "fetch" | "search";
|
||||
|
||||
type WebProviderRuntimeMetadata = RuntimeWebFetchMetadata | RuntimeWebSearchMetadata;
|
||||
|
||||
type WebProviderContract = "webFetchProviders" | "webSearchProviders";
|
||||
|
||||
type ResolvedWebToolRuntimeContext<TMetadata extends WebProviderRuntimeMetadata> = {
|
||||
config?: OpenClawConfig;
|
||||
preferRuntimeProviders: boolean;
|
||||
@@ -36,23 +34,21 @@ function resolveRuntimeWebProviderId(metadata: WebProviderRuntimeMetadata | unde
|
||||
return metadata?.selectedProvider ?? metadata?.providerConfigured ?? "";
|
||||
}
|
||||
|
||||
function resolveWebProviderContract(kind: WebProviderKind): WebProviderContract {
|
||||
return kind === "fetch" ? "webFetchProviders" : "webSearchProviders";
|
||||
}
|
||||
|
||||
function shouldPreferRuntimeProviders(params: {
|
||||
config?: OpenClawConfig;
|
||||
kind: WebProviderKind;
|
||||
providerSelectionId: string;
|
||||
}): boolean {
|
||||
if (!params.providerSelectionId) {
|
||||
// Agent-side web_search must use the live runtime registry; runWebSearch
|
||||
// applies manifest ownership only as a load-scope hint after that.
|
||||
if (!params.providerSelectionId || params.kind === "search") {
|
||||
return true;
|
||||
}
|
||||
// Built-in providers are handled by core; plugin-owned selections should route through plugins.
|
||||
return !resolveManifestContractOwnerPluginId({
|
||||
contract: resolveWebProviderContract(params.kind),
|
||||
contract: "webFetchProviders",
|
||||
value: params.providerSelectionId,
|
||||
...(params.kind === "fetch" ? { origin: "bundled" as const } : {}),
|
||||
origin: "bundled",
|
||||
config: params.config,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user