@nuanu-ai/magicsearch
v0.2.3
Published
Provider-index and web-search URL resolver for MagicPay agent purchase flows
Maintainers
Readme
@nuanu-ai/magicsearch
MagicSearch resolves a refined purchase prompt to the best URL for an agent to continue a checkout, provider, or product discovery flow.
It is the search layer used by MagicPay SDK and CLI surfaces before browser handoff. It can rank a first-party provider catalog, call the MagicPay remote MagicSearch API, query Exa, or return a deterministic DuckDuckGo fallback URL when no indexed provider URL is available.
Breaking Changes in 0.2.0
- The root package exports only the product MagicSearch API; provider ranking
helpers moved to
@nuanu-ai/magicsearch/internal. - Web discovery is deterministic: Exa first, then DuckDuckGo only.
searchResolver,fallbackProvider, Google/Bing fallback rotation, and browser-search helper aliases were removed.- Provider selection is stricter about taxonomy evidence and keeps
x402ahead of browser methods by default. choicesare advisory metadata.MagicSearchUrlResult.urlremains the best engine choice, whilechoiceRecommendedtells SDK/agent callers whether to block for a user choice.
Install
npm install @nuanu-ai/magicsearchThis package is ESM-only and supports Node.js 18 or newer.
Remote Client
Use the remote client when an application should query the MagicPay gateway.
import { createRemoteMagicSearchClient } from "@nuanu-ai/magicsearch";
const search = createRemoteMagicSearchClient({
apiKey: process.env.MAGICPAY_API_KEY!,
apiUrl: "https://api.mercuryo.example/functions/v1/api",
});
const result = await search.query({
query: "buy Claude Pro",
hints: {
merchantHint: "Claude",
country: "US",
},
});
console.log(result.methodType, result.url);The remote client posts to POST /magicsearch/query and returns a
MagicSearchUrlResult. Its top-level methodType tells the runtime which
mechanism should continue. The beta release returns browser for every URL so
the runtime hands it to MagicBrowse; nested provider metadata still reports
catalog capabilities for future method dispatch.
Local Client
Use the local client when a runtime already has a provider catalog or wants deterministic public-search fallback behavior.
import {
createCachedCatalogSource,
createLocalMagicSearchClient,
loadProviderCatalog,
} from "@nuanu-ai/magicsearch";
const catalogSource = createCachedCatalogSource(
{
loadCatalog: () => loadProviderCatalog(supabaseServiceClient),
},
{ ttlMs: 30_000, refreshTimeoutMs: 5000 },
);
const search = createLocalMagicSearchClient({
catalogSource,
exaApiKey: process.env.EXA_API_KEY ?? null,
catalogTimeoutMs: 5000,
searchTimeoutMs: 8000,
});
const result = await search.query({
query: "book a flight from Singapore to Istanbul",
hints: {
merchantHint: "Google Flights",
},
choicePolicy: "auto",
});The local search policy is deterministic: Exa is tried first when exaApiKey
or EXA_API_KEY is available, and DuckDuckGo is the only public fallback. Pass
exaApiKey: null to force DuckDuckGo fallback URLs. The caller query abort
signal cancels the whole query. catalogTimeoutMs limits provider catalog
loading and continues to web discovery with
fallbackReason: "provider_catalog_unavailable"; searchTimeoutMs only times
out the internal Exa request and returns a DuckDuckGo result with
fallbackReason: "exa_timeout".
Set resolutionMode: "x402_only" to admit only active x402 catalog methods.
That mode never invokes provider-feasibility switching, Exa, DuckDuckGo, browser,
MCP, or API fallback; it fails with no_eligible_x402_provider when the catalog
has no compatible x402 target. The MagicPay API defaults to this mode; set
MAGICSEARCH_RESOLUTION_MODE=hybrid only to restore the legacy mixed resolver.
Use createCachedCatalogSource to share a TTL cache and single-flight catalog
load across local queries. The cached source bounds refreshes with
refreshTimeoutMs and serves stale catalog data after refresh failures or
timeouts. Pass onStaleRefreshError to observe refresh failures when a stale
catalog is served instead of failing the hot path.
Choice Policy
choices can come from Exa alternatives or close provider-index candidates.
When a choice-oriented query resolves to a single provider-index target without
enough selectable provider choices, MagicSearch falls back to Exa and returns
the Exa target with fallbackReason: "provider_choices_unavailable".
Use choiceRecommended and choiceRecommendationReason to decide whether a
caller should ask the user. choicePolicy defaults to auto, always
recommends whenever at least two valid choices exist, and never skips choice
construction and omits choices from the result. choiceLimit is an integer from
2 to 8 and defaults to 8. Auto policy is intentionally conservative: it
recommends for explicit choice wording or recognized travel verticals, while
other alternative lists remain advisory unless the caller uses always.
Exports
The root package is the product API:
createRemoteMagicSearchClientcreateLocalMagicSearchClientresolveMagicSearchUrlbuildMagicSearchDiscoveryQuerybuildMagicSearchProviderQuerybuildMagicSearchClarificationResultcreateCachedCatalogSourceloadProviderCatalogbuildMagicSearchFallbackUrlMagicSearch*types
Ranking and provider search helpers are internal implementation APIs. If a
workspace package needs them, import from @nuanu-ai/magicsearch/internal:
import {
rankMethodsForProvider,
rankProviderSelection,
searchProviders,
} from "@nuanu-ai/magicsearch/internal";CLI
For a standalone command-line tool, install @nuanu-ai/magicsearch-cli.
Architecture
See the repository reference doc for the current component map, ranking logic,
fallback behavior, local/remote clients, and integration points:
docs/reference/magicsearch-architecture.md.
