@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 +55 -2
- package/dist/index.cjs +102 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -5
- package/dist/index.d.ts +54 -5
- package/dist/index.js +102 -3
- package/dist/index.js.map +1 -1
- package/package.json +11 -12
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.
|
|
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:
|
|
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);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/errors.ts","../src/http.ts","../src/client.ts","../src/auth.ts","../src/extract.ts","../src/ask.ts","../src/crawl.ts","../src/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":";;;;;;;;;;;;;;;;;;;;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;;;ACpCA,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,UACwB;AACxB,QAAM,UAAU,EAAE,eAAe,UAAU,OAAO,KAAK,GAAG;AAC1D,QAAM,UAAU,EAAE,OAAO,oBAAoB,UAAU,QAAQ,KAAK;AAEpE,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;;;AClEO,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;;;AC/LA,eAAsB,UACpB,QACA,MACA,UAAuD,CAAC,GACnC;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;AAEhE,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"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/errors.ts","../src/http.ts","../src/client.ts","../src/auth.ts","../src/extract.ts","../src/ask.ts","../src/crawl.ts","../src/ontology.ts","../src/kg.ts","../src/nlp.ts","../src/ontology-store.ts","../src/web-search.ts"],"sourcesContent":["export { DiffbotClient, type DiffbotClientOptions } from \"./client.js\";\nexport { resolveTokenFromEnv, type TokenSource } from \"./auth.js\";\nexport { extract } from \"./extract.js\";\nexport {\n ANY_OBJECT_SCHEMA,\n RESPONSE_FORMAT_TYPES,\n ask,\n askJson,\n extractJson,\n jsonSchemaFormat,\n type AskOptions,\n type ChatMessage,\n type ResponseFormat,\n type ResponseFormatType,\n} from \"./ask.js\";\nexport {\n crawl,\n crawlDeleteJob,\n crawlGetJob,\n crawlListJobs,\n CrawlEventType,\n type CrawlEvent,\n type CrawlOptions,\n} from \"./crawl.js\";\nexport {\n dql,\n dqlFetchOntology,\n dqlFetchOntologyText,\n dqlParallel,\n type DqlOptions,\n} from \"./kg.js\";\nexport { entities } from \"./nlp.js\";\nexport { Ontology } from \"./ontology.js\";\nexport {\n OntologyStore,\n KVOntologyStore,\n type OntologyStoreOptions,\n type KVOntologyStoreOptions,\n type KVLike,\n} from \"./ontology-store.js\";\nexport { webSearch, SNIPPET_LENGTHS, type SnippetLength, type WebSearchOptions } from \"./web-search.js\";\nexport {\n DiffbotError,\n ValidationError,\n APIError,\n AuthError,\n RateLimitError,\n ExtractionError,\n} from \"./errors.js\";\nexport { VERSION } from \"./constants.js\";\nexport type { FetchFn } from \"./http.js\";\nexport type { JsonObject } from \"./json.js\";\n","export const VERSION = \"0.3.0\";\n\nexport const DEFAULT_TIMEOUT = 30_000;\n\nexport const EXTRACT_BASE = \"https://api.diffbot.com/v3\";\nexport const CRAWL_BASE = \"https://api.diffbot.com/v3/crawl\";\nexport const DIFFBOT_LLM_BASE = \"https://llm.diffbot.com/rag/v1/chat/completions\";\nexport const WEB_SEARCH_BASE = \"https://llm.diffbot.com/api/v1/web_search\";\nexport const NLP_BASE = \"https://nl.diffbot.com/v1/\";\nexport const KG_DQL_ENDPOINT = \"https://kg.diffbot.com/kg/v3/dql\";\nexport const KG_ONTOLOGY_ENDPOINT = \"https://kg.diffbot.com/kg/ontology\";\n\nexport const TOKEN_ENV_VAR = \"DIFFBOT_API_TOKEN\";\n","/** Exception hierarchy for the Diffbot SDK. */\n\nexport class DiffbotError extends Error {\n override name = \"DiffbotError\";\n}\n\nexport class ValidationError extends DiffbotError {\n override name = \"ValidationError\";\n}\n\nexport class APIError extends DiffbotError {\n statusCode: number;\n body: string;\n apiMessage: string | undefined;\n requestId: string | undefined;\n\n constructor(statusCode: number, body: string) {\n let apiMessage: string | undefined;\n let requestId: string | undefined;\n try {\n const data = JSON.parse(body) as { message?: string; requestId?: string };\n apiMessage = data.message;\n requestId = data.requestId;\n } catch {\n /* ignore parse errors */\n }\n const display = apiMessage ?? (body.length > 200 ? `${body.slice(0, 200)}...` : body);\n super(`Diffbot API error ${statusCode}: ${display}`);\n this.name = \"APIError\";\n this.statusCode = statusCode;\n this.body = body;\n this.apiMessage = apiMessage;\n this.requestId = requestId;\n }\n\n}\n\nexport class AuthError extends APIError {\n override name = \"AuthError\";\n}\n\nexport class RateLimitError extends APIError {\n retryAfter: string | undefined;\n override name = \"RateLimitError\";\n\n constructor(statusCode: number, body: string, retryAfter?: string | null) {\n super(statusCode, body);\n this.retryAfter = retryAfter ?? undefined;\n }\n}\n\nexport class ExtractionError extends DiffbotError {\n errorCode: number;\n error: string;\n override name = \"ExtractionError\";\n\n constructor(errorCode: number, error: string) {\n super(`Diffbot extraction error ${errorCode}: ${error}`);\n this.errorCode = errorCode;\n this.error = error;\n }\n}\n","import { APIError, AuthError, RateLimitError } from \"./errors.js\";\n\nexport type FetchFn = typeof fetch;\n\nexport interface HttpRequestOptions {\n params?: Record<string, string | number | boolean | undefined>;\n headers?: Record<string, string>;\n json?: unknown;\n redirect?: \"follow\" | \"error\" | \"manual\";\n}\n\nexport class HttpClient {\n private closed = false;\n\n constructor(\n private readonly fetchFn: FetchFn,\n private readonly timeoutMs: number,\n readonly userAgent: string,\n ) {}\n\n async get(url: string, options: HttpRequestOptions = {}): Promise<Response> {\n return this.request(url, { ...options, method: \"GET\" });\n }\n\n async post(url: string, options: HttpRequestOptions = {}): Promise<Response> {\n return this.request(url, { ...options, method: \"POST\" });\n }\n\n async request(url: string, options: HttpRequestOptions & { method?: string } = {}): Promise<Response> {\n if (this.closed) {\n throw new Error(\"HTTP client is closed\");\n }\n\n const parsed = new URL(url);\n if (options.params) {\n for (const [key, value] of Object.entries(options.params)) {\n if (value !== undefined) {\n parsed.searchParams.set(key, String(value));\n }\n }\n }\n\n const headers = new Headers(options.headers);\n headers.set(\"User-Agent\", this.userAgent);\n if (options.json !== undefined) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n const init: RequestInit = {\n method: options.method ?? \"GET\",\n headers,\n redirect: options.redirect,\n signal: AbortSignal.timeout(this.timeoutMs),\n };\n if (options.json !== undefined) {\n init.body = JSON.stringify(options.json);\n }\n\n return this.fetchFn(parsed.toString(), init);\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n get isClosed(): boolean {\n return this.closed;\n }\n}\n\nexport function raiseForStatus(response: Response, bodyText?: string): void {\n if (response.ok) {\n return;\n }\n const status = response.status;\n const body = bodyText ?? \"\";\n if (status === 401 || status === 403) {\n throw new AuthError(status, body);\n }\n if (status === 429) {\n throw new RateLimitError(status, body, response.headers.get(\"retry-after\"));\n }\n throw new APIError(status, body);\n}\n\nexport async function readBodyText(response: Response): Promise<string> {\n return response.text();\n}\n","import {\n CRAWL_BASE,\n DEFAULT_TIMEOUT,\n DIFFBOT_LLM_BASE,\n EXTRACT_BASE,\n KG_DQL_ENDPOINT,\n KG_ONTOLOGY_ENDPOINT,\n NLP_BASE,\n VERSION,\n WEB_SEARCH_BASE,\n} from \"./constants.js\";\nimport { ValidationError } from \"./errors.js\";\nimport { HttpClient, type FetchFn } from \"./http.js\";\n\nexport interface DiffbotClientOptions {\n token: string;\n timeout?: number;\n analyzeUrl?: string;\n llmUrl?: string;\n crawlerUrl?: string;\n webSearchUrl?: string;\n nlpUrl?: string;\n dqlUrl?: string;\n ontologyUrl?: string;\n fetch?: FetchFn;\n}\n\nexport class DiffbotClient {\n readonly token: string;\n readonly analyzeUrl: string;\n readonly llmUrl: string;\n readonly crawlerUrl: string;\n readonly webSearchUrl: string;\n readonly nlpUrl: string;\n readonly dqlUrl: string;\n readonly ontologyUrl: string;\n readonly http: HttpClient;\n\n constructor(options: DiffbotClientOptions) {\n if (!options.token) {\n throw new ValidationError(\"token is required\");\n }\n this.token = options.token;\n this.analyzeUrl = options.analyzeUrl ?? EXTRACT_BASE;\n this.llmUrl = options.llmUrl ?? DIFFBOT_LLM_BASE;\n this.crawlerUrl = options.crawlerUrl ?? CRAWL_BASE;\n this.webSearchUrl = options.webSearchUrl ?? WEB_SEARCH_BASE;\n this.nlpUrl = options.nlpUrl ?? NLP_BASE;\n this.dqlUrl = options.dqlUrl ?? KG_DQL_ENDPOINT;\n this.ontologyUrl = options.ontologyUrl ?? KG_ONTOLOGY_ENDPOINT;\n this.http = new HttpClient(\n options.fetch ?? fetch,\n options.timeout ?? DEFAULT_TIMEOUT,\n `diffbot-typescript/${VERSION}`,\n );\n }\n\n async close(): Promise<void> {\n await this.http.close();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n","import { TOKEN_ENV_VAR } from \"./constants.js\";\n\n/*\n * `object`, not `Record<string, unknown>`: a typed Workers `Env` is normally\n * an `interface`, and interfaces don't get TypeScript's implicit index\n * signature, so a `Record<string, unknown>` parameter would reject exactly\n * the argument this function exists to accept. `object` has no members, so\n * any object type is assignable to it; the bracket access below is cast\n * internally instead.\n */\nexport type TokenSource = object;\n\nfunction envToken(env: TokenSource | undefined): string {\n const fromEnv = (env as Record<string, unknown> | undefined)?.[TOKEN_ENV_VAR];\n if (typeof fromEnv === \"string\" && fromEnv.trim()) {\n return fromEnv.trim();\n }\n\n /*\n * Guarded rather than a static `process.env` read: `process` does not exist\n * in Workers/browsers, and touching it unconditionally would reintroduce a\n * runtime-specific dependency into an otherwise platform-neutral module.\n */\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n const fromProcess = proc?.env?.[TOKEN_ENV_VAR];\n return fromProcess?.trim() ?? \"\";\n}\n\n/**\n * Resolve a Diffbot API token from an explicit arg, then a Workers-style\n * `env` object, then `process.env`. Does not touch the filesystem — for a\n * credentials-file fallback, use `resolveToken` from `@diffbot/typescript/node`.\n */\nexport function resolveTokenFromEnv(token?: string | null, env?: TokenSource): string {\n if (token?.trim()) {\n return token.trim();\n }\n return envToken(env);\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { ExtractionError } from \"./errors.js\";\nimport { raiseForStatus, readBodyText } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nfunction buildParams(client: DiffbotClient, url: string, fmt: string) {\n const params: Record<string, string | number> = {\n token: client.token,\n url,\n timeout: 30_000,\n };\n if (fmt === \"markdown\") {\n params.mode = \"llm\";\n }\n return params;\n}\n\nfunction parseResponse(data: JsonObject): JsonObject {\n if (\"errorCode\" in data) {\n throw new ExtractionError(\n Number(data.errorCode),\n String(data.error ?? \"\"),\n );\n }\n return data;\n}\n\nfunction normalizeUrl(url: string): string {\n return url.startsWith(\"http\") ? url : `https://${url}`;\n}\n\nexport async function extract(\n client: DiffbotClient,\n url: string,\n api = \"analyze\",\n fmt = \"markdown\",\n): Promise<JsonObject> {\n const normalized = normalizeUrl(url);\n const response = await client.http.get(`${client.analyzeUrl}/${api}`, {\n params: buildParams(client, normalized, fmt),\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return parseResponse(JSON.parse(body) as JsonObject);\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { ValidationError } from \"./errors.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nexport interface ChatMessage {\n role: string;\n content: string;\n}\n\nconst MODEL = \"diffbot-small-xl\";\n\n/** `response_format` types accepted by the Diffbot LLM endpoint. */\nexport const RESPONSE_FORMAT_TYPES = [\"text\", \"json_object\", \"json_schema\"] as const;\nexport type ResponseFormatType = (typeof RESPONSE_FORMAT_TYPES)[number];\n\nexport interface ResponseFormat {\n type: ResponseFormatType;\n json_schema?: { name?: string; schema: JsonObject };\n}\n\nexport interface AskOptions {\n /**\n * Constrain the output, e.g. `{ type: \"json_object\" }` or `jsonSchemaFormat(schema)`.\n * Prefer a schema: `json_object` applies no server-side grammar.\n */\n responseFormat?: ResponseFormat;\n}\n\n/**\n * Build a `response_format` that constrains output to `schema`. The endpoint requires\n * the schema nested under `json_schema.schema`; anywhere else is ignored server-side\n * without an error, so prefer this helper over hand-building the object.\n */\nexport function jsonSchemaFormat(schema: JsonObject, name = \"response\"): ResponseFormat {\n if (schema === null || typeof schema !== \"object\" || Array.isArray(schema)) {\n throw new ValidationError(\"schema must be a JSON Schema object\");\n }\n return { type: \"json_schema\", json_schema: { name, schema } };\n}\n\n/** Reject shapes the endpoint would accept but silently not enforce. */\nfunction validateResponseFormat(responseFormat: ResponseFormat | undefined): void {\n if (responseFormat === undefined) return;\n if (responseFormat === null || typeof responseFormat !== \"object\" || Array.isArray(responseFormat)) {\n throw new ValidationError(\"responseFormat must be an object\");\n }\n const fmtType = responseFormat.type ?? \"text\";\n if (!(RESPONSE_FORMAT_TYPES as readonly string[]).includes(fmtType)) {\n throw new ValidationError(\n `responseFormat type must be one of ${RESPONSE_FORMAT_TYPES.join(\", \")}; got ${JSON.stringify(fmtType)}`,\n );\n }\n if (fmtType === \"json_schema\") {\n const jsonSchema = responseFormat.json_schema;\n if (jsonSchema === null || typeof jsonSchema !== \"object\" || !(\"schema\" in jsonSchema)) {\n throw new ValidationError(\n 'responseFormat { type: \"json_schema\" } requires the schema nested as ' +\n \"{ json_schema: { schema: {...} } }. Without it the server returns 200 and \" +\n \"ignores the constraint. Use jsonSchemaFormat(schema) to build it.\",\n );\n }\n }\n}\n\n// The RAG loop may prefix its final answer with a think block, and the model\n// occasionally wraps JSON in a markdown fence despite being told not to.\nconst THINK_BLOCK = /<think>[\\s\\S]*?<\\/think>/g;\nconst JSON_FENCE = /^```(?:json)?\\s*|\\s*```$/gm;\n\n/** Parse the model's final answer as JSON, tolerating think blocks and fences. */\nexport function extractJson(text: string): unknown {\n let cleaned = text.replace(THINK_BLOCK, \"\").trim();\n cleaned = cleaned.replace(JSON_FENCE, \"\").trim();\n\n try {\n return JSON.parse(cleaned);\n } catch {\n // fall through to span search\n }\n\n // Fall back to the outermost object or array span in the response.\n const spans: Array<[number, string]> = [];\n for (const [opener, closer] of [\n [\"{\", \"}\"],\n [\"[\", \"]\"],\n ] as const) {\n const start = cleaned.indexOf(opener);\n const end = cleaned.lastIndexOf(closer);\n if (start !== -1 && end > start) spans.push([start, cleaned.slice(start, end + 1)]);\n }\n spans.sort((a, b) => a[0] - b[0]);\n for (const [, span] of spans) {\n try {\n return JSON.parse(span);\n } catch {\n continue;\n }\n }\n\n throw new ValidationError(\n `could not parse JSON from the model response: ${JSON.stringify(text.slice(0, 200))}`,\n );\n}\n\n/**\n * Schema used when the caller wants JSON but has no shape in mind. This goes through\n * the json_schema path rather than `{ type: \"json_object\" }` on purpose: json_object\n * applies no server-side grammar, so the RAG loop's internal <functioncall> JSON\n * satisfies it and gets returned as the final answer. That is reproducible whenever\n * the request carries a system message.\n */\nexport const ANY_OBJECT_SCHEMA: JsonObject = { type: \"object\" };\n\nfunction resolveFormat(\n schema: JsonObject | undefined,\n responseFormat: ResponseFormat | undefined,\n): ResponseFormat {\n if (schema !== undefined && responseFormat !== undefined) {\n throw new ValidationError(\"pass either schema or responseFormat, not both\");\n }\n if (responseFormat !== undefined) return responseFormat;\n return jsonSchemaFormat(schema ?? ANY_OBJECT_SCHEMA);\n}\n\n/** Catch the internal tool call surfacing as the answer (see ANY_OBJECT_SCHEMA). */\nfunction checkToolCallLeak<T>(parsed: T): T {\n if (\n parsed !== null &&\n typeof parsed === \"object\" &&\n !Array.isArray(parsed) &&\n (parsed as JsonObject).name === \"functioncall\" &&\n \"arguments\" in (parsed as JsonObject)\n ) {\n throw new ValidationError(\n \"the model returned its internal tool call instead of an answer; this happens with \" +\n 'responseFormat { type: \"json_object\" } because the server applies no grammar to it. ' +\n \"Pass a schema instead.\",\n );\n }\n return parsed;\n}\n\nfunction parseChunk(line: string): string | undefined {\n try {\n const chunk = JSON.parse(line.replace(/^data: /, \"\")) as {\n choices?: Array<{ delta?: { content?: string } }>;\n };\n const content = chunk.choices?.[0]?.delta?.content;\n return content ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction* linesFromText(text: string): Generator<string> {\n for (const line of text.split(\"\\n\")) {\n if (line) yield line;\n }\n}\n\nasync function* linesFromStream(body: ReadableStream<Uint8Array>): AsyncGenerator<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\");\n buffer = parts.pop() ?? \"\";\n for (const line of parts) {\n if (line) yield line;\n }\n }\n if (buffer) yield buffer;\n}\n\nexport async function* ask(\n client: DiffbotClient,\n messages: ChatMessage[],\n options: AskOptions = {},\n): AsyncGenerator<string> {\n validateResponseFormat(options.responseFormat);\n const headers = { Authorization: `Bearer ${client.token}` };\n const payload: JsonObject = { model: MODEL, messages, stream: true };\n if (options.responseFormat !== undefined) payload.response_format = options.responseFormat;\n\n const response = await client.http.post(client.llmUrl, { headers, json: payload });\n if (!response.ok) {\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return;\n }\n\n if (response.body) {\n for await (const line of linesFromStream(response.body)) {\n const content = parseChunk(line);\n if (content) yield content;\n }\n return;\n }\n\n const text = await response.text();\n for (const line of linesFromText(text)) {\n const content = parseChunk(line);\n if (content) yield content;\n }\n}\n\n/**\n * Ask the Diffbot LLM and return the answer parsed as JSON. With `schema` (a JSON Schema\n * object) the model is constrained to it by grammar; without one it falls back to\n * unconstrained JSON output. Pass `responseFormat` instead of `schema` for full control.\n */\nexport async function askJson<T = unknown>(\n client: DiffbotClient,\n messages: ChatMessage[],\n schema?: JsonObject,\n options: AskOptions = {},\n): Promise<T> {\n const responseFormat = resolveFormat(schema, options.responseFormat);\n let text = \"\";\n for await (const chunk of ask(client, messages, { responseFormat })) text += chunk;\n return checkToolCallLeak(extractJson(text)) as T;\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { APIError } from \"./errors.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nexport enum CrawlEventType {\n JobCreated = \"job_created\",\n UrlProcessed = \"url_processed\",\n}\n\nexport interface CrawlEvent {\n eventType: CrawlEventType;\n timestamp: string;\n details: JsonObject;\n}\n\nexport interface CrawlOptions {\n hops?: number;\n jobName?: string;\n maxToCrawl?: number;\n maxToProcess?: number;\n restrictDomain?: boolean;\n apiUrl?: string;\n crawlDelay?: number;\n urlCrawlPattern?: string;\n urlProcessPattern?: string;\n obeyRobots?: boolean;\n useProxies?: boolean;\n customHeaders?: string;\n watch?: boolean;\n pollInterval?: number;\n}\n\nfunction buildCrawlParams(\n client: DiffbotClient,\n jobName: string,\n site: string,\n options: Required<Pick<CrawlOptions, \"maxToCrawl\" | \"maxToProcess\" | \"hops\" | \"restrictDomain\" | \"apiUrl\" | \"crawlDelay\" | \"obeyRobots\" | \"useProxies\">> &\n Pick<CrawlOptions, \"urlCrawlPattern\" | \"urlProcessPattern\" | \"customHeaders\">,\n) {\n const params: Record<string, string | number> = {\n token: client.token,\n name: jobName,\n seeds: site,\n maxToCrawl: options.maxToCrawl,\n maxToProcess: options.maxToProcess,\n maxHops: options.hops,\n restrictDomain: options.restrictDomain ? 1 : 0,\n };\n if (options.apiUrl) params.apiUrl = options.apiUrl;\n if (options.crawlDelay > 0) params.crawlDelay = options.crawlDelay;\n if (options.urlCrawlPattern) params.urlCrawlPattern = options.urlCrawlPattern;\n if (options.urlProcessPattern) params.urlProcessPattern = options.urlProcessPattern;\n if (options.obeyRobots) params.obeyRobots = 1;\n if (options.useProxies) params.useProxies = 1;\n if (options.customHeaders) params.customHeaders = options.customHeaders;\n return params;\n}\n\nfunction parseUrlCsv(text: string, seenUrls: Set<string>): CrawlEvent[] {\n const events: CrawlEvent[] = [];\n const lines = text.trim().split(\"\\n\");\n if (lines.length < 2) return events;\n\n const headers = lines[0]!.split(\",\").map((h) => h.trim());\n const urlIdx = headers.indexOf(\"Url\");\n const timeIdx = headers.indexOf(\"Crawled Time\");\n const statusIdx = headers.indexOf(\"Crawl Status\");\n\n for (const line of lines.slice(1)) {\n const cols = line.split(\",\");\n const url = cols[urlIdx]?.replace(/^\"|\"$/g, \"\").trim() ?? \"\";\n if (url && !seenUrls.has(url)) {\n seenUrls.add(url);\n events.push({\n eventType: CrawlEventType.UrlProcessed,\n timestamp: cols[timeIdx]?.trim() ?? new Date().toISOString(),\n details: {\n url,\n status: cols[statusIdx]?.trim() ?? \"unknown\",\n },\n });\n }\n }\n return events;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function* crawl(\n client: DiffbotClient,\n site: string,\n options: CrawlOptions = {},\n): AsyncGenerator<CrawlEvent> {\n let normalizedSite = site.startsWith(\"http\") ? site : `https://${site}`;\n const jobName = options.jobName ?? `crawl-${Math.floor(Date.now() / 1000)}`;\n\n const params = buildCrawlParams(client, jobName, normalizedSite, {\n hops: options.hops ?? 2,\n maxToCrawl: options.maxToCrawl ?? 100,\n maxToProcess: options.maxToProcess ?? 100,\n restrictDomain: options.restrictDomain ?? true,\n apiUrl: options.apiUrl ?? \"\",\n crawlDelay: options.crawlDelay ?? -1,\n urlCrawlPattern: options.urlCrawlPattern,\n urlProcessPattern: options.urlProcessPattern,\n obeyRobots: options.obeyRobots ?? false,\n useProxies: options.useProxies ?? false,\n customHeaders: options.customHeaders,\n });\n\n const response = await client.http.get(client.crawlerUrl, { params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n\n yield {\n eventType: CrawlEventType.JobCreated,\n timestamp: new Date().toISOString(),\n details: { job_name: jobName },\n };\n\n if (!options.watch) {\n return;\n }\n\n const seenUrls = new Set<string>();\n const pollInterval = options.pollInterval ?? 2000;\n\n while (true) {\n const statusResponse = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName },\n });\n const statusBody = await readBodyText(statusResponse);\n raiseForStatus(statusResponse, statusBody);\n const jobs = (JSON.parse(statusBody) as JsonObject).jobs as JsonObject[] | undefined;\n if (!jobs?.length) break;\n\n const jobStatus = (jobs[0]!.jobStatus ?? {}) as JsonObject;\n const statusCode = Number(jobStatus.status ?? 0);\n\n const urlsResponse = await client.http.get(`${client.crawlerUrl}/data`, {\n params: { token: client.token, name: jobName, type: \"urls\" },\n redirect: \"follow\",\n });\n const urlsBody = await readBodyText(urlsResponse);\n raiseForStatus(urlsResponse, urlsBody);\n if (urlsBody) {\n for (const event of parseUrlCsv(urlsBody, seenUrls)) {\n yield event;\n }\n }\n\n if (statusCode !== 0 && statusCode !== 7) {\n const message = String(jobStatus.message ?? \"\");\n if (/fail|error/i.test(message)) {\n throw new APIError(500, `Crawler job failed: ${message}`);\n }\n break;\n }\n\n await sleep(pollInterval);\n }\n}\n\nexport async function crawlListJobs(client: DiffbotClient): Promise<JsonObject[]> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return ((JSON.parse(body) as JsonObject).jobs as JsonObject[] | undefined) ?? [];\n}\n\nexport async function crawlGetJob(client: DiffbotClient, jobName: string): Promise<JsonObject> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n const jobs = (JSON.parse(body) as JsonObject).jobs as JsonObject[] | undefined;\n return jobs?.[0] ?? {};\n}\n\nexport async function crawlDeleteJob(client: DiffbotClient, jobName: string): Promise<void> {\n const response = await client.http.get(client.crawlerUrl, {\n params: { token: client.token, name: jobName, delete: 1 },\n });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n}\n","import type { JsonObject } from \"./json.js\";\n\ntype FieldMeta = JsonObject;\ntype FieldEntry = [string, FieldMeta];\n\nexport class Ontology {\n readonly data: JsonObject;\n\n constructor(data: JsonObject) {\n this.data = data;\n }\n\n static fromJson(raw: string | Uint8Array): Ontology {\n const text = typeof raw === \"string\" ? raw : new TextDecoder().decode(raw);\n return new Ontology(JSON.parse(text) as JsonObject);\n }\n\n types(): string[] {\n const types = this.data.types as Record<string, unknown> | undefined;\n return Object.keys(types ?? {}).sort();\n }\n\n composites(): string[] {\n const composites = this.data.composites as Record<string, unknown> | undefined;\n return Object.keys(composites ?? {}).sort();\n }\n\n enums(): string[] {\n const enums = this.data.enums as Record<string, unknown> | undefined;\n return Object.keys(enums ?? {}).sort();\n }\n\n taxonomies(): string[] {\n const taxonomies = this.data.taxonomies as Record<string, unknown> | undefined;\n return Object.keys(taxonomies ?? {}).sort();\n }\n\n private static fieldsOf(container: Record<string, JsonObject>, typeName: string): Record<string, FieldMeta> {\n const entry = container[typeName];\n if (!entry) throw new Error(`Unknown name: ${typeName}`);\n return (entry.fields as Record<string, FieldMeta> | undefined) ?? {};\n }\n\n fieldsFor(typeName: string): Record<string, FieldMeta> {\n const types = (this.data.types ?? {}) as Record<string, JsonObject>;\n const composites = (this.data.composites ?? {}) as Record<string, JsonObject>;\n if (typeName in types) return Ontology.fieldsOf(types, typeName);\n if (typeName in composites) return Ontology.fieldsOf(composites, typeName);\n throw new Error(`${typeName} is not a known entity type or composite`);\n }\n\n static filterFields(\n fields: Record<string, FieldMeta>,\n search?: string | null,\n includeDeprecated = false,\n ): FieldEntry[] {\n const pattern = search ? new RegExp(search, \"i\") : null;\n const out: FieldEntry[] = [];\n for (const [name, meta] of Object.entries(fields)) {\n if (!includeDeprecated && meta.isDeprecated) continue;\n if (pattern && !pattern.test(name)) continue;\n out.push([name, meta]);\n }\n return out;\n }\n\n taxonomyValues(name: string, search?: string | null): string[] {\n const taxonomies = (this.data.taxonomies ?? {}) as Record<string, JsonObject>;\n const tax = taxonomies[name];\n if (!tax) throw new Error(`Unknown taxonomy: ${name}`);\n\n const pattern = search ? new RegExp(search, \"i\") : null;\n const out: string[] = [];\n\n const walk = (node: JsonObject): void => {\n const n = node.name;\n if (typeof n === \"string\" && (!pattern || pattern.test(n))) {\n out.push(n);\n }\n for (const child of (node.children as JsonObject[] | undefined) ?? []) {\n walk(child);\n }\n };\n\n for (const cat of (tax.categories as JsonObject[] | undefined) ?? []) {\n walk(cat);\n }\n return out;\n }\n\n enumValues(name: string): string[] {\n const enums = (this.data.enums ?? {}) as Record<string, JsonObject>;\n const enumEntry = enums[name];\n if (!enumEntry) throw new Error(`Unknown enum: ${name}`);\n return [...((enumEntry.values as string[] | undefined) ?? [])];\n }\n\n findNamed(search: string): string[] {\n const pattern = new RegExp(search, \"i\");\n const found = new Set<string>();\n\n const walk = (node: unknown): void => {\n if (Array.isArray(node)) {\n for (const v of node) walk(v);\n } else if (node && typeof node === \"object\") {\n const obj = node as JsonObject;\n const n = obj.name;\n if (typeof n === \"string\" && pattern.test(n)) found.add(n);\n for (const v of Object.values(obj)) walk(v);\n }\n };\n\n walk(this.data);\n return [...found].sort();\n }\n\n static formatField(name: string, meta: FieldMeta): string {\n let typeName = String(meta.type ?? \"?\");\n if (typeName === \"LinkedEntity\") {\n const le = meta.leType as string[] | undefined;\n if (le?.length) typeName = `LinkedEntity (${le[0]})`;\n }\n const flags: string[] = [];\n if (meta.isList) flags.push(\"isList\");\n if (meta.isComposite) flags.push(\"isComposite\");\n if (meta.isEnum) flags.push(\"isEnum\");\n if (meta.isDeprecated) flags.push(\"DEPRECATED\");\n const suffix = flags.map((f) => ` [${f}]`).join(\"\");\n return `${name}: [${typeName}]${suffix}`;\n }\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\nimport { Ontology } from \"./ontology.js\";\n\nexport interface DqlOptions {\n size?: number;\n from?: number;\n format?: string;\n filter?: string;\n exportspec?: string;\n extra?: Record<string, string>;\n raw?: boolean;\n}\n\nfunction buildDqlParams(\n client: DiffbotClient,\n query: string,\n options: DqlOptions,\n): Record<string, string | number> {\n const params: Record<string, string | number> = {\n token: client.token,\n query,\n size: options.size ?? 10,\n };\n if (options.from) params.from = options.from;\n if (options.format && options.format !== \"json\") params.format = options.format;\n if (options.filter !== undefined) params.filter = options.filter;\n if (options.exportspec !== undefined) params.exportspec = options.exportspec;\n if (options.extra) Object.assign(params, options.extra);\n return params;\n}\n\nexport async function dql(\n client: DiffbotClient,\n query: string,\n options: DqlOptions = {},\n): Promise<JsonObject | Uint8Array> {\n const params = buildDqlParams(client, query, options);\n const response = await client.http.get(client.dqlUrl, { params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n if (options.raw) {\n return new TextEncoder().encode(body);\n }\n return JSON.parse(body) as JsonObject;\n}\n\nexport async function dqlParallel(\n client: DiffbotClient,\n queries: Array<DqlOptions & { query: string }>,\n workers = 8,\n): Promise<Array<JsonObject | Uint8Array>> {\n if (!queries.length) return [];\n\n const limit = Math.min(workers, queries.length);\n const results: Array<JsonObject | Uint8Array> = new Array(queries.length);\n let index = 0;\n\n async function worker(): Promise<void> {\n while (true) {\n const current = index++;\n if (current >= queries.length) return;\n const { query, ...opts } = queries[current]!;\n results[current] = await dql(client, query, opts);\n }\n }\n\n await Promise.all(Array.from({ length: limit }, () => worker()));\n return results;\n}\n\n/** Fetch the raw ontology JSON text. For a parsed, cached `Ontology`, see `OntologyStore`. */\nexport async function dqlFetchOntologyText(client: DiffbotClient): Promise<string> {\n const response = await client.http.get(client.ontologyUrl);\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return body;\n}\n\nexport async function dqlFetchOntology(client: DiffbotClient): Promise<Ontology> {\n return Ontology.fromJson(await dqlFetchOntologyText(client));\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\nconst NLP_FIELDS = \"entities,sentiment\";\n\nexport async function entities(\n client: DiffbotClient,\n text: string,\n lang = \"auto\",\n): Promise<JsonObject> {\n const params = { token: client.token, fields: NLP_FIELDS };\n const payload = [{ lang, format: \"plain text\", content: text }];\n const response = await client.http.post(client.nlpUrl, { params, json: payload });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n const data = JSON.parse(body) as JsonObject | JsonObject[];\n return Array.isArray(data) ? (data[0] ?? {}) : data;\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { dqlFetchOntologyText } from \"./kg.js\";\nimport { Ontology } from \"./ontology.js\";\n\nexport interface OntologyStoreOptions {\n /**\n * How long a cached entry should be kept, in seconds. Default 86_400 (24h).\n * The base `OntologyStore` doesn't expire its in-memory cache on its own —\n * an explicit `refresh: true` is the only way to bust it — so this only\n * takes effect in subclasses backed by a store with real expiration, like\n * `KVOntologyStore` (where it becomes the KV entry's `expirationTtl`).\n */\n ttlSeconds?: number;\n}\n\n/**\n * Fetches and caches the Diffbot KG ontology for a client. The base class\n * caches only in memory, for the lifetime of the instance; subclasses\n * override `read`/`write` to back the cache with a durable store (a\n * filesystem, a KV namespace, ...).\n */\nexport class OntologyStore {\n readonly client: DiffbotClient;\n protected readonly ttlSeconds: number;\n private inFlight: Promise<Ontology> | null = null;\n\n constructor(client: DiffbotClient, options: OntologyStoreOptions = {}) {\n this.client = client;\n this.ttlSeconds = options.ttlSeconds ?? 86_400;\n }\n\n /**\n * Resolve the ontology, from cache when possible. Concurrent calls share\n * one in-flight fetch rather than issuing duplicate requests; a rejected\n * fetch clears the in-flight memo so the next call retries instead of\n * replaying the same failure forever.\n */\n load(options: { refresh?: boolean } = {}): Promise<Ontology> {\n if (options.refresh) {\n this.inFlight = null;\n }\n if (!this.inFlight) {\n this.inFlight = this.resolve(options.refresh ?? false).catch((error: unknown) => {\n this.inFlight = null;\n throw error;\n });\n }\n return this.inFlight;\n }\n\n private async resolve(refresh: boolean): Promise<Ontology> {\n if (!refresh) {\n const cached = await this.read();\n if (cached !== undefined) {\n try {\n return Ontology.fromJson(cached);\n } catch {\n /* Corrupt cache entry: fall through to a live fetch below. */\n }\n }\n }\n const text = await dqlFetchOntologyText(this.client);\n await this.write(text);\n return Ontology.fromJson(text);\n }\n\n /** Read the cached ontology text, or `undefined` on a miss. Memory-only by default. */\n protected read(): Promise<string | undefined> {\n return Promise.resolve(undefined);\n }\n\n /** Persist ontology text after a fetch. No-op by default. */\n protected write(_text: string): Promise<void> {\n return Promise.resolve();\n }\n}\n\n/**\n * Structurally typed rather than importing `@cloudflare/workers-types`, so\n * the SDK takes no Cloudflare dependency — a `KVNamespace` binding satisfies\n * this directly.\n */\nexport interface KVLike {\n get(key: string): Promise<string | null>;\n put(key: string, value: string, options?: { expirationTtl?: number }): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\nexport interface KVOntologyStoreOptions extends OntologyStoreOptions {\n /** Default `\"diffbot:ontology:v1\"`. Bump the suffix to force cache invalidation on a schema change. */\n key?: string;\n /**\n * After this many seconds, a cached entry is served immediately while a\n * refresh runs behind it (stale-while-revalidate) instead of being trusted\n * outright. 0 (default) disables SWR — a cached entry is trusted for its\n * full `ttlSeconds`. Should be less than `ttlSeconds`, or the KV entry\n * expires before it is ever considered stale.\n */\n staleAfterSeconds?: number;\n /**\n * TTL on the refresh lock that prevents concurrent refetches (cron, SWR,\n * manual). Default 60s — Cloudflare KV rejects `expirationTtl` below 60.\n */\n lockTtlSeconds?: number;\n /**\n * `ExecutionContext.waitUntil`. Without it, a background stale-while-revalidate\n * refresh is killed as soon as the response is returned, so SWR degrades to a\n * blocking refresh-on-expiry.\n */\n waitUntil?: (promise: Promise<unknown>) => void;\n}\n\n/**\n * KV-backed ontology cache for Cloudflare Workers. Ports the stampede\n * protection and stale-while-revalidate behavior of a production Worker's\n * hand-rolled ontology cache: a short-lived lock key prevents concurrent\n * refreshes from cron, SWR, and a manual refresh all refetching at once, and\n * a `refreshed_at` companion key lets a stale entry be served immediately\n * while a refresh runs in the background.\n */\nexport class KVOntologyStore extends OntologyStore {\n private readonly kv: KVLike;\n private readonly key: string;\n private readonly refreshedAtKey: string;\n private readonly lockKey: string;\n private readonly staleAfterSeconds: number;\n private readonly lockTtlSeconds: number;\n private readonly waitUntil: ((promise: Promise<unknown>) => void) | undefined;\n\n constructor(client: DiffbotClient, kv: KVLike, options: KVOntologyStoreOptions = {}) {\n super(client, options);\n this.kv = kv;\n this.key = options.key ?? \"diffbot:ontology:v1\";\n this.refreshedAtKey = `${this.key}:refreshed_at`;\n this.lockKey = `${this.key}:lock`;\n this.staleAfterSeconds = options.staleAfterSeconds ?? 0;\n this.lockTtlSeconds = options.lockTtlSeconds ?? 60;\n this.waitUntil = options.waitUntil;\n }\n\n override load(options: { refresh?: boolean } = {}): Promise<Ontology> {\n if (!options.refresh && this.staleAfterSeconds > 0) {\n return this.loadWithStaleWhileRevalidate();\n }\n return super.load(options);\n }\n\n private async loadWithStaleWhileRevalidate(): Promise<Ontology> {\n const [cached, refreshedAt] = await Promise.all([\n this.kv.get(this.key),\n this.kv.get(this.refreshedAtKey),\n ]);\n if (cached === null) {\n return super.load();\n }\n\n const age = refreshedAt ? (Date.now() - Number(refreshedAt)) / 1000 : Infinity;\n const isStale = age > this.staleAfterSeconds;\n const ontology = Ontology.fromJson(cached);\n\n if (isStale) {\n const refresh = super.load({ refresh: true }).catch(() => {\n /* Stale value already served; a failed background refresh just retries next time. */\n });\n if (this.waitUntil) {\n this.waitUntil(refresh);\n } else {\n await refresh;\n return super.load();\n }\n }\n\n return ontology;\n }\n\n protected override async read(): Promise<string | undefined> {\n const cached = await this.kv.get(this.key);\n return cached ?? undefined;\n }\n\n protected override async write(text: string): Promise<void> {\n /* Lock prevents concurrent refreshes from all refetching the same large payload. */\n if (await this.kv.get(this.lockKey)) {\n return;\n }\n await this.kv.put(this.lockKey, \"1\", { expirationTtl: this.lockTtlSeconds });\n try {\n await this.kv.put(this.key, text, { expirationTtl: this.ttlSeconds });\n await this.kv.put(this.refreshedAtKey, String(Date.now()), {\n expirationTtl: this.ttlSeconds,\n });\n } finally {\n await this.kv.delete(this.lockKey);\n }\n }\n}\n","import type { DiffbotClient } from \"./client.js\";\nimport { ValidationError } from \"./errors.js\";\nimport { readBodyText, raiseForStatus } from \"./http.js\";\nimport type { JsonObject } from \"./json.js\";\n\n/** How much of each page's matching content the web search returns in `content`. */\nexport type SnippetLength = \"short\" | \"medium\" | \"long\" | \"full\";\n\nexport const SNIPPET_LENGTHS: readonly SnippetLength[] = [\"short\", \"medium\", \"long\", \"full\"];\n\nexport interface WebSearchOptions {\n numResults?: number;\n maxTokens?: number;\n /**\n * `short` keeps a result to ~1-1.5 KB; `long` is the API default; `full` returns the\n * whole stored page and is meant for `url:<URL>` queries. The reranker always chunks,\n * so `full` also sends `rerank=none` and query terms after the URL are ignored.\n */\n snippetLength?: SnippetLength;\n}\n\nexport async function webSearch(\n client: DiffbotClient,\n text: string,\n options: WebSearchOptions = {},\n): Promise<JsonObject> {\n const headers = { Authorization: `Bearer ${client.token}` };\n const params: Record<string, string | number> = { text };\n if (options.numResults !== undefined) params.size = options.numResults;\n if (options.maxTokens !== undefined) params.maxTokens = options.maxTokens;\n if (options.snippetLength !== undefined) {\n const length = options.snippetLength.toLowerCase() as SnippetLength;\n if (!SNIPPET_LENGTHS.includes(length)) {\n throw new ValidationError(\n `snippetLength must be one of ${SNIPPET_LENGTHS.join(\", \")}; got ${JSON.stringify(options.snippetLength)}`,\n );\n }\n params.snippetLength = length.toUpperCase();\n if (length === \"full\") params.rerank = \"none\";\n }\n\n const response = await client.http.get(client.webSearchUrl, { headers, params });\n const body = await readBodyText(response);\n raiseForStatus(response, body);\n return JSON.parse(body) as JsonObject;\n}\n"],"mappings":"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","names":["CrawlEventType"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -63,7 +63,46 @@ interface ChatMessage {
|
|
|
63
63
|
role: string;
|
|
64
64
|
content: string;
|
|
65
65
|
}
|
|
66
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
+
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:
|
|
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.
|
|
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
|
+
}
|