@acosmi/sdk-ts 2.19.2 → 2.19.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.
@@ -2079,7 +2079,12 @@ interface OpenAIStreamChunk {
2079
2079
  id: string;
2080
2080
  /** "chat.completion.chunk" */
2081
2081
  object: string;
2082
- choices: OpenAIStreamChoice[];
2082
+ /**
2083
+ * [W-QUAD-CHAIN-20260914] 可空。类型此前声明为必填, 但线上确实存在没有该字段的 data 帧
2084
+ * (网关错误契约帧、部分兼容实现的 usage-only 尾帧) —— 「类型说它一定在、运行时它不在」
2085
+ * 正是那句 `chunk.choices.length` TypeError 的来源。消费处必须先判 Array.isArray。
2086
+ */
2087
+ choices?: OpenAIStreamChoice[];
2083
2088
  usage?: OpenAIUsage;
2084
2089
  }
2085
2090
  interface OpenAIStreamChoice {
@@ -2079,7 +2079,12 @@ interface OpenAIStreamChunk {
2079
2079
  id: string;
2080
2080
  /** "chat.completion.chunk" */
2081
2081
  object: string;
2082
- choices: OpenAIStreamChoice[];
2082
+ /**
2083
+ * [W-QUAD-CHAIN-20260914] 可空。类型此前声明为必填, 但线上确实存在没有该字段的 data 帧
2084
+ * (网关错误契约帧、部分兼容实现的 usage-only 尾帧) —— 「类型说它一定在、运行时它不在」
2085
+ * 正是那句 `chunk.choices.length` TypeError 的来源。消费处必须先判 Array.isArray。
2086
+ */
2087
+ choices?: OpenAIStreamChoice[];
2083
2088
  usage?: OpenAIUsage;
2084
2089
  }
2085
2090
  interface OpenAIStreamChoice {
@@ -1084,7 +1084,7 @@ var init_openai = __esm({
1084
1084
  throw new Error(`parse openai stream chunk: ${e instanceof Error ? e.message : String(e)}`);
1085
1085
  }
1086
1086
  const events = [];
1087
- if (chunk.choices.length === 0) {
1087
+ if (!Array.isArray(chunk.choices) || chunk.choices.length === 0) {
1088
1088
  return { events, done: false };
1089
1089
  }
1090
1090
  const choice = chunk.choices[0];
@@ -4355,13 +4355,17 @@ var Client = class _Client {
4355
4355
  }
4356
4356
  if (adapter.format() === 1 /* OpenAI */) {
4357
4357
  const converter = newOpenAIStreamConverter();
4358
+ let currentEvent = "";
4358
4359
  for await (const line of iterSSELines(resp.body)) {
4359
4360
  notifyUpstreamActivity(onUpstreamActivity);
4360
4361
  if (isSSECommentLine(line)) continue;
4361
4362
  if (line.startsWith("event:")) {
4362
- line.slice("event:".length).trim();
4363
+ currentEvent = line.slice("event:".length).trim();
4363
4364
  } else if (line.startsWith("data:")) {
4364
4365
  const data = line.slice("data:".length).trim();
4366
+ if (currentEvent === "failed" || currentEvent === "error") {
4367
+ throw parseStreamError(data);
4368
+ }
4365
4369
  const { events, done } = converter.convert(data);
4366
4370
  for (const ev of events) yield ev;
4367
4371
  if (done) return;