blob: bd21753e9a3cdc9f6263def1056caa8dd552362d [file]
import {
buildWebSearchTool,
createProxiedFetchTransport,
queryTavily,
type MakaTool,
type ProxiedFetchProxy,
type ProxiedFetchTransport,
} from '@maka/runtime';
import type { WebSearchResponse } from '@maka/core';
import type {
ResolveWebSearchExecutionInput,
RuntimePolicyOperationCoordinator,
} from '@maka/storage/runtime-policy-stores';
import { toRuntimePolicyProxy } from './runtime-policy-proxy.js';
interface HostWebSearchServiceInput {
readonly policy: Pick<RuntimePolicyOperationCoordinator, 'resolveWebSearchExecution'>;
readonly createFetchTransport?: (proxy: ProxiedFetchProxy | null) => ProxiedFetchTransport;
}
export interface HostWebSearchService {
search(input: {
readonly query: string;
readonly limit: number;
readonly abortSignal?: AbortSignal;
readonly policy?: ResolveWebSearchExecutionInput;
}): Promise<WebSearchResponse>;
}
export function createHostWebSearchService(input: HostWebSearchServiceInput): HostWebSearchService {
const createFetchTransport = input.createFetchTransport ?? createProxiedFetchTransport;
return {
search: async ({ query, limit, abortSignal, policy }) => {
const resolved = await input.policy.resolveWebSearchExecution(policy);
switch (resolved.kind) {
case 'privacy_mode':
return {
ok: false,
reason: 'incognito_active',
message: 'Web search is disabled while privacy mode is active.',
};
case 'disabled':
return {
ok: false,
reason: 'not_configured',
message: 'Enable web search before using this tool.',
};
case 'model_native_only':
return {
ok: false,
reason: 'unsupported_provider',
message: 'Provider-native web search executes inside the primary model request.',
};
case 'credential_not_configured':
return {
ok: false,
reason: 'not_configured',
message:
resolved.status.locator.scope === 'network_proxy'
? 'Configure the network proxy credential before using web search.'
: 'Configure a Tavily API key before using web search.',
};
case 'ready': {
if (resolved.provider !== 'tavily') {
return {
ok: false,
reason: 'unsupported_provider',
message: 'The configured web search provider is not supported by this Host.',
};
}
const apiKey = resolved.secretMaterial.webSearch.secret;
const transport = createFetchTransport(
toRuntimePolicyProxy(
resolved.networkProxy,
resolved.secretMaterial.networkProxy?.secret,
),
);
try {
return await queryTavily({
apiKey,
query,
limit,
fetch: transport.fetch,
...(abortSignal ? { abortSignal } : {}),
});
} finally {
await transport.close();
}
}
}
},
};
}
export function createHostWebSearchTool(input: HostWebSearchServiceInput): MakaTool {
return createHostWebSearchToolFromService(createHostWebSearchService(input));
}
export function createHostWebSearchToolFromService(service: HostWebSearchService): MakaTool {
return buildWebSearchTool({
search: ({ query, limit, abortSignal }) =>
service.search({
query,
limit,
...(abortSignal ? { abortSignal } : {}),
}),
});
}