@diffbot/typescript 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +196 -9
- package/dist/index.cjs +242 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +163 -9
- package/dist/index.d.ts +163 -9
- package/dist/index.js +242 -47
- package/dist/index.js.map +1 -1
- package/dist/node/index.cjs +93 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.d.cts +27 -0
- package/dist/node/index.d.ts +27 -0
- package/dist/node/index.js +63 -0
- package/dist/node/index.js.map +1 -0
- package/package.json +18 -12
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/errors.ts","../src/http.ts","../src/client.ts","../src/auth.ts","../src/extract.ts","../src/ask.ts","../src/crawl.ts","../src/kg.ts","../src/ontology.ts","../src/nlp.ts","../src/web-search.ts"],"sourcesContent":["export { DiffbotClient, type DiffbotClientOptions } from \"./client.js\";\nexport { resolveToken } from \"./auth.js\";\nexport { extract } from \"./extract.js\";\nexport { ask, type ChatMessage } from \"./ask.js\";\nexport {\n crawl,\n crawlDeleteJob,\n crawlGetJob,\n crawlListJobs,\n CrawlEventType,\n type CrawlEvent,\n type CrawlOptions,\n} from \"./crawl.js\";\nexport {\n dql,\n dqlFetchOntology,\n dqlParallel,\n dqlRefreshOntology,\n type DqlOptions,\n} from \"./kg.js\";\nexport { entities } from \"./nlp.js\";\nexport { Ontology } from \"./ontology.js\";\nexport { webSearch } from \"./web-search.js\";\nexport {\n DiffbotError,\n ValidationError,\n APIError,\n AuthError,\n RateLimitError,\n ExtractionError,\n} from \"./errors.js\";\nexport { VERSION } from \"./constants.js\";\nexport type { FetchFn } from \"./http.js\";\nexport type { JsonObject } from \"./json.js\";\n","export const VERSION = \"0.1.0\";\n\nexport const DEFAULT_TIMEOUT = 30_000;\n\nexport const EXTRACT_BASE = \"https://api.diffbot.com/v3\";\nexport const CRAWL_BASE = \"https://api.diffbot.com/v3/crawl\";\nexport const DIFFBOT_LLM_BASE = \"https://llm.diffbot.com/rag/v1/chat/completions\";\nexport const WEB_SEARCH_BASE = \"https://llm.diffbot.com/api/v1/web_search\";\nexport const NLP_BASE = \"https://nl.diffbot.com/v1/\";\nexport const KG_DQL_ENDPOINT = \"https://kg.diffbot.com/kg/v3/dql\";\nexport const KG_ONTOLOGY_ENDPOINT = \"https://kg.diffbot.com/kg/ontology\";\n\nexport const TOKEN_ENV_VAR = \"DIFFBOT_API_TOKEN\";\n","/** Exception hierarchy for the Diffbot SDK. */\n\nexport class DiffbotError extends Error {\n override name = \"DiffbotError\";\n}\n\nexport class ValidationError extends DiffbotError {\n override name = \"ValidationError\";\n}\n\nexport class APIError extends DiffbotError {\n statusCode: number;\n body: string;\n apiMessage: string | undefined;\n requestId: string | undefined;\n\n constructor(statusCode: number, body: string) {\n let apiMessage: string | undefined;\n let requestId: string | undefined;\n try {\n const data = JSON.parse(body) as { message?: string; requestId?: string };\n apiMessage = data.message;\n requestId = data.requestId;\n } catch {\n /* ignore parse errors */\n }\n const display = apiMessage ?? (body.length > 200 ? `${body.slice(0, 200)}...` : body);\n super(`Diffbot API error ${statusCode}: ${display}`);\n this.name = \"APIError\";\n this.statusCode = statusCode;\n this.body = body;\n this.apiMessage = apiMessage;\n this.requestId = requestId;\n }\n\n}\n\nexport class AuthError extends APIError {\n override name = \"AuthError\";\n}\n\nexport class RateLimitError extends APIError {\n retryAfter: string | undefined;\n override name = \"RateLimitError\";\n\n constructor(statusCode: number, body: string, retryAfter?: string | null) {\n super(statusCode, body);\n this.retryAfter = retryAfter ?? undefined;\n }\n}\n\nexport class ExtractionError extends DiffbotError {\n errorCode: number;\n error: string;\n override name = \"ExtractionError\";\n\n constructor(errorCode: number, error: string) {\n super(`Diffbot extraction error ${errorCode}: ${error}`);\n this.errorCode = errorCode;\n this.error = error;\n }\n}\n","import { APIError, AuthError, RateLimitError } from \"./errors.js\";\n\nexport type FetchFn = typeof fetch;\n\nexport interface HttpRequestOptions {\n params?: Record<string, string | number | boolean | undefined>;\n headers?: Record<string, string>;\n json?: unknown;\n redirect?: \"follow\" | \"error\" | \"manual\";\n}\n\nexport class HttpClient {\n private closed = false;\n\n constructor(\n private readonly fetchFn: FetchFn,\n private readonly timeoutMs: number,\n readonly userAgent: string,\n ) {}\n\n async get(url: string, options: HttpRequestOptions = {}): Promise<Response> {\n return this.request(url, { ...options, method: \"GET\" });\n }\n\n async post(url: string, options: HttpRequestOptions = {}): Promise<Response> {\n return this.request(url, { ...options, method: \"POST\" });\n }\n\n async request(url: string, options: HttpRequestOptions & { method?: string } = {}): Promise<Response> {\n if (this.closed) {\n throw new Error(\"HTTP client is closed\");\n }\n\n const parsed = new URL(url);\n if (options.params) {\n for (const [key, value] of Object.entries(options.params)) {\n if (value !== undefined) {\n parsed.searchParams.set(key, String(value));\n }\n }\n }\n\n const headers = new Headers(options.headers);\n headers.set(\"User-Agent\", this.userAgent);\n if (options.json !== undefined) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n const init: RequestInit = {\n method: options.method ?? \"GET\",\n headers,\n redirect: options.redirect,\n signal: AbortSignal.timeout(this.timeoutMs),\n };\n if (options.json !== undefined) {\n init.body = JSON.stringify(options.json);\n }\n\n return this.fetchFn(parsed.toString(), init);\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n get isClosed(): boolean {\n return this.closed;\n }\n}\n\nexport function raiseForStatus(response: Response, bodyText?: string): void {\n if (response.ok) {\n return;\n }\n const status = response.status;\n const body = bodyText ?? \"\";\n if (status === 401 || status === 403) {\n throw new AuthError(status, body);\n }\n if (status === 429) {\n throw new RateLimitError(status, body, response.headers.get(\"retry-after\"));\n }\n throw new APIError(status, body);\n}\n\nexport async function readBodyText(response: Response): Promise<string> {\n return response.text();\n}\n","import {\n CRAWL_BASE,\n DEFAULT_TIMEOUT,\n DIFFBOT_LLM_BASE,\n EXTRACT_BASE,\n NLP_BASE,\n VERSION,\n WEB_SEARCH_BASE,\n} from \"./constants.js\";\nimport { ValidationError } from \"./errors.js\";\nimport { HttpClient, type FetchFn } from \"./http.js\";\n\nexport interface DiffbotClientOptions {\n token: string;\n timeout?: number;\n analyzeUrl?: string;\n llmUrl?: string;\n crawlerUrl?: string;\n webSearchUrl?: string;\n nlpUrl?: string;\n fetch?: FetchFn;\n}\n\nexport class DiffbotClient {\n readonly token: string;\n readonly analyzeUrl: string;\n readonly llmUrl: string;\n readonly crawlerUrl: string;\n readonly webSearchUrl: string;\n readonly nlpUrl: string;\n readonly http: HttpClient;\n\n constructor(options: DiffbotClientOptions) {\n if (!options.token) {\n throw new ValidationError(\"token is required\");\n }\n this.token = options.token;\n this.analyzeUrl = options.analyzeUrl ?? EXTRACT_BASE;\n this.llmUrl = options.llmUrl ?? DIFFBOT_LLM_BASE;\n this.crawlerUrl = options.crawlerUrl ?? CRAWL_BASE;\n this.webSearchUrl = options.webSearchUrl ?? WEB_SEARCH_BASE;\n this.nlpUrl = options.nlpUrl ?? NLP_BASE;\n this.http = new HttpClient(\n options.fetch ?? fetch,\n options.timeout ?? DEFAULT_TIMEOUT,\n `diffbot-typescript/${VERSION}`,\n );\n }\n\n async close(): Promise<void> {\n await this.http.close();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { TOKEN_ENV_VAR } from \"./constants.js\";\n\n/** Mutable for tests; defaults to ~/.diffbot/credentials. */\nexport const authConfig = {\n credentialsPath: join(homedir(), \".diffbot\", \"credentials\"),\n};\n\nfunction readCredentialsFile(path = authConfig.credentialsPath): string {\n if (!existsSync(path)) {\n return \"\";\n }\n const text = readFileSync(path, \"utf8\");\n for (const line of text.split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed.startsWith(`${TOKEN_ENV_VAR}=`)) {\n return trimmed.slice(TOKEN_ENV_VAR.length + 1).trim();\n }\n }\n return \"\";\n}\n\n/** Resolve a Diffbot API token from explicit arg, env var, or credentials file. */\nexport function resolveToken(token?: string | null): string {\n if (token?.trim()) {\n return token.trim();\n }\n\n const envToken = process.env[TOKEN_ENV_VAR]?.trim();\n if (envToken) {\n return envToken;\n }\n\n return readCredentialsFile();\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { ExtractionError } from \"./errors.js\";\nimport { raiseForStatus, readBodyText } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nfunction buildParams(client: DiffbotClient, url: string, fmt: string) {\n const params: Record<string, string | number> = {\n token: client.token,\n url,\n timeout: 30_000,\n };\n if (fmt === \"markdown\") {\n params.mode = \"llm\";\n }\n return params;\n}\n\nfunction parseResponse(data: JsonObject): JsonObject {\n if (\"errorCode\" in data) {\n throw new ExtractionError(\n Number(data.errorCode),\n String(data.error ?? \"\"),\n );\n }\n return data;\n}\n\nfunction normalizeUrl(url: string): string {\n return url.startsWith(\"http\") ? url : `https://${url}`;\n}\n\nexport async function extract(\n client: DiffbotClient,\n url: string,\n api = \"analyze\",\n fmt = \"markdown\",\n): Promise<JsonObject> {\n const normalized = normalizeUrl(url);\n const response = await client.http.get(`${client.analyzeUrl}/${api}`, {\n params: buildParams(client, normalized, fmt),\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return parseResponse(JSON.parse(body) as JsonObject);\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\n\nexport interface ChatMessage {\n role: string;\n content: string;\n}\n\nfunction parseChunk(line: string): string | undefined {\n try {\n const chunk = JSON.parse(line.replace(/^data: /, \"\")) as {\n choices?: Array<{ delta?: { content?: string } }>;\n };\n const content = chunk.choices?.[0]?.delta?.content;\n return content ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction* linesFromText(text: string): Generator<string> {\n for (const line of text.split(\"\\n\")) {\n if (line) yield line;\n }\n}\n\nasync function* linesFromStream(body: ReadableStream<Uint8Array>): AsyncGenerator<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\");\n buffer = parts.pop() ?? \"\";\n for (const line of parts) {\n if (line) yield line;\n }\n }\n if (buffer) yield buffer;\n}\n\nexport async function* ask(\n client: DiffbotClient,\n messages: ChatMessage[],\n): AsyncGenerator<string> {\n const headers = { Authorization: `Bearer ${client.token}` };\n const payload = { model: \"diffbot-small-xl\", messages, stream: true };\n\n const response = await client.http.post(client.llmUrl, { headers, json: payload });\n if (!response.ok) {\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return;\n }\n\n if (response.body) {\n for await (const line of linesFromStream(response.body)) {\n const content = parseChunk(line);\n if (content) yield content;\n }\n return;\n }\n\n const text = await response.text();\n for (const line of linesFromText(text)) {\n const content = parseChunk(line);\n if (content) yield content;\n }\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { APIError } from \"./errors.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nexport enum CrawlEventType {\n JobCreated = \"job_created\",\n UrlProcessed = \"url_processed\",\n}\n\nexport interface CrawlEvent {\n eventType: CrawlEventType;\n timestamp: string;\n details: JsonObject;\n}\n\nexport interface CrawlOptions {\n hops?: number;\n jobName?: string;\n maxToCrawl?: number;\n maxToProcess?: number;\n restrictDomain?: boolean;\n apiUrl?: string;\n crawlDelay?: number;\n urlCrawlPattern?: string;\n urlProcessPattern?: string;\n obeyRobots?: boolean;\n useProxies?: boolean;\n customHeaders?: string;\n watch?: boolean;\n pollInterval?: number;\n}\n\nfunction buildCrawlParams(\n client: DiffbotClient,\n jobName: string,\n site: string,\n options: Required<Pick<CrawlOptions, \"maxToCrawl\" | \"maxToProcess\" | \"hops\" | \"restrictDomain\" | \"apiUrl\" | \"crawlDelay\" | \"obeyRobots\" | \"useProxies\">> &\n Pick<CrawlOptions, \"urlCrawlPattern\" | \"urlProcessPattern\" | \"customHeaders\">,\n) {\n const params: Record<string, string | number> = {\n token: client.token,\n name: jobName,\n seeds: site,\n maxToCrawl: options.maxToCrawl,\n maxToProcess: options.maxToProcess,\n maxHops: options.hops,\n restrictDomain: options.restrictDomain ? 1 : 0,\n };\n if (options.apiUrl) params.apiUrl = options.apiUrl;\n if (options.crawlDelay > 0) params.crawlDelay = options.crawlDelay;\n if (options.urlCrawlPattern) params.urlCrawlPattern = options.urlCrawlPattern;\n if (options.urlProcessPattern) params.urlProcessPattern = options.urlProcessPattern;\n if (options.obeyRobots) params.obeyRobots = 1;\n if (options.useProxies) params.useProxies = 1;\n if (options.customHeaders) params.customHeaders = options.customHeaders;\n return params;\n}\n\nfunction parseUrlCsv(text: string, seenUrls: Set<string>): CrawlEvent[] {\n const events: CrawlEvent[] = [];\n const lines = text.trim().split(\"\\n\");\n if (lines.length < 2) return events;\n\n const headers = lines[0]!.split(\",\").map((h) => h.trim());\n const urlIdx = headers.indexOf(\"Url\");\n const timeIdx = headers.indexOf(\"Crawled Time\");\n const statusIdx = headers.indexOf(\"Crawl Status\");\n\n for (const line of lines.slice(1)) {\n const cols = line.split(\",\");\n const url = cols[urlIdx]?.replace(/^\"|\"$/g, \"\").trim() ?? \"\";\n if (url && !seenUrls.has(url)) {\n seenUrls.add(url);\n events.push({\n eventType: CrawlEventType.UrlProcessed,\n timestamp: cols[timeIdx]?.trim() ?? new Date().toISOString(),\n details: {\n url,\n status: cols[statusIdx]?.trim() ?? \"unknown\",\n },\n });\n }\n }\n return events;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function* crawl(\n client: DiffbotClient,\n site: string,\n options: CrawlOptions = {},\n): AsyncGenerator<CrawlEvent> {\n let normalizedSite = site.startsWith(\"http\") ? site : `https://${site}`;\n const jobName = options.jobName ?? `crawl-${Math.floor(Date.now() / 1000)}`;\n\n const params = buildCrawlParams(client, jobName, normalizedSite, {\n hops: options.hops ?? 2,\n maxToCrawl: options.maxToCrawl ?? 100,\n maxToProcess: options.maxToProcess ?? 100,\n restrictDomain: options.restrictDomain ?? true,\n apiUrl: options.apiUrl ?? \"\",\n crawlDelay: options.crawlDelay ?? -1,\n urlCrawlPattern: options.urlCrawlPattern,\n urlProcessPattern: options.urlProcessPattern,\n obeyRobots: options.obeyRobots ?? false,\n useProxies: options.useProxies ?? false,\n customHeaders: options.customHeaders,\n });\n\n const response = await client.http.get(client.crawlerUrl, { params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n\n yield {\n eventType: CrawlEventType.JobCreated,\n timestamp: new Date().toISOString(),\n details: { job_name: jobName },\n };\n\n if (!options.watch) {\n return;\n }\n\n const seenUrls = new Set<string>();\n const pollInterval = options.pollInterval ?? 2000;\n\n while (true) {\n const statusResponse = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName },\n });\n const statusBody = await readBodyText(statusResponse);\n raiseForStatus(statusResponse, statusBody);\n const jobs = (JSON.parse(statusBody) as JsonObject).jobs as JsonObject[] | undefined;\n if (!jobs?.length) break;\n\n const jobStatus = (jobs[0]!.jobStatus ?? {}) as JsonObject;\n const statusCode = Number(jobStatus.status ?? 0);\n\n const urlsResponse = await client.http.get(`${client.crawlerUrl}/data`, {\n params: { token: client.token, name: jobName, type: \"urls\" },\n redirect: \"follow\",\n });\n const urlsBody = await readBodyText(urlsResponse);\n raiseForStatus(urlsResponse, urlsBody);\n if (urlsBody) {\n for (const event of parseUrlCsv(urlsBody, seenUrls)) {\n yield event;\n }\n }\n\n if (statusCode !== 0 && statusCode !== 7) {\n const message = String(jobStatus.message ?? \"\");\n if (/fail|error/i.test(message)) {\n throw new APIError(500, `Crawler job failed: ${message}`);\n }\n break;\n }\n\n await sleep(pollInterval);\n }\n}\n\nexport async function crawlListJobs(client: DiffbotClient): Promise<JsonObject[]> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return ((JSON.parse(body) as JsonObject).jobs as JsonObject[] | undefined) ?? [];\n}\n\nexport async function crawlGetJob(client: DiffbotClient, jobName: string): Promise<JsonObject> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n const jobs = (JSON.parse(body) as JsonObject).jobs as JsonObject[] | undefined;\n return jobs?.[0] ?? {};\n}\n\nexport async function crawlDeleteJob(client: DiffbotClient, jobName: string): Promise<void> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName, delete: 1 },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { KG_DQL_ENDPOINT, KG_ONTOLOGY_ENDPOINT } from \"./constants.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\nimport { Ontology } from \"./ontology.js\";\n\nexport interface DqlOptions {\n size?: number;\n from?: number;\n format?: string;\n filter?: string;\n exportspec?: string;\n extra?: Record<string, string>;\n raw?: boolean;\n}\n\nfunction buildDqlParams(\n client: DiffbotClient,\n query: string,\n options: DqlOptions,\n): Record<string, string | number> {\n const params: Record<string, string | number> = {\n token: client.token,\n query,\n size: options.size ?? 10,\n };\n if (options.from) params.from = options.from;\n if (options.format && options.format !== \"json\") params.format = options.format;\n if (options.filter !== undefined) params.filter = options.filter;\n if (options.exportspec !== undefined) params.exportspec = options.exportspec;\n if (options.extra) Object.assign(params, options.extra);\n return params;\n}\n\nexport async function dql(\n client: DiffbotClient,\n query: string,\n options: DqlOptions = {},\n): Promise<JsonObject | Uint8Array> {\n const params = buildDqlParams(client, query, options);\n const response = await client.http.get(KG_DQL_ENDPOINT, { params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n if (options.raw) {\n return new TextEncoder().encode(body);\n }\n return JSON.parse(body) as JsonObject;\n}\n\nexport async function dqlParallel(\n client: DiffbotClient,\n queries: Array<DqlOptions & { query: string }>,\n workers = 8,\n): Promise<Array<JsonObject | Uint8Array>> {\n if (!queries.length) return [];\n\n const limit = Math.min(workers, queries.length);\n const results: Array<JsonObject | Uint8Array> = new Array(queries.length);\n let index = 0;\n\n async function worker(): Promise<void> {\n while (true) {\n const current = index++;\n if (current >= queries.length) return;\n const { query, ...opts } = queries[current]!;\n results[current] = await dql(client, query, opts);\n }\n }\n\n await Promise.all(Array.from({ length: limit }, () => worker()));\n return results;\n}\n\nexport async function dqlRefreshOntology(client: DiffbotClient, dest: string): Promise<void> {\n const response = await client.http.get(KG_ONTOLOGY_ENDPOINT);\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, body);\n}\n\nexport async function dqlFetchOntology(client: DiffbotClient): Promise<Ontology> {\n const response = await client.http.get(KG_ONTOLOGY_ENDPOINT);\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return Ontology.fromJson(body);\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { JsonObject } from \"./json.js\";\n\ntype FieldMeta = JsonObject;\ntype FieldEntry = [string, FieldMeta];\n\nexport class Ontology {\n readonly data: JsonObject;\n\n constructor(data: JsonObject) {\n this.data = data;\n }\n\n static fromJson(raw: string | Uint8Array): Ontology {\n const text = typeof raw === \"string\" ? raw : new TextDecoder().decode(raw);\n return new Ontology(JSON.parse(text) as JsonObject);\n }\n\n static async fromPath(path: string): Promise<Ontology> {\n const text = await readFile(path, \"utf8\");\n return Ontology.fromJson(text);\n }\n\n types(): string[] {\n const types = this.data.types as Record<string, unknown> | undefined;\n return Object.keys(types ?? {}).sort();\n }\n\n composites(): string[] {\n const composites = this.data.composites as Record<string, unknown> | undefined;\n return Object.keys(composites ?? {}).sort();\n }\n\n enums(): string[] {\n const enums = this.data.enums as Record<string, unknown> | undefined;\n return Object.keys(enums ?? {}).sort();\n }\n\n taxonomies(): string[] {\n const taxonomies = this.data.taxonomies as Record<string, unknown> | undefined;\n return Object.keys(taxonomies ?? {}).sort();\n }\n\n private static fieldsOf(container: Record<string, JsonObject>, typeName: string): Record<string, FieldMeta> {\n const entry = container[typeName];\n if (!entry) throw new Error(`Unknown name: ${typeName}`);\n return (entry.fields as Record<string, FieldMeta> | undefined) ?? {};\n }\n\n fieldsFor(typeName: string): Record<string, FieldMeta> {\n const types = (this.data.types ?? {}) as Record<string, JsonObject>;\n const composites = (this.data.composites ?? {}) as Record<string, JsonObject>;\n if (typeName in types) return Ontology.fieldsOf(types, typeName);\n if (typeName in composites) return Ontology.fieldsOf(composites, typeName);\n throw new Error(`${typeName} is not a known entity type or composite`);\n }\n\n static filterFields(\n fields: Record<string, FieldMeta>,\n search?: string | null,\n includeDeprecated = false,\n ): FieldEntry[] {\n const pattern = search ? new RegExp(search, \"i\") : null;\n const out: FieldEntry[] = [];\n for (const [name, meta] of Object.entries(fields)) {\n if (!includeDeprecated && meta.isDeprecated) continue;\n if (pattern && !pattern.test(name)) continue;\n out.push([name, meta]);\n }\n return out;\n }\n\n taxonomyValues(name: string, search?: string | null): string[] {\n const taxonomies = (this.data.taxonomies ?? {}) as Record<string, JsonObject>;\n const tax = taxonomies[name];\n if (!tax) throw new Error(`Unknown taxonomy: ${name}`);\n\n const pattern = search ? new RegExp(search, \"i\") : null;\n const out: string[] = [];\n\n const walk = (node: JsonObject): void => {\n const n = node.name;\n if (typeof n === \"string\" && (!pattern || pattern.test(n))) {\n out.push(n);\n }\n for (const child of (node.children as JsonObject[] | undefined) ?? []) {\n walk(child);\n }\n };\n\n for (const cat of (tax.categories as JsonObject[] | undefined) ?? []) {\n walk(cat);\n }\n return out;\n }\n\n enumValues(name: string): string[] {\n const enums = (this.data.enums ?? {}) as Record<string, JsonObject>;\n const enumEntry = enums[name];\n if (!enumEntry) throw new Error(`Unknown enum: ${name}`);\n return [...((enumEntry.values as string[] | undefined) ?? [])];\n }\n\n findNamed(search: string): string[] {\n const pattern = new RegExp(search, \"i\");\n const found = new Set<string>();\n\n const walk = (node: unknown): void => {\n if (Array.isArray(node)) {\n for (const v of node) walk(v);\n } else if (node && typeof node === \"object\") {\n const obj = node as JsonObject;\n const n = obj.name;\n if (typeof n === \"string\" && pattern.test(n)) found.add(n);\n for (const v of Object.values(obj)) walk(v);\n }\n };\n\n walk(this.data);\n return [...found].sort();\n }\n\n static formatField(name: string, meta: FieldMeta): string {\n let typeName = String(meta.type ?? \"?\");\n if (typeName === \"LinkedEntity\") {\n const le = meta.leType as string[] | undefined;\n if (le?.length) typeName = `LinkedEntity (${le[0]})`;\n }\n const flags: string[] = [];\n if (meta.isList) flags.push(\"isList\");\n if (meta.isComposite) flags.push(\"isComposite\");\n if (meta.isEnum) flags.push(\"isEnum\");\n if (meta.isDeprecated) flags.push(\"DEPRECATED\");\n const suffix = flags.map((f) => ` [${f}]`).join(\"\");\n return `${name}: [${typeName}]${suffix}`;\n }\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nconst NLP_FIELDS = \"entities,sentiment\";\n\nexport async function entities(\n client: DiffbotClient,\n text: string,\n lang = \"auto\",\n): Promise<JsonObject> {\n const params = { token: client.token, fields: NLP_FIELDS };\n const payload = [{ lang, format: \"plain text\", content: text }];\n const response = await client.http.post(client.nlpUrl, { params, json: payload });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n const data = JSON.parse(body) as JsonObject | JsonObject[];\n return Array.isArray(data) ? (data[0] ?? {}) : data;\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nexport async function webSearch(\n client: DiffbotClient,\n text: string,\n options: { numResults?: number; maxTokens?: number } = {},\n): Promise<JsonObject> {\n const headers = { Authorization: `Bearer ${client.token}` };\n const params: Record<string, string | number> = { text };\n if (options.numResults !== undefined) params.size = options.numResults;\n if (options.maxTokens !== undefined) params.maxTokens = options.maxTokens;\n\n const response = await client.http.get(client.webSearchUrl, { headers, params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return JSON.parse(body) as JsonObject;\n}\n"],"mappings":"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","names":["CrawlEventType","import_promises","import_node_path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/errors.ts","../src/http.ts","../src/client.ts","../src/auth.ts","../src/extract.ts","../src/ask.ts","../src/crawl.ts","../src/ontology.ts","../src/kg.ts","../src/nlp.ts","../src/ontology-store.ts","../src/web-search.ts"],"sourcesContent":["export { DiffbotClient, type DiffbotClientOptions } from \"./client.js\";\nexport { resolveTokenFromEnv, type TokenSource } from \"./auth.js\";\nexport { extract } from \"./extract.js\";\nexport {\n ANY_OBJECT_SCHEMA,\n RESPONSE_FORMAT_TYPES,\n ask,\n askJson,\n extractJson,\n jsonSchemaFormat,\n type AskOptions,\n type ChatMessage,\n type ResponseFormat,\n type ResponseFormatType,\n} from \"./ask.js\";\nexport {\n crawl,\n crawlDeleteJob,\n crawlGetJob,\n crawlListJobs,\n CrawlEventType,\n type CrawlEvent,\n type CrawlOptions,\n} from \"./crawl.js\";\nexport {\n dql,\n dqlFetchOntology,\n dqlFetchOntologyText,\n dqlParallel,\n type DqlOptions,\n} from \"./kg.js\";\nexport { entities } from \"./nlp.js\";\nexport { Ontology } from \"./ontology.js\";\nexport {\n OntologyStore,\n KVOntologyStore,\n type OntologyStoreOptions,\n type KVOntologyStoreOptions,\n type KVLike,\n} from \"./ontology-store.js\";\nexport { webSearch, SNIPPET_LENGTHS, type SnippetLength, type WebSearchOptions } from \"./web-search.js\";\nexport {\n DiffbotError,\n ValidationError,\n APIError,\n AuthError,\n RateLimitError,\n ExtractionError,\n} from \"./errors.js\";\nexport { VERSION } from \"./constants.js\";\nexport type { FetchFn } from \"./http.js\";\nexport type { JsonObject } from \"./json.js\";\n","export const VERSION = \"0.3.0\";\n\nexport const DEFAULT_TIMEOUT = 30_000;\n\nexport const EXTRACT_BASE = \"https://api.diffbot.com/v3\";\nexport const CRAWL_BASE = \"https://api.diffbot.com/v3/crawl\";\nexport const DIFFBOT_LLM_BASE = \"https://llm.diffbot.com/rag/v1/chat/completions\";\nexport const WEB_SEARCH_BASE = \"https://llm.diffbot.com/api/v1/web_search\";\nexport const NLP_BASE = \"https://nl.diffbot.com/v1/\";\nexport const KG_DQL_ENDPOINT = \"https://kg.diffbot.com/kg/v3/dql\";\nexport const KG_ONTOLOGY_ENDPOINT = \"https://kg.diffbot.com/kg/ontology\";\n\nexport const TOKEN_ENV_VAR = \"DIFFBOT_API_TOKEN\";\n","/** Exception hierarchy for the Diffbot SDK. */\n\nexport class DiffbotError extends Error {\n override name = \"DiffbotError\";\n}\n\nexport class ValidationError extends DiffbotError {\n override name = \"ValidationError\";\n}\n\nexport class APIError extends DiffbotError {\n statusCode: number;\n body: string;\n apiMessage: string | undefined;\n requestId: string | undefined;\n\n constructor(statusCode: number, body: string) {\n let apiMessage: string | undefined;\n let requestId: string | undefined;\n try {\n const data = JSON.parse(body) as { message?: string; requestId?: string };\n apiMessage = data.message;\n requestId = data.requestId;\n } catch {\n /* ignore parse errors */\n }\n const display = apiMessage ?? (body.length > 200 ? `${body.slice(0, 200)}...` : body);\n super(`Diffbot API error ${statusCode}: ${display}`);\n this.name = \"APIError\";\n this.statusCode = statusCode;\n this.body = body;\n this.apiMessage = apiMessage;\n this.requestId = requestId;\n }\n\n}\n\nexport class AuthError extends APIError {\n override name = \"AuthError\";\n}\n\nexport class RateLimitError extends APIError {\n retryAfter: string | undefined;\n override name = \"RateLimitError\";\n\n constructor(statusCode: number, body: string, retryAfter?: string | null) {\n super(statusCode, body);\n this.retryAfter = retryAfter ?? undefined;\n }\n}\n\nexport class ExtractionError extends DiffbotError {\n errorCode: number;\n error: string;\n override name = \"ExtractionError\";\n\n constructor(errorCode: number, error: string) {\n super(`Diffbot extraction error ${errorCode}: ${error}`);\n this.errorCode = errorCode;\n this.error = error;\n }\n}\n","import { APIError, AuthError, RateLimitError } from \"./errors.js\";\n\nexport type FetchFn = typeof fetch;\n\nexport interface HttpRequestOptions {\n params?: Record<string, string | number | boolean | undefined>;\n headers?: Record<string, string>;\n json?: unknown;\n redirect?: \"follow\" | \"error\" | \"manual\";\n}\n\nexport class HttpClient {\n private closed = false;\n\n constructor(\n private readonly fetchFn: FetchFn,\n private readonly timeoutMs: number,\n readonly userAgent: string,\n ) {}\n\n async get(url: string, options: HttpRequestOptions = {}): Promise<Response> {\n return this.request(url, { ...options, method: \"GET\" });\n }\n\n async post(url: string, options: HttpRequestOptions = {}): Promise<Response> {\n return this.request(url, { ...options, method: \"POST\" });\n }\n\n async request(url: string, options: HttpRequestOptions & { method?: string } = {}): Promise<Response> {\n if (this.closed) {\n throw new Error(\"HTTP client is closed\");\n }\n\n const parsed = new URL(url);\n if (options.params) {\n for (const [key, value] of Object.entries(options.params)) {\n if (value !== undefined) {\n parsed.searchParams.set(key, String(value));\n }\n }\n }\n\n const headers = new Headers(options.headers);\n headers.set(\"User-Agent\", this.userAgent);\n if (options.json !== undefined) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n const init: RequestInit = {\n method: options.method ?? \"GET\",\n headers,\n redirect: options.redirect,\n signal: AbortSignal.timeout(this.timeoutMs),\n };\n if (options.json !== undefined) {\n init.body = JSON.stringify(options.json);\n }\n\n return this.fetchFn(parsed.toString(), init);\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n get isClosed(): boolean {\n return this.closed;\n }\n}\n\nexport function raiseForStatus(response: Response, bodyText?: string): void {\n if (response.ok) {\n return;\n }\n const status = response.status;\n const body = bodyText ?? \"\";\n if (status === 401 || status === 403) {\n throw new AuthError(status, body);\n }\n if (status === 429) {\n throw new RateLimitError(status, body, response.headers.get(\"retry-after\"));\n }\n throw new APIError(status, body);\n}\n\nexport async function readBodyText(response: Response): Promise<string> {\n return response.text();\n}\n","import {\n CRAWL_BASE,\n DEFAULT_TIMEOUT,\n DIFFBOT_LLM_BASE,\n EXTRACT_BASE,\n KG_DQL_ENDPOINT,\n KG_ONTOLOGY_ENDPOINT,\n NLP_BASE,\n VERSION,\n WEB_SEARCH_BASE,\n} from \"./constants.js\";\nimport { ValidationError } from \"./errors.js\";\nimport { HttpClient, type FetchFn } from \"./http.js\";\n\nexport interface DiffbotClientOptions {\n token: string;\n timeout?: number;\n analyzeUrl?: string;\n llmUrl?: string;\n crawlerUrl?: string;\n webSearchUrl?: string;\n nlpUrl?: string;\n dqlUrl?: string;\n ontologyUrl?: string;\n fetch?: FetchFn;\n}\n\nexport class DiffbotClient {\n readonly token: string;\n readonly analyzeUrl: string;\n readonly llmUrl: string;\n readonly crawlerUrl: string;\n readonly webSearchUrl: string;\n readonly nlpUrl: string;\n readonly dqlUrl: string;\n readonly ontologyUrl: string;\n readonly http: HttpClient;\n\n constructor(options: DiffbotClientOptions) {\n if (!options.token) {\n throw new ValidationError(\"token is required\");\n }\n this.token = options.token;\n this.analyzeUrl = options.analyzeUrl ?? EXTRACT_BASE;\n this.llmUrl = options.llmUrl ?? DIFFBOT_LLM_BASE;\n this.crawlerUrl = options.crawlerUrl ?? CRAWL_BASE;\n this.webSearchUrl = options.webSearchUrl ?? WEB_SEARCH_BASE;\n this.nlpUrl = options.nlpUrl ?? NLP_BASE;\n this.dqlUrl = options.dqlUrl ?? KG_DQL_ENDPOINT;\n this.ontologyUrl = options.ontologyUrl ?? KG_ONTOLOGY_ENDPOINT;\n this.http = new HttpClient(\n options.fetch ?? fetch,\n options.timeout ?? DEFAULT_TIMEOUT,\n `diffbot-typescript/${VERSION}`,\n );\n }\n\n async close(): Promise<void> {\n await this.http.close();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n","import { TOKEN_ENV_VAR } from \"./constants.js\";\n\n/*\n * `object`, not `Record<string, unknown>`: a typed Workers `Env` is normally\n * an `interface`, and interfaces don't get TypeScript's implicit index\n * signature, so a `Record<string, unknown>` parameter would reject exactly\n * the argument this function exists to accept. `object` has no members, so\n * any object type is assignable to it; the bracket access below is cast\n * internally instead.\n */\nexport type TokenSource = object;\n\nfunction envToken(env: TokenSource | undefined): string {\n const fromEnv = (env as Record<string, unknown> | undefined)?.[TOKEN_ENV_VAR];\n if (typeof fromEnv === \"string\" && fromEnv.trim()) {\n return fromEnv.trim();\n }\n\n /*\n * Guarded rather than a static `process.env` read: `process` does not exist\n * in Workers/browsers, and touching it unconditionally would reintroduce a\n * runtime-specific dependency into an otherwise platform-neutral module.\n */\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n const fromProcess = proc?.env?.[TOKEN_ENV_VAR];\n return fromProcess?.trim() ?? \"\";\n}\n\n/**\n * Resolve a Diffbot API token from an explicit arg, then a Workers-style\n * `env` object, then `process.env`. Does not touch the filesystem — for a\n * credentials-file fallback, use `resolveToken` from `@diffbot/typescript/node`.\n */\nexport function resolveTokenFromEnv(token?: string | null, env?: TokenSource): string {\n if (token?.trim()) {\n return token.trim();\n }\n return envToken(env);\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { ExtractionError } from \"./errors.js\";\nimport { raiseForStatus, readBodyText } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nfunction buildParams(client: DiffbotClient, url: string, fmt: string) {\n const params: Record<string, string | number> = {\n token: client.token,\n url,\n timeout: 30_000,\n };\n if (fmt === \"markdown\") {\n params.mode = \"llm\";\n }\n return params;\n}\n\nfunction parseResponse(data: JsonObject): JsonObject {\n if (\"errorCode\" in data) {\n throw new ExtractionError(\n Number(data.errorCode),\n String(data.error ?? \"\"),\n );\n }\n return data;\n}\n\nfunction normalizeUrl(url: string): string {\n return url.startsWith(\"http\") ? url : `https://${url}`;\n}\n\nexport async function extract(\n client: DiffbotClient,\n url: string,\n api = \"analyze\",\n fmt = \"markdown\",\n): Promise<JsonObject> {\n const normalized = normalizeUrl(url);\n const response = await client.http.get(`${client.analyzeUrl}/${api}`, {\n params: buildParams(client, normalized, fmt),\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return parseResponse(JSON.parse(body) as JsonObject);\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { ValidationError } from \"./errors.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nexport interface ChatMessage {\n role: string;\n content: string;\n}\n\nconst MODEL = \"diffbot-small-xl\";\n\n/** `response_format` types accepted by the Diffbot LLM endpoint. */\nexport const RESPONSE_FORMAT_TYPES = [\"text\", \"json_object\", \"json_schema\"] as const;\nexport type ResponseFormatType = (typeof RESPONSE_FORMAT_TYPES)[number];\n\nexport interface ResponseFormat {\n type: ResponseFormatType;\n json_schema?: { name?: string; schema: JsonObject };\n}\n\nexport interface AskOptions {\n /**\n * Constrain the output, e.g. `{ type: \"json_object\" }` or `jsonSchemaFormat(schema)`.\n * Prefer a schema: `json_object` applies no server-side grammar.\n */\n responseFormat?: ResponseFormat;\n}\n\n/**\n * Build a `response_format` that constrains output to `schema`. The endpoint requires\n * the schema nested under `json_schema.schema`; anywhere else is ignored server-side\n * without an error, so prefer this helper over hand-building the object.\n */\nexport function jsonSchemaFormat(schema: JsonObject, name = \"response\"): ResponseFormat {\n if (schema === null || typeof schema !== \"object\" || Array.isArray(schema)) {\n throw new ValidationError(\"schema must be a JSON Schema object\");\n }\n return { type: \"json_schema\", json_schema: { name, schema } };\n}\n\n/** Reject shapes the endpoint would accept but silently not enforce. */\nfunction validateResponseFormat(responseFormat: ResponseFormat | undefined): void {\n if (responseFormat === undefined) return;\n if (responseFormat === null || typeof responseFormat !== \"object\" || Array.isArray(responseFormat)) {\n throw new ValidationError(\"responseFormat must be an object\");\n }\n const fmtType = responseFormat.type ?? \"text\";\n if (!(RESPONSE_FORMAT_TYPES as readonly string[]).includes(fmtType)) {\n throw new ValidationError(\n `responseFormat type must be one of ${RESPONSE_FORMAT_TYPES.join(\", \")}; got ${JSON.stringify(fmtType)}`,\n );\n }\n if (fmtType === \"json_schema\") {\n const jsonSchema = responseFormat.json_schema;\n if (jsonSchema === null || typeof jsonSchema !== \"object\" || !(\"schema\" in jsonSchema)) {\n throw new ValidationError(\n 'responseFormat { type: \"json_schema\" } requires the schema nested as ' +\n \"{ json_schema: { schema: {...} } }. Without it the server returns 200 and \" +\n \"ignores the constraint. Use jsonSchemaFormat(schema) to build it.\",\n );\n }\n }\n}\n\n// The RAG loop may prefix its final answer with a think block, and the model\n// occasionally wraps JSON in a markdown fence despite being told not to.\nconst THINK_BLOCK = /<think>[\\s\\S]*?<\\/think>/g;\nconst JSON_FENCE = /^```(?:json)?\\s*|\\s*```$/gm;\n\n/** Parse the model's final answer as JSON, tolerating think blocks and fences. */\nexport function extractJson(text: string): unknown {\n let cleaned = text.replace(THINK_BLOCK, \"\").trim();\n cleaned = cleaned.replace(JSON_FENCE, \"\").trim();\n\n try {\n return JSON.parse(cleaned);\n } catch {\n // fall through to span search\n }\n\n // Fall back to the outermost object or array span in the response.\n const spans: Array<[number, string]> = [];\n for (const [opener, closer] of [\n [\"{\", \"}\"],\n [\"[\", \"]\"],\n ] as const) {\n const start = cleaned.indexOf(opener);\n const end = cleaned.lastIndexOf(closer);\n if (start !== -1 && end > start) spans.push([start, cleaned.slice(start, end + 1)]);\n }\n spans.sort((a, b) => a[0] - b[0]);\n for (const [, span] of spans) {\n try {\n return JSON.parse(span);\n } catch {\n continue;\n }\n }\n\n throw new ValidationError(\n `could not parse JSON from the model response: ${JSON.stringify(text.slice(0, 200))}`,\n );\n}\n\n/**\n * Schema used when the caller wants JSON but has no shape in mind. This goes through\n * the json_schema path rather than `{ type: \"json_object\" }` on purpose: json_object\n * applies no server-side grammar, so the RAG loop's internal <functioncall> JSON\n * satisfies it and gets returned as the final answer. That is reproducible whenever\n * the request carries a system message.\n */\nexport const ANY_OBJECT_SCHEMA: JsonObject = { type: \"object\" };\n\nfunction resolveFormat(\n schema: JsonObject | undefined,\n responseFormat: ResponseFormat | undefined,\n): ResponseFormat {\n if (schema !== undefined && responseFormat !== undefined) {\n throw new ValidationError(\"pass either schema or responseFormat, not both\");\n }\n if (responseFormat !== undefined) return responseFormat;\n return jsonSchemaFormat(schema ?? ANY_OBJECT_SCHEMA);\n}\n\n/** Catch the internal tool call surfacing as the answer (see ANY_OBJECT_SCHEMA). */\nfunction checkToolCallLeak<T>(parsed: T): T {\n if (\n parsed !== null &&\n typeof parsed === \"object\" &&\n !Array.isArray(parsed) &&\n (parsed as JsonObject).name === \"functioncall\" &&\n \"arguments\" in (parsed as JsonObject)\n ) {\n throw new ValidationError(\n \"the model returned its internal tool call instead of an answer; this happens with \" +\n 'responseFormat { type: \"json_object\" } because the server applies no grammar to it. ' +\n \"Pass a schema instead.\",\n );\n }\n return parsed;\n}\n\nfunction parseChunk(line: string): string | undefined {\n try {\n const chunk = JSON.parse(line.replace(/^data: /, \"\")) as {\n choices?: Array<{ delta?: { content?: string } }>;\n };\n const content = chunk.choices?.[0]?.delta?.content;\n return content ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction* linesFromText(text: string): Generator<string> {\n for (const line of text.split(\"\\n\")) {\n if (line) yield line;\n }\n}\n\nasync function* linesFromStream(body: ReadableStream<Uint8Array>): AsyncGenerator<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\");\n buffer = parts.pop() ?? \"\";\n for (const line of parts) {\n if (line) yield line;\n }\n }\n if (buffer) yield buffer;\n}\n\nexport async function* ask(\n client: DiffbotClient,\n messages: ChatMessage[],\n options: AskOptions = {},\n): AsyncGenerator<string> {\n validateResponseFormat(options.responseFormat);\n const headers = { Authorization: `Bearer ${client.token}` };\n const payload: JsonObject = { model: MODEL, messages, stream: true };\n if (options.responseFormat !== undefined) payload.response_format = options.responseFormat;\n\n const response = await client.http.post(client.llmUrl, { headers, json: payload });\n if (!response.ok) {\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return;\n }\n\n if (response.body) {\n for await (const line of linesFromStream(response.body)) {\n const content = parseChunk(line);\n if (content) yield content;\n }\n return;\n }\n\n const text = await response.text();\n for (const line of linesFromText(text)) {\n const content = parseChunk(line);\n if (content) yield content;\n }\n}\n\n/**\n * Ask the Diffbot LLM and return the answer parsed as JSON. With `schema` (a JSON Schema\n * object) the model is constrained to it by grammar; without one it falls back to\n * unconstrained JSON output. Pass `responseFormat` instead of `schema` for full control.\n */\nexport async function askJson<T = unknown>(\n client: DiffbotClient,\n messages: ChatMessage[],\n schema?: JsonObject,\n options: AskOptions = {},\n): Promise<T> {\n const responseFormat = resolveFormat(schema, options.responseFormat);\n let text = \"\";\n for await (const chunk of ask(client, messages, { responseFormat })) text += chunk;\n return checkToolCallLeak(extractJson(text)) as T;\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { APIError } from \"./errors.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nexport enum CrawlEventType {\n JobCreated = \"job_created\",\n UrlProcessed = \"url_processed\",\n}\n\nexport interface CrawlEvent {\n eventType: CrawlEventType;\n timestamp: string;\n details: JsonObject;\n}\n\nexport interface CrawlOptions {\n hops?: number;\n jobName?: string;\n maxToCrawl?: number;\n maxToProcess?: number;\n restrictDomain?: boolean;\n apiUrl?: string;\n crawlDelay?: number;\n urlCrawlPattern?: string;\n urlProcessPattern?: string;\n obeyRobots?: boolean;\n useProxies?: boolean;\n customHeaders?: string;\n watch?: boolean;\n pollInterval?: number;\n}\n\nfunction buildCrawlParams(\n client: DiffbotClient,\n jobName: string,\n site: string,\n options: Required<Pick<CrawlOptions, \"maxToCrawl\" | \"maxToProcess\" | \"hops\" | \"restrictDomain\" | \"apiUrl\" | \"crawlDelay\" | \"obeyRobots\" | \"useProxies\">> &\n Pick<CrawlOptions, \"urlCrawlPattern\" | \"urlProcessPattern\" | \"customHeaders\">,\n) {\n const params: Record<string, string | number> = {\n token: client.token,\n name: jobName,\n seeds: site,\n maxToCrawl: options.maxToCrawl,\n maxToProcess: options.maxToProcess,\n maxHops: options.hops,\n restrictDomain: options.restrictDomain ? 1 : 0,\n };\n if (options.apiUrl) params.apiUrl = options.apiUrl;\n if (options.crawlDelay > 0) params.crawlDelay = options.crawlDelay;\n if (options.urlCrawlPattern) params.urlCrawlPattern = options.urlCrawlPattern;\n if (options.urlProcessPattern) params.urlProcessPattern = options.urlProcessPattern;\n if (options.obeyRobots) params.obeyRobots = 1;\n if (options.useProxies) params.useProxies = 1;\n if (options.customHeaders) params.customHeaders = options.customHeaders;\n return params;\n}\n\nfunction parseUrlCsv(text: string, seenUrls: Set<string>): CrawlEvent[] {\n const events: CrawlEvent[] = [];\n const lines = text.trim().split(\"\\n\");\n if (lines.length < 2) return events;\n\n const headers = lines[0]!.split(\",\").map((h) => h.trim());\n const urlIdx = headers.indexOf(\"Url\");\n const timeIdx = headers.indexOf(\"Crawled Time\");\n const statusIdx = headers.indexOf(\"Crawl Status\");\n\n for (const line of lines.slice(1)) {\n const cols = line.split(\",\");\n const url = cols[urlIdx]?.replace(/^\"|\"$/g, \"\").trim() ?? \"\";\n if (url && !seenUrls.has(url)) {\n seenUrls.add(url);\n events.push({\n eventType: CrawlEventType.UrlProcessed,\n timestamp: cols[timeIdx]?.trim() ?? new Date().toISOString(),\n details: {\n url,\n status: cols[statusIdx]?.trim() ?? \"unknown\",\n },\n });\n }\n }\n return events;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function* crawl(\n client: DiffbotClient,\n site: string,\n options: CrawlOptions = {},\n): AsyncGenerator<CrawlEvent> {\n let normalizedSite = site.startsWith(\"http\") ? site : `https://${site}`;\n const jobName = options.jobName ?? `crawl-${Math.floor(Date.now() / 1000)}`;\n\n const params = buildCrawlParams(client, jobName, normalizedSite, {\n hops: options.hops ?? 2,\n maxToCrawl: options.maxToCrawl ?? 100,\n maxToProcess: options.maxToProcess ?? 100,\n restrictDomain: options.restrictDomain ?? true,\n apiUrl: options.apiUrl ?? \"\",\n crawlDelay: options.crawlDelay ?? -1,\n urlCrawlPattern: options.urlCrawlPattern,\n urlProcessPattern: options.urlProcessPattern,\n obeyRobots: options.obeyRobots ?? false,\n useProxies: options.useProxies ?? false,\n customHeaders: options.customHeaders,\n });\n\n const response = await client.http.get(client.crawlerUrl, { params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n\n yield {\n eventType: CrawlEventType.JobCreated,\n timestamp: new Date().toISOString(),\n details: { job_name: jobName },\n };\n\n if (!options.watch) {\n return;\n }\n\n const seenUrls = new Set<string>();\n const pollInterval = options.pollInterval ?? 2000;\n\n while (true) {\n const statusResponse = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName },\n });\n const statusBody = await readBodyText(statusResponse);\n raiseForStatus(statusResponse, statusBody);\n const jobs = (JSON.parse(statusBody) as JsonObject).jobs as JsonObject[] | undefined;\n if (!jobs?.length) break;\n\n const jobStatus = (jobs[0]!.jobStatus ?? {}) as JsonObject;\n const statusCode = Number(jobStatus.status ?? 0);\n\n const urlsResponse = await client.http.get(`${client.crawlerUrl}/data`, {\n params: { token: client.token, name: jobName, type: \"urls\" },\n redirect: \"follow\",\n });\n const urlsBody = await readBodyText(urlsResponse);\n raiseForStatus(urlsResponse, urlsBody);\n if (urlsBody) {\n for (const event of parseUrlCsv(urlsBody, seenUrls)) {\n yield event;\n }\n }\n\n if (statusCode !== 0 && statusCode !== 7) {\n const message = String(jobStatus.message ?? \"\");\n if (/fail|error/i.test(message)) {\n throw new APIError(500, `Crawler job failed: ${message}`);\n }\n break;\n }\n\n await sleep(pollInterval);\n }\n}\n\nexport async function crawlListJobs(client: DiffbotClient): Promise<JsonObject[]> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return ((JSON.parse(body) as JsonObject).jobs as JsonObject[] | undefined) ?? [];\n}\n\nexport async function crawlGetJob(client: DiffbotClient, jobName: string): Promise<JsonObject> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n const jobs = (JSON.parse(body) as JsonObject).jobs as JsonObject[] | undefined;\n return jobs?.[0] ?? {};\n}\n\nexport async function crawlDeleteJob(client: DiffbotClient, jobName: string): Promise<void> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName, delete: 1 },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n}\n","import type { JsonObject } from \"./json.js\";\n\ntype FieldMeta = JsonObject;\ntype FieldEntry = [string, FieldMeta];\n\nexport class Ontology {\n readonly data: JsonObject;\n\n constructor(data: JsonObject) {\n this.data = data;\n }\n\n static fromJson(raw: string | Uint8Array): Ontology {\n const text = typeof raw === \"string\" ? raw : new TextDecoder().decode(raw);\n return new Ontology(JSON.parse(text) as JsonObject);\n }\n\n types(): string[] {\n const types = this.data.types as Record<string, unknown> | undefined;\n return Object.keys(types ?? {}).sort();\n }\n\n composites(): string[] {\n const composites = this.data.composites as Record<string, unknown> | undefined;\n return Object.keys(composites ?? {}).sort();\n }\n\n enums(): string[] {\n const enums = this.data.enums as Record<string, unknown> | undefined;\n return Object.keys(enums ?? {}).sort();\n }\n\n taxonomies(): string[] {\n const taxonomies = this.data.taxonomies as Record<string, unknown> | undefined;\n return Object.keys(taxonomies ?? {}).sort();\n }\n\n private static fieldsOf(container: Record<string, JsonObject>, typeName: string): Record<string, FieldMeta> {\n const entry = container[typeName];\n if (!entry) throw new Error(`Unknown name: ${typeName}`);\n return (entry.fields as Record<string, FieldMeta> | undefined) ?? {};\n }\n\n fieldsFor(typeName: string): Record<string, FieldMeta> {\n const types = (this.data.types ?? {}) as Record<string, JsonObject>;\n const composites = (this.data.composites ?? {}) as Record<string, JsonObject>;\n if (typeName in types) return Ontology.fieldsOf(types, typeName);\n if (typeName in composites) return Ontology.fieldsOf(composites, typeName);\n throw new Error(`${typeName} is not a known entity type or composite`);\n }\n\n static filterFields(\n fields: Record<string, FieldMeta>,\n search?: string | null,\n includeDeprecated = false,\n ): FieldEntry[] {\n const pattern = search ? new RegExp(search, \"i\") : null;\n const out: FieldEntry[] = [];\n for (const [name, meta] of Object.entries(fields)) {\n if (!includeDeprecated && meta.isDeprecated) continue;\n if (pattern && !pattern.test(name)) continue;\n out.push([name, meta]);\n }\n return out;\n }\n\n taxonomyValues(name: string, search?: string | null): string[] {\n const taxonomies = (this.data.taxonomies ?? {}) as Record<string, JsonObject>;\n const tax = taxonomies[name];\n if (!tax) throw new Error(`Unknown taxonomy: ${name}`);\n\n const pattern = search ? new RegExp(search, \"i\") : null;\n const out: string[] = [];\n\n const walk = (node: JsonObject): void => {\n const n = node.name;\n if (typeof n === \"string\" && (!pattern || pattern.test(n))) {\n out.push(n);\n }\n for (const child of (node.children as JsonObject[] | undefined) ?? []) {\n walk(child);\n }\n };\n\n for (const cat of (tax.categories as JsonObject[] | undefined) ?? []) {\n walk(cat);\n }\n return out;\n }\n\n enumValues(name: string): string[] {\n const enums = (this.data.enums ?? {}) as Record<string, JsonObject>;\n const enumEntry = enums[name];\n if (!enumEntry) throw new Error(`Unknown enum: ${name}`);\n return [...((enumEntry.values as string[] | undefined) ?? [])];\n }\n\n findNamed(search: string): string[] {\n const pattern = new RegExp(search, \"i\");\n const found = new Set<string>();\n\n const walk = (node: unknown): void => {\n if (Array.isArray(node)) {\n for (const v of node) walk(v);\n } else if (node && typeof node === \"object\") {\n const obj = node as JsonObject;\n const n = obj.name;\n if (typeof n === \"string\" && pattern.test(n)) found.add(n);\n for (const v of Object.values(obj)) walk(v);\n }\n };\n\n walk(this.data);\n return [...found].sort();\n }\n\n static formatField(name: string, meta: FieldMeta): string {\n let typeName = String(meta.type ?? \"?\");\n if (typeName === \"LinkedEntity\") {\n const le = meta.leType as string[] | undefined;\n if (le?.length) typeName = `LinkedEntity (${le[0]})`;\n }\n const flags: string[] = [];\n if (meta.isList) flags.push(\"isList\");\n if (meta.isComposite) flags.push(\"isComposite\");\n if (meta.isEnum) flags.push(\"isEnum\");\n if (meta.isDeprecated) flags.push(\"DEPRECATED\");\n const suffix = flags.map((f) => ` [${f}]`).join(\"\");\n return `${name}: [${typeName}]${suffix}`;\n }\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\nimport { Ontology } from \"./ontology.js\";\n\nexport interface DqlOptions {\n size?: number;\n from?: number;\n format?: string;\n filter?: string;\n exportspec?: string;\n extra?: Record<string, string>;\n raw?: boolean;\n}\n\nfunction buildDqlParams(\n client: DiffbotClient,\n query: string,\n options: DqlOptions,\n): Record<string, string | number> {\n const params: Record<string, string | number> = {\n token: client.token,\n query,\n size: options.size ?? 10,\n };\n if (options.from) params.from = options.from;\n if (options.format && options.format !== \"json\") params.format = options.format;\n if (options.filter !== undefined) params.filter = options.filter;\n if (options.exportspec !== undefined) params.exportspec = options.exportspec;\n if (options.extra) Object.assign(params, options.extra);\n return params;\n}\n\nexport async function dql(\n client: DiffbotClient,\n query: string,\n options: DqlOptions = {},\n): Promise<JsonObject | Uint8Array> {\n const params = buildDqlParams(client, query, options);\n const response = await client.http.get(client.dqlUrl, { params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n if (options.raw) {\n return new TextEncoder().encode(body);\n }\n return JSON.parse(body) as JsonObject;\n}\n\nexport async function dqlParallel(\n client: DiffbotClient,\n queries: Array<DqlOptions & { query: string }>,\n workers = 8,\n): Promise<Array<JsonObject | Uint8Array>> {\n if (!queries.length) return [];\n\n const limit = Math.min(workers, queries.length);\n const results: Array<JsonObject | Uint8Array> = new Array(queries.length);\n let index = 0;\n\n async function worker(): Promise<void> {\n while (true) {\n const current = index++;\n if (current >= queries.length) return;\n const { query, ...opts } = queries[current]!;\n results[current] = await dql(client, query, opts);\n }\n }\n\n await Promise.all(Array.from({ length: limit }, () => worker()));\n return results;\n}\n\n/** Fetch the raw ontology JSON text. For a parsed, cached `Ontology`, see `OntologyStore`. */\nexport async function dqlFetchOntologyText(client: DiffbotClient): Promise<string> {\n const response = await client.http.get(client.ontologyUrl);\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return body;\n}\n\nexport async function dqlFetchOntology(client: DiffbotClient): Promise<Ontology> {\n return Ontology.fromJson(await dqlFetchOntologyText(client));\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nconst NLP_FIELDS = \"entities,sentiment\";\n\nexport async function entities(\n client: DiffbotClient,\n text: string,\n lang = \"auto\",\n): Promise<JsonObject> {\n const params = { token: client.token, fields: NLP_FIELDS };\n const payload = [{ lang, format: \"plain text\", content: text }];\n const response = await client.http.post(client.nlpUrl, { params, json: payload });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n const data = JSON.parse(body) as JsonObject | JsonObject[];\n return Array.isArray(data) ? (data[0] ?? {}) : data;\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { dqlFetchOntologyText } from \"./kg.js\";\nimport { Ontology } from \"./ontology.js\";\n\nexport interface OntologyStoreOptions {\n /**\n * How long a cached entry should be kept, in seconds. Default 86_400 (24h).\n * The base `OntologyStore` doesn't expire its in-memory cache on its own —\n * an explicit `refresh: true` is the only way to bust it — so this only\n * takes effect in subclasses backed by a store with real expiration, like\n * `KVOntologyStore` (where it becomes the KV entry's `expirationTtl`).\n */\n ttlSeconds?: number;\n}\n\n/**\n * Fetches and caches the Diffbot KG ontology for a client. The base class\n * caches only in memory, for the lifetime of the instance; subclasses\n * override `read`/`write` to back the cache with a durable store (a\n * filesystem, a KV namespace, ...).\n */\nexport class OntologyStore {\n readonly client: DiffbotClient;\n protected readonly ttlSeconds: number;\n private inFlight: Promise<Ontology> | null = null;\n\n constructor(client: DiffbotClient, options: OntologyStoreOptions = {}) {\n this.client = client;\n this.ttlSeconds = options.ttlSeconds ?? 86_400;\n }\n\n /**\n * Resolve the ontology, from cache when possible. Concurrent calls share\n * one in-flight fetch rather than issuing duplicate requests; a rejected\n * fetch clears the in-flight memo so the next call retries instead of\n * replaying the same failure forever.\n */\n load(options: { refresh?: boolean } = {}): Promise<Ontology> {\n if (options.refresh) {\n this.inFlight = null;\n }\n if (!this.inFlight) {\n this.inFlight = this.resolve(options.refresh ?? false).catch((error: unknown) => {\n this.inFlight = null;\n throw error;\n });\n }\n return this.inFlight;\n }\n\n private async resolve(refresh: boolean): Promise<Ontology> {\n if (!refresh) {\n const cached = await this.read();\n if (cached !== undefined) {\n try {\n return Ontology.fromJson(cached);\n } catch {\n /* Corrupt cache entry: fall through to a live fetch below. */\n }\n }\n }\n const text = await dqlFetchOntologyText(this.client);\n await this.write(text);\n return Ontology.fromJson(text);\n }\n\n /** Read the cached ontology text, or `undefined` on a miss. Memory-only by default. */\n protected read(): Promise<string | undefined> {\n return Promise.resolve(undefined);\n }\n\n /** Persist ontology text after a fetch. No-op by default. */\n protected write(_text: string): Promise<void> {\n return Promise.resolve();\n }\n}\n\n/**\n * Structurally typed rather than importing `@cloudflare/workers-types`, so\n * the SDK takes no Cloudflare dependency — a `KVNamespace` binding satisfies\n * this directly.\n */\nexport interface KVLike {\n get(key: string): Promise<string | null>;\n put(key: string, value: string, options?: { expirationTtl?: number }): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\nexport interface KVOntologyStoreOptions extends OntologyStoreOptions {\n /** Default `\"diffbot:ontology:v1\"`. Bump the suffix to force cache invalidation on a schema change. */\n key?: string;\n /**\n * After this many seconds, a cached entry is served immediately while a\n * refresh runs behind it (stale-while-revalidate) instead of being trusted\n * outright. 0 (default) disables SWR — a cached entry is trusted for its\n * full `ttlSeconds`. Should be less than `ttlSeconds`, or the KV entry\n * expires before it is ever considered stale.\n */\n staleAfterSeconds?: number;\n /**\n * TTL on the refresh lock that prevents concurrent refetches (cron, SWR,\n * manual). Default 60s — Cloudflare KV rejects `expirationTtl` below 60.\n */\n lockTtlSeconds?: number;\n /**\n * `ExecutionContext.waitUntil`. Without it, a background stale-while-revalidate\n * refresh is killed as soon as the response is returned, so SWR degrades to a\n * blocking refresh-on-expiry.\n */\n waitUntil?: (promise: Promise<unknown>) => void;\n}\n\n/**\n * KV-backed ontology cache for Cloudflare Workers. Ports the stampede\n * protection and stale-while-revalidate behavior of a production Worker's\n * hand-rolled ontology cache: a short-lived lock key prevents concurrent\n * refreshes from cron, SWR, and a manual refresh all refetching at once, and\n * a `refreshed_at` companion key lets a stale entry be served immediately\n * while a refresh runs in the background.\n */\nexport class KVOntologyStore extends OntologyStore {\n private readonly kv: KVLike;\n private readonly key: string;\n private readonly refreshedAtKey: string;\n private readonly lockKey: string;\n private readonly staleAfterSeconds: number;\n private readonly lockTtlSeconds: number;\n private readonly waitUntil: ((promise: Promise<unknown>) => void) | undefined;\n\n constructor(client: DiffbotClient, kv: KVLike, options: KVOntologyStoreOptions = {}) {\n super(client, options);\n this.kv = kv;\n this.key = options.key ?? \"diffbot:ontology:v1\";\n this.refreshedAtKey = `${this.key}:refreshed_at`;\n this.lockKey = `${this.key}:lock`;\n this.staleAfterSeconds = options.staleAfterSeconds ?? 0;\n this.lockTtlSeconds = options.lockTtlSeconds ?? 60;\n this.waitUntil = options.waitUntil;\n }\n\n override load(options: { refresh?: boolean } = {}): Promise<Ontology> {\n if (!options.refresh && this.staleAfterSeconds > 0) {\n return this.loadWithStaleWhileRevalidate();\n }\n return super.load(options);\n }\n\n private async loadWithStaleWhileRevalidate(): Promise<Ontology> {\n const [cached, refreshedAt] = await Promise.all([\n this.kv.get(this.key),\n this.kv.get(this.refreshedAtKey),\n ]);\n if (cached === null) {\n return super.load();\n }\n\n const age = refreshedAt ? (Date.now() - Number(refreshedAt)) / 1000 : Infinity;\n const isStale = age > this.staleAfterSeconds;\n const ontology = Ontology.fromJson(cached);\n\n if (isStale) {\n const refresh = super.load({ refresh: true }).catch(() => {\n /* Stale value already served; a failed background refresh just retries next time. */\n });\n if (this.waitUntil) {\n this.waitUntil(refresh);\n } else {\n await refresh;\n return super.load();\n }\n }\n\n return ontology;\n }\n\n protected override async read(): Promise<string | undefined> {\n const cached = await this.kv.get(this.key);\n return cached ?? undefined;\n }\n\n protected override async write(text: string): Promise<void> {\n /* Lock prevents concurrent refreshes from all refetching the same large payload. */\n if (await this.kv.get(this.lockKey)) {\n return;\n }\n await this.kv.put(this.lockKey, \"1\", { expirationTtl: this.lockTtlSeconds });\n try {\n await this.kv.put(this.key, text, { expirationTtl: this.ttlSeconds });\n await this.kv.put(this.refreshedAtKey, String(Date.now()), {\n expirationTtl: this.ttlSeconds,\n });\n } finally {\n await this.kv.delete(this.lockKey);\n }\n }\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { ValidationError } from \"./errors.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\n/** How much of each page's matching content the web search returns in `content`. */\nexport type SnippetLength = \"short\" | \"medium\" | \"long\" | \"full\";\n\nexport const SNIPPET_LENGTHS: readonly SnippetLength[] = [\"short\", \"medium\", \"long\", \"full\"];\n\nexport interface WebSearchOptions {\n numResults?: number;\n maxTokens?: number;\n /**\n * `short` keeps a result to ~1-1.5 KB; `long` is the API default; `full` returns the\n * whole stored page and is meant for `url:<URL>` queries. The reranker always chunks,\n * so `full` also sends `rerank=none` and query terms after the URL are ignored.\n */\n snippetLength?: SnippetLength;\n}\n\nexport async function webSearch(\n client: DiffbotClient,\n text: string,\n options: WebSearchOptions = {},\n): Promise<JsonObject> {\n const headers = { Authorization: `Bearer ${client.token}` };\n const params: Record<string, string | number> = { text };\n if (options.numResults !== undefined) params.size = options.numResults;\n if (options.maxTokens !== undefined) params.maxTokens = options.maxTokens;\n if (options.snippetLength !== undefined) {\n const length = options.snippetLength.toLowerCase() as SnippetLength;\n if (!SNIPPET_LENGTHS.includes(length)) {\n throw new ValidationError(\n `snippetLength must be one of ${SNIPPET_LENGTHS.join(\", \")}; got ${JSON.stringify(options.snippetLength)}`,\n );\n }\n params.snippetLength = length.toUpperCase();\n if (length === \"full\") params.rerank = \"none\";\n }\n\n const response = await client.http.get(client.webSearchUrl, { headers, params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return JSON.parse(body) as JsonObject;\n}\n"],"mappings":"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","names":["CrawlEventType"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -28,6 +28,8 @@ interface DiffbotClientOptions {
|
|
|
28
28
|
crawlerUrl?: string;
|
|
29
29
|
webSearchUrl?: string;
|
|
30
30
|
nlpUrl?: string;
|
|
31
|
+
dqlUrl?: string;
|
|
32
|
+
ontologyUrl?: string;
|
|
31
33
|
fetch?: FetchFn;
|
|
32
34
|
}
|
|
33
35
|
declare class DiffbotClient {
|
|
@@ -37,14 +39,21 @@ declare class DiffbotClient {
|
|
|
37
39
|
readonly crawlerUrl: string;
|
|
38
40
|
readonly webSearchUrl: string;
|
|
39
41
|
readonly nlpUrl: string;
|
|
42
|
+
readonly dqlUrl: string;
|
|
43
|
+
readonly ontologyUrl: string;
|
|
40
44
|
readonly http: HttpClient;
|
|
41
45
|
constructor(options: DiffbotClientOptions);
|
|
42
46
|
close(): Promise<void>;
|
|
43
47
|
[Symbol.asyncDispose](): Promise<void>;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
type TokenSource = object;
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a Diffbot API token from an explicit arg, then a Workers-style
|
|
53
|
+
* `env` object, then `process.env`. Does not touch the filesystem — for a
|
|
54
|
+
* credentials-file fallback, use `resolveToken` from `@diffbot/typescript/node`.
|
|
55
|
+
*/
|
|
56
|
+
declare function resolveTokenFromEnv(token?: string | null, env?: TokenSource): string;
|
|
48
57
|
|
|
49
58
|
type JsonObject = Record<string, unknown>;
|
|
50
59
|
|
|
@@ -54,7 +63,46 @@ interface ChatMessage {
|
|
|
54
63
|
role: string;
|
|
55
64
|
content: string;
|
|
56
65
|
}
|
|
57
|
-
|
|
66
|
+
/** `response_format` types accepted by the Diffbot LLM endpoint. */
|
|
67
|
+
declare const RESPONSE_FORMAT_TYPES: readonly ["text", "json_object", "json_schema"];
|
|
68
|
+
type ResponseFormatType = (typeof RESPONSE_FORMAT_TYPES)[number];
|
|
69
|
+
interface ResponseFormat {
|
|
70
|
+
type: ResponseFormatType;
|
|
71
|
+
json_schema?: {
|
|
72
|
+
name?: string;
|
|
73
|
+
schema: JsonObject;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
interface AskOptions {
|
|
77
|
+
/**
|
|
78
|
+
* Constrain the output, e.g. `{ type: "json_object" }` or `jsonSchemaFormat(schema)`.
|
|
79
|
+
* Prefer a schema: `json_object` applies no server-side grammar.
|
|
80
|
+
*/
|
|
81
|
+
responseFormat?: ResponseFormat;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build a `response_format` that constrains output to `schema`. The endpoint requires
|
|
85
|
+
* the schema nested under `json_schema.schema`; anywhere else is ignored server-side
|
|
86
|
+
* without an error, so prefer this helper over hand-building the object.
|
|
87
|
+
*/
|
|
88
|
+
declare function jsonSchemaFormat(schema: JsonObject, name?: string): ResponseFormat;
|
|
89
|
+
/** Parse the model's final answer as JSON, tolerating think blocks and fences. */
|
|
90
|
+
declare function extractJson(text: string): unknown;
|
|
91
|
+
/**
|
|
92
|
+
* Schema used when the caller wants JSON but has no shape in mind. This goes through
|
|
93
|
+
* the json_schema path rather than `{ type: "json_object" }` on purpose: json_object
|
|
94
|
+
* applies no server-side grammar, so the RAG loop's internal <functioncall> JSON
|
|
95
|
+
* satisfies it and gets returned as the final answer. That is reproducible whenever
|
|
96
|
+
* the request carries a system message.
|
|
97
|
+
*/
|
|
98
|
+
declare const ANY_OBJECT_SCHEMA: JsonObject;
|
|
99
|
+
declare function ask(client: DiffbotClient, messages: ChatMessage[], options?: AskOptions): AsyncGenerator<string>;
|
|
100
|
+
/**
|
|
101
|
+
* Ask the Diffbot LLM and return the answer parsed as JSON. With `schema` (a JSON Schema
|
|
102
|
+
* object) the model is constrained to it by grammar; without one it falls back to
|
|
103
|
+
* unconstrained JSON output. Pass `responseFormat` instead of `schema` for full control.
|
|
104
|
+
*/
|
|
105
|
+
declare function askJson<T = unknown>(client: DiffbotClient, messages: ChatMessage[], schema?: JsonObject, options?: AskOptions): Promise<T>;
|
|
58
106
|
|
|
59
107
|
declare enum CrawlEventType {
|
|
60
108
|
JobCreated = "job_created",
|
|
@@ -92,7 +140,6 @@ declare class Ontology {
|
|
|
92
140
|
readonly data: JsonObject;
|
|
93
141
|
constructor(data: JsonObject);
|
|
94
142
|
static fromJson(raw: string | Uint8Array): Ontology;
|
|
95
|
-
static fromPath(path: string): Promise<Ontology>;
|
|
96
143
|
types(): string[];
|
|
97
144
|
composites(): string[];
|
|
98
145
|
enums(): string[];
|
|
@@ -119,15 +166,122 @@ declare function dql(client: DiffbotClient, query: string, options?: DqlOptions)
|
|
|
119
166
|
declare function dqlParallel(client: DiffbotClient, queries: Array<DqlOptions & {
|
|
120
167
|
query: string;
|
|
121
168
|
}>, workers?: number): Promise<Array<JsonObject | Uint8Array>>;
|
|
122
|
-
|
|
169
|
+
/** Fetch the raw ontology JSON text. For a parsed, cached `Ontology`, see `OntologyStore`. */
|
|
170
|
+
declare function dqlFetchOntologyText(client: DiffbotClient): Promise<string>;
|
|
123
171
|
declare function dqlFetchOntology(client: DiffbotClient): Promise<Ontology>;
|
|
124
172
|
|
|
125
173
|
declare function entities(client: DiffbotClient, text: string, lang?: string): Promise<JsonObject>;
|
|
126
174
|
|
|
127
|
-
|
|
175
|
+
interface OntologyStoreOptions {
|
|
176
|
+
/**
|
|
177
|
+
* How long a cached entry should be kept, in seconds. Default 86_400 (24h).
|
|
178
|
+
* The base `OntologyStore` doesn't expire its in-memory cache on its own —
|
|
179
|
+
* an explicit `refresh: true` is the only way to bust it — so this only
|
|
180
|
+
* takes effect in subclasses backed by a store with real expiration, like
|
|
181
|
+
* `KVOntologyStore` (where it becomes the KV entry's `expirationTtl`).
|
|
182
|
+
*/
|
|
183
|
+
ttlSeconds?: number;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Fetches and caches the Diffbot KG ontology for a client. The base class
|
|
187
|
+
* caches only in memory, for the lifetime of the instance; subclasses
|
|
188
|
+
* override `read`/`write` to back the cache with a durable store (a
|
|
189
|
+
* filesystem, a KV namespace, ...).
|
|
190
|
+
*/
|
|
191
|
+
declare class OntologyStore {
|
|
192
|
+
readonly client: DiffbotClient;
|
|
193
|
+
protected readonly ttlSeconds: number;
|
|
194
|
+
private inFlight;
|
|
195
|
+
constructor(client: DiffbotClient, options?: OntologyStoreOptions);
|
|
196
|
+
/**
|
|
197
|
+
* Resolve the ontology, from cache when possible. Concurrent calls share
|
|
198
|
+
* one in-flight fetch rather than issuing duplicate requests; a rejected
|
|
199
|
+
* fetch clears the in-flight memo so the next call retries instead of
|
|
200
|
+
* replaying the same failure forever.
|
|
201
|
+
*/
|
|
202
|
+
load(options?: {
|
|
203
|
+
refresh?: boolean;
|
|
204
|
+
}): Promise<Ontology>;
|
|
205
|
+
private resolve;
|
|
206
|
+
/** Read the cached ontology text, or `undefined` on a miss. Memory-only by default. */
|
|
207
|
+
protected read(): Promise<string | undefined>;
|
|
208
|
+
/** Persist ontology text after a fetch. No-op by default. */
|
|
209
|
+
protected write(_text: string): Promise<void>;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Structurally typed rather than importing `@cloudflare/workers-types`, so
|
|
213
|
+
* the SDK takes no Cloudflare dependency — a `KVNamespace` binding satisfies
|
|
214
|
+
* this directly.
|
|
215
|
+
*/
|
|
216
|
+
interface KVLike {
|
|
217
|
+
get(key: string): Promise<string | null>;
|
|
218
|
+
put(key: string, value: string, options?: {
|
|
219
|
+
expirationTtl?: number;
|
|
220
|
+
}): Promise<void>;
|
|
221
|
+
delete(key: string): Promise<void>;
|
|
222
|
+
}
|
|
223
|
+
interface KVOntologyStoreOptions extends OntologyStoreOptions {
|
|
224
|
+
/** Default `"diffbot:ontology:v1"`. Bump the suffix to force cache invalidation on a schema change. */
|
|
225
|
+
key?: string;
|
|
226
|
+
/**
|
|
227
|
+
* After this many seconds, a cached entry is served immediately while a
|
|
228
|
+
* refresh runs behind it (stale-while-revalidate) instead of being trusted
|
|
229
|
+
* outright. 0 (default) disables SWR — a cached entry is trusted for its
|
|
230
|
+
* full `ttlSeconds`. Should be less than `ttlSeconds`, or the KV entry
|
|
231
|
+
* expires before it is ever considered stale.
|
|
232
|
+
*/
|
|
233
|
+
staleAfterSeconds?: number;
|
|
234
|
+
/**
|
|
235
|
+
* TTL on the refresh lock that prevents concurrent refetches (cron, SWR,
|
|
236
|
+
* manual). Default 60s — Cloudflare KV rejects `expirationTtl` below 60.
|
|
237
|
+
*/
|
|
238
|
+
lockTtlSeconds?: number;
|
|
239
|
+
/**
|
|
240
|
+
* `ExecutionContext.waitUntil`. Without it, a background stale-while-revalidate
|
|
241
|
+
* refresh is killed as soon as the response is returned, so SWR degrades to a
|
|
242
|
+
* blocking refresh-on-expiry.
|
|
243
|
+
*/
|
|
244
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* KV-backed ontology cache for Cloudflare Workers. Ports the stampede
|
|
248
|
+
* protection and stale-while-revalidate behavior of a production Worker's
|
|
249
|
+
* hand-rolled ontology cache: a short-lived lock key prevents concurrent
|
|
250
|
+
* refreshes from cron, SWR, and a manual refresh all refetching at once, and
|
|
251
|
+
* a `refreshed_at` companion key lets a stale entry be served immediately
|
|
252
|
+
* while a refresh runs in the background.
|
|
253
|
+
*/
|
|
254
|
+
declare class KVOntologyStore extends OntologyStore {
|
|
255
|
+
private readonly kv;
|
|
256
|
+
private readonly key;
|
|
257
|
+
private readonly refreshedAtKey;
|
|
258
|
+
private readonly lockKey;
|
|
259
|
+
private readonly staleAfterSeconds;
|
|
260
|
+
private readonly lockTtlSeconds;
|
|
261
|
+
private readonly waitUntil;
|
|
262
|
+
constructor(client: DiffbotClient, kv: KVLike, options?: KVOntologyStoreOptions);
|
|
263
|
+
load(options?: {
|
|
264
|
+
refresh?: boolean;
|
|
265
|
+
}): Promise<Ontology>;
|
|
266
|
+
private loadWithStaleWhileRevalidate;
|
|
267
|
+
protected read(): Promise<string | undefined>;
|
|
268
|
+
protected write(text: string): Promise<void>;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** How much of each page's matching content the web search returns in `content`. */
|
|
272
|
+
type SnippetLength = "short" | "medium" | "long" | "full";
|
|
273
|
+
declare const SNIPPET_LENGTHS: readonly SnippetLength[];
|
|
274
|
+
interface WebSearchOptions {
|
|
128
275
|
numResults?: number;
|
|
129
276
|
maxTokens?: number;
|
|
130
|
-
|
|
277
|
+
/**
|
|
278
|
+
* `short` keeps a result to ~1-1.5 KB; `long` is the API default; `full` returns the
|
|
279
|
+
* whole stored page and is meant for `url:<URL>` queries. The reranker always chunks,
|
|
280
|
+
* so `full` also sends `rerank=none` and query terms after the URL are ignored.
|
|
281
|
+
*/
|
|
282
|
+
snippetLength?: SnippetLength;
|
|
283
|
+
}
|
|
284
|
+
declare function webSearch(client: DiffbotClient, text: string, options?: WebSearchOptions): Promise<JsonObject>;
|
|
131
285
|
|
|
132
286
|
/** Exception hierarchy for the Diffbot SDK. */
|
|
133
287
|
declare class DiffbotError extends Error {
|
|
@@ -158,6 +312,6 @@ declare class ExtractionError extends DiffbotError {
|
|
|
158
312
|
constructor(errorCode: number, error: string);
|
|
159
313
|
}
|
|
160
314
|
|
|
161
|
-
declare const VERSION = "0.
|
|
315
|
+
declare const VERSION = "0.3.0";
|
|
162
316
|
|
|
163
|
-
export { APIError, AuthError, type ChatMessage, type CrawlEvent, CrawlEventType, type CrawlOptions, DiffbotClient, type DiffbotClientOptions, DiffbotError, type DqlOptions, ExtractionError, type FetchFn, type JsonObject, Ontology, RateLimitError, VERSION, ValidationError, ask, crawl, crawlDeleteJob, crawlGetJob, crawlListJobs, dql, dqlFetchOntology,
|
|
317
|
+
export { ANY_OBJECT_SCHEMA, APIError, type AskOptions, AuthError, type ChatMessage, type CrawlEvent, CrawlEventType, type CrawlOptions, DiffbotClient, type DiffbotClientOptions, DiffbotError, type DqlOptions, ExtractionError, type FetchFn, type JsonObject, type KVLike, KVOntologyStore, type KVOntologyStoreOptions, Ontology, OntologyStore, type OntologyStoreOptions, RESPONSE_FORMAT_TYPES, RateLimitError, type ResponseFormat, type ResponseFormatType, SNIPPET_LENGTHS, type SnippetLength, type TokenSource, VERSION, ValidationError, type WebSearchOptions, ask, askJson, crawl, crawlDeleteJob, crawlGetJob, crawlListJobs, dql, dqlFetchOntology, dqlFetchOntologyText, dqlParallel, entities, extract, extractJson, jsonSchemaFormat, resolveTokenFromEnv, webSearch };
|