@clinia/context-engine-js 0.6.0-rc.1 → 0.6.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/CHANGELOG.md +16 -0
- package/README.md +29 -13
- package/dist/context-engine-client.d.ts +14 -2
- package/dist/form-data.d.ts +14 -0
- package/dist/generated/context-engine.d.ts +4139 -877
- package/dist/generated/types.d.ts +13 -11
- package/dist/index.d.ts +1 -0
- package/dist/index.js +388 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/graph.d.ts +872 -13
- package/dist/resources/index.d.ts +23 -0
- package/dist/resources/ingest.d.ts +25 -279
- package/package.json +2 -2
|
@@ -6,17 +6,6 @@ export type ApiError = components["schemas"]["ApiError"];
|
|
|
6
6
|
export type Patient = components["schemas"]["Patient"];
|
|
7
7
|
export type ResolutionReport = components["schemas"]["ResolutionReport"];
|
|
8
8
|
export type ReconciliationData = components["schemas"]["ReconciliationData"];
|
|
9
|
-
export type IngestExecutionEnvelope = components["schemas"]["IngestExecutionEnvelope"];
|
|
10
|
-
export type IngestExecutionStatus = components["schemas"]["IngestExecutionStatus"];
|
|
11
|
-
export type IngestSourceLabel = components["schemas"]["IngestSourceLabel"];
|
|
12
|
-
export type PatientRef = components["schemas"]["PatientRef"];
|
|
13
|
-
export type IngestDocumentBody = components["schemas"]["IngestDocumentBody"];
|
|
14
|
-
export type IngestBatchBody = components["schemas"]["IngestBatchBody"];
|
|
15
|
-
export type IngestStatusResponse = components["schemas"]["IngestStatusResponse"];
|
|
16
|
-
export type IngestStats = components["schemas"]["IngestStats"];
|
|
17
|
-
export type IngestExecutionList = components["schemas"]["IngestExecutionList"];
|
|
18
|
-
export type IngestExecutionListItem = components["schemas"]["IngestExecutionListItem"];
|
|
19
|
-
export type IngestExecutionDetail = components["schemas"]["IngestExecutionDetail"];
|
|
20
9
|
export type Ingestion = components["schemas"]["Ingestion"];
|
|
21
10
|
export type IngestionSource = components["schemas"]["IngestionSource"];
|
|
22
11
|
export type IngestionStatus = components["schemas"]["IngestionStatus"];
|
|
@@ -34,7 +23,20 @@ export type IngestSessionBody = components["schemas"]["IngestSessionBody"];
|
|
|
34
23
|
export type BrowseResult = components["schemas"]["BrowseResult"];
|
|
35
24
|
export type ReadResponse = components["schemas"]["ReadResponse"];
|
|
36
25
|
export type Node = components["schemas"]["Node"];
|
|
26
|
+
export type FactConflicts = components["schemas"]["FactConflicts"];
|
|
27
|
+
export type ScoredFactMember = components["schemas"]["ScoredFactMember"];
|
|
37
28
|
export type NodeList = components["schemas"]["NodeList"];
|
|
38
29
|
export type Edge = components["schemas"]["Edge"];
|
|
39
30
|
export type NodeRef = components["schemas"]["NodeRef"];
|
|
40
31
|
export type EdgeList = components["schemas"]["EdgeList"];
|
|
32
|
+
export type ExtractedFactNodeList = components["schemas"]["ExtractedFactNodeList"];
|
|
33
|
+
export type FactNodeList = components["schemas"]["FactNodeList"];
|
|
34
|
+
export type ExtractedNarrativeNodeList = components["schemas"]["ExtractedNarrativeNodeList"];
|
|
35
|
+
export type NarrativePassageNodeList = components["schemas"]["NarrativePassageNodeList"];
|
|
36
|
+
export type NarrativeNodeList = components["schemas"]["NarrativeNodeList"];
|
|
37
|
+
export type LearnedMemoryNodeList = components["schemas"]["LearnedMemoryNodeList"];
|
|
38
|
+
export type ExtractedClinicalEventNodeList = components["schemas"]["ExtractedClinicalEventNodeList"];
|
|
39
|
+
export type ResolutionDecisionEdgeList = components["schemas"]["ResolutionDecisionEdgeList"];
|
|
40
|
+
export type ResolvesToEdgeList = components["schemas"]["ResolvesToEdgeList"];
|
|
41
|
+
export type ChunkedIntoEdgeList = components["schemas"]["ChunkedIntoEdgeList"];
|
|
42
|
+
export type RelationshipEdgeList = components["schemas"]["RelationshipEdgeList"];
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -146,19 +146,406 @@ var HttpClient = class {
|
|
|
146
146
|
}
|
|
147
147
|
};
|
|
148
148
|
|
|
149
|
+
// src/resources/info.ts
|
|
150
|
+
var InfoResource = class {
|
|
151
|
+
#http;
|
|
152
|
+
constructor(http) {
|
|
153
|
+
this.#http = http;
|
|
154
|
+
}
|
|
155
|
+
getServiceInfo() {
|
|
156
|
+
return this.#http.GET("/", void 0);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// src/resources/patients.ts
|
|
161
|
+
var PatientsResource = class {
|
|
162
|
+
#http;
|
|
163
|
+
constructor(http) {
|
|
164
|
+
this.#http = http;
|
|
165
|
+
}
|
|
166
|
+
listPatients() {
|
|
167
|
+
return this.#http.GET("/v1/patients", void 0);
|
|
168
|
+
}
|
|
169
|
+
getPatient(patientId) {
|
|
170
|
+
return this.#http.GET("/v1/patients/{patientId}", { params: { path: { patientId } } });
|
|
171
|
+
}
|
|
172
|
+
getResolution(patientId, params) {
|
|
173
|
+
return this.#http.GET("/v1/patients/{patientId}/resolution", {
|
|
174
|
+
params: {
|
|
175
|
+
path: { patientId },
|
|
176
|
+
...params?.query !== void 0 ? { query: params.query } : {}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
getReconciliation(patientId, params) {
|
|
181
|
+
return this.#http.GET("/v1/patients/{patientId}/reconciliation", {
|
|
182
|
+
params: {
|
|
183
|
+
path: { patientId },
|
|
184
|
+
...params?.query !== void 0 ? { query: params.query } : {}
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
deletePatient(patientId) {
|
|
189
|
+
return this.#http.DELETE("/v1/patients/{patientId}", { params: { path: { patientId } } });
|
|
190
|
+
}
|
|
191
|
+
upsertPatient(patientId) {
|
|
192
|
+
return this.#http.PUT("/v1/patients/{patientId}", { params: { path: { patientId } } });
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// src/form-data.ts
|
|
197
|
+
function toFormData(body) {
|
|
198
|
+
const form = new FormData();
|
|
199
|
+
if (body === null || typeof body !== "object") return form;
|
|
200
|
+
for (const [field, value] of Object.entries(body)) {
|
|
201
|
+
if (value === void 0 || value === null) continue;
|
|
202
|
+
for (const part of Array.isArray(value) ? value : [value]) {
|
|
203
|
+
form.append(field, part);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return form;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/resources/ingest.ts
|
|
210
|
+
var IngestResource = class {
|
|
211
|
+
#http;
|
|
212
|
+
constructor(http) {
|
|
213
|
+
this.#http = http;
|
|
214
|
+
}
|
|
215
|
+
listIngestions(patientId, params) {
|
|
216
|
+
return this.#http.GET("/v1/patients/{patientId}/ingestions", {
|
|
217
|
+
params: {
|
|
218
|
+
path: { patientId },
|
|
219
|
+
...params?.query !== void 0 ? { query: params.query } : {}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
getIngestion(patientId, ingestionId) {
|
|
224
|
+
return this.#http.GET("/v1/patients/{patientId}/ingestions/{ingestionId}", {
|
|
225
|
+
params: { path: { patientId, ingestionId } }
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
ingestFhirR4(patientId, body) {
|
|
229
|
+
return this.#http.POST("/v1/patients/{patientId}/ingestions/fhir/r4", {
|
|
230
|
+
params: { path: { patientId } },
|
|
231
|
+
body
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
ingestFhirR5(patientId, body) {
|
|
235
|
+
return this.#http.POST("/v1/patients/{patientId}/ingestions/fhir/r5", {
|
|
236
|
+
params: { path: { patientId } },
|
|
237
|
+
body
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
ingestCdaR2(patientId, body) {
|
|
241
|
+
return this.#http.POST("/v1/patients/{patientId}/ingestions/cda/r2", {
|
|
242
|
+
params: { path: { patientId } },
|
|
243
|
+
body,
|
|
244
|
+
bodySerializer: (b) => typeof b === "string" ? b : JSON.stringify(b),
|
|
245
|
+
headers: { "Content-Type": "application/cda+xml" }
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
ingestCdaR2Multipart(patientId, body) {
|
|
249
|
+
return this.#http.POST("/v1/patients/{patientId}/ingestions/cda/r2", {
|
|
250
|
+
params: { path: { patientId } },
|
|
251
|
+
body,
|
|
252
|
+
bodySerializer: (b) => toFormData(b)
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// src/resources/sessions.ts
|
|
258
|
+
var SessionsResource = class {
|
|
259
|
+
#http;
|
|
260
|
+
constructor(http) {
|
|
261
|
+
this.#http = http;
|
|
262
|
+
}
|
|
263
|
+
listSessionMemories(patientId, sessionId, params) {
|
|
264
|
+
return this.#http.GET("/v1/patients/{patientId}/sessions/{sessionId}/memories", {
|
|
265
|
+
params: {
|
|
266
|
+
path: { patientId, sessionId },
|
|
267
|
+
...params?.query !== void 0 ? { query: params.query } : {}
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
createSession(patientId) {
|
|
272
|
+
return this.#http.POST("/v1/patients/{patientId}/sessions", {
|
|
273
|
+
params: { path: { patientId } }
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
getSession(patientId, sessionId) {
|
|
277
|
+
return this.#http.GET("/v1/patients/{patientId}/sessions/{sessionId}", {
|
|
278
|
+
params: { path: { patientId, sessionId } }
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
upsertSession(patientId, sessionId) {
|
|
282
|
+
return this.#http.PUT("/v1/patients/{patientId}/sessions/{sessionId}", {
|
|
283
|
+
params: { path: { patientId, sessionId } }
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
appendMessages(patientId, sessionId, body) {
|
|
287
|
+
return this.#http.POST("/v1/patients/{patientId}/sessions/{sessionId}/messages", {
|
|
288
|
+
params: { path: { patientId, sessionId } },
|
|
289
|
+
body
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
generateMemories(patientId, sessionId) {
|
|
293
|
+
return this.#http.POST("/v1/patients/{patientId}/sessions/{sessionId}/memories", {
|
|
294
|
+
params: { path: { patientId, sessionId } }
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
ingestSession(patientId, body) {
|
|
298
|
+
return this.#http.POST("/v1/patients/{patientId}/sessions/ingest", {
|
|
299
|
+
params: { path: { patientId } },
|
|
300
|
+
body
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// src/resources/vfs.ts
|
|
306
|
+
var VFSResource = class {
|
|
307
|
+
#http;
|
|
308
|
+
constructor(http) {
|
|
309
|
+
this.#http = http;
|
|
310
|
+
}
|
|
311
|
+
browseVfs(patientId, params) {
|
|
312
|
+
return this.#http.GET("/v1/patients/{patientId}/vfs", {
|
|
313
|
+
params: {
|
|
314
|
+
path: { patientId },
|
|
315
|
+
...params?.query !== void 0 ? { query: params.query } : {}
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
readVfs(patientId, params) {
|
|
320
|
+
return this.#http.GET("/v1/patients/{patientId}/read", {
|
|
321
|
+
params: {
|
|
322
|
+
path: { patientId },
|
|
323
|
+
...params?.query !== void 0 ? { query: params.query } : {}
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// src/resources/graph.ts
|
|
330
|
+
var GraphResource = class {
|
|
331
|
+
#http;
|
|
332
|
+
constructor(http) {
|
|
333
|
+
this.#http = http;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Technical preview.
|
|
337
|
+
*
|
|
338
|
+
* @experimental
|
|
339
|
+
*/
|
|
340
|
+
listNodes(patientId, type, params) {
|
|
341
|
+
return this.#http.GET("/v1/patients/{patientId}/graph/nodes/{type}/items", {
|
|
342
|
+
params: {
|
|
343
|
+
path: { patientId, type },
|
|
344
|
+
...params?.query !== void 0 ? { query: params.query } : {}
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Technical preview.
|
|
350
|
+
*
|
|
351
|
+
* @experimental
|
|
352
|
+
*/
|
|
353
|
+
listEdges(patientId, type, params) {
|
|
354
|
+
return this.#http.GET("/v1/patients/{patientId}/graph/edges/{type}/items", {
|
|
355
|
+
params: {
|
|
356
|
+
path: { patientId, type },
|
|
357
|
+
...params?.query !== void 0 ? { query: params.query } : {}
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Technical preview.
|
|
363
|
+
*
|
|
364
|
+
* @experimental
|
|
365
|
+
*/
|
|
366
|
+
getNode(patientId, type, nodeId) {
|
|
367
|
+
return this.#http.GET("/v1/patients/{patientId}/graph/nodes/{type}/items/{nodeId}", {
|
|
368
|
+
params: { path: { patientId, type, nodeId } }
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Technical preview.
|
|
373
|
+
*
|
|
374
|
+
* @experimental
|
|
375
|
+
*/
|
|
376
|
+
getEdge(patientId, type, edgeId) {
|
|
377
|
+
return this.#http.GET("/v1/patients/{patientId}/graph/edges/{type}/items/{edgeId}", {
|
|
378
|
+
params: { path: { patientId, type, edgeId } }
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Technical preview.
|
|
383
|
+
*
|
|
384
|
+
* @experimental
|
|
385
|
+
*/
|
|
386
|
+
queryExtractedFactNodes(patientId, body) {
|
|
387
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/nodes/extracted_fact/query", {
|
|
388
|
+
params: { path: { patientId } },
|
|
389
|
+
body
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Technical preview.
|
|
394
|
+
*
|
|
395
|
+
* @experimental
|
|
396
|
+
*/
|
|
397
|
+
queryFactNodes(patientId, body) {
|
|
398
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/nodes/fact/query", {
|
|
399
|
+
params: { path: { patientId } },
|
|
400
|
+
body
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Technical preview.
|
|
405
|
+
*
|
|
406
|
+
* @experimental
|
|
407
|
+
*/
|
|
408
|
+
queryExtractedNarrativeNodes(patientId, body) {
|
|
409
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/nodes/extracted_narrative/query", {
|
|
410
|
+
params: { path: { patientId } },
|
|
411
|
+
body
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Technical preview.
|
|
416
|
+
*
|
|
417
|
+
* @experimental
|
|
418
|
+
*/
|
|
419
|
+
queryNarrativePassageNodes(patientId, body) {
|
|
420
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/nodes/narrative_passage/query", {
|
|
421
|
+
params: { path: { patientId } },
|
|
422
|
+
body
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Technical preview.
|
|
427
|
+
*
|
|
428
|
+
* @experimental
|
|
429
|
+
*/
|
|
430
|
+
queryNarrativeNodes(patientId, body) {
|
|
431
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/nodes/narrative/query", {
|
|
432
|
+
params: { path: { patientId } },
|
|
433
|
+
body
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Technical preview.
|
|
438
|
+
*
|
|
439
|
+
* @experimental
|
|
440
|
+
*/
|
|
441
|
+
queryLearnedMemoryNodes(patientId, body) {
|
|
442
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/nodes/learned_memory/query", {
|
|
443
|
+
params: { path: { patientId } },
|
|
444
|
+
body
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Technical preview.
|
|
449
|
+
*
|
|
450
|
+
* @experimental
|
|
451
|
+
*/
|
|
452
|
+
queryExtractedClinicalEventNodes(patientId, body) {
|
|
453
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/nodes/extracted_clinical_event/query", {
|
|
454
|
+
params: { path: { patientId } },
|
|
455
|
+
body
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Technical preview.
|
|
460
|
+
*
|
|
461
|
+
* @experimental
|
|
462
|
+
*/
|
|
463
|
+
queryResolutionDecisionEdges(patientId, body) {
|
|
464
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/edges/resolution_decision/query", {
|
|
465
|
+
params: { path: { patientId } },
|
|
466
|
+
body
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Technical preview.
|
|
471
|
+
*
|
|
472
|
+
* @experimental
|
|
473
|
+
*/
|
|
474
|
+
queryResolvesToEdges(patientId, body) {
|
|
475
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/edges/resolves_to/query", {
|
|
476
|
+
params: { path: { patientId } },
|
|
477
|
+
body
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Technical preview.
|
|
482
|
+
*
|
|
483
|
+
* @experimental
|
|
484
|
+
*/
|
|
485
|
+
queryChunkedIntoEdges(patientId, body) {
|
|
486
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/edges/chunked_into/query", {
|
|
487
|
+
params: { path: { patientId } },
|
|
488
|
+
body
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Technical preview.
|
|
493
|
+
*
|
|
494
|
+
* @experimental
|
|
495
|
+
*/
|
|
496
|
+
queryRelationshipEdges(patientId, body) {
|
|
497
|
+
return this.#http.POST("/v1/patients/{patientId}/graph/edges/relationship/query", {
|
|
498
|
+
params: { path: { patientId } },
|
|
499
|
+
body
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
// src/resources/index.ts
|
|
505
|
+
function createResources(http) {
|
|
506
|
+
return {
|
|
507
|
+
info: new InfoResource(http),
|
|
508
|
+
patients: new PatientsResource(http),
|
|
509
|
+
ingest: new IngestResource(http),
|
|
510
|
+
sessions: new SessionsResource(http),
|
|
511
|
+
vfs: new VFSResource(http),
|
|
512
|
+
graph: new GraphResource(http)
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
149
516
|
// src/context-engine-client.ts
|
|
150
517
|
var ContextEngineClient = class {
|
|
151
518
|
/**
|
|
152
519
|
* Low-level http client. Use when a resource method does not cover your use case.
|
|
153
520
|
*/
|
|
154
521
|
http;
|
|
522
|
+
info;
|
|
523
|
+
patients;
|
|
524
|
+
ingest;
|
|
525
|
+
sessions;
|
|
526
|
+
vfs;
|
|
527
|
+
graph;
|
|
155
528
|
constructor(options) {
|
|
156
529
|
this.http = new HttpClient(options);
|
|
530
|
+
const resources = createResources(this.http);
|
|
531
|
+
this.info = resources.info;
|
|
532
|
+
this.patients = resources.patients;
|
|
533
|
+
this.ingest = resources.ingest;
|
|
534
|
+
this.sessions = resources.sessions;
|
|
535
|
+
this.vfs = resources.vfs;
|
|
536
|
+
this.graph = resources.graph;
|
|
157
537
|
}
|
|
158
538
|
};
|
|
159
539
|
export {
|
|
160
540
|
ContextEngineClient,
|
|
541
|
+
GraphResource,
|
|
161
542
|
HttpClient,
|
|
162
|
-
|
|
543
|
+
InfoResource,
|
|
544
|
+
IngestResource,
|
|
545
|
+
PatientsResource,
|
|
546
|
+
SessionsResource,
|
|
547
|
+
VFSResource,
|
|
548
|
+
createClientCredentialsTokenProvider,
|
|
549
|
+
createResources
|
|
163
550
|
};
|
|
164
551
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth.ts","../src/http-client.ts","../src/context-engine-client.ts"],"sourcesContent":["import * as oauth from \"oauth4webapi\";\n\n/**\n * OAuth2 client-credentials helpers for authenticating against a secured\n * Context Engine workspace.\n *\n * The server validates a bearer JWT in the `Authorization` header against a\n * JWKS. This module provides the client half: a token provider that exchanges\n * a `client_id`/`client_secret` for an access token, caches it, and refreshes\n * it before expiry. The token exchange itself is delegated to `oauth4webapi`\n * (standards-compliant request building + response validation); this module\n * only adds caching, concurrent-request de-duplication, and a small config\n * surface. Pass the raw config as {@link HttpClientOptions.auth}, or — for full\n * control — pass the returned provider as the {@link HttpClientOptions.auth}\n * token function.\n */\n\n/**\n * Resolves to a currently-valid bearer access token. Called per request; a\n * well-behaved provider caches internally and only hits the network when the\n * cached token is missing or about to expire.\n */\nexport type TokenProvider = () => Promise<string>;\n\n/**\n * Clinia's authorization server, applied when a config names neither a\n * `tokenUrl` nor an `issuer` — so `{ clientId, clientSecret }` is a complete\n * config for a Clinia workspace, which is the overwhelmingly common case.\n *\n * `RESOURCE` is only defaulted alongside `TOKEN_URL`: it is an RFC 8707\n * indicator naming Clinia's protected resource, and sending it to somebody\n * else's authorization server would be wrong.\n */\nconst CLINIA_OAUTH_TOKEN_URL = \"https://console.clinia.cloud/api/auth/oauth2/token\";\nconst CLINIA_OAUTH_RESOURCE = \"https://console.clinia.cloud\";\n\n/** Fields common to both ways of locating the authorization server. */\ntype ClientCredentialsBase = {\n clientId: string;\n clientSecret: string;\n /**\n * Optional `resource` indicator (RFC 8707) naming the protected resource the\n * token is for. This is what the Clinia authorization server expects (e.g.\n * `https://console.clinia.cloud`).\n */\n resource?: string;\n /** Optional `audience` parameter (used by some IdPs, e.g. Auth0). */\n audience?: string;\n /** Optional space-delimited `scope`. */\n scope?: string;\n /**\n * How the client credentials are presented to the token endpoint. `post`\n * (the default) sends them in the request body — what the Clinia\n * authorization server expects; `basic` sends them in the `Authorization`\n * header (RFC 6749 §2.3.1) for IdPs that require it.\n */\n authMethod?: \"basic\" | \"post\";\n /**\n * Custom fetch implementation. Defaults to `globalThis.fetch`. Useful for\n * injecting a mock in tests.\n */\n fetch?: typeof globalThis.fetch;\n /**\n * Refresh the token this many milliseconds before it actually expires, to\n * avoid handing out a token that expires mid-flight. Defaults to 60_000.\n */\n expiryMarginMs?: number;\n};\n\n/**\n * Client-credentials configuration.\n *\n * For a Clinia workspace, `{ clientId, clientSecret }` is enough — the token\n * endpoint and `resource` indicator default to Clinia's authorization server.\n * Naming an {@link issuer} instead locates a different authorization server by\n * OIDC/OAuth2 discovery; naming a {@link tokenUrl} points at one explicitly.\n */\nexport type ClientCredentialsConfig =\n | (ClientCredentialsBase & {\n /**\n * Issuer identifier of the authorization server. Its metadata (token\n * endpoint, etc.) is resolved via discovery on first use.\n */\n issuer: string;\n /** Discovery transformation: `oidc` (default) or `oauth2` (RFC 8414). */\n discoveryAlgorithm?: \"oidc\" | \"oauth2\";\n tokenUrl?: never;\n })\n | (ClientCredentialsBase & {\n /**\n * Explicit OAuth2 token endpoint; discovery is skipped. Omit it — along\n * with `issuer` — to use Clinia's.\n */\n tokenUrl?: string;\n /** Issuer identifier for response validation; defaults to the token URL's origin. */\n issuer?: string;\n discoveryAlgorithm?: never;\n });\n\nconst DEFAULT_EXPIRY_MARGIN_MS = 60_000;\n/** Fallback lifetime when the token endpoint omits `expires_in`. */\nconst DEFAULT_TTL_MS = 5 * 60_000;\n\n/** Turns an `oauth4webapi` failure into a concise, stable error message. */\nfunction describeOAuthError(err: unknown): string {\n if (err instanceof oauth.ResponseBodyError) {\n return `${err.status} ${err.error}${err.error_description ? ` — ${err.error_description}` : \"\"}`;\n }\n if (err instanceof oauth.WWWAuthenticateChallengeError) {\n return `${err.status} ${err.message}`;\n }\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Builds a {@link TokenProvider} backed by the OAuth2 client-credentials grant.\n *\n * The provider caches the access token and reuses it until it is within\n * `expiryMarginMs` of expiry. Concurrent calls while a fetch is in flight share\n * the same request rather than each hitting the token endpoint. When configured\n * with an {@link ClientCredentialsConfig.issuer}, the authorization server\n * metadata is discovered once and memoized.\n */\nexport function createClientCredentialsTokenProvider(\n config: ClientCredentialsConfig,\n): TokenProvider {\n const expiryMarginMs = config.expiryMarginMs ?? DEFAULT_EXPIRY_MARGIN_MS;\n\n // Defaulted only when the token endpoint is also defaulted. `resource` names\n // Clinia's protected resource, so attaching it to a request aimed at somebody\n // else's authorization server would be both wrong and a small disclosure.\n const usesCliniaAuthServer = !config.tokenUrl && !config.issuer;\n const resource = config.resource ?? (usesCliniaAuthServer ? CLINIA_OAUTH_RESOURCE : undefined);\n\n const client: oauth.Client = { client_id: config.clientId };\n const clientAuth =\n config.authMethod === \"basic\"\n ? oauth.ClientSecretBasic(config.clientSecret)\n : oauth.ClientSecretPost(config.clientSecret);\n\n // Shared HTTP options (custom fetch + insecure opt-in) applied to every\n // oauth4webapi call. The `as never` bridges the customFetch signature, which\n // is generic over method/body per call site but is the same fn at runtime.\n // oauth4webapi rejects non-TLS endpoints by default; we relax that per call\n // when — and only when — the target URL is itself `http://` (local dev),\n // rather than exposing a separate flag.\n const fetchImpl = config.fetch;\n const isInsecure = (url: string | undefined): boolean =>\n !!url && new URL(url).protocol === \"http:\";\n function withHttpOptions<T extends object>(opts: T, insecure: boolean): T {\n const o = opts as T & {\n [oauth.customFetch]?: unknown;\n [oauth.allowInsecureRequests]?: boolean;\n };\n if (fetchImpl) {\n o[oauth.customFetch] = ((url: string, options: RequestInit) =>\n fetchImpl(url, options)) as never;\n }\n if (insecure) o[oauth.allowInsecureRequests] = true;\n return o;\n }\n\n // Authorization server metadata, resolved once. For an explicit tokenUrl it's\n // synchronous; for an issuer it requires a discovery request, so it's async\n // and memoized (with retry on failure — a rejected attempt isn't cached).\n let resolvedAs: oauth.AuthorizationServer | null = null;\n let asInFlight: Promise<oauth.AuthorizationServer> | null = null;\n\n async function resolveAuthServer(): Promise<oauth.AuthorizationServer> {\n // Discovery only when an issuer is named and no explicit endpoint overrides\n // it. There is no \"neither given\" case left to handle — that is the Clinia\n // default, which is why this no longer throws.\n if (!config.issuer || config.tokenUrl) {\n const tokenUrl = config.tokenUrl ?? CLINIA_OAUTH_TOKEN_URL;\n return {\n issuer: config.issuer ?? new URL(tokenUrl).origin,\n token_endpoint: tokenUrl,\n };\n }\n const issuerUrl = new URL(config.issuer);\n const response = await oauth.discoveryRequest(\n issuerUrl,\n withHttpOptions<oauth.DiscoveryRequestOptions>(\n { algorithm: config.discoveryAlgorithm ?? \"oidc\" },\n isInsecure(config.issuer),\n ),\n );\n return oauth.processDiscoveryResponse(issuerUrl, response);\n }\n\n function getAuthServer(): Promise<oauth.AuthorizationServer> {\n if (resolvedAs) return Promise.resolve(resolvedAs);\n if (!asInFlight) {\n asInFlight = resolveAuthServer()\n .then((as) => (resolvedAs = as))\n .finally(() => {\n asInFlight = null;\n });\n }\n return asInFlight;\n }\n\n let cachedToken: string | null = null;\n /** Absolute epoch ms at which the cached token should be considered stale. */\n let expiresAt = 0;\n /** In-flight fetch, shared across concurrent callers to dedupe requests. */\n let inFlight: Promise<string> | null = null;\n\n async function fetchToken(): Promise<string> {\n const params = new URLSearchParams();\n if (resource) params.set(\"resource\", resource);\n if (config.audience) params.set(\"audience\", config.audience);\n if (config.scope) params.set(\"scope\", config.scope);\n\n let result: oauth.TokenEndpointResponse;\n try {\n const as = await getAuthServer();\n const response = await oauth.clientCredentialsGrantRequest(\n as,\n client,\n clientAuth,\n params,\n withHttpOptions<oauth.ClientCredentialsGrantRequestOptions>(\n {},\n isInsecure(as.token_endpoint),\n ),\n );\n result = await oauth.processClientCredentialsResponse(as, client, response);\n } catch (err) {\n throw new Error(`client_credentials token request failed: ${describeOAuthError(err)}`, {\n cause: err,\n });\n }\n\n const ttlMs = result.expires_in ? result.expires_in * 1000 : DEFAULT_TTL_MS;\n cachedToken = result.access_token;\n expiresAt = Date.now() + Math.max(0, ttlMs - expiryMarginMs);\n return cachedToken;\n }\n\n return async function getAccessToken(): Promise<string> {\n if (cachedToken && Date.now() < expiresAt) return cachedToken;\n if (inFlight) return inFlight;\n\n inFlight = fetchToken().finally(() => {\n inFlight = null;\n });\n return inFlight;\n };\n}\n","import createFetchClient, { type Client, type Middleware } from \"openapi-fetch\";\n\nimport { createClientCredentialsTokenProvider, type ClientCredentialsConfig } from \"./auth\";\nimport type { paths } from \"./generated/context-engine\";\n\nexport type HttpClientOptions = {\n baseUrl: string;\n /**\n * Custom fetch implementation. Defaults to `globalThis.fetch`.\n * Works in Node 20+ and all modern browsers out of the box.\n * Useful for injecting a mock or a custom fetch in tests.\n */\n fetch?: typeof globalThis.fetch;\n /**\n * How to authenticate against a secured Context Engine server. Accepts either\n * shape:\n *\n * - A {@link ClientCredentialsConfig} — the common case. Pass just your OAuth2\n * client credentials and the client sets up token acquisition, caching, and\n * refresh for you.\n * - A token function `() => string | Promise<string>` — the escape hatch for\n * full control (a token from elsewhere, a different grant, or a custom\n * refresh strategy). Called per request, so a provider can cache and refresh\n * internally (e.g. {@link createClientCredentialsTokenProvider}); a falsy\n * return value leaves the header unset.\n *\n * Either way the resolved token is attached as `Authorization: Bearer <token>`\n * on every request. Omit for an unsecured server.\n */\n auth?: ClientCredentialsConfig | (() => string | Promise<string>);\n};\n\nexport class HttpClient {\n readonly #client: Client<paths>;\n\n constructor(options: HttpClientOptions) {\n this.#client = createFetchClient<paths>({\n baseUrl: options.baseUrl,\n fetch: options.fetch,\n });\n\n // A token function is used as-is; a config object builds a client-credentials\n // provider. The custom `fetch` is threaded into the token exchange too so\n // tests/proxies apply to both hops.\n const getAccessToken =\n typeof options.auth === \"function\"\n ? options.auth\n : options.auth\n ? createClientCredentialsTokenProvider({ fetch: options.fetch, ...options.auth })\n : undefined;\n\n if (getAccessToken) {\n const authMiddleware: Middleware = {\n async onRequest({ request }) {\n const token = await getAccessToken();\n if (token) request.headers.set(\"Authorization\", `Bearer ${token}`);\n return request;\n },\n };\n this.#client.use(authMiddleware);\n }\n }\n\n get GET(): Client<paths>[\"GET\"] {\n return this.#client.GET;\n }\n\n get POST(): Client<paths>[\"POST\"] {\n return this.#client.POST;\n }\n\n get PUT(): Client<paths>[\"PUT\"] {\n return this.#client.PUT;\n }\n\n get PATCH(): Client<paths>[\"PATCH\"] {\n return this.#client.PATCH;\n }\n\n get DELETE(): Client<paths>[\"DELETE\"] {\n return this.#client.DELETE;\n }\n\n use(...middleware: Middleware[]): this {\n this.#client.use(...middleware);\n return this;\n }\n\n eject(...middleware: Middleware[]): this {\n this.#client.eject(...middleware);\n return this;\n }\n}\n","import { HttpClient, type HttpClientOptions } from \"./http-client\";\n\nexport type ContextEngineClientOptions = HttpClientOptions;\n\n/**\n * Client for the Clinia Context Engine API.\n *\n * For now this client only exposes a low-level `http` client for making requests to the API. Higher-level resource methods can be added as the API surface stabilizes.\n */\nexport class ContextEngineClient {\n /**\n * Low-level http client. Use when a resource method does not cover your use case.\n */\n readonly http: HttpClient;\n\n constructor(options: ContextEngineClientOptions) {\n this.http = new HttpClient(options);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/auth.ts","../src/http-client.ts","../src/resources/info.ts","../src/resources/patients.ts","../src/form-data.ts","../src/resources/ingest.ts","../src/resources/sessions.ts","../src/resources/vfs.ts","../src/resources/graph.ts","../src/resources/index.ts","../src/context-engine-client.ts"],"sourcesContent":["import * as oauth from \"oauth4webapi\";\n\n/**\n * OAuth2 client-credentials helpers for authenticating against a secured\n * Context Engine workspace.\n *\n * The server validates a bearer JWT in the `Authorization` header against a\n * JWKS. This module provides the client half: a token provider that exchanges\n * a `client_id`/`client_secret` for an access token, caches it, and refreshes\n * it before expiry. The token exchange itself is delegated to `oauth4webapi`\n * (standards-compliant request building + response validation); this module\n * only adds caching, concurrent-request de-duplication, and a small config\n * surface. Pass the raw config as {@link HttpClientOptions.auth}, or — for full\n * control — pass the returned provider as the {@link HttpClientOptions.auth}\n * token function.\n */\n\n/**\n * Resolves to a currently-valid bearer access token. Called per request; a\n * well-behaved provider caches internally and only hits the network when the\n * cached token is missing or about to expire.\n */\nexport type TokenProvider = () => Promise<string>;\n\n/**\n * Clinia's authorization server, applied when a config names neither a\n * `tokenUrl` nor an `issuer` — so `{ clientId, clientSecret }` is a complete\n * config for a Clinia workspace, which is the overwhelmingly common case.\n *\n * `RESOURCE` is only defaulted alongside `TOKEN_URL`: it is an RFC 8707\n * indicator naming Clinia's protected resource, and sending it to somebody\n * else's authorization server would be wrong.\n */\nconst CLINIA_OAUTH_TOKEN_URL = \"https://console.clinia.cloud/api/auth/oauth2/token\";\nconst CLINIA_OAUTH_RESOURCE = \"https://console.clinia.cloud\";\n\n/** Fields common to both ways of locating the authorization server. */\ntype ClientCredentialsBase = {\n clientId: string;\n clientSecret: string;\n /**\n * Optional `resource` indicator (RFC 8707) naming the protected resource the\n * token is for. This is what the Clinia authorization server expects (e.g.\n * `https://console.clinia.cloud`).\n */\n resource?: string;\n /** Optional `audience` parameter (used by some IdPs, e.g. Auth0). */\n audience?: string;\n /** Optional space-delimited `scope`. */\n scope?: string;\n /**\n * How the client credentials are presented to the token endpoint. `post`\n * (the default) sends them in the request body — what the Clinia\n * authorization server expects; `basic` sends them in the `Authorization`\n * header (RFC 6749 §2.3.1) for IdPs that require it.\n */\n authMethod?: \"basic\" | \"post\";\n /**\n * Custom fetch implementation. Defaults to `globalThis.fetch`. Useful for\n * injecting a mock in tests.\n */\n fetch?: typeof globalThis.fetch;\n /**\n * Refresh the token this many milliseconds before it actually expires, to\n * avoid handing out a token that expires mid-flight. Defaults to 60_000.\n */\n expiryMarginMs?: number;\n};\n\n/**\n * Client-credentials configuration.\n *\n * For a Clinia workspace, `{ clientId, clientSecret }` is enough — the token\n * endpoint and `resource` indicator default to Clinia's authorization server.\n * Naming an {@link issuer} instead locates a different authorization server by\n * OIDC/OAuth2 discovery; naming a {@link tokenUrl} points at one explicitly.\n */\nexport type ClientCredentialsConfig =\n | (ClientCredentialsBase & {\n /**\n * Issuer identifier of the authorization server. Its metadata (token\n * endpoint, etc.) is resolved via discovery on first use.\n */\n issuer: string;\n /** Discovery transformation: `oidc` (default) or `oauth2` (RFC 8414). */\n discoveryAlgorithm?: \"oidc\" | \"oauth2\";\n tokenUrl?: never;\n })\n | (ClientCredentialsBase & {\n /**\n * Explicit OAuth2 token endpoint; discovery is skipped. Omit it — along\n * with `issuer` — to use Clinia's.\n */\n tokenUrl?: string;\n /** Issuer identifier for response validation; defaults to the token URL's origin. */\n issuer?: string;\n discoveryAlgorithm?: never;\n });\n\nconst DEFAULT_EXPIRY_MARGIN_MS = 60_000;\n/** Fallback lifetime when the token endpoint omits `expires_in`. */\nconst DEFAULT_TTL_MS = 5 * 60_000;\n\n/** Turns an `oauth4webapi` failure into a concise, stable error message. */\nfunction describeOAuthError(err: unknown): string {\n if (err instanceof oauth.ResponseBodyError) {\n return `${err.status} ${err.error}${err.error_description ? ` — ${err.error_description}` : \"\"}`;\n }\n if (err instanceof oauth.WWWAuthenticateChallengeError) {\n return `${err.status} ${err.message}`;\n }\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Builds a {@link TokenProvider} backed by the OAuth2 client-credentials grant.\n *\n * The provider caches the access token and reuses it until it is within\n * `expiryMarginMs` of expiry. Concurrent calls while a fetch is in flight share\n * the same request rather than each hitting the token endpoint. When configured\n * with an {@link ClientCredentialsConfig.issuer}, the authorization server\n * metadata is discovered once and memoized.\n */\nexport function createClientCredentialsTokenProvider(\n config: ClientCredentialsConfig,\n): TokenProvider {\n const expiryMarginMs = config.expiryMarginMs ?? DEFAULT_EXPIRY_MARGIN_MS;\n\n // Defaulted only when the token endpoint is also defaulted. `resource` names\n // Clinia's protected resource, so attaching it to a request aimed at somebody\n // else's authorization server would be both wrong and a small disclosure.\n const usesCliniaAuthServer = !config.tokenUrl && !config.issuer;\n const resource = config.resource ?? (usesCliniaAuthServer ? CLINIA_OAUTH_RESOURCE : undefined);\n\n const client: oauth.Client = { client_id: config.clientId };\n const clientAuth =\n config.authMethod === \"basic\"\n ? oauth.ClientSecretBasic(config.clientSecret)\n : oauth.ClientSecretPost(config.clientSecret);\n\n // Shared HTTP options (custom fetch + insecure opt-in) applied to every\n // oauth4webapi call. The `as never` bridges the customFetch signature, which\n // is generic over method/body per call site but is the same fn at runtime.\n // oauth4webapi rejects non-TLS endpoints by default; we relax that per call\n // when — and only when — the target URL is itself `http://` (local dev),\n // rather than exposing a separate flag.\n const fetchImpl = config.fetch;\n const isInsecure = (url: string | undefined): boolean =>\n !!url && new URL(url).protocol === \"http:\";\n function withHttpOptions<T extends object>(opts: T, insecure: boolean): T {\n const o = opts as T & {\n [oauth.customFetch]?: unknown;\n [oauth.allowInsecureRequests]?: boolean;\n };\n if (fetchImpl) {\n o[oauth.customFetch] = ((url: string, options: RequestInit) =>\n fetchImpl(url, options)) as never;\n }\n if (insecure) o[oauth.allowInsecureRequests] = true;\n return o;\n }\n\n // Authorization server metadata, resolved once. For an explicit tokenUrl it's\n // synchronous; for an issuer it requires a discovery request, so it's async\n // and memoized (with retry on failure — a rejected attempt isn't cached).\n let resolvedAs: oauth.AuthorizationServer | null = null;\n let asInFlight: Promise<oauth.AuthorizationServer> | null = null;\n\n async function resolveAuthServer(): Promise<oauth.AuthorizationServer> {\n // Discovery only when an issuer is named and no explicit endpoint overrides\n // it. There is no \"neither given\" case left to handle — that is the Clinia\n // default, which is why this no longer throws.\n if (!config.issuer || config.tokenUrl) {\n const tokenUrl = config.tokenUrl ?? CLINIA_OAUTH_TOKEN_URL;\n return {\n issuer: config.issuer ?? new URL(tokenUrl).origin,\n token_endpoint: tokenUrl,\n };\n }\n const issuerUrl = new URL(config.issuer);\n const response = await oauth.discoveryRequest(\n issuerUrl,\n withHttpOptions<oauth.DiscoveryRequestOptions>(\n { algorithm: config.discoveryAlgorithm ?? \"oidc\" },\n isInsecure(config.issuer),\n ),\n );\n return oauth.processDiscoveryResponse(issuerUrl, response);\n }\n\n function getAuthServer(): Promise<oauth.AuthorizationServer> {\n if (resolvedAs) return Promise.resolve(resolvedAs);\n if (!asInFlight) {\n asInFlight = resolveAuthServer()\n .then((as) => (resolvedAs = as))\n .finally(() => {\n asInFlight = null;\n });\n }\n return asInFlight;\n }\n\n let cachedToken: string | null = null;\n /** Absolute epoch ms at which the cached token should be considered stale. */\n let expiresAt = 0;\n /** In-flight fetch, shared across concurrent callers to dedupe requests. */\n let inFlight: Promise<string> | null = null;\n\n async function fetchToken(): Promise<string> {\n const params = new URLSearchParams();\n if (resource) params.set(\"resource\", resource);\n if (config.audience) params.set(\"audience\", config.audience);\n if (config.scope) params.set(\"scope\", config.scope);\n\n let result: oauth.TokenEndpointResponse;\n try {\n const as = await getAuthServer();\n const response = await oauth.clientCredentialsGrantRequest(\n as,\n client,\n clientAuth,\n params,\n withHttpOptions<oauth.ClientCredentialsGrantRequestOptions>(\n {},\n isInsecure(as.token_endpoint),\n ),\n );\n result = await oauth.processClientCredentialsResponse(as, client, response);\n } catch (err) {\n throw new Error(`client_credentials token request failed: ${describeOAuthError(err)}`, {\n cause: err,\n });\n }\n\n const ttlMs = result.expires_in ? result.expires_in * 1000 : DEFAULT_TTL_MS;\n cachedToken = result.access_token;\n expiresAt = Date.now() + Math.max(0, ttlMs - expiryMarginMs);\n return cachedToken;\n }\n\n return async function getAccessToken(): Promise<string> {\n if (cachedToken && Date.now() < expiresAt) return cachedToken;\n if (inFlight) return inFlight;\n\n inFlight = fetchToken().finally(() => {\n inFlight = null;\n });\n return inFlight;\n };\n}\n","import createFetchClient, { type Client, type Middleware } from \"openapi-fetch\";\n\nimport { createClientCredentialsTokenProvider, type ClientCredentialsConfig } from \"./auth\";\nimport type { paths } from \"./generated/context-engine\";\n\nexport type HttpClientOptions = {\n baseUrl: string;\n /**\n * Custom fetch implementation. Defaults to `globalThis.fetch`.\n * Works in Node 20+ and all modern browsers out of the box.\n * Useful for injecting a mock or a custom fetch in tests.\n */\n fetch?: typeof globalThis.fetch;\n /**\n * How to authenticate against a secured Context Engine server. Accepts either\n * shape:\n *\n * - A {@link ClientCredentialsConfig} — the common case. Pass just your OAuth2\n * client credentials and the client sets up token acquisition, caching, and\n * refresh for you.\n * - A token function `() => string | Promise<string>` — the escape hatch for\n * full control (a token from elsewhere, a different grant, or a custom\n * refresh strategy). Called per request, so a provider can cache and refresh\n * internally (e.g. {@link createClientCredentialsTokenProvider}); a falsy\n * return value leaves the header unset.\n *\n * Either way the resolved token is attached as `Authorization: Bearer <token>`\n * on every request. Omit for an unsecured server.\n */\n auth?: ClientCredentialsConfig | (() => string | Promise<string>);\n};\n\nexport class HttpClient {\n readonly #client: Client<paths>;\n\n constructor(options: HttpClientOptions) {\n this.#client = createFetchClient<paths>({\n baseUrl: options.baseUrl,\n fetch: options.fetch,\n });\n\n // A token function is used as-is; a config object builds a client-credentials\n // provider. The custom `fetch` is threaded into the token exchange too so\n // tests/proxies apply to both hops.\n const getAccessToken =\n typeof options.auth === \"function\"\n ? options.auth\n : options.auth\n ? createClientCredentialsTokenProvider({ fetch: options.fetch, ...options.auth })\n : undefined;\n\n if (getAccessToken) {\n const authMiddleware: Middleware = {\n async onRequest({ request }) {\n const token = await getAccessToken();\n if (token) request.headers.set(\"Authorization\", `Bearer ${token}`);\n return request;\n },\n };\n this.#client.use(authMiddleware);\n }\n }\n\n get GET(): Client<paths>[\"GET\"] {\n return this.#client.GET;\n }\n\n get POST(): Client<paths>[\"POST\"] {\n return this.#client.POST;\n }\n\n get PUT(): Client<paths>[\"PUT\"] {\n return this.#client.PUT;\n }\n\n get PATCH(): Client<paths>[\"PATCH\"] {\n return this.#client.PATCH;\n }\n\n get DELETE(): Client<paths>[\"DELETE\"] {\n return this.#client.DELETE;\n }\n\n use(...middleware: Middleware[]): this {\n this.#client.use(...middleware);\n return this;\n }\n\n eject(...middleware: Middleware[]): this {\n this.#client.eject(...middleware);\n return this;\n }\n}\n","// This file is auto-generated. Do not edit manually.\n// Re-generate by running: pnpm generate\n\nimport type { HttpClient } from \"../http-client\";\n\nexport class InfoResource {\n readonly #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n getServiceInfo() {\n return this.#http.GET(\"/\", undefined);\n }\n}\n","// This file is auto-generated. Do not edit manually.\n// Re-generate by running: pnpm generate\n\nimport type { HttpClient } from \"../http-client\";\n\nexport class PatientsResource {\n readonly #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n listPatients() {\n return this.#http.GET(\"/v1/patients\", undefined);\n }\n\n getPatient(patientId: string) {\n return this.#http.GET(\"/v1/patients/{patientId}\", { params: { path: { patientId } } });\n }\n\n getResolution(patientId: string, params?: { query?: { page?: number; perPage?: number } }) {\n return this.#http.GET(\"/v1/patients/{patientId}/resolution\", {\n params: {\n path: { patientId },\n ...(params?.query !== undefined ? { query: params.query } : {}),\n },\n });\n }\n\n getReconciliation(patientId: string, params?: { query?: { format?: \"json\" | \"markdown\" } }) {\n return this.#http.GET(\"/v1/patients/{patientId}/reconciliation\", {\n params: {\n path: { patientId },\n ...(params?.query !== undefined ? { query: params.query } : {}),\n },\n });\n }\n\n deletePatient(patientId: string) {\n return this.#http.DELETE(\"/v1/patients/{patientId}\", { params: { path: { patientId } } });\n }\n\n upsertPatient(patientId: string) {\n return this.#http.PUT(\"/v1/patients/{patientId}\", { params: { path: { patientId } } });\n }\n}\n","/**\n * A `multipart/form-data` request body, built from the object form of the schema.\n *\n * An array-valued field becomes one part per item under the same field name — how a schema\n * declaring an array of items is sent — and every other field becomes a single part. A field\n * left `undefined` or `null` is omitted rather than sent as the string `\"undefined\"` or `\"null\"`.\n *\n * Values are appended as given, so a string is sent as text and a `Blob` or `File` keeps the\n * filename and content type it was created with.\n *\n * No `Content-Type` is set anywhere: the header carries the multipart boundary, which only\n * the runtime sending the request can know.\n */\nexport function toFormData(body: unknown): FormData {\n const form = new FormData();\n if (body === null || typeof body !== \"object\") return form;\n\n for (const [field, value] of Object.entries(body)) {\n if (value === undefined || value === null) continue;\n for (const part of Array.isArray(value) ? value : [value]) {\n form.append(field, part as string | Blob);\n }\n }\n return form;\n}\n","// This file is auto-generated. Do not edit manually.\n// Re-generate by running: pnpm generate\n\nimport type { HttpClient } from \"../http-client\";\nimport { toFormData } from \"../form-data\";\nimport type { operations } from \"../generated/context-engine\";\nimport type { IngestFhirBody } from \"../generated/types\";\n\nexport class IngestResource {\n readonly #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n listIngestions(\n patientId: string,\n params?: {\n query?: {\n page?: number;\n perPage?: number;\n sort?: \"receivedAt\";\n order?: \"asc\" | \"desc\";\n status?: (\"pending\" | \"processing\" | \"succeeded\" | \"partial\" | \"failed\")[];\n };\n },\n ) {\n return this.#http.GET(\"/v1/patients/{patientId}/ingestions\", {\n params: {\n path: { patientId },\n ...(params?.query !== undefined ? { query: params.query } : {}),\n },\n });\n }\n\n getIngestion(patientId: string, ingestionId: string) {\n return this.#http.GET(\"/v1/patients/{patientId}/ingestions/{ingestionId}\", {\n params: { path: { patientId, ingestionId } },\n });\n }\n\n ingestFhirR4(patientId: string, body: IngestFhirBody) {\n return this.#http.POST(\"/v1/patients/{patientId}/ingestions/fhir/r4\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n ingestFhirR5(patientId: string, body: IngestFhirBody) {\n return this.#http.POST(\"/v1/patients/{patientId}/ingestions/fhir/r5\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n ingestCdaR2(\n patientId: string,\n body: NonNullable<operations[\"ingest-cda-r2\"][\"requestBody\"]>[\"content\"][\"application/cda+xml\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/ingestions/cda/r2\", {\n params: { path: { patientId } },\n body,\n bodySerializer: (b: unknown) => (typeof b === \"string\" ? b : JSON.stringify(b)),\n headers: { \"Content-Type\": \"application/cda+xml\" },\n });\n }\n\n ingestCdaR2Multipart(\n patientId: string,\n body: NonNullable<operations[\"ingest-cda-r2\"][\"requestBody\"]>[\"content\"][\"multipart/form-data\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/ingestions/cda/r2\", {\n params: { path: { patientId } },\n body,\n bodySerializer: (b: unknown) => toFormData(b),\n });\n }\n}\n","// This file is auto-generated. Do not edit manually.\n// Re-generate by running: pnpm generate\n\nimport type { HttpClient } from \"../http-client\";\nimport type { AppendMessagesBody, IngestSessionBody } from \"../generated/types\";\n\nexport class SessionsResource {\n readonly #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n listSessionMemories(\n patientId: string,\n sessionId: string,\n params?: {\n query?: { page?: number; perPage?: number; sort?: \"createdAt\"; order?: \"asc\" | \"desc\" };\n },\n ) {\n return this.#http.GET(\"/v1/patients/{patientId}/sessions/{sessionId}/memories\", {\n params: {\n path: { patientId, sessionId },\n ...(params?.query !== undefined ? { query: params.query } : {}),\n },\n });\n }\n\n createSession(patientId: string) {\n return this.#http.POST(\"/v1/patients/{patientId}/sessions\", {\n params: { path: { patientId } },\n });\n }\n\n getSession(patientId: string, sessionId: string) {\n return this.#http.GET(\"/v1/patients/{patientId}/sessions/{sessionId}\", {\n params: { path: { patientId, sessionId } },\n });\n }\n\n upsertSession(patientId: string, sessionId: string) {\n return this.#http.PUT(\"/v1/patients/{patientId}/sessions/{sessionId}\", {\n params: { path: { patientId, sessionId } },\n });\n }\n\n appendMessages(patientId: string, sessionId: string, body: AppendMessagesBody) {\n return this.#http.POST(\"/v1/patients/{patientId}/sessions/{sessionId}/messages\", {\n params: { path: { patientId, sessionId } },\n body,\n });\n }\n\n generateMemories(patientId: string, sessionId: string) {\n return this.#http.POST(\"/v1/patients/{patientId}/sessions/{sessionId}/memories\", {\n params: { path: { patientId, sessionId } },\n });\n }\n\n ingestSession(patientId: string, body: IngestSessionBody) {\n return this.#http.POST(\"/v1/patients/{patientId}/sessions/ingest\", {\n params: { path: { patientId } },\n body,\n });\n }\n}\n","// This file is auto-generated. Do not edit manually.\n// Re-generate by running: pnpm generate\n\nimport type { HttpClient } from \"../http-client\";\n\nexport class VFSResource {\n readonly #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n browseVfs(patientId: string, params?: { query?: { path?: string } }) {\n return this.#http.GET(\"/v1/patients/{patientId}/vfs\", {\n params: {\n path: { patientId },\n ...(params?.query !== undefined ? { query: params.query } : {}),\n },\n });\n }\n\n readVfs(\n patientId: string,\n params?: {\n query?: {\n path?: string;\n format?: \"narrative\" | \"structured\" | \"compact\";\n token_budget?: number;\n };\n },\n ) {\n return this.#http.GET(\"/v1/patients/{patientId}/read\", {\n params: {\n path: { patientId },\n ...(params?.query !== undefined ? { query: params.query } : {}),\n },\n });\n }\n}\n","// This file is auto-generated. Do not edit manually.\n// Re-generate by running: pnpm generate\n\nimport type { HttpClient } from \"../http-client\";\nimport type { operations } from \"../generated/context-engine\";\n\nexport class GraphResource {\n readonly #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n listNodes(\n patientId: string,\n type:\n | \"extracted_fact\"\n | \"fact\"\n | \"extracted_narrative\"\n | \"narrative_passage\"\n | \"narrative\"\n | \"learned_memory\"\n | \"extracted_clinical_event\",\n params?: { query?: { page?: number; perPage?: number } },\n ) {\n return this.#http.GET(\"/v1/patients/{patientId}/graph/nodes/{type}/items\", {\n params: {\n path: { patientId, type },\n ...(params?.query !== undefined ? { query: params.query } : {}),\n },\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n listEdges(\n patientId: string,\n type: \"resolution_decision\" | \"resolves_to\" | \"chunked_into\" | \"relationship\",\n params?: { query?: { page?: number; perPage?: number; touching?: string | string[] } },\n ) {\n return this.#http.GET(\"/v1/patients/{patientId}/graph/edges/{type}/items\", {\n params: {\n path: { patientId, type },\n ...(params?.query !== undefined ? { query: params.query } : {}),\n },\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n getNode(\n patientId: string,\n type:\n | \"extracted_fact\"\n | \"fact\"\n | \"extracted_narrative\"\n | \"narrative_passage\"\n | \"narrative\"\n | \"learned_memory\"\n | \"extracted_clinical_event\",\n nodeId: string,\n ) {\n return this.#http.GET(\"/v1/patients/{patientId}/graph/nodes/{type}/items/{nodeId}\", {\n params: { path: { patientId, type, nodeId } },\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n getEdge(\n patientId: string,\n type: \"resolution_decision\" | \"resolves_to\" | \"chunked_into\" | \"relationship\",\n edgeId: string,\n ) {\n return this.#http.GET(\"/v1/patients/{patientId}/graph/edges/{type}/items/{edgeId}\", {\n params: { path: { patientId, type, edgeId } },\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryExtractedFactNodes(\n patientId: string,\n body: NonNullable<\n operations[\"query-extracted-fact-nodes\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/nodes/extracted_fact/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryFactNodes(\n patientId: string,\n body: NonNullable<operations[\"query-fact-nodes\"][\"requestBody\"]>[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/nodes/fact/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryExtractedNarrativeNodes(\n patientId: string,\n body: NonNullable<\n operations[\"query-extracted-narrative-nodes\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/nodes/extracted_narrative/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryNarrativePassageNodes(\n patientId: string,\n body: NonNullable<\n operations[\"query-narrative-passage-nodes\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/nodes/narrative_passage/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryNarrativeNodes(\n patientId: string,\n body: NonNullable<\n operations[\"query-narrative-nodes\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/nodes/narrative/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryLearnedMemoryNodes(\n patientId: string,\n body: NonNullable<\n operations[\"query-learned-memory-nodes\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/nodes/learned_memory/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryExtractedClinicalEventNodes(\n patientId: string,\n body: NonNullable<\n operations[\"query-extracted-clinical-event-nodes\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/nodes/extracted_clinical_event/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryResolutionDecisionEdges(\n patientId: string,\n body: NonNullable<\n operations[\"query-resolution-decision-edges\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/edges/resolution_decision/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryResolvesToEdges(\n patientId: string,\n body: NonNullable<\n operations[\"query-resolves-to-edges\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/edges/resolves_to/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryChunkedIntoEdges(\n patientId: string,\n body: NonNullable<\n operations[\"query-chunked-into-edges\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/edges/chunked_into/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n\n /**\n * Technical preview.\n *\n * @experimental\n */\n queryRelationshipEdges(\n patientId: string,\n body: NonNullable<\n operations[\"query-relationship-edges\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n ) {\n return this.#http.POST(\"/v1/patients/{patientId}/graph/edges/relationship/query\", {\n params: { path: { patientId } },\n body,\n });\n }\n}\n","// This file is auto-generated. Do not edit manually.\n// Re-generate by running: pnpm generate\n\nimport type { HttpClient } from \"../http-client\";\nimport { InfoResource } from \"./info\";\nimport { PatientsResource } from \"./patients\";\nimport { IngestResource } from \"./ingest\";\nimport { SessionsResource } from \"./sessions\";\nimport { VFSResource } from \"./vfs\";\nimport { GraphResource } from \"./graph\";\n\nexport { InfoResource } from \"./info\";\nexport { PatientsResource } from \"./patients\";\nexport { IngestResource } from \"./ingest\";\nexport { SessionsResource } from \"./sessions\";\nexport { VFSResource } from \"./vfs\";\nexport { GraphResource } from \"./graph\";\n\n/** Every resource, under the property it takes on `ContextEngineClient`. */\nexport interface Resources {\n readonly info: InfoResource;\n readonly patients: PatientsResource;\n readonly ingest: IngestResource;\n readonly sessions: SessionsResource;\n readonly vfs: VFSResource;\n readonly graph: GraphResource;\n}\n\n/**\n * Build one of each resource over a shared http client.\n *\n * Generated alongside the classes, so a new tag in the spec lands here on its own and\n * `ContextEngineClient` fails to compile until it names the new property.\n */\nexport function createResources(http: HttpClient): Resources {\n return {\n info: new InfoResource(http),\n patients: new PatientsResource(http),\n ingest: new IngestResource(http),\n sessions: new SessionsResource(http),\n vfs: new VFSResource(http),\n graph: new GraphResource(http),\n };\n}\n","import { HttpClient, type HttpClientOptions } from \"./http-client\";\nimport {\n createResources,\n GraphResource,\n InfoResource,\n IngestResource,\n PatientsResource,\n SessionsResource,\n VFSResource,\n type Resources,\n} from \"./resources\";\n\nexport type ContextEngineClientOptions = HttpClientOptions;\n\n/**\n * Client for the Clinia Context Engine API.\n *\n * Each area of the API is a resource property — `client.patients`, `client.ingest`,\n * `client.graph` — and `http` stays available underneath for anything a resource method does\n * not cover. Every resource shares that one http client, so authentication is configured once.\n *\n * `implements Resources` is what keeps this list honest: the resources are generated from the\n * API spec, and a new one is a compile error here until it is named.\n */\nexport class ContextEngineClient implements Resources {\n /**\n * Low-level http client. Use when a resource method does not cover your use case.\n */\n readonly http: HttpClient;\n\n readonly info: InfoResource;\n readonly patients: PatientsResource;\n readonly ingest: IngestResource;\n readonly sessions: SessionsResource;\n readonly vfs: VFSResource;\n readonly graph: GraphResource;\n\n constructor(options: ContextEngineClientOptions) {\n this.http = new HttpClient(options);\n\n const resources = createResources(this.http);\n this.info = resources.info;\n this.patients = resources.patients;\n this.ingest = resources.ingest;\n this.sessions = resources.sessions;\n this.vfs = resources.vfs;\n this.graph = resources.graph;\n }\n}\n"],"mappings":"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","names":[]}
|