cencori 1.3.0 → 1.3.1

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
@@ -633,6 +633,57 @@ var VisionNamespace = class {
633
633
  async classify(request) {
634
634
  return this.post("/api/ai/vision/classify", request);
635
635
  }
636
+ /**
637
+ * Stream a vision analysis. Yields `{ delta }` chunks as text arrives, then
638
+ * a final `{ done: true, model, provider, usage, cost }` chunk with totals.
639
+ *
640
+ * @example
641
+ * for await (const chunk of cencori.vision.analyzeStream({ image: { url } })) {
642
+ * if (chunk.delta) process.stdout.write(chunk.delta);
643
+ * if (chunk.done) console.log(chunk.cost);
644
+ * }
645
+ */
646
+ async *analyzeStream(request) {
647
+ const body = { ...toBody(request), stream: true };
648
+ const response = await fetch(`${this.config.baseUrl}/api/ai/vision`, {
649
+ method: "POST",
650
+ headers: {
651
+ "CENCORI_API_KEY": this.config.apiKey,
652
+ "Content-Type": "application/json",
653
+ ...this.config.headers
654
+ },
655
+ body: JSON.stringify(body)
656
+ });
657
+ if (!response.ok) {
658
+ const data = await response.json().catch(() => ({}));
659
+ const message = data && typeof data === "object" && "message" in data && typeof data.message === "string" ? data.message : `Vision stream request failed with status ${response.status}`;
660
+ throw new Error(message);
661
+ }
662
+ if (!response.body) throw new Error("Response body is null");
663
+ const reader = response.body.getReader();
664
+ const decoder = new TextDecoder();
665
+ let buffer = "";
666
+ try {
667
+ while (true) {
668
+ const { done, value } = await reader.read();
669
+ if (done) break;
670
+ buffer += decoder.decode(value, { stream: true });
671
+ const lines = buffer.split("\n");
672
+ buffer = lines.pop() ?? "";
673
+ for (const line of lines) {
674
+ if (!line.startsWith("data: ")) continue;
675
+ const data = line.slice(6);
676
+ if (data === "[DONE]") return;
677
+ try {
678
+ yield JSON.parse(data);
679
+ } catch {
680
+ }
681
+ }
682
+ }
683
+ } finally {
684
+ reader.releaseLock();
685
+ }
686
+ }
636
687
  async post(path, request) {
637
688
  const response = await fetch(`${this.config.baseUrl}${path}`, {
638
689
  method: "POST",