├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── lib.rs ├── types.rs └── types ├── config.rs ├── helpers.rs ├── item.rs ├── request.rs ├── response.rs ├── stream.rs └── tools.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "android-tzdata" 22 | version = "0.1.1" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 25 | 26 | [[package]] 27 | name = "android_system_properties" 28 | version = "0.1.5" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 31 | dependencies = [ 32 | "libc", 33 | ] 34 | 35 | [[package]] 36 | name = "async-fn-stream" 37 | version = "0.2.2" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "e71711442f1016c768c259bec59300a10efe753bc3e686ec19e2c6a54a97c29b" 40 | dependencies = [ 41 | "futures-util", 42 | "pin-project-lite", 43 | ] 44 | 45 | [[package]] 46 | name = "autocfg" 47 | version = "1.4.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 50 | 51 | [[package]] 52 | name = "backtrace" 53 | version = "0.3.74" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 56 | dependencies = [ 57 | "addr2line", 58 | "cfg-if", 59 | "libc", 60 | "miniz_oxide", 61 | "object", 62 | "rustc-demangle", 63 | "windows-targets 0.52.6", 64 | ] 65 | 66 | [[package]] 67 | name = "base64" 68 | version = "0.22.1" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 71 | 72 | [[package]] 73 | name = "bitflags" 74 | version = "2.9.0" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 77 | 78 | [[package]] 79 | name = "bumpalo" 80 | version = "3.17.0" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 83 | 84 | [[package]] 85 | name = "bytes" 86 | version = "1.10.1" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 89 | 90 | [[package]] 91 | name = "cc" 92 | version = "1.2.16" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" 95 | dependencies = [ 96 | "shlex", 97 | ] 98 | 99 | [[package]] 100 | name = "cfg-if" 101 | version = "1.0.0" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 104 | 105 | [[package]] 106 | name = "cfg_aliases" 107 | version = "0.2.1" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 110 | 111 | [[package]] 112 | name = "chrono" 113 | version = "0.4.40" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" 116 | dependencies = [ 117 | "android-tzdata", 118 | "iana-time-zone", 119 | "js-sys", 120 | "num-traits", 121 | "serde", 122 | "wasm-bindgen", 123 | "windows-link", 124 | ] 125 | 126 | [[package]] 127 | name = "core-foundation" 128 | version = "0.9.4" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 131 | dependencies = [ 132 | "core-foundation-sys", 133 | "libc", 134 | ] 135 | 136 | [[package]] 137 | name = "core-foundation" 138 | version = "0.10.0" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" 141 | dependencies = [ 142 | "core-foundation-sys", 143 | "libc", 144 | ] 145 | 146 | [[package]] 147 | name = "core-foundation-sys" 148 | version = "0.8.7" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 151 | 152 | [[package]] 153 | name = "displaydoc" 154 | version = "0.2.5" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 157 | dependencies = [ 158 | "proc-macro2", 159 | "quote", 160 | "syn", 161 | ] 162 | 163 | [[package]] 164 | name = "errno" 165 | version = "0.3.10" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" 168 | dependencies = [ 169 | "libc", 170 | "windows-sys 0.59.0", 171 | ] 172 | 173 | [[package]] 174 | name = "eventsource-stream" 175 | version = "0.2.3" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" 178 | dependencies = [ 179 | "futures-core", 180 | "nom", 181 | "pin-project-lite", 182 | ] 183 | 184 | [[package]] 185 | name = "fastrand" 186 | version = "2.3.0" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 189 | 190 | [[package]] 191 | name = "fnv" 192 | version = "1.0.7" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 195 | 196 | [[package]] 197 | name = "foreign-types" 198 | version = "0.3.2" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 201 | dependencies = [ 202 | "foreign-types-shared", 203 | ] 204 | 205 | [[package]] 206 | name = "foreign-types-shared" 207 | version = "0.1.1" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 210 | 211 | [[package]] 212 | name = "form_urlencoded" 213 | version = "1.2.1" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 216 | dependencies = [ 217 | "percent-encoding", 218 | ] 219 | 220 | [[package]] 221 | name = "futures" 222 | version = "0.3.31" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 225 | dependencies = [ 226 | "futures-channel", 227 | "futures-core", 228 | "futures-executor", 229 | "futures-io", 230 | "futures-sink", 231 | "futures-task", 232 | "futures-util", 233 | ] 234 | 235 | [[package]] 236 | name = "futures-channel" 237 | version = "0.3.31" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 240 | dependencies = [ 241 | "futures-core", 242 | "futures-sink", 243 | ] 244 | 245 | [[package]] 246 | name = "futures-core" 247 | version = "0.3.31" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 250 | 251 | [[package]] 252 | name = "futures-executor" 253 | version = "0.3.31" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 256 | dependencies = [ 257 | "futures-core", 258 | "futures-task", 259 | "futures-util", 260 | ] 261 | 262 | [[package]] 263 | name = "futures-io" 264 | version = "0.3.31" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 267 | 268 | [[package]] 269 | name = "futures-macro" 270 | version = "0.3.31" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 273 | dependencies = [ 274 | "proc-macro2", 275 | "quote", 276 | "syn", 277 | ] 278 | 279 | [[package]] 280 | name = "futures-sink" 281 | version = "0.3.31" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 284 | 285 | [[package]] 286 | name = "futures-task" 287 | version = "0.3.31" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 290 | 291 | [[package]] 292 | name = "futures-timer" 293 | version = "3.0.3" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" 296 | 297 | [[package]] 298 | name = "futures-util" 299 | version = "0.3.31" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 302 | dependencies = [ 303 | "futures-channel", 304 | "futures-core", 305 | "futures-io", 306 | "futures-macro", 307 | "futures-sink", 308 | "futures-task", 309 | "memchr", 310 | "pin-project-lite", 311 | "pin-utils", 312 | "slab", 313 | ] 314 | 315 | [[package]] 316 | name = "getrandom" 317 | version = "0.2.15" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 320 | dependencies = [ 321 | "cfg-if", 322 | "js-sys", 323 | "libc", 324 | "wasi 0.11.0+wasi-snapshot-preview1", 325 | "wasm-bindgen", 326 | ] 327 | 328 | [[package]] 329 | name = "getrandom" 330 | version = "0.3.1" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" 333 | dependencies = [ 334 | "cfg-if", 335 | "libc", 336 | "wasi 0.13.3+wasi-0.2.2", 337 | "windows-targets 0.52.6", 338 | ] 339 | 340 | [[package]] 341 | name = "gimli" 342 | version = "0.31.1" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 345 | 346 | [[package]] 347 | name = "http" 348 | version = "1.3.1" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 351 | dependencies = [ 352 | "bytes", 353 | "fnv", 354 | "itoa", 355 | ] 356 | 357 | [[package]] 358 | name = "http-body" 359 | version = "1.0.1" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 362 | dependencies = [ 363 | "bytes", 364 | "http", 365 | ] 366 | 367 | [[package]] 368 | name = "http-body-util" 369 | version = "0.1.3" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 372 | dependencies = [ 373 | "bytes", 374 | "futures-core", 375 | "http", 376 | "http-body", 377 | "pin-project-lite", 378 | ] 379 | 380 | [[package]] 381 | name = "httparse" 382 | version = "1.10.1" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 385 | 386 | [[package]] 387 | name = "hyper" 388 | version = "1.6.0" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 391 | dependencies = [ 392 | "bytes", 393 | "futures-channel", 394 | "futures-util", 395 | "http", 396 | "http-body", 397 | "httparse", 398 | "itoa", 399 | "pin-project-lite", 400 | "smallvec", 401 | "tokio", 402 | "want", 403 | ] 404 | 405 | [[package]] 406 | name = "hyper-rustls" 407 | version = "0.27.5" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" 410 | dependencies = [ 411 | "futures-util", 412 | "http", 413 | "hyper", 414 | "hyper-util", 415 | "rustls", 416 | "rustls-native-certs", 417 | "rustls-pki-types", 418 | "tokio", 419 | "tokio-rustls", 420 | "tower-service", 421 | "webpki-roots", 422 | ] 423 | 424 | [[package]] 425 | name = "hyper-tls" 426 | version = "0.6.0" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 429 | dependencies = [ 430 | "bytes", 431 | "http-body-util", 432 | "hyper", 433 | "hyper-util", 434 | "native-tls", 435 | "tokio", 436 | "tokio-native-tls", 437 | "tower-service", 438 | ] 439 | 440 | [[package]] 441 | name = "hyper-util" 442 | version = "0.1.10" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" 445 | dependencies = [ 446 | "bytes", 447 | "futures-channel", 448 | "futures-util", 449 | "http", 450 | "http-body", 451 | "hyper", 452 | "pin-project-lite", 453 | "socket2", 454 | "tokio", 455 | "tower-service", 456 | "tracing", 457 | ] 458 | 459 | [[package]] 460 | name = "iana-time-zone" 461 | version = "0.1.61" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 464 | dependencies = [ 465 | "android_system_properties", 466 | "core-foundation-sys", 467 | "iana-time-zone-haiku", 468 | "js-sys", 469 | "wasm-bindgen", 470 | "windows-core", 471 | ] 472 | 473 | [[package]] 474 | name = "iana-time-zone-haiku" 475 | version = "0.1.2" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 478 | dependencies = [ 479 | "cc", 480 | ] 481 | 482 | [[package]] 483 | name = "icu_collections" 484 | version = "1.5.0" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 487 | dependencies = [ 488 | "displaydoc", 489 | "yoke", 490 | "zerofrom", 491 | "zerovec", 492 | ] 493 | 494 | [[package]] 495 | name = "icu_locid" 496 | version = "1.5.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 499 | dependencies = [ 500 | "displaydoc", 501 | "litemap", 502 | "tinystr", 503 | "writeable", 504 | "zerovec", 505 | ] 506 | 507 | [[package]] 508 | name = "icu_locid_transform" 509 | version = "1.5.0" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 512 | dependencies = [ 513 | "displaydoc", 514 | "icu_locid", 515 | "icu_locid_transform_data", 516 | "icu_provider", 517 | "tinystr", 518 | "zerovec", 519 | ] 520 | 521 | [[package]] 522 | name = "icu_locid_transform_data" 523 | version = "1.5.0" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 526 | 527 | [[package]] 528 | name = "icu_normalizer" 529 | version = "1.5.0" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 532 | dependencies = [ 533 | "displaydoc", 534 | "icu_collections", 535 | "icu_normalizer_data", 536 | "icu_properties", 537 | "icu_provider", 538 | "smallvec", 539 | "utf16_iter", 540 | "utf8_iter", 541 | "write16", 542 | "zerovec", 543 | ] 544 | 545 | [[package]] 546 | name = "icu_normalizer_data" 547 | version = "1.5.0" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 550 | 551 | [[package]] 552 | name = "icu_properties" 553 | version = "1.5.1" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 556 | dependencies = [ 557 | "displaydoc", 558 | "icu_collections", 559 | "icu_locid_transform", 560 | "icu_properties_data", 561 | "icu_provider", 562 | "tinystr", 563 | "zerovec", 564 | ] 565 | 566 | [[package]] 567 | name = "icu_properties_data" 568 | version = "1.5.0" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 571 | 572 | [[package]] 573 | name = "icu_provider" 574 | version = "1.5.0" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 577 | dependencies = [ 578 | "displaydoc", 579 | "icu_locid", 580 | "icu_provider_macros", 581 | "stable_deref_trait", 582 | "tinystr", 583 | "writeable", 584 | "yoke", 585 | "zerofrom", 586 | "zerovec", 587 | ] 588 | 589 | [[package]] 590 | name = "icu_provider_macros" 591 | version = "1.5.0" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 594 | dependencies = [ 595 | "proc-macro2", 596 | "quote", 597 | "syn", 598 | ] 599 | 600 | [[package]] 601 | name = "idna" 602 | version = "1.0.3" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 605 | dependencies = [ 606 | "idna_adapter", 607 | "smallvec", 608 | "utf8_iter", 609 | ] 610 | 611 | [[package]] 612 | name = "idna_adapter" 613 | version = "1.2.0" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 616 | dependencies = [ 617 | "icu_normalizer", 618 | "icu_properties", 619 | ] 620 | 621 | [[package]] 622 | name = "ipnet" 623 | version = "2.11.0" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 626 | 627 | [[package]] 628 | name = "itoa" 629 | version = "1.0.15" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 632 | 633 | [[package]] 634 | name = "js-sys" 635 | version = "0.3.77" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 638 | dependencies = [ 639 | "once_cell", 640 | "wasm-bindgen", 641 | ] 642 | 643 | [[package]] 644 | name = "libc" 645 | version = "0.2.171" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" 648 | 649 | [[package]] 650 | name = "linux-raw-sys" 651 | version = "0.9.3" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" 654 | 655 | [[package]] 656 | name = "litemap" 657 | version = "0.7.5" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" 660 | 661 | [[package]] 662 | name = "log" 663 | version = "0.4.26" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" 666 | 667 | [[package]] 668 | name = "macon" 669 | version = "1.3.0" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "4e2360fdc60235ad3db2d65bb74539e0813c20a626f7e330ce9a64b2d4e513f0" 672 | dependencies = [ 673 | "macon_api", 674 | "macon_derive", 675 | ] 676 | 677 | [[package]] 678 | name = "macon_api" 679 | version = "1.3.0" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "2330ee9375fc537d78cc438ed16695a5d0201f0be9d977bf6bc4ac11e5b4e177" 682 | 683 | [[package]] 684 | name = "macon_derive" 685 | version = "1.3.0" 686 | source = "registry+https://github.com/rust-lang/crates.io-index" 687 | checksum = "ccd7e1436ba066ad10c8b43ac4a00d304322831b90f039f1d83815f846fee024" 688 | dependencies = [ 689 | "proc-macro2", 690 | "quote", 691 | "syn", 692 | ] 693 | 694 | [[package]] 695 | name = "memchr" 696 | version = "2.7.4" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 699 | 700 | [[package]] 701 | name = "mime" 702 | version = "0.3.17" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 705 | 706 | [[package]] 707 | name = "minimal-lexical" 708 | version = "0.2.1" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 711 | 712 | [[package]] 713 | name = "miniz_oxide" 714 | version = "0.8.5" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" 717 | dependencies = [ 718 | "adler2", 719 | ] 720 | 721 | [[package]] 722 | name = "mio" 723 | version = "1.0.3" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 726 | dependencies = [ 727 | "libc", 728 | "wasi 0.11.0+wasi-snapshot-preview1", 729 | "windows-sys 0.52.0", 730 | ] 731 | 732 | [[package]] 733 | name = "native-tls" 734 | version = "0.2.14" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 737 | dependencies = [ 738 | "libc", 739 | "log", 740 | "openssl", 741 | "openssl-probe", 742 | "openssl-sys", 743 | "schannel", 744 | "security-framework 2.11.1", 745 | "security-framework-sys", 746 | "tempfile", 747 | ] 748 | 749 | [[package]] 750 | name = "nom" 751 | version = "7.1.3" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 754 | dependencies = [ 755 | "memchr", 756 | "minimal-lexical", 757 | ] 758 | 759 | [[package]] 760 | name = "num-traits" 761 | version = "0.2.19" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 764 | dependencies = [ 765 | "autocfg", 766 | ] 767 | 768 | [[package]] 769 | name = "object" 770 | version = "0.36.7" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 773 | dependencies = [ 774 | "memchr", 775 | ] 776 | 777 | [[package]] 778 | name = "once_cell" 779 | version = "1.21.1" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" 782 | 783 | [[package]] 784 | name = "openai_responses" 785 | version = "0.1.6" 786 | dependencies = [ 787 | "async-fn-stream", 788 | "chrono", 789 | "futures", 790 | "macon", 791 | "reqwest", 792 | "reqwest-eventsource", 793 | "serde", 794 | "serde_json", 795 | "thiserror 2.0.12", 796 | "tokio", 797 | ] 798 | 799 | [[package]] 800 | name = "openssl" 801 | version = "0.10.71" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" 804 | dependencies = [ 805 | "bitflags", 806 | "cfg-if", 807 | "foreign-types", 808 | "libc", 809 | "once_cell", 810 | "openssl-macros", 811 | "openssl-sys", 812 | ] 813 | 814 | [[package]] 815 | name = "openssl-macros" 816 | version = "0.1.1" 817 | source = "registry+https://github.com/rust-lang/crates.io-index" 818 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 819 | dependencies = [ 820 | "proc-macro2", 821 | "quote", 822 | "syn", 823 | ] 824 | 825 | [[package]] 826 | name = "openssl-probe" 827 | version = "0.1.6" 828 | source = "registry+https://github.com/rust-lang/crates.io-index" 829 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 830 | 831 | [[package]] 832 | name = "openssl-src" 833 | version = "300.4.2+3.4.1" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "168ce4e058f975fe43e89d9ccf78ca668601887ae736090aacc23ae353c298e2" 836 | dependencies = [ 837 | "cc", 838 | ] 839 | 840 | [[package]] 841 | name = "openssl-sys" 842 | version = "0.9.106" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" 845 | dependencies = [ 846 | "cc", 847 | "libc", 848 | "openssl-src", 849 | "pkg-config", 850 | "vcpkg", 851 | ] 852 | 853 | [[package]] 854 | name = "percent-encoding" 855 | version = "2.3.1" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 858 | 859 | [[package]] 860 | name = "pin-project-lite" 861 | version = "0.2.16" 862 | source = "registry+https://github.com/rust-lang/crates.io-index" 863 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 864 | 865 | [[package]] 866 | name = "pin-utils" 867 | version = "0.1.0" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 870 | 871 | [[package]] 872 | name = "pkg-config" 873 | version = "0.3.32" 874 | source = "registry+https://github.com/rust-lang/crates.io-index" 875 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 876 | 877 | [[package]] 878 | name = "ppv-lite86" 879 | version = "0.2.21" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 882 | dependencies = [ 883 | "zerocopy", 884 | ] 885 | 886 | [[package]] 887 | name = "proc-macro2" 888 | version = "1.0.94" 889 | source = "registry+https://github.com/rust-lang/crates.io-index" 890 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" 891 | dependencies = [ 892 | "unicode-ident", 893 | ] 894 | 895 | [[package]] 896 | name = "quinn" 897 | version = "0.11.6" 898 | source = "registry+https://github.com/rust-lang/crates.io-index" 899 | checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" 900 | dependencies = [ 901 | "bytes", 902 | "pin-project-lite", 903 | "quinn-proto", 904 | "quinn-udp", 905 | "rustc-hash", 906 | "rustls", 907 | "socket2", 908 | "thiserror 2.0.12", 909 | "tokio", 910 | "tracing", 911 | ] 912 | 913 | [[package]] 914 | name = "quinn-proto" 915 | version = "0.11.9" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" 918 | dependencies = [ 919 | "bytes", 920 | "getrandom 0.2.15", 921 | "rand", 922 | "ring", 923 | "rustc-hash", 924 | "rustls", 925 | "rustls-pki-types", 926 | "slab", 927 | "thiserror 2.0.12", 928 | "tinyvec", 929 | "tracing", 930 | "web-time", 931 | ] 932 | 933 | [[package]] 934 | name = "quinn-udp" 935 | version = "0.5.10" 936 | source = "registry+https://github.com/rust-lang/crates.io-index" 937 | checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" 938 | dependencies = [ 939 | "cfg_aliases", 940 | "libc", 941 | "once_cell", 942 | "socket2", 943 | "tracing", 944 | "windows-sys 0.59.0", 945 | ] 946 | 947 | [[package]] 948 | name = "quote" 949 | version = "1.0.40" 950 | source = "registry+https://github.com/rust-lang/crates.io-index" 951 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 952 | dependencies = [ 953 | "proc-macro2", 954 | ] 955 | 956 | [[package]] 957 | name = "rand" 958 | version = "0.8.5" 959 | source = "registry+https://github.com/rust-lang/crates.io-index" 960 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 961 | dependencies = [ 962 | "libc", 963 | "rand_chacha", 964 | "rand_core", 965 | ] 966 | 967 | [[package]] 968 | name = "rand_chacha" 969 | version = "0.3.1" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 972 | dependencies = [ 973 | "ppv-lite86", 974 | "rand_core", 975 | ] 976 | 977 | [[package]] 978 | name = "rand_core" 979 | version = "0.6.4" 980 | source = "registry+https://github.com/rust-lang/crates.io-index" 981 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 982 | dependencies = [ 983 | "getrandom 0.2.15", 984 | ] 985 | 986 | [[package]] 987 | name = "reqwest" 988 | version = "0.12.14" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "989e327e510263980e231de548a33e63d34962d29ae61b467389a1a09627a254" 991 | dependencies = [ 992 | "base64", 993 | "bytes", 994 | "futures-core", 995 | "futures-util", 996 | "http", 997 | "http-body", 998 | "http-body-util", 999 | "hyper", 1000 | "hyper-rustls", 1001 | "hyper-tls", 1002 | "hyper-util", 1003 | "ipnet", 1004 | "js-sys", 1005 | "log", 1006 | "mime", 1007 | "native-tls", 1008 | "once_cell", 1009 | "percent-encoding", 1010 | "pin-project-lite", 1011 | "quinn", 1012 | "rustls", 1013 | "rustls-native-certs", 1014 | "rustls-pemfile", 1015 | "rustls-pki-types", 1016 | "serde", 1017 | "serde_json", 1018 | "serde_urlencoded", 1019 | "sync_wrapper", 1020 | "tokio", 1021 | "tokio-native-tls", 1022 | "tokio-rustls", 1023 | "tokio-util", 1024 | "tower", 1025 | "tower-service", 1026 | "url", 1027 | "wasm-bindgen", 1028 | "wasm-bindgen-futures", 1029 | "wasm-streams", 1030 | "web-sys", 1031 | "webpki-roots", 1032 | "windows-registry", 1033 | ] 1034 | 1035 | [[package]] 1036 | name = "reqwest-eventsource" 1037 | version = "0.6.0" 1038 | source = "registry+https://github.com/rust-lang/crates.io-index" 1039 | checksum = "632c55746dbb44275691640e7b40c907c16a2dc1a5842aa98aaec90da6ec6bde" 1040 | dependencies = [ 1041 | "eventsource-stream", 1042 | "futures-core", 1043 | "futures-timer", 1044 | "mime", 1045 | "nom", 1046 | "pin-project-lite", 1047 | "reqwest", 1048 | "thiserror 1.0.69", 1049 | ] 1050 | 1051 | [[package]] 1052 | name = "ring" 1053 | version = "0.17.14" 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" 1055 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 1056 | dependencies = [ 1057 | "cc", 1058 | "cfg-if", 1059 | "getrandom 0.2.15", 1060 | "libc", 1061 | "untrusted", 1062 | "windows-sys 0.52.0", 1063 | ] 1064 | 1065 | [[package]] 1066 | name = "rustc-demangle" 1067 | version = "0.1.24" 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" 1069 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1070 | 1071 | [[package]] 1072 | name = "rustc-hash" 1073 | version = "2.1.1" 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" 1075 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 1076 | 1077 | [[package]] 1078 | name = "rustix" 1079 | version = "1.0.2" 1080 | source = "registry+https://github.com/rust-lang/crates.io-index" 1081 | checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825" 1082 | dependencies = [ 1083 | "bitflags", 1084 | "errno", 1085 | "libc", 1086 | "linux-raw-sys", 1087 | "windows-sys 0.59.0", 1088 | ] 1089 | 1090 | [[package]] 1091 | name = "rustls" 1092 | version = "0.23.23" 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" 1094 | checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" 1095 | dependencies = [ 1096 | "once_cell", 1097 | "ring", 1098 | "rustls-pki-types", 1099 | "rustls-webpki", 1100 | "subtle", 1101 | "zeroize", 1102 | ] 1103 | 1104 | [[package]] 1105 | name = "rustls-native-certs" 1106 | version = "0.8.1" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" 1109 | dependencies = [ 1110 | "openssl-probe", 1111 | "rustls-pki-types", 1112 | "schannel", 1113 | "security-framework 3.2.0", 1114 | ] 1115 | 1116 | [[package]] 1117 | name = "rustls-pemfile" 1118 | version = "2.2.0" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 1121 | dependencies = [ 1122 | "rustls-pki-types", 1123 | ] 1124 | 1125 | [[package]] 1126 | name = "rustls-pki-types" 1127 | version = "1.11.0" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" 1130 | dependencies = [ 1131 | "web-time", 1132 | ] 1133 | 1134 | [[package]] 1135 | name = "rustls-webpki" 1136 | version = "0.102.8" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 1139 | dependencies = [ 1140 | "ring", 1141 | "rustls-pki-types", 1142 | "untrusted", 1143 | ] 1144 | 1145 | [[package]] 1146 | name = "rustversion" 1147 | version = "1.0.20" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 1150 | 1151 | [[package]] 1152 | name = "ryu" 1153 | version = "1.0.20" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1156 | 1157 | [[package]] 1158 | name = "schannel" 1159 | version = "0.1.27" 1160 | source = "registry+https://github.com/rust-lang/crates.io-index" 1161 | checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 1162 | dependencies = [ 1163 | "windows-sys 0.59.0", 1164 | ] 1165 | 1166 | [[package]] 1167 | name = "security-framework" 1168 | version = "2.11.1" 1169 | source = "registry+https://github.com/rust-lang/crates.io-index" 1170 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 1171 | dependencies = [ 1172 | "bitflags", 1173 | "core-foundation 0.9.4", 1174 | "core-foundation-sys", 1175 | "libc", 1176 | "security-framework-sys", 1177 | ] 1178 | 1179 | [[package]] 1180 | name = "security-framework" 1181 | version = "3.2.0" 1182 | source = "registry+https://github.com/rust-lang/crates.io-index" 1183 | checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" 1184 | dependencies = [ 1185 | "bitflags", 1186 | "core-foundation 0.10.0", 1187 | "core-foundation-sys", 1188 | "libc", 1189 | "security-framework-sys", 1190 | ] 1191 | 1192 | [[package]] 1193 | name = "security-framework-sys" 1194 | version = "2.14.0" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 1197 | dependencies = [ 1198 | "core-foundation-sys", 1199 | "libc", 1200 | ] 1201 | 1202 | [[package]] 1203 | name = "serde" 1204 | version = "1.0.219" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 1207 | dependencies = [ 1208 | "serde_derive", 1209 | ] 1210 | 1211 | [[package]] 1212 | name = "serde_derive" 1213 | version = "1.0.219" 1214 | source = "registry+https://github.com/rust-lang/crates.io-index" 1215 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 1216 | dependencies = [ 1217 | "proc-macro2", 1218 | "quote", 1219 | "syn", 1220 | ] 1221 | 1222 | [[package]] 1223 | name = "serde_json" 1224 | version = "1.0.140" 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" 1226 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 1227 | dependencies = [ 1228 | "itoa", 1229 | "memchr", 1230 | "ryu", 1231 | "serde", 1232 | ] 1233 | 1234 | [[package]] 1235 | name = "serde_urlencoded" 1236 | version = "0.7.1" 1237 | source = "registry+https://github.com/rust-lang/crates.io-index" 1238 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1239 | dependencies = [ 1240 | "form_urlencoded", 1241 | "itoa", 1242 | "ryu", 1243 | "serde", 1244 | ] 1245 | 1246 | [[package]] 1247 | name = "shlex" 1248 | version = "1.3.0" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1251 | 1252 | [[package]] 1253 | name = "slab" 1254 | version = "0.4.9" 1255 | source = "registry+https://github.com/rust-lang/crates.io-index" 1256 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1257 | dependencies = [ 1258 | "autocfg", 1259 | ] 1260 | 1261 | [[package]] 1262 | name = "smallvec" 1263 | version = "1.14.0" 1264 | source = "registry+https://github.com/rust-lang/crates.io-index" 1265 | checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" 1266 | 1267 | [[package]] 1268 | name = "socket2" 1269 | version = "0.5.8" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" 1272 | dependencies = [ 1273 | "libc", 1274 | "windows-sys 0.52.0", 1275 | ] 1276 | 1277 | [[package]] 1278 | name = "stable_deref_trait" 1279 | version = "1.2.0" 1280 | source = "registry+https://github.com/rust-lang/crates.io-index" 1281 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1282 | 1283 | [[package]] 1284 | name = "subtle" 1285 | version = "2.6.1" 1286 | source = "registry+https://github.com/rust-lang/crates.io-index" 1287 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1288 | 1289 | [[package]] 1290 | name = "syn" 1291 | version = "2.0.100" 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" 1293 | checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 1294 | dependencies = [ 1295 | "proc-macro2", 1296 | "quote", 1297 | "unicode-ident", 1298 | ] 1299 | 1300 | [[package]] 1301 | name = "sync_wrapper" 1302 | version = "1.0.2" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1305 | dependencies = [ 1306 | "futures-core", 1307 | ] 1308 | 1309 | [[package]] 1310 | name = "synstructure" 1311 | version = "0.13.1" 1312 | source = "registry+https://github.com/rust-lang/crates.io-index" 1313 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 1314 | dependencies = [ 1315 | "proc-macro2", 1316 | "quote", 1317 | "syn", 1318 | ] 1319 | 1320 | [[package]] 1321 | name = "tempfile" 1322 | version = "3.19.0" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "488960f40a3fd53d72c2a29a58722561dee8afdd175bd88e3db4677d7b2ba600" 1325 | dependencies = [ 1326 | "fastrand", 1327 | "getrandom 0.3.1", 1328 | "once_cell", 1329 | "rustix", 1330 | "windows-sys 0.59.0", 1331 | ] 1332 | 1333 | [[package]] 1334 | name = "thiserror" 1335 | version = "1.0.69" 1336 | source = "registry+https://github.com/rust-lang/crates.io-index" 1337 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1338 | dependencies = [ 1339 | "thiserror-impl 1.0.69", 1340 | ] 1341 | 1342 | [[package]] 1343 | name = "thiserror" 1344 | version = "2.0.12" 1345 | source = "registry+https://github.com/rust-lang/crates.io-index" 1346 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 1347 | dependencies = [ 1348 | "thiserror-impl 2.0.12", 1349 | ] 1350 | 1351 | [[package]] 1352 | name = "thiserror-impl" 1353 | version = "1.0.69" 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" 1355 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1356 | dependencies = [ 1357 | "proc-macro2", 1358 | "quote", 1359 | "syn", 1360 | ] 1361 | 1362 | [[package]] 1363 | name = "thiserror-impl" 1364 | version = "2.0.12" 1365 | source = "registry+https://github.com/rust-lang/crates.io-index" 1366 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 1367 | dependencies = [ 1368 | "proc-macro2", 1369 | "quote", 1370 | "syn", 1371 | ] 1372 | 1373 | [[package]] 1374 | name = "tinystr" 1375 | version = "0.7.6" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 1378 | dependencies = [ 1379 | "displaydoc", 1380 | "zerovec", 1381 | ] 1382 | 1383 | [[package]] 1384 | name = "tinyvec" 1385 | version = "1.9.0" 1386 | source = "registry+https://github.com/rust-lang/crates.io-index" 1387 | checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" 1388 | dependencies = [ 1389 | "tinyvec_macros", 1390 | ] 1391 | 1392 | [[package]] 1393 | name = "tinyvec_macros" 1394 | version = "0.1.1" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1397 | 1398 | [[package]] 1399 | name = "tokio" 1400 | version = "1.44.1" 1401 | source = "registry+https://github.com/rust-lang/crates.io-index" 1402 | checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" 1403 | dependencies = [ 1404 | "backtrace", 1405 | "bytes", 1406 | "libc", 1407 | "mio", 1408 | "pin-project-lite", 1409 | "socket2", 1410 | "tokio-macros", 1411 | "windows-sys 0.52.0", 1412 | ] 1413 | 1414 | [[package]] 1415 | name = "tokio-macros" 1416 | version = "2.5.0" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 1419 | dependencies = [ 1420 | "proc-macro2", 1421 | "quote", 1422 | "syn", 1423 | ] 1424 | 1425 | [[package]] 1426 | name = "tokio-native-tls" 1427 | version = "0.3.1" 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" 1429 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 1430 | dependencies = [ 1431 | "native-tls", 1432 | "tokio", 1433 | ] 1434 | 1435 | [[package]] 1436 | name = "tokio-rustls" 1437 | version = "0.26.2" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 1440 | dependencies = [ 1441 | "rustls", 1442 | "tokio", 1443 | ] 1444 | 1445 | [[package]] 1446 | name = "tokio-util" 1447 | version = "0.7.14" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" 1450 | dependencies = [ 1451 | "bytes", 1452 | "futures-core", 1453 | "futures-sink", 1454 | "pin-project-lite", 1455 | "tokio", 1456 | ] 1457 | 1458 | [[package]] 1459 | name = "tower" 1460 | version = "0.5.2" 1461 | source = "registry+https://github.com/rust-lang/crates.io-index" 1462 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 1463 | dependencies = [ 1464 | "futures-core", 1465 | "futures-util", 1466 | "pin-project-lite", 1467 | "sync_wrapper", 1468 | "tokio", 1469 | "tower-layer", 1470 | "tower-service", 1471 | ] 1472 | 1473 | [[package]] 1474 | name = "tower-layer" 1475 | version = "0.3.3" 1476 | source = "registry+https://github.com/rust-lang/crates.io-index" 1477 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1478 | 1479 | [[package]] 1480 | name = "tower-service" 1481 | version = "0.3.3" 1482 | source = "registry+https://github.com/rust-lang/crates.io-index" 1483 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1484 | 1485 | [[package]] 1486 | name = "tracing" 1487 | version = "0.1.41" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 1490 | dependencies = [ 1491 | "pin-project-lite", 1492 | "tracing-core", 1493 | ] 1494 | 1495 | [[package]] 1496 | name = "tracing-core" 1497 | version = "0.1.33" 1498 | source = "registry+https://github.com/rust-lang/crates.io-index" 1499 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 1500 | dependencies = [ 1501 | "once_cell", 1502 | ] 1503 | 1504 | [[package]] 1505 | name = "try-lock" 1506 | version = "0.2.5" 1507 | source = "registry+https://github.com/rust-lang/crates.io-index" 1508 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1509 | 1510 | [[package]] 1511 | name = "unicode-ident" 1512 | version = "1.0.18" 1513 | source = "registry+https://github.com/rust-lang/crates.io-index" 1514 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1515 | 1516 | [[package]] 1517 | name = "untrusted" 1518 | version = "0.9.0" 1519 | source = "registry+https://github.com/rust-lang/crates.io-index" 1520 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 1521 | 1522 | [[package]] 1523 | name = "url" 1524 | version = "2.5.4" 1525 | source = "registry+https://github.com/rust-lang/crates.io-index" 1526 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 1527 | dependencies = [ 1528 | "form_urlencoded", 1529 | "idna", 1530 | "percent-encoding", 1531 | ] 1532 | 1533 | [[package]] 1534 | name = "utf16_iter" 1535 | version = "1.0.5" 1536 | source = "registry+https://github.com/rust-lang/crates.io-index" 1537 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 1538 | 1539 | [[package]] 1540 | name = "utf8_iter" 1541 | version = "1.0.4" 1542 | source = "registry+https://github.com/rust-lang/crates.io-index" 1543 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 1544 | 1545 | [[package]] 1546 | name = "vcpkg" 1547 | version = "0.2.15" 1548 | source = "registry+https://github.com/rust-lang/crates.io-index" 1549 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1550 | 1551 | [[package]] 1552 | name = "want" 1553 | version = "0.3.1" 1554 | source = "registry+https://github.com/rust-lang/crates.io-index" 1555 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1556 | dependencies = [ 1557 | "try-lock", 1558 | ] 1559 | 1560 | [[package]] 1561 | name = "wasi" 1562 | version = "0.11.0+wasi-snapshot-preview1" 1563 | source = "registry+https://github.com/rust-lang/crates.io-index" 1564 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1565 | 1566 | [[package]] 1567 | name = "wasi" 1568 | version = "0.13.3+wasi-0.2.2" 1569 | source = "registry+https://github.com/rust-lang/crates.io-index" 1570 | checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" 1571 | dependencies = [ 1572 | "wit-bindgen-rt", 1573 | ] 1574 | 1575 | [[package]] 1576 | name = "wasm-bindgen" 1577 | version = "0.2.100" 1578 | source = "registry+https://github.com/rust-lang/crates.io-index" 1579 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 1580 | dependencies = [ 1581 | "cfg-if", 1582 | "once_cell", 1583 | "rustversion", 1584 | "wasm-bindgen-macro", 1585 | ] 1586 | 1587 | [[package]] 1588 | name = "wasm-bindgen-backend" 1589 | version = "0.2.100" 1590 | source = "registry+https://github.com/rust-lang/crates.io-index" 1591 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 1592 | dependencies = [ 1593 | "bumpalo", 1594 | "log", 1595 | "proc-macro2", 1596 | "quote", 1597 | "syn", 1598 | "wasm-bindgen-shared", 1599 | ] 1600 | 1601 | [[package]] 1602 | name = "wasm-bindgen-futures" 1603 | version = "0.4.50" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 1606 | dependencies = [ 1607 | "cfg-if", 1608 | "js-sys", 1609 | "once_cell", 1610 | "wasm-bindgen", 1611 | "web-sys", 1612 | ] 1613 | 1614 | [[package]] 1615 | name = "wasm-bindgen-macro" 1616 | version = "0.2.100" 1617 | source = "registry+https://github.com/rust-lang/crates.io-index" 1618 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 1619 | dependencies = [ 1620 | "quote", 1621 | "wasm-bindgen-macro-support", 1622 | ] 1623 | 1624 | [[package]] 1625 | name = "wasm-bindgen-macro-support" 1626 | version = "0.2.100" 1627 | source = "registry+https://github.com/rust-lang/crates.io-index" 1628 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 1629 | dependencies = [ 1630 | "proc-macro2", 1631 | "quote", 1632 | "syn", 1633 | "wasm-bindgen-backend", 1634 | "wasm-bindgen-shared", 1635 | ] 1636 | 1637 | [[package]] 1638 | name = "wasm-bindgen-shared" 1639 | version = "0.2.100" 1640 | source = "registry+https://github.com/rust-lang/crates.io-index" 1641 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 1642 | dependencies = [ 1643 | "unicode-ident", 1644 | ] 1645 | 1646 | [[package]] 1647 | name = "wasm-streams" 1648 | version = "0.4.2" 1649 | source = "registry+https://github.com/rust-lang/crates.io-index" 1650 | checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" 1651 | dependencies = [ 1652 | "futures-util", 1653 | "js-sys", 1654 | "wasm-bindgen", 1655 | "wasm-bindgen-futures", 1656 | "web-sys", 1657 | ] 1658 | 1659 | [[package]] 1660 | name = "web-sys" 1661 | version = "0.3.77" 1662 | source = "registry+https://github.com/rust-lang/crates.io-index" 1663 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 1664 | dependencies = [ 1665 | "js-sys", 1666 | "wasm-bindgen", 1667 | ] 1668 | 1669 | [[package]] 1670 | name = "web-time" 1671 | version = "1.1.0" 1672 | source = "registry+https://github.com/rust-lang/crates.io-index" 1673 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 1674 | dependencies = [ 1675 | "js-sys", 1676 | "wasm-bindgen", 1677 | ] 1678 | 1679 | [[package]] 1680 | name = "webpki-roots" 1681 | version = "0.26.8" 1682 | source = "registry+https://github.com/rust-lang/crates.io-index" 1683 | checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" 1684 | dependencies = [ 1685 | "rustls-pki-types", 1686 | ] 1687 | 1688 | [[package]] 1689 | name = "windows-core" 1690 | version = "0.52.0" 1691 | source = "registry+https://github.com/rust-lang/crates.io-index" 1692 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 1693 | dependencies = [ 1694 | "windows-targets 0.52.6", 1695 | ] 1696 | 1697 | [[package]] 1698 | name = "windows-link" 1699 | version = "0.1.0" 1700 | source = "registry+https://github.com/rust-lang/crates.io-index" 1701 | checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" 1702 | 1703 | [[package]] 1704 | name = "windows-registry" 1705 | version = "0.4.0" 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" 1707 | checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" 1708 | dependencies = [ 1709 | "windows-result", 1710 | "windows-strings", 1711 | "windows-targets 0.53.0", 1712 | ] 1713 | 1714 | [[package]] 1715 | name = "windows-result" 1716 | version = "0.3.1" 1717 | source = "registry+https://github.com/rust-lang/crates.io-index" 1718 | checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" 1719 | dependencies = [ 1720 | "windows-link", 1721 | ] 1722 | 1723 | [[package]] 1724 | name = "windows-strings" 1725 | version = "0.3.1" 1726 | source = "registry+https://github.com/rust-lang/crates.io-index" 1727 | checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 1728 | dependencies = [ 1729 | "windows-link", 1730 | ] 1731 | 1732 | [[package]] 1733 | name = "windows-sys" 1734 | version = "0.52.0" 1735 | source = "registry+https://github.com/rust-lang/crates.io-index" 1736 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1737 | dependencies = [ 1738 | "windows-targets 0.52.6", 1739 | ] 1740 | 1741 | [[package]] 1742 | name = "windows-sys" 1743 | version = "0.59.0" 1744 | source = "registry+https://github.com/rust-lang/crates.io-index" 1745 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1746 | dependencies = [ 1747 | "windows-targets 0.52.6", 1748 | ] 1749 | 1750 | [[package]] 1751 | name = "windows-targets" 1752 | version = "0.52.6" 1753 | source = "registry+https://github.com/rust-lang/crates.io-index" 1754 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1755 | dependencies = [ 1756 | "windows_aarch64_gnullvm 0.52.6", 1757 | "windows_aarch64_msvc 0.52.6", 1758 | "windows_i686_gnu 0.52.6", 1759 | "windows_i686_gnullvm 0.52.6", 1760 | "windows_i686_msvc 0.52.6", 1761 | "windows_x86_64_gnu 0.52.6", 1762 | "windows_x86_64_gnullvm 0.52.6", 1763 | "windows_x86_64_msvc 0.52.6", 1764 | ] 1765 | 1766 | [[package]] 1767 | name = "windows-targets" 1768 | version = "0.53.0" 1769 | source = "registry+https://github.com/rust-lang/crates.io-index" 1770 | checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" 1771 | dependencies = [ 1772 | "windows_aarch64_gnullvm 0.53.0", 1773 | "windows_aarch64_msvc 0.53.0", 1774 | "windows_i686_gnu 0.53.0", 1775 | "windows_i686_gnullvm 0.53.0", 1776 | "windows_i686_msvc 0.53.0", 1777 | "windows_x86_64_gnu 0.53.0", 1778 | "windows_x86_64_gnullvm 0.53.0", 1779 | "windows_x86_64_msvc 0.53.0", 1780 | ] 1781 | 1782 | [[package]] 1783 | name = "windows_aarch64_gnullvm" 1784 | version = "0.52.6" 1785 | source = "registry+https://github.com/rust-lang/crates.io-index" 1786 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1787 | 1788 | [[package]] 1789 | name = "windows_aarch64_gnullvm" 1790 | version = "0.53.0" 1791 | source = "registry+https://github.com/rust-lang/crates.io-index" 1792 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 1793 | 1794 | [[package]] 1795 | name = "windows_aarch64_msvc" 1796 | version = "0.52.6" 1797 | source = "registry+https://github.com/rust-lang/crates.io-index" 1798 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1799 | 1800 | [[package]] 1801 | name = "windows_aarch64_msvc" 1802 | version = "0.53.0" 1803 | source = "registry+https://github.com/rust-lang/crates.io-index" 1804 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 1805 | 1806 | [[package]] 1807 | name = "windows_i686_gnu" 1808 | version = "0.52.6" 1809 | source = "registry+https://github.com/rust-lang/crates.io-index" 1810 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1811 | 1812 | [[package]] 1813 | name = "windows_i686_gnu" 1814 | version = "0.53.0" 1815 | source = "registry+https://github.com/rust-lang/crates.io-index" 1816 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 1817 | 1818 | [[package]] 1819 | name = "windows_i686_gnullvm" 1820 | version = "0.52.6" 1821 | source = "registry+https://github.com/rust-lang/crates.io-index" 1822 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1823 | 1824 | [[package]] 1825 | name = "windows_i686_gnullvm" 1826 | version = "0.53.0" 1827 | source = "registry+https://github.com/rust-lang/crates.io-index" 1828 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 1829 | 1830 | [[package]] 1831 | name = "windows_i686_msvc" 1832 | version = "0.52.6" 1833 | source = "registry+https://github.com/rust-lang/crates.io-index" 1834 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1835 | 1836 | [[package]] 1837 | name = "windows_i686_msvc" 1838 | version = "0.53.0" 1839 | source = "registry+https://github.com/rust-lang/crates.io-index" 1840 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 1841 | 1842 | [[package]] 1843 | name = "windows_x86_64_gnu" 1844 | version = "0.52.6" 1845 | source = "registry+https://github.com/rust-lang/crates.io-index" 1846 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1847 | 1848 | [[package]] 1849 | name = "windows_x86_64_gnu" 1850 | version = "0.53.0" 1851 | source = "registry+https://github.com/rust-lang/crates.io-index" 1852 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 1853 | 1854 | [[package]] 1855 | name = "windows_x86_64_gnullvm" 1856 | version = "0.52.6" 1857 | source = "registry+https://github.com/rust-lang/crates.io-index" 1858 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1859 | 1860 | [[package]] 1861 | name = "windows_x86_64_gnullvm" 1862 | version = "0.53.0" 1863 | source = "registry+https://github.com/rust-lang/crates.io-index" 1864 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 1865 | 1866 | [[package]] 1867 | name = "windows_x86_64_msvc" 1868 | version = "0.52.6" 1869 | source = "registry+https://github.com/rust-lang/crates.io-index" 1870 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1871 | 1872 | [[package]] 1873 | name = "windows_x86_64_msvc" 1874 | version = "0.53.0" 1875 | source = "registry+https://github.com/rust-lang/crates.io-index" 1876 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 1877 | 1878 | [[package]] 1879 | name = "wit-bindgen-rt" 1880 | version = "0.33.0" 1881 | source = "registry+https://github.com/rust-lang/crates.io-index" 1882 | checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" 1883 | dependencies = [ 1884 | "bitflags", 1885 | ] 1886 | 1887 | [[package]] 1888 | name = "write16" 1889 | version = "1.0.0" 1890 | source = "registry+https://github.com/rust-lang/crates.io-index" 1891 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 1892 | 1893 | [[package]] 1894 | name = "writeable" 1895 | version = "0.5.5" 1896 | source = "registry+https://github.com/rust-lang/crates.io-index" 1897 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 1898 | 1899 | [[package]] 1900 | name = "yoke" 1901 | version = "0.7.5" 1902 | source = "registry+https://github.com/rust-lang/crates.io-index" 1903 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 1904 | dependencies = [ 1905 | "serde", 1906 | "stable_deref_trait", 1907 | "yoke-derive", 1908 | "zerofrom", 1909 | ] 1910 | 1911 | [[package]] 1912 | name = "yoke-derive" 1913 | version = "0.7.5" 1914 | source = "registry+https://github.com/rust-lang/crates.io-index" 1915 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 1916 | dependencies = [ 1917 | "proc-macro2", 1918 | "quote", 1919 | "syn", 1920 | "synstructure", 1921 | ] 1922 | 1923 | [[package]] 1924 | name = "zerocopy" 1925 | version = "0.8.23" 1926 | source = "registry+https://github.com/rust-lang/crates.io-index" 1927 | checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" 1928 | dependencies = [ 1929 | "zerocopy-derive", 1930 | ] 1931 | 1932 | [[package]] 1933 | name = "zerocopy-derive" 1934 | version = "0.8.23" 1935 | source = "registry+https://github.com/rust-lang/crates.io-index" 1936 | checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" 1937 | dependencies = [ 1938 | "proc-macro2", 1939 | "quote", 1940 | "syn", 1941 | ] 1942 | 1943 | [[package]] 1944 | name = "zerofrom" 1945 | version = "0.1.6" 1946 | source = "registry+https://github.com/rust-lang/crates.io-index" 1947 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 1948 | dependencies = [ 1949 | "zerofrom-derive", 1950 | ] 1951 | 1952 | [[package]] 1953 | name = "zerofrom-derive" 1954 | version = "0.1.6" 1955 | source = "registry+https://github.com/rust-lang/crates.io-index" 1956 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 1957 | dependencies = [ 1958 | "proc-macro2", 1959 | "quote", 1960 | "syn", 1961 | "synstructure", 1962 | ] 1963 | 1964 | [[package]] 1965 | name = "zeroize" 1966 | version = "1.8.1" 1967 | source = "registry+https://github.com/rust-lang/crates.io-index" 1968 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 1969 | 1970 | [[package]] 1971 | name = "zerovec" 1972 | version = "0.10.4" 1973 | source = "registry+https://github.com/rust-lang/crates.io-index" 1974 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 1975 | dependencies = [ 1976 | "yoke", 1977 | "zerofrom", 1978 | "zerovec-derive", 1979 | ] 1980 | 1981 | [[package]] 1982 | name = "zerovec-derive" 1983 | version = "0.10.3" 1984 | source = "registry+https://github.com/rust-lang/crates.io-index" 1985 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 1986 | dependencies = [ 1987 | "proc-macro2", 1988 | "quote", 1989 | "syn", 1990 | ] 1991 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | license = "MIT" 3 | edition = "2024" 4 | version = "0.1.6" 5 | readme = "README.md" 6 | name = "openai_responses" 7 | authors = ["Miguel Piedrafita "] 8 | description = "Rust SDK for the OpenAI Responses API" 9 | homepage = "https://github.com/m1guelpf/openai-responses-rs" 10 | keywords = ["openai", "async", "openapi", "ai", "responses"] 11 | repository = "https://github.com/m1guelpf/openai-responses-rs" 12 | categories = ["api-bindings", "web-programming", "asynchronous"] 13 | 14 | [dependencies] 15 | macon = "1.3.0" 16 | thiserror = "2.0.12" 17 | serde_json = "1.0.140" 18 | futures = { version = "0.3.31", optional = true } 19 | chrono = { version = "0.4.40", features = ["serde"] } 20 | serde = { version = "1.0.219", features = ["derive"] } 21 | async-fn-stream = { version = "0.2.2", optional = true } 22 | reqwest-eventsource = { version = "0.6.0", optional = true } 23 | reqwest = { version = "0.12.14", features = ["json"], default-features = false } 24 | 25 | [features] 26 | default = ["rustls", "stream"] 27 | # Enable streaming responses 28 | stream = ["dep:reqwest-eventsource", "dep:futures", "dep:async-fn-stream"] 29 | # Enable rustls for TLS support 30 | rustls = ["reqwest/rustls-tls-native-roots"] 31 | # Enable rustls and webpki-roots 32 | rustls-webpki-roots = ["reqwest/rustls-tls-webpki-roots"] 33 | # Enable native-tls for TLS support 34 | native-tls = ["reqwest/native-tls"] 35 | # Remove dependency on OpenSSL 36 | native-tls-vendored = ["reqwest/native-tls-vendored"] 37 | 38 | [dev-dependencies] 39 | tokio = { version = "1.44.1", features = ["macros", "rt", "rt-multi-thread"] } 40 | 41 | [package.metadata.docs.rs] 42 | all-features = true 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Miguel Piedrafita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenAI Responses SDK 2 | 3 | [![crates.io](https://img.shields.io/crates/v/openai_responses.svg)](https://crates.io/crates/openai_responses) 4 | [![download count badge](https://img.shields.io/crates/d/openai_responses.svg)](https://crates.io/crates/openai_responses) 5 | [![docs.rs](https://img.shields.io/badge/docs-latest-blue.svg)](https://docs.rs/openai_responses) 6 | 7 | An unofficial Rust SDK for the [OpenAI Responses API](https://platform.openai.com/docs/api-reference/responses). 8 | 9 | ## Usage 10 | 11 | To get started, create a new `Client` and call the `create` method with a `Request` object. The `Request` object contains the parameters for the API call, such as the model, instructions, and input. The `create` method returns a `Response` object, which contains the output of the API call. 12 | 13 | ```rust ignore 14 | use openai_responses::{Client, Request, types::{Input, Model}}; 15 | 16 | let response = Client::from_env()?.create(Request { 17 | model: Model::GPT4o, 18 | input: Input::Text("Are semicolons optional in JavaScript?".to_string()), 19 | instructions: Some("You are a coding assistant that talks like a pirate".to_string()), 20 | ..Default::default() 21 | }).await?; 22 | 23 | println!("{}", response.output_text()); 24 | ``` 25 | 26 | To stream the response as it is generated, use the `stream` method: 27 | 28 | ```rust ignore 29 | use openai_responses::{Client, Request}; 30 | 31 | // You can also build the `Request` struct with a fluent interface 32 | let mut stream = Client::from_env()?.stream( 33 | Request::builder() 34 | .model("gpt-4o") 35 | .input("Are semicolons optional in JavaScript?") 36 | .instructions("You are a coding assistant that talks like a pirate") 37 | .build() 38 | ); 39 | 40 | while let Some(event) = stream.next().await { 41 | dbg!(event?); 42 | } 43 | ``` 44 | 45 | ## License 46 | 47 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 48 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)] 2 | #![allow(clippy::doc_markdown)] 3 | #![doc = include_str!("../README.md")] 4 | 5 | use reqwest::{ 6 | Client as Http, StatusCode, 7 | header::{self, HeaderMap, HeaderValue}, 8 | }; 9 | use serde_json::json; 10 | use std::env; 11 | use types::{Error, Include, InputItemList, Request, Response, ResponseResult}; 12 | #[cfg(feature = "stream")] 13 | use { 14 | async_fn_stream::try_fn_stream, 15 | futures::{Stream, StreamExt}, 16 | reqwest_eventsource::{Event as EventSourceEvent, RequestBuilderExt}, 17 | types::Event, 18 | }; 19 | 20 | /// Types for interacting with the Responses API. 21 | pub mod types; 22 | 23 | /// The OpenAI Responses API Client. 24 | #[derive(Debug, Clone)] 25 | pub struct Client { 26 | client: reqwest::Client, 27 | } 28 | 29 | /// Errors that can occur when creating a new Client. 30 | #[derive(Debug, thiserror::Error)] 31 | pub enum CreateError { 32 | /// The provided API key contains invalid header value characters. Only visible ASCII characters (32-127) are permitted. 33 | #[error( 34 | "The provided API key contains invalid header value characters. Only visible ASCII characters (32-127) are permitted." 35 | )] 36 | InvalidApiKey, 37 | /// Failed to create the HTTP Client 38 | #[error("Failed to create the HTTP Client: {0}")] 39 | CouldNotCreateClient(#[from] reqwest::Error), 40 | /// Could not retrieve the ``OPENAI_API_KEY`` env var 41 | #[error("Could not retrieve the $OPENAI_API_KEY env var")] 42 | ApiKeyNotFound, 43 | } 44 | 45 | #[cfg(feature = "stream")] 46 | #[derive(Debug, thiserror::Error)] 47 | pub enum StreamError { 48 | #[error("{0}")] 49 | Stream(#[from] reqwest_eventsource::Error), 50 | #[error("Failed to parse event data: {0}")] 51 | Parsing(#[from] serde_json::Error), 52 | } 53 | 54 | impl Client { 55 | /// Creates a new Client with the given API key. 56 | /// 57 | /// # Errors 58 | /// - `CreateError::CouldNotCreateClient` if the HTTP Client could not be created. 59 | /// - `CreateError::InvalidApiKey` if the API key contains invalid header value characters. 60 | pub fn new(api_key: &str) -> Result { 61 | let client = Http::builder() 62 | .default_headers(HeaderMap::from_iter([( 63 | header::AUTHORIZATION, 64 | HeaderValue::from_str(&format!("Bearer {api_key}")) 65 | .map_err(|_| CreateError::InvalidApiKey)?, 66 | )])) 67 | .build()?; 68 | 69 | Ok(Self { client }) 70 | } 71 | 72 | /// Creates a new Client from the `OPENAI_API_KEY` environment variable. 73 | /// 74 | /// # Errors 75 | /// - `CreateError::CouldNotCreateClient` if the HTTP Client could not be created. 76 | /// - `CreateError::InvalidApiKey` if the API key contains invalid header value characters. 77 | /// - `CreateError::ApiKeyNotFound` if the `OPENAI_API_KEY` environment variable is not set or contains an equal sign or NUL (`'='` or `'\0'`). 78 | pub fn from_env() -> Result { 79 | let api_key = env::var("OPENAI_API_KEY").map_err(|_| CreateError::ApiKeyNotFound)?; 80 | 81 | Self::new(&api_key) 82 | } 83 | 84 | /// Creates a model response. 85 | /// 86 | /// Provide [text](https://platform.openai.com/docs/guides/text) or [image](https://platform.openai.com/docs/guides/images) inputs to generate [text](https://platform.openai.com/docs/guides/text) or [JSON](https://platform.openai.com/docs/guides/structured-outputs) outputs. 87 | /// Have the model call your own [custom code](https://platform.openai.com/docs/guides/function-calling) or use built-in [tools](https://platform.openai.com/docs/guides/tools) like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search) to use your own data as input for the model's response. 88 | /// To receive a stream of tokens as they are generated, use the `stream` function instead. 89 | /// 90 | /// ## Errors 91 | /// 92 | /// Errors if the request fails to send or has a non-200 status code (except for 400, which will return an OpenAI error instead). 93 | pub async fn create( 94 | &self, 95 | mut request: Request, 96 | ) -> Result, reqwest::Error> { 97 | // Use the `stream` function to stream the response. 98 | request.stream = Some(false); 99 | 100 | let mut response = self 101 | .client 102 | .post("https://api.openai.com/v1/responses") 103 | .json(&request) 104 | .send() 105 | .await?; 106 | 107 | if response.status() != StatusCode::BAD_REQUEST { 108 | response = response.error_for_status()?; 109 | } 110 | 111 | response.json::().await.map(Into::into) 112 | } 113 | 114 | #[cfg(feature = "stream")] 115 | /// Creates a model response and streams it back as it is generated. 116 | /// 117 | /// Provide [text](https://platform.openai.com/docs/guides/text) or [image](https://platform.openai.com/docs/guides/images) inputs to generate [text](https://platform.openai.com/docs/guides/text) or [JSON](https://platform.openai.com/docs/guides/structured-outputs) outputs. 118 | /// Have the model call your own [custom code](https://platform.openai.com/docs/guides/function-calling) or use built-in [tools](https://platform.openai.com/docs/guides/tools) like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search) to use your own data as input for the model's response. 119 | /// 120 | /// To receive the response as a regular HTTP response, use the `create` function. 121 | pub fn stream(&self, mut request: Request) -> impl Stream> { 122 | // Use the `create` function to receive a regular HTTP response. 123 | request.stream = Some(true); 124 | 125 | let mut event_source = self 126 | .client 127 | .post("https://api.openai.com/v1/responses") 128 | .json(&request) 129 | .eventsource() 130 | .unwrap_or_else(|_| unreachable!("Body is never a stream")); 131 | 132 | let stream = try_fn_stream(|emitter| async move { 133 | while let Some(event) = event_source.next().await { 134 | let message = match event { 135 | Ok(EventSourceEvent::Open) => continue, 136 | Ok(EventSourceEvent::Message(message)) => message, 137 | Err(error) => { 138 | if matches!(error, reqwest_eventsource::Error::StreamEnded) { 139 | break; 140 | } 141 | 142 | emitter.emit_err(StreamError::Stream(error)).await; 143 | continue; 144 | } 145 | }; 146 | 147 | match serde_json::from_str::(&message.data) { 148 | Ok(event) => emitter.emit(event).await, 149 | Err(error) => emitter.emit_err(StreamError::Parsing(error)).await, 150 | } 151 | } 152 | 153 | Ok(()) 154 | }); 155 | 156 | Box::pin(stream) 157 | } 158 | 159 | /// Retrieves a model response with the given ID. 160 | /// 161 | /// ## Errors 162 | /// 163 | /// Errors if the request fails to send or has a non-200 status code (except for 400, which will return an OpenAI error instead). 164 | pub async fn get( 165 | &self, 166 | response_id: &str, 167 | include: Option, 168 | ) -> Result, reqwest::Error> { 169 | let mut response = self 170 | .client 171 | .get(format!("https://api.openai.com/v1/responses/{response_id}")) 172 | .query(&json!({ "include": include })) 173 | .send() 174 | .await?; 175 | 176 | if response.status() != StatusCode::BAD_REQUEST { 177 | response = response.error_for_status()?; 178 | } 179 | 180 | response.json::().await.map(Into::into) 181 | } 182 | 183 | /// Deletes a model response with the given ID. 184 | /// 185 | /// ## Errors 186 | /// 187 | /// Errors if the request fails to send or has a non-200 status code. 188 | pub async fn delete(&self, response_id: &str) -> Result<(), reqwest::Error> { 189 | self.client 190 | .delete(format!("https://api.openai.com/v1/responses/{response_id}")) 191 | .send() 192 | .await? 193 | .error_for_status()?; 194 | 195 | Ok(()) 196 | } 197 | 198 | /// Returns a list of input items for a given response. 199 | /// 200 | /// ## Errors 201 | /// 202 | /// Errors if the request fails to send or has a non-200 status code. 203 | pub async fn list_inputs(&self, response_id: &str) -> Result { 204 | self.client 205 | .get(format!( 206 | "https://api.openai.com/v1/responses/{response_id}/inputs" 207 | )) 208 | .send() 209 | .await? 210 | .error_for_status()? 211 | .json() 212 | .await 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | pub mod config; 2 | mod helpers; 3 | pub mod item; 4 | pub mod request; 5 | pub mod response; 6 | #[cfg(feature = "stream")] 7 | pub mod stream; 8 | pub mod tools; 9 | 10 | pub use config::*; 11 | pub use item::*; 12 | pub use request::*; 13 | pub use response::*; 14 | #[cfg(feature = "stream")] 15 | pub use stream::*; 16 | pub use tools::*; 17 | 18 | /// The model to use for generating a response. 19 | #[allow(non_camel_case_types)] 20 | #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] 21 | pub enum Model { 22 | o1, 23 | #[serde(rename = "o1-mini")] 24 | o1Mini, 25 | #[serde(rename = "o1-pro")] 26 | o1Pro, 27 | #[serde(rename = "o3-mini")] 28 | o3Mini, 29 | #[serde(rename = "gpt-4.5-preview")] 30 | GPT4_5Preview, 31 | #[serde(rename = "gpt-4o")] 32 | GPT4o, 33 | #[serde(rename = "gpt-4o-mini")] 34 | GPT4oMini, 35 | #[serde(rename = "gpt-4o-turbo")] 36 | GPT4Turbo, 37 | #[serde(rename = "gpt-4")] 38 | GPT4, 39 | #[serde(rename = "gpt-3.5-turbo")] 40 | GPT3_5Turbo, 41 | #[serde(rename = "computer-use-preview")] 42 | ComputerUsePreview, 43 | #[serde(untagged)] 44 | Other(String), 45 | } 46 | 47 | /// The role of a message. 48 | #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] 49 | #[serde(rename_all = "lowercase")] 50 | pub enum Role { 51 | User, 52 | System, 53 | Assistant, 54 | Developer, 55 | } 56 | -------------------------------------------------------------------------------- /src/types/config.rs: -------------------------------------------------------------------------------- 1 | use macon::Builder; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | /// The truncation strategy to use for the model response. 5 | #[derive(Debug, Clone, Default, Serialize, Deserialize)] 6 | #[serde(rename_all = "lowercase")] 7 | pub enum Truncation { 8 | /// If the context of this response and previous ones exceeds the model's context window size, the model will truncate the response to fit the context window by dropping input items in the middle of the conversation. 9 | Auto, 10 | /// If a model response will exceed the context window size for a model, the request will fail with a 400 error. 11 | #[default] 12 | Disabled, 13 | } 14 | 15 | /// Configuration options for a text response from the model. Can be plain text or structured JSON data. 16 | /// 17 | /// Learn more: 18 | /// - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) 19 | /// - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) 20 | #[derive(Debug, Clone, Builder, Default, Serialize, Deserialize)] 21 | pub struct TextConfig { 22 | /// An object specifying the format that the model must output. 23 | pub format: TextFormat, 24 | } 25 | 26 | /// An object specifying the format that the model must output. 27 | #[derive(Debug, Clone, Default, Serialize, Deserialize)] 28 | #[serde(tag = "type", rename_all = "snake_case")] 29 | pub enum TextFormat { 30 | /// Used to generate text responses. 31 | #[default] 32 | Text, 33 | /// JSON Schema response format. Used to generate structured JSON responses. Learn more about [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs). 34 | JsonSchema { 35 | /// The schema for the response format, described as a JSON Schema object. Learn how to build JSON schemas [here](https://json-schema.org/). 36 | schema: serde_json::Value, 37 | /// A description of what the response format is for, used by the model to determine how to respond in the format. 38 | description: String, 39 | /// The name of the response format. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. 40 | name: String, 41 | /// Whether to enable strict schema adherence when generating the output. 42 | /// If set to true, the model will always follow the exact schema defined in the schema field. Only a subset of JSON Schema is supported when strict is true. 43 | /// To learn more, read the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). 44 | strict: Option, 45 | }, 46 | /// JSON object response format. An older method of generating JSON responses. 47 | /// Using `JsonSchema` is recommended for models that support it. 48 | /// Note that the model will not generate JSON without a system or user message instructing it to do so. 49 | JsonObject, 50 | } 51 | 52 | /// Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). 53 | /// Only available for o-series models. 54 | #[derive(Debug, Clone, Default, Builder, Serialize, Deserialize)] 55 | pub struct ReasoningConfig { 56 | /// Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. 57 | pub effort: Option, 58 | /// A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. 59 | pub generate_summary: Option, 60 | } 61 | 62 | /// Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). 63 | /// 64 | /// Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. 65 | #[derive(Debug, Clone, Serialize, Deserialize)] 66 | #[serde(rename_all = "lowercase")] 67 | pub enum ReasoningEffort { 68 | Low, 69 | High, 70 | Medium, 71 | } 72 | 73 | /// A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. 74 | #[derive(Debug, Clone, Serialize, Deserialize)] 75 | #[serde(rename_all = "lowercase")] 76 | pub enum SummaryConfig { 77 | Concise, 78 | Detailed, 79 | } 80 | 81 | /// The latency tier to use for processing the request. 82 | #[derive(Debug, Clone, Serialize, Deserialize, Default)] 83 | #[serde(rename_all = "lowercase")] 84 | pub enum ServiceTier { 85 | #[default] 86 | Auto, 87 | Flex, 88 | Default, 89 | } 90 | -------------------------------------------------------------------------------- /src/types/helpers.rs: -------------------------------------------------------------------------------- 1 | use super::{ContentInput, ContentItem, Input, InputItem, InputListItem, InputMessage, Model}; 2 | 3 | macro_rules! string_variant { 4 | ($name:ident, $variant:ident) => { 5 | impl From for $name { 6 | fn from(value: String) -> Self { 7 | Self::$variant(value) 8 | } 9 | } 10 | impl From<&str> for $name { 11 | fn from(value: &str) -> Self { 12 | Self::from(value.to_string()) 13 | } 14 | } 15 | }; 16 | } 17 | 18 | macro_rules! string_variant_var { 19 | ($name:ident, $variant:ident, $key:ident) => { 20 | impl From for $name { 21 | fn from(value: String) -> Self { 22 | Self::$variant { $key: value } 23 | } 24 | } 25 | impl From<&str> for $name { 26 | fn from(value: &str) -> Self { 27 | Self::from(value.to_string()) 28 | } 29 | } 30 | }; 31 | } 32 | 33 | impl From for InputListItem { 34 | fn from(value: InputMessage) -> Self { 35 | Self::Message(value) 36 | } 37 | } 38 | impl From for InputListItem { 39 | fn from(value: InputItem) -> Self { 40 | Self::Item(value) 41 | } 42 | } 43 | 44 | string_variant!(Input, Text); 45 | string_variant!(ContentInput, Text); 46 | string_variant_var!(ContentItem, Text, text); 47 | 48 | impl From for Model { 49 | fn from(s: String) -> Self { 50 | match s.as_str() { 51 | "o1" => Self::o1, 52 | "gpt-4" => Self::GPT4, 53 | "gpt-4o" => Self::GPT4o, 54 | "o1-mini" => Self::o1Mini, 55 | "o3-mini" => Self::o3Mini, 56 | "gpt-4o-mini" => Self::GPT4oMini, 57 | "gpt-4o-turbo" => Self::GPT4Turbo, 58 | "gpt-3.5-turbo" => Self::GPT3_5Turbo, 59 | "gpt-4.5-preview" => Self::GPT4_5Preview, 60 | "computer-use-preview" => Self::ComputerUsePreview, 61 | _ => Self::Other(s), 62 | } 63 | } 64 | } 65 | 66 | impl From<&str> for Model { 67 | fn from(s: &str) -> Self { 68 | Self::from(s.to_string()) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/types/item.rs: -------------------------------------------------------------------------------- 1 | use super::{APIInputMessage, Role}; 2 | use serde::{Deserialize, Serialize}; 3 | use std::collections::HashMap; 4 | 5 | /// Content items generated by the model. 6 | #[derive(Debug, Clone, Serialize, Deserialize)] 7 | #[serde(tag = "type", rename_all = "snake_case")] 8 | pub enum OutputItem { 9 | /// An output message from the model. 10 | Message(OutputMessage), 11 | /// The results of a file search tool call. See the [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more information. 12 | #[serde(rename = "file_search_call")] 13 | FileSearch(FileSearchCall), 14 | /// A tool call to run a function. See the [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more information. 15 | FunctionCall(FunctionCall), 16 | /// The results of a web search tool call. See the [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more information. 17 | #[serde(rename = "web_search_call")] 18 | WebSearchResults(WebSearchCall), 19 | /// A tool call to a computer use tool. See the [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more information. 20 | #[serde(rename = "computer_call")] 21 | ComputerToolCall(ComputerToolCall), 22 | /// A description of the chain of thought used by a reasoning model while generating a response. 23 | Reasoning(Reasoning), 24 | } 25 | 26 | /// An item representing part of the context for the response to be generated by the model. 27 | /// 28 | /// Can contain text, images, and audio inputs, as well as previous assistant responses and tool call outputs. 29 | #[derive(Debug, Clone, Serialize, Deserialize)] 30 | #[serde(tag = "type", rename_all = "snake_case")] 31 | pub enum InputItem { 32 | /// A message input to the model with a role indicating instruction following hierarchy. 33 | /// 34 | /// Instructions given with the `Developer` or `System` role take precedence over instructions given with the `User` role. 35 | #[serde(rename = "message")] 36 | InputMessage(APIInputMessage), 37 | /// An output message from the model. 38 | #[serde(rename = "message")] 39 | OutputMessage(OutputMessage), 40 | /// The results of a file search tool call. 41 | /// 42 | /// See the [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more information. 43 | #[serde(rename = "file_search_call")] 44 | FileSearch(FileSearchCall), 45 | /// A tool call to a computer use tool. 46 | /// 47 | /// See the [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more information. 48 | #[serde(rename = "computer_call")] 49 | ComputerToolCall(ComputerToolCall), 50 | /// The output of a computer tool call. 51 | #[serde(rename = "computer_call_output")] 52 | ComputerToolCallOutput(ComputerToolCallOutput), 53 | /// The results of a web search tool call. 54 | /// 55 | /// See the [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more information. 56 | #[serde(rename = "web_search_call")] 57 | WebSearchResults(WebSearchCall), 58 | /// A tool call to run a function. 59 | /// 60 | /// See the [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more information. 61 | FunctionCall(FunctionCall), 62 | /// The output of a function tool call. 63 | FunctionCallOutput(FunctionCallOutput), 64 | /// A description of the chain of thought used by a reasoning model while generating a response. 65 | Reasoning(Reasoning), 66 | } 67 | 68 | /// An output message from the model. 69 | #[derive(Debug, Clone, Serialize, Deserialize)] 70 | pub struct OutputMessage { 71 | /// The content of the output message. 72 | pub content: Vec, 73 | /// The unique ID of the output message. 74 | pub id: String, 75 | /// The role of the output message. Always `Assistant`. 76 | pub role: Role, 77 | /// The status of the message input. 78 | pub status: MessageStatus, 79 | } 80 | 81 | /// The content of the output message. 82 | #[derive(Debug, Clone, Serialize, Deserialize)] 83 | #[serde(tag = "type", rename_all = "snake_case")] 84 | pub enum OutputContent { 85 | /// A text output from the model. 86 | #[serde(rename = "output_text")] 87 | Text { 88 | /// The text output from the model. 89 | text: String, 90 | /// The annotations of the text output. 91 | annotations: Vec, 92 | }, 93 | /// A refusal from the model. 94 | Refusal { 95 | /// The refusal explanation from the model. 96 | refusal: String, 97 | }, 98 | } 99 | 100 | /// An annotation of the text output. 101 | #[derive(Debug, Clone, Serialize, Deserialize)] 102 | #[serde(tag = "type", rename_all = "snake_case")] 103 | pub enum Annotation { 104 | /// A citation to a file. 105 | FileCitation { 106 | /// The ID of the file. 107 | file_id: String, 108 | /// The index of the file in the list of files. 109 | index: u64, 110 | }, 111 | #[serde(rename = "url_citation")] 112 | /// A citation for a web resource used to generate a model response. 113 | URLCitation { 114 | /// The index of the last character of the URL citation in the message. 115 | end_index: u64, 116 | /// The index of the first character of the URL citation in the message. 117 | start_index: u64, 118 | /// The title of the web resource. 119 | title: String, 120 | /// The URL of the web resource. 121 | url: String, 122 | }, 123 | /// A path to a file. 124 | FilePath { 125 | /// The ID of the file. 126 | file_id: String, 127 | /// The index of the file in the list of files. 128 | index: u64, 129 | }, 130 | } 131 | 132 | /// The status of a message. 133 | #[derive(Debug, Clone, Copy, Serialize, Deserialize)] 134 | #[serde(rename_all = "snake_case")] 135 | pub enum MessageStatus { 136 | InProgress, 137 | Completed, 138 | Incomplete, 139 | } 140 | 141 | /// The results of a file search tool call. 142 | /// 143 | /// See the [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more information. 144 | #[derive(Debug, Clone, Serialize, Deserialize)] 145 | pub struct FileSearchCall { 146 | /// The unique ID of the file search tool call. 147 | pub id: String, 148 | /// The queries used to search for files. 149 | pub queries: Vec, 150 | /// The status of the file search tool call. 151 | pub status: FileSearchStatus, 152 | /// The results of the file search tool call. 153 | pub results: Option>, 154 | } 155 | 156 | /// A result of the file search tool call. 157 | /// 158 | /// See the [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more information. 159 | #[derive(Debug, Clone, Serialize, Deserialize)] 160 | pub struct FileSearchResult { 161 | /// Set of 16 key-value pairs that can be attached to an object. 162 | /// 163 | /// This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. 164 | /// Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. 165 | pub attributes: HashMap, 166 | /// The unique ID of the file. 167 | pub file_id: String, 168 | /// The name of the file. 169 | pub filename: String, 170 | /// The relevance score of the file - a value between 0 and 1. 171 | pub score: f32, 172 | /// The text that was retrieved from the file. 173 | pub text: String, 174 | } 175 | 176 | /// The status of the file search tool call. 177 | /// 178 | /// See the [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more information. 179 | #[derive(Debug, Clone, Copy, Serialize, Deserialize)] 180 | #[serde(rename_all = "snake_case")] 181 | pub enum FileSearchStatus { 182 | Completed, 183 | InProgress, 184 | Searching, 185 | Incomplete, 186 | Failed, 187 | } 188 | 189 | /// A tool call to run a function. 190 | /// 191 | /// See the [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more information. 192 | #[derive(Debug, Clone, Serialize, Deserialize)] 193 | pub struct FunctionCall { 194 | /// A JSON string of the arguments to pass to the function. 195 | pub arguments: String, 196 | /// The unique ID of the function tool call generated by the model. 197 | pub call_id: String, 198 | /// The unique ID of the function tool call. 199 | pub id: Option, 200 | /// The name of the function to run. 201 | pub name: String, 202 | /// The status of the item. 203 | pub status: Option, 204 | } 205 | 206 | /// The status of the function call. 207 | /// 208 | /// See the [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more information. 209 | #[derive(Debug, Clone, Copy, Serialize, Deserialize)] 210 | #[serde(rename_all = "snake_case")] 211 | pub enum FunctionCallStatus { 212 | InProgress, 213 | Completed, 214 | Incomplete, 215 | } 216 | 217 | /// The output of a function call. 218 | /// 219 | /// See the [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more information. 220 | #[derive(Debug, Clone, Serialize, Deserialize)] 221 | pub struct FunctionCallOutput { 222 | /// The unique ID of the function tool call output. Populated when this item is returned via API. 223 | pub id: Option, 224 | /// The status of the item. Populated when items are returned via API. 225 | pub status: Option, 226 | /// The ID of the computer tool call that produced the output. 227 | pub call_id: String, 228 | /// A JSON string of the output of the function tool call. 229 | pub output: String, 230 | } 231 | 232 | /// A tool call to run a web search. 233 | /// 234 | /// See the [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more information. 235 | #[derive(Debug, Clone, Serialize, Deserialize)] 236 | pub struct WebSearchCall { 237 | /// The unique ID of the web search tool call. 238 | pub id: String, 239 | /// The status of the web search tool call. 240 | pub status: String, 241 | } 242 | 243 | /// A tool call to run a computer action. 244 | /// 245 | /// See the [computer action guide](https://platform.openai.com/docs/guides/tools-computer-use) for more information. 246 | #[derive(Debug, Clone, Serialize, Deserialize)] 247 | pub struct ComputerToolCall { 248 | /// The action to execute. 249 | pub action: ComputerAction, 250 | /// The unique ID of the computer call. 251 | pub call_id: String, 252 | /// The pending safety checks for the computer call. 253 | pub pending_safety_checks: Vec, 254 | /// The status of the item. 255 | pub status: ComputerCallStatus, 256 | } 257 | 258 | /// The action of the computer call. 259 | /// 260 | /// See the [computer action guide](https://platform.openai.com/docs/guides/tools-computer-use) for more information. 261 | #[derive(Debug, Clone, Serialize, Deserialize)] 262 | #[serde(tag = "type", rename_all = "snake_case")] 263 | pub enum ComputerAction { 264 | /// A click action. 265 | Click { 266 | /// Indicates which mouse button was pressed during the click. 267 | button: ClickButton, 268 | /// The x-coordinate where the click occurred. 269 | x: u64, 270 | /// The y-coordinate where the click occurred. 271 | y: u64, 272 | }, 273 | /// A double click action. 274 | DoubleClick { 275 | /// The x-coordinate where the double click occurred. 276 | x: u64, 277 | /// The y-coordinate where the double click occurred. 278 | y: u64, 279 | }, 280 | /// A drag action. 281 | Drag { 282 | /// An array of coordinates representing the path of the drag action. 283 | path: Vec, 284 | }, 285 | #[serde(rename = "keypress")] 286 | KeyPress { 287 | /// The combination of keys the model is requesting to be pressed. 288 | keys: Vec, 289 | }, 290 | /// A mouse move action. 291 | Move { 292 | /// The x-coordinate to move to. 293 | x: u64, 294 | /// The y-coordinate to move to. 295 | y: u64, 296 | }, 297 | /// A screenshot action. 298 | Screenshot, 299 | /// A scroll action. 300 | Scroll { 301 | /// The horizontal scroll distance. 302 | scroll_x: u64, 303 | /// The vertical scroll distance. 304 | scroll_y: u64, 305 | /// The x-coordinate where the scroll occurred. 306 | x: u64, 307 | /// The y-coordinate where the scroll occurred. 308 | y: u64, 309 | }, 310 | /// An action to type in text. 311 | Type { 312 | /// The text to type. 313 | text: String, 314 | }, 315 | /// A wait action. 316 | Wait, 317 | } 318 | 319 | /// Indicates which mouse button was pressed during the click. 320 | #[derive(Debug, Clone, Serialize, Deserialize)] 321 | #[serde(rename_all = "snake_case")] 322 | pub enum ClickButton { 323 | Left, 324 | Right, 325 | Wheel, 326 | Back, 327 | Forward, 328 | } 329 | 330 | /// Represents a coordinate in a drag action. 331 | #[derive(Debug, Clone, Serialize, Deserialize)] 332 | pub struct DragCoordinate { 333 | /// The x-coordinate of the drag action. 334 | pub x: u64, 335 | /// The y-coordinate of the drag action. 336 | pub y: u64, 337 | } 338 | 339 | /// Represents a pending safety check for a computer use call. 340 | #[derive(Debug, Clone, Serialize, Deserialize)] 341 | pub struct SafetyCheck { 342 | /// The type of the pending safety check. 343 | pub code: String, 344 | /// The ID of the pending safety check. 345 | pub id: String, 346 | /// Details about the pending safety check. 347 | pub message: String, 348 | } 349 | 350 | /// The status of the computer use call. 351 | /// 352 | /// See the [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more information. 353 | #[derive(Debug, Clone, Copy, Serialize, Deserialize)] 354 | #[serde(rename_all = "snake_case")] 355 | pub enum ComputerCallStatus { 356 | InProgress, 357 | Completed, 358 | Incomplete, 359 | } 360 | 361 | /// The output of a computer use call. 362 | #[derive(Debug, Clone, Serialize, Deserialize)] 363 | pub struct ComputerToolCallOutput { 364 | /// The ID of the computer tool call output. Populated when this item is returned via API. 365 | pub id: Option, 366 | /// The status of the item. Populated when items are returned via API. 367 | pub status: Option, 368 | /// The ID of the computer tool call that produced the output. 369 | pub call_id: String, 370 | /// A computer screenshot image used with the computer use tool. 371 | pub output: ComputerCallOutput, 372 | /// The safety checks reported by the API that have been acknowledged by the developer. 373 | pub acknowledged_safety_checks: Option>, 374 | } 375 | 376 | /// A computer screenshot image used with the computer use tool. 377 | #[derive(Debug, Clone, Serialize, Deserialize)] 378 | #[serde(tag = "type", rename_all = "snake_case")] 379 | pub enum ComputerCallOutput { 380 | /// A computer screenshot image used with the computer use tool. 381 | #[serde(rename = "computer_screenshot")] 382 | Screenshot { 383 | /// The identifier of an uploaded file that contains the screenshot. 384 | file_id: Option, 385 | /// The URL of the screenshot image. 386 | image_url: Option, 387 | }, 388 | } 389 | 390 | /// A description of the chain of thought used by a reasoning model while generating a response. 391 | #[derive(Debug, Clone, Serialize, Deserialize)] 392 | pub struct Reasoning { 393 | /// The unique identifier of the reasoning content. 394 | pub id: String, 395 | /// Reasoning text contents. 396 | pub summary: Vec, 397 | /// The status of the item. 398 | pub status: ReasoningStatus, 399 | } 400 | 401 | /// Reasoning text contents. 402 | #[derive(Debug, Clone, Serialize, Deserialize)] 403 | #[serde(tag = "type")] 404 | pub enum ReasoningSummary { 405 | #[serde(rename = "summary_text")] 406 | Text { 407 | /// A short summary of the reasoning used by the model when generating the response. 408 | text: String, 409 | }, 410 | } 411 | 412 | /// The status of the reasoning data. 413 | #[derive(Debug, Clone, Copy, Serialize, Deserialize)] 414 | #[serde(rename_all = "snake_case")] 415 | pub enum ReasoningStatus { 416 | InProgress, 417 | Completed, 418 | Incomplete, 419 | } 420 | -------------------------------------------------------------------------------- /src/types/request.rs: -------------------------------------------------------------------------------- 1 | use macon::Builder; 2 | use serde::{Deserialize, Serialize}; 3 | use std::collections::HashMap; 4 | 5 | use super::{ 6 | InputItem, MessageStatus, Model, ReasoningConfig, Role, ServiceTier, TextConfig, Tool, 7 | ToolChoice, Truncation, 8 | }; 9 | 10 | /// The Request object. 11 | #[derive(Debug, Clone, Builder, Serialize, Deserialize)] 12 | pub struct Request { 13 | /// Model ID used to generate the response. 14 | /// OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. 15 | pub model: Model, 16 | /// Text, image, or file inputs to the model, used to generate a response. 17 | pub input: Input, 18 | /// Specify additional output data to include in the model response. 19 | pub include: Option>, 20 | /// Inserts a system (or developer) message as the first item in the model's context. 21 | /// When using along with `previous_response_id`, the instructions from a previous response will be not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. 22 | pub instructions: Option, 23 | /// An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). 24 | pub max_output_tokens: Option, 25 | /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. 26 | /// Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. 27 | pub metadata: Option>, 28 | /// Whether to allow the model to run tool calls in parallel. 29 | pub parallel_tool_calls: Option, 30 | /// The unique ID of the previous response to the model. Use this to create multi-turn conversations. 31 | /// Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). 32 | pub previous_response_id: Option, 33 | /// Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). 34 | pub reasoning: Option, 35 | /// Specifies the latency tier to use for processing the request. 36 | pub service_tier: Option, 37 | /// Whether to store the generated model response for later retrieval via API. 38 | pub store: Option, 39 | /// If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format). 40 | /// 41 | /// This flag is automatically set depending on the function you call, so it's best to not touch it. 42 | #[doc(hidden)] 43 | pub stream: Option, 44 | /// What sampling temperature to use, between 0 and 2. 45 | /// Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. 46 | /// We generally recommend altering this or `top_p` but not both. 47 | pub temperature: Option, 48 | /// Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: 49 | /// - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) 50 | /// - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) 51 | pub text: Option, 52 | /// How the model should select which tool (or tools) to use when generating a response. 53 | /// 54 | /// See the `tools` parameter to see how to specify which tools the model can call. 55 | pub tool_choice: Option, 56 | /// An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. 57 | /// The two categories of tools you can provide the model are: 58 | /// - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). 59 | /// - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). 60 | pub tools: Option>, 61 | /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with `top_p` probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. 62 | /// We generally recommend altering this or `temperature` but not both. 63 | pub top_p: Option, 64 | /// The truncation strategy to use for the model response. 65 | pub truncation: Option, 66 | /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). 67 | pub user: Option, 68 | } 69 | 70 | impl Default for Request { 71 | fn default() -> Self { 72 | Self { 73 | user: None, 74 | text: None, 75 | tools: None, 76 | store: None, 77 | top_p: None, 78 | stream: None, 79 | include: None, 80 | metadata: None, 81 | reasoning: None, 82 | truncation: None, 83 | tool_choice: None, 84 | temperature: None, 85 | instructions: None, 86 | service_tier: None, 87 | model: Model::GPT4o, 88 | max_output_tokens: None, 89 | parallel_tool_calls: None, 90 | previous_response_id: None, 91 | input: Input::Text(String::new()), 92 | } 93 | } 94 | } 95 | 96 | /// Text, image, or file inputs to the model, used to generate a response. 97 | #[derive(Debug, Clone, Serialize, Deserialize)] 98 | #[serde(untagged)] 99 | pub enum Input { 100 | /// A text input to the model, equivalent to a text input with the user role. 101 | Text(String), 102 | /// A list of one or many input items to the model, containing different content types. 103 | List(Vec), 104 | } 105 | 106 | /// One or many input items to the model, containing different content types. 107 | #[derive(Debug, Clone, Serialize, Deserialize)] 108 | #[serde(tag = "type", rename_all = "snake_case")] 109 | pub enum InputListItem { 110 | /// A message input to the model with a role indicating instruction following hierarchy. 111 | /// Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. 112 | /// Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. 113 | Message(InputMessage), 114 | /// An internal identifier for an item to reference. 115 | #[serde(rename = "item_reference")] 116 | ItemRef { 117 | /// The ID of the item to reference. 118 | id: String, 119 | }, 120 | /// An item representing part of the context for the response to be generated by the model. 121 | /// Can contain text, images, and audio inputs, as well as previous assistant responses and tool call outputs. 122 | #[serde(untagged)] 123 | Item(InputItem), 124 | } 125 | 126 | /// A message input to the model with a role indicating instruction following hierarchy. 127 | /// 128 | /// Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. 129 | /// Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. 130 | #[derive(Debug, Clone, Serialize, Deserialize)] 131 | pub struct InputMessage { 132 | /// The role of the message input. 133 | pub role: Role, 134 | /// Text, image, or audio input to the model, used to generate a response. Can also contain previous assistant responses. 135 | pub content: ContentInput, 136 | } 137 | 138 | /// Text, image, or audio input to the model, used to generate a response. Can also contain previous assistant responses. 139 | #[derive(Debug, Clone, Serialize, Deserialize)] 140 | #[serde(untagged)] 141 | pub enum ContentInput { 142 | Text(String), 143 | List(Vec), 144 | } 145 | 146 | /// A message input to the model with a role indicating instruction following hierarchy, retrieved from the API. 147 | #[derive(Debug, Clone, Serialize, Deserialize)] 148 | pub struct APIInputMessage { 149 | /// The role of the message input. 150 | pub role: Role, 151 | /// Text, image, or audio input to the model, used to generate a response. Can also contain previous assistant responses. 152 | pub content: ContentItem, 153 | /// The status of the message. Populated when the message is returned via API. 154 | pub status: Option, 155 | } 156 | 157 | /// Text, image, or audio input to the model, used to generate a response. Can also contain previous assistant responses. 158 | #[derive(Debug, Clone, Serialize, Deserialize)] 159 | #[serde(tag = "type", rename_all = "snake_case")] 160 | pub enum ContentItem { 161 | /// A text input to the model. 162 | #[serde(rename = "input_text")] 163 | Text { text: String }, 164 | /// An image input to the model. Learn about [image inputs](https://platform.openai.com/docs/guides/vision). 165 | #[serde(rename = "input_image")] 166 | Image { 167 | /// The detail level of the image to be sent to the model. 168 | detail: ImageDetail, 169 | /// The ID of the file to be sent to the model. 170 | file_id: Option, 171 | /// The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL. 172 | image_url: Option, 173 | }, 174 | /// A file input to the model. 175 | #[serde(rename = "input_file")] 176 | File { 177 | /// The content of the file to be sent to the model. 178 | file_data: Option, 179 | /// The ID of the file to be sent to the model. 180 | file_id: Option, 181 | /// The name of the file to be sent to the model. 182 | filename: Option, 183 | }, 184 | } 185 | 186 | /// The detail level of the image sent to the model. 187 | #[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)] 188 | #[serde(rename_all = "snake_case")] 189 | pub enum ImageDetail { 190 | #[default] 191 | Auto, 192 | Low, 193 | High, 194 | Medium, 195 | } 196 | 197 | /// Additional output data to include in the model response. 198 | #[derive(Debug, Clone, Serialize, Deserialize)] 199 | pub enum Include { 200 | /// Include the search results of the file search tool call. 201 | #[serde(rename = "file_search_call.results")] 202 | FileSearchResults, 203 | /// Include image urls from the input message. 204 | #[serde(rename = "message.input_image.image_url")] 205 | InputImageURLs, 206 | /// Include image urls from the computer call output. 207 | #[serde(rename = "computer_call_output.output.image_url")] 208 | ComputerCallImageURLs, 209 | } 210 | -------------------------------------------------------------------------------- /src/types/response.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, Utc, serde::ts_seconds}; 2 | use serde::{Deserialize, Serialize}; 3 | use std::collections::HashMap; 4 | 5 | use crate::types::OutputContent; 6 | 7 | use super::{ 8 | InputItem, OutputItem, ReasoningConfig, ServiceTier, TextConfig, Tool, ToolChoice, Truncation, 9 | }; 10 | 11 | /// The Response object. 12 | #[derive(Debug, Clone, Serialize, Deserialize)] 13 | pub struct Response { 14 | /// When this Response was created. 15 | #[serde(with = "ts_seconds")] 16 | pub created_at: DateTime, 17 | /// Unique identifier for this Response. 18 | pub id: String, 19 | /// Details about why the response is incomplete. 20 | pub incomplete_details: Option, 21 | /// Inserts a system (or developer) message as the first item in the model's context. 22 | /// When using along with `previous_response_id`, the instructions from a previous response will be not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. 23 | pub instructions: Option, 24 | /// An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). 25 | pub max_output_tokens: Option, 26 | /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. 27 | /// Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. 28 | pub metadata: HashMap, 29 | /// Model ID used to generate the response, like gpt-4o or o1. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. 30 | /// Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. 31 | pub model: String, 32 | /// An array of content items generated by the model. 33 | /// - The length and order of items in the `output` array is dependent on the model's response. 34 | /// - Rather than accessing the first item in the `output` array and assuming it's an assistant message with the content generated by the model, you might consider using the `output_text` function. 35 | pub output: Vec, 36 | /// Whether to allow the model to run tool calls in parallel. 37 | pub parallel_tool_calls: bool, 38 | /// The unique ID of the previous response to the model. Use this to create multi-turn conversations. 39 | /// Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). 40 | pub previous_response_id: Option, 41 | /// Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). 42 | /// Only available for o-series models. 43 | pub reasoning: ReasoningConfig, 44 | /// Specifies the latency tier to use for processing the request. 45 | pub service_tier: Option, 46 | /// The status of the response generation. 47 | pub status: ResponseStatus, 48 | /// What sampling temperature to use, between 0 and 2. 49 | /// Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. 50 | /// We generally recommend altering this or `top_p` but not both. 51 | pub temperature: f32, 52 | /// Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: 53 | /// - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) 54 | /// - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) 55 | pub text: TextConfig, 56 | /// How the model should select which tool (or tools) to use when generating a response. 57 | /// See the `tools` parameter to see how to specify which tools the model can call. 58 | pub tool_choice: ToolChoice, 59 | /// An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. 60 | /// The two categories of tools you can provide the model are: 61 | /// - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). 62 | /// - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). 63 | pub tools: Vec, 64 | /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. 65 | /// We generally recommend altering this or `temperature` but not both. 66 | pub top_p: f32, 67 | /// The truncation strategy to use for the model response. 68 | pub truncation: Truncation, 69 | /// Represents token usage details including input tokens, output tokens, a breakdown of output tokens, and the total tokens used. 70 | pub usage: Option, 71 | /// Whether the response was stored on OpenAI's server for later retrieval. 72 | pub store: bool, 73 | /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). 74 | pub user: Option, 75 | } 76 | 77 | impl Response { 78 | #[must_use] 79 | pub fn output_text(&self) -> String { 80 | self.output 81 | .iter() 82 | .filter_map(|output| match output { 83 | OutputItem::Message(message) => Some(message), 84 | _ => None, 85 | }) 86 | .flat_map(|message| &message.content) 87 | .map(|content| match content { 88 | OutputContent::Text { text, .. } => text.to_owned(), 89 | OutputContent::Refusal { refusal } => refusal.to_owned(), 90 | }) 91 | .collect::() 92 | } 93 | } 94 | 95 | /// Represents token usage details including input tokens, output tokens, a breakdown of output tokens, and the total tokens used. 96 | #[derive(Debug, Clone, Serialize, Deserialize)] 97 | pub struct Usage { 98 | /// The number of input tokens. 99 | pub input_tokens: u64, 100 | /// A detailed breakdown of the input tokens. 101 | pub input_tokens_details: InputTokensDetails, 102 | /// The number of output tokens. 103 | pub output_tokens: u64, 104 | /// A detailed breakdown of the output tokens. 105 | pub output_tokens_details: OutputTokensDetails, 106 | /// The total number of tokens used. 107 | pub total_tokens: u64, 108 | } 109 | 110 | /// A detailed breakdown of the input tokens. 111 | #[derive(Debug, Clone, Serialize, Deserialize)] 112 | pub struct InputTokensDetails { 113 | /// The number of cached tokens. 114 | pub cached_tokens: u64, 115 | } 116 | 117 | /// A detailed breakdown of the output tokens. 118 | #[derive(Debug, Clone, Serialize, Deserialize)] 119 | pub struct OutputTokensDetails { 120 | /// The number of reasoning tokens. 121 | pub reasoning_tokens: u64, 122 | } 123 | 124 | /// Details about why a response is incomplete. 125 | #[derive(Debug, Clone, Serialize, Deserialize)] 126 | pub struct IncompleteDetails { 127 | /// The reason why the response is incomplete. 128 | pub reason: String, 129 | } 130 | 131 | /// The status of the response generation. 132 | #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] 133 | #[serde(rename_all = "snake_case")] 134 | pub enum ResponseStatus { 135 | Failed, 136 | Completed, 137 | Incomplete, 138 | InProgress, 139 | } 140 | 141 | /// An error object returned when the model fails to generate a Response. 142 | #[derive(Debug, Clone, Serialize, Deserialize)] 143 | pub struct Error { 144 | /// The type of error. 145 | pub r#type: String, 146 | /// A human-readable description of the error. 147 | pub message: String, 148 | /// The error code for the response. 149 | pub code: Option, 150 | /// The parameter that caused the error. 151 | pub param: Option, 152 | } 153 | 154 | /// A list of items used to generate a model response. 155 | #[derive(Debug, Clone, Serialize, Deserialize)] 156 | pub struct InputItemList { 157 | /// A list of items used to generate this response. 158 | data: Vec, 159 | /// The ID of the first item in the list. 160 | first_id: String, 161 | /// The ID of the last item in the list. 162 | last_id: String, 163 | /// Whether there are more items available. 164 | has_more: bool, 165 | } 166 | 167 | #[allow(clippy::redundant_pub_crate)] 168 | #[derive(Debug, Clone, Serialize, Deserialize)] 169 | #[serde(untagged)] 170 | pub(crate) enum ResponseResult { 171 | Ok(Box), 172 | Err { error: Error }, 173 | } 174 | 175 | impl From for Result { 176 | fn from(val: ResponseResult) -> Self { 177 | match val { 178 | ResponseResult::Err { error } => Err(error), 179 | ResponseResult::Ok(response) => Ok(*response), 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/types/stream.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use super::{Annotation, OutputContent, OutputItem, Response}; 4 | 5 | #[derive(Debug, Clone, Serialize, Deserialize)] 6 | #[serde(tag = "type")] 7 | pub enum Event { 8 | /// An event that is emitted when a response is created. 9 | #[serde(rename = "response.created")] 10 | ResponseCreated { 11 | /// The response that was created. 12 | response: Response, 13 | }, 14 | /// Emitted when the response is in progress. 15 | #[serde(rename = "response.in_progress")] 16 | ResponseInProgress { 17 | /// The response that is in progress. 18 | response: Response, 19 | }, 20 | /// Emitted when the model response is complete. 21 | #[serde(rename = "response.completed")] 22 | ResponseCompleted { 23 | /// Properties of the completed response. 24 | response: Response, 25 | }, 26 | /// An event that is emitted when a response fails. 27 | #[serde(rename = "response.failed")] 28 | ResponseFailed { 29 | /// The response that failed. 30 | response: Response, 31 | }, // todo: probably we just care about error? 32 | /// An event that is emitted when a response finishes as incomplete. 33 | #[serde(rename = "response.incomplete")] 34 | ResponseIncomplete { 35 | /// The response that was incomplete. 36 | response: Response, 37 | }, 38 | /// Emitted when a new output item is added. 39 | #[serde(rename = "response.output_item.added")] 40 | OutputItemAdded { 41 | /// The output item that was added. 42 | item: OutputItem, 43 | /// The index of the output item that was added. 44 | output_index: u64, 45 | }, 46 | /// Emitted when an output item is marked done. 47 | #[serde(rename = "response.output_item.done")] 48 | OutputItemDone { 49 | /// The output item that was marked done. 50 | item: OutputItem, 51 | /// The index of the output item that was marked done. 52 | output_index: u64, 53 | }, 54 | /// Emitted when a new content part is added. 55 | #[serde(rename = "response.content_part.added")] 56 | ContentPartAdded { 57 | /// The index of the content part that was added. 58 | content_index: u64, 59 | /// The ID of the output item that the content part was added to. 60 | item_id: String, 61 | /// The index of the output item that the content part was added to. 62 | output_index: u64, 63 | /// The content part that was added. 64 | part: OutputContent, 65 | }, 66 | /// Emitted when a content part is done. 67 | #[serde(rename = "response.content_part.done")] 68 | ContentPartDone { 69 | /// The index of the content part that is done. 70 | content_index: u64, 71 | /// The ID of the output item that the content part was added to. 72 | item_id: String, 73 | /// The index of the output item that the content part was added to. 74 | output_index: u64, 75 | /// The content part that is done. 76 | part: OutputContent, 77 | }, 78 | /// Emitted when there is an additional text delta. 79 | #[serde(rename = "response.output_text.delta")] 80 | OutputTextDelta { 81 | /// The index of the content part that the text delta was added to. 82 | content_index: u64, 83 | /// The text delta that was added. 84 | delta: String, 85 | /// The ID of the output item that the text delta was added to. 86 | item_id: String, 87 | /// The index of the output item that the text delta was added to. 88 | output_index: u64, 89 | }, 90 | /// Emitted when a text annotation is added. 91 | #[serde(rename = "response.output_text.annotation.added")] 92 | OutputTextAnnotationAdded { 93 | /// The annotation that was added. 94 | annotation: Annotation, 95 | /// The index of the annotation that was added. 96 | annotation_index: u64, 97 | /// The index of the content part that the text annotation was added to. 98 | content_index: u64, 99 | /// The ID of the output item that the text annotation was added to. 100 | item_id: String, 101 | /// The index of the output item that the text annotation was added to. 102 | output_index: u64, 103 | }, 104 | /// Emitted when text content is finalized. 105 | #[serde(rename = "response.output_text.done")] 106 | OutputTextDone { 107 | /// The index of the content part that the text content is finalized. 108 | content_index: u64, 109 | /// The ID of the output item that the text content is finalized. 110 | item_id: String, 111 | /// The index of the output item that the text content is finalized. 112 | output_index: u64, 113 | /// The text content that is finalized. 114 | text: String, 115 | }, 116 | /// Emitted when there is a partial refusal text. 117 | #[serde(rename = "response.refusal.delta")] 118 | RefusalDelta { 119 | /// The index of the content part that the refusal text is added to. 120 | content_index: u64, 121 | /// The refusal text that is added. 122 | delta: String, 123 | /// The ID of the output item that the refusal text is added to. 124 | item_id: String, 125 | /// The index of the output item that the refusal text is added to. 126 | output_index: u64, 127 | }, 128 | /// Emitted when refusal text is finalized. 129 | #[serde(rename = "response.refusal.done")] 130 | RefusalDone { 131 | /// The index of the content part that the refusal text is finalized. 132 | content_index: u64, 133 | /// The ID of the output item that the refusal text is finalized. 134 | item_id: String, 135 | /// The index of the output item that the refusal text is finalized. 136 | output_index: u64, 137 | /// The refusal text that is finalized. 138 | refusal: String, 139 | }, 140 | /// Emitted when there is a partial function-call arguments delta. 141 | #[serde(rename = "response.function_call_arguments.delta")] 142 | FunctionCallArgumentsDelta { 143 | /// The function-call arguments delta that is added. 144 | delta: String, 145 | /// The ID of the output item that the function-call arguments delta is added to. 146 | item_id: String, 147 | /// The index of the output item that the function-call arguments delta is added to. 148 | output_index: u64, 149 | }, 150 | /// Emitted when function-call arguments are finalized. 151 | #[serde(rename = "response.function_call_arguments.done")] 152 | FunctionCallArgumentsDone { 153 | /// The function-call arguments. 154 | arguments: String, 155 | /// The ID of the item. 156 | item_id: String, 157 | /// The index of the output item. 158 | output_index: u64, 159 | }, 160 | /// Emitted when a file search call is initiated. 161 | #[serde(rename = "response.file_search_call.in_progress")] 162 | FileSearchCallInitiated { 163 | /// The ID of the output item that the file search call is initiated. 164 | item_id: String, 165 | /// The index of the output item that the file search call is initiated. 166 | output_index: u64, 167 | }, 168 | /// Emitted when a file search is currently searching. 169 | #[serde(rename = "response.file_search_call.searching")] 170 | FileSearchCallSearching { 171 | /// The ID of the output item that the file search call is searching. 172 | item_id: String, 173 | /// The index of the output item that the file search call is searching. 174 | output_index: u64, 175 | }, 176 | /// Emitted when a file search call is completed (results found). 177 | #[serde(rename = "response.file_search_call.completed")] 178 | FileSearchCallCompleted { 179 | /// The ID of the output item that the file search call completed at. 180 | item_id: String, 181 | /// The index of the output item that the file search call completed at. 182 | output_index: u64, 183 | }, 184 | /// Emitted when a web search call is initiated. 185 | #[serde(rename = "response.web_search_call.in_progress")] 186 | WebSearchCallInitiated { 187 | /// Unique ID for the output item associated with the web search call. 188 | item_id: String, 189 | /// The index of the output item that the web search call is associated with. 190 | output_index: u64, 191 | }, 192 | /// Emitted when a web search call is executing. 193 | #[serde(rename = "response.web_search_call.searching")] 194 | WebSearchCallSearching { 195 | /// Unique ID for the output item associated with the web search call. 196 | item_id: String, 197 | /// The index of the output item that the web search call is associated with. 198 | output_index: u64, 199 | }, 200 | /// Emitted when a web search call is completed. 201 | #[serde(rename = "response.web_search_call.completed")] 202 | WebSearchCallCompleted { 203 | /// Unique ID for the output item associated with the web search call. 204 | item_id: String, 205 | /// The index of the output item that the web search call is associated with. 206 | output_index: u64, 207 | }, 208 | /// Emitted when an error occurs. 209 | #[serde(rename = "error")] 210 | Error { 211 | /// The error code. 212 | code: Option, 213 | /// The error message. 214 | message: String, 215 | /// The error parameter. 216 | param: Option, 217 | }, 218 | } 219 | -------------------------------------------------------------------------------- /src/types/tools.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize, de::Visitor, ser::SerializeStruct}; 2 | use std::collections::HashMap; 3 | 4 | /// A tool the model may call while generating a response. 5 | /// 6 | /// The two categories of tools you can provide the model are: 7 | /// - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). 8 | /// - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). 9 | #[derive(Debug, Clone, Serialize, Deserialize)] 10 | #[serde(tag = "type", rename_all = "snake_case")] 11 | pub enum Tool { 12 | /// Defines a function in your own code the model can choose to call. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). 13 | Function { 14 | /// The name of the function to call. 15 | name: String, 16 | /// A JSON schema object describing the parameters of the function. 17 | parameters: serde_json::Value, 18 | /// Whether to enforce strict parameter validation. 19 | strict: bool, 20 | /// A description of the function. Used by the model to determine whether or not to call the function. 21 | description: Option, 22 | }, 23 | /// A tool that searches for relevant content from uploaded files. Learn more about the [file search tool](https://platform.openai.com/docs/guides/tools-file-search). 24 | FileSearch { 25 | /// The IDs of the vector stores to search. 26 | vector_store_ids: Vec, 27 | /// A filter to apply based on file attributes. 28 | filters: FileSearchFilters, 29 | /// The maximum number of results to return. This number should be between 1 and 50 inclusive. 30 | max_num_results: u8, 31 | /// Ranking options for search. 32 | ranking_options: RankingOptions, 33 | }, 34 | #[serde(rename = "computer_use_preview")] 35 | ComputerUse { 36 | /// The height of the computer display. 37 | display_height: u64, 38 | /// The width of the computer display. 39 | display_width: u64, 40 | /// The type of computer environment to control. 41 | environment: Environment, 42 | }, 43 | #[serde(rename = "web_search_preview")] 44 | WebSearch { 45 | /// High level guidance for the amount of context window space to use for the search. 46 | search_context_size: SearchContextSize, 47 | /// Approximate location parameters for the search. 48 | user_location: Option, 49 | }, 50 | } 51 | 52 | /// Approximate location parameters for the search. 53 | #[derive(Debug, Clone, Default, Serialize, Deserialize)] 54 | pub struct UserLocation { 55 | /// The type of location approximation 56 | pub r#type: UserLocationType, 57 | /// Free text input for the city of the user, e.g. `San Francisco`. 58 | pub city: Option, 59 | /// The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`. 60 | pub country: Option, 61 | /// Free text input for the region of the user, e.g. `California`. 62 | pub region: Option, 63 | /// The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`. 64 | pub timezone: Option, 65 | } 66 | 67 | /// The type of location approximation 68 | #[derive(Debug, Clone, Default, Serialize, Deserialize)] 69 | #[serde(rename_all = "lowercase")] 70 | pub enum UserLocationType { 71 | #[default] 72 | Approximate, 73 | } 74 | 75 | /// High level guidance for the amount of context window space to use for the search. 76 | #[derive(Debug, Clone, Default, Serialize, Deserialize)] 77 | #[serde(rename_all = "lowercase")] 78 | pub enum SearchContextSize { 79 | Low, 80 | High, 81 | #[default] 82 | Medium, 83 | } 84 | 85 | /// The type of computer environment to control. 86 | #[non_exhaustive] 87 | #[derive(Debug, Clone, Serialize, Deserialize)] 88 | #[serde(rename_all = "snake_case")] 89 | pub enum Environment { 90 | Mac, 91 | Ubuntu, 92 | Browser, 93 | Windows, 94 | } 95 | 96 | /// A filter to apply based on file attributes. 97 | #[derive(Debug, Clone, Serialize, Deserialize)] 98 | #[serde(untagged)] 99 | pub enum FileSearchFilters { 100 | /// A filter used to compare a specified attribute key to a given value using a defined comparison operation. 101 | Single(ComparisonFilter), 102 | /// Combine multiple filters using and or or. 103 | Compound(CompoundFilter), 104 | } 105 | 106 | /// A filter used to compare a specified attribute key to a given value using a defined comparison operation. 107 | #[derive(Debug, Clone, Serialize, Deserialize)] 108 | pub struct ComparisonFilter { 109 | /// The key to compare against the value. 110 | pub key: String, 111 | /// Specifies the comparison operator. 112 | pub r#type: ComparisonFilterType, 113 | /// The value to compare against the attribute key. 114 | pub value: ComparisonFilterValue, 115 | } 116 | 117 | /// The value to compare against the attribute key. 118 | #[derive(Debug, Clone, Serialize, Deserialize)] 119 | #[serde(untagged)] 120 | pub enum ComparisonFilterValue { 121 | Number(f64), 122 | Boolean(bool), 123 | String(String), 124 | } 125 | 126 | /// Specifies the comparison operator. 127 | #[derive(Debug, Clone, Serialize, Deserialize)] 128 | pub enum ComparisonFilterType { 129 | #[serde(rename = "eq")] 130 | Equals, 131 | #[serde(rename = "ne")] 132 | NotEqual, 133 | #[serde(rename = "gt")] 134 | GreaterThan, 135 | #[serde(rename = "gte")] 136 | GreaterThanOrEqual, 137 | #[serde(rename = "lt")] 138 | LessThan, 139 | #[serde(rename = "lte")] 140 | LessThanOrEqual, 141 | } 142 | 143 | /// Combine multiple filters using and or or. 144 | #[derive(Debug, Clone, Serialize, Deserialize)] 145 | pub struct CompoundFilter { 146 | /// Array of filters to combine. 147 | pub filters: Vec, 148 | /// Type of operation. 149 | pub r#type: CompoundFilterType, 150 | } 151 | 152 | /// Type of operation. 153 | #[derive(Debug, Clone, Serialize, Deserialize)] 154 | #[serde(rename_all = "lowercase")] 155 | pub enum CompoundFilterType { 156 | And, 157 | Or, 158 | } 159 | 160 | /// Ranking options for search. 161 | #[derive(Debug, Clone, Serialize, Deserialize)] 162 | pub struct RankingOptions { 163 | /// The ranker to use for the file search. 164 | pub ranker: String, 165 | /// The score threshold for the file search, a number between 0 and 1. Numbers closer to 1 will attempt to return only the most relevant results, but may return fewer results. 166 | pub score_threshold: f32, 167 | } 168 | 169 | /// How the model should select which tool (or tools) to use when generating a response. 170 | /// 171 | /// See the `tools` parameter to see how to specify which tools the model can call. 172 | #[derive(Debug, Clone, Default)] 173 | pub enum ToolChoice { 174 | /// The model will not call any tool and instead generates a message. 175 | None, 176 | /// The model can pick between generating a message or calling one or more tools. 177 | #[default] 178 | Auto, 179 | /// The model must call one or more tools. 180 | Required, 181 | /// Search the contents of uploaded files when generating a response. 182 | FileSearch, 183 | /// Include data from the internet in model response generation. 184 | WebSearchPreview, 185 | /// Create agentic workflows that enable a model to control a computer interface. 186 | ComputerUsePreview, 187 | /// Enable the model to call custom code that you define, giving it access to additional data and capabilities. 188 | Function(String), 189 | } 190 | 191 | impl<'de> Deserialize<'de> for ToolChoice { 192 | fn deserialize(deserializer: D) -> Result 193 | where 194 | D: serde::Deserializer<'de>, 195 | { 196 | struct ToolChoiceVisitor; 197 | 198 | impl<'de> Visitor<'de> for ToolChoiceVisitor { 199 | type Value = ToolChoice; 200 | 201 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 202 | formatter.write_str("string or struct") 203 | } 204 | 205 | fn visit_str(self, value: &str) -> Result 206 | where 207 | E: serde::de::Error, 208 | { 209 | match value { 210 | "none" => Ok(ToolChoice::None), 211 | "auto" => Ok(ToolChoice::Auto), 212 | "required" => Ok(ToolChoice::Required), 213 | _ => Err(serde::de::Error::unknown_variant( 214 | value, 215 | &["none", "auto", "required"], 216 | )), 217 | } 218 | } 219 | 220 | fn visit_map(self, mut map: A) -> Result 221 | where 222 | A: serde::de::MapAccess<'de>, 223 | { 224 | let mut record = HashMap::::new(); 225 | 226 | while let Some((key, value)) = map.next_entry()? { 227 | record.insert(key, value); 228 | } 229 | 230 | let Some(r#type) = record.get("type") else { 231 | return Err(serde::de::Error::missing_field("type")); 232 | }; 233 | 234 | match r#type.as_str() { 235 | "file_search" => Ok(ToolChoice::FileSearch), 236 | "web_search_preview" => Ok(ToolChoice::WebSearchPreview), 237 | "computer_use_preview" => Ok(ToolChoice::ComputerUsePreview), 238 | "function" => { 239 | let Some(name) = record.get("name") else { 240 | return Err(serde::de::Error::missing_field("name")); 241 | }; 242 | Ok(ToolChoice::Function(name.clone())) 243 | } 244 | _ => Err(serde::de::Error::unknown_variant( 245 | r#type.as_str(), 246 | &[ 247 | "file_search", 248 | "web_search_preview", 249 | "computer_use_preview", 250 | "function", 251 | ], 252 | )), 253 | } 254 | } 255 | } 256 | 257 | deserializer.deserialize_any(ToolChoiceVisitor {}) 258 | } 259 | } 260 | 261 | impl Serialize for ToolChoice { 262 | fn serialize(&self, serializer: S) -> Result 263 | where 264 | S: serde::Serializer, 265 | { 266 | match self { 267 | Self::None => serializer.serialize_str("none"), 268 | Self::Auto => serializer.serialize_str("auto"), 269 | Self::Required => serializer.serialize_str("required"), 270 | Self::FileSearch => { 271 | let mut fn_struct = serializer.serialize_struct("Function", 1)?; 272 | fn_struct.serialize_field("type", "file_search")?; 273 | fn_struct.end() 274 | } 275 | Self::WebSearchPreview => { 276 | let mut fn_struct = serializer.serialize_struct("Function", 1)?; 277 | fn_struct.serialize_field("type", "web_search_preview")?; 278 | fn_struct.end() 279 | } 280 | Self::ComputerUsePreview => { 281 | let mut fn_struct = serializer.serialize_struct("Function", 1)?; 282 | fn_struct.serialize_field("type", "computer_use_preview")?; 283 | fn_struct.end() 284 | } 285 | Self::Function(name) => { 286 | let mut fn_struct = serializer.serialize_struct("Function", 2)?; 287 | fn_struct.serialize_field("name", name)?; 288 | fn_struct.serialize_field("type", "function")?; 289 | fn_struct.end() 290 | } 291 | } 292 | } 293 | } 294 | --------------------------------------------------------------------------------