cograph 0.1.25 → 0.1.27
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 +32 -0
- package/dist/chunk-PE2EOIGT.js +978 -0
- package/dist/chunk-PE2EOIGT.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/index.d.ts +220 -1
- package/dist/index.js +423 -2
- package/dist/index.js.map +1 -1
- package/dist/{shell-ILZ322LT.js → shell-A5UU33YS.js} +2 -2
- package/package.json +6 -3
- package/dist/chunk-O3L4FCRY.js +0 -558
- package/dist/chunk-O3L4FCRY.js.map +0 -1
- /package/dist/{shell-ILZ322LT.js.map → shell-A5UU33YS.js.map} +0 -0
|
@@ -0,0 +1,978 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
readConfig
|
|
4
|
+
} from "./chunk-7VVBEUZQ.js";
|
|
5
|
+
|
|
6
|
+
// src/client.ts
|
|
7
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
8
|
+
import { extname } from "path";
|
|
9
|
+
var CographError = class extends Error {
|
|
10
|
+
status;
|
|
11
|
+
body;
|
|
12
|
+
constructor(message, opts) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "CographError";
|
|
15
|
+
this.status = opts?.status;
|
|
16
|
+
this.body = opts?.body;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var SCHEMA_SAMPLE_CAP = 5e3;
|
|
20
|
+
function stridedSample(rows, cap = SCHEMA_SAMPLE_CAP) {
|
|
21
|
+
if (rows.length <= cap) return rows;
|
|
22
|
+
const out = [];
|
|
23
|
+
for (let i = 0; i < cap; i++) out.push(rows[Math.floor(i * rows.length / cap)]);
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
function envVar(name, fallback) {
|
|
27
|
+
return process.env[`COGRAPH_${name}`] || process.env[`OMNIX_${name}`] || fallback;
|
|
28
|
+
}
|
|
29
|
+
var EXT_FORMAT = {
|
|
30
|
+
".csv": "csv",
|
|
31
|
+
".json": "json",
|
|
32
|
+
".jsonl": "json",
|
|
33
|
+
".txt": "text"
|
|
34
|
+
};
|
|
35
|
+
function parseCsv(content) {
|
|
36
|
+
const rows = [];
|
|
37
|
+
let cur = [];
|
|
38
|
+
let field = "";
|
|
39
|
+
let inQuotes = false;
|
|
40
|
+
for (let i = 0; i < content.length; i++) {
|
|
41
|
+
const ch = content[i];
|
|
42
|
+
if (inQuotes) {
|
|
43
|
+
if (ch === '"') {
|
|
44
|
+
if (content[i + 1] === '"') {
|
|
45
|
+
field += '"';
|
|
46
|
+
i++;
|
|
47
|
+
} else {
|
|
48
|
+
inQuotes = false;
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
field += ch;
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
if (ch === '"') {
|
|
55
|
+
inQuotes = true;
|
|
56
|
+
} else if (ch === ",") {
|
|
57
|
+
cur.push(field);
|
|
58
|
+
field = "";
|
|
59
|
+
} else if (ch === "\n") {
|
|
60
|
+
cur.push(field);
|
|
61
|
+
rows.push(cur);
|
|
62
|
+
cur = [];
|
|
63
|
+
field = "";
|
|
64
|
+
} else if (ch === "\r") {
|
|
65
|
+
if (content[i + 1] !== "\n") {
|
|
66
|
+
cur.push(field);
|
|
67
|
+
rows.push(cur);
|
|
68
|
+
cur = [];
|
|
69
|
+
field = "";
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
field += ch;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (field.length > 0 || cur.length > 0) {
|
|
77
|
+
cur.push(field);
|
|
78
|
+
rows.push(cur);
|
|
79
|
+
}
|
|
80
|
+
if (rows.length === 0) return [];
|
|
81
|
+
const headers = rows[0].map((h) => h.trim());
|
|
82
|
+
const out = [];
|
|
83
|
+
for (let r = 1; r < rows.length; r++) {
|
|
84
|
+
const row = rows[r];
|
|
85
|
+
if (row.length === 1 && row[0] === "") continue;
|
|
86
|
+
const obj = {};
|
|
87
|
+
for (let c = 0; c < headers.length; c++) {
|
|
88
|
+
obj[headers[c]] = row[c] ?? "";
|
|
89
|
+
}
|
|
90
|
+
out.push(obj);
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
var Client = class {
|
|
95
|
+
apiKey;
|
|
96
|
+
baseUrl;
|
|
97
|
+
tenant;
|
|
98
|
+
/**
|
|
99
|
+
* Raw / passthrough API — one method per canonical backend operation, with
|
|
100
|
+
* the path encoded inside the SDK. Each method returns the backend
|
|
101
|
+
* {@link Response} VERBATIM: it does NOT throw on non-2xx and does NOT reshape
|
|
102
|
+
* the body. This is the seam the webapp's proxy layer adopts so per-operation
|
|
103
|
+
* paths live in one place (here) instead of being hand-rolled at each call
|
|
104
|
+
* site. See {@link RawApi}. The typed methods on this class (which throw on
|
|
105
|
+
* non-2xx and reshape some payloads) are left unchanged — this is additive.
|
|
106
|
+
*/
|
|
107
|
+
raw;
|
|
108
|
+
constructor(opts = {}) {
|
|
109
|
+
const cfg = readConfig();
|
|
110
|
+
this.apiKey = opts.apiKey ?? envVar("API_KEY") ?? cfg.apiKey;
|
|
111
|
+
const url = opts.baseUrl ?? envVar("API_URL") ?? cfg.apiUrl ?? "https://api.cograph.cloud";
|
|
112
|
+
this.baseUrl = url.replace(/\/+$/, "");
|
|
113
|
+
this.tenant = opts.tenant ?? envVar("TENANT") ?? cfg.tenant ?? "demo-tenant";
|
|
114
|
+
this.raw = new RawApi(this);
|
|
115
|
+
}
|
|
116
|
+
headers() {
|
|
117
|
+
const h = { "Content-Type": "application/json" };
|
|
118
|
+
if (this.apiKey) h["X-API-Key"] = this.apiKey;
|
|
119
|
+
return h;
|
|
120
|
+
}
|
|
121
|
+
base() {
|
|
122
|
+
return `${this.baseUrl}/graphs/${this.tenant}`;
|
|
123
|
+
}
|
|
124
|
+
// --- Path builders -------------------------------------------------------- #
|
|
125
|
+
// SINGLE source of truth for every canonical backend path. Both the raw API
|
|
126
|
+
// and the new typed parsed methods build URLs through these, so a path lives
|
|
127
|
+
// in exactly one place. Tenant-scoped paths hang off `base()`
|
|
128
|
+
// (`{baseUrl}/graphs/{tenant}`); the handful of account-level paths
|
|
129
|
+
// (e.g. tenant CRUD) hang off `baseUrl` directly.
|
|
130
|
+
//
|
|
131
|
+
// These are marked `@internal` (not part of the public SDK surface) but are
|
|
132
|
+
// not `private`, so the sibling {@link RawApi} can build the same canonical
|
|
133
|
+
// paths without duplicating them.
|
|
134
|
+
/** @internal */
|
|
135
|
+
pAgent() {
|
|
136
|
+
return `${this.base()}/agent`;
|
|
137
|
+
}
|
|
138
|
+
/** @internal */
|
|
139
|
+
pAsk() {
|
|
140
|
+
return `${this.base()}/ask`;
|
|
141
|
+
}
|
|
142
|
+
/** @internal */
|
|
143
|
+
pIngest() {
|
|
144
|
+
return `${this.base()}/ingest`;
|
|
145
|
+
}
|
|
146
|
+
/** @internal */
|
|
147
|
+
pIngestCsvSchema() {
|
|
148
|
+
return `${this.base()}/ingest/csv/schema`;
|
|
149
|
+
}
|
|
150
|
+
/** @internal */
|
|
151
|
+
pIngestCsvRows() {
|
|
152
|
+
return `${this.base()}/ingest/csv/rows`;
|
|
153
|
+
}
|
|
154
|
+
/** @internal */
|
|
155
|
+
pEnrichJobs() {
|
|
156
|
+
return `${this.base()}/enrich/jobs`;
|
|
157
|
+
}
|
|
158
|
+
/** @internal */
|
|
159
|
+
pEnrichJob(jobId) {
|
|
160
|
+
return `${this.base()}/enrich/jobs/${encodeURIComponent(jobId)}`;
|
|
161
|
+
}
|
|
162
|
+
/** @internal */
|
|
163
|
+
pEnrichJobConflicts(jobId) {
|
|
164
|
+
return `${this.pEnrichJob(jobId)}/conflicts`;
|
|
165
|
+
}
|
|
166
|
+
/** @internal */
|
|
167
|
+
pEnrichJobApply(jobId) {
|
|
168
|
+
return `${this.pEnrichJob(jobId)}/apply`;
|
|
169
|
+
}
|
|
170
|
+
/** @internal */
|
|
171
|
+
pOntologyTypes() {
|
|
172
|
+
return `${this.base()}/ontology/types`;
|
|
173
|
+
}
|
|
174
|
+
/** @internal */
|
|
175
|
+
pOntologyResolve() {
|
|
176
|
+
return `${this.base()}/ontology/resolve`;
|
|
177
|
+
}
|
|
178
|
+
/** @internal Targets the premium ontology-recommender route, mounted only on
|
|
179
|
+
* deployments with the proprietary layer — 404s on bare OSS. */
|
|
180
|
+
pOntologyRecommend() {
|
|
181
|
+
return `${this.base()}/ontology/recommend`;
|
|
182
|
+
}
|
|
183
|
+
/** @internal */
|
|
184
|
+
pOntologyApply() {
|
|
185
|
+
return `${this.base()}/ontology/apply`;
|
|
186
|
+
}
|
|
187
|
+
/** @internal */
|
|
188
|
+
pKgs() {
|
|
189
|
+
return `${this.base()}/kgs`;
|
|
190
|
+
}
|
|
191
|
+
/** @internal */
|
|
192
|
+
pKg(name) {
|
|
193
|
+
return `${this.base()}/kgs/${encodeURIComponent(name)}`;
|
|
194
|
+
}
|
|
195
|
+
/** @internal */
|
|
196
|
+
pTypeCounts(kg) {
|
|
197
|
+
return `${this.pKg(kg)}/type-counts`;
|
|
198
|
+
}
|
|
199
|
+
/** @internal */
|
|
200
|
+
pExploreSummary(kg, typeName) {
|
|
201
|
+
return `${this.base()}/explore/kgs/${encodeURIComponent(kg)}/types/${encodeURIComponent(typeName)}/summary`;
|
|
202
|
+
}
|
|
203
|
+
/** @internal */
|
|
204
|
+
pExploreRecords(kg, typeName, query) {
|
|
205
|
+
return `${this.base()}/explore/kgs/${encodeURIComponent(kg)}/types/${encodeURIComponent(typeName)}/records${query ?? ""}`;
|
|
206
|
+
}
|
|
207
|
+
/** @internal */
|
|
208
|
+
pExploreTypeEdges(kg) {
|
|
209
|
+
return `${this.base()}/explore/kgs/${encodeURIComponent(kg)}/type-edges`;
|
|
210
|
+
}
|
|
211
|
+
/** @internal */
|
|
212
|
+
pExploreSearch(query) {
|
|
213
|
+
return `${this.base()}/explore/search${query}`;
|
|
214
|
+
}
|
|
215
|
+
/** @internal */
|
|
216
|
+
pNormalizeSuggest(query) {
|
|
217
|
+
return `${this.base()}/normalize/suggest${query}`;
|
|
218
|
+
}
|
|
219
|
+
/** @internal */
|
|
220
|
+
pNormalizeRules(query) {
|
|
221
|
+
return `${this.base()}/normalize/rules${query ?? ""}`;
|
|
222
|
+
}
|
|
223
|
+
/** @internal */
|
|
224
|
+
pNormalizeRule(ruleId, action) {
|
|
225
|
+
return `${this.base()}/normalize/rules/${encodeURIComponent(ruleId)}/${action}`;
|
|
226
|
+
}
|
|
227
|
+
/** @internal */
|
|
228
|
+
pTenants() {
|
|
229
|
+
return `${this.baseUrl}/v1/me/tenants`;
|
|
230
|
+
}
|
|
231
|
+
/** @internal */
|
|
232
|
+
pTenant(tenantId) {
|
|
233
|
+
return `${this.baseUrl}/v1/me/tenants/${encodeURIComponent(tenantId)}`;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Low-level passthrough request. Centralizes the absolute URL (already built
|
|
237
|
+
* by a path-builder, so it carries the base URL + `/graphs/{tenant}` prefix),
|
|
238
|
+
* the `X-API-Key` header, JSON content-type, body stringification, and a
|
|
239
|
+
* timeout/abort — then returns the backend {@link Response} UNCHANGED.
|
|
240
|
+
*
|
|
241
|
+
* Unlike {@link request}, this does NOT inspect `res.ok` and does NOT parse or
|
|
242
|
+
* reshape the body. A 4xx/5xx comes back as a resolved `Response` (the caller
|
|
243
|
+
* reads `.status`/`.headers`/`.body`), NOT a thrown {@link CographError}. The
|
|
244
|
+
* only rejection paths are a genuine network failure or a timeout abort —
|
|
245
|
+
* exactly the cases where there is no HTTP response to hand back.
|
|
246
|
+
*
|
|
247
|
+
* `init.headers` is merged last so a caller can add/override headers; `init.body`,
|
|
248
|
+
* when a non-string is passed, is JSON-stringified for convenience.
|
|
249
|
+
*/
|
|
250
|
+
async requestRaw(method, path, init = {}) {
|
|
251
|
+
const timeoutMs = init.timeoutMs ?? 12e4;
|
|
252
|
+
const controller = new AbortController();
|
|
253
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
254
|
+
let body;
|
|
255
|
+
if (init.body !== void 0) {
|
|
256
|
+
body = typeof init.body === "string" ? init.body : JSON.stringify(init.body);
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
return await fetch(path, {
|
|
260
|
+
method,
|
|
261
|
+
headers: { ...this.headers(), ...init.headers ?? {} },
|
|
262
|
+
body,
|
|
263
|
+
signal: controller.signal
|
|
264
|
+
});
|
|
265
|
+
} catch (err) {
|
|
266
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
267
|
+
throw new CographError(`Request to ${path} timed out after ${timeoutMs}ms`);
|
|
268
|
+
}
|
|
269
|
+
throw new CographError(
|
|
270
|
+
`Network error contacting ${path}: ${err instanceof Error ? err.message : String(err)}`
|
|
271
|
+
);
|
|
272
|
+
} finally {
|
|
273
|
+
clearTimeout(timer);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Probe the backend to determine reachability and whether endpoints
|
|
278
|
+
* require an X-API-Key header. Used at shell startup to distinguish
|
|
279
|
+
* cloud (auth required) from self-hosted open-access deployments.
|
|
280
|
+
*/
|
|
281
|
+
async healthCheck() {
|
|
282
|
+
const healthUrl = `${this.baseUrl}/health`;
|
|
283
|
+
try {
|
|
284
|
+
const res = await fetch(healthUrl, {
|
|
285
|
+
signal: AbortSignal.timeout(5e3)
|
|
286
|
+
});
|
|
287
|
+
if (!res.ok) return { ok: false, requiresAuth: false, url: this.baseUrl };
|
|
288
|
+
} catch {
|
|
289
|
+
return { ok: false, requiresAuth: false, url: this.baseUrl };
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
const res = await fetch(`${this.base()}/kgs`, {
|
|
293
|
+
headers: { "Content-Type": "application/json" },
|
|
294
|
+
signal: AbortSignal.timeout(5e3)
|
|
295
|
+
});
|
|
296
|
+
return {
|
|
297
|
+
ok: true,
|
|
298
|
+
requiresAuth: res.status === 401,
|
|
299
|
+
url: this.baseUrl
|
|
300
|
+
};
|
|
301
|
+
} catch {
|
|
302
|
+
return { ok: true, requiresAuth: true, url: this.baseUrl };
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async request(method, url, body, timeoutMs = 12e4) {
|
|
306
|
+
const controller = new AbortController();
|
|
307
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
308
|
+
let res;
|
|
309
|
+
try {
|
|
310
|
+
res = await fetch(url, {
|
|
311
|
+
method,
|
|
312
|
+
headers: this.headers(),
|
|
313
|
+
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
314
|
+
signal: controller.signal
|
|
315
|
+
});
|
|
316
|
+
} catch (err) {
|
|
317
|
+
clearTimeout(timer);
|
|
318
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
319
|
+
throw new CographError(`Request to ${url} timed out after ${timeoutMs}ms`);
|
|
320
|
+
}
|
|
321
|
+
throw new CographError(
|
|
322
|
+
`Network error contacting ${url}: ${err instanceof Error ? err.message : String(err)}`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
clearTimeout(timer);
|
|
326
|
+
if (!res.ok) {
|
|
327
|
+
let text2 = "";
|
|
328
|
+
try {
|
|
329
|
+
text2 = await res.text();
|
|
330
|
+
} catch {
|
|
331
|
+
}
|
|
332
|
+
throw new CographError(`HTTP ${res.status}: ${text2}`, {
|
|
333
|
+
status: res.status,
|
|
334
|
+
body: text2
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
if (res.status === 204) return void 0;
|
|
338
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
339
|
+
if (ct.includes("application/json")) {
|
|
340
|
+
return await res.json();
|
|
341
|
+
}
|
|
342
|
+
const text = await res.text();
|
|
343
|
+
try {
|
|
344
|
+
return JSON.parse(text);
|
|
345
|
+
} catch {
|
|
346
|
+
return text;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Ingest a file path or raw text into a knowledge graph.
|
|
351
|
+
*
|
|
352
|
+
* If `pathOrText` points to an existing file, its contents are read and the
|
|
353
|
+
* format is inferred from the extension (.csv, .json, .txt) unless
|
|
354
|
+
* `contentType` is given. CSV files use the two-step schema-inference + row
|
|
355
|
+
* mapping flow.
|
|
356
|
+
*/
|
|
357
|
+
async ingest(pathOrText, opts = {}) {
|
|
358
|
+
let content;
|
|
359
|
+
let fmt;
|
|
360
|
+
let isFile = false;
|
|
361
|
+
try {
|
|
362
|
+
isFile = existsSync(pathOrText) && statSync(pathOrText).isFile();
|
|
363
|
+
} catch {
|
|
364
|
+
isFile = false;
|
|
365
|
+
}
|
|
366
|
+
if (isFile) {
|
|
367
|
+
const ext = extname(pathOrText).toLowerCase();
|
|
368
|
+
if (ext === ".pdf") {
|
|
369
|
+
throw new CographError(
|
|
370
|
+
"PDF ingest not yet supported in the Node CLI; use the Python CLI or POST raw bytes to the API."
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
content = readFileSync(pathOrText, "utf-8");
|
|
374
|
+
fmt = opts.contentType ?? EXT_FORMAT[ext] ?? "text";
|
|
375
|
+
if (fmt === "csv") {
|
|
376
|
+
return this.ingestCsv(content, opts);
|
|
377
|
+
}
|
|
378
|
+
} else {
|
|
379
|
+
content = pathOrText;
|
|
380
|
+
fmt = opts.contentType ?? "text";
|
|
381
|
+
}
|
|
382
|
+
const body = {
|
|
383
|
+
content,
|
|
384
|
+
content_type: fmt,
|
|
385
|
+
source: "client"
|
|
386
|
+
};
|
|
387
|
+
if (opts.kg) body.kg_name = opts.kg;
|
|
388
|
+
return this.request("POST", `${this.base()}/ingest`, body, 12e4);
|
|
389
|
+
}
|
|
390
|
+
async ingestCsv(content, opts) {
|
|
391
|
+
const kgName = opts.kg;
|
|
392
|
+
const batchSize = opts.batchSize ?? 200;
|
|
393
|
+
const concurrency = opts.concurrency ?? 4;
|
|
394
|
+
const rows = parseCsv(content);
|
|
395
|
+
if (rows.length === 0) throw new CographError("CSV is empty");
|
|
396
|
+
const headers = Object.keys(rows[0]);
|
|
397
|
+
const sampleRows = stridedSample(rows);
|
|
398
|
+
const schemaBody = {
|
|
399
|
+
headers,
|
|
400
|
+
sample_rows: sampleRows,
|
|
401
|
+
total_rows: rows.length
|
|
402
|
+
};
|
|
403
|
+
const mapping = await this.request(
|
|
404
|
+
"POST",
|
|
405
|
+
`${this.base()}/ingest/csv/schema`,
|
|
406
|
+
schemaBody,
|
|
407
|
+
3e5
|
|
408
|
+
);
|
|
409
|
+
let mappingToPost = mapping;
|
|
410
|
+
if (opts.onSchemaInferred) {
|
|
411
|
+
const reviewed = await opts.onSchemaInferred(mapping, {
|
|
412
|
+
totalRows: rows.length,
|
|
413
|
+
rowsProfiled: sampleRows.length
|
|
414
|
+
});
|
|
415
|
+
if (reviewed == null) {
|
|
416
|
+
return { cancelled: true, message: "Ingest cancelled before any rows were written." };
|
|
417
|
+
}
|
|
418
|
+
mappingToPost = reviewed;
|
|
419
|
+
}
|
|
420
|
+
const batches = [];
|
|
421
|
+
for (let i = 0; i < rows.length; i += batchSize) {
|
|
422
|
+
batches.push(rows.slice(i, i + batchSize));
|
|
423
|
+
}
|
|
424
|
+
let totalEntities = 0;
|
|
425
|
+
let totalTriples = 0;
|
|
426
|
+
let rowsProcessed = 0;
|
|
427
|
+
let nextBatch = 0;
|
|
428
|
+
const postBatch = async (batch) => {
|
|
429
|
+
const body = {
|
|
430
|
+
mapping: mappingToPost,
|
|
431
|
+
rows: batch,
|
|
432
|
+
source: "client"
|
|
433
|
+
};
|
|
434
|
+
if (kgName) body.kg_name = kgName;
|
|
435
|
+
const result = await this.request("POST", `${this.base()}/ingest/csv/rows`, body, 3e5);
|
|
436
|
+
return {
|
|
437
|
+
entities: result.entities_resolved ?? 0,
|
|
438
|
+
triples: result.triples_inserted ?? 0,
|
|
439
|
+
size: batch.length
|
|
440
|
+
};
|
|
441
|
+
};
|
|
442
|
+
const worker = async () => {
|
|
443
|
+
while (true) {
|
|
444
|
+
const idx = nextBatch++;
|
|
445
|
+
if (idx >= batches.length) return;
|
|
446
|
+
const r = await postBatch(batches[idx]);
|
|
447
|
+
totalEntities += r.entities;
|
|
448
|
+
totalTriples += r.triples;
|
|
449
|
+
rowsProcessed += r.size;
|
|
450
|
+
opts.onProgress?.({
|
|
451
|
+
rowsProcessed,
|
|
452
|
+
totalRows: rows.length,
|
|
453
|
+
entitiesResolved: totalEntities,
|
|
454
|
+
triplesInserted: totalTriples
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
const workers = [];
|
|
459
|
+
for (let i = 0; i < Math.min(concurrency, batches.length); i++) {
|
|
460
|
+
workers.push(worker());
|
|
461
|
+
}
|
|
462
|
+
await Promise.all(workers);
|
|
463
|
+
if (kgName) {
|
|
464
|
+
try {
|
|
465
|
+
await this.request(
|
|
466
|
+
"POST",
|
|
467
|
+
`${this.base()}/explore/kgs/${encodeURIComponent(kgName)}/recompute-stats`,
|
|
468
|
+
{},
|
|
469
|
+
15e3
|
|
470
|
+
);
|
|
471
|
+
} catch {
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return {
|
|
475
|
+
entities_resolved: totalEntities,
|
|
476
|
+
triples_inserted: totalTriples,
|
|
477
|
+
mapping
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
/** Ask a natural language question and return the parsed response. */
|
|
481
|
+
async ask(question, opts = {}) {
|
|
482
|
+
const body = { question };
|
|
483
|
+
if (opts.kg) body.kg_name = opts.kg;
|
|
484
|
+
if (opts.model) body.model = opts.model;
|
|
485
|
+
return this.request("POST", `${this.base()}/ask`, body, 6e4);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* One turn of the unified Ask-AI agent — the SINGLE conversational surface
|
|
489
|
+
* (`POST /graphs/{tenant}/agent`, COG-118). Mirrors the HTTP contract exactly:
|
|
490
|
+
*
|
|
491
|
+
* - `confirmPlanId` set → the server runs `execute_plan` (the only mutating
|
|
492
|
+
* path) and returns `{kind:"result", steps}`.
|
|
493
|
+
* - otherwise → the server runs `planner.handle(message)` and returns one of
|
|
494
|
+
* `{kind:"answer"}` / `{kind:"clarify"}` / `{kind:"plan"}`.
|
|
495
|
+
*
|
|
496
|
+
* The agent classifies intent server-side and drives the underlying engines
|
|
497
|
+
* through its capability registry — the client never talks to `/ask`,
|
|
498
|
+
* `/enrich/*` etc. for an agent turn. ENTITLEMENT for any paid step a plan
|
|
499
|
+
* contains is enforced server-side at execute time (the same authorization the
|
|
500
|
+
* direct paid routes apply), so confirming a plan here cannot bypass a gate the
|
|
501
|
+
* direct path enforces — the gate lives behind the endpoint, not in this client.
|
|
502
|
+
*/
|
|
503
|
+
async agent(opts) {
|
|
504
|
+
const body = {
|
|
505
|
+
message: opts.message ?? "",
|
|
506
|
+
context: {
|
|
507
|
+
kg_name: opts.kgName ?? "",
|
|
508
|
+
type_name: opts.typeName ?? null
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
if (opts.sessionId) body.session_id = opts.sessionId;
|
|
512
|
+
if (opts.confirmPlanId) body.confirm = { plan_id: opts.confirmPlanId };
|
|
513
|
+
return this.request(
|
|
514
|
+
"POST",
|
|
515
|
+
`${this.base()}/agent`,
|
|
516
|
+
body,
|
|
517
|
+
// Generous: a confirmed plan can kick off enrichment/dedup work, and a
|
|
518
|
+
// question turn runs an LLM round-trip server-side.
|
|
519
|
+
12e4
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
/** List the tenants the authenticated user can access (GET /v1/me/tenants).
|
|
523
|
+
* Keyed by the API key (X-API-Key → user), so it's independent of the active
|
|
524
|
+
* tenant. Throws CographError with status 501 on deployments without a tenant
|
|
525
|
+
* provider (e.g. OSS-only). */
|
|
526
|
+
async listTenants() {
|
|
527
|
+
return this.request(
|
|
528
|
+
"GET",
|
|
529
|
+
`${this.baseUrl}/v1/me/tenants`,
|
|
530
|
+
void 0,
|
|
531
|
+
15e3
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
/** List all knowledge graphs for the current tenant. */
|
|
535
|
+
async listKgs() {
|
|
536
|
+
const data = await this.request(
|
|
537
|
+
"GET",
|
|
538
|
+
`${this.base()}/kgs`,
|
|
539
|
+
void 0,
|
|
540
|
+
15e3
|
|
541
|
+
);
|
|
542
|
+
if (Array.isArray(data)) return data;
|
|
543
|
+
if (data && typeof data === "object" && "kgs" in data) {
|
|
544
|
+
const kgs = data.kgs;
|
|
545
|
+
if (Array.isArray(kgs)) return kgs;
|
|
546
|
+
}
|
|
547
|
+
return [];
|
|
548
|
+
}
|
|
549
|
+
/** Create a knowledge graph. */
|
|
550
|
+
async createKg(name, description) {
|
|
551
|
+
const body = { name };
|
|
552
|
+
if (description) body.description = description;
|
|
553
|
+
return this.request("POST", `${this.base()}/kgs`, body, 15e3);
|
|
554
|
+
}
|
|
555
|
+
/** Delete a knowledge graph by name. */
|
|
556
|
+
async deleteKg(name) {
|
|
557
|
+
return this.request(
|
|
558
|
+
"DELETE",
|
|
559
|
+
`${this.base()}/kgs/${encodeURIComponent(name)}`,
|
|
560
|
+
void 0,
|
|
561
|
+
3e4
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
/** List ontology types. */
|
|
565
|
+
async ontologyTypes() {
|
|
566
|
+
const data = await this.request(
|
|
567
|
+
"GET",
|
|
568
|
+
`${this.base()}/ontology/types`,
|
|
569
|
+
void 0,
|
|
570
|
+
15e3
|
|
571
|
+
);
|
|
572
|
+
return Array.isArray(data) ? data : [];
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Resolve a natural-language ontology change against the existing ontology.
|
|
576
|
+
* The caller does not need to know exact type/attribute/relationship names —
|
|
577
|
+
* the server matches the plain-language `ask` to the current schema and
|
|
578
|
+
* returns auto-applied changes plus proposals that need confirmation.
|
|
579
|
+
*/
|
|
580
|
+
async ontologyResolve(ask, opts = {}) {
|
|
581
|
+
const body = { ask };
|
|
582
|
+
if (opts.knowledge_graph) body.knowledge_graph = opts.knowledge_graph;
|
|
583
|
+
return this.request(
|
|
584
|
+
"POST",
|
|
585
|
+
`${this.base()}/ontology/resolve`,
|
|
586
|
+
body,
|
|
587
|
+
6e4
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Apply a single resolved ontology change — one of the `proposals` returned
|
|
592
|
+
* by {@link ontologyResolve}. Pass the proposal object through unchanged.
|
|
593
|
+
*/
|
|
594
|
+
async ontologyApply(proposal) {
|
|
595
|
+
return this.request(
|
|
596
|
+
"POST",
|
|
597
|
+
`${this.base()}/ontology/apply`,
|
|
598
|
+
proposal,
|
|
599
|
+
6e4
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Second-pass entity resolution: re-run ER over an already-ingested KG to
|
|
604
|
+
* collapse intra-batch fragments. Synchronous on the server; returns a
|
|
605
|
+
* per-type before/after report. Generous timeout — it rewrites triples.
|
|
606
|
+
*/
|
|
607
|
+
async erRebuild(kg) {
|
|
608
|
+
return this.request(
|
|
609
|
+
"POST",
|
|
610
|
+
`${this.base()}/explore/kgs/${encodeURIComponent(kg)}/er-rebuild`,
|
|
611
|
+
{},
|
|
612
|
+
3e5
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
/** Per-KG type counts: every type with ≥1 instance, sorted desc. */
|
|
616
|
+
async typeCounts(kg) {
|
|
617
|
+
const data = await this.request(
|
|
618
|
+
"GET",
|
|
619
|
+
`${this.base()}/kgs/${encodeURIComponent(kg)}/type-counts`,
|
|
620
|
+
void 0,
|
|
621
|
+
3e4
|
|
622
|
+
);
|
|
623
|
+
return Array.isArray(data) ? data : [];
|
|
624
|
+
}
|
|
625
|
+
/** Plan + run an enrichment job. Returns immediately with the job id. */
|
|
626
|
+
async enrichRun(req) {
|
|
627
|
+
return this.request(
|
|
628
|
+
"POST",
|
|
629
|
+
`${this.base()}/enrich/jobs`,
|
|
630
|
+
req,
|
|
631
|
+
3e4
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
/** List recent enrichment jobs for the current tenant. */
|
|
635
|
+
async enrichJobs() {
|
|
636
|
+
const data = await this.request(
|
|
637
|
+
"GET",
|
|
638
|
+
`${this.base()}/enrich/jobs`,
|
|
639
|
+
void 0,
|
|
640
|
+
15e3
|
|
641
|
+
);
|
|
642
|
+
return Array.isArray(data) ? data : [];
|
|
643
|
+
}
|
|
644
|
+
/** Fetch a single enrichment job (with truncated results). */
|
|
645
|
+
async enrichJob(jobId) {
|
|
646
|
+
return this.request(
|
|
647
|
+
"GET",
|
|
648
|
+
`${this.base()}/enrich/jobs/${encodeURIComponent(jobId)}`,
|
|
649
|
+
void 0,
|
|
650
|
+
15e3
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
/** Fetch the conflict review queue for a job. */
|
|
654
|
+
async enrichConflicts(jobId) {
|
|
655
|
+
const data = await this.request(
|
|
656
|
+
"GET",
|
|
657
|
+
`${this.base()}/enrich/jobs/${encodeURIComponent(jobId)}/conflicts`,
|
|
658
|
+
void 0,
|
|
659
|
+
3e4
|
|
660
|
+
);
|
|
661
|
+
return Array.isArray(data) ? data : [];
|
|
662
|
+
}
|
|
663
|
+
/** Apply a set of conflict review decisions to a job. */
|
|
664
|
+
async enrichApply(jobId, decisions) {
|
|
665
|
+
return this.request(
|
|
666
|
+
"POST",
|
|
667
|
+
`${this.base()}/enrich/jobs/${encodeURIComponent(jobId)}/apply`,
|
|
668
|
+
{ decisions },
|
|
669
|
+
6e4
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
/** Cancel an enrichment job. */
|
|
673
|
+
async enrichCancel(jobId) {
|
|
674
|
+
await this.request(
|
|
675
|
+
"DELETE",
|
|
676
|
+
`${this.base()}/enrich/jobs/${encodeURIComponent(jobId)}`,
|
|
677
|
+
void 0,
|
|
678
|
+
15e3
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
/** Per-type breakdown for one type in one KG: definition + counts + samples.
|
|
682
|
+
*
|
|
683
|
+
* System predicates (rdfs:label, ingested_at, source) are hidden by default
|
|
684
|
+
* — they're attached to every entity at 100% and drown out the columns the
|
|
685
|
+
* user cares about. Pass `includeSystem: true` to see them. */
|
|
686
|
+
async typeUsage(kg, typeName, opts = {}) {
|
|
687
|
+
const qs = opts.includeSystem ? "?include_system=true" : "";
|
|
688
|
+
return this.request(
|
|
689
|
+
"GET",
|
|
690
|
+
`${this.base()}/kgs/${encodeURIComponent(kg)}/types/${encodeURIComponent(typeName)}/usage${qs}`,
|
|
691
|
+
void 0,
|
|
692
|
+
3e4
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
/** Explorer summary for a type — like typeUsage but adds coverage_pct + avg_degree. */
|
|
696
|
+
async typeSummary(kg, typeName) {
|
|
697
|
+
return this.request(
|
|
698
|
+
"GET",
|
|
699
|
+
`${this.base()}/explore/kgs/${encodeURIComponent(kg)}/types/${encodeURIComponent(typeName)}/summary`,
|
|
700
|
+
void 0,
|
|
701
|
+
3e4
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
/** Search types or attributes by name substring within a KG. */
|
|
705
|
+
async exploreSearch(kg, q, kind = "type") {
|
|
706
|
+
const qs = new URLSearchParams({ kg, q, kind }).toString();
|
|
707
|
+
const data = await this.request(
|
|
708
|
+
"GET",
|
|
709
|
+
this.pExploreSearch(`?${qs}`),
|
|
710
|
+
void 0,
|
|
711
|
+
15e3
|
|
712
|
+
);
|
|
713
|
+
return Array.isArray(data) ? data : [];
|
|
714
|
+
}
|
|
715
|
+
// --- New typed methods (COG-128) ------------------------------------------ #
|
|
716
|
+
// Parsed/throwing variants of the previously-MISSING ops, sharing the same
|
|
717
|
+
// path-builders as the raw API. These follow the existing typed-method
|
|
718
|
+
// contract (throw on non-2xx, light reshape) — the raw equivalents under
|
|
719
|
+
// `client.raw.*` are the non-throwing, non-reshaping passthrough versions.
|
|
720
|
+
/**
|
|
721
|
+
* One page of entity instances of a type for the Explorer Data table
|
|
722
|
+
* (`GET /explore/kgs/{kg}/types/{type}/records`). Keyset-paginated by entity
|
|
723
|
+
* URI: pass the previous page's `next_cursor` as `cursor`. `limit` is clamped
|
|
724
|
+
* server-side to 1..200 (default 50).
|
|
725
|
+
*/
|
|
726
|
+
async exploreRecords(kg, typeName, opts = {}) {
|
|
727
|
+
const qs = new URLSearchParams();
|
|
728
|
+
if (opts.limit != null) qs.set("limit", String(opts.limit));
|
|
729
|
+
if (opts.cursor) qs.set("cursor", opts.cursor);
|
|
730
|
+
const query = qs.toString() ? `?${qs.toString()}` : "";
|
|
731
|
+
return this.request(
|
|
732
|
+
"GET",
|
|
733
|
+
this.pExploreRecords(kg, typeName, query),
|
|
734
|
+
void 0,
|
|
735
|
+
3e4
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
/** Undirected type→type edges for the Explorer overview graph
|
|
739
|
+
* (`GET /explore/kgs/{kg}/type-edges`). Returns `[{source, target, weight}]`. */
|
|
740
|
+
async exploreTypeEdges(kg) {
|
|
741
|
+
const data = await this.request(
|
|
742
|
+
"GET",
|
|
743
|
+
this.pExploreTypeEdges(kg),
|
|
744
|
+
void 0,
|
|
745
|
+
3e4
|
|
746
|
+
);
|
|
747
|
+
return Array.isArray(data) ? data : [];
|
|
748
|
+
}
|
|
749
|
+
/** Infer + persist normalization rules for a type's predicates, returned ranked
|
|
750
|
+
* by confidence desc (`POST /normalize/suggest?kg&type`). */
|
|
751
|
+
async normalizeSuggest(kg, type) {
|
|
752
|
+
const qs = new URLSearchParams({ kg, type }).toString();
|
|
753
|
+
const data = await this.request(
|
|
754
|
+
"POST",
|
|
755
|
+
this.pNormalizeSuggest(`?${qs}`),
|
|
756
|
+
void 0,
|
|
757
|
+
6e4
|
|
758
|
+
);
|
|
759
|
+
return Array.isArray(data) ? data : [];
|
|
760
|
+
}
|
|
761
|
+
/** List stored normalization rules, optionally filtered by KG and/or status
|
|
762
|
+
* (`GET /normalize/rules?kg&status`). */
|
|
763
|
+
async normalizeRules(opts = {}) {
|
|
764
|
+
const qs = new URLSearchParams();
|
|
765
|
+
if (opts.kg) qs.set("kg", opts.kg);
|
|
766
|
+
if (opts.status) qs.set("status", opts.status);
|
|
767
|
+
const query = qs.toString() ? `?${qs.toString()}` : "";
|
|
768
|
+
const data = await this.request(
|
|
769
|
+
"GET",
|
|
770
|
+
this.pNormalizeRules(query),
|
|
771
|
+
void 0,
|
|
772
|
+
15e3
|
|
773
|
+
);
|
|
774
|
+
return Array.isArray(data) ? data : [];
|
|
775
|
+
}
|
|
776
|
+
/** Confirm a suggested normalization rule (`POST /normalize/rules/{id}/confirm`). */
|
|
777
|
+
async normalizeConfirmRule(ruleId) {
|
|
778
|
+
return this.request(
|
|
779
|
+
"POST",
|
|
780
|
+
this.pNormalizeRule(ruleId, "confirm"),
|
|
781
|
+
void 0,
|
|
782
|
+
15e3
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
/** Reject a suggested normalization rule (`POST /normalize/rules/{id}/reject`). */
|
|
786
|
+
async normalizeRejectRule(ruleId) {
|
|
787
|
+
return this.request(
|
|
788
|
+
"POST",
|
|
789
|
+
this.pNormalizeRule(ruleId, "reject"),
|
|
790
|
+
void 0,
|
|
791
|
+
15e3
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
/** Apply a confirmed normalization rule in the background; the server acks 202
|
|
795
|
+
* (`POST /normalize/rules/{id}/apply`). */
|
|
796
|
+
async normalizeApplyRule(ruleId) {
|
|
797
|
+
return this.request(
|
|
798
|
+
"POST",
|
|
799
|
+
this.pNormalizeRule(ruleId, "apply"),
|
|
800
|
+
{},
|
|
801
|
+
6e4
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
/** Recommend ontology relationships/changes for the active KG
|
|
805
|
+
* (`POST /ontology/recommend`). Body shape is passed through unchanged.
|
|
806
|
+
*
|
|
807
|
+
* NOTE: this targets the *premium* ontology-recommender route, which is only
|
|
808
|
+
* mounted on deployments carrying the proprietary layer. It 404s on a bare
|
|
809
|
+
* OSS deployment. */
|
|
810
|
+
async ontologyRecommend(body = {}) {
|
|
811
|
+
return this.request(
|
|
812
|
+
"POST",
|
|
813
|
+
this.pOntologyRecommend(),
|
|
814
|
+
body,
|
|
815
|
+
6e4
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
var RawApi = class {
|
|
820
|
+
constructor(client) {
|
|
821
|
+
this.client = client;
|
|
822
|
+
}
|
|
823
|
+
client;
|
|
824
|
+
// -- agent / ask --------------------------------------------------------- #
|
|
825
|
+
/** `POST /graphs/{tenant}/agent` — one turn of the unified Ask-AI agent. */
|
|
826
|
+
agent(body, init) {
|
|
827
|
+
return this.client.requestRaw("POST", this.client.pAgent(), { body, ...init });
|
|
828
|
+
}
|
|
829
|
+
/** `POST /graphs/{tenant}/ask` — natural-language question. */
|
|
830
|
+
ask(body, init) {
|
|
831
|
+
return this.client.requestRaw("POST", this.client.pAsk(), { body, ...init });
|
|
832
|
+
}
|
|
833
|
+
// -- ingest -------------------------------------------------------------- #
|
|
834
|
+
/** `POST /graphs/{tenant}/ingest` — ingest text/json (or csv) content. */
|
|
835
|
+
ingest(body, init) {
|
|
836
|
+
return this.client.requestRaw("POST", this.client.pIngest(), { body, ...init });
|
|
837
|
+
}
|
|
838
|
+
/** `POST /graphs/{tenant}/ingest/csv/schema` — infer a CSV schema mapping. */
|
|
839
|
+
ingestCsvSchema(body, init) {
|
|
840
|
+
return this.client.requestRaw("POST", this.client.pIngestCsvSchema(), { body, ...init });
|
|
841
|
+
}
|
|
842
|
+
/** `POST /graphs/{tenant}/ingest/csv/rows` — write a batch of mapped rows. */
|
|
843
|
+
ingestCsvRows(body, init) {
|
|
844
|
+
return this.client.requestRaw("POST", this.client.pIngestCsvRows(), { body, ...init });
|
|
845
|
+
}
|
|
846
|
+
// -- enrich jobs --------------------------------------------------------- #
|
|
847
|
+
/** `POST /graphs/{tenant}/enrich/jobs` — plan + run an enrichment job. */
|
|
848
|
+
enrichCreateJob(body, init) {
|
|
849
|
+
return this.client.requestRaw("POST", this.client.pEnrichJobs(), { body, ...init });
|
|
850
|
+
}
|
|
851
|
+
/** `GET /graphs/{tenant}/enrich/jobs` — list recent enrichment jobs. */
|
|
852
|
+
enrichJobs(init) {
|
|
853
|
+
return this.client.requestRaw("GET", this.client.pEnrichJobs(), init);
|
|
854
|
+
}
|
|
855
|
+
/** `GET /graphs/{tenant}/enrich/jobs/{id}` — fetch a single job. */
|
|
856
|
+
enrichJob(jobId, init) {
|
|
857
|
+
return this.client.requestRaw("GET", this.client.pEnrichJob(jobId), init);
|
|
858
|
+
}
|
|
859
|
+
/** `GET /graphs/{tenant}/enrich/jobs/{id}/conflicts` — conflict review queue. */
|
|
860
|
+
enrichConflicts(jobId, init) {
|
|
861
|
+
return this.client.requestRaw("GET", this.client.pEnrichJobConflicts(jobId), init);
|
|
862
|
+
}
|
|
863
|
+
/** `POST /graphs/{tenant}/enrich/jobs/{id}/apply` — apply review decisions. */
|
|
864
|
+
enrichApply(jobId, body, init) {
|
|
865
|
+
return this.client.requestRaw("POST", this.client.pEnrichJobApply(jobId), { body, ...init });
|
|
866
|
+
}
|
|
867
|
+
/** `DELETE /graphs/{tenant}/enrich/jobs/{id}` — cancel a job. */
|
|
868
|
+
enrichCancel(jobId, init) {
|
|
869
|
+
return this.client.requestRaw("DELETE", this.client.pEnrichJob(jobId), init);
|
|
870
|
+
}
|
|
871
|
+
// -- ontology ------------------------------------------------------------ #
|
|
872
|
+
/** `GET /graphs/{tenant}/ontology/types` — list ontology types. */
|
|
873
|
+
ontologyTypes(init) {
|
|
874
|
+
return this.client.requestRaw("GET", this.client.pOntologyTypes(), init);
|
|
875
|
+
}
|
|
876
|
+
/** `POST /graphs/{tenant}/ontology/resolve` — resolve an NL ontology change. */
|
|
877
|
+
ontologyResolve(body, init) {
|
|
878
|
+
return this.client.requestRaw("POST", this.client.pOntologyResolve(), { body, ...init });
|
|
879
|
+
}
|
|
880
|
+
/** `POST /graphs/{tenant}/ontology/recommend` — recommend ontology changes.
|
|
881
|
+
* Premium route: only mounted on deployments with the proprietary layer,
|
|
882
|
+
* 404s on bare OSS. */
|
|
883
|
+
ontologyRecommend(body, init) {
|
|
884
|
+
return this.client.requestRaw("POST", this.client.pOntologyRecommend(), { body, ...init });
|
|
885
|
+
}
|
|
886
|
+
/** `POST /graphs/{tenant}/ontology/apply` — apply one resolved change. */
|
|
887
|
+
ontologyApply(body, init) {
|
|
888
|
+
return this.client.requestRaw("POST", this.client.pOntologyApply(), { body, ...init });
|
|
889
|
+
}
|
|
890
|
+
// -- knowledge graphs ---------------------------------------------------- #
|
|
891
|
+
/** `GET /graphs/{tenant}/kgs` — list knowledge graphs. */
|
|
892
|
+
kgs(init) {
|
|
893
|
+
return this.client.requestRaw("GET", this.client.pKgs(), init);
|
|
894
|
+
}
|
|
895
|
+
/** `POST /graphs/{tenant}/kgs` — create a knowledge graph. */
|
|
896
|
+
createKg(body, init) {
|
|
897
|
+
return this.client.requestRaw("POST", this.client.pKgs(), { body, ...init });
|
|
898
|
+
}
|
|
899
|
+
/** `DELETE /graphs/{tenant}/kgs/{name}` — delete a knowledge graph. */
|
|
900
|
+
deleteKg(name, init) {
|
|
901
|
+
return this.client.requestRaw("DELETE", this.client.pKg(name), init);
|
|
902
|
+
}
|
|
903
|
+
// -- explore ------------------------------------------------------------- #
|
|
904
|
+
/** `GET /graphs/{tenant}/explore/kgs/{kg}/types/{type}/summary`. */
|
|
905
|
+
exploreSummary(kg, typeName, init) {
|
|
906
|
+
return this.client.requestRaw("GET", this.client.pExploreSummary(kg, typeName), init);
|
|
907
|
+
}
|
|
908
|
+
/** `GET /graphs/{tenant}/explore/kgs/{kg}/types/{type}/records?limit&cursor`. */
|
|
909
|
+
exploreRecords(kg, typeName, opts = {}, init) {
|
|
910
|
+
const qs = new URLSearchParams();
|
|
911
|
+
if (opts.limit != null) qs.set("limit", String(opts.limit));
|
|
912
|
+
if (opts.cursor) qs.set("cursor", opts.cursor);
|
|
913
|
+
const query = qs.toString() ? `?${qs.toString()}` : "";
|
|
914
|
+
return this.client.requestRaw("GET", this.client.pExploreRecords(kg, typeName, query), init);
|
|
915
|
+
}
|
|
916
|
+
/** `GET /graphs/{tenant}/explore/kgs/{kg}/type-edges`. */
|
|
917
|
+
exploreTypeEdges(kg, init) {
|
|
918
|
+
return this.client.requestRaw("GET", this.client.pExploreTypeEdges(kg), init);
|
|
919
|
+
}
|
|
920
|
+
/** `GET /graphs/{tenant}/kgs/{kg}/type-counts`. */
|
|
921
|
+
typeCounts(kg, init) {
|
|
922
|
+
return this.client.requestRaw("GET", this.client.pTypeCounts(kg), init);
|
|
923
|
+
}
|
|
924
|
+
/** `GET /graphs/{tenant}/explore/search?kg&q&kind`. */
|
|
925
|
+
exploreSearch(kg, q, kind = "type", init) {
|
|
926
|
+
const qs = new URLSearchParams({ kg, q, kind }).toString();
|
|
927
|
+
return this.client.requestRaw("GET", this.client.pExploreSearch(`?${qs}`), init);
|
|
928
|
+
}
|
|
929
|
+
// -- normalize ----------------------------------------------------------- #
|
|
930
|
+
/** `POST /graphs/{tenant}/normalize/suggest?kg&type` — infer + persist rules. */
|
|
931
|
+
normalizeSuggest(kg, type, init) {
|
|
932
|
+
const qs = new URLSearchParams({ kg, type }).toString();
|
|
933
|
+
return this.client.requestRaw("POST", this.client.pNormalizeSuggest(`?${qs}`), init);
|
|
934
|
+
}
|
|
935
|
+
/** `GET /graphs/{tenant}/normalize/rules?kg&status` — list stored rules. */
|
|
936
|
+
normalizeRules(opts = {}, init) {
|
|
937
|
+
const qs = new URLSearchParams();
|
|
938
|
+
if (opts.kg) qs.set("kg", opts.kg);
|
|
939
|
+
if (opts.status) qs.set("status", opts.status);
|
|
940
|
+
const query = qs.toString() ? `?${qs.toString()}` : "";
|
|
941
|
+
return this.client.requestRaw("GET", this.client.pNormalizeRules(query), init);
|
|
942
|
+
}
|
|
943
|
+
/** `POST /graphs/{tenant}/normalize/rules` — create a user-authored rule. */
|
|
944
|
+
normalizeCreateRule(body, init) {
|
|
945
|
+
return this.client.requestRaw("POST", this.client.pNormalizeRules(), { body, ...init });
|
|
946
|
+
}
|
|
947
|
+
/** `POST /graphs/{tenant}/normalize/rules/{id}/confirm`. */
|
|
948
|
+
normalizeConfirmRule(ruleId, init) {
|
|
949
|
+
return this.client.requestRaw("POST", this.client.pNormalizeRule(ruleId, "confirm"), init);
|
|
950
|
+
}
|
|
951
|
+
/** `POST /graphs/{tenant}/normalize/rules/{id}/reject`. */
|
|
952
|
+
normalizeRejectRule(ruleId, init) {
|
|
953
|
+
return this.client.requestRaw("POST", this.client.pNormalizeRule(ruleId, "reject"), init);
|
|
954
|
+
}
|
|
955
|
+
/** `POST /graphs/{tenant}/normalize/rules/{id}/apply`. */
|
|
956
|
+
normalizeApplyRule(ruleId, init) {
|
|
957
|
+
return this.client.requestRaw("POST", this.client.pNormalizeRule(ruleId, "apply"), init);
|
|
958
|
+
}
|
|
959
|
+
// -- tenants (account-level, NOT tenant-scoped) -------------------------- #
|
|
960
|
+
/** `POST /v1/me/tenants` — create/grant a tenant for the authed user. */
|
|
961
|
+
createTenant(body, init) {
|
|
962
|
+
return this.client.requestRaw("POST", this.client.pTenants(), { body, ...init });
|
|
963
|
+
}
|
|
964
|
+
/** `DELETE /v1/me/tenants/{id}` — remove a tenant grant. */
|
|
965
|
+
deleteTenant(tenantId, init) {
|
|
966
|
+
return this.client.requestRaw("DELETE", this.client.pTenant(tenantId), init);
|
|
967
|
+
}
|
|
968
|
+
/** `GET /v1/me/tenants` — list tenants the authed user can access. */
|
|
969
|
+
tenants(init) {
|
|
970
|
+
return this.client.requestRaw("GET", this.client.pTenants(), init);
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
|
|
974
|
+
export {
|
|
975
|
+
CographError,
|
|
976
|
+
Client
|
|
977
|
+
};
|
|
978
|
+
//# sourceMappingURL=chunk-PE2EOIGT.js.map
|