cograph 0.1.25 → 0.1.28

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.js CHANGED
@@ -116,12 +116,23 @@ var Client = class {
116
116
  apiKey;
117
117
  baseUrl;
118
118
  tenant;
119
+ /**
120
+ * Raw / passthrough API — one method per canonical backend operation, with
121
+ * the path encoded inside the SDK. Each method returns the backend
122
+ * {@link Response} VERBATIM: it does NOT throw on non-2xx and does NOT reshape
123
+ * the body. This is the seam the webapp's proxy layer adopts so per-operation
124
+ * paths live in one place (here) instead of being hand-rolled at each call
125
+ * site. See {@link RawApi}. The typed methods on this class (which throw on
126
+ * non-2xx and reshape some payloads) are left unchanged — this is additive.
127
+ */
128
+ raw;
119
129
  constructor(opts = {}) {
120
130
  const cfg = readConfig();
121
131
  this.apiKey = opts.apiKey ?? envVar("API_KEY") ?? cfg.apiKey;
122
132
  const url = opts.baseUrl ?? envVar("API_URL") ?? cfg.apiUrl ?? "https://api.cograph.cloud";
123
133
  this.baseUrl = url.replace(/\/+$/, "");
124
134
  this.tenant = opts.tenant ?? envVar("TENANT") ?? cfg.tenant ?? "demo-tenant";
135
+ this.raw = new RawApi(this);
125
136
  }
126
137
  headers() {
127
138
  const h = { "Content-Type": "application/json" };
@@ -131,6 +142,158 @@ var Client = class {
131
142
  base() {
132
143
  return `${this.baseUrl}/graphs/${this.tenant}`;
133
144
  }
145
+ // --- Path builders -------------------------------------------------------- #
146
+ // SINGLE source of truth for every canonical backend path. Both the raw API
147
+ // and the new typed parsed methods build URLs through these, so a path lives
148
+ // in exactly one place. Tenant-scoped paths hang off `base()`
149
+ // (`{baseUrl}/graphs/{tenant}`); the handful of account-level paths
150
+ // (e.g. tenant CRUD) hang off `baseUrl` directly.
151
+ //
152
+ // These are marked `@internal` (not part of the public SDK surface) but are
153
+ // not `private`, so the sibling {@link RawApi} can build the same canonical
154
+ // paths without duplicating them.
155
+ /** @internal */
156
+ pAgent() {
157
+ return `${this.base()}/agent`;
158
+ }
159
+ /** @internal */
160
+ pAsk() {
161
+ return `${this.base()}/ask`;
162
+ }
163
+ /** @internal */
164
+ pIngest() {
165
+ return `${this.base()}/ingest`;
166
+ }
167
+ /** @internal */
168
+ pIngestCsvSchema() {
169
+ return `${this.base()}/ingest/csv/schema`;
170
+ }
171
+ /** @internal */
172
+ pIngestCsvRows() {
173
+ return `${this.base()}/ingest/csv/rows`;
174
+ }
175
+ /** @internal */
176
+ pEnrichJobs() {
177
+ return `${this.base()}/enrich/jobs`;
178
+ }
179
+ /** @internal */
180
+ pEnrichJob(jobId) {
181
+ return `${this.base()}/enrich/jobs/${encodeURIComponent(jobId)}`;
182
+ }
183
+ /** @internal */
184
+ pEnrichJobConflicts(jobId) {
185
+ return `${this.pEnrichJob(jobId)}/conflicts`;
186
+ }
187
+ /** @internal */
188
+ pEnrichJobApply(jobId) {
189
+ return `${this.pEnrichJob(jobId)}/apply`;
190
+ }
191
+ /** @internal */
192
+ pOntologyTypes() {
193
+ return `${this.base()}/ontology/types`;
194
+ }
195
+ /** @internal */
196
+ pOntologyResolve() {
197
+ return `${this.base()}/ontology/resolve`;
198
+ }
199
+ /** @internal Targets the premium ontology-recommender route, mounted only on
200
+ * deployments with the proprietary layer — 404s on bare OSS. */
201
+ pOntologyRecommend() {
202
+ return `${this.base()}/ontology/recommend`;
203
+ }
204
+ /** @internal */
205
+ pOntologyApply() {
206
+ return `${this.base()}/ontology/apply`;
207
+ }
208
+ /** @internal */
209
+ pKgs() {
210
+ return `${this.base()}/kgs`;
211
+ }
212
+ /** @internal */
213
+ pKg(name) {
214
+ return `${this.base()}/kgs/${encodeURIComponent(name)}`;
215
+ }
216
+ /** @internal */
217
+ pTypeCounts(kg) {
218
+ return `${this.pKg(kg)}/type-counts`;
219
+ }
220
+ /** @internal */
221
+ pExploreSummary(kg, typeName) {
222
+ return `${this.base()}/explore/kgs/${encodeURIComponent(kg)}/types/${encodeURIComponent(typeName)}/summary`;
223
+ }
224
+ /** @internal */
225
+ pExploreRecords(kg, typeName, query) {
226
+ return `${this.base()}/explore/kgs/${encodeURIComponent(kg)}/types/${encodeURIComponent(typeName)}/records${query ?? ""}`;
227
+ }
228
+ /** @internal */
229
+ pExploreTypeEdges(kg) {
230
+ return `${this.base()}/explore/kgs/${encodeURIComponent(kg)}/type-edges`;
231
+ }
232
+ /** @internal */
233
+ pExploreSearch(query) {
234
+ return `${this.base()}/explore/search${query}`;
235
+ }
236
+ /** @internal */
237
+ pNormalizeSuggest(query) {
238
+ return `${this.base()}/normalize/suggest${query}`;
239
+ }
240
+ /** @internal */
241
+ pNormalizeRules(query) {
242
+ return `${this.base()}/normalize/rules${query ?? ""}`;
243
+ }
244
+ /** @internal */
245
+ pNormalizeRule(ruleId, action) {
246
+ return `${this.base()}/normalize/rules/${encodeURIComponent(ruleId)}/${action}`;
247
+ }
248
+ /** @internal */
249
+ pTenants() {
250
+ return `${this.baseUrl}/v1/me/tenants`;
251
+ }
252
+ /** @internal */
253
+ pTenant(tenantId) {
254
+ return `${this.baseUrl}/v1/me/tenants/${encodeURIComponent(tenantId)}`;
255
+ }
256
+ /**
257
+ * Low-level passthrough request. Centralizes the absolute URL (already built
258
+ * by a path-builder, so it carries the base URL + `/graphs/{tenant}` prefix),
259
+ * the `X-API-Key` header, JSON content-type, body stringification, and a
260
+ * timeout/abort — then returns the backend {@link Response} UNCHANGED.
261
+ *
262
+ * Unlike {@link request}, this does NOT inspect `res.ok` and does NOT parse or
263
+ * reshape the body. A 4xx/5xx comes back as a resolved `Response` (the caller
264
+ * reads `.status`/`.headers`/`.body`), NOT a thrown {@link CographError}. The
265
+ * only rejection paths are a genuine network failure or a timeout abort —
266
+ * exactly the cases where there is no HTTP response to hand back.
267
+ *
268
+ * `init.headers` is merged last so a caller can add/override headers; `init.body`,
269
+ * when a non-string is passed, is JSON-stringified for convenience.
270
+ */
271
+ async requestRaw(method, path, init = {}) {
272
+ const timeoutMs = init.timeoutMs ?? 12e4;
273
+ const controller = new AbortController();
274
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
275
+ let body;
276
+ if (init.body !== void 0) {
277
+ body = typeof init.body === "string" ? init.body : JSON.stringify(init.body);
278
+ }
279
+ try {
280
+ return await fetch(path, {
281
+ method,
282
+ headers: { ...this.headers(), ...init.headers ?? {} },
283
+ body,
284
+ signal: controller.signal
285
+ });
286
+ } catch (err) {
287
+ if (err instanceof Error && err.name === "AbortError") {
288
+ throw new CographError(`Request to ${path} timed out after ${timeoutMs}ms`);
289
+ }
290
+ throw new CographError(
291
+ `Network error contacting ${path}: ${err instanceof Error ? err.message : String(err)}`
292
+ );
293
+ } finally {
294
+ clearTimeout(timer);
295
+ }
296
+ }
134
297
  /**
135
298
  * Probe the backend to determine reachability and whether endpoints
136
299
  * require an X-API-Key header. Used at shell startup to distinguish
@@ -564,15 +727,273 @@ var Client = class {
564
727
  const qs = new URLSearchParams({ kg, q, kind }).toString();
565
728
  const data = await this.request(
566
729
  "GET",
567
- `${this.base()}/explore/search?${qs}`,
730
+ this.pExploreSearch(`?${qs}`),
568
731
  void 0,
569
732
  15e3
570
733
  );
571
734
  return Array.isArray(data) ? data : [];
572
735
  }
736
+ // --- New typed methods (COG-128) ------------------------------------------ #
737
+ // Parsed/throwing variants of the previously-MISSING ops, sharing the same
738
+ // path-builders as the raw API. These follow the existing typed-method
739
+ // contract (throw on non-2xx, light reshape) — the raw equivalents under
740
+ // `client.raw.*` are the non-throwing, non-reshaping passthrough versions.
741
+ /**
742
+ * One page of entity instances of a type for the Explorer Data table
743
+ * (`GET /explore/kgs/{kg}/types/{type}/records`). Keyset-paginated by entity
744
+ * URI: pass the previous page's `next_cursor` as `cursor`. `limit` is clamped
745
+ * server-side to 1..200 (default 50).
746
+ */
747
+ async exploreRecords(kg, typeName, opts = {}) {
748
+ const qs = new URLSearchParams();
749
+ if (opts.limit != null) qs.set("limit", String(opts.limit));
750
+ if (opts.cursor) qs.set("cursor", opts.cursor);
751
+ const query = qs.toString() ? `?${qs.toString()}` : "";
752
+ return this.request(
753
+ "GET",
754
+ this.pExploreRecords(kg, typeName, query),
755
+ void 0,
756
+ 3e4
757
+ );
758
+ }
759
+ /** Undirected type→type edges for the Explorer overview graph
760
+ * (`GET /explore/kgs/{kg}/type-edges`). Returns `[{source, target, weight}]`. */
761
+ async exploreTypeEdges(kg) {
762
+ const data = await this.request(
763
+ "GET",
764
+ this.pExploreTypeEdges(kg),
765
+ void 0,
766
+ 3e4
767
+ );
768
+ return Array.isArray(data) ? data : [];
769
+ }
770
+ /** Infer + persist normalization rules for a type's predicates, returned ranked
771
+ * by confidence desc (`POST /normalize/suggest?kg&type`). */
772
+ async normalizeSuggest(kg, type) {
773
+ const qs = new URLSearchParams({ kg, type }).toString();
774
+ const data = await this.request(
775
+ "POST",
776
+ this.pNormalizeSuggest(`?${qs}`),
777
+ void 0,
778
+ 6e4
779
+ );
780
+ return Array.isArray(data) ? data : [];
781
+ }
782
+ /** List stored normalization rules, optionally filtered by KG and/or status
783
+ * (`GET /normalize/rules?kg&status`). */
784
+ async normalizeRules(opts = {}) {
785
+ const qs = new URLSearchParams();
786
+ if (opts.kg) qs.set("kg", opts.kg);
787
+ if (opts.status) qs.set("status", opts.status);
788
+ const query = qs.toString() ? `?${qs.toString()}` : "";
789
+ const data = await this.request(
790
+ "GET",
791
+ this.pNormalizeRules(query),
792
+ void 0,
793
+ 15e3
794
+ );
795
+ return Array.isArray(data) ? data : [];
796
+ }
797
+ /** Confirm a suggested normalization rule (`POST /normalize/rules/{id}/confirm`). */
798
+ async normalizeConfirmRule(ruleId) {
799
+ return this.request(
800
+ "POST",
801
+ this.pNormalizeRule(ruleId, "confirm"),
802
+ void 0,
803
+ 15e3
804
+ );
805
+ }
806
+ /** Reject a suggested normalization rule (`POST /normalize/rules/{id}/reject`). */
807
+ async normalizeRejectRule(ruleId) {
808
+ return this.request(
809
+ "POST",
810
+ this.pNormalizeRule(ruleId, "reject"),
811
+ void 0,
812
+ 15e3
813
+ );
814
+ }
815
+ /** Apply a confirmed normalization rule in the background; the server acks 202
816
+ * (`POST /normalize/rules/{id}/apply`). */
817
+ async normalizeApplyRule(ruleId) {
818
+ return this.request(
819
+ "POST",
820
+ this.pNormalizeRule(ruleId, "apply"),
821
+ {},
822
+ 6e4
823
+ );
824
+ }
825
+ /** Recommend ontology relationships/changes for the active KG
826
+ * (`POST /ontology/recommend`). Body shape is passed through unchanged.
827
+ *
828
+ * NOTE: this targets the *premium* ontology-recommender route, which is only
829
+ * mounted on deployments carrying the proprietary layer. It 404s on a bare
830
+ * OSS deployment. */
831
+ async ontologyRecommend(body = {}) {
832
+ return this.request(
833
+ "POST",
834
+ this.pOntologyRecommend(),
835
+ body,
836
+ 6e4
837
+ );
838
+ }
839
+ };
840
+ var RawApi = class {
841
+ constructor(client) {
842
+ this.client = client;
843
+ }
844
+ client;
845
+ // -- agent / ask --------------------------------------------------------- #
846
+ /** `POST /graphs/{tenant}/agent` — one turn of the unified Ask-AI agent. */
847
+ agent(body, init) {
848
+ return this.client.requestRaw("POST", this.client.pAgent(), { body, ...init });
849
+ }
850
+ /** `POST /graphs/{tenant}/ask` — natural-language question. */
851
+ ask(body, init) {
852
+ return this.client.requestRaw("POST", this.client.pAsk(), { body, ...init });
853
+ }
854
+ // -- ingest -------------------------------------------------------------- #
855
+ /** `POST /graphs/{tenant}/ingest` — ingest text/json (or csv) content. */
856
+ ingest(body, init) {
857
+ return this.client.requestRaw("POST", this.client.pIngest(), { body, ...init });
858
+ }
859
+ /** `POST /graphs/{tenant}/ingest/csv/schema` — infer a CSV schema mapping. */
860
+ ingestCsvSchema(body, init) {
861
+ return this.client.requestRaw("POST", this.client.pIngestCsvSchema(), { body, ...init });
862
+ }
863
+ /** `POST /graphs/{tenant}/ingest/csv/rows` — write a batch of mapped rows. */
864
+ ingestCsvRows(body, init) {
865
+ return this.client.requestRaw("POST", this.client.pIngestCsvRows(), { body, ...init });
866
+ }
867
+ // -- enrich jobs --------------------------------------------------------- #
868
+ /** `POST /graphs/{tenant}/enrich/jobs` — plan + run an enrichment job. */
869
+ enrichCreateJob(body, init) {
870
+ return this.client.requestRaw("POST", this.client.pEnrichJobs(), { body, ...init });
871
+ }
872
+ /** `GET /graphs/{tenant}/enrich/jobs` — list recent enrichment jobs. */
873
+ enrichJobs(init) {
874
+ return this.client.requestRaw("GET", this.client.pEnrichJobs(), init);
875
+ }
876
+ /** `GET /graphs/{tenant}/enrich/jobs/{id}` — fetch a single job. */
877
+ enrichJob(jobId, init) {
878
+ return this.client.requestRaw("GET", this.client.pEnrichJob(jobId), init);
879
+ }
880
+ /** `GET /graphs/{tenant}/enrich/jobs/{id}/conflicts` — conflict review queue. */
881
+ enrichConflicts(jobId, init) {
882
+ return this.client.requestRaw("GET", this.client.pEnrichJobConflicts(jobId), init);
883
+ }
884
+ /** `POST /graphs/{tenant}/enrich/jobs/{id}/apply` — apply review decisions. */
885
+ enrichApply(jobId, body, init) {
886
+ return this.client.requestRaw("POST", this.client.pEnrichJobApply(jobId), { body, ...init });
887
+ }
888
+ /** `DELETE /graphs/{tenant}/enrich/jobs/{id}` — cancel a job. */
889
+ enrichCancel(jobId, init) {
890
+ return this.client.requestRaw("DELETE", this.client.pEnrichJob(jobId), init);
891
+ }
892
+ // -- ontology ------------------------------------------------------------ #
893
+ /** `GET /graphs/{tenant}/ontology/types` — list ontology types. */
894
+ ontologyTypes(init) {
895
+ return this.client.requestRaw("GET", this.client.pOntologyTypes(), init);
896
+ }
897
+ /** `POST /graphs/{tenant}/ontology/resolve` — resolve an NL ontology change. */
898
+ ontologyResolve(body, init) {
899
+ return this.client.requestRaw("POST", this.client.pOntologyResolve(), { body, ...init });
900
+ }
901
+ /** `POST /graphs/{tenant}/ontology/recommend` — recommend ontology changes.
902
+ * Premium route: only mounted on deployments with the proprietary layer,
903
+ * 404s on bare OSS. */
904
+ ontologyRecommend(body, init) {
905
+ return this.client.requestRaw("POST", this.client.pOntologyRecommend(), { body, ...init });
906
+ }
907
+ /** `POST /graphs/{tenant}/ontology/apply` — apply one resolved change. */
908
+ ontologyApply(body, init) {
909
+ return this.client.requestRaw("POST", this.client.pOntologyApply(), { body, ...init });
910
+ }
911
+ // -- knowledge graphs ---------------------------------------------------- #
912
+ /** `GET /graphs/{tenant}/kgs` — list knowledge graphs. */
913
+ kgs(init) {
914
+ return this.client.requestRaw("GET", this.client.pKgs(), init);
915
+ }
916
+ /** `POST /graphs/{tenant}/kgs` — create a knowledge graph. */
917
+ createKg(body, init) {
918
+ return this.client.requestRaw("POST", this.client.pKgs(), { body, ...init });
919
+ }
920
+ /** `DELETE /graphs/{tenant}/kgs/{name}` — delete a knowledge graph. */
921
+ deleteKg(name, init) {
922
+ return this.client.requestRaw("DELETE", this.client.pKg(name), init);
923
+ }
924
+ // -- explore ------------------------------------------------------------- #
925
+ /** `GET /graphs/{tenant}/explore/kgs/{kg}/types/{type}/summary`. */
926
+ exploreSummary(kg, typeName, init) {
927
+ return this.client.requestRaw("GET", this.client.pExploreSummary(kg, typeName), init);
928
+ }
929
+ /** `GET /graphs/{tenant}/explore/kgs/{kg}/types/{type}/records?limit&cursor`. */
930
+ exploreRecords(kg, typeName, opts = {}, init) {
931
+ const qs = new URLSearchParams();
932
+ if (opts.limit != null) qs.set("limit", String(opts.limit));
933
+ if (opts.cursor) qs.set("cursor", opts.cursor);
934
+ const query = qs.toString() ? `?${qs.toString()}` : "";
935
+ return this.client.requestRaw("GET", this.client.pExploreRecords(kg, typeName, query), init);
936
+ }
937
+ /** `GET /graphs/{tenant}/explore/kgs/{kg}/type-edges`. */
938
+ exploreTypeEdges(kg, init) {
939
+ return this.client.requestRaw("GET", this.client.pExploreTypeEdges(kg), init);
940
+ }
941
+ /** `GET /graphs/{tenant}/kgs/{kg}/type-counts`. */
942
+ typeCounts(kg, init) {
943
+ return this.client.requestRaw("GET", this.client.pTypeCounts(kg), init);
944
+ }
945
+ /** `GET /graphs/{tenant}/explore/search?kg&q&kind`. */
946
+ exploreSearch(kg, q, kind = "type", init) {
947
+ const qs = new URLSearchParams({ kg, q, kind }).toString();
948
+ return this.client.requestRaw("GET", this.client.pExploreSearch(`?${qs}`), init);
949
+ }
950
+ // -- normalize ----------------------------------------------------------- #
951
+ /** `POST /graphs/{tenant}/normalize/suggest?kg&type` — infer + persist rules. */
952
+ normalizeSuggest(kg, type, init) {
953
+ const qs = new URLSearchParams({ kg, type }).toString();
954
+ return this.client.requestRaw("POST", this.client.pNormalizeSuggest(`?${qs}`), init);
955
+ }
956
+ /** `GET /graphs/{tenant}/normalize/rules?kg&status` — list stored rules. */
957
+ normalizeRules(opts = {}, init) {
958
+ const qs = new URLSearchParams();
959
+ if (opts.kg) qs.set("kg", opts.kg);
960
+ if (opts.status) qs.set("status", opts.status);
961
+ const query = qs.toString() ? `?${qs.toString()}` : "";
962
+ return this.client.requestRaw("GET", this.client.pNormalizeRules(query), init);
963
+ }
964
+ /** `POST /graphs/{tenant}/normalize/rules` — create a user-authored rule. */
965
+ normalizeCreateRule(body, init) {
966
+ return this.client.requestRaw("POST", this.client.pNormalizeRules(), { body, ...init });
967
+ }
968
+ /** `POST /graphs/{tenant}/normalize/rules/{id}/confirm`. */
969
+ normalizeConfirmRule(ruleId, init) {
970
+ return this.client.requestRaw("POST", this.client.pNormalizeRule(ruleId, "confirm"), init);
971
+ }
972
+ /** `POST /graphs/{tenant}/normalize/rules/{id}/reject`. */
973
+ normalizeRejectRule(ruleId, init) {
974
+ return this.client.requestRaw("POST", this.client.pNormalizeRule(ruleId, "reject"), init);
975
+ }
976
+ /** `POST /graphs/{tenant}/normalize/rules/{id}/apply`. */
977
+ normalizeApplyRule(ruleId, init) {
978
+ return this.client.requestRaw("POST", this.client.pNormalizeRule(ruleId, "apply"), init);
979
+ }
980
+ // -- tenants (account-level, NOT tenant-scoped) -------------------------- #
981
+ /** `POST /v1/me/tenants` — create/grant a tenant for the authed user. */
982
+ createTenant(body, init) {
983
+ return this.client.requestRaw("POST", this.client.pTenants(), { body, ...init });
984
+ }
985
+ /** `DELETE /v1/me/tenants/{id}` — remove a tenant grant. */
986
+ deleteTenant(tenantId, init) {
987
+ return this.client.requestRaw("DELETE", this.client.pTenant(tenantId), init);
988
+ }
989
+ /** `GET /v1/me/tenants` — list tenants the authed user can access. */
990
+ tenants(init) {
991
+ return this.client.requestRaw("GET", this.client.pTenants(), init);
992
+ }
573
993
  };
574
994
  export {
575
995
  Client,
576
- CographError
996
+ CographError,
997
+ RawApi
577
998
  };
578
999
  //# sourceMappingURL=index.js.map