@babav/knowledge-core-client 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +51 -106
- package/dist/index.js +48 -35
- package/package.json +1 -1
- package/src/index.ts +74 -99
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Babav Knowledge Core — TypeScript client.
|
|
3
3
|
*
|
|
4
|
-
* Portable: uses the global `fetch` + `ReadableStream`, so it
|
|
5
|
-
* Supabase Edge Functions (Deno) and Railway (Node 18+). Zero
|
|
4
|
+
* Portable: uses the global `fetch`, `FormData`, `Blob` + `ReadableStream`, so it
|
|
5
|
+
* runs unchanged in Supabase Edge Functions (Deno) and Railway (Node 18+). Zero
|
|
6
|
+
* dependencies.
|
|
6
7
|
*
|
|
7
8
|
* Wire shapes are snake_case to mirror the Knowledge Core API 1:1 — so an API
|
|
8
9
|
* change is reflected here with a one-to-one type edit and never drifts.
|
|
9
10
|
*
|
|
10
|
-
* Auth: every call carries an X-API-Key. Use
|
|
11
|
-
* all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
12
|
-
* management. The key is server-side only — never ship it to a browser.
|
|
11
|
+
* Auth: every call carries an X-API-Key. Use KnowledgeCoreClient with a TENANT
|
|
12
|
+
* key for all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
13
|
+
* agent management. The key is server-side only — never ship it to a browser.
|
|
13
14
|
*/
|
|
14
15
|
export type UUID = string;
|
|
15
16
|
export interface Page<T> {
|
|
@@ -18,6 +19,8 @@ export interface Page<T> {
|
|
|
18
19
|
}
|
|
19
20
|
export type Visibility = "downloadable" | "viewable" | "attributable" | "hidden";
|
|
20
21
|
export type FilterOp = "eq" | "ne" | "in" | "nin" | "gt" | "gte" | "lt" | "lte" | "exists";
|
|
22
|
+
/** Raw file input accepted by upload/parse helpers. */
|
|
23
|
+
export type FileData = Blob | Uint8Array | ArrayBuffer;
|
|
21
24
|
export interface FilterClause {
|
|
22
25
|
field: string;
|
|
23
26
|
op: FilterOp;
|
|
@@ -80,53 +83,45 @@ export interface Groundedness {
|
|
|
80
83
|
}
|
|
81
84
|
export interface Corpus {
|
|
82
85
|
id: UUID;
|
|
83
|
-
tenant_id: UUID | null;
|
|
84
86
|
name: string;
|
|
85
87
|
description: string | null;
|
|
86
|
-
embedding_model: string;
|
|
87
|
-
external_ref: string | null;
|
|
88
|
-
created_at: string;
|
|
89
|
-
updated_at: string;
|
|
90
88
|
}
|
|
91
89
|
export interface Folder {
|
|
92
90
|
id: UUID;
|
|
93
91
|
corpus_id: UUID;
|
|
94
92
|
name: string;
|
|
95
|
-
is_default: boolean;
|
|
96
|
-
created_at: string;
|
|
97
|
-
updated_at: string;
|
|
98
93
|
}
|
|
99
94
|
export interface Document {
|
|
100
95
|
id: UUID;
|
|
101
96
|
corpus_id: UUID;
|
|
102
97
|
folder_id: UUID;
|
|
103
|
-
source_uri: string;
|
|
104
98
|
status: string;
|
|
105
99
|
visibility: Visibility;
|
|
106
100
|
content_type: string | null;
|
|
107
101
|
filename: string | null;
|
|
108
|
-
parse_job_id: UUID | null;
|
|
109
102
|
chunk_count: number;
|
|
110
|
-
datapoint_ids: string[];
|
|
111
103
|
custom_metadata: Record<string, unknown>;
|
|
112
104
|
error: string | null;
|
|
113
|
-
created_at: string;
|
|
114
|
-
updated_at: string;
|
|
115
105
|
}
|
|
116
106
|
export interface ContentUrl {
|
|
117
107
|
content_url: string;
|
|
118
108
|
content_type: string;
|
|
119
109
|
filename: string;
|
|
120
110
|
}
|
|
111
|
+
/** Document tally for a corpus or folder. `indexed` = searchable; `in_flight` =
|
|
112
|
+
* pending + ingesting (still processing); `failed` = terminal; `total` = all. */
|
|
113
|
+
export interface DocumentCount {
|
|
114
|
+
total: number;
|
|
115
|
+
indexed: number;
|
|
116
|
+
in_flight: number;
|
|
117
|
+
failed: number;
|
|
118
|
+
}
|
|
121
119
|
export interface Conversation {
|
|
122
120
|
id: UUID;
|
|
123
|
-
tenant_id: UUID | null;
|
|
124
121
|
title: string | null;
|
|
125
122
|
custom_metadata: Record<string, unknown>;
|
|
126
123
|
ephemeral: boolean;
|
|
127
124
|
last_activity: string;
|
|
128
|
-
created_at: string;
|
|
129
|
-
updated_at: string;
|
|
130
125
|
}
|
|
131
126
|
export interface Message {
|
|
132
127
|
id: UUID;
|
|
@@ -138,55 +133,33 @@ export interface Message {
|
|
|
138
133
|
citations: Record<string, unknown> | null;
|
|
139
134
|
groundedness: Record<string, unknown> | null;
|
|
140
135
|
retrieval_contents: unknown[] | null;
|
|
141
|
-
retrieval_debug: Record<string, unknown> | null;
|
|
142
136
|
usage: Record<string, unknown> | null;
|
|
143
|
-
created_at: string;
|
|
144
137
|
}
|
|
145
|
-
export interface
|
|
138
|
+
export interface Attachment {
|
|
146
139
|
id: UUID;
|
|
147
140
|
conversation_id: UUID;
|
|
148
|
-
tenant_id: UUID;
|
|
149
141
|
filename: string | null;
|
|
150
142
|
content_type: string | null;
|
|
151
143
|
byte_size: number | null;
|
|
152
144
|
status: "parsing" | "ready" | "failed";
|
|
153
145
|
custom_metadata: Record<string, unknown> | null;
|
|
154
146
|
error: string | null;
|
|
155
|
-
created_at: string;
|
|
156
|
-
updated_at: string;
|
|
157
|
-
}
|
|
158
|
-
export interface ParseJob {
|
|
159
|
-
id: UUID;
|
|
160
|
-
tenant_id: UUID | null;
|
|
161
|
-
status: string;
|
|
162
|
-
document_count: number;
|
|
163
|
-
completed_count: number;
|
|
164
|
-
failed_count: number;
|
|
165
|
-
documents: unknown[];
|
|
166
|
-
created_at: string;
|
|
167
|
-
updated_at: string;
|
|
168
147
|
}
|
|
169
148
|
export interface Feedback {
|
|
170
149
|
id: UUID;
|
|
171
150
|
message_id: UUID;
|
|
172
151
|
rating: number | null;
|
|
173
152
|
comment: string | null;
|
|
174
|
-
created_at: string;
|
|
175
|
-
updated_at: string;
|
|
176
153
|
}
|
|
177
154
|
export interface Agent {
|
|
178
155
|
id: UUID;
|
|
179
156
|
name: string;
|
|
180
|
-
kind: "query" | "ingestion";
|
|
181
|
-
tenant_id: UUID | null;
|
|
182
157
|
generation_model: string | null;
|
|
183
158
|
top_k: number | null;
|
|
184
159
|
rerank_instruction: string | null;
|
|
185
160
|
max_hops: number | null;
|
|
186
161
|
groundedness_threshold: number | null;
|
|
187
162
|
grounding_enabled: boolean | null;
|
|
188
|
-
created_at: string;
|
|
189
|
-
updated_at: string;
|
|
190
163
|
}
|
|
191
164
|
export interface Tenant {
|
|
192
165
|
id: UUID;
|
|
@@ -198,25 +171,18 @@ export interface Tenant {
|
|
|
198
171
|
query_endpoint: string | null;
|
|
199
172
|
query_public_domain: string | null;
|
|
200
173
|
query_deployed_index_id: string | null;
|
|
201
|
-
created_at: string;
|
|
202
|
-
updated_at: string;
|
|
203
174
|
}
|
|
204
175
|
export interface ApiKeyCreated {
|
|
205
176
|
id: UUID;
|
|
206
177
|
api_key: string;
|
|
207
178
|
prefix: string;
|
|
208
179
|
label: string | null;
|
|
209
|
-
created_at: string;
|
|
210
180
|
}
|
|
211
|
-
export interface
|
|
181
|
+
export interface ApiKey {
|
|
212
182
|
id: UUID;
|
|
213
|
-
tenant_id: UUID;
|
|
214
183
|
prefix: string;
|
|
215
184
|
label: string | null;
|
|
216
|
-
|
|
217
|
-
revoked_at: string | null;
|
|
218
|
-
created_at: string;
|
|
219
|
-
updated_at: string;
|
|
185
|
+
revoked: boolean;
|
|
220
186
|
}
|
|
221
187
|
/** Thrown on any non-2xx response. `detail` is the structured body when present
|
|
222
188
|
* (e.g. {error:"attachments_pending", attachments:[...]} or
|
|
@@ -232,7 +198,8 @@ export declare class KnowledgeCoreError extends Error {
|
|
|
232
198
|
export interface ClientOptions {
|
|
233
199
|
baseUrl: string;
|
|
234
200
|
apiKey: string;
|
|
235
|
-
/** Optional default fetch timeout (ms). Streaming ignores this.
|
|
201
|
+
/** Optional default fetch timeout (ms). Streaming ignores this. Note:
|
|
202
|
+
* synchronous ingest can take a while — set this generously or omit. */
|
|
236
203
|
timeoutMs?: number;
|
|
237
204
|
fetch?: typeof fetch;
|
|
238
205
|
}
|
|
@@ -289,9 +256,7 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
289
256
|
corpora: {
|
|
290
257
|
create: (b: {
|
|
291
258
|
name: string;
|
|
292
|
-
embedding_model: string;
|
|
293
259
|
description?: string;
|
|
294
|
-
external_ref?: string;
|
|
295
260
|
}) => Promise<Corpus>;
|
|
296
261
|
list: (q?: {
|
|
297
262
|
limit?: number;
|
|
@@ -302,7 +267,6 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
302
267
|
update: (id: UUID, b: {
|
|
303
268
|
name?: string;
|
|
304
269
|
description?: string;
|
|
305
|
-
external_ref?: string;
|
|
306
270
|
}) => Promise<Corpus>;
|
|
307
271
|
delete: (id: UUID, confirmName: string) => Promise<void>;
|
|
308
272
|
listFolders: (id: UUID) => Promise<Folder[]>;
|
|
@@ -310,26 +274,27 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
310
274
|
limit?: number;
|
|
311
275
|
cursor?: string;
|
|
312
276
|
}) => Promise<Page<Document>>;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
277
|
+
/** Count documents in the corpus: { total, indexed, in_flight, failed }. */
|
|
278
|
+
countDocuments: (id: UUID) => Promise<DocumentCount>;
|
|
279
|
+
/** Upload a file and ingest it ASYNCHRONOUSLY — resolves with the created
|
|
280
|
+
* document at status `pending` (HTTP 202); track via documents.get() polling
|
|
281
|
+
* the status to `indexed`/`failed`, or the tenant result webhook. */
|
|
282
|
+
ingestDocument: (id: UUID, a: {
|
|
283
|
+
file: FileData;
|
|
284
|
+
filename: string;
|
|
285
|
+
content_type?: string;
|
|
316
286
|
visibility?: Visibility;
|
|
317
|
-
|
|
318
|
-
parse_job_id?: UUID;
|
|
287
|
+
folder_id?: UUID;
|
|
319
288
|
custom_metadata?: Record<string, unknown>;
|
|
320
289
|
}) => Promise<Document>;
|
|
321
|
-
ingest: (id: UUID, b: {
|
|
322
|
-
ingestion_agent_id: UUID;
|
|
323
|
-
folder_id?: UUID;
|
|
324
|
-
documents: {
|
|
325
|
-
gcs_uri: string;
|
|
326
|
-
custom_metadata?: Record<string, unknown>;
|
|
327
|
-
visibility?: Visibility;
|
|
328
|
-
}[];
|
|
329
|
-
}) => Promise<{
|
|
330
|
-
parse_job_id: UUID;
|
|
331
|
-
}>;
|
|
332
290
|
};
|
|
291
|
+
parse(a: {
|
|
292
|
+
file: FileData;
|
|
293
|
+
filename?: string;
|
|
294
|
+
content_type?: string;
|
|
295
|
+
}): Promise<{
|
|
296
|
+
text: string;
|
|
297
|
+
}>;
|
|
333
298
|
folders: {
|
|
334
299
|
create: (corpusId: UUID, name: string) => Promise<Folder>;
|
|
335
300
|
rename: (folderId: UUID, name: string) => Promise<Folder>;
|
|
@@ -338,17 +303,14 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
338
303
|
limit?: number;
|
|
339
304
|
cursor?: string;
|
|
340
305
|
}) => Promise<Page<Document>>;
|
|
306
|
+
/** Count documents in the folder: { total, indexed, in_flight, failed }. */
|
|
307
|
+
countDocuments: (folderId: UUID) => Promise<DocumentCount>;
|
|
341
308
|
};
|
|
342
309
|
documents: {
|
|
343
310
|
get: (id: UUID) => Promise<Document>;
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
}>;
|
|
348
|
-
patchMetadata: (id: UUID, custom_metadata: Record<string, unknown>) => Promise<{
|
|
349
|
-
document_id: UUID;
|
|
350
|
-
custom_metadata: Record<string, unknown>;
|
|
351
|
-
}>;
|
|
311
|
+
getCustomMetadata: (id: UUID) => Promise<Record<string, unknown>>;
|
|
312
|
+
/** Merge custom_metadata (a null value deletes a key). Returns the merged object. */
|
|
313
|
+
patchCustomMetadata: (id: UUID, custom_metadata: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
352
314
|
update: (id: UUID, b: {
|
|
353
315
|
visibility?: Visibility;
|
|
354
316
|
folder_id?: UUID;
|
|
@@ -384,25 +346,20 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
384
346
|
}) => Promise<Page<Message>>;
|
|
385
347
|
};
|
|
386
348
|
attachments: {
|
|
387
|
-
/** Upload + attach a
|
|
349
|
+
/** Upload + attach a file and parse it SYNCHRONOUSLY — resolves with status=ready. */
|
|
388
350
|
upload: (conversationId: UUID, a: {
|
|
351
|
+
file: FileData;
|
|
389
352
|
filename: string;
|
|
390
|
-
content_type
|
|
391
|
-
data: BodyInit;
|
|
353
|
+
content_type?: string;
|
|
392
354
|
custom_metadata?: Record<string, unknown>;
|
|
393
|
-
}) => Promise<
|
|
355
|
+
}) => Promise<Attachment>;
|
|
394
356
|
list: (conversationId: UUID, q?: {
|
|
395
357
|
limit?: number;
|
|
396
358
|
cursor?: string;
|
|
397
|
-
}) => Promise<Page<
|
|
398
|
-
get: (conversationId: UUID, docId: UUID) => Promise<
|
|
359
|
+
}) => Promise<Page<Attachment>>;
|
|
360
|
+
get: (conversationId: UUID, docId: UUID) => Promise<Attachment>;
|
|
399
361
|
contentUrl: (conversationId: UUID, docId: UUID, disposition?: "inline" | "attachment") => Promise<ContentUrl>;
|
|
400
362
|
delete: (conversationId: UUID, docId: UUID) => Promise<void>;
|
|
401
|
-
/** Poll until the attachment is ready or failed (or timeout). */
|
|
402
|
-
waitReady: (conversationId: UUID, docId: UUID, opts?: {
|
|
403
|
-
intervalMs?: number;
|
|
404
|
-
timeoutMs?: number;
|
|
405
|
-
}) => Promise<ConversationDocument>;
|
|
406
363
|
};
|
|
407
364
|
messages: {
|
|
408
365
|
get: (id: UUID) => Promise<Message>;
|
|
@@ -419,17 +376,8 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
419
376
|
get: (id: UUID) => Promise<Feedback>;
|
|
420
377
|
delete: (id: UUID) => Promise<void>;
|
|
421
378
|
};
|
|
422
|
-
parseJobs: {
|
|
423
|
-
list: (q?: {
|
|
424
|
-
status_filter?: string;
|
|
425
|
-
limit?: number;
|
|
426
|
-
cursor?: string;
|
|
427
|
-
}) => Promise<Page<ParseJob>>;
|
|
428
|
-
get: (id: UUID) => Promise<ParseJob>;
|
|
429
|
-
};
|
|
430
379
|
agents: {
|
|
431
380
|
list: (q?: {
|
|
432
|
-
kind?: "query" | "ingestion";
|
|
433
381
|
limit?: number;
|
|
434
382
|
cursor?: string;
|
|
435
383
|
}) => Promise<Page<Agent>>;
|
|
@@ -454,15 +402,12 @@ export declare class AdminClient extends HttpBase {
|
|
|
454
402
|
listApiKeys: (tenantId: UUID, q?: {
|
|
455
403
|
limit?: number;
|
|
456
404
|
cursor?: string;
|
|
457
|
-
}) => Promise<Page<
|
|
405
|
+
}) => Promise<Page<ApiKey>>;
|
|
458
406
|
revokeApiKey: (tenantId: UUID, keyId: UUID) => Promise<void>;
|
|
459
407
|
};
|
|
460
408
|
agents: {
|
|
461
|
-
/** tenant_id explicit, or null for a global/shared agent. */
|
|
462
409
|
create: (b: {
|
|
463
410
|
name: string;
|
|
464
|
-
kind: "query" | "ingestion";
|
|
465
|
-
tenant_id?: UUID | null;
|
|
466
411
|
generation_model?: string;
|
|
467
412
|
top_k?: number;
|
|
468
413
|
rerank_instruction?: string;
|
|
@@ -470,7 +415,7 @@ export declare class AdminClient extends HttpBase {
|
|
|
470
415
|
groundedness_threshold?: number;
|
|
471
416
|
grounding_enabled?: boolean;
|
|
472
417
|
}) => Promise<Agent>;
|
|
473
|
-
update: (id: UUID, b: Partial<Omit<Agent, "id"
|
|
418
|
+
update: (id: UUID, b: Partial<Omit<Agent, "id">>) => Promise<Agent>;
|
|
474
419
|
delete: (id: UUID) => Promise<void>;
|
|
475
420
|
};
|
|
476
421
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Babav Knowledge Core — TypeScript client.
|
|
3
3
|
*
|
|
4
|
-
* Portable: uses the global `fetch` + `ReadableStream`, so it
|
|
5
|
-
* Supabase Edge Functions (Deno) and Railway (Node 18+). Zero
|
|
4
|
+
* Portable: uses the global `fetch`, `FormData`, `Blob` + `ReadableStream`, so it
|
|
5
|
+
* runs unchanged in Supabase Edge Functions (Deno) and Railway (Node 18+). Zero
|
|
6
|
+
* dependencies.
|
|
6
7
|
*
|
|
7
8
|
* Wire shapes are snake_case to mirror the Knowledge Core API 1:1 — so an API
|
|
8
9
|
* change is reflected here with a one-to-one type edit and never drifts.
|
|
9
10
|
*
|
|
10
|
-
* Auth: every call carries an X-API-Key. Use
|
|
11
|
-
* all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
12
|
-
* management. The key is server-side only — never ship it to a browser.
|
|
11
|
+
* Auth: every call carries an X-API-Key. Use KnowledgeCoreClient with a TENANT
|
|
12
|
+
* key for all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
13
|
+
* agent management. The key is server-side only — never ship it to a browser.
|
|
13
14
|
*/
|
|
14
15
|
// ---------------------------------------------------------------------------
|
|
15
16
|
// Errors
|
|
@@ -63,6 +64,7 @@ class HttpBase {
|
|
|
63
64
|
body = JSON.stringify(opts.json);
|
|
64
65
|
}
|
|
65
66
|
else if (opts.body !== undefined) {
|
|
67
|
+
// FormData sets its own multipart content-type (with boundary) on fetch.
|
|
66
68
|
body = opts.body;
|
|
67
69
|
}
|
|
68
70
|
let signal = opts.signal;
|
|
@@ -110,6 +112,11 @@ function safeJson(t) {
|
|
|
110
112
|
return t;
|
|
111
113
|
}
|
|
112
114
|
}
|
|
115
|
+
function toBlob(data, contentType) {
|
|
116
|
+
if (data instanceof Blob)
|
|
117
|
+
return data;
|
|
118
|
+
return new Blob([data], { type: contentType ?? "application/octet-stream" });
|
|
119
|
+
}
|
|
113
120
|
// ---------------------------------------------------------------------------
|
|
114
121
|
// Tenant client (data ops) — use a TENANT key
|
|
115
122
|
// ---------------------------------------------------------------------------
|
|
@@ -157,21 +164,44 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
157
164
|
delete: (id, confirmName) => this.request("DELETE", `/v1/corpora/${id}`, { query: { confirm: confirmName } }),
|
|
158
165
|
listFolders: (id) => this.pageAll(`/v1/corpora/${id}/folders`),
|
|
159
166
|
listDocuments: (id, q) => this.request("GET", `/v1/corpora/${id}/documents`, { query: q }),
|
|
160
|
-
|
|
161
|
-
|
|
167
|
+
/** Count documents in the corpus: { total, indexed, in_flight, failed }. */
|
|
168
|
+
countDocuments: (id) => this.request("GET", `/v1/corpora/${id}/documents/count`),
|
|
169
|
+
/** Upload a file and ingest it ASYNCHRONOUSLY — resolves with the created
|
|
170
|
+
* document at status `pending` (HTTP 202); track via documents.get() polling
|
|
171
|
+
* the status to `indexed`/`failed`, or the tenant result webhook. */
|
|
172
|
+
ingestDocument: (id, a) => {
|
|
173
|
+
const fd = new FormData();
|
|
174
|
+
fd.append("file", toBlob(a.file, a.content_type), a.filename);
|
|
175
|
+
if (a.custom_metadata)
|
|
176
|
+
fd.append("custom_metadata", JSON.stringify(a.custom_metadata));
|
|
177
|
+
if (a.visibility)
|
|
178
|
+
fd.append("visibility", a.visibility);
|
|
179
|
+
if (a.folder_id)
|
|
180
|
+
fd.append("folder_id", a.folder_id);
|
|
181
|
+
return this.request("POST", `/v1/corpora/${id}/documents`, { body: fd });
|
|
182
|
+
},
|
|
162
183
|
};
|
|
184
|
+
// --- parsing (utility: file -> text, stores nothing) ---
|
|
185
|
+
parse(a) {
|
|
186
|
+
const fd = new FormData();
|
|
187
|
+
fd.append("file", toBlob(a.file, a.content_type), a.filename ?? "document");
|
|
188
|
+
return this.request("POST", "/v1/documents/parse", { body: fd });
|
|
189
|
+
}
|
|
163
190
|
// --- folders ---
|
|
164
191
|
folders = {
|
|
165
192
|
create: (corpusId, name) => this.request("POST", `/v1/corpora/${corpusId}/folders`, { json: { name } }),
|
|
166
193
|
rename: (folderId, name) => this.request("PATCH", `/v1/folders/${folderId}`, { json: { name } }),
|
|
167
194
|
delete: (folderId) => this.request("DELETE", `/v1/folders/${folderId}`),
|
|
168
195
|
listDocuments: (folderId, q) => this.request("GET", `/v1/folders/${folderId}/documents`, { query: q }),
|
|
196
|
+
/** Count documents in the folder: { total, indexed, in_flight, failed }. */
|
|
197
|
+
countDocuments: (folderId) => this.request("GET", `/v1/folders/${folderId}/documents/count`),
|
|
169
198
|
};
|
|
170
199
|
// --- documents ---
|
|
171
200
|
documents = {
|
|
172
201
|
get: (id) => this.request("GET", `/v1/documents/${id}`),
|
|
173
|
-
|
|
174
|
-
|
|
202
|
+
getCustomMetadata: (id) => this.request("GET", `/v1/documents/${id}/custom_metadata`),
|
|
203
|
+
/** Merge custom_metadata (a null value deletes a key). Returns the merged object. */
|
|
204
|
+
patchCustomMetadata: (id, custom_metadata) => this.request("PATCH", `/v1/documents/${id}/custom_metadata`, { json: custom_metadata }),
|
|
175
205
|
update: (id, b) => this.request("PATCH", `/v1/documents/${id}`, { json: b }),
|
|
176
206
|
contentUrl: (id, disposition = "inline") => this.request("GET", `/v1/documents/${id}/content-url`, { query: { disposition } }),
|
|
177
207
|
delete: (id) => this.request("DELETE", `/v1/documents/${id}`),
|
|
@@ -189,27 +219,18 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
189
219
|
};
|
|
190
220
|
// --- conversation attachments (pinned full-document review) ---
|
|
191
221
|
attachments = {
|
|
192
|
-
/** Upload + attach a
|
|
193
|
-
upload: (conversationId, a) =>
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
222
|
+
/** Upload + attach a file and parse it SYNCHRONOUSLY — resolves with status=ready. */
|
|
223
|
+
upload: (conversationId, a) => {
|
|
224
|
+
const fd = new FormData();
|
|
225
|
+
fd.append("file", toBlob(a.file, a.content_type), a.filename);
|
|
226
|
+
if (a.custom_metadata)
|
|
227
|
+
fd.append("custom_metadata", JSON.stringify(a.custom_metadata));
|
|
228
|
+
return this.request("POST", `/v1/conversations/${conversationId}/documents`, { body: fd });
|
|
229
|
+
},
|
|
198
230
|
list: (conversationId, q) => this.request("GET", `/v1/conversations/${conversationId}/documents`, { query: q }),
|
|
199
231
|
get: (conversationId, docId) => this.request("GET", `/v1/conversations/${conversationId}/documents/${docId}`),
|
|
200
232
|
contentUrl: (conversationId, docId, disposition = "inline") => this.request("GET", `/v1/conversations/${conversationId}/documents/${docId}/content-url`, { query: { disposition } }),
|
|
201
233
|
delete: (conversationId, docId) => this.request("DELETE", `/v1/conversations/${conversationId}/documents/${docId}`),
|
|
202
|
-
/** Poll until the attachment is ready or failed (or timeout). */
|
|
203
|
-
waitReady: async (conversationId, docId, opts = {}) => {
|
|
204
|
-
const interval = opts.intervalMs ?? 3000;
|
|
205
|
-
const deadline = Date.now() + (opts.timeoutMs ?? 180_000);
|
|
206
|
-
for (;;) {
|
|
207
|
-
const d = await this.attachments.get(conversationId, docId);
|
|
208
|
-
if (d.status === "ready" || d.status === "failed" || Date.now() > deadline)
|
|
209
|
-
return d;
|
|
210
|
-
await sleep(interval);
|
|
211
|
-
}
|
|
212
|
-
},
|
|
213
234
|
};
|
|
214
235
|
// --- messages + feedback ---
|
|
215
236
|
messages = {
|
|
@@ -221,11 +242,6 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
221
242
|
get: (id) => this.request("GET", `/v1/feedback/${id}`),
|
|
222
243
|
delete: (id) => this.request("DELETE", `/v1/feedback/${id}`),
|
|
223
244
|
};
|
|
224
|
-
// --- parse jobs ---
|
|
225
|
-
parseJobs = {
|
|
226
|
-
list: (q) => this.request("GET", "/v1/parse_jobs", { query: q }),
|
|
227
|
-
get: (id) => this.request("GET", `/v1/parse_jobs/${id}`),
|
|
228
|
-
};
|
|
229
245
|
// --- agents (tenant read-only: choose an agent to query) ---
|
|
230
246
|
agents = {
|
|
231
247
|
list: (q) => this.request("GET", "/v1/agents", { query: q }),
|
|
@@ -248,8 +264,8 @@ export class AdminClient extends HttpBase {
|
|
|
248
264
|
listApiKeys: (tenantId, q) => this.request("GET", `/v1/tenants/${tenantId}/api-keys`, { query: q }),
|
|
249
265
|
revokeApiKey: (tenantId, keyId) => this.request("DELETE", `/v1/tenants/${tenantId}/api-keys/${keyId}`),
|
|
250
266
|
};
|
|
267
|
+
// Agents are query agents, global for now.
|
|
251
268
|
agents = {
|
|
252
|
-
/** tenant_id explicit, or null for a global/shared agent. */
|
|
253
269
|
create: (b) => this.request("POST", "/v1/agents", { json: b }),
|
|
254
270
|
update: (id, b) => this.request("PATCH", `/v1/agents/${id}`, { json: b }),
|
|
255
271
|
delete: (id) => this.request("DELETE", `/v1/agents/${id}`),
|
|
@@ -292,6 +308,3 @@ function dispatchSse(frame, h) {
|
|
|
292
308
|
break;
|
|
293
309
|
}
|
|
294
310
|
}
|
|
295
|
-
function sleep(ms) {
|
|
296
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
297
|
-
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Babav Knowledge Core — TypeScript client.
|
|
3
3
|
*
|
|
4
|
-
* Portable: uses the global `fetch` + `ReadableStream`, so it
|
|
5
|
-
* Supabase Edge Functions (Deno) and Railway (Node 18+). Zero
|
|
4
|
+
* Portable: uses the global `fetch`, `FormData`, `Blob` + `ReadableStream`, so it
|
|
5
|
+
* runs unchanged in Supabase Edge Functions (Deno) and Railway (Node 18+). Zero
|
|
6
|
+
* dependencies.
|
|
6
7
|
*
|
|
7
8
|
* Wire shapes are snake_case to mirror the Knowledge Core API 1:1 — so an API
|
|
8
9
|
* change is reflected here with a one-to-one type edit and never drifts.
|
|
9
10
|
*
|
|
10
|
-
* Auth: every call carries an X-API-Key. Use
|
|
11
|
-
* all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
12
|
-
* management. The key is server-side only — never ship it to a browser.
|
|
11
|
+
* Auth: every call carries an X-API-Key. Use KnowledgeCoreClient with a TENANT
|
|
12
|
+
* key for all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
13
|
+
* agent management. The key is server-side only — never ship it to a browser.
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
|
-
// Shared types (mirror the API
|
|
17
|
+
// Shared types (mirror the API objects)
|
|
17
18
|
// ---------------------------------------------------------------------------
|
|
18
19
|
export type UUID = string;
|
|
19
20
|
|
|
@@ -25,6 +26,9 @@ export interface Page<T> {
|
|
|
25
26
|
export type Visibility = "downloadable" | "viewable" | "attributable" | "hidden";
|
|
26
27
|
export type FilterOp = "eq" | "ne" | "in" | "nin" | "gt" | "gte" | "lt" | "lte" | "exists";
|
|
27
28
|
|
|
29
|
+
/** Raw file input accepted by upload/parse helpers. */
|
|
30
|
+
export type FileData = Blob | Uint8Array | ArrayBuffer;
|
|
31
|
+
|
|
28
32
|
export interface FilterClause {
|
|
29
33
|
field: string;
|
|
30
34
|
op: FilterOp;
|
|
@@ -93,53 +97,45 @@ export interface Groundedness {
|
|
|
93
97
|
|
|
94
98
|
export interface Corpus {
|
|
95
99
|
id: UUID;
|
|
96
|
-
tenant_id: UUID | null;
|
|
97
100
|
name: string;
|
|
98
101
|
description: string | null;
|
|
99
|
-
embedding_model: string;
|
|
100
|
-
external_ref: string | null;
|
|
101
|
-
created_at: string;
|
|
102
|
-
updated_at: string;
|
|
103
102
|
}
|
|
104
103
|
export interface Folder {
|
|
105
104
|
id: UUID;
|
|
106
105
|
corpus_id: UUID;
|
|
107
106
|
name: string;
|
|
108
|
-
is_default: boolean;
|
|
109
|
-
created_at: string;
|
|
110
|
-
updated_at: string;
|
|
111
107
|
}
|
|
112
108
|
export interface Document {
|
|
113
109
|
id: UUID;
|
|
114
110
|
corpus_id: UUID;
|
|
115
111
|
folder_id: UUID;
|
|
116
|
-
source_uri: string;
|
|
117
112
|
status: string;
|
|
118
113
|
visibility: Visibility;
|
|
119
114
|
content_type: string | null;
|
|
120
115
|
filename: string | null;
|
|
121
|
-
parse_job_id: UUID | null;
|
|
122
116
|
chunk_count: number;
|
|
123
|
-
datapoint_ids: string[];
|
|
124
117
|
custom_metadata: Record<string, unknown>;
|
|
125
118
|
error: string | null;
|
|
126
|
-
created_at: string;
|
|
127
|
-
updated_at: string;
|
|
128
119
|
}
|
|
129
120
|
export interface ContentUrl {
|
|
130
121
|
content_url: string;
|
|
131
122
|
content_type: string;
|
|
132
123
|
filename: string;
|
|
133
124
|
}
|
|
125
|
+
/** Document tally for a corpus or folder. `indexed` = searchable; `in_flight` =
|
|
126
|
+
* pending + ingesting (still processing); `failed` = terminal; `total` = all. */
|
|
127
|
+
export interface DocumentCount {
|
|
128
|
+
total: number;
|
|
129
|
+
indexed: number;
|
|
130
|
+
in_flight: number;
|
|
131
|
+
failed: number;
|
|
132
|
+
}
|
|
134
133
|
export interface Conversation {
|
|
135
134
|
id: UUID;
|
|
136
|
-
tenant_id: UUID | null;
|
|
137
135
|
title: string | null;
|
|
138
136
|
custom_metadata: Record<string, unknown>;
|
|
139
137
|
ephemeral: boolean;
|
|
140
138
|
last_activity: string;
|
|
141
|
-
created_at: string;
|
|
142
|
-
updated_at: string;
|
|
143
139
|
}
|
|
144
140
|
export interface Message {
|
|
145
141
|
id: UUID;
|
|
@@ -151,55 +147,33 @@ export interface Message {
|
|
|
151
147
|
citations: Record<string, unknown> | null;
|
|
152
148
|
groundedness: Record<string, unknown> | null;
|
|
153
149
|
retrieval_contents: unknown[] | null;
|
|
154
|
-
retrieval_debug: Record<string, unknown> | null;
|
|
155
150
|
usage: Record<string, unknown> | null;
|
|
156
|
-
created_at: string;
|
|
157
151
|
}
|
|
158
|
-
export interface
|
|
152
|
+
export interface Attachment {
|
|
159
153
|
id: UUID;
|
|
160
154
|
conversation_id: UUID;
|
|
161
|
-
tenant_id: UUID;
|
|
162
155
|
filename: string | null;
|
|
163
156
|
content_type: string | null;
|
|
164
157
|
byte_size: number | null;
|
|
165
158
|
status: "parsing" | "ready" | "failed";
|
|
166
159
|
custom_metadata: Record<string, unknown> | null;
|
|
167
160
|
error: string | null;
|
|
168
|
-
created_at: string;
|
|
169
|
-
updated_at: string;
|
|
170
|
-
}
|
|
171
|
-
export interface ParseJob {
|
|
172
|
-
id: UUID;
|
|
173
|
-
tenant_id: UUID | null;
|
|
174
|
-
status: string;
|
|
175
|
-
document_count: number;
|
|
176
|
-
completed_count: number;
|
|
177
|
-
failed_count: number;
|
|
178
|
-
documents: unknown[];
|
|
179
|
-
created_at: string;
|
|
180
|
-
updated_at: string;
|
|
181
161
|
}
|
|
182
162
|
export interface Feedback {
|
|
183
163
|
id: UUID;
|
|
184
164
|
message_id: UUID;
|
|
185
165
|
rating: number | null;
|
|
186
166
|
comment: string | null;
|
|
187
|
-
created_at: string;
|
|
188
|
-
updated_at: string;
|
|
189
167
|
}
|
|
190
168
|
export interface Agent {
|
|
191
169
|
id: UUID;
|
|
192
170
|
name: string;
|
|
193
|
-
kind: "query" | "ingestion";
|
|
194
|
-
tenant_id: UUID | null;
|
|
195
171
|
generation_model: string | null;
|
|
196
172
|
top_k: number | null;
|
|
197
173
|
rerank_instruction: string | null;
|
|
198
174
|
max_hops: number | null;
|
|
199
175
|
groundedness_threshold: number | null;
|
|
200
176
|
grounding_enabled: boolean | null;
|
|
201
|
-
created_at: string;
|
|
202
|
-
updated_at: string;
|
|
203
177
|
}
|
|
204
178
|
export interface Tenant {
|
|
205
179
|
id: UUID;
|
|
@@ -211,25 +185,18 @@ export interface Tenant {
|
|
|
211
185
|
query_endpoint: string | null;
|
|
212
186
|
query_public_domain: string | null;
|
|
213
187
|
query_deployed_index_id: string | null;
|
|
214
|
-
created_at: string;
|
|
215
|
-
updated_at: string;
|
|
216
188
|
}
|
|
217
189
|
export interface ApiKeyCreated {
|
|
218
190
|
id: UUID;
|
|
219
191
|
api_key: string; // shown ONCE — store it now
|
|
220
192
|
prefix: string;
|
|
221
193
|
label: string | null;
|
|
222
|
-
created_at: string;
|
|
223
194
|
}
|
|
224
|
-
export interface
|
|
195
|
+
export interface ApiKey {
|
|
225
196
|
id: UUID;
|
|
226
|
-
tenant_id: UUID;
|
|
227
197
|
prefix: string;
|
|
228
198
|
label: string | null;
|
|
229
|
-
|
|
230
|
-
revoked_at: string | null;
|
|
231
|
-
created_at: string;
|
|
232
|
-
updated_at: string;
|
|
199
|
+
revoked: boolean;
|
|
233
200
|
}
|
|
234
201
|
|
|
235
202
|
// ---------------------------------------------------------------------------
|
|
@@ -260,7 +227,8 @@ export class KnowledgeCoreError extends Error {
|
|
|
260
227
|
export interface ClientOptions {
|
|
261
228
|
baseUrl: string;
|
|
262
229
|
apiKey: string;
|
|
263
|
-
/** Optional default fetch timeout (ms). Streaming ignores this.
|
|
230
|
+
/** Optional default fetch timeout (ms). Streaming ignores this. Note:
|
|
231
|
+
* synchronous ingest can take a while — set this generously or omit. */
|
|
264
232
|
timeoutMs?: number;
|
|
265
233
|
fetch?: typeof fetch; // override for tests
|
|
266
234
|
}
|
|
@@ -268,7 +236,7 @@ export interface ClientOptions {
|
|
|
268
236
|
interface RequestOpts {
|
|
269
237
|
query?: Record<string, string | number | boolean | undefined>;
|
|
270
238
|
json?: unknown;
|
|
271
|
-
body?: BodyInit; // raw body (
|
|
239
|
+
body?: BodyInit; // raw body / multipart FormData (file uploads)
|
|
272
240
|
headers?: Record<string, string>;
|
|
273
241
|
signal?: AbortSignal;
|
|
274
242
|
}
|
|
@@ -303,6 +271,7 @@ class HttpBase {
|
|
|
303
271
|
headers["content-type"] = "application/json";
|
|
304
272
|
body = JSON.stringify(opts.json);
|
|
305
273
|
} else if (opts.body !== undefined) {
|
|
274
|
+
// FormData sets its own multipart content-type (with boundary) on fetch.
|
|
306
275
|
body = opts.body;
|
|
307
276
|
}
|
|
308
277
|
let signal = opts.signal;
|
|
@@ -350,6 +319,11 @@ function safeJson(t: string): unknown {
|
|
|
350
319
|
}
|
|
351
320
|
}
|
|
352
321
|
|
|
322
|
+
function toBlob(data: FileData, contentType?: string): Blob {
|
|
323
|
+
if (data instanceof Blob) return data;
|
|
324
|
+
return new Blob([data as BlobPart], { type: contentType ?? "application/octet-stream" });
|
|
325
|
+
}
|
|
326
|
+
|
|
353
327
|
// ---------------------------------------------------------------------------
|
|
354
328
|
// SSE handlers
|
|
355
329
|
// ---------------------------------------------------------------------------
|
|
@@ -404,23 +378,40 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
404
378
|
|
|
405
379
|
// --- corpora ---
|
|
406
380
|
corpora = {
|
|
407
|
-
create: (b: { name: string;
|
|
381
|
+
create: (b: { name: string; description?: string }) =>
|
|
408
382
|
this.request<Corpus>("POST", "/v1/corpora", { json: b }),
|
|
409
383
|
list: (q?: { limit?: number; cursor?: string }) => this.request<Page<Corpus>>("GET", "/v1/corpora", { query: q }),
|
|
410
384
|
listAll: () => this.pageAll<Corpus>("/v1/corpora"),
|
|
411
385
|
get: (id: UUID) => this.request<Corpus>("GET", `/v1/corpora/${id}`),
|
|
412
|
-
update: (id: UUID, b: { name?: string; description?: string
|
|
386
|
+
update: (id: UUID, b: { name?: string; description?: string }) =>
|
|
413
387
|
this.request<Corpus>("PATCH", `/v1/corpora/${id}`, { json: b }),
|
|
414
388
|
delete: (id: UUID, confirmName: string) => this.request<void>("DELETE", `/v1/corpora/${id}`, { query: { confirm: confirmName } }),
|
|
415
389
|
listFolders: (id: UUID) => this.pageAll<Folder>(`/v1/corpora/${id}/folders`),
|
|
416
390
|
listDocuments: (id: UUID, q?: { limit?: number; cursor?: string }) =>
|
|
417
391
|
this.request<Page<Document>>("GET", `/v1/corpora/${id}/documents`, { query: q }),
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
392
|
+
/** Count documents in the corpus: { total, indexed, in_flight, failed }. */
|
|
393
|
+
countDocuments: (id: UUID) =>
|
|
394
|
+
this.request<DocumentCount>("GET", `/v1/corpora/${id}/documents/count`),
|
|
395
|
+
/** Upload a file and ingest it ASYNCHRONOUSLY — resolves with the created
|
|
396
|
+
* document at status `pending` (HTTP 202); track via documents.get() polling
|
|
397
|
+
* the status to `indexed`/`failed`, or the tenant result webhook. */
|
|
398
|
+
ingestDocument: (id: UUID, a: { file: FileData; filename: string; content_type?: string; visibility?: Visibility; folder_id?: UUID; custom_metadata?: Record<string, unknown> }) => {
|
|
399
|
+
const fd = new FormData();
|
|
400
|
+
fd.append("file", toBlob(a.file, a.content_type), a.filename);
|
|
401
|
+
if (a.custom_metadata) fd.append("custom_metadata", JSON.stringify(a.custom_metadata));
|
|
402
|
+
if (a.visibility) fd.append("visibility", a.visibility);
|
|
403
|
+
if (a.folder_id) fd.append("folder_id", a.folder_id);
|
|
404
|
+
return this.request<Document>("POST", `/v1/corpora/${id}/documents`, { body: fd });
|
|
405
|
+
},
|
|
422
406
|
};
|
|
423
407
|
|
|
408
|
+
// --- parsing (utility: file -> text, stores nothing) ---
|
|
409
|
+
parse(a: { file: FileData; filename?: string; content_type?: string }): Promise<{ text: string }> {
|
|
410
|
+
const fd = new FormData();
|
|
411
|
+
fd.append("file", toBlob(a.file, a.content_type), a.filename ?? "document");
|
|
412
|
+
return this.request<{ text: string }>("POST", "/v1/documents/parse", { body: fd });
|
|
413
|
+
}
|
|
414
|
+
|
|
424
415
|
// --- folders ---
|
|
425
416
|
folders = {
|
|
426
417
|
create: (corpusId: UUID, name: string) => this.request<Folder>("POST", `/v1/corpora/${corpusId}/folders`, { json: { name } }),
|
|
@@ -428,14 +419,18 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
428
419
|
delete: (folderId: UUID) => this.request<void>("DELETE", `/v1/folders/${folderId}`),
|
|
429
420
|
listDocuments: (folderId: UUID, q?: { limit?: number; cursor?: string }) =>
|
|
430
421
|
this.request<Page<Document>>("GET", `/v1/folders/${folderId}/documents`, { query: q }),
|
|
422
|
+
/** Count documents in the folder: { total, indexed, in_flight, failed }. */
|
|
423
|
+
countDocuments: (folderId: UUID) =>
|
|
424
|
+
this.request<DocumentCount>("GET", `/v1/folders/${folderId}/documents/count`),
|
|
431
425
|
};
|
|
432
426
|
|
|
433
427
|
// --- documents ---
|
|
434
428
|
documents = {
|
|
435
429
|
get: (id: UUID) => this.request<Document>("GET", `/v1/documents/${id}`),
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
430
|
+
getCustomMetadata: (id: UUID) => this.request<Record<string, unknown>>("GET", `/v1/documents/${id}/custom_metadata`),
|
|
431
|
+
/** Merge custom_metadata (a null value deletes a key). Returns the merged object. */
|
|
432
|
+
patchCustomMetadata: (id: UUID, custom_metadata: Record<string, unknown>) =>
|
|
433
|
+
this.request<Record<string, unknown>>("PATCH", `/v1/documents/${id}/custom_metadata`, { json: custom_metadata }),
|
|
439
434
|
update: (id: UUID, b: { visibility?: Visibility; folder_id?: UUID }) => this.request<Document>("PATCH", `/v1/documents/${id}`, { json: b }),
|
|
440
435
|
contentUrl: (id: UUID, disposition: "inline" | "attachment" = "inline") =>
|
|
441
436
|
this.request<ContentUrl>("GET", `/v1/documents/${id}/content-url`, { query: { disposition } }),
|
|
@@ -460,29 +455,19 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
460
455
|
|
|
461
456
|
// --- conversation attachments (pinned full-document review) ---
|
|
462
457
|
attachments = {
|
|
463
|
-
/** Upload + attach a
|
|
464
|
-
upload: (conversationId: UUID, a: {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
458
|
+
/** Upload + attach a file and parse it SYNCHRONOUSLY — resolves with status=ready. */
|
|
459
|
+
upload: (conversationId: UUID, a: { file: FileData; filename: string; content_type?: string; custom_metadata?: Record<string, unknown> }) => {
|
|
460
|
+
const fd = new FormData();
|
|
461
|
+
fd.append("file", toBlob(a.file, a.content_type), a.filename);
|
|
462
|
+
if (a.custom_metadata) fd.append("custom_metadata", JSON.stringify(a.custom_metadata));
|
|
463
|
+
return this.request<Attachment>("POST", `/v1/conversations/${conversationId}/documents`, { body: fd });
|
|
464
|
+
},
|
|
470
465
|
list: (conversationId: UUID, q?: { limit?: number; cursor?: string }) =>
|
|
471
|
-
this.request<Page<
|
|
472
|
-
get: (conversationId: UUID, docId: UUID) => this.request<
|
|
466
|
+
this.request<Page<Attachment>>("GET", `/v1/conversations/${conversationId}/documents`, { query: q }),
|
|
467
|
+
get: (conversationId: UUID, docId: UUID) => this.request<Attachment>("GET", `/v1/conversations/${conversationId}/documents/${docId}`),
|
|
473
468
|
contentUrl: (conversationId: UUID, docId: UUID, disposition: "inline" | "attachment" = "inline") =>
|
|
474
469
|
this.request<ContentUrl>("GET", `/v1/conversations/${conversationId}/documents/${docId}/content-url`, { query: { disposition } }),
|
|
475
470
|
delete: (conversationId: UUID, docId: UUID) => this.request<void>("DELETE", `/v1/conversations/${conversationId}/documents/${docId}`),
|
|
476
|
-
/** Poll until the attachment is ready or failed (or timeout). */
|
|
477
|
-
waitReady: async (conversationId: UUID, docId: UUID, opts: { intervalMs?: number; timeoutMs?: number } = {}): Promise<ConversationDocument> => {
|
|
478
|
-
const interval = opts.intervalMs ?? 3000;
|
|
479
|
-
const deadline = Date.now() + (opts.timeoutMs ?? 180_000);
|
|
480
|
-
for (;;) {
|
|
481
|
-
const d = await this.attachments.get(conversationId, docId);
|
|
482
|
-
if (d.status === "ready" || d.status === "failed" || Date.now() > deadline) return d;
|
|
483
|
-
await sleep(interval);
|
|
484
|
-
}
|
|
485
|
-
},
|
|
486
471
|
};
|
|
487
472
|
|
|
488
473
|
// --- messages + feedback ---
|
|
@@ -498,15 +483,9 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
498
483
|
delete: (id: UUID) => this.request<void>("DELETE", `/v1/feedback/${id}`),
|
|
499
484
|
};
|
|
500
485
|
|
|
501
|
-
// --- parse jobs ---
|
|
502
|
-
parseJobs = {
|
|
503
|
-
list: (q?: { status_filter?: string; limit?: number; cursor?: string }) => this.request<Page<ParseJob>>("GET", "/v1/parse_jobs", { query: q }),
|
|
504
|
-
get: (id: UUID) => this.request<ParseJob>("GET", `/v1/parse_jobs/${id}`),
|
|
505
|
-
};
|
|
506
|
-
|
|
507
486
|
// --- agents (tenant read-only: choose an agent to query) ---
|
|
508
487
|
agents = {
|
|
509
|
-
list: (q?: {
|
|
488
|
+
list: (q?: { limit?: number; cursor?: string }) => this.request<Page<Agent>>("GET", "/v1/agents", { query: q }),
|
|
510
489
|
listAll: () => this.pageAll<Agent>("/v1/agents"),
|
|
511
490
|
get: (id: UUID) => this.request<Agent>("GET", `/v1/agents/${id}`),
|
|
512
491
|
};
|
|
@@ -524,15 +503,15 @@ export class AdminClient extends HttpBase {
|
|
|
524
503
|
delete: (id: UUID, confirmName: string) => this.request<void>("DELETE", `/v1/tenants/${id}`, { query: { confirm: confirmName } }),
|
|
525
504
|
/** Mint a tenant API key — the raw key is in the response ONCE; store it now. */
|
|
526
505
|
createApiKey: (tenantId: UUID, label?: string) => this.request<ApiKeyCreated>("POST", `/v1/tenants/${tenantId}/api-keys`, { json: { label } }),
|
|
527
|
-
listApiKeys: (tenantId: UUID, q?: { limit?: number; cursor?: string }) => this.request<Page<
|
|
506
|
+
listApiKeys: (tenantId: UUID, q?: { limit?: number; cursor?: string }) => this.request<Page<ApiKey>>("GET", `/v1/tenants/${tenantId}/api-keys`, { query: q }),
|
|
528
507
|
revokeApiKey: (tenantId: UUID, keyId: UUID) => this.request<void>("DELETE", `/v1/tenants/${tenantId}/api-keys/${keyId}`),
|
|
529
508
|
};
|
|
530
509
|
|
|
510
|
+
// Agents are query agents, global for now.
|
|
531
511
|
agents = {
|
|
532
|
-
|
|
533
|
-
create: (b: { name: string; kind: "query" | "ingestion"; tenant_id?: UUID | null; generation_model?: string; top_k?: number; rerank_instruction?: string; max_hops?: number; groundedness_threshold?: number; grounding_enabled?: boolean }) =>
|
|
512
|
+
create: (b: { name: string; generation_model?: string; top_k?: number; rerank_instruction?: string; max_hops?: number; groundedness_threshold?: number; grounding_enabled?: boolean }) =>
|
|
534
513
|
this.request<Agent>("POST", "/v1/agents", { json: b }),
|
|
535
|
-
update: (id: UUID, b: Partial<Omit<Agent, "id"
|
|
514
|
+
update: (id: UUID, b: Partial<Omit<Agent, "id">>) =>
|
|
536
515
|
this.request<Agent>("PATCH", `/v1/agents/${id}`, { json: b }),
|
|
537
516
|
delete: (id: UUID) => this.request<void>("DELETE", `/v1/agents/${id}`),
|
|
538
517
|
};
|
|
@@ -560,7 +539,3 @@ function dispatchSse(frame: string, h: StreamHandlers): void {
|
|
|
560
539
|
case "done": h.onDone?.(); break;
|
|
561
540
|
}
|
|
562
541
|
}
|
|
563
|
-
|
|
564
|
-
function sleep(ms: number): Promise<void> {
|
|
565
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
566
|
-
}
|