cencori 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -600,6 +600,17 @@ function toBody(request) {
600
600
  temperature: request.temperature,
601
601
  response_format: request.responseFormat
602
602
  };
603
+ if (request.images && request.images.length > 0) {
604
+ body.images = request.images.map((img) => {
605
+ if (img.url) return { url: img.url };
606
+ if (img.base64) return { base64: img.base64, mime_type: img.mimeType };
607
+ throw new Error("Each entry in images requires url or base64");
608
+ });
609
+ return body;
610
+ }
611
+ if (!request.image) {
612
+ throw new Error("vision request requires `image` or `images[]`");
613
+ }
603
614
  if (request.image.url) {
604
615
  body.image_url = request.image.url;
605
616
  } else if (request.image.base64) {
@@ -633,6 +644,57 @@ var VisionNamespace = class {
633
644
  async classify(request) {
634
645
  return this.post("/api/ai/vision/classify", request);
635
646
  }
647
+ /**
648
+ * Stream a vision analysis. Yields `{ delta }` chunks as text arrives, then
649
+ * a final `{ done: true, model, provider, usage, cost }` chunk with totals.
650
+ *
651
+ * @example
652
+ * for await (const chunk of cencori.vision.analyzeStream({ image: { url } })) {
653
+ * if (chunk.delta) process.stdout.write(chunk.delta);
654
+ * if (chunk.done) console.log(chunk.cost);
655
+ * }
656
+ */
657
+ async *analyzeStream(request) {
658
+ const body = { ...toBody(request), stream: true };
659
+ const response = await fetch(`${this.config.baseUrl}/api/ai/vision`, {
660
+ method: "POST",
661
+ headers: {
662
+ "CENCORI_API_KEY": this.config.apiKey,
663
+ "Content-Type": "application/json",
664
+ ...this.config.headers
665
+ },
666
+ body: JSON.stringify(body)
667
+ });
668
+ if (!response.ok) {
669
+ const data = await response.json().catch(() => ({}));
670
+ const message = data && typeof data === "object" && "message" in data && typeof data.message === "string" ? data.message : `Vision stream request failed with status ${response.status}`;
671
+ throw new Error(message);
672
+ }
673
+ if (!response.body) throw new Error("Response body is null");
674
+ const reader = response.body.getReader();
675
+ const decoder = new TextDecoder();
676
+ let buffer = "";
677
+ try {
678
+ while (true) {
679
+ const { done, value } = await reader.read();
680
+ if (done) break;
681
+ buffer += decoder.decode(value, { stream: true });
682
+ const lines = buffer.split("\n");
683
+ buffer = lines.pop() ?? "";
684
+ for (const line of lines) {
685
+ if (!line.startsWith("data: ")) continue;
686
+ const data = line.slice(6);
687
+ if (data === "[DONE]") return;
688
+ try {
689
+ yield JSON.parse(data);
690
+ } catch {
691
+ }
692
+ }
693
+ }
694
+ } finally {
695
+ reader.releaseLock();
696
+ }
697
+ }
636
698
  async post(path, request) {
637
699
  const response = await fetch(`${this.config.baseUrl}${path}`, {
638
700
  method: "POST",
@@ -656,6 +718,66 @@ var VisionNamespace = class {
656
718
  }
657
719
  };
658
720
 
721
+ // src/documents/index.ts
722
+ function toBody2(request, extra = {}) {
723
+ const body = {
724
+ prompt: request.prompt,
725
+ model: request.model,
726
+ max_tokens: request.maxTokens,
727
+ temperature: request.temperature,
728
+ ...extra
729
+ };
730
+ if (request.document.url) {
731
+ body.document_url = request.document.url;
732
+ } else if (request.document.base64) {
733
+ body.document_base64 = request.document.base64;
734
+ body.mime_type = request.document.mimeType;
735
+ body.filename = request.document.filename;
736
+ } else {
737
+ throw new Error("documents request requires document.url or document.base64");
738
+ }
739
+ return body;
740
+ }
741
+ var DocumentsNamespace = class {
742
+ constructor(config) {
743
+ this.config = config;
744
+ }
745
+ /** Extract text from a PDF (native, no LLM) or image (via Vision OCR). */
746
+ async extract(request) {
747
+ return this.post("/api/ai/documents/extract", toBody2(request));
748
+ }
749
+ /** Extract then summarize the document with a chat model. */
750
+ async summarize(request) {
751
+ return this.post("/api/ai/documents/summarize", toBody2(request));
752
+ }
753
+ /** Extract then answer a question about the document. */
754
+ async query(request) {
755
+ if (!request.question) throw new Error("documents.query requires a `question`");
756
+ return this.post("/api/ai/documents/query", toBody2(request, { question: request.question }));
757
+ }
758
+ async post(path, body) {
759
+ const response = await fetch(`${this.config.baseUrl}${path}`, {
760
+ method: "POST",
761
+ headers: {
762
+ "CENCORI_API_KEY": this.config.apiKey,
763
+ "Content-Type": "application/json",
764
+ ...this.config.headers
765
+ },
766
+ body: JSON.stringify(body)
767
+ });
768
+ const data = await response.json();
769
+ if (!response.ok) {
770
+ const message = data && typeof data === "object" && "message" in data && typeof data.message === "string" ? data.message : `Documents request failed with status ${response.status}`;
771
+ const code = data && typeof data === "object" && "error" in data && typeof data.error === "string" ? data.error : "request_failed";
772
+ const err = new Error(message);
773
+ err.code = code;
774
+ err.details = data;
775
+ throw err;
776
+ }
777
+ return data;
778
+ }
779
+ };
780
+
659
781
  // src/sessions/index.ts
660
782
  var SessionsNamespace = class {
661
783
  constructor(config) {
@@ -1180,6 +1302,7 @@ var Cencori = class {
1180
1302
  };
1181
1303
  this.ai = new AINamespace(this.config);
1182
1304
  this.vision = new VisionNamespace(this.config);
1305
+ this.documents = new DocumentsNamespace(this.config);
1183
1306
  this.agents = new AgentsNamespace(this.config);
1184
1307
  this.compute = new ComputeNamespace();
1185
1308
  this.workflow = new WorkflowNamespace();
@@ -1606,6 +1729,7 @@ export {
1606
1729
  Cencori,
1607
1730
  CencoriError,
1608
1731
  ComputeNamespace,
1732
+ DocumentsNamespace,
1609
1733
  MemoryClient,
1610
1734
  RateLimitError,
1611
1735
  SafetyError,