ovrule-lab 0.2.0 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +39 -20
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const DEFAULT_OVRULE_BASE_URL = "https://decision-receipt-lab.vercel.app";
2
+ const SDK_VERSION = "0.2.1";
2
3
  let hasShownReadyMessage = false;
3
4
  function isQuietModeEnabled() {
4
5
  return (typeof process !== "undefined" &&
@@ -21,7 +22,7 @@ function logSuccessfulAudit(receipt, baseUrl) {
21
22
  }
22
23
  const caseUrl = `${getConsoleBaseUrl(baseUrl)}/case/${receipt.receiptId}`;
23
24
  if (!hasShownReadyMessage) {
24
- console.info(`[ovrule-lab v0.2.0] ready · docs: ${DEFAULT_OVRULE_BASE_URL}/docs`);
25
+ console.info(`[ovrule-lab v${SDK_VERSION}] ready · docs: ${DEFAULT_OVRULE_BASE_URL}/docs`);
25
26
  hasShownReadyMessage = true;
26
27
  }
27
28
  console.info(`[ovrule-lab] ✓ audited via ${caseUrl}`);
@@ -45,6 +46,33 @@ async function readJson(response) {
45
46
  }
46
47
  return data;
47
48
  }
49
+ function parseSseBlock(block) {
50
+ const lines = block.split("\n");
51
+ const eventName = lines.find((line) => line.startsWith("event:"))?.slice(6).trim();
52
+ const data = lines
53
+ .filter((line) => line.startsWith("data:"))
54
+ .map((line) => line.slice(5).trim())
55
+ .join("\n");
56
+ if (!eventName || !data) {
57
+ return null;
58
+ }
59
+ return {
60
+ eventName,
61
+ data: JSON.parse(data),
62
+ };
63
+ }
64
+ function applySseEvent(parsed, currentReceipt) {
65
+ if (!parsed) {
66
+ return currentReceipt;
67
+ }
68
+ if (parsed.data.type === "session.error") {
69
+ throw new Error(parsed.data.message);
70
+ }
71
+ if (parsed.data.type === "analysis.completed") {
72
+ return parsed.data.receipt;
73
+ }
74
+ return currentReceipt;
75
+ }
48
76
  export class OvruleClient {
49
77
  baseUrl;
50
78
  fetchImpl;
@@ -85,30 +113,21 @@ export class OvruleClient {
85
113
  let finalReceipt = null;
86
114
  while (true) {
87
115
  const { done, value } = await reader.read();
88
- if (done) {
89
- break;
116
+ if (value) {
117
+ buffer += decoder.decode(value, { stream: !done });
90
118
  }
91
- buffer += decoder.decode(value, { stream: true });
92
119
  const blocks = buffer.split("\n\n");
93
120
  buffer = blocks.pop() ?? "";
94
121
  for (const block of blocks) {
95
- const lines = block.split("\n");
96
- const eventName = lines.find((line) => line.startsWith("event:"))?.slice(6).trim();
97
- const data = lines
98
- .filter((line) => line.startsWith("data:"))
99
- .map((line) => line.slice(5).trim())
100
- .join("\n");
101
- if (!eventName || !data) {
102
- continue;
103
- }
104
- const parsed = JSON.parse(data);
105
- if (parsed.type === "analysis.completed") {
106
- finalReceipt = parsed.receipt;
107
- }
108
- if (parsed.type === "session.error") {
109
- throw new Error(parsed.message);
110
- }
122
+ finalReceipt = applySseEvent(parseSseBlock(block), finalReceipt);
111
123
  }
124
+ if (done) {
125
+ break;
126
+ }
127
+ }
128
+ buffer += decoder.decode();
129
+ if (buffer.trim()) {
130
+ finalReceipt = applySseEvent(parseSseBlock(buffer.trim()), finalReceipt);
112
131
  }
113
132
  if (!finalReceipt) {
114
133
  throw new Error("Ovrule classify stream finished without a final receipt.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ovrule-lab",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "TypeScript SDK for Ovrule case-file classification, guardrails, and receipt verification.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",