Files
openclaw/extensions/parallel/parallel.live.test.ts
Matt H db7d70ae4d feat(parallel): add Parallel as a bundled web_search provider (#85158)
- New extensions/parallel package modeled on extensions/exa
- Wires Parallel's POST /v1/search through the generic web_search contract,
  exposing Parallel's recommended {objective, search_queries} shape (plus
  optional count, session_id, client_model) so the model can supply both the
  natural-language goal and 2-3 short keyword queries as Parallel docs advise
- client_model lets the model report its own slug so Parallel can tailor
  optimizations for the consuming model's capabilities; partitions the cache
  by client_model so different models do not silently share ranked excerpts
- Honors top-level tools.web.search.{maxResults,timeoutSeconds,cacheTtlMinutes}
  via the shared SDK helpers (mergeScopedSearchConfig, withTrustedWebSearchEndpoint,
  buildSearchCacheKey, read/writeCachedSearchPayload)
- Auto-detect order 75; auth via PARALLEL_API_KEY or
  plugins.entries.parallel.config.webSearch.apiKey
- Optional baseUrl override for proxies (e.g. Cloudflare AI Gateway)
- Threads caller-supplied session_id through follow-up calls; strips
  auto-generated session_id from the shared cache to avoid cross-task leaks
- Always sends advanced_settings.max_results so result volume matches the
  OpenClaw web_search default (5) instead of Parallel's default (10)
- Identifies the plugin via User-Agent header built from package version
- Runtime accepts the generic `query` arg as a fallback so the operator
  CLI (openclaw capability web.search) keeps working when Parallel is the
  active provider: it is promoted into the lone `search_queries` entry.
  `objective` stays optional and is never synthesized from a keyword
  query (Parallel documents it as natural-language intent). Agent callers
  using the native objective+search_queries shape take precedence; the
  schema still advertises only the native keys
- Updates the agent tool-display extractor (src/agents/tool-display-common.ts)
  to recognize Parallel's objective+search_queries shape so calls render with
  query context in CLI progress and Codex activity metadata
- Adds /tools/parallel-search docs page, web.md provider listing, docs nav,
  labeler entry, per-plugin registration contract test, and minimal core
  touch-points (legacy migrate, registration cases, providers contract list,
  runtime bundled list, vitest extension paths)
2026-06-05 12:01:58 -07:00

47 lines
1.7 KiB
TypeScript

import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import { createParallelWebSearchProvider } from "./src/parallel-web-search-provider.js";
const PARALLEL_API_KEY = process.env.PARALLEL_API_KEY?.trim() ?? "";
const describeLive = isLiveTestEnabled() && PARALLEL_API_KEY.length > 0 ? describe : describe.skip;
const PARALLEL_LIVE_TIMEOUT_MS = 120_000;
describeLive("parallel plugin live", () => {
it(
"runs Parallel web search through the provider tool",
async () => {
const provider = createParallelWebSearchProvider();
const tool = provider.createTool?.({
config: {},
searchConfig: { parallel: { apiKey: PARALLEL_API_KEY } },
});
if (!tool) {
throw new Error("Expected Parallel provider tool");
}
const result = (await tool.execute({
objective:
"Find the OpenClaw GitHub repository and recent project activity for a quick smoke test.",
search_queries: ["openclaw github repository", "openclaw release notes"],
count: 3,
client_model: "claude-opus-4-7",
})) as {
provider?: string;
count?: number;
results?: Array<{ url?: string; title?: string }>;
sessionId?: string;
};
expect(result.provider).toBe("parallel");
expect(typeof result.count).toBe("number");
expect(Array.isArray(result.results)).toBe(true);
expect((result.results ?? []).length).toBeGreaterThan(0);
const first = result.results?.[0];
expect((first?.url ?? "").startsWith("http")).toBe(true);
expect(typeof result.sessionId).toBe("string");
},
PARALLEL_LIVE_TIMEOUT_MS,
);
});