@revojs/ai 0.3.1 → 0.3.3

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.
@@ -150,6 +150,24 @@ function toFinishReason(raw) {
150
150
  raw: raw ?? void 0
151
151
  };
152
152
  }
153
+ function toStreamError(chunk) {
154
+ if (typeof chunk.error === "string") return chunk.error;
155
+ if (chunk.error !== void 0) return chunk.error.message ?? "Unknown AI provider error";
156
+ if (chunk.object === "error") return chunk.message ?? "Unknown AI provider error";
157
+ }
158
+ function hasCompleteToolCalls(tools) {
159
+ if (tools.size === 0) return false;
160
+ for (const accumulator of tools.values()) {
161
+ if (accumulator.name.length === 0) return false;
162
+ try {
163
+ const input = JSON.parse(toToolInput(accumulator.arguments));
164
+ if (typeof input !== "object" || input === null || Array.isArray(input)) return false;
165
+ } catch {
166
+ return false;
167
+ }
168
+ }
169
+ return true;
170
+ }
153
171
  async function* readParts(response, warnings) {
154
172
  yield {
155
173
  type: "stream-start",
@@ -160,6 +178,7 @@ async function* readParts(response, warnings) {
160
178
  let textStarted = false;
161
179
  let reasoningStarted = false;
162
180
  let finishRaw;
181
+ let failure;
163
182
  let usage;
164
183
  for await (const data of readDataFrames(response)) {
165
184
  if (data === "[DONE]") break;
@@ -169,6 +188,8 @@ async function* readParts(response, warnings) {
169
188
  } catch {
170
189
  continue;
171
190
  }
191
+ failure = toStreamError(chunk);
192
+ if (failure !== void 0) break;
172
193
  if (!metadataSent) {
173
194
  metadataSent = true;
174
195
  yield {
@@ -213,11 +234,14 @@ async function* readParts(response, warnings) {
213
234
  }
214
235
  for (const partial of delta.tool_calls ?? []) {
215
236
  const index = partial.index ?? 0;
237
+ const id = typeof partial.id === "string" && partial.id.length > 0 ? partial.id : void 0;
238
+ const name = typeof partial.function?.name === "string" ? partial.function.name : "";
239
+ const input = typeof partial.function?.arguments === "string" ? partial.function.arguments : "";
216
240
  let accumulator = tools.get(index);
217
241
  if (accumulator === void 0) {
218
242
  accumulator = {
219
- streamId: partial.id ?? `openai-tool-${index}`,
220
- callId: partial.id ?? "",
243
+ streamId: id ?? `openai-tool-${index}`,
244
+ callId: id ?? "",
221
245
  name: "",
222
246
  arguments: ""
223
247
  };
@@ -225,22 +249,25 @@ async function* readParts(response, warnings) {
225
249
  yield {
226
250
  type: "tool-input-start",
227
251
  id: accumulator.streamId,
228
- toolName: partial.function?.name ?? ""
252
+ toolName: name
229
253
  };
230
254
  }
231
- if (partial.id !== void 0 && partial.id !== accumulator.callId) accumulator.callId = partial.id;
232
- if (partial.function?.name !== void 0) accumulator.name += partial.function.name;
233
- if (partial.function?.arguments !== void 0) {
234
- accumulator.arguments += partial.function.arguments;
255
+ if (id !== void 0) accumulator.callId = id;
256
+ accumulator.name += name;
257
+ if (input.length > 0) {
258
+ accumulator.arguments += input;
235
259
  yield {
236
260
  type: "tool-input-delta",
237
261
  id: accumulator.streamId,
238
- delta: partial.function.arguments
262
+ delta: input
239
263
  };
240
264
  }
241
265
  }
242
266
  }
243
- if (finishRaw === void 0) throw new Error("Incomplete chat completions stream.");
267
+ if (finishRaw === void 0) {
268
+ if (!hasCompleteToolCalls(tools)) throw new Error(failure ?? "Incomplete chat completions stream.");
269
+ finishRaw = "tool_calls";
270
+ }
244
271
  if (reasoningStarted) yield {
245
272
  type: "reasoning-end",
246
273
  id: "openai-reasoning-0"
@@ -289,9 +316,9 @@ function chatCompletionsGenerateProtocol(config) {
289
316
  });
290
317
  for (const call of choice.message.tool_calls ?? []) content.push({
291
318
  type: "tool-call",
292
- toolCallId: call.id ?? "",
293
- toolName: call.function?.name ?? "",
294
- input: toToolInput(call.function?.arguments)
319
+ toolCallId: typeof call.id === "string" ? call.id : "",
320
+ toolName: typeof call.function?.name === "string" ? call.function.name : "",
321
+ input: toToolInput(typeof call.function?.arguments === "string" ? call.function.arguments : void 0)
295
322
  });
296
323
  return {
297
324
  content,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revojs/ai",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -30,10 +30,10 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@cfworker/json-schema": "^4.1.1",
33
- "@revojs/server": "0.3.1",
34
- "revojs": "0.3.1"
33
+ "@revojs/server": "0.3.3",
34
+ "revojs": "0.3.3"
35
35
  },
36
36
  "devDependencies": {
37
- "@revojs/tsconfig": "0.3.1"
37
+ "@revojs/tsconfig": "0.3.3"
38
38
  }
39
39
  }