openai 4.12.1 → 4.12.2

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 (78) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +3 -3
  3. package/_shims/auto/types.d.ts +3 -1
  4. package/_shims/index.d.ts +2 -0
  5. package/_shims/node-runtime.d.ts.map +1 -1
  6. package/_shims/node-runtime.js +2 -0
  7. package/_shims/node-runtime.js.map +1 -1
  8. package/_shims/node-runtime.mjs +2 -0
  9. package/_shims/node-runtime.mjs.map +1 -1
  10. package/_shims/node-types.d.ts +1 -1
  11. package/_shims/registry.d.ts +2 -0
  12. package/_shims/registry.d.ts.map +1 -1
  13. package/_shims/registry.js +3 -1
  14. package/_shims/registry.js.map +1 -1
  15. package/_shims/registry.mjs +2 -0
  16. package/_shims/registry.mjs.map +1 -1
  17. package/_shims/web-runtime.d.ts.map +1 -1
  18. package/_shims/web-runtime.js +8 -0
  19. package/_shims/web-runtime.js.map +1 -1
  20. package/_shims/web-runtime.mjs +8 -0
  21. package/_shims/web-runtime.mjs.map +1 -1
  22. package/_shims/web-types.d.ts +2 -1
  23. package/core.d.ts +1 -1
  24. package/core.d.ts.map +1 -1
  25. package/core.js +28 -14
  26. package/core.js.map +1 -1
  27. package/core.mjs +26 -12
  28. package/core.mjs.map +1 -1
  29. package/error.d.ts.map +1 -1
  30. package/error.js +14 -4
  31. package/error.js.map +1 -1
  32. package/error.mjs +14 -4
  33. package/error.mjs.map +1 -1
  34. package/index.d.mts +8 -5
  35. package/index.d.ts +8 -5
  36. package/index.d.ts.map +1 -1
  37. package/index.js +3 -3
  38. package/index.js.map +1 -1
  39. package/index.mjs +3 -3
  40. package/index.mjs.map +1 -1
  41. package/package.json +3 -2
  42. package/resources/chat/chat.d.ts +3 -0
  43. package/resources/chat/chat.d.ts.map +1 -1
  44. package/resources/chat/chat.js.map +1 -1
  45. package/resources/chat/chat.mjs.map +1 -1
  46. package/resources/chat/completions.d.ts +3 -0
  47. package/resources/chat/completions.d.ts.map +1 -1
  48. package/resources/chat/completions.js.map +1 -1
  49. package/resources/chat/completions.mjs.map +1 -1
  50. package/shims/node.d.ts +1 -1
  51. package/shims/node.d.ts.map +1 -1
  52. package/shims/web.d.ts +1 -1
  53. package/shims/web.d.ts.map +1 -1
  54. package/src/_shims/auto/types.d.ts +3 -1
  55. package/src/_shims/index.d.ts +2 -0
  56. package/src/_shims/node-runtime.ts +2 -0
  57. package/src/_shims/node-types.d.ts +1 -1
  58. package/src/_shims/registry.ts +3 -0
  59. package/src/_shims/web-runtime.ts +12 -0
  60. package/src/_shims/web-types.d.ts +2 -1
  61. package/src/core.ts +29 -10
  62. package/src/error.ts +15 -5
  63. package/src/index.ts +10 -7
  64. package/src/resources/chat/chat.ts +3 -0
  65. package/src/resources/chat/completions.ts +3 -0
  66. package/src/shims/node.ts +1 -1
  67. package/src/shims/web.ts +1 -1
  68. package/src/streaming.ts +162 -44
  69. package/src/version.ts +1 -1
  70. package/streaming.d.ts +8 -6
  71. package/streaming.d.ts.map +1 -1
  72. package/streaming.js +157 -46
  73. package/streaming.js.map +1 -1
  74. package/streaming.mjs +157 -46
  75. package/streaming.mjs.map +1 -1
  76. package/version.d.ts +1 -1
  77. package/version.js +1 -1
  78. package/version.mjs +1 -1
package/shims/node.d.ts CHANGED
@@ -23,7 +23,7 @@ declare module '../_shims/manual-types' {
23
23
  export import Blob = types.Blob;
24
24
  type Readable = types.Readable;
25
25
  type FsReadStream = types.FsReadStream;
26
- type ReadableStream = types.ReadableStream;
26
+ export import ReadableStream = types.ReadableStream;
27
27
  }
28
28
  }
29
29
  //# sourceMappingURL=node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/shims/node.ts"],"names":[],"mappings":";;;AACA,OAAO,KAAK,KAAK,MAAM,sBAAsB,CAAC;AAK9C,OAAO,QAAQ,wBAAwB,CAAC;IACtC,UAAiB,MAAM,CAAC;QAEtB,KAAY,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAEhC,MAAM,QAAQ,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAElC,KAAY,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAEpC,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAEpC,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAEpD,KAAY,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAEpD,KAAY,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,CAAC;QAE5D,MAAM,QAAQ,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAExC,MAAM,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAEhC,MAAM,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAEhC,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;KACnD;CACF"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/shims/node.ts"],"names":[],"mappings":";;;AACA,OAAO,KAAK,KAAK,MAAM,sBAAsB,CAAC;AAK9C,OAAO,QAAQ,wBAAwB,CAAC;IACtC,UAAiB,MAAM,CAAC;QAEtB,KAAY,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAEhC,MAAM,QAAQ,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAElC,KAAY,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAEpC,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAEpC,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAEpD,KAAY,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAEpD,KAAY,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,CAAC;QAE5D,MAAM,QAAQ,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAExC,MAAM,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAEhC,MAAM,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAEhC,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,MAAM,QAAQ,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;KACrD;CACF"}
package/shims/web.d.ts CHANGED
@@ -20,7 +20,7 @@ declare module '../_shims/manual-types' {
20
20
  export import Blob = types.Blob;
21
21
  type Readable = types.Readable;
22
22
  type FsReadStream = types.FsReadStream;
23
- type ReadableStream = types.ReadableStream;
23
+ export import ReadableStream = types.ReadableStream;
24
24
  }
25
25
  }
26
26
  //# sourceMappingURL=web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/shims/web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,qBAAqB,CAAC;AAK7C,OAAO,QAAQ,wBAAwB,CAAC;IACtC,UAAiB,MAAM,CAAC;QAEtB,KAAY,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAEhC,MAAM,QAAQ,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAElC,KAAY,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAEpC,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAEpC,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAEpD,KAAY,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAEpD,KAAY,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,CAAC;QAE5D,MAAM,QAAQ,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAExC,MAAM,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAEhC,MAAM,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAEhC,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;KACnD;CACF"}
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/shims/web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,qBAAqB,CAAC;AAK7C,OAAO,QAAQ,wBAAwB,CAAC;IACtC,UAAiB,MAAM,CAAC;QAEtB,KAAY,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAEhC,MAAM,QAAQ,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAElC,KAAY,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAEpC,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAEpC,KAAY,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAE5C,KAAY,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAEpD,KAAY,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAEpD,KAAY,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,CAAC;QAE5D,MAAM,QAAQ,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAExC,MAAM,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAEhC,MAAM,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAEhC,KAAY,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEtC,KAAY,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAE9C,MAAM,QAAQ,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;KACrD;CACF"}
@@ -96,4 +96,6 @@ export declare class FsReadStream extends Readable {
96
96
 
97
97
  // @ts-ignore
98
98
  type _ReadableStream<R = any> = ReadableStream<R>;
99
- export { type _ReadableStream as ReadableStream };
99
+ // @ts-ignore
100
+ declare const _ReadableStream: typeof ReadableStream;
101
+ export { _ReadableStream as ReadableStream };
@@ -62,6 +62,8 @@ export type Readable = SelectType<manual.Readable, auto.Readable>;
62
62
  export type FsReadStream = SelectType<manual.FsReadStream, auto.FsReadStream>;
63
63
  // @ts-ignore
64
64
  export type ReadableStream = SelectType<manual.ReadableStream, auto.ReadableStream>;
65
+ // @ts-ignore
66
+ export const ReadableStream: SelectType<typeof manual.ReadableStream, typeof auto.ReadableStream>;
65
67
 
66
68
  export function getMultipartRequestOptions<T extends {} = Record<string, unknown>>(
67
69
  form: FormData,
@@ -13,6 +13,7 @@ import { Readable } from 'node:stream';
13
13
  import { type RequestOptions } from '../core';
14
14
  import { MultipartBody } from './MultipartBody';
15
15
  import { type Shims } from './registry';
16
+ import { ReadableStream } from 'web-streams-polyfill';
16
17
 
17
18
  type FileFromPathOptions = Omit<FilePropertyBag, 'lastModified'>;
18
19
 
@@ -71,6 +72,7 @@ export function getRuntime(): Shims {
71
72
  FormData: fd.FormData,
72
73
  Blob: fd.Blob,
73
74
  File: fd.File,
75
+ ReadableStream,
74
76
  getMultipartRequestOptions,
75
77
  getDefaultAgent: (url: string): Agent => (url.startsWith('https') ? defaultHttpsAgent : defaultHttpAgent),
76
78
  fileFromPath,
@@ -7,7 +7,7 @@ import * as fd from 'formdata-node';
7
7
  export { type Agent } from 'node:http';
8
8
  export { type Readable } from 'node:stream';
9
9
  export { type ReadStream as FsReadStream } from 'node:fs';
10
- export { type ReadableStream } from 'web-streams-polyfill';
10
+ export { ReadableStream } from 'web-streams-polyfill';
11
11
 
12
12
  export const fetch: typeof nf.default;
13
13
 
@@ -12,6 +12,7 @@ export interface Shims {
12
12
  FormData: any;
13
13
  Blob: any;
14
14
  File: any;
15
+ ReadableStream: any;
15
16
  getMultipartRequestOptions: <T extends {} = Record<string, unknown>>(
16
17
  form: Shims['FormData'],
17
18
  opts: RequestOptions<T>,
@@ -32,6 +33,7 @@ export let Headers: Shims['Headers'] | undefined = undefined;
32
33
  export let FormData: Shims['FormData'] | undefined = undefined;
33
34
  export let Blob: Shims['Blob'] | undefined = undefined;
34
35
  export let File: Shims['File'] | undefined = undefined;
36
+ export let ReadableStream: Shims['ReadableStream'] | undefined = undefined;
35
37
  export let getMultipartRequestOptions: Shims['getMultipartRequestOptions'] | undefined = undefined;
36
38
  export let getDefaultAgent: Shims['getDefaultAgent'] | undefined = undefined;
37
39
  export let fileFromPath: Shims['fileFromPath'] | undefined = undefined;
@@ -55,6 +57,7 @@ export function setShims(shims: Shims, options: { auto: boolean } = { auto: fals
55
57
  FormData = shims.FormData;
56
58
  Blob = shims.Blob;
57
59
  File = shims.File;
60
+ ReadableStream = shims.ReadableStream;
58
61
  getMultipartRequestOptions = shims.getMultipartRequestOptions;
59
62
  getDefaultAgent = shims.getDefaultAgent;
60
63
  fileFromPath = shims.fileFromPath;
@@ -72,6 +72,18 @@ export function getRuntime({ manuallyImported }: { manuallyImported?: boolean }
72
72
  }
73
73
  }
74
74
  ),
75
+ ReadableStream:
76
+ // @ts-ignore
77
+ typeof ReadableStream !== 'undefined' ? ReadableStream : (
78
+ class ReadableStream {
79
+ // @ts-ignore
80
+ constructor() {
81
+ throw new Error(
82
+ `streaming isn't supported in this environment yet as 'ReadableStream' is undefined. ${recommendation}`,
83
+ );
84
+ }
85
+ }
86
+ ),
75
87
  getMultipartRequestOptions: async <T extends {} = Record<string, unknown>>(
76
88
  // @ts-ignore
77
89
  form: FormData,
@@ -79,4 +79,5 @@ export declare class FsReadStream extends Readable {
79
79
  }
80
80
 
81
81
  type _ReadableStream<R = any> = ReadableStream<R>;
82
- export { type _ReadableStream as ReadableStream };
82
+ declare const _ReadableStream: typeof ReadableStream;
83
+ export { _ReadableStream as ReadableStream };
package/src/core.ts CHANGED
@@ -42,9 +42,11 @@ type APIResponseProps = {
42
42
  async function defaultParseResponse<T>(props: APIResponseProps): Promise<T> {
43
43
  const { response } = props;
44
44
  if (props.options.stream) {
45
+ debug('response', response.status, response.url, response.headers, response.body);
46
+
45
47
  // Note: there is an invariant here that isn't represented in the type system
46
48
  // that if you set `stream: true` the response type must also be `Stream<T>`
47
- return new Stream(response, props.controller) as any;
49
+ return Stream.fromSSEResponse(response, props.controller) as any;
48
50
  }
49
51
 
50
52
  const contentType = response.headers.get('content-type');
@@ -1059,16 +1061,33 @@ export const isHeadersProtocol = (headers: any): headers is HeadersProtocol => {
1059
1061
  return typeof headers?.get === 'function';
1060
1062
  };
1061
1063
 
1062
- export const getHeader = (headers: HeadersLike, key: string): string | null | undefined => {
1063
- const lowerKey = key.toLowerCase();
1064
- if (isHeadersProtocol(headers)) return headers.get(key) || headers.get(lowerKey);
1065
- const value = headers[key] || headers[lowerKey];
1066
- if (Array.isArray(value)) {
1067
- if (value.length <= 1) return value[0];
1068
- console.warn(`Received ${value.length} entries for the ${key} header, using the first entry.`);
1069
- return value[0];
1064
+ export const getRequiredHeader = (headers: HeadersLike, header: string): string => {
1065
+ const lowerCasedHeader = header.toLowerCase();
1066
+ if (isHeadersProtocol(headers)) {
1067
+ // to deal with the case where the header looks like Stainless-Event-Id
1068
+ const intercapsHeader =
1069
+ header[0]?.toUpperCase() +
1070
+ header.substring(1).replace(/([^\w])(\w)/g, (_m, g1, g2) => g1 + g2.toUpperCase());
1071
+ for (const key of [header, lowerCasedHeader, header.toUpperCase(), intercapsHeader]) {
1072
+ const value = headers.get(key);
1073
+ if (value) {
1074
+ return value;
1075
+ }
1076
+ }
1070
1077
  }
1071
- return value;
1078
+
1079
+ for (const [key, value] of Object.entries(headers)) {
1080
+ if (key.toLowerCase() === lowerCasedHeader) {
1081
+ if (Array.isArray(value)) {
1082
+ if (value.length <= 1) return value[0];
1083
+ console.warn(`Received ${value.length} entries for the ${header} header, using the first entry.`);
1084
+ return value[0];
1085
+ }
1086
+ return value;
1087
+ }
1088
+ }
1089
+
1090
+ throw new Error(`Could not find ${header} header`);
1072
1091
  };
1073
1092
 
1074
1093
  /**
package/src/error.ts CHANGED
@@ -19,7 +19,7 @@ export class APIError extends OpenAIError {
19
19
  message: string | undefined,
20
20
  headers: Headers | undefined,
21
21
  ) {
22
- super(`${status} ${APIError.makeMessage(error, message)}`);
22
+ super(`${APIError.makeMessage(status, error, message)}`);
23
23
  this.status = status;
24
24
  this.headers = headers;
25
25
 
@@ -30,14 +30,24 @@ export class APIError extends OpenAIError {
30
30
  this.type = data?.['type'];
31
31
  }
32
32
 
33
- private static makeMessage(error: any, message: string | undefined) {
34
- return (
33
+ private static makeMessage(status: number | undefined, error: any, message: string | undefined) {
34
+ const msg =
35
35
  error?.message ?
36
36
  typeof error.message === 'string' ? error.message
37
37
  : JSON.stringify(error.message)
38
38
  : error ? JSON.stringify(error)
39
- : message || 'status code (no body)'
40
- );
39
+ : message;
40
+
41
+ if (status && msg) {
42
+ return `${status} ${msg}`;
43
+ }
44
+ if (status) {
45
+ return `${status} status code (no body)`;
46
+ }
47
+ if (msg) {
48
+ return msg;
49
+ }
50
+ return '(no status code or body)';
41
51
  }
42
52
 
43
53
  static generate(
package/src/index.ts CHANGED
@@ -9,10 +9,15 @@ import * as API from "./resources/index";
9
9
 
10
10
  export interface ClientOptions {
11
11
  /**
12
- * Defaults to process.env["OPENAI_API_KEY"].
12
+ * Defaults to process.env['OPENAI_API_KEY'].
13
13
  */
14
14
  apiKey?: string;
15
15
 
16
+ /**
17
+ * Defaults to process.env['OPENAI_ORG_ID'].
18
+ */
19
+ organization?: string | null;
20
+
16
21
  /**
17
22
  * Override the default base URL for the API, e.g., "https://api.example.com/v2/"
18
23
  */
@@ -72,21 +77,20 @@ export interface ClientOptions {
72
77
  * Only set this option to `true` if you understand the risks and have appropriate mitigations in place.
73
78
  */
74
79
  dangerouslyAllowBrowser?: boolean;
75
-
76
- organization?: string | null;
77
80
  }
78
81
 
79
82
  /** API Client for interfacing with the OpenAI API. */
80
83
  export class OpenAI extends Core.APIClient {
81
84
  apiKey: string;
82
- organization?: string | null;
85
+ organization: string | null;
83
86
 
84
87
  private _options: ClientOptions;
85
88
 
86
89
  /**
87
90
  * API Client for interfacing with the OpenAI API.
88
91
  *
89
- * @param {string} [opts.apiKey=process.env['OPENAI_API_KEY']] - The API Key to send to the API.
92
+ * @param {string} [opts.apiKey==process.env['OPENAI_API_KEY'] ?? undefined]
93
+ * @param {string | null} [opts.organization==process.env['OPENAI_ORG_ID'] ?? null]
90
94
  * @param {string} [opts.baseURL] - Override the default base URL for the API.
91
95
  * @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
92
96
  * @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections.
@@ -95,7 +99,6 @@ export class OpenAI extends Core.APIClient {
95
99
  * @param {Core.Headers} opts.defaultHeaders - Default headers to include with every request to the API.
96
100
  * @param {Core.DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API.
97
101
  * @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
98
- * @param {string | null} [opts.organization]
99
102
  */
100
103
  constructor({
101
104
  apiKey = Core.readEnv('OPENAI_API_KEY'),
@@ -104,7 +107,7 @@ export class OpenAI extends Core.APIClient {
104
107
  }: ClientOptions = {}) {
105
108
  if (apiKey === undefined) {
106
109
  throw new Errors.OpenAIError(
107
- "The OPENAI_API_KEY environment variable is missing or empty; either provide it, or instantiate the OpenAI client with an apiKey option, like new OpenAI({ apiKey: 'my apiKey' }).",
110
+ "The OPENAI_API_KEY environment variable is missing or empty; either provide it, or instantiate the OpenAI client with an apiKey option, like new OpenAI({ apiKey: 'My API Key' }).",
108
111
  );
109
112
  }
110
113
 
@@ -14,6 +14,9 @@ export namespace Chat {
14
14
  export import ChatCompletionMessage = CompletionsAPI.ChatCompletionMessage;
15
15
  export import ChatCompletionMessageParam = CompletionsAPI.ChatCompletionMessageParam;
16
16
  export import ChatCompletionRole = CompletionsAPI.ChatCompletionRole;
17
+ /**
18
+ * @deprecated ChatCompletionMessageParam should be used instead
19
+ */
17
20
  export import CreateChatCompletionRequestMessage = CompletionsAPI.CreateChatCompletionRequestMessage;
18
21
  export import ChatCompletionCreateParams = CompletionsAPI.ChatCompletionCreateParams;
19
22
  export import CompletionCreateParams = CompletionsAPI.CompletionCreateParams;
@@ -509,6 +509,9 @@ export namespace Completions {
509
509
  export import ChatCompletionMessage = ChatCompletionsAPI.ChatCompletionMessage;
510
510
  export import ChatCompletionMessageParam = ChatCompletionsAPI.ChatCompletionMessageParam;
511
511
  export import ChatCompletionRole = ChatCompletionsAPI.ChatCompletionRole;
512
+ /**
513
+ * @deprecated ChatCompletionMessageParam should be used instead
514
+ */
512
515
  export import CreateChatCompletionRequestMessage = ChatCompletionsAPI.CreateChatCompletionRequestMessage;
513
516
  export import ChatCompletionCreateParams = ChatCompletionsAPI.ChatCompletionCreateParams;
514
517
  export import CompletionCreateParams = ChatCompletionsAPI.CompletionCreateParams;
package/src/shims/node.ts CHANGED
@@ -45,6 +45,6 @@ declare module '../_shims/manual-types' {
45
45
  // @ts-ignore
46
46
  export type FsReadStream = types.FsReadStream;
47
47
  // @ts-ignore
48
- export type ReadableStream = types.ReadableStream;
48
+ export import ReadableStream = types.ReadableStream;
49
49
  }
50
50
  }
package/src/shims/web.ts CHANGED
@@ -45,6 +45,6 @@ declare module '../_shims/manual-types' {
45
45
  // @ts-ignore
46
46
  export type FsReadStream = types.FsReadStream;
47
47
  // @ts-ignore
48
- export type ReadableStream = types.ReadableStream;
48
+ export import ReadableStream = types.ReadableStream;
49
49
  }
50
50
  }
package/src/streaming.ts CHANGED
@@ -1,6 +1,8 @@
1
- import { type Response } from './_shims/index';
1
+ import { ReadableStream, type Response } from './_shims/index';
2
2
  import { OpenAIError } from './error';
3
3
 
4
+ import { APIError } from "./error";
5
+
4
6
  type Bytes = string | ArrayBuffer | Uint8Array | Buffer | null | undefined;
5
7
 
6
8
  type ServerSentEvent = {
@@ -12,67 +14,183 @@ type ServerSentEvent = {
12
14
  export class Stream<Item> implements AsyncIterable<Item> {
13
15
  controller: AbortController;
14
16
 
15
- private response: Response;
16
- private decoder: SSEDecoder;
17
-
18
- constructor(response: Response, controller: AbortController) {
19
- this.response = response;
17
+ constructor(private iterator: () => AsyncIterator<Item>, controller: AbortController) {
20
18
  this.controller = controller;
21
- this.decoder = new SSEDecoder();
22
19
  }
23
20
 
24
- private async *iterMessages(): AsyncGenerator<ServerSentEvent, void, unknown> {
25
- if (!this.response.body) {
26
- this.controller.abort();
27
- throw new OpenAIError(`Attempted to iterate over a response with no body`);
28
- }
21
+ static fromSSEResponse<Item>(response: Response, controller: AbortController) {
22
+ let consumed = false;
23
+ const decoder = new SSEDecoder();
29
24
 
30
- const lineDecoder = new LineDecoder();
25
+ async function* iterMessages(): AsyncGenerator<ServerSentEvent, void, unknown> {
26
+ if (!response.body) {
27
+ controller.abort();
28
+ throw new OpenAIError(`Attempted to iterate over a response with no body`);
29
+ }
30
+
31
+ const lineDecoder = new LineDecoder();
31
32
 
32
- const iter = readableStreamAsyncIterable<Bytes>(this.response.body);
33
- for await (const chunk of iter) {
34
- for (const line of lineDecoder.decode(chunk)) {
35
- const sse = this.decoder.decode(line);
33
+ const iter = readableStreamAsyncIterable<Bytes>(response.body);
34
+ for await (const chunk of iter) {
35
+ for (const line of lineDecoder.decode(chunk)) {
36
+ const sse = decoder.decode(line);
37
+ if (sse) yield sse;
38
+ }
39
+ }
40
+
41
+ for (const line of lineDecoder.flush()) {
42
+ const sse = decoder.decode(line);
36
43
  if (sse) yield sse;
37
44
  }
38
45
  }
39
46
 
40
- for (const line of lineDecoder.flush()) {
41
- const sse = this.decoder.decode(line);
42
- if (sse) yield sse;
47
+ async function* iterator(): AsyncIterator<Item, any, undefined> {
48
+ if (consumed) {
49
+ throw new Error('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');
50
+ }
51
+ consumed = true;
52
+ let done = false;
53
+ try {
54
+ for await (const sse of iterMessages()) {
55
+ if (done) continue;
56
+
57
+ if (sse.data.startsWith('[DONE]')) {
58
+ done = true;
59
+ continue;
60
+ }
61
+
62
+ if (sse.event === null) {
63
+ let data;
64
+
65
+ try {
66
+ data = JSON.parse(sse.data);
67
+ } catch (e) {
68
+ console.error(`Could not parse message into JSON:`, sse.data);
69
+ console.error(`From chunk:`, sse.raw);
70
+ throw e;
71
+ }
72
+
73
+ if (data && data.error) {
74
+ throw new APIError(undefined, data.error, undefined, undefined);
75
+ }
76
+
77
+ yield data;
78
+ }
79
+ }
80
+ done = true;
81
+ } catch (e) {
82
+ // If the user calls `stream.controller.abort()`, we should exit without throwing.
83
+ if (e instanceof Error && e.name === 'AbortError') return;
84
+ throw e;
85
+ } finally {
86
+ // If the user `break`s, abort the ongoing request.
87
+ if (!done) controller.abort();
88
+ }
43
89
  }
90
+
91
+ return new Stream(iterator, controller);
44
92
  }
45
93
 
46
- async *[Symbol.asyncIterator](): AsyncIterator<Item, any, undefined> {
47
- let done = false;
48
- try {
49
- for await (const sse of this.iterMessages()) {
50
- if (done) continue;
94
+ // Generates a Stream from a newline-separated ReadableStream where each item
95
+ // is a JSON Value.
96
+ static fromReadableStream<Item>(readableStream: ReadableStream, controller: AbortController) {
97
+ let consumed = false;
51
98
 
52
- if (sse.data.startsWith('[DONE]')) {
53
- done = true;
54
- continue;
99
+ async function* iterLines(): AsyncGenerator<string, void, unknown> {
100
+ const lineDecoder = new LineDecoder();
101
+
102
+ const iter = readableStreamAsyncIterable<Bytes>(readableStream);
103
+ for await (const chunk of iter) {
104
+ for (const line of lineDecoder.decode(chunk)) {
105
+ yield line;
55
106
  }
107
+ }
56
108
 
57
- if (sse.event === null) {
58
- try {
59
- yield JSON.parse(sse.data);
60
- } catch (e) {
61
- console.error(`Could not parse message into JSON:`, sse.data);
62
- console.error(`From chunk:`, sse.raw);
63
- throw e;
64
- }
109
+ for (const line of lineDecoder.flush()) {
110
+ yield line;
111
+ }
112
+ }
113
+
114
+ async function* iterator(): AsyncIterator<Item, any, undefined> {
115
+ if (consumed) {
116
+ throw new Error('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');
117
+ }
118
+ consumed = true;
119
+ let done = false;
120
+ try {
121
+ for await (const line of iterLines()) {
122
+ if (done) continue;
123
+ if (line) yield JSON.parse(line);
65
124
  }
125
+ done = true;
126
+ } catch (e) {
127
+ // If the user calls `stream.controller.abort()`, we should exit without throwing.
128
+ if (e instanceof Error && e.name === 'AbortError') return;
129
+ throw e;
130
+ } finally {
131
+ // If the user `break`s, abort the ongoing request.
132
+ if (!done) controller.abort();
66
133
  }
67
- done = true;
68
- } catch (e) {
69
- // If the user calls `stream.controller.abort()`, we should exit without throwing.
70
- if (e instanceof Error && e.name === 'AbortError') return;
71
- throw e;
72
- } finally {
73
- // If the user `break`s, abort the ongoing request.
74
- if (!done) this.controller.abort();
75
134
  }
135
+
136
+ return new Stream(iterator, controller);
137
+ }
138
+
139
+ [Symbol.asyncIterator](): AsyncIterator<Item> {
140
+ return this.iterator();
141
+ }
142
+
143
+ tee(): [Stream<Item>, Stream<Item>] {
144
+ const left: Array<Promise<IteratorResult<Item>>> = [];
145
+ const right: Array<Promise<IteratorResult<Item>>> = [];
146
+ const iterator = this.iterator();
147
+
148
+ const teeIterator = (queue: Array<Promise<IteratorResult<Item>>>): AsyncIterator<Item> => {
149
+ return {
150
+ next: () => {
151
+ if (queue.length === 0) {
152
+ const result = iterator.next();
153
+ left.push(result);
154
+ right.push(result);
155
+ }
156
+ return queue.shift()!;
157
+ },
158
+ };
159
+ };
160
+
161
+ return [
162
+ new Stream(() => teeIterator(left), this.controller),
163
+ new Stream(() => teeIterator(right), this.controller),
164
+ ];
165
+ }
166
+
167
+ // Converts this stream to a newline-separated ReadableStream of JSON Stringified values in the stream
168
+ // which can be turned back into a Stream with Stream.fromReadableStream.
169
+ toReadableStream(): ReadableStream {
170
+ const self = this;
171
+ let iter: AsyncIterator<Item>;
172
+ const encoder = new TextEncoder();
173
+
174
+ return new ReadableStream({
175
+ async start() {
176
+ iter = self[Symbol.asyncIterator]();
177
+ },
178
+ async pull(ctrl) {
179
+ try {
180
+ const { value, done } = await iter.next();
181
+ if (done) return ctrl.close();
182
+
183
+ const bytes = encoder.encode(JSON.stringify(value) + '\n');
184
+
185
+ ctrl.enqueue(bytes);
186
+ } catch (err) {
187
+ ctrl.error(err);
188
+ }
189
+ },
190
+ async cancel() {
191
+ await iter.return?.();
192
+ },
193
+ });
76
194
  }
77
195
  }
78
196
 
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '4.12.1'; // x-release-please-version
1
+ export const VERSION = '4.12.2'; // x-release-please-version
package/streaming.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
 
2
- import { type Response } from "./_shims/index.js";
2
+ import { ReadableStream, type Response } from "./_shims/index.js";
3
3
  export declare class Stream<Item> implements AsyncIterable<Item> {
4
+ private iterator;
4
5
  controller: AbortController;
5
- private response;
6
- private decoder;
7
- constructor(response: Response, controller: AbortController);
8
- private iterMessages;
9
- [Symbol.asyncIterator](): AsyncIterator<Item, any, undefined>;
6
+ constructor(iterator: () => AsyncIterator<Item>, controller: AbortController);
7
+ static fromSSEResponse<Item>(response: Response, controller: AbortController): Stream<Item>;
8
+ static fromReadableStream<Item>(readableStream: ReadableStream, controller: AbortController): Stream<Item>;
9
+ [Symbol.asyncIterator](): AsyncIterator<Item>;
10
+ tee(): [Stream<Item>, Stream<Item>];
11
+ toReadableStream(): ReadableStream;
10
12
  }
11
13
  //# sourceMappingURL=streaming.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["src/streaming.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAW/C,qBAAa,MAAM,CAAC,IAAI,CAAE,YAAW,aAAa,CAAC,IAAI,CAAC;IACtD,UAAU,EAAE,eAAe,CAAC;IAE5B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,OAAO,CAAa;gBAEhB,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe;YAM5C,YAAY;IAsBpB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC;CA+BrE"}
1
+ {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["src/streaming.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAa/D,qBAAa,MAAM,CAAC,IAAI,CAAE,YAAW,aAAa,CAAC,IAAI,CAAC;IAG1C,OAAO,CAAC,QAAQ;IAF5B,UAAU,EAAE,eAAe,CAAC;gBAER,QAAQ,EAAE,MAAM,aAAa,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,eAAe;IAIpF,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe;IA2E5E,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe;IA2C3F,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC;IAI7C,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IA0BnC,gBAAgB,IAAI,cAAc;CA0BnC"}