|
| 1 | +# Migration guide |
| 2 | + |
| 3 | +This guide outlines the changes and steps needed to migrate your codebase to the latest version of the OpenAI TypeScript and JavaScript SDK. |
| 4 | + |
| 5 | +The main changes are that the SDK now relies on the [builtin Web fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) instead of `node-fetch` and has zero dependencies. |
| 6 | + |
| 7 | +## Environment requirements |
| 8 | + |
| 9 | +The minimum supported runtime and tooling versions are now: |
| 10 | + |
| 11 | +- Node.js 18.x last LTS (Required for built-in fetch support) |
| 12 | + - This was previously documented as the minimum supported Node.js version but Node.js 16.x mostly worked at runtime; now it will not. |
| 13 | +- TypeScript 4.9 |
| 14 | +- Jest 28 |
| 15 | + |
| 16 | +## Minimum types requirements |
| 17 | + |
| 18 | +### DOM |
| 19 | + |
| 20 | +`tsconfig.json` |
| 21 | + |
| 22 | +```jsonc |
| 23 | +{ |
| 24 | + "target": "ES2015", // note: we recommend ES2020 or higher |
| 25 | + "lib": ["DOM", "DOM.Iterable", "ES2018"] |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +### Node.js |
| 30 | + |
| 31 | +`tsconfig.json` |
| 32 | + |
| 33 | +```jsonc |
| 34 | +{ |
| 35 | + "target": "ES2015" // note: we recommend ES2020 or higher |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +`package.json` |
| 40 | + |
| 41 | +```json |
| 42 | +{ |
| 43 | + "devDependencies": { |
| 44 | + "@types/node": ">= 18.18.7" |
| 45 | + } |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +### Cloudflare Workers |
| 50 | + |
| 51 | +`tsconfig.json` |
| 52 | + |
| 53 | +```jsonc |
| 54 | +{ |
| 55 | + "target": "ES2015", // note: we recommend ES2020 or higher |
| 56 | + "lib": ["ES2020"], // <- needed by @cloudflare/workers-types |
| 57 | + "types": ["@cloudflare/workers-types"] |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +`package.json` |
| 62 | + |
| 63 | +```json |
| 64 | +{ |
| 65 | + "devDependencies": { |
| 66 | + "@cloudflare/workers-types": ">= 0.20221111.0" |
| 67 | + } |
| 68 | +} |
| 69 | +``` |
| 70 | + |
| 71 | +### Bun |
| 72 | + |
| 73 | +`tsconfig.json` |
| 74 | + |
| 75 | +```jsonc |
| 76 | +{ |
| 77 | + "target": "ES2015" // note: we recommend ES2020 or higher |
| 78 | +} |
| 79 | +``` |
| 80 | + |
| 81 | +`package.json` |
| 82 | + |
| 83 | +```json |
| 84 | +{ |
| 85 | + "devDependencies": { |
| 86 | + "@types/bun": ">= 1.2.0" |
| 87 | + } |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +### Deno |
| 92 | + |
| 93 | +No config needed! |
| 94 | + |
| 95 | +## Breaking changes |
| 96 | + |
| 97 | +### Named path parameters |
| 98 | + |
| 99 | +Methods that take multiple path parameters typically now use named instead of positional arguments for better clarity and to prevent a footgun where it was easy to accidentally pass arguments in the incorrect order. |
| 100 | + |
| 101 | +For example, for a method that would call an endpoint at `/v1/parents/{parent_id}/children/{child_id}`, only the _last_ path parameter is positional and the rest must be passed as named arguments. |
| 102 | + |
| 103 | +```ts |
| 104 | +// Before |
| 105 | +client.parents.children.create('p_123', 'c_456'); |
| 106 | + |
| 107 | +// After |
| 108 | +client.example.create('c_456', { parent_id: 'p_123' }); |
| 109 | +``` |
| 110 | + |
| 111 | +This affects the following methods: |
| 112 | + |
| 113 | +- `client.beta.vectorStores.files.retrieve()` |
| 114 | +- `client.beta.vectorStores.files.delete()` |
| 115 | +- `client.beta.vectorStores.fileBatches.retrieve()` |
| 116 | +- `client.beta.vectorStores.fileBatches.cancel()` |
| 117 | +- `client.beta.vectorStores.fileBatches.listFiles()` |
| 118 | +- `client.beta.threads.runs.retrieve()` |
| 119 | +- `client.beta.threads.runs.update()` |
| 120 | +- `client.beta.threads.runs.cancel()` |
| 121 | +- `client.beta.threads.runs.submitToolOutputs()` |
| 122 | +- `client.beta.threads.runs.steps.retrieve()` |
| 123 | +- `client.beta.threads.runs.steps.list()` |
| 124 | +- `client.beta.threads.messages.retrieve()` |
| 125 | +- `client.beta.threads.messages.update()` |
| 126 | +- `client.beta.threads.messages.delete()` |
| 127 | + |
| 128 | +### URI encoded path parameters |
| 129 | + |
| 130 | +Path params are now properly encoded by default. If you were manually encoding path parameters before giving them to the SDK, you must now stop doing that and pass the |
| 131 | +param without any encoding applied. |
| 132 | + |
| 133 | +For example: |
| 134 | + |
| 135 | +```diff |
| 136 | +- client.example.retrieve(encodeURIComponent('string/with/slash')) |
| 137 | ++ client.example.retrieve('string/with/slash') // renders example/string%2Fwith%2Fslash |
| 138 | +``` |
| 139 | + |
| 140 | +Previously without the `encodeURIComponent()` call we would have used the path `/example/string/with/slash`; now we'll use `/example/string%2Fwith%2Fslash`. |
| 141 | + |
| 142 | +### Removed `httpAgent` in favor of `fetchOptions` |
| 143 | + |
| 144 | +The `httpAgent` client option has been removed in favor of a [platform-specific `fetchOptions` property](https://github.com/stainless-sdks/openai-typescript#fetch-options). |
| 145 | +This change was made as `httpAgent` relied on `node:http` agents which are not supported by any runtime's builtin fetch implementation. |
| 146 | + |
| 147 | +If you were using `httpAgent` for proxy support, check out the [new proxy documentation](https://github.com/stainless-sdks/openai-typescript#configuring-proxies). |
| 148 | + |
| 149 | +Before: |
| 150 | + |
| 151 | +```ts |
| 152 | +import OpenAI from 'openai'; |
| 153 | +import http from 'http'; |
| 154 | +import { HttpsProxyAgent } from 'https-proxy-agent'; |
| 155 | + |
| 156 | +// Configure the default for all requests: |
| 157 | +const client = new OpenAI({ |
| 158 | + httpAgent: new HttpsProxyAgent(process.env.PROXY_URL), |
| 159 | +}); |
| 160 | +``` |
| 161 | + |
| 162 | +After: |
| 163 | + |
| 164 | +```ts |
| 165 | +import OpenAI from 'openai'; |
| 166 | +import * as undici from 'undici'; |
| 167 | + |
| 168 | +const proxyAgent = new undici.ProxyAgent(process.env.PROXY_URL); |
| 169 | +const client = new OpenAI({ |
| 170 | + fetchOptions: { |
| 171 | + dispatcher: proxyAgent, |
| 172 | + }, |
| 173 | +}); |
| 174 | +``` |
| 175 | + |
| 176 | +### HTTP method naming |
| 177 | + |
| 178 | +Some methods could not be named intuitively due to an internal naming conflict. This has been resolved and the methods are now correctly named. |
| 179 | + |
| 180 | +```ts |
| 181 | +// Before |
| 182 | +client.chat.completions.del(); |
| 183 | +client.files.del(); |
| 184 | +client.models.del(); |
| 185 | +client.beta.vectorStores.del(); |
| 186 | +client.beta.vectorStores.files.del(); |
| 187 | +client.beta.assistants.del(); |
| 188 | +client.beta.threads.del(); |
| 189 | +client.beta.threads.messages.del(); |
| 190 | + |
| 191 | +// After |
| 192 | +client.chat.completions.delete(); |
| 193 | +client.files.delete(); |
| 194 | +client.models.delete(); |
| 195 | +client.beta.vectorStores.delete(); |
| 196 | +client.beta.vectorStores.files.delete(); |
| 197 | +client.beta.assistants.delete(); |
| 198 | +client.beta.threads.delete(); |
| 199 | +client.beta.threads.messages.delete(); |
| 200 | +``` |
| 201 | + |
| 202 | +### Removed request options overloads |
| 203 | + |
| 204 | +When making requests with no required body, query or header parameters, you must now explicitly pass `null`, `undefined` or an empty object `{}` to the params argument in order to customise request options. |
| 205 | + |
| 206 | +```diff |
| 207 | +client.example.list(); |
| 208 | +client.example.list({}, { headers: { ... } }); |
| 209 | +client.example.list(null, { headers: { ... } }); |
| 210 | +client.example.list(undefined, { headers: { ... } }); |
| 211 | +- client.example.list({ headers: { ... } }); |
| 212 | ++ client.example.list({}, { headers: { ... } }); |
| 213 | +``` |
| 214 | + |
| 215 | +This affects the following methods: |
| 216 | + |
| 217 | +- `client.chat.completions.list()` |
| 218 | +- `client.chat.completions.messages.list()` |
| 219 | +- `client.files.list()` |
| 220 | +- `client.fineTuning.jobs.list()` |
| 221 | +- `client.fineTuning.jobs.listEvents()` |
| 222 | +- `client.fineTuning.jobs.checkpoints.list()` |
| 223 | +- `client.beta.vectorStores.list()` |
| 224 | +- `client.beta.vectorStores.files.list()` |
| 225 | +- `client.beta.assistants.list()` |
| 226 | +- `client.beta.threads.create()` |
| 227 | +- `client.beta.threads.runs.list()` |
| 228 | +- `client.beta.threads.messages.list()` |
| 229 | +- `client.batches.list()` |
| 230 | + |
| 231 | +### Pagination changes |
| 232 | + |
| 233 | +Note that the `for await` syntax is _not_ affected. This still works as-is: |
| 234 | + |
| 235 | +```ts |
| 236 | +// Automatically fetches more pages as needed. |
| 237 | +for await (const fineTuningJob of client.fineTuning.jobs.list()) { |
| 238 | + console.log(fineTuningJob); |
| 239 | +} |
| 240 | +``` |
| 241 | + |
| 242 | +#### Simplified interface |
| 243 | + |
| 244 | +The pagination interface has been simplified: |
| 245 | + |
| 246 | +```ts |
| 247 | +// Before |
| 248 | +page.nextPageParams(); |
| 249 | +page.nextPageInfo(); |
| 250 | +// Required manually handling { url } | { params } type |
| 251 | + |
| 252 | +// After |
| 253 | +page.nextPageRequestOptions(); |
| 254 | +``` |
| 255 | + |
| 256 | +#### Removed unnecessary classes |
| 257 | + |
| 258 | +Page classes for individual methods are now type aliases: |
| 259 | + |
| 260 | +```ts |
| 261 | +// Before |
| 262 | +export class FineTuningJobsPage extends CursorPage<FineTuningJob> {} |
| 263 | + |
| 264 | +// After |
| 265 | +export type FineTuningJobsPage = CursorPage<FineTuningJob>; |
| 266 | +``` |
| 267 | + |
| 268 | +If you were importing these classes at runtime, you'll need to switch to importing the base class or only import them at the type-level. |
| 269 | + |
| 270 | +### File handling |
| 271 | + |
| 272 | +The deprecated `fileFromPath` helper has been removed in favor of native Node.js streams: |
| 273 | + |
| 274 | +```ts |
| 275 | +// Before |
| 276 | +OpenAI.fileFromPath('path/to/file'); |
| 277 | + |
| 278 | +// After |
| 279 | +import fs from 'fs'; |
| 280 | +fs.createReadStream('path/to/file'); |
| 281 | +``` |
| 282 | + |
| 283 | +Note that this function previously only worked on Node.j. If you're using Bun, you can use [`Bun.file`](https://bun.sh/docs/api/file-io) instead. |
| 284 | + |
| 285 | +### Shims removal |
| 286 | + |
| 287 | +Previously you could configure the types that the SDK used like this: |
| 288 | + |
| 289 | +```ts |
| 290 | +// Tell TypeScript and the package to use the global Web fetch instead of node-fetch. |
| 291 | +import 'openai/shims/web'; |
| 292 | +import OpenAI from 'openai'; |
| 293 | +``` |
| 294 | + |
| 295 | +The `openai/shims` imports have been removed. Your global types must now be [correctly configured](#minimum-types-requirements). |
| 296 | + |
| 297 | +### `openai/src` directory removed |
| 298 | + |
| 299 | +Previously IDEs may have auto-completed imports from the `openai/src` directory, however this |
| 300 | +directory was only included for an improved go-to-definition experience and should not have been used at runtime. |
| 301 | + |
| 302 | +If you have any `openai/src` imports, you must replace it with `openai`. |
| 303 | + |
| 304 | +```ts |
| 305 | +// Before |
| 306 | +import OpenAI from 'openai/src'; |
| 307 | + |
| 308 | +// After |
| 309 | +import OpenAI from 'openai'; |
| 310 | +``` |
| 311 | + |
| 312 | +### Headers |
| 313 | + |
| 314 | +The `headers` property on `APIError` objects is now an instance of the Web [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) class. It was previously just `Record<string, string | null | undefined>`. |
| 315 | + |
| 316 | +### Removed exports |
| 317 | + |
| 318 | +#### `Response` |
| 319 | + |
| 320 | +```typescript |
| 321 | +// Before |
| 322 | +import { Response } from 'openai'; |
| 323 | + |
| 324 | +// After |
| 325 | +// `Response` must now come from the builtin types |
| 326 | +``` |
| 327 | + |
| 328 | +#### Resource classes |
| 329 | + |
| 330 | +If you were importing resource classes from the root package then you must now import them from the file they are defined in: |
| 331 | + |
| 332 | +```typescript |
| 333 | +// Before |
| 334 | +import { Completions } from 'openai'; |
| 335 | + |
| 336 | +// After |
| 337 | +import { Completions } from 'openai/resources/completions'; |
| 338 | +``` |
| 339 | + |
| 340 | +#### `openai/core` |
| 341 | + |
| 342 | +The `openai/core` file was intended to be internal-only but it was publicly accessible, as such it has been refactored and split up into internal files. |
| 343 | + |
| 344 | +If you were relying on anything that was only exported from `openai/core` and is also not accessible anywhere else, please open an issue and we'll consider adding it to the public API. |
| 345 | + |
| 346 | +#### `APIClient` |
| 347 | + |
| 348 | +The `APIClient` base client class has been removed as it is no longer needed. If you were importing this class then you must now import the main client class: |
| 349 | + |
| 350 | +```typescript |
| 351 | +// Before |
| 352 | +import { APIClient } from 'openai/core'; |
| 353 | + |
| 354 | +// After |
| 355 | +import { OpenAI } from 'openai'; |
| 356 | +``` |
| 357 | + |
| 358 | +#### Cleaned up `openai/uploads` exports |
| 359 | + |
| 360 | +The following exports have been removed from `openai/uploads` as they were not intended to be a part of the public API: |
| 361 | + |
| 362 | +- `fileFromPath` |
| 363 | +- `BlobPart` |
| 364 | +- `BlobLike` |
| 365 | +- `FileLike` |
| 366 | +- `ResponseLike` |
| 367 | +- `isResponseLike` |
| 368 | +- `isBlobLike` |
| 369 | +- `isFileLike` |
| 370 | +- `isUploadable` |
| 371 | +- `isMultipartBody` |
| 372 | +- `maybeMultipartFormRequestOptions` |
| 373 | +- `multipartFormRequestOptions` |
| 374 | +- `createForm` |
| 375 | + |
| 376 | +Note that `Uploadable` & `toFile` **are** still exported: |
| 377 | + |
| 378 | +```typescript |
| 379 | +import { type Uploadable, toFile } from 'openai/uploads'; |
| 380 | +``` |
0 commit comments