@canarycoders/ai 0.6.0 → 0.8.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/README.md CHANGED
@@ -4,7 +4,7 @@ TypeScript SDK for the [CanaryCoders AI](https://ai.canarycoders.es) gateway. Ru
4
4
 
5
5
  **Docs:** https://docs.ai.canarycoders.es
6
6
 
7
- One client covers chat, image/video/audio generation, embeddings, vision, conversational agents, realtime sessions, and usage data. The queue polling, SSE streaming, retries, and error typing are handled for you, so most calls are a single `await`.
7
+ One client covers chat, image/video/audio generation, embeddings, vision, OCR/PII-redaction, conversational agents, realtime sessions, and usage data. The queue polling, SSE streaming, retries, and error typing are handled for you, so most calls are a single `await`.
8
8
 
9
9
  ## Install
10
10
 
@@ -77,6 +77,20 @@ const song = await client.audio.music({ prompt: "calm lo-fi", durationMs: 20000
77
77
  const { detections } = await client.vision.detect({ image });
78
78
  ```
79
79
 
80
+ ## OCR and PII redaction (local)
81
+
82
+ Text recognition with bounding boxes and PII redaction, processed fully on CanaryLLM's own EU infrastructure (Apple Vision). Images and extracted text are never stored.
83
+
84
+ ```ts
85
+ const { text, lines } = await client.ocr.recognize({ image, granularity: "word" });
86
+
87
+ const { redactedImage, counts } = await client.ocr.redact({
88
+ image,
89
+ presets: ["email", "phone", "iban"],
90
+ style: "blur", // "box" is the safest for hard PII redaction
91
+ });
92
+ ```
93
+
80
94
  ## Embeddings
81
95
 
82
96
  Embed text into vectors with a local model (LM Studio), for customer-side RAG. The gateway processes the text transiently and stores nothing — you keep the vectors and documents in your own store (e.g. pgvector, sqlite-vec).
package/dist/index.cjs CHANGED
@@ -682,6 +682,7 @@ async function* nativeQueueAdapter(frames, includeRaw) {
682
682
  const raw = (v) => includeRaw ? v : void 0;
683
683
  let lastUsage;
684
684
  let lastFinish;
685
+ let lastCost;
685
686
  for await (const frame of frames) {
686
687
  switch (frame.event) {
687
688
  case "start":
@@ -690,11 +691,12 @@ async function* nativeQueueAdapter(frames, includeRaw) {
690
691
  case "error":
691
692
  throw streamError(tryParse(frame.data));
692
693
  case "done":
693
- yield { type: "done", finishReason: lastFinish, usage: lastUsage };
694
+ yield { type: "done", finishReason: lastFinish, usage: lastUsage, cost: lastCost };
694
695
  return;
695
696
  case "chunk": {
696
697
  const chunk = tryParse(frame.data);
697
698
  if (!chunk) break;
699
+ if (chunk.cost) lastCost = chunk.cost;
698
700
  if (chunk.usage) {
699
701
  lastUsage = chunk.usage;
700
702
  yield { type: "usage", usage: chunk.usage, raw: raw(chunk) };
@@ -722,7 +724,7 @@ async function* nativeQueueAdapter(frames, includeRaw) {
722
724
  }
723
725
  }
724
726
  }
725
- yield { type: "done", finishReason: lastFinish, usage: lastUsage };
727
+ yield { type: "done", finishReason: lastFinish, usage: lastUsage, cost: lastCost };
726
728
  }
727
729
  async function* openAIAdapter(frames, includeRaw) {
728
730
  const raw = (v) => includeRaw ? v : void 0;
@@ -1588,6 +1590,27 @@ var VisionResource = class extends BaseResource {
1588
1590
  }
1589
1591
  };
1590
1592
 
1593
+ // src/resources/ocr.ts
1594
+ var OcrResource = class extends BaseResource {
1595
+ recognize(params, poll) {
1596
+ return this.runQueued("/api/ocr/recognize", params, "vision", poll);
1597
+ }
1598
+ recognizeJob(params, signal) {
1599
+ return this.submitQueued("/api/ocr/recognize", params, "vision", signal);
1600
+ }
1601
+ redact(params, poll) {
1602
+ return this.runQueued("/api/ocr/redact", params, "vision", poll);
1603
+ }
1604
+ redactJob(params, signal) {
1605
+ return this.submitQueued("/api/ocr/redact", params, "vision", signal);
1606
+ }
1607
+ async languages(signal) {
1608
+ return this.transport.json("GET", "/api/ocr/languages", {
1609
+ signal
1610
+ });
1611
+ }
1612
+ };
1613
+
1591
1614
  // src/client.ts
1592
1615
  var DEFAULT_BASE_URL = "https://api.ai.canarycoders.es";
1593
1616
  function readEnv(key) {
@@ -1602,6 +1625,7 @@ var CanaryCodersAI = class {
1602
1625
  audio;
1603
1626
  embeddings;
1604
1627
  vision;
1628
+ ocr;
1605
1629
  conversations;
1606
1630
  agents;
1607
1631
  realtime;
@@ -1634,6 +1658,7 @@ var CanaryCodersAI = class {
1634
1658
  this.audio = new AudioResource(this.transport, poll);
1635
1659
  this.embeddings = new EmbeddingsResource(this.transport, poll);
1636
1660
  this.vision = new VisionResource(this.transport, poll);
1661
+ this.ocr = new OcrResource(this.transport, poll);
1637
1662
  this.conversations = new ConversationsResource(this.transport, poll);
1638
1663
  this.agents = new AgentsResource(this.transport, poll);
1639
1664
  this.realtime = new RealtimeResource(this.transport, poll);