ResponseStream.mjs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
  2. if (kind === "m") throw new TypeError("Private method is not writable");
  3. if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
  4. if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
  5. return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
  6. };
  7. var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
  8. if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
  9. if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
  10. return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
  11. };
  12. var _ResponseStream_instances, _ResponseStream_params, _ResponseStream_currentResponseSnapshot, _ResponseStream_finalResponse, _ResponseStream_beginRequest, _ResponseStream_addEvent, _ResponseStream_endRequest, _ResponseStream_accumulateResponse;
  13. import { APIUserAbortError, OpenAIError } from "../../error.mjs";
  14. import { EventStream } from "../EventStream.mjs";
  15. import { maybeParseResponse } from "../ResponsesParser.mjs";
  16. export class ResponseStream extends EventStream {
  17. constructor(params) {
  18. super();
  19. _ResponseStream_instances.add(this);
  20. _ResponseStream_params.set(this, void 0);
  21. _ResponseStream_currentResponseSnapshot.set(this, void 0);
  22. _ResponseStream_finalResponse.set(this, void 0);
  23. __classPrivateFieldSet(this, _ResponseStream_params, params, "f");
  24. }
  25. static createResponse(client, params, options) {
  26. const runner = new ResponseStream(params);
  27. runner._run(() => runner._createOrRetrieveResponse(client, params, {
  28. ...options,
  29. headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' },
  30. }));
  31. return runner;
  32. }
  33. async _createOrRetrieveResponse(client, params, options) {
  34. const signal = options?.signal;
  35. if (signal) {
  36. if (signal.aborted)
  37. this.controller.abort();
  38. signal.addEventListener('abort', () => this.controller.abort());
  39. }
  40. __classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_beginRequest).call(this);
  41. let stream;
  42. let starting_after = null;
  43. if ('response_id' in params) {
  44. stream = await client.responses.retrieve(params.response_id, { stream: true }, { ...options, signal: this.controller.signal, stream: true });
  45. starting_after = params.starting_after ?? null;
  46. }
  47. else {
  48. stream = await client.responses.create({ ...params, stream: true }, { ...options, signal: this.controller.signal });
  49. }
  50. this._connected();
  51. for await (const event of stream) {
  52. __classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_addEvent).call(this, event, starting_after);
  53. }
  54. if (stream.controller.signal?.aborted) {
  55. throw new APIUserAbortError();
  56. }
  57. return __classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_endRequest).call(this);
  58. }
  59. [(_ResponseStream_params = new WeakMap(), _ResponseStream_currentResponseSnapshot = new WeakMap(), _ResponseStream_finalResponse = new WeakMap(), _ResponseStream_instances = new WeakSet(), _ResponseStream_beginRequest = function _ResponseStream_beginRequest() {
  60. if (this.ended)
  61. return;
  62. __classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, undefined, "f");
  63. }, _ResponseStream_addEvent = function _ResponseStream_addEvent(event, starting_after) {
  64. if (this.ended)
  65. return;
  66. const maybeEmit = (name, event) => {
  67. if (starting_after == null || event.sequence_number > starting_after) {
  68. this._emit(name, event);
  69. }
  70. };
  71. const response = __classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_accumulateResponse).call(this, event);
  72. maybeEmit('event', event);
  73. switch (event.type) {
  74. case 'response.output_text.delta': {
  75. const output = response.output[event.output_index];
  76. if (!output) {
  77. throw new OpenAIError(`missing output at index ${event.output_index}`);
  78. }
  79. if (output.type === 'message') {
  80. const content = output.content[event.content_index];
  81. if (!content) {
  82. throw new OpenAIError(`missing content at index ${event.content_index}`);
  83. }
  84. if (content.type !== 'output_text') {
  85. throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
  86. }
  87. maybeEmit('response.output_text.delta', {
  88. ...event,
  89. snapshot: content.text,
  90. });
  91. }
  92. break;
  93. }
  94. case 'response.function_call_arguments.delta': {
  95. const output = response.output[event.output_index];
  96. if (!output) {
  97. throw new OpenAIError(`missing output at index ${event.output_index}`);
  98. }
  99. if (output.type === 'function_call') {
  100. maybeEmit('response.function_call_arguments.delta', {
  101. ...event,
  102. snapshot: output.arguments,
  103. });
  104. }
  105. break;
  106. }
  107. default:
  108. maybeEmit(event.type, event);
  109. break;
  110. }
  111. }, _ResponseStream_endRequest = function _ResponseStream_endRequest() {
  112. if (this.ended) {
  113. throw new OpenAIError(`stream has ended, this shouldn't happen`);
  114. }
  115. const snapshot = __classPrivateFieldGet(this, _ResponseStream_currentResponseSnapshot, "f");
  116. if (!snapshot) {
  117. throw new OpenAIError(`request ended without sending any events`);
  118. }
  119. __classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, undefined, "f");
  120. const parsedResponse = finalizeResponse(snapshot, __classPrivateFieldGet(this, _ResponseStream_params, "f"));
  121. __classPrivateFieldSet(this, _ResponseStream_finalResponse, parsedResponse, "f");
  122. return parsedResponse;
  123. }, _ResponseStream_accumulateResponse = function _ResponseStream_accumulateResponse(event) {
  124. let snapshot = __classPrivateFieldGet(this, _ResponseStream_currentResponseSnapshot, "f");
  125. if (!snapshot) {
  126. if (event.type !== 'response.created') {
  127. throw new OpenAIError(`When snapshot hasn't been set yet, expected 'response.created' event, got ${event.type}`);
  128. }
  129. snapshot = __classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, event.response, "f");
  130. return snapshot;
  131. }
  132. switch (event.type) {
  133. case 'response.output_item.added': {
  134. snapshot.output.push(event.item);
  135. break;
  136. }
  137. case 'response.content_part.added': {
  138. const output = snapshot.output[event.output_index];
  139. if (!output) {
  140. throw new OpenAIError(`missing output at index ${event.output_index}`);
  141. }
  142. if (output.type === 'message') {
  143. output.content.push(event.part);
  144. }
  145. break;
  146. }
  147. case 'response.output_text.delta': {
  148. const output = snapshot.output[event.output_index];
  149. if (!output) {
  150. throw new OpenAIError(`missing output at index ${event.output_index}`);
  151. }
  152. if (output.type === 'message') {
  153. const content = output.content[event.content_index];
  154. if (!content) {
  155. throw new OpenAIError(`missing content at index ${event.content_index}`);
  156. }
  157. if (content.type !== 'output_text') {
  158. throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
  159. }
  160. content.text += event.delta;
  161. }
  162. break;
  163. }
  164. case 'response.function_call_arguments.delta': {
  165. const output = snapshot.output[event.output_index];
  166. if (!output) {
  167. throw new OpenAIError(`missing output at index ${event.output_index}`);
  168. }
  169. if (output.type === 'function_call') {
  170. output.arguments += event.delta;
  171. }
  172. break;
  173. }
  174. case 'response.completed': {
  175. __classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, event.response, "f");
  176. break;
  177. }
  178. }
  179. return snapshot;
  180. }, Symbol.asyncIterator)]() {
  181. const pushQueue = [];
  182. const readQueue = [];
  183. let done = false;
  184. this.on('event', (event) => {
  185. const reader = readQueue.shift();
  186. if (reader) {
  187. reader.resolve(event);
  188. }
  189. else {
  190. pushQueue.push(event);
  191. }
  192. });
  193. this.on('end', () => {
  194. done = true;
  195. for (const reader of readQueue) {
  196. reader.resolve(undefined);
  197. }
  198. readQueue.length = 0;
  199. });
  200. this.on('abort', (err) => {
  201. done = true;
  202. for (const reader of readQueue) {
  203. reader.reject(err);
  204. }
  205. readQueue.length = 0;
  206. });
  207. this.on('error', (err) => {
  208. done = true;
  209. for (const reader of readQueue) {
  210. reader.reject(err);
  211. }
  212. readQueue.length = 0;
  213. });
  214. return {
  215. next: async () => {
  216. if (!pushQueue.length) {
  217. if (done) {
  218. return { value: undefined, done: true };
  219. }
  220. return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((event) => (event ? { value: event, done: false } : { value: undefined, done: true }));
  221. }
  222. const event = pushQueue.shift();
  223. return { value: event, done: false };
  224. },
  225. return: async () => {
  226. this.abort();
  227. return { value: undefined, done: true };
  228. },
  229. };
  230. }
  231. /**
  232. * @returns a promise that resolves with the final Response, or rejects
  233. * if an error occurred or the stream ended prematurely without producing a REsponse.
  234. */
  235. async finalResponse() {
  236. await this.done();
  237. const response = __classPrivateFieldGet(this, _ResponseStream_finalResponse, "f");
  238. if (!response)
  239. throw new OpenAIError('stream ended without producing a ChatCompletion');
  240. return response;
  241. }
  242. }
  243. function finalizeResponse(snapshot, params) {
  244. return maybeParseResponse(snapshot, params);
  245. }
  246. //# sourceMappingURL=ResponseStream.mjs.map