@diffbot/typescript 0.2.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 CHANGED
@@ -50,7 +50,7 @@ settings from the client you hand it.
50
50
  | `fetch` | global `fetch` | all |
51
51
  | `analyzeUrl` | `https://api.diffbot.com/v3` | `extract` |
52
52
  | `crawlerUrl` | `https://api.diffbot.com/v3/crawl` | `crawl`, `crawlListJobs`, `crawlGetJob`, `crawlDeleteJob` |
53
- | `llmUrl` | `https://llm.diffbot.com/rag/v1/chat/completions` | `ask` |
53
+ | `llmUrl` | `https://llm.diffbot.com/rag/v1/chat/completions` | `ask`, `askJson` |
54
54
  | `webSearchUrl` | `https://llm.diffbot.com/api/v1/web_search` | `webSearch` |
55
55
  | `nlpUrl` | `https://nl.diffbot.com/v1/` | `entities` |
56
56
  | `dqlUrl` | `https://kg.diffbot.com/kg/v3/dql` | `dql`, `dqlParallel` |
@@ -101,6 +101,49 @@ for await (const chunk of ask(db, [{ role: "user", content: "What's the capital
101
101
  }
102
102
  ```
103
103
 
104
+ ### Structured output
105
+
106
+ Pass a JSON Schema to constrain the answer. The model is held to the schema by a grammar
107
+ during decoding, so the result parses reliably even though the answer is retrieved live
108
+ from the web.
109
+
110
+ ```typescript
111
+ import { askJson } from "@diffbot/typescript";
112
+
113
+ const schema = {
114
+ type: "object",
115
+ properties: { country: { type: "string" }, capital: { type: "string" } },
116
+ required: ["country", "capital"],
117
+ };
118
+ const answer = await askJson<{ country: string; capital: string }>(
119
+ db,
120
+ [{ role: "user", content: "What's the capital of France?" }],
121
+ schema,
122
+ );
123
+ console.log(answer.capital);
124
+ ```
125
+
126
+ Omit the schema to let the model choose the shape, or use `ask` with `responseFormat` to
127
+ stream a constrained answer:
128
+
129
+ ```typescript
130
+ import { ask, askJson, jsonSchemaFormat } from "@diffbot/typescript";
131
+
132
+ const answer = await askJson(db, [{ role: "user", content: "What's the capital of France?" }]);
133
+
134
+ for await (const chunk of ask(db, [{ role: "user", content: "What's the capital of France?" }], {
135
+ responseFormat: jsonSchemaFormat(schema),
136
+ })) {
137
+ process.stdout.write(chunk);
138
+ }
139
+ ```
140
+
141
+ > **Avoid `responseFormat: { type: "json_object" }`.** The endpoint accepts it, but applies
142
+ > no grammar to it: the RAG loop's internal tool call is itself a JSON object, so it can be
143
+ > returned as the final answer. This is reproducible whenever the request includes a system
144
+ > message. `askJson` therefore defaults to a permissive JSON Schema instead, and throws
145
+ > `ValidationError` if it ever sees a tool call come back.
146
+
104
147
  ### Crawl a site
105
148
 
106
149
  ```typescript
@@ -128,6 +171,13 @@ const results = await webSearch(db, "diffbot knowledge graph");
128
171
  for (const r of results.search_results as Array<Record<string, unknown>>) {
129
172
  console.log(r.score, r.title, r.pageUrl);
130
173
  }
174
+
175
+ // snippetLength controls how much of each page comes back in "content":
176
+ // "short" (~1-1.5 KB per result), "medium", "long" (default), or "full"
177
+ const brief = await webSearch(db, "diffbot knowledge graph", { numResults: 5, snippetLength: "short" });
178
+
179
+ // "full" with a url: query returns the whole stored page
180
+ const page = await webSearch(db, "url:https://en.wikipedia.org/wiki/Knowledge_graph", { snippetLength: "full" });
131
181
  ```
132
182
 
133
183
  ### Caching the Knowledge Graph ontology
@@ -233,7 +283,10 @@ in CI against workerd with `compatibility_flags: []`.
233
283
  | `dql_parallel()` | `dqlParallel()` |
234
284
  | `dql_fetch_ontology()` | `dqlFetchOntology()` |
235
285
  | `dql_refresh_ontology()` | `new OntologyStore(db).load({ refresh: true })` (or `FileOntologyStore` from `@diffbot/typescript/node`) |
236
- | `web_search()` | `webSearch()` |
286
+ | `web_search(snippet_length=...)` | `webSearch(db, text, { snippetLength })` |
287
+ | `ask(response_format=...)` | `ask(db, messages, { responseFormat })` |
288
+ | `ask_json()` | `askJson()` |
289
+ | `json_schema_format()` | `jsonSchemaFormat()` |
237
290
 
238
291
  ## Development
239
292
 
package/dist/index.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ ANY_OBJECT_SCHEMA: () => ANY_OBJECT_SCHEMA,
23
24
  APIError: () => APIError,
24
25
  AuthError: () => AuthError,
25
26
  CrawlEventType: () => CrawlEventType,
@@ -29,10 +30,13 @@ __export(index_exports, {
29
30
  KVOntologyStore: () => KVOntologyStore,
30
31
  Ontology: () => Ontology,
31
32
  OntologyStore: () => OntologyStore,
33
+ RESPONSE_FORMAT_TYPES: () => RESPONSE_FORMAT_TYPES,
32
34
  RateLimitError: () => RateLimitError,
35
+ SNIPPET_LENGTHS: () => SNIPPET_LENGTHS,
33
36
  VERSION: () => VERSION,
34
37
  ValidationError: () => ValidationError,
35
38
  ask: () => ask,
39
+ askJson: () => askJson,
36
40
  crawl: () => crawl,
37
41
  crawlDeleteJob: () => crawlDeleteJob,
38
42
  crawlGetJob: () => crawlGetJob,
@@ -43,13 +47,15 @@ __export(index_exports, {
43
47
  dqlParallel: () => dqlParallel,
44
48
  entities: () => entities,
45
49
  extract: () => extract,
50
+ extractJson: () => extractJson,
51
+ jsonSchemaFormat: () => jsonSchemaFormat,
46
52
  resolveTokenFromEnv: () => resolveTokenFromEnv,
47
53
  webSearch: () => webSearch
48
54
  });
49
55
  module.exports = __toCommonJS(index_exports);
50
56
 
51
57
  // src/constants.ts
52
- var VERSION = "0.2.0";
58
+ var VERSION = "0.3.0";
53
59
  var DEFAULT_TIMEOUT = 3e4;
54
60
  var EXTRACT_BASE = "https://api.diffbot.com/v3";
55
61
  var CRAWL_BASE = "https://api.diffbot.com/v3/crawl";
@@ -271,6 +277,80 @@ async function extract(client, url, api = "analyze", fmt = "markdown") {
271
277
  }
272
278
 
273
279
  // src/ask.ts
280
+ var MODEL = "diffbot-small-xl";
281
+ var RESPONSE_FORMAT_TYPES = ["text", "json_object", "json_schema"];
282
+ function jsonSchemaFormat(schema, name = "response") {
283
+ if (schema === null || typeof schema !== "object" || Array.isArray(schema)) {
284
+ throw new ValidationError("schema must be a JSON Schema object");
285
+ }
286
+ return { type: "json_schema", json_schema: { name, schema } };
287
+ }
288
+ function validateResponseFormat(responseFormat) {
289
+ if (responseFormat === void 0) return;
290
+ if (responseFormat === null || typeof responseFormat !== "object" || Array.isArray(responseFormat)) {
291
+ throw new ValidationError("responseFormat must be an object");
292
+ }
293
+ const fmtType = responseFormat.type ?? "text";
294
+ if (!RESPONSE_FORMAT_TYPES.includes(fmtType)) {
295
+ throw new ValidationError(
296
+ `responseFormat type must be one of ${RESPONSE_FORMAT_TYPES.join(", ")}; got ${JSON.stringify(fmtType)}`
297
+ );
298
+ }
299
+ if (fmtType === "json_schema") {
300
+ const jsonSchema = responseFormat.json_schema;
301
+ if (jsonSchema === null || typeof jsonSchema !== "object" || !("schema" in jsonSchema)) {
302
+ throw new ValidationError(
303
+ 'responseFormat { type: "json_schema" } requires the schema nested as { json_schema: { schema: {...} } }. Without it the server returns 200 and ignores the constraint. Use jsonSchemaFormat(schema) to build it.'
304
+ );
305
+ }
306
+ }
307
+ }
308
+ var THINK_BLOCK = /<think>[\s\S]*?<\/think>/g;
309
+ var JSON_FENCE = /^```(?:json)?\s*|\s*```$/gm;
310
+ function extractJson(text) {
311
+ let cleaned = text.replace(THINK_BLOCK, "").trim();
312
+ cleaned = cleaned.replace(JSON_FENCE, "").trim();
313
+ try {
314
+ return JSON.parse(cleaned);
315
+ } catch {
316
+ }
317
+ const spans = [];
318
+ for (const [opener, closer] of [
319
+ ["{", "}"],
320
+ ["[", "]"]
321
+ ]) {
322
+ const start = cleaned.indexOf(opener);
323
+ const end = cleaned.lastIndexOf(closer);
324
+ if (start !== -1 && end > start) spans.push([start, cleaned.slice(start, end + 1)]);
325
+ }
326
+ spans.sort((a, b) => a[0] - b[0]);
327
+ for (const [, span] of spans) {
328
+ try {
329
+ return JSON.parse(span);
330
+ } catch {
331
+ continue;
332
+ }
333
+ }
334
+ throw new ValidationError(
335
+ `could not parse JSON from the model response: ${JSON.stringify(text.slice(0, 200))}`
336
+ );
337
+ }
338
+ var ANY_OBJECT_SCHEMA = { type: "object" };
339
+ function resolveFormat(schema, responseFormat) {
340
+ if (schema !== void 0 && responseFormat !== void 0) {
341
+ throw new ValidationError("pass either schema or responseFormat, not both");
342
+ }
343
+ if (responseFormat !== void 0) return responseFormat;
344
+ return jsonSchemaFormat(schema ?? ANY_OBJECT_SCHEMA);
345
+ }
346
+ function checkToolCallLeak(parsed) {
347
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.name === "functioncall" && "arguments" in parsed) {
348
+ throw new ValidationError(
349
+ 'the model returned its internal tool call instead of an answer; this happens with responseFormat { type: "json_object" } because the server applies no grammar to it. Pass a schema instead.'
350
+ );
351
+ }
352
+ return parsed;
353
+ }
274
354
  function parseChunk(line) {
275
355
  try {
276
356
  const chunk = JSON.parse(line.replace(/^data: /, ""));
@@ -301,9 +381,11 @@ async function* linesFromStream(body) {
301
381
  }
302
382
  if (buffer) yield buffer;
303
383
  }
304
- async function* ask(client, messages) {
384
+ async function* ask(client, messages, options = {}) {
385
+ validateResponseFormat(options.responseFormat);
305
386
  const headers = { Authorization: `Bearer ${client.token}` };
306
- const payload = { model: "diffbot-small-xl", messages, stream: true };
387
+ const payload = { model: MODEL, messages, stream: true };
388
+ if (options.responseFormat !== void 0) payload.response_format = options.responseFormat;
307
389
  const response = await client.http.post(client.llmUrl, { headers, json: payload });
308
390
  if (!response.ok) {
309
391
  const body = await readBodyText(response);
@@ -323,6 +405,12 @@ async function* ask(client, messages) {
323
405
  if (content) yield content;
324
406
  }
325
407
  }
408
+ async function askJson(client, messages, schema, options = {}) {
409
+ const responseFormat = resolveFormat(schema, options.responseFormat);
410
+ let text = "";
411
+ for await (const chunk of ask(client, messages, { responseFormat })) text += chunk;
412
+ return checkToolCallLeak(extractJson(text));
413
+ }
326
414
 
327
415
  // src/crawl.ts
328
416
  var CrawlEventType = /* @__PURE__ */ ((CrawlEventType2) => {
@@ -748,11 +836,22 @@ var KVOntologyStore = class extends OntologyStore {
748
836
  };
749
837
 
750
838
  // src/web-search.ts
839
+ var SNIPPET_LENGTHS = ["short", "medium", "long", "full"];
751
840
  async function webSearch(client, text, options = {}) {
752
841
  const headers = { Authorization: `Bearer ${client.token}` };
753
842
  const params = { text };
754
843
  if (options.numResults !== void 0) params.size = options.numResults;
755
844
  if (options.maxTokens !== void 0) params.maxTokens = options.maxTokens;
845
+ if (options.snippetLength !== void 0) {
846
+ const length = options.snippetLength.toLowerCase();
847
+ if (!SNIPPET_LENGTHS.includes(length)) {
848
+ throw new ValidationError(
849
+ `snippetLength must be one of ${SNIPPET_LENGTHS.join(", ")}; got ${JSON.stringify(options.snippetLength)}`
850
+ );
851
+ }
852
+ params.snippetLength = length.toUpperCase();
853
+ if (length === "full") params.rerank = "none";
854
+ }
756
855
  const response = await client.http.get(client.webSearchUrl, { headers, params });
757
856
  const body = await readBodyText(response);
758
857
  raiseForStatus(response, body);
@@ -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/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 { 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 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 } 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.2.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 { 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 { 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 { 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"]}
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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,UAAU;AAEhB,IAAM,kBAAkB;AAExB,IAAM,eAAe;AACrB,IAAM,aAAa;AACnB,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AACxB,IAAM,WAAW;AACjB,IAAM,kBAAkB;AACxB,IAAM,uBAAuB;AAE7B,IAAM,gBAAgB;;;ACVtB,IAAM,eAAN,cAA2B,MAAM;AAAA,EAC7B,OAAO;AAClB;AAEO,IAAM,kBAAN,cAA8B,aAAa;AAAA,EACvC,OAAO;AAClB;AAEO,IAAM,WAAN,cAAuB,aAAa;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,YAAoB,MAAc;AAC5C,QAAI;AACJ,QAAI;AACJ,QAAI;AACF,YAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,mBAAa,KAAK;AAClB,kBAAY,KAAK;AAAA,IACnB,QAAQ;AAAA,IAER;AACA,UAAM,UAAU,eAAe,KAAK,SAAS,MAAM,GAAG,KAAK,MAAM,GAAG,GAAG,CAAC,QAAQ;AAChF,UAAM,qBAAqB,UAAU,KAAK,OAAO,EAAE;AACnD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,YAAY;AAAA,EACnB;AAEF;AAEO,IAAM,YAAN,cAAwB,SAAS;AAAA,EAC7B,OAAO;AAClB;AAEO,IAAM,iBAAN,cAA6B,SAAS;AAAA,EAC3C;AAAA,EACS,OAAO;AAAA,EAEhB,YAAY,YAAoB,MAAc,YAA4B;AACxE,UAAM,YAAY,IAAI;AACtB,SAAK,aAAa,cAAc;AAAA,EAClC;AACF;AAEO,IAAM,kBAAN,cAA8B,aAAa;AAAA,EAChD;AAAA,EACA;AAAA,EACS,OAAO;AAAA,EAEhB,YAAY,WAAmB,OAAe;AAC5C,UAAM,4BAA4B,SAAS,KAAK,KAAK,EAAE;AACvD,SAAK,YAAY;AACjB,SAAK,QAAQ;AAAA,EACf;AACF;;;AClDO,IAAM,aAAN,MAAiB;AAAA,EAGtB,YACmB,SACA,WACR,WACT;AAHiB;AACA;AACR;AAAA,EACR;AAAA,EAHgB;AAAA,EACA;AAAA,EACR;AAAA,EALH,SAAS;AAAA,EAQjB,MAAM,IAAI,KAAa,UAA8B,CAAC,GAAsB;AAC1E,WAAO,KAAK,QAAQ,KAAK,EAAE,GAAG,SAAS,QAAQ,MAAM,CAAC;AAAA,EACxD;AAAA,EAEA,MAAM,KAAK,KAAa,UAA8B,CAAC,GAAsB;AAC3E,WAAO,KAAK,QAAQ,KAAK,EAAE,GAAG,SAAS,QAAQ,OAAO,CAAC;AAAA,EACzD;AAAA,EAEA,MAAM,QAAQ,KAAa,UAAoD,CAAC,GAAsB;AACpG,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AAEA,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,QAAQ,QAAQ;AAClB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,MAAM,GAAG;AACzD,YAAI,UAAU,QAAW;AACvB,iBAAO,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,YAAQ,IAAI,cAAc,KAAK,SAAS;AACxC,QAAI,QAAQ,SAAS,QAAW;AAC9B,cAAQ,IAAI,gBAAgB,kBAAkB;AAAA,IAChD;AAEA,UAAM,OAAoB;AAAA,MACxB,QAAQ,QAAQ,UAAU;AAAA,MAC1B;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB,QAAQ,YAAY,QAAQ,KAAK,SAAS;AAAA,IAC5C;AACA,QAAI,QAAQ,SAAS,QAAW;AAC9B,WAAK,OAAO,KAAK,UAAU,QAAQ,IAAI;AAAA,IACzC;AAEA,WAAO,KAAK,QAAQ,OAAO,SAAS,GAAG,IAAI;AAAA,EAC7C;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AACF;AAEO,SAAS,eAAe,UAAoB,UAAyB;AAC1E,MAAI,SAAS,IAAI;AACf;AAAA,EACF;AACA,QAAM,SAAS,SAAS;AACxB,QAAM,OAAO,YAAY;AACzB,MAAI,WAAW,OAAO,WAAW,KAAK;AACpC,UAAM,IAAI,UAAU,QAAQ,IAAI;AAAA,EAClC;AACA,MAAI,WAAW,KAAK;AAClB,UAAM,IAAI,eAAe,QAAQ,MAAM,SAAS,QAAQ,IAAI,aAAa,CAAC;AAAA,EAC5E;AACA,QAAM,IAAI,SAAS,QAAQ,IAAI;AACjC;AAEA,eAAsB,aAAa,UAAqC;AACtE,SAAO,SAAS,KAAK;AACvB;;;AC5DO,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAA+B;AACzC,QAAI,CAAC,QAAQ,OAAO;AAClB,YAAM,IAAI,gBAAgB,mBAAmB;AAAA,IAC/C;AACA,SAAK,QAAQ,QAAQ;AACrB,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,OAAO,IAAI;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB,QAAQ,WAAW;AAAA,MACnB,sBAAsB,OAAO;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,KAAK,MAAM;AAAA,EACxB;AAAA,EAEA,OAAO,OAAO,YAAY,IAAmB;AAC3C,UAAM,KAAK,MAAM;AAAA,EACnB;AACF;;;ACpDA,SAAS,SAAS,KAAsC;AACtD,QAAM,UAAW,MAA8C,aAAa;AAC5E,MAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,GAAG;AACjD,WAAO,QAAQ,KAAK;AAAA,EACtB;AAOA,QAAM,OAAQ,WAA0E;AACxF,QAAM,cAAc,MAAM,MAAM,aAAa;AAC7C,SAAO,aAAa,KAAK,KAAK;AAChC;AAOO,SAAS,oBAAoB,OAAuB,KAA2B;AACpF,MAAI,OAAO,KAAK,GAAG;AACjB,WAAO,MAAM,KAAK;AAAA,EACpB;AACA,SAAO,SAAS,GAAG;AACrB;;;ACjCA,SAAS,YAAY,QAAuB,KAAa,KAAa;AACpE,QAAM,SAA0C;AAAA,IAC9C,OAAO,OAAO;AAAA,IACd;AAAA,IACA,SAAS;AAAA,EACX;AACA,MAAI,QAAQ,YAAY;AACtB,WAAO,OAAO;AAAA,EAChB;AACA,SAAO;AACT;AAEA,SAAS,cAAc,MAA8B;AACnD,MAAI,eAAe,MAAM;AACvB,UAAM,IAAI;AAAA,MACR,OAAO,KAAK,SAAS;AAAA,MACrB,OAAO,KAAK,SAAS,EAAE;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aAAa,KAAqB;AACzC,SAAO,IAAI,WAAW,MAAM,IAAI,MAAM,WAAW,GAAG;AACtD;AAEA,eAAsB,QACpB,QACA,KACA,MAAM,WACN,MAAM,YACe;AACrB,QAAM,aAAa,aAAa,GAAG;AACnC,QAAM,WAAW,MAAM,OAAO,KAAK,IAAI,GAAG,OAAO,UAAU,IAAI,GAAG,IAAI;AAAA,IACpE,QAAQ,YAAY,QAAQ,YAAY,GAAG;AAAA,EAC7C,CAAC;AACD,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAC7B,SAAO,cAAc,KAAK,MAAM,IAAI,CAAe;AACrD;;;AClCA,IAAM,QAAQ;AAGP,IAAM,wBAAwB,CAAC,QAAQ,eAAe,aAAa;AAqBnE,SAAS,iBAAiB,QAAoB,OAAO,YAA4B;AACtF,MAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAC1E,UAAM,IAAI,gBAAgB,qCAAqC;AAAA,EACjE;AACA,SAAO,EAAE,MAAM,eAAe,aAAa,EAAE,MAAM,OAAO,EAAE;AAC9D;AAGA,SAAS,uBAAuB,gBAAkD;AAChF,MAAI,mBAAmB,OAAW;AAClC,MAAI,mBAAmB,QAAQ,OAAO,mBAAmB,YAAY,MAAM,QAAQ,cAAc,GAAG;AAClG,UAAM,IAAI,gBAAgB,kCAAkC;AAAA,EAC9D;AACA,QAAM,UAAU,eAAe,QAAQ;AACvC,MAAI,CAAE,sBAA4C,SAAS,OAAO,GAAG;AACnE,UAAM,IAAI;AAAA,MACR,sCAAsC,sBAAsB,KAAK,IAAI,CAAC,SAAS,KAAK,UAAU,OAAO,CAAC;AAAA,IACxG;AAAA,EACF;AACA,MAAI,YAAY,eAAe;AAC7B,UAAM,aAAa,eAAe;AAClC,QAAI,eAAe,QAAQ,OAAO,eAAe,YAAY,EAAE,YAAY,aAAa;AACtF,YAAM,IAAI;AAAA,QACR;AAAA,MAGF;AAAA,IACF;AAAA,EACF;AACF;AAIA,IAAM,cAAc;AACpB,IAAM,aAAa;AAGZ,SAAS,YAAY,MAAuB;AACjD,MAAI,UAAU,KAAK,QAAQ,aAAa,EAAE,EAAE,KAAK;AACjD,YAAU,QAAQ,QAAQ,YAAY,EAAE,EAAE,KAAK;AAE/C,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AAAA,EAER;AAGA,QAAM,QAAiC,CAAC;AACxC,aAAW,CAAC,QAAQ,MAAM,KAAK;AAAA,IAC7B,CAAC,KAAK,GAAG;AAAA,IACT,CAAC,KAAK,GAAG;AAAA,EACX,GAAY;AACV,UAAM,QAAQ,QAAQ,QAAQ,MAAM;AACpC,UAAM,MAAM,QAAQ,YAAY,MAAM;AACtC,QAAI,UAAU,MAAM,MAAM,MAAO,OAAM,KAAK,CAAC,OAAO,QAAQ,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC;AAAA,EACpF;AACA,QAAM,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAChC,aAAW,CAAC,EAAE,IAAI,KAAK,OAAO;AAC5B,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR,iDAAiD,KAAK,UAAU,KAAK,MAAM,GAAG,GAAG,CAAC,CAAC;AAAA,EACrF;AACF;AASO,IAAM,oBAAgC,EAAE,MAAM,SAAS;AAE9D,SAAS,cACP,QACA,gBACgB;AAChB,MAAI,WAAW,UAAa,mBAAmB,QAAW;AACxD,UAAM,IAAI,gBAAgB,gDAAgD;AAAA,EAC5E;AACA,MAAI,mBAAmB,OAAW,QAAO;AACzC,SAAO,iBAAiB,UAAU,iBAAiB;AACrD;AAGA,SAAS,kBAAqB,QAAc;AAC1C,MACE,WAAW,QACX,OAAO,WAAW,YAClB,CAAC,MAAM,QAAQ,MAAM,KACpB,OAAsB,SAAS,kBAChC,eAAgB,QAChB;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,MAAkC;AACpD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,KAAK,QAAQ,WAAW,EAAE,CAAC;AAGpD,UAAM,UAAU,MAAM,UAAU,CAAC,GAAG,OAAO;AAC3C,WAAO,WAAW;AAAA,EACpB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,UAAU,cAAc,MAAiC;AACvD,aAAW,QAAQ,KAAK,MAAM,IAAI,GAAG;AACnC,QAAI,KAAM,OAAM;AAAA,EAClB;AACF;AAEA,gBAAgB,gBAAgB,MAA0D;AACxF,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AAEb,SAAO,MAAM;AACX,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,QAAI,KAAM;AACV,cAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,UAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,aAAS,MAAM,IAAI,KAAK;AACxB,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAM,OAAM;AAAA,IAClB;AAAA,EACF;AACA,MAAI,OAAQ,OAAM;AACpB;AAEA,gBAAuB,IACrB,QACA,UACA,UAAsB,CAAC,GACC;AACxB,yBAAuB,QAAQ,cAAc;AAC7C,QAAM,UAAU,EAAE,eAAe,UAAU,OAAO,KAAK,GAAG;AAC1D,QAAM,UAAsB,EAAE,OAAO,OAAO,UAAU,QAAQ,KAAK;AACnE,MAAI,QAAQ,mBAAmB,OAAW,SAAQ,kBAAkB,QAAQ;AAE5E,QAAM,WAAW,MAAM,OAAO,KAAK,KAAK,OAAO,QAAQ,EAAE,SAAS,MAAM,QAAQ,CAAC;AACjF,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,mBAAe,UAAU,IAAI;AAC7B;AAAA,EACF;AAEA,MAAI,SAAS,MAAM;AACjB,qBAAiB,QAAQ,gBAAgB,SAAS,IAAI,GAAG;AACvD,YAAM,UAAU,WAAW,IAAI;AAC/B,UAAI,QAAS,OAAM;AAAA,IACrB;AACA;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAW,QAAQ,cAAc,IAAI,GAAG;AACtC,UAAM,UAAU,WAAW,IAAI;AAC/B,QAAI,QAAS,OAAM;AAAA,EACrB;AACF;AAOA,eAAsB,QACpB,QACA,UACA,QACA,UAAsB,CAAC,GACX;AACZ,QAAM,iBAAiB,cAAc,QAAQ,QAAQ,cAAc;AACnE,MAAI,OAAO;AACX,mBAAiB,SAAS,IAAI,QAAQ,UAAU,EAAE,eAAe,CAAC,EAAG,SAAQ;AAC7E,SAAO,kBAAkB,YAAY,IAAI,CAAC;AAC5C;;;AC7NO,IAAK,iBAAL,kBAAKA,oBAAL;AACL,EAAAA,gBAAA,gBAAa;AACb,EAAAA,gBAAA,kBAAe;AAFL,SAAAA;AAAA,GAAA;AA4BZ,SAAS,iBACP,QACA,SACA,MACA,SAEA;AACA,QAAM,SAA0C;AAAA,IAC9C,OAAO,OAAO;AAAA,IACd,MAAM;AAAA,IACN,OAAO;AAAA,IACP,YAAY,QAAQ;AAAA,IACpB,cAAc,QAAQ;AAAA,IACtB,SAAS,QAAQ;AAAA,IACjB,gBAAgB,QAAQ,iBAAiB,IAAI;AAAA,EAC/C;AACA,MAAI,QAAQ,OAAQ,QAAO,SAAS,QAAQ;AAC5C,MAAI,QAAQ,aAAa,EAAG,QAAO,aAAa,QAAQ;AACxD,MAAI,QAAQ,gBAAiB,QAAO,kBAAkB,QAAQ;AAC9D,MAAI,QAAQ,kBAAmB,QAAO,oBAAoB,QAAQ;AAClE,MAAI,QAAQ,WAAY,QAAO,aAAa;AAC5C,MAAI,QAAQ,WAAY,QAAO,aAAa;AAC5C,MAAI,QAAQ,cAAe,QAAO,gBAAgB,QAAQ;AAC1D,SAAO;AACT;AAEA,SAAS,YAAY,MAAc,UAAqC;AACtE,QAAM,SAAuB,CAAC;AAC9B,QAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,IAAI;AACpC,MAAI,MAAM,SAAS,EAAG,QAAO;AAE7B,QAAM,UAAU,MAAM,CAAC,EAAG,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACxD,QAAM,SAAS,QAAQ,QAAQ,KAAK;AACpC,QAAM,UAAU,QAAQ,QAAQ,cAAc;AAC9C,QAAM,YAAY,QAAQ,QAAQ,cAAc;AAEhD,aAAW,QAAQ,MAAM,MAAM,CAAC,GAAG;AACjC,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,UAAM,MAAM,KAAK,MAAM,GAAG,QAAQ,UAAU,EAAE,EAAE,KAAK,KAAK;AAC1D,QAAI,OAAO,CAAC,SAAS,IAAI,GAAG,GAAG;AAC7B,eAAS,IAAI,GAAG;AAChB,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,WAAW,KAAK,OAAO,GAAG,KAAK,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,QAC3D,SAAS;AAAA,UACP;AAAA,UACA,QAAQ,KAAK,SAAS,GAAG,KAAK,KAAK;AAAA,QACrC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,gBAAuB,MACrB,QACA,MACA,UAAwB,CAAC,GACG;AAC5B,MAAI,iBAAiB,KAAK,WAAW,MAAM,IAAI,OAAO,WAAW,IAAI;AACrE,QAAM,UAAU,QAAQ,WAAW,SAAS,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,CAAC;AAEzE,QAAM,SAAS,iBAAiB,QAAQ,SAAS,gBAAgB;AAAA,IAC/D,MAAM,QAAQ,QAAQ;AAAA,IACtB,YAAY,QAAQ,cAAc;AAAA,IAClC,cAAc,QAAQ,gBAAgB;AAAA,IACtC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,QAAQ,QAAQ,UAAU;AAAA,IAC1B,YAAY,QAAQ,cAAc;AAAA,IAClC,iBAAiB,QAAQ;AAAA,IACzB,mBAAmB,QAAQ;AAAA,IAC3B,YAAY,QAAQ,cAAc;AAAA,IAClC,YAAY,QAAQ,cAAc;AAAA,IAClC,eAAe,QAAQ;AAAA,EACzB,CAAC;AAED,QAAM,WAAW,MAAM,OAAO,KAAK,IAAI,OAAO,YAAY,EAAE,OAAO,CAAC;AACpE,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAE7B,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS,EAAE,UAAU,QAAQ;AAAA,EAC/B;AAEA,MAAI,CAAC,QAAQ,OAAO;AAClB;AAAA,EACF;AAEA,QAAM,WAAW,oBAAI,IAAY;AACjC,QAAM,eAAe,QAAQ,gBAAgB;AAE7C,SAAO,MAAM;AACX,UAAM,iBAAiB,MAAM,OAAO,KAAK,IAAI,OAAO,YAAY;AAAA,MAC9D,QAAQ,EAAE,OAAO,OAAO,OAAO,MAAM,QAAQ;AAAA,IAC/C,CAAC;AACD,UAAM,aAAa,MAAM,aAAa,cAAc;AACpD,mBAAe,gBAAgB,UAAU;AACzC,UAAM,OAAQ,KAAK,MAAM,UAAU,EAAiB;AACpD,QAAI,CAAC,MAAM,OAAQ;AAEnB,UAAM,YAAa,KAAK,CAAC,EAAG,aAAa,CAAC;AAC1C,UAAM,aAAa,OAAO,UAAU,UAAU,CAAC;AAE/C,UAAM,eAAe,MAAM,OAAO,KAAK,IAAI,GAAG,OAAO,UAAU,SAAS;AAAA,MACtE,QAAQ,EAAE,OAAO,OAAO,OAAO,MAAM,SAAS,MAAM,OAAO;AAAA,MAC3D,UAAU;AAAA,IACZ,CAAC;AACD,UAAM,WAAW,MAAM,aAAa,YAAY;AAChD,mBAAe,cAAc,QAAQ;AACrC,QAAI,UAAU;AACZ,iBAAW,SAAS,YAAY,UAAU,QAAQ,GAAG;AACnD,cAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,eAAe,KAAK,eAAe,GAAG;AACxC,YAAM,UAAU,OAAO,UAAU,WAAW,EAAE;AAC9C,UAAI,cAAc,KAAK,OAAO,GAAG;AAC/B,cAAM,IAAI,SAAS,KAAK,uBAAuB,OAAO,EAAE;AAAA,MAC1D;AACA;AAAA,IACF;AAEA,UAAM,MAAM,YAAY;AAAA,EAC1B;AACF;AAEA,eAAsB,cAAc,QAA8C;AAChF,QAAM,WAAW,MAAM,OAAO,KAAK,IAAI,OAAO,YAAY;AAAA,IACxD,QAAQ,EAAE,OAAO,OAAO,MAAM;AAAA,EAChC,CAAC;AACD,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAC7B,SAAS,KAAK,MAAM,IAAI,EAAiB,QAAqC,CAAC;AACjF;AAEA,eAAsB,YAAY,QAAuB,SAAsC;AAC7F,QAAM,WAAW,MAAM,OAAO,KAAK,IAAI,OAAO,YAAY;AAAA,IACxD,QAAQ,EAAE,OAAO,OAAO,OAAO,MAAM,QAAQ;AAAA,EAC/C,CAAC;AACD,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAC7B,QAAM,OAAQ,KAAK,MAAM,IAAI,EAAiB;AAC9C,SAAO,OAAO,CAAC,KAAK,CAAC;AACvB;AAEA,eAAsB,eAAe,QAAuB,SAAgC;AAC1F,QAAM,WAAW,MAAM,OAAO,KAAK,IAAI,OAAO,YAAY;AAAA,IACxD,QAAQ,EAAE,OAAO,OAAO,OAAO,MAAM,SAAS,QAAQ,EAAE;AAAA,EAC1D,CAAC;AACD,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAC/B;;;AC1LO,IAAM,WAAN,MAAM,UAAS;AAAA,EACX;AAAA,EAET,YAAY,MAAkB;AAC5B,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,OAAO,SAAS,KAAoC;AAClD,UAAM,OAAO,OAAO,QAAQ,WAAW,MAAM,IAAI,YAAY,EAAE,OAAO,GAAG;AACzE,WAAO,IAAI,UAAS,KAAK,MAAM,IAAI,CAAe;AAAA,EACpD;AAAA,EAEA,QAAkB;AAChB,UAAM,QAAQ,KAAK,KAAK;AACxB,WAAO,OAAO,KAAK,SAAS,CAAC,CAAC,EAAE,KAAK;AAAA,EACvC;AAAA,EAEA,aAAuB;AACrB,UAAM,aAAa,KAAK,KAAK;AAC7B,WAAO,OAAO,KAAK,cAAc,CAAC,CAAC,EAAE,KAAK;AAAA,EAC5C;AAAA,EAEA,QAAkB;AAChB,UAAM,QAAQ,KAAK,KAAK;AACxB,WAAO,OAAO,KAAK,SAAS,CAAC,CAAC,EAAE,KAAK;AAAA,EACvC;AAAA,EAEA,aAAuB;AACrB,UAAM,aAAa,KAAK,KAAK;AAC7B,WAAO,OAAO,KAAK,cAAc,CAAC,CAAC,EAAE,KAAK;AAAA,EAC5C;AAAA,EAEA,OAAe,SAAS,WAAuC,UAA6C;AAC1G,UAAM,QAAQ,UAAU,QAAQ;AAChC,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iBAAiB,QAAQ,EAAE;AACvD,WAAQ,MAAM,UAAoD,CAAC;AAAA,EACrE;AAAA,EAEA,UAAU,UAA6C;AACrD,UAAM,QAAS,KAAK,KAAK,SAAS,CAAC;AACnC,UAAM,aAAc,KAAK,KAAK,cAAc,CAAC;AAC7C,QAAI,YAAY,MAAO,QAAO,UAAS,SAAS,OAAO,QAAQ;AAC/D,QAAI,YAAY,WAAY,QAAO,UAAS,SAAS,YAAY,QAAQ;AACzE,UAAM,IAAI,MAAM,GAAG,QAAQ,0CAA0C;AAAA,EACvE;AAAA,EAEA,OAAO,aACL,QACA,QACA,oBAAoB,OACN;AACd,UAAM,UAAU,SAAS,IAAI,OAAO,QAAQ,GAAG,IAAI;AACnD,UAAM,MAAoB,CAAC;AAC3B,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAI,CAAC,qBAAqB,KAAK,aAAc;AAC7C,UAAI,WAAW,CAAC,QAAQ,KAAK,IAAI,EAAG;AACpC,UAAI,KAAK,CAAC,MAAM,IAAI,CAAC;AAAA,IACvB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,MAAc,QAAkC;AAC7D,UAAM,aAAc,KAAK,KAAK,cAAc,CAAC;AAC7C,UAAM,MAAM,WAAW,IAAI;AAC3B,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,qBAAqB,IAAI,EAAE;AAErD,UAAM,UAAU,SAAS,IAAI,OAAO,QAAQ,GAAG,IAAI;AACnD,UAAM,MAAgB,CAAC;AAEvB,UAAM,OAAO,CAAC,SAA2B;AACvC,YAAM,IAAI,KAAK;AACf,UAAI,OAAO,MAAM,aAAa,CAAC,WAAW,QAAQ,KAAK,CAAC,IAAI;AAC1D,YAAI,KAAK,CAAC;AAAA,MACZ;AACA,iBAAW,SAAU,KAAK,YAAyC,CAAC,GAAG;AACrE,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AAEA,eAAW,OAAQ,IAAI,cAA2C,CAAC,GAAG;AACpE,WAAK,GAAG;AAAA,IACV;AACA,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,MAAwB;AACjC,UAAM,QAAS,KAAK,KAAK,SAAS,CAAC;AACnC,UAAM,YAAY,MAAM,IAAI;AAC5B,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,iBAAiB,IAAI,EAAE;AACvD,WAAO,CAAC,GAAK,UAAU,UAAmC,CAAC,CAAE;AAAA,EAC/D;AAAA,EAEA,UAAU,QAA0B;AAClC,UAAM,UAAU,IAAI,OAAO,QAAQ,GAAG;AACtC,UAAM,QAAQ,oBAAI,IAAY;AAE9B,UAAM,OAAO,CAAC,SAAwB;AACpC,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,mBAAW,KAAK,KAAM,MAAK,CAAC;AAAA,MAC9B,WAAW,QAAQ,OAAO,SAAS,UAAU;AAC3C,cAAM,MAAM;AACZ,cAAM,IAAI,IAAI;AACd,YAAI,OAAO,MAAM,YAAY,QAAQ,KAAK,CAAC,EAAG,OAAM,IAAI,CAAC;AACzD,mBAAW,KAAK,OAAO,OAAO,GAAG,EAAG,MAAK,CAAC;AAAA,MAC5C;AAAA,IACF;AAEA,SAAK,KAAK,IAAI;AACd,WAAO,CAAC,GAAG,KAAK,EAAE,KAAK;AAAA,EACzB;AAAA,EAEA,OAAO,YAAY,MAAc,MAAyB;AACxD,QAAI,WAAW,OAAO,KAAK,QAAQ,GAAG;AACtC,QAAI,aAAa,gBAAgB;AAC/B,YAAM,KAAK,KAAK;AAChB,UAAI,IAAI,OAAQ,YAAW,iBAAiB,GAAG,CAAC,CAAC;AAAA,IACnD;AACA,UAAM,QAAkB,CAAC;AACzB,QAAI,KAAK,OAAQ,OAAM,KAAK,QAAQ;AACpC,QAAI,KAAK,YAAa,OAAM,KAAK,aAAa;AAC9C,QAAI,KAAK,OAAQ,OAAM,KAAK,QAAQ;AACpC,QAAI,KAAK,aAAc,OAAM,KAAK,YAAY;AAC9C,UAAM,SAAS,MAAM,IAAI,CAAC,MAAM,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE;AAClD,WAAO,GAAG,IAAI,MAAM,QAAQ,IAAI,MAAM;AAAA,EACxC;AACF;;;ACnHA,SAAS,eACP,QACA,OACA,SACiC;AACjC,QAAM,SAA0C;AAAA,IAC9C,OAAO,OAAO;AAAA,IACd;AAAA,IACA,MAAM,QAAQ,QAAQ;AAAA,EACxB;AACA,MAAI,QAAQ,KAAM,QAAO,OAAO,QAAQ;AACxC,MAAI,QAAQ,UAAU,QAAQ,WAAW,OAAQ,QAAO,SAAS,QAAQ;AACzE,MAAI,QAAQ,WAAW,OAAW,QAAO,SAAS,QAAQ;AAC1D,MAAI,QAAQ,eAAe,OAAW,QAAO,aAAa,QAAQ;AAClE,MAAI,QAAQ,MAAO,QAAO,OAAO,QAAQ,QAAQ,KAAK;AACtD,SAAO;AACT;AAEA,eAAsB,IACpB,QACA,OACA,UAAsB,CAAC,GACW;AAClC,QAAM,SAAS,eAAe,QAAQ,OAAO,OAAO;AACpD,QAAM,WAAW,MAAM,OAAO,KAAK,IAAI,OAAO,QAAQ,EAAE,OAAO,CAAC;AAChE,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAC7B,MAAI,QAAQ,KAAK;AACf,WAAO,IAAI,YAAY,EAAE,OAAO,IAAI;AAAA,EACtC;AACA,SAAO,KAAK,MAAM,IAAI;AACxB;AAEA,eAAsB,YACpB,QACA,SACA,UAAU,GAC+B;AACzC,MAAI,CAAC,QAAQ,OAAQ,QAAO,CAAC;AAE7B,QAAM,QAAQ,KAAK,IAAI,SAAS,QAAQ,MAAM;AAC9C,QAAM,UAA0C,IAAI,MAAM,QAAQ,MAAM;AACxE,MAAI,QAAQ;AAEZ,iBAAe,SAAwB;AACrC,WAAO,MAAM;AACX,YAAM,UAAU;AAChB,UAAI,WAAW,QAAQ,OAAQ;AAC/B,YAAM,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,OAAO;AAC1C,cAAQ,OAAO,IAAI,MAAM,IAAI,QAAQ,OAAO,IAAI;AAAA,IAClD;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC;AAC/D,SAAO;AACT;AAGA,eAAsB,qBAAqB,QAAwC;AACjF,QAAM,WAAW,MAAM,OAAO,KAAK,IAAI,OAAO,WAAW;AACzD,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAC7B,SAAO;AACT;AAEA,eAAsB,iBAAiB,QAA0C;AAC/E,SAAO,SAAS,SAAS,MAAM,qBAAqB,MAAM,CAAC;AAC7D;;;AC9EA,IAAM,aAAa;AAEnB,eAAsB,SACpB,QACA,MACA,OAAO,QACc;AACrB,QAAM,SAAS,EAAE,OAAO,OAAO,OAAO,QAAQ,WAAW;AACzD,QAAM,UAAU,CAAC,EAAE,MAAM,QAAQ,cAAc,SAAS,KAAK,CAAC;AAC9D,QAAM,WAAW,MAAM,OAAO,KAAK,KAAK,OAAO,QAAQ,EAAE,QAAQ,MAAM,QAAQ,CAAC;AAChF,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAC7B,QAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,SAAO,MAAM,QAAQ,IAAI,IAAK,KAAK,CAAC,KAAK,CAAC,IAAK;AACjD;;;ACGO,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACU;AAAA,EACX,WAAqC;AAAA,EAE7C,YAAY,QAAuB,UAAgC,CAAC,GAAG;AACrE,SAAK,SAAS;AACd,SAAK,aAAa,QAAQ,cAAc;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAK,UAAiC,CAAC,GAAsB;AAC3D,QAAI,QAAQ,SAAS;AACnB,WAAK,WAAW;AAAA,IAClB;AACA,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,KAAK,QAAQ,QAAQ,WAAW,KAAK,EAAE,MAAM,CAAC,UAAmB;AAC/E,aAAK,WAAW;AAChB,cAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,QAAQ,SAAqC;AACzD,QAAI,CAAC,SAAS;AACZ,YAAM,SAAS,MAAM,KAAK,KAAK;AAC/B,UAAI,WAAW,QAAW;AACxB,YAAI;AACF,iBAAO,SAAS,SAAS,MAAM;AAAA,QACjC,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AACA,UAAM,OAAO,MAAM,qBAAqB,KAAK,MAAM;AACnD,UAAM,KAAK,MAAM,IAAI;AACrB,WAAO,SAAS,SAAS,IAAI;AAAA,EAC/B;AAAA;AAAA,EAGU,OAAoC;AAC5C,WAAO,QAAQ,QAAQ,MAAS;AAAA,EAClC;AAAA;AAAA,EAGU,MAAM,OAA8B;AAC5C,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;AA6CO,IAAM,kBAAN,cAA8B,cAAc;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAAuB,IAAY,UAAkC,CAAC,GAAG;AACnF,UAAM,QAAQ,OAAO;AACrB,SAAK,KAAK;AACV,SAAK,MAAM,QAAQ,OAAO;AAC1B,SAAK,iBAAiB,GAAG,KAAK,GAAG;AACjC,SAAK,UAAU,GAAG,KAAK,GAAG;AAC1B,SAAK,oBAAoB,QAAQ,qBAAqB;AACtD,SAAK,iBAAiB,QAAQ,kBAAkB;AAChD,SAAK,YAAY,QAAQ;AAAA,EAC3B;AAAA,EAES,KAAK,UAAiC,CAAC,GAAsB;AACpE,QAAI,CAAC,QAAQ,WAAW,KAAK,oBAAoB,GAAG;AAClD,aAAO,KAAK,6BAA6B;AAAA,IAC3C;AACA,WAAO,MAAM,KAAK,OAAO;AAAA,EAC3B;AAAA,EAEA,MAAc,+BAAkD;AAC9D,UAAM,CAAC,QAAQ,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC9C,KAAK,GAAG,IAAI,KAAK,GAAG;AAAA,MACpB,KAAK,GAAG,IAAI,KAAK,cAAc;AAAA,IACjC,CAAC;AACD,QAAI,WAAW,MAAM;AACnB,aAAO,MAAM,KAAK;AAAA,IACpB;AAEA,UAAM,MAAM,eAAe,KAAK,IAAI,IAAI,OAAO,WAAW,KAAK,MAAO;AACtE,UAAM,UAAU,MAAM,KAAK;AAC3B,UAAM,WAAW,SAAS,SAAS,MAAM;AAEzC,QAAI,SAAS;AACX,YAAM,UAAU,MAAM,KAAK,EAAE,SAAS,KAAK,CAAC,EAAE,MAAM,MAAM;AAAA,MAE1D,CAAC;AACD,UAAI,KAAK,WAAW;AAClB,aAAK,UAAU,OAAO;AAAA,MACxB,OAAO;AACL,cAAM;AACN,eAAO,MAAM,KAAK;AAAA,MACpB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAyB,OAAoC;AAC3D,UAAM,SAAS,MAAM,KAAK,GAAG,IAAI,KAAK,GAAG;AACzC,WAAO,UAAU;AAAA,EACnB;AAAA,EAEA,MAAyB,MAAM,MAA6B;AAE1D,QAAI,MAAM,KAAK,GAAG,IAAI,KAAK,OAAO,GAAG;AACnC;AAAA,IACF;AACA,UAAM,KAAK,GAAG,IAAI,KAAK,SAAS,KAAK,EAAE,eAAe,KAAK,eAAe,CAAC;AAC3E,QAAI;AACF,YAAM,KAAK,GAAG,IAAI,KAAK,KAAK,MAAM,EAAE,eAAe,KAAK,WAAW,CAAC;AACpE,YAAM,KAAK,GAAG,IAAI,KAAK,gBAAgB,OAAO,KAAK,IAAI,CAAC,GAAG;AAAA,QACzD,eAAe,KAAK;AAAA,MACtB,CAAC;AAAA,IACH,UAAE;AACA,YAAM,KAAK,GAAG,OAAO,KAAK,OAAO;AAAA,IACnC;AAAA,EACF;AACF;;;AC3LO,IAAM,kBAA4C,CAAC,SAAS,UAAU,QAAQ,MAAM;AAa3F,eAAsB,UACpB,QACA,MACA,UAA4B,CAAC,GACR;AACrB,QAAM,UAAU,EAAE,eAAe,UAAU,OAAO,KAAK,GAAG;AAC1D,QAAM,SAA0C,EAAE,KAAK;AACvD,MAAI,QAAQ,eAAe,OAAW,QAAO,OAAO,QAAQ;AAC5D,MAAI,QAAQ,cAAc,OAAW,QAAO,YAAY,QAAQ;AAChE,MAAI,QAAQ,kBAAkB,QAAW;AACvC,UAAM,SAAS,QAAQ,cAAc,YAAY;AACjD,QAAI,CAAC,gBAAgB,SAAS,MAAM,GAAG;AACrC,YAAM,IAAI;AAAA,QACR,gCAAgC,gBAAgB,KAAK,IAAI,CAAC,SAAS,KAAK,UAAU,QAAQ,aAAa,CAAC;AAAA,MAC1G;AAAA,IACF;AACA,WAAO,gBAAgB,OAAO,YAAY;AAC1C,QAAI,WAAW,OAAQ,QAAO,SAAS;AAAA,EACzC;AAEA,QAAM,WAAW,MAAM,OAAO,KAAK,IAAI,OAAO,cAAc,EAAE,SAAS,OAAO,CAAC;AAC/E,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,iBAAe,UAAU,IAAI;AAC7B,SAAO,KAAK,MAAM,IAAI;AACxB;","names":["CrawlEventType"]}
package/dist/index.d.cts CHANGED
@@ -63,7 +63,46 @@ interface ChatMessage {
63
63
  role: string;
64
64
  content: string;
65
65
  }
66
- declare function ask(client: DiffbotClient, messages: ChatMessage[]): AsyncGenerator<string>;
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>;
67
106
 
68
107
  declare enum CrawlEventType {
69
108
  JobCreated = "job_created",
@@ -229,10 +268,20 @@ declare class KVOntologyStore extends OntologyStore {
229
268
  protected write(text: string): Promise<void>;
230
269
  }
231
270
 
232
- declare function webSearch(client: DiffbotClient, text: string, options?: {
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 {
233
275
  numResults?: number;
234
276
  maxTokens?: number;
235
- }): Promise<JsonObject>;
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>;
236
285
 
237
286
  /** Exception hierarchy for the Diffbot SDK. */
238
287
  declare class DiffbotError extends Error {
@@ -263,6 +312,6 @@ declare class ExtractionError extends DiffbotError {
263
312
  constructor(errorCode: number, error: string);
264
313
  }
265
314
 
266
- declare const VERSION = "0.2.0";
315
+ declare const VERSION = "0.3.0";
267
316
 
268
- export { APIError, 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, RateLimitError, type TokenSource, VERSION, ValidationError, ask, crawl, crawlDeleteJob, crawlGetJob, crawlListJobs, dql, dqlFetchOntology, dqlFetchOntologyText, dqlParallel, entities, extract, resolveTokenFromEnv, webSearch };
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 };
package/dist/index.d.ts CHANGED
@@ -63,7 +63,46 @@ interface ChatMessage {
63
63
  role: string;
64
64
  content: string;
65
65
  }
66
- declare function ask(client: DiffbotClient, messages: ChatMessage[]): AsyncGenerator<string>;
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>;
67
106
 
68
107
  declare enum CrawlEventType {
69
108
  JobCreated = "job_created",
@@ -229,10 +268,20 @@ declare class KVOntologyStore extends OntologyStore {
229
268
  protected write(text: string): Promise<void>;
230
269
  }
231
270
 
232
- declare function webSearch(client: DiffbotClient, text: string, options?: {
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 {
233
275
  numResults?: number;
234
276
  maxTokens?: number;
235
- }): Promise<JsonObject>;
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>;
236
285
 
237
286
  /** Exception hierarchy for the Diffbot SDK. */
238
287
  declare class DiffbotError extends Error {
@@ -263,6 +312,6 @@ declare class ExtractionError extends DiffbotError {
263
312
  constructor(errorCode: number, error: string);
264
313
  }
265
314
 
266
- declare const VERSION = "0.2.0";
315
+ declare const VERSION = "0.3.0";
267
316
 
268
- export { APIError, 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, RateLimitError, type TokenSource, VERSION, ValidationError, ask, crawl, crawlDeleteJob, crawlGetJob, crawlListJobs, dql, dqlFetchOntology, dqlFetchOntologyText, dqlParallel, entities, extract, resolveTokenFromEnv, webSearch };
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 };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/constants.ts
2
- var VERSION = "0.2.0";
2
+ var VERSION = "0.3.0";
3
3
  var DEFAULT_TIMEOUT = 3e4;
4
4
  var EXTRACT_BASE = "https://api.diffbot.com/v3";
5
5
  var CRAWL_BASE = "https://api.diffbot.com/v3/crawl";
@@ -221,6 +221,80 @@ async function extract(client, url, api = "analyze", fmt = "markdown") {
221
221
  }
222
222
 
223
223
  // src/ask.ts
224
+ var MODEL = "diffbot-small-xl";
225
+ var RESPONSE_FORMAT_TYPES = ["text", "json_object", "json_schema"];
226
+ function jsonSchemaFormat(schema, name = "response") {
227
+ if (schema === null || typeof schema !== "object" || Array.isArray(schema)) {
228
+ throw new ValidationError("schema must be a JSON Schema object");
229
+ }
230
+ return { type: "json_schema", json_schema: { name, schema } };
231
+ }
232
+ function validateResponseFormat(responseFormat) {
233
+ if (responseFormat === void 0) return;
234
+ if (responseFormat === null || typeof responseFormat !== "object" || Array.isArray(responseFormat)) {
235
+ throw new ValidationError("responseFormat must be an object");
236
+ }
237
+ const fmtType = responseFormat.type ?? "text";
238
+ if (!RESPONSE_FORMAT_TYPES.includes(fmtType)) {
239
+ throw new ValidationError(
240
+ `responseFormat type must be one of ${RESPONSE_FORMAT_TYPES.join(", ")}; got ${JSON.stringify(fmtType)}`
241
+ );
242
+ }
243
+ if (fmtType === "json_schema") {
244
+ const jsonSchema = responseFormat.json_schema;
245
+ if (jsonSchema === null || typeof jsonSchema !== "object" || !("schema" in jsonSchema)) {
246
+ throw new ValidationError(
247
+ 'responseFormat { type: "json_schema" } requires the schema nested as { json_schema: { schema: {...} } }. Without it the server returns 200 and ignores the constraint. Use jsonSchemaFormat(schema) to build it.'
248
+ );
249
+ }
250
+ }
251
+ }
252
+ var THINK_BLOCK = /<think>[\s\S]*?<\/think>/g;
253
+ var JSON_FENCE = /^```(?:json)?\s*|\s*```$/gm;
254
+ function extractJson(text) {
255
+ let cleaned = text.replace(THINK_BLOCK, "").trim();
256
+ cleaned = cleaned.replace(JSON_FENCE, "").trim();
257
+ try {
258
+ return JSON.parse(cleaned);
259
+ } catch {
260
+ }
261
+ const spans = [];
262
+ for (const [opener, closer] of [
263
+ ["{", "}"],
264
+ ["[", "]"]
265
+ ]) {
266
+ const start = cleaned.indexOf(opener);
267
+ const end = cleaned.lastIndexOf(closer);
268
+ if (start !== -1 && end > start) spans.push([start, cleaned.slice(start, end + 1)]);
269
+ }
270
+ spans.sort((a, b) => a[0] - b[0]);
271
+ for (const [, span] of spans) {
272
+ try {
273
+ return JSON.parse(span);
274
+ } catch {
275
+ continue;
276
+ }
277
+ }
278
+ throw new ValidationError(
279
+ `could not parse JSON from the model response: ${JSON.stringify(text.slice(0, 200))}`
280
+ );
281
+ }
282
+ var ANY_OBJECT_SCHEMA = { type: "object" };
283
+ function resolveFormat(schema, responseFormat) {
284
+ if (schema !== void 0 && responseFormat !== void 0) {
285
+ throw new ValidationError("pass either schema or responseFormat, not both");
286
+ }
287
+ if (responseFormat !== void 0) return responseFormat;
288
+ return jsonSchemaFormat(schema ?? ANY_OBJECT_SCHEMA);
289
+ }
290
+ function checkToolCallLeak(parsed) {
291
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.name === "functioncall" && "arguments" in parsed) {
292
+ throw new ValidationError(
293
+ 'the model returned its internal tool call instead of an answer; this happens with responseFormat { type: "json_object" } because the server applies no grammar to it. Pass a schema instead.'
294
+ );
295
+ }
296
+ return parsed;
297
+ }
224
298
  function parseChunk(line) {
225
299
  try {
226
300
  const chunk = JSON.parse(line.replace(/^data: /, ""));
@@ -251,9 +325,11 @@ async function* linesFromStream(body) {
251
325
  }
252
326
  if (buffer) yield buffer;
253
327
  }
254
- async function* ask(client, messages) {
328
+ async function* ask(client, messages, options = {}) {
329
+ validateResponseFormat(options.responseFormat);
255
330
  const headers = { Authorization: `Bearer ${client.token}` };
256
- const payload = { model: "diffbot-small-xl", messages, stream: true };
331
+ const payload = { model: MODEL, messages, stream: true };
332
+ if (options.responseFormat !== void 0) payload.response_format = options.responseFormat;
257
333
  const response = await client.http.post(client.llmUrl, { headers, json: payload });
258
334
  if (!response.ok) {
259
335
  const body = await readBodyText(response);
@@ -273,6 +349,12 @@ async function* ask(client, messages) {
273
349
  if (content) yield content;
274
350
  }
275
351
  }
352
+ async function askJson(client, messages, schema, options = {}) {
353
+ const responseFormat = resolveFormat(schema, options.responseFormat);
354
+ let text = "";
355
+ for await (const chunk of ask(client, messages, { responseFormat })) text += chunk;
356
+ return checkToolCallLeak(extractJson(text));
357
+ }
276
358
 
277
359
  // src/crawl.ts
278
360
  var CrawlEventType = /* @__PURE__ */ ((CrawlEventType2) => {
@@ -698,17 +780,29 @@ var KVOntologyStore = class extends OntologyStore {
698
780
  };
699
781
 
700
782
  // src/web-search.ts
783
+ var SNIPPET_LENGTHS = ["short", "medium", "long", "full"];
701
784
  async function webSearch(client, text, options = {}) {
702
785
  const headers = { Authorization: `Bearer ${client.token}` };
703
786
  const params = { text };
704
787
  if (options.numResults !== void 0) params.size = options.numResults;
705
788
  if (options.maxTokens !== void 0) params.maxTokens = options.maxTokens;
789
+ if (options.snippetLength !== void 0) {
790
+ const length = options.snippetLength.toLowerCase();
791
+ if (!SNIPPET_LENGTHS.includes(length)) {
792
+ throw new ValidationError(
793
+ `snippetLength must be one of ${SNIPPET_LENGTHS.join(", ")}; got ${JSON.stringify(options.snippetLength)}`
794
+ );
795
+ }
796
+ params.snippetLength = length.toUpperCase();
797
+ if (length === "full") params.rerank = "none";
798
+ }
706
799
  const response = await client.http.get(client.webSearchUrl, { headers, params });
707
800
  const body = await readBodyText(response);
708
801
  raiseForStatus(response, body);
709
802
  return JSON.parse(body);
710
803
  }
711
804
  export {
805
+ ANY_OBJECT_SCHEMA,
712
806
  APIError,
713
807
  AuthError,
714
808
  CrawlEventType,
@@ -718,10 +812,13 @@ export {
718
812
  KVOntologyStore,
719
813
  Ontology,
720
814
  OntologyStore,
815
+ RESPONSE_FORMAT_TYPES,
721
816
  RateLimitError,
817
+ SNIPPET_LENGTHS,
722
818
  VERSION,
723
819
  ValidationError,
724
820
  ask,
821
+ askJson,
725
822
  crawl,
726
823
  crawlDeleteJob,
727
824
  crawlGetJob,
@@ -732,6 +829,8 @@ export {
732
829
  dqlParallel,
733
830
  entities,
734
831
  extract,
832
+ extractJson,
833
+ jsonSchemaFormat,
735
834
  resolveTokenFromEnv,
736
835
  webSearch
737
836
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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 const VERSION = \"0.2.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 { 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 { 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 { 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"]}
1
+ {"version":3,"sources":["../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 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diffbot/typescript",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "TypeScript client library for Diffbot APIs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -28,16 +28,6 @@
28
28
  "engines": {
29
29
  "node": ">=18"
30
30
  },
31
- "scripts": {
32
- "build": "tsup",
33
- "prepublishOnly": "pnpm run build",
34
- "test": "vitest run",
35
- "test:watch": "vitest",
36
- "test:live": "vitest run --config vitest.live.config.ts",
37
- "test:coverage": "vitest run --coverage --coverage.include='src/**'",
38
- "typecheck": "tsc --noEmit",
39
- "postbuild": "node scripts/assert-no-node-builtins.mjs"
40
- },
41
31
  "keywords": [
42
32
  "diffbot",
43
33
  "knowledge-graph",
@@ -67,5 +57,14 @@
67
57
  "tsup": "^8.5.0",
68
58
  "typescript": "^5.8.3",
69
59
  "vitest": "^3.2.1"
60
+ },
61
+ "scripts": {
62
+ "build": "tsup",
63
+ "test": "vitest run",
64
+ "test:watch": "vitest",
65
+ "test:live": "vitest run --config vitest.live.config.ts",
66
+ "test:coverage": "vitest run --coverage --coverage.include='src/**'",
67
+ "typecheck": "tsc --noEmit",
68
+ "postbuild": "node scripts/assert-no-node-builtins.mjs"
70
69
  }
71
- }
70
+ }