@oberik/sdk 0.65.0 → 0.67.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/dist/cjs/index.js +65 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.d.ts +108 -12
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +65 -9
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -758,6 +758,25 @@ function asBlob(input) {
|
|
|
758
758
|
// handing that straight to Blob can carry bytes belonging to something else.
|
|
759
759
|
return new Blob([bytes.slice()]);
|
|
760
760
|
}
|
|
761
|
+
/**
|
|
762
|
+
* The name a document is stored under: what the caller passed, the file's own, or a
|
|
763
|
+
* placeholder.
|
|
764
|
+
*
|
|
765
|
+
* One function for both clients, because they disagreed about it. The project client
|
|
766
|
+
* derived a name and fell back to `"upload.bin"`; the end-user client took `filename` in a
|
|
767
|
+
* **required** options object, so a JavaScript caller writing the documented
|
|
768
|
+
* `uploadAndWait(file)` got `TypeError: Cannot read properties of undefined (reading
|
|
769
|
+
* 'filename')` — thrown from inside the SDK, with nothing in the stack naming Oberik, at
|
|
770
|
+
* the reader most likely to have copied the snippet (OBE-195).
|
|
771
|
+
*
|
|
772
|
+
* Both are optional now and both land here. `"upload.bin"` rather than a refusal: a `File`
|
|
773
|
+
* carries its name and a Blob, Buffer or ArrayBuffer does not, and an upload that arrives
|
|
774
|
+
* with a placeholder name is visibly wrong in the listing, where a caller can fix it with
|
|
775
|
+
* `documents.update`. Pass `filename` — it is what the document is listed and cited under.
|
|
776
|
+
*/
|
|
777
|
+
function uploadName(file, filename) {
|
|
778
|
+
return filename || file?.name || "upload.bin";
|
|
779
|
+
}
|
|
761
780
|
/** Normalise whatever an `onQuestion` handler returned into an answer the API accepts.
|
|
762
781
|
*
|
|
763
782
|
* A handler returning a bare string was silently ignored. `{ ...answer }` on a string
|
|
@@ -2346,17 +2365,35 @@ export class AgentFramework {
|
|
|
2346
2365
|
},
|
|
2347
2366
|
};
|
|
2348
2367
|
documents = {
|
|
2368
|
+
/**
|
|
2369
|
+
* One PAGE of documents, newest first — `{ items, has_more, next_offset }`.
|
|
2370
|
+
*
|
|
2371
|
+
* It was a bare array, which asserts completeness by omission, on the one collection
|
|
2372
|
+
* that only grows: a live project of 302 documents returned all 302 and 181KB on every
|
|
2373
|
+
* call, and a 10k corpus would be ~6MB on a route a dashboard opens with (OBE-190).
|
|
2374
|
+
* `limit` defaults to 100 and is capped at 500; page with `next_offset`, which is given
|
|
2375
|
+
* rather than left as arithmetic because the cap can make `offset + limit` wrong.
|
|
2376
|
+
*
|
|
2377
|
+
* `with_total` adds a `total` and costs a second query — for a summary, not for paging.
|
|
2378
|
+
* "Is there another page" is `has_more`, and it is free.
|
|
2379
|
+
*/
|
|
2349
2380
|
list: (query = {}) => this.request("GET", "/documents", { query }),
|
|
2350
2381
|
get: (id) => this.request("GET", `/documents/${id}`),
|
|
2351
2382
|
delete: (id) => this.request("DELETE", `/documents/${id}`),
|
|
2352
2383
|
retrieve: (body) => this.request("POST", "/documents/retrieve", { body }),
|
|
2353
2384
|
/** Small-file convenience upload via multipart form (server proxies to S3). */
|
|
2354
|
-
uploadSimple: async (file,
|
|
2385
|
+
uploadSimple: async (file,
|
|
2386
|
+
// Optional, and the same shape the project client takes: this signature required an
|
|
2387
|
+
// options object, so `uploadSimple(file)` and `uploadAndWait(file)` — the way the
|
|
2388
|
+
// docs write them — threw a TypeError out of the SDK's own body instead of saying
|
|
2389
|
+
// what was missing (OBE-195).
|
|
2390
|
+
opts = {}) => {
|
|
2391
|
+
const filename = uploadName(file, opts.filename);
|
|
2355
2392
|
const form = new FormData();
|
|
2356
2393
|
const blob = typeof Blob !== "undefined" && file instanceof Blob
|
|
2357
2394
|
? file
|
|
2358
2395
|
: new Blob([file], { type: opts.contentType ?? "application/octet-stream" });
|
|
2359
|
-
form.append("file", blob,
|
|
2396
|
+
form.append("file", blob, filename);
|
|
2360
2397
|
form.append("tags", (opts.tags ?? []).join(","));
|
|
2361
2398
|
// Set visibility AT UPLOAD, not after: a document is retrievable as soon as
|
|
2362
2399
|
// ingestion finishes, so patching later leaves a window where it's readable by
|
|
@@ -2389,7 +2426,7 @@ export class AgentFramework {
|
|
|
2389
2426
|
return (await res.json());
|
|
2390
2427
|
},
|
|
2391
2428
|
/** Resumable presigned multipart upload (direct to S3). */
|
|
2392
|
-
upload: (file, opts) => this.multipartUpload(file, opts),
|
|
2429
|
+
upload: (file, opts = {}) => this.multipartUpload(file, opts),
|
|
2393
2430
|
/** Poll a document until ingestion finishes (status "ready" or "failed").
|
|
2394
2431
|
* Ingestion is async, so querying a just-uploaded doc may return nothing until
|
|
2395
2432
|
* this resolves. Throws on "failed" or timeout. */
|
|
@@ -2413,7 +2450,7 @@ export class AgentFramework {
|
|
|
2413
2450
|
// Takes the ACL fields too: this is the upload most callers use, so omitting them
|
|
2414
2451
|
// here forced a second `patch` and left a window where the document was already
|
|
2415
2452
|
// retrievable at its default visibility.
|
|
2416
|
-
opts) => {
|
|
2453
|
+
opts = {}) => {
|
|
2417
2454
|
const doc = await this.documents.uploadSimple(file, opts);
|
|
2418
2455
|
return this.documents.waitReady(doc.id, { timeoutMs: opts.timeoutMs, signal: opts.signal });
|
|
2419
2456
|
},
|
|
@@ -3074,7 +3111,7 @@ export class AgentFramework {
|
|
|
3074
3111
|
const maxRetries = opts.maxRetries ?? 5;
|
|
3075
3112
|
const presign = await this.request("POST", "/documents/presign-upload", {
|
|
3076
3113
|
body: {
|
|
3077
|
-
filename: opts.filename,
|
|
3114
|
+
filename: uploadName(file, opts.filename),
|
|
3078
3115
|
content_type: opts.contentType,
|
|
3079
3116
|
tags: opts.tags ?? [],
|
|
3080
3117
|
...(opts.visibility ? { visibility: opts.visibility } : {}),
|
|
@@ -3353,6 +3390,9 @@ export class OberikProject {
|
|
|
3353
3390
|
* turning citation markers off, meant dropping to raw HTTP through `raw()`.
|
|
3354
3391
|
*/
|
|
3355
3392
|
project = {
|
|
3393
|
+
/** The project, its capability ceiling and its settings — plus `readiness` and the
|
|
3394
|
+
* `health` / `healthDetail` badge, so "is this project working" is answered by the
|
|
3395
|
+
* first thing you fetch rather than one route further on. */
|
|
3356
3396
|
get: () => this.request("GET", ""),
|
|
3357
3397
|
/** Merges — send only what you want to change. */
|
|
3358
3398
|
set: (fields) => this.request("PATCH", "", fields),
|
|
@@ -3426,9 +3466,26 @@ export class OberikProject {
|
|
|
3426
3466
|
* accepted nor needed — a recipe that worked by luck rather than by expression.
|
|
3427
3467
|
*/
|
|
3428
3468
|
documents = {
|
|
3429
|
-
/**
|
|
3469
|
+
/**
|
|
3470
|
+
* One PAGE of the corpus — the same envelope, the same filters and the same paging as
|
|
3471
|
+
* the end-user client's `documents.list`, because they are the same route.
|
|
3472
|
+
*
|
|
3473
|
+
* The route became a page in OBE-190 and this declaration did not move with it: it
|
|
3474
|
+
* still said `Promise<DocumentOut[]>`, so a TypeScript caller wrote `.length` and got
|
|
3475
|
+
* `undefined` with no type error and no exception — a census that counted documents
|
|
3476
|
+
* reported zero. That is OBE-147 verbatim, one collection over, and the docstring
|
|
3477
|
+
* describing it sits sixty lines above this one (OBE-195). The query type had the
|
|
3478
|
+
* mirror-image gap: `limit`/`offset` worked at runtime and were unwritable in
|
|
3479
|
+
* TypeScript, so the documented paging loop did not compile against the client that
|
|
3480
|
+
* recommends it.
|
|
3481
|
+
*
|
|
3482
|
+
* `with_total` adds a `total`; it is what "how big is this corpus" is asked with, and
|
|
3483
|
+
* it costs a second query. "Is there another page" is `has_more`, and it is free.
|
|
3484
|
+
*/
|
|
3430
3485
|
list: (query = {}) => {
|
|
3431
|
-
const qs = new URLSearchParams(Object.entries(query)
|
|
3486
|
+
const qs = new URLSearchParams(Object.entries(query)
|
|
3487
|
+
.filter(([, v]) => v != null)
|
|
3488
|
+
.map(([k, v]) => [k, String(v)])).toString();
|
|
3432
3489
|
return this.request("GET", `/documents${qs ? `?${qs}` : ""}`);
|
|
3433
3490
|
},
|
|
3434
3491
|
get: (documentId) => this.request("GET", `/documents/${documentId}`),
|
|
@@ -3473,8 +3530,7 @@ export class OberikProject {
|
|
|
3473
3530
|
*/
|
|
3474
3531
|
opts = {}) => {
|
|
3475
3532
|
const form = new FormData();
|
|
3476
|
-
|
|
3477
|
-
form.append("file", asBlob(file), name);
|
|
3533
|
+
form.append("file", asBlob(file), uploadName(file, opts.filename));
|
|
3478
3534
|
form.append("tags", (opts.tags ?? []).join(","));
|
|
3479
3535
|
if (opts.visibility)
|
|
3480
3536
|
form.append("visibility", opts.visibility);
|