Web search and content fetching extension for Pi using the Linkup API.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113import { Type } from "@sinclair/typebox";import packageJson from "../package.json" with { type: "json" };
import type { LinkupBalanceResponse, LinkupErrorResponse, LinkupFetchResponse, LinkupSearchResponse, LinkupSourcedAnswerResponse,} from "./types";
const BASE_URL = "https://api.linkup.so/v1";
export const SearchDepth = Type.Union( [Type.Literal("fast"), Type.Literal("standard"), Type.Literal("deep")], { description: "Search depth: 'fast' for sub-second quick facts, 'standard' (default) for balanced speed/depth, 'deep' for comprehensive multi-step research (slower).", },);
export type SearchDepthType = "fast" | "standard" | "deep";
export class LinkupClient { private apiKey: string;
constructor(apiKey: string) { this.apiKey = apiKey; }
private async request<T>( endpoint: string, options: RequestInit = {}, signal?: AbortSignal, ): Promise<T> { const response = await fetch(`${BASE_URL}${endpoint}`, { ...options, signal, headers: { Authorization: `Bearer ${this.apiKey}`, "Content-Type": "application/json", "User-Agent": `pi-linkup/${packageJson.version} (+https://github.com/aliou/pi-linkup)`, ...options.headers, }, });
if (!response.ok) { const error = (await response.json()) as LinkupErrorResponse; throw new Error( error.error?.message || `HTTP ${response.status}: ${response.statusText}`, ); }
return response.json(); }
async search(params: { query: string; depth: SearchDepthType; outputType: "searchResults" | "sourcedAnswer"; maxResults?: number; signal?: AbortSignal; }): Promise<LinkupSearchResponse | LinkupSourcedAnswerResponse> { const body: Record<string, unknown> = { q: params.query, depth: params.depth, outputType: params.outputType, }; if (params.maxResults !== undefined) { body.maxResults = params.maxResults; } return this.request( "/search", { method: "POST", body: JSON.stringify(body), }, params.signal, ); }
async fetch(params: { url: string; renderJs?: boolean; signal?: AbortSignal; }): Promise<LinkupFetchResponse> { return this.request( "/fetch", { method: "POST", body: JSON.stringify({ url: params.url, renderJs: params.renderJs ?? true, }), }, params.signal, ); }
async getBalance(): Promise<LinkupBalanceResponse> { return this.request("/credits/balance", { method: "GET", }); }}
import { getLinkupApiKey } from "./lib/env";
export function getClient(): LinkupClient { return new LinkupClient(getLinkupApiKey());}