ChatCompletionStream.mjs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. var _ChatCompletionStream_instances, _ChatCompletionStream_params, _ChatCompletionStream_choiceEventStates, _ChatCompletionStream_currentChatCompletionSnapshot, _ChatCompletionStream_beginRequest, _ChatCompletionStream_getChoiceEventState, _ChatCompletionStream_addChunk, _ChatCompletionStream_emitToolCallDoneEvent, _ChatCompletionStream_emitContentDoneEvents, _ChatCompletionStream_endRequest, _ChatCompletionStream_getAutoParseableResponseFormat, _ChatCompletionStream_accumulateChatCompletion;
  2. import { __classPrivateFieldGet, __classPrivateFieldSet } from "../internal/tslib.mjs";
  3. import { partialParse } from "../_vendor/partial-json-parser/parser.mjs";
  4. import { APIUserAbortError, ContentFilterFinishReasonError, LengthFinishReasonError, OpenAIError, } from "../error.mjs";
  5. import { hasAutoParseableInput, isAutoParsableResponseFormat, isAutoParsableTool, isChatCompletionFunctionTool, maybeParseChatCompletion, shouldParseToolCall, } from "../lib/parser.mjs";
  6. import { Stream } from "../streaming.mjs";
  7. import { AbstractChatCompletionRunner, } from "./AbstractChatCompletionRunner.mjs";
  8. export class ChatCompletionStream extends AbstractChatCompletionRunner {
  9. constructor(params) {
  10. super();
  11. _ChatCompletionStream_instances.add(this);
  12. _ChatCompletionStream_params.set(this, void 0);
  13. _ChatCompletionStream_choiceEventStates.set(this, void 0);
  14. _ChatCompletionStream_currentChatCompletionSnapshot.set(this, void 0);
  15. __classPrivateFieldSet(this, _ChatCompletionStream_params, params, "f");
  16. __classPrivateFieldSet(this, _ChatCompletionStream_choiceEventStates, [], "f");
  17. }
  18. get currentChatCompletionSnapshot() {
  19. return __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
  20. }
  21. /**
  22. * Intended for use on the frontend, consuming a stream produced with
  23. * `.toReadableStream()` on the backend.
  24. *
  25. * Note that messages sent to the model do not appear in `.on('message')`
  26. * in this context.
  27. */
  28. static fromReadableStream(stream) {
  29. const runner = new ChatCompletionStream(null);
  30. runner._run(() => runner._fromReadableStream(stream));
  31. return runner;
  32. }
  33. static createChatCompletion(client, params, options) {
  34. const runner = new ChatCompletionStream(params);
  35. runner._run(() => runner._runChatCompletion(client, { ...params, stream: true }, { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } }));
  36. return runner;
  37. }
  38. async _createChatCompletion(client, params, options) {
  39. super._createChatCompletion;
  40. const signal = options?.signal;
  41. if (signal) {
  42. if (signal.aborted)
  43. this.controller.abort();
  44. signal.addEventListener('abort', () => this.controller.abort());
  45. }
  46. __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_beginRequest).call(this);
  47. const stream = await client.chat.completions.create({ ...params, stream: true }, { ...options, signal: this.controller.signal });
  48. this._connected();
  49. for await (const chunk of stream) {
  50. __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_addChunk).call(this, chunk);
  51. }
  52. if (stream.controller.signal?.aborted) {
  53. throw new APIUserAbortError();
  54. }
  55. return this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
  56. }
  57. async _fromReadableStream(readableStream, options) {
  58. const signal = options?.signal;
  59. if (signal) {
  60. if (signal.aborted)
  61. this.controller.abort();
  62. signal.addEventListener('abort', () => this.controller.abort());
  63. }
  64. __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_beginRequest).call(this);
  65. this._connected();
  66. const stream = Stream.fromReadableStream(readableStream, this.controller);
  67. let chatId;
  68. for await (const chunk of stream) {
  69. if (chatId && chatId !== chunk.id) {
  70. // A new request has been made.
  71. this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
  72. }
  73. __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_addChunk).call(this, chunk);
  74. chatId = chunk.id;
  75. }
  76. if (stream.controller.signal?.aborted) {
  77. throw new APIUserAbortError();
  78. }
  79. return this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
  80. }
  81. [(_ChatCompletionStream_params = new WeakMap(), _ChatCompletionStream_choiceEventStates = new WeakMap(), _ChatCompletionStream_currentChatCompletionSnapshot = new WeakMap(), _ChatCompletionStream_instances = new WeakSet(), _ChatCompletionStream_beginRequest = function _ChatCompletionStream_beginRequest() {
  82. if (this.ended)
  83. return;
  84. __classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, undefined, "f");
  85. }, _ChatCompletionStream_getChoiceEventState = function _ChatCompletionStream_getChoiceEventState(choice) {
  86. let state = __classPrivateFieldGet(this, _ChatCompletionStream_choiceEventStates, "f")[choice.index];
  87. if (state) {
  88. return state;
  89. }
  90. state = {
  91. content_done: false,
  92. refusal_done: false,
  93. logprobs_content_done: false,
  94. logprobs_refusal_done: false,
  95. done_tool_calls: new Set(),
  96. current_tool_call_index: null,
  97. };
  98. __classPrivateFieldGet(this, _ChatCompletionStream_choiceEventStates, "f")[choice.index] = state;
  99. return state;
  100. }, _ChatCompletionStream_addChunk = function _ChatCompletionStream_addChunk(chunk) {
  101. if (this.ended)
  102. return;
  103. const completion = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_accumulateChatCompletion).call(this, chunk);
  104. this._emit('chunk', chunk, completion);
  105. for (const choice of chunk.choices) {
  106. const choiceSnapshot = completion.choices[choice.index];
  107. if (choice.delta.content != null &&
  108. choiceSnapshot.message?.role === 'assistant' &&
  109. choiceSnapshot.message?.content) {
  110. this._emit('content', choice.delta.content, choiceSnapshot.message.content);
  111. this._emit('content.delta', {
  112. delta: choice.delta.content,
  113. snapshot: choiceSnapshot.message.content,
  114. parsed: choiceSnapshot.message.parsed,
  115. });
  116. }
  117. if (choice.delta.refusal != null &&
  118. choiceSnapshot.message?.role === 'assistant' &&
  119. choiceSnapshot.message?.refusal) {
  120. this._emit('refusal.delta', {
  121. delta: choice.delta.refusal,
  122. snapshot: choiceSnapshot.message.refusal,
  123. });
  124. }
  125. if (choice.logprobs?.content != null && choiceSnapshot.message?.role === 'assistant') {
  126. this._emit('logprobs.content.delta', {
  127. content: choice.logprobs?.content,
  128. snapshot: choiceSnapshot.logprobs?.content ?? [],
  129. });
  130. }
  131. if (choice.logprobs?.refusal != null && choiceSnapshot.message?.role === 'assistant') {
  132. this._emit('logprobs.refusal.delta', {
  133. refusal: choice.logprobs?.refusal,
  134. snapshot: choiceSnapshot.logprobs?.refusal ?? [],
  135. });
  136. }
  137. const state = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
  138. if (choiceSnapshot.finish_reason) {
  139. __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitContentDoneEvents).call(this, choiceSnapshot);
  140. if (state.current_tool_call_index != null) {
  141. __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitToolCallDoneEvent).call(this, choiceSnapshot, state.current_tool_call_index);
  142. }
  143. }
  144. for (const toolCall of choice.delta.tool_calls ?? []) {
  145. if (state.current_tool_call_index !== toolCall.index) {
  146. __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitContentDoneEvents).call(this, choiceSnapshot);
  147. // new tool call started, the previous one is done
  148. if (state.current_tool_call_index != null) {
  149. __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitToolCallDoneEvent).call(this, choiceSnapshot, state.current_tool_call_index);
  150. }
  151. }
  152. state.current_tool_call_index = toolCall.index;
  153. }
  154. for (const toolCallDelta of choice.delta.tool_calls ?? []) {
  155. const toolCallSnapshot = choiceSnapshot.message.tool_calls?.[toolCallDelta.index];
  156. if (!toolCallSnapshot?.type) {
  157. continue;
  158. }
  159. if (toolCallSnapshot?.type === 'function') {
  160. this._emit('tool_calls.function.arguments.delta', {
  161. name: toolCallSnapshot.function?.name,
  162. index: toolCallDelta.index,
  163. arguments: toolCallSnapshot.function.arguments,
  164. parsed_arguments: toolCallSnapshot.function.parsed_arguments,
  165. arguments_delta: toolCallDelta.function?.arguments ?? '',
  166. });
  167. }
  168. else {
  169. assertNever(toolCallSnapshot?.type);
  170. }
  171. }
  172. }
  173. }, _ChatCompletionStream_emitToolCallDoneEvent = function _ChatCompletionStream_emitToolCallDoneEvent(choiceSnapshot, toolCallIndex) {
  174. const state = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
  175. if (state.done_tool_calls.has(toolCallIndex)) {
  176. // we've already fired the done event
  177. return;
  178. }
  179. const toolCallSnapshot = choiceSnapshot.message.tool_calls?.[toolCallIndex];
  180. if (!toolCallSnapshot) {
  181. throw new Error('no tool call snapshot');
  182. }
  183. if (!toolCallSnapshot.type) {
  184. throw new Error('tool call snapshot missing `type`');
  185. }
  186. if (toolCallSnapshot.type === 'function') {
  187. const inputTool = __classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.tools?.find((tool) => isChatCompletionFunctionTool(tool) && tool.function.name === toolCallSnapshot.function.name); // TS doesn't narrow based on isChatCompletionTool
  188. this._emit('tool_calls.function.arguments.done', {
  189. name: toolCallSnapshot.function.name,
  190. index: toolCallIndex,
  191. arguments: toolCallSnapshot.function.arguments,
  192. parsed_arguments: isAutoParsableTool(inputTool) ? inputTool.$parseRaw(toolCallSnapshot.function.arguments)
  193. : inputTool?.function.strict ? JSON.parse(toolCallSnapshot.function.arguments)
  194. : null,
  195. });
  196. }
  197. else {
  198. assertNever(toolCallSnapshot.type);
  199. }
  200. }, _ChatCompletionStream_emitContentDoneEvents = function _ChatCompletionStream_emitContentDoneEvents(choiceSnapshot) {
  201. const state = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
  202. if (choiceSnapshot.message.content && !state.content_done) {
  203. state.content_done = true;
  204. const responseFormat = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getAutoParseableResponseFormat).call(this);
  205. this._emit('content.done', {
  206. content: choiceSnapshot.message.content,
  207. parsed: responseFormat ? responseFormat.$parseRaw(choiceSnapshot.message.content) : null,
  208. });
  209. }
  210. if (choiceSnapshot.message.refusal && !state.refusal_done) {
  211. state.refusal_done = true;
  212. this._emit('refusal.done', { refusal: choiceSnapshot.message.refusal });
  213. }
  214. if (choiceSnapshot.logprobs?.content && !state.logprobs_content_done) {
  215. state.logprobs_content_done = true;
  216. this._emit('logprobs.content.done', { content: choiceSnapshot.logprobs.content });
  217. }
  218. if (choiceSnapshot.logprobs?.refusal && !state.logprobs_refusal_done) {
  219. state.logprobs_refusal_done = true;
  220. this._emit('logprobs.refusal.done', { refusal: choiceSnapshot.logprobs.refusal });
  221. }
  222. }, _ChatCompletionStream_endRequest = function _ChatCompletionStream_endRequest() {
  223. if (this.ended) {
  224. throw new OpenAIError(`stream has ended, this shouldn't happen`);
  225. }
  226. const snapshot = __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
  227. if (!snapshot) {
  228. throw new OpenAIError(`request ended without sending any chunks`);
  229. }
  230. __classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, undefined, "f");
  231. __classPrivateFieldSet(this, _ChatCompletionStream_choiceEventStates, [], "f");
  232. return finalizeChatCompletion(snapshot, __classPrivateFieldGet(this, _ChatCompletionStream_params, "f"));
  233. }, _ChatCompletionStream_getAutoParseableResponseFormat = function _ChatCompletionStream_getAutoParseableResponseFormat() {
  234. const responseFormat = __classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.response_format;
  235. if (isAutoParsableResponseFormat(responseFormat)) {
  236. return responseFormat;
  237. }
  238. return null;
  239. }, _ChatCompletionStream_accumulateChatCompletion = function _ChatCompletionStream_accumulateChatCompletion(chunk) {
  240. var _a, _b, _c, _d;
  241. let snapshot = __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
  242. const { choices, ...rest } = chunk;
  243. if (!snapshot) {
  244. snapshot = __classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, {
  245. ...rest,
  246. choices: [],
  247. }, "f");
  248. }
  249. else {
  250. Object.assign(snapshot, rest);
  251. }
  252. for (const { delta, finish_reason, index, logprobs = null, ...other } of chunk.choices) {
  253. let choice = snapshot.choices[index];
  254. if (!choice) {
  255. choice = snapshot.choices[index] = { finish_reason, index, message: {}, logprobs, ...other };
  256. }
  257. if (logprobs) {
  258. if (!choice.logprobs) {
  259. choice.logprobs = Object.assign({}, logprobs);
  260. }
  261. else {
  262. const { content, refusal, ...rest } = logprobs;
  263. assertIsEmpty(rest);
  264. Object.assign(choice.logprobs, rest);
  265. if (content) {
  266. (_a = choice.logprobs).content ?? (_a.content = []);
  267. choice.logprobs.content.push(...content);
  268. }
  269. if (refusal) {
  270. (_b = choice.logprobs).refusal ?? (_b.refusal = []);
  271. choice.logprobs.refusal.push(...refusal);
  272. }
  273. }
  274. }
  275. if (finish_reason) {
  276. choice.finish_reason = finish_reason;
  277. if (__classPrivateFieldGet(this, _ChatCompletionStream_params, "f") && hasAutoParseableInput(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f"))) {
  278. if (finish_reason === 'length') {
  279. throw new LengthFinishReasonError();
  280. }
  281. if (finish_reason === 'content_filter') {
  282. throw new ContentFilterFinishReasonError();
  283. }
  284. }
  285. }
  286. Object.assign(choice, other);
  287. if (!delta)
  288. continue; // Shouldn't happen; just in case.
  289. const { content, refusal, function_call, role, tool_calls, ...rest } = delta;
  290. assertIsEmpty(rest);
  291. Object.assign(choice.message, rest);
  292. if (refusal) {
  293. choice.message.refusal = (choice.message.refusal || '') + refusal;
  294. }
  295. if (role)
  296. choice.message.role = role;
  297. if (function_call) {
  298. if (!choice.message.function_call) {
  299. choice.message.function_call = function_call;
  300. }
  301. else {
  302. if (function_call.name)
  303. choice.message.function_call.name = function_call.name;
  304. if (function_call.arguments) {
  305. (_c = choice.message.function_call).arguments ?? (_c.arguments = '');
  306. choice.message.function_call.arguments += function_call.arguments;
  307. }
  308. }
  309. }
  310. if (content) {
  311. choice.message.content = (choice.message.content || '') + content;
  312. if (!choice.message.refusal && __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getAutoParseableResponseFormat).call(this)) {
  313. choice.message.parsed = partialParse(choice.message.content);
  314. }
  315. }
  316. if (tool_calls) {
  317. if (!choice.message.tool_calls)
  318. choice.message.tool_calls = [];
  319. for (const { index, id, type, function: fn, ...rest } of tool_calls) {
  320. const tool_call = ((_d = choice.message.tool_calls)[index] ?? (_d[index] = {}));
  321. Object.assign(tool_call, rest);
  322. if (id)
  323. tool_call.id = id;
  324. if (type)
  325. tool_call.type = type;
  326. if (fn)
  327. tool_call.function ?? (tool_call.function = { name: fn.name ?? '', arguments: '' });
  328. if (fn?.name)
  329. tool_call.function.name = fn.name;
  330. if (fn?.arguments) {
  331. tool_call.function.arguments += fn.arguments;
  332. if (shouldParseToolCall(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f"), tool_call)) {
  333. tool_call.function.parsed_arguments = partialParse(tool_call.function.arguments);
  334. }
  335. }
  336. }
  337. }
  338. }
  339. return snapshot;
  340. }, Symbol.asyncIterator)]() {
  341. const pushQueue = [];
  342. const readQueue = [];
  343. let done = false;
  344. this.on('chunk', (chunk) => {
  345. const reader = readQueue.shift();
  346. if (reader) {
  347. reader.resolve(chunk);
  348. }
  349. else {
  350. pushQueue.push(chunk);
  351. }
  352. });
  353. this.on('end', () => {
  354. done = true;
  355. for (const reader of readQueue) {
  356. reader.resolve(undefined);
  357. }
  358. readQueue.length = 0;
  359. });
  360. this.on('abort', (err) => {
  361. done = true;
  362. for (const reader of readQueue) {
  363. reader.reject(err);
  364. }
  365. readQueue.length = 0;
  366. });
  367. this.on('error', (err) => {
  368. done = true;
  369. for (const reader of readQueue) {
  370. reader.reject(err);
  371. }
  372. readQueue.length = 0;
  373. });
  374. return {
  375. next: async () => {
  376. if (!pushQueue.length) {
  377. if (done) {
  378. return { value: undefined, done: true };
  379. }
  380. return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((chunk) => (chunk ? { value: chunk, done: false } : { value: undefined, done: true }));
  381. }
  382. const chunk = pushQueue.shift();
  383. return { value: chunk, done: false };
  384. },
  385. return: async () => {
  386. this.abort();
  387. return { value: undefined, done: true };
  388. },
  389. };
  390. }
  391. toReadableStream() {
  392. const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
  393. return stream.toReadableStream();
  394. }
  395. }
  396. function finalizeChatCompletion(snapshot, params) {
  397. const { id, choices, created, model, system_fingerprint, ...rest } = snapshot;
  398. const completion = {
  399. ...rest,
  400. id,
  401. choices: choices.map(({ message, finish_reason, index, logprobs, ...choiceRest }) => {
  402. if (!finish_reason) {
  403. throw new OpenAIError(`missing finish_reason for choice ${index}`);
  404. }
  405. const { content = null, function_call, tool_calls, ...messageRest } = message;
  406. const role = message.role; // this is what we expect; in theory it could be different which would make our types a slight lie but would be fine.
  407. if (!role) {
  408. throw new OpenAIError(`missing role for choice ${index}`);
  409. }
  410. if (function_call) {
  411. const { arguments: args, name } = function_call;
  412. if (args == null) {
  413. throw new OpenAIError(`missing function_call.arguments for choice ${index}`);
  414. }
  415. if (!name) {
  416. throw new OpenAIError(`missing function_call.name for choice ${index}`);
  417. }
  418. return {
  419. ...choiceRest,
  420. message: {
  421. content,
  422. function_call: { arguments: args, name },
  423. role,
  424. refusal: message.refusal ?? null,
  425. },
  426. finish_reason,
  427. index,
  428. logprobs,
  429. };
  430. }
  431. if (tool_calls) {
  432. return {
  433. ...choiceRest,
  434. index,
  435. finish_reason,
  436. logprobs,
  437. message: {
  438. ...messageRest,
  439. role,
  440. content,
  441. refusal: message.refusal ?? null,
  442. tool_calls: tool_calls.map((tool_call, i) => {
  443. const { function: fn, type, id, ...toolRest } = tool_call;
  444. const { arguments: args, name, ...fnRest } = fn || {};
  445. if (id == null) {
  446. throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].id\n${str(snapshot)}`);
  447. }
  448. if (type == null) {
  449. throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].type\n${str(snapshot)}`);
  450. }
  451. if (name == null) {
  452. throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].function.name\n${str(snapshot)}`);
  453. }
  454. if (args == null) {
  455. throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].function.arguments\n${str(snapshot)}`);
  456. }
  457. return { ...toolRest, id, type, function: { ...fnRest, name, arguments: args } };
  458. }),
  459. },
  460. };
  461. }
  462. return {
  463. ...choiceRest,
  464. message: { ...messageRest, content, role, refusal: message.refusal ?? null },
  465. finish_reason,
  466. index,
  467. logprobs,
  468. };
  469. }),
  470. created,
  471. model,
  472. object: 'chat.completion',
  473. ...(system_fingerprint ? { system_fingerprint } : {}),
  474. };
  475. return maybeParseChatCompletion(completion, params);
  476. }
  477. function str(x) {
  478. return JSON.stringify(x);
  479. }
  480. /**
  481. * Ensures the given argument is an empty object, useful for
  482. * asserting that all known properties on an object have been
  483. * destructured.
  484. */
  485. function assertIsEmpty(obj) {
  486. return;
  487. }
  488. function assertNever(_x) { }
  489. //# sourceMappingURL=ChatCompletionStream.mjs.map