Merge commit '36c66dd290d3ce6eb1ccd310d0c658d4a32bb8eb' as 'repos/effect'

This commit is contained in:
-Puter
2026-07-19 03:25:10 +05:30
parent dd1071cc10
commit 2daf979036
2214 changed files with 673090 additions and 0 deletions

View File

@@ -0,0 +1,736 @@
# @effect/ai-anthropic
## 4.0.0-beta.99
### Patch Changes
- [#6371](https://github.com/Effect-TS/effect/pull/6371) [`7543afe`](https://github.com/Effect-TS/effect/commit/7543afea6f4d97d1f1ad876224323838a48daadd) Thanks @polRk! - Fix client-executed provider tools (Memory, Text Editor, Computer Use, Bash) which were unusable on the wire.
- `makeResponse` (and the streaming equivalents) now map a provider `tool_use` wire name (e.g. `"memory"`) back to the tool's custom name (e.g. `"AnthropicMemory"`) that the toolkit is keyed by, instead of raising `ToolNotFoundError`.
- `AnthropicTool.MemoryCreateCommand` now includes the required `file_text` field, so a `create` command no longer drops the file body.
- Optional parameters on client-executed provider tools now use `Schema.optionalKey` instead of `Schema.optional`, which the Anthropic codec rejected with "Unsupported AST Undefined": `Memory`/`TextEditor` `view_range`, `ComputerUse` `coordinate`, and `Bash` `restart`.
Closes [#2615](https://github.com/Effect-TS/effect/issues/2615).
- Updated dependencies [[`8ce4795`](https://github.com/Effect-TS/effect/commit/8ce4795ccbaebca4292757db568c005a992546a4), [`80b539f`](https://github.com/Effect-TS/effect/commit/80b539f8aba68f478c75c35c2b4140c4ffc4fada), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`e6e6dba`](https://github.com/Effect-TS/effect/commit/e6e6dba6e9d86e7c2ad27dcedf289db76a19697f), [`bfb203e`](https://github.com/Effect-TS/effect/commit/bfb203e95aa439f731acad37fc3a9a831a190f1c), [`2e9a34a`](https://github.com/Effect-TS/effect/commit/2e9a34ac2bece4f3a206160480c991e3841dc67a), [`55d4eb3`](https://github.com/Effect-TS/effect/commit/55d4eb34f2c64d54f6a25a305b5c5438ebd7934e), [`bddb010`](https://github.com/Effect-TS/effect/commit/bddb010eac3d4436cb094edbbee7460c5440c162), [`a328835`](https://github.com/Effect-TS/effect/commit/a328835e50d76bc96648a1c1550456e8c9f81210), [`5560d05`](https://github.com/Effect-TS/effect/commit/5560d05aa6abdd29466d9c3412cc5e648b0adbde), [`8f6e3ad`](https://github.com/Effect-TS/effect/commit/8f6e3adb185b16e8820b98c509b308086f7ff1af), [`46997fa`](https://github.com/Effect-TS/effect/commit/46997fa60401f5e3c93daa4b61f7df8e31caaab4), [`9e6e12d`](https://github.com/Effect-TS/effect/commit/9e6e12d75c118cd265496f2880490d1f33a5c8bf), [`3394b93`](https://github.com/Effect-TS/effect/commit/3394b93d97d6f24fc38670641d1490289ffca7f1), [`febeabc`](https://github.com/Effect-TS/effect/commit/febeabc3f7c31094da000a23edeaabfe2ab00a38), [`54161c9`](https://github.com/Effect-TS/effect/commit/54161c98f6f3569e0c31842f54e6a257f9421c4c), [`385f7a4`](https://github.com/Effect-TS/effect/commit/385f7a4ee4a7359928597ea56d151dbaf5eb5802), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`7543afe`](https://github.com/Effect-TS/effect/commit/7543afea6f4d97d1f1ad876224323838a48daadd), [`44b9cf3`](https://github.com/Effect-TS/effect/commit/44b9cf3d240d726997b4bbcd0ede48e074d3c456), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`0a8aa6a`](https://github.com/Effect-TS/effect/commit/0a8aa6acb90a72b91c24d17133c950e4cacd8abd), [`c8d9fcf`](https://github.com/Effect-TS/effect/commit/c8d9fcf7b030f7c474effbab2764ce7aee1c7209), [`9ca7f9a`](https://github.com/Effect-TS/effect/commit/9ca7f9a69363e4485645966d5a93b8f9597c5206), [`e7aca89`](https://github.com/Effect-TS/effect/commit/e7aca894bb32fbb785b5830837e6061c415a6015), [`55d7560`](https://github.com/Effect-TS/effect/commit/55d75609b8acf8a1b54c1b1c7fbbb65ec741aa3e), [`f809189`](https://github.com/Effect-TS/effect/commit/f809189ddf6b6011ba43a9901baaa734e315da2a), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`0ebdbe7`](https://github.com/Effect-TS/effect/commit/0ebdbe74463dc84385956d0b1e8c2b79ebab5400), [`7517d09`](https://github.com/Effect-TS/effect/commit/7517d09f12a0b183a81bd425962c4e280a68b05d), [`212493b`](https://github.com/Effect-TS/effect/commit/212493b9a1eb98cd1ef6959c707a2e5784a5ae91), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`80ea8cb`](https://github.com/Effect-TS/effect/commit/80ea8cb9222ca73f564c8267ab2f82966fea027a), [`8df19f4`](https://github.com/Effect-TS/effect/commit/8df19f4fe81d90cc33ace88b9a77e5534f82d604)]:
- effect@4.0.0-beta.99
## 4.0.0-beta.98
### Patch Changes
- Updated dependencies [[`989603b`](https://github.com/Effect-TS/effect-smol/commit/989603b60ab1197b64acf214208e0d370cd1f842), [`214c458`](https://github.com/Effect-TS/effect-smol/commit/214c458084bb6995d543cd37d1055f24be3d454e), [`a037273`](https://github.com/Effect-TS/effect-smol/commit/a0372736ac34796969b051bbba4717d7983f1ebe), [`97fdaa9`](https://github.com/Effect-TS/effect-smol/commit/97fdaa9c1f522c65e579365d314a07878e2b904f), [`b24d248`](https://github.com/Effect-TS/effect-smol/commit/b24d248c8df44222ce642087cde2bd859a2dc709), [`19c222c`](https://github.com/Effect-TS/effect-smol/commit/19c222cac2353a3d7b7733caecb00556fffe9a5c), [`eec85dd`](https://github.com/Effect-TS/effect-smol/commit/eec85ddba09ea326fd268ee33eeffd47e50d4671), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`8849052`](https://github.com/Effect-TS/effect-smol/commit/884905232d1e9a365e046d8dde27bf9c5707f57f), [`c15e16a`](https://github.com/Effect-TS/effect-smol/commit/c15e16ad130d1fbde25d912b7ac55995066cb35b), [`01d00a3`](https://github.com/Effect-TS/effect-smol/commit/01d00a3abfbf1f37996cdbe738ea5137c646cdd7), [`8bd4589`](https://github.com/Effect-TS/effect-smol/commit/8bd458975a1b3a8ed042eccf317b93d28ded91e7), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`6e08428`](https://github.com/Effect-TS/effect-smol/commit/6e08428d980501b856f846ad3f3f0e4ea46e7786), [`388dcf9`](https://github.com/Effect-TS/effect-smol/commit/388dcf953f65d317547f34d40e6443c5f264205f), [`2b7ce2b`](https://github.com/Effect-TS/effect-smol/commit/2b7ce2b513e7ec2a77822f1116dc6ffb6ba93f4e), [`87bea7e`](https://github.com/Effect-TS/effect-smol/commit/87bea7e16259246f3bcdf565446394751abca953), [`ce38dc3`](https://github.com/Effect-TS/effect-smol/commit/ce38dc33bda805a684432cca071f4dc3c6b9a1ba), [`a807cd1`](https://github.com/Effect-TS/effect-smol/commit/a807cd170341deca8a1cfb52c4222585f2431bb9), [`fd8a356`](https://github.com/Effect-TS/effect-smol/commit/fd8a356f06a8c9ce4e7e0a13fc4021c178ed31de), [`c2a5edc`](https://github.com/Effect-TS/effect-smol/commit/c2a5edc3abd31ad5bc123362bc1213e03e4095c3), [`5946da3`](https://github.com/Effect-TS/effect-smol/commit/5946da3804a1be5e752b05b96bd058cdba50a1bf), [`4ae0c5f`](https://github.com/Effect-TS/effect-smol/commit/4ae0c5ffcbe6c56ddfcb05c639112a079483539e), [`5b2a0bc`](https://github.com/Effect-TS/effect-smol/commit/5b2a0bceea3a28a33a58555210c90a415dc74a76), [`72ac585`](https://github.com/Effect-TS/effect-smol/commit/72ac585884befde6af9208da738699a93f1bae79), [`5e8c1b8`](https://github.com/Effect-TS/effect-smol/commit/5e8c1b82bfafa121311f987a49ab75395e3647a7), [`0f9c078`](https://github.com/Effect-TS/effect-smol/commit/0f9c07841b04183f485ee6e6458de73b290b09f5)]:
- effect@4.0.0-beta.98
## 4.0.0-beta.97
### Patch Changes
- [#2568](https://github.com/Effect-TS/effect-smol/pull/2568) [`97a4138`](https://github.com/Effect-TS/effect-smol/commit/97a4138f9e9d31d38026f935b52d423f5ccadc4f) Thanks @K-Mistele! - Widen the Anthropic `Model` schema to accept both known model identifiers as well
as any string to allow for newer models
- Updated dependencies []:
- effect@4.0.0-beta.97
## 4.0.0-beta.96
### Patch Changes
- Updated dependencies [[`1503f45`](https://github.com/Effect-TS/effect-smol/commit/1503f45cb5bb2a74f4705252ec505a1f0ade7e62), [`57fe793`](https://github.com/Effect-TS/effect-smol/commit/57fe79316ffbc380b30626a168981fb26ae97459), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`97f29df`](https://github.com/Effect-TS/effect-smol/commit/97f29df457f7ffd07cfb4b379315c12c086af805)]:
- effect@4.0.0-beta.96
## 4.0.0-beta.95
### Patch Changes
- [#2531](https://github.com/Effect-TS/effect-smol/pull/2531) [`bdca354`](https://github.com/Effect-TS/effect-smol/commit/bdca35449d5dfce5b4433da75ec0a88d0a9b2b27) Thanks @polRk! - Fix `Memory_20250818` provider-defined tool missing `requiresHandler: true`. Like the other client-executed tools (`TextEditor_20250728`, `Bash_2025*`, `ComputerUse_2025*`), the memory tool requires the application to implement its execution (view/create/str_replace/insert/delete/rename over `/memories/*`). Without this flag, `Tool.HandlersFor` excluded it from the required handlers, making it impossible to type-check a handler for `Memory_20250818` in `Toolkit.toLayer`.
- Updated dependencies [[`a482442`](https://github.com/Effect-TS/effect-smol/commit/a482442abdeb490e9652b854ec3495e4aa7273e7), [`fbefa85`](https://github.com/Effect-TS/effect-smol/commit/fbefa850fab2f0a302c20614496aeaaa2a8b5590), [`0b4a32f`](https://github.com/Effect-TS/effect-smol/commit/0b4a32f4260f0d8500942a133001b0d349328102), [`18a49e1`](https://github.com/Effect-TS/effect-smol/commit/18a49e1786679456258002ff9397faf02f678c2d), [`266cb90`](https://github.com/Effect-TS/effect-smol/commit/266cb90bb2c17aabc40563c32db334f09ba3d74b), [`912f095`](https://github.com/Effect-TS/effect-smol/commit/912f095a34572bbd3cedf6edb27878443e3e4a95), [`a6718f9`](https://github.com/Effect-TS/effect-smol/commit/a6718f9e00a15ca903b0732da46116cbf3d6aca7), [`bef5154`](https://github.com/Effect-TS/effect-smol/commit/bef51540a243aa2f872a00c01d0cd58b7a769baa), [`18e0564`](https://github.com/Effect-TS/effect-smol/commit/18e0564bd0f8ebbdfcaf1e2c21529948e9e4a81d), [`fb50f14`](https://github.com/Effect-TS/effect-smol/commit/fb50f14fc3657c1973785aa5b72ecf0b0d28e0b2)]:
- effect@4.0.0-beta.95
## 4.0.0-beta.94
### Patch Changes
- Updated dependencies [[`95a0e9b`](https://github.com/Effect-TS/effect-smol/commit/95a0e9bb62797af0e81c9998773405f248f218c5), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63), [`f11ce73`](https://github.com/Effect-TS/effect-smol/commit/f11ce73af60823754dc24194f4ffc561b9ea1c2d), [`ff30b6e`](https://github.com/Effect-TS/effect-smol/commit/ff30b6e7c2c63ffc56a4c5818d6d86b01b5ad528), [`1caab3c`](https://github.com/Effect-TS/effect-smol/commit/1caab3cc30f626efbf15e59d74f539a487e5c85c), [`aa80c47`](https://github.com/Effect-TS/effect-smol/commit/aa80c4775a04db87553e5568764cab7e32a72814), [`c2ae4fc`](https://github.com/Effect-TS/effect-smol/commit/c2ae4fce2f03a4cd1861c2b1179da7df656e662d), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63)]:
- effect@4.0.0-beta.94
## 4.0.0-beta.93
### Patch Changes
- Updated dependencies [[`00652fe`](https://github.com/Effect-TS/effect-smol/commit/00652fe95c18f87208e91343eb8bf218faa2f677), [`6c58167`](https://github.com/Effect-TS/effect-smol/commit/6c5816746eaf91d2a3c7c899c5720809fa230ae3), [`2bc5415`](https://github.com/Effect-TS/effect-smol/commit/2bc541501a7ef89e542d7cb98e96beb53cd205cc), [`e11cccc`](https://github.com/Effect-TS/effect-smol/commit/e11cccc7d5fe631abccc7d6e3bd296938de0fa2e), [`ba7e77e`](https://github.com/Effect-TS/effect-smol/commit/ba7e77e046b8641a3a4e9750bb88ca4a1d063d3f), [`5713ee7`](https://github.com/Effect-TS/effect-smol/commit/5713ee7edbc3054efde407b2286bbfd45bbc6e1c)]:
- effect@4.0.0-beta.93
## 4.0.0-beta.92
### Patch Changes
- Updated dependencies [[`affdc13`](https://github.com/Effect-TS/effect-smol/commit/affdc139045cc325dce321a84a580fdc1b2da7b9)]:
- effect@4.0.0-beta.92
## 4.0.0-beta.91
### Patch Changes
- Updated dependencies [[`b135b25`](https://github.com/Effect-TS/effect-smol/commit/b135b2517fca9e7839734ace3699a7dfa75b9075), [`aaa21a3`](https://github.com/Effect-TS/effect-smol/commit/aaa21a369a171c600db294f2a4f640583043e150), [`3475ee6`](https://github.com/Effect-TS/effect-smol/commit/3475ee6c2bda6b05c6d7a12ce30c8bb840b5b1a6)]:
- effect@4.0.0-beta.91
## 4.0.0-beta.90
### Patch Changes
- Updated dependencies [[`d237fdf`](https://github.com/Effect-TS/effect-smol/commit/d237fdf726481f76eb52a6196e111b24122bc3d5)]:
- effect@4.0.0-beta.90
## 4.0.0-beta.89
### Patch Changes
- Updated dependencies [[`b7d46ab`](https://github.com/Effect-TS/effect-smol/commit/b7d46ab7e1a29d8711817bab583c9febf48a0dad), [`7777e15`](https://github.com/Effect-TS/effect-smol/commit/7777e1540fd3680dd8346723cffec812b9384669), [`5376197`](https://github.com/Effect-TS/effect-smol/commit/5376197ca8e50358a41b1fd3cec27bd1ec680ec6)]:
- effect@4.0.0-beta.89
## 4.0.0-beta.88
### Patch Changes
- [#2450](https://github.com/Effect-TS/effect-smol/pull/2450) [`7b8a549`](https://github.com/Effect-TS/effect-smol/commit/7b8a5493950aa6f9e20024cd7e588838722218f0) Thanks @DomiR! - Fix non-streaming Anthropic responses throwing when a tool call carries `caller` metadata. The mapper emitted `caller.toolId: undefined`, but `ProviderMetadata` is `Record(String, NullOr(Json))` and `undefined` is not a valid Json value, so decoding the model's own response threw `Expected JSON value`. Emit `null` instead, matching the streaming mappers.
- Updated dependencies [[`911f1b8`](https://github.com/Effect-TS/effect-smol/commit/911f1b84790ce42b3a70c95b33e6f6fd9e74de8b), [`8beeeea`](https://github.com/Effect-TS/effect-smol/commit/8beeeea52879d8613a39468848f01c3092bd54d4), [`c306fcf`](https://github.com/Effect-TS/effect-smol/commit/c306fcfeb1ef38455156932a1faf49292b1318da)]:
- effect@4.0.0-beta.88
## 4.0.0-beta.87
### Patch Changes
- Updated dependencies [[`5a0c1a4`](https://github.com/Effect-TS/effect-smol/commit/5a0c1a4faee5707b5cc35e646ff1ffdad70f1956), [`1eea2ea`](https://github.com/Effect-TS/effect-smol/commit/1eea2ea3795ba47316b82b1ac8d4612c0ba389ed)]:
- effect@4.0.0-beta.87
## 4.0.0-beta.86
### Patch Changes
- Updated dependencies [[`0b5795a`](https://github.com/Effect-TS/effect-smol/commit/0b5795a0ab4395e8f15955d8d96f2303084bfc64), [`3e3a859`](https://github.com/Effect-TS/effect-smol/commit/3e3a859ec6351a9e0d31674aabbd48fcefabb12e), [`7dbec24`](https://github.com/Effect-TS/effect-smol/commit/7dbec240dbf3bca599a20c486632abce694ef5ab), [`d8c00a1`](https://github.com/Effect-TS/effect-smol/commit/d8c00a171ac7141e8adc08c332d1162d9a9d56fc), [`85b6317`](https://github.com/Effect-TS/effect-smol/commit/85b631701e935866f2762bd595237aa718370cd9), [`6d0fda0`](https://github.com/Effect-TS/effect-smol/commit/6d0fda0d0cbdfffc523c89c57dfdb1608f84fb12), [`108a933`](https://github.com/Effect-TS/effect-smol/commit/108a9335ff8571928197e5847a09c28ac83d6f46), [`7e1f455`](https://github.com/Effect-TS/effect-smol/commit/7e1f455fab5005d769b939c91e519d450f802cf9), [`46b3e79`](https://github.com/Effect-TS/effect-smol/commit/46b3e79944cfdae7901eb148135c85b7eb39834e)]:
- effect@4.0.0-beta.86
## 4.0.0-beta.85
### Patch Changes
- Updated dependencies [[`328d97c`](https://github.com/Effect-TS/effect-smol/commit/328d97cc53c0dcb89077a5623e35b095eaa59a8c), [`8441836`](https://github.com/Effect-TS/effect-smol/commit/8441836e6dde70e8ae2126be9cefe9b45798b134), [`074e436`](https://github.com/Effect-TS/effect-smol/commit/074e4361091289104cb0ab6959dc3b0ea7794a6a), [`c1dfd60`](https://github.com/Effect-TS/effect-smol/commit/c1dfd60663eb13a58916f3712d877499943b628a), [`2ba316b`](https://github.com/Effect-TS/effect-smol/commit/2ba316bd15fcbf1c50626500d44a2c9b3bec19f5), [`7ce7344`](https://github.com/Effect-TS/effect-smol/commit/7ce7344c41056c79e2ee19ee6a9346c0f1d227c1)]:
- effect@4.0.0-beta.85
## 4.0.0-beta.84
### Patch Changes
- Updated dependencies [[`87f52ba`](https://github.com/Effect-TS/effect-smol/commit/87f52ba16c4370ffa3f84bf8e53038e1419c284e), [`b8ee07f`](https://github.com/Effect-TS/effect-smol/commit/b8ee07ffda8903b5ec2e45a786ddcba59f128fda), [`867c0d7`](https://github.com/Effect-TS/effect-smol/commit/867c0d70a09079b040260d45a1e92ff04dbfbf2f), [`b93bc6c`](https://github.com/Effect-TS/effect-smol/commit/b93bc6c9cb27b909a41d094c97c4f9d25bbc6d6b), [`57d387f`](https://github.com/Effect-TS/effect-smol/commit/57d387f92c30ab63e15e3e641f0a903b65886610), [`bacca41`](https://github.com/Effect-TS/effect-smol/commit/bacca4141c2400effae1eabfdb36c89a459cf246), [`0f8ac79`](https://github.com/Effect-TS/effect-smol/commit/0f8ac7959d29ed68c68ce25aabd6bf0cb7e63ecc), [`25b4482`](https://github.com/Effect-TS/effect-smol/commit/25b448270c01317703f25107e1480d4cd0246d9a), [`9cf3a25`](https://github.com/Effect-TS/effect-smol/commit/9cf3a25c66b0c44a52be9829870c44517ea52db2), [`8def767`](https://github.com/Effect-TS/effect-smol/commit/8def7674b1787f91035298cda4d122937e87ef72)]:
- effect@4.0.0-beta.84
## 4.0.0-beta.83
### Patch Changes
- Updated dependencies [[`1f2e8ce`](https://github.com/Effect-TS/effect-smol/commit/1f2e8ceef09e0a791c850ed2ade01f97089596f9)]:
- effect@4.0.0-beta.83
## 4.0.0-beta.82
### Patch Changes
- Updated dependencies [[`193690b`](https://github.com/Effect-TS/effect-smol/commit/193690b642ea802bbed40d663bd677251bbe9dc3)]:
- effect@4.0.0-beta.82
## 4.0.0-beta.81
### Patch Changes
- Updated dependencies [[`93cb4f8`](https://github.com/Effect-TS/effect-smol/commit/93cb4f8fbfb9e07cb9dc86ce6b155fd1f8167914), [`60341d9`](https://github.com/Effect-TS/effect-smol/commit/60341d9ca744d0473ce3fab621ca9bd225af3a39), [`1105ab5`](https://github.com/Effect-TS/effect-smol/commit/1105ab56cb724212f7ea7b431396ce82e8fd0484), [`4500fbf`](https://github.com/Effect-TS/effect-smol/commit/4500fbfe00763d8a72af6e5d6c5988e8bd4ade36)]:
- effect@4.0.0-beta.81
## 4.0.0-beta.80
### Patch Changes
- Updated dependencies [[`d944330`](https://github.com/Effect-TS/effect-smol/commit/d94433090ee03f426d43e13b883abae4494e55e6), [`f48659f`](https://github.com/Effect-TS/effect-smol/commit/f48659fdcc84930ebc1e5b45b540c0f973389182), [`7652aaa`](https://github.com/Effect-TS/effect-smol/commit/7652aaa3bdbc39f241fe58b54b9a43b713e22e12), [`98630b7`](https://github.com/Effect-TS/effect-smol/commit/98630b7c8f679c352ba6796636c85688fa009d8d), [`90ae23c`](https://github.com/Effect-TS/effect-smol/commit/90ae23cf07284da5e1bcd9dffa882e85df7e617b)]:
- effect@4.0.0-beta.80
## 4.0.0-beta.79
### Patch Changes
- [#2357](https://github.com/Effect-TS/effect-smol/pull/2357) [`3efe308`](https://github.com/Effect-TS/effect-smol/commit/3efe308fcc6ac642c65560efbd1b3afc68052553) Thanks @jbmusso! - Mark the Claude 4-6 generation as supporting native structured output in `getModelCapabilities`. `claude-opus-4-6` and `claude-sonnet-4-6` support Anthropic's constrained-decoding structured output (verified against the live API), but were classified as `supportsStructuredOutput: false`, so `generateObject` fell back to a forced JSON tool instead of requesting `output_config.format` (`json_schema`). `claude-opus-4-7` / `claude-opus-4-8` are classified the same way for when the generated `Model` enum picks them up.
- Updated dependencies [[`b9704dc`](https://github.com/Effect-TS/effect-smol/commit/b9704dc9de9f1649ad502371014fe869b69a49a3), [`a207113`](https://github.com/Effect-TS/effect-smol/commit/a207113f66837bb54416926718a9a7d66774d079), [`5e9b9e2`](https://github.com/Effect-TS/effect-smol/commit/5e9b9e217b164ebfd4a002dd4380b3b1563200c3), [`7c128ae`](https://github.com/Effect-TS/effect-smol/commit/7c128aef458a1e2d224712e51c483c9badad1d44), [`0ada457`](https://github.com/Effect-TS/effect-smol/commit/0ada457c0513d8d908254ab77ebb7d29d2b523d6), [`d7cc5a2`](https://github.com/Effect-TS/effect-smol/commit/d7cc5a2bede3de10943aa0c6bdb4f26836a91efd), [`aad63be`](https://github.com/Effect-TS/effect-smol/commit/aad63becf65e0a6b076e94f8973be7bbe7fbd46f), [`09809f6`](https://github.com/Effect-TS/effect-smol/commit/09809f60f19ec98232f98b33e33e02ecb7e4fbd6), [`2fddda5`](https://github.com/Effect-TS/effect-smol/commit/2fddda5311929f46b61e503f0ade4fc749e8c77d), [`5f21768`](https://github.com/Effect-TS/effect-smol/commit/5f2176833399757c4500d8875b7f2fba0393de75), [`f27003e`](https://github.com/Effect-TS/effect-smol/commit/f27003e00524ff83f20dd9909f62b2f8795efe03)]:
- effect@4.0.0-beta.79
## 4.0.0-beta.78
### Patch Changes
- Updated dependencies [[`7836b8e`](https://github.com/Effect-TS/effect-smol/commit/7836b8eb8bb0f3e04cdf554ee070caccf74f00c1), [`35d49a3`](https://github.com/Effect-TS/effect-smol/commit/35d49a3a09bdba6b513de87ddcead9e61a1042ba), [`4093258`](https://github.com/Effect-TS/effect-smol/commit/40932580e65bafab5f23c5f14b520cb411d0b2cd)]:
- effect@4.0.0-beta.78
## 4.0.0-beta.77
### Patch Changes
- Updated dependencies [[`6e9a5ca`](https://github.com/Effect-TS/effect-smol/commit/6e9a5ca62a61156fd67b2518ad3ab14ac0d25f23), [`302f398`](https://github.com/Effect-TS/effect-smol/commit/302f3984ce206e35d86ddd99d3b72be144850a51)]:
- effect@4.0.0-beta.77
## 4.0.0-beta.76
### Patch Changes
- Updated dependencies [[`016108a`](https://github.com/Effect-TS/effect-smol/commit/016108a472af7048ddbbfd05f233e67529fafe12), [`95c03d2`](https://github.com/Effect-TS/effect-smol/commit/95c03d2c55930668c215b5a41c23cf7742fead84), [`07299a3`](https://github.com/Effect-TS/effect-smol/commit/07299a33c09fd52faa9810d30835a2622c752386)]:
- effect@4.0.0-beta.76
## 4.0.0-beta.75
### Patch Changes
- Updated dependencies [[`81b187c`](https://github.com/Effect-TS/effect-smol/commit/81b187c17a0d8817b58232826939154010ae49d7), [`ad4b535`](https://github.com/Effect-TS/effect-smol/commit/ad4b535e17f94ce35261829d5a3675f0a7808b4e), [`a29c2e7`](https://github.com/Effect-TS/effect-smol/commit/a29c2e7e3570920156702671d6f3367cd0195f6c), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`ffea4ec`](https://github.com/Effect-TS/effect-smol/commit/ffea4ecf2925f6a4c9fd13079d47584cbf2bed00), [`4255c9b`](https://github.com/Effect-TS/effect-smol/commit/4255c9ba78bb98c7838fbe9dccdd8465e9da5427)]:
- effect@4.0.0-beta.75
## 4.0.0-beta.74
### Patch Changes
- Updated dependencies [[`b1fc6a4`](https://github.com/Effect-TS/effect-smol/commit/b1fc6a4b4d0ca7fa9fd162799ae17c86f2f7ee8e)]:
- effect@4.0.0-beta.74
## 4.0.0-beta.73
### Patch Changes
- Updated dependencies [[`361ca30`](https://github.com/Effect-TS/effect-smol/commit/361ca30eb6e134feece547d6e00f82be4cb23f75), [`b9598c6`](https://github.com/Effect-TS/effect-smol/commit/b9598c6a209e75bfdb87ee3b024ecd1e3923ff6e)]:
- effect@4.0.0-beta.73
## 4.0.0-beta.72
### Patch Changes
- Updated dependencies [[`73e67d1`](https://github.com/Effect-TS/effect-smol/commit/73e67d119a84d697773eaecb4865c6a71eb1a9cb), [`01d71ec`](https://github.com/Effect-TS/effect-smol/commit/01d71ec5a75f3c2747a8d3b1ad9701d1e27b7ce5), [`fcd707e`](https://github.com/Effect-TS/effect-smol/commit/fcd707e091a16e1b35343c901cc4052274e32239)]:
- effect@4.0.0-beta.72
## 4.0.0-beta.71
### Patch Changes
- Updated dependencies [[`d8ac76b`](https://github.com/Effect-TS/effect-smol/commit/d8ac76b5bad458c42cebe8a0c1b3843f955ac293), [`2c3c00a`](https://github.com/Effect-TS/effect-smol/commit/2c3c00af6faba7b7d422af26a7a2bbc35636d230), [`3751e7c`](https://github.com/Effect-TS/effect-smol/commit/3751e7cf353e7a54cd692c37401207d9afba1e63), [`fc5f25b`](https://github.com/Effect-TS/effect-smol/commit/fc5f25b03ada5fc2431987768a74d3d3e75ca485), [`7ccced4`](https://github.com/Effect-TS/effect-smol/commit/7ccced42867c14c013b01160b3d292f14c05bd04), [`a2e1fe5`](https://github.com/Effect-TS/effect-smol/commit/a2e1fe5835c98c8ee4393a091b1d11b75126e349), [`4a4a36b`](https://github.com/Effect-TS/effect-smol/commit/4a4a36b10e6e616cad07584a43908f6a7e07e618), [`d350292`](https://github.com/Effect-TS/effect-smol/commit/d3502922b4740fa9d745797cbc3775cb67839b6d), [`730afb6`](https://github.com/Effect-TS/effect-smol/commit/730afb66696adf9bd5a328cbca29df9c05968771), [`df1b008`](https://github.com/Effect-TS/effect-smol/commit/df1b008f370f414c2a67a7b8139ef747af8e5fba), [`6d469d5`](https://github.com/Effect-TS/effect-smol/commit/6d469d567a7c41d7e5343bdee21d45b07b0e8190)]:
- effect@4.0.0-beta.71
## 4.0.0-beta.70
### Patch Changes
- Updated dependencies [[`af7782d`](https://github.com/Effect-TS/effect-smol/commit/af7782d3008d08b043f3a3f261516001514b2b4e), [`7212d70`](https://github.com/Effect-TS/effect-smol/commit/7212d701a3eee7b3553ff502e2c066126e52e839)]:
- effect@4.0.0-beta.70
## 4.0.0-beta.69
### Patch Changes
- Updated dependencies [[`70ea04a`](https://github.com/Effect-TS/effect-smol/commit/70ea04aa96a2a7859d738d414e1f0e3ed081a27a), [`d0ea8b0`](https://github.com/Effect-TS/effect-smol/commit/d0ea8b03f7d73ae076c1db12666141e480d11178), [`a57674b`](https://github.com/Effect-TS/effect-smol/commit/a57674b64845e9e75a456cf907bfdcb858859118), [`59aa334`](https://github.com/Effect-TS/effect-smol/commit/59aa334fbd0a504dda3c36f6d2ef1be7449b4b8b), [`8f4208e`](https://github.com/Effect-TS/effect-smol/commit/8f4208ee83bc7bdaa6793b5429847b45aab72470)]:
- effect@4.0.0-beta.69
## 4.0.0-beta.68
### Patch Changes
- Updated dependencies [[`af8267f`](https://github.com/Effect-TS/effect-smol/commit/af8267f2f3588c3fb611e9286f6f933f29ce1217), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`f136bb7`](https://github.com/Effect-TS/effect-smol/commit/f136bb763048cbc6b17edd26496dba3e2415b9fa), [`6f38f07`](https://github.com/Effect-TS/effect-smol/commit/6f38f07d5941a211b251383aaab0f4f55e8a6557), [`aec9c40`](https://github.com/Effect-TS/effect-smol/commit/aec9c401a53db227f18bf5e0c84db7130ad862d6)]:
- effect@4.0.0-beta.68
## 4.0.0-beta.67
### Patch Changes
- Updated dependencies [[`a42ef66`](https://github.com/Effect-TS/effect-smol/commit/a42ef6632abbddfa820995ae310ccc84ae8d9b6f), [`35594f8`](https://github.com/Effect-TS/effect-smol/commit/35594f811cafe471acd490114b103a1f8392c8d8), [`8bddd62`](https://github.com/Effect-TS/effect-smol/commit/8bddd628cb623f9533d345082583ff51cead6836), [`4be4c8d`](https://github.com/Effect-TS/effect-smol/commit/4be4c8d60862aa963869ee2ed9ffa048ffac0527), [`0c9d3ab`](https://github.com/Effect-TS/effect-smol/commit/0c9d3ab43eb721a370ed8306260cbac218c27e87), [`b156acc`](https://github.com/Effect-TS/effect-smol/commit/b156accd2691b4a051f823affdece7c39923ce85), [`d16c034`](https://github.com/Effect-TS/effect-smol/commit/d16c03434ee3e6dcd3bfc82b65d99e881d89025b), [`b559d68`](https://github.com/Effect-TS/effect-smol/commit/b559d68845f848a10153395778f035682d399075), [`a3de5d9`](https://github.com/Effect-TS/effect-smol/commit/a3de5d9215e5cc4a62e2666efbd7c1bf595eb84f), [`7e6c12e`](https://github.com/Effect-TS/effect-smol/commit/7e6c12ec9b3a5945f6c26e272cc8f6390541ad3e), [`098167a`](https://github.com/Effect-TS/effect-smol/commit/098167a220fe07da6f14455818733ab1b269c9dd)]:
- effect@4.0.0-beta.67
## 4.0.0-beta.66
### Patch Changes
- Updated dependencies [[`ca2498e`](https://github.com/Effect-TS/effect-smol/commit/ca2498e702ac2d83fb7187707b7eb069bdb261a2), [`cd7d1fb`](https://github.com/Effect-TS/effect-smol/commit/cd7d1fba7e2e2c5ac3ad64e1be433440a5bda436), [`19a7033`](https://github.com/Effect-TS/effect-smol/commit/19a703367ec817cffc41d152da9b594827408e2b), [`33d26b4`](https://github.com/Effect-TS/effect-smol/commit/33d26b4210b2e974f146a71e7eed962f8ce00900), [`856766b`](https://github.com/Effect-TS/effect-smol/commit/856766b2c506aaed6d2df1d63bf3a5b1b062e1d4), [`079c7df`](https://github.com/Effect-TS/effect-smol/commit/079c7df82559bb9ce10a86dffb85d25e6ce07dc3)]:
- effect@4.0.0-beta.66
## 4.0.0-beta.65
### Patch Changes
- Updated dependencies [[`6f11454`](https://github.com/Effect-TS/effect-smol/commit/6f11454a9b6c3bd00f6b35fd7af14a2f2d63a0a2)]:
- effect@4.0.0-beta.65
## 4.0.0-beta.64
### Patch Changes
- Updated dependencies [[`7d4877a`](https://github.com/Effect-TS/effect-smol/commit/7d4877a1929cdb690280ea254326c04f2ec97ea5)]:
- effect@4.0.0-beta.64
## 4.0.0-beta.63
### Patch Changes
- Updated dependencies [[`7f927ff`](https://github.com/Effect-TS/effect-smol/commit/7f927ffb7a9801dcfc4096c29e369d13d65cd0ac), [`a696b3e`](https://github.com/Effect-TS/effect-smol/commit/a696b3e83a8504cdbe261a18c10a1cc0619ae102)]:
- effect@4.0.0-beta.63
## 4.0.0-beta.62
### Patch Changes
- Updated dependencies [[`4ab4b90`](https://github.com/Effect-TS/effect-smol/commit/4ab4b9007dc27a52ffabc6fcb37c96eeec795bf7)]:
- effect@4.0.0-beta.62
## 4.0.0-beta.61
### Patch Changes
- Updated dependencies [[`50790af`](https://github.com/Effect-TS/effect-smol/commit/50790af9b190c38d10fb0723837d49b66432638f), [`71f7c3d`](https://github.com/Effect-TS/effect-smol/commit/71f7c3df997deda92c84146d569696dab3bd645c), [`aae8797`](https://github.com/Effect-TS/effect-smol/commit/aae8797b9cb383be0c182dd58d03d787c354238b)]:
- effect@4.0.0-beta.61
## 4.0.0-beta.60
### Patch Changes
- Updated dependencies [[`f69d567`](https://github.com/Effect-TS/effect-smol/commit/f69d5675dcff9f4137295752baf066b7153fdc09), [`7909c95`](https://github.com/Effect-TS/effect-smol/commit/7909c954b8f6244a35a4b429f8dd0dff45dad620), [`bbb4dcc`](https://github.com/Effect-TS/effect-smol/commit/bbb4dcc6c406b83a416b4ad3541cc02037c420e4), [`7af2207`](https://github.com/Effect-TS/effect-smol/commit/7af2207901eabf3132c1b7010a69b3899c06fbbe), [`848b40a`](https://github.com/Effect-TS/effect-smol/commit/848b40a4bd4bf54a5098617d50c33c88eee8270a)]:
- effect@4.0.0-beta.60
## 4.0.0-beta.59
### Patch Changes
- Updated dependencies [[`56837ea`](https://github.com/Effect-TS/effect-smol/commit/56837ea2a338395b35550641374e9e589bd8b71d)]:
- effect@4.0.0-beta.59
## 4.0.0-beta.58
### Patch Changes
- Updated dependencies [[`11993d4`](https://github.com/Effect-TS/effect-smol/commit/11993d4934c66f5dc611b8bbf553f01d501ef8f7), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec)]:
- effect@4.0.0-beta.58
## 4.0.0-beta.57
### Patch Changes
- Updated dependencies [[`a971f5c`](https://github.com/Effect-TS/effect-smol/commit/a971f5cbd92dfe4274420bf0966595eb35531060), [`8e110c5`](https://github.com/Effect-TS/effect-smol/commit/8e110c5f02a429ccc43a91df8678e402138c0851)]:
- effect@4.0.0-beta.57
## 4.0.0-beta.56
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.56
## 4.0.0-beta.55
### Patch Changes
- Updated dependencies [[`42cc744`](https://github.com/Effect-TS/effect-smol/commit/42cc744570968deb365fb46d47b53d3277050c93), [`04855ce`](https://github.com/Effect-TS/effect-smol/commit/04855ceeca4d40c55a5750dd9893b691f8ea741a)]:
- effect@4.0.0-beta.55
## 4.0.0-beta.54
### Patch Changes
- Updated dependencies [[`e4b74f9`](https://github.com/Effect-TS/effect-smol/commit/e4b74f9c01a0e9b6cd58416de4af3a26d51da7c8), [`4c72808`](https://github.com/Effect-TS/effect-smol/commit/4c728081851c66dacf889a816535671bc841ae96)]:
- effect@4.0.0-beta.54
## 4.0.0-beta.53
### Patch Changes
- Updated dependencies [[`0768509`](https://github.com/Effect-TS/effect-smol/commit/07685094e931af07d104165195826a535b55fa7e), [`476aede`](https://github.com/Effect-TS/effect-smol/commit/476aede69c6efa06b5781ca5eb3e3b128ca29141), [`4f79c54`](https://github.com/Effect-TS/effect-smol/commit/4f79c542e7b508c235ff485d862cc8b29a8260c5), [`4be6a7c`](https://github.com/Effect-TS/effect-smol/commit/4be6a7cf35dab2a01d652f56dd35f0358c5a7e88), [`88927eb`](https://github.com/Effect-TS/effect-smol/commit/88927ebb896162cdba103b36553280b58e0facac)]:
- effect@4.0.0-beta.53
## 4.0.0-beta.52
### Patch Changes
- Updated dependencies [[`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`cf3a311`](https://github.com/Effect-TS/effect-smol/commit/cf3a311d863a8abb818840c3b80f847e621c43c1), [`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`131fdd5`](https://github.com/Effect-TS/effect-smol/commit/131fdd5b1f26531e265fe1a08f002002f47c276e)]:
- effect@4.0.0-beta.52
## 4.0.0-beta.51
### Patch Changes
- Updated dependencies [[`778d2af`](https://github.com/Effect-TS/effect-smol/commit/778d2afe9b5154bc1f9abae46d93ea7e54c87344), [`4e24dcf`](https://github.com/Effect-TS/effect-smol/commit/4e24dcf75037f65eebc1eb68623bc7cbf9d5512a), [`4b1c015`](https://github.com/Effect-TS/effect-smol/commit/4b1c0150e9bdb5559ed32d250deb66e17b4240c7), [`454f8ad`](https://github.com/Effect-TS/effect-smol/commit/454f8adad822929c3ef60f8280d0987226b049fd), [`6754a0c`](https://github.com/Effect-TS/effect-smol/commit/6754a0cd18626b06805a079cc5265525a5eb7d27), [`90f7fd5`](https://github.com/Effect-TS/effect-smol/commit/90f7fd5243871b30980964135db4512b8119fa82), [`d7e1519`](https://github.com/Effect-TS/effect-smol/commit/d7e151974934201fd93fa4c8a1192ee9a5d965a0), [`72a8122`](https://github.com/Effect-TS/effect-smol/commit/72a81228e09782bae512f7d041bbfbc78bc668d0)]:
- effect@4.0.0-beta.51
## 4.0.0-beta.50
### Patch Changes
- Updated dependencies [[`07be594`](https://github.com/Effect-TS/effect-smol/commit/07be594825de60f8e1b2102d21dbb9b8fc63b414), [`ae02433`](https://github.com/Effect-TS/effect-smol/commit/ae02433103ce28f53a0c9bfb4a44e75773289b7b)]:
- effect@4.0.0-beta.50
## 4.0.0-beta.49
### Patch Changes
- Updated dependencies [[`7d87873`](https://github.com/Effect-TS/effect-smol/commit/7d8787340ff549370f6f2a88b612e9ebbfd6ba45), [`c2f6f90`](https://github.com/Effect-TS/effect-smol/commit/c2f6f901b200a6e515b4f02c93ce8005b7bbf1c5), [`216f13c`](https://github.com/Effect-TS/effect-smol/commit/216f13c1fce454a21b489bb915714a17e791a1ac)]:
- effect@4.0.0-beta.49
## 4.0.0-beta.48
### Patch Changes
- Updated dependencies [[`4da56ec`](https://github.com/Effect-TS/effect-smol/commit/4da56ecff129b2da40137ffede23a73cc4e532d8), [`a5e6f77`](https://github.com/Effect-TS/effect-smol/commit/a5e6f774bab195cf50ecdc818240765f69a3bf4a), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070)]:
- effect@4.0.0-beta.48
## 4.0.0-beta.47
### Patch Changes
- Updated dependencies [[`c584726`](https://github.com/Effect-TS/effect-smol/commit/c58472674e750e6938df955044eab88feda95e45), [`86a91a4`](https://github.com/Effect-TS/effect-smol/commit/86a91a4f0c59286dfa9393232d8020dea70ed4db), [`131caf9`](https://github.com/Effect-TS/effect-smol/commit/131caf9525151a0cb29803a8f1dffa0f4f479d12), [`c3615c8`](https://github.com/Effect-TS/effect-smol/commit/c3615c88379b9daf252df0db72c6ac5a20326406)]:
- effect@4.0.0-beta.47
## 4.0.0-beta.46
### Patch Changes
- Updated dependencies [[`3a30b9e`](https://github.com/Effect-TS/effect-smol/commit/3a30b9e2ec2bd8b8193e1aa139f6878a07e3f5ee)]:
- effect@4.0.0-beta.46
## 4.0.0-beta.45
### Patch Changes
- Updated dependencies [[`5c3af6d`](https://github.com/Effect-TS/effect-smol/commit/5c3af6d554f60be34f8fc21d598d9a298ae11beb)]:
- effect@4.0.0-beta.45
## 4.0.0-beta.44
### Patch Changes
- [#1961](https://github.com/Effect-TS/effect-smol/pull/1961) [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970) Thanks @IMax153! - Rename the `ServiceMap` module to `Context` across exports, docs, and tests.
- Updated dependencies [[`e3f0621`](https://github.com/Effect-TS/effect-smol/commit/e3f0621454c3f5d11070d30619da27c9232cadc1), [`5b476ab`](https://github.com/Effect-TS/effect-smol/commit/5b476abc0bd7e9bb59135ea1bcad2e4936227ced), [`6b40e5a`](https://github.com/Effect-TS/effect-smol/commit/6b40e5a4a6bd2087c15a3d7374d25057fdedfa16), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`3b09fb3`](https://github.com/Effect-TS/effect-smol/commit/3b09fb31c40c2802b01f21c23bcdd1fe7fb0aa82), [`2370410`](https://github.com/Effect-TS/effect-smol/commit/237041062e5af4594d32db91597e34e70a632877), [`dabc272`](https://github.com/Effect-TS/effect-smol/commit/dabc272444a700eb629c07ba3e77671a841ca86e), [`08b63c3`](https://github.com/Effect-TS/effect-smol/commit/08b63c3df11bd35c9fd6090dbd166287fdc40664), [`dfff04c`](https://github.com/Effect-TS/effect-smol/commit/dfff04c4c2b1d352dfad83992a6dce1280c85cf9), [`9baed9e`](https://github.com/Effect-TS/effect-smol/commit/9baed9e17e84702e6e480fcef6f86404f9e24be9), [`7846792`](https://github.com/Effect-TS/effect-smol/commit/7846792adc7e1631d62d26d657bd7ba6139f369b), [`1556a24`](https://github.com/Effect-TS/effect-smol/commit/1556a247623636b7ebe438fb56d77f1a7bf957bb), [`7c11bc2`](https://github.com/Effect-TS/effect-smol/commit/7c11bc292ab8e46252fe8f7576fb685917bfb8b5), [`b5ea591`](https://github.com/Effect-TS/effect-smol/commit/b5ea5913ec1d45d0dd12a327b9dd966bda2f6d02), [`0853afa`](https://github.com/Effect-TS/effect-smol/commit/0853afaeb1633b2d7f8b66893bd01c3aa1ef2c22), [`ac845f3`](https://github.com/Effect-TS/effect-smol/commit/ac845f3ab40e0b8719576e7f9bc16ea2e0e02cd4), [`b80c462`](https://github.com/Effect-TS/effect-smol/commit/b80c46247480f47bb64fc480fab48a3f37bc8888), [`b3f535d`](https://github.com/Effect-TS/effect-smol/commit/b3f535d9a7ac13b5fb984c29f93561c57a081ff0), [`6fe2e93`](https://github.com/Effect-TS/effect-smol/commit/6fe2e93cc2f1b173ef89651d74b6a5d2626b3226), [`cda8004`](https://github.com/Effect-TS/effect-smol/commit/cda800451c1ffbdddfc08415aed7b2d91e0412ee), [`8335477`](https://github.com/Effect-TS/effect-smol/commit/8335477a8a936a24b5f3ee6203c1b268bd1bfc3c), [`8c836f9`](https://github.com/Effect-TS/effect-smol/commit/8c836f99ab1e896b9580a71d67773625baff2eaf), [`718ff6f`](https://github.com/Effect-TS/effect-smol/commit/718ff6fe3e3d3820cefd67d2bff1b2224fe08060), [`7eed84f`](https://github.com/Effect-TS/effect-smol/commit/7eed84fc33c5781a6fb11bf4fd189d424902ebd4), [`5df46fe`](https://github.com/Effect-TS/effect-smol/commit/5df46fe2f654d59ab5fc1578f4fc27fa40368ef9), [`82dd0f2`](https://github.com/Effect-TS/effect-smol/commit/82dd0f26c6442b07143762ef7bc33742d3978dd6), [`03ae41e`](https://github.com/Effect-TS/effect-smol/commit/03ae41e7304cffac9f18feea22b73468feafc43a), [`4677a0a`](https://github.com/Effect-TS/effect-smol/commit/4677a0a58f95eea38a211efcd3f345f237a9e44a), [`87e1fc8`](https://github.com/Effect-TS/effect-smol/commit/87e1fc8b67e4901d75f567b2fecc3841ab762cc4), [`c1af1b7`](https://github.com/Effect-TS/effect-smol/commit/c1af1b756f63291e9c0298cf95c98a6920a0c2a0), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`c8a877b`](https://github.com/Effect-TS/effect-smol/commit/c8a877b53e8f29616335719e5dd1c3992dddf780), [`7da961a`](https://github.com/Effect-TS/effect-smol/commit/7da961ae4916229d2246699a5d3b20e5b2dd2020)]:
- effect@4.0.0-beta.44
## 4.0.0-beta.43
### Patch Changes
- Updated dependencies [[`2ae33d0`](https://github.com/Effect-TS/effect-smol/commit/2ae33d050914915f7cb9c25ab0a020901e08d596), [`979811a`](https://github.com/Effect-TS/effect-smol/commit/979811a4c3f7ed21ed18ef560c49fb7f5569e80e), [`eb7dbef`](https://github.com/Effect-TS/effect-smol/commit/eb7dbeffa883386ad912815e62c0820cac1fdf8e), [`cf50eb4`](https://github.com/Effect-TS/effect-smol/commit/cf50eb49cb04706dae5185f624708117c413dee8), [`1d046fe`](https://github.com/Effect-TS/effect-smol/commit/1d046fe484560e23f3e22cb23eec6433f8f1fa02)]:
- effect@4.0.0-beta.43
## 4.0.0-beta.42
### Patch Changes
- Updated dependencies [[`924e216`](https://github.com/Effect-TS/effect-smol/commit/924e216caa7e0bbf22e994a0cd2ce8b1f0f0b3ee), [`80e7f0c`](https://github.com/Effect-TS/effect-smol/commit/80e7f0cd9116e811e97b0ce30a77a8d1ecd072aa), [`f8328bf`](https://github.com/Effect-TS/effect-smol/commit/f8328bf0314da3dc7f31d314f94a5840e8d5217f), [`66d1c06`](https://github.com/Effect-TS/effect-smol/commit/66d1c06039079129707a230f7ad8c676439d7133), [`bee800b`](https://github.com/Effect-TS/effect-smol/commit/bee800bf285192a01bec72a7b7b51bc1159434e6), [`8930441`](https://github.com/Effect-TS/effect-smol/commit/8930441dee6f94c59c583d18d3ebd677cf1f2623)]:
- effect@4.0.0-beta.42
## 4.0.0-beta.41
### Patch Changes
- Updated dependencies [[`36f5c21`](https://github.com/Effect-TS/effect-smol/commit/36f5c2174d31ab42c4598bf81f178f40d0802283), [`d8ce758`](https://github.com/Effect-TS/effect-smol/commit/d8ce758669d6297ae932ac3251d83e7b49b22f30), [`11aab4c`](https://github.com/Effect-TS/effect-smol/commit/11aab4c6d37d5691adafc2d33da1a631b28ce814), [`3bc1efb`](https://github.com/Effect-TS/effect-smol/commit/3bc1efb53dd75b4a40de46f1f80c7f8a7d50af86), [`70e724e`](https://github.com/Effect-TS/effect-smol/commit/70e724e604604d4be1061cd8da0d360494998c84), [`738dee7`](https://github.com/Effect-TS/effect-smol/commit/738dee7edfd70af82dc4d2376db3a8ebe603eb48), [`2111963`](https://github.com/Effect-TS/effect-smol/commit/2111963f19b4c28c800664a8fac9590c1321885f), [`198a553`](https://github.com/Effect-TS/effect-smol/commit/198a553d9ce45f6a00bfc4d65ed0640669602d95)]:
- effect@4.0.0-beta.41
## 4.0.0-beta.40
### Patch Changes
- Updated dependencies [[`f62860f`](https://github.com/Effect-TS/effect-smol/commit/f62860f0e5e45978fabf7256ae620a13152a772a), [`973f281`](https://github.com/Effect-TS/effect-smol/commit/973f2812529aadc1cc54598b2039799fa72b80f8)]:
- effect@4.0.0-beta.40
## 4.0.0-beta.39
### Patch Changes
- Updated dependencies [[`f91fd3d`](https://github.com/Effect-TS/effect-smol/commit/f91fd3db39fe5628439fd175fba201a65a1aa9d0), [`edaae9d`](https://github.com/Effect-TS/effect-smol/commit/edaae9d65f464f941d7eddd723cd33d324f4b071), [`b47db0b`](https://github.com/Effect-TS/effect-smol/commit/b47db0bd5802064b6a24b3ea27c6ff2e0520d513), [`82d3c8e`](https://github.com/Effect-TS/effect-smol/commit/82d3c8e4f3f49b00df611b25aa6f8f74ec21b59b), [`7c22b31`](https://github.com/Effect-TS/effect-smol/commit/7c22b315d198dcbf44ae8cdb8b37879e1c9e3996)]:
- effect@4.0.0-beta.39
## 4.0.0-beta.38
### Patch Changes
- Updated dependencies [[`f4dbe5b`](https://github.com/Effect-TS/effect-smol/commit/f4dbe5b26b9c2d33fae024bf44afbdf8541792cd), [`a71a607`](https://github.com/Effect-TS/effect-smol/commit/a71a607c89fb6669a12a562c2c23be81dfbe1adb), [`66a0494`](https://github.com/Effect-TS/effect-smol/commit/66a0494ed75cd12f2721dcbb1d8a072e3d9e14b6), [`5ef7218`](https://github.com/Effect-TS/effect-smol/commit/5ef7218fc559d57301fe929b8a0cab4033f4f1fd), [`472d260`](https://github.com/Effect-TS/effect-smol/commit/472d260655bc311fba5c2c6e23bb77d8f7e36ba0)]:
- effect@4.0.0-beta.38
## 4.0.0-beta.37
### Patch Changes
- Updated dependencies [[`f7a0b71`](https://github.com/Effect-TS/effect-smol/commit/f7a0b711da8fdd645597dee29cacc5619c6afcf2), [`1e223c3`](https://github.com/Effect-TS/effect-smol/commit/1e223c30ccf835dfbb21284535d78549efaeca80), [`53740f4`](https://github.com/Effect-TS/effect-smol/commit/53740f47aa76d114b7d535649fb50efc54a09608), [`8c7cf89`](https://github.com/Effect-TS/effect-smol/commit/8c7cf89f719e580cbce1bf6c24e6996f1992a0a6), [`b6b81a9`](https://github.com/Effect-TS/effect-smol/commit/b6b81a940eaafcbc792d25413d6c02c707de31b2), [`8f4c1f9`](https://github.com/Effect-TS/effect-smol/commit/8f4c1f97ed60f8810b0b327b50117ffb2d8260d4), [`f2479f9`](https://github.com/Effect-TS/effect-smol/commit/f2479f9d3113b1f012db17a3852b4e28f478cf9c), [`c919921`](https://github.com/Effect-TS/effect-smol/commit/c9199217fad65529421d2cf95ecfff41257090fd), [`7af90c2`](https://github.com/Effect-TS/effect-smol/commit/7af90c2e3c99038eafa39650433839523790e2fe), [`f3be185`](https://github.com/Effect-TS/effect-smol/commit/f3be18569e5ca57c25eabf00df3ca601ebab43c7)]:
- effect@4.0.0-beta.37
## 4.0.0-beta.36
### Patch Changes
- [#1775](https://github.com/Effect-TS/effect-smol/pull/1775) [`954e6d6`](https://github.com/Effect-TS/effect-smol/commit/954e6d655cd32d329b0bfeb872bb654f88b48a13) Thanks @tim-smart! - Add dynamic tool support to the Anthropic language model provider when preparing tool definitions for requests.
- Updated dependencies [[`60fcbcc`](https://github.com/Effect-TS/effect-smol/commit/60fcbcc43d09471e8f7e0969955d99dcefc5be81), [`0a60837`](https://github.com/Effect-TS/effect-smol/commit/0a6083713124440e630030375bab367e8d7df24e), [`49164d2`](https://github.com/Effect-TS/effect-smol/commit/49164d2c20a8d21b66514992c4a15d8521f6b36e), [`334b6e4`](https://github.com/Effect-TS/effect-smol/commit/334b6e4f76fe11941b516d61f57e268bc31f0ca6), [`5700695`](https://github.com/Effect-TS/effect-smol/commit/5700695f76ae6da6b94c9c87d4dd2b8054fb829b), [`f8f4456`](https://github.com/Effect-TS/effect-smol/commit/f8f445644f3aa7ec093cab7445198a62ba18a480), [`969d24f`](https://github.com/Effect-TS/effect-smol/commit/969d24fdfa48c4838e811983848d9cb4e9b3b12c), [`851eda0`](https://github.com/Effect-TS/effect-smol/commit/851eda0533946e39bacaaf581896320d7a4f3e8c), [`8059c1c`](https://github.com/Effect-TS/effect-smol/commit/8059c1c3eba9a90af7cd889ea261bcb8fff0c185), [`6f83295`](https://github.com/Effect-TS/effect-smol/commit/6f8329546a73eaddc7cb5e85ea8e37e73fbfb611), [`65f7f57`](https://github.com/Effect-TS/effect-smol/commit/65f7f5737575fed668987462c96d29a446707c32), [`e7fabd2`](https://github.com/Effect-TS/effect-smol/commit/e7fabd2265db690eae5cfc9b83730c84699aef61), [`89c3e98`](https://github.com/Effect-TS/effect-smol/commit/89c3e985401eb38f33a3ae21a94ad27de3c1d28b), [`53794ab`](https://github.com/Effect-TS/effect-smol/commit/53794ab7af30aa5c5004ecf53659fafbe4b10542)]:
- effect@4.0.0-beta.36
## 4.0.0-beta.35
### Patch Changes
- Updated dependencies [[`9252b43`](https://github.com/Effect-TS/effect-smol/commit/9252b43560f507709c2985abcf52a7837b23ddf8), [`7daf387`](https://github.com/Effect-TS/effect-smol/commit/7daf3870a656882a488a60f67881e6808c8f4d04), [`e1664a3`](https://github.com/Effect-TS/effect-smol/commit/e1664a38bc31ef4ceb4e9324c7226e1e99bf9c07), [`fdaa6e0`](https://github.com/Effect-TS/effect-smol/commit/fdaa6e0a41b6b6605438fa8557441792135380a2), [`19aa47e`](https://github.com/Effect-TS/effect-smol/commit/19aa47ef7b470e427620edca8970dd9cdd551216), [`c667dad`](https://github.com/Effect-TS/effect-smol/commit/c667dad07777b860e4764a3ba9a6cc41c236cd98), [`764d150`](https://github.com/Effect-TS/effect-smol/commit/764d1501bc5026b60fc8aef6cb02a5a87c762801), [`3c27098`](https://github.com/Effect-TS/effect-smol/commit/3c27098b5685a63db2c2eff654a250c94d3fcfa7)]:
- effect@4.0.0-beta.35
## 4.0.0-beta.34
### Patch Changes
- [#1763](https://github.com/Effect-TS/effect-smol/pull/1763) [`2fa940d`](https://github.com/Effect-TS/effect-smol/commit/2fa940d0709769c5fd1337c1f88400867f91989b) Thanks @teeverc! - Remove duplicate `ToolApprovalResponsePartOptions` from Anthropic package
- Updated dependencies [[`f2f75ee`](https://github.com/Effect-TS/effect-smol/commit/f2f75ee564bce1cd95f5189c7bdeeed4f92dacb1), [`342fc4b`](https://github.com/Effect-TS/effect-smol/commit/342fc4b051739e32e7977159f26ff9541eda664f), [`5d704ee`](https://github.com/Effect-TS/effect-smol/commit/5d704ee10d20e8eb107e34bb8a21feb5aa4a7685), [`00add69`](https://github.com/Effect-TS/effect-smol/commit/00add69b59551e9df34772eb927638b093f6d71e), [`58217d3`](https://github.com/Effect-TS/effect-smol/commit/58217d318a7d716ccd707cce0f41573946939c28), [`f4e2aba`](https://github.com/Effect-TS/effect-smol/commit/f4e2aba01b76d1e3059b297e3cc942284dfeafb2), [`e3b44b6`](https://github.com/Effect-TS/effect-smol/commit/e3b44b6a2af9ee21dc5c1e928f0c20af857fa7a9), [`e1472b7`](https://github.com/Effect-TS/effect-smol/commit/e1472b7525c5d57a48bdec2353c3b742f7f916c0), [`7686320`](https://github.com/Effect-TS/effect-smol/commit/7686320cd123fa352b5c3d076fb18a3cac0a9bba)]:
- effect@4.0.0-beta.34
## 4.0.0-beta.33
### Patch Changes
- Updated dependencies [[`571447d`](https://github.com/Effect-TS/effect-smol/commit/571447da67334449f8ae3d6ecb3d77ea4e0c4295)]:
- effect@4.0.0-beta.33
## 4.0.0-beta.32
### Patch Changes
- Updated dependencies [[`bf8fff8`](https://github.com/Effect-TS/effect-smol/commit/bf8fff8a5f54b6df74cb7bbb42346fe9ba52435a), [`1af3ef3`](https://github.com/Effect-TS/effect-smol/commit/1af3ef3e3ca7fd417d0fc15f8ca8fe207eba4f74), [`27fea0f`](https://github.com/Effect-TS/effect-smol/commit/27fea0f66910de5905f40fd63f8ddbb6f7ac5aba), [`2ad6c1b`](https://github.com/Effect-TS/effect-smol/commit/2ad6c1b2c85a3a0fe351e3d56636a75eb76b4b4e), [`398ac3e`](https://github.com/Effect-TS/effect-smol/commit/398ac3e01cb75efce0e4e2913d1450cf65866732), [`51fe22f`](https://github.com/Effect-TS/effect-smol/commit/51fe22f3266e417b6c541aaed4b75d246fac91e7), [`4605db6`](https://github.com/Effect-TS/effect-smol/commit/4605db69cfacddbdbf1525865ddfde135158090c), [`f4de1b0`](https://github.com/Effect-TS/effect-smol/commit/f4de1b087c998d0bad1d9468f70b7d16c13b9f6f), [`60214f2`](https://github.com/Effect-TS/effect-smol/commit/60214f2080b2aeb091f691140eb20acb741691c3), [`c4b8b0f`](https://github.com/Effect-TS/effect-smol/commit/c4b8b0ffa8efb47c4cd7578a8943d6868509373f), [`6d9393a`](https://github.com/Effect-TS/effect-smol/commit/6d9393a0770a18722d23340e77f15455de341245), [`6de4efe`](https://github.com/Effect-TS/effect-smol/commit/6de4efe463c783614ceb0c094d77a336a899cbe0), [`4f969d1`](https://github.com/Effect-TS/effect-smol/commit/4f969d1563ba755ffa116c8ae409bb3436bd881d), [`6cc67c8`](https://github.com/Effect-TS/effect-smol/commit/6cc67c855e054ee3f3ac3485dca5f7805e79e8fb), [`8531a22`](https://github.com/Effect-TS/effect-smol/commit/8531a22ffbb52e11a030b09f358cafbfdf5edff7), [`b226760`](https://github.com/Effect-TS/effect-smol/commit/b22676067617f15c00722a3a63fd7c2c172c3d45), [`47a51ab`](https://github.com/Effect-TS/effect-smol/commit/47a51aba0ecdf3ef478bfa28a498bca188399bd4), [`1521d02`](https://github.com/Effect-TS/effect-smol/commit/1521d02e1f19f1d795edaaf862c1a1031d9c755e)]:
- effect@4.0.0-beta.32
## 4.0.0-beta.31
### Patch Changes
- Updated dependencies [[`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6f23f0e`](https://github.com/Effect-TS/effect-smol/commit/6f23f0ed4cba573cd9395c2e582f582fe7271544), [`654aaec`](https://github.com/Effect-TS/effect-smol/commit/654aaec593305521b65dd042c204d761cc6e8c28), [`2958a42`](https://github.com/Effect-TS/effect-smol/commit/2958a42078966a8713a98f00485ab36484d5eccf), [`95d27a2`](https://github.com/Effect-TS/effect-smol/commit/95d27a239ed5147302605ab0b3147a056541b0c7), [`0fbaea8`](https://github.com/Effect-TS/effect-smol/commit/0fbaea8f9555a8044cec31a770394db613fc78e2), [`21d5d5e`](https://github.com/Effect-TS/effect-smol/commit/21d5d5e0439fd4d9bb6e508377215b1087555d45), [`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6e49959`](https://github.com/Effect-TS/effect-smol/commit/6e499590357a104c81779b3176cd3f84e4f91064), [`8f5805d`](https://github.com/Effect-TS/effect-smol/commit/8f5805dbdd0d1bc0ff0727cc398c8d80e544edee), [`990df2c`](https://github.com/Effect-TS/effect-smol/commit/990df2c3ceeb32e659acc10cc9485617f7b3c423)]:
- effect@4.0.0-beta.31
## 4.0.0-beta.30
### Patch Changes
- Updated dependencies [[`c88e5b7`](https://github.com/Effect-TS/effect-smol/commit/c88e5b723ff09da4edaef6ce14d927ca01104a32), [`947d0e4`](https://github.com/Effect-TS/effect-smol/commit/947d0e4268ba5c4020ead380aa80812c7342408f), [`7517908`](https://github.com/Effect-TS/effect-smol/commit/75179085d159b88a1ab0bce70669d76dcf0d79a4), [`a49ecd5`](https://github.com/Effect-TS/effect-smol/commit/a49ecd5a183d7e7d33f47ff95e9d2dea5a12ead5), [`6993e33`](https://github.com/Effect-TS/effect-smol/commit/6993e3329122c834c20bacea72d8678232f4f103), [`514f2a2`](https://github.com/Effect-TS/effect-smol/commit/514f2a2ae54580fcacdbe2ea2196a83a852d0748), [`3214b47`](https://github.com/Effect-TS/effect-smol/commit/3214b47676de2d33fddc5fecfc2d226e6e83cc7b), [`95ec5ed`](https://github.com/Effect-TS/effect-smol/commit/95ec5ed345de77c893049e182d37a37cf164a268)]:
- effect@4.0.0-beta.30
## 4.0.0-beta.29
### Patch Changes
- Updated dependencies [[`9d93adb`](https://github.com/Effect-TS/effect-smol/commit/9d93adb1c1795d1978391b30d7d2972c88052662), [`b52721c`](https://github.com/Effect-TS/effect-smol/commit/b52721cf0d11a567722b060c8536e3bdd4161f07), [`a891c7b`](https://github.com/Effect-TS/effect-smol/commit/a891c7b12f415b2287613dd4b91a09dfd38ef30d), [`ef26cdf`](https://github.com/Effect-TS/effect-smol/commit/ef26cdfb65d9955fc7e161629191930c2cc2c63f), [`82fd3ed`](https://github.com/Effect-TS/effect-smol/commit/82fd3ed922063ee5a34f96f3993c15c7515e4f67)]:
- effect@4.0.0-beta.29
## 4.0.0-beta.28
### Patch Changes
- Updated dependencies [[`ff533f2`](https://github.com/Effect-TS/effect-smol/commit/ff533f203cd06302ad08032a27e01269b4a2d4c6), [`dc803ee`](https://github.com/Effect-TS/effect-smol/commit/dc803ee52ebd3e9f931118f0dfcb804542847556), [`d660b1c`](https://github.com/Effect-TS/effect-smol/commit/d660b1c99cb93d4f79715e91c7a4486801c0eefa), [`93a05e3`](https://github.com/Effect-TS/effect-smol/commit/93a05e3eaa624058b162aedd66aad70102837270), [`2a65cf6`](https://github.com/Effect-TS/effect-smol/commit/2a65cf6fd81ef63d944e6fb51f058d439bf4a834), [`a561a40`](https://github.com/Effect-TS/effect-smol/commit/a561a40cc41c548c2cf3153aca065ee92ee8aa57), [`29cd24d`](https://github.com/Effect-TS/effect-smol/commit/29cd24d1fe78480a72eeb38a90281ffddc0530bc), [`662a8e6`](https://github.com/Effect-TS/effect-smol/commit/662a8e6857dac64a7cd13bd8df4b0674654622f8), [`d2b52ba`](https://github.com/Effect-TS/effect-smol/commit/d2b52bae5b9336cf59729fbdcc4d7f09512b0cbf), [`407c3b4`](https://github.com/Effect-TS/effect-smol/commit/407c3b43a5d1414558e0e33b6f1fc0e6a6d489cc), [`42bc7ce`](https://github.com/Effect-TS/effect-smol/commit/42bc7ce5480f6f2953c39f8cb5c850d61df6f5a2), [`e741322`](https://github.com/Effect-TS/effect-smol/commit/e74132226cbfee24234311c7c1c13e6b7391384e), [`5c75fa8`](https://github.com/Effect-TS/effect-smol/commit/5c75fa8fb71163bc4c035ba1a215574dfd4badfc), [`747177b`](https://github.com/Effect-TS/effect-smol/commit/747177b0602f12d4461a843e953dfdffbeb0a429), [`326cd48`](https://github.com/Effect-TS/effect-smol/commit/326cd4828bce573fe985f35152155464bf4c5a70), [`627e922`](https://github.com/Effect-TS/effect-smol/commit/627e922b8d1e9521eae5e1caa5d667ad00b1619a), [`662287e`](https://github.com/Effect-TS/effect-smol/commit/662287e9abc76c941ccc2ee330aa07904d571341)]:
- effect@4.0.0-beta.28
## 4.0.0-beta.27
### Patch Changes
- Updated dependencies [[`903a839`](https://github.com/Effect-TS/effect-smol/commit/903a839e94239e6ec4568315af28e405bcad95f4), [`91a0168`](https://github.com/Effect-TS/effect-smol/commit/91a016836680a6669308ecf464d3584bcc4ae1b7), [`c890f9a`](https://github.com/Effect-TS/effect-smol/commit/c890f9a1b3a989ed22528bd5a43326342e05b142), [`1e985f2`](https://github.com/Effect-TS/effect-smol/commit/1e985f237d250b51b91de22dde77160c1e778ce7)]:
- effect@4.0.0-beta.27
## 4.0.0-beta.26
### Patch Changes
- Updated dependencies [[`fb21462`](https://github.com/Effect-TS/effect-smol/commit/fb21462642cdd5b1bada92f3eba18ae20445be42), [`2ed26b1`](https://github.com/Effect-TS/effect-smol/commit/2ed26b139805700e3df39efaa768ff01565e5c86), [`e832a57`](https://github.com/Effect-TS/effect-smol/commit/e832a57b570fe38f010c1fd99bceac5a325a9e07), [`7f01be7`](https://github.com/Effect-TS/effect-smol/commit/7f01be7f8db363d4b2e88e6b5571e96bb815786f), [`e965143`](https://github.com/Effect-TS/effect-smol/commit/e9651431e114479e6becf8ca7b1ed99ac7e91ccc), [`b9b80f1`](https://github.com/Effect-TS/effect-smol/commit/b9b80f1f15e152ceef0a727d150b7dc230abae99), [`98252aa`](https://github.com/Effect-TS/effect-smol/commit/98252aa0c0b17fc73fbdad65d0a1104965f9fc0f), [`56fbd94`](https://github.com/Effect-TS/effect-smol/commit/56fbd94311ad19a05001ad649d9e34ab00c74541), [`3faa109`](https://github.com/Effect-TS/effect-smol/commit/3faa109b7d093fbf14ad410d3e11d663f16e28f1), [`692ecfe`](https://github.com/Effect-TS/effect-smol/commit/692ecfed99fe58056b7a5afe001f4fcd1a61c446), [`1e70b72`](https://github.com/Effect-TS/effect-smol/commit/1e70b72d0b210474d0e96a15a5cfc279eae37e0c), [`ecf0782`](https://github.com/Effect-TS/effect-smol/commit/ecf07829ef2dfc01d8943c96c4fe9c1b44b97926)]:
- effect@4.0.0-beta.26
## 4.0.0-beta.25
### Patch Changes
- Updated dependencies [[`fa17bb5`](https://github.com/Effect-TS/effect-smol/commit/fa17bb5be9f2533d01e11322b14804c7dec43714), [`f46e5b5`](https://github.com/Effect-TS/effect-smol/commit/f46e5b5ca2a918ee4d9270167e79db223077c96f), [`ce4767c`](https://github.com/Effect-TS/effect-smol/commit/ce4767cadcacc6ce8ff4c3a0d0fbc82ede655f63), [`c830a8b`](https://github.com/Effect-TS/effect-smol/commit/c830a8b6c292a6528d7f9318759d34800b00372d)]:
- effect@4.0.0-beta.25
## 4.0.0-beta.24
### Patch Changes
- Updated dependencies [[`a909e1c`](https://github.com/Effect-TS/effect-smol/commit/a909e1c1ac2bc707527f5073776e3e7d239688d9), [`8814a4e`](https://github.com/Effect-TS/effect-smol/commit/8814a4ef78d67144d27689370af10099ea210399), [`3f942c5`](https://github.com/Effect-TS/effect-smol/commit/3f942c51cefa7b2ffa7c49e8c8a2c887570ba4c0), [`774ed59`](https://github.com/Effect-TS/effect-smol/commit/774ed59c52b2ab578bbb897c4f551f812231e1d2), [`f54b8d3`](https://github.com/Effect-TS/effect-smol/commit/f54b8d398fedad1815fd1f4c49814ab938cfc385)]:
- effect@4.0.0-beta.24
## 4.0.0-beta.23
### Patch Changes
- Updated dependencies [[`5c73c41`](https://github.com/Effect-TS/effect-smol/commit/5c73c41b69eaeab80fcd62c9bfda490b446d1966)]:
- effect@4.0.0-beta.23
## 4.0.0-beta.22
### Patch Changes
- Updated dependencies [[`0874332`](https://github.com/Effect-TS/effect-smol/commit/0874332f7c81118b06ac2eb105e0710211631479), [`c592dcd`](https://github.com/Effect-TS/effect-smol/commit/c592dcde0697e322065c8f418c0480ef910cb183), [`1dbe28d`](https://github.com/Effect-TS/effect-smol/commit/1dbe28dac8299cd3e218c9768450cfd173b5e294), [`564d730`](https://github.com/Effect-TS/effect-smol/commit/564d730b6bbf38dd8548a3b046e7a693b28699a4), [`3cfadc4`](https://github.com/Effect-TS/effect-smol/commit/3cfadc458b070c6cba6c5674b72a059f1e49118b), [`6634fd0`](https://github.com/Effect-TS/effect-smol/commit/6634fd07da067d80b8261fb2959d1a952b9e412e), [`d10dabe`](https://github.com/Effect-TS/effect-smol/commit/d10dabeb7af9a368f995829cd36ad08167cd8f95), [`f82f549`](https://github.com/Effect-TS/effect-smol/commit/f82f549a09e950e9d4987f279a800f4d953f0939), [`78a3382`](https://github.com/Effect-TS/effect-smol/commit/78a3382ddfbe034408f7480fa794733d9e82147b)]:
- effect@4.0.0-beta.22
## 4.0.0-beta.21
### Patch Changes
- Updated dependencies [[`e691909`](https://github.com/Effect-TS/effect-smol/commit/e691909495ccb162ea7bfa351dd74632b99997cb), [`d5f413f`](https://github.com/Effect-TS/effect-smol/commit/d5f413f3c8fc57f2413cc5649c2003d6d4e5a6d7), [`139d152`](https://github.com/Effect-TS/effect-smol/commit/139d152941e562a073b5be12e8d66c8a4d4a8a57), [`947e3d4`](https://github.com/Effect-TS/effect-smol/commit/947e3d436ab8a017efda9b29be523efd1ca8df28), [`84b2cce`](https://github.com/Effect-TS/effect-smol/commit/84b2ccefe2aa3a7413b86738a4dc33cdb311ca55), [`7f5305e`](https://github.com/Effect-TS/effect-smol/commit/7f5305e69f5a33309e77b08a576edb25d7daaee2), [`9e6fd84`](https://github.com/Effect-TS/effect-smol/commit/9e6fd8471c93a3c643929151a3bdb62cb9c0ca0e), [`fdb8a4b`](https://github.com/Effect-TS/effect-smol/commit/fdb8a4b172721fbefe98bd5aa6fe4f0efd1da3eb), [`0f986ef`](https://github.com/Effect-TS/effect-smol/commit/0f986ef22f196fe091a7afdbd179485a7d888882), [`9355fc0`](https://github.com/Effect-TS/effect-smol/commit/9355fc0ffb5b7382146a5aed9eea83974b10d007)]:
- effect@4.0.0-beta.21
## 4.0.0-beta.20
### Patch Changes
- [#1529](https://github.com/Effect-TS/effect-smol/pull/1529) [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8) Thanks @tim-smart! - Add dedicated AiError metadata interfaces per reason so provider packages can safely augment metadata without conflicting module declarations.
- [#1528](https://github.com/Effect-TS/effect-smol/pull/1528) [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34) Thanks @tim-smart! - Add `Model.ModelName` and provide it from AI model constructors.
- Updated dependencies [[`842a624`](https://github.com/Effect-TS/effect-smol/commit/842a624f79d5e1407460b0ef3ab27d14d48ccf74), [`4785eef`](https://github.com/Effect-TS/effect-smol/commit/4785eef5d7cf1edb96ef2509aed2ba4d1edf3862), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`12ee8e2`](https://github.com/Effect-TS/effect-smol/commit/12ee8e27df7eb393d83a5e403390d0cfc82ca732), [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34), [`989d1cc`](https://github.com/Effect-TS/effect-smol/commit/989d1cca936fce0cc459057825ba40e3f5ef3827)]:
- effect@4.0.0-beta.20
## 4.0.0-beta.19
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.19
## 4.0.0-beta.18
### Patch Changes
- Updated dependencies [[`01e31fd`](https://github.com/Effect-TS/effect-smol/commit/01e31fdf8e5206849d23cbafd23a346f2f177ab8), [`0890aab`](https://github.com/Effect-TS/effect-smol/commit/0890aab15ed9c5ba52c383a72fdc6a444d7504d5), [`725260b`](https://github.com/Effect-TS/effect-smol/commit/725260b53f5142d6af7a93a2f9f464f974eda92d)]:
- effect@4.0.0-beta.18
## 4.0.0-beta.17
### Patch Changes
- Updated dependencies [[`8f59c32`](https://github.com/Effect-TS/effect-smol/commit/8f59c32922597a48392744f7203e284866747781)]:
- effect@4.0.0-beta.17
## 4.0.0-beta.16
### Patch Changes
- Updated dependencies [[`bf9096c`](https://github.com/Effect-TS/effect-smol/commit/bf9096c52a7d8791d93d232739e523eb84f6625a), [`29f81ca`](https://github.com/Effect-TS/effect-smol/commit/29f81ca07c67dba265804b140a7487fb15a5fc6b), [`68eb28c`](https://github.com/Effect-TS/effect-smol/commit/68eb28c2b0fc67a9f6204ade9bd16c5b37803bfb)]:
- effect@4.0.0-beta.16
## 4.0.0-beta.15
### Patch Changes
- [#1502](https://github.com/Effect-TS/effect-smol/pull/1502) [`285b7e6`](https://github.com/Effect-TS/effect-smol/commit/285b7e667167566d5788367d5155b19c79f1bf22) Thanks @tim-smart! - allow undefined for ai config
- Updated dependencies [[`24ae609`](https://github.com/Effect-TS/effect-smol/commit/24ae60995d2fd7d621be356cdfdfd328c79639ba), [`0e3c059`](https://github.com/Effect-TS/effect-smol/commit/0e3c059987caa55ebd0c134f7c7b147c639c328e), [`e843b0a`](https://github.com/Effect-TS/effect-smol/commit/e843b0a7d7e7b600a0b3bd477f24e2e4cd26bc8b), [`f4389a2`](https://github.com/Effect-TS/effect-smol/commit/f4389a2cca3c5bbf00d69779f52ce41255f15a28), [`5b73de0`](https://github.com/Effect-TS/effect-smol/commit/5b73de095b3402d0c5c74092ace6ce18ebfad566), [`595d2d6`](https://github.com/Effect-TS/effect-smol/commit/595d2d6e7d50419f3532bd39266191532ace38f2)]:
- effect@4.0.0-beta.15
## 4.0.0-beta.14
### Patch Changes
- Updated dependencies [[`c414700`](https://github.com/Effect-TS/effect-smol/commit/c414700ef1932e4b67d0102856de417336912350), [`a30c969`](https://github.com/Effect-TS/effect-smol/commit/a30c9699c0d736cf3952041e45d508b7d58907a9)]:
- effect@4.0.0-beta.14
## 4.0.0-beta.13
### Patch Changes
- Updated dependencies [[`368f4c3`](https://github.com/Effect-TS/effect-smol/commit/368f4c363dd117e6f5a19ad77b161176cfd29fdd), [`db8a579`](https://github.com/Effect-TS/effect-smol/commit/db8a579e93e93ff73b1e60712732e03b597b916b), [`668b703`](https://github.com/Effect-TS/effect-smol/commit/668b70337e9ddbb0d1ae2282a95c282ce404e562), [`d40e76b`](https://github.com/Effect-TS/effect-smol/commit/d40e76b973543979e60e04a6baca04a8c65bdfc2), [`6e18cf8`](https://github.com/Effect-TS/effect-smol/commit/6e18cf883e9905ca718a6697b6a2a4bbd42739aa), [`86062e8`](https://github.com/Effect-TS/effect-smol/commit/86062e8a0c61bca5412fc40d2cf151d676901f08), [`c27ce75`](https://github.com/Effect-TS/effect-smol/commit/c27ce75d34c74dcfc6dba1bf77f1ce88f410a0de), [`e2d4fbf`](https://github.com/Effect-TS/effect-smol/commit/e2d4fbfeeda6a5d2a4c5aeb0501d8240c248b9eb), [`114ab42`](https://github.com/Effect-TS/effect-smol/commit/114ab42ad0edc590d29169675a493e0e915aa58f), [`484caec`](https://github.com/Effect-TS/effect-smol/commit/484caec47cccac8b86db2910742e406dfc7173ab)]:
- effect@4.0.0-beta.13
## 4.0.0-beta.12
### Patch Changes
- Updated dependencies [[`70a74e8`](https://github.com/Effect-TS/effect-smol/commit/70a74e88a8767c9d4acdb9e5f25aec9a33588d07), [`b5b6e10`](https://github.com/Effect-TS/effect-smol/commit/b5b6e10621d54bf8c9857fec0d647ced78ecd857), [`f5ce5a9`](https://github.com/Effect-TS/effect-smol/commit/f5ce5a915359c6ebf254079e1da23cab6cde34fb), [`a29eb70`](https://github.com/Effect-TS/effect-smol/commit/a29eb702ffe3fc58bd28c4d7857298cd65d73668), [`c7b36e5`](https://github.com/Effect-TS/effect-smol/commit/c7b36e541a23e9a00f64e25b23851e51a37dfce5), [`9381d6d`](https://github.com/Effect-TS/effect-smol/commit/9381d6d4d9d819a81a46e56d0364c76e92a4fbca), [`88439f1`](https://github.com/Effect-TS/effect-smol/commit/88439f13ca13549f3e4822c48c4f019c14fc2bcc), [`e35307d`](https://github.com/Effect-TS/effect-smol/commit/e35307dbeb8eb26a9923f958b894a8eaaf259bf2), [`c7df4bc`](https://github.com/Effect-TS/effect-smol/commit/c7df4bce34009474c63d62a807abfdafb76971eb), [`accaf3b`](https://github.com/Effect-TS/effect-smol/commit/accaf3be7ac8da36e2334c509c23b8c9e88ea160), [`3e1c270`](https://github.com/Effect-TS/effect-smol/commit/3e1c2707bbdf67720af1509642b8ced195790882), [`6cd81f7`](https://github.com/Effect-TS/effect-smol/commit/6cd81f73baad86f5bbfa455a55d75cde71e9611a), [`f222da3`](https://github.com/Effect-TS/effect-smol/commit/f222da3cdb44554f3324c2c52d0d005ee575053e), [`61f901d`](https://github.com/Effect-TS/effect-smol/commit/61f901d830005b66e22d1de889fda132aeea97cd)]:
- effect@4.0.0-beta.12
## 4.0.0-beta.11
### Patch Changes
- Updated dependencies [[`88659ed`](https://github.com/Effect-TS/effect-smol/commit/88659edb26e3623d557dccfe914c2c949672da16), [`f2915e8`](https://github.com/Effect-TS/effect-smol/commit/f2915e8e2efe80d50c281e53f297b9701d6dc199), [`eb71ace`](https://github.com/Effect-TS/effect-smol/commit/eb71acebbe0f228e4920278013beee3b67d62310), [`2a16999`](https://github.com/Effect-TS/effect-smol/commit/2a169996c7513d377ac47adbfd68e1490457135c), [`d42dd52`](https://github.com/Effect-TS/effect-smol/commit/d42dd52f11203f8e749fb5d3ecf7153e4a5a6814), [`339adaf`](https://github.com/Effect-TS/effect-smol/commit/339adaf850a62a892adebcb208c2d9dddf3b97b3), [`de19645`](https://github.com/Effect-TS/effect-smol/commit/de1964526d01102dd1cb99c8cfdd3e8df1f49ef1), [`9b1dc3b`](https://github.com/Effect-TS/effect-smol/commit/9b1dc3bcf2a1b68d0a67e3465db5ad01a1a56997), [`e4cb2f5`](https://github.com/Effect-TS/effect-smol/commit/e4cb2f55b30f4771ec1bf613ced36d6d96464dd5), [`8bced95`](https://github.com/Effect-TS/effect-smol/commit/8bced954ecb35d4489197a57b0efe927e7d75f49), [`9431420`](https://github.com/Effect-TS/effect-smol/commit/94314207c8019918200fbcb97aec992219f801f0), [`948dca2`](https://github.com/Effect-TS/effect-smol/commit/948dca22e4f672ba7a6db57f9899272bec7c08b8), [`d18e327`](https://github.com/Effect-TS/effect-smol/commit/d18e32765a2665e31ffb31e746bf983fcfac34c5), [`ab512f7`](https://github.com/Effect-TS/effect-smol/commit/ab512f7be1c0e6b359da921e22cd4944e4c57d3e)]:
- effect@4.0.0-beta.11
## 4.0.0-beta.10
### Patch Changes
- Updated dependencies [[`371acab`](https://github.com/Effect-TS/effect-smol/commit/371acabb58d56f3a7a5e3e33d3d5fdc9f5573c74), [`856d774`](https://github.com/Effect-TS/effect-smol/commit/856d7741f1e296dd5048c6ff2b44b95d023e6ae4), [`b9e9202`](https://github.com/Effect-TS/effect-smol/commit/b9e92023c38caa322975d77cfe83e2d34ac9305a), [`1d1a974`](https://github.com/Effect-TS/effect-smol/commit/1d1a974bd280c81bff5d4505491cda03ba7a3f36), [`6bfe2a6`](https://github.com/Effect-TS/effect-smol/commit/6bfe2a659bc6335db75709931f405da45301cba2), [`b12c811`](https://github.com/Effect-TS/effect-smol/commit/b12c81157be287b1649c210616a244b50ec094d2), [`d17d98a`](https://github.com/Effect-TS/effect-smol/commit/d17d98ad78e2b44d95ef434adab79ac3c35e75ab), [`68c3c7c`](https://github.com/Effect-TS/effect-smol/commit/68c3c7cb1e06ed94fa5c4c123a234b4ccbfdecd8)]:
- effect@4.0.0-beta.10
## 4.0.0-beta.9
### Patch Changes
- Updated dependencies [[`3386557`](https://github.com/Effect-TS/effect-smol/commit/338655731564a7be9f8859dedbf4d5bcac6eb350), [`b6666e3`](https://github.com/Effect-TS/effect-smol/commit/b6666e3cf6bd44ba1a8704e65c256c30359cb422)]:
- effect@4.0.0-beta.9
## 4.0.0-beta.8
### Patch Changes
- [#1354](https://github.com/Effect-TS/effect-smol/pull/1354) [`b94962c`](https://github.com/Effect-TS/effect-smol/commit/b94962c249d46cf96cdf2e41188dc9feda41536a) Thanks @IMax153! - Fix the generated schemas for ai providers
- Updated dependencies [[`246e672`](https://github.com/Effect-TS/effect-smol/commit/246e672dbbd7848d60e0c78fd66671b2f10b3752), [`807dec0`](https://github.com/Effect-TS/effect-smol/commit/807dec03801b4c58a6d00c237b6d98d6386911df)]:
- effect@4.0.0-beta.8
## 4.0.0-beta.7
### Patch Changes
- Updated dependencies [[`a2bda6d`](https://github.com/Effect-TS/effect-smol/commit/a2bda6d4ef6de9d9b0c53ae2df5434f778d6161a), [`1f95a2b`](https://github.com/Effect-TS/effect-smol/commit/1f95a2b5aa9524bb38f4437f4691a664bf463ca1), [`a8d5e79`](https://github.com/Effect-TS/effect-smol/commit/a8d5e792fec201a83af0eb92fc79928d055125fd), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`06d8a03`](https://github.com/Effect-TS/effect-smol/commit/06d8a0391631e6130e3ab25227e59817852e227f), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`f9e883e`](https://github.com/Effect-TS/effect-smol/commit/f9e883e266fbda870336ee62f46b7ac85ba3de6e), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430)]:
- effect@4.0.0-beta.7
## 4.0.0-beta.6
### Patch Changes
- [#1333](https://github.com/Effect-TS/effect-smol/pull/1333) [`96260bf`](https://github.com/Effect-TS/effect-smol/commit/96260bf5331fad6e38d2a79e94d70fd9a502ec29) Thanks @IMax153! - Fix tool calling for the Anthropic Effect AI SDK provider integration
- Updated dependencies [[`3247da2`](https://github.com/Effect-TS/effect-smol/commit/3247da28331f345f68be5dbd2974a7e03d300fe1), [`f205705`](https://github.com/Effect-TS/effect-smol/commit/f2057050dbd034b8c186be2d40c3d03ee63a5a3b), [`f35022c`](https://github.com/Effect-TS/effect-smol/commit/f35022c212e4111527e1bb43f360a67b2b49fa85), [`8622721`](https://github.com/Effect-TS/effect-smol/commit/86227217b02d43680a3c6f3c21731b1d852c91f5), [`fc660ab`](https://github.com/Effect-TS/effect-smol/commit/fc660ab8b5ebae38b8d6b96cbf2f9b880cc09253), [`f37dc33`](https://github.com/Effect-TS/effect-smol/commit/f37dc335f64622fa9ce8d6d1d5dd8fc3f260257b), [`3662f32`](https://github.com/Effect-TS/effect-smol/commit/3662f328fcfa3b2fa01ffa79da40e12e93fcede8), [`a7d436f`](https://github.com/Effect-TS/effect-smol/commit/a7d436f438dcd7f49b9485e4e95a4511f31fad7d), [`6856a41`](https://github.com/Effect-TS/effect-smol/commit/6856a415d7eddd9d73d60919e976f1d071421be4), [`8c417d0`](https://github.com/Effect-TS/effect-smol/commit/8c417d03475e5e12d00dca0c4781d0af7e66b86c), [`5419570`](https://github.com/Effect-TS/effect-smol/commit/5419570ba47ce882a3a10882707b46f66e464906), [`449c5ed`](https://github.com/Effect-TS/effect-smol/commit/449c5ed5318e8a874e730420bcf52918fa2ec80f), [`4b5ec12`](https://github.com/Effect-TS/effect-smol/commit/4b5ec12f87f95f2a3cd8fe4d5b26c6eb0529381a), [`df87937`](https://github.com/Effect-TS/effect-smol/commit/df879375fc3b169c43f9c434b3775e12b80dffe4), [`5dbfca8`](https://github.com/Effect-TS/effect-smol/commit/5dbfca8d1dbb6d18d1605d4f8562e99c86e2ff11), [`e629497`](https://github.com/Effect-TS/effect-smol/commit/e6294973d55597ab6b6deca6babbe1e946b2c91d), [`981c991`](https://github.com/Effect-TS/effect-smol/commit/981c991cd78db34def815d5754379d737157f005), [`1ca2ed6`](https://github.com/Effect-TS/effect-smol/commit/1ca2ed67301a5dc40ae0ed94346b99f26fd22bbe), [`45722bd`](https://github.com/Effect-TS/effect-smol/commit/45722bde974458311f11ad237711363a10ec6894), [`eb2a85e`](https://github.com/Effect-TS/effect-smol/commit/eb2a85ed4dc162b2535d304799333a5a20477fd0)]:
- effect@4.0.0-beta.6
## 4.0.0-beta.5
### Patch Changes
- Updated dependencies [[`f6e133e`](https://github.com/Effect-TS/effect-smol/commit/f6e133e9a16b32317bd09ff08c12b97a0ae44600), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8), [`a88e206`](https://github.com/Effect-TS/effect-smol/commit/a88e206e44dc66ca5a2b45bedc797877c5dbb083), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8)]:
- effect@4.0.0-beta.5
## 4.0.0-beta.4
### Patch Changes
- Updated dependencies [[`c5a18ef`](https://github.com/Effect-TS/effect-smol/commit/c5a18ef44171e3880bf983faee74529908974b32), [`bc6b885`](https://github.com/Effect-TS/effect-smol/commit/bc6b885b94d887a200657c0775dfa874dc15bc0c)]:
- effect@4.0.0-beta.4
## 4.0.0-beta.3
### Patch Changes
- Updated dependencies [[`3a0cf36`](https://github.com/Effect-TS/effect-smol/commit/3a0cf36eff106ba48d74e133c1598cd40613e530), [`c4da328`](https://github.com/Effect-TS/effect-smol/commit/c4da328d32fad1d61e0e538f5d371edf61521d7e)]:
- effect@4.0.0-beta.3
## 4.0.0-beta.2
### Patch Changes
- Updated dependencies [[`a22ce73`](https://github.com/Effect-TS/effect-smol/commit/a22ce73b2bd9305b7ba665694d2255c0e6d5a8d0), [`ebdabf7`](https://github.com/Effect-TS/effect-smol/commit/ebdabf79ff4e62c8384aa8cf9a8d2787d536ee78), [`8f663bb`](https://github.com/Effect-TS/effect-smol/commit/8f663bb121021bf12bd264e8ae385187cb7a5dae)]:
- effect@4.0.0-beta.2
## 4.0.0-beta.1
### Patch Changes
- Updated dependencies [[`0fecf70`](https://github.com/Effect-TS/effect-smol/commit/0fecf70048057623eed7c584a06671773a2b1743), [`709569e`](https://github.com/Effect-TS/effect-smol/commit/709569ed76bead9ebb0670599e4d890a07ca5a43)]:
- effect@4.0.0-beta.1
## 4.0.0-beta.0
### Major Changes
- [#1183](https://github.com/Effect-TS/effect-smol/pull/1183) [`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66) Thanks @tim-smart! - v4 beta
### Patch Changes
- Updated dependencies [[`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66)]:
- effect@4.0.0-beta.0

View File

@@ -0,0 +1,62 @@
# yaml-language-server: $schema=../../tools/ai-codegen/codegen.schema.json
spec:
type: stainless-stats
statsUrl: https://raw.githubusercontent.com/anthropics/anthropic-sdk-typescript/main/.stats.yml
output: src/Generated.ts
name: AnthropicClient
patches:
# Make iterations and speed optional in BetaUsage, iterations optional in BetaMessageDeltaUsage (API may omit these fields)
- '[{"op":"remove","path":"/components/schemas/BetaUsage/required/9"},{"op":"remove","path":"/components/schemas/BetaUsage/required/5"},{"op":"remove","path":"/components/schemas/BetaMessageDeltaUsage/required/3"}]'
header: |
/**
* @since 1.0.0
*/
excludeAnnotations:
- examples
replacements:
# Schema.Unknown doesn't work with Schema.toCodecJson (used by HttpClientResponse.schemaBodyJson)
# Replace with Schema.Json which properly handles arbitrary JSON values
- from: "Schema.Record(Schema.String, Schema.Unknown)"
to: "Schema.Record(Schema.String, Schema.Json)"
- from: "{ readonly [x: string]: unknown }"
to: "{ readonly [x: string]: Schema.Json }"
# Index signature in struct rest pattern
- from: "readonly [x: string]: unknown"
to: "readonly [x: string]: Schema.Json"
# Make citations optional in ResponseTextBlock (API may omit this field)
- from: 'export type ResponseTextBlock = { readonly "citations":'
to: 'export type ResponseTextBlock = { readonly "citations"?:'
- from: "export const ResponseTextBlock = Schema.Struct({ \"citations\": Schema.Union([Schema.Array(Schema.Union([ResponseCharLocationCitation, ResponsePageLocationCitation, ResponseContentBlockLocationCitation, ResponseWebSearchResultLocationCitation, ResponseSearchResultLocationCitation], { mode: \"oneOf\" })), Schema.Null]).annotate({ \"title\": \"Citations\", \"description\": \"Citations supporting the text block.\\n\\nThe type of citation returned will depend on the type of document being cited. Citing a PDF results in `page_location`, plain text results in `char_location`, and content document results in `content_block_location`.\", \"default\": null }), \"text\":"
to: "export const ResponseTextBlock = Schema.Struct({ \"citations\": Schema.optionalKey(Schema.Union([Schema.Array(Schema.Union([ResponseCharLocationCitation, ResponsePageLocationCitation, ResponseContentBlockLocationCitation, ResponseWebSearchResultLocationCitation, ResponseSearchResultLocationCitation], { mode: \"oneOf\" })), Schema.Null]).annotate({ \"title\": \"Citations\", \"description\": \"Citations supporting the text block.\\n\\nThe type of citation returned will depend on the type of document being cited. Citing a PDF results in `page_location`, plain text results in `char_location`, and content document results in `content_block_location`.\", \"default\": null })), \"text\":"
# Make citations optional in BetaResponseTextBlock (API may omit this field)
- from: 'export type BetaResponseTextBlock = { readonly "citations":'
to: 'export type BetaResponseTextBlock = { readonly "citations"?:'
- from: "export const BetaResponseTextBlock = Schema.Struct({ \"citations\": Schema.Union([Schema.Array(Schema.Union([BetaResponseCharLocationCitation, BetaResponsePageLocationCitation, BetaResponseContentBlockLocationCitation, BetaResponseWebSearchResultLocationCitation, BetaResponseSearchResultLocationCitation], { mode: \"oneOf\" })), Schema.Null]).annotate({ \"title\": \"Citations\", \"description\": \"Citations supporting the text block.\\n\\nThe type of citation returned will depend on the type of document being cited. Citing a PDF results in `page_location`, plain text results in `char_location`, and content document results in `content_block_location`.\", \"default\": null }), \"text\":"
to: "export const BetaResponseTextBlock = Schema.Struct({ \"citations\": Schema.optionalKey(Schema.Union([Schema.Array(Schema.Union([BetaResponseCharLocationCitation, BetaResponsePageLocationCitation, BetaResponseContentBlockLocationCitation, BetaResponseWebSearchResultLocationCitation, BetaResponseSearchResultLocationCitation], { mode: \"oneOf\" })), Schema.Null]).annotate({ \"title\": \"Citations\", \"description\": \"Citations supporting the text block.\\n\\nThe type of citation returned will depend on the type of document being cited. Citing a PDF results in `page_location`, plain text results in `char_location`, and content document results in `content_block_location`.\", \"default\": null })), \"text\":"
# Make server_tool_use optional in usage (API may omit this field)
- from: 'readonly "server_tool_use": ServerToolUsage | null'
to: 'readonly "server_tool_use"?: ServerToolUsage | null'
- from: 'readonly "server_tool_use": BetaServerToolUsage | null'
to: 'readonly "server_tool_use"?: BetaServerToolUsage | null'
- from: '"server_tool_use": Schema.Union([ServerToolUsage, Schema.Null]).annotate({ "description": "The number of server tool requests.", "default": null }),'
to: '"server_tool_use": Schema.optionalKey(Schema.Union([ServerToolUsage, Schema.Null]).annotate({ "description": "The number of server tool requests.", "default": null })),'
- from: '"server_tool_use": Schema.Union([BetaServerToolUsage, Schema.Null]).annotate({ "description": "The number of server tool requests.", "default": null }),'
to: '"server_tool_use": Schema.optionalKey(Schema.Union([BetaServerToolUsage, Schema.Null]).annotate({ "description": "The number of server tool requests.", "default": null })),'
# Without trailing comma (for last field in struct)
- from: '"server_tool_use": Schema.Union([BetaServerToolUsage, Schema.Null]).annotate({ "description": "The number of server tool requests.", "default": null }) })'
to: '"server_tool_use": Schema.optionalKey(Schema.Union([BetaServerToolUsage, Schema.Null]).annotate({ "description": "The number of server tool requests.", "default": null })) })'
- from: '"server_tool_use": Schema.Union([ServerToolUsage, Schema.Null]).annotate({ "description": "The number of server tool requests.", "default": null }) })'
to: '"server_tool_use": Schema.optionalKey(Schema.Union([ServerToolUsage, Schema.Null]).annotate({ "description": "The number of server tool requests.", "default": null })) })'
# Make context_management and container optional in BetaMessage (API may omit these fields)
- from: 'readonly "context_management": BetaResponseContextManagement | null'
to: 'readonly "context_management"?: BetaResponseContextManagement | null'
- from: 'readonly "container": BetaContainer | null'
to: 'readonly "container"?: BetaContainer | null'
- from: "\"context_management\": Schema.Union([BetaResponseContextManagement, Schema.Null]).annotate({ \"description\": \"Context management response.\\n\\nInformation about context management strategies applied during the request.\", \"default\": null }),"
to: "\"context_management\": Schema.optionalKey(Schema.Union([BetaResponseContextManagement, Schema.Null]).annotate({ \"description\": \"Context management response.\\n\\nInformation about context management strategies applied during the request.\", \"default\": null })),"
- from: "\"container\": Schema.Union([BetaContainer, Schema.Null]).annotate({ \"description\": \"Information about the container used in this request.\\n\\nThis will be non-null if a container tool (e.g. code execution) was used.\", \"default\": null })"
to: "\"container\": Schema.optionalKey(Schema.Union([BetaContainer, Schema.Null]).annotate({ \"description\": \"Information about the container used in this request.\\n\\nThis will be non-null if a container tool (e.g. code execution) was used.\", \"default\": null }))"
# Make context_management optional in BetaMessageDeltaEvent (API may omit this field)
- from: '"context_management": Schema.Union([BetaResponseContextManagement, Schema.Null]).annotate({ "description": "Information about context management strategies applied during the request", "default": null }),'
to: '"context_management": Schema.optionalKey(Schema.Union([BetaResponseContextManagement, Schema.Null]).annotate({ "description": "Information about context management strategies applied during the request", "default": null })),'

View File

@@ -0,0 +1,25 @@
{
"$schema": "../../node_modules/@effect/docgen/schema.json",
"srcLink": "https://github.com/Effect-TS/effect/tree/main/packages/ai/anthropic/src/",
"exclude": ["src/internal/**/*.ts", "src/Generated.ts"],
"examplesCompilerOptions": {
"noEmit": true,
"strict": true,
"exactOptionalPropertyTypes": true,
"skipLibCheck": true,
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2022",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"types": ["node"],
"rewriteRelativeImportExtensions": true,
"allowImportingTsExtensions": true,
"paths": {
"effect": ["../../../effect/src/index.js"],
"effect/*": ["../../../effect/src/*.js"]
},
"plugins": [
{ "name": "@effect/language-service", "includeSuggestionsInTsc": false }
]
}
}

View File

@@ -0,0 +1,66 @@
{
"name": "@effect/ai-anthropic",
"version": "4.0.0-beta.99",
"type": "module",
"license": "MIT",
"description": "An Anthropic provider integration for Effect AI SDK",
"homepage": "https://effect.website",
"repository": {
"type": "git",
"url": "https://github.com/Effect-TS/effect.git",
"directory": "packages/ai/anthropic"
},
"bugs": {
"url": "https://github.com/Effect-TS/effect/issues"
},
"tags": [
"typescript",
"ai",
"anthropic"
],
"keywords": [
"typescript",
"ai",
"anthropic"
],
"sideEffects": [],
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts",
"./*": "./src/*.ts",
"./internal/*": null,
"./*/index": null
},
"files": [
"src/**/*.ts",
"dist/**/*.js",
"dist/**/*.js.map",
"dist/**/*.d.ts",
"dist/**/*.d.ts.map"
],
"publishConfig": {
"access": "public",
"provenance": true,
"exports": {
"./package.json": "./package.json",
".": "./dist/index.js",
"./*": "./dist/*.js",
"./internal/*": null,
"./*/index": null
}
},
"scripts": {
"codegen": "effect-utils codegen",
"build": "tsc -b tsconfig.json && pnpm babel",
"babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
"check": "tsc -b tsconfig.json",
"test": "vitest",
"coverage": "vitest --coverage"
},
"devDependencies": {
"effect": "workspace:^"
},
"peerDependencies": {
"effect": "workspace:^"
}
}

View File

@@ -0,0 +1,432 @@
/**
* The `AnthropicClient` module defines the low-level Effect service for
* Anthropic's Messages API. It builds a generated Anthropic HTTP client with
* authentication headers, API version headers, response decoding, and error
* mapping, then exposes helpers for regular and streaming message requests.
*
* @since 4.0.0
*/
import * as Array from "effect/Array"
import type * as Config from "effect/Config"
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { identity } from "effect/Function"
import * as Layer from "effect/Layer"
import * as Predicate from "effect/Predicate"
import * as Redacted from "effect/Redacted"
import * as Schema from "effect/Schema"
import * as Stream from "effect/Stream"
import type * as AiError from "effect/unstable/ai/AiError"
import * as Sse from "effect/unstable/encoding/Sse"
import * as Headers from "effect/unstable/http/Headers"
import * as HttpBody from "effect/unstable/http/HttpBody"
import * as HttpClient from "effect/unstable/http/HttpClient"
import type * as HttpClientError from "effect/unstable/http/HttpClientError"
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import type * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
import { AnthropicConfig } from "./AnthropicConfig.ts"
import * as Generated from "./Generated.ts"
import * as Errors from "./internal/errors.ts"
// =============================================================================
// Service Interface
// =============================================================================
/**
* Represents the Anthropic client service with methods for the Messages API, including regular and streaming message
* creation.
*
* @category models
* @since 4.0.0
*/
export interface Service {
/**
* The underlying generated Anthropic client that exposes all API endpoints.
*/
readonly client: Generated.AnthropicClient
/**
* Executes a low-level streaming HTTP request and decodes the Server-Sent Events response using the provided schema.
*/
readonly streamRequest: <S extends Sse.EventCodec>(
schema: S
) => (request: HttpClientRequest.HttpClientRequest) => Stream.Stream<
S["Type"],
HttpClientError.HttpClientError | Schema.SchemaError | Sse.Retry,
S["DecodingServices"]
>
/**
* Creates a message using the Anthropic Messages API and maps all errors to the unified `AiError` type.
*/
readonly createMessage: (options: {
readonly payload: typeof Generated.BetaCreateMessageParams.Encoded
readonly params?: typeof Generated.BetaMessagesPostParams.Encoded | undefined
}) => Effect.Effect<
[body: typeof Generated.BetaMessage.Type, response: HttpClientResponse.HttpClientResponse],
AiError.AiError
>
/**
* Creates a streaming message using the Anthropic Messages API and maps all errors to the unified `AiError` type.
*
* **Details**
*
* The returned Effect yields the HTTP response and a stream of events as the model generates its response. The stream
* automatically terminates when a `message_stop` event is received.
*/
readonly createMessageStream: (options: {
readonly payload: Omit<typeof Generated.BetaCreateMessageParams.Encoded, "stream">
readonly params?: typeof Generated.BetaMessagesPostParams.Encoded | undefined
}) => Effect.Effect<
[response: HttpClientResponse.HttpClientResponse, stream: Stream.Stream<MessageStreamEvent, AiError.AiError>],
AiError.AiError
>
}
/**
* Represents an event received from the Anthropic Messages API during a streaming request.
*
* **Details**
*
* Events include:
* - `message_start`: Initial event containing message metadata
* - `message_delta`: Incremental updates to the message (e.g., stop reason)
* - `message_stop`: Final event indicating the message is complete
* - `content_block_start`: Start of a content block
* - `content_block_delta`: Incremental content updates (text, tool use, etc.)
* - `content_block_stop`: End of a content block
* - `error`: Error events with type and message
*
* @category models
* @since 4.0.0
*/
export type MessageStreamEvent =
| typeof Generated.BetaMessageStartEvent.Type
| typeof Generated.BetaMessageDeltaEvent.Type
| typeof Generated.BetaMessageStopEvent.Type
| typeof Generated.BetaContentBlockStartEvent.Type
| typeof Generated.BetaContentBlockDeltaEvent.Type
| typeof Generated.BetaContentBlockStopEvent.Type
| typeof Generated.BetaErrorResponse.Type
// =============================================================================
// Service Identifier
// =============================================================================
/**
* Service tag for the Anthropic client.
*
* **When to use**
*
* Use when accessing or providing the Anthropic client service through Effect's
* context.
*
* @see {@link make} for constructing an Anthropic client effectfully
* @see {@link layer} for providing a client from explicit options
* @see {@link layerConfig} for providing a client from `Config`
*
* @category services
* @since 4.0.0
*/
export class AnthropicClient extends Context.Service<AnthropicClient, Service>()(
"@effect/ai-anthropic/AnthropicClient"
) {}
// =============================================================================
// Options
// =============================================================================
/**
* Configuration for creating an Anthropic client.
*
* **When to use**
*
* Use when the Anthropic client settings are already available as values and
* should be passed directly to `make` or `layer`.
*
* **Details**
*
* These options configure the base Anthropic URL, the `x-api-key`
* authentication header, the `anthropic-version` header, and an optional
* transformation of the underlying `HttpClient`.
*
* @see {@link make} for constructing an Anthropic client from explicit options
* @see {@link layer} for providing an Anthropic client from explicit options
* @see {@link layerConfig} for loading Anthropic client settings from `Config`
*
* @category options
* @since 4.0.0
*/
export type Options = {
/**
* The Anthropic API key for authentication. Requests are made without authentication when this is omitted, which is
* useful for proxied setups or testing.
*/
readonly apiKey?: Redacted.Redacted<string> | undefined
/**
* The base URL for the Anthropic API. Override this to use a proxy or a different API-compatible endpoint.
*
* @default "https://api.anthropic.com"
*/
readonly apiUrl?: string | undefined
/**
* The Anthropic API version header value. This controls which version of the API to use.
*
* @default "2023-06-01"
*/
readonly apiVersion?: string | undefined
/**
* Optional transformer for the underlying HTTP client, such as middleware, logging, or custom request/response
* handling.
*/
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
}
// =============================================================================
// Constructor
// =============================================================================
const RedactedAnthropicHeaders = {
AnthropicApiKey: "x-api-key"
}
/**
* Creates an Anthropic client service with the given options.
*
* **When to use**
*
* Use when you have explicit configuration values and need an `Effect` that
* constructs the Anthropic client service, rather than providing it as a `Layer`.
*
* **Details**
*
* The client handles API key authentication via the `x-api-key` header, API versioning via the `anthropic-version`
* header, error mapping to the unified `AiError` type, and request/response transformations via `AnthropicConfig`. It
* requires an `HttpClient` in the context.
*
* @see {@link layer} for providing the client as a `Layer` from explicit options
* @see {@link layerConfig} for providing the client as a `Layer` with `Config`-based settings
*
* @category constructors
* @since 4.0.0
*/
export const make = Effect.fnUntraced(
function*(options: Options): Effect.fn.Return<Service, never, HttpClient.HttpClient> {
const baseClient = yield* HttpClient.HttpClient
const apiVersion = options.apiVersion ?? "2023-06-01"
const httpClient = baseClient.pipe(
HttpClient.mapRequest((request) =>
request.pipe(
HttpClientRequest.prependUrl(options.apiUrl ?? "https://api.anthropic.com"),
Predicate.isNotUndefined(options.apiKey)
? HttpClientRequest.setHeader(
RedactedAnthropicHeaders.AnthropicApiKey,
Redacted.value(options.apiKey)
)
: identity,
HttpClientRequest.setHeader("anthropic-version", apiVersion),
HttpClientRequest.acceptJson
)
),
Predicate.isNotUndefined(options.transformClient)
? options.transformClient
: identity
)
const client = Generated.make(httpClient, {
transformClient: Effect.fnUntraced(function*(client) {
const config = yield* AnthropicConfig.getOrUndefined
if (Predicate.isNotUndefined(config?.transformClient)) {
return config.transformClient(client)
}
return client
})
})
const httpClientOk = HttpClient.filterStatusOk(httpClient)
const streamRequest =
<S extends Sse.EventCodec>(schema: S) =>
(request: HttpClientRequest.HttpClientRequest): Stream.Stream<
S["Type"],
HttpClientError.HttpClientError | Schema.SchemaError | Sse.Retry,
S["DecodingServices"]
> =>
httpClientOk.execute(request).pipe(
Effect.map((response) => response.stream),
Stream.unwrap,
Stream.decodeText,
Stream.pipeThroughChannel(Sse.decodeSchema(schema))
)
const createMessage = (options: {
readonly payload: typeof Generated.BetaCreateMessageParams.Encoded
readonly params?: typeof Generated.BetaMessagesPostParams.Encoded | undefined
}): Effect.Effect<
[body: typeof Generated.BetaMessage.Type, response: HttpClientResponse.HttpClientResponse],
AiError.AiError
> =>
client.betaMessagesPost({ ...options, config: { includeResponse: true } }).pipe(
Effect.catchTags({
BetaMessagesPost4XX: (error) => Effect.fail(Errors.mapClientError(error, "createMessage")),
HttpClientError: (error) => Errors.mapHttpClientError(error, "createMessage"),
SchemaError: (error) => Effect.fail(Errors.mapSchemaError(error, "createMessage"))
})
)
const PingEvent = Schema.Struct({
type: Schema.Literal("ping")
})
const MessageEvent = Schema.Union([
PingEvent,
Generated.BetaMessageStartEvent,
Generated.BetaMessageDeltaEvent,
Generated.BetaMessageStopEvent,
Generated.BetaContentBlockStartEvent,
Generated.BetaContentBlockDeltaEvent,
Generated.BetaContentBlockStopEvent,
Generated.BetaErrorResponse
])
const buildMessageStream = (
response: HttpClientResponse.HttpClientResponse
): [HttpClientResponse.HttpClientResponse, Stream.Stream<MessageStreamEvent, AiError.AiError>] => {
const stream = response.stream.pipe(
Stream.decodeText,
Stream.pipeThroughChannel(Sse.decodeDataSchema(MessageEvent)),
Stream.takeUntil((event) => event.data.type === "message_stop"),
Stream.map((event) => event.data),
Stream.filter((event): event is MessageStreamEvent => event.type !== "ping"),
Stream.catchTags({
// TODO: handle SSE retries
Retry: (error) => Stream.die(error),
HttpClientError: (error) => Stream.fromEffect(Errors.mapHttpClientError(error, "createMessageStream")),
SchemaError: (error) => Stream.fail(Errors.mapSchemaError(error, "createMessageStream"))
})
) as any
return [response, stream]
}
const createMessageStream: Service["createMessageStream"] = (options) => {
const request = HttpClientRequest.post("/v1/messages", {
headers: Headers.fromInput({
"anthropic-beta": options.params?.["anthropic-beta"] ?? undefined,
"anthropic-version": options.params?.["anthropic-version"] ?? apiVersion
}),
body: HttpBody.jsonUnsafe({
...options.payload,
stream: true
})
})
return httpClientOk.execute(request).pipe(
Effect.map(buildMessageStream),
Effect.catchTag(
"HttpClientError",
(error) => Errors.mapHttpClientError(error, "createMessageStream")
)
)
}
return AnthropicClient.of({
client,
streamRequest,
createMessage,
createMessageStream
})
},
Effect.updateService(
Headers.CurrentRedactedNames,
Array.appendAll(Object.values(RedactedAnthropicHeaders))
)
)
// =============================================================================
// Layers
// =============================================================================
/**
* Creates a layer for the Anthropic client with the given options.
*
* **When to use**
*
* Use when you already have explicit `Options` values, such as an API key or
* custom API URL, and want to provide `AnthropicClient` as a `Layer`.
*
* @see {@link make} for constructing the client service effectfully
* @see {@link layerConfig} for loading client settings from `Config`
*
* @category layers
* @since 4.0.0
*/
export const layer = (options: Options): Layer.Layer<AnthropicClient, never, HttpClient.HttpClient> =>
Layer.effect(AnthropicClient, make(options))
/**
* Creates a layer for the Anthropic client, loading the requisite configuration
* via Effect's `Config` module.
*
* **When to use**
*
* Use when you want to provide the Anthropic client as a `Layer` with
* configuration loaded from Effect's `Config` module, such as from environment
* variables or a secrets provider.
*
* @see {@link layer} for providing the client from explicit options instead of `Config`
* @see {@link make} for constructing the client service effectfully
*
* @category layers
* @since 4.0.0
*/
export const layerConfig = (options?: {
/**
* The Anthropic API key for authentication. Requests are made without authentication when this is omitted, which is
* useful for proxied setups or testing.
*/
readonly apiKey?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
/**
* The base URL for the Anthropic API. Override this to use a proxy or a different API-compatible endpoint.
*
* @default "https://api.anthropic.com"
*/
readonly apiUrl?: Config.Config<string> | undefined
/**
* The Anthropic API version header value. This controls which version of the API to use.
*
* @default "2023-06-01"
*/
readonly apiVersion?: Config.Config<string> | undefined
/**
* Optional transformer for the underlying HTTP client, such as middleware, logging, or custom request/response
* handling.
*/
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
}): Layer.Layer<AnthropicClient, Config.ConfigError, HttpClient.HttpClient> =>
Layer.effect(
AnthropicClient,
Effect.gen(function*() {
const apiKey = Predicate.isNotUndefined(options?.apiKey)
? yield* options.apiKey :
undefined
const apiUrl = Predicate.isNotUndefined(options?.apiUrl)
? yield* options.apiUrl :
undefined
const apiVersion = Predicate.isNotUndefined(options?.apiVersion)
? yield* options.apiVersion :
undefined
return yield* make({
apiKey,
apiUrl,
apiVersion,
transformClient: options?.transformClient
})
})
)

View File

@@ -0,0 +1,84 @@
/**
* The `AnthropicConfig` module lets a workflow temporarily customize the HTTP
* client used by generated Anthropic requests. It is used by
* `AnthropicClient` when request helpers run, so code can add middleware,
* logging, or other client changes without rebuilding the client layer.
*
* @since 4.0.0
*/
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import type { HttpClient } from "effect/unstable/http/HttpClient"
/**
* Service tag for Anthropic client configuration overrides, such as transformations applied to the generated HTTP client.
*
* **When to use**
*
* Use when you need to provide or read Anthropic client configuration through
* Effect's context from a layer or integration.
*
* @see {@link withClientTransform} for scoping an HTTP client transformation
*
* @category services
* @since 4.0.0
*/
export class AnthropicConfig extends Context.Service<
AnthropicConfig,
AnthropicConfig.Service
>()("@effect/ai-anthropic/AnthropicConfig") {
/**
* Gets the configured Anthropic service from the current context when present.
*
* @since 4.0.0
*/
static readonly getOrUndefined: Effect.Effect<typeof AnthropicConfig.Service | undefined> = Effect.map(
Effect.context<never>(),
(services) => services.mapUnsafe.get(AnthropicConfig.key)
)
}
/**
* Namespace containing types associated with the `AnthropicConfig` service.
*
* @since 4.0.0
*/
export declare namespace AnthropicConfig {
/**
* Configuration provided through `AnthropicConfig`.
*
* **Details**
*
* Use `transformClient` to wrap or replace the `HttpClient` used by generated Anthropic API requests.
*
* @category models
* @since 4.0.0
*/
export interface Service {
readonly transformClient?: ((client: HttpClient) => HttpClient) | undefined
}
}
/**
* Runs an effect with an `AnthropicConfig` override that transforms the underlying `HttpClient` used by generated Anthropic requests.
*
* **When to use**
*
* Use when you need to apply a temporary `HttpClient` transformation, such as adding middleware or logging, to a
* specific scope of an effectful program.
*
* @category configuration
* @since 4.0.0
*/
export const withClientTransform: {
(transform: (client: HttpClient) => HttpClient): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
<A, E, R>(self: Effect.Effect<A, E, R>, transform: (client: HttpClient) => HttpClient): Effect.Effect<A, E, R>
} = dual(2, <A, E, R>(
self: Effect.Effect<A, E, R>,
transformClient: (client: HttpClient) => HttpClient
) =>
Effect.flatMap(
AnthropicConfig.getOrUndefined,
(config) => Effect.provideService(self, AnthropicConfig, { ...config, transformClient })
))

View File

@@ -0,0 +1,212 @@
/**
* Anthropic error metadata augmentation.
*
* Provides Anthropic-specific metadata fields for AI error types through module
* augmentation, enabling typed access to Anthropic error details.
*
* @since 4.0.0
*/
/**
* Anthropic-specific error metadata fields.
*
* **Details**
*
* Contains the Anthropic error type and request identifier copied from provider
* error responses when available. Either field may be `null` when Anthropic
* does not include it or the response cannot be decoded.
*
* @see {@link AnthropicRateLimitMetadata} for rate-limit responses that also include parsed Anthropic rate-limit headers
*
* @category models
* @since 4.0.0
*/
export type AnthropicErrorMetadata = {
/**
* The Anthropic error type returned by the API.
*/
readonly errorType: string | null
/**
* The unique request ID for debugging with Anthropic support.
*/
readonly requestId: string | null
}
/**
* Anthropic-specific rate limit metadata fields.
*
* **Details**
*
* Extends base error metadata with rate limit-specific information from Anthropic's rate limit headers.
*
* @category models
* @since 4.0.0
*/
export type AnthropicRateLimitMetadata = AnthropicErrorMetadata & {
/**
* Number of requests allowed in the current period.
*/
readonly requestsLimit: number | null
/**
* Number of requests remaining in the current period.
*/
readonly requestsRemaining: number | null
/**
* Time when the request rate limit resets.
*/
readonly requestsReset: string | null
/**
* Number of tokens allowed in the current period.
*/
readonly tokensLimit: number | null
/**
* Number of tokens remaining in the current period.
*/
readonly tokensRemaining: number | null
/**
* Time when the token rate limit resets.
*/
readonly tokensReset: string | null
}
declare module "effect/unstable/ai/AiError" {
/**
* Anthropic metadata attached to `RateLimitError` values.
*
* **Details**
*
* Includes request identifiers, Anthropic error types, and parsed request or token limit headers when the provider rejects a request due to rate limits.
*
* @category configuration
* @since 4.0.0
*/
export interface RateLimitErrorMetadata {
readonly anthropic?: AnthropicRateLimitMetadata | null
}
/**
* Anthropic metadata attached to `QuotaExhaustedError` values.
*
* **Details**
*
* Captures the Anthropic error type and request identifier for failures where the account or workspace has exhausted its available quota.
*
* @category configuration
* @since 4.0.0
*/
export interface QuotaExhaustedErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
/**
* Anthropic metadata attached to `AuthenticationError` values.
*
* **Details**
*
* Preserves Anthropic error details for missing, invalid, or unauthorized API credentials while keeping the error in the shared AI error model.
*
* @category configuration
* @since 4.0.0
*/
export interface AuthenticationErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
/**
* Anthropic metadata attached to `ContentPolicyError` values.
*
* **Details**
*
* Records Anthropic error details returned when a request or response is rejected by Anthropic safety or content policy enforcement.
*
* @category configuration
* @since 4.0.0
*/
export interface ContentPolicyErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
/**
* Anthropic metadata attached to `InvalidRequestError` values.
*
* **Details**
*
* Provides the Anthropic error type and request identifier for malformed or unsupported requests rejected before model execution.
*
* @category configuration
* @since 4.0.0
*/
export interface InvalidRequestErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
/**
* Anthropic metadata attached to `InternalProviderError` values.
*
* **Details**
*
* Preserves Anthropic request correlation data for provider-side failures that should be reported or investigated with Anthropic support.
*
* @category configuration
* @since 4.0.0
*/
export interface InternalProviderErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
/**
* Anthropic metadata attached to `InvalidOutputError` values.
*
* **Details**
*
* Describes Anthropic-specific context for responses that could not be decoded or interpreted as valid AI output.
*
* @category configuration
* @since 4.0.0
*/
export interface InvalidOutputErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
/**
* Anthropic metadata attached to `StructuredOutputError` values.
*
* **Details**
*
* Captures Anthropic error details for structured-output failures, including request correlation data useful when diagnosing schema-related responses.
*
* @category configuration
* @since 4.0.0
*/
export interface StructuredOutputErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
/**
* Anthropic metadata attached to `UnsupportedSchemaError` values.
*
* **Details**
*
* Provides Anthropic error details for schemas that cannot be represented by or submitted to the Anthropic API.
*
* @category configuration
* @since 4.0.0
*/
export interface UnsupportedSchemaErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
/**
* Anthropic metadata attached to `UnknownError` values.
*
* **Details**
*
* Retains the Anthropic error type and request identifier when a provider response cannot be classified as a more specific AI error.
*
* @category configuration
* @since 4.0.0
*/
export interface UnknownErrorMetadata {
readonly anthropic?: AnthropicErrorMetadata | null
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
/**
* The `AnthropicTelemetry` module defines Anthropic-specific telemetry
* attributes and a helper for adding them to a tracing span. It keeps the
* standard GenAI telemetry attributes and adds request and response metadata
* under the `gen_ai.anthropic.*` OpenTelemetry namespaces.
*
* @since 4.0.0
*/
import { dual } from "effect/Function"
import * as String from "effect/String"
import type { Span } from "effect/Tracer"
import type { Simplify } from "effect/Types"
import * as Telemetry from "effect/unstable/ai/Telemetry"
/**
* The attributes used to describe telemetry in the context of Generative
* Artificial Intelligence (GenAI) Models requests and responses.
*
* **Details**
*
* These attributes follow the OpenTelemetry generative AI semantic
* conventions:
* https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/
*
* @category models
* @since 4.0.0
*/
export type AnthropicTelemetryAttributes = Simplify<
& Telemetry.GenAITelemetryAttributes
& Telemetry.AttributesWithPrefix<RequestAttributes, "gen_ai.anthropic.request">
& Telemetry.AttributesWithPrefix<ResponseAttributes, "gen_ai.anthropic.response">
>
/**
* All telemetry attributes which are part of the GenAI specification,
* including the Anthropic-specific attributes.
*
* @category models
* @since 4.0.0
*/
export type AllAttributes = Telemetry.AllAttributes & RequestAttributes & ResponseAttributes
/**
* Telemetry attributes which are part of the GenAI specification and are
* namespaced by `gen_ai.anthropic.request`.
*
* @category models
* @since 4.0.0
*/
export interface RequestAttributes {
/**
* Whether extended thinking is enabled.
*/
readonly extendedThinking?: boolean | null | undefined
/**
* The budget tokens for extended thinking.
*/
readonly thinkingBudgetTokens?: number | null | undefined
}
/**
* Telemetry attributes which are part of the GenAI specification and are
* namespaced by `gen_ai.anthropic.response`.
*
* @category models
* @since 4.0.0
*/
export interface ResponseAttributes {
/**
* The stop reason from the response.
*/
readonly stopReason?: string | null | undefined
/**
* Number of cache creation input tokens.
*/
readonly cacheCreationInputTokens?: number | null | undefined
/**
* Number of cache read input tokens.
*/
readonly cacheReadInputTokens?: number | null | undefined
}
/**
* Options accepted by `addGenAIAnnotations`, combining standard GenAI telemetry attributes with optional Anthropic request and response attributes.
*
* @category options
* @since 4.0.0
*/
export type AnthropicTelemetryAttributeOptions = Telemetry.GenAITelemetryAttributeOptions & {
anthropic?: {
request?: RequestAttributes | undefined
response?: ResponseAttributes | undefined
} | undefined
}
const addAnthropicRequestAttributes = Telemetry.addSpanAttributes("gen_ai.anthropic.request", String.camelToSnake)<
RequestAttributes
>
const addAnthropicResponseAttributes = Telemetry.addSpanAttributes("gen_ai.anthropic.response", String.camelToSnake)<
ResponseAttributes
>
/**
* Applies the specified Anthropic GenAI telemetry attributes to the provided
* `Span`.
*
* **When to use**
*
* Use to annotate an Anthropic model span with standard GenAI telemetry
* attributes and Anthropic-specific request or response metadata.
*
* **Gotchas**
*
* This method mutates the `Span` in place.
*
* @category annotations
* @since 4.0.0
*/
export const addGenAIAnnotations: {
(options: AnthropicTelemetryAttributeOptions): (span: Span) => void
(span: Span, options: AnthropicTelemetryAttributeOptions): void
} = dual(2, (span: Span, options: AnthropicTelemetryAttributeOptions) => {
Telemetry.addGenAIAnnotations(span, options)
if (options.anthropic != null) {
if (options.anthropic.request != null) {
addAnthropicRequestAttributes(span, options.anthropic.request)
}
if (options.anthropic.response != null) {
addAnthropicResponseAttributes(span, options.anthropic.response)
}
}
})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/**
* @since 4.0.0
*/
// @barrel: Auto-generated exports. Do not edit manually.
/**
* @since 4.0.0
*/
export * as AnthropicClient from "./AnthropicClient.ts"
/**
* @since 4.0.0
*/
export * as AnthropicConfig from "./AnthropicConfig.ts"
/**
* @since 4.0.0
*/
export * as AnthropicError from "./AnthropicError.ts"
/**
* @since 4.0.0
*/
export * as AnthropicLanguageModel from "./AnthropicLanguageModel.ts"
/**
* @since 4.0.0
*/
export * as AnthropicTelemetry from "./AnthropicTelemetry.ts"
/**
* @since 4.0.0
*/
export * as AnthropicTool from "./AnthropicTool.ts"
/**
* @since 4.0.0
*/
export * as Generated from "./Generated.ts"

View File

@@ -0,0 +1,370 @@
import * as Duration from "effect/Duration"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import * as Number from "effect/Number"
import * as Option from "effect/Option"
import * as Predicate from "effect/Predicate"
import * as Redactable from "effect/Redactable"
import * as Schema from "effect/Schema"
import * as AiError from "effect/unstable/ai/AiError"
import type * as Response from "effect/unstable/ai/Response"
import type * as HttpClientError from "effect/unstable/http/HttpClientError"
import type * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import type * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
import type { AnthropicErrorMetadata } from "../AnthropicError.ts"
import type * as Generated from "../Generated.ts"
// =============================================================================
// Anthropic Error Body Schema
// =============================================================================
/** @internal */
export const AnthropicErrorBody = Schema.Struct({
type: Schema.Literal("error"),
error: Schema.Struct({
type: Schema.String,
message: Schema.String
})
})
/** @internal */
export type AnthropicClientErrorBody = {
readonly type: "error"
readonly error: {
readonly type: string
readonly message: string
}
readonly request_id: string | null
}
// =============================================================================
// Error Mappers
// =============================================================================
/** @internal */
export const mapSchemaError = dual<
(method: string) => (error: Schema.SchemaError) => AiError.AiError,
(error: Schema.SchemaError, method: string) => AiError.AiError
>(2, (error, method) =>
AiError.make({
module: "AnthropicClient",
method,
reason: AiError.InvalidOutputError.fromSchemaError(error)
}))
/** @internal */
export const mapClientError = dual<
(method: string) => (error: Generated.AnthropicClientError<string, AnthropicClientErrorBody>) => AiError.AiError,
(error: Generated.AnthropicClientError<string, AnthropicClientErrorBody>, method: string) => AiError.AiError
>(2, (error, method) => {
const { request, response, cause } = error
const status = response.status
const headers = response.headers as Record<string, string>
const metadata: AnthropicErrorMetadata = {
errorType: cause.error.type,
requestId: cause.request_id
}
const http = buildHttpContext({ request, response, body: JSON.stringify(cause) })
const reason = mapStatusCodeToReason({
status,
headers,
message: cause.error.message,
metadata,
http
})
return AiError.make({ module: "AnthropicClient", method, reason })
})
/** @internal */
export const mapHttpClientError = dual<
(method: string) => (error: HttpClientError.HttpClientError) => Effect.Effect<never, AiError.AiError>,
(error: HttpClientError.HttpClientError, method: string) => Effect.Effect<never, AiError.AiError>
>(2, (error, method) => {
const reason = error.reason
switch (reason._tag) {
case "TransportError": {
return Effect.fail(AiError.make({
module: "AnthropicClient",
method,
reason: new AiError.NetworkError({
reason: "TransportError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "EncodeError": {
return Effect.fail(AiError.make({
module: "AnthropicClient",
method,
reason: new AiError.NetworkError({
reason: "EncodeError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "InvalidUrlError": {
return Effect.fail(AiError.make({
module: "AnthropicClient",
method,
reason: new AiError.NetworkError({
reason: "InvalidUrlError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "StatusCodeError": {
return mapStatusCodeError(reason, method)
}
case "DecodeError": {
return Effect.fail(AiError.make({
module: "AnthropicClient",
method,
reason: new AiError.InvalidOutputError({
description: reason.description ?? "Failed to decode response"
})
}))
}
case "EmptyBodyError": {
return Effect.fail(AiError.make({
module: "AnthropicClient",
method,
reason: new AiError.InvalidOutputError({
description: reason.description ?? "Response body was empty"
})
}))
}
}
})
/** @internal */
const mapStatusCodeError = Effect.fnUntraced(function*(
error: HttpClientError.StatusCodeError,
method: string
) {
const { request, response, description } = error
const status = response.status
const headers = response.headers as Record<string, string>
const requestId = headers["request-id"]
let body: string | undefined = description
if (!description || !description.startsWith("{")) {
const responseBody = yield* Effect.option(response.text)
if (Option.isSome(responseBody) && responseBody.value) {
body = responseBody.value
}
}
let json: unknown = undefined
// @effect-diagnostics effect/tryCatchInEffectGen:off
try {
json = Predicate.isNotUndefined(body) ? JSON.parse(body) : undefined
} catch {
json = undefined
}
const decoded = Schema.decodeUnknownOption(AnthropicErrorBody)(json)
const reason = mapStatusCodeToReason({
status,
headers,
message: Option.isSome(decoded) ? decoded.value.error.message : undefined,
http: buildHttpContext({ request, response, body }),
metadata: {
errorType: Option.isSome(decoded) ? decoded.value.error.type : null,
requestId: requestId ?? null
}
})
return yield* AiError.make({ module: "AnthropicClient", method, reason })
})
// =============================================================================
// Rate Limits
// =============================================================================
/** @internal */
export const parseRateLimitHeaders = (headers: Record<string, string>) => {
const retryAfterRaw = headers["retry-after"]
let retryAfter: Duration.Duration | undefined
if (Predicate.isNotUndefined(retryAfterRaw)) {
const parsed = Number.parse(retryAfterRaw)
if (Option.isSome(parsed)) {
retryAfter = Duration.seconds(parsed.value)
}
}
const requestsLimitRaw = headers["anthropic-ratelimit-requests-limit"]
const requestsRemainingRaw = headers["anthropic-ratelimit-requests-remaining"]
const tokensLimitRaw = headers["anthropic-ratelimit-tokens-limit"]
const tokensRemainingRaw = headers["anthropic-ratelimit-tokens-remaining"]
return {
retryAfter,
requestsLimit: Predicate.isNotUndefined(requestsLimitRaw) ? Option.getOrNull(Number.parse(requestsLimitRaw)) : null,
requestsRemaining: Predicate.isNotUndefined(requestsRemainingRaw)
? Option.getOrNull(Number.parse(requestsRemainingRaw))
: null,
requestsReset: headers["anthropic-ratelimit-requests-reset"] ?? null,
tokensLimit: Predicate.isNotUndefined(tokensLimitRaw) ? Option.getOrNull(Number.parse(tokensLimitRaw)) : null,
tokensRemaining: Predicate.isNotUndefined(tokensRemainingRaw)
? Option.getOrNull(Number.parse(tokensRemainingRaw))
: null,
tokensReset: headers["anthropic-ratelimit-tokens-reset"] ?? null
}
}
// =============================================================================
// HTTP Context
// =============================================================================
/** @internal */
export const buildHttpRequestDetails = (
request: HttpClientRequest.HttpClientRequest
): typeof Response.HttpRequestDetails.Type => ({
method: request.method,
url: request.url,
urlParams: Array.from(request.urlParams),
hash: Option.getOrUndefined(request.hash),
headers: Redactable.redact(request.headers) as Record<string, string>
})
/** @internal */
export const buildHttpContext = (params: {
readonly request: HttpClientRequest.HttpClientRequest
readonly response?: HttpClientResponse.HttpClientResponse
readonly body?: string | undefined
}): typeof AiError.HttpContext.Type => ({
request: buildHttpRequestDetails(params.request),
response: Predicate.isNotUndefined(params.response)
? {
status: params.response.status,
headers: Redactable.redact(params.response.headers) as Record<string, string>
}
: undefined,
body: params.body
})
// =============================================================================
// HTTP Status Code
// =============================================================================
const buildInvalidRequestDescription = (params: {
readonly status: number
readonly message: string | undefined
readonly method: string
readonly url: string
readonly errorType: string | null
readonly requestId: string | null
readonly body: string | undefined
}): string => {
const parts: Array<string> = []
if (params.message) {
parts.push(params.message)
} else {
parts.push(`HTTP ${params.status}`)
}
parts.push(`(${params.method} ${params.url})`)
if (params.errorType) {
parts.push(`[type: ${params.errorType}]`)
}
if (params.requestId) {
parts.push(`[requestId: ${params.requestId}]`)
}
if (!params.message && params.body) {
const truncated = params.body.length > 200
? params.body.slice(0, 200) + "..."
: params.body
parts.push(`Response: ${truncated}`)
}
return parts.join(" ")
}
/** @internal */
export const mapStatusCodeToReason = ({ status, headers, message, metadata, http }: {
readonly status: number
readonly headers: Record<string, string>
readonly message: string | undefined
readonly metadata: AnthropicErrorMetadata
readonly http: typeof AiError.HttpContext.Type
}): AiError.AiErrorReason => {
const invalidRequestDescription = buildInvalidRequestDescription({
status,
message,
method: http.request.method,
url: http.request.url,
errorType: metadata.errorType,
requestId: metadata.requestId,
body: http.body
})
switch (status) {
case 400:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { anthropic: metadata },
http
})
case 401:
return new AiError.AuthenticationError({
kind: "InvalidKey",
metadata: { anthropic: metadata },
http
})
case 403:
return new AiError.AuthenticationError({
kind: "InsufficientPermissions",
metadata: { anthropic: metadata },
http
})
case 404:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { anthropic: metadata },
http
})
case 422:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { anthropic: metadata },
http
})
case 429: {
const { retryAfter, ...rateLimitMetadata } = parseRateLimitHeaders(headers)
return new AiError.RateLimitError({
retryAfter,
metadata: {
anthropic: {
...metadata,
...rateLimitMetadata
}
},
http
})
}
case 529:
return new AiError.InternalProviderError({
description: message ?? "Anthropic API is overloaded",
metadata: { anthropic: metadata },
http
})
default:
if (status >= 500) {
return new AiError.InternalProviderError({
description: message ?? "Server error",
metadata: { anthropic: metadata },
http
})
}
return new AiError.UnknownError({
description: message,
metadata: { anthropic: metadata },
http
})
}
}

View File

@@ -0,0 +1,26 @@
import * as Predicate from "effect/Predicate"
import type * as Response from "effect/unstable/ai/Response"
const finishReasonMap: Record<string, Response.FinishReason> = {
end_turn: "stop",
max_tokens: "length",
pause_turn: "pause",
refusal: "content-filter",
stop_sequence: "stop",
tool_use: "tool-calls"
}
/** @internal */
export const resolveFinishReason = (
finishReason: string,
isJsonResponse: boolean = false
): Response.FinishReason => {
const reason = finishReasonMap[finishReason]
if (Predicate.isUndefined(reason)) {
return "unknown"
}
if (isJsonResponse && reason === "tool-calls") {
return "stop"
}
return reason
}

View File

@@ -0,0 +1,526 @@
import { AnthropicClient, AnthropicLanguageModel, AnthropicTool } from "@effect/ai-anthropic"
import { assert, describe, it } from "@effect/vitest"
import { Effect, Layer, Redacted, Schema, Stream } from "effect"
import { AnthropicStructuredOutput, LanguageModel, Tool, Toolkit } from "effect/unstable/ai"
import { HttpClient, type HttpClientError, type HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
describe("AnthropicLanguageModel", () => {
describe("streamText", () => {
it.effect("decodes tool call params in content_block_stop", () =>
Effect.gen(function*() {
const toolParams = { pattern: "*.ts" }
const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(sseResponse(request, [
{
type: "message_start",
message: {
id: "msg_test_1",
type: "message",
role: "assistant",
model: "claude-sonnet-4-20250514",
content: [],
stop_reason: null,
stop_sequence: null,
usage: {
cache_creation: null,
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
inference_geo: null,
input_tokens: 10,
output_tokens: 0,
service_tier: null
}
}
},
{
type: "content_block_start",
index: 0,
content_block: {
type: "tool_use",
id: "toolu_test_1",
name: "GlobTool",
input: {}
}
},
{
type: "content_block_delta",
index: 0,
delta: {
type: "input_json_delta",
partial_json: JSON.stringify(toolParams)
}
},
{
type: "content_block_stop",
index: 0
},
{
type: "message_delta",
delta: {
stop_reason: "tool_use",
stop_sequence: null
},
usage: {
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
input_tokens: null,
output_tokens: 5
}
},
{
type: "message_stop"
}
]))
)
))
)
const GlobTool = Tool.make("GlobTool", {
description: "Search for files",
parameters: Schema.Struct({ pattern: Schema.String }),
success: Schema.String
})
const toolkit = Toolkit.make(GlobTool)
const toolkitLayer = toolkit.toLayer({
GlobTool: () => Effect.succeed("found.ts")
})
const partsChunk = yield* LanguageModel.streamText({
prompt: "find ts files",
toolkit,
disableToolCallResolution: true
}).pipe(
Stream.runCollect,
Effect.provide(AnthropicLanguageModel.model("claude-sonnet-4-20250514")),
Effect.provide(toolkitLayer),
Effect.provide(layer)
)
const parts = globalThis.Array.from(partsChunk)
const toolCall = parts.find((part) => part.type === "tool-call")
assert.isDefined(toolCall)
if (toolCall?.type !== "tool-call") {
return
}
assert.strictEqual(toolCall.name, "GlobTool")
assert.deepStrictEqual(toolCall.params, toolParams)
}))
// `Model` is an open enum in Anthropic's spec (`anyOf: [{ type: string }, ...consts]`), and it is
// $ref'd by response schemas. Responses must therefore decode for model ids that are newer than the
// generated literals, and the id must survive decoding unchanged.
it.effect("decodes responses for a model id that is not a known literal", () =>
Effect.gen(function*() {
const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(sseResponse(request, [
{
type: "message_start",
message: {
id: "msg_test_1",
type: "message",
role: "assistant",
model: "claude-not-a-known-model-id",
content: [],
stop_reason: null,
stop_sequence: null,
usage: {
cache_creation: null,
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
inference_geo: null,
input_tokens: 10,
output_tokens: 0,
service_tier: null
}
}
},
{
type: "content_block_start",
index: 0,
content_block: { type: "text", text: "" }
},
{
type: "content_block_delta",
index: 0,
delta: { type: "text_delta", text: "Hello" }
},
{
type: "content_block_stop",
index: 0
},
{
type: "message_delta",
delta: {
stop_reason: "end_turn",
stop_sequence: null
},
usage: {
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
input_tokens: null,
output_tokens: 5
}
},
{
type: "message_stop"
}
]))
)
))
)
const partsChunk = yield* LanguageModel.streamText({
prompt: "say hello"
}).pipe(
Stream.runCollect,
Effect.provide(AnthropicLanguageModel.model("claude-not-a-known-model-id")),
Effect.provide(layer)
)
const parts = globalThis.Array.from(partsChunk)
const metadata = parts.find((part) => part.type === "response-metadata")
assert.isDefined(metadata)
if (metadata?.type !== "response-metadata") {
return
}
assert.strictEqual(metadata.modelId, "claude-not-a-known-model-id")
const text = parts.find((part) => part.type === "text-delta")
assert.isDefined(text)
if (text?.type !== "text-delta") {
return
}
assert.strictEqual(text.delta, "Hello")
}))
})
describe("generateText", () => {
it.effect("encodes dynamic tools", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined = undefined
const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, {
id: "msg_test_1",
type: "message",
role: "assistant",
model: "claude-sonnet-4-20250514",
content: [{ type: "text", text: "Done" }],
stop_reason: "end_turn",
stop_sequence: null,
usage: {
cache_creation: null,
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
inference_geo: null,
input_tokens: 10,
output_tokens: 5,
service_tier: null
}
}))
})
))
)
const inputSchema = {
type: "object",
properties: {
query: { type: "string" },
limit: { type: "number" }
},
required: ["query"],
additionalProperties: false
} as const
const DynamicTool = Tool.dynamic("DynamicTool", {
description: "A dynamic tool",
parameters: inputSchema
})
yield* LanguageModel.generateText({
prompt: "Use the dynamic tool",
toolkit: Toolkit.make(DynamicTool),
disableToolCallResolution: true
}).pipe(
Effect.provide(AnthropicLanguageModel.model("claude-sonnet-4-20250514")),
Effect.provide(layer)
)
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const body = yield* getRequestBody(capturedRequest)
const dynamicTool = body.tools.find((tool: any) => tool.name === "DynamicTool")
assert.isDefined(dynamicTool)
if (dynamicTool === undefined) {
return
}
assert.strictEqual(dynamicTool.description, "A dynamic tool")
assert.deepStrictEqual(dynamicTool.input_schema, inputSchema)
}))
})
describe("generateObject", () => {
// A model that supports native structured output requests it via `output_config.format` (json_schema)
// rather than falling back to a forced JSON tool.
const assertNativeStructuredOutput = (model: string) =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined = undefined
const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, {
id: "msg_test_1",
type: "message",
role: "assistant",
model,
content: [{ type: "text", text: JSON.stringify({ name: "John", age: 30 }) }],
stop_reason: "end_turn",
stop_sequence: null,
usage: {
cache_creation: null,
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
inference_geo: null,
input_tokens: 10,
output_tokens: 5,
service_tier: null
}
}))
})
))
)
// Assert the request shape; the response outcome is irrelevant here.
yield* LanguageModel.generateObject({
prompt: "Give me a person",
schema: Schema.Struct({ name: Schema.String, age: Schema.Number })
}).pipe(
Effect.provide(AnthropicLanguageModel.model(model)),
Effect.provide(layer),
Effect.ignore
)
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const body = yield* getRequestBody(capturedRequest)
assert.strictEqual(body.output_config?.format?.type, "json_schema")
})
it.effect("uses native json_schema output for claude-opus-4-6", () =>
assertNativeStructuredOutput("claude-opus-4-6"))
it.effect("uses native json_schema output for claude-sonnet-4-6", () =>
assertNativeStructuredOutput("claude-sonnet-4-6"))
})
// The packaged `Memory_20250818` tool ships `customName: "AnthropicMemory"` /
// `providerName: "memory"`, and is a client-executed provider tool. These
// tests cover the round-trip that was broken on beta.98 (see #2615):
// - the provider wire name ("memory") must resolve to the toolkit's custom
// name ("AnthropicMemory"), otherwise `makeResponse` raises ToolNotFound
// - `view_range` uses `Schema.optionalKey`, otherwise the Anthropic codec
// rejects the tool schema with "Unsupported AST Undefined"
// - `create` must carry `file_text`, otherwise the file body is dropped
describe("Memory tool", () => {
const memoryResponse = (request: HttpClientRequest.HttpClientRequest, input: unknown) =>
jsonResponse(request, {
id: "msg_test_1",
type: "message",
role: "assistant",
model: "claude-sonnet-4-20250514",
content: [{ type: "tool_use", id: "toolu_mem_1", name: "memory", input }],
stop_reason: "tool_use",
stop_sequence: null,
usage: {
cache_creation: null,
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
inference_geo: null,
input_tokens: 10,
output_tokens: 5,
service_tier: null
}
})
it.effect("resolves the provider wire name to the tool's custom name (view)", () =>
Effect.gen(function*() {
let receivedParams: unknown = undefined
const toolkit = Toolkit.make(AnthropicTool.Memory_20250818({}))
const toolkitLayer = toolkit.toLayer({
AnthropicMemory: (params) => {
receivedParams = params
return Effect.succeed("memory listing")
}
})
const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => Effect.succeed(memoryResponse(request, { command: "view", path: "/memories" })))
))
)
const response = yield* LanguageModel.generateText({
prompt: "check memory",
toolkit
}).pipe(
Effect.provide(AnthropicLanguageModel.model("claude-sonnet-4-20250514")),
Effect.provide(toolkitLayer),
Effect.provide(layer)
)
// Handler was resolved under the custom name and received the decoded command
assert.deepStrictEqual(receivedParams, { command: "view", path: "/memories" })
const toolResult = response.toolResults[0]
assert.isDefined(toolResult)
assert.strictEqual(toolResult.name, "AnthropicMemory")
assert.strictEqual(toolResult.result, "memory listing")
}))
it.effect("decodes the create command including file_text", () =>
Effect.gen(function*() {
let receivedParams: unknown = undefined
const toolkit = Toolkit.make(AnthropicTool.Memory_20250818({}))
const toolkitLayer = toolkit.toLayer({
AnthropicMemory: (params) => {
receivedParams = params
return Effect.succeed("File created successfully at: /memories/notes.txt")
}
})
const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(memoryResponse(request, {
command: "create",
path: "/memories/notes.txt",
file_text: "hello world"
}))
)
))
)
const response = yield* LanguageModel.generateText({
prompt: "save a note",
toolkit
}).pipe(
Effect.provide(AnthropicLanguageModel.model("claude-sonnet-4-20250514")),
Effect.provide(toolkitLayer),
Effect.provide(layer)
)
assert.deepStrictEqual(receivedParams, {
command: "create",
path: "/memories/notes.txt",
file_text: "hello world"
})
assert.strictEqual(response.toolResults[0]?.name, "AnthropicMemory")
}))
})
// Client-executed (`requiresHandler`) provider tools have their `parameters`
// decoded via `toCodecAnthropic` when the model calls them. Optional
// parameters must use `Schema.optionalKey` (not `Schema.optional`), otherwise
// the codec rejects the schema with "Unsupported AST Undefined" (see #2615).
describe("client provider tool parameters compile with the Anthropic codec", () => {
const displayArgs = { displayWidthPx: 800, displayHeightPx: 600 }
const clientTools: ReadonlyArray<readonly [string, Tool.AnyProviderDefined]> = [
["Bash_20241022", AnthropicTool.Bash_20241022({})],
["Bash_20250124", AnthropicTool.Bash_20250124({})],
["ComputerUse_20241022", AnthropicTool.ComputerUse_20241022(displayArgs)],
["ComputerUse_20250124", AnthropicTool.ComputerUse_20250124(displayArgs)],
["ComputerUse_20251124", AnthropicTool.ComputerUse_20251124(displayArgs)],
["Memory_20250818", AnthropicTool.Memory_20250818({})],
["TextEditor_20241022", AnthropicTool.TextEditor_20241022({})],
["TextEditor_20250124", AnthropicTool.TextEditor_20250124({})],
["TextEditor_20250429", AnthropicTool.TextEditor_20250429({})],
["TextEditor_20250728", AnthropicTool.TextEditor_20250728({})]
]
for (const [name, tool] of clientTools) {
it(name, () => {
const codec = AnthropicStructuredOutput.toCodecAnthropic(tool.parametersSchema)
assert.isDefined(codec)
})
}
})
})
const makeHttpClient = (
handler: (
request: HttpClientRequest.HttpClientRequest
) => Effect.Effect<HttpClientResponse.HttpClientResponse, HttpClientError.HttpClientError>
) =>
HttpClient.makeWith(
Effect.fnUntraced(function*(requestEffect) {
const request = yield* requestEffect
return yield* handler(request)
}),
Effect.succeed as HttpClient.HttpClient.Preprocess<HttpClientError.HttpClientError, never>
)
const sseResponse = (
request: HttpClientRequest.HttpClientRequest,
events: ReadonlyArray<unknown>
): HttpClientResponse.HttpClientResponse =>
HttpClientResponse.fromWeb(
request,
new Response(toSseBody(events), {
status: 200,
headers: {
"content-type": "text/event-stream"
}
})
)
const jsonResponse = (
request: HttpClientRequest.HttpClientRequest,
body: unknown
): HttpClientResponse.HttpClientResponse =>
HttpClientResponse.fromWeb(
request,
new Response(JSON.stringify(body), {
status: 200,
headers: {
"content-type": "application/json"
}
})
)
const getRequestBody = (request: HttpClientRequest.HttpClientRequest) =>
Effect.gen(function*() {
const body = request.body
if (body._tag !== "Uint8Array") {
return yield* Effect.die(new Error("Expected Uint8Array body"))
}
return JSON.parse(new TextDecoder().decode(body.body))
})
const toSseBody = (events: ReadonlyArray<unknown>): string =>
events.map((event) => `event: message_stream\ndata: ${JSON.stringify(event)}\n\n`).join("")

View File

@@ -0,0 +1,8 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "../../../tsconfig.base.json",
"include": ["src"],
"references": [
{ "path": "../../effect" }
]
}

View File

@@ -0,0 +1,14 @@
import { AnthropicLanguageModel } from "@effect/ai-anthropic"
import { describe, expect, it } from "tstyche"
declare const acceptsKnownModel: (model: AnthropicLanguageModel.Model) => void
describe("AnthropicLanguageModel", () => {
describe("Model", () => {
it("keeps the known model ids as literals, while the constructors still accept custom ids", () => {
expect(acceptsKnownModel).type.toBeCallableWith("claude-opus-4-8")
expect(acceptsKnownModel).type.not.toBeCallableWith("not-a-real-model")
expect(AnthropicLanguageModel.model).type.toBeCallableWith("not-a-real-model")
})
})
})

View File

@@ -0,0 +1,6 @@
import { mergeConfig, type ViteUserConfig } from "vitest/config"
import shared from "../../../vitest.shared.ts"
const config: ViteUserConfig = {}
export default mergeConfig(shared, config)

View File

@@ -0,0 +1,742 @@
# @effect/ai-openai-compat
## 4.0.0-beta.99
### Patch Changes
- Updated dependencies [[`8ce4795`](https://github.com/Effect-TS/effect/commit/8ce4795ccbaebca4292757db568c005a992546a4), [`80b539f`](https://github.com/Effect-TS/effect/commit/80b539f8aba68f478c75c35c2b4140c4ffc4fada), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`e6e6dba`](https://github.com/Effect-TS/effect/commit/e6e6dba6e9d86e7c2ad27dcedf289db76a19697f), [`bfb203e`](https://github.com/Effect-TS/effect/commit/bfb203e95aa439f731acad37fc3a9a831a190f1c), [`2e9a34a`](https://github.com/Effect-TS/effect/commit/2e9a34ac2bece4f3a206160480c991e3841dc67a), [`55d4eb3`](https://github.com/Effect-TS/effect/commit/55d4eb34f2c64d54f6a25a305b5c5438ebd7934e), [`bddb010`](https://github.com/Effect-TS/effect/commit/bddb010eac3d4436cb094edbbee7460c5440c162), [`a328835`](https://github.com/Effect-TS/effect/commit/a328835e50d76bc96648a1c1550456e8c9f81210), [`5560d05`](https://github.com/Effect-TS/effect/commit/5560d05aa6abdd29466d9c3412cc5e648b0adbde), [`8f6e3ad`](https://github.com/Effect-TS/effect/commit/8f6e3adb185b16e8820b98c509b308086f7ff1af), [`46997fa`](https://github.com/Effect-TS/effect/commit/46997fa60401f5e3c93daa4b61f7df8e31caaab4), [`9e6e12d`](https://github.com/Effect-TS/effect/commit/9e6e12d75c118cd265496f2880490d1f33a5c8bf), [`3394b93`](https://github.com/Effect-TS/effect/commit/3394b93d97d6f24fc38670641d1490289ffca7f1), [`febeabc`](https://github.com/Effect-TS/effect/commit/febeabc3f7c31094da000a23edeaabfe2ab00a38), [`54161c9`](https://github.com/Effect-TS/effect/commit/54161c98f6f3569e0c31842f54e6a257f9421c4c), [`385f7a4`](https://github.com/Effect-TS/effect/commit/385f7a4ee4a7359928597ea56d151dbaf5eb5802), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`7543afe`](https://github.com/Effect-TS/effect/commit/7543afea6f4d97d1f1ad876224323838a48daadd), [`44b9cf3`](https://github.com/Effect-TS/effect/commit/44b9cf3d240d726997b4bbcd0ede48e074d3c456), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`0a8aa6a`](https://github.com/Effect-TS/effect/commit/0a8aa6acb90a72b91c24d17133c950e4cacd8abd), [`c8d9fcf`](https://github.com/Effect-TS/effect/commit/c8d9fcf7b030f7c474effbab2764ce7aee1c7209), [`9ca7f9a`](https://github.com/Effect-TS/effect/commit/9ca7f9a69363e4485645966d5a93b8f9597c5206), [`e7aca89`](https://github.com/Effect-TS/effect/commit/e7aca894bb32fbb785b5830837e6061c415a6015), [`55d7560`](https://github.com/Effect-TS/effect/commit/55d75609b8acf8a1b54c1b1c7fbbb65ec741aa3e), [`f809189`](https://github.com/Effect-TS/effect/commit/f809189ddf6b6011ba43a9901baaa734e315da2a), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`0ebdbe7`](https://github.com/Effect-TS/effect/commit/0ebdbe74463dc84385956d0b1e8c2b79ebab5400), [`7517d09`](https://github.com/Effect-TS/effect/commit/7517d09f12a0b183a81bd425962c4e280a68b05d), [`212493b`](https://github.com/Effect-TS/effect/commit/212493b9a1eb98cd1ef6959c707a2e5784a5ae91), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`80ea8cb`](https://github.com/Effect-TS/effect/commit/80ea8cb9222ca73f564c8267ab2f82966fea027a), [`8df19f4`](https://github.com/Effect-TS/effect/commit/8df19f4fe81d90cc33ace88b9a77e5534f82d604)]:
- effect@4.0.0-beta.99
## 4.0.0-beta.98
### Patch Changes
- [#2608](https://github.com/Effect-TS/effect-smol/pull/2608) [`5f142a2`](https://github.com/Effect-TS/effect-smol/commit/5f142a2136e62274ec121273fecb5d248c19f159) Thanks @tim-smart! - Preserve autocomplete for known OpenAI-compatible model config properties while allowing provider-specific properties.
- [#2576](https://github.com/Effect-TS/effect-smol/pull/2576) [`0c2ed5e`](https://github.com/Effect-TS/effect-smol/commit/0c2ed5ee0ef5a437c5e6a2de456a5ddf214c281f) Thanks @tim-smart! - Normalize empty assistant message content to an empty string for OpenAI-compatible providers that reject null content values.
- Updated dependencies [[`989603b`](https://github.com/Effect-TS/effect-smol/commit/989603b60ab1197b64acf214208e0d370cd1f842), [`214c458`](https://github.com/Effect-TS/effect-smol/commit/214c458084bb6995d543cd37d1055f24be3d454e), [`a037273`](https://github.com/Effect-TS/effect-smol/commit/a0372736ac34796969b051bbba4717d7983f1ebe), [`97fdaa9`](https://github.com/Effect-TS/effect-smol/commit/97fdaa9c1f522c65e579365d314a07878e2b904f), [`b24d248`](https://github.com/Effect-TS/effect-smol/commit/b24d248c8df44222ce642087cde2bd859a2dc709), [`19c222c`](https://github.com/Effect-TS/effect-smol/commit/19c222cac2353a3d7b7733caecb00556fffe9a5c), [`eec85dd`](https://github.com/Effect-TS/effect-smol/commit/eec85ddba09ea326fd268ee33eeffd47e50d4671), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`8849052`](https://github.com/Effect-TS/effect-smol/commit/884905232d1e9a365e046d8dde27bf9c5707f57f), [`c15e16a`](https://github.com/Effect-TS/effect-smol/commit/c15e16ad130d1fbde25d912b7ac55995066cb35b), [`01d00a3`](https://github.com/Effect-TS/effect-smol/commit/01d00a3abfbf1f37996cdbe738ea5137c646cdd7), [`8bd4589`](https://github.com/Effect-TS/effect-smol/commit/8bd458975a1b3a8ed042eccf317b93d28ded91e7), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`6e08428`](https://github.com/Effect-TS/effect-smol/commit/6e08428d980501b856f846ad3f3f0e4ea46e7786), [`388dcf9`](https://github.com/Effect-TS/effect-smol/commit/388dcf953f65d317547f34d40e6443c5f264205f), [`2b7ce2b`](https://github.com/Effect-TS/effect-smol/commit/2b7ce2b513e7ec2a77822f1116dc6ffb6ba93f4e), [`87bea7e`](https://github.com/Effect-TS/effect-smol/commit/87bea7e16259246f3bcdf565446394751abca953), [`ce38dc3`](https://github.com/Effect-TS/effect-smol/commit/ce38dc33bda805a684432cca071f4dc3c6b9a1ba), [`a807cd1`](https://github.com/Effect-TS/effect-smol/commit/a807cd170341deca8a1cfb52c4222585f2431bb9), [`fd8a356`](https://github.com/Effect-TS/effect-smol/commit/fd8a356f06a8c9ce4e7e0a13fc4021c178ed31de), [`c2a5edc`](https://github.com/Effect-TS/effect-smol/commit/c2a5edc3abd31ad5bc123362bc1213e03e4095c3), [`5946da3`](https://github.com/Effect-TS/effect-smol/commit/5946da3804a1be5e752b05b96bd058cdba50a1bf), [`4ae0c5f`](https://github.com/Effect-TS/effect-smol/commit/4ae0c5ffcbe6c56ddfcb05c639112a079483539e), [`5b2a0bc`](https://github.com/Effect-TS/effect-smol/commit/5b2a0bceea3a28a33a58555210c90a415dc74a76), [`72ac585`](https://github.com/Effect-TS/effect-smol/commit/72ac585884befde6af9208da738699a93f1bae79), [`5e8c1b8`](https://github.com/Effect-TS/effect-smol/commit/5e8c1b82bfafa121311f987a49ab75395e3647a7), [`0f9c078`](https://github.com/Effect-TS/effect-smol/commit/0f9c07841b04183f485ee6e6458de73b290b09f5)]:
- effect@4.0.0-beta.98
## 4.0.0-beta.97
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.97
## 4.0.0-beta.96
### Patch Changes
- Updated dependencies [[`1503f45`](https://github.com/Effect-TS/effect-smol/commit/1503f45cb5bb2a74f4705252ec505a1f0ade7e62), [`57fe793`](https://github.com/Effect-TS/effect-smol/commit/57fe79316ffbc380b30626a168981fb26ae97459), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`97f29df`](https://github.com/Effect-TS/effect-smol/commit/97f29df457f7ffd07cfb4b379315c12c086af805)]:
- effect@4.0.0-beta.96
## 4.0.0-beta.95
### Patch Changes
- Updated dependencies [[`a482442`](https://github.com/Effect-TS/effect-smol/commit/a482442abdeb490e9652b854ec3495e4aa7273e7), [`fbefa85`](https://github.com/Effect-TS/effect-smol/commit/fbefa850fab2f0a302c20614496aeaaa2a8b5590), [`0b4a32f`](https://github.com/Effect-TS/effect-smol/commit/0b4a32f4260f0d8500942a133001b0d349328102), [`18a49e1`](https://github.com/Effect-TS/effect-smol/commit/18a49e1786679456258002ff9397faf02f678c2d), [`266cb90`](https://github.com/Effect-TS/effect-smol/commit/266cb90bb2c17aabc40563c32db334f09ba3d74b), [`912f095`](https://github.com/Effect-TS/effect-smol/commit/912f095a34572bbd3cedf6edb27878443e3e4a95), [`a6718f9`](https://github.com/Effect-TS/effect-smol/commit/a6718f9e00a15ca903b0732da46116cbf3d6aca7), [`bef5154`](https://github.com/Effect-TS/effect-smol/commit/bef51540a243aa2f872a00c01d0cd58b7a769baa), [`18e0564`](https://github.com/Effect-TS/effect-smol/commit/18e0564bd0f8ebbdfcaf1e2c21529948e9e4a81d), [`fb50f14`](https://github.com/Effect-TS/effect-smol/commit/fb50f14fc3657c1973785aa5b72ecf0b0d28e0b2)]:
- effect@4.0.0-beta.95
## 4.0.0-beta.94
### Patch Changes
- Updated dependencies [[`95a0e9b`](https://github.com/Effect-TS/effect-smol/commit/95a0e9bb62797af0e81c9998773405f248f218c5), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63), [`f11ce73`](https://github.com/Effect-TS/effect-smol/commit/f11ce73af60823754dc24194f4ffc561b9ea1c2d), [`ff30b6e`](https://github.com/Effect-TS/effect-smol/commit/ff30b6e7c2c63ffc56a4c5818d6d86b01b5ad528), [`1caab3c`](https://github.com/Effect-TS/effect-smol/commit/1caab3cc30f626efbf15e59d74f539a487e5c85c), [`aa80c47`](https://github.com/Effect-TS/effect-smol/commit/aa80c4775a04db87553e5568764cab7e32a72814), [`c2ae4fc`](https://github.com/Effect-TS/effect-smol/commit/c2ae4fce2f03a4cd1861c2b1179da7df656e662d), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63)]:
- effect@4.0.0-beta.94
## 4.0.0-beta.93
### Patch Changes
- Updated dependencies [[`00652fe`](https://github.com/Effect-TS/effect-smol/commit/00652fe95c18f87208e91343eb8bf218faa2f677), [`6c58167`](https://github.com/Effect-TS/effect-smol/commit/6c5816746eaf91d2a3c7c899c5720809fa230ae3), [`2bc5415`](https://github.com/Effect-TS/effect-smol/commit/2bc541501a7ef89e542d7cb98e96beb53cd205cc), [`e11cccc`](https://github.com/Effect-TS/effect-smol/commit/e11cccc7d5fe631abccc7d6e3bd296938de0fa2e), [`ba7e77e`](https://github.com/Effect-TS/effect-smol/commit/ba7e77e046b8641a3a4e9750bb88ca4a1d063d3f), [`5713ee7`](https://github.com/Effect-TS/effect-smol/commit/5713ee7edbc3054efde407b2286bbfd45bbc6e1c)]:
- effect@4.0.0-beta.93
## 4.0.0-beta.92
### Patch Changes
- Updated dependencies [[`affdc13`](https://github.com/Effect-TS/effect-smol/commit/affdc139045cc325dce321a84a580fdc1b2da7b9)]:
- effect@4.0.0-beta.92
## 4.0.0-beta.91
### Patch Changes
- Updated dependencies [[`b135b25`](https://github.com/Effect-TS/effect-smol/commit/b135b2517fca9e7839734ace3699a7dfa75b9075), [`aaa21a3`](https://github.com/Effect-TS/effect-smol/commit/aaa21a369a171c600db294f2a4f640583043e150), [`3475ee6`](https://github.com/Effect-TS/effect-smol/commit/3475ee6c2bda6b05c6d7a12ce30c8bb840b5b1a6)]:
- effect@4.0.0-beta.91
## 4.0.0-beta.90
### Patch Changes
- Updated dependencies [[`d237fdf`](https://github.com/Effect-TS/effect-smol/commit/d237fdf726481f76eb52a6196e111b24122bc3d5)]:
- effect@4.0.0-beta.90
## 4.0.0-beta.89
### Patch Changes
- Updated dependencies [[`b7d46ab`](https://github.com/Effect-TS/effect-smol/commit/b7d46ab7e1a29d8711817bab583c9febf48a0dad), [`7777e15`](https://github.com/Effect-TS/effect-smol/commit/7777e1540fd3680dd8346723cffec812b9384669), [`5376197`](https://github.com/Effect-TS/effect-smol/commit/5376197ca8e50358a41b1fd3cec27bd1ec680ec6)]:
- effect@4.0.0-beta.89
## 4.0.0-beta.88
### Patch Changes
- Updated dependencies [[`911f1b8`](https://github.com/Effect-TS/effect-smol/commit/911f1b84790ce42b3a70c95b33e6f6fd9e74de8b), [`8beeeea`](https://github.com/Effect-TS/effect-smol/commit/8beeeea52879d8613a39468848f01c3092bd54d4), [`c306fcf`](https://github.com/Effect-TS/effect-smol/commit/c306fcfeb1ef38455156932a1faf49292b1318da)]:
- effect@4.0.0-beta.88
## 4.0.0-beta.87
### Patch Changes
- Updated dependencies [[`5a0c1a4`](https://github.com/Effect-TS/effect-smol/commit/5a0c1a4faee5707b5cc35e646ff1ffdad70f1956), [`1eea2ea`](https://github.com/Effect-TS/effect-smol/commit/1eea2ea3795ba47316b82b1ac8d4612c0ba389ed)]:
- effect@4.0.0-beta.87
## 4.0.0-beta.86
### Patch Changes
- Updated dependencies [[`0b5795a`](https://github.com/Effect-TS/effect-smol/commit/0b5795a0ab4395e8f15955d8d96f2303084bfc64), [`3e3a859`](https://github.com/Effect-TS/effect-smol/commit/3e3a859ec6351a9e0d31674aabbd48fcefabb12e), [`7dbec24`](https://github.com/Effect-TS/effect-smol/commit/7dbec240dbf3bca599a20c486632abce694ef5ab), [`d8c00a1`](https://github.com/Effect-TS/effect-smol/commit/d8c00a171ac7141e8adc08c332d1162d9a9d56fc), [`85b6317`](https://github.com/Effect-TS/effect-smol/commit/85b631701e935866f2762bd595237aa718370cd9), [`6d0fda0`](https://github.com/Effect-TS/effect-smol/commit/6d0fda0d0cbdfffc523c89c57dfdb1608f84fb12), [`108a933`](https://github.com/Effect-TS/effect-smol/commit/108a9335ff8571928197e5847a09c28ac83d6f46), [`7e1f455`](https://github.com/Effect-TS/effect-smol/commit/7e1f455fab5005d769b939c91e519d450f802cf9), [`46b3e79`](https://github.com/Effect-TS/effect-smol/commit/46b3e79944cfdae7901eb148135c85b7eb39834e)]:
- effect@4.0.0-beta.86
## 4.0.0-beta.85
### Patch Changes
- Updated dependencies [[`328d97c`](https://github.com/Effect-TS/effect-smol/commit/328d97cc53c0dcb89077a5623e35b095eaa59a8c), [`8441836`](https://github.com/Effect-TS/effect-smol/commit/8441836e6dde70e8ae2126be9cefe9b45798b134), [`074e436`](https://github.com/Effect-TS/effect-smol/commit/074e4361091289104cb0ab6959dc3b0ea7794a6a), [`c1dfd60`](https://github.com/Effect-TS/effect-smol/commit/c1dfd60663eb13a58916f3712d877499943b628a), [`2ba316b`](https://github.com/Effect-TS/effect-smol/commit/2ba316bd15fcbf1c50626500d44a2c9b3bec19f5), [`7ce7344`](https://github.com/Effect-TS/effect-smol/commit/7ce7344c41056c79e2ee19ee6a9346c0f1d227c1)]:
- effect@4.0.0-beta.85
## 4.0.0-beta.84
### Patch Changes
- Updated dependencies [[`87f52ba`](https://github.com/Effect-TS/effect-smol/commit/87f52ba16c4370ffa3f84bf8e53038e1419c284e), [`b8ee07f`](https://github.com/Effect-TS/effect-smol/commit/b8ee07ffda8903b5ec2e45a786ddcba59f128fda), [`867c0d7`](https://github.com/Effect-TS/effect-smol/commit/867c0d70a09079b040260d45a1e92ff04dbfbf2f), [`b93bc6c`](https://github.com/Effect-TS/effect-smol/commit/b93bc6c9cb27b909a41d094c97c4f9d25bbc6d6b), [`57d387f`](https://github.com/Effect-TS/effect-smol/commit/57d387f92c30ab63e15e3e641f0a903b65886610), [`bacca41`](https://github.com/Effect-TS/effect-smol/commit/bacca4141c2400effae1eabfdb36c89a459cf246), [`0f8ac79`](https://github.com/Effect-TS/effect-smol/commit/0f8ac7959d29ed68c68ce25aabd6bf0cb7e63ecc), [`25b4482`](https://github.com/Effect-TS/effect-smol/commit/25b448270c01317703f25107e1480d4cd0246d9a), [`9cf3a25`](https://github.com/Effect-TS/effect-smol/commit/9cf3a25c66b0c44a52be9829870c44517ea52db2), [`8def767`](https://github.com/Effect-TS/effect-smol/commit/8def7674b1787f91035298cda4d122937e87ef72)]:
- effect@4.0.0-beta.84
## 4.0.0-beta.83
### Patch Changes
- Updated dependencies [[`1f2e8ce`](https://github.com/Effect-TS/effect-smol/commit/1f2e8ceef09e0a791c850ed2ade01f97089596f9)]:
- effect@4.0.0-beta.83
## 4.0.0-beta.82
### Patch Changes
- Updated dependencies [[`193690b`](https://github.com/Effect-TS/effect-smol/commit/193690b642ea802bbed40d663bd677251bbe9dc3)]:
- effect@4.0.0-beta.82
## 4.0.0-beta.81
### Patch Changes
- Updated dependencies [[`93cb4f8`](https://github.com/Effect-TS/effect-smol/commit/93cb4f8fbfb9e07cb9dc86ce6b155fd1f8167914), [`60341d9`](https://github.com/Effect-TS/effect-smol/commit/60341d9ca744d0473ce3fab621ca9bd225af3a39), [`1105ab5`](https://github.com/Effect-TS/effect-smol/commit/1105ab56cb724212f7ea7b431396ce82e8fd0484), [`4500fbf`](https://github.com/Effect-TS/effect-smol/commit/4500fbfe00763d8a72af6e5d6c5988e8bd4ade36)]:
- effect@4.0.0-beta.81
## 4.0.0-beta.80
### Patch Changes
- [#2380](https://github.com/Effect-TS/effect-smol/pull/2380) [`b5f67a0`](https://github.com/Effect-TS/effect-smol/commit/b5f67a0ce9c110b98731ac485e5894df9da07e3a) Thanks @walln! - Surface reasoning tokens from OpenAI-compatible chat completion responses.
- Updated dependencies [[`d944330`](https://github.com/Effect-TS/effect-smol/commit/d94433090ee03f426d43e13b883abae4494e55e6), [`f48659f`](https://github.com/Effect-TS/effect-smol/commit/f48659fdcc84930ebc1e5b45b540c0f973389182), [`7652aaa`](https://github.com/Effect-TS/effect-smol/commit/7652aaa3bdbc39f241fe58b54b9a43b713e22e12), [`98630b7`](https://github.com/Effect-TS/effect-smol/commit/98630b7c8f679c352ba6796636c85688fa009d8d), [`90ae23c`](https://github.com/Effect-TS/effect-smol/commit/90ae23cf07284da5e1bcd9dffa882e85df7e617b)]:
- effect@4.0.0-beta.80
## 4.0.0-beta.79
### Patch Changes
- [#2338](https://github.com/Effect-TS/effect-smol/pull/2338) [`b12991f`](https://github.com/Effect-TS/effect-smol/commit/b12991f2346eda47fec72df5a89034394ad6c8fb) Thanks @boozedog! - Fix dropped streamed tool-call arguments when a provider sends `function.name: null` on continuation fragments.
OpenAI-compatible providers such as Fireworks send the tool name only on the first streamed `tool_calls` fragment and `function.name: null` on the continuation fragments that carry the argument deltas. `ChatCompletionToolFunctionDelta.name` was `Schema.optionalKey(Schema.String)` (non-nullable), so chunk validation rejected every continuation and silently discarded its argument delta, leaving the assembled tool call with empty or partial params. `name` is now nullable (`Schema.NullOr(Schema.String)`).
- Updated dependencies [[`b9704dc`](https://github.com/Effect-TS/effect-smol/commit/b9704dc9de9f1649ad502371014fe869b69a49a3), [`a207113`](https://github.com/Effect-TS/effect-smol/commit/a207113f66837bb54416926718a9a7d66774d079), [`5e9b9e2`](https://github.com/Effect-TS/effect-smol/commit/5e9b9e217b164ebfd4a002dd4380b3b1563200c3), [`7c128ae`](https://github.com/Effect-TS/effect-smol/commit/7c128aef458a1e2d224712e51c483c9badad1d44), [`0ada457`](https://github.com/Effect-TS/effect-smol/commit/0ada457c0513d8d908254ab77ebb7d29d2b523d6), [`d7cc5a2`](https://github.com/Effect-TS/effect-smol/commit/d7cc5a2bede3de10943aa0c6bdb4f26836a91efd), [`aad63be`](https://github.com/Effect-TS/effect-smol/commit/aad63becf65e0a6b076e94f8973be7bbe7fbd46f), [`09809f6`](https://github.com/Effect-TS/effect-smol/commit/09809f60f19ec98232f98b33e33e02ecb7e4fbd6), [`2fddda5`](https://github.com/Effect-TS/effect-smol/commit/2fddda5311929f46b61e503f0ade4fc749e8c77d), [`5f21768`](https://github.com/Effect-TS/effect-smol/commit/5f2176833399757c4500d8875b7f2fba0393de75), [`f27003e`](https://github.com/Effect-TS/effect-smol/commit/f27003e00524ff83f20dd9909f62b2f8795efe03)]:
- effect@4.0.0-beta.79
## 4.0.0-beta.78
### Patch Changes
- Updated dependencies [[`7836b8e`](https://github.com/Effect-TS/effect-smol/commit/7836b8eb8bb0f3e04cdf554ee070caccf74f00c1), [`35d49a3`](https://github.com/Effect-TS/effect-smol/commit/35d49a3a09bdba6b513de87ddcead9e61a1042ba), [`4093258`](https://github.com/Effect-TS/effect-smol/commit/40932580e65bafab5f23c5f14b520cb411d0b2cd)]:
- effect@4.0.0-beta.78
## 4.0.0-beta.77
### Patch Changes
- Updated dependencies [[`6e9a5ca`](https://github.com/Effect-TS/effect-smol/commit/6e9a5ca62a61156fd67b2518ad3ab14ac0d25f23), [`302f398`](https://github.com/Effect-TS/effect-smol/commit/302f3984ce206e35d86ddd99d3b72be144850a51)]:
- effect@4.0.0-beta.77
## 4.0.0-beta.76
### Patch Changes
- Updated dependencies [[`016108a`](https://github.com/Effect-TS/effect-smol/commit/016108a472af7048ddbbfd05f233e67529fafe12), [`95c03d2`](https://github.com/Effect-TS/effect-smol/commit/95c03d2c55930668c215b5a41c23cf7742fead84), [`07299a3`](https://github.com/Effect-TS/effect-smol/commit/07299a33c09fd52faa9810d30835a2622c752386)]:
- effect@4.0.0-beta.76
## 4.0.0-beta.75
### Patch Changes
- Updated dependencies [[`81b187c`](https://github.com/Effect-TS/effect-smol/commit/81b187c17a0d8817b58232826939154010ae49d7), [`ad4b535`](https://github.com/Effect-TS/effect-smol/commit/ad4b535e17f94ce35261829d5a3675f0a7808b4e), [`a29c2e7`](https://github.com/Effect-TS/effect-smol/commit/a29c2e7e3570920156702671d6f3367cd0195f6c), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`ffea4ec`](https://github.com/Effect-TS/effect-smol/commit/ffea4ecf2925f6a4c9fd13079d47584cbf2bed00), [`4255c9b`](https://github.com/Effect-TS/effect-smol/commit/4255c9ba78bb98c7838fbe9dccdd8465e9da5427)]:
- effect@4.0.0-beta.75
## 4.0.0-beta.74
### Patch Changes
- Updated dependencies [[`b1fc6a4`](https://github.com/Effect-TS/effect-smol/commit/b1fc6a4b4d0ca7fa9fd162799ae17c86f2f7ee8e)]:
- effect@4.0.0-beta.74
## 4.0.0-beta.73
### Patch Changes
- Updated dependencies [[`361ca30`](https://github.com/Effect-TS/effect-smol/commit/361ca30eb6e134feece547d6e00f82be4cb23f75), [`b9598c6`](https://github.com/Effect-TS/effect-smol/commit/b9598c6a209e75bfdb87ee3b024ecd1e3923ff6e)]:
- effect@4.0.0-beta.73
## 4.0.0-beta.72
### Patch Changes
- Updated dependencies [[`73e67d1`](https://github.com/Effect-TS/effect-smol/commit/73e67d119a84d697773eaecb4865c6a71eb1a9cb), [`01d71ec`](https://github.com/Effect-TS/effect-smol/commit/01d71ec5a75f3c2747a8d3b1ad9701d1e27b7ce5), [`fcd707e`](https://github.com/Effect-TS/effect-smol/commit/fcd707e091a16e1b35343c901cc4052274e32239)]:
- effect@4.0.0-beta.72
## 4.0.0-beta.71
### Patch Changes
- Updated dependencies [[`d8ac76b`](https://github.com/Effect-TS/effect-smol/commit/d8ac76b5bad458c42cebe8a0c1b3843f955ac293), [`2c3c00a`](https://github.com/Effect-TS/effect-smol/commit/2c3c00af6faba7b7d422af26a7a2bbc35636d230), [`3751e7c`](https://github.com/Effect-TS/effect-smol/commit/3751e7cf353e7a54cd692c37401207d9afba1e63), [`fc5f25b`](https://github.com/Effect-TS/effect-smol/commit/fc5f25b03ada5fc2431987768a74d3d3e75ca485), [`7ccced4`](https://github.com/Effect-TS/effect-smol/commit/7ccced42867c14c013b01160b3d292f14c05bd04), [`a2e1fe5`](https://github.com/Effect-TS/effect-smol/commit/a2e1fe5835c98c8ee4393a091b1d11b75126e349), [`4a4a36b`](https://github.com/Effect-TS/effect-smol/commit/4a4a36b10e6e616cad07584a43908f6a7e07e618), [`d350292`](https://github.com/Effect-TS/effect-smol/commit/d3502922b4740fa9d745797cbc3775cb67839b6d), [`730afb6`](https://github.com/Effect-TS/effect-smol/commit/730afb66696adf9bd5a328cbca29df9c05968771), [`df1b008`](https://github.com/Effect-TS/effect-smol/commit/df1b008f370f414c2a67a7b8139ef747af8e5fba), [`6d469d5`](https://github.com/Effect-TS/effect-smol/commit/6d469d567a7c41d7e5343bdee21d45b07b0e8190)]:
- effect@4.0.0-beta.71
## 4.0.0-beta.70
### Patch Changes
- Updated dependencies [[`af7782d`](https://github.com/Effect-TS/effect-smol/commit/af7782d3008d08b043f3a3f261516001514b2b4e), [`7212d70`](https://github.com/Effect-TS/effect-smol/commit/7212d701a3eee7b3553ff502e2c066126e52e839)]:
- effect@4.0.0-beta.70
## 4.0.0-beta.69
### Patch Changes
- Updated dependencies [[`70ea04a`](https://github.com/Effect-TS/effect-smol/commit/70ea04aa96a2a7859d738d414e1f0e3ed081a27a), [`d0ea8b0`](https://github.com/Effect-TS/effect-smol/commit/d0ea8b03f7d73ae076c1db12666141e480d11178), [`a57674b`](https://github.com/Effect-TS/effect-smol/commit/a57674b64845e9e75a456cf907bfdcb858859118), [`59aa334`](https://github.com/Effect-TS/effect-smol/commit/59aa334fbd0a504dda3c36f6d2ef1be7449b4b8b), [`8f4208e`](https://github.com/Effect-TS/effect-smol/commit/8f4208ee83bc7bdaa6793b5429847b45aab72470)]:
- effect@4.0.0-beta.69
## 4.0.0-beta.68
### Patch Changes
- Updated dependencies [[`af8267f`](https://github.com/Effect-TS/effect-smol/commit/af8267f2f3588c3fb611e9286f6f933f29ce1217), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`f136bb7`](https://github.com/Effect-TS/effect-smol/commit/f136bb763048cbc6b17edd26496dba3e2415b9fa), [`6f38f07`](https://github.com/Effect-TS/effect-smol/commit/6f38f07d5941a211b251383aaab0f4f55e8a6557), [`aec9c40`](https://github.com/Effect-TS/effect-smol/commit/aec9c401a53db227f18bf5e0c84db7130ad862d6)]:
- effect@4.0.0-beta.68
## 4.0.0-beta.67
### Patch Changes
- Updated dependencies [[`a42ef66`](https://github.com/Effect-TS/effect-smol/commit/a42ef6632abbddfa820995ae310ccc84ae8d9b6f), [`35594f8`](https://github.com/Effect-TS/effect-smol/commit/35594f811cafe471acd490114b103a1f8392c8d8), [`8bddd62`](https://github.com/Effect-TS/effect-smol/commit/8bddd628cb623f9533d345082583ff51cead6836), [`4be4c8d`](https://github.com/Effect-TS/effect-smol/commit/4be4c8d60862aa963869ee2ed9ffa048ffac0527), [`0c9d3ab`](https://github.com/Effect-TS/effect-smol/commit/0c9d3ab43eb721a370ed8306260cbac218c27e87), [`b156acc`](https://github.com/Effect-TS/effect-smol/commit/b156accd2691b4a051f823affdece7c39923ce85), [`d16c034`](https://github.com/Effect-TS/effect-smol/commit/d16c03434ee3e6dcd3bfc82b65d99e881d89025b), [`b559d68`](https://github.com/Effect-TS/effect-smol/commit/b559d68845f848a10153395778f035682d399075), [`a3de5d9`](https://github.com/Effect-TS/effect-smol/commit/a3de5d9215e5cc4a62e2666efbd7c1bf595eb84f), [`7e6c12e`](https://github.com/Effect-TS/effect-smol/commit/7e6c12ec9b3a5945f6c26e272cc8f6390541ad3e), [`098167a`](https://github.com/Effect-TS/effect-smol/commit/098167a220fe07da6f14455818733ab1b269c9dd)]:
- effect@4.0.0-beta.67
## 4.0.0-beta.66
### Patch Changes
- Updated dependencies [[`ca2498e`](https://github.com/Effect-TS/effect-smol/commit/ca2498e702ac2d83fb7187707b7eb069bdb261a2), [`cd7d1fb`](https://github.com/Effect-TS/effect-smol/commit/cd7d1fba7e2e2c5ac3ad64e1be433440a5bda436), [`19a7033`](https://github.com/Effect-TS/effect-smol/commit/19a703367ec817cffc41d152da9b594827408e2b), [`33d26b4`](https://github.com/Effect-TS/effect-smol/commit/33d26b4210b2e974f146a71e7eed962f8ce00900), [`856766b`](https://github.com/Effect-TS/effect-smol/commit/856766b2c506aaed6d2df1d63bf3a5b1b062e1d4), [`079c7df`](https://github.com/Effect-TS/effect-smol/commit/079c7df82559bb9ce10a86dffb85d25e6ce07dc3)]:
- effect@4.0.0-beta.66
## 4.0.0-beta.65
### Patch Changes
- Updated dependencies [[`6f11454`](https://github.com/Effect-TS/effect-smol/commit/6f11454a9b6c3bd00f6b35fd7af14a2f2d63a0a2)]:
- effect@4.0.0-beta.65
## 4.0.0-beta.64
### Patch Changes
- Updated dependencies [[`7d4877a`](https://github.com/Effect-TS/effect-smol/commit/7d4877a1929cdb690280ea254326c04f2ec97ea5)]:
- effect@4.0.0-beta.64
## 4.0.0-beta.63
### Patch Changes
- [#2133](https://github.com/Effect-TS/effect-smol/pull/2133) [`5be0aaa`](https://github.com/Effect-TS/effect-smol/commit/5be0aaad694c9eb943a710eb4f896bc4c3fcae99) Thanks @Zelys-DFKH! - Fix `OpenAiLanguageModel` leaking library-only config fields (`fileIdPrefixes`, `strictJsonSchema`) into request body, causing OpenAI 400 errors.
- Updated dependencies [[`7f927ff`](https://github.com/Effect-TS/effect-smol/commit/7f927ffb7a9801dcfc4096c29e369d13d65cd0ac), [`a696b3e`](https://github.com/Effect-TS/effect-smol/commit/a696b3e83a8504cdbe261a18c10a1cc0619ae102)]:
- effect@4.0.0-beta.63
## 4.0.0-beta.62
### Patch Changes
- Updated dependencies [[`4ab4b90`](https://github.com/Effect-TS/effect-smol/commit/4ab4b9007dc27a52ffabc6fcb37c96eeec795bf7)]:
- effect@4.0.0-beta.62
## 4.0.0-beta.61
### Patch Changes
- Updated dependencies [[`50790af`](https://github.com/Effect-TS/effect-smol/commit/50790af9b190c38d10fb0723837d49b66432638f), [`71f7c3d`](https://github.com/Effect-TS/effect-smol/commit/71f7c3df997deda92c84146d569696dab3bd645c), [`aae8797`](https://github.com/Effect-TS/effect-smol/commit/aae8797b9cb383be0c182dd58d03d787c354238b)]:
- effect@4.0.0-beta.61
## 4.0.0-beta.60
### Patch Changes
- Updated dependencies [[`f69d567`](https://github.com/Effect-TS/effect-smol/commit/f69d5675dcff9f4137295752baf066b7153fdc09), [`7909c95`](https://github.com/Effect-TS/effect-smol/commit/7909c954b8f6244a35a4b429f8dd0dff45dad620), [`bbb4dcc`](https://github.com/Effect-TS/effect-smol/commit/bbb4dcc6c406b83a416b4ad3541cc02037c420e4), [`7af2207`](https://github.com/Effect-TS/effect-smol/commit/7af2207901eabf3132c1b7010a69b3899c06fbbe), [`848b40a`](https://github.com/Effect-TS/effect-smol/commit/848b40a4bd4bf54a5098617d50c33c88eee8270a)]:
- effect@4.0.0-beta.60
## 4.0.0-beta.59
### Patch Changes
- Updated dependencies [[`56837ea`](https://github.com/Effect-TS/effect-smol/commit/56837ea2a338395b35550641374e9e589bd8b71d)]:
- effect@4.0.0-beta.59
## 4.0.0-beta.58
### Patch Changes
- Updated dependencies [[`11993d4`](https://github.com/Effect-TS/effect-smol/commit/11993d4934c66f5dc611b8bbf553f01d501ef8f7), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec)]:
- effect@4.0.0-beta.58
## 4.0.0-beta.57
### Patch Changes
- Updated dependencies [[`a971f5c`](https://github.com/Effect-TS/effect-smol/commit/a971f5cbd92dfe4274420bf0966595eb35531060), [`8e110c5`](https://github.com/Effect-TS/effect-smol/commit/8e110c5f02a429ccc43a91df8678e402138c0851)]:
- effect@4.0.0-beta.57
## 4.0.0-beta.56
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.56
## 4.0.0-beta.55
### Patch Changes
- Updated dependencies [[`42cc744`](https://github.com/Effect-TS/effect-smol/commit/42cc744570968deb365fb46d47b53d3277050c93), [`04855ce`](https://github.com/Effect-TS/effect-smol/commit/04855ceeca4d40c55a5750dd9893b691f8ea741a)]:
- effect@4.0.0-beta.55
## 4.0.0-beta.54
### Patch Changes
- Updated dependencies [[`e4b74f9`](https://github.com/Effect-TS/effect-smol/commit/e4b74f9c01a0e9b6cd58416de4af3a26d51da7c8), [`4c72808`](https://github.com/Effect-TS/effect-smol/commit/4c728081851c66dacf889a816535671bc841ae96)]:
- effect@4.0.0-beta.54
## 4.0.0-beta.53
### Patch Changes
- Updated dependencies [[`0768509`](https://github.com/Effect-TS/effect-smol/commit/07685094e931af07d104165195826a535b55fa7e), [`476aede`](https://github.com/Effect-TS/effect-smol/commit/476aede69c6efa06b5781ca5eb3e3b128ca29141), [`4f79c54`](https://github.com/Effect-TS/effect-smol/commit/4f79c542e7b508c235ff485d862cc8b29a8260c5), [`4be6a7c`](https://github.com/Effect-TS/effect-smol/commit/4be6a7cf35dab2a01d652f56dd35f0358c5a7e88), [`88927eb`](https://github.com/Effect-TS/effect-smol/commit/88927ebb896162cdba103b36553280b58e0facac)]:
- effect@4.0.0-beta.53
## 4.0.0-beta.52
### Patch Changes
- Updated dependencies [[`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`cf3a311`](https://github.com/Effect-TS/effect-smol/commit/cf3a311d863a8abb818840c3b80f847e621c43c1), [`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`131fdd5`](https://github.com/Effect-TS/effect-smol/commit/131fdd5b1f26531e265fe1a08f002002f47c276e)]:
- effect@4.0.0-beta.52
## 4.0.0-beta.51
### Patch Changes
- Updated dependencies [[`778d2af`](https://github.com/Effect-TS/effect-smol/commit/778d2afe9b5154bc1f9abae46d93ea7e54c87344), [`4e24dcf`](https://github.com/Effect-TS/effect-smol/commit/4e24dcf75037f65eebc1eb68623bc7cbf9d5512a), [`4b1c015`](https://github.com/Effect-TS/effect-smol/commit/4b1c0150e9bdb5559ed32d250deb66e17b4240c7), [`454f8ad`](https://github.com/Effect-TS/effect-smol/commit/454f8adad822929c3ef60f8280d0987226b049fd), [`6754a0c`](https://github.com/Effect-TS/effect-smol/commit/6754a0cd18626b06805a079cc5265525a5eb7d27), [`90f7fd5`](https://github.com/Effect-TS/effect-smol/commit/90f7fd5243871b30980964135db4512b8119fa82), [`d7e1519`](https://github.com/Effect-TS/effect-smol/commit/d7e151974934201fd93fa4c8a1192ee9a5d965a0), [`72a8122`](https://github.com/Effect-TS/effect-smol/commit/72a81228e09782bae512f7d041bbfbc78bc668d0)]:
- effect@4.0.0-beta.51
## 4.0.0-beta.50
### Patch Changes
- Updated dependencies [[`07be594`](https://github.com/Effect-TS/effect-smol/commit/07be594825de60f8e1b2102d21dbb9b8fc63b414), [`ae02433`](https://github.com/Effect-TS/effect-smol/commit/ae02433103ce28f53a0c9bfb4a44e75773289b7b)]:
- effect@4.0.0-beta.50
## 4.0.0-beta.49
### Patch Changes
- Updated dependencies [[`7d87873`](https://github.com/Effect-TS/effect-smol/commit/7d8787340ff549370f6f2a88b612e9ebbfd6ba45), [`c2f6f90`](https://github.com/Effect-TS/effect-smol/commit/c2f6f901b200a6e515b4f02c93ce8005b7bbf1c5), [`216f13c`](https://github.com/Effect-TS/effect-smol/commit/216f13c1fce454a21b489bb915714a17e791a1ac)]:
- effect@4.0.0-beta.49
## 4.0.0-beta.48
### Patch Changes
- Updated dependencies [[`4da56ec`](https://github.com/Effect-TS/effect-smol/commit/4da56ecff129b2da40137ffede23a73cc4e532d8), [`a5e6f77`](https://github.com/Effect-TS/effect-smol/commit/a5e6f774bab195cf50ecdc818240765f69a3bf4a), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070)]:
- effect@4.0.0-beta.48
## 4.0.0-beta.47
### Patch Changes
- Updated dependencies [[`c584726`](https://github.com/Effect-TS/effect-smol/commit/c58472674e750e6938df955044eab88feda95e45), [`86a91a4`](https://github.com/Effect-TS/effect-smol/commit/86a91a4f0c59286dfa9393232d8020dea70ed4db), [`131caf9`](https://github.com/Effect-TS/effect-smol/commit/131caf9525151a0cb29803a8f1dffa0f4f479d12), [`c3615c8`](https://github.com/Effect-TS/effect-smol/commit/c3615c88379b9daf252df0db72c6ac5a20326406)]:
- effect@4.0.0-beta.47
## 4.0.0-beta.46
### Patch Changes
- Updated dependencies [[`3a30b9e`](https://github.com/Effect-TS/effect-smol/commit/3a30b9e2ec2bd8b8193e1aa139f6878a07e3f5ee)]:
- effect@4.0.0-beta.46
## 4.0.0-beta.45
### Patch Changes
- Updated dependencies [[`5c3af6d`](https://github.com/Effect-TS/effect-smol/commit/5c3af6d554f60be34f8fc21d598d9a298ae11beb)]:
- effect@4.0.0-beta.45
## 4.0.0-beta.44
### Patch Changes
- [#1961](https://github.com/Effect-TS/effect-smol/pull/1961) [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970) Thanks @IMax153! - Rename the `ServiceMap` module to `Context` across exports, docs, and tests.
- Updated dependencies [[`e3f0621`](https://github.com/Effect-TS/effect-smol/commit/e3f0621454c3f5d11070d30619da27c9232cadc1), [`5b476ab`](https://github.com/Effect-TS/effect-smol/commit/5b476abc0bd7e9bb59135ea1bcad2e4936227ced), [`6b40e5a`](https://github.com/Effect-TS/effect-smol/commit/6b40e5a4a6bd2087c15a3d7374d25057fdedfa16), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`3b09fb3`](https://github.com/Effect-TS/effect-smol/commit/3b09fb31c40c2802b01f21c23bcdd1fe7fb0aa82), [`2370410`](https://github.com/Effect-TS/effect-smol/commit/237041062e5af4594d32db91597e34e70a632877), [`dabc272`](https://github.com/Effect-TS/effect-smol/commit/dabc272444a700eb629c07ba3e77671a841ca86e), [`08b63c3`](https://github.com/Effect-TS/effect-smol/commit/08b63c3df11bd35c9fd6090dbd166287fdc40664), [`dfff04c`](https://github.com/Effect-TS/effect-smol/commit/dfff04c4c2b1d352dfad83992a6dce1280c85cf9), [`9baed9e`](https://github.com/Effect-TS/effect-smol/commit/9baed9e17e84702e6e480fcef6f86404f9e24be9), [`7846792`](https://github.com/Effect-TS/effect-smol/commit/7846792adc7e1631d62d26d657bd7ba6139f369b), [`1556a24`](https://github.com/Effect-TS/effect-smol/commit/1556a247623636b7ebe438fb56d77f1a7bf957bb), [`7c11bc2`](https://github.com/Effect-TS/effect-smol/commit/7c11bc292ab8e46252fe8f7576fb685917bfb8b5), [`b5ea591`](https://github.com/Effect-TS/effect-smol/commit/b5ea5913ec1d45d0dd12a327b9dd966bda2f6d02), [`0853afa`](https://github.com/Effect-TS/effect-smol/commit/0853afaeb1633b2d7f8b66893bd01c3aa1ef2c22), [`ac845f3`](https://github.com/Effect-TS/effect-smol/commit/ac845f3ab40e0b8719576e7f9bc16ea2e0e02cd4), [`b80c462`](https://github.com/Effect-TS/effect-smol/commit/b80c46247480f47bb64fc480fab48a3f37bc8888), [`b3f535d`](https://github.com/Effect-TS/effect-smol/commit/b3f535d9a7ac13b5fb984c29f93561c57a081ff0), [`6fe2e93`](https://github.com/Effect-TS/effect-smol/commit/6fe2e93cc2f1b173ef89651d74b6a5d2626b3226), [`cda8004`](https://github.com/Effect-TS/effect-smol/commit/cda800451c1ffbdddfc08415aed7b2d91e0412ee), [`8335477`](https://github.com/Effect-TS/effect-smol/commit/8335477a8a936a24b5f3ee6203c1b268bd1bfc3c), [`8c836f9`](https://github.com/Effect-TS/effect-smol/commit/8c836f99ab1e896b9580a71d67773625baff2eaf), [`718ff6f`](https://github.com/Effect-TS/effect-smol/commit/718ff6fe3e3d3820cefd67d2bff1b2224fe08060), [`7eed84f`](https://github.com/Effect-TS/effect-smol/commit/7eed84fc33c5781a6fb11bf4fd189d424902ebd4), [`5df46fe`](https://github.com/Effect-TS/effect-smol/commit/5df46fe2f654d59ab5fc1578f4fc27fa40368ef9), [`82dd0f2`](https://github.com/Effect-TS/effect-smol/commit/82dd0f26c6442b07143762ef7bc33742d3978dd6), [`03ae41e`](https://github.com/Effect-TS/effect-smol/commit/03ae41e7304cffac9f18feea22b73468feafc43a), [`4677a0a`](https://github.com/Effect-TS/effect-smol/commit/4677a0a58f95eea38a211efcd3f345f237a9e44a), [`87e1fc8`](https://github.com/Effect-TS/effect-smol/commit/87e1fc8b67e4901d75f567b2fecc3841ab762cc4), [`c1af1b7`](https://github.com/Effect-TS/effect-smol/commit/c1af1b756f63291e9c0298cf95c98a6920a0c2a0), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`c8a877b`](https://github.com/Effect-TS/effect-smol/commit/c8a877b53e8f29616335719e5dd1c3992dddf780), [`7da961a`](https://github.com/Effect-TS/effect-smol/commit/7da961ae4916229d2246699a5d3b20e5b2dd2020)]:
- effect@4.0.0-beta.44
## 4.0.0-beta.43
### Patch Changes
- Updated dependencies [[`2ae33d0`](https://github.com/Effect-TS/effect-smol/commit/2ae33d050914915f7cb9c25ab0a020901e08d596), [`979811a`](https://github.com/Effect-TS/effect-smol/commit/979811a4c3f7ed21ed18ef560c49fb7f5569e80e), [`eb7dbef`](https://github.com/Effect-TS/effect-smol/commit/eb7dbeffa883386ad912815e62c0820cac1fdf8e), [`cf50eb4`](https://github.com/Effect-TS/effect-smol/commit/cf50eb49cb04706dae5185f624708117c413dee8), [`1d046fe`](https://github.com/Effect-TS/effect-smol/commit/1d046fe484560e23f3e22cb23eec6433f8f1fa02)]:
- effect@4.0.0-beta.43
## 4.0.0-beta.42
### Patch Changes
- [#1859](https://github.com/Effect-TS/effect-smol/pull/1859) [`a4809db`](https://github.com/Effect-TS/effect-smol/commit/a4809db80f65601d37ccafc13d773e55909c4e98) Thanks @lloydrichards! - add dynamic tooling for openai and openai-compact language models
- Updated dependencies [[`924e216`](https://github.com/Effect-TS/effect-smol/commit/924e216caa7e0bbf22e994a0cd2ce8b1f0f0b3ee), [`80e7f0c`](https://github.com/Effect-TS/effect-smol/commit/80e7f0cd9116e811e97b0ce30a77a8d1ecd072aa), [`f8328bf`](https://github.com/Effect-TS/effect-smol/commit/f8328bf0314da3dc7f31d314f94a5840e8d5217f), [`66d1c06`](https://github.com/Effect-TS/effect-smol/commit/66d1c06039079129707a230f7ad8c676439d7133), [`bee800b`](https://github.com/Effect-TS/effect-smol/commit/bee800bf285192a01bec72a7b7b51bc1159434e6), [`8930441`](https://github.com/Effect-TS/effect-smol/commit/8930441dee6f94c59c583d18d3ebd677cf1f2623)]:
- effect@4.0.0-beta.42
## 4.0.0-beta.41
### Patch Changes
- Updated dependencies [[`36f5c21`](https://github.com/Effect-TS/effect-smol/commit/36f5c2174d31ab42c4598bf81f178f40d0802283), [`d8ce758`](https://github.com/Effect-TS/effect-smol/commit/d8ce758669d6297ae932ac3251d83e7b49b22f30), [`11aab4c`](https://github.com/Effect-TS/effect-smol/commit/11aab4c6d37d5691adafc2d33da1a631b28ce814), [`3bc1efb`](https://github.com/Effect-TS/effect-smol/commit/3bc1efb53dd75b4a40de46f1f80c7f8a7d50af86), [`70e724e`](https://github.com/Effect-TS/effect-smol/commit/70e724e604604d4be1061cd8da0d360494998c84), [`738dee7`](https://github.com/Effect-TS/effect-smol/commit/738dee7edfd70af82dc4d2376db3a8ebe603eb48), [`2111963`](https://github.com/Effect-TS/effect-smol/commit/2111963f19b4c28c800664a8fac9590c1321885f), [`198a553`](https://github.com/Effect-TS/effect-smol/commit/198a553d9ce45f6a00bfc4d65ed0640669602d95)]:
- effect@4.0.0-beta.41
## 4.0.0-beta.40
### Patch Changes
- Updated dependencies [[`f62860f`](https://github.com/Effect-TS/effect-smol/commit/f62860f0e5e45978fabf7256ae620a13152a772a), [`973f281`](https://github.com/Effect-TS/effect-smol/commit/973f2812529aadc1cc54598b2039799fa72b80f8)]:
- effect@4.0.0-beta.40
## 4.0.0-beta.39
### Patch Changes
- Updated dependencies [[`f91fd3d`](https://github.com/Effect-TS/effect-smol/commit/f91fd3db39fe5628439fd175fba201a65a1aa9d0), [`edaae9d`](https://github.com/Effect-TS/effect-smol/commit/edaae9d65f464f941d7eddd723cd33d324f4b071), [`b47db0b`](https://github.com/Effect-TS/effect-smol/commit/b47db0bd5802064b6a24b3ea27c6ff2e0520d513), [`82d3c8e`](https://github.com/Effect-TS/effect-smol/commit/82d3c8e4f3f49b00df611b25aa6f8f74ec21b59b), [`7c22b31`](https://github.com/Effect-TS/effect-smol/commit/7c22b315d198dcbf44ae8cdb8b37879e1c9e3996)]:
- effect@4.0.0-beta.39
## 4.0.0-beta.38
### Patch Changes
- Updated dependencies [[`f4dbe5b`](https://github.com/Effect-TS/effect-smol/commit/f4dbe5b26b9c2d33fae024bf44afbdf8541792cd), [`a71a607`](https://github.com/Effect-TS/effect-smol/commit/a71a607c89fb6669a12a562c2c23be81dfbe1adb), [`66a0494`](https://github.com/Effect-TS/effect-smol/commit/66a0494ed75cd12f2721dcbb1d8a072e3d9e14b6), [`5ef7218`](https://github.com/Effect-TS/effect-smol/commit/5ef7218fc559d57301fe929b8a0cab4033f4f1fd), [`472d260`](https://github.com/Effect-TS/effect-smol/commit/472d260655bc311fba5c2c6e23bb77d8f7e36ba0)]:
- effect@4.0.0-beta.38
## 4.0.0-beta.37
### Patch Changes
- Updated dependencies [[`f7a0b71`](https://github.com/Effect-TS/effect-smol/commit/f7a0b711da8fdd645597dee29cacc5619c6afcf2), [`1e223c3`](https://github.com/Effect-TS/effect-smol/commit/1e223c30ccf835dfbb21284535d78549efaeca80), [`53740f4`](https://github.com/Effect-TS/effect-smol/commit/53740f47aa76d114b7d535649fb50efc54a09608), [`8c7cf89`](https://github.com/Effect-TS/effect-smol/commit/8c7cf89f719e580cbce1bf6c24e6996f1992a0a6), [`b6b81a9`](https://github.com/Effect-TS/effect-smol/commit/b6b81a940eaafcbc792d25413d6c02c707de31b2), [`8f4c1f9`](https://github.com/Effect-TS/effect-smol/commit/8f4c1f97ed60f8810b0b327b50117ffb2d8260d4), [`f2479f9`](https://github.com/Effect-TS/effect-smol/commit/f2479f9d3113b1f012db17a3852b4e28f478cf9c), [`c919921`](https://github.com/Effect-TS/effect-smol/commit/c9199217fad65529421d2cf95ecfff41257090fd), [`7af90c2`](https://github.com/Effect-TS/effect-smol/commit/7af90c2e3c99038eafa39650433839523790e2fe), [`f3be185`](https://github.com/Effect-TS/effect-smol/commit/f3be18569e5ca57c25eabf00df3ca601ebab43c7)]:
- effect@4.0.0-beta.37
## 4.0.0-beta.36
### Patch Changes
- Updated dependencies [[`60fcbcc`](https://github.com/Effect-TS/effect-smol/commit/60fcbcc43d09471e8f7e0969955d99dcefc5be81), [`0a60837`](https://github.com/Effect-TS/effect-smol/commit/0a6083713124440e630030375bab367e8d7df24e), [`49164d2`](https://github.com/Effect-TS/effect-smol/commit/49164d2c20a8d21b66514992c4a15d8521f6b36e), [`334b6e4`](https://github.com/Effect-TS/effect-smol/commit/334b6e4f76fe11941b516d61f57e268bc31f0ca6), [`5700695`](https://github.com/Effect-TS/effect-smol/commit/5700695f76ae6da6b94c9c87d4dd2b8054fb829b), [`f8f4456`](https://github.com/Effect-TS/effect-smol/commit/f8f445644f3aa7ec093cab7445198a62ba18a480), [`969d24f`](https://github.com/Effect-TS/effect-smol/commit/969d24fdfa48c4838e811983848d9cb4e9b3b12c), [`851eda0`](https://github.com/Effect-TS/effect-smol/commit/851eda0533946e39bacaaf581896320d7a4f3e8c), [`8059c1c`](https://github.com/Effect-TS/effect-smol/commit/8059c1c3eba9a90af7cd889ea261bcb8fff0c185), [`6f83295`](https://github.com/Effect-TS/effect-smol/commit/6f8329546a73eaddc7cb5e85ea8e37e73fbfb611), [`65f7f57`](https://github.com/Effect-TS/effect-smol/commit/65f7f5737575fed668987462c96d29a446707c32), [`e7fabd2`](https://github.com/Effect-TS/effect-smol/commit/e7fabd2265db690eae5cfc9b83730c84699aef61), [`89c3e98`](https://github.com/Effect-TS/effect-smol/commit/89c3e985401eb38f33a3ae21a94ad27de3c1d28b), [`53794ab`](https://github.com/Effect-TS/effect-smol/commit/53794ab7af30aa5c5004ecf53659fafbe4b10542)]:
- effect@4.0.0-beta.36
## 4.0.0-beta.35
### Patch Changes
- Updated dependencies [[`9252b43`](https://github.com/Effect-TS/effect-smol/commit/9252b43560f507709c2985abcf52a7837b23ddf8), [`7daf387`](https://github.com/Effect-TS/effect-smol/commit/7daf3870a656882a488a60f67881e6808c8f4d04), [`e1664a3`](https://github.com/Effect-TS/effect-smol/commit/e1664a38bc31ef4ceb4e9324c7226e1e99bf9c07), [`fdaa6e0`](https://github.com/Effect-TS/effect-smol/commit/fdaa6e0a41b6b6605438fa8557441792135380a2), [`19aa47e`](https://github.com/Effect-TS/effect-smol/commit/19aa47ef7b470e427620edca8970dd9cdd551216), [`c667dad`](https://github.com/Effect-TS/effect-smol/commit/c667dad07777b860e4764a3ba9a6cc41c236cd98), [`764d150`](https://github.com/Effect-TS/effect-smol/commit/764d1501bc5026b60fc8aef6cb02a5a87c762801), [`3c27098`](https://github.com/Effect-TS/effect-smol/commit/3c27098b5685a63db2c2eff654a250c94d3fcfa7)]:
- effect@4.0.0-beta.35
## 4.0.0-beta.34
### Patch Changes
- [#1764](https://github.com/Effect-TS/effect-smol/pull/1764) [`342fc4b`](https://github.com/Effect-TS/effect-smol/commit/342fc4b051739e32e7977159f26ff9541eda664f) Thanks @tim-smart! - Add unstable EmbeddingModel support across core and OpenAI providers.
- Add the unstable EmbeddingModel module API surface in `effect`, including service, request, response, and provider types.
- Implement the unstable EmbeddingModel runtime constructor in `effect`, with `RequestResolver` batching, `embed` / `embedMany` spans, provider error propagation, deterministic ordering, and empty-input `embedMany` fast-path behavior.
- Add and align EmbeddingModel behavior tests in `effect` for embedding usage, batching, ordering, and error handling.
- Add `OpenAiEmbeddingModel` in `@effect/ai-openai`, including model / make / layer constructors, config overrides, and provider output index validation with deterministic reordering.
- Add OpenAI-compatible EmbeddingModel provider support in `@effect/ai-openai-compat`, including config overrides, layer constructors, and output index validation.
- [#1771](https://github.com/Effect-TS/effect-smol/pull/1771) [`00add69`](https://github.com/Effect-TS/effect-smol/commit/00add69b59551e9df34772eb927638b093f6d71e) Thanks @tim-smart! - Add `EmbeddingModel.ModelDimensions` and require dimensions in embedding provider `model` constructors.
- Updated dependencies [[`f2f75ee`](https://github.com/Effect-TS/effect-smol/commit/f2f75ee564bce1cd95f5189c7bdeeed4f92dacb1), [`342fc4b`](https://github.com/Effect-TS/effect-smol/commit/342fc4b051739e32e7977159f26ff9541eda664f), [`5d704ee`](https://github.com/Effect-TS/effect-smol/commit/5d704ee10d20e8eb107e34bb8a21feb5aa4a7685), [`00add69`](https://github.com/Effect-TS/effect-smol/commit/00add69b59551e9df34772eb927638b093f6d71e), [`58217d3`](https://github.com/Effect-TS/effect-smol/commit/58217d318a7d716ccd707cce0f41573946939c28), [`f4e2aba`](https://github.com/Effect-TS/effect-smol/commit/f4e2aba01b76d1e3059b297e3cc942284dfeafb2), [`e3b44b6`](https://github.com/Effect-TS/effect-smol/commit/e3b44b6a2af9ee21dc5c1e928f0c20af857fa7a9), [`e1472b7`](https://github.com/Effect-TS/effect-smol/commit/e1472b7525c5d57a48bdec2353c3b742f7f916c0), [`7686320`](https://github.com/Effect-TS/effect-smol/commit/7686320cd123fa352b5c3d076fb18a3cac0a9bba)]:
- effect@4.0.0-beta.34
## 4.0.0-beta.33
### Patch Changes
- Updated dependencies [[`571447d`](https://github.com/Effect-TS/effect-smol/commit/571447da67334449f8ae3d6ecb3d77ea4e0c4295)]:
- effect@4.0.0-beta.33
## 4.0.0-beta.32
### Patch Changes
- Updated dependencies [[`bf8fff8`](https://github.com/Effect-TS/effect-smol/commit/bf8fff8a5f54b6df74cb7bbb42346fe9ba52435a), [`1af3ef3`](https://github.com/Effect-TS/effect-smol/commit/1af3ef3e3ca7fd417d0fc15f8ca8fe207eba4f74), [`27fea0f`](https://github.com/Effect-TS/effect-smol/commit/27fea0f66910de5905f40fd63f8ddbb6f7ac5aba), [`2ad6c1b`](https://github.com/Effect-TS/effect-smol/commit/2ad6c1b2c85a3a0fe351e3d56636a75eb76b4b4e), [`398ac3e`](https://github.com/Effect-TS/effect-smol/commit/398ac3e01cb75efce0e4e2913d1450cf65866732), [`51fe22f`](https://github.com/Effect-TS/effect-smol/commit/51fe22f3266e417b6c541aaed4b75d246fac91e7), [`4605db6`](https://github.com/Effect-TS/effect-smol/commit/4605db69cfacddbdbf1525865ddfde135158090c), [`f4de1b0`](https://github.com/Effect-TS/effect-smol/commit/f4de1b087c998d0bad1d9468f70b7d16c13b9f6f), [`60214f2`](https://github.com/Effect-TS/effect-smol/commit/60214f2080b2aeb091f691140eb20acb741691c3), [`c4b8b0f`](https://github.com/Effect-TS/effect-smol/commit/c4b8b0ffa8efb47c4cd7578a8943d6868509373f), [`6d9393a`](https://github.com/Effect-TS/effect-smol/commit/6d9393a0770a18722d23340e77f15455de341245), [`6de4efe`](https://github.com/Effect-TS/effect-smol/commit/6de4efe463c783614ceb0c094d77a336a899cbe0), [`4f969d1`](https://github.com/Effect-TS/effect-smol/commit/4f969d1563ba755ffa116c8ae409bb3436bd881d), [`6cc67c8`](https://github.com/Effect-TS/effect-smol/commit/6cc67c855e054ee3f3ac3485dca5f7805e79e8fb), [`8531a22`](https://github.com/Effect-TS/effect-smol/commit/8531a22ffbb52e11a030b09f358cafbfdf5edff7), [`b226760`](https://github.com/Effect-TS/effect-smol/commit/b22676067617f15c00722a3a63fd7c2c172c3d45), [`47a51ab`](https://github.com/Effect-TS/effect-smol/commit/47a51aba0ecdf3ef478bfa28a498bca188399bd4), [`1521d02`](https://github.com/Effect-TS/effect-smol/commit/1521d02e1f19f1d795edaaf862c1a1031d9c755e)]:
- effect@4.0.0-beta.32
## 4.0.0-beta.31
### Patch Changes
- Updated dependencies [[`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6f23f0e`](https://github.com/Effect-TS/effect-smol/commit/6f23f0ed4cba573cd9395c2e582f582fe7271544), [`654aaec`](https://github.com/Effect-TS/effect-smol/commit/654aaec593305521b65dd042c204d761cc6e8c28), [`2958a42`](https://github.com/Effect-TS/effect-smol/commit/2958a42078966a8713a98f00485ab36484d5eccf), [`95d27a2`](https://github.com/Effect-TS/effect-smol/commit/95d27a239ed5147302605ab0b3147a056541b0c7), [`0fbaea8`](https://github.com/Effect-TS/effect-smol/commit/0fbaea8f9555a8044cec31a770394db613fc78e2), [`21d5d5e`](https://github.com/Effect-TS/effect-smol/commit/21d5d5e0439fd4d9bb6e508377215b1087555d45), [`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6e49959`](https://github.com/Effect-TS/effect-smol/commit/6e499590357a104c81779b3176cd3f84e4f91064), [`8f5805d`](https://github.com/Effect-TS/effect-smol/commit/8f5805dbdd0d1bc0ff0727cc398c8d80e544edee), [`990df2c`](https://github.com/Effect-TS/effect-smol/commit/990df2c3ceeb32e659acc10cc9485617f7b3c423)]:
- effect@4.0.0-beta.31
## 4.0.0-beta.30
### Patch Changes
- [#1692](https://github.com/Effect-TS/effect-smol/pull/1692) [`00caf4f`](https://github.com/Effect-TS/effect-smol/commit/00caf4fbe209ff56426e9bcd51a205bdb84b978e) Thanks @tim-smart! - Preserve streamed OpenAI compat tool call ids and names across fragmented chat completion chunks.
- Updated dependencies [[`c88e5b7`](https://github.com/Effect-TS/effect-smol/commit/c88e5b723ff09da4edaef6ce14d927ca01104a32), [`947d0e4`](https://github.com/Effect-TS/effect-smol/commit/947d0e4268ba5c4020ead380aa80812c7342408f), [`7517908`](https://github.com/Effect-TS/effect-smol/commit/75179085d159b88a1ab0bce70669d76dcf0d79a4), [`a49ecd5`](https://github.com/Effect-TS/effect-smol/commit/a49ecd5a183d7e7d33f47ff95e9d2dea5a12ead5), [`6993e33`](https://github.com/Effect-TS/effect-smol/commit/6993e3329122c834c20bacea72d8678232f4f103), [`514f2a2`](https://github.com/Effect-TS/effect-smol/commit/514f2a2ae54580fcacdbe2ea2196a83a852d0748), [`3214b47`](https://github.com/Effect-TS/effect-smol/commit/3214b47676de2d33fddc5fecfc2d226e6e83cc7b), [`95ec5ed`](https://github.com/Effect-TS/effect-smol/commit/95ec5ed345de77c893049e182d37a37cf164a268)]:
- effect@4.0.0-beta.30
## 4.0.0-beta.29
### Patch Changes
- Updated dependencies [[`9d93adb`](https://github.com/Effect-TS/effect-smol/commit/9d93adb1c1795d1978391b30d7d2972c88052662), [`b52721c`](https://github.com/Effect-TS/effect-smol/commit/b52721cf0d11a567722b060c8536e3bdd4161f07), [`a891c7b`](https://github.com/Effect-TS/effect-smol/commit/a891c7b12f415b2287613dd4b91a09dfd38ef30d), [`ef26cdf`](https://github.com/Effect-TS/effect-smol/commit/ef26cdfb65d9955fc7e161629191930c2cc2c63f), [`82fd3ed`](https://github.com/Effect-TS/effect-smol/commit/82fd3ed922063ee5a34f96f3993c15c7515e4f67)]:
- effect@4.0.0-beta.29
## 4.0.0-beta.28
### Patch Changes
- [#1634](https://github.com/Effect-TS/effect-smol/pull/1634) [`621d3a1`](https://github.com/Effect-TS/effect-smol/commit/621d3a1248ef50e83c35d71333c69bf01bc33a11) Thanks @tim-smart! - Allow custom request properties in openai-compat model config and chat request types, and forward model-level custom properties to chat-completions payloads.
- Updated dependencies [[`ff533f2`](https://github.com/Effect-TS/effect-smol/commit/ff533f203cd06302ad08032a27e01269b4a2d4c6), [`dc803ee`](https://github.com/Effect-TS/effect-smol/commit/dc803ee52ebd3e9f931118f0dfcb804542847556), [`d660b1c`](https://github.com/Effect-TS/effect-smol/commit/d660b1c99cb93d4f79715e91c7a4486801c0eefa), [`93a05e3`](https://github.com/Effect-TS/effect-smol/commit/93a05e3eaa624058b162aedd66aad70102837270), [`2a65cf6`](https://github.com/Effect-TS/effect-smol/commit/2a65cf6fd81ef63d944e6fb51f058d439bf4a834), [`a561a40`](https://github.com/Effect-TS/effect-smol/commit/a561a40cc41c548c2cf3153aca065ee92ee8aa57), [`29cd24d`](https://github.com/Effect-TS/effect-smol/commit/29cd24d1fe78480a72eeb38a90281ffddc0530bc), [`662a8e6`](https://github.com/Effect-TS/effect-smol/commit/662a8e6857dac64a7cd13bd8df4b0674654622f8), [`d2b52ba`](https://github.com/Effect-TS/effect-smol/commit/d2b52bae5b9336cf59729fbdcc4d7f09512b0cbf), [`407c3b4`](https://github.com/Effect-TS/effect-smol/commit/407c3b43a5d1414558e0e33b6f1fc0e6a6d489cc), [`42bc7ce`](https://github.com/Effect-TS/effect-smol/commit/42bc7ce5480f6f2953c39f8cb5c850d61df6f5a2), [`e741322`](https://github.com/Effect-TS/effect-smol/commit/e74132226cbfee24234311c7c1c13e6b7391384e), [`5c75fa8`](https://github.com/Effect-TS/effect-smol/commit/5c75fa8fb71163bc4c035ba1a215574dfd4badfc), [`747177b`](https://github.com/Effect-TS/effect-smol/commit/747177b0602f12d4461a843e953dfdffbeb0a429), [`326cd48`](https://github.com/Effect-TS/effect-smol/commit/326cd4828bce573fe985f35152155464bf4c5a70), [`627e922`](https://github.com/Effect-TS/effect-smol/commit/627e922b8d1e9521eae5e1caa5d667ad00b1619a), [`662287e`](https://github.com/Effect-TS/effect-smol/commit/662287e9abc76c941ccc2ee330aa07904d571341)]:
- effect@4.0.0-beta.28
## 4.0.0-beta.27
### Patch Changes
- [#1623](https://github.com/Effect-TS/effect-smol/pull/1623) [`2cf00c1`](https://github.com/Effect-TS/effect-smol/commit/2cf00c184ccc994b7977f33996321923fa3534c4) Thanks @tim-smart! - Forward `OpenAiLanguageModel` `reasoning` config into chat-completions requests.
- Updated dependencies [[`903a839`](https://github.com/Effect-TS/effect-smol/commit/903a839e94239e6ec4568315af28e405bcad95f4), [`91a0168`](https://github.com/Effect-TS/effect-smol/commit/91a016836680a6669308ecf464d3584bcc4ae1b7), [`c890f9a`](https://github.com/Effect-TS/effect-smol/commit/c890f9a1b3a989ed22528bd5a43326342e05b142), [`1e985f2`](https://github.com/Effect-TS/effect-smol/commit/1e985f237d250b51b91de22dde77160c1e778ce7)]:
- effect@4.0.0-beta.27
## 4.0.0-beta.26
### Patch Changes
- Updated dependencies [[`fb21462`](https://github.com/Effect-TS/effect-smol/commit/fb21462642cdd5b1bada92f3eba18ae20445be42), [`2ed26b1`](https://github.com/Effect-TS/effect-smol/commit/2ed26b139805700e3df39efaa768ff01565e5c86), [`e832a57`](https://github.com/Effect-TS/effect-smol/commit/e832a57b570fe38f010c1fd99bceac5a325a9e07), [`7f01be7`](https://github.com/Effect-TS/effect-smol/commit/7f01be7f8db363d4b2e88e6b5571e96bb815786f), [`e965143`](https://github.com/Effect-TS/effect-smol/commit/e9651431e114479e6becf8ca7b1ed99ac7e91ccc), [`b9b80f1`](https://github.com/Effect-TS/effect-smol/commit/b9b80f1f15e152ceef0a727d150b7dc230abae99), [`98252aa`](https://github.com/Effect-TS/effect-smol/commit/98252aa0c0b17fc73fbdad65d0a1104965f9fc0f), [`56fbd94`](https://github.com/Effect-TS/effect-smol/commit/56fbd94311ad19a05001ad649d9e34ab00c74541), [`3faa109`](https://github.com/Effect-TS/effect-smol/commit/3faa109b7d093fbf14ad410d3e11d663f16e28f1), [`692ecfe`](https://github.com/Effect-TS/effect-smol/commit/692ecfed99fe58056b7a5afe001f4fcd1a61c446), [`1e70b72`](https://github.com/Effect-TS/effect-smol/commit/1e70b72d0b210474d0e96a15a5cfc279eae37e0c), [`ecf0782`](https://github.com/Effect-TS/effect-smol/commit/ecf07829ef2dfc01d8943c96c4fe9c1b44b97926)]:
- effect@4.0.0-beta.26
## 4.0.0-beta.25
### Patch Changes
- Updated dependencies [[`fa17bb5`](https://github.com/Effect-TS/effect-smol/commit/fa17bb5be9f2533d01e11322b14804c7dec43714), [`f46e5b5`](https://github.com/Effect-TS/effect-smol/commit/f46e5b5ca2a918ee4d9270167e79db223077c96f), [`ce4767c`](https://github.com/Effect-TS/effect-smol/commit/ce4767cadcacc6ce8ff4c3a0d0fbc82ede655f63), [`c830a8b`](https://github.com/Effect-TS/effect-smol/commit/c830a8b6c292a6528d7f9318759d34800b00372d)]:
- effect@4.0.0-beta.25
## 4.0.0-beta.24
### Patch Changes
- Updated dependencies [[`a909e1c`](https://github.com/Effect-TS/effect-smol/commit/a909e1c1ac2bc707527f5073776e3e7d239688d9), [`8814a4e`](https://github.com/Effect-TS/effect-smol/commit/8814a4ef78d67144d27689370af10099ea210399), [`3f942c5`](https://github.com/Effect-TS/effect-smol/commit/3f942c51cefa7b2ffa7c49e8c8a2c887570ba4c0), [`774ed59`](https://github.com/Effect-TS/effect-smol/commit/774ed59c52b2ab578bbb897c4f551f812231e1d2), [`f54b8d3`](https://github.com/Effect-TS/effect-smol/commit/f54b8d398fedad1815fd1f4c49814ab938cfc385)]:
- effect@4.0.0-beta.24
## 4.0.0-beta.23
### Patch Changes
- Updated dependencies [[`5c73c41`](https://github.com/Effect-TS/effect-smol/commit/5c73c41b69eaeab80fcd62c9bfda490b446d1966)]:
- effect@4.0.0-beta.23
## 4.0.0-beta.22
### Patch Changes
- Updated dependencies [[`0874332`](https://github.com/Effect-TS/effect-smol/commit/0874332f7c81118b06ac2eb105e0710211631479), [`c592dcd`](https://github.com/Effect-TS/effect-smol/commit/c592dcde0697e322065c8f418c0480ef910cb183), [`1dbe28d`](https://github.com/Effect-TS/effect-smol/commit/1dbe28dac8299cd3e218c9768450cfd173b5e294), [`564d730`](https://github.com/Effect-TS/effect-smol/commit/564d730b6bbf38dd8548a3b046e7a693b28699a4), [`3cfadc4`](https://github.com/Effect-TS/effect-smol/commit/3cfadc458b070c6cba6c5674b72a059f1e49118b), [`6634fd0`](https://github.com/Effect-TS/effect-smol/commit/6634fd07da067d80b8261fb2959d1a952b9e412e), [`d10dabe`](https://github.com/Effect-TS/effect-smol/commit/d10dabeb7af9a368f995829cd36ad08167cd8f95), [`f82f549`](https://github.com/Effect-TS/effect-smol/commit/f82f549a09e950e9d4987f279a800f4d953f0939), [`78a3382`](https://github.com/Effect-TS/effect-smol/commit/78a3382ddfbe034408f7480fa794733d9e82147b)]:
- effect@4.0.0-beta.22
## 4.0.0-beta.21
### Patch Changes
- Updated dependencies [[`e691909`](https://github.com/Effect-TS/effect-smol/commit/e691909495ccb162ea7bfa351dd74632b99997cb), [`d5f413f`](https://github.com/Effect-TS/effect-smol/commit/d5f413f3c8fc57f2413cc5649c2003d6d4e5a6d7), [`139d152`](https://github.com/Effect-TS/effect-smol/commit/139d152941e562a073b5be12e8d66c8a4d4a8a57), [`947e3d4`](https://github.com/Effect-TS/effect-smol/commit/947e3d436ab8a017efda9b29be523efd1ca8df28), [`84b2cce`](https://github.com/Effect-TS/effect-smol/commit/84b2ccefe2aa3a7413b86738a4dc33cdb311ca55), [`7f5305e`](https://github.com/Effect-TS/effect-smol/commit/7f5305e69f5a33309e77b08a576edb25d7daaee2), [`9e6fd84`](https://github.com/Effect-TS/effect-smol/commit/9e6fd8471c93a3c643929151a3bdb62cb9c0ca0e), [`fdb8a4b`](https://github.com/Effect-TS/effect-smol/commit/fdb8a4b172721fbefe98bd5aa6fe4f0efd1da3eb), [`0f986ef`](https://github.com/Effect-TS/effect-smol/commit/0f986ef22f196fe091a7afdbd179485a7d888882), [`9355fc0`](https://github.com/Effect-TS/effect-smol/commit/9355fc0ffb5b7382146a5aed9eea83974b10d007)]:
- effect@4.0.0-beta.21
## 4.0.0-beta.20
### Patch Changes
- [#1529](https://github.com/Effect-TS/effect-smol/pull/1529) [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8) Thanks @tim-smart! - Add dedicated AiError metadata interfaces per reason so provider packages can safely augment metadata without conflicting module declarations.
- [#1528](https://github.com/Effect-TS/effect-smol/pull/1528) [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34) Thanks @tim-smart! - Add `Model.ModelName` and provide it from AI model constructors.
- Updated dependencies [[`842a624`](https://github.com/Effect-TS/effect-smol/commit/842a624f79d5e1407460b0ef3ab27d14d48ccf74), [`4785eef`](https://github.com/Effect-TS/effect-smol/commit/4785eef5d7cf1edb96ef2509aed2ba4d1edf3862), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`12ee8e2`](https://github.com/Effect-TS/effect-smol/commit/12ee8e27df7eb393d83a5e403390d0cfc82ca732), [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34), [`989d1cc`](https://github.com/Effect-TS/effect-smol/commit/989d1cca936fce0cc459057825ba40e3f5ef3827)]:
- effect@4.0.0-beta.20
## 4.0.0-beta.19
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.19
## 4.0.0-beta.18
### Patch Changes
- Updated dependencies [[`01e31fd`](https://github.com/Effect-TS/effect-smol/commit/01e31fdf8e5206849d23cbafd23a346f2f177ab8), [`0890aab`](https://github.com/Effect-TS/effect-smol/commit/0890aab15ed9c5ba52c383a72fdc6a444d7504d5), [`725260b`](https://github.com/Effect-TS/effect-smol/commit/725260b53f5142d6af7a93a2f9f464f974eda92d)]:
- effect@4.0.0-beta.18
## 4.0.0-beta.17
### Patch Changes
- Updated dependencies [[`8f59c32`](https://github.com/Effect-TS/effect-smol/commit/8f59c32922597a48392744f7203e284866747781)]:
- effect@4.0.0-beta.17
## 4.0.0-beta.16
### Patch Changes
- Updated dependencies [[`bf9096c`](https://github.com/Effect-TS/effect-smol/commit/bf9096c52a7d8791d93d232739e523eb84f6625a), [`29f81ca`](https://github.com/Effect-TS/effect-smol/commit/29f81ca07c67dba265804b140a7487fb15a5fc6b), [`68eb28c`](https://github.com/Effect-TS/effect-smol/commit/68eb28c2b0fc67a9f6204ade9bd16c5b37803bfb)]:
- effect@4.0.0-beta.16
## 4.0.0-beta.15
### Patch Changes
- [#1502](https://github.com/Effect-TS/effect-smol/pull/1502) [`285b7e6`](https://github.com/Effect-TS/effect-smol/commit/285b7e667167566d5788367d5155b19c79f1bf22) Thanks @tim-smart! - allow undefined for ai config
- Updated dependencies [[`24ae609`](https://github.com/Effect-TS/effect-smol/commit/24ae60995d2fd7d621be356cdfdfd328c79639ba), [`0e3c059`](https://github.com/Effect-TS/effect-smol/commit/0e3c059987caa55ebd0c134f7c7b147c639c328e), [`e843b0a`](https://github.com/Effect-TS/effect-smol/commit/e843b0a7d7e7b600a0b3bd477f24e2e4cd26bc8b), [`f4389a2`](https://github.com/Effect-TS/effect-smol/commit/f4389a2cca3c5bbf00d69779f52ce41255f15a28), [`5b73de0`](https://github.com/Effect-TS/effect-smol/commit/5b73de095b3402d0c5c74092ace6ce18ebfad566), [`595d2d6`](https://github.com/Effect-TS/effect-smol/commit/595d2d6e7d50419f3532bd39266191532ace38f2)]:
- effect@4.0.0-beta.15
## 4.0.0-beta.14
### Patch Changes
- Updated dependencies [[`c414700`](https://github.com/Effect-TS/effect-smol/commit/c414700ef1932e4b67d0102856de417336912350), [`a30c969`](https://github.com/Effect-TS/effect-smol/commit/a30c9699c0d736cf3952041e45d508b7d58907a9)]:
- effect@4.0.0-beta.14
## 4.0.0-beta.13
### Patch Changes
- Updated dependencies [[`368f4c3`](https://github.com/Effect-TS/effect-smol/commit/368f4c363dd117e6f5a19ad77b161176cfd29fdd), [`db8a579`](https://github.com/Effect-TS/effect-smol/commit/db8a579e93e93ff73b1e60712732e03b597b916b), [`668b703`](https://github.com/Effect-TS/effect-smol/commit/668b70337e9ddbb0d1ae2282a95c282ce404e562), [`d40e76b`](https://github.com/Effect-TS/effect-smol/commit/d40e76b973543979e60e04a6baca04a8c65bdfc2), [`6e18cf8`](https://github.com/Effect-TS/effect-smol/commit/6e18cf883e9905ca718a6697b6a2a4bbd42739aa), [`86062e8`](https://github.com/Effect-TS/effect-smol/commit/86062e8a0c61bca5412fc40d2cf151d676901f08), [`c27ce75`](https://github.com/Effect-TS/effect-smol/commit/c27ce75d34c74dcfc6dba1bf77f1ce88f410a0de), [`e2d4fbf`](https://github.com/Effect-TS/effect-smol/commit/e2d4fbfeeda6a5d2a4c5aeb0501d8240c248b9eb), [`114ab42`](https://github.com/Effect-TS/effect-smol/commit/114ab42ad0edc590d29169675a493e0e915aa58f), [`484caec`](https://github.com/Effect-TS/effect-smol/commit/484caec47cccac8b86db2910742e406dfc7173ab)]:
- effect@4.0.0-beta.13
## 4.0.0-beta.12
### Patch Changes
- Updated dependencies [[`70a74e8`](https://github.com/Effect-TS/effect-smol/commit/70a74e88a8767c9d4acdb9e5f25aec9a33588d07), [`b5b6e10`](https://github.com/Effect-TS/effect-smol/commit/b5b6e10621d54bf8c9857fec0d647ced78ecd857), [`f5ce5a9`](https://github.com/Effect-TS/effect-smol/commit/f5ce5a915359c6ebf254079e1da23cab6cde34fb), [`a29eb70`](https://github.com/Effect-TS/effect-smol/commit/a29eb702ffe3fc58bd28c4d7857298cd65d73668), [`c7b36e5`](https://github.com/Effect-TS/effect-smol/commit/c7b36e541a23e9a00f64e25b23851e51a37dfce5), [`9381d6d`](https://github.com/Effect-TS/effect-smol/commit/9381d6d4d9d819a81a46e56d0364c76e92a4fbca), [`88439f1`](https://github.com/Effect-TS/effect-smol/commit/88439f13ca13549f3e4822c48c4f019c14fc2bcc), [`e35307d`](https://github.com/Effect-TS/effect-smol/commit/e35307dbeb8eb26a9923f958b894a8eaaf259bf2), [`c7df4bc`](https://github.com/Effect-TS/effect-smol/commit/c7df4bce34009474c63d62a807abfdafb76971eb), [`accaf3b`](https://github.com/Effect-TS/effect-smol/commit/accaf3be7ac8da36e2334c509c23b8c9e88ea160), [`3e1c270`](https://github.com/Effect-TS/effect-smol/commit/3e1c2707bbdf67720af1509642b8ced195790882), [`6cd81f7`](https://github.com/Effect-TS/effect-smol/commit/6cd81f73baad86f5bbfa455a55d75cde71e9611a), [`f222da3`](https://github.com/Effect-TS/effect-smol/commit/f222da3cdb44554f3324c2c52d0d005ee575053e), [`61f901d`](https://github.com/Effect-TS/effect-smol/commit/61f901d830005b66e22d1de889fda132aeea97cd)]:
- effect@4.0.0-beta.12
## 4.0.0-beta.11
### Patch Changes
- Updated dependencies [[`88659ed`](https://github.com/Effect-TS/effect-smol/commit/88659edb26e3623d557dccfe914c2c949672da16), [`f2915e8`](https://github.com/Effect-TS/effect-smol/commit/f2915e8e2efe80d50c281e53f297b9701d6dc199), [`eb71ace`](https://github.com/Effect-TS/effect-smol/commit/eb71acebbe0f228e4920278013beee3b67d62310), [`2a16999`](https://github.com/Effect-TS/effect-smol/commit/2a169996c7513d377ac47adbfd68e1490457135c), [`d42dd52`](https://github.com/Effect-TS/effect-smol/commit/d42dd52f11203f8e749fb5d3ecf7153e4a5a6814), [`339adaf`](https://github.com/Effect-TS/effect-smol/commit/339adaf850a62a892adebcb208c2d9dddf3b97b3), [`de19645`](https://github.com/Effect-TS/effect-smol/commit/de1964526d01102dd1cb99c8cfdd3e8df1f49ef1), [`9b1dc3b`](https://github.com/Effect-TS/effect-smol/commit/9b1dc3bcf2a1b68d0a67e3465db5ad01a1a56997), [`e4cb2f5`](https://github.com/Effect-TS/effect-smol/commit/e4cb2f55b30f4771ec1bf613ced36d6d96464dd5), [`8bced95`](https://github.com/Effect-TS/effect-smol/commit/8bced954ecb35d4489197a57b0efe927e7d75f49), [`9431420`](https://github.com/Effect-TS/effect-smol/commit/94314207c8019918200fbcb97aec992219f801f0), [`948dca2`](https://github.com/Effect-TS/effect-smol/commit/948dca22e4f672ba7a6db57f9899272bec7c08b8), [`d18e327`](https://github.com/Effect-TS/effect-smol/commit/d18e32765a2665e31ffb31e746bf983fcfac34c5), [`ab512f7`](https://github.com/Effect-TS/effect-smol/commit/ab512f7be1c0e6b359da921e22cd4944e4c57d3e)]:
- effect@4.0.0-beta.11
## 4.0.0-beta.10
### Patch Changes
- Updated dependencies [[`371acab`](https://github.com/Effect-TS/effect-smol/commit/371acabb58d56f3a7a5e3e33d3d5fdc9f5573c74), [`856d774`](https://github.com/Effect-TS/effect-smol/commit/856d7741f1e296dd5048c6ff2b44b95d023e6ae4), [`b9e9202`](https://github.com/Effect-TS/effect-smol/commit/b9e92023c38caa322975d77cfe83e2d34ac9305a), [`1d1a974`](https://github.com/Effect-TS/effect-smol/commit/1d1a974bd280c81bff5d4505491cda03ba7a3f36), [`6bfe2a6`](https://github.com/Effect-TS/effect-smol/commit/6bfe2a659bc6335db75709931f405da45301cba2), [`b12c811`](https://github.com/Effect-TS/effect-smol/commit/b12c81157be287b1649c210616a244b50ec094d2), [`d17d98a`](https://github.com/Effect-TS/effect-smol/commit/d17d98ad78e2b44d95ef434adab79ac3c35e75ab), [`68c3c7c`](https://github.com/Effect-TS/effect-smol/commit/68c3c7cb1e06ed94fa5c4c123a234b4ccbfdecd8)]:
- effect@4.0.0-beta.10
## 4.0.0-beta.9
### Patch Changes
- Updated dependencies [[`3386557`](https://github.com/Effect-TS/effect-smol/commit/338655731564a7be9f8859dedbf4d5bcac6eb350), [`b6666e3`](https://github.com/Effect-TS/effect-smol/commit/b6666e3cf6bd44ba1a8704e65c256c30359cb422)]:
- effect@4.0.0-beta.9
## 4.0.0-beta.8
### Patch Changes
- Updated dependencies [[`246e672`](https://github.com/Effect-TS/effect-smol/commit/246e672dbbd7848d60e0c78fd66671b2f10b3752), [`807dec0`](https://github.com/Effect-TS/effect-smol/commit/807dec03801b4c58a6d00c237b6d98d6386911df)]:
- effect@4.0.0-beta.8
## 4.0.0-beta.7
### Patch Changes
- Updated dependencies [[`a2bda6d`](https://github.com/Effect-TS/effect-smol/commit/a2bda6d4ef6de9d9b0c53ae2df5434f778d6161a), [`1f95a2b`](https://github.com/Effect-TS/effect-smol/commit/1f95a2b5aa9524bb38f4437f4691a664bf463ca1), [`a8d5e79`](https://github.com/Effect-TS/effect-smol/commit/a8d5e792fec201a83af0eb92fc79928d055125fd), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`06d8a03`](https://github.com/Effect-TS/effect-smol/commit/06d8a0391631e6130e3ab25227e59817852e227f), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`f9e883e`](https://github.com/Effect-TS/effect-smol/commit/f9e883e266fbda870336ee62f46b7ac85ba3de6e), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430)]:
- effect@4.0.0-beta.7
## 4.0.0-beta.6
### Patch Changes
- Updated dependencies [[`3247da2`](https://github.com/Effect-TS/effect-smol/commit/3247da28331f345f68be5dbd2974a7e03d300fe1), [`f205705`](https://github.com/Effect-TS/effect-smol/commit/f2057050dbd034b8c186be2d40c3d03ee63a5a3b), [`f35022c`](https://github.com/Effect-TS/effect-smol/commit/f35022c212e4111527e1bb43f360a67b2b49fa85), [`8622721`](https://github.com/Effect-TS/effect-smol/commit/86227217b02d43680a3c6f3c21731b1d852c91f5), [`fc660ab`](https://github.com/Effect-TS/effect-smol/commit/fc660ab8b5ebae38b8d6b96cbf2f9b880cc09253), [`f37dc33`](https://github.com/Effect-TS/effect-smol/commit/f37dc335f64622fa9ce8d6d1d5dd8fc3f260257b), [`3662f32`](https://github.com/Effect-TS/effect-smol/commit/3662f328fcfa3b2fa01ffa79da40e12e93fcede8), [`a7d436f`](https://github.com/Effect-TS/effect-smol/commit/a7d436f438dcd7f49b9485e4e95a4511f31fad7d), [`6856a41`](https://github.com/Effect-TS/effect-smol/commit/6856a415d7eddd9d73d60919e976f1d071421be4), [`8c417d0`](https://github.com/Effect-TS/effect-smol/commit/8c417d03475e5e12d00dca0c4781d0af7e66b86c), [`5419570`](https://github.com/Effect-TS/effect-smol/commit/5419570ba47ce882a3a10882707b46f66e464906), [`449c5ed`](https://github.com/Effect-TS/effect-smol/commit/449c5ed5318e8a874e730420bcf52918fa2ec80f), [`4b5ec12`](https://github.com/Effect-TS/effect-smol/commit/4b5ec12f87f95f2a3cd8fe4d5b26c6eb0529381a), [`df87937`](https://github.com/Effect-TS/effect-smol/commit/df879375fc3b169c43f9c434b3775e12b80dffe4), [`5dbfca8`](https://github.com/Effect-TS/effect-smol/commit/5dbfca8d1dbb6d18d1605d4f8562e99c86e2ff11), [`e629497`](https://github.com/Effect-TS/effect-smol/commit/e6294973d55597ab6b6deca6babbe1e946b2c91d), [`981c991`](https://github.com/Effect-TS/effect-smol/commit/981c991cd78db34def815d5754379d737157f005), [`1ca2ed6`](https://github.com/Effect-TS/effect-smol/commit/1ca2ed67301a5dc40ae0ed94346b99f26fd22bbe), [`45722bd`](https://github.com/Effect-TS/effect-smol/commit/45722bde974458311f11ad237711363a10ec6894), [`eb2a85e`](https://github.com/Effect-TS/effect-smol/commit/eb2a85ed4dc162b2535d304799333a5a20477fd0)]:
- effect@4.0.0-beta.6
## 4.0.0-beta.5
### Patch Changes
- Updated dependencies [[`f6e133e`](https://github.com/Effect-TS/effect-smol/commit/f6e133e9a16b32317bd09ff08c12b97a0ae44600), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8), [`a88e206`](https://github.com/Effect-TS/effect-smol/commit/a88e206e44dc66ca5a2b45bedc797877c5dbb083), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8)]:
- effect@4.0.0-beta.5
## 4.0.0-beta.4
### Patch Changes
- Updated dependencies [[`c5a18ef`](https://github.com/Effect-TS/effect-smol/commit/c5a18ef44171e3880bf983faee74529908974b32), [`bc6b885`](https://github.com/Effect-TS/effect-smol/commit/bc6b885b94d887a200657c0775dfa874dc15bc0c)]:
- effect@4.0.0-beta.4
## 4.0.0-beta.3
### Patch Changes
- Updated dependencies [[`3a0cf36`](https://github.com/Effect-TS/effect-smol/commit/3a0cf36eff106ba48d74e133c1598cd40613e530), [`c4da328`](https://github.com/Effect-TS/effect-smol/commit/c4da328d32fad1d61e0e538f5d371edf61521d7e)]:
- effect@4.0.0-beta.3
## 4.0.0-beta.2
### Patch Changes
- Updated dependencies [[`a22ce73`](https://github.com/Effect-TS/effect-smol/commit/a22ce73b2bd9305b7ba665694d2255c0e6d5a8d0), [`ebdabf7`](https://github.com/Effect-TS/effect-smol/commit/ebdabf79ff4e62c8384aa8cf9a8d2787d536ee78), [`8f663bb`](https://github.com/Effect-TS/effect-smol/commit/8f663bb121021bf12bd264e8ae385187cb7a5dae)]:
- effect@4.0.0-beta.2
## 4.0.0-beta.1
### Patch Changes
- Updated dependencies [[`0fecf70`](https://github.com/Effect-TS/effect-smol/commit/0fecf70048057623eed7c584a06671773a2b1743), [`709569e`](https://github.com/Effect-TS/effect-smol/commit/709569ed76bead9ebb0670599e4d890a07ca5a43)]:
- effect@4.0.0-beta.1
## 4.0.0-beta.0
### Major Changes
- [#1183](https://github.com/Effect-TS/effect-smol/pull/1183) [`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66) Thanks @tim-smart! - v4 beta
### Patch Changes
- Updated dependencies [[`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66)]:
- effect@4.0.0-beta.0

View File

@@ -0,0 +1,23 @@
{
"$schema": "../../node_modules/@effect/docgen/schema.json",
"srcLink": "https://github.com/Effect-TS/effect/tree/main/packages/ai/openai-compat/src/",
"exclude": ["src/internal/**"],
"examplesCompilerOptions": {
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"rewriteRelativeImportExtensions": true,
"allowImportingTsExtensions": true,
"paths": {
"effect": ["../../../effect/src/index.js"],
"effect/*": ["../../../effect/src/*.js"]
},
"plugins": [
{ "name": "@effect/language-service", "includeSuggestionsInTsc": false }
]
}
}

View File

@@ -0,0 +1,68 @@
{
"name": "@effect/ai-openai-compat",
"version": "4.0.0-beta.99",
"type": "module",
"license": "MIT",
"description": "An OpenAI compat integration for Effect",
"homepage": "https://effect.website",
"repository": {
"type": "git",
"url": "https://github.com/Effect-TS/effect.git",
"directory": "packages/ai/openai-compat"
},
"bugs": {
"url": "https://github.com/Effect-TS/effect/issues"
},
"tags": [
"typescript",
"ai",
"openai",
"compat"
],
"keywords": [
"typescript",
"ai",
"openai",
"compat"
],
"sideEffects": [],
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts",
"./*": "./src/*.ts",
"./internal/*": null,
"./*/index": null
},
"files": [
"src/**/*.ts",
"dist/**/*.js",
"dist/**/*.js.map",
"dist/**/*.d.ts",
"dist/**/*.d.ts.map"
],
"publishConfig": {
"access": "public",
"provenance": true,
"exports": {
"./package.json": "./package.json",
".": "./dist/index.js",
"./*": "./dist/*.js",
"./internal/*": null,
"./*/index": null
}
},
"scripts": {
"codegen": "effect-utils codegen",
"build": "tsc -b tsconfig.json && pnpm babel",
"babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
"check": "tsc -b tsconfig.json",
"test": "vitest",
"coverage": "vitest --coverage"
},
"devDependencies": {
"effect": "workspace:^"
},
"peerDependencies": {
"effect": "workspace:^"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
/**
* The `OpenAiConfig` module lets a workflow temporarily customize the HTTP
* client used by OpenAI-compatible request helpers. Model, embedding, and
* tool-calling code can use this scoped configuration to add middleware,
* instrumentation, or routing without rebuilding the client layer.
*
* @since 4.0.0
*/
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import type { HttpClient } from "effect/unstable/http/HttpClient"
/**
* Context service for OpenAI-compatible client configuration in the current
* Effect scope.
*
* **When to use**
*
* Use as the context service for scoped OpenAI-compatible client configuration
* and HTTP client transforms.
*
* @see {@link withClientTransform} for scoping an HTTP client transformation
*
* @category services
* @since 4.0.0
*/
export class OpenAiConfig extends Context.Service<
OpenAiConfig,
OpenAiConfig.Service
>()("@effect/ai-openai-compat/OpenAiConfig") {
/**
* Gets the configured OpenAI-compatible service from the current context when present.
*
* @since 4.0.0
*/
static readonly getOrUndefined: Effect.Effect<typeof OpenAiConfig.Service | undefined> = Effect.map(
Effect.context<never>(),
(context) => context.mapUnsafe.get(OpenAiConfig.key)
)
}
/**
* Types associated with the `OpenAiConfig` context service.
*
* @since 4.0.0
*/
export declare namespace OpenAiConfig {
/**
* Configuration consumed by OpenAI-compatible clients when they build or
* resolve the underlying HTTP client.
*
* @category models
* @since 4.0.0
*/
export interface Service {
readonly transformClient?: ((client: HttpClient) => HttpClient) | undefined
}
}
/**
* Provides an HTTP client transform for the supplied effect.
*
* **When to use**
*
* Use to add provider-specific OpenAI-compatible HTTP behavior, such as
* headers, retries, instrumentation, or proxy routing.
*
* **Details**
*
* OpenAI-compatible provider services read the transform from the
* `OpenAiConfig` context.
*
* @category configuration
* @since 4.0.0
*/
export const withClientTransform: {
(transform: (client: HttpClient) => HttpClient): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
<A, E, R>(self: Effect.Effect<A, E, R>, transform: (client: HttpClient) => HttpClient): Effect.Effect<A, E, R>
} = dual(2, <A, E, R>(
self: Effect.Effect<A, E, R>,
transformClient: (client: HttpClient) => HttpClient
) =>
Effect.flatMap(
OpenAiConfig.getOrUndefined,
(config) => Effect.provideService(self, OpenAiConfig, { ...config, transformClient })
))

View File

@@ -0,0 +1,244 @@
/**
* The `OpenAiEmbeddingModel` module adapts OpenAI-compatible embeddings
* endpoints to Effect's embedding model service. It sends embedding requests
* through {@link OpenAiClient}, exposes constructors for layers and `AiModel`
* values, supports scoped request configuration overrides, and checks that the
* provider returns one numeric vector for each requested input.
*
* @since 4.0.0
*/
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import * as Layer from "effect/Layer"
import type { Simplify } from "effect/Types"
import * as AiError from "effect/unstable/ai/AiError"
import * as EmbeddingModel from "effect/unstable/ai/EmbeddingModel"
import * as AiModel from "effect/unstable/ai/Model"
import type { CreateEmbedding200, CreateEmbeddingRequestJson } from "./OpenAiClient.ts"
import { OpenAiClient } from "./OpenAiClient.ts"
/**
* A model identifier accepted by an OpenAI-compatible embeddings endpoint.
*
* @category models
* @since 4.0.0
*/
export type Model = string
type ConfigOptions = Simplify<Partial<Omit<CreateEmbeddingRequestJson, "input">>>
type ModelConfig = Omit<ConfigOptions, "model"> & { readonly [x: string]: unknown }
/**
* Context service for OpenAI embedding model configuration.
*
* **When to use**
*
* Use when you need to provide shared default request options for
* OpenAI-compatible embedding operations through the Effect context, such as
* `dimensions`, `encoding_format`, or `user`.
*
* **Details**
*
* The service stores the embedding request payload without `input`. Requests
* combine the selected model, layer or constructor config, and scoped context
* config, with scoped context config taking precedence.
*
* @see {@link withConfigOverride} for scoping embedding request overrides
*
* @category context
* @since 4.0.0
*/
export class Config extends Context.Service<
Config,
ConfigOptions & { readonly [x: string]: unknown }
>()("@effect/ai-openai-compat/OpenAiEmbeddingModel/Config") {}
/**
* Creates an `AiModel` for an OpenAI-compatible embedding model with its configured vector dimensions.
*
* **When to use**
*
* Use to provide an OpenAI-compatible `EmbeddingModel` and its `Dimensions`
* service to an Effect program.
*
* @see {@link layer} for providing only the embedding model service
* @see {@link withConfigOverride} for scoped request configuration overrides
*
* @category constructors
* @since 4.0.0
*/
export const model = (
model: string,
options: Omit<ConfigOptions, "model" | "dimensions"> & {
readonly dimensions: number
readonly [x: string]: unknown
}
): AiModel.Model<"openai", EmbeddingModel.EmbeddingModel | EmbeddingModel.Dimensions, OpenAiClient> =>
AiModel.make(
"openai",
model,
Layer.merge(
layer({
model,
config: options
}),
Layer.succeed(EmbeddingModel.Dimensions, options.dimensions)
)
)
/**
* Creates an OpenAI-compatible embedding model service backed by `OpenAiClient`.
*
* **When to use**
*
* Use when you need to build or provide an `EmbeddingModel` service directly
* from an existing `OpenAiClient`.
*
* **Details**
*
* The service sends embedding requests through `OpenAiClient.createEmbedding`.
* Request config is merged as the selected model, constructor config, then
* scoped `Config`, so scoped overrides take precedence. Provider usage
* `prompt_tokens` is exposed as `usage.inputTokens`.
*
* **Gotchas**
*
* Provider responses must contain one numeric vector for every requested input
* with unique, in-range `index` values; otherwise embedding operations fail with
* `AiError.InvalidOutputError`.
*
* @see {@link model} for the higher-level `AiModel` descriptor that also provides `EmbeddingModel.Dimensions`
* @see {@link layer} for providing the service as a `Layer`
* @see {@link withConfigOverride} for scoping embedding request overrides
*
* @category constructors
* @since 4.0.0
*/
export const make = Effect.fnUntraced(function*({ model, config: providerConfig }: {
readonly model: string
readonly config?: ModelConfig | undefined
}): Effect.fn.Return<EmbeddingModel.Service, never, OpenAiClient> {
const client = yield* OpenAiClient
const makeConfig = Effect.gen(function*() {
const services = yield* Effect.context<never>()
return { model, ...providerConfig, ...services.mapUnsafe.get(Config.key) }
})
return yield* EmbeddingModel.make({
embedMany: Effect.fnUntraced(function*({ inputs }) {
const config = yield* makeConfig
const response = yield* client.createEmbedding({ ...config, input: inputs })
return yield* mapProviderResponse(inputs.length, response)
})
})
})
/**
* Creates a layer for an OpenAI-compatible embedding model service.
*
* **When to use**
*
* Use when composing application layers and you want an OpenAI-compatible
* embeddings endpoint to satisfy `EmbeddingModel.EmbeddingModel` while
* supplying `OpenAiClient` from another layer.
*
* @see {@link make} for constructing the embedding model service effectfully
* @see {@link model} for creating an `AiModel` with configured dimensions
*
* @category layers
* @since 4.0.0
*/
export const layer = (options: {
readonly model: string
readonly config?: ModelConfig | undefined
}): Layer.Layer<EmbeddingModel.EmbeddingModel, never, OpenAiClient> =>
Layer.effect(EmbeddingModel.EmbeddingModel, make(options))
/**
* Provides scoped request config overrides for OpenAI-compatible embedding model operations.
*
* **When to use**
*
* Use to apply embedding request options to one effect without changing the
* model's default configuration.
*
* **Details**
*
* The overrides are merged with any existing `Config` service for the duration
* of the supplied effect. Fields in `overrides` take precedence over existing
* config, and the helper supports both `effect.pipe(withConfigOverride(overrides))`
* and `withConfigOverride(effect, overrides)`.
*
* @see {@link Config} for available OpenAI-compatible embedding request configuration fields
*
* @category configuration
* @since 4.0.0
*/
export const withConfigOverride: {
(overrides: typeof Config.Service): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Config>>
<A, E, R>(self: Effect.Effect<A, E, R>, overrides: typeof Config.Service): Effect.Effect<A, E, Exclude<R, Config>>
} = dual<
(
overrides: typeof Config.Service
) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Config>>,
<A, E, R>(self: Effect.Effect<A, E, R>, overrides: typeof Config.Service) => Effect.Effect<A, E, Exclude<R, Config>>
>(2, (self, overrides) =>
Effect.flatMap(
Effect.serviceOption(Config),
(config) =>
Effect.provideService(self, Config, {
...(config._tag === "Some" ? config.value : {}),
...overrides
})
))
const mapProviderResponse = (
inputLength: number,
response: CreateEmbedding200
): Effect.Effect<EmbeddingModel.ProviderResponse, AiError.AiError> => {
if (response.data.length !== inputLength) {
return Effect.fail(
invalidOutput(`Provider returned ${response.data.length} embeddings but expected ${inputLength}`)
)
}
const results = new Array<Array<number>>(inputLength)
const seen = new Set<number>()
for (const entry of response.data) {
if (!Number.isInteger(entry.index) || entry.index < 0 || entry.index >= inputLength) {
return Effect.fail(invalidOutput(`Provider returned invalid embedding index: ${entry.index}`))
}
if (seen.has(entry.index)) {
return Effect.fail(invalidOutput(`Provider returned duplicate embedding index: ${entry.index}`))
}
if (!Array.isArray(entry.embedding)) {
return Effect.fail(invalidOutput(`Provider returned non-vector embedding at index ${entry.index}`))
}
seen.add(entry.index)
results[entry.index] = [...entry.embedding]
}
if (seen.size !== inputLength) {
return Effect.fail(
invalidOutput(`Provider returned embeddings for ${seen.size} inputs but expected ${inputLength}`)
)
}
return Effect.succeed({
results,
usage: {
inputTokens: response.usage?.prompt_tokens
}
})
}
const invalidOutput = (description: string): AiError.AiError =>
AiError.make({
module: "OpenAiEmbeddingModel",
method: "embedMany",
reason: new AiError.InvalidOutputError({ description })
})

View File

@@ -0,0 +1,178 @@
/**
* The `OpenAiError` module defines OpenAI-specific metadata that can be
* attached to the shared `AiError` error types used by the AI packages. It is
* primarily used by OpenAI-compatible clients to preserve provider details
* such as error codes, error types, request IDs, and rate limit headers while
* still exposing errors through the provider-neutral Effect AI error model.
*
* Use this module when mapping OpenAI API failures into `AiError` values and
* when consumers need enough structured metadata to debug failed requests,
* inspect quota or rate limit responses, or correlate an error with OpenAI
* support. The exported types are metadata shapes only; the module augmentation
* makes those shapes available on the corresponding shared AI error metadata
* interfaces without defining new runtime error classes.
*
* @since 4.0.0
*/
/**
* OpenAI-specific error metadata fields.
*
* @category models
* @since 4.0.0
*/
export type OpenAiErrorMetadata = {
/**
* The OpenAI error code returned by the API.
*/
readonly errorCode: string | null
/**
* The OpenAI error type returned by the API.
*/
readonly errorType: string | null
/**
* The unique request ID for debugging with OpenAI support.
*/
readonly requestId: string | null
}
/**
* OpenAI-specific rate limit metadata fields.
*
* **Details**
*
* Extends base error metadata with rate limit specific information from
* OpenAI's rate limit headers.
*
* @category models
* @since 4.0.0
*/
export type OpenAiRateLimitMetadata = OpenAiErrorMetadata & {
/**
* The rate limit type (e.g. "requests", "tokens").
*/
readonly limit: string | null
/**
* Number of remaining requests in the current window.
*/
readonly remaining: number | null
/**
* Time until the request rate limit resets.
*/
readonly resetRequests: string | null
/**
* Time until the token rate limit resets.
*/
readonly resetTokens: string | null
}
declare module "effect/unstable/ai/AiError" {
/**
* Metadata attached to rate limit errors returned by OpenAI-compatible APIs.
*
* @category models
* @since 4.0.0
*/
export interface RateLimitErrorMetadata {
readonly openai?: OpenAiRateLimitMetadata | null
}
/**
* Metadata attached when an OpenAI-compatible provider reports that quota or
* billing limits have been exhausted.
*
* @category models
* @since 4.0.0
*/
export interface QuotaExhaustedErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
/**
* Metadata attached to authentication failures from OpenAI-compatible APIs,
* such as invalid, missing, or unauthorized API credentials.
*
* @category models
* @since 4.0.0
*/
export interface AuthenticationErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
/**
* Metadata attached when an OpenAI-compatible provider rejects content because
* it violates a safety or usage policy.
*
* @category models
* @since 4.0.0
*/
export interface ContentPolicyErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
/**
* Metadata attached to malformed or unsupported requests rejected by an
* OpenAI-compatible API before model execution.
*
* @category models
* @since 4.0.0
*/
export interface InvalidRequestErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
/**
* Metadata attached to unexpected server-side failures reported by an
* OpenAI-compatible provider.
*
* @category models
* @since 4.0.0
*/
export interface InternalProviderErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
/**
* Metadata attached when an OpenAI-compatible response cannot be converted
* into the expected AI package output shape.
*
* @category models
* @since 4.0.0
*/
export interface InvalidOutputErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
/**
* Metadata attached when an OpenAI-compatible structured output response does
* not satisfy the requested schema or parsing constraints.
*
* @category models
* @since 4.0.0
*/
export interface StructuredOutputErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
/**
* Metadata attached when an OpenAI-compatible provider cannot support the
* schema supplied for structured output or tool definitions.
*
* @category models
* @since 4.0.0
*/
export interface UnsupportedSchemaErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
/**
* Metadata attached when an OpenAI-compatible error response cannot be mapped
* to a more specific shared AI error category.
*
* @category models
* @since 4.0.0
*/
export interface UnknownErrorMetadata {
readonly openai?: OpenAiErrorMetadata | null
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,164 @@
/**
* The `OpenAiTelemetry` module defines OpenAI-compatible telemetry attributes
* and a helper for adding them to a tracing span. It keeps the standard GenAI
* telemetry attributes and adds request and response metadata under the
* `gen_ai.openai.*` OpenTelemetry namespaces.
*
* @since 4.0.0
*/
import { dual } from "effect/Function"
import * as String from "effect/String"
import type { Span } from "effect/Tracer"
import type { Simplify } from "effect/Types"
import * as Telemetry from "effect/unstable/ai/Telemetry"
/**
* The attributes used to describe telemetry in the context of Generative
* Artificial Intelligence (GenAI) Models requests and responses.
*
* **Details**
*
* These attributes follow the OpenTelemetry generative AI semantic
* conventions:
* https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/
*
* @category models
* @since 4.0.0
*/
export type OpenAiTelemetryAttributes = Simplify<
& Telemetry.GenAITelemetryAttributes
& Telemetry.AttributesWithPrefix<RequestAttributes, "gen_ai.openai.request">
& Telemetry.AttributesWithPrefix<ResponseAttributes, "gen_ai.openai.request">
>
/**
* All telemetry attributes which are part of the GenAI specification,
* including the OpenAI-specific attributes.
*
* @category models
* @since 4.0.0
*/
export type AllAttributes = Telemetry.AllAttributes & RequestAttributes & ResponseAttributes
/**
* Telemetry attributes which are part of the GenAI specification and are
* namespaced by `gen_ai.openai.request`.
*
* @category models
* @since 4.0.0
*/
export interface RequestAttributes {
/**
* The response format that is requested.
*/
readonly responseFormat?: (string & {}) | WellKnownResponseFormat | null | undefined
/**
* The service tier requested. May be a specific tier, `default`, or `auto`.
*/
readonly serviceTier?: (string & {}) | WellKnownServiceTier | null | undefined
}
/**
* Telemetry attributes which are part of the GenAI specification and are
* namespaced by `gen_ai.openai.response`.
*
* @category models
* @since 4.0.0
*/
export interface ResponseAttributes {
/**
* The service tier used for the response.
*/
readonly serviceTier?: string | null | undefined
/**
* A fingerprint to track any eventual change in the Generative AI
* environment.
*/
readonly systemFingerprint?: string | null | undefined
}
/**
* The `gen_ai.openai.request.response_format` attribute has a list of
* well-known values.
*
* **Details**
*
* If one of them applies, then the respective value **MUST** be used;
* otherwise, a custom value **MAY** be used.
*
* @category models
* @since 4.0.0
*/
export type WellKnownResponseFormat = "json_object" | "json_schema" | "text"
/**
* The `gen_ai.openai.request.service_tier` attribute has a list of
* well-known values.
*
* **Details**
*
* If one of them applies, then the respective value **MUST** be used;
* otherwise, a custom value **MAY** be used.
*
* @category models
* @since 4.0.0
*/
export type WellKnownServiceTier = "auto" | "default"
/**
* Options accepted by `addGenAIAnnotations`, combining standard GenAI telemetry
* attributes with optional OpenAI-compatible request and response attributes.
*
* @category options
* @since 4.0.0
*/
export type OpenAiTelemetryAttributeOptions = Telemetry.GenAITelemetryAttributeOptions & {
openai?: {
request?: RequestAttributes | undefined
response?: ResponseAttributes | undefined
} | undefined
}
const addOpenAiRequestAttributes = Telemetry.addSpanAttributes("gen_ai.openai.request", String.camelToSnake)<
RequestAttributes
>
const addOpenAiResponseAttributes = Telemetry.addSpanAttributes("gen_ai.openai.response", String.camelToSnake)<
ResponseAttributes
>
/**
* Applies the specified OpenAI GenAI telemetry attributes to the provided
* `Span`.
*
* **When to use**
*
* Use to annotate an OpenAI-compatible model span with standard GenAI telemetry
* attributes and OpenAI-specific request or response metadata.
*
* **Details**
*
* Standard GenAI attributes are applied first. When OpenAI request or response
* metadata is present, it is written under `gen_ai.openai.request.*` and
* `gen_ai.openai.response.*` attributes.
*
* **Gotchas**
*
* Mutates the supplied `Span` in place.
*
* @category tracing
* @since 4.0.0
*/
export const addGenAIAnnotations: {
(options: OpenAiTelemetryAttributeOptions): (span: Span) => void
(span: Span, options: OpenAiTelemetryAttributeOptions): void
} = dual(2, (span: Span, options: OpenAiTelemetryAttributeOptions) => {
Telemetry.addGenAIAnnotations(span, options)
if (options.openai != null) {
if (options.openai.request != null) {
addOpenAiRequestAttributes(span, options.openai.request)
}
if (options.openai.response != null) {
addOpenAiResponseAttributes(span, options.openai.response)
}
}
})

View File

@@ -0,0 +1,35 @@
/**
* @since 4.0.0
*/
// @barrel: Auto-generated exports. Do not edit manually.
/**
* @since 4.0.0
*/
export * as OpenAiClient from "./OpenAiClient.ts"
/**
* @since 4.0.0
*/
export * as OpenAiConfig from "./OpenAiConfig.ts"
/**
* @since 4.0.0
*/
export * as OpenAiEmbeddingModel from "./OpenAiEmbeddingModel.ts"
/**
* @since 4.0.0
*/
export * as OpenAiError from "./OpenAiError.ts"
/**
* @since 4.0.0
*/
export * as OpenAiLanguageModel from "./OpenAiLanguageModel.ts"
/**
* @since 4.0.0
*/
export * as OpenAiTelemetry from "./OpenAiTelemetry.ts"

View File

@@ -0,0 +1,327 @@
import * as Arr from "effect/Array"
import * as Duration from "effect/Duration"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import * as Number from "effect/Number"
import * as Option from "effect/Option"
import * as Redactable from "effect/Redactable"
import * as Schema from "effect/Schema"
import * as SchemaTransformation from "effect/SchemaTransformation"
import * as String from "effect/String"
import * as AiError from "effect/unstable/ai/AiError"
import type * as Response from "effect/unstable/ai/Response"
import type * as HttpClientError from "effect/unstable/http/HttpClientError"
import type * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import type * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
import type { OpenAiErrorMetadata } from "../OpenAiError.ts"
/** @internal */
export const OpenAiErrorBody = Schema.Struct({
error: Schema.Struct({
message: Schema.String,
type: Schema.optional(Schema.NullOr(Schema.String)),
status: Schema.optional(Schema.NullOr(Schema.String)),
param: Schema.optional(Schema.NullOr(Schema.String)),
code: Schema.optional(Schema.NullOr(Schema.Union([Schema.String, Schema.Number])))
})
})
const OpenAiErrorBodyJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Union([
OpenAiErrorBody,
Schema.NonEmptyArray(OpenAiErrorBody).pipe(
Schema.decodeTo(
Schema.toType(OpenAiErrorBody),
SchemaTransformation.transform({
decode: Arr.headNonEmpty,
encode: (item) => [item]
})
)
)
])))
/** @internal */
export const mapSchemaError = dual<
(method: string) => (error: Schema.SchemaError) => AiError.AiError,
(error: Schema.SchemaError, method: string) => AiError.AiError
>(2, (error, method) =>
AiError.make({
module: "OpenAiClient",
method,
reason: AiError.InvalidOutputError.fromSchemaError(error)
}))
/** @internal */
export const mapHttpClientError = dual<
(method: string) => (error: HttpClientError.HttpClientError) => Effect.Effect<never, AiError.AiError>,
(error: HttpClientError.HttpClientError, method: string) => Effect.Effect<never, AiError.AiError>
>(2, (error, method) => {
const reason = error.reason
switch (reason._tag) {
case "TransportError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.NetworkError({
reason: "TransportError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "EncodeError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.NetworkError({
reason: "EncodeError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "InvalidUrlError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.NetworkError({
reason: "InvalidUrlError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "StatusCodeError": {
return mapStatusCodeError(reason, method)
}
case "DecodeError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.InvalidOutputError({
description: reason.description ?? "Failed to decode response"
})
}))
}
case "EmptyBodyError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.InvalidOutputError({
description: reason.description ?? "Response body was empty"
})
}))
}
}
})
/** @internal */
const mapStatusCodeError = Effect.fnUntraced(function*(
error: HttpClientError.StatusCodeError,
method: string
) {
const { request, response, description } = error
const status = response.status
const headers = response.headers as Record<string, string>
const requestId = headers["x-request-id"]
let body = yield* response.text.pipe(
Effect.catchCause(() => Effect.succeed(description?.startsWith("{") ? description : undefined))
)
const decoded = OpenAiErrorBodyJson(body)
const reason = mapStatusCodeToReason({
status,
headers,
message: Option.isSome(decoded) ? decoded.value.error.message : undefined,
http: buildHttpContext({ request, response, body }),
metadata: {
errorCode: Option.isSome(decoded) ? decoded.value.error.code?.toString() ?? null : null,
errorType: decoded.pipe(
Option.flatMapNullishOr((d) => d.error.type ?? d.error.status),
Option.map(String.toLowerCase),
Option.getOrNull
),
requestId: requestId ?? null
}
})
return yield* AiError.make({ module: "OpenAiClient", method, reason })
})
/** @internal */
export const parseRateLimitHeaders = (headers: Record<string, string>) => {
const retryAfterRaw = headers["retry-after"]
let retryAfter: Duration.Duration | undefined
if (retryAfterRaw !== undefined) {
const parsed = Number.parse(retryAfterRaw)
if (Option.isSome(parsed)) {
retryAfter = Duration.seconds(parsed.value)
}
}
const remainingRaw = headers["x-ratelimit-remaining-requests"]
const remaining = remainingRaw !== undefined ? Option.getOrNull(Number.parse(remainingRaw)) : null
return {
retryAfter,
limit: headers["x-ratelimit-limit-requests"] ?? null,
remaining,
resetRequests: headers["x-ratelimit-reset-requests"] ?? null,
resetTokens: headers["x-ratelimit-reset-tokens"] ?? null
}
}
/** @internal */
export const buildHttpRequestDetails = (
request: HttpClientRequest.HttpClientRequest
): typeof Response.HttpRequestDetails.Type => ({
method: request.method,
url: request.url,
urlParams: Array.from(request.urlParams),
hash: Option.getOrUndefined(request.hash),
headers: Redactable.redact(request.headers) as Record<string, string>
})
/** @internal */
export const buildHttpContext = (params: {
readonly request: HttpClientRequest.HttpClientRequest
readonly response?: HttpClientResponse.HttpClientResponse
readonly body?: string | undefined
}): typeof AiError.HttpContext.Type => ({
request: buildHttpRequestDetails(params.request),
response: params.response !== undefined
? {
status: params.response.status,
headers: Redactable.redact(params.response.headers) as Record<string, string>
}
: undefined,
body: params.body
})
const buildInvalidRequestDescription = (params: {
readonly status: number
readonly message: string | undefined
readonly method: string
readonly url: string
readonly errorCode: string | null
readonly errorType: string | null
readonly requestId: string | null
readonly body: string | undefined
}): string => {
const parts: Array<string> = []
if (params.message) {
parts.push(params.message)
} else {
parts.push(`HTTP ${params.status}`)
}
parts.push(`(${params.method} ${params.url})`)
if (params.errorCode) {
parts.push(`[code: ${params.errorCode}]`)
} else if (params.errorType) {
parts.push(`[type: ${params.errorType}]`)
}
if (params.requestId) {
parts.push(`[requestId: ${params.requestId}]`)
}
if (!params.message && params.body) {
const truncated = params.body.length > 200
? params.body.slice(0, 200) + "..."
: params.body
parts.push(`Response: ${truncated}`)
}
return parts.join(" ")
}
/** @internal */
export const mapStatusCodeToReason = ({ status, headers, message, metadata, http }: {
readonly status: number
readonly headers: Record<string, string>
readonly message: string | undefined
readonly metadata: OpenAiErrorMetadata
readonly http: typeof AiError.HttpContext.Type
}): AiError.AiErrorReason => {
const invalidRequestDescription = buildInvalidRequestDescription({
status,
message,
method: http.request.method,
url: http.request.url,
errorCode: metadata.errorCode,
errorType: metadata.errorType,
requestId: metadata.requestId,
body: http.body
})
switch (status) {
case 400:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { openai: metadata },
http
})
case 401:
return new AiError.AuthenticationError({
kind: "InvalidKey",
metadata,
http
})
case 403:
return new AiError.AuthenticationError({
kind: "InsufficientPermissions",
metadata,
http
})
case 404:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { openai: metadata },
http
})
case 409:
case 422:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { openai: metadata },
http
})
case 429: {
if (
metadata.errorCode === "insufficient_quota" ||
metadata.errorType === "insufficient_quota" ||
metadata.errorType?.includes("quota") ||
metadata.errorType?.includes("exhausted")
) {
return new AiError.QuotaExhaustedError({
metadata: { openai: metadata },
http
})
}
const { retryAfter, ...rateLimitMetadata } = parseRateLimitHeaders(headers)
return new AiError.RateLimitError({
retryAfter,
metadata: {
openai: {
...metadata,
...rateLimitMetadata
}
},
http
})
}
default:
if (status >= 500) {
return new AiError.InternalProviderError({
description: message ?? "Server error",
metadata,
http
})
}
return new AiError.UnknownError({
description: message,
metadata,
http
})
}
}

View File

@@ -0,0 +1,24 @@
import type * as Response from "effect/unstable/ai/Response"
const finishReasonMap: Record<string, Response.FinishReason> = {
content_filter: "content-filter",
function_call: "tool-calls",
length: "length",
stop: "stop",
tool_calls: "tool-calls"
}
/** @internal */
export const resolveFinishReason = (
finishReason: string | null | undefined,
hasToolCalls: boolean
): Response.FinishReason => {
if (finishReason == null) {
return hasToolCalls ? "tool-calls" : "stop"
}
const reason = finishReasonMap[finishReason]
if (reason == null) {
return hasToolCalls ? "tool-calls" : "unknown"
}
return reason
}

View File

@@ -0,0 +1,474 @@
import * as OpenAiClient from "@effect/ai-openai-compat/OpenAiClient"
import { assert, describe, it } from "@effect/vitest"
import { Effect, Layer, Redacted, Stream } from "effect"
import { HttpClient, type HttpClientError, type HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
describe("OpenAiClient", () => {
describe("request behavior", () => {
it.effect("sets auth and OpenAI headers on /chat/completions requests", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-key"),
apiUrl: "https://compat.example.test/v1",
organizationId: Redacted.make("org_123"),
projectId: Redacted.make("proj_456")
}).pipe(
Effect.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, 200, makeChatCompletion()))
})
))
)
yield* client.createResponse({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "hello" }]
})
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
assert.isTrue(capturedRequest.url.endsWith("/chat/completions"))
assert.isTrue(capturedRequest.url.startsWith("https://compat.example.test/v1"))
assert.strictEqual(capturedRequest.headers["authorization"], "Bearer sk-test-key")
assert.strictEqual(capturedRequest.headers["openai-organization"], "org_123")
assert.strictEqual(capturedRequest.headers["openai-project"], "proj_456")
const body = yield* getRequestBody(capturedRequest)
assert.strictEqual(body.messages[0]?.role, "user")
assert.strictEqual(body.messages[0]?.content, "hello")
}))
it.effect("passes custom chat-completions request properties through", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-key")
}).pipe(
Effect.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, 200, makeChatCompletion()))
})
))
)
yield* client.createResponse({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "hello" }],
provider_feature: {
enabled: true
}
})
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const body = yield* getRequestBody(capturedRequest)
assert.deepStrictEqual(body.provider_feature, {
enabled: true
})
}))
it.effect("uses /embeddings path and decodes permissive embedding payloads", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-key"),
apiUrl: "https://compat.example.test/v1"
}).pipe(
Effect.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, 200, {
data: [{
embedding: "YmFzZTY0LWRhdGE=",
index: 0,
object: "embedding",
vendor_payload: { future_field: true }
}],
model: "my-custom-embedding-model",
object: "list",
usage: {
prompt_tokens: 5,
total_tokens: 5
},
unknown_top_level: true
}))
})
))
)
const embedding = yield* client.createEmbedding({
model: "my-custom-embedding-model",
input: "embed this"
})
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
assert.isTrue(capturedRequest.url.endsWith("/embeddings"))
assert.strictEqual(embedding.model, "my-custom-embedding-model")
assert.strictEqual(embedding.data[0]?.index, 0)
assert.strictEqual(typeof embedding.data[0]?.embedding, "string")
}))
it.effect("sets stream=true for createResponseStream and returns chat chunks", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-key")
}).pipe(
Effect.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(sseResponse(request, [
{
id: "chatcmpl_test_1",
object: "chat.completion.chunk",
model: "gpt-4o-mini",
created: 1,
future_provider_field: { accepted: true },
choices: [{
index: 0,
delta: { content: "Hello" },
finish_reason: null
}]
},
{
id: "chatcmpl_test_1",
object: "chat.completion.chunk",
model: "gpt-4o-mini",
created: 1,
usage: {
prompt_tokens: 4,
completion_tokens: 2,
total_tokens: 6,
prompt_tokens_details: { cached_tokens: 1 },
completion_tokens_details: { reasoning_tokens: 1 }
},
choices: [{
index: 0,
delta: {},
finish_reason: "stop"
}]
},
"[DONE]"
]))
})
))
)
const eventsChunk = yield* client.createResponseStream({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "hello" }]
}).pipe(
Effect.flatMap(([_, stream]) => Stream.runCollect(stream))
)
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const body = yield* getRequestBody(capturedRequest)
assert.strictEqual(body.stream, true)
assert.strictEqual(body.stream_options.include_usage, true)
assert.isTrue(capturedRequest.url.endsWith("/chat/completions"))
const events = globalThis.Array.from(eventsChunk)
const firstEvent = events[0]
const secondEvent = events[1]
assert.isTrue(typeof firstEvent === "object")
assert.isTrue(typeof secondEvent === "object")
if (
typeof firstEvent !== "object" || firstEvent === null || typeof secondEvent !== "object" ||
secondEvent === null
) {
return
}
assert.strictEqual(firstEvent.id, "chatcmpl_test_1")
assert.strictEqual(secondEvent.id, "chatcmpl_test_1")
assert.strictEqual(events[2], "[DONE]")
}))
it.effect("passes chat-completions tool_choice payload through unchanged", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-key")
}).pipe(
Effect.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, 200, makeChatCompletion()))
})
))
)
yield* client.createResponse({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "hello" }],
tool_choice: {
type: "function",
function: {
name: "TestTool"
}
},
tools: [{
type: "function",
function: {
name: "TestTool",
parameters: {
type: "object",
additionalProperties: false,
properties: {
input: { type: "string" }
},
required: ["input"]
}
}
}]
})
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const body = yield* getRequestBody(capturedRequest)
assert.deepStrictEqual(body.tool_choice, { type: "function", function: { name: "TestTool" } })
}))
it.effect("accepts assistant tool-call and tool result chat history", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-key")
}).pipe(
Effect.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, 200, makeChatCompletion()))
})
))
)
yield* client.createResponse({
model: "gpt-4o-mini",
messages: [
{
role: "assistant",
content: null,
tool_calls: [{
id: "patch_call_1",
type: "function",
function: {
name: "apply_patch",
arguments: JSON.stringify({
call_id: "patch_call_1",
operation: {
type: "delete_file",
path: "src/obsolete.ts"
}
})
}
}]
},
{
role: "tool",
tool_call_id: "patch_call_1",
content: "deleted"
}
]
})
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const body = yield* getRequestBody(capturedRequest)
const assistantMessages = body.messages.filter((message: any) => message.role === "assistant")
const patchMessage = assistantMessages.find((message: any) =>
message.tool_calls?.[0]?.function?.name === "apply_patch"
)
assert.isDefined(patchMessage)
assert.strictEqual(patchMessage.tool_calls[0].id, "patch_call_1")
assert.deepStrictEqual(JSON.parse(patchMessage.tool_calls[0].function.arguments), {
call_id: "patch_call_1",
operation: {
type: "delete_file",
path: "src/obsolete.ts"
}
})
const toolMessages = body.messages.filter((message: any) => message.role === "tool")
const patchOutput = toolMessages.find((message: any) => message.tool_call_id === "patch_call_1")
assert.isDefined(patchOutput)
assert.strictEqual(patchOutput.content, "deleted")
}))
})
describe("error mapping", () => {
it.effect("maps 400 responses to InvalidRequestError", () =>
Effect.gen(function*() {
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-key")
}).pipe(
Effect.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(jsonResponse(request, 400, {
error: {
message: "Bad request",
type: "invalid_request_error",
code: null
}
}))
)
))
)
const error = yield* client.createResponse({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "hello" }]
}).pipe(Effect.flip)
assert.strictEqual(error._tag, "AiError")
assert.strictEqual(error.method, "createResponse")
assert.strictEqual(error.reason._tag, "InvalidRequestError")
}))
it.effect("maps insufficient quota errors to QuotaExhaustedError", () =>
Effect.gen(function*() {
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-key")
}).pipe(
Effect.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(jsonResponse(request, 429, {
error: {
message: "You exceeded your current quota",
type: "insufficient_quota",
code: "insufficient_quota"
}
}))
)
))
)
const error = yield* client.createResponse({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "hello" }]
}).pipe(Effect.flip)
assert.strictEqual(error._tag, "AiError")
assert.strictEqual(error.method, "createResponse")
assert.strictEqual(error.reason._tag, "QuotaExhaustedError")
}))
})
})
const makeHttpClient = (
handler: (
request: HttpClientRequest.HttpClientRequest
) => Effect.Effect<HttpClientResponse.HttpClientResponse, HttpClientError.HttpClientError>
) =>
HttpClient.makeWith(
Effect.fnUntraced(function*(requestEffect) {
const request = yield* requestEffect
return yield* handler(request)
}),
Effect.succeed as HttpClient.HttpClient.Preprocess<HttpClientError.HttpClientError, never>
)
const makeChatCompletion = () => ({
id: "chatcmpl_test_1",
object: "chat.completion",
model: "gpt-4o-mini",
created: 1,
choices: [{
index: 0,
finish_reason: "stop",
message: {
role: "assistant",
content: "Hello"
}
}],
usage: {
prompt_tokens: 1,
completion_tokens: 1,
total_tokens: 2
}
})
const jsonResponse = (
request: HttpClientRequest.HttpClientRequest,
status: number,
body: unknown
): HttpClientResponse.HttpClientResponse =>
HttpClientResponse.fromWeb(
request,
new Response(JSON.stringify(body), {
status,
headers: {
"content-type": "application/json"
}
})
)
const sseResponse = (
request: HttpClientRequest.HttpClientRequest,
events: ReadonlyArray<unknown>
): HttpClientResponse.HttpClientResponse =>
HttpClientResponse.fromWeb(
request,
new Response(toSseBody(events), {
status: 200,
headers: {
"content-type": "text/event-stream"
}
})
)
const getRequestBody = (request: HttpClientRequest.HttpClientRequest) =>
Effect.gen(function*() {
const body = request.body
if (body._tag === "Uint8Array") {
const text = new TextDecoder().decode(body.body)
return JSON.parse(text)
}
return yield* Effect.die(new Error("Expected Uint8Array body"))
})
const toSseBody = (events: ReadonlyArray<unknown>): string =>
events.map((event) => {
if (typeof event === "string") {
return `data: ${event}\n\n`
}
return `data: ${JSON.stringify(event)}\n\n`
}).join("")

View File

@@ -0,0 +1,216 @@
import { OpenAiClient, OpenAiEmbeddingModel } from "@effect/ai-openai-compat"
import { assert, describe, it } from "@effect/vitest"
import { Effect, Layer, Redacted } from "effect"
import { EmbeddingModel } from "effect/unstable/ai"
import { HttpClient, type HttpClientError, type HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
describe("OpenAiEmbeddingModel", () => {
it.effect("model provides dimensions service", () =>
Effect.gen(function*() {
const dimensions = yield* EmbeddingModel.Dimensions
assert.strictEqual(dimensions, 1536)
}).pipe(
Effect.provide(OpenAiEmbeddingModel.model("text-embedding-3-small", { dimensions: 1536 })),
Effect.provideService(OpenAiClient.OpenAiClient, noopOpenAiClient)
))
it.effect("reorders embeddings by provider index", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, {
data: [
{ index: 1, embedding: [20, 21] },
{ index: 0, embedding: [10, 11] }
],
model: "text-embedding-3-small",
usage: {
prompt_tokens: 7,
total_tokens: 7
}
}))
})
))
)
const response = yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
return yield* model.embedMany(["first", "second"])
}).pipe(
Effect.provide(OpenAiEmbeddingModel.layer({ model: "text-embedding-3-small" })),
Effect.provide(clientLayer)
)
assert.deepStrictEqual(response.embeddings.map((embedding) => embedding.vector), [[10, 11], [20, 21]])
assert.strictEqual(response.usage.inputTokens, 7)
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const requestBody = yield* getRequestBody(capturedRequest)
assert.strictEqual(requestBody.model, "text-embedding-3-small")
assert.deepStrictEqual(requestBody.input, ["first", "second"])
}))
it.effect("merges config and applies withConfigOverride precedence", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, {
data: [{ index: 0, embedding: [1, 2, 3] }],
model: "override-model"
}))
})
))
)
yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
yield* model.embed("hello")
}).pipe(
OpenAiEmbeddingModel.withConfigOverride({
model: "override-model",
dimensions: 1024,
user: "request-user"
}),
Effect.provide(OpenAiEmbeddingModel.layer({
model: "base-model",
config: {
dimensions: 256,
user: "provider-user"
}
})),
Effect.provide(clientLayer)
)
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const requestBody = yield* getRequestBody(capturedRequest)
assert.strictEqual(requestBody.model, "override-model")
assert.strictEqual(requestBody.dimensions, 1024)
assert.strictEqual(requestBody.user, "request-user")
assert.deepStrictEqual(requestBody.input, ["hello"])
}))
it.effect("fails with InvalidOutputError when provider returns duplicate indices", () =>
Effect.gen(function*() {
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(jsonResponse(request, {
data: [
{ index: 0, embedding: [1] },
{ index: 0, embedding: [2] }
],
model: "text-embedding-3-small",
usage: {
prompt_tokens: 2,
total_tokens: 2
}
}))
)
))
)
const error = yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
return yield* model.embedMany(["a", "b"]).pipe(Effect.flip)
}).pipe(
Effect.provide(OpenAiEmbeddingModel.layer({ model: "text-embedding-3-small" })),
Effect.provide(clientLayer)
)
assert.strictEqual(error._tag, "AiError")
assert.strictEqual(error.reason._tag, "InvalidOutputError")
}))
it.effect("fails with InvalidOutputError when provider returns non-vector embedding payload", () =>
Effect.gen(function*() {
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(jsonResponse(request, {
data: [{ index: 0, embedding: "AQID" }],
model: "text-embedding-3-small",
usage: {
prompt_tokens: 1,
total_tokens: 1
}
}))
)
))
)
const error = yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
return yield* model.embed("a").pipe(Effect.flip)
}).pipe(
Effect.provide(OpenAiEmbeddingModel.layer({ model: "text-embedding-3-small" })),
Effect.provide(clientLayer)
)
assert.strictEqual(error._tag, "AiError")
assert.strictEqual(error.reason._tag, "InvalidOutputError")
}))
})
const makeHttpClient = (
handler: (
request: HttpClientRequest.HttpClientRequest
) => Effect.Effect<HttpClientResponse.HttpClientResponse, HttpClientError.HttpClientError>
) =>
HttpClient.makeWith(
Effect.fnUntraced(function*(requestEffect) {
const request = yield* requestEffect
return yield* handler(request)
}),
Effect.succeed as HttpClient.HttpClient.Preprocess<HttpClientError.HttpClientError, never>
)
const jsonResponse = (
request: HttpClientRequest.HttpClientRequest,
body: unknown
): HttpClientResponse.HttpClientResponse =>
HttpClientResponse.fromWeb(
request,
new Response(JSON.stringify(body), {
status: 200,
headers: {
"content-type": "application/json"
}
})
)
const getRequestBody = (request: HttpClientRequest.HttpClientRequest) =>
Effect.gen(function*() {
const body = request.body
if (body._tag === "Uint8Array") {
const text = new TextDecoder().decode(body.body)
return JSON.parse(text)
}
return yield* Effect.die(new Error("Expected Uint8Array body"))
})
const noopOpenAiClient: OpenAiClient.Service = {
client: undefined as unknown as OpenAiClient.Service["client"],
createResponse: () => Effect.die(new Error("noop")),
createResponseStream: () => Effect.die(new Error("noop")),
createEmbedding: () => Effect.die(new Error("noop"))
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "../../../tsconfig.base.json",
"include": ["src"],
"references": [
{ "path": "../../effect" }
]
}

View File

@@ -0,0 +1,26 @@
import { OpenAiEmbeddingModel, OpenAiLanguageModel } from "@effect/ai-openai-compat"
import { describe, expect, it } from "tstyche"
describe("OpenAI-compatible config", () => {
it("accepts custom language model properties while preserving known property types", () => {
expect(OpenAiLanguageModel.model).type.toBeCallableWith("model", {
temperature: 0.5,
vendor_setting: true
})
expect(OpenAiLanguageModel.model).type.not.toBeCallableWith("model", {
temperature: "high"
})
})
it("accepts custom embedding properties while preserving known property types", () => {
expect(OpenAiEmbeddingModel.model).type.toBeCallableWith("model", {
dimensions: 3,
user: "test-user",
vendor_setting: true
})
expect(OpenAiEmbeddingModel.model).type.not.toBeCallableWith("model", {
dimensions: 3,
user: 1
})
})
})

View File

@@ -0,0 +1,6 @@
import { mergeConfig, type ViteUserConfig } from "vitest/config"
import shared from "../../../vitest.shared.ts"
const config: ViteUserConfig = {}
export default mergeConfig(shared, config)

View File

@@ -0,0 +1,780 @@
# @effect/ai-openai
## 4.0.0-beta.99
### Patch Changes
- Updated dependencies [[`8ce4795`](https://github.com/Effect-TS/effect/commit/8ce4795ccbaebca4292757db568c005a992546a4), [`80b539f`](https://github.com/Effect-TS/effect/commit/80b539f8aba68f478c75c35c2b4140c4ffc4fada), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`e6e6dba`](https://github.com/Effect-TS/effect/commit/e6e6dba6e9d86e7c2ad27dcedf289db76a19697f), [`bfb203e`](https://github.com/Effect-TS/effect/commit/bfb203e95aa439f731acad37fc3a9a831a190f1c), [`2e9a34a`](https://github.com/Effect-TS/effect/commit/2e9a34ac2bece4f3a206160480c991e3841dc67a), [`55d4eb3`](https://github.com/Effect-TS/effect/commit/55d4eb34f2c64d54f6a25a305b5c5438ebd7934e), [`bddb010`](https://github.com/Effect-TS/effect/commit/bddb010eac3d4436cb094edbbee7460c5440c162), [`a328835`](https://github.com/Effect-TS/effect/commit/a328835e50d76bc96648a1c1550456e8c9f81210), [`5560d05`](https://github.com/Effect-TS/effect/commit/5560d05aa6abdd29466d9c3412cc5e648b0adbde), [`8f6e3ad`](https://github.com/Effect-TS/effect/commit/8f6e3adb185b16e8820b98c509b308086f7ff1af), [`46997fa`](https://github.com/Effect-TS/effect/commit/46997fa60401f5e3c93daa4b61f7df8e31caaab4), [`9e6e12d`](https://github.com/Effect-TS/effect/commit/9e6e12d75c118cd265496f2880490d1f33a5c8bf), [`3394b93`](https://github.com/Effect-TS/effect/commit/3394b93d97d6f24fc38670641d1490289ffca7f1), [`febeabc`](https://github.com/Effect-TS/effect/commit/febeabc3f7c31094da000a23edeaabfe2ab00a38), [`54161c9`](https://github.com/Effect-TS/effect/commit/54161c98f6f3569e0c31842f54e6a257f9421c4c), [`385f7a4`](https://github.com/Effect-TS/effect/commit/385f7a4ee4a7359928597ea56d151dbaf5eb5802), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`7543afe`](https://github.com/Effect-TS/effect/commit/7543afea6f4d97d1f1ad876224323838a48daadd), [`44b9cf3`](https://github.com/Effect-TS/effect/commit/44b9cf3d240d726997b4bbcd0ede48e074d3c456), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`0a8aa6a`](https://github.com/Effect-TS/effect/commit/0a8aa6acb90a72b91c24d17133c950e4cacd8abd), [`c8d9fcf`](https://github.com/Effect-TS/effect/commit/c8d9fcf7b030f7c474effbab2764ce7aee1c7209), [`9ca7f9a`](https://github.com/Effect-TS/effect/commit/9ca7f9a69363e4485645966d5a93b8f9597c5206), [`e7aca89`](https://github.com/Effect-TS/effect/commit/e7aca894bb32fbb785b5830837e6061c415a6015), [`55d7560`](https://github.com/Effect-TS/effect/commit/55d75609b8acf8a1b54c1b1c7fbbb65ec741aa3e), [`f809189`](https://github.com/Effect-TS/effect/commit/f809189ddf6b6011ba43a9901baaa734e315da2a), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`0ebdbe7`](https://github.com/Effect-TS/effect/commit/0ebdbe74463dc84385956d0b1e8c2b79ebab5400), [`7517d09`](https://github.com/Effect-TS/effect/commit/7517d09f12a0b183a81bd425962c4e280a68b05d), [`212493b`](https://github.com/Effect-TS/effect/commit/212493b9a1eb98cd1ef6959c707a2e5784a5ae91), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`80ea8cb`](https://github.com/Effect-TS/effect/commit/80ea8cb9222ca73f564c8267ab2f82966fea027a), [`8df19f4`](https://github.com/Effect-TS/effect/commit/8df19f4fe81d90cc33ace88b9a77e5534f82d604)]:
- effect@4.0.0-beta.99
## 4.0.0-beta.98
### Patch Changes
- Updated dependencies [[`989603b`](https://github.com/Effect-TS/effect-smol/commit/989603b60ab1197b64acf214208e0d370cd1f842), [`214c458`](https://github.com/Effect-TS/effect-smol/commit/214c458084bb6995d543cd37d1055f24be3d454e), [`a037273`](https://github.com/Effect-TS/effect-smol/commit/a0372736ac34796969b051bbba4717d7983f1ebe), [`97fdaa9`](https://github.com/Effect-TS/effect-smol/commit/97fdaa9c1f522c65e579365d314a07878e2b904f), [`b24d248`](https://github.com/Effect-TS/effect-smol/commit/b24d248c8df44222ce642087cde2bd859a2dc709), [`19c222c`](https://github.com/Effect-TS/effect-smol/commit/19c222cac2353a3d7b7733caecb00556fffe9a5c), [`eec85dd`](https://github.com/Effect-TS/effect-smol/commit/eec85ddba09ea326fd268ee33eeffd47e50d4671), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`8849052`](https://github.com/Effect-TS/effect-smol/commit/884905232d1e9a365e046d8dde27bf9c5707f57f), [`c15e16a`](https://github.com/Effect-TS/effect-smol/commit/c15e16ad130d1fbde25d912b7ac55995066cb35b), [`01d00a3`](https://github.com/Effect-TS/effect-smol/commit/01d00a3abfbf1f37996cdbe738ea5137c646cdd7), [`8bd4589`](https://github.com/Effect-TS/effect-smol/commit/8bd458975a1b3a8ed042eccf317b93d28ded91e7), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`6e08428`](https://github.com/Effect-TS/effect-smol/commit/6e08428d980501b856f846ad3f3f0e4ea46e7786), [`388dcf9`](https://github.com/Effect-TS/effect-smol/commit/388dcf953f65d317547f34d40e6443c5f264205f), [`2b7ce2b`](https://github.com/Effect-TS/effect-smol/commit/2b7ce2b513e7ec2a77822f1116dc6ffb6ba93f4e), [`87bea7e`](https://github.com/Effect-TS/effect-smol/commit/87bea7e16259246f3bcdf565446394751abca953), [`ce38dc3`](https://github.com/Effect-TS/effect-smol/commit/ce38dc33bda805a684432cca071f4dc3c6b9a1ba), [`a807cd1`](https://github.com/Effect-TS/effect-smol/commit/a807cd170341deca8a1cfb52c4222585f2431bb9), [`fd8a356`](https://github.com/Effect-TS/effect-smol/commit/fd8a356f06a8c9ce4e7e0a13fc4021c178ed31de), [`c2a5edc`](https://github.com/Effect-TS/effect-smol/commit/c2a5edc3abd31ad5bc123362bc1213e03e4095c3), [`5946da3`](https://github.com/Effect-TS/effect-smol/commit/5946da3804a1be5e752b05b96bd058cdba50a1bf), [`4ae0c5f`](https://github.com/Effect-TS/effect-smol/commit/4ae0c5ffcbe6c56ddfcb05c639112a079483539e), [`5b2a0bc`](https://github.com/Effect-TS/effect-smol/commit/5b2a0bceea3a28a33a58555210c90a415dc74a76), [`72ac585`](https://github.com/Effect-TS/effect-smol/commit/72ac585884befde6af9208da738699a93f1bae79), [`5e8c1b8`](https://github.com/Effect-TS/effect-smol/commit/5e8c1b82bfafa121311f987a49ab75395e3647a7), [`0f9c078`](https://github.com/Effect-TS/effect-smol/commit/0f9c07841b04183f485ee6e6458de73b290b09f5)]:
- effect@4.0.0-beta.98
## 4.0.0-beta.97
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.97
## 4.0.0-beta.96
### Patch Changes
- Updated dependencies [[`1503f45`](https://github.com/Effect-TS/effect-smol/commit/1503f45cb5bb2a74f4705252ec505a1f0ade7e62), [`57fe793`](https://github.com/Effect-TS/effect-smol/commit/57fe79316ffbc380b30626a168981fb26ae97459), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`97f29df`](https://github.com/Effect-TS/effect-smol/commit/97f29df457f7ffd07cfb4b379315c12c086af805)]:
- effect@4.0.0-beta.96
## 4.0.0-beta.95
### Patch Changes
- Updated dependencies [[`a482442`](https://github.com/Effect-TS/effect-smol/commit/a482442abdeb490e9652b854ec3495e4aa7273e7), [`fbefa85`](https://github.com/Effect-TS/effect-smol/commit/fbefa850fab2f0a302c20614496aeaaa2a8b5590), [`0b4a32f`](https://github.com/Effect-TS/effect-smol/commit/0b4a32f4260f0d8500942a133001b0d349328102), [`18a49e1`](https://github.com/Effect-TS/effect-smol/commit/18a49e1786679456258002ff9397faf02f678c2d), [`266cb90`](https://github.com/Effect-TS/effect-smol/commit/266cb90bb2c17aabc40563c32db334f09ba3d74b), [`912f095`](https://github.com/Effect-TS/effect-smol/commit/912f095a34572bbd3cedf6edb27878443e3e4a95), [`a6718f9`](https://github.com/Effect-TS/effect-smol/commit/a6718f9e00a15ca903b0732da46116cbf3d6aca7), [`bef5154`](https://github.com/Effect-TS/effect-smol/commit/bef51540a243aa2f872a00c01d0cd58b7a769baa), [`18e0564`](https://github.com/Effect-TS/effect-smol/commit/18e0564bd0f8ebbdfcaf1e2c21529948e9e4a81d), [`fb50f14`](https://github.com/Effect-TS/effect-smol/commit/fb50f14fc3657c1973785aa5b72ecf0b0d28e0b2)]:
- effect@4.0.0-beta.95
## 4.0.0-beta.94
### Patch Changes
- Updated dependencies [[`95a0e9b`](https://github.com/Effect-TS/effect-smol/commit/95a0e9bb62797af0e81c9998773405f248f218c5), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63), [`f11ce73`](https://github.com/Effect-TS/effect-smol/commit/f11ce73af60823754dc24194f4ffc561b9ea1c2d), [`ff30b6e`](https://github.com/Effect-TS/effect-smol/commit/ff30b6e7c2c63ffc56a4c5818d6d86b01b5ad528), [`1caab3c`](https://github.com/Effect-TS/effect-smol/commit/1caab3cc30f626efbf15e59d74f539a487e5c85c), [`aa80c47`](https://github.com/Effect-TS/effect-smol/commit/aa80c4775a04db87553e5568764cab7e32a72814), [`c2ae4fc`](https://github.com/Effect-TS/effect-smol/commit/c2ae4fce2f03a4cd1861c2b1179da7df656e662d), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63)]:
- effect@4.0.0-beta.94
## 4.0.0-beta.93
### Patch Changes
- Updated dependencies [[`00652fe`](https://github.com/Effect-TS/effect-smol/commit/00652fe95c18f87208e91343eb8bf218faa2f677), [`6c58167`](https://github.com/Effect-TS/effect-smol/commit/6c5816746eaf91d2a3c7c899c5720809fa230ae3), [`2bc5415`](https://github.com/Effect-TS/effect-smol/commit/2bc541501a7ef89e542d7cb98e96beb53cd205cc), [`e11cccc`](https://github.com/Effect-TS/effect-smol/commit/e11cccc7d5fe631abccc7d6e3bd296938de0fa2e), [`ba7e77e`](https://github.com/Effect-TS/effect-smol/commit/ba7e77e046b8641a3a4e9750bb88ca4a1d063d3f), [`5713ee7`](https://github.com/Effect-TS/effect-smol/commit/5713ee7edbc3054efde407b2286bbfd45bbc6e1c)]:
- effect@4.0.0-beta.93
## 4.0.0-beta.92
### Patch Changes
- Updated dependencies [[`affdc13`](https://github.com/Effect-TS/effect-smol/commit/affdc139045cc325dce321a84a580fdc1b2da7b9)]:
- effect@4.0.0-beta.92
## 4.0.0-beta.91
### Patch Changes
- Updated dependencies [[`b135b25`](https://github.com/Effect-TS/effect-smol/commit/b135b2517fca9e7839734ace3699a7dfa75b9075), [`aaa21a3`](https://github.com/Effect-TS/effect-smol/commit/aaa21a369a171c600db294f2a4f640583043e150), [`3475ee6`](https://github.com/Effect-TS/effect-smol/commit/3475ee6c2bda6b05c6d7a12ce30c8bb840b5b1a6)]:
- effect@4.0.0-beta.91
## 4.0.0-beta.90
### Patch Changes
- Updated dependencies [[`d237fdf`](https://github.com/Effect-TS/effect-smol/commit/d237fdf726481f76eb52a6196e111b24122bc3d5)]:
- effect@4.0.0-beta.90
## 4.0.0-beta.89
### Patch Changes
- Updated dependencies [[`b7d46ab`](https://github.com/Effect-TS/effect-smol/commit/b7d46ab7e1a29d8711817bab583c9febf48a0dad), [`7777e15`](https://github.com/Effect-TS/effect-smol/commit/7777e1540fd3680dd8346723cffec812b9384669), [`5376197`](https://github.com/Effect-TS/effect-smol/commit/5376197ca8e50358a41b1fd3cec27bd1ec680ec6)]:
- effect@4.0.0-beta.89
## 4.0.0-beta.88
### Patch Changes
- Updated dependencies [[`911f1b8`](https://github.com/Effect-TS/effect-smol/commit/911f1b84790ce42b3a70c95b33e6f6fd9e74de8b), [`8beeeea`](https://github.com/Effect-TS/effect-smol/commit/8beeeea52879d8613a39468848f01c3092bd54d4), [`c306fcf`](https://github.com/Effect-TS/effect-smol/commit/c306fcfeb1ef38455156932a1faf49292b1318da)]:
- effect@4.0.0-beta.88
## 4.0.0-beta.87
### Patch Changes
- Updated dependencies [[`5a0c1a4`](https://github.com/Effect-TS/effect-smol/commit/5a0c1a4faee5707b5cc35e646ff1ffdad70f1956), [`1eea2ea`](https://github.com/Effect-TS/effect-smol/commit/1eea2ea3795ba47316b82b1ac8d4612c0ba389ed)]:
- effect@4.0.0-beta.87
## 4.0.0-beta.86
### Patch Changes
- Updated dependencies [[`0b5795a`](https://github.com/Effect-TS/effect-smol/commit/0b5795a0ab4395e8f15955d8d96f2303084bfc64), [`3e3a859`](https://github.com/Effect-TS/effect-smol/commit/3e3a859ec6351a9e0d31674aabbd48fcefabb12e), [`7dbec24`](https://github.com/Effect-TS/effect-smol/commit/7dbec240dbf3bca599a20c486632abce694ef5ab), [`d8c00a1`](https://github.com/Effect-TS/effect-smol/commit/d8c00a171ac7141e8adc08c332d1162d9a9d56fc), [`85b6317`](https://github.com/Effect-TS/effect-smol/commit/85b631701e935866f2762bd595237aa718370cd9), [`6d0fda0`](https://github.com/Effect-TS/effect-smol/commit/6d0fda0d0cbdfffc523c89c57dfdb1608f84fb12), [`108a933`](https://github.com/Effect-TS/effect-smol/commit/108a9335ff8571928197e5847a09c28ac83d6f46), [`7e1f455`](https://github.com/Effect-TS/effect-smol/commit/7e1f455fab5005d769b939c91e519d450f802cf9), [`46b3e79`](https://github.com/Effect-TS/effect-smol/commit/46b3e79944cfdae7901eb148135c85b7eb39834e)]:
- effect@4.0.0-beta.86
## 4.0.0-beta.85
### Patch Changes
- Updated dependencies [[`328d97c`](https://github.com/Effect-TS/effect-smol/commit/328d97cc53c0dcb89077a5623e35b095eaa59a8c), [`8441836`](https://github.com/Effect-TS/effect-smol/commit/8441836e6dde70e8ae2126be9cefe9b45798b134), [`074e436`](https://github.com/Effect-TS/effect-smol/commit/074e4361091289104cb0ab6959dc3b0ea7794a6a), [`c1dfd60`](https://github.com/Effect-TS/effect-smol/commit/c1dfd60663eb13a58916f3712d877499943b628a), [`2ba316b`](https://github.com/Effect-TS/effect-smol/commit/2ba316bd15fcbf1c50626500d44a2c9b3bec19f5), [`7ce7344`](https://github.com/Effect-TS/effect-smol/commit/7ce7344c41056c79e2ee19ee6a9346c0f1d227c1)]:
- effect@4.0.0-beta.85
## 4.0.0-beta.84
### Patch Changes
- Updated dependencies [[`87f52ba`](https://github.com/Effect-TS/effect-smol/commit/87f52ba16c4370ffa3f84bf8e53038e1419c284e), [`b8ee07f`](https://github.com/Effect-TS/effect-smol/commit/b8ee07ffda8903b5ec2e45a786ddcba59f128fda), [`867c0d7`](https://github.com/Effect-TS/effect-smol/commit/867c0d70a09079b040260d45a1e92ff04dbfbf2f), [`b93bc6c`](https://github.com/Effect-TS/effect-smol/commit/b93bc6c9cb27b909a41d094c97c4f9d25bbc6d6b), [`57d387f`](https://github.com/Effect-TS/effect-smol/commit/57d387f92c30ab63e15e3e641f0a903b65886610), [`bacca41`](https://github.com/Effect-TS/effect-smol/commit/bacca4141c2400effae1eabfdb36c89a459cf246), [`0f8ac79`](https://github.com/Effect-TS/effect-smol/commit/0f8ac7959d29ed68c68ce25aabd6bf0cb7e63ecc), [`25b4482`](https://github.com/Effect-TS/effect-smol/commit/25b448270c01317703f25107e1480d4cd0246d9a), [`9cf3a25`](https://github.com/Effect-TS/effect-smol/commit/9cf3a25c66b0c44a52be9829870c44517ea52db2), [`8def767`](https://github.com/Effect-TS/effect-smol/commit/8def7674b1787f91035298cda4d122937e87ef72)]:
- effect@4.0.0-beta.84
## 4.0.0-beta.83
### Patch Changes
- Updated dependencies [[`1f2e8ce`](https://github.com/Effect-TS/effect-smol/commit/1f2e8ceef09e0a791c850ed2ade01f97089596f9)]:
- effect@4.0.0-beta.83
## 4.0.0-beta.82
### Patch Changes
- Updated dependencies [[`193690b`](https://github.com/Effect-TS/effect-smol/commit/193690b642ea802bbed40d663bd677251bbe9dc3)]:
- effect@4.0.0-beta.82
## 4.0.0-beta.81
### Patch Changes
- Updated dependencies [[`93cb4f8`](https://github.com/Effect-TS/effect-smol/commit/93cb4f8fbfb9e07cb9dc86ce6b155fd1f8167914), [`60341d9`](https://github.com/Effect-TS/effect-smol/commit/60341d9ca744d0473ce3fab621ca9bd225af3a39), [`1105ab5`](https://github.com/Effect-TS/effect-smol/commit/1105ab56cb724212f7ea7b431396ce82e8fd0484), [`4500fbf`](https://github.com/Effect-TS/effect-smol/commit/4500fbfe00763d8a72af6e5d6c5988e8bd4ade36)]:
- effect@4.0.0-beta.81
## 4.0.0-beta.80
### Patch Changes
- Updated dependencies [[`d944330`](https://github.com/Effect-TS/effect-smol/commit/d94433090ee03f426d43e13b883abae4494e55e6), [`f48659f`](https://github.com/Effect-TS/effect-smol/commit/f48659fdcc84930ebc1e5b45b540c0f973389182), [`7652aaa`](https://github.com/Effect-TS/effect-smol/commit/7652aaa3bdbc39f241fe58b54b9a43b713e22e12), [`98630b7`](https://github.com/Effect-TS/effect-smol/commit/98630b7c8f679c352ba6796636c85688fa009d8d), [`90ae23c`](https://github.com/Effect-TS/effect-smol/commit/90ae23cf07284da5e1bcd9dffa882e85df7e617b)]:
- effect@4.0.0-beta.80
## 4.0.0-beta.79
### Patch Changes
- Updated dependencies [[`b9704dc`](https://github.com/Effect-TS/effect-smol/commit/b9704dc9de9f1649ad502371014fe869b69a49a3), [`a207113`](https://github.com/Effect-TS/effect-smol/commit/a207113f66837bb54416926718a9a7d66774d079), [`5e9b9e2`](https://github.com/Effect-TS/effect-smol/commit/5e9b9e217b164ebfd4a002dd4380b3b1563200c3), [`7c128ae`](https://github.com/Effect-TS/effect-smol/commit/7c128aef458a1e2d224712e51c483c9badad1d44), [`0ada457`](https://github.com/Effect-TS/effect-smol/commit/0ada457c0513d8d908254ab77ebb7d29d2b523d6), [`d7cc5a2`](https://github.com/Effect-TS/effect-smol/commit/d7cc5a2bede3de10943aa0c6bdb4f26836a91efd), [`aad63be`](https://github.com/Effect-TS/effect-smol/commit/aad63becf65e0a6b076e94f8973be7bbe7fbd46f), [`09809f6`](https://github.com/Effect-TS/effect-smol/commit/09809f60f19ec98232f98b33e33e02ecb7e4fbd6), [`2fddda5`](https://github.com/Effect-TS/effect-smol/commit/2fddda5311929f46b61e503f0ade4fc749e8c77d), [`5f21768`](https://github.com/Effect-TS/effect-smol/commit/5f2176833399757c4500d8875b7f2fba0393de75), [`f27003e`](https://github.com/Effect-TS/effect-smol/commit/f27003e00524ff83f20dd9909f62b2f8795efe03)]:
- effect@4.0.0-beta.79
## 4.0.0-beta.78
### Patch Changes
- Updated dependencies [[`7836b8e`](https://github.com/Effect-TS/effect-smol/commit/7836b8eb8bb0f3e04cdf554ee070caccf74f00c1), [`35d49a3`](https://github.com/Effect-TS/effect-smol/commit/35d49a3a09bdba6b513de87ddcead9e61a1042ba), [`4093258`](https://github.com/Effect-TS/effect-smol/commit/40932580e65bafab5f23c5f14b520cb411d0b2cd)]:
- effect@4.0.0-beta.78
## 4.0.0-beta.77
### Patch Changes
- Updated dependencies [[`6e9a5ca`](https://github.com/Effect-TS/effect-smol/commit/6e9a5ca62a61156fd67b2518ad3ab14ac0d25f23), [`302f398`](https://github.com/Effect-TS/effect-smol/commit/302f3984ce206e35d86ddd99d3b72be144850a51)]:
- effect@4.0.0-beta.77
## 4.0.0-beta.76
### Patch Changes
- Updated dependencies [[`016108a`](https://github.com/Effect-TS/effect-smol/commit/016108a472af7048ddbbfd05f233e67529fafe12), [`95c03d2`](https://github.com/Effect-TS/effect-smol/commit/95c03d2c55930668c215b5a41c23cf7742fead84), [`07299a3`](https://github.com/Effect-TS/effect-smol/commit/07299a33c09fd52faa9810d30835a2622c752386)]:
- effect@4.0.0-beta.76
## 4.0.0-beta.75
### Patch Changes
- [#2312](https://github.com/Effect-TS/effect-smol/pull/2312) [`ad4b535`](https://github.com/Effect-TS/effect-smol/commit/ad4b535e17f94ce35261829d5a3675f0a7808b4e) Thanks @gcanti! - Validate `Schema.StructWithRest` fixed fields against rest index signatures at the type level so schemas cannot be constructed with incompatible decoded, encoded, or make shapes. This keeps `StructWithRest` types sound and updates the generated OpenAI conversation-items request schema to keep accepting arbitrary additional fields under the stricter validation.
- Updated dependencies [[`81b187c`](https://github.com/Effect-TS/effect-smol/commit/81b187c17a0d8817b58232826939154010ae49d7), [`ad4b535`](https://github.com/Effect-TS/effect-smol/commit/ad4b535e17f94ce35261829d5a3675f0a7808b4e), [`a29c2e7`](https://github.com/Effect-TS/effect-smol/commit/a29c2e7e3570920156702671d6f3367cd0195f6c), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`ffea4ec`](https://github.com/Effect-TS/effect-smol/commit/ffea4ecf2925f6a4c9fd13079d47584cbf2bed00), [`4255c9b`](https://github.com/Effect-TS/effect-smol/commit/4255c9ba78bb98c7838fbe9dccdd8465e9da5427)]:
- effect@4.0.0-beta.75
## 4.0.0-beta.74
### Patch Changes
- Updated dependencies [[`b1fc6a4`](https://github.com/Effect-TS/effect-smol/commit/b1fc6a4b4d0ca7fa9fd162799ae17c86f2f7ee8e)]:
- effect@4.0.0-beta.74
## 4.0.0-beta.73
### Patch Changes
- Updated dependencies [[`361ca30`](https://github.com/Effect-TS/effect-smol/commit/361ca30eb6e134feece547d6e00f82be4cb23f75), [`b9598c6`](https://github.com/Effect-TS/effect-smol/commit/b9598c6a209e75bfdb87ee3b024ecd1e3923ff6e)]:
- effect@4.0.0-beta.73
## 4.0.0-beta.72
### Patch Changes
- [#2280](https://github.com/Effect-TS/effect-smol/pull/2280) [`fa07f9e`](https://github.com/Effect-TS/effect-smol/commit/fa07f9e7138bde3e9404aa91c22b41e273aba091) Thanks @tim-smart! - improve openai websocket error status
- Updated dependencies [[`73e67d1`](https://github.com/Effect-TS/effect-smol/commit/73e67d119a84d697773eaecb4865c6a71eb1a9cb), [`01d71ec`](https://github.com/Effect-TS/effect-smol/commit/01d71ec5a75f3c2747a8d3b1ad9701d1e27b7ce5), [`fcd707e`](https://github.com/Effect-TS/effect-smol/commit/fcd707e091a16e1b35343c901cc4052274e32239)]:
- effect@4.0.0-beta.72
## 4.0.0-beta.71
### Patch Changes
- [#2279](https://github.com/Effect-TS/effect-smol/pull/2279) [`1fab4ac`](https://github.com/Effect-TS/effect-smol/commit/1fab4acc63818dece3a0e732b1a71843f0759f21) Thanks @tim-smart! - handle missing output array in openai responses
- Updated dependencies [[`d8ac76b`](https://github.com/Effect-TS/effect-smol/commit/d8ac76b5bad458c42cebe8a0c1b3843f955ac293), [`2c3c00a`](https://github.com/Effect-TS/effect-smol/commit/2c3c00af6faba7b7d422af26a7a2bbc35636d230), [`3751e7c`](https://github.com/Effect-TS/effect-smol/commit/3751e7cf353e7a54cd692c37401207d9afba1e63), [`fc5f25b`](https://github.com/Effect-TS/effect-smol/commit/fc5f25b03ada5fc2431987768a74d3d3e75ca485), [`7ccced4`](https://github.com/Effect-TS/effect-smol/commit/7ccced42867c14c013b01160b3d292f14c05bd04), [`a2e1fe5`](https://github.com/Effect-TS/effect-smol/commit/a2e1fe5835c98c8ee4393a091b1d11b75126e349), [`4a4a36b`](https://github.com/Effect-TS/effect-smol/commit/4a4a36b10e6e616cad07584a43908f6a7e07e618), [`d350292`](https://github.com/Effect-TS/effect-smol/commit/d3502922b4740fa9d745797cbc3775cb67839b6d), [`730afb6`](https://github.com/Effect-TS/effect-smol/commit/730afb66696adf9bd5a328cbca29df9c05968771), [`df1b008`](https://github.com/Effect-TS/effect-smol/commit/df1b008f370f414c2a67a7b8139ef747af8e5fba), [`6d469d5`](https://github.com/Effect-TS/effect-smol/commit/6d469d567a7c41d7e5343bdee21d45b07b0e8190)]:
- effect@4.0.0-beta.71
## 4.0.0-beta.70
### Patch Changes
- [#2224](https://github.com/Effect-TS/effect-smol/pull/2224) [`74d8f37`](https://github.com/Effect-TS/effect-smol/commit/74d8f37a05ce755ff09cff48f992cb80ce9e4769) Thanks @aniravi24! - Fix `OpenAIFile` schema decode failure on responses where `expires_at` and `status_details` are returned as literal `null`. The OpenAI files endpoint returns `null` (not omitted) for these fields when no expiration / status detail applies (e.g. uploads with `purpose: "user_data"`), but the upstream OpenAPI spec marks them only as optional. Codegen patches widen both fields to allow `null`, which now decodes cleanly via `OpenAiClient.createFile`, `retrieveFile`, `listFiles`, and any other endpoint returning the `OpenAIFile` shape.
- Updated dependencies [[`af7782d`](https://github.com/Effect-TS/effect-smol/commit/af7782d3008d08b043f3a3f261516001514b2b4e), [`7212d70`](https://github.com/Effect-TS/effect-smol/commit/7212d701a3eee7b3553ff502e2c066126e52e839)]:
- effect@4.0.0-beta.70
## 4.0.0-beta.69
### Patch Changes
- Updated dependencies [[`70ea04a`](https://github.com/Effect-TS/effect-smol/commit/70ea04aa96a2a7859d738d414e1f0e3ed081a27a), [`d0ea8b0`](https://github.com/Effect-TS/effect-smol/commit/d0ea8b03f7d73ae076c1db12666141e480d11178), [`a57674b`](https://github.com/Effect-TS/effect-smol/commit/a57674b64845e9e75a456cf907bfdcb858859118), [`59aa334`](https://github.com/Effect-TS/effect-smol/commit/59aa334fbd0a504dda3c36f6d2ef1be7449b4b8b), [`8f4208e`](https://github.com/Effect-TS/effect-smol/commit/8f4208ee83bc7bdaa6793b5429847b45aab72470)]:
- effect@4.0.0-beta.69
## 4.0.0-beta.68
### Patch Changes
- Updated dependencies [[`af8267f`](https://github.com/Effect-TS/effect-smol/commit/af8267f2f3588c3fb611e9286f6f933f29ce1217), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`f136bb7`](https://github.com/Effect-TS/effect-smol/commit/f136bb763048cbc6b17edd26496dba3e2415b9fa), [`6f38f07`](https://github.com/Effect-TS/effect-smol/commit/6f38f07d5941a211b251383aaab0f4f55e8a6557), [`aec9c40`](https://github.com/Effect-TS/effect-smol/commit/aec9c401a53db227f18bf5e0c84db7130ad862d6)]:
- effect@4.0.0-beta.68
## 4.0.0-beta.67
### Patch Changes
- Updated dependencies [[`a42ef66`](https://github.com/Effect-TS/effect-smol/commit/a42ef6632abbddfa820995ae310ccc84ae8d9b6f), [`35594f8`](https://github.com/Effect-TS/effect-smol/commit/35594f811cafe471acd490114b103a1f8392c8d8), [`8bddd62`](https://github.com/Effect-TS/effect-smol/commit/8bddd628cb623f9533d345082583ff51cead6836), [`4be4c8d`](https://github.com/Effect-TS/effect-smol/commit/4be4c8d60862aa963869ee2ed9ffa048ffac0527), [`0c9d3ab`](https://github.com/Effect-TS/effect-smol/commit/0c9d3ab43eb721a370ed8306260cbac218c27e87), [`b156acc`](https://github.com/Effect-TS/effect-smol/commit/b156accd2691b4a051f823affdece7c39923ce85), [`d16c034`](https://github.com/Effect-TS/effect-smol/commit/d16c03434ee3e6dcd3bfc82b65d99e881d89025b), [`b559d68`](https://github.com/Effect-TS/effect-smol/commit/b559d68845f848a10153395778f035682d399075), [`a3de5d9`](https://github.com/Effect-TS/effect-smol/commit/a3de5d9215e5cc4a62e2666efbd7c1bf595eb84f), [`7e6c12e`](https://github.com/Effect-TS/effect-smol/commit/7e6c12ec9b3a5945f6c26e272cc8f6390541ad3e), [`098167a`](https://github.com/Effect-TS/effect-smol/commit/098167a220fe07da6f14455818733ab1b269c9dd)]:
- effect@4.0.0-beta.67
## 4.0.0-beta.66
### Patch Changes
- Updated dependencies [[`ca2498e`](https://github.com/Effect-TS/effect-smol/commit/ca2498e702ac2d83fb7187707b7eb069bdb261a2), [`cd7d1fb`](https://github.com/Effect-TS/effect-smol/commit/cd7d1fba7e2e2c5ac3ad64e1be433440a5bda436), [`19a7033`](https://github.com/Effect-TS/effect-smol/commit/19a703367ec817cffc41d152da9b594827408e2b), [`33d26b4`](https://github.com/Effect-TS/effect-smol/commit/33d26b4210b2e974f146a71e7eed962f8ce00900), [`856766b`](https://github.com/Effect-TS/effect-smol/commit/856766b2c506aaed6d2df1d63bf3a5b1b062e1d4), [`079c7df`](https://github.com/Effect-TS/effect-smol/commit/079c7df82559bb9ce10a86dffb85d25e6ce07dc3)]:
- effect@4.0.0-beta.66
## 4.0.0-beta.65
### Patch Changes
- Updated dependencies [[`6f11454`](https://github.com/Effect-TS/effect-smol/commit/6f11454a9b6c3bd00f6b35fd7af14a2f2d63a0a2)]:
- effect@4.0.0-beta.65
## 4.0.0-beta.64
### Patch Changes
- Updated dependencies [[`7d4877a`](https://github.com/Effect-TS/effect-smol/commit/7d4877a1929cdb690280ea254326c04f2ec97ea5)]:
- effect@4.0.0-beta.64
## 4.0.0-beta.63
### Patch Changes
- [#2133](https://github.com/Effect-TS/effect-smol/pull/2133) [`5be0aaa`](https://github.com/Effect-TS/effect-smol/commit/5be0aaad694c9eb943a710eb4f896bc4c3fcae99) Thanks @Zelys-DFKH! - Fix `OpenAiLanguageModel` leaking library-only config fields (`fileIdPrefixes`, `strictJsonSchema`) into request body, causing OpenAI 400 errors.
- Updated dependencies [[`7f927ff`](https://github.com/Effect-TS/effect-smol/commit/7f927ffb7a9801dcfc4096c29e369d13d65cd0ac), [`a696b3e`](https://github.com/Effect-TS/effect-smol/commit/a696b3e83a8504cdbe261a18c10a1cc0619ae102)]:
- effect@4.0.0-beta.63
## 4.0.0-beta.62
### Patch Changes
- Updated dependencies [[`4ab4b90`](https://github.com/Effect-TS/effect-smol/commit/4ab4b9007dc27a52ffabc6fcb37c96eeec795bf7)]:
- effect@4.0.0-beta.62
## 4.0.0-beta.61
### Patch Changes
- Updated dependencies [[`50790af`](https://github.com/Effect-TS/effect-smol/commit/50790af9b190c38d10fb0723837d49b66432638f), [`71f7c3d`](https://github.com/Effect-TS/effect-smol/commit/71f7c3df997deda92c84146d569696dab3bd645c), [`aae8797`](https://github.com/Effect-TS/effect-smol/commit/aae8797b9cb383be0c182dd58d03d787c354238b)]:
- effect@4.0.0-beta.61
## 4.0.0-beta.60
### Patch Changes
- Updated dependencies [[`f69d567`](https://github.com/Effect-TS/effect-smol/commit/f69d5675dcff9f4137295752baf066b7153fdc09), [`7909c95`](https://github.com/Effect-TS/effect-smol/commit/7909c954b8f6244a35a4b429f8dd0dff45dad620), [`bbb4dcc`](https://github.com/Effect-TS/effect-smol/commit/bbb4dcc6c406b83a416b4ad3541cc02037c420e4), [`7af2207`](https://github.com/Effect-TS/effect-smol/commit/7af2207901eabf3132c1b7010a69b3899c06fbbe), [`848b40a`](https://github.com/Effect-TS/effect-smol/commit/848b40a4bd4bf54a5098617d50c33c88eee8270a)]:
- effect@4.0.0-beta.60
## 4.0.0-beta.59
### Patch Changes
- [#2101](https://github.com/Effect-TS/effect-smol/pull/2101) [`953edef`](https://github.com/Effect-TS/effect-smol/commit/953edef2e1ade369e530017d64391281ef22f28f) Thanks @tim-smart! - don't omit reasoning from openai config
- Updated dependencies [[`56837ea`](https://github.com/Effect-TS/effect-smol/commit/56837ea2a338395b35550641374e9e589bd8b71d)]:
- effect@4.0.0-beta.59
## 4.0.0-beta.58
### Patch Changes
- Updated dependencies [[`11993d4`](https://github.com/Effect-TS/effect-smol/commit/11993d4934c66f5dc611b8bbf553f01d501ef8f7), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec)]:
- effect@4.0.0-beta.58
## 4.0.0-beta.57
### Patch Changes
- Updated dependencies [[`a971f5c`](https://github.com/Effect-TS/effect-smol/commit/a971f5cbd92dfe4274420bf0966595eb35531060), [`8e110c5`](https://github.com/Effect-TS/effect-smol/commit/8e110c5f02a429ccc43a91df8678e402138c0851)]:
- effect@4.0.0-beta.57
## 4.0.0-beta.56
### Patch Changes
- [#1933](https://github.com/Effect-TS/effect-smol/pull/1933) [`c5a7327`](https://github.com/Effect-TS/effect-smol/commit/c5a732746690185b8bb7935d0cf26a5ef21658e4) Thanks @IMax153! - Accept both `in-memory` and `in_memory` for OpenAI `prompt_cache_retention` schema fields.
- [#1933](https://github.com/Effect-TS/effect-smol/pull/1933) [`c5a7327`](https://github.com/Effect-TS/effect-smol/commit/c5a732746690185b8bb7935d0cf26a5ef21658e4) Thanks @IMax153! - Fix OpenAI MCP tool call handling to keep the canonical `OpenAiMcp` tool name across response and stream paths, including approval flows.
- Updated dependencies []:
- effect@4.0.0-beta.56
## 4.0.0-beta.55
### Patch Changes
- Updated dependencies [[`42cc744`](https://github.com/Effect-TS/effect-smol/commit/42cc744570968deb365fb46d47b53d3277050c93), [`04855ce`](https://github.com/Effect-TS/effect-smol/commit/04855ceeca4d40c55a5750dd9893b691f8ea741a)]:
- effect@4.0.0-beta.55
## 4.0.0-beta.54
### Patch Changes
- Updated dependencies [[`e4b74f9`](https://github.com/Effect-TS/effect-smol/commit/e4b74f9c01a0e9b6cd58416de4af3a26d51da7c8), [`4c72808`](https://github.com/Effect-TS/effect-smol/commit/4c728081851c66dacf889a816535671bc841ae96)]:
- effect@4.0.0-beta.54
## 4.0.0-beta.53
### Patch Changes
- [#2060](https://github.com/Effect-TS/effect-smol/pull/2060) [`aef2b1c`](https://github.com/Effect-TS/effect-smol/commit/aef2b1c0130a61a430f116465e4c200c51bcd9e2) Thanks @tim-smart! - add back openai reasoning types
- Updated dependencies [[`0768509`](https://github.com/Effect-TS/effect-smol/commit/07685094e931af07d104165195826a535b55fa7e), [`476aede`](https://github.com/Effect-TS/effect-smol/commit/476aede69c6efa06b5781ca5eb3e3b128ca29141), [`4f79c54`](https://github.com/Effect-TS/effect-smol/commit/4f79c542e7b508c235ff485d862cc8b29a8260c5), [`4be6a7c`](https://github.com/Effect-TS/effect-smol/commit/4be6a7cf35dab2a01d652f56dd35f0358c5a7e88), [`88927eb`](https://github.com/Effect-TS/effect-smol/commit/88927ebb896162cdba103b36553280b58e0facac)]:
- effect@4.0.0-beta.53
## 4.0.0-beta.52
### Minor Changes
- [#2059](https://github.com/Effect-TS/effect-smol/pull/2059) [`6f73f92`](https://github.com/Effect-TS/effect-smol/commit/6f73f92291733dc1e970e222e63aba865183a072) Thanks @tim-smart! - Add a new public `OpenAiSchema` module with minimal local schemas for responses, streaming SSE events (including unknown-event fallback), and embeddings.
### Patch Changes
- [#2059](https://github.com/Effect-TS/effect-smol/pull/2059) [`6f73f92`](https://github.com/Effect-TS/effect-smol/commit/6f73f92291733dc1e970e222e63aba865183a072) Thanks @tim-smart! - Add a new `OpenAiClientGenerated` module that exposes the generated OpenAI client as a dedicated context service with `make`, `layer`, and `layerConfig` constructors. This provides a compatibility path for direct generated-client access while preserving existing auth, base URL, header, and `OpenAiConfig.transformClient` wiring.
- [#2059](https://github.com/Effect-TS/effect-smol/pull/2059) [`6f73f92`](https://github.com/Effect-TS/effect-smol/commit/6f73f92291733dc1e970e222e63aba865183a072) Thanks @tim-smart! - Refactor `OpenAiClient` to the handwritten minimal-schema path so `client` now exposes the configured `HttpClient`, `createResponse` / `createResponseStream` / `createEmbedding` use `OpenAiSchema` request-response types, and websocket mode no longer depends on generated-client internals.
Also migrate OpenAI language and embedding model request-response typing to `OpenAiSchema` and make embedding decoding explicitly reject non-vector (string/base64) payloads with `InvalidOutputError`.
- Updated dependencies [[`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`cf3a311`](https://github.com/Effect-TS/effect-smol/commit/cf3a311d863a8abb818840c3b80f847e621c43c1), [`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`131fdd5`](https://github.com/Effect-TS/effect-smol/commit/131fdd5b1f26531e265fe1a08f002002f47c276e)]:
- effect@4.0.0-beta.52
## 4.0.0-beta.51
### Patch Changes
- Updated dependencies [[`778d2af`](https://github.com/Effect-TS/effect-smol/commit/778d2afe9b5154bc1f9abae46d93ea7e54c87344), [`4e24dcf`](https://github.com/Effect-TS/effect-smol/commit/4e24dcf75037f65eebc1eb68623bc7cbf9d5512a), [`4b1c015`](https://github.com/Effect-TS/effect-smol/commit/4b1c0150e9bdb5559ed32d250deb66e17b4240c7), [`454f8ad`](https://github.com/Effect-TS/effect-smol/commit/454f8adad822929c3ef60f8280d0987226b049fd), [`6754a0c`](https://github.com/Effect-TS/effect-smol/commit/6754a0cd18626b06805a079cc5265525a5eb7d27), [`90f7fd5`](https://github.com/Effect-TS/effect-smol/commit/90f7fd5243871b30980964135db4512b8119fa82), [`d7e1519`](https://github.com/Effect-TS/effect-smol/commit/d7e151974934201fd93fa4c8a1192ee9a5d965a0), [`72a8122`](https://github.com/Effect-TS/effect-smol/commit/72a81228e09782bae512f7d041bbfbc78bc668d0)]:
- effect@4.0.0-beta.51
## 4.0.0-beta.50
### Patch Changes
- Updated dependencies [[`07be594`](https://github.com/Effect-TS/effect-smol/commit/07be594825de60f8e1b2102d21dbb9b8fc63b414), [`ae02433`](https://github.com/Effect-TS/effect-smol/commit/ae02433103ce28f53a0c9bfb4a44e75773289b7b)]:
- effect@4.0.0-beta.50
## 4.0.0-beta.49
### Patch Changes
- Updated dependencies [[`7d87873`](https://github.com/Effect-TS/effect-smol/commit/7d8787340ff549370f6f2a88b612e9ebbfd6ba45), [`c2f6f90`](https://github.com/Effect-TS/effect-smol/commit/c2f6f901b200a6e515b4f02c93ce8005b7bbf1c5), [`216f13c`](https://github.com/Effect-TS/effect-smol/commit/216f13c1fce454a21b489bb915714a17e791a1ac)]:
- effect@4.0.0-beta.49
## 4.0.0-beta.48
### Patch Changes
- Updated dependencies [[`4da56ec`](https://github.com/Effect-TS/effect-smol/commit/4da56ecff129b2da40137ffede23a73cc4e532d8), [`a5e6f77`](https://github.com/Effect-TS/effect-smol/commit/a5e6f774bab195cf50ecdc818240765f69a3bf4a), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070)]:
- effect@4.0.0-beta.48
## 4.0.0-beta.47
### Patch Changes
- Updated dependencies [[`c584726`](https://github.com/Effect-TS/effect-smol/commit/c58472674e750e6938df955044eab88feda95e45), [`86a91a4`](https://github.com/Effect-TS/effect-smol/commit/86a91a4f0c59286dfa9393232d8020dea70ed4db), [`131caf9`](https://github.com/Effect-TS/effect-smol/commit/131caf9525151a0cb29803a8f1dffa0f4f479d12), [`c3615c8`](https://github.com/Effect-TS/effect-smol/commit/c3615c88379b9daf252df0db72c6ac5a20326406)]:
- effect@4.0.0-beta.47
## 4.0.0-beta.46
### Patch Changes
- Updated dependencies [[`3a30b9e`](https://github.com/Effect-TS/effect-smol/commit/3a30b9e2ec2bd8b8193e1aa139f6878a07e3f5ee)]:
- effect@4.0.0-beta.46
## 4.0.0-beta.45
### Patch Changes
- Updated dependencies [[`5c3af6d`](https://github.com/Effect-TS/effect-smol/commit/5c3af6d554f60be34f8fc21d598d9a298ae11beb)]:
- effect@4.0.0-beta.45
## 4.0.0-beta.44
### Patch Changes
- [#1961](https://github.com/Effect-TS/effect-smol/pull/1961) [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970) Thanks @IMax153! - Rename the `ServiceMap` module to `Context` across exports, docs, and tests.
- Updated dependencies [[`e3f0621`](https://github.com/Effect-TS/effect-smol/commit/e3f0621454c3f5d11070d30619da27c9232cadc1), [`5b476ab`](https://github.com/Effect-TS/effect-smol/commit/5b476abc0bd7e9bb59135ea1bcad2e4936227ced), [`6b40e5a`](https://github.com/Effect-TS/effect-smol/commit/6b40e5a4a6bd2087c15a3d7374d25057fdedfa16), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`3b09fb3`](https://github.com/Effect-TS/effect-smol/commit/3b09fb31c40c2802b01f21c23bcdd1fe7fb0aa82), [`2370410`](https://github.com/Effect-TS/effect-smol/commit/237041062e5af4594d32db91597e34e70a632877), [`dabc272`](https://github.com/Effect-TS/effect-smol/commit/dabc272444a700eb629c07ba3e77671a841ca86e), [`08b63c3`](https://github.com/Effect-TS/effect-smol/commit/08b63c3df11bd35c9fd6090dbd166287fdc40664), [`dfff04c`](https://github.com/Effect-TS/effect-smol/commit/dfff04c4c2b1d352dfad83992a6dce1280c85cf9), [`9baed9e`](https://github.com/Effect-TS/effect-smol/commit/9baed9e17e84702e6e480fcef6f86404f9e24be9), [`7846792`](https://github.com/Effect-TS/effect-smol/commit/7846792adc7e1631d62d26d657bd7ba6139f369b), [`1556a24`](https://github.com/Effect-TS/effect-smol/commit/1556a247623636b7ebe438fb56d77f1a7bf957bb), [`7c11bc2`](https://github.com/Effect-TS/effect-smol/commit/7c11bc292ab8e46252fe8f7576fb685917bfb8b5), [`b5ea591`](https://github.com/Effect-TS/effect-smol/commit/b5ea5913ec1d45d0dd12a327b9dd966bda2f6d02), [`0853afa`](https://github.com/Effect-TS/effect-smol/commit/0853afaeb1633b2d7f8b66893bd01c3aa1ef2c22), [`ac845f3`](https://github.com/Effect-TS/effect-smol/commit/ac845f3ab40e0b8719576e7f9bc16ea2e0e02cd4), [`b80c462`](https://github.com/Effect-TS/effect-smol/commit/b80c46247480f47bb64fc480fab48a3f37bc8888), [`b3f535d`](https://github.com/Effect-TS/effect-smol/commit/b3f535d9a7ac13b5fb984c29f93561c57a081ff0), [`6fe2e93`](https://github.com/Effect-TS/effect-smol/commit/6fe2e93cc2f1b173ef89651d74b6a5d2626b3226), [`cda8004`](https://github.com/Effect-TS/effect-smol/commit/cda800451c1ffbdddfc08415aed7b2d91e0412ee), [`8335477`](https://github.com/Effect-TS/effect-smol/commit/8335477a8a936a24b5f3ee6203c1b268bd1bfc3c), [`8c836f9`](https://github.com/Effect-TS/effect-smol/commit/8c836f99ab1e896b9580a71d67773625baff2eaf), [`718ff6f`](https://github.com/Effect-TS/effect-smol/commit/718ff6fe3e3d3820cefd67d2bff1b2224fe08060), [`7eed84f`](https://github.com/Effect-TS/effect-smol/commit/7eed84fc33c5781a6fb11bf4fd189d424902ebd4), [`5df46fe`](https://github.com/Effect-TS/effect-smol/commit/5df46fe2f654d59ab5fc1578f4fc27fa40368ef9), [`82dd0f2`](https://github.com/Effect-TS/effect-smol/commit/82dd0f26c6442b07143762ef7bc33742d3978dd6), [`03ae41e`](https://github.com/Effect-TS/effect-smol/commit/03ae41e7304cffac9f18feea22b73468feafc43a), [`4677a0a`](https://github.com/Effect-TS/effect-smol/commit/4677a0a58f95eea38a211efcd3f345f237a9e44a), [`87e1fc8`](https://github.com/Effect-TS/effect-smol/commit/87e1fc8b67e4901d75f567b2fecc3841ab762cc4), [`c1af1b7`](https://github.com/Effect-TS/effect-smol/commit/c1af1b756f63291e9c0298cf95c98a6920a0c2a0), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`c8a877b`](https://github.com/Effect-TS/effect-smol/commit/c8a877b53e8f29616335719e5dd1c3992dddf780), [`7da961a`](https://github.com/Effect-TS/effect-smol/commit/7da961ae4916229d2246699a5d3b20e5b2dd2020)]:
- effect@4.0.0-beta.44
## 4.0.0-beta.43
### Patch Changes
- [#1905](https://github.com/Effect-TS/effect-smol/pull/1905) [`fc1444d`](https://github.com/Effect-TS/effect-smol/commit/fc1444df6fb7223ed228650c5c927b1df54a8757) Thanks @tim-smart! - openai ws tweaks
- Updated dependencies [[`2ae33d0`](https://github.com/Effect-TS/effect-smol/commit/2ae33d050914915f7cb9c25ab0a020901e08d596), [`979811a`](https://github.com/Effect-TS/effect-smol/commit/979811a4c3f7ed21ed18ef560c49fb7f5569e80e), [`eb7dbef`](https://github.com/Effect-TS/effect-smol/commit/eb7dbeffa883386ad912815e62c0820cac1fdf8e), [`cf50eb4`](https://github.com/Effect-TS/effect-smol/commit/cf50eb49cb04706dae5185f624708117c413dee8), [`1d046fe`](https://github.com/Effect-TS/effect-smol/commit/1d046fe484560e23f3e22cb23eec6433f8f1fa02)]:
- effect@4.0.0-beta.43
## 4.0.0-beta.42
### Patch Changes
- [#1859](https://github.com/Effect-TS/effect-smol/pull/1859) [`a4809db`](https://github.com/Effect-TS/effect-smol/commit/a4809db80f65601d37ccafc13d773e55909c4e98) Thanks @lloydrichards! - add dynamic tooling for openai and openai-compact language models
- [#1890](https://github.com/Effect-TS/effect-smol/pull/1890) [`4549175`](https://github.com/Effect-TS/effect-smol/commit/454917547e8c305707f0777f4efac7adaa924f00) Thanks @tim-smart! - reset openai websocket on error
- Updated dependencies [[`924e216`](https://github.com/Effect-TS/effect-smol/commit/924e216caa7e0bbf22e994a0cd2ce8b1f0f0b3ee), [`80e7f0c`](https://github.com/Effect-TS/effect-smol/commit/80e7f0cd9116e811e97b0ce30a77a8d1ecd072aa), [`f8328bf`](https://github.com/Effect-TS/effect-smol/commit/f8328bf0314da3dc7f31d314f94a5840e8d5217f), [`66d1c06`](https://github.com/Effect-TS/effect-smol/commit/66d1c06039079129707a230f7ad8c676439d7133), [`bee800b`](https://github.com/Effect-TS/effect-smol/commit/bee800bf285192a01bec72a7b7b51bc1159434e6), [`8930441`](https://github.com/Effect-TS/effect-smol/commit/8930441dee6f94c59c583d18d3ebd677cf1f2623)]:
- effect@4.0.0-beta.42
## 4.0.0-beta.41
### Patch Changes
- [#1887](https://github.com/Effect-TS/effect-smol/pull/1887) [`f291344`](https://github.com/Effect-TS/effect-smol/commit/f2913443d99146a6b36d8437e50b94f7c03c1284) Thanks @tim-smart! - make defects a retryable network error in websocket mode
- Updated dependencies [[`36f5c21`](https://github.com/Effect-TS/effect-smol/commit/36f5c2174d31ab42c4598bf81f178f40d0802283), [`d8ce758`](https://github.com/Effect-TS/effect-smol/commit/d8ce758669d6297ae932ac3251d83e7b49b22f30), [`11aab4c`](https://github.com/Effect-TS/effect-smol/commit/11aab4c6d37d5691adafc2d33da1a631b28ce814), [`3bc1efb`](https://github.com/Effect-TS/effect-smol/commit/3bc1efb53dd75b4a40de46f1f80c7f8a7d50af86), [`70e724e`](https://github.com/Effect-TS/effect-smol/commit/70e724e604604d4be1061cd8da0d360494998c84), [`738dee7`](https://github.com/Effect-TS/effect-smol/commit/738dee7edfd70af82dc4d2376db3a8ebe603eb48), [`2111963`](https://github.com/Effect-TS/effect-smol/commit/2111963f19b4c28c800664a8fac9590c1321885f), [`198a553`](https://github.com/Effect-TS/effect-smol/commit/198a553d9ce45f6a00bfc4d65ed0640669602d95)]:
- effect@4.0.0-beta.41
## 4.0.0-beta.40
### Patch Changes
- Updated dependencies [[`f62860f`](https://github.com/Effect-TS/effect-smol/commit/f62860f0e5e45978fabf7256ae620a13152a772a), [`973f281`](https://github.com/Effect-TS/effect-smol/commit/973f2812529aadc1cc54598b2039799fa72b80f8)]:
- effect@4.0.0-beta.40
## 4.0.0-beta.39
### Patch Changes
- Updated dependencies [[`f91fd3d`](https://github.com/Effect-TS/effect-smol/commit/f91fd3db39fe5628439fd175fba201a65a1aa9d0), [`edaae9d`](https://github.com/Effect-TS/effect-smol/commit/edaae9d65f464f941d7eddd723cd33d324f4b071), [`b47db0b`](https://github.com/Effect-TS/effect-smol/commit/b47db0bd5802064b6a24b3ea27c6ff2e0520d513), [`82d3c8e`](https://github.com/Effect-TS/effect-smol/commit/82d3c8e4f3f49b00df611b25aa6f8f74ec21b59b), [`7c22b31`](https://github.com/Effect-TS/effect-smol/commit/7c22b315d198dcbf44ae8cdb8b37879e1c9e3996)]:
- effect@4.0.0-beta.39
## 4.0.0-beta.38
### Patch Changes
- Updated dependencies [[`f4dbe5b`](https://github.com/Effect-TS/effect-smol/commit/f4dbe5b26b9c2d33fae024bf44afbdf8541792cd), [`a71a607`](https://github.com/Effect-TS/effect-smol/commit/a71a607c89fb6669a12a562c2c23be81dfbe1adb), [`66a0494`](https://github.com/Effect-TS/effect-smol/commit/66a0494ed75cd12f2721dcbb1d8a072e3d9e14b6), [`5ef7218`](https://github.com/Effect-TS/effect-smol/commit/5ef7218fc559d57301fe929b8a0cab4033f4f1fd), [`472d260`](https://github.com/Effect-TS/effect-smol/commit/472d260655bc311fba5c2c6e23bb77d8f7e36ba0)]:
- effect@4.0.0-beta.38
## 4.0.0-beta.37
### Patch Changes
- Updated dependencies [[`f7a0b71`](https://github.com/Effect-TS/effect-smol/commit/f7a0b711da8fdd645597dee29cacc5619c6afcf2), [`1e223c3`](https://github.com/Effect-TS/effect-smol/commit/1e223c30ccf835dfbb21284535d78549efaeca80), [`53740f4`](https://github.com/Effect-TS/effect-smol/commit/53740f47aa76d114b7d535649fb50efc54a09608), [`8c7cf89`](https://github.com/Effect-TS/effect-smol/commit/8c7cf89f719e580cbce1bf6c24e6996f1992a0a6), [`b6b81a9`](https://github.com/Effect-TS/effect-smol/commit/b6b81a940eaafcbc792d25413d6c02c707de31b2), [`8f4c1f9`](https://github.com/Effect-TS/effect-smol/commit/8f4c1f97ed60f8810b0b327b50117ffb2d8260d4), [`f2479f9`](https://github.com/Effect-TS/effect-smol/commit/f2479f9d3113b1f012db17a3852b4e28f478cf9c), [`c919921`](https://github.com/Effect-TS/effect-smol/commit/c9199217fad65529421d2cf95ecfff41257090fd), [`7af90c2`](https://github.com/Effect-TS/effect-smol/commit/7af90c2e3c99038eafa39650433839523790e2fe), [`f3be185`](https://github.com/Effect-TS/effect-smol/commit/f3be18569e5ca57c25eabf00df3ca601ebab43c7)]:
- effect@4.0.0-beta.37
## 4.0.0-beta.36
### Patch Changes
- [#1807](https://github.com/Effect-TS/effect-smol/pull/1807) [`1bbd4d9`](https://github.com/Effect-TS/effect-smol/commit/1bbd4d9d617e683a7f338ddd40d11f5838c722bd) Thanks @tim-smart! - Handle streamed OpenAI function calls from `response.function_call_arguments.done` so tool calls are emitted even when `response.output_item.done` is missing.
- [#1809](https://github.com/Effect-TS/effect-smol/pull/1809) [`126db2e`](https://github.com/Effect-TS/effect-smol/commit/126db2e38774c8ef4934321a70d39428ed4491ed) Thanks @tim-smart! - Fix OpenAI reasoning stream state handling so out-of-order reasoning summary events do not crash when prior reasoning item state is missing.
- Updated dependencies [[`60fcbcc`](https://github.com/Effect-TS/effect-smol/commit/60fcbcc43d09471e8f7e0969955d99dcefc5be81), [`0a60837`](https://github.com/Effect-TS/effect-smol/commit/0a6083713124440e630030375bab367e8d7df24e), [`49164d2`](https://github.com/Effect-TS/effect-smol/commit/49164d2c20a8d21b66514992c4a15d8521f6b36e), [`334b6e4`](https://github.com/Effect-TS/effect-smol/commit/334b6e4f76fe11941b516d61f57e268bc31f0ca6), [`5700695`](https://github.com/Effect-TS/effect-smol/commit/5700695f76ae6da6b94c9c87d4dd2b8054fb829b), [`f8f4456`](https://github.com/Effect-TS/effect-smol/commit/f8f445644f3aa7ec093cab7445198a62ba18a480), [`969d24f`](https://github.com/Effect-TS/effect-smol/commit/969d24fdfa48c4838e811983848d9cb4e9b3b12c), [`851eda0`](https://github.com/Effect-TS/effect-smol/commit/851eda0533946e39bacaaf581896320d7a4f3e8c), [`8059c1c`](https://github.com/Effect-TS/effect-smol/commit/8059c1c3eba9a90af7cd889ea261bcb8fff0c185), [`6f83295`](https://github.com/Effect-TS/effect-smol/commit/6f8329546a73eaddc7cb5e85ea8e37e73fbfb611), [`65f7f57`](https://github.com/Effect-TS/effect-smol/commit/65f7f5737575fed668987462c96d29a446707c32), [`e7fabd2`](https://github.com/Effect-TS/effect-smol/commit/e7fabd2265db690eae5cfc9b83730c84699aef61), [`89c3e98`](https://github.com/Effect-TS/effect-smol/commit/89c3e985401eb38f33a3ae21a94ad27de3c1d28b), [`53794ab`](https://github.com/Effect-TS/effect-smol/commit/53794ab7af30aa5c5004ecf53659fafbe4b10542)]:
- effect@4.0.0-beta.36
## 4.0.0-beta.35
### Patch Changes
- [#1776](https://github.com/Effect-TS/effect-smol/pull/1776) [`f5e553d`](https://github.com/Effect-TS/effect-smol/commit/f5e553d133b8e0a303f6c82624d2fec4ab8043da) Thanks @tim-smart! - improve openai socket errors
- Updated dependencies [[`9252b43`](https://github.com/Effect-TS/effect-smol/commit/9252b43560f507709c2985abcf52a7837b23ddf8), [`7daf387`](https://github.com/Effect-TS/effect-smol/commit/7daf3870a656882a488a60f67881e6808c8f4d04), [`e1664a3`](https://github.com/Effect-TS/effect-smol/commit/e1664a38bc31ef4ceb4e9324c7226e1e99bf9c07), [`fdaa6e0`](https://github.com/Effect-TS/effect-smol/commit/fdaa6e0a41b6b6605438fa8557441792135380a2), [`19aa47e`](https://github.com/Effect-TS/effect-smol/commit/19aa47ef7b470e427620edca8970dd9cdd551216), [`c667dad`](https://github.com/Effect-TS/effect-smol/commit/c667dad07777b860e4764a3ba9a6cc41c236cd98), [`764d150`](https://github.com/Effect-TS/effect-smol/commit/764d1501bc5026b60fc8aef6cb02a5a87c762801), [`3c27098`](https://github.com/Effect-TS/effect-smol/commit/3c27098b5685a63db2c2eff654a250c94d3fcfa7)]:
- effect@4.0.0-beta.35
## 4.0.0-beta.34
### Patch Changes
- [#1759](https://github.com/Effect-TS/effect-smol/pull/1759) [`8feecd2`](https://github.com/Effect-TS/effect-smol/commit/8feecd24158f254ca0571a1ddb554b560ed3177d) Thanks @tim-smart! - Ensure OpenAiSocket sends a `{"type":"response.cancel"}` websocket event when a response stream is interrupted.
- [#1764](https://github.com/Effect-TS/effect-smol/pull/1764) [`342fc4b`](https://github.com/Effect-TS/effect-smol/commit/342fc4b051739e32e7977159f26ff9541eda664f) Thanks @tim-smart! - Add unstable EmbeddingModel support across core and OpenAI providers.
- Add the unstable EmbeddingModel module API surface in `effect`, including service, request, response, and provider types.
- Implement the unstable EmbeddingModel runtime constructor in `effect`, with `RequestResolver` batching, `embed` / `embedMany` spans, provider error propagation, deterministic ordering, and empty-input `embedMany` fast-path behavior.
- Add and align EmbeddingModel behavior tests in `effect` for embedding usage, batching, ordering, and error handling.
- Add `OpenAiEmbeddingModel` in `@effect/ai-openai`, including model / make / layer constructors, config overrides, and provider output index validation with deterministic reordering.
- Add OpenAI-compatible EmbeddingModel provider support in `@effect/ai-openai-compat`, including config overrides, layer constructors, and output index validation.
- [#1771](https://github.com/Effect-TS/effect-smol/pull/1771) [`00add69`](https://github.com/Effect-TS/effect-smol/commit/00add69b59551e9df34772eb927638b093f6d71e) Thanks @tim-smart! - Add `EmbeddingModel.ModelDimensions` and require dimensions in embedding provider `model` constructors.
- [#1765](https://github.com/Effect-TS/effect-smol/pull/1765) [`f4e2aba`](https://github.com/Effect-TS/effect-smol/commit/f4e2aba01b76d1e3059b297e3cc942284dfeafb2) Thanks @tim-smart! - retry incremental prompt on invalid request
- [#1760](https://github.com/Effect-TS/effect-smol/pull/1760) [`273f4c6`](https://github.com/Effect-TS/effect-smol/commit/273f4c6517f5adc4994734a46698c52015890d1a) Thanks @tim-smart! - handle openai ws error events
- Updated dependencies [[`f2f75ee`](https://github.com/Effect-TS/effect-smol/commit/f2f75ee564bce1cd95f5189c7bdeeed4f92dacb1), [`342fc4b`](https://github.com/Effect-TS/effect-smol/commit/342fc4b051739e32e7977159f26ff9541eda664f), [`5d704ee`](https://github.com/Effect-TS/effect-smol/commit/5d704ee10d20e8eb107e34bb8a21feb5aa4a7685), [`00add69`](https://github.com/Effect-TS/effect-smol/commit/00add69b59551e9df34772eb927638b093f6d71e), [`58217d3`](https://github.com/Effect-TS/effect-smol/commit/58217d318a7d716ccd707cce0f41573946939c28), [`f4e2aba`](https://github.com/Effect-TS/effect-smol/commit/f4e2aba01b76d1e3059b297e3cc942284dfeafb2), [`e3b44b6`](https://github.com/Effect-TS/effect-smol/commit/e3b44b6a2af9ee21dc5c1e928f0c20af857fa7a9), [`e1472b7`](https://github.com/Effect-TS/effect-smol/commit/e1472b7525c5d57a48bdec2353c3b742f7f916c0), [`7686320`](https://github.com/Effect-TS/effect-smol/commit/7686320cd123fa352b5c3d076fb18a3cac0a9bba)]:
- effect@4.0.0-beta.34
## 4.0.0-beta.33
### Patch Changes
- [#1638](https://github.com/Effect-TS/effect-smol/pull/1638) [`e198fea`](https://github.com/Effect-TS/effect-smol/commit/e198fea76c89a36c6f05ea7b7d11d222cf5a240c) Thanks @tim-smart! - add OpenAiClient.withWebSocketMode
- Updated dependencies [[`571447d`](https://github.com/Effect-TS/effect-smol/commit/571447da67334449f8ae3d6ecb3d77ea4e0c4295)]:
- effect@4.0.0-beta.33
## 4.0.0-beta.32
### Patch Changes
- Updated dependencies [[`bf8fff8`](https://github.com/Effect-TS/effect-smol/commit/bf8fff8a5f54b6df74cb7bbb42346fe9ba52435a), [`1af3ef3`](https://github.com/Effect-TS/effect-smol/commit/1af3ef3e3ca7fd417d0fc15f8ca8fe207eba4f74), [`27fea0f`](https://github.com/Effect-TS/effect-smol/commit/27fea0f66910de5905f40fd63f8ddbb6f7ac5aba), [`2ad6c1b`](https://github.com/Effect-TS/effect-smol/commit/2ad6c1b2c85a3a0fe351e3d56636a75eb76b4b4e), [`398ac3e`](https://github.com/Effect-TS/effect-smol/commit/398ac3e01cb75efce0e4e2913d1450cf65866732), [`51fe22f`](https://github.com/Effect-TS/effect-smol/commit/51fe22f3266e417b6c541aaed4b75d246fac91e7), [`4605db6`](https://github.com/Effect-TS/effect-smol/commit/4605db69cfacddbdbf1525865ddfde135158090c), [`f4de1b0`](https://github.com/Effect-TS/effect-smol/commit/f4de1b087c998d0bad1d9468f70b7d16c13b9f6f), [`60214f2`](https://github.com/Effect-TS/effect-smol/commit/60214f2080b2aeb091f691140eb20acb741691c3), [`c4b8b0f`](https://github.com/Effect-TS/effect-smol/commit/c4b8b0ffa8efb47c4cd7578a8943d6868509373f), [`6d9393a`](https://github.com/Effect-TS/effect-smol/commit/6d9393a0770a18722d23340e77f15455de341245), [`6de4efe`](https://github.com/Effect-TS/effect-smol/commit/6de4efe463c783614ceb0c094d77a336a899cbe0), [`4f969d1`](https://github.com/Effect-TS/effect-smol/commit/4f969d1563ba755ffa116c8ae409bb3436bd881d), [`6cc67c8`](https://github.com/Effect-TS/effect-smol/commit/6cc67c855e054ee3f3ac3485dca5f7805e79e8fb), [`8531a22`](https://github.com/Effect-TS/effect-smol/commit/8531a22ffbb52e11a030b09f358cafbfdf5edff7), [`b226760`](https://github.com/Effect-TS/effect-smol/commit/b22676067617f15c00722a3a63fd7c2c172c3d45), [`47a51ab`](https://github.com/Effect-TS/effect-smol/commit/47a51aba0ecdf3ef478bfa28a498bca188399bd4), [`1521d02`](https://github.com/Effect-TS/effect-smol/commit/1521d02e1f19f1d795edaaf862c1a1031d9c755e)]:
- effect@4.0.0-beta.32
## 4.0.0-beta.31
### Patch Changes
- Updated dependencies [[`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6f23f0e`](https://github.com/Effect-TS/effect-smol/commit/6f23f0ed4cba573cd9395c2e582f582fe7271544), [`654aaec`](https://github.com/Effect-TS/effect-smol/commit/654aaec593305521b65dd042c204d761cc6e8c28), [`2958a42`](https://github.com/Effect-TS/effect-smol/commit/2958a42078966a8713a98f00485ab36484d5eccf), [`95d27a2`](https://github.com/Effect-TS/effect-smol/commit/95d27a239ed5147302605ab0b3147a056541b0c7), [`0fbaea8`](https://github.com/Effect-TS/effect-smol/commit/0fbaea8f9555a8044cec31a770394db613fc78e2), [`21d5d5e`](https://github.com/Effect-TS/effect-smol/commit/21d5d5e0439fd4d9bb6e508377215b1087555d45), [`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6e49959`](https://github.com/Effect-TS/effect-smol/commit/6e499590357a104c81779b3176cd3f84e4f91064), [`8f5805d`](https://github.com/Effect-TS/effect-smol/commit/8f5805dbdd0d1bc0ff0727cc398c8d80e544edee), [`990df2c`](https://github.com/Effect-TS/effect-smol/commit/990df2c3ceeb32e659acc10cc9485617f7b3c423)]:
- effect@4.0.0-beta.31
## 4.0.0-beta.30
### Patch Changes
- [#1679](https://github.com/Effect-TS/effect-smol/pull/1679) [`d440fd4`](https://github.com/Effect-TS/effect-smol/commit/d440fd4e79f5943998249f5e67fb42505bd20228) Thanks @tim-smart! - Add support for OpenAI `keepalive` response stream events.
- Updated dependencies [[`c88e5b7`](https://github.com/Effect-TS/effect-smol/commit/c88e5b723ff09da4edaef6ce14d927ca01104a32), [`947d0e4`](https://github.com/Effect-TS/effect-smol/commit/947d0e4268ba5c4020ead380aa80812c7342408f), [`7517908`](https://github.com/Effect-TS/effect-smol/commit/75179085d159b88a1ab0bce70669d76dcf0d79a4), [`a49ecd5`](https://github.com/Effect-TS/effect-smol/commit/a49ecd5a183d7e7d33f47ff95e9d2dea5a12ead5), [`6993e33`](https://github.com/Effect-TS/effect-smol/commit/6993e3329122c834c20bacea72d8678232f4f103), [`514f2a2`](https://github.com/Effect-TS/effect-smol/commit/514f2a2ae54580fcacdbe2ea2196a83a852d0748), [`3214b47`](https://github.com/Effect-TS/effect-smol/commit/3214b47676de2d33fddc5fecfc2d226e6e83cc7b), [`95ec5ed`](https://github.com/Effect-TS/effect-smol/commit/95ec5ed345de77c893049e182d37a37cf164a268)]:
- effect@4.0.0-beta.30
## 4.0.0-beta.29
### Patch Changes
- Updated dependencies [[`9d93adb`](https://github.com/Effect-TS/effect-smol/commit/9d93adb1c1795d1978391b30d7d2972c88052662), [`b52721c`](https://github.com/Effect-TS/effect-smol/commit/b52721cf0d11a567722b060c8536e3bdd4161f07), [`a891c7b`](https://github.com/Effect-TS/effect-smol/commit/a891c7b12f415b2287613dd4b91a09dfd38ef30d), [`ef26cdf`](https://github.com/Effect-TS/effect-smol/commit/ef26cdfb65d9955fc7e161629191930c2cc2c63f), [`82fd3ed`](https://github.com/Effect-TS/effect-smol/commit/82fd3ed922063ee5a34f96f3993c15c7515e4f67)]:
- effect@4.0.0-beta.29
## 4.0.0-beta.28
### Patch Changes
- Updated dependencies [[`ff533f2`](https://github.com/Effect-TS/effect-smol/commit/ff533f203cd06302ad08032a27e01269b4a2d4c6), [`dc803ee`](https://github.com/Effect-TS/effect-smol/commit/dc803ee52ebd3e9f931118f0dfcb804542847556), [`d660b1c`](https://github.com/Effect-TS/effect-smol/commit/d660b1c99cb93d4f79715e91c7a4486801c0eefa), [`93a05e3`](https://github.com/Effect-TS/effect-smol/commit/93a05e3eaa624058b162aedd66aad70102837270), [`2a65cf6`](https://github.com/Effect-TS/effect-smol/commit/2a65cf6fd81ef63d944e6fb51f058d439bf4a834), [`a561a40`](https://github.com/Effect-TS/effect-smol/commit/a561a40cc41c548c2cf3153aca065ee92ee8aa57), [`29cd24d`](https://github.com/Effect-TS/effect-smol/commit/29cd24d1fe78480a72eeb38a90281ffddc0530bc), [`662a8e6`](https://github.com/Effect-TS/effect-smol/commit/662a8e6857dac64a7cd13bd8df4b0674654622f8), [`d2b52ba`](https://github.com/Effect-TS/effect-smol/commit/d2b52bae5b9336cf59729fbdcc4d7f09512b0cbf), [`407c3b4`](https://github.com/Effect-TS/effect-smol/commit/407c3b43a5d1414558e0e33b6f1fc0e6a6d489cc), [`42bc7ce`](https://github.com/Effect-TS/effect-smol/commit/42bc7ce5480f6f2953c39f8cb5c850d61df6f5a2), [`e741322`](https://github.com/Effect-TS/effect-smol/commit/e74132226cbfee24234311c7c1c13e6b7391384e), [`5c75fa8`](https://github.com/Effect-TS/effect-smol/commit/5c75fa8fb71163bc4c035ba1a215574dfd4badfc), [`747177b`](https://github.com/Effect-TS/effect-smol/commit/747177b0602f12d4461a843e953dfdffbeb0a429), [`326cd48`](https://github.com/Effect-TS/effect-smol/commit/326cd4828bce573fe985f35152155464bf4c5a70), [`627e922`](https://github.com/Effect-TS/effect-smol/commit/627e922b8d1e9521eae5e1caa5d667ad00b1619a), [`662287e`](https://github.com/Effect-TS/effect-smol/commit/662287e9abc76c941ccc2ee330aa07904d571341)]:
- effect@4.0.0-beta.28
## 4.0.0-beta.27
### Patch Changes
- Updated dependencies [[`903a839`](https://github.com/Effect-TS/effect-smol/commit/903a839e94239e6ec4568315af28e405bcad95f4), [`91a0168`](https://github.com/Effect-TS/effect-smol/commit/91a016836680a6669308ecf464d3584bcc4ae1b7), [`c890f9a`](https://github.com/Effect-TS/effect-smol/commit/c890f9a1b3a989ed22528bd5a43326342e05b142), [`1e985f2`](https://github.com/Effect-TS/effect-smol/commit/1e985f237d250b51b91de22dde77160c1e778ce7)]:
- effect@4.0.0-beta.27
## 4.0.0-beta.26
### Patch Changes
- Updated dependencies [[`fb21462`](https://github.com/Effect-TS/effect-smol/commit/fb21462642cdd5b1bada92f3eba18ae20445be42), [`2ed26b1`](https://github.com/Effect-TS/effect-smol/commit/2ed26b139805700e3df39efaa768ff01565e5c86), [`e832a57`](https://github.com/Effect-TS/effect-smol/commit/e832a57b570fe38f010c1fd99bceac5a325a9e07), [`7f01be7`](https://github.com/Effect-TS/effect-smol/commit/7f01be7f8db363d4b2e88e6b5571e96bb815786f), [`e965143`](https://github.com/Effect-TS/effect-smol/commit/e9651431e114479e6becf8ca7b1ed99ac7e91ccc), [`b9b80f1`](https://github.com/Effect-TS/effect-smol/commit/b9b80f1f15e152ceef0a727d150b7dc230abae99), [`98252aa`](https://github.com/Effect-TS/effect-smol/commit/98252aa0c0b17fc73fbdad65d0a1104965f9fc0f), [`56fbd94`](https://github.com/Effect-TS/effect-smol/commit/56fbd94311ad19a05001ad649d9e34ab00c74541), [`3faa109`](https://github.com/Effect-TS/effect-smol/commit/3faa109b7d093fbf14ad410d3e11d663f16e28f1), [`692ecfe`](https://github.com/Effect-TS/effect-smol/commit/692ecfed99fe58056b7a5afe001f4fcd1a61c446), [`1e70b72`](https://github.com/Effect-TS/effect-smol/commit/1e70b72d0b210474d0e96a15a5cfc279eae37e0c), [`ecf0782`](https://github.com/Effect-TS/effect-smol/commit/ecf07829ef2dfc01d8943c96c4fe9c1b44b97926)]:
- effect@4.0.0-beta.26
## 4.0.0-beta.25
### Patch Changes
- Updated dependencies [[`fa17bb5`](https://github.com/Effect-TS/effect-smol/commit/fa17bb5be9f2533d01e11322b14804c7dec43714), [`f46e5b5`](https://github.com/Effect-TS/effect-smol/commit/f46e5b5ca2a918ee4d9270167e79db223077c96f), [`ce4767c`](https://github.com/Effect-TS/effect-smol/commit/ce4767cadcacc6ce8ff4c3a0d0fbc82ede655f63), [`c830a8b`](https://github.com/Effect-TS/effect-smol/commit/c830a8b6c292a6528d7f9318759d34800b00372d)]:
- effect@4.0.0-beta.25
## 4.0.0-beta.24
### Patch Changes
- Updated dependencies [[`a909e1c`](https://github.com/Effect-TS/effect-smol/commit/a909e1c1ac2bc707527f5073776e3e7d239688d9), [`8814a4e`](https://github.com/Effect-TS/effect-smol/commit/8814a4ef78d67144d27689370af10099ea210399), [`3f942c5`](https://github.com/Effect-TS/effect-smol/commit/3f942c51cefa7b2ffa7c49e8c8a2c887570ba4c0), [`774ed59`](https://github.com/Effect-TS/effect-smol/commit/774ed59c52b2ab578bbb897c4f551f812231e1d2), [`f54b8d3`](https://github.com/Effect-TS/effect-smol/commit/f54b8d398fedad1815fd1f4c49814ab938cfc385)]:
- effect@4.0.0-beta.24
## 4.0.0-beta.23
### Patch Changes
- Updated dependencies [[`5c73c41`](https://github.com/Effect-TS/effect-smol/commit/5c73c41b69eaeab80fcd62c9bfda490b446d1966)]:
- effect@4.0.0-beta.23
## 4.0.0-beta.22
### Patch Changes
- Updated dependencies [[`0874332`](https://github.com/Effect-TS/effect-smol/commit/0874332f7c81118b06ac2eb105e0710211631479), [`c592dcd`](https://github.com/Effect-TS/effect-smol/commit/c592dcde0697e322065c8f418c0480ef910cb183), [`1dbe28d`](https://github.com/Effect-TS/effect-smol/commit/1dbe28dac8299cd3e218c9768450cfd173b5e294), [`564d730`](https://github.com/Effect-TS/effect-smol/commit/564d730b6bbf38dd8548a3b046e7a693b28699a4), [`3cfadc4`](https://github.com/Effect-TS/effect-smol/commit/3cfadc458b070c6cba6c5674b72a059f1e49118b), [`6634fd0`](https://github.com/Effect-TS/effect-smol/commit/6634fd07da067d80b8261fb2959d1a952b9e412e), [`d10dabe`](https://github.com/Effect-TS/effect-smol/commit/d10dabeb7af9a368f995829cd36ad08167cd8f95), [`f82f549`](https://github.com/Effect-TS/effect-smol/commit/f82f549a09e950e9d4987f279a800f4d953f0939), [`78a3382`](https://github.com/Effect-TS/effect-smol/commit/78a3382ddfbe034408f7480fa794733d9e82147b)]:
- effect@4.0.0-beta.22
## 4.0.0-beta.21
### Patch Changes
- Updated dependencies [[`e691909`](https://github.com/Effect-TS/effect-smol/commit/e691909495ccb162ea7bfa351dd74632b99997cb), [`d5f413f`](https://github.com/Effect-TS/effect-smol/commit/d5f413f3c8fc57f2413cc5649c2003d6d4e5a6d7), [`139d152`](https://github.com/Effect-TS/effect-smol/commit/139d152941e562a073b5be12e8d66c8a4d4a8a57), [`947e3d4`](https://github.com/Effect-TS/effect-smol/commit/947e3d436ab8a017efda9b29be523efd1ca8df28), [`84b2cce`](https://github.com/Effect-TS/effect-smol/commit/84b2ccefe2aa3a7413b86738a4dc33cdb311ca55), [`7f5305e`](https://github.com/Effect-TS/effect-smol/commit/7f5305e69f5a33309e77b08a576edb25d7daaee2), [`9e6fd84`](https://github.com/Effect-TS/effect-smol/commit/9e6fd8471c93a3c643929151a3bdb62cb9c0ca0e), [`fdb8a4b`](https://github.com/Effect-TS/effect-smol/commit/fdb8a4b172721fbefe98bd5aa6fe4f0efd1da3eb), [`0f986ef`](https://github.com/Effect-TS/effect-smol/commit/0f986ef22f196fe091a7afdbd179485a7d888882), [`9355fc0`](https://github.com/Effect-TS/effect-smol/commit/9355fc0ffb5b7382146a5aed9eea83974b10d007)]:
- effect@4.0.0-beta.21
## 4.0.0-beta.20
### Patch Changes
- [#1529](https://github.com/Effect-TS/effect-smol/pull/1529) [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8) Thanks @tim-smart! - Add dedicated AiError metadata interfaces per reason so provider packages can safely augment metadata without conflicting module declarations.
- [#1528](https://github.com/Effect-TS/effect-smol/pull/1528) [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34) Thanks @tim-smart! - Add `Model.ModelName` and provide it from AI model constructors.
- Updated dependencies [[`842a624`](https://github.com/Effect-TS/effect-smol/commit/842a624f79d5e1407460b0ef3ab27d14d48ccf74), [`4785eef`](https://github.com/Effect-TS/effect-smol/commit/4785eef5d7cf1edb96ef2509aed2ba4d1edf3862), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`12ee8e2`](https://github.com/Effect-TS/effect-smol/commit/12ee8e27df7eb393d83a5e403390d0cfc82ca732), [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34), [`989d1cc`](https://github.com/Effect-TS/effect-smol/commit/989d1cca936fce0cc459057825ba40e3f5ef3827)]:
- effect@4.0.0-beta.20
## 4.0.0-beta.19
### Patch Changes
- [#1522](https://github.com/Effect-TS/effect-smol/pull/1522) [`19984c2`](https://github.com/Effect-TS/effect-smol/commit/19984c2c1b23ef06d69f9bbd4c4ad992a03c6860) Thanks @IMax153! - Fix missing `yield*` in `OpenAiLanguageModel.prepareResponseFormat`
- Updated dependencies []:
- effect@4.0.0-beta.19
## 4.0.0-beta.18
### Patch Changes
- [#1520](https://github.com/Effect-TS/effect-smol/pull/1520) [`725260b`](https://github.com/Effect-TS/effect-smol/commit/725260b53f5142d6af7a93a2f9f464f974eda92d) Thanks @IMax153! - Ensure that OpenAI JSON schemas for tool calls and structured outputs are properly transformed
- Updated dependencies [[`01e31fd`](https://github.com/Effect-TS/effect-smol/commit/01e31fdf8e5206849d23cbafd23a346f2f177ab8), [`0890aab`](https://github.com/Effect-TS/effect-smol/commit/0890aab15ed9c5ba52c383a72fdc6a444d7504d5), [`725260b`](https://github.com/Effect-TS/effect-smol/commit/725260b53f5142d6af7a93a2f9f464f974eda92d)]:
- effect@4.0.0-beta.18
## 4.0.0-beta.17
### Patch Changes
- Updated dependencies [[`8f59c32`](https://github.com/Effect-TS/effect-smol/commit/8f59c32922597a48392744f7203e284866747781)]:
- effect@4.0.0-beta.17
## 4.0.0-beta.16
### Patch Changes
- Updated dependencies [[`bf9096c`](https://github.com/Effect-TS/effect-smol/commit/bf9096c52a7d8791d93d232739e523eb84f6625a), [`29f81ca`](https://github.com/Effect-TS/effect-smol/commit/29f81ca07c67dba265804b140a7487fb15a5fc6b), [`68eb28c`](https://github.com/Effect-TS/effect-smol/commit/68eb28c2b0fc67a9f6204ade9bd16c5b37803bfb)]:
- effect@4.0.0-beta.16
## 4.0.0-beta.15
### Patch Changes
- [#1502](https://github.com/Effect-TS/effect-smol/pull/1502) [`285b7e6`](https://github.com/Effect-TS/effect-smol/commit/285b7e667167566d5788367d5155b19c79f1bf22) Thanks @tim-smart! - allow undefined for ai config
- Updated dependencies [[`24ae609`](https://github.com/Effect-TS/effect-smol/commit/24ae60995d2fd7d621be356cdfdfd328c79639ba), [`0e3c059`](https://github.com/Effect-TS/effect-smol/commit/0e3c059987caa55ebd0c134f7c7b147c639c328e), [`e843b0a`](https://github.com/Effect-TS/effect-smol/commit/e843b0a7d7e7b600a0b3bd477f24e2e4cd26bc8b), [`f4389a2`](https://github.com/Effect-TS/effect-smol/commit/f4389a2cca3c5bbf00d69779f52ce41255f15a28), [`5b73de0`](https://github.com/Effect-TS/effect-smol/commit/5b73de095b3402d0c5c74092ace6ce18ebfad566), [`595d2d6`](https://github.com/Effect-TS/effect-smol/commit/595d2d6e7d50419f3532bd39266191532ace38f2)]:
- effect@4.0.0-beta.15
## 4.0.0-beta.14
### Patch Changes
- Updated dependencies [[`c414700`](https://github.com/Effect-TS/effect-smol/commit/c414700ef1932e4b67d0102856de417336912350), [`a30c969`](https://github.com/Effect-TS/effect-smol/commit/a30c9699c0d736cf3952041e45d508b7d58907a9)]:
- effect@4.0.0-beta.14
## 4.0.0-beta.13
### Patch Changes
- Updated dependencies [[`368f4c3`](https://github.com/Effect-TS/effect-smol/commit/368f4c363dd117e6f5a19ad77b161176cfd29fdd), [`db8a579`](https://github.com/Effect-TS/effect-smol/commit/db8a579e93e93ff73b1e60712732e03b597b916b), [`668b703`](https://github.com/Effect-TS/effect-smol/commit/668b70337e9ddbb0d1ae2282a95c282ce404e562), [`d40e76b`](https://github.com/Effect-TS/effect-smol/commit/d40e76b973543979e60e04a6baca04a8c65bdfc2), [`6e18cf8`](https://github.com/Effect-TS/effect-smol/commit/6e18cf883e9905ca718a6697b6a2a4bbd42739aa), [`86062e8`](https://github.com/Effect-TS/effect-smol/commit/86062e8a0c61bca5412fc40d2cf151d676901f08), [`c27ce75`](https://github.com/Effect-TS/effect-smol/commit/c27ce75d34c74dcfc6dba1bf77f1ce88f410a0de), [`e2d4fbf`](https://github.com/Effect-TS/effect-smol/commit/e2d4fbfeeda6a5d2a4c5aeb0501d8240c248b9eb), [`114ab42`](https://github.com/Effect-TS/effect-smol/commit/114ab42ad0edc590d29169675a493e0e915aa58f), [`484caec`](https://github.com/Effect-TS/effect-smol/commit/484caec47cccac8b86db2910742e406dfc7173ab)]:
- effect@4.0.0-beta.13
## 4.0.0-beta.12
### Patch Changes
- Updated dependencies [[`70a74e8`](https://github.com/Effect-TS/effect-smol/commit/70a74e88a8767c9d4acdb9e5f25aec9a33588d07), [`b5b6e10`](https://github.com/Effect-TS/effect-smol/commit/b5b6e10621d54bf8c9857fec0d647ced78ecd857), [`f5ce5a9`](https://github.com/Effect-TS/effect-smol/commit/f5ce5a915359c6ebf254079e1da23cab6cde34fb), [`a29eb70`](https://github.com/Effect-TS/effect-smol/commit/a29eb702ffe3fc58bd28c4d7857298cd65d73668), [`c7b36e5`](https://github.com/Effect-TS/effect-smol/commit/c7b36e541a23e9a00f64e25b23851e51a37dfce5), [`9381d6d`](https://github.com/Effect-TS/effect-smol/commit/9381d6d4d9d819a81a46e56d0364c76e92a4fbca), [`88439f1`](https://github.com/Effect-TS/effect-smol/commit/88439f13ca13549f3e4822c48c4f019c14fc2bcc), [`e35307d`](https://github.com/Effect-TS/effect-smol/commit/e35307dbeb8eb26a9923f958b894a8eaaf259bf2), [`c7df4bc`](https://github.com/Effect-TS/effect-smol/commit/c7df4bce34009474c63d62a807abfdafb76971eb), [`accaf3b`](https://github.com/Effect-TS/effect-smol/commit/accaf3be7ac8da36e2334c509c23b8c9e88ea160), [`3e1c270`](https://github.com/Effect-TS/effect-smol/commit/3e1c2707bbdf67720af1509642b8ced195790882), [`6cd81f7`](https://github.com/Effect-TS/effect-smol/commit/6cd81f73baad86f5bbfa455a55d75cde71e9611a), [`f222da3`](https://github.com/Effect-TS/effect-smol/commit/f222da3cdb44554f3324c2c52d0d005ee575053e), [`61f901d`](https://github.com/Effect-TS/effect-smol/commit/61f901d830005b66e22d1de889fda132aeea97cd)]:
- effect@4.0.0-beta.12
## 4.0.0-beta.11
### Patch Changes
- Updated dependencies [[`88659ed`](https://github.com/Effect-TS/effect-smol/commit/88659edb26e3623d557dccfe914c2c949672da16), [`f2915e8`](https://github.com/Effect-TS/effect-smol/commit/f2915e8e2efe80d50c281e53f297b9701d6dc199), [`eb71ace`](https://github.com/Effect-TS/effect-smol/commit/eb71acebbe0f228e4920278013beee3b67d62310), [`2a16999`](https://github.com/Effect-TS/effect-smol/commit/2a169996c7513d377ac47adbfd68e1490457135c), [`d42dd52`](https://github.com/Effect-TS/effect-smol/commit/d42dd52f11203f8e749fb5d3ecf7153e4a5a6814), [`339adaf`](https://github.com/Effect-TS/effect-smol/commit/339adaf850a62a892adebcb208c2d9dddf3b97b3), [`de19645`](https://github.com/Effect-TS/effect-smol/commit/de1964526d01102dd1cb99c8cfdd3e8df1f49ef1), [`9b1dc3b`](https://github.com/Effect-TS/effect-smol/commit/9b1dc3bcf2a1b68d0a67e3465db5ad01a1a56997), [`e4cb2f5`](https://github.com/Effect-TS/effect-smol/commit/e4cb2f55b30f4771ec1bf613ced36d6d96464dd5), [`8bced95`](https://github.com/Effect-TS/effect-smol/commit/8bced954ecb35d4489197a57b0efe927e7d75f49), [`9431420`](https://github.com/Effect-TS/effect-smol/commit/94314207c8019918200fbcb97aec992219f801f0), [`948dca2`](https://github.com/Effect-TS/effect-smol/commit/948dca22e4f672ba7a6db57f9899272bec7c08b8), [`d18e327`](https://github.com/Effect-TS/effect-smol/commit/d18e32765a2665e31ffb31e746bf983fcfac34c5), [`ab512f7`](https://github.com/Effect-TS/effect-smol/commit/ab512f7be1c0e6b359da921e22cd4944e4c57d3e)]:
- effect@4.0.0-beta.11
## 4.0.0-beta.10
### Patch Changes
- Updated dependencies [[`371acab`](https://github.com/Effect-TS/effect-smol/commit/371acabb58d56f3a7a5e3e33d3d5fdc9f5573c74), [`856d774`](https://github.com/Effect-TS/effect-smol/commit/856d7741f1e296dd5048c6ff2b44b95d023e6ae4), [`b9e9202`](https://github.com/Effect-TS/effect-smol/commit/b9e92023c38caa322975d77cfe83e2d34ac9305a), [`1d1a974`](https://github.com/Effect-TS/effect-smol/commit/1d1a974bd280c81bff5d4505491cda03ba7a3f36), [`6bfe2a6`](https://github.com/Effect-TS/effect-smol/commit/6bfe2a659bc6335db75709931f405da45301cba2), [`b12c811`](https://github.com/Effect-TS/effect-smol/commit/b12c81157be287b1649c210616a244b50ec094d2), [`d17d98a`](https://github.com/Effect-TS/effect-smol/commit/d17d98ad78e2b44d95ef434adab79ac3c35e75ab), [`68c3c7c`](https://github.com/Effect-TS/effect-smol/commit/68c3c7cb1e06ed94fa5c4c123a234b4ccbfdecd8)]:
- effect@4.0.0-beta.10
## 4.0.0-beta.9
### Patch Changes
- Updated dependencies [[`3386557`](https://github.com/Effect-TS/effect-smol/commit/338655731564a7be9f8859dedbf4d5bcac6eb350), [`b6666e3`](https://github.com/Effect-TS/effect-smol/commit/b6666e3cf6bd44ba1a8704e65c256c30359cb422)]:
- effect@4.0.0-beta.9
## 4.0.0-beta.8
### Patch Changes
- [#1354](https://github.com/Effect-TS/effect-smol/pull/1354) [`b94962c`](https://github.com/Effect-TS/effect-smol/commit/b94962c249d46cf96cdf2e41188dc9feda41536a) Thanks @IMax153! - Fix the generated schemas for ai providers
- Updated dependencies [[`246e672`](https://github.com/Effect-TS/effect-smol/commit/246e672dbbd7848d60e0c78fd66671b2f10b3752), [`807dec0`](https://github.com/Effect-TS/effect-smol/commit/807dec03801b4c58a6d00c237b6d98d6386911df)]:
- effect@4.0.0-beta.8
## 4.0.0-beta.7
### Patch Changes
- Updated dependencies [[`a2bda6d`](https://github.com/Effect-TS/effect-smol/commit/a2bda6d4ef6de9d9b0c53ae2df5434f778d6161a), [`1f95a2b`](https://github.com/Effect-TS/effect-smol/commit/1f95a2b5aa9524bb38f4437f4691a664bf463ca1), [`a8d5e79`](https://github.com/Effect-TS/effect-smol/commit/a8d5e792fec201a83af0eb92fc79928d055125fd), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`06d8a03`](https://github.com/Effect-TS/effect-smol/commit/06d8a0391631e6130e3ab25227e59817852e227f), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`f9e883e`](https://github.com/Effect-TS/effect-smol/commit/f9e883e266fbda870336ee62f46b7ac85ba3de6e), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430)]:
- effect@4.0.0-beta.7
## 4.0.0-beta.6
### Patch Changes
- Updated dependencies [[`3247da2`](https://github.com/Effect-TS/effect-smol/commit/3247da28331f345f68be5dbd2974a7e03d300fe1), [`f205705`](https://github.com/Effect-TS/effect-smol/commit/f2057050dbd034b8c186be2d40c3d03ee63a5a3b), [`f35022c`](https://github.com/Effect-TS/effect-smol/commit/f35022c212e4111527e1bb43f360a67b2b49fa85), [`8622721`](https://github.com/Effect-TS/effect-smol/commit/86227217b02d43680a3c6f3c21731b1d852c91f5), [`fc660ab`](https://github.com/Effect-TS/effect-smol/commit/fc660ab8b5ebae38b8d6b96cbf2f9b880cc09253), [`f37dc33`](https://github.com/Effect-TS/effect-smol/commit/f37dc335f64622fa9ce8d6d1d5dd8fc3f260257b), [`3662f32`](https://github.com/Effect-TS/effect-smol/commit/3662f328fcfa3b2fa01ffa79da40e12e93fcede8), [`a7d436f`](https://github.com/Effect-TS/effect-smol/commit/a7d436f438dcd7f49b9485e4e95a4511f31fad7d), [`6856a41`](https://github.com/Effect-TS/effect-smol/commit/6856a415d7eddd9d73d60919e976f1d071421be4), [`8c417d0`](https://github.com/Effect-TS/effect-smol/commit/8c417d03475e5e12d00dca0c4781d0af7e66b86c), [`5419570`](https://github.com/Effect-TS/effect-smol/commit/5419570ba47ce882a3a10882707b46f66e464906), [`449c5ed`](https://github.com/Effect-TS/effect-smol/commit/449c5ed5318e8a874e730420bcf52918fa2ec80f), [`4b5ec12`](https://github.com/Effect-TS/effect-smol/commit/4b5ec12f87f95f2a3cd8fe4d5b26c6eb0529381a), [`df87937`](https://github.com/Effect-TS/effect-smol/commit/df879375fc3b169c43f9c434b3775e12b80dffe4), [`5dbfca8`](https://github.com/Effect-TS/effect-smol/commit/5dbfca8d1dbb6d18d1605d4f8562e99c86e2ff11), [`e629497`](https://github.com/Effect-TS/effect-smol/commit/e6294973d55597ab6b6deca6babbe1e946b2c91d), [`981c991`](https://github.com/Effect-TS/effect-smol/commit/981c991cd78db34def815d5754379d737157f005), [`1ca2ed6`](https://github.com/Effect-TS/effect-smol/commit/1ca2ed67301a5dc40ae0ed94346b99f26fd22bbe), [`45722bd`](https://github.com/Effect-TS/effect-smol/commit/45722bde974458311f11ad237711363a10ec6894), [`eb2a85e`](https://github.com/Effect-TS/effect-smol/commit/eb2a85ed4dc162b2535d304799333a5a20477fd0)]:
- effect@4.0.0-beta.6
## 4.0.0-beta.5
### Patch Changes
- Updated dependencies [[`f6e133e`](https://github.com/Effect-TS/effect-smol/commit/f6e133e9a16b32317bd09ff08c12b97a0ae44600), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8), [`a88e206`](https://github.com/Effect-TS/effect-smol/commit/a88e206e44dc66ca5a2b45bedc797877c5dbb083), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8)]:
- effect@4.0.0-beta.5
## 4.0.0-beta.4
### Patch Changes
- Updated dependencies [[`c5a18ef`](https://github.com/Effect-TS/effect-smol/commit/c5a18ef44171e3880bf983faee74529908974b32), [`bc6b885`](https://github.com/Effect-TS/effect-smol/commit/bc6b885b94d887a200657c0775dfa874dc15bc0c)]:
- effect@4.0.0-beta.4
## 4.0.0-beta.3
### Patch Changes
- Updated dependencies [[`3a0cf36`](https://github.com/Effect-TS/effect-smol/commit/3a0cf36eff106ba48d74e133c1598cd40613e530), [`c4da328`](https://github.com/Effect-TS/effect-smol/commit/c4da328d32fad1d61e0e538f5d371edf61521d7e)]:
- effect@4.0.0-beta.3
## 4.0.0-beta.2
### Patch Changes
- Updated dependencies [[`a22ce73`](https://github.com/Effect-TS/effect-smol/commit/a22ce73b2bd9305b7ba665694d2255c0e6d5a8d0), [`ebdabf7`](https://github.com/Effect-TS/effect-smol/commit/ebdabf79ff4e62c8384aa8cf9a8d2787d536ee78), [`8f663bb`](https://github.com/Effect-TS/effect-smol/commit/8f663bb121021bf12bd264e8ae385187cb7a5dae)]:
- effect@4.0.0-beta.2
## 4.0.0-beta.1
### Patch Changes
- Updated dependencies [[`0fecf70`](https://github.com/Effect-TS/effect-smol/commit/0fecf70048057623eed7c584a06671773a2b1743), [`709569e`](https://github.com/Effect-TS/effect-smol/commit/709569ed76bead9ebb0670599e4d890a07ca5a43)]:
- effect@4.0.0-beta.1
## 4.0.0-beta.0
### Major Changes
- [#1183](https://github.com/Effect-TS/effect-smol/pull/1183) [`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66) Thanks @tim-smart! - v4 beta
### Patch Changes
- Updated dependencies [[`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66)]:
- effect@4.0.0-beta.0

View File

@@ -0,0 +1,41 @@
# yaml-language-server: $schema=../../tools/ai-codegen/codegen.schema.json
spec: https://app.stainless.com/api/spec/documented/openai/openapi.documented.yml
output: src/Generated.ts
name: OpenAiClient
header: |
/**
* @since 1.0.0
*/
patches:
- '[{"op":"replace","path":"/openapi","value":"3.0.0"}]'
- '[{"op":"add","path":"/components/schemas/ModelResponseProperties/properties/user/nullable","value":true}]'
- '[{"op":"add","path":"/components/schemas/ModelResponseProperties/properties/safety_identifier/nullable","value":true}]'
- '[{"op":"add","path":"/components/schemas/ModelResponseProperties/properties/prompt_cache_key/nullable","value":true}]'
- '[{"op":"add","path":"/components/schemas/Response/allOf/2/properties/usage/nullable","value":true}]'
- '[{"op":"remove","path":"/components/schemas/ResponseFunctionCallArgumentsDoneEvent/required/2"}]'
- '[{"op":"remove","path":"/components/schemas/WebSearchActionSearch/required/1"}]'
- '[{"op":"add","path":"/components/schemas/ModelResponseProperties/properties/prompt_cache_retention/anyOf/0/enum/1","value":"in_memory"}]'
- '[{"op":"add","path":"/components/schemas/PromptCacheRetentionEnum/enum/1","value":"in-memory"}]'
- '[{"op":"replace","path":"/components/schemas/OpenAIFile/properties/expires_at","value":{"anyOf":[{"type":"integer","format":"unixtime","description":"The Unix timestamp (in seconds) for when the file will expire."},{"type":"null"}]}}]'
- '[{"op":"add","path":"/components/schemas/OpenAIFile/properties/status_details/nullable","value":true}]'
# Add missing keepalive stream event support
- '[{"op":"add","path":"/components/schemas/ResponseKeepAliveEvent","value":{"type":"object","title":"Keep alive","description":"A keepalive event emitted during long-running response streams.","properties":{"type":{"type":"string","enum":["keepalive"],"description":"The type of the keepalive event. Always `keepalive`.","default":"keepalive","x-stainless-const":true},"sequence_number":{"type":"integer","description":"The sequence number of this keepalive event."}},"required":["type","sequence_number"]}}]'
- '[{"op":"add","path":"/components/schemas/ResponseStreamEvent/anyOf/-","value":{"$ref":"#/components/schemas/ResponseKeepAliveEvent"}}]'
# Add missing ResponseApplyPatchCallOperationDiffDeltaEvent schema
- '[{"op":"add","path":"/components/schemas/ResponseApplyPatchCallOperationDiffDeltaEvent","value":{"title":"ResponseApplyPatchCallOperationDiffDelta","type":"object","description":"Event representing a delta for an apply_patch tool call operation diff.","properties":{"type":{"type":"string","enum":["response.apply_patch_call_operation_diff.delta"],"description":"The event type identifier.","x-stainless-const":true},"sequence_number":{"type":"integer","description":"The sequence number of this event."},"output_index":{"type":"integer","description":"The index of the output this delta applies to."},"item_id":{"type":"string","description":"Unique identifier for the API item associated with this event."},"delta":{"type":"string","description":"The incremental diff data for the apply_patch tool call."}},"required":["type","output_index","item_id","delta","sequence_number"]}}]'
# Add missing ResponseApplyPatchCallOperationDiffDoneEvent schema (delta is optional - not always sent by OpenAI)
- '[{"op":"add","path":"/components/schemas/ResponseApplyPatchCallOperationDiffDoneEvent","value":{"title":"ResponseApplyPatchCallOperationDiffDone","type":"object","description":"Event indicating that the operation diff for an apply_patch tool call is complete.","properties":{"type":{"type":"string","enum":["response.apply_patch_call_operation_diff.done"],"description":"The event type identifier.","x-stainless-const":true},"sequence_number":{"type":"integer","description":"The sequence number of this event."},"output_index":{"type":"integer","description":"The index of the output this event applies to."},"item_id":{"type":"string","description":"Unique identifier for the API item associated with this event."},"delta":{"type":"string","description":"The final diff data for the apply_patch tool call."}},"required":["type","output_index","item_id","sequence_number"]}}]'
# Add both events to ResponseStreamEvent anyOf array
- '[{"op":"add","path":"/components/schemas/ResponseStreamEvent/anyOf/-","value":{"$ref":"#/components/schemas/ResponseApplyPatchCallOperationDiffDeltaEvent"}}]'
- '[{"op":"add","path":"/components/schemas/ResponseStreamEvent/anyOf/-","value":{"$ref":"#/components/schemas/ResponseApplyPatchCallOperationDiffDoneEvent"}}]'
excludeAnnotations:
- examples
- default
disableAdditionalProperties: true
replacements:
# Schema.Unknown doesn't work with Schema.toCodecJson (used by HttpClientResponse.schemaBodyJson)
# Replace with Schema.Json which properly handles arbitrary JSON values
- from: "Schema.Record(Schema.String, Schema.Unknown)"
to: "Schema.Record(Schema.String, Schema.Json)"
- from: "{ readonly [x: string]: unknown }"
to: "{ readonly [x: string]: Schema.Json }"

View File

@@ -0,0 +1,23 @@
{
"$schema": "../../node_modules/@effect/docgen/schema.json",
"srcLink": "https://github.com/Effect-TS/effect/tree/main/packages/ai/openai/src/",
"exclude": ["src/Generated.ts", "src/internal/**/*.ts"],
"examplesCompilerOptions": {
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"rewriteRelativeImportExtensions": true,
"allowImportingTsExtensions": true,
"paths": {
"effect": ["../../../effect/src/index.js"],
"effect/*": ["../../../effect/src/*.js"]
},
"plugins": [
{ "name": "@effect/language-service", "includeSuggestionsInTsc": false }
]
}
}

View File

@@ -0,0 +1,66 @@
{
"name": "@effect/ai-openai",
"version": "4.0.0-beta.99",
"type": "module",
"license": "MIT",
"description": "An OpenAI provider integration for Effect AI SDK",
"homepage": "https://effect.website",
"repository": {
"type": "git",
"url": "https://github.com/Effect-TS/effect.git",
"directory": "packages/ai/openai"
},
"bugs": {
"url": "https://github.com/Effect-TS/effect/issues"
},
"tags": [
"typescript",
"ai",
"openai"
],
"keywords": [
"typescript",
"ai",
"openai"
],
"sideEffects": [],
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts",
"./*": "./src/*.ts",
"./internal/*": null,
"./*/index": null
},
"files": [
"src/**/*.ts",
"dist/**/*.js",
"dist/**/*.js.map",
"dist/**/*.d.ts",
"dist/**/*.d.ts.map"
],
"publishConfig": {
"access": "public",
"provenance": true,
"exports": {
"./package.json": "./package.json",
".": "./dist/index.js",
"./*": "./dist/*.js",
"./internal/*": null,
"./*/index": null
}
},
"scripts": {
"codegen": "effect-utils codegen",
"build": "tsc -b tsconfig.json && pnpm babel",
"babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
"check": "tsc -b tsconfig.json",
"test": "vitest",
"coverage": "vitest --coverage"
},
"devDependencies": {
"effect": "workspace:^"
},
"peerDependencies": {
"effect": "workspace:^"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,730 @@
/**
* The `OpenAiClient` module defines the low-level Effect service used by the
* OpenAI integration for Responses API and embedding requests. It builds a
* configured HTTP client with authentication and OpenAI organization or project
* headers, exposes helpers for non-streaming responses, SSE response streams,
* WebSocket response streams, and embeddings, and maps transport or decoding
* failures into `AiError`.
*
* @since 4.0.0
*/
import * as Array from "effect/Array"
import type * as Config from "effect/Config"
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { identity } from "effect/Function"
import * as Function from "effect/Function"
import * as Layer from "effect/Layer"
import * as Predicate from "effect/Predicate"
import * as Queue from "effect/Queue"
import * as RcRef from "effect/RcRef"
import * as Redacted from "effect/Redacted"
import * as Schema from "effect/Schema"
import * as Scope from "effect/Scope"
import * as Semaphore from "effect/Semaphore"
import * as Stream from "effect/Stream"
import * as AiError from "effect/unstable/ai/AiError"
import * as ResponseIdTracker from "effect/unstable/ai/ResponseIdTracker"
import * as Sse from "effect/unstable/encoding/Sse"
import * as Headers from "effect/unstable/http/Headers"
import * as HttpBody from "effect/unstable/http/HttpBody"
import * as HttpClient from "effect/unstable/http/HttpClient"
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
import * as Socket from "effect/unstable/socket/Socket"
import * as Errors from "./internal/errors.ts"
import { OpenAiConfig } from "./OpenAiConfig.ts"
import * as OpenAiSchema from "./OpenAiSchema.ts"
// =============================================================================
// Service Interface
// =============================================================================
/**
* Effect service interface for the handwritten OpenAI client.
*
* **Details**
*
* Provides the configured HTTP client plus helpers for Responses API calls, streaming Responses events, and embeddings. Transport and schema decoding failures are mapped to `AiError`.
*
* @category models
* @since 4.0.0
*/
export interface Service {
/**
* The transformed HTTP client used by this service.
*/
readonly client: HttpClient.HttpClient
/**
* Create a response using the OpenAI responses endpoint.
*/
readonly createResponse: (
options: typeof OpenAiSchema.CreateResponse.Encoded
) => Effect.Effect<
readonly [body: typeof OpenAiSchema.Response.Type, response: HttpClientResponse.HttpClientResponse],
AiError.AiError
>
/**
* Create a streaming response using the OpenAI responses endpoint.
*/
readonly createResponseStream: (
options: Omit<typeof OpenAiSchema.CreateResponse.Encoded, "stream">
) => Effect.Effect<
readonly [
response: HttpClientResponse.HttpClientResponse,
stream: Stream.Stream<typeof OpenAiSchema.ResponseStreamEvent.Type, AiError.AiError>
],
AiError.AiError
>
/**
* Create embeddings using the OpenAI embeddings endpoint.
*/
readonly createEmbedding: (
options: typeof OpenAiSchema.CreateEmbeddingRequest.Encoded
) => Effect.Effect<typeof OpenAiSchema.CreateEmbeddingResponse.Type, AiError.AiError>
}
// =============================================================================
// Service Identifier
// =============================================================================
/**
* Service tag for the OpenAI client.
*
* **When to use**
*
* Use when accessing or providing the OpenAI client service through Effect's
* context.
*
* @see {@link make} for constructing an OpenAI client effectfully
* @see {@link layer} for providing a client from explicit options
* @see {@link layerConfig} for providing a client from `Config`
*
* @category services
* @since 4.0.0
*/
export class OpenAiClient extends Context.Service<OpenAiClient, Service>()(
"@effect/ai-openai/OpenAiClient"
) {}
// =============================================================================
// Options
// =============================================================================
/**
* Options for configuring the OpenAI client.
*
* @category options
* @since 4.0.0
*/
export type Options = {
/**
* The OpenAI API key.
*/
readonly apiKey?: Redacted.Redacted<string> | undefined
/**
* The base URL for the OpenAI API.
*
* @default "https://api.openai.com/v1"
*/
readonly apiUrl?: string | undefined
/**
* Optional organization ID for multi-org accounts.
*/
readonly organizationId?: Redacted.Redacted<string> | undefined
/**
* Optional project ID for project-scoped requests.
*/
readonly projectId?: Redacted.Redacted<string> | undefined
/**
* Optional transformer for the HTTP client.
*/
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
}
// =============================================================================
// Constructor
// =============================================================================
const RedactedOpenAiHeaders = {
OpenAiOrganization: "OpenAI-Organization",
OpenAiProject: "OpenAI-Project"
}
/**
* Creates an OpenAI client service with the given options.
*
* **When to use**
*
* Use when you need the OpenAI client service value inside an effect.
*
* **Details**
*
* The returned service uses the current `HttpClient`, prepends `apiUrl` or
* `https://api.openai.com/v1`, adds the bearer token and optional OpenAI
* organization/project headers, accepts JSON responses, filters for successful
* HTTP statuses, and applies `transformClient` when provided.
*
* **Gotchas**
*
* A scoped `OpenAiConfig.withClientTransform` is applied when request helpers
* run, after the `transformClient` option supplied to `make`.
*
* @see {@link layer} for providing this client from explicit options
* @see {@link layerConfig} for loading client settings from `Config`
*
* @category constructors
* @since 4.0.0
*/
export const make = Effect.fnUntraced(
function*(
options: Options
): Effect.fn.Return<Service, never, HttpClient.HttpClient> {
const baseClient = yield* HttpClient.HttpClient
const apiUrl = options.apiUrl ?? "https://api.openai.com/v1"
const httpClient = baseClient.pipe(
HttpClient.mapRequest(Function.flow(
HttpClientRequest.prependUrl(apiUrl),
options.apiKey
? HttpClientRequest.bearerToken(Redacted.value(options.apiKey))
: identity,
options.organizationId
? HttpClientRequest.setHeader(
RedactedOpenAiHeaders.OpenAiOrganization,
Redacted.value(options.organizationId)
)
: identity,
options.projectId
? HttpClientRequest.setHeader(
RedactedOpenAiHeaders.OpenAiProject,
Redacted.value(options.projectId)
)
: identity,
HttpClientRequest.acceptJson
)),
HttpClient.filterStatusOk,
options.transformClient
? options.transformClient
: identity
)
const resolveHttpClient = Effect.map(
OpenAiConfig.getOrUndefined,
(config) =>
Predicate.isNotUndefined(config?.transformClient)
? config.transformClient(httpClient)
: httpClient
)
const decodeResponse = HttpClientResponse.schemaBodyJson(OpenAiSchema.Response)
const createResponse = (
payload: typeof OpenAiSchema.CreateResponse.Encoded
): Effect.Effect<
[body: typeof OpenAiSchema.Response.Type, response: HttpClientResponse.HttpClientResponse],
AiError.AiError
> =>
Effect.flatMap(resolveHttpClient, (client) =>
client.execute(
HttpClientRequest.post("/responses", {
body: HttpBody.jsonUnsafe(payload)
})
).pipe(
Effect.flatMap((response) =>
decodeResponse(response).pipe(
Effect.map((body): [typeof OpenAiSchema.Response.Type, HttpClientResponse.HttpClientResponse] => [
body,
response
])
)
),
Effect.catchTags({
HttpClientError: (error) => Errors.mapHttpClientError(error, "createResponse"),
SchemaError: (error) => Effect.fail(Errors.mapSchemaError(error, "createResponse"))
})
))
const buildResponseStream = (
response: HttpClientResponse.HttpClientResponse
): [
HttpClientResponse.HttpClientResponse,
Stream.Stream<typeof OpenAiSchema.ResponseStreamEvent.Type, AiError.AiError>
] => {
const stream = response.stream.pipe(
Stream.decodeText(),
Stream.pipeThroughChannel(Sse.decodeDataSchema(OpenAiSchema.ResponseStreamEvent)),
Stream.takeUntil((event) =>
event.data.type === "response.completed" ||
event.data.type === "response.incomplete"
),
Stream.map((event) => event.data),
Stream.catchTags({
// TODO: handle SSE retries
Retry: (error) => Stream.die(error),
HttpClientError: (error) => Stream.fromEffect(Errors.mapHttpClientError(error, "createResponseStream")),
SchemaError: (error) => Stream.fail(Errors.mapSchemaError(error, "createResponseStream"))
})
)
return [response, stream]
}
const createResponseStream: Service["createResponseStream"] = (payload) =>
Effect.contextWith((services) => {
const socket = Context.getOrUndefined(services, OpenAiSocket)
if (socket) return socket.createResponseStream(payload)
return Effect.flatMap(resolveHttpClient, (client) =>
client.execute(
HttpClientRequest.post("/responses", {
body: HttpBody.jsonUnsafe({ ...payload, stream: true })
})
).pipe(
Effect.map(buildResponseStream),
Effect.catchTag(
"HttpClientError",
(error) => Errors.mapHttpClientError(error, "createResponseStream")
)
))
})
const decodeEmbedding = HttpClientResponse.schemaBodyJson(OpenAiSchema.CreateEmbeddingResponse)
const createEmbedding = (
payload: typeof OpenAiSchema.CreateEmbeddingRequest.Encoded
): Effect.Effect<typeof OpenAiSchema.CreateEmbeddingResponse.Type, AiError.AiError> =>
Effect.flatMap(resolveHttpClient, (client) =>
client.execute(
HttpClientRequest.post("/embeddings", {
body: HttpBody.jsonUnsafe(payload)
})
).pipe(
Effect.flatMap(decodeEmbedding),
Effect.catchTags({
HttpClientError: (error) => Errors.mapHttpClientError(error, "createEmbedding"),
SchemaError: (error) => Effect.fail(Errors.mapSchemaError(error, "createEmbedding"))
})
))
return OpenAiClient.of({
client: httpClient,
createResponse,
createResponseStream,
createEmbedding
})
},
Effect.updateService(
Headers.CurrentRedactedNames,
Array.appendAll(Object.values(RedactedOpenAiHeaders))
)
)
// =============================================================================
// Layers
// =============================================================================
/**
* Creates a layer for the OpenAI client with the given options.
*
* **When to use**
*
* Use when you already have explicit `Options` values, such as an API key or
* custom API URL, and want to provide `OpenAiClient` as a `Layer`.
*
* @see {@link make} for constructing the client service effectfully
* @see {@link layerConfig} for loading client settings from `Config`
*
* @category layers
* @since 4.0.0
*/
export const layer = (options: Options): Layer.Layer<OpenAiClient, never, HttpClient.HttpClient> =>
Layer.effect(OpenAiClient, make(options))
/**
* Creates a layer for the OpenAI client from provided `Config` values.
*
* **When to use**
*
* Use when you need client settings for OpenAI-compatible APIs to be read from
* Effect `Config` values while providing `OpenAiClient` as a `Layer`.
*
* **Details**
*
* Only config values supplied in `options` are loaded. Omitted fields are
* passed to `make` as `undefined`, and `transformClient` is forwarded as a
* plain option.
*
* @see {@link make} for constructing the client service effectfully
* @see {@link layer} for providing the client from already-resolved options
*
* @category layers
* @since 4.0.0
*/
export const layerConfig = (options?: {
/**
* The config value to load for the API key.
*/
readonly apiKey?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
/**
* The config value to load for the API URL.
*/
readonly apiUrl?: Config.Config<string> | undefined
/**
* The config value to load for the organization ID.
*/
readonly organizationId?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
/**
* The config value to load for the project ID.
*/
readonly projectId?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
/**
* Optional transformer for the HTTP client.
*/
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
}): Layer.Layer<OpenAiClient, Config.ConfigError, HttpClient.HttpClient> =>
Layer.effect(
OpenAiClient,
Effect.gen(function*() {
const apiKey = Predicate.isNotUndefined(options?.apiKey)
? yield* options.apiKey :
undefined
const apiUrl = Predicate.isNotUndefined(options?.apiUrl)
? yield* options.apiUrl :
undefined
const organizationId = Predicate.isNotUndefined(options?.organizationId)
? yield* options.organizationId
: undefined
const projectId = Predicate.isNotUndefined(options?.projectId)
? yield* options.projectId :
undefined
return yield* make({
apiKey,
apiUrl,
organizationId,
projectId,
transformClient: options?.transformClient
})
})
)
// =============================================================================
// Websocket mode
// =============================================================================
/**
* Response stream event emitted by the OpenAI Responses API.
*
* @category Events
* @since 4.0.0
*/
export type ResponseStreamEvent = typeof OpenAiSchema.ResponseStreamEvent.Type
/**
* Service for creating OpenAI response streams over a WebSocket connection.
*
* **When to use**
*
* Use when you need direct access to the WebSocket-backed response streaming
* service rather than wrapping an effect with WebSocket mode.
*
* **Details**
*
* `createResponseStream` sends a `response.create` message over the WebSocket
* connection and returns an HTTP response together with a stream of
* `ResponseStreamEvent` values.
*
* **Gotchas**
*
* WebSocket response streams are serialized to one request at a time by the
* shared socket service.
*
* @see {@link withWebSocketMode} for enabling WebSocket mode for one effect
* @see {@link layerWebSocketMode} for providing WebSocket mode through a layer
*
* @category Websocket mode
* @since 4.0.0
*/
export class OpenAiSocket extends Context.Service<OpenAiSocket, {
/**
* Create a streaming response using the OpenAI responses endpoint.
*/
readonly createResponseStream: (
options: Omit<typeof OpenAiSchema.CreateResponse.Encoded, "stream">
) => Effect.Effect<
readonly [
response: HttpClientResponse.HttpClientResponse,
stream: Stream.Stream<ResponseStreamEvent, AiError.AiError>
],
AiError.AiError
>
}>()("@effect/ai-openai/OpenAiClient/OpenAiSocket") {}
const makeSocket = Effect.gen(function*() {
const client = yield* OpenAiClient
const tracker = yield* ResponseIdTracker.make
const socketScope = yield* Effect.scope
const makeRequest = Effect.flatMap(
OpenAiConfig.getOrUndefined,
(config) => {
const httpClient = Predicate.isNotUndefined(config?.transformClient)
? config.transformClient(client.client)
: client.client
return Effect.orDie(httpClient.preprocess(HttpClientRequest.post("/responses")))
}
)
const makeWebSocket = yield* Socket.WebSocketConstructor
const decoder = new TextDecoder()
const queueRef: RcRef.RcRef<
{
readonly send: (message: typeof OpenAiSchema.CreateResponse.Encoded) => Effect.Effect<void, AiError.AiError>
readonly incoming: Queue.Dequeue<ResponseStreamEvent, AiError.AiError>
}
> = yield* RcRef.make({
idleTimeToLive: 60_000,
acquire: Effect.gen(function*() {
const scope = yield* Effect.scope
const request = yield* makeRequest
const socket = yield* Socket.makeWebSocket(request.url.replace(/^http/, "ws")).pipe(
Effect.provideService(Socket.WebSocketConstructor, (url) =>
makeWebSocket(url, {
headers: request.headers
} as any))
)
const write = yield* socket.writer
yield* Scope.addFinalizerExit(scope, () => {
tracker.clearUnsafe()
return Effect.void
})
const incoming = yield* Queue.unbounded<ResponseStreamEvent, AiError.AiError>()
const send = (message: typeof OpenAiSchema.CreateResponse.Encoded) =>
write(JSON.stringify({
type: "response.create",
...message
})).pipe(
Effect.mapError((_error) =>
AiError.make({
module: "OpenAiClient",
method: "createResponseStream",
reason: new AiError.NetworkError({
reason: "TransportError",
request: {
method: "POST",
url: request.url,
urlParams: [],
hash: undefined,
headers: request.headers
},
description: "Failed to send message over WebSocket"
})
})
)
)
yield* socket.runRaw((msg) => {
const text = typeof msg === "string" ? msg : decoder.decode(msg)
try {
const event = decodeEvent(text)
if (event.type === "error" && "status" in event) {
const status = Number(event.status)
const error = "error" in event ? event.error as typeof ErrorEvent.Type.error : event
const json = JSON.stringify(error)
return Effect.fail(
AiError.make({
module: "OpenAiClient",
method: "createResponseStream",
reason: AiError.reasonFromHttpStatus({
description: json,
status: isNaN(status) ? errorTypeToStatus[error.type] ?? 500 : status,
metadata: error as any,
http: {
body: json,
request: {
method: "POST",
url: request.url,
urlParams: [],
hash: undefined,
headers: request.headers
}
}
})
})
)
}
Queue.offerUnsafe(incoming, event)
} catch {}
}).pipe(
Effect.catchTag("SocketError", (error) =>
AiError.make({
module: "OpenAiClient",
method: "createResponseStream",
reason: new AiError.NetworkError({
reason: "TransportError",
request: {
method: "POST",
url: request.url,
urlParams: [],
hash: undefined,
headers: request.headers
},
description: error.message
})
})),
Effect.catchCause((cause) => Queue.failCause(incoming, cause)),
Effect.ensuring(Effect.forkIn(RcRef.invalidate(queueRef), socketScope, {
startImmediately: true
})),
Effect.forkScoped({ startImmediately: true })
)
return { send, incoming } as const
})
})
// Prime the websocket
yield* Effect.scoped(RcRef.get(queueRef))
// Websocket mode only allows one request at a time
const semaphore = Semaphore.makeUnsafe(1)
const request = yield* makeRequest
return OpenAiSocket.context({
createResponseStream(options) {
const stream = Stream.unwrap(Effect.gen(function*() {
const scope = yield* Effect.scope
yield* Effect.acquireRelease(
semaphore.take(1),
() => semaphore.release(1),
{ interruptible: true }
)
const { send, incoming } = yield* RcRef.get(queueRef)
let done = false
yield* Scope.addFinalizerExit(
scope,
() => done ? Effect.void : RcRef.invalidate(queueRef)
)
yield* send(options).pipe(
Effect.forkScoped({ startImmediately: true })
)
return Stream.fromQueue(incoming).pipe(
Stream.takeUntil((e) => {
done = e.type === "response.completed" || e.type === "response.incomplete"
return done
})
)
}))
return Effect.succeed([
HttpClientResponse.fromWeb(request, new Response()),
stream
])
}
}).pipe(
Context.add(ResponseIdTracker.ResponseIdTracker, tracker)
)
})
const ErrorEvent = Schema.Struct({
type: Schema.Literal("error"),
status: Schema.Number.pipe(
Schema.withDecodingDefault(Effect.succeed(500))
),
error: Schema.Struct({
type: Schema.String,
message: Schema.String
})
})
const errorTypeToStatus: Record<string, number> = {
invalid_request_error: 400,
invalid_api_key_error: 401,
insufficient_quota_error: 429,
rate_limit_error: 429,
service_unavailable_error: 503
}
const AllEvents = Schema.Union([ErrorEvent, OpenAiSchema.ResponseStreamEvent])
const decodeEvent = Schema.decodeUnknownSync(Schema.fromJsonString(AllEvents))
/**
* Uses OpenAI's WebSocket mode for response streams within the provided effect.
*
* **When to use**
*
* Use to enable WebSocket mode around one effect that creates OpenAI response
* streams.
*
* **Gotchas**
*
* This only works with the following WebSocket constructor layers:
*
* - `NodeSocket.layerWebSocketConstructorWS`
* - `BunSocket.layerWebSocketConstructor`
*
* These constructor layers support the non-standard options needed to set the
* Authorization header.
*
* @see {@link layerWebSocketMode} for providing WebSocket mode through a layer
* @see {@link OpenAiSocket} for direct access to the WebSocket-backed streaming service
*
* @category Websocket mode
* @since 4.0.0
*/
export const withWebSocketMode = <A, E, R>(
effect: Effect.Effect<A, E, R>
): Effect.Effect<
A,
E,
Exclude<R, OpenAiSocket | ResponseIdTracker.ResponseIdTracker> | OpenAiClient | Socket.WebSocketConstructor
> =>
Effect.scopedWith((scope) =>
Effect.flatMap(
Scope.provide(makeSocket, scope),
(services) => Effect.provideContext(effect, services)
)
)
/**
* Uses OpenAI's websocket mode for all responses that use the Layer.
*
* **When to use**
*
* Use to provide WebSocket mode through layer composition for effects that use
* OpenAI response streaming.
*
* **Gotchas**
*
* This only works with the following WebSocket constructor layers:
*
* - `NodeSocket.layerWebSocketConstructorWS`
* - `BunSocket.layerWebSocketConstructor`
*
* These constructor layers support the non-standard options needed to set the
* Authorization header.
*
* @see {@link withWebSocketMode} for enabling WebSocket mode around a single effect
*
* @category Websocket mode
* @since 4.0.0
*/
export const layerWebSocketMode: Layer.Layer<
OpenAiSocket | ResponseIdTracker.ResponseIdTracker,
never,
OpenAiClient | Socket.WebSocketConstructor
> = Layer.effectContext(makeSocket)

View File

@@ -0,0 +1,202 @@
/**
* @since 4.0.0
*/
import * as Array from "effect/Array"
import type * as Config from "effect/Config"
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { identity } from "effect/Function"
import * as Function from "effect/Function"
import * as Layer from "effect/Layer"
import * as Predicate from "effect/Predicate"
import * as Redacted from "effect/Redacted"
import * as Headers from "effect/unstable/http/Headers"
import * as HttpClient from "effect/unstable/http/HttpClient"
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import * as Generated from "./Generated.ts"
import { OpenAiConfig } from "./OpenAiConfig.ts"
// =============================================================================
// Service Identifier
// =============================================================================
/**
* Service identifier for the generated OpenAI client.
*
* @since 4.0.0
* @category service
*/
export class OpenAiClientGenerated extends Context.Service<OpenAiClientGenerated, Generated.OpenAiClient>()(
"@effect/ai-openai/OpenAiClientGenerated"
) {}
// =============================================================================
// Options
// =============================================================================
/**
* Options for configuring the generated OpenAI client.
*
* @since 4.0.0
* @category options
*/
export type Options = {
/**
* The OpenAI API key.
*/
readonly apiKey?: Redacted.Redacted<string> | undefined
/**
* The base URL for the OpenAI API.
*
* @default "https://api.openai.com/v1"
*/
readonly apiUrl?: string | undefined
/**
* Optional organization ID for multi-org accounts.
*/
readonly organizationId?: Redacted.Redacted<string> | undefined
/**
* Optional project ID for project-scoped requests.
*/
readonly projectId?: Redacted.Redacted<string> | undefined
/**
* Optional transformer for the HTTP client.
*/
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
}
const RedactedOpenAiHeaders = {
OpenAiOrganization: "OpenAI-Organization",
OpenAiProject: "OpenAI-Project"
}
// =============================================================================
// Constructor
// =============================================================================
/**
* Creates a generated OpenAI client service with the given options.
*
* @since 4.0.0
* @category constructors
*/
export const make = Effect.fnUntraced(
function*(options: Options): Effect.fn.Return<Generated.OpenAiClient, never, HttpClient.HttpClient> {
const baseClient = yield* HttpClient.HttpClient
const apiUrl = options.apiUrl ?? "https://api.openai.com/v1"
const httpClient = baseClient.pipe(
HttpClient.mapRequest(Function.flow(
HttpClientRequest.prependUrl(apiUrl),
options.apiKey
? HttpClientRequest.bearerToken(Redacted.value(options.apiKey))
: identity,
options.organizationId
? HttpClientRequest.setHeader(
RedactedOpenAiHeaders.OpenAiOrganization,
Redacted.value(options.organizationId)
)
: identity,
options.projectId
? HttpClientRequest.setHeader(
RedactedOpenAiHeaders.OpenAiProject,
Redacted.value(options.projectId)
)
: identity,
HttpClientRequest.acceptJson
)),
options.transformClient
? options.transformClient
: identity
)
return Generated.make(httpClient, {
transformClient: Effect.fnUntraced(function*(client) {
const config = yield* OpenAiConfig.getOrUndefined
if (Predicate.isNotUndefined(config?.transformClient)) {
return config.transformClient(client)
}
return client
})
})
},
Effect.updateService(
Headers.CurrentRedactedNames,
Array.appendAll(Object.values(RedactedOpenAiHeaders))
)
)
// =============================================================================
// Layers
// =============================================================================
/**
* Creates a layer for the generated OpenAI client with the given options.
*
* @since 4.0.0
* @category layers
*/
export const layer = (options: Options): Layer.Layer<OpenAiClientGenerated, never, HttpClient.HttpClient> =>
Layer.effect(OpenAiClientGenerated, make(options))
/**
* Creates a layer for the generated OpenAI client, loading the requisite
* configuration via Effect's `Config` module.
*
* @since 4.0.0
* @category layers
*/
export const layerConfig = (options?: {
/**
* The config value to load for the API key.
*/
readonly apiKey?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
/**
* The config value to load for the API URL.
*/
readonly apiUrl?: Config.Config<string> | undefined
/**
* The config value to load for the organization ID.
*/
readonly organizationId?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
/**
* The config value to load for the project ID.
*/
readonly projectId?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
/**
* Optional transformer for the HTTP client.
*/
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
}): Layer.Layer<OpenAiClientGenerated, Config.ConfigError, HttpClient.HttpClient> =>
Layer.effect(
OpenAiClientGenerated,
Effect.gen(function*() {
const apiKey = Predicate.isNotUndefined(options?.apiKey)
? yield* options.apiKey :
undefined
const apiUrl = Predicate.isNotUndefined(options?.apiUrl)
? yield* options.apiUrl :
undefined
const organizationId = Predicate.isNotUndefined(options?.organizationId)
? yield* options.organizationId
: undefined
const projectId = Predicate.isNotUndefined(options?.projectId)
? yield* options.projectId :
undefined
return yield* make({
apiKey,
apiUrl,
organizationId,
projectId,
transformClient: options?.transformClient
})
})
)

View File

@@ -0,0 +1,93 @@
/**
* The `OpenAiConfig` module lets a workflow temporarily customize the HTTP
* client used by `@effect/ai-openai` request helpers. OpenAI client, language
* model, and embedding code read this scoped transform when they execute
* provider calls.
*
* @since 4.0.0
*/
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import type { HttpClient } from "effect/unstable/http/HttpClient"
/**
* Context service for scoped OpenAI configuration used by provider operations.
*
* **When to use**
*
* Use to provide scoped OpenAI client configuration, such as an HTTP client
* transform, to OpenAI provider operations without passing it through each call.
*
* @see {@link withClientTransform} for scoping an HTTP client transformation
*
* @category services
* @since 4.0.0
*/
export class OpenAiConfig extends Context.Service<
OpenAiConfig,
OpenAiConfig.Service
>()("@effect/ai-openai/OpenAiConfig") {
/**
* Gets the configured OpenAI service from the current context when present.
*
* @since 4.0.0
*/
static readonly getOrUndefined: Effect.Effect<typeof OpenAiConfig.Service | undefined> = Effect.map(
Effect.context<never>(),
(context) => context.mapUnsafe.get(OpenAiConfig.key)
)
}
/**
* Types used by the `OpenAiConfig` context service.
*
* @since 4.0.0
*/
export declare namespace OpenAiConfig {
/**
* Configuration values read by OpenAI provider operations when executing
* requests.
*
* @category models
* @since 4.0.0
*/
export interface Service {
readonly transformClient?: ((client: HttpClient) => HttpClient) | undefined
}
}
/**
* Provides a scoped transform for the OpenAI HTTP client used by provider
* operations.
*
* **When to use**
*
* Use when you need temporary OpenAI HTTP client customization for a single
* effect or workflow without rebuilding the client layer.
*
* **Details**
*
* Supports both data-first and data-last forms. The transform is stored in the
* scoped `OpenAiConfig` service and read by OpenAI provider operations while
* running the supplied effect.
*
* **Gotchas**
*
* If a transform is already present in the scoped config, this helper replaces
* it. Compose transforms manually when both should apply.
*
* @category configuration
* @since 4.0.0
*/
export const withClientTransform: {
(transform: (client: HttpClient) => HttpClient): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
<A, E, R>(self: Effect.Effect<A, E, R>, transform: (client: HttpClient) => HttpClient): Effect.Effect<A, E, R>
} = dual(2, <A, E, R>(
self: Effect.Effect<A, E, R>,
transformClient: (client: HttpClient) => HttpClient
) =>
Effect.flatMap(
OpenAiConfig.getOrUndefined,
(config) => Effect.provideService(self, OpenAiConfig, { ...config, transformClient })
))

View File

@@ -0,0 +1,258 @@
/**
* The `OpenAiEmbeddingModel` module provides the OpenAI implementation of
* Effect AI's `EmbeddingModel` service. It sends embedding requests through
* `OpenAiClient`, exposes constructors for layers and `AiModel` values,
* supports scoped request configuration overrides, and checks that OpenAI
* returns one numeric vector for each requested input.
*
* @since 4.0.0
*/
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import * as Layer from "effect/Layer"
import type { Simplify } from "effect/Types"
import * as AiError from "effect/unstable/ai/AiError"
import * as EmbeddingModel from "effect/unstable/ai/EmbeddingModel"
import * as AiModel from "effect/unstable/ai/Model"
import { OpenAiClient } from "./OpenAiClient.ts"
import type * as OpenAiSchema from "./OpenAiSchema.ts"
/**
* Model identifiers supported by OpenAI's embeddings API.
*
* @category models
* @since 4.0.0
*/
export type Model = "text-embedding-ada-002" | "text-embedding-3-small" | "text-embedding-3-large"
/**
* Context service for OpenAI embedding model configuration.
*
* **When to use**
*
* Use when you need scoped OpenAI request defaults or overrides for embedding
* requests from Effect context.
*
* **Details**
*
* The service stores the OpenAI create-embedding request payload without
* `input`, carrying options such as `model`, `dimensions`, `encoding_format`,
* and `user`.
*
* @see {@link withConfigOverride} for scoping embedding request overrides
*
* @category services
* @since 4.0.0
*/
export class Config extends Context.Service<
Config,
Simplify<
& Partial<
Omit<
typeof OpenAiSchema.CreateEmbeddingRequest.Encoded,
"input"
>
>
& {
readonly [x: string]: unknown
}
>
>()("@effect/ai-openai/OpenAiEmbeddingModel/Config") {}
/**
* Creates an `AiModel` for an OpenAI embedding model with its configured vector dimensions.
*
* **When to use**
*
* Use to provide an OpenAI `EmbeddingModel` and its `Dimensions` service to an
* Effect program.
*
* @see {@link layer} for providing only the embedding model service
* @see {@link withConfigOverride} for scoped request configuration overrides
*
* @category constructors
* @since 4.0.0
*/
export const model = (
model: (string & {}) | Model,
options: {
readonly dimensions: number
readonly config?: Omit<typeof Config.Service, "model" | "dimensions">
}
): AiModel.Model<"openai", EmbeddingModel.EmbeddingModel | EmbeddingModel.Dimensions, OpenAiClient> =>
AiModel.make(
"openai",
model,
Layer.merge(
layer({
model,
config: {
...options.config,
dimensions: options.dimensions
}
}),
Layer.succeed(EmbeddingModel.Dimensions, options.dimensions)
)
)
/**
* Creates an OpenAI embedding model service.
*
* **When to use**
*
* Use to construct the `EmbeddingModel.Service` effectfully when
* `OpenAiClient` is already available in the environment.
*
* **Details**
*
* The `model` option is sent with each embedding request. Constructor `config`
* supplies create-embedding request fields other than `model` and `input`, and
* scoped overrides from `withConfigOverride` are merged last for each request.
*
* **Gotchas**
*
* The service expects numeric embedding vectors. It fails with
* `InvalidOutputError` when the provider returns base64 embeddings,
* out-of-range indexes, duplicate indexes, or an unexpected number of
* embeddings.
*
* @see {@link layer} for providing the embedding model service as a layer
* @see {@link model} for creating an `AiModel` that also provides dimensions
* @see {@link withConfigOverride} for scoped request configuration overrides
*
* @category constructors
* @since 4.0.0
*/
export const make = Effect.fnUntraced(function*({ model, config: providerConfig }: {
readonly model: (string & {}) | Model
readonly config?: Omit<typeof Config.Service, "model"> | undefined
}): Effect.fn.Return<EmbeddingModel.Service, never, OpenAiClient> {
const client = yield* OpenAiClient
const makeConfig = Effect.gen(function*() {
const services = yield* Effect.context<never>()
return { model, ...providerConfig, ...services.mapUnsafe.get(Config.key) }
})
return yield* EmbeddingModel.make({
embedMany: Effect.fnUntraced(function*({ inputs }) {
const config = yield* makeConfig
const response = yield* client.createEmbedding({ ...config, input: inputs })
return yield* mapProviderResponse(inputs.length, response)
})
})
})
/**
* Creates a layer for the OpenAI embedding model.
*
* **When to use**
*
* Use when composing application layers and you want OpenAI to satisfy
* `EmbeddingModel.EmbeddingModel` while supplying `OpenAiClient` from another
* layer.
*
* **Gotchas**
*
* Use the default floating-point embedding format. The service expects numeric
* vectors and fails with `InvalidOutputError` if OpenAI returns base64
* embeddings.
*
* @see {@link make} for constructing the embedding model service effectfully
* @see {@link model} for creating an `AiModel` that also provides embedding dimensions
*
* @category layers
* @since 4.0.0
*/
export const layer = (options: {
readonly model: (string & {}) | Model
readonly config?: Omit<typeof Config.Service, "model"> | undefined
}): Layer.Layer<EmbeddingModel.EmbeddingModel, never, OpenAiClient> =>
Layer.effect(EmbeddingModel.EmbeddingModel, make(options))
/**
* Provides config overrides for OpenAI embedding model operations.
*
* **When to use**
*
* Use when you need scoped OpenAI embedding request defaults for a single
* effect or workflow without rebuilding the embedding model service.
*
* **Details**
*
* Supports both data-first and data-last forms. Existing scoped config is read
* first, then the provided overrides are applied so override fields take
* precedence.
*
* @see {@link Config} for the scoped embedding request configuration service
*
* @category configuration
* @since 4.0.0
*/
export const withConfigOverride: {
(overrides: typeof Config.Service): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Config>>
<A, E, R>(self: Effect.Effect<A, E, R>, overrides: typeof Config.Service): Effect.Effect<A, E, Exclude<R, Config>>
} = dual<
(
overrides: typeof Config.Service
) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Config>>,
<A, E, R>(self: Effect.Effect<A, E, R>, overrides: typeof Config.Service) => Effect.Effect<A, E, Exclude<R, Config>>
>(2, (self, overrides) =>
Effect.flatMap(
Effect.serviceOption(Config),
(config) =>
Effect.provideService(self, Config, {
...(config._tag === "Some" ? config.value : {}),
...overrides
})
))
const mapProviderResponse = (
inputLength: number,
response: typeof OpenAiSchema.CreateEmbeddingResponse.Type
): Effect.Effect<EmbeddingModel.ProviderResponse, AiError.AiError> => {
if (response.data.length !== inputLength) {
return Effect.fail(
invalidOutput("Provider returned " + response.data.length + " embeddings but expected " + inputLength)
)
}
const results = new Array<Array<number>>(inputLength)
const seen = new Set<number>()
for (const entry of response.data) {
if (!Number.isInteger(entry.index) || entry.index < 0 || entry.index >= inputLength) {
return Effect.fail(invalidOutput("Provider returned invalid embedding index: " + entry.index))
}
if (seen.has(entry.index)) {
return Effect.fail(invalidOutput("Provider returned duplicate embedding index: " + entry.index))
}
if (!Array.isArray(entry.embedding)) {
return Effect.fail(invalidOutput("Provider returned non-vector embedding at index " + entry.index))
}
seen.add(entry.index)
results[entry.index] = [...entry.embedding]
}
if (seen.size !== inputLength) {
return Effect.fail(
invalidOutput("Provider returned embeddings for " + seen.size + " inputs but expected " + inputLength)
)
}
return Effect.succeed({
results,
usage: {
inputTokens: response.usage?.prompt_tokens
}
})
}
const invalidOutput = (description: string): AiError.AiError =>
AiError.make({
module: "OpenAiEmbeddingModel",
method: "embedMany",
reason: new AiError.InvalidOutputError({ description })
})

View File

@@ -0,0 +1,242 @@
/**
* OpenAI error metadata augmentation.
*
* Provides OpenAI-specific metadata fields for AI error types through module
* augmentation, enabling typed access to OpenAI error details.
*
* @since 4.0.0
*/
/**
* OpenAI-specific error metadata fields.
*
* @category models
* @since 4.0.0
*/
export type OpenAiErrorMetadata = {
/**
* The OpenAI error code returned by the API.
*/
readonly errorCode: string | null
/**
* The OpenAI error type returned by the API.
*/
readonly errorType: string | null
/**
* The unique request ID for debugging with OpenAI support.
*/
readonly requestId: string | null
}
/**
* OpenAI-specific rate limit metadata fields.
*
* **Details**
*
* Extends base error metadata with rate limit specific information from
* OpenAI's rate limit headers.
*
* @category models
* @since 4.0.0
*/
export type OpenAiRateLimitMetadata = OpenAiErrorMetadata & {
/**
* The rate limit type (e.g. "requests", "tokens").
*/
readonly limit: string | null
/**
* Number of remaining requests in the current window.
*/
readonly remaining: number | null
/**
* Time until the request rate limit resets.
*/
readonly resetRequests: string | null
/**
* Time until the token rate limit resets.
*/
readonly resetTokens: string | null
}
declare module "effect/unstable/ai/AiError" {
/**
* OpenAI metadata attached to `RateLimitError` values.
*
* **Details**
*
* Captures OpenAI error details together with rate limit header information
* from responses where the provider rejected the request because a limit was
* reached.
*
* @category configuration
* @since 4.0.0
*/
export interface RateLimitErrorMetadata {
/**
* OpenAI-specific details for the rate limit response.
*/
readonly openai?: OpenAiRateLimitMetadata | null
}
/**
* OpenAI metadata attached to `QuotaExhaustedError` values.
*
* **Details**
*
* Preserves provider error details for failures caused by exhausted account,
* billing, or usage quota.
*
* @category configuration
* @since 4.0.0
*/
export interface QuotaExhaustedErrorMetadata {
/**
* OpenAI-specific details for the quota exhaustion response.
*/
readonly openai?: OpenAiErrorMetadata | null
}
/**
* OpenAI metadata attached to `AuthenticationError` values.
*
* **Details**
*
* Preserves provider error details for failed API key, authorization, or
* permission checks.
*
* @category configuration
* @since 4.0.0
*/
export interface AuthenticationErrorMetadata {
/**
* OpenAI-specific details for the authentication failure.
*/
readonly openai?: OpenAiErrorMetadata | null
}
/**
* OpenAI metadata attached to `ContentPolicyError` values.
*
* **Details**
*
* Preserves provider error details when OpenAI rejects input or output because
* it violates a content policy.
*
* @category configuration
* @since 4.0.0
*/
export interface ContentPolicyErrorMetadata {
/**
* OpenAI-specific details for the content policy response.
*/
readonly openai?: OpenAiErrorMetadata | null
}
/**
* OpenAI metadata attached to `InvalidRequestError` values.
*
* **Details**
*
* Preserves provider error details for malformed requests, unsupported
* parameters, or other request validation failures reported by OpenAI.
*
* @category configuration
* @since 4.0.0
*/
export interface InvalidRequestErrorMetadata {
/**
* OpenAI-specific details for the invalid request response.
*/
readonly openai?: OpenAiErrorMetadata | null
}
/**
* OpenAI metadata attached to `InternalProviderError` values.
*
* **Details**
*
* Preserves provider error details for OpenAI-side failures such as transient
* server errors.
*
* @category configuration
* @since 4.0.0
*/
export interface InternalProviderErrorMetadata {
/**
* OpenAI-specific details for the internal provider response.
*/
readonly openai?: OpenAiErrorMetadata | null
}
/**
* OpenAI metadata attached to `InvalidOutputError` values.
*
* **Details**
*
* Preserves provider error details when an OpenAI response cannot be parsed or
* validated as the expected output.
*
* @category configuration
* @since 4.0.0
*/
export interface InvalidOutputErrorMetadata {
/**
* OpenAI-specific details for the invalid output response.
*/
readonly openai?: OpenAiErrorMetadata | null
}
/**
* OpenAI metadata attached to `StructuredOutputError` values.
*
* **Details**
*
* Preserves provider error details when OpenAI returns content that does not
* satisfy the requested structured output schema.
*
* @category configuration
* @since 4.0.0
*/
export interface StructuredOutputErrorMetadata {
/**
* OpenAI-specific details for the structured output failure.
*/
readonly openai?: OpenAiErrorMetadata | null
}
/**
* OpenAI metadata attached to `UnsupportedSchemaError` values.
*
* **Details**
*
* Preserves provider error details when an unsupported schema failure is
* associated with an OpenAI response.
*
* @category configuration
* @since 4.0.0
*/
export interface UnsupportedSchemaErrorMetadata {
/**
* OpenAI-specific details for the unsupported schema failure.
*/
readonly openai?: OpenAiErrorMetadata | null
}
/**
* OpenAI metadata attached to `UnknownError` values.
*
* **Details**
*
* Preserves provider error details for OpenAI failures that do not map cleanly
* to a more specific AI error category.
*
* @category configuration
* @since 4.0.0
*/
export interface UnknownErrorMetadata {
/**
* OpenAI-specific details for the unclassified provider failure.
*/
readonly openai?: OpenAiErrorMetadata | null
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
/**
* The `OpenAiTelemetry` module defines OpenAI-specific telemetry attributes
* and a helper for adding them to a tracing span. It keeps the standard GenAI
* telemetry attributes and adds request and response metadata, such as response
* format, service tier, and system fingerprint, under the `gen_ai.openai.*`
* OpenTelemetry namespaces.
*
* @since 4.0.0
*/
import { dual } from "effect/Function"
import * as String from "effect/String"
import type { Span } from "effect/Tracer"
import type { Simplify } from "effect/Types"
import * as Telemetry from "effect/unstable/ai/Telemetry"
/**
* The attributes used to describe telemetry in the context of Generative
* Artificial Intelligence (GenAI) Models requests and responses.
*
* **Details**
*
* These attributes follow the OpenTelemetry generative AI semantic
* conventions:
* https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/
*
* @category models
* @since 4.0.0
*/
export type OpenAiTelemetryAttributes = Simplify<
& Telemetry.GenAITelemetryAttributes
& Telemetry.AttributesWithPrefix<RequestAttributes, "gen_ai.openai.request">
& Telemetry.AttributesWithPrefix<ResponseAttributes, "gen_ai.openai.request">
>
/**
* All telemetry attributes which are part of the GenAI specification,
* including the OpenAI-specific attributes.
*
* @category models
* @since 4.0.0
*/
export type AllAttributes = Telemetry.AllAttributes & RequestAttributes & ResponseAttributes
/**
* Telemetry attributes which are part of the GenAI specification and are
* namespaced by `gen_ai.openai.request`.
*
* @category models
* @since 4.0.0
*/
export interface RequestAttributes {
/**
* The response format that is requested.
*/
readonly responseFormat?: (string & {}) | WellKnownResponseFormat | null | undefined
/**
* The service tier requested. May be a specific tier, `default`, or `auto`.
*/
readonly serviceTier?: (string & {}) | WellKnownServiceTier | null | undefined
}
/**
* Telemetry attributes which are part of the GenAI specification and are
* namespaced by `gen_ai.openai.response`.
*
* @category models
* @since 4.0.0
*/
export interface ResponseAttributes {
/**
* The service tier used for the response.
*/
readonly serviceTier?: string | null | undefined
/**
* A fingerprint to track any eventual change in the Generative AI
* environment.
*/
readonly systemFingerprint?: string | null | undefined
}
/**
* The `gen_ai.openai.request.response_format` attribute has the following
* list of well-known values.
*
* **Details**
*
* If one of them applies, then the respective value **MUST** be used;
* otherwise, a custom value **MAY** be used.
*
* @category models
* @since 4.0.0
*/
export type WellKnownResponseFormat = "json_object" | "json_schema" | "text"
/**
* The `gen_ai.openai.request.service_tier` attribute has the following
* list of well-known values.
*
* **Details**
*
* If one of them applies, then the respective value **MUST** be used;
* otherwise, a custom value **MAY** be used.
*
* @category models
* @since 4.0.0
*/
export type WellKnownServiceTier = "auto" | "default"
/**
* Options accepted by `addGenAIAnnotations`, combining standard GenAI
* telemetry attributes with optional OpenAI request and response attributes.
*
* @category options
* @since 4.0.0
*/
export type OpenAiTelemetryAttributeOptions = Telemetry.GenAITelemetryAttributeOptions & {
openai?: {
request?: RequestAttributes | undefined
response?: ResponseAttributes | undefined
} | undefined
}
const addOpenAiRequestAttributes = Telemetry.addSpanAttributes("gen_ai.openai.request", String.camelToSnake)<
RequestAttributes
>
const addOpenAiResponseAttributes = Telemetry.addSpanAttributes("gen_ai.openai.response", String.camelToSnake)<
ResponseAttributes
>
/**
* Applies the specified OpenAI GenAI telemetry attributes to the provided
* `Span`.
*
* **When to use**
*
* Use to annotate an existing OpenTelemetry span with standard GenAI attributes
* plus OpenAI-specific request and response metadata.
*
* **Gotchas**
*
* Mutates the supplied `Span` in place.
*
* @see {@link OpenAiTelemetryAttributeOptions} for the accepted telemetry attributes
* @see {@link Telemetry.addGenAIAnnotations} for the provider-neutral annotation helper
*
* @category tracing
* @since 4.0.0
*/
export const addGenAIAnnotations: {
(options: OpenAiTelemetryAttributeOptions): (span: Span) => void
(span: Span, options: OpenAiTelemetryAttributeOptions): void
} = dual(2, (span: Span, options: OpenAiTelemetryAttributeOptions) => {
Telemetry.addGenAIAnnotations(span, options)
if (options.openai != null) {
if (options.openai.request != null) {
addOpenAiRequestAttributes(span, options.openai.request)
}
if (options.openai.response != null) {
addOpenAiResponseAttributes(span, options.openai.response)
}
}
})

View File

@@ -0,0 +1,342 @@
/**
* The `OpenAiTool` module defines OpenAI provider tools for Effect AI language
* model requests. It exposes typed descriptors for tools such as Apply Patch,
* Code Interpreter, File Search, Image Generation, MCP, Web Search, and
* shell-like local tools, including their provider names, configuration
* arguments, call parameters, success schemas, and handler requirements.
*
* @since 4.0.0
*/
import * as Schema from "effect/Schema"
import * as Tool from "effect/unstable/ai/Tool"
import * as Generated from "./Generated.ts"
/**
* Union of all OpenAI provider-defined tools.
*
* @category models
* @since 4.0.0
*/
export type OpenAiTool =
| ReturnType<typeof ApplyPatch>
| ReturnType<typeof CodeInterpreter>
| ReturnType<typeof FileSearch>
| ReturnType<typeof Shell>
| ReturnType<typeof ImageGeneration>
| ReturnType<typeof LocalShell>
| ReturnType<typeof Mcp>
| ReturnType<typeof WebSearch>
| ReturnType<typeof WebSearchPreview>
/**
* Defines the OpenAI Apply Patch tool that allows the model to apply diffs by creating,
* deleting, or updating files. This local tool runs in your environment and
* requires a handler to execute file operations.
*
* **When to use**
*
* Use when you want an OpenAI model to request structured file edits as create,
* delete, or update operations that your application executes through a local
* handler.
*
* @category tools
* @since 4.0.0
*/
export const ApplyPatch = Tool.providerDefined({
id: "openai.apply_patch",
customName: "OpenAiApplyPatch",
providerName: "apply_patch",
requiresHandler: true,
parameters: Schema.Struct({
call_id: Generated.ApplyPatchToolCall.fields.call_id,
operation: Generated.ApplyPatchToolCall.fields.operation
}),
success: Schema.Struct({
status: Generated.ApplyPatchToolCallOutput.fields.status,
output: Generated.ApplyPatchToolCallOutput.fields.output
})
})
/**
* Defines the OpenAI Code Interpreter tool that allows the model to execute Python code in
* a sandboxed environment.
*
* **When to use**
*
* Use to enable OpenAI-hosted Python execution for a model response.
*
* **Details**
*
* The tool is configured with a `container` argument. Successful tool calls
* expose `outputs`, which may contain logs or generated images, or `null` when
* no outputs are available.
*
* @category tools
* @since 4.0.0
*/
export const CodeInterpreter = Tool.providerDefined({
id: "openai.code_interpreter",
customName: "OpenAiCodeInterpreter",
providerName: "code_interpreter",
args: Schema.Struct({
container: Generated.CodeInterpreterTool.fields.container
}),
parameters: Schema.Struct({
code: Generated.CodeInterpreterToolCall.fields.code,
container_id: Generated.CodeInterpreterToolCall.fields.container_id
}),
success: Schema.Struct({
outputs: Generated.CodeInterpreterToolCall.fields.outputs
})
})
/**
* Defines the OpenAI File Search tool that enables the model to search through uploaded
* files and vector stores.
*
* **When to use**
*
* Use to let an OpenAI model search uploaded files through one or more vector
* stores.
*
* **Details**
*
* The tool requires `vector_store_ids` and accepts optional `filters`,
* `max_num_results`, and `ranking_options`. Successful tool calls expose the
* search `status`, generated `queries`, and optional `results`.
*
* @category tools
* @since 4.0.0
*/
export const FileSearch = Tool.providerDefined({
id: "openai.file_search",
customName: "OpenAiFileSearch",
providerName: "file_search",
args: Schema.Struct({
filters: Generated.FileSearchTool.fields.filters,
max_num_results: Generated.FileSearchTool.fields.max_num_results,
ranking_options: Generated.FileSearchTool.fields.ranking_options,
vector_store_ids: Generated.FileSearchTool.fields.vector_store_ids
}),
success: Schema.Struct({
status: Generated.FileSearchToolCall.fields.status,
queries: Generated.FileSearchToolCall.fields.queries,
results: Generated.FileSearchToolCall.fields.results
})
})
/**
* Defines the OpenAI Image Generation tool that enables the model to generate images using
* the GPT image models.
*
* **When to use**
*
* Use to enable OpenAI provider-defined image generation through a language
* model response.
*
* **Details**
*
* The tool configures the `image_generation` provider tool, including model,
* size, quality, output format, moderation, background, input-image options,
* and partial image settings. Successful tool calls expose `result` as base64
* image data or `null`.
*
* @category tools
* @since 4.0.0
*/
export const ImageGeneration = Tool.providerDefined({
id: "openai.image_generation",
customName: "OpenAiImageGeneration",
providerName: "image_generation",
args: Schema.Struct({
background: Generated.ImageGenTool.fields.background,
input_fidelity: Generated.ImageGenTool.fields.input_fidelity,
input_image_mask: Generated.ImageGenTool.fields.input_image_mask,
model: Generated.ImageGenTool.fields.model,
moderation: Generated.ImageGenTool.fields.moderation,
output_compression: Generated.ImageGenTool.fields.output_compression,
output_format: Generated.ImageGenTool.fields.output_format,
partial_images: Generated.ImageGenTool.fields.partial_images,
quality: Generated.ImageGenTool.fields.quality,
size: Generated.ImageGenTool.fields.size
}),
success: Schema.Struct({
result: Generated.ImageGenToolCall.fields.result
})
})
/**
* Defines the OpenAI Local Shell tool that enables the model to run a command with a local
* shell. This local tool runs in your environment and requires a handler to
* execute commands.
*
* **When to use**
*
* Use to let an OpenAI model request local shell commands that your application
* executes through a handler.
*
* **Details**
*
* The tool exposes a provider-defined `local_shell` call. It is marked as
* handler-required, so applications must provide the command execution policy
* and implementation.
*
* @category tools
* @since 4.0.0
*/
export const LocalShell = Tool.providerDefined({
id: "openai.local_shell",
customName: "OpenAiLocalShell",
providerName: "local_shell",
requiresHandler: true,
parameters: Schema.Struct({
action: Generated.LocalShellToolCall.fields.action
}),
success: Schema.Struct({
output: Generated.LocalShellToolCallOutput.fields.output
})
})
/**
* Defines the OpenAI MCP tool that gives the model access to additional tools via remote
* Model Context Protocol (MCP) servers.
*
* **When to use**
*
* Use to let an OpenAI model call tools exposed by a remote MCP server.
*
* **Details**
*
* The tool accepts MCP server configuration such as allowed tools,
* authorization, connector id, approval requirements, server metadata, and
* server URL. Tool call results include the called tool name, arguments, output,
* error, and server label.
*
* **Gotchas**
*
* This schema leaves both `server_url` and `connector_id` optional, but OpenAI
* may require a server URL or connector id for a usable MCP tool configuration.
*
* @category tools
* @since 4.0.0
*/
export const Mcp = Tool.providerDefined({
id: "openai.mcp",
customName: "OpenAiMcp",
providerName: "mcp",
args: Schema.Struct({
allowed_tools: Generated.MCPTool.fields.allowed_tools,
authorization: Generated.MCPTool.fields.authorization,
connector_id: Generated.MCPTool.fields.connector_id,
require_approval: Generated.MCPTool.fields.require_approval,
server_description: Generated.MCPTool.fields.server_description,
server_label: Generated.MCPTool.fields.server_label,
server_url: Generated.MCPTool.fields.server_url
}),
parameters: Schema.Unknown,
success: Schema.Struct({
type: Generated.MCPToolCall.fields.type,
name: Generated.MCPToolCall.fields.name,
arguments: Generated.MCPToolCall.fields.arguments,
output: Generated.MCPToolCall.fields.output,
error: Generated.MCPToolCall.fields.error,
server_label: Generated.MCPToolCall.fields.server_label
})
})
/**
* Defines the OpenAI shell tool for model-requested command execution.
*
* **When to use**
*
* Use to let an OpenAI model request shell commands that your application
* executes through a handler.
*
* **Details**
*
* The tool exposes a provider-defined `shell` call. It is marked as
* handler-required, so applications must provide the command execution policy
* and implementation.
*
* @category tools
* @since 4.0.0
*/
export const Shell = Tool.providerDefined({
id: "openai.shell",
customName: "OpenAiShell",
providerName: "shell",
requiresHandler: true,
parameters: Schema.Struct({
action: Generated.FunctionShellCall.fields.action
}),
success: Schema.Struct({
output: Generated.FunctionShellCallOutput.fields.output
})
})
/**
* Defines the OpenAI Web Search tool that enables the model to search the web for
* information.
*
* **When to use**
*
* Use to enable OpenAI provider-defined web search for a model response.
*
* **Details**
*
* The tool accepts optional filters, user location, and search context size.
* Successful calls expose the performed search action and status.
*
* @see {@link WebSearchPreview} for the preview web search provider tool
*
* @category tools
* @since 4.0.0
*/
export const WebSearch = Tool.providerDefined({
id: "openai.web_search",
customName: "OpenAiWebSearch",
providerName: "web_search",
args: Schema.Struct({
filters: Generated.WebSearchTool.fields.filters,
user_location: Generated.WebSearchTool.fields.user_location,
search_context_size: Generated.WebSearchTool.fields.search_context_size
}),
parameters: Schema.Struct({
action: Generated.WebSearchToolCall.fields.action
}),
success: Schema.Struct({
action: Generated.WebSearchToolCall.fields.action,
status: Generated.WebSearchToolCall.fields.status
})
})
/**
* Defines the OpenAI preview Web Search tool for model responses.
*
* **When to use**
*
* Use to enable the preview OpenAI web search provider tool.
*
* **Details**
*
* The preview tool accepts optional user location and search context size, then
* exposes the performed search action and status in successful calls.
*
* @see {@link WebSearch} for the stable web search provider tool
*
* @category tools
* @since 4.0.0
*/
export const WebSearchPreview = Tool.providerDefined({
id: "openai.web_search_preview",
customName: "OpenAiWebSearchPreview",
providerName: "web_search_preview",
args: Schema.Struct({
user_location: Generated.WebSearchPreviewTool.fields.user_location,
search_context_size: Generated.WebSearchPreviewTool.fields.search_context_size
}),
success: Schema.Struct({
action: Generated.WebSearchToolCall.fields.action,
status: Generated.WebSearchToolCall.fields.status
})
})

View File

@@ -0,0 +1,55 @@
/**
* @since 4.0.0
*/
// @barrel: Auto-generated exports. Do not edit manually.
/**
* @since 1.0.0
*/
export * as Generated from "./Generated.ts"
/**
* @since 4.0.0
*/
export * as OpenAiClient from "./OpenAiClient.ts"
/**
* @since 4.0.0
*/
export * as OpenAiClientGenerated from "./OpenAiClientGenerated.ts"
/**
* @since 4.0.0
*/
export * as OpenAiConfig from "./OpenAiConfig.ts"
/**
* @since 4.0.0
*/
export * as OpenAiEmbeddingModel from "./OpenAiEmbeddingModel.ts"
/**
* @since 4.0.0
*/
export * as OpenAiError from "./OpenAiError.ts"
/**
* @since 4.0.0
*/
export * as OpenAiLanguageModel from "./OpenAiLanguageModel.ts"
/**
* @since 4.0.0
*/
export * as OpenAiSchema from "./OpenAiSchema.ts"
/**
* @since 4.0.0
*/
export * as OpenAiTelemetry from "./OpenAiTelemetry.ts"
/**
* @since 4.0.0
*/
export * as OpenAiTool from "./OpenAiTool.ts"

View File

@@ -0,0 +1,349 @@
import * as Duration from "effect/Duration"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import * as Number from "effect/Number"
import * as Option from "effect/Option"
import * as Predicate from "effect/Predicate"
import * as Redactable from "effect/Redactable"
import * as Schema from "effect/Schema"
import * as AiError from "effect/unstable/ai/AiError"
import type * as Response from "effect/unstable/ai/Response"
import type * as HttpClientError from "effect/unstable/http/HttpClientError"
import type * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import type * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
import type { OpenAiErrorMetadata } from "../OpenAiError.ts"
// =============================================================================
// OpenAI Error Body Schema
// =============================================================================
/** @internal */
export const OpenAiErrorBody = Schema.Struct({
error: Schema.Struct({
message: Schema.String,
type: Schema.optional(Schema.NullOr(Schema.String)),
param: Schema.optional(Schema.NullOr(Schema.String)),
code: Schema.optional(Schema.NullOr(Schema.String))
})
})
// =============================================================================
// Error Mappers
// =============================================================================
/** @internal */
export const mapSchemaError = dual<
(method: string) => (error: Schema.SchemaError) => AiError.AiError,
(error: Schema.SchemaError, method: string) => AiError.AiError
>(2, (error, method) =>
AiError.make({
module: "OpenAiClient",
method,
reason: AiError.InvalidOutputError.fromSchemaError(error)
}))
/** @internal */
export const mapHttpClientError = dual<
(method: string) => (error: HttpClientError.HttpClientError) => Effect.Effect<never, AiError.AiError>,
(error: HttpClientError.HttpClientError, method: string) => Effect.Effect<never, AiError.AiError>
>(2, (error, method) => {
const reason = error.reason
switch (reason._tag) {
case "TransportError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.NetworkError({
reason: "TransportError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "EncodeError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.NetworkError({
reason: "EncodeError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "InvalidUrlError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.NetworkError({
reason: "InvalidUrlError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "StatusCodeError": {
return mapStatusCodeError(reason, method)
}
case "DecodeError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.InvalidOutputError({
description: reason.description ?? "Failed to decode response"
})
}))
}
case "EmptyBodyError": {
return Effect.fail(AiError.make({
module: "OpenAiClient",
method,
reason: new AiError.InvalidOutputError({
description: reason.description ?? "Response body was empty"
})
}))
}
}
})
/** @internal */
const mapStatusCodeError = Effect.fnUntraced(function*(
error: HttpClientError.StatusCodeError,
method: string
) {
const { request, response, description } = error
const status = response.status
const headers = response.headers as Record<string, string>
const requestId = headers["x-request-id"]
// Try to get the actual response body. The description from filterStatusOk
// is often just "non 2xx status code", so try reading from response.text
let body: string | undefined = description
if (!description || !description.startsWith("{")) {
const responseBody = yield* Effect.option(response.text)
if (Option.isSome(responseBody) && responseBody.value) {
body = responseBody.value
}
}
// Try to parse the body as JSON to extract error details
let json: unknown = undefined
// @effect-diagnostics effect/tryCatchInEffectGen:off
try {
json = Predicate.isNotUndefined(body) ? JSON.parse(body) : undefined
} catch {
json = undefined
}
const decoded = Schema.decodeUnknownOption(OpenAiErrorBody)(json)
const reason = mapStatusCodeToReason({
status,
headers,
message: Option.isSome(decoded) ? decoded.value.error.message : undefined,
http: buildHttpContext({ request, response, body }),
metadata: {
errorCode: Option.isSome(decoded) ? decoded.value.error.code ?? null : null,
errorType: Option.isSome(decoded) ? decoded.value.error.type ?? null : null,
requestId: requestId ?? null
}
})
return yield* AiError.make({ module: "OpenAiClient", method, reason })
})
// =============================================================================
// Rate Limits
// =============================================================================
/** @internal */
export const parseRateLimitHeaders = (headers: Record<string, string>) => {
const retryAfterRaw = headers["retry-after"]
let retryAfter: Duration.Duration | undefined
if (Predicate.isNotUndefined(retryAfterRaw)) {
const parsed = Number.parse(retryAfterRaw)
if (Option.isSome(parsed)) {
retryAfter = Duration.seconds(parsed.value)
}
}
const remainingRaw = headers["x-ratelimit-remaining-requests"]
const remaining = Predicate.isNotUndefined(remainingRaw)
? Option.getOrNull(Number.parse(remainingRaw))
: null
return {
retryAfter,
limit: headers["x-ratelimit-limit-requests"] ?? null,
remaining,
resetRequests: headers["x-ratelimit-reset-requests"] ?? null,
resetTokens: headers["x-ratelimit-reset-tokens"] ?? null
}
}
// =============================================================================
// HTTP Context
// =============================================================================
/** @internal */
export const buildHttpRequestDetails = (
request: HttpClientRequest.HttpClientRequest
): typeof Response.HttpRequestDetails.Type => ({
method: request.method,
url: request.url,
urlParams: Array.from(request.urlParams),
hash: Option.getOrUndefined(request.hash),
headers: Redactable.redact(request.headers) as Record<string, string>
})
/** @internal */
export const buildHttpContext = (params: {
readonly request: HttpClientRequest.HttpClientRequest
readonly response?: HttpClientResponse.HttpClientResponse
readonly body?: string | undefined
}): typeof AiError.HttpContext.Type => ({
request: buildHttpRequestDetails(params.request),
response: Predicate.isNotUndefined(params.response)
? {
status: params.response.status,
headers: Redactable.redact(params.response.headers) as Record<string, string>
}
: undefined,
body: params.body
})
// =============================================================================
// HTTP Status Code
// =============================================================================
const buildInvalidRequestDescription = (params: {
readonly status: number
readonly message: string | undefined
readonly method: string
readonly url: string
readonly errorCode: string | null
readonly errorType: string | null
readonly requestId: string | null
readonly body: string | undefined
}): string => {
const parts: Array<string> = []
// Primary message or status description
if (params.message) {
parts.push(params.message)
} else {
parts.push(`HTTP ${params.status}`)
}
// Request context
parts.push(`(${params.method} ${params.url})`)
// Error code/type if available
if (params.errorCode) {
parts.push(`[code: ${params.errorCode}]`)
} else if (params.errorType) {
parts.push(`[type: ${params.errorType}]`)
}
// Request ID for debugging
if (params.requestId) {
parts.push(`[requestId: ${params.requestId}]`)
}
// If no message and we have body, show truncated body
if (!params.message && params.body) {
const truncated = params.body.length > 200
? params.body.slice(0, 200) + "..."
: params.body
parts.push(`Response: ${truncated}`)
}
return parts.join(" ")
}
/** @internal */
export const mapStatusCodeToReason = ({ status, headers, message, metadata, http }: {
readonly status: number
readonly headers: Record<string, string>
readonly message: string | undefined
readonly metadata: OpenAiErrorMetadata
readonly http: typeof AiError.HttpContext.Type
}): AiError.AiErrorReason => {
const invalidRequestDescription = buildInvalidRequestDescription({
status,
message,
method: http.request.method,
url: http.request.url,
errorCode: metadata.errorCode,
errorType: metadata.errorType,
requestId: metadata.requestId,
body: http.body
})
switch (status) {
case 400:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { openai: metadata },
http
})
case 401:
return new AiError.AuthenticationError({
kind: "InvalidKey",
metadata,
http
})
case 403:
return new AiError.AuthenticationError({
kind: "InsufficientPermissions",
metadata,
http
})
case 404:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { openai: metadata },
http
})
case 409:
case 422:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { openai: metadata },
http
})
case 429: {
// Best-effort detection: OpenAI returns insufficient_quota for billing/quota issues
if (
metadata.errorCode === "insufficient_quota" ||
metadata.errorType === "insufficient_quota"
) {
return new AiError.QuotaExhaustedError({
metadata: { openai: metadata },
http
})
}
const { retryAfter, ...rateLimitMetadata } = parseRateLimitHeaders(headers)
return new AiError.RateLimitError({
retryAfter,
metadata: {
openai: {
...metadata,
...rateLimitMetadata
}
},
http
})
}
default:
if (status >= 500) {
return new AiError.InternalProviderError({
description: message ?? "Server error",
metadata,
http
})
}
return new AiError.UnknownError({
description: message,
metadata,
http
})
}
}

View File

@@ -0,0 +1,27 @@
import type * as Response from "effect/unstable/ai/Response"
const finishReasonMap: Record<string, Response.FinishReason> = {
content_filter: "content-filter",
function_call: "tool-calls",
length: "length",
stop: "stop",
tool_calls: "tool-calls"
}
/** @internal */
export const escapeJSONDelta = (delta: string): string => JSON.stringify(delta).slice(1, -1)
/** @internal */
export const resolveFinishReason = (
finishReason: string | null | undefined,
hasToolCalls: boolean
): Response.FinishReason => {
if (finishReason == null) {
return hasToolCalls ? "tool-calls" : "stop"
}
const reason = finishReasonMap[finishReason]
if (reason == null) {
return hasToolCalls ? "tool-calls" : "unknown"
}
return reason
}

View File

@@ -0,0 +1,798 @@
import type * as Generated from "@effect/ai-openai/Generated"
import * as Errors from "@effect/ai-openai/internal/errors"
import * as OpenAiClient from "@effect/ai-openai/OpenAiClient"
import * as OpenAiClientGenerated from "@effect/ai-openai/OpenAiClientGenerated"
import * as OpenAiConfig from "@effect/ai-openai/OpenAiConfig"
import { assert, describe, it } from "@effect/vitest"
import { Config, ConfigProvider, Effect, Layer, Redacted, Schema, Stream } from "effect"
import type * as AiError from "effect/unstable/ai/AiError"
import * as HttpClient from "effect/unstable/http/HttpClient"
import * as HttpClientError from "effect/unstable/http/HttpClientError"
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
// =============================================================================
// Mock Helpers
// =============================================================================
const makeMockResponse = (options: {
readonly status: number
readonly body: unknown
readonly request?: HttpClientRequest.HttpClientRequest
}): HttpClientResponse.HttpClientResponse => {
// Always use a plain request for the response to avoid Redacted headers in error contexts
const request = HttpClientRequest.get(options.request?.url ?? "/")
const json = JSON.stringify(options.body)
return HttpClientResponse.fromWeb(
request,
new Response(json, {
status: options.status,
headers: { "content-type": "application/json" }
})
)
}
const makeMockStreamResponse = (options: {
readonly events: ReadonlyArray<unknown>
readonly request?: HttpClientRequest.HttpClientRequest
}): HttpClientResponse.HttpClientResponse => {
const request = HttpClientRequest.get(options.request?.url ?? "/")
const body = options.events.map((event) => `data: ${JSON.stringify(event)}\n\n`).join("")
return HttpClientResponse.fromWeb(
request,
new Response(body, {
status: 200,
headers: { "content-type": "text/event-stream" }
})
)
}
const makeMockHttpClient = (
handler: (
request: HttpClientRequest.HttpClientRequest
) => Effect.Effect<HttpClientResponse.HttpClientResponse, HttpClientError.HttpClientError>
): HttpClient.HttpClient =>
HttpClient.makeWith<HttpClientError.HttpClientError, never, HttpClientError.HttpClientError, never>(
(effect) =>
Effect.flatMap(effect, handler) as Effect.Effect<
HttpClientResponse.HttpClientResponse,
HttpClientError.HttpClientError,
never
>,
Effect.succeed
)
const makeResponseBody = (
overrides: Partial<typeof Generated.Response.Encoded> = {}
): typeof Generated.Response.Encoded => ({
id: "resp_test123",
object: "response",
created_at: 1,
model: "gpt-4o-mini",
status: "completed",
output: [],
metadata: null,
temperature: null,
top_p: null,
tools: [],
tool_choice: "auto",
error: null,
incomplete_details: null,
instructions: null,
parallel_tool_calls: false,
...overrides
})
// =============================================================================
// Tests
// =============================================================================
describe("OpenAiClient", () => {
describe("make", () => {
it.effect("sets Bearer token from apiKey", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: {}, request }))
})
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("sk-test-12345")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
// Call method and ignore response parsing errors - we only care about the request
yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(Effect.ignore)
assert.isDefined(capturedRequest)
const authHeader = capturedRequest!.headers["authorization"]
assert.strictEqual(authHeader, "Bearer sk-test-12345")
}))
it.effect("prepends default URL", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: {}, request }))
})
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(Effect.ignore)
assert.isDefined(capturedRequest)
assert.isTrue(capturedRequest!.url.startsWith("https://api.openai.com/v1"))
}))
it.effect("uses custom apiUrl when provided", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: {}, request }))
})
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key"),
apiUrl: "https://custom.api.com/v2"
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(Effect.ignore)
assert.isDefined(capturedRequest)
assert.isTrue(capturedRequest!.url.startsWith("https://custom.api.com/v2"))
}))
it.effect("sets OpenAI-Organization header when organizationId provided", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: {}, request }))
})
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key"),
organizationId: Redacted.make("org-12345")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(Effect.ignore)
assert.isDefined(capturedRequest)
assert.strictEqual(capturedRequest!.headers["openai-organization"], "org-12345")
}))
it.effect("sets OpenAI-Project header when projectId provided", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: {}, request }))
})
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key"),
projectId: Redacted.make("proj-67890")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(Effect.ignore)
assert.isDefined(capturedRequest)
assert.strictEqual(capturedRequest!.headers["openai-project"], "proj-67890")
}))
it.effect("applies transformClient option", () =>
Effect.gen(function*() {
let transformApplied = false
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({ status: 200, body: {}, request }))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key"),
transformClient: (client) => {
transformApplied = true
return client
}
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(Effect.ignore)
assert.isTrue(transformApplied)
}))
it.effect("exposes transformed HttpClient via client field", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: {}, request }))
})
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key"),
transformClient: (client) =>
client.pipe(HttpClient.mapRequest(HttpClientRequest.setHeader("x-client-field", "enabled")))
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.client.execute(HttpClientRequest.get("/responses")).pipe(Effect.ignore)
assert.isDefined(capturedRequest)
assert.isTrue(capturedRequest!.url.startsWith("https://api.openai.com/v1"))
assert.strictEqual(capturedRequest!.headers["authorization"], "Bearer test-key")
assert.strictEqual(capturedRequest!.headers["x-client-field"], "enabled")
}))
it.effect("applies OpenAiConfig transformClient after options transformClient", () =>
Effect.gen(function*() {
let optionsTransformApplied = false
let configTransformApplied = false
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: makeResponseBody(), request }))
})
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key"),
transformClient: (client) => {
optionsTransformApplied = true
return client.pipe(
HttpClient.mapRequest(HttpClientRequest.setHeader("x-openai-transform", "options"))
)
}
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({
model: "gpt-4o",
input: "test"
}).pipe(
OpenAiConfig.withClientTransform((client) => {
configTransformApplied = true
return client.pipe(
HttpClient.mapRequest(HttpClientRequest.setHeader("x-openai-transform", "config"))
)
})
)
assert.isTrue(optionsTransformApplied)
assert.isTrue(configTransformApplied)
assert.isDefined(capturedRequest)
assert.strictEqual(capturedRequest!.headers["x-openai-transform"], "config")
}))
})
describe("OpenAiClientGenerated", () => {
it.effect("sets Bearer token from apiKey", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: makeResponseBody(), request }))
})
const client = yield* OpenAiClientGenerated.make({
apiKey: Redacted.make("sk-generated-test")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({
payload: {
model: "gpt-4o",
input: "test"
}
})
assert.isDefined(capturedRequest)
assert.strictEqual(capturedRequest!.headers["authorization"], "Bearer sk-generated-test")
}))
it.effect("prepends custom apiUrl", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: makeResponseBody(), request }))
})
const client = yield* OpenAiClientGenerated.make({
apiKey: Redacted.make("test-key"),
apiUrl: "https://generated.example.test/v2"
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({
payload: {
model: "gpt-4o",
input: "test"
}
})
assert.isDefined(capturedRequest)
assert.isTrue(capturedRequest!.url.startsWith("https://generated.example.test/v2"))
}))
it.effect("applies OpenAiConfig transformClient after options transformClient", () =>
Effect.gen(function*() {
let optionsTransformApplied = false
let configTransformApplied = false
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const mockClient = makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: makeResponseBody(), request }))
})
const client = yield* OpenAiClientGenerated.make({
apiKey: Redacted.make("test-key"),
transformClient: (client) => {
optionsTransformApplied = true
return client.pipe(
HttpClient.mapRequest(HttpClientRequest.setHeader("x-openai-transform", "options"))
)
}
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
yield* client.createResponse({
payload: {
model: "gpt-4o",
input: "test"
}
}).pipe(
OpenAiConfig.withClientTransform((client) => {
configTransformApplied = true
return client.pipe(
HttpClient.mapRequest(HttpClientRequest.setHeader("x-openai-transform", "config"))
)
})
)
assert.isTrue(optionsTransformApplied)
assert.isTrue(configTransformApplied)
assert.isDefined(capturedRequest)
assert.strictEqual(capturedRequest!.headers["x-openai-transform"], "config")
}))
})
describe("layer", () => {
it.effect("creates working service", () => {
const HttpClientLayer = Layer.succeed(
HttpClient.HttpClient,
makeMockHttpClient(() => Effect.succeed(makeMockResponse({ status: 200, body: {} })))
)
const MainLayer = OpenAiClient.layer({
apiKey: Redacted.make("test-key")
}).pipe(Layer.provide(HttpClientLayer))
return Effect.gen(function*() {
const client = yield* OpenAiClient.OpenAiClient
assert.isNotNull(client.client)
}).pipe(Effect.provide(MainLayer))
})
it.effect("layerConfig loads from Config", () => {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const HttpClientLayer = Layer.succeed(
HttpClient.HttpClient,
makeMockHttpClient((request) => {
capturedRequest = request
return Effect.succeed(makeMockResponse({ status: 200, body: {}, request }))
})
)
const configProvider = ConfigProvider.fromEnv({
env: {
MY_API_KEY: "sk-config-key",
MY_API_URL: "https://config.api.com/v1"
}
})
// Use explicit config values to test the layerConfig mechanism
// Provide explicit configs that won't fail for optional fields
const MainLayer = OpenAiClient.layerConfig({
apiKey: Config.redacted("MY_API_KEY"),
apiUrl: Config.string("MY_API_URL")
}).pipe(
Layer.provide(HttpClientLayer),
Layer.provide(ConfigProvider.layer(configProvider))
)
return Effect.gen(function*() {
const client = yield* OpenAiClient.OpenAiClient
yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(Effect.ignore)
assert.isDefined(capturedRequest)
assert.strictEqual(capturedRequest!.headers["authorization"], "Bearer sk-config-key")
assert.isTrue(capturedRequest!.url.startsWith("https://config.api.com/v1"))
}).pipe(Effect.provide(MainLayer))
})
})
describe("error mapping", () => {
it.effect("maps TransportError to NetworkError reason", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient(() =>
Effect.fail(
new HttpClientError.HttpClientError({
reason: new HttpClientError.TransportError({
request: HttpClientRequest.get("/"),
cause: new Error("Connection refused")
})
})
)
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.module, "OpenAiClient")
assert.strictEqual(result.method, "createResponse")
assert.strictEqual(result.reason._tag, "NetworkError")
}))
it.effect("maps 400 status to InvalidRequestError reason", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 400,
body: { error: { message: "Bad request" } },
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.module, "OpenAiClient")
assert.strictEqual(result.method, "createResponse")
assert.strictEqual(result.reason._tag, "InvalidRequestError")
}))
it.effect("maps 401 status to AuthenticationError reason", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 401,
body: { error: { message: "Invalid API key" } },
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.reason._tag, "AuthenticationError")
assert.strictEqual((result.reason as AiError.AuthenticationError).kind, "InvalidKey")
}))
it.effect("maps 403 status to AuthenticationError with InsufficientPermissions", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 403,
body: { error: { message: "Access denied" } },
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.reason._tag, "AuthenticationError")
assert.strictEqual((result.reason as AiError.AuthenticationError).kind, "InsufficientPermissions")
}))
it.effect("maps 429 status to RateLimitError reason", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 429,
body: { error: { message: "Rate limit exceeded", type: "rate_limit_error", code: null } },
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.reason._tag, "RateLimitError")
assert.isTrue(result.isRetryable)
}))
it.effect("maps 429 with insufficient_quota code to QuotaExhaustedError", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 429,
body: {
error: {
message: "You exceeded your current quota",
type: "insufficient_quota",
code: "insufficient_quota"
}
},
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.reason._tag, "QuotaExhaustedError")
assert.isFalse(result.isRetryable)
}))
it("mapStatusCodeToReason detects insufficient_quota as QuotaExhaustedError", () => {
const http = {
request: {
method: "POST" as const,
url: "https://api.openai.com",
urlParams: [],
hash: undefined,
headers: {}
}
}
const reason = Errors.mapStatusCodeToReason({
status: 429,
headers: {},
message: "You exceeded your current quota",
metadata: {
errorCode: "insufficient_quota",
errorType: "insufficient_quota",
requestId: null
},
http
})
assert.strictEqual(reason._tag, "QuotaExhaustedError")
})
it("OpenAiErrorBody decodes error with type and code", () => {
const json = {
error: {
message: "You exceeded your current quota",
type: "insufficient_quota",
code: "insufficient_quota"
}
}
const decoded = Schema.decodeUnknownSync(Errors.OpenAiErrorBody)(json)
assert.strictEqual(decoded.error.message, "You exceeded your current quota")
assert.strictEqual(decoded.error.type, "insufficient_quota")
assert.strictEqual(decoded.error.code, "insufficient_quota")
})
it.effect("maps 5xx status to InternalProviderError reason", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 500,
body: { error: { message: "Internal server error" } },
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.reason._tag, "InternalProviderError")
assert.isTrue(result.isRetryable)
}))
it.effect("maps schema error to InvalidOutputError reason", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 200,
body: { invalid: "response" },
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createResponse({ model: "gpt-4o", input: "test" }).pipe(
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.method, "createResponse")
assert.strictEqual(result.reason._tag, "InvalidOutputError")
}))
})
describe("createEmbedding", () => {
it.effect("maps 400 error to AiError", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 400,
body: { error: { message: "Invalid model" } },
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createEmbedding({
model: "invalid-model",
input: "test"
}).pipe(Effect.flip)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.method, "createEmbedding")
assert.strictEqual(result.reason._tag, "InvalidRequestError")
}))
it.effect("maps 429 error to RateLimitError", () =>
Effect.gen(function*() {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 429,
body: { error: { message: "Rate limit exceeded" } },
request
}))
)
const client = yield* OpenAiClient.make({
apiKey: Redacted.make("test-key")
}).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, mockClient)))
const result = yield* client.createEmbedding({
model: "text-embedding-ada-002",
input: "test"
}).pipe(Effect.flip)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.reason._tag, "RateLimitError")
}))
})
describe("createResponseStream", () => {
it.effect("accepts keepalive stream events", () => {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockStreamResponse({
request,
events: [
{
type: "response.created",
sequence_number: 1,
response: makeResponseBody({
id: "resp_stream",
status: "in_progress"
})
},
{
type: "keepalive",
sequence_number: 2
},
{
type: "response.completed",
sequence_number: 3,
response: makeResponseBody({
id: "resp_stream"
})
}
]
}))
)
const HttpClientLayer = Layer.succeed(HttpClient.HttpClient, mockClient)
const MainLayer = OpenAiClient.layer({
apiKey: Redacted.make("test-key")
}).pipe(Layer.provide(HttpClientLayer))
return Effect.gen(function*() {
const client = yield* OpenAiClient.OpenAiClient
const [_, stream] = yield* client.createResponseStream({
model: "gpt-4o",
input: "test"
})
const events = yield* Stream.runCollect(stream)
const parts = globalThis.Array.from(events)
assert.strictEqual(parts.length, 3)
const keepAlive = parts[1]
assert.strictEqual(keepAlive.type, "keepalive")
if (keepAlive.type === "keepalive" && "sequence_number" in keepAlive) {
assert.strictEqual(keepAlive.sequence_number, 2)
}
const completed = parts[2]
assert.isTrue(typeof completed === "object" && completed !== null && "type" in completed)
if (typeof completed === "object" && completed !== null && "type" in completed) {
assert.strictEqual(completed.type, "response.completed")
if (
completed.type === "response.completed" &&
"response" in completed &&
typeof completed.response === "object" &&
completed.response !== null &&
"id" in completed.response
) {
assert.strictEqual(completed.response.id, "resp_stream")
}
}
}).pipe(Effect.provide(MainLayer))
})
it.effect("maps HTTP error before stream starts", () => {
const mockClient = makeMockHttpClient((request) =>
Effect.succeed(makeMockResponse({
status: 500,
body: { error: { message: "Server error" } },
request
}))
)
const HttpClientLayer = Layer.succeed(HttpClient.HttpClient, mockClient)
const MainLayer = OpenAiClient.layer({
apiKey: Redacted.make("test-key")
}).pipe(Layer.provide(HttpClientLayer))
return Effect.gen(function*() {
const client = yield* OpenAiClient.OpenAiClient
const result = yield* client.createResponseStream({
model: "gpt-4o",
input: "test"
}).pipe(
Effect.andThen(([_, stream]) => Stream.runDrain(stream)),
Effect.flip
)
assert.strictEqual(result._tag, "AiError")
assert.strictEqual(result.reason._tag, "InternalProviderError")
}).pipe(Effect.provide(MainLayer))
})
})
})

View File

@@ -0,0 +1,289 @@
import { OpenAiClient, OpenAiEmbeddingModel } from "@effect/ai-openai"
import { assert, describe, it } from "@effect/vitest"
import { Effect, Layer, Redacted } from "effect"
import { EmbeddingModel } from "effect/unstable/ai"
import { HttpClient, type HttpClientError, type HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
describe("OpenAiEmbeddingModel", () => {
it.effect("model provides dimensions service", () =>
Effect.gen(function*() {
const dimensions = yield* EmbeddingModel.Dimensions
assert.strictEqual(dimensions, 1536)
}).pipe(
Effect.provide(OpenAiEmbeddingModel.model("text-embedding-3-small", { dimensions: 1536 })),
Effect.provideService(OpenAiClient.OpenAiClient, noopOpenAiClient)
))
it.effect("reorders embeddings by provider index", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, {
data: [
{ index: 1, embedding: [20, 21], object: "embedding" },
{ index: 0, embedding: [10, 11], object: "embedding" }
],
model: "text-embedding-3-small",
object: "list",
usage: {
prompt_tokens: 7,
total_tokens: 7
}
}))
})
))
)
const response = yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
return yield* model.embedMany(["first", "second"])
}).pipe(
Effect.provide(OpenAiEmbeddingModel.layer({ model: "text-embedding-3-small" })),
Effect.provide(clientLayer)
)
assert.deepStrictEqual(response.embeddings.map((embedding) => embedding.vector), [[10, 11], [20, 21]])
assert.strictEqual(response.usage.inputTokens, 7)
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const requestBody = yield* getRequestBody(capturedRequest)
assert.strictEqual(requestBody.model, "text-embedding-3-small")
assert.deepStrictEqual(requestBody.input, ["first", "second"])
}))
it.effect("merges config and applies withConfigOverride precedence", () =>
Effect.gen(function*() {
let capturedRequest: HttpClientRequest.HttpClientRequest | undefined
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) => {
capturedRequest = request
return Effect.succeed(jsonResponse(request, {
data: [{ index: 0, embedding: [1, 2, 3], object: "embedding" }],
model: "override-model",
object: "list",
usage: {
prompt_tokens: 3,
total_tokens: 3
}
}))
})
))
)
yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
yield* model.embed("hello")
}).pipe(
OpenAiEmbeddingModel.withConfigOverride({
model: "override-model",
dimensions: 1024,
user: "request-user"
}),
Effect.provide(OpenAiEmbeddingModel.layer({
model: "base-model",
config: {
dimensions: 256,
user: "provider-user"
}
})),
Effect.provide(clientLayer)
)
assert.isDefined(capturedRequest)
if (capturedRequest === undefined) {
return
}
const requestBody = yield* getRequestBody(capturedRequest)
assert.strictEqual(requestBody.model, "override-model")
assert.strictEqual(requestBody.dimensions, 1024)
assert.strictEqual(requestBody.user, "request-user")
assert.deepStrictEqual(requestBody.input, ["hello"])
}))
it.effect("fails with InvalidOutputError when provider returns duplicate indices", () =>
Effect.gen(function*() {
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(jsonResponse(request, {
data: [
{ index: 0, embedding: [1], object: "embedding" },
{ index: 0, embedding: [2], object: "embedding" }
],
model: "text-embedding-3-small",
object: "list",
usage: {
prompt_tokens: 2,
total_tokens: 2
}
}))
)
))
)
const error = yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
return yield* model.embedMany(["a", "b"]).pipe(Effect.flip)
}).pipe(
Effect.provide(OpenAiEmbeddingModel.layer({ model: "text-embedding-3-small" })),
Effect.provide(clientLayer)
)
assert.strictEqual(error._tag, "AiError")
assert.strictEqual(error.reason._tag, "InvalidOutputError")
}))
it.effect("fails with InvalidOutputError when provider returns out-of-range indices", () =>
Effect.gen(function*() {
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(jsonResponse(request, {
data: [
{ index: 0, embedding: [1], object: "embedding" },
{ index: 2, embedding: [2], object: "embedding" }
],
model: "text-embedding-3-small",
object: "list",
usage: {
prompt_tokens: 2,
total_tokens: 2
}
}))
)
))
)
const error = yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
return yield* model.embedMany(["a", "b"]).pipe(Effect.flip)
}).pipe(
Effect.provide(OpenAiEmbeddingModel.layer({ model: "text-embedding-3-small" })),
Effect.provide(clientLayer)
)
assert.strictEqual(error._tag, "AiError")
assert.strictEqual(error.reason._tag, "InvalidOutputError")
}))
it.effect("fails with InvalidOutputError when provider returns wrong embedding count", () =>
Effect.gen(function*() {
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(jsonResponse(request, {
data: [{ index: 0, embedding: [1], object: "embedding" }],
model: "text-embedding-3-small",
object: "list",
usage: {
prompt_tokens: 1,
total_tokens: 1
}
}))
)
))
)
const error = yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
return yield* model.embedMany(["a", "b"]).pipe(Effect.flip)
}).pipe(
Effect.provide(OpenAiEmbeddingModel.layer({ model: "text-embedding-3-small" })),
Effect.provide(clientLayer)
)
assert.strictEqual(error._tag, "AiError")
assert.strictEqual(error.reason._tag, "InvalidOutputError")
}))
it.effect("fails with InvalidOutputError when provider returns base64 embeddings", () =>
Effect.gen(function*() {
const clientLayer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provide(Layer.succeed(
HttpClient.HttpClient,
makeHttpClient((request) =>
Effect.succeed(jsonResponse(request, {
data: [{ index: 0, embedding: "AQID", object: "embedding" }],
model: "text-embedding-3-small",
object: "list",
usage: {
prompt_tokens: 1,
total_tokens: 1
}
}))
)
))
)
const error = yield* Effect.gen(function*() {
const model = yield* EmbeddingModel.EmbeddingModel
return yield* model.embed("a").pipe(Effect.flip)
}).pipe(
Effect.provide(OpenAiEmbeddingModel.layer({ model: "text-embedding-3-small" })),
Effect.provide(clientLayer)
)
assert.strictEqual(error._tag, "AiError")
assert.strictEqual(error.reason._tag, "InvalidOutputError")
}))
})
const makeHttpClient = (
handler: (
request: HttpClientRequest.HttpClientRequest
) => Effect.Effect<HttpClientResponse.HttpClientResponse, HttpClientError.HttpClientError>
) =>
HttpClient.makeWith(
Effect.fnUntraced(function*(requestEffect) {
const request = yield* requestEffect
return yield* handler(request)
}),
Effect.succeed as HttpClient.HttpClient.Preprocess<HttpClientError.HttpClientError, never>
)
const jsonResponse = (
request: HttpClientRequest.HttpClientRequest,
body: unknown
): HttpClientResponse.HttpClientResponse =>
HttpClientResponse.fromWeb(
request,
new Response(JSON.stringify(body), {
status: 200,
headers: {
"content-type": "application/json"
}
})
)
const getRequestBody = (request: HttpClientRequest.HttpClientRequest) =>
Effect.gen(function*() {
const body = request.body
if (body._tag === "Uint8Array") {
const text = new TextDecoder().decode(body.body)
return JSON.parse(text)
}
return yield* Effect.die(new Error("Expected Uint8Array body"))
})
const noopOpenAiClient: OpenAiClient.Service = {
client: undefined as unknown as OpenAiClient.Service["client"],
createResponse: () => Effect.die(new Error("noop")),
createResponseStream: () => Effect.die(new Error("noop")),
createEmbedding: () => Effect.die(new Error("noop"))
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,273 @@
import * as OpenAiSchema from "@effect/ai-openai/OpenAiSchema"
import { assert, describe, it } from "@effect/vitest"
import { Effect, Schema, Stream } from "effect"
import * as Sse from "effect/unstable/encoding/Sse"
const makeResponse = (overrides: Record<string, unknown> = {}) => ({
id: "resp_123",
object: "response",
model: "gpt-4o-mini",
status: "completed",
created_at: 1,
output: [],
...overrides
})
describe("OpenAiSchema", () => {
it("decodes a representative response payload", () => {
const decoded = Schema.decodeUnknownSync(OpenAiSchema.Response)({
...makeResponse(),
output: [
{
id: "msg_1",
type: "message",
role: "assistant",
status: "completed",
content: [
{
type: "output_text",
text: "hello",
annotations: [
{
type: "url_citation",
url: "https://example.com",
start_index: 0,
end_index: 5,
title: "example"
}
]
},
{
type: "refusal",
refusal: "cannot comply"
}
]
},
{
id: "fc_1",
type: "function_call",
call_id: "call_1",
name: "lookup",
arguments: "{}",
status: "completed"
},
{
id: "reasoning_1",
type: "reasoning",
summary: [
{
type: "summary_text",
text: "thinking"
}
]
}
],
usage: {
input_tokens: 10,
output_tokens: 20,
total_tokens: 30
}
})
assert.strictEqual(decoded.id, "resp_123")
assert.strictEqual(decoded.output.length, 3)
assert.strictEqual(decoded.output[0].type, "message")
if (decoded.output[0].type === "message") {
assert.strictEqual(decoded.output[0].content[0].type, "output_text")
}
})
it("decodes required stream events", () => {
const response = makeResponse({ status: "in_progress" })
const applyPatchItem = {
id: "ap_1",
type: "apply_patch_call",
call_id: "call_ap",
operation: {
type: "update_file",
path: "README.md",
diff: "@@"
}
}
const events = [
{ type: "response.created", sequence_number: 1, response },
{
type: "response.completed",
sequence_number: 2,
response: makeResponse()
},
{ type: "response.incomplete", sequence_number: 3, response: makeResponse({ status: "incomplete" }) },
{ type: "response.failed", sequence_number: 4, response: makeResponse({ status: "failed" }) },
{ type: "response.output_item.added", sequence_number: 5, output_index: 0, item: applyPatchItem },
{ type: "response.output_item.done", sequence_number: 6, output_index: 0, item: applyPatchItem },
{
type: "response.output_text.delta",
sequence_number: 7,
item_id: "msg_1",
output_index: 0,
content_index: 0,
delta: "hel"
},
{
type: "response.output_text.annotation.added",
sequence_number: 8,
item_id: "msg_1",
output_index: 0,
content_index: 0,
annotation_index: 0,
annotation: {
type: "file_path",
file_id: "file_1",
index: 0
}
},
{
type: "response.reasoning_summary_part.added",
sequence_number: 9,
item_id: "reasoning_1",
output_index: 1,
summary_index: 0,
part: { type: "summary_text", text: "thinking" }
},
{
type: "response.reasoning_summary_part.done",
sequence_number: 10,
item_id: "reasoning_1",
output_index: 1,
summary_index: 0,
part: { type: "summary_text", text: "thinking" }
},
{
type: "response.reasoning_summary_text.delta",
sequence_number: 11,
item_id: "reasoning_1",
output_index: 1,
summary_index: 0,
delta: "..."
},
{
type: "response.function_call_arguments.delta",
sequence_number: 12,
item_id: "fc_1",
output_index: 2,
delta: "{"
},
{
type: "response.function_call_arguments.done",
sequence_number: 13,
item_id: "fc_1",
output_index: 2,
arguments: "{}"
},
{
type: "response.code_interpreter_call_code.delta",
sequence_number: 14,
item_id: "code_1",
output_index: 3,
delta: "print"
},
{
type: "response.code_interpreter_call_code.done",
sequence_number: 15,
item_id: "code_1",
output_index: 3,
code: "print('ok')"
},
{
type: "response.apply_patch_call_operation_diff.delta",
sequence_number: 16,
item_id: "ap_1",
output_index: 4,
delta: "@@"
},
{
type: "response.apply_patch_call_operation_diff.done",
sequence_number: 17,
item_id: "ap_1",
output_index: 4,
delta: "@@"
},
{
type: "response.image_generation_call.partial_image",
sequence_number: 18,
item_id: "img_1",
output_index: 5,
partial_image_b64: "AQID"
}
]
for (const event of events) {
const decoded = Schema.decodeUnknownSync(OpenAiSchema.ResponseStreamEvent)(event)
assert.strictEqual(decoded.type, event.type)
}
})
it.effect("keeps keepalive and unknown events tolerant in SSE decoding", () =>
Effect.gen(function*() {
const sseBody = [
{
type: "response.created",
sequence_number: 1,
response: makeResponse({ status: "in_progress" })
},
{
type: "keepalive",
sequence_number: 2,
heartbeat: true
},
{
type: "provider.future_event",
sequence_number: 3,
nested: { ok: true }
},
{
type: "response.completed",
sequence_number: 4,
response: makeResponse({ status: "completed" })
}
].map((event) => `data: ${JSON.stringify(event)}\n\n`).join("")
const events = yield* Stream.fromIterable([sseBody]).pipe(
Stream.pipeThroughChannel(Sse.decodeDataSchema(OpenAiSchema.ResponseStreamEvent)),
Stream.map((event) => event.data),
Stream.runCollect
)
const decoded = globalThis.Array.from(events)
assert.strictEqual(decoded.length, 4)
assert.strictEqual(decoded[1].type, "keepalive")
assert.strictEqual(decoded[2].type, "provider.future_event")
if (decoded[1].type === "keepalive") {
assert.strictEqual(decoded[1].sequence_number, 2)
}
}))
it.effect("does not silently decode malformed known events as unknown", () =>
Effect.gen(function*() {
const malformed = yield* Schema.decodeUnknownEffect(OpenAiSchema.ResponseStreamEvent)({
type: "response.completed",
sequence_number: 1
}).pipe(Effect.flip)
assert.isDefined(malformed)
}))
it("decodes embedding response variants (numeric + string/base64)", () => {
const numeric = Schema.decodeUnknownSync(OpenAiSchema.CreateEmbeddingResponse)({
object: "list",
model: "text-embedding-3-small",
data: [{ object: "embedding", index: 0, embedding: [0.1, 0.2] }],
usage: { prompt_tokens: 2, total_tokens: 2 }
})
const base64 = Schema.decodeUnknownSync(OpenAiSchema.CreateEmbeddingResponse)({
object: "list",
model: "text-embedding-3-small",
data: [{ object: "embedding", index: 0, embedding: "AQID" }],
usage: { prompt_tokens: 2, total_tokens: 2 }
})
assert.strictEqual(numeric.data[0].embedding[0], 0.1)
assert.strictEqual(base64.data[0].embedding, "AQID")
})
})

View File

@@ -0,0 +1,8 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "../../../tsconfig.base.json",
"include": ["src"],
"references": [
{ "path": "../../effect" }
]
}

View File

@@ -0,0 +1,6 @@
import { mergeConfig, type ViteUserConfig } from "vitest/config"
import shared from "../../../vitest.shared.ts"
const config: ViteUserConfig = {}
export default mergeConfig(shared, config)

View File

@@ -0,0 +1,725 @@
# @effect/ai-openrouter
## 4.0.0-beta.99
### Patch Changes
- Updated dependencies [[`8ce4795`](https://github.com/Effect-TS/effect/commit/8ce4795ccbaebca4292757db568c005a992546a4), [`80b539f`](https://github.com/Effect-TS/effect/commit/80b539f8aba68f478c75c35c2b4140c4ffc4fada), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`e6e6dba`](https://github.com/Effect-TS/effect/commit/e6e6dba6e9d86e7c2ad27dcedf289db76a19697f), [`bfb203e`](https://github.com/Effect-TS/effect/commit/bfb203e95aa439f731acad37fc3a9a831a190f1c), [`2e9a34a`](https://github.com/Effect-TS/effect/commit/2e9a34ac2bece4f3a206160480c991e3841dc67a), [`55d4eb3`](https://github.com/Effect-TS/effect/commit/55d4eb34f2c64d54f6a25a305b5c5438ebd7934e), [`bddb010`](https://github.com/Effect-TS/effect/commit/bddb010eac3d4436cb094edbbee7460c5440c162), [`a328835`](https://github.com/Effect-TS/effect/commit/a328835e50d76bc96648a1c1550456e8c9f81210), [`5560d05`](https://github.com/Effect-TS/effect/commit/5560d05aa6abdd29466d9c3412cc5e648b0adbde), [`8f6e3ad`](https://github.com/Effect-TS/effect/commit/8f6e3adb185b16e8820b98c509b308086f7ff1af), [`46997fa`](https://github.com/Effect-TS/effect/commit/46997fa60401f5e3c93daa4b61f7df8e31caaab4), [`9e6e12d`](https://github.com/Effect-TS/effect/commit/9e6e12d75c118cd265496f2880490d1f33a5c8bf), [`3394b93`](https://github.com/Effect-TS/effect/commit/3394b93d97d6f24fc38670641d1490289ffca7f1), [`febeabc`](https://github.com/Effect-TS/effect/commit/febeabc3f7c31094da000a23edeaabfe2ab00a38), [`54161c9`](https://github.com/Effect-TS/effect/commit/54161c98f6f3569e0c31842f54e6a257f9421c4c), [`385f7a4`](https://github.com/Effect-TS/effect/commit/385f7a4ee4a7359928597ea56d151dbaf5eb5802), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`7543afe`](https://github.com/Effect-TS/effect/commit/7543afea6f4d97d1f1ad876224323838a48daadd), [`44b9cf3`](https://github.com/Effect-TS/effect/commit/44b9cf3d240d726997b4bbcd0ede48e074d3c456), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`0a8aa6a`](https://github.com/Effect-TS/effect/commit/0a8aa6acb90a72b91c24d17133c950e4cacd8abd), [`c8d9fcf`](https://github.com/Effect-TS/effect/commit/c8d9fcf7b030f7c474effbab2764ce7aee1c7209), [`9ca7f9a`](https://github.com/Effect-TS/effect/commit/9ca7f9a69363e4485645966d5a93b8f9597c5206), [`e7aca89`](https://github.com/Effect-TS/effect/commit/e7aca894bb32fbb785b5830837e6061c415a6015), [`55d7560`](https://github.com/Effect-TS/effect/commit/55d75609b8acf8a1b54c1b1c7fbbb65ec741aa3e), [`f809189`](https://github.com/Effect-TS/effect/commit/f809189ddf6b6011ba43a9901baaa734e315da2a), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`0ebdbe7`](https://github.com/Effect-TS/effect/commit/0ebdbe74463dc84385956d0b1e8c2b79ebab5400), [`7517d09`](https://github.com/Effect-TS/effect/commit/7517d09f12a0b183a81bd425962c4e280a68b05d), [`212493b`](https://github.com/Effect-TS/effect/commit/212493b9a1eb98cd1ef6959c707a2e5784a5ae91), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`80ea8cb`](https://github.com/Effect-TS/effect/commit/80ea8cb9222ca73f564c8267ab2f82966fea027a), [`8df19f4`](https://github.com/Effect-TS/effect/commit/8df19f4fe81d90cc33ace88b9a77e5534f82d604)]:
- effect@4.0.0-beta.99
## 4.0.0-beta.98
### Patch Changes
- Updated dependencies [[`989603b`](https://github.com/Effect-TS/effect-smol/commit/989603b60ab1197b64acf214208e0d370cd1f842), [`214c458`](https://github.com/Effect-TS/effect-smol/commit/214c458084bb6995d543cd37d1055f24be3d454e), [`a037273`](https://github.com/Effect-TS/effect-smol/commit/a0372736ac34796969b051bbba4717d7983f1ebe), [`97fdaa9`](https://github.com/Effect-TS/effect-smol/commit/97fdaa9c1f522c65e579365d314a07878e2b904f), [`b24d248`](https://github.com/Effect-TS/effect-smol/commit/b24d248c8df44222ce642087cde2bd859a2dc709), [`19c222c`](https://github.com/Effect-TS/effect-smol/commit/19c222cac2353a3d7b7733caecb00556fffe9a5c), [`eec85dd`](https://github.com/Effect-TS/effect-smol/commit/eec85ddba09ea326fd268ee33eeffd47e50d4671), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`8849052`](https://github.com/Effect-TS/effect-smol/commit/884905232d1e9a365e046d8dde27bf9c5707f57f), [`c15e16a`](https://github.com/Effect-TS/effect-smol/commit/c15e16ad130d1fbde25d912b7ac55995066cb35b), [`01d00a3`](https://github.com/Effect-TS/effect-smol/commit/01d00a3abfbf1f37996cdbe738ea5137c646cdd7), [`8bd4589`](https://github.com/Effect-TS/effect-smol/commit/8bd458975a1b3a8ed042eccf317b93d28ded91e7), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`6e08428`](https://github.com/Effect-TS/effect-smol/commit/6e08428d980501b856f846ad3f3f0e4ea46e7786), [`388dcf9`](https://github.com/Effect-TS/effect-smol/commit/388dcf953f65d317547f34d40e6443c5f264205f), [`2b7ce2b`](https://github.com/Effect-TS/effect-smol/commit/2b7ce2b513e7ec2a77822f1116dc6ffb6ba93f4e), [`87bea7e`](https://github.com/Effect-TS/effect-smol/commit/87bea7e16259246f3bcdf565446394751abca953), [`ce38dc3`](https://github.com/Effect-TS/effect-smol/commit/ce38dc33bda805a684432cca071f4dc3c6b9a1ba), [`a807cd1`](https://github.com/Effect-TS/effect-smol/commit/a807cd170341deca8a1cfb52c4222585f2431bb9), [`fd8a356`](https://github.com/Effect-TS/effect-smol/commit/fd8a356f06a8c9ce4e7e0a13fc4021c178ed31de), [`c2a5edc`](https://github.com/Effect-TS/effect-smol/commit/c2a5edc3abd31ad5bc123362bc1213e03e4095c3), [`5946da3`](https://github.com/Effect-TS/effect-smol/commit/5946da3804a1be5e752b05b96bd058cdba50a1bf), [`4ae0c5f`](https://github.com/Effect-TS/effect-smol/commit/4ae0c5ffcbe6c56ddfcb05c639112a079483539e), [`5b2a0bc`](https://github.com/Effect-TS/effect-smol/commit/5b2a0bceea3a28a33a58555210c90a415dc74a76), [`72ac585`](https://github.com/Effect-TS/effect-smol/commit/72ac585884befde6af9208da738699a93f1bae79), [`5e8c1b8`](https://github.com/Effect-TS/effect-smol/commit/5e8c1b82bfafa121311f987a49ab75395e3647a7), [`0f9c078`](https://github.com/Effect-TS/effect-smol/commit/0f9c07841b04183f485ee6e6458de73b290b09f5)]:
- effect@4.0.0-beta.98
## 4.0.0-beta.97
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.97
## 4.0.0-beta.96
### Patch Changes
- Updated dependencies [[`1503f45`](https://github.com/Effect-TS/effect-smol/commit/1503f45cb5bb2a74f4705252ec505a1f0ade7e62), [`57fe793`](https://github.com/Effect-TS/effect-smol/commit/57fe79316ffbc380b30626a168981fb26ae97459), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`97f29df`](https://github.com/Effect-TS/effect-smol/commit/97f29df457f7ffd07cfb4b379315c12c086af805)]:
- effect@4.0.0-beta.96
## 4.0.0-beta.95
### Patch Changes
- Updated dependencies [[`a482442`](https://github.com/Effect-TS/effect-smol/commit/a482442abdeb490e9652b854ec3495e4aa7273e7), [`fbefa85`](https://github.com/Effect-TS/effect-smol/commit/fbefa850fab2f0a302c20614496aeaaa2a8b5590), [`0b4a32f`](https://github.com/Effect-TS/effect-smol/commit/0b4a32f4260f0d8500942a133001b0d349328102), [`18a49e1`](https://github.com/Effect-TS/effect-smol/commit/18a49e1786679456258002ff9397faf02f678c2d), [`266cb90`](https://github.com/Effect-TS/effect-smol/commit/266cb90bb2c17aabc40563c32db334f09ba3d74b), [`912f095`](https://github.com/Effect-TS/effect-smol/commit/912f095a34572bbd3cedf6edb27878443e3e4a95), [`a6718f9`](https://github.com/Effect-TS/effect-smol/commit/a6718f9e00a15ca903b0732da46116cbf3d6aca7), [`bef5154`](https://github.com/Effect-TS/effect-smol/commit/bef51540a243aa2f872a00c01d0cd58b7a769baa), [`18e0564`](https://github.com/Effect-TS/effect-smol/commit/18e0564bd0f8ebbdfcaf1e2c21529948e9e4a81d), [`fb50f14`](https://github.com/Effect-TS/effect-smol/commit/fb50f14fc3657c1973785aa5b72ecf0b0d28e0b2)]:
- effect@4.0.0-beta.95
## 4.0.0-beta.94
### Patch Changes
- Updated dependencies [[`95a0e9b`](https://github.com/Effect-TS/effect-smol/commit/95a0e9bb62797af0e81c9998773405f248f218c5), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63), [`f11ce73`](https://github.com/Effect-TS/effect-smol/commit/f11ce73af60823754dc24194f4ffc561b9ea1c2d), [`ff30b6e`](https://github.com/Effect-TS/effect-smol/commit/ff30b6e7c2c63ffc56a4c5818d6d86b01b5ad528), [`1caab3c`](https://github.com/Effect-TS/effect-smol/commit/1caab3cc30f626efbf15e59d74f539a487e5c85c), [`aa80c47`](https://github.com/Effect-TS/effect-smol/commit/aa80c4775a04db87553e5568764cab7e32a72814), [`c2ae4fc`](https://github.com/Effect-TS/effect-smol/commit/c2ae4fce2f03a4cd1861c2b1179da7df656e662d), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63)]:
- effect@4.0.0-beta.94
## 4.0.0-beta.93
### Patch Changes
- Updated dependencies [[`00652fe`](https://github.com/Effect-TS/effect-smol/commit/00652fe95c18f87208e91343eb8bf218faa2f677), [`6c58167`](https://github.com/Effect-TS/effect-smol/commit/6c5816746eaf91d2a3c7c899c5720809fa230ae3), [`2bc5415`](https://github.com/Effect-TS/effect-smol/commit/2bc541501a7ef89e542d7cb98e96beb53cd205cc), [`e11cccc`](https://github.com/Effect-TS/effect-smol/commit/e11cccc7d5fe631abccc7d6e3bd296938de0fa2e), [`ba7e77e`](https://github.com/Effect-TS/effect-smol/commit/ba7e77e046b8641a3a4e9750bb88ca4a1d063d3f), [`5713ee7`](https://github.com/Effect-TS/effect-smol/commit/5713ee7edbc3054efde407b2286bbfd45bbc6e1c)]:
- effect@4.0.0-beta.93
## 4.0.0-beta.92
### Patch Changes
- Updated dependencies [[`affdc13`](https://github.com/Effect-TS/effect-smol/commit/affdc139045cc325dce321a84a580fdc1b2da7b9)]:
- effect@4.0.0-beta.92
## 4.0.0-beta.91
### Patch Changes
- Updated dependencies [[`b135b25`](https://github.com/Effect-TS/effect-smol/commit/b135b2517fca9e7839734ace3699a7dfa75b9075), [`aaa21a3`](https://github.com/Effect-TS/effect-smol/commit/aaa21a369a171c600db294f2a4f640583043e150), [`3475ee6`](https://github.com/Effect-TS/effect-smol/commit/3475ee6c2bda6b05c6d7a12ce30c8bb840b5b1a6)]:
- effect@4.0.0-beta.91
## 4.0.0-beta.90
### Patch Changes
- Updated dependencies [[`d237fdf`](https://github.com/Effect-TS/effect-smol/commit/d237fdf726481f76eb52a6196e111b24122bc3d5)]:
- effect@4.0.0-beta.90
## 4.0.0-beta.89
### Patch Changes
- Updated dependencies [[`b7d46ab`](https://github.com/Effect-TS/effect-smol/commit/b7d46ab7e1a29d8711817bab583c9febf48a0dad), [`7777e15`](https://github.com/Effect-TS/effect-smol/commit/7777e1540fd3680dd8346723cffec812b9384669), [`5376197`](https://github.com/Effect-TS/effect-smol/commit/5376197ca8e50358a41b1fd3cec27bd1ec680ec6)]:
- effect@4.0.0-beta.89
## 4.0.0-beta.88
### Patch Changes
- Updated dependencies [[`911f1b8`](https://github.com/Effect-TS/effect-smol/commit/911f1b84790ce42b3a70c95b33e6f6fd9e74de8b), [`8beeeea`](https://github.com/Effect-TS/effect-smol/commit/8beeeea52879d8613a39468848f01c3092bd54d4), [`c306fcf`](https://github.com/Effect-TS/effect-smol/commit/c306fcfeb1ef38455156932a1faf49292b1318da)]:
- effect@4.0.0-beta.88
## 4.0.0-beta.87
### Patch Changes
- Updated dependencies [[`5a0c1a4`](https://github.com/Effect-TS/effect-smol/commit/5a0c1a4faee5707b5cc35e646ff1ffdad70f1956), [`1eea2ea`](https://github.com/Effect-TS/effect-smol/commit/1eea2ea3795ba47316b82b1ac8d4612c0ba389ed)]:
- effect@4.0.0-beta.87
## 4.0.0-beta.86
### Patch Changes
- Updated dependencies [[`0b5795a`](https://github.com/Effect-TS/effect-smol/commit/0b5795a0ab4395e8f15955d8d96f2303084bfc64), [`3e3a859`](https://github.com/Effect-TS/effect-smol/commit/3e3a859ec6351a9e0d31674aabbd48fcefabb12e), [`7dbec24`](https://github.com/Effect-TS/effect-smol/commit/7dbec240dbf3bca599a20c486632abce694ef5ab), [`d8c00a1`](https://github.com/Effect-TS/effect-smol/commit/d8c00a171ac7141e8adc08c332d1162d9a9d56fc), [`85b6317`](https://github.com/Effect-TS/effect-smol/commit/85b631701e935866f2762bd595237aa718370cd9), [`6d0fda0`](https://github.com/Effect-TS/effect-smol/commit/6d0fda0d0cbdfffc523c89c57dfdb1608f84fb12), [`108a933`](https://github.com/Effect-TS/effect-smol/commit/108a9335ff8571928197e5847a09c28ac83d6f46), [`7e1f455`](https://github.com/Effect-TS/effect-smol/commit/7e1f455fab5005d769b939c91e519d450f802cf9), [`46b3e79`](https://github.com/Effect-TS/effect-smol/commit/46b3e79944cfdae7901eb148135c85b7eb39834e)]:
- effect@4.0.0-beta.86
## 4.0.0-beta.85
### Patch Changes
- Updated dependencies [[`328d97c`](https://github.com/Effect-TS/effect-smol/commit/328d97cc53c0dcb89077a5623e35b095eaa59a8c), [`8441836`](https://github.com/Effect-TS/effect-smol/commit/8441836e6dde70e8ae2126be9cefe9b45798b134), [`074e436`](https://github.com/Effect-TS/effect-smol/commit/074e4361091289104cb0ab6959dc3b0ea7794a6a), [`c1dfd60`](https://github.com/Effect-TS/effect-smol/commit/c1dfd60663eb13a58916f3712d877499943b628a), [`2ba316b`](https://github.com/Effect-TS/effect-smol/commit/2ba316bd15fcbf1c50626500d44a2c9b3bec19f5), [`7ce7344`](https://github.com/Effect-TS/effect-smol/commit/7ce7344c41056c79e2ee19ee6a9346c0f1d227c1)]:
- effect@4.0.0-beta.85
## 4.0.0-beta.84
### Patch Changes
- [#2379](https://github.com/Effect-TS/effect-smol/pull/2379) [`717d1c8`](https://github.com/Effect-TS/effect-smol/commit/717d1c8b160d4de631b6b7938abcad9e3472c3d7) Thanks @walln! - Convert audio file parts in prompts into OpenRouter `input_audio` content blocks.
Previously, every non-image file part was converted into a generic `file` content block. OpenRouter only accepts audio as base64-encoded `input_audio` content parts, so audio attachments were rejected or mishandled by the upstream provider.
Audio file parts with a recognized `mediaType` (aac, aiff, flac, m4a, mp3, ogg, pcm16, pcm24, and wav) are now converted into `input_audio` blocks. Unsupported audio media types and `URL` audio data fail with an `AiError` since OpenRouter requires base64-encoded audio data and does not fetch audio URLs.
- Updated dependencies [[`87f52ba`](https://github.com/Effect-TS/effect-smol/commit/87f52ba16c4370ffa3f84bf8e53038e1419c284e), [`b8ee07f`](https://github.com/Effect-TS/effect-smol/commit/b8ee07ffda8903b5ec2e45a786ddcba59f128fda), [`867c0d7`](https://github.com/Effect-TS/effect-smol/commit/867c0d70a09079b040260d45a1e92ff04dbfbf2f), [`b93bc6c`](https://github.com/Effect-TS/effect-smol/commit/b93bc6c9cb27b909a41d094c97c4f9d25bbc6d6b), [`57d387f`](https://github.com/Effect-TS/effect-smol/commit/57d387f92c30ab63e15e3e641f0a903b65886610), [`bacca41`](https://github.com/Effect-TS/effect-smol/commit/bacca4141c2400effae1eabfdb36c89a459cf246), [`0f8ac79`](https://github.com/Effect-TS/effect-smol/commit/0f8ac7959d29ed68c68ce25aabd6bf0cb7e63ecc), [`25b4482`](https://github.com/Effect-TS/effect-smol/commit/25b448270c01317703f25107e1480d4cd0246d9a), [`9cf3a25`](https://github.com/Effect-TS/effect-smol/commit/9cf3a25c66b0c44a52be9829870c44517ea52db2), [`8def767`](https://github.com/Effect-TS/effect-smol/commit/8def7674b1787f91035298cda4d122937e87ef72)]:
- effect@4.0.0-beta.84
## 4.0.0-beta.83
### Patch Changes
- Updated dependencies [[`1f2e8ce`](https://github.com/Effect-TS/effect-smol/commit/1f2e8ceef09e0a791c850ed2ade01f97089596f9)]:
- effect@4.0.0-beta.83
## 4.0.0-beta.82
### Patch Changes
- Updated dependencies [[`193690b`](https://github.com/Effect-TS/effect-smol/commit/193690b642ea802bbed40d663bd677251bbe9dc3)]:
- effect@4.0.0-beta.82
## 4.0.0-beta.81
### Patch Changes
- Updated dependencies [[`93cb4f8`](https://github.com/Effect-TS/effect-smol/commit/93cb4f8fbfb9e07cb9dc86ce6b155fd1f8167914), [`60341d9`](https://github.com/Effect-TS/effect-smol/commit/60341d9ca744d0473ce3fab621ca9bd225af3a39), [`1105ab5`](https://github.com/Effect-TS/effect-smol/commit/1105ab56cb724212f7ea7b431396ce82e8fd0484), [`4500fbf`](https://github.com/Effect-TS/effect-smol/commit/4500fbfe00763d8a72af6e5d6c5988e8bd4ade36)]:
- effect@4.0.0-beta.81
## 4.0.0-beta.80
### Patch Changes
- Updated dependencies [[`d944330`](https://github.com/Effect-TS/effect-smol/commit/d94433090ee03f426d43e13b883abae4494e55e6), [`f48659f`](https://github.com/Effect-TS/effect-smol/commit/f48659fdcc84930ebc1e5b45b540c0f973389182), [`7652aaa`](https://github.com/Effect-TS/effect-smol/commit/7652aaa3bdbc39f241fe58b54b9a43b713e22e12), [`98630b7`](https://github.com/Effect-TS/effect-smol/commit/98630b7c8f679c352ba6796636c85688fa009d8d), [`90ae23c`](https://github.com/Effect-TS/effect-smol/commit/90ae23cf07284da5e1bcd9dffa882e85df7e617b)]:
- effect@4.0.0-beta.80
## 4.0.0-beta.79
### Patch Changes
- Updated dependencies [[`b9704dc`](https://github.com/Effect-TS/effect-smol/commit/b9704dc9de9f1649ad502371014fe869b69a49a3), [`a207113`](https://github.com/Effect-TS/effect-smol/commit/a207113f66837bb54416926718a9a7d66774d079), [`5e9b9e2`](https://github.com/Effect-TS/effect-smol/commit/5e9b9e217b164ebfd4a002dd4380b3b1563200c3), [`7c128ae`](https://github.com/Effect-TS/effect-smol/commit/7c128aef458a1e2d224712e51c483c9badad1d44), [`0ada457`](https://github.com/Effect-TS/effect-smol/commit/0ada457c0513d8d908254ab77ebb7d29d2b523d6), [`d7cc5a2`](https://github.com/Effect-TS/effect-smol/commit/d7cc5a2bede3de10943aa0c6bdb4f26836a91efd), [`aad63be`](https://github.com/Effect-TS/effect-smol/commit/aad63becf65e0a6b076e94f8973be7bbe7fbd46f), [`09809f6`](https://github.com/Effect-TS/effect-smol/commit/09809f60f19ec98232f98b33e33e02ecb7e4fbd6), [`2fddda5`](https://github.com/Effect-TS/effect-smol/commit/2fddda5311929f46b61e503f0ade4fc749e8c77d), [`5f21768`](https://github.com/Effect-TS/effect-smol/commit/5f2176833399757c4500d8875b7f2fba0393de75), [`f27003e`](https://github.com/Effect-TS/effect-smol/commit/f27003e00524ff83f20dd9909f62b2f8795efe03)]:
- effect@4.0.0-beta.79
## 4.0.0-beta.78
### Patch Changes
- Updated dependencies [[`7836b8e`](https://github.com/Effect-TS/effect-smol/commit/7836b8eb8bb0f3e04cdf554ee070caccf74f00c1), [`35d49a3`](https://github.com/Effect-TS/effect-smol/commit/35d49a3a09bdba6b513de87ddcead9e61a1042ba), [`4093258`](https://github.com/Effect-TS/effect-smol/commit/40932580e65bafab5f23c5f14b520cb411d0b2cd)]:
- effect@4.0.0-beta.78
## 4.0.0-beta.77
### Patch Changes
- Updated dependencies [[`6e9a5ca`](https://github.com/Effect-TS/effect-smol/commit/6e9a5ca62a61156fd67b2518ad3ab14ac0d25f23), [`302f398`](https://github.com/Effect-TS/effect-smol/commit/302f3984ce206e35d86ddd99d3b72be144850a51)]:
- effect@4.0.0-beta.77
## 4.0.0-beta.76
### Patch Changes
- Updated dependencies [[`016108a`](https://github.com/Effect-TS/effect-smol/commit/016108a472af7048ddbbfd05f233e67529fafe12), [`95c03d2`](https://github.com/Effect-TS/effect-smol/commit/95c03d2c55930668c215b5a41c23cf7742fead84), [`07299a3`](https://github.com/Effect-TS/effect-smol/commit/07299a33c09fd52faa9810d30835a2622c752386)]:
- effect@4.0.0-beta.76
## 4.0.0-beta.75
### Patch Changes
- Updated dependencies [[`81b187c`](https://github.com/Effect-TS/effect-smol/commit/81b187c17a0d8817b58232826939154010ae49d7), [`ad4b535`](https://github.com/Effect-TS/effect-smol/commit/ad4b535e17f94ce35261829d5a3675f0a7808b4e), [`a29c2e7`](https://github.com/Effect-TS/effect-smol/commit/a29c2e7e3570920156702671d6f3367cd0195f6c), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`ffea4ec`](https://github.com/Effect-TS/effect-smol/commit/ffea4ecf2925f6a4c9fd13079d47584cbf2bed00), [`4255c9b`](https://github.com/Effect-TS/effect-smol/commit/4255c9ba78bb98c7838fbe9dccdd8465e9da5427)]:
- effect@4.0.0-beta.75
## 4.0.0-beta.74
### Patch Changes
- Updated dependencies [[`b1fc6a4`](https://github.com/Effect-TS/effect-smol/commit/b1fc6a4b4d0ca7fa9fd162799ae17c86f2f7ee8e)]:
- effect@4.0.0-beta.74
## 4.0.0-beta.73
### Patch Changes
- Updated dependencies [[`361ca30`](https://github.com/Effect-TS/effect-smol/commit/361ca30eb6e134feece547d6e00f82be4cb23f75), [`b9598c6`](https://github.com/Effect-TS/effect-smol/commit/b9598c6a209e75bfdb87ee3b024ecd1e3923ff6e)]:
- effect@4.0.0-beta.73
## 4.0.0-beta.72
### Patch Changes
- Updated dependencies [[`73e67d1`](https://github.com/Effect-TS/effect-smol/commit/73e67d119a84d697773eaecb4865c6a71eb1a9cb), [`01d71ec`](https://github.com/Effect-TS/effect-smol/commit/01d71ec5a75f3c2747a8d3b1ad9701d1e27b7ce5), [`fcd707e`](https://github.com/Effect-TS/effect-smol/commit/fcd707e091a16e1b35343c901cc4052274e32239)]:
- effect@4.0.0-beta.72
## 4.0.0-beta.71
### Patch Changes
- Updated dependencies [[`d8ac76b`](https://github.com/Effect-TS/effect-smol/commit/d8ac76b5bad458c42cebe8a0c1b3843f955ac293), [`2c3c00a`](https://github.com/Effect-TS/effect-smol/commit/2c3c00af6faba7b7d422af26a7a2bbc35636d230), [`3751e7c`](https://github.com/Effect-TS/effect-smol/commit/3751e7cf353e7a54cd692c37401207d9afba1e63), [`fc5f25b`](https://github.com/Effect-TS/effect-smol/commit/fc5f25b03ada5fc2431987768a74d3d3e75ca485), [`7ccced4`](https://github.com/Effect-TS/effect-smol/commit/7ccced42867c14c013b01160b3d292f14c05bd04), [`a2e1fe5`](https://github.com/Effect-TS/effect-smol/commit/a2e1fe5835c98c8ee4393a091b1d11b75126e349), [`4a4a36b`](https://github.com/Effect-TS/effect-smol/commit/4a4a36b10e6e616cad07584a43908f6a7e07e618), [`d350292`](https://github.com/Effect-TS/effect-smol/commit/d3502922b4740fa9d745797cbc3775cb67839b6d), [`730afb6`](https://github.com/Effect-TS/effect-smol/commit/730afb66696adf9bd5a328cbca29df9c05968771), [`df1b008`](https://github.com/Effect-TS/effect-smol/commit/df1b008f370f414c2a67a7b8139ef747af8e5fba), [`6d469d5`](https://github.com/Effect-TS/effect-smol/commit/6d469d567a7c41d7e5343bdee21d45b07b0e8190)]:
- effect@4.0.0-beta.71
## 4.0.0-beta.70
### Patch Changes
- Updated dependencies [[`af7782d`](https://github.com/Effect-TS/effect-smol/commit/af7782d3008d08b043f3a3f261516001514b2b4e), [`7212d70`](https://github.com/Effect-TS/effect-smol/commit/7212d701a3eee7b3553ff502e2c066126e52e839)]:
- effect@4.0.0-beta.70
## 4.0.0-beta.69
### Patch Changes
- Updated dependencies [[`70ea04a`](https://github.com/Effect-TS/effect-smol/commit/70ea04aa96a2a7859d738d414e1f0e3ed081a27a), [`d0ea8b0`](https://github.com/Effect-TS/effect-smol/commit/d0ea8b03f7d73ae076c1db12666141e480d11178), [`a57674b`](https://github.com/Effect-TS/effect-smol/commit/a57674b64845e9e75a456cf907bfdcb858859118), [`59aa334`](https://github.com/Effect-TS/effect-smol/commit/59aa334fbd0a504dda3c36f6d2ef1be7449b4b8b), [`8f4208e`](https://github.com/Effect-TS/effect-smol/commit/8f4208ee83bc7bdaa6793b5429847b45aab72470)]:
- effect@4.0.0-beta.69
## 4.0.0-beta.68
### Patch Changes
- Updated dependencies [[`af8267f`](https://github.com/Effect-TS/effect-smol/commit/af8267f2f3588c3fb611e9286f6f933f29ce1217), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`f136bb7`](https://github.com/Effect-TS/effect-smol/commit/f136bb763048cbc6b17edd26496dba3e2415b9fa), [`6f38f07`](https://github.com/Effect-TS/effect-smol/commit/6f38f07d5941a211b251383aaab0f4f55e8a6557), [`aec9c40`](https://github.com/Effect-TS/effect-smol/commit/aec9c401a53db227f18bf5e0c84db7130ad862d6)]:
- effect@4.0.0-beta.68
## 4.0.0-beta.67
### Patch Changes
- Updated dependencies [[`a42ef66`](https://github.com/Effect-TS/effect-smol/commit/a42ef6632abbddfa820995ae310ccc84ae8d9b6f), [`35594f8`](https://github.com/Effect-TS/effect-smol/commit/35594f811cafe471acd490114b103a1f8392c8d8), [`8bddd62`](https://github.com/Effect-TS/effect-smol/commit/8bddd628cb623f9533d345082583ff51cead6836), [`4be4c8d`](https://github.com/Effect-TS/effect-smol/commit/4be4c8d60862aa963869ee2ed9ffa048ffac0527), [`0c9d3ab`](https://github.com/Effect-TS/effect-smol/commit/0c9d3ab43eb721a370ed8306260cbac218c27e87), [`b156acc`](https://github.com/Effect-TS/effect-smol/commit/b156accd2691b4a051f823affdece7c39923ce85), [`d16c034`](https://github.com/Effect-TS/effect-smol/commit/d16c03434ee3e6dcd3bfc82b65d99e881d89025b), [`b559d68`](https://github.com/Effect-TS/effect-smol/commit/b559d68845f848a10153395778f035682d399075), [`a3de5d9`](https://github.com/Effect-TS/effect-smol/commit/a3de5d9215e5cc4a62e2666efbd7c1bf595eb84f), [`7e6c12e`](https://github.com/Effect-TS/effect-smol/commit/7e6c12ec9b3a5945f6c26e272cc8f6390541ad3e), [`098167a`](https://github.com/Effect-TS/effect-smol/commit/098167a220fe07da6f14455818733ab1b269c9dd)]:
- effect@4.0.0-beta.67
## 4.0.0-beta.66
### Patch Changes
- Updated dependencies [[`ca2498e`](https://github.com/Effect-TS/effect-smol/commit/ca2498e702ac2d83fb7187707b7eb069bdb261a2), [`cd7d1fb`](https://github.com/Effect-TS/effect-smol/commit/cd7d1fba7e2e2c5ac3ad64e1be433440a5bda436), [`19a7033`](https://github.com/Effect-TS/effect-smol/commit/19a703367ec817cffc41d152da9b594827408e2b), [`33d26b4`](https://github.com/Effect-TS/effect-smol/commit/33d26b4210b2e974f146a71e7eed962f8ce00900), [`856766b`](https://github.com/Effect-TS/effect-smol/commit/856766b2c506aaed6d2df1d63bf3a5b1b062e1d4), [`079c7df`](https://github.com/Effect-TS/effect-smol/commit/079c7df82559bb9ce10a86dffb85d25e6ce07dc3)]:
- effect@4.0.0-beta.66
## 4.0.0-beta.65
### Patch Changes
- Updated dependencies [[`6f11454`](https://github.com/Effect-TS/effect-smol/commit/6f11454a9b6c3bd00f6b35fd7af14a2f2d63a0a2)]:
- effect@4.0.0-beta.65
## 4.0.0-beta.64
### Patch Changes
- Updated dependencies [[`7d4877a`](https://github.com/Effect-TS/effect-smol/commit/7d4877a1929cdb690280ea254326c04f2ec97ea5)]:
- effect@4.0.0-beta.64
## 4.0.0-beta.63
### Patch Changes
- Updated dependencies [[`7f927ff`](https://github.com/Effect-TS/effect-smol/commit/7f927ffb7a9801dcfc4096c29e369d13d65cd0ac), [`a696b3e`](https://github.com/Effect-TS/effect-smol/commit/a696b3e83a8504cdbe261a18c10a1cc0619ae102)]:
- effect@4.0.0-beta.63
## 4.0.0-beta.62
### Patch Changes
- Updated dependencies [[`4ab4b90`](https://github.com/Effect-TS/effect-smol/commit/4ab4b9007dc27a52ffabc6fcb37c96eeec795bf7)]:
- effect@4.0.0-beta.62
## 4.0.0-beta.61
### Patch Changes
- Updated dependencies [[`50790af`](https://github.com/Effect-TS/effect-smol/commit/50790af9b190c38d10fb0723837d49b66432638f), [`71f7c3d`](https://github.com/Effect-TS/effect-smol/commit/71f7c3df997deda92c84146d569696dab3bd645c), [`aae8797`](https://github.com/Effect-TS/effect-smol/commit/aae8797b9cb383be0c182dd58d03d787c354238b)]:
- effect@4.0.0-beta.61
## 4.0.0-beta.60
### Patch Changes
- Updated dependencies [[`f69d567`](https://github.com/Effect-TS/effect-smol/commit/f69d5675dcff9f4137295752baf066b7153fdc09), [`7909c95`](https://github.com/Effect-TS/effect-smol/commit/7909c954b8f6244a35a4b429f8dd0dff45dad620), [`bbb4dcc`](https://github.com/Effect-TS/effect-smol/commit/bbb4dcc6c406b83a416b4ad3541cc02037c420e4), [`7af2207`](https://github.com/Effect-TS/effect-smol/commit/7af2207901eabf3132c1b7010a69b3899c06fbbe), [`848b40a`](https://github.com/Effect-TS/effect-smol/commit/848b40a4bd4bf54a5098617d50c33c88eee8270a)]:
- effect@4.0.0-beta.60
## 4.0.0-beta.59
### Patch Changes
- Updated dependencies [[`56837ea`](https://github.com/Effect-TS/effect-smol/commit/56837ea2a338395b35550641374e9e589bd8b71d)]:
- effect@4.0.0-beta.59
## 4.0.0-beta.58
### Patch Changes
- Updated dependencies [[`11993d4`](https://github.com/Effect-TS/effect-smol/commit/11993d4934c66f5dc611b8bbf553f01d501ef8f7), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec)]:
- effect@4.0.0-beta.58
## 4.0.0-beta.57
### Patch Changes
- Updated dependencies [[`a971f5c`](https://github.com/Effect-TS/effect-smol/commit/a971f5cbd92dfe4274420bf0966595eb35531060), [`8e110c5`](https://github.com/Effect-TS/effect-smol/commit/8e110c5f02a429ccc43a91df8678e402138c0851)]:
- effect@4.0.0-beta.57
## 4.0.0-beta.56
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.56
## 4.0.0-beta.55
### Patch Changes
- Updated dependencies [[`42cc744`](https://github.com/Effect-TS/effect-smol/commit/42cc744570968deb365fb46d47b53d3277050c93), [`04855ce`](https://github.com/Effect-TS/effect-smol/commit/04855ceeca4d40c55a5750dd9893b691f8ea741a)]:
- effect@4.0.0-beta.55
## 4.0.0-beta.54
### Patch Changes
- Updated dependencies [[`e4b74f9`](https://github.com/Effect-TS/effect-smol/commit/e4b74f9c01a0e9b6cd58416de4af3a26d51da7c8), [`4c72808`](https://github.com/Effect-TS/effect-smol/commit/4c728081851c66dacf889a816535671bc841ae96)]:
- effect@4.0.0-beta.54
## 4.0.0-beta.53
### Patch Changes
- Updated dependencies [[`0768509`](https://github.com/Effect-TS/effect-smol/commit/07685094e931af07d104165195826a535b55fa7e), [`476aede`](https://github.com/Effect-TS/effect-smol/commit/476aede69c6efa06b5781ca5eb3e3b128ca29141), [`4f79c54`](https://github.com/Effect-TS/effect-smol/commit/4f79c542e7b508c235ff485d862cc8b29a8260c5), [`4be6a7c`](https://github.com/Effect-TS/effect-smol/commit/4be6a7cf35dab2a01d652f56dd35f0358c5a7e88), [`88927eb`](https://github.com/Effect-TS/effect-smol/commit/88927ebb896162cdba103b36553280b58e0facac)]:
- effect@4.0.0-beta.53
## 4.0.0-beta.52
### Patch Changes
- Updated dependencies [[`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`cf3a311`](https://github.com/Effect-TS/effect-smol/commit/cf3a311d863a8abb818840c3b80f847e621c43c1), [`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`131fdd5`](https://github.com/Effect-TS/effect-smol/commit/131fdd5b1f26531e265fe1a08f002002f47c276e)]:
- effect@4.0.0-beta.52
## 4.0.0-beta.51
### Patch Changes
- Updated dependencies [[`778d2af`](https://github.com/Effect-TS/effect-smol/commit/778d2afe9b5154bc1f9abae46d93ea7e54c87344), [`4e24dcf`](https://github.com/Effect-TS/effect-smol/commit/4e24dcf75037f65eebc1eb68623bc7cbf9d5512a), [`4b1c015`](https://github.com/Effect-TS/effect-smol/commit/4b1c0150e9bdb5559ed32d250deb66e17b4240c7), [`454f8ad`](https://github.com/Effect-TS/effect-smol/commit/454f8adad822929c3ef60f8280d0987226b049fd), [`6754a0c`](https://github.com/Effect-TS/effect-smol/commit/6754a0cd18626b06805a079cc5265525a5eb7d27), [`90f7fd5`](https://github.com/Effect-TS/effect-smol/commit/90f7fd5243871b30980964135db4512b8119fa82), [`d7e1519`](https://github.com/Effect-TS/effect-smol/commit/d7e151974934201fd93fa4c8a1192ee9a5d965a0), [`72a8122`](https://github.com/Effect-TS/effect-smol/commit/72a81228e09782bae512f7d041bbfbc78bc668d0)]:
- effect@4.0.0-beta.51
## 4.0.0-beta.50
### Patch Changes
- Updated dependencies [[`07be594`](https://github.com/Effect-TS/effect-smol/commit/07be594825de60f8e1b2102d21dbb9b8fc63b414), [`ae02433`](https://github.com/Effect-TS/effect-smol/commit/ae02433103ce28f53a0c9bfb4a44e75773289b7b)]:
- effect@4.0.0-beta.50
## 4.0.0-beta.49
### Patch Changes
- Updated dependencies [[`7d87873`](https://github.com/Effect-TS/effect-smol/commit/7d8787340ff549370f6f2a88b612e9ebbfd6ba45), [`c2f6f90`](https://github.com/Effect-TS/effect-smol/commit/c2f6f901b200a6e515b4f02c93ce8005b7bbf1c5), [`216f13c`](https://github.com/Effect-TS/effect-smol/commit/216f13c1fce454a21b489bb915714a17e791a1ac)]:
- effect@4.0.0-beta.49
## 4.0.0-beta.48
### Patch Changes
- Updated dependencies [[`4da56ec`](https://github.com/Effect-TS/effect-smol/commit/4da56ecff129b2da40137ffede23a73cc4e532d8), [`a5e6f77`](https://github.com/Effect-TS/effect-smol/commit/a5e6f774bab195cf50ecdc818240765f69a3bf4a), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070)]:
- effect@4.0.0-beta.48
## 4.0.0-beta.47
### Patch Changes
- Updated dependencies [[`c584726`](https://github.com/Effect-TS/effect-smol/commit/c58472674e750e6938df955044eab88feda95e45), [`86a91a4`](https://github.com/Effect-TS/effect-smol/commit/86a91a4f0c59286dfa9393232d8020dea70ed4db), [`131caf9`](https://github.com/Effect-TS/effect-smol/commit/131caf9525151a0cb29803a8f1dffa0f4f479d12), [`c3615c8`](https://github.com/Effect-TS/effect-smol/commit/c3615c88379b9daf252df0db72c6ac5a20326406)]:
- effect@4.0.0-beta.47
## 4.0.0-beta.46
### Patch Changes
- Updated dependencies [[`3a30b9e`](https://github.com/Effect-TS/effect-smol/commit/3a30b9e2ec2bd8b8193e1aa139f6878a07e3f5ee)]:
- effect@4.0.0-beta.46
## 4.0.0-beta.45
### Patch Changes
- Updated dependencies [[`5c3af6d`](https://github.com/Effect-TS/effect-smol/commit/5c3af6d554f60be34f8fc21d598d9a298ae11beb)]:
- effect@4.0.0-beta.45
## 4.0.0-beta.44
### Patch Changes
- [#1961](https://github.com/Effect-TS/effect-smol/pull/1961) [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970) Thanks @IMax153! - Rename the `ServiceMap` module to `Context` across exports, docs, and tests.
- Updated dependencies [[`e3f0621`](https://github.com/Effect-TS/effect-smol/commit/e3f0621454c3f5d11070d30619da27c9232cadc1), [`5b476ab`](https://github.com/Effect-TS/effect-smol/commit/5b476abc0bd7e9bb59135ea1bcad2e4936227ced), [`6b40e5a`](https://github.com/Effect-TS/effect-smol/commit/6b40e5a4a6bd2087c15a3d7374d25057fdedfa16), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`3b09fb3`](https://github.com/Effect-TS/effect-smol/commit/3b09fb31c40c2802b01f21c23bcdd1fe7fb0aa82), [`2370410`](https://github.com/Effect-TS/effect-smol/commit/237041062e5af4594d32db91597e34e70a632877), [`dabc272`](https://github.com/Effect-TS/effect-smol/commit/dabc272444a700eb629c07ba3e77671a841ca86e), [`08b63c3`](https://github.com/Effect-TS/effect-smol/commit/08b63c3df11bd35c9fd6090dbd166287fdc40664), [`dfff04c`](https://github.com/Effect-TS/effect-smol/commit/dfff04c4c2b1d352dfad83992a6dce1280c85cf9), [`9baed9e`](https://github.com/Effect-TS/effect-smol/commit/9baed9e17e84702e6e480fcef6f86404f9e24be9), [`7846792`](https://github.com/Effect-TS/effect-smol/commit/7846792adc7e1631d62d26d657bd7ba6139f369b), [`1556a24`](https://github.com/Effect-TS/effect-smol/commit/1556a247623636b7ebe438fb56d77f1a7bf957bb), [`7c11bc2`](https://github.com/Effect-TS/effect-smol/commit/7c11bc292ab8e46252fe8f7576fb685917bfb8b5), [`b5ea591`](https://github.com/Effect-TS/effect-smol/commit/b5ea5913ec1d45d0dd12a327b9dd966bda2f6d02), [`0853afa`](https://github.com/Effect-TS/effect-smol/commit/0853afaeb1633b2d7f8b66893bd01c3aa1ef2c22), [`ac845f3`](https://github.com/Effect-TS/effect-smol/commit/ac845f3ab40e0b8719576e7f9bc16ea2e0e02cd4), [`b80c462`](https://github.com/Effect-TS/effect-smol/commit/b80c46247480f47bb64fc480fab48a3f37bc8888), [`b3f535d`](https://github.com/Effect-TS/effect-smol/commit/b3f535d9a7ac13b5fb984c29f93561c57a081ff0), [`6fe2e93`](https://github.com/Effect-TS/effect-smol/commit/6fe2e93cc2f1b173ef89651d74b6a5d2626b3226), [`cda8004`](https://github.com/Effect-TS/effect-smol/commit/cda800451c1ffbdddfc08415aed7b2d91e0412ee), [`8335477`](https://github.com/Effect-TS/effect-smol/commit/8335477a8a936a24b5f3ee6203c1b268bd1bfc3c), [`8c836f9`](https://github.com/Effect-TS/effect-smol/commit/8c836f99ab1e896b9580a71d67773625baff2eaf), [`718ff6f`](https://github.com/Effect-TS/effect-smol/commit/718ff6fe3e3d3820cefd67d2bff1b2224fe08060), [`7eed84f`](https://github.com/Effect-TS/effect-smol/commit/7eed84fc33c5781a6fb11bf4fd189d424902ebd4), [`5df46fe`](https://github.com/Effect-TS/effect-smol/commit/5df46fe2f654d59ab5fc1578f4fc27fa40368ef9), [`82dd0f2`](https://github.com/Effect-TS/effect-smol/commit/82dd0f26c6442b07143762ef7bc33742d3978dd6), [`03ae41e`](https://github.com/Effect-TS/effect-smol/commit/03ae41e7304cffac9f18feea22b73468feafc43a), [`4677a0a`](https://github.com/Effect-TS/effect-smol/commit/4677a0a58f95eea38a211efcd3f345f237a9e44a), [`87e1fc8`](https://github.com/Effect-TS/effect-smol/commit/87e1fc8b67e4901d75f567b2fecc3841ab762cc4), [`c1af1b7`](https://github.com/Effect-TS/effect-smol/commit/c1af1b756f63291e9c0298cf95c98a6920a0c2a0), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`c8a877b`](https://github.com/Effect-TS/effect-smol/commit/c8a877b53e8f29616335719e5dd1c3992dddf780), [`7da961a`](https://github.com/Effect-TS/effect-smol/commit/7da961ae4916229d2246699a5d3b20e5b2dd2020)]:
- effect@4.0.0-beta.44
## 4.0.0-beta.43
### Patch Changes
- Updated dependencies [[`2ae33d0`](https://github.com/Effect-TS/effect-smol/commit/2ae33d050914915f7cb9c25ab0a020901e08d596), [`979811a`](https://github.com/Effect-TS/effect-smol/commit/979811a4c3f7ed21ed18ef560c49fb7f5569e80e), [`eb7dbef`](https://github.com/Effect-TS/effect-smol/commit/eb7dbeffa883386ad912815e62c0820cac1fdf8e), [`cf50eb4`](https://github.com/Effect-TS/effect-smol/commit/cf50eb49cb04706dae5185f624708117c413dee8), [`1d046fe`](https://github.com/Effect-TS/effect-smol/commit/1d046fe484560e23f3e22cb23eec6433f8f1fa02)]:
- effect@4.0.0-beta.43
## 4.0.0-beta.42
### Patch Changes
- Updated dependencies [[`924e216`](https://github.com/Effect-TS/effect-smol/commit/924e216caa7e0bbf22e994a0cd2ce8b1f0f0b3ee), [`80e7f0c`](https://github.com/Effect-TS/effect-smol/commit/80e7f0cd9116e811e97b0ce30a77a8d1ecd072aa), [`f8328bf`](https://github.com/Effect-TS/effect-smol/commit/f8328bf0314da3dc7f31d314f94a5840e8d5217f), [`66d1c06`](https://github.com/Effect-TS/effect-smol/commit/66d1c06039079129707a230f7ad8c676439d7133), [`bee800b`](https://github.com/Effect-TS/effect-smol/commit/bee800bf285192a01bec72a7b7b51bc1159434e6), [`8930441`](https://github.com/Effect-TS/effect-smol/commit/8930441dee6f94c59c583d18d3ebd677cf1f2623)]:
- effect@4.0.0-beta.42
## 4.0.0-beta.41
### Patch Changes
- [#1871](https://github.com/Effect-TS/effect-smol/pull/1871) [`977386d`](https://github.com/Effect-TS/effect-smol/commit/977386da5e2e8aac2c07e99175673e0b5771191b) Thanks @IMax153! - Fix HTTP Referer header name in the `OpenRouterClient`
- Updated dependencies [[`36f5c21`](https://github.com/Effect-TS/effect-smol/commit/36f5c2174d31ab42c4598bf81f178f40d0802283), [`d8ce758`](https://github.com/Effect-TS/effect-smol/commit/d8ce758669d6297ae932ac3251d83e7b49b22f30), [`11aab4c`](https://github.com/Effect-TS/effect-smol/commit/11aab4c6d37d5691adafc2d33da1a631b28ce814), [`3bc1efb`](https://github.com/Effect-TS/effect-smol/commit/3bc1efb53dd75b4a40de46f1f80c7f8a7d50af86), [`70e724e`](https://github.com/Effect-TS/effect-smol/commit/70e724e604604d4be1061cd8da0d360494998c84), [`738dee7`](https://github.com/Effect-TS/effect-smol/commit/738dee7edfd70af82dc4d2376db3a8ebe603eb48), [`2111963`](https://github.com/Effect-TS/effect-smol/commit/2111963f19b4c28c800664a8fac9590c1321885f), [`198a553`](https://github.com/Effect-TS/effect-smol/commit/198a553d9ce45f6a00bfc4d65ed0640669602d95)]:
- effect@4.0.0-beta.41
## 4.0.0-beta.40
### Patch Changes
- Updated dependencies [[`f62860f`](https://github.com/Effect-TS/effect-smol/commit/f62860f0e5e45978fabf7256ae620a13152a772a), [`973f281`](https://github.com/Effect-TS/effect-smol/commit/973f2812529aadc1cc54598b2039799fa72b80f8)]:
- effect@4.0.0-beta.40
## 4.0.0-beta.39
### Patch Changes
- Updated dependencies [[`f91fd3d`](https://github.com/Effect-TS/effect-smol/commit/f91fd3db39fe5628439fd175fba201a65a1aa9d0), [`edaae9d`](https://github.com/Effect-TS/effect-smol/commit/edaae9d65f464f941d7eddd723cd33d324f4b071), [`b47db0b`](https://github.com/Effect-TS/effect-smol/commit/b47db0bd5802064b6a24b3ea27c6ff2e0520d513), [`82d3c8e`](https://github.com/Effect-TS/effect-smol/commit/82d3c8e4f3f49b00df611b25aa6f8f74ec21b59b), [`7c22b31`](https://github.com/Effect-TS/effect-smol/commit/7c22b315d198dcbf44ae8cdb8b37879e1c9e3996)]:
- effect@4.0.0-beta.39
## 4.0.0-beta.38
### Patch Changes
- Updated dependencies [[`f4dbe5b`](https://github.com/Effect-TS/effect-smol/commit/f4dbe5b26b9c2d33fae024bf44afbdf8541792cd), [`a71a607`](https://github.com/Effect-TS/effect-smol/commit/a71a607c89fb6669a12a562c2c23be81dfbe1adb), [`66a0494`](https://github.com/Effect-TS/effect-smol/commit/66a0494ed75cd12f2721dcbb1d8a072e3d9e14b6), [`5ef7218`](https://github.com/Effect-TS/effect-smol/commit/5ef7218fc559d57301fe929b8a0cab4033f4f1fd), [`472d260`](https://github.com/Effect-TS/effect-smol/commit/472d260655bc311fba5c2c6e23bb77d8f7e36ba0)]:
- effect@4.0.0-beta.38
## 4.0.0-beta.37
### Patch Changes
- Updated dependencies [[`f7a0b71`](https://github.com/Effect-TS/effect-smol/commit/f7a0b711da8fdd645597dee29cacc5619c6afcf2), [`1e223c3`](https://github.com/Effect-TS/effect-smol/commit/1e223c30ccf835dfbb21284535d78549efaeca80), [`53740f4`](https://github.com/Effect-TS/effect-smol/commit/53740f47aa76d114b7d535649fb50efc54a09608), [`8c7cf89`](https://github.com/Effect-TS/effect-smol/commit/8c7cf89f719e580cbce1bf6c24e6996f1992a0a6), [`b6b81a9`](https://github.com/Effect-TS/effect-smol/commit/b6b81a940eaafcbc792d25413d6c02c707de31b2), [`8f4c1f9`](https://github.com/Effect-TS/effect-smol/commit/8f4c1f97ed60f8810b0b327b50117ffb2d8260d4), [`f2479f9`](https://github.com/Effect-TS/effect-smol/commit/f2479f9d3113b1f012db17a3852b4e28f478cf9c), [`c919921`](https://github.com/Effect-TS/effect-smol/commit/c9199217fad65529421d2cf95ecfff41257090fd), [`7af90c2`](https://github.com/Effect-TS/effect-smol/commit/7af90c2e3c99038eafa39650433839523790e2fe), [`f3be185`](https://github.com/Effect-TS/effect-smol/commit/f3be18569e5ca57c25eabf00df3ca601ebab43c7)]:
- effect@4.0.0-beta.37
## 4.0.0-beta.36
### Patch Changes
- Updated dependencies [[`60fcbcc`](https://github.com/Effect-TS/effect-smol/commit/60fcbcc43d09471e8f7e0969955d99dcefc5be81), [`0a60837`](https://github.com/Effect-TS/effect-smol/commit/0a6083713124440e630030375bab367e8d7df24e), [`49164d2`](https://github.com/Effect-TS/effect-smol/commit/49164d2c20a8d21b66514992c4a15d8521f6b36e), [`334b6e4`](https://github.com/Effect-TS/effect-smol/commit/334b6e4f76fe11941b516d61f57e268bc31f0ca6), [`5700695`](https://github.com/Effect-TS/effect-smol/commit/5700695f76ae6da6b94c9c87d4dd2b8054fb829b), [`f8f4456`](https://github.com/Effect-TS/effect-smol/commit/f8f445644f3aa7ec093cab7445198a62ba18a480), [`969d24f`](https://github.com/Effect-TS/effect-smol/commit/969d24fdfa48c4838e811983848d9cb4e9b3b12c), [`851eda0`](https://github.com/Effect-TS/effect-smol/commit/851eda0533946e39bacaaf581896320d7a4f3e8c), [`8059c1c`](https://github.com/Effect-TS/effect-smol/commit/8059c1c3eba9a90af7cd889ea261bcb8fff0c185), [`6f83295`](https://github.com/Effect-TS/effect-smol/commit/6f8329546a73eaddc7cb5e85ea8e37e73fbfb611), [`65f7f57`](https://github.com/Effect-TS/effect-smol/commit/65f7f5737575fed668987462c96d29a446707c32), [`e7fabd2`](https://github.com/Effect-TS/effect-smol/commit/e7fabd2265db690eae5cfc9b83730c84699aef61), [`89c3e98`](https://github.com/Effect-TS/effect-smol/commit/89c3e985401eb38f33a3ae21a94ad27de3c1d28b), [`53794ab`](https://github.com/Effect-TS/effect-smol/commit/53794ab7af30aa5c5004ecf53659fafbe4b10542)]:
- effect@4.0.0-beta.36
## 4.0.0-beta.35
### Patch Changes
- Updated dependencies [[`9252b43`](https://github.com/Effect-TS/effect-smol/commit/9252b43560f507709c2985abcf52a7837b23ddf8), [`7daf387`](https://github.com/Effect-TS/effect-smol/commit/7daf3870a656882a488a60f67881e6808c8f4d04), [`e1664a3`](https://github.com/Effect-TS/effect-smol/commit/e1664a38bc31ef4ceb4e9324c7226e1e99bf9c07), [`fdaa6e0`](https://github.com/Effect-TS/effect-smol/commit/fdaa6e0a41b6b6605438fa8557441792135380a2), [`19aa47e`](https://github.com/Effect-TS/effect-smol/commit/19aa47ef7b470e427620edca8970dd9cdd551216), [`c667dad`](https://github.com/Effect-TS/effect-smol/commit/c667dad07777b860e4764a3ba9a6cc41c236cd98), [`764d150`](https://github.com/Effect-TS/effect-smol/commit/764d1501bc5026b60fc8aef6cb02a5a87c762801), [`3c27098`](https://github.com/Effect-TS/effect-smol/commit/3c27098b5685a63db2c2eff654a250c94d3fcfa7)]:
- effect@4.0.0-beta.35
## 4.0.0-beta.34
### Patch Changes
- Updated dependencies [[`f2f75ee`](https://github.com/Effect-TS/effect-smol/commit/f2f75ee564bce1cd95f5189c7bdeeed4f92dacb1), [`342fc4b`](https://github.com/Effect-TS/effect-smol/commit/342fc4b051739e32e7977159f26ff9541eda664f), [`5d704ee`](https://github.com/Effect-TS/effect-smol/commit/5d704ee10d20e8eb107e34bb8a21feb5aa4a7685), [`00add69`](https://github.com/Effect-TS/effect-smol/commit/00add69b59551e9df34772eb927638b093f6d71e), [`58217d3`](https://github.com/Effect-TS/effect-smol/commit/58217d318a7d716ccd707cce0f41573946939c28), [`f4e2aba`](https://github.com/Effect-TS/effect-smol/commit/f4e2aba01b76d1e3059b297e3cc942284dfeafb2), [`e3b44b6`](https://github.com/Effect-TS/effect-smol/commit/e3b44b6a2af9ee21dc5c1e928f0c20af857fa7a9), [`e1472b7`](https://github.com/Effect-TS/effect-smol/commit/e1472b7525c5d57a48bdec2353c3b742f7f916c0), [`7686320`](https://github.com/Effect-TS/effect-smol/commit/7686320cd123fa352b5c3d076fb18a3cac0a9bba)]:
- effect@4.0.0-beta.34
## 4.0.0-beta.33
### Patch Changes
- Updated dependencies [[`571447d`](https://github.com/Effect-TS/effect-smol/commit/571447da67334449f8ae3d6ecb3d77ea4e0c4295)]:
- effect@4.0.0-beta.33
## 4.0.0-beta.32
### Patch Changes
- Updated dependencies [[`bf8fff8`](https://github.com/Effect-TS/effect-smol/commit/bf8fff8a5f54b6df74cb7bbb42346fe9ba52435a), [`1af3ef3`](https://github.com/Effect-TS/effect-smol/commit/1af3ef3e3ca7fd417d0fc15f8ca8fe207eba4f74), [`27fea0f`](https://github.com/Effect-TS/effect-smol/commit/27fea0f66910de5905f40fd63f8ddbb6f7ac5aba), [`2ad6c1b`](https://github.com/Effect-TS/effect-smol/commit/2ad6c1b2c85a3a0fe351e3d56636a75eb76b4b4e), [`398ac3e`](https://github.com/Effect-TS/effect-smol/commit/398ac3e01cb75efce0e4e2913d1450cf65866732), [`51fe22f`](https://github.com/Effect-TS/effect-smol/commit/51fe22f3266e417b6c541aaed4b75d246fac91e7), [`4605db6`](https://github.com/Effect-TS/effect-smol/commit/4605db69cfacddbdbf1525865ddfde135158090c), [`f4de1b0`](https://github.com/Effect-TS/effect-smol/commit/f4de1b087c998d0bad1d9468f70b7d16c13b9f6f), [`60214f2`](https://github.com/Effect-TS/effect-smol/commit/60214f2080b2aeb091f691140eb20acb741691c3), [`c4b8b0f`](https://github.com/Effect-TS/effect-smol/commit/c4b8b0ffa8efb47c4cd7578a8943d6868509373f), [`6d9393a`](https://github.com/Effect-TS/effect-smol/commit/6d9393a0770a18722d23340e77f15455de341245), [`6de4efe`](https://github.com/Effect-TS/effect-smol/commit/6de4efe463c783614ceb0c094d77a336a899cbe0), [`4f969d1`](https://github.com/Effect-TS/effect-smol/commit/4f969d1563ba755ffa116c8ae409bb3436bd881d), [`6cc67c8`](https://github.com/Effect-TS/effect-smol/commit/6cc67c855e054ee3f3ac3485dca5f7805e79e8fb), [`8531a22`](https://github.com/Effect-TS/effect-smol/commit/8531a22ffbb52e11a030b09f358cafbfdf5edff7), [`b226760`](https://github.com/Effect-TS/effect-smol/commit/b22676067617f15c00722a3a63fd7c2c172c3d45), [`47a51ab`](https://github.com/Effect-TS/effect-smol/commit/47a51aba0ecdf3ef478bfa28a498bca188399bd4), [`1521d02`](https://github.com/Effect-TS/effect-smol/commit/1521d02e1f19f1d795edaaf862c1a1031d9c755e)]:
- effect@4.0.0-beta.32
## 4.0.0-beta.31
### Patch Changes
- Updated dependencies [[`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6f23f0e`](https://github.com/Effect-TS/effect-smol/commit/6f23f0ed4cba573cd9395c2e582f582fe7271544), [`654aaec`](https://github.com/Effect-TS/effect-smol/commit/654aaec593305521b65dd042c204d761cc6e8c28), [`2958a42`](https://github.com/Effect-TS/effect-smol/commit/2958a42078966a8713a98f00485ab36484d5eccf), [`95d27a2`](https://github.com/Effect-TS/effect-smol/commit/95d27a239ed5147302605ab0b3147a056541b0c7), [`0fbaea8`](https://github.com/Effect-TS/effect-smol/commit/0fbaea8f9555a8044cec31a770394db613fc78e2), [`21d5d5e`](https://github.com/Effect-TS/effect-smol/commit/21d5d5e0439fd4d9bb6e508377215b1087555d45), [`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6e49959`](https://github.com/Effect-TS/effect-smol/commit/6e499590357a104c81779b3176cd3f84e4f91064), [`8f5805d`](https://github.com/Effect-TS/effect-smol/commit/8f5805dbdd0d1bc0ff0727cc398c8d80e544edee), [`990df2c`](https://github.com/Effect-TS/effect-smol/commit/990df2c3ceeb32e659acc10cc9485617f7b3c423)]:
- effect@4.0.0-beta.31
## 4.0.0-beta.30
### Patch Changes
- Updated dependencies [[`c88e5b7`](https://github.com/Effect-TS/effect-smol/commit/c88e5b723ff09da4edaef6ce14d927ca01104a32), [`947d0e4`](https://github.com/Effect-TS/effect-smol/commit/947d0e4268ba5c4020ead380aa80812c7342408f), [`7517908`](https://github.com/Effect-TS/effect-smol/commit/75179085d159b88a1ab0bce70669d76dcf0d79a4), [`a49ecd5`](https://github.com/Effect-TS/effect-smol/commit/a49ecd5a183d7e7d33f47ff95e9d2dea5a12ead5), [`6993e33`](https://github.com/Effect-TS/effect-smol/commit/6993e3329122c834c20bacea72d8678232f4f103), [`514f2a2`](https://github.com/Effect-TS/effect-smol/commit/514f2a2ae54580fcacdbe2ea2196a83a852d0748), [`3214b47`](https://github.com/Effect-TS/effect-smol/commit/3214b47676de2d33fddc5fecfc2d226e6e83cc7b), [`95ec5ed`](https://github.com/Effect-TS/effect-smol/commit/95ec5ed345de77c893049e182d37a37cf164a268)]:
- effect@4.0.0-beta.30
## 4.0.0-beta.29
### Patch Changes
- Updated dependencies [[`9d93adb`](https://github.com/Effect-TS/effect-smol/commit/9d93adb1c1795d1978391b30d7d2972c88052662), [`b52721c`](https://github.com/Effect-TS/effect-smol/commit/b52721cf0d11a567722b060c8536e3bdd4161f07), [`a891c7b`](https://github.com/Effect-TS/effect-smol/commit/a891c7b12f415b2287613dd4b91a09dfd38ef30d), [`ef26cdf`](https://github.com/Effect-TS/effect-smol/commit/ef26cdfb65d9955fc7e161629191930c2cc2c63f), [`82fd3ed`](https://github.com/Effect-TS/effect-smol/commit/82fd3ed922063ee5a34f96f3993c15c7515e4f67)]:
- effect@4.0.0-beta.29
## 4.0.0-beta.28
### Patch Changes
- Updated dependencies [[`ff533f2`](https://github.com/Effect-TS/effect-smol/commit/ff533f203cd06302ad08032a27e01269b4a2d4c6), [`dc803ee`](https://github.com/Effect-TS/effect-smol/commit/dc803ee52ebd3e9f931118f0dfcb804542847556), [`d660b1c`](https://github.com/Effect-TS/effect-smol/commit/d660b1c99cb93d4f79715e91c7a4486801c0eefa), [`93a05e3`](https://github.com/Effect-TS/effect-smol/commit/93a05e3eaa624058b162aedd66aad70102837270), [`2a65cf6`](https://github.com/Effect-TS/effect-smol/commit/2a65cf6fd81ef63d944e6fb51f058d439bf4a834), [`a561a40`](https://github.com/Effect-TS/effect-smol/commit/a561a40cc41c548c2cf3153aca065ee92ee8aa57), [`29cd24d`](https://github.com/Effect-TS/effect-smol/commit/29cd24d1fe78480a72eeb38a90281ffddc0530bc), [`662a8e6`](https://github.com/Effect-TS/effect-smol/commit/662a8e6857dac64a7cd13bd8df4b0674654622f8), [`d2b52ba`](https://github.com/Effect-TS/effect-smol/commit/d2b52bae5b9336cf59729fbdcc4d7f09512b0cbf), [`407c3b4`](https://github.com/Effect-TS/effect-smol/commit/407c3b43a5d1414558e0e33b6f1fc0e6a6d489cc), [`42bc7ce`](https://github.com/Effect-TS/effect-smol/commit/42bc7ce5480f6f2953c39f8cb5c850d61df6f5a2), [`e741322`](https://github.com/Effect-TS/effect-smol/commit/e74132226cbfee24234311c7c1c13e6b7391384e), [`5c75fa8`](https://github.com/Effect-TS/effect-smol/commit/5c75fa8fb71163bc4c035ba1a215574dfd4badfc), [`747177b`](https://github.com/Effect-TS/effect-smol/commit/747177b0602f12d4461a843e953dfdffbeb0a429), [`326cd48`](https://github.com/Effect-TS/effect-smol/commit/326cd4828bce573fe985f35152155464bf4c5a70), [`627e922`](https://github.com/Effect-TS/effect-smol/commit/627e922b8d1e9521eae5e1caa5d667ad00b1619a), [`662287e`](https://github.com/Effect-TS/effect-smol/commit/662287e9abc76c941ccc2ee330aa07904d571341)]:
- effect@4.0.0-beta.28
## 4.0.0-beta.27
### Patch Changes
- Updated dependencies [[`903a839`](https://github.com/Effect-TS/effect-smol/commit/903a839e94239e6ec4568315af28e405bcad95f4), [`91a0168`](https://github.com/Effect-TS/effect-smol/commit/91a016836680a6669308ecf464d3584bcc4ae1b7), [`c890f9a`](https://github.com/Effect-TS/effect-smol/commit/c890f9a1b3a989ed22528bd5a43326342e05b142), [`1e985f2`](https://github.com/Effect-TS/effect-smol/commit/1e985f237d250b51b91de22dde77160c1e778ce7)]:
- effect@4.0.0-beta.27
## 4.0.0-beta.26
### Patch Changes
- Updated dependencies [[`fb21462`](https://github.com/Effect-TS/effect-smol/commit/fb21462642cdd5b1bada92f3eba18ae20445be42), [`2ed26b1`](https://github.com/Effect-TS/effect-smol/commit/2ed26b139805700e3df39efaa768ff01565e5c86), [`e832a57`](https://github.com/Effect-TS/effect-smol/commit/e832a57b570fe38f010c1fd99bceac5a325a9e07), [`7f01be7`](https://github.com/Effect-TS/effect-smol/commit/7f01be7f8db363d4b2e88e6b5571e96bb815786f), [`e965143`](https://github.com/Effect-TS/effect-smol/commit/e9651431e114479e6becf8ca7b1ed99ac7e91ccc), [`b9b80f1`](https://github.com/Effect-TS/effect-smol/commit/b9b80f1f15e152ceef0a727d150b7dc230abae99), [`98252aa`](https://github.com/Effect-TS/effect-smol/commit/98252aa0c0b17fc73fbdad65d0a1104965f9fc0f), [`56fbd94`](https://github.com/Effect-TS/effect-smol/commit/56fbd94311ad19a05001ad649d9e34ab00c74541), [`3faa109`](https://github.com/Effect-TS/effect-smol/commit/3faa109b7d093fbf14ad410d3e11d663f16e28f1), [`692ecfe`](https://github.com/Effect-TS/effect-smol/commit/692ecfed99fe58056b7a5afe001f4fcd1a61c446), [`1e70b72`](https://github.com/Effect-TS/effect-smol/commit/1e70b72d0b210474d0e96a15a5cfc279eae37e0c), [`ecf0782`](https://github.com/Effect-TS/effect-smol/commit/ecf07829ef2dfc01d8943c96c4fe9c1b44b97926)]:
- effect@4.0.0-beta.26
## 4.0.0-beta.25
### Patch Changes
- Updated dependencies [[`fa17bb5`](https://github.com/Effect-TS/effect-smol/commit/fa17bb5be9f2533d01e11322b14804c7dec43714), [`f46e5b5`](https://github.com/Effect-TS/effect-smol/commit/f46e5b5ca2a918ee4d9270167e79db223077c96f), [`ce4767c`](https://github.com/Effect-TS/effect-smol/commit/ce4767cadcacc6ce8ff4c3a0d0fbc82ede655f63), [`c830a8b`](https://github.com/Effect-TS/effect-smol/commit/c830a8b6c292a6528d7f9318759d34800b00372d)]:
- effect@4.0.0-beta.25
## 4.0.0-beta.24
### Patch Changes
- Updated dependencies [[`a909e1c`](https://github.com/Effect-TS/effect-smol/commit/a909e1c1ac2bc707527f5073776e3e7d239688d9), [`8814a4e`](https://github.com/Effect-TS/effect-smol/commit/8814a4ef78d67144d27689370af10099ea210399), [`3f942c5`](https://github.com/Effect-TS/effect-smol/commit/3f942c51cefa7b2ffa7c49e8c8a2c887570ba4c0), [`774ed59`](https://github.com/Effect-TS/effect-smol/commit/774ed59c52b2ab578bbb897c4f551f812231e1d2), [`f54b8d3`](https://github.com/Effect-TS/effect-smol/commit/f54b8d398fedad1815fd1f4c49814ab938cfc385)]:
- effect@4.0.0-beta.24
## 4.0.0-beta.23
### Patch Changes
- Updated dependencies [[`5c73c41`](https://github.com/Effect-TS/effect-smol/commit/5c73c41b69eaeab80fcd62c9bfda490b446d1966)]:
- effect@4.0.0-beta.23
## 4.0.0-beta.22
### Patch Changes
- Updated dependencies [[`0874332`](https://github.com/Effect-TS/effect-smol/commit/0874332f7c81118b06ac2eb105e0710211631479), [`c592dcd`](https://github.com/Effect-TS/effect-smol/commit/c592dcde0697e322065c8f418c0480ef910cb183), [`1dbe28d`](https://github.com/Effect-TS/effect-smol/commit/1dbe28dac8299cd3e218c9768450cfd173b5e294), [`564d730`](https://github.com/Effect-TS/effect-smol/commit/564d730b6bbf38dd8548a3b046e7a693b28699a4), [`3cfadc4`](https://github.com/Effect-TS/effect-smol/commit/3cfadc458b070c6cba6c5674b72a059f1e49118b), [`6634fd0`](https://github.com/Effect-TS/effect-smol/commit/6634fd07da067d80b8261fb2959d1a952b9e412e), [`d10dabe`](https://github.com/Effect-TS/effect-smol/commit/d10dabeb7af9a368f995829cd36ad08167cd8f95), [`f82f549`](https://github.com/Effect-TS/effect-smol/commit/f82f549a09e950e9d4987f279a800f4d953f0939), [`78a3382`](https://github.com/Effect-TS/effect-smol/commit/78a3382ddfbe034408f7480fa794733d9e82147b)]:
- effect@4.0.0-beta.22
## 4.0.0-beta.21
### Patch Changes
- Updated dependencies [[`e691909`](https://github.com/Effect-TS/effect-smol/commit/e691909495ccb162ea7bfa351dd74632b99997cb), [`d5f413f`](https://github.com/Effect-TS/effect-smol/commit/d5f413f3c8fc57f2413cc5649c2003d6d4e5a6d7), [`139d152`](https://github.com/Effect-TS/effect-smol/commit/139d152941e562a073b5be12e8d66c8a4d4a8a57), [`947e3d4`](https://github.com/Effect-TS/effect-smol/commit/947e3d436ab8a017efda9b29be523efd1ca8df28), [`84b2cce`](https://github.com/Effect-TS/effect-smol/commit/84b2ccefe2aa3a7413b86738a4dc33cdb311ca55), [`7f5305e`](https://github.com/Effect-TS/effect-smol/commit/7f5305e69f5a33309e77b08a576edb25d7daaee2), [`9e6fd84`](https://github.com/Effect-TS/effect-smol/commit/9e6fd8471c93a3c643929151a3bdb62cb9c0ca0e), [`fdb8a4b`](https://github.com/Effect-TS/effect-smol/commit/fdb8a4b172721fbefe98bd5aa6fe4f0efd1da3eb), [`0f986ef`](https://github.com/Effect-TS/effect-smol/commit/0f986ef22f196fe091a7afdbd179485a7d888882), [`9355fc0`](https://github.com/Effect-TS/effect-smol/commit/9355fc0ffb5b7382146a5aed9eea83974b10d007)]:
- effect@4.0.0-beta.21
## 4.0.0-beta.20
### Patch Changes
- [#1529](https://github.com/Effect-TS/effect-smol/pull/1529) [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8) Thanks @tim-smart! - Add dedicated AiError metadata interfaces per reason so provider packages can safely augment metadata without conflicting module declarations.
- [#1528](https://github.com/Effect-TS/effect-smol/pull/1528) [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34) Thanks @tim-smart! - Add `Model.ModelName` and provide it from AI model constructors.
- Updated dependencies [[`842a624`](https://github.com/Effect-TS/effect-smol/commit/842a624f79d5e1407460b0ef3ab27d14d48ccf74), [`4785eef`](https://github.com/Effect-TS/effect-smol/commit/4785eef5d7cf1edb96ef2509aed2ba4d1edf3862), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`12ee8e2`](https://github.com/Effect-TS/effect-smol/commit/12ee8e27df7eb393d83a5e403390d0cfc82ca732), [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34), [`989d1cc`](https://github.com/Effect-TS/effect-smol/commit/989d1cca936fce0cc459057825ba40e3f5ef3827)]:
- effect@4.0.0-beta.20
## 4.0.0-beta.19
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.19
## 4.0.0-beta.18
### Patch Changes
- Updated dependencies [[`01e31fd`](https://github.com/Effect-TS/effect-smol/commit/01e31fdf8e5206849d23cbafd23a346f2f177ab8), [`0890aab`](https://github.com/Effect-TS/effect-smol/commit/0890aab15ed9c5ba52c383a72fdc6a444d7504d5), [`725260b`](https://github.com/Effect-TS/effect-smol/commit/725260b53f5142d6af7a93a2f9f464f974eda92d)]:
- effect@4.0.0-beta.18
## 4.0.0-beta.17
### Patch Changes
- Updated dependencies [[`8f59c32`](https://github.com/Effect-TS/effect-smol/commit/8f59c32922597a48392744f7203e284866747781)]:
- effect@4.0.0-beta.17
## 4.0.0-beta.16
### Patch Changes
- Updated dependencies [[`bf9096c`](https://github.com/Effect-TS/effect-smol/commit/bf9096c52a7d8791d93d232739e523eb84f6625a), [`29f81ca`](https://github.com/Effect-TS/effect-smol/commit/29f81ca07c67dba265804b140a7487fb15a5fc6b), [`68eb28c`](https://github.com/Effect-TS/effect-smol/commit/68eb28c2b0fc67a9f6204ade9bd16c5b37803bfb)]:
- effect@4.0.0-beta.16
## 4.0.0-beta.15
### Patch Changes
- [#1502](https://github.com/Effect-TS/effect-smol/pull/1502) [`285b7e6`](https://github.com/Effect-TS/effect-smol/commit/285b7e667167566d5788367d5155b19c79f1bf22) Thanks @tim-smart! - allow undefined for ai config
- Updated dependencies [[`24ae609`](https://github.com/Effect-TS/effect-smol/commit/24ae60995d2fd7d621be356cdfdfd328c79639ba), [`0e3c059`](https://github.com/Effect-TS/effect-smol/commit/0e3c059987caa55ebd0c134f7c7b147c639c328e), [`e843b0a`](https://github.com/Effect-TS/effect-smol/commit/e843b0a7d7e7b600a0b3bd477f24e2e4cd26bc8b), [`f4389a2`](https://github.com/Effect-TS/effect-smol/commit/f4389a2cca3c5bbf00d69779f52ce41255f15a28), [`5b73de0`](https://github.com/Effect-TS/effect-smol/commit/5b73de095b3402d0c5c74092ace6ce18ebfad566), [`595d2d6`](https://github.com/Effect-TS/effect-smol/commit/595d2d6e7d50419f3532bd39266191532ace38f2)]:
- effect@4.0.0-beta.15
## 4.0.0-beta.14
### Patch Changes
- Updated dependencies [[`c414700`](https://github.com/Effect-TS/effect-smol/commit/c414700ef1932e4b67d0102856de417336912350), [`a30c969`](https://github.com/Effect-TS/effect-smol/commit/a30c9699c0d736cf3952041e45d508b7d58907a9)]:
- effect@4.0.0-beta.14
## 4.0.0-beta.13
### Patch Changes
- Updated dependencies [[`368f4c3`](https://github.com/Effect-TS/effect-smol/commit/368f4c363dd117e6f5a19ad77b161176cfd29fdd), [`db8a579`](https://github.com/Effect-TS/effect-smol/commit/db8a579e93e93ff73b1e60712732e03b597b916b), [`668b703`](https://github.com/Effect-TS/effect-smol/commit/668b70337e9ddbb0d1ae2282a95c282ce404e562), [`d40e76b`](https://github.com/Effect-TS/effect-smol/commit/d40e76b973543979e60e04a6baca04a8c65bdfc2), [`6e18cf8`](https://github.com/Effect-TS/effect-smol/commit/6e18cf883e9905ca718a6697b6a2a4bbd42739aa), [`86062e8`](https://github.com/Effect-TS/effect-smol/commit/86062e8a0c61bca5412fc40d2cf151d676901f08), [`c27ce75`](https://github.com/Effect-TS/effect-smol/commit/c27ce75d34c74dcfc6dba1bf77f1ce88f410a0de), [`e2d4fbf`](https://github.com/Effect-TS/effect-smol/commit/e2d4fbfeeda6a5d2a4c5aeb0501d8240c248b9eb), [`114ab42`](https://github.com/Effect-TS/effect-smol/commit/114ab42ad0edc590d29169675a493e0e915aa58f), [`484caec`](https://github.com/Effect-TS/effect-smol/commit/484caec47cccac8b86db2910742e406dfc7173ab)]:
- effect@4.0.0-beta.13
## 4.0.0-beta.12
### Patch Changes
- Updated dependencies [[`70a74e8`](https://github.com/Effect-TS/effect-smol/commit/70a74e88a8767c9d4acdb9e5f25aec9a33588d07), [`b5b6e10`](https://github.com/Effect-TS/effect-smol/commit/b5b6e10621d54bf8c9857fec0d647ced78ecd857), [`f5ce5a9`](https://github.com/Effect-TS/effect-smol/commit/f5ce5a915359c6ebf254079e1da23cab6cde34fb), [`a29eb70`](https://github.com/Effect-TS/effect-smol/commit/a29eb702ffe3fc58bd28c4d7857298cd65d73668), [`c7b36e5`](https://github.com/Effect-TS/effect-smol/commit/c7b36e541a23e9a00f64e25b23851e51a37dfce5), [`9381d6d`](https://github.com/Effect-TS/effect-smol/commit/9381d6d4d9d819a81a46e56d0364c76e92a4fbca), [`88439f1`](https://github.com/Effect-TS/effect-smol/commit/88439f13ca13549f3e4822c48c4f019c14fc2bcc), [`e35307d`](https://github.com/Effect-TS/effect-smol/commit/e35307dbeb8eb26a9923f958b894a8eaaf259bf2), [`c7df4bc`](https://github.com/Effect-TS/effect-smol/commit/c7df4bce34009474c63d62a807abfdafb76971eb), [`accaf3b`](https://github.com/Effect-TS/effect-smol/commit/accaf3be7ac8da36e2334c509c23b8c9e88ea160), [`3e1c270`](https://github.com/Effect-TS/effect-smol/commit/3e1c2707bbdf67720af1509642b8ced195790882), [`6cd81f7`](https://github.com/Effect-TS/effect-smol/commit/6cd81f73baad86f5bbfa455a55d75cde71e9611a), [`f222da3`](https://github.com/Effect-TS/effect-smol/commit/f222da3cdb44554f3324c2c52d0d005ee575053e), [`61f901d`](https://github.com/Effect-TS/effect-smol/commit/61f901d830005b66e22d1de889fda132aeea97cd)]:
- effect@4.0.0-beta.12
## 4.0.0-beta.11
### Patch Changes
- Updated dependencies [[`88659ed`](https://github.com/Effect-TS/effect-smol/commit/88659edb26e3623d557dccfe914c2c949672da16), [`f2915e8`](https://github.com/Effect-TS/effect-smol/commit/f2915e8e2efe80d50c281e53f297b9701d6dc199), [`eb71ace`](https://github.com/Effect-TS/effect-smol/commit/eb71acebbe0f228e4920278013beee3b67d62310), [`2a16999`](https://github.com/Effect-TS/effect-smol/commit/2a169996c7513d377ac47adbfd68e1490457135c), [`d42dd52`](https://github.com/Effect-TS/effect-smol/commit/d42dd52f11203f8e749fb5d3ecf7153e4a5a6814), [`339adaf`](https://github.com/Effect-TS/effect-smol/commit/339adaf850a62a892adebcb208c2d9dddf3b97b3), [`de19645`](https://github.com/Effect-TS/effect-smol/commit/de1964526d01102dd1cb99c8cfdd3e8df1f49ef1), [`9b1dc3b`](https://github.com/Effect-TS/effect-smol/commit/9b1dc3bcf2a1b68d0a67e3465db5ad01a1a56997), [`e4cb2f5`](https://github.com/Effect-TS/effect-smol/commit/e4cb2f55b30f4771ec1bf613ced36d6d96464dd5), [`8bced95`](https://github.com/Effect-TS/effect-smol/commit/8bced954ecb35d4489197a57b0efe927e7d75f49), [`9431420`](https://github.com/Effect-TS/effect-smol/commit/94314207c8019918200fbcb97aec992219f801f0), [`948dca2`](https://github.com/Effect-TS/effect-smol/commit/948dca22e4f672ba7a6db57f9899272bec7c08b8), [`d18e327`](https://github.com/Effect-TS/effect-smol/commit/d18e32765a2665e31ffb31e746bf983fcfac34c5), [`ab512f7`](https://github.com/Effect-TS/effect-smol/commit/ab512f7be1c0e6b359da921e22cd4944e4c57d3e)]:
- effect@4.0.0-beta.11
## 4.0.0-beta.10
### Patch Changes
- Updated dependencies [[`371acab`](https://github.com/Effect-TS/effect-smol/commit/371acabb58d56f3a7a5e3e33d3d5fdc9f5573c74), [`856d774`](https://github.com/Effect-TS/effect-smol/commit/856d7741f1e296dd5048c6ff2b44b95d023e6ae4), [`b9e9202`](https://github.com/Effect-TS/effect-smol/commit/b9e92023c38caa322975d77cfe83e2d34ac9305a), [`1d1a974`](https://github.com/Effect-TS/effect-smol/commit/1d1a974bd280c81bff5d4505491cda03ba7a3f36), [`6bfe2a6`](https://github.com/Effect-TS/effect-smol/commit/6bfe2a659bc6335db75709931f405da45301cba2), [`b12c811`](https://github.com/Effect-TS/effect-smol/commit/b12c81157be287b1649c210616a244b50ec094d2), [`d17d98a`](https://github.com/Effect-TS/effect-smol/commit/d17d98ad78e2b44d95ef434adab79ac3c35e75ab), [`68c3c7c`](https://github.com/Effect-TS/effect-smol/commit/68c3c7cb1e06ed94fa5c4c123a234b4ccbfdecd8)]:
- effect@4.0.0-beta.10
## 4.0.0-beta.9
### Patch Changes
- Updated dependencies [[`3386557`](https://github.com/Effect-TS/effect-smol/commit/338655731564a7be9f8859dedbf4d5bcac6eb350), [`b6666e3`](https://github.com/Effect-TS/effect-smol/commit/b6666e3cf6bd44ba1a8704e65c256c30359cb422)]:
- effect@4.0.0-beta.9
## 4.0.0-beta.8
### Patch Changes
- [#1354](https://github.com/Effect-TS/effect-smol/pull/1354) [`b94962c`](https://github.com/Effect-TS/effect-smol/commit/b94962c249d46cf96cdf2e41188dc9feda41536a) Thanks @IMax153! - Fix the generated schemas for ai providers
- Updated dependencies [[`246e672`](https://github.com/Effect-TS/effect-smol/commit/246e672dbbd7848d60e0c78fd66671b2f10b3752), [`807dec0`](https://github.com/Effect-TS/effect-smol/commit/807dec03801b4c58a6d00c237b6d98d6386911df)]:
- effect@4.0.0-beta.8
## 4.0.0-beta.7
### Patch Changes
- Updated dependencies [[`a2bda6d`](https://github.com/Effect-TS/effect-smol/commit/a2bda6d4ef6de9d9b0c53ae2df5434f778d6161a), [`1f95a2b`](https://github.com/Effect-TS/effect-smol/commit/1f95a2b5aa9524bb38f4437f4691a664bf463ca1), [`a8d5e79`](https://github.com/Effect-TS/effect-smol/commit/a8d5e792fec201a83af0eb92fc79928d055125fd), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`06d8a03`](https://github.com/Effect-TS/effect-smol/commit/06d8a0391631e6130e3ab25227e59817852e227f), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`f9e883e`](https://github.com/Effect-TS/effect-smol/commit/f9e883e266fbda870336ee62f46b7ac85ba3de6e), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430)]:
- effect@4.0.0-beta.7
## 4.0.0-beta.6
### Patch Changes
- Updated dependencies [[`3247da2`](https://github.com/Effect-TS/effect-smol/commit/3247da28331f345f68be5dbd2974a7e03d300fe1), [`f205705`](https://github.com/Effect-TS/effect-smol/commit/f2057050dbd034b8c186be2d40c3d03ee63a5a3b), [`f35022c`](https://github.com/Effect-TS/effect-smol/commit/f35022c212e4111527e1bb43f360a67b2b49fa85), [`8622721`](https://github.com/Effect-TS/effect-smol/commit/86227217b02d43680a3c6f3c21731b1d852c91f5), [`fc660ab`](https://github.com/Effect-TS/effect-smol/commit/fc660ab8b5ebae38b8d6b96cbf2f9b880cc09253), [`f37dc33`](https://github.com/Effect-TS/effect-smol/commit/f37dc335f64622fa9ce8d6d1d5dd8fc3f260257b), [`3662f32`](https://github.com/Effect-TS/effect-smol/commit/3662f328fcfa3b2fa01ffa79da40e12e93fcede8), [`a7d436f`](https://github.com/Effect-TS/effect-smol/commit/a7d436f438dcd7f49b9485e4e95a4511f31fad7d), [`6856a41`](https://github.com/Effect-TS/effect-smol/commit/6856a415d7eddd9d73d60919e976f1d071421be4), [`8c417d0`](https://github.com/Effect-TS/effect-smol/commit/8c417d03475e5e12d00dca0c4781d0af7e66b86c), [`5419570`](https://github.com/Effect-TS/effect-smol/commit/5419570ba47ce882a3a10882707b46f66e464906), [`449c5ed`](https://github.com/Effect-TS/effect-smol/commit/449c5ed5318e8a874e730420bcf52918fa2ec80f), [`4b5ec12`](https://github.com/Effect-TS/effect-smol/commit/4b5ec12f87f95f2a3cd8fe4d5b26c6eb0529381a), [`df87937`](https://github.com/Effect-TS/effect-smol/commit/df879375fc3b169c43f9c434b3775e12b80dffe4), [`5dbfca8`](https://github.com/Effect-TS/effect-smol/commit/5dbfca8d1dbb6d18d1605d4f8562e99c86e2ff11), [`e629497`](https://github.com/Effect-TS/effect-smol/commit/e6294973d55597ab6b6deca6babbe1e946b2c91d), [`981c991`](https://github.com/Effect-TS/effect-smol/commit/981c991cd78db34def815d5754379d737157f005), [`1ca2ed6`](https://github.com/Effect-TS/effect-smol/commit/1ca2ed67301a5dc40ae0ed94346b99f26fd22bbe), [`45722bd`](https://github.com/Effect-TS/effect-smol/commit/45722bde974458311f11ad237711363a10ec6894), [`eb2a85e`](https://github.com/Effect-TS/effect-smol/commit/eb2a85ed4dc162b2535d304799333a5a20477fd0)]:
- effect@4.0.0-beta.6
## 4.0.0-beta.5
### Patch Changes
- Updated dependencies [[`f6e133e`](https://github.com/Effect-TS/effect-smol/commit/f6e133e9a16b32317bd09ff08c12b97a0ae44600), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8), [`a88e206`](https://github.com/Effect-TS/effect-smol/commit/a88e206e44dc66ca5a2b45bedc797877c5dbb083), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8)]:
- effect@4.0.0-beta.5
## 4.0.0-beta.4
### Patch Changes
- Updated dependencies [[`c5a18ef`](https://github.com/Effect-TS/effect-smol/commit/c5a18ef44171e3880bf983faee74529908974b32), [`bc6b885`](https://github.com/Effect-TS/effect-smol/commit/bc6b885b94d887a200657c0775dfa874dc15bc0c)]:
- effect@4.0.0-beta.4
## 4.0.0-beta.3
### Patch Changes
- [#1306](https://github.com/Effect-TS/effect-smol/pull/1306) [`c9fb5a5`](https://github.com/Effect-TS/effect-smol/commit/c9fb5a5bfb1c331c91d592323f4027b72a3bc0b4) Thanks @Leka74! - Fix sparse array crash in `streamText` tool call handling.
- Updated dependencies [[`3a0cf36`](https://github.com/Effect-TS/effect-smol/commit/3a0cf36eff106ba48d74e133c1598cd40613e530), [`c4da328`](https://github.com/Effect-TS/effect-smol/commit/c4da328d32fad1d61e0e538f5d371edf61521d7e)]:
- effect@4.0.0-beta.3
## 4.0.0-beta.2
### Patch Changes
- Updated dependencies [[`a22ce73`](https://github.com/Effect-TS/effect-smol/commit/a22ce73b2bd9305b7ba665694d2255c0e6d5a8d0), [`ebdabf7`](https://github.com/Effect-TS/effect-smol/commit/ebdabf79ff4e62c8384aa8cf9a8d2787d536ee78), [`8f663bb`](https://github.com/Effect-TS/effect-smol/commit/8f663bb121021bf12bd264e8ae385187cb7a5dae)]:
- effect@4.0.0-beta.2
## 4.0.0-beta.1
### Patch Changes
- Updated dependencies [[`0fecf70`](https://github.com/Effect-TS/effect-smol/commit/0fecf70048057623eed7c584a06671773a2b1743), [`709569e`](https://github.com/Effect-TS/effect-smol/commit/709569ed76bead9ebb0670599e4d890a07ca5a43)]:
- effect@4.0.0-beta.1
## 4.0.0-beta.0
### Major Changes
- [#1183](https://github.com/Effect-TS/effect-smol/pull/1183) [`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66) Thanks @tim-smart! - v4 beta
### Patch Changes
- Updated dependencies [[`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66)]:
- effect@4.0.0-beta.0

View File

@@ -0,0 +1,35 @@
# yaml-language-server: $schema=../../tools/ai-codegen/codegen.schema.json
spec: https://openrouter.ai/openapi.yaml
output: src/Generated.ts
name: OpenRouterClient
header: |
/**
* @since 1.0.0
*/
excludeAnnotations:
- default
disableAdditionalProperties: true
patches:
# Replace OpenResponsesStreamEvent with a flat oneOf of $refs.
# The original uses allOf wrappers that inline OpenResponsesNonStreamingResponse
# into each variant, producing lines over 1M chars that crash dprint.
- '[{"op":"replace","path":"/components/schemas/OpenResponsesStreamEvent","value":{"oneOf":[{"$ref":"#/components/schemas/OpenResponsesCreatedEvent"},{"$ref":"#/components/schemas/OpenResponsesInProgressEvent"},{"$ref":"#/components/schemas/OpenResponsesCompletedEvent"},{"$ref":"#/components/schemas/OpenResponsesIncompleteEvent"},{"$ref":"#/components/schemas/OpenResponsesFailedEvent"},{"$ref":"#/components/schemas/OpenResponsesErrorEvent"},{"$ref":"#/components/schemas/OpenResponsesOutputItemAddedEvent"},{"$ref":"#/components/schemas/OpenResponsesOutputItemDoneEvent"},{"$ref":"#/components/schemas/OpenResponsesContentPartAddedEvent"},{"$ref":"#/components/schemas/OpenResponsesContentPartDoneEvent"},{"$ref":"#/components/schemas/OpenResponsesTextDeltaEvent"},{"$ref":"#/components/schemas/OpenResponsesTextDoneEvent"},{"$ref":"#/components/schemas/OpenResponsesRefusalDeltaEvent"},{"$ref":"#/components/schemas/OpenResponsesRefusalDoneEvent"},{"$ref":"#/components/schemas/OpenResponsesOutputTextAnnotationAddedEvent"},{"$ref":"#/components/schemas/OpenResponsesFunctionCallArgumentsDeltaEvent"},{"$ref":"#/components/schemas/OpenResponsesFunctionCallArgumentsDoneEvent"},{"$ref":"#/components/schemas/OpenResponsesReasoningDeltaEvent"},{"$ref":"#/components/schemas/OpenResponsesReasoningDoneEvent"},{"$ref":"#/components/schemas/OpenResponsesReasoningSummaryPartAddedEvent"},{"$ref":"#/components/schemas/OpenResponsesReasoningSummaryPartDoneEvent"},{"$ref":"#/components/schemas/OpenResponsesReasoningSummaryTextDeltaEvent"},{"$ref":"#/components/schemas/OpenResponsesReasoningSummaryTextDoneEvent"},{"$ref":"#/components/schemas/OpenResponsesImageGenCallInProgress"},{"$ref":"#/components/schemas/OpenResponsesImageGenCallGenerating"},{"$ref":"#/components/schemas/OpenResponsesImageGenCallPartialImage"},{"$ref":"#/components/schemas/OpenResponsesImageGenCallCompleted"}]}}]'
# Fix AssistantMessage images to include type:"image_url" discriminator and nullable
- '[{"op":"replace","path":"/components/schemas/AssistantMessage/properties/images","value":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"image_url"},"image_url":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]}},"required":["type","image_url"]}},{"type":"null"}]}}]'
# Add images to ChatStreamingMessageChunk (streaming delta)
- '[{"op":"add","path":"/components/schemas/ChatStreamingMessageChunk/properties/images","value":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"image_url"},"image_url":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]}},"required":["type","image_url"]}},{"type":"null"}]}}]'
# Add annotations to AssistantMessage (non-streaming)
- '[{"op":"add","path":"/components/schemas/AssistantMessage/properties/annotations","value":{"anyOf":[{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"url_citation"},"url_citation":{"type":"object","properties":{"url":{"type":"string"},"title":{"type":"string"},"start_index":{"type":"number"},"end_index":{"type":"number"},"content":{"type":"string"}},"required":["url"]}},"required":["type","url_citation"]},{"type":"object","properties":{"type":{"type":"string","const":"file_annotation"},"file_annotation":{"type":"object","properties":{"file_id":{"type":"string"},"quote":{"type":"string"}},"required":["file_id"]}},"required":["type","file_annotation"]},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file":{"type":"object","properties":{"hash":{"type":"string"},"name":{"type":"string"},"content":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"}},"required":["type"]}}},"required":["hash","name"]}},"required":["type","file"]}]}},{"type":"null"}]}}]'
# Add annotations to ChatStreamingMessageChunk (streaming delta)
- '[{"op":"add","path":"/components/schemas/ChatStreamingMessageChunk/properties/annotations","value":{"anyOf":[{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"url_citation"},"url_citation":{"type":"object","properties":{"url":{"type":"string"},"title":{"type":"string"},"start_index":{"type":"number"},"end_index":{"type":"number"},"content":{"type":"string"}},"required":["url"]}},"required":["type","url_citation"]},{"type":"object","properties":{"type":{"type":"string","const":"file_annotation"},"file_annotation":{"type":"object","properties":{"file_id":{"type":"string"},"quote":{"type":"string"}},"required":["file_id"]}},"required":["type","file_annotation"]},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file":{"type":"object","properties":{"hash":{"type":"string"},"name":{"type":"string"},"content":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"}},"required":["type"]}}},"required":["hash","name"]}},"required":["type","file"]}]}},{"type":"null"}]}}]'
# Make tool call delta fields nullable (models like kimi-k2.5, minimax-m2.5 send null)
- '[{"op":"replace","path":"/components/schemas/ChatStreamingMessageToolCall/properties/id","value":{"anyOf":[{"type":"string"},{"type":"null"}]}},{"op":"replace","path":"/components/schemas/ChatStreamingMessageToolCall/properties/type","value":{"anyOf":[{"type":"string","const":"function"},{"type":"null"}]}},{"op":"replace","path":"/components/schemas/ChatStreamingMessageToolCall/properties/function/properties/name","value":{"anyOf":[{"type":"string"},{"type":"null"}]}}]'
# Make finish_reason optional (only present on final streaming chunk)
- '[{"op":"remove","path":"/components/schemas/ChatStreamingChoice/required/1"}]'
replacements:
# Schema.Unknown doesn't work with Schema.toCodecJson (used by HttpClientResponse.schemaBodyJson)
# Replace with Schema.Json which properly handles arbitrary JSON values
- from: "Schema.Record(Schema.String, Schema.Unknown)"
to: "Schema.Record(Schema.String, Schema.Json)"
- from: "{ readonly [x: string]: unknown }"
to: "{ readonly [x: string]: Schema.Json }"

View File

@@ -0,0 +1,23 @@
{
"$schema": "../../node_modules/@effect/docgen/schema.json",
"srcLink": "https://github.com/Effect-TS/effect/tree/main/packages/ai/openrouter/src/",
"exclude": ["src/Generated.ts", "src/internal/**/*.ts"],
"examplesCompilerOptions": {
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"rewriteRelativeImportExtensions": true,
"allowImportingTsExtensions": true,
"paths": {
"effect": ["../../../effect/src/index.js"],
"effect/*": ["../../../effect/src/*.js"]
},
"plugins": [
{ "name": "@effect/language-service", "includeSuggestionsInTsc": false }
]
}
}

View File

@@ -0,0 +1,66 @@
{
"name": "@effect/ai-openrouter",
"version": "4.0.0-beta.99",
"type": "module",
"license": "MIT",
"description": "An OpenRouter provider integration for Effect AI SDK",
"homepage": "https://effect.website",
"repository": {
"type": "git",
"url": "https://github.com/Effect-TS/effect.git",
"directory": "packages/ai/openrouter"
},
"bugs": {
"url": "https://github.com/Effect-TS/effect/issues"
},
"tags": [
"typescript",
"ai",
"openrouter"
],
"keywords": [
"typescript",
"ai",
"openrouter"
],
"sideEffects": [],
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts",
"./*": "./src/*.ts",
"./internal/*": null,
"./*/index": null
},
"files": [
"src/**/*.ts",
"dist/**/*.js",
"dist/**/*.js.map",
"dist/**/*.d.ts",
"dist/**/*.d.ts.map"
],
"publishConfig": {
"access": "public",
"provenance": true,
"exports": {
"./package.json": "./package.json",
".": "./dist/index.js",
"./*": "./dist/*.js",
"./internal/*": null,
"./*/index": null
}
},
"scripts": {
"codegen": "effect-utils codegen",
"build": "tsc -b tsconfig.json && pnpm babel",
"babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
"check": "tsc -b tsconfig.json",
"test": "vitest",
"coverage": "vitest --coverage"
},
"devDependencies": {
"effect": "workspace:^"
},
"peerDependencies": {
"effect": "workspace:^"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,357 @@
/**
* The `OpenRouterClient` module provides an Effect service for calling
* OpenRouter's chat completions API. It wraps the generated OpenRouter HTTP
* client with Effect-native constructors, layers, authentication and optional
* site ranking headers, typed errors, and streaming support.
*
* @since 4.0.0
*/
import type * as Config from "effect/Config"
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { identity } from "effect/Function"
import * as Layer from "effect/Layer"
import * as Predicate from "effect/Predicate"
import type * as Redacted from "effect/Redacted"
import * as Schema from "effect/Schema"
import * as Stream from "effect/Stream"
import type * as AiError from "effect/unstable/ai/AiError"
import * as Sse from "effect/unstable/encoding/Sse"
import * as HttpBody from "effect/unstable/http/HttpBody"
import * as HttpClient from "effect/unstable/http/HttpClient"
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import type * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
import * as Generated from "./Generated.ts"
import * as Errors from "./internal/errors.ts"
import { OpenRouterConfig } from "./OpenRouterConfig.ts"
// =============================================================================
// Service Interface
// =============================================================================
/**
* The OpenRouter client service interface.
*
* **Details**
*
* Provides methods for interacting with OpenRouter's Chat Completions API,
* including both synchronous and streaming message creation.
*
* @category models
* @since 4.0.0
*/
export interface Service {
readonly client: Generated.OpenRouterClient
readonly createChatCompletion: (
options: typeof Generated.ChatGenerationParams.Encoded
) => Effect.Effect<
[body: typeof Generated.SendChatCompletionRequest200.Type, response: HttpClientResponse.HttpClientResponse],
AiError.AiError
>
readonly createChatCompletionStream: (
options: Omit<typeof Generated.ChatGenerationParams.Encoded, "stream" | "stream_options">
) => Effect.Effect<
[
response: HttpClientResponse.HttpClientResponse,
stream: Stream.Stream<ChatStreamingResponseChunkData, AiError.AiError>
],
AiError.AiError
>
}
/**
* Decoded `data` payload from an OpenRouter chat completion streaming chunk.
*
* **Details**
*
* The payload contains streamed choices, model metadata, optional usage, and may
* include an OpenRouter error object for a streamed response.
*
* @category models
* @since 4.0.0
*/
export type ChatStreamingResponseChunkData = typeof Generated.ChatStreamingResponseChunk.fields.data.Type
// =============================================================================
// Service Identifier
// =============================================================================
/**
* Service tag for the OpenRouter client.
*
* **When to use**
*
* Use when accessing or providing the OpenRouter client service through
* Effect's context.
*
* @see {@link make} for constructing an OpenRouter client effectfully
* @see {@link layer} for providing a client from explicit options
* @see {@link layerConfig} for providing a client from `Config`
*
* @category services
* @since 4.0.0
*/
export class OpenRouterClient extends Context.Service<
OpenRouterClient,
Service
>()("@effect/ai-openrouter/OpenRouterClient") {}
// =============================================================================
// Options
// =============================================================================
/**
* Configuration for creating an OpenRouter client.
*
* @category options
* @since 4.0.0
*/
export type Options = {
readonly apiKey?: Redacted.Redacted<string> | undefined
readonly apiUrl?: string | undefined
/**
* Optional URL of your site for rankings on `openrouter.ai`.
*/
readonly siteReferrer?: string | undefined
/**
* Optional title of your site for rankings on `openrouter.ai`.
*/
readonly siteTitle?: string | undefined
/**
* Optional transformer for the underlying HTTP client.
*
* **When to use**
*
* Use to add middleware, logging, or custom request/response handling.
*/
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
}
// =============================================================================
// Constructor
// =============================================================================
/**
* Creates an OpenRouter client service from explicit options.
*
* **When to use**
*
* Use when you need the OpenRouter client service value inside an effect.
*
* **Details**
*
* The returned service uses the current `HttpClient`, prepends `apiUrl` or
* `https://openrouter.ai/api/v1`, adds the bearer token and optional
* `HTTP-Referer` and `X-Title` headers, accepts JSON responses, and applies
* `transformClient` when provided.
*
* **Gotchas**
*
* Scoped `OpenRouterConfig.withClientTransform` applies to generated client
* request methods. Streaming chat completion requests are sent directly by this
* module and do not read that scoped transform.
*
* @see {@link layer} for providing this client from explicit options
* @see {@link layerConfig} for loading client settings from `Config`
*
* @category constructors
* @since 4.0.0
*/
export const make = Effect.fnUntraced(
function*(options: Options): Effect.fn.Return<Service, never, HttpClient.HttpClient> {
const baseClient = yield* HttpClient.HttpClient
const httpClient = baseClient.pipe(
HttpClient.mapRequest((request) =>
request.pipe(
HttpClientRequest.prependUrl(options.apiUrl ?? "https://openrouter.ai/api/v1"),
options.apiKey ? HttpClientRequest.bearerToken(options.apiKey) : identity,
options.siteReferrer ? HttpClientRequest.setHeader("HTTP-Referer", options.siteReferrer) : identity,
options.siteTitle ? HttpClientRequest.setHeader("X-Title", options.siteTitle) : identity,
HttpClientRequest.acceptJson
)
),
options.transformClient ?? identity
)
const httpClientOk = HttpClient.filterStatusOk(httpClient)
const client = Generated.make(httpClient, {
transformClient: Effect.fnUntraced(function*(client) {
const config = yield* OpenRouterConfig.getOrUndefined
if (Predicate.isNotUndefined(config?.transformClient)) {
return config.transformClient(client)
}
return client
})
})
const createChatCompletion: Service["createChatCompletion"] = (payload) =>
client.sendChatCompletionRequest({ payload, config: { includeResponse: true } }).pipe(
Effect.catchTags({
SendChatCompletionRequest400: (error) => Effect.fail(Errors.mapClientError(error, "createChatCompletion")),
SendChatCompletionRequest401: (error) => Effect.fail(Errors.mapClientError(error, "createChatCompletion")),
SendChatCompletionRequest429: (error) => Effect.fail(Errors.mapClientError(error, "createChatCompletion")),
SendChatCompletionRequest500: (error) => Effect.fail(Errors.mapClientError(error, "createChatCompletion")),
HttpClientError: (error) => Errors.mapHttpClientError(error, "createChatCompletion"),
SchemaError: (error) => Effect.fail(Errors.mapSchemaError(error, "createChatCompletion"))
})
)
const buildChatCompletionStream = (
response: HttpClientResponse.HttpClientResponse
): [
HttpClientResponse.HttpClientResponse,
Stream.Stream<ChatStreamingResponseChunkData, AiError.AiError>
] => {
const stream = response.stream.pipe(
Stream.decodeText(),
Stream.pipeThroughChannel(Sse.decode()),
Stream.mapEffect((event) => decodeChatCompletionSseData(event.data)),
Stream.takeWhile((data) => data !== "[DONE]"),
Stream.catchTags({
// TODO: handle SSE retries
Retry: (error) => Stream.die(error),
HttpClientError: (error) => Stream.fromEffect(Errors.mapHttpClientError(error, "createChatCompletionStream")),
SchemaError: (error) => Stream.fail(Errors.mapSchemaError(error, "createChatCompletionStream"))
})
) as any
return [response, stream]
}
const createChatCompletionStream: Service["createChatCompletionStream"] = (payload) =>
httpClientOk.execute(
HttpClientRequest.post("/chat/completions", {
body: HttpBody.jsonUnsafe({
...payload,
stream: true,
stream_options: { include_usage: true }
})
})
).pipe(
Effect.map(buildChatCompletionStream),
Effect.catchTag(
"HttpClientError",
(error) => Errors.mapHttpClientError(error, "createChatCompletionStream")
)
)
return OpenRouterClient.of({
client,
createChatCompletion,
createChatCompletionStream
})
}
)
// =============================================================================
// Layers
// =============================================================================
/**
* Creates a layer for the OpenRouter client with the given options.
*
* **When to use**
*
* Use when you already have the OpenRouter client options in code and want to
* provide `OpenRouterClient` as a layer.
*
* @see {@link make} for constructing the client service effectfully
* @see {@link layerConfig} for loading client settings from `Config`
*
* @category layers
* @since 4.0.0
*/
export const layer = (options: Options): Layer.Layer<OpenRouterClient, never, HttpClient.HttpClient> =>
Layer.effect(OpenRouterClient, make(options))
/**
* Creates a layer for the OpenRouter client from provided `Config` values.
*
* **When to use**
*
* Use when you need client settings for OpenRouter to be read from Effect
* `Config` values while providing `OpenRouterClient` as a layer.
*
* **Details**
*
* Only config values supplied in `options` are loaded. Omitted fields are
* passed to `make` as `undefined`, and `transformClient` is forwarded as a
* plain option.
*
* @see {@link make} for constructing the client service effectfully
* @see {@link layer} for providing the client from already-resolved options
*
* @category layers
* @since 4.0.0
*/
export const layerConfig = (options?: {
/**
* The config value to load for the API key.
*/
readonly apiKey?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
/**
* The config value to load for the API URL.
*/
readonly apiUrl?: Config.Config<string> | undefined
/**
* The config value to load for the site referrer URL.
*/
readonly siteReferrer?: Config.Config<string> | undefined
/**
* The config value to load for the site title.
*/
readonly siteTitle?: Config.Config<string> | undefined
/**
* Optional transformer for the HTTP client.
*/
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
}): Layer.Layer<OpenRouterClient, Config.ConfigError, HttpClient.HttpClient> =>
Layer.effect(
OpenRouterClient,
Effect.gen(function*() {
const apiKey = Predicate.isNotUndefined(options?.apiKey)
? yield* options.apiKey
: undefined
const apiUrl = Predicate.isNotUndefined(options?.apiUrl)
? yield* options.apiUrl
: undefined
const siteReferrer = Predicate.isNotUndefined(options?.siteReferrer)
? yield* options.siteReferrer
: undefined
const siteTitle = Predicate.isNotUndefined(options?.siteTitle)
? yield* options.siteTitle
: undefined
return yield* make({
apiKey,
apiUrl,
siteReferrer,
siteTitle,
transformClient: options?.transformClient
})
})
)
// =============================================================================
// Internal Utilities
// =============================================================================
const ChatStreamingResponseChunkDataFromString = Schema.fromJsonString(Generated.ChatStreamingResponseChunk.fields.data)
const decodeChatStreamingResponseChunkData = Schema.decodeUnknownEffect(ChatStreamingResponseChunkDataFromString)
const decodeChatCompletionSseData = (
data: string
): Effect.Effect<ChatStreamingResponseChunkData | "[DONE]", Schema.SchemaError> =>
data === "[DONE]"
? Effect.succeed(data)
: decodeChatStreamingResponseChunkData(data)

View File

@@ -0,0 +1,99 @@
/**
* The `OpenRouterConfig` module lets a workflow temporarily customize the HTTP
* client used by generated OpenRouter request methods. `OpenRouterClient` reads
* this scoped transform when generated client operations execute, so callers can
* add middleware or instrumentation without rebuilding the client layer.
*
* @since 4.0.0
*/
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import type { HttpClient } from "effect/unstable/http/HttpClient"
/**
* Context service for scoped OpenRouter provider configuration used by client
* operations.
*
* **When to use**
*
* Use as the context service tag when manually providing or reading scoped
* OpenRouter provider configuration in an Effect context.
*
* @see {@link withClientTransform} for scoping an HTTP client transformation
*
* @category services
* @since 4.0.0
*/
export class OpenRouterConfig extends Context.Service<
OpenRouterConfig,
OpenRouterConfig.Service
>()("@effect/ai-openrouter/OpenRouterConfig") {
/**
* Gets the configured OpenRouter service from the current context when present.
*
* @since 4.0.0
*/
static readonly getOrUndefined: Effect.Effect<typeof OpenRouterConfig.Service | undefined> = Effect.map(
Effect.context<never>(),
(services) => services.mapUnsafe.get(OpenRouterConfig.key)
)
}
/**
* Types associated with the `OpenRouterConfig` context service.
*
* @since 4.0.0
*/
export declare namespace OpenRouterConfig {
/**
* Configuration values read by OpenRouter provider operations when resolving
* the generated HTTP client.
*
* @category models
* @since 4.0.0
*/
export interface Service {
readonly transformClient?: ((client: HttpClient) => HttpClient) | undefined
}
}
/**
* Provides a scoped transform for the OpenRouter HTTP client used by provider
* operations.
*
* **When to use**
*
* Use when you need temporary OpenRouter HTTP client customization for a
* single effect or workflow without rebuilding the client layer.
*
* **Details**
*
* Supports both data-first and data-last forms. The transform is stored in the
* scoped `OpenRouterConfig` service and read by generated OpenRouter request
* operations while running the supplied effect.
*
* **Gotchas**
*
* If a transform is already present in the scoped config, this helper replaces
* it. Compose transforms manually when both should apply. Streaming chat
* completion requests are sent directly by `OpenRouterClient.make` and do not
* read this scoped transform.
*
* @category configuration
* @since 4.0.0
*/
export const withClientTransform: {
(transform: (client: HttpClient) => HttpClient): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
<A, E, R>(self: Effect.Effect<A, E, R>, transform: (client: HttpClient) => HttpClient): Effect.Effect<A, E, R>
} = dual<
(transform: (client: HttpClient) => HttpClient) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>,
<A, E, R>(self: Effect.Effect<A, E, R>, transform: (client: HttpClient) => HttpClient) => Effect.Effect<A, E, R>
>(
2,
(self, transformClient) =>
Effect.flatMap(
OpenRouterConfig.getOrUndefined,
(config) => Effect.provideService(self, OpenRouterConfig, { ...config, transformClient })
)
)

View File

@@ -0,0 +1,225 @@
/**
* OpenRouter error metadata augmentation.
*
* Provides OpenRouter-specific metadata fields for AI error types through
* module augmentation, enabling typed access to OpenRouter error details.
*
* @since 4.0.0
*/
/**
* OpenRouter-specific error metadata fields.
*
* @category models
* @since 4.0.0
*/
export type OpenRouterErrorMetadata = {
/**
* The error code returned by the API.
*/
readonly errorCode: string | number | null
/**
* The error type returned by the API.
*/
readonly errorType: string | null
/**
* The unique request ID for debugging.
*/
readonly requestId: string | null
}
/**
* OpenRouter-specific rate limit metadata fields.
*
* @category models
* @since 4.0.0
*/
export type OpenRouterRateLimitMetadata = OpenRouterErrorMetadata & {
readonly limit: string | null
readonly remaining: number | null
readonly resetRequests: string | null
readonly resetTokens: string | null
}
declare module "effect/unstable/ai/AiError" {
/**
* OpenRouter metadata attached to `RateLimitError` values.
*
* **Details**
*
* Captures OpenRouter error details together with rate limit header
* information from responses where the provider rejected the request because
* a limit was reached.
*
* @category configuration
* @since 4.0.0
*/
export interface RateLimitErrorMetadata {
/**
* OpenRouter-specific details for the rate limit response.
*/
readonly openrouter?: OpenRouterRateLimitMetadata | null
}
/**
* OpenRouter metadata attached to `QuotaExhaustedError` values.
*
* **Details**
*
* Preserves provider error details for failures caused by exhausted account,
* billing, or usage quota.
*
* @category configuration
* @since 4.0.0
*/
export interface QuotaExhaustedErrorMetadata {
/**
* OpenRouter-specific details for the quota exhaustion response.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
/**
* OpenRouter metadata attached to `AuthenticationError` values.
*
* **Details**
*
* Preserves provider error details for failed API key, authorization, or
* permission checks.
*
* @category configuration
* @since 4.0.0
*/
export interface AuthenticationErrorMetadata {
/**
* OpenRouter-specific details for the authentication failure.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
/**
* OpenRouter metadata attached to `ContentPolicyError` values.
*
* **Details**
*
* Preserves provider error details when OpenRouter rejects input or output
* because it violates a content policy.
*
* @category configuration
* @since 4.0.0
*/
export interface ContentPolicyErrorMetadata {
/**
* OpenRouter-specific details for the content policy response.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
/**
* OpenRouter metadata attached to `InvalidRequestError` values.
*
* **Details**
*
* Preserves provider error details for malformed requests, unsupported
* parameters, or other request validation failures reported by OpenRouter.
*
* @category configuration
* @since 4.0.0
*/
export interface InvalidRequestErrorMetadata {
/**
* OpenRouter-specific details for the invalid request response.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
/**
* OpenRouter metadata attached to `InternalProviderError` values.
*
* **Details**
*
* Preserves provider error details for OpenRouter-side failures such as
* transient server errors or overload responses.
*
* @category configuration
* @since 4.0.0
*/
export interface InternalProviderErrorMetadata {
/**
* OpenRouter-specific details for the internal provider response.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
/**
* OpenRouter metadata attached to `InvalidOutputError` values.
*
* **Details**
*
* Preserves provider error details when an OpenRouter response cannot be
* parsed or validated as the expected output.
*
* @category configuration
* @since 4.0.0
*/
export interface InvalidOutputErrorMetadata {
/**
* OpenRouter-specific details for the invalid output response.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
/**
* OpenRouter metadata attached to `StructuredOutputError` values.
*
* **Details**
*
* Preserves provider error details when OpenRouter returns content that does
* not satisfy the requested structured output schema.
*
* @category configuration
* @since 4.0.0
*/
export interface StructuredOutputErrorMetadata {
/**
* OpenRouter-specific details for the structured output failure.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
/**
* OpenRouter metadata attached to `UnsupportedSchemaError` values.
*
* **Details**
*
* Preserves provider error details when an unsupported schema failure is
* associated with an OpenRouter response.
*
* @category configuration
* @since 4.0.0
*/
export interface UnsupportedSchemaErrorMetadata {
/**
* OpenRouter-specific details for the unsupported schema failure.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
/**
* OpenRouter metadata attached to `UnknownError` values.
*
* **Details**
*
* Preserves provider error details for OpenRouter failures that do not map
* cleanly to a more specific AI error category.
*
* @category configuration
* @since 4.0.0
*/
export interface UnknownErrorMetadata {
/**
* OpenRouter-specific details for the unclassified provider failure.
*/
readonly openrouter?: OpenRouterErrorMetadata | null
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
/**
* @since 4.0.0
*/
// @barrel: Auto-generated exports. Do not edit manually.
/**
* @since 4.0.0
*/
export * as Generated from "./Generated.ts"
/**
* @since 4.0.0
*/
export * as OpenRouterClient from "./OpenRouterClient.ts"
/**
* @since 4.0.0
*/
export * as OpenRouterConfig from "./OpenRouterConfig.ts"
/**
* @since 4.0.0
*/
export * as OpenRouterError from "./OpenRouterError.ts"
/**
* @since 4.0.0
*/
export * as OpenRouterLanguageModel from "./OpenRouterLanguageModel.ts"

View File

@@ -0,0 +1,375 @@
import * as Duration from "effect/Duration"
import * as Effect from "effect/Effect"
import { dual } from "effect/Function"
import * as Number from "effect/Number"
import * as Option from "effect/Option"
import * as Predicate from "effect/Predicate"
import * as Redactable from "effect/Redactable"
import * as Schema from "effect/Schema"
import * as AiError from "effect/unstable/ai/AiError"
import type * as Response from "effect/unstable/ai/Response"
import type * as HttpClientError from "effect/unstable/http/HttpClientError"
import type * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
import type * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
import type * as Generated from "../Generated.ts"
import type { OpenRouterErrorMetadata } from "../OpenRouterError.ts"
// =============================================================================
// OpenRouter Error Body Schema
// =============================================================================
/** @internal */
export const OpenRouterErrorBody = Schema.Struct({
error: Schema.Struct({
message: Schema.String,
type: Schema.optional(Schema.NullOr(Schema.String)),
code: Schema.optional(Schema.NullOr(Schema.Union([Schema.String, Schema.Number.check(Schema.isFinite())])))
})
})
/** @internal */
export type OpenRouterClientErrorBody = {
readonly error: {
readonly code: string | number | null
readonly message: string
readonly param?: string | null
readonly type?: string | null
}
}
// =============================================================================
// Error Mappers
// =============================================================================
/** @internal */
export const mapSchemaError = dual<
(method: string) => (error: Schema.SchemaError) => AiError.AiError,
(error: Schema.SchemaError, method: string) => AiError.AiError
>(2, (error, method) =>
AiError.make({
module: "OpenRouterClient",
method,
reason: AiError.InvalidOutputError.fromSchemaError(error)
}))
/** @internal */
export const mapClientError = dual<
(method: string) => (error: Generated.OpenRouterClientError<string, OpenRouterClientErrorBody>) => AiError.AiError,
(error: Generated.OpenRouterClientError<string, OpenRouterClientErrorBody>, method: string) => AiError.AiError
>(2, (error, method) => {
const { request, response, cause } = error
const status = response.status
const headers = response.headers as Record<string, string>
const metadata: OpenRouterErrorMetadata = {
errorCode: cause.error.code ?? null,
errorType: cause.error.type ?? null,
requestId: headers["x-request-id"] ?? null
}
const http = buildHttpContext({ request, response, body: JSON.stringify(cause) })
const reason = mapStatusCodeToReason({
status,
headers,
message: cause.error.message,
metadata,
http
})
return AiError.make({ module: "OpenRouterClient", method, reason })
})
/** @internal */
export const mapHttpClientError = dual<
(method: string) => (error: HttpClientError.HttpClientError) => Effect.Effect<never, AiError.AiError>,
(error: HttpClientError.HttpClientError, method: string) => Effect.Effect<never, AiError.AiError>
>(2, (error, method) => {
const reason = error.reason
switch (reason._tag) {
case "TransportError": {
return Effect.fail(AiError.make({
module: "OpenRouterClient",
method,
reason: new AiError.NetworkError({
reason: "TransportError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "EncodeError": {
return Effect.fail(AiError.make({
module: "OpenRouterClient",
method,
reason: new AiError.NetworkError({
reason: "EncodeError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "InvalidUrlError": {
return Effect.fail(AiError.make({
module: "OpenRouterClient",
method,
reason: new AiError.NetworkError({
reason: "InvalidUrlError",
description: reason.description,
request: buildHttpRequestDetails(reason.request)
})
}))
}
case "StatusCodeError": {
return mapStatusCodeError(reason, method)
}
case "DecodeError": {
return Effect.fail(AiError.make({
module: "OpenRouterClient",
method,
reason: new AiError.InvalidOutputError({
description: reason.description ?? "Failed to decode response"
})
}))
}
case "EmptyBodyError": {
return Effect.fail(AiError.make({
module: "OpenRouterClient",
method,
reason: new AiError.InvalidOutputError({
description: reason.description ?? "Response body was empty"
})
}))
}
}
})
/** @internal */
const mapStatusCodeError = Effect.fnUntraced(function*(
error: HttpClientError.StatusCodeError,
method: string
) {
const { request, response, description } = error
const status = response.status
const headers = response.headers as Record<string, string>
const requestId = headers["x-request-id"]
let body: string | undefined = description
if (!description || !description.startsWith("{")) {
const responseBody = yield* Effect.option(response.text)
if (Option.isSome(responseBody) && responseBody.value) {
body = responseBody.value
}
}
let json: unknown = undefined
// @effect-diagnostics effect/tryCatchInEffectGen:off
try {
json = Predicate.isNotUndefined(body) ? JSON.parse(body) : undefined
} catch {
json = undefined
}
const decoded = Schema.decodeUnknownOption(OpenRouterErrorBody)(json)
const reason = mapStatusCodeToReason({
status,
headers,
message: Option.isSome(decoded) ? decoded.value.error.message : undefined,
http: buildHttpContext({ request, response, body }),
metadata: {
errorCode: Option.isSome(decoded) ? decoded.value.error.code ?? null : null,
errorType: Option.isSome(decoded) ? decoded.value.error.type ?? null : null,
requestId: requestId ?? null
}
})
return yield* AiError.make({ module: "OpenRouterClient", method, reason })
})
// =============================================================================
// Rate Limits
// =============================================================================
/** @internal */
export const parseRateLimitHeaders = (headers: Record<string, string>) => {
const retryAfterRaw = headers["retry-after"]
let retryAfter: Duration.Duration | undefined
if (Predicate.isNotUndefined(retryAfterRaw)) {
const parsed = Number.parse(retryAfterRaw)
if (Option.isSome(parsed)) {
retryAfter = Duration.seconds(parsed.value)
}
}
const remainingRaw = headers["x-ratelimit-remaining-requests"]
const remaining = Predicate.isNotUndefined(remainingRaw)
? Option.getOrNull(Number.parse(remainingRaw))
: null
return {
retryAfter,
limit: headers["x-ratelimit-limit-requests"] ?? null,
remaining,
resetRequests: headers["x-ratelimit-reset-requests"] ?? null,
resetTokens: headers["x-ratelimit-reset-tokens"] ?? null
}
}
// =============================================================================
// HTTP Context
// =============================================================================
/** @internal */
export const buildHttpRequestDetails = (
request: HttpClientRequest.HttpClientRequest
): typeof Response.HttpRequestDetails.Type => ({
method: request.method,
url: request.url,
urlParams: Array.from(request.urlParams),
hash: Option.getOrUndefined(request.hash),
headers: Redactable.redact(request.headers) as Record<string, string>
})
/** @internal */
export const buildHttpContext = (params: {
readonly request: HttpClientRequest.HttpClientRequest
readonly response?: HttpClientResponse.HttpClientResponse
readonly body?: string | undefined
}): typeof AiError.HttpContext.Type => ({
request: buildHttpRequestDetails(params.request),
response: Predicate.isNotUndefined(params.response)
? {
status: params.response.status,
headers: Redactable.redact(params.response.headers) as Record<string, string>
}
: undefined,
body: params.body
})
// =============================================================================
// HTTP Status Code
// =============================================================================
const buildInvalidRequestDescription = (params: {
readonly status: number
readonly message: string | undefined
readonly method: string
readonly url: string
readonly errorCode: string | number | null
readonly errorType: string | null
readonly requestId: string | null
readonly body: string | undefined
}): string => {
const parts: Array<string> = []
if (params.message) {
parts.push(params.message)
} else {
parts.push(`HTTP ${params.status}`)
}
parts.push(`(${params.method} ${params.url})`)
if (params.errorCode) {
parts.push(`[code: ${params.errorCode}]`)
} else if (params.errorType) {
parts.push(`[type: ${params.errorType}]`)
}
if (params.requestId) {
parts.push(`[requestId: ${params.requestId}]`)
}
if (!params.message && params.body) {
const truncated = params.body.length > 200
? params.body.slice(0, 200) + "..."
: params.body
parts.push(`Response: ${truncated}`)
}
return parts.join(" ")
}
/** @internal */
export const mapStatusCodeToReason = ({ status, headers, message, metadata, http }: {
readonly status: number
readonly headers: Record<string, string>
readonly message: string | undefined
readonly metadata: OpenRouterErrorMetadata
readonly http: typeof AiError.HttpContext.Type
}): AiError.AiErrorReason => {
const invalidRequestDescription = buildInvalidRequestDescription({
status,
message,
method: http.request.method,
url: http.request.url,
errorCode: metadata.errorCode,
errorType: metadata.errorType,
requestId: metadata.requestId,
body: http.body
})
switch (status) {
case 400:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { openrouter: metadata },
http
})
case 401:
return new AiError.AuthenticationError({
kind: "InvalidKey",
metadata: { openrouter: metadata },
http
})
case 403:
return new AiError.AuthenticationError({
kind: "InsufficientPermissions",
metadata: { openrouter: metadata },
http
})
case 404:
case 409:
case 422:
return new AiError.InvalidRequestError({
description: invalidRequestDescription,
metadata: { openrouter: metadata },
http
})
case 429: {
if (
metadata.errorCode === "insufficient_quota" ||
metadata.errorType === "insufficient_quota"
) {
return new AiError.QuotaExhaustedError({
metadata: { openrouter: metadata },
http
})
}
const { retryAfter, ...rateLimitMetadata } = parseRateLimitHeaders(headers)
return new AiError.RateLimitError({
retryAfter,
metadata: {
openrouter: {
...metadata,
...rateLimitMetadata
}
},
http
})
}
case 529:
return new AiError.InternalProviderError({
description: message ?? "OpenRouter API is overloaded",
metadata: { openrouter: metadata },
http
})
default:
if (status >= 500) {
return new AiError.InternalProviderError({
description: message ?? "Server error",
metadata: { openrouter: metadata },
http
})
}
return new AiError.UnknownError({
description: message,
metadata: { openrouter: metadata },
http
})
}
}

View File

@@ -0,0 +1,92 @@
import * as Predicate from "effect/Predicate"
import type * as Response from "effect/unstable/ai/Response"
import type { ReasoningDetails } from "../OpenRouterLanguageModel.ts"
const finishReasonMap: Record<string, Response.FinishReason> = {
content_filter: "content-filter",
error: "error",
function_call: "tool-calls",
length: "length",
tool_calls: "tool-calls",
stop: "stop"
}
/** @internal */
export const resolveFinishReason = (
finishReason: string | null | undefined
): Response.FinishReason =>
Predicate.isNotNullish(finishReason)
? finishReasonMap[finishReason]
: "other"
/**
* Tracks ReasoningDetailUnion entries and deduplicates them based
* on a derived canonical key.
*
* This is used when converting messages to ensure the API request only
* contains unique reasoning details, preventing "Duplicate item found with id"
* errors in multi-turn conversations.
*
* The canonical key logic matches the OpenRouter API's deduplication exactly
* (see openrouter-web/packages/llm-interfaces/reasonings/duplicate-tracker.ts):
* - Summary: key = summary field
* - Encrypted: key = id field (if truthy) or data field
* - Text: key = text field (if truthy) or signature field (if truthy)
*
* @internal
*/
export class ReasoningDetailsDuplicateTracker {
readonly #seenKeys = new Set<string>()
/**
* Attempts to track a detail.
*
* or `false` if it was skipped (no valid key) or already seen (duplicate).
*/
upsert(detail: ReasoningDetails[number]): boolean {
const key = this.getCanonicalKey(detail)
if (Predicate.isNull(key)) {
return false
}
if (this.#seenKeys.has(key)) {
return false
}
this.#seenKeys.add(key)
return true
}
private getCanonicalKey(detail: ReasoningDetails[number]): string | null {
// This logic matches the OpenRouter API's deduplication exactly.
// See: openrouter-web/packages/llm-interfaces/reasonings/duplicate-tracker.ts
switch (detail.type) {
case "reasoning.summary": {
return detail.summary
}
case "reasoning.encrypted": {
return Predicate.isNotNullish(detail.id) ? detail.id : detail.data
}
case "reasoning.text": {
if (Predicate.isNotNullish(detail.text)) {
return detail.text
}
if (Predicate.isNotNullish(detail.signature)) {
return detail.signature
}
return null
}
default: {
// Handle unknown types gracefully
return null
}
}
}
}

View File

@@ -0,0 +1,265 @@
import { Generated, OpenRouterClient, OpenRouterLanguageModel } from "@effect/ai-openrouter"
import { assert, describe, it } from "@effect/vitest"
import { deepStrictEqual, strictEqual } from "@effect/vitest/utils"
import { Array, Context, Effect, Layer, Redacted, Ref, Schema } from "effect"
import { LanguageModel, Prompt } from "effect/unstable/ai"
import { HttpClient, type HttpClientError, type HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
describe("OpenRouterLanguageModel", () => {
describe("generateText", () => {
describe("message preparation", () => {
describe("audio file parts", () => {
it.effect("converts audio bytes to input_audio", () =>
Effect.gen(function*() {
const audioData = new Uint8Array([0x49, 0x44, 0x33, 0x04]) // ID3v2 magic bytes
yield* LanguageModel.generateText({
prompt: Prompt.make([{
role: "user",
content: [
Prompt.filePart({
mediaType: "audio/mpeg",
data: audioData
})
]
}])
}).pipe(Effect.provide(OpenRouterLanguageModel.model("google/gemini-2.5-flash")))
const requests = yield* MockHttpClient.requests
const body = yield* getRequestBody(requests[0])
const userMessage = body.messages.find((message: any) => message.role === "user")
deepStrictEqual(userMessage.content, [{
type: "input_audio",
input_audio: {
data: "SUQzBA==",
format: "mp3"
}
}])
}).pipe(Effect.provide(makeTestLayer())))
it.effect("converts base64 data url audio to input_audio", () =>
Effect.gen(function*() {
yield* LanguageModel.generateText({
prompt: Prompt.make([{
role: "user",
content: [
Prompt.filePart({
mediaType: "audio/wav",
data: "data:audio/wav;base64,UklGRg=="
})
]
}])
}).pipe(Effect.provide(OpenRouterLanguageModel.model("google/gemini-2.5-flash")))
const requests = yield* MockHttpClient.requests
const body = yield* getRequestBody(requests[0])
const userMessage = body.messages.find((message: any) => message.role === "user")
deepStrictEqual(userMessage.content, [{
type: "input_audio",
input_audio: {
data: "UklGRg==",
format: "wav"
}
}])
}).pipe(Effect.provide(makeTestLayer())))
it.effect("maps audio media types to OpenRouter audio formats", () =>
Effect.gen(function*() {
const mediaTypes: ReadonlyArray<readonly [mediaType: string, format: string]> = [
["audio/aac", "aac"],
["audio/x-aiff", "aiff"],
["audio/flac", "flac"],
["audio/L16", "pcm16"],
["audio/mp4", "m4a"],
["audio/mp3", "mp3"],
["audio/ogg", "ogg"],
["audio/x-wav", "wav"]
]
yield* LanguageModel.generateText({
prompt: Prompt.make([{
role: "user",
content: mediaTypes.map(([mediaType]) =>
Prompt.filePart({
mediaType,
data: new Uint8Array([0x00])
})
)
}])
}).pipe(Effect.provide(OpenRouterLanguageModel.model("google/gemini-2.5-flash")))
const requests = yield* MockHttpClient.requests
const body = yield* getRequestBody(requests[0])
const userMessage = body.messages.find((message: any) => message.role === "user")
deepStrictEqual(
userMessage.content.map((item: any) => item.input_audio.format),
mediaTypes.map(([, format]) => format)
)
}).pipe(Effect.provide(makeTestLayer())))
it.effect("fails on unsupported audio media types", () =>
Effect.gen(function*() {
const error = yield* LanguageModel.generateText({
prompt: Prompt.make([{
role: "user",
content: [
Prompt.filePart({
mediaType: "audio/webm",
data: new Uint8Array([0x00])
})
]
}])
}).pipe(
Effect.provide(OpenRouterLanguageModel.model("google/gemini-2.5-flash")),
Effect.flip
)
strictEqual(error.reason._tag, "InvalidUserInputError")
assert.include(error.message, "audio/webm")
}).pipe(Effect.provide(makeTestLayer())))
it.effect("fails on audio URLs", () =>
Effect.gen(function*() {
const error = yield* LanguageModel.generateText({
prompt: Prompt.make([{
role: "user",
content: [
Prompt.filePart({
mediaType: "audio/mpeg",
data: new URL("https://example.com/audio.mp3")
})
]
}])
}).pipe(
Effect.provide(OpenRouterLanguageModel.model("google/gemini-2.5-flash")),
Effect.flip
)
strictEqual(error.reason._tag, "InvalidUserInputError")
}).pipe(Effect.provide(makeTestLayer())))
it.effect("converts non-audio files to file blocks", () =>
Effect.gen(function*() {
const pdfData = new Uint8Array([0x25, 0x50, 0x44, 0x46]) // %PDF
yield* LanguageModel.generateText({
prompt: Prompt.make([{
role: "user",
content: [
Prompt.filePart({
mediaType: "application/pdf",
fileName: "document.pdf",
data: pdfData
})
]
}])
}).pipe(Effect.provide(OpenRouterLanguageModel.model("google/gemini-2.5-flash")))
const requests = yield* MockHttpClient.requests
const body = yield* getRequestBody(requests[0])
const userMessage = body.messages.find((message: any) => message.role === "user")
deepStrictEqual(userMessage.content, [{
type: "file",
file: {
filename: "document.pdf",
file_data: "data:application/pdf;base64,JVBERg=="
}
}])
}).pipe(Effect.provide(makeTestLayer())))
})
})
})
})
// =============================================================================
// Test Infrastructure
// =============================================================================
class MockOpenRouterResponse extends Context.Service<MockOpenRouterResponse, {
readonly status: number
readonly body: typeof Generated.SendChatCompletionRequest200.Type
readonly headers?: Record<string, string> | undefined
}>()("MockOpenRouterResponse") {}
class MockHttpClient extends Context.Service<MockHttpClient, {
readonly requests: Effect.Effect<ReadonlyArray<HttpClientRequest.HttpClientRequest>>
}>()("MockHttpClient") {
static requests = Effect.service(MockHttpClient).pipe(
Effect.flatMap((client) => client.requests)
)
}
const encodeResponse = Schema.encodeEffect(Generated.SendChatCompletionRequest200)
const makeHttpClient = Effect.gen(function*() {
const capturedRequests = yield* Ref.make<ReadonlyArray<HttpClientRequest.HttpClientRequest>>([])
const response = yield* MockOpenRouterResponse
const body = yield* Effect.orDie(encodeResponse(response.body))
const httpClient = HttpClient.makeWith(
Effect.fnUntraced(function*(requestEffect) {
const request = yield* requestEffect
yield* Ref.update(capturedRequests, Array.append(request))
return HttpClientResponse.fromWeb(
request,
new Response(JSON.stringify(body), {
headers: response.headers ?? {},
status: response.status
})
)
}),
Effect.succeed as HttpClient.HttpClient.Preprocess<HttpClientError.HttpClientError, never>
)
return Context.make(HttpClient.HttpClient, httpClient).pipe(
Context.add(MockHttpClient, MockHttpClient.of({ requests: Ref.get(capturedRequests) }))
)
})
const HttpClientLayer = Layer.effectContext(makeHttpClient)
const makeDefaultResponse = (
overrides: Partial<typeof Generated.SendChatCompletionRequest200.Type> = {}
): typeof Generated.SendChatCompletionRequest200.Type => ({
id: "gen-test123",
choices: [{
finish_reason: "stop",
index: 0,
message: {
role: "assistant",
content: "Hello!"
}
}],
created: 1234567890,
model: "google/gemini-2.5-flash",
object: "chat.completion",
...overrides
})
const makeTestLayer = (options: {
readonly body?: Partial<typeof Generated.SendChatCompletionRequest200.Type>
readonly status?: number
readonly headers?: Record<string, string>
} = {}) =>
OpenRouterClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe(
Layer.provideMerge(HttpClientLayer),
Layer.provide(Layer.succeed(MockOpenRouterResponse, {
body: makeDefaultResponse(options.body),
status: options.status ?? 200,
headers: options.headers ?? {}
}))
)
const getRequestBody = (request: HttpClientRequest.HttpClientRequest) =>
Effect.gen(function*() {
const body = request.body
if (body._tag === "Uint8Array") {
const text = new TextDecoder().decode(body.body)
return JSON.parse(text)
}
return yield* Effect.die(new Error("Expected Uint8Array body"))
})

View File

@@ -0,0 +1,10 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "../../../tsconfig.base.json",
"include": ["src"],
"references": [
{ "path": "../../effect" },
{ "path": "../anthropic" },
{ "path": "../openai" }
]
}

View File

@@ -0,0 +1,6 @@
import { mergeConfig, type ViteUserConfig } from "vitest/config"
import shared from "../../../vitest.shared.ts"
const config: ViteUserConfig = {}
export default mergeConfig(shared, config)

View File

@@ -0,0 +1,711 @@
# @effect/atom-react
## 4.0.0-beta.99
### Patch Changes
- Updated dependencies [[`8ce4795`](https://github.com/Effect-TS/effect/commit/8ce4795ccbaebca4292757db568c005a992546a4), [`80b539f`](https://github.com/Effect-TS/effect/commit/80b539f8aba68f478c75c35c2b4140c4ffc4fada), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`e6e6dba`](https://github.com/Effect-TS/effect/commit/e6e6dba6e9d86e7c2ad27dcedf289db76a19697f), [`bfb203e`](https://github.com/Effect-TS/effect/commit/bfb203e95aa439f731acad37fc3a9a831a190f1c), [`2e9a34a`](https://github.com/Effect-TS/effect/commit/2e9a34ac2bece4f3a206160480c991e3841dc67a), [`55d4eb3`](https://github.com/Effect-TS/effect/commit/55d4eb34f2c64d54f6a25a305b5c5438ebd7934e), [`bddb010`](https://github.com/Effect-TS/effect/commit/bddb010eac3d4436cb094edbbee7460c5440c162), [`a328835`](https://github.com/Effect-TS/effect/commit/a328835e50d76bc96648a1c1550456e8c9f81210), [`5560d05`](https://github.com/Effect-TS/effect/commit/5560d05aa6abdd29466d9c3412cc5e648b0adbde), [`8f6e3ad`](https://github.com/Effect-TS/effect/commit/8f6e3adb185b16e8820b98c509b308086f7ff1af), [`46997fa`](https://github.com/Effect-TS/effect/commit/46997fa60401f5e3c93daa4b61f7df8e31caaab4), [`9e6e12d`](https://github.com/Effect-TS/effect/commit/9e6e12d75c118cd265496f2880490d1f33a5c8bf), [`3394b93`](https://github.com/Effect-TS/effect/commit/3394b93d97d6f24fc38670641d1490289ffca7f1), [`febeabc`](https://github.com/Effect-TS/effect/commit/febeabc3f7c31094da000a23edeaabfe2ab00a38), [`54161c9`](https://github.com/Effect-TS/effect/commit/54161c98f6f3569e0c31842f54e6a257f9421c4c), [`385f7a4`](https://github.com/Effect-TS/effect/commit/385f7a4ee4a7359928597ea56d151dbaf5eb5802), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`7543afe`](https://github.com/Effect-TS/effect/commit/7543afea6f4d97d1f1ad876224323838a48daadd), [`44b9cf3`](https://github.com/Effect-TS/effect/commit/44b9cf3d240d726997b4bbcd0ede48e074d3c456), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`0a8aa6a`](https://github.com/Effect-TS/effect/commit/0a8aa6acb90a72b91c24d17133c950e4cacd8abd), [`c8d9fcf`](https://github.com/Effect-TS/effect/commit/c8d9fcf7b030f7c474effbab2764ce7aee1c7209), [`9ca7f9a`](https://github.com/Effect-TS/effect/commit/9ca7f9a69363e4485645966d5a93b8f9597c5206), [`e7aca89`](https://github.com/Effect-TS/effect/commit/e7aca894bb32fbb785b5830837e6061c415a6015), [`55d7560`](https://github.com/Effect-TS/effect/commit/55d75609b8acf8a1b54c1b1c7fbbb65ec741aa3e), [`f809189`](https://github.com/Effect-TS/effect/commit/f809189ddf6b6011ba43a9901baaa734e315da2a), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`0ebdbe7`](https://github.com/Effect-TS/effect/commit/0ebdbe74463dc84385956d0b1e8c2b79ebab5400), [`7517d09`](https://github.com/Effect-TS/effect/commit/7517d09f12a0b183a81bd425962c4e280a68b05d), [`212493b`](https://github.com/Effect-TS/effect/commit/212493b9a1eb98cd1ef6959c707a2e5784a5ae91), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`80ea8cb`](https://github.com/Effect-TS/effect/commit/80ea8cb9222ca73f564c8267ab2f82966fea027a), [`8df19f4`](https://github.com/Effect-TS/effect/commit/8df19f4fe81d90cc33ace88b9a77e5534f82d604)]:
- effect@4.0.0-beta.99
## 4.0.0-beta.98
### Patch Changes
- Updated dependencies [[`989603b`](https://github.com/Effect-TS/effect-smol/commit/989603b60ab1197b64acf214208e0d370cd1f842), [`214c458`](https://github.com/Effect-TS/effect-smol/commit/214c458084bb6995d543cd37d1055f24be3d454e), [`a037273`](https://github.com/Effect-TS/effect-smol/commit/a0372736ac34796969b051bbba4717d7983f1ebe), [`97fdaa9`](https://github.com/Effect-TS/effect-smol/commit/97fdaa9c1f522c65e579365d314a07878e2b904f), [`b24d248`](https://github.com/Effect-TS/effect-smol/commit/b24d248c8df44222ce642087cde2bd859a2dc709), [`19c222c`](https://github.com/Effect-TS/effect-smol/commit/19c222cac2353a3d7b7733caecb00556fffe9a5c), [`eec85dd`](https://github.com/Effect-TS/effect-smol/commit/eec85ddba09ea326fd268ee33eeffd47e50d4671), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`8849052`](https://github.com/Effect-TS/effect-smol/commit/884905232d1e9a365e046d8dde27bf9c5707f57f), [`c15e16a`](https://github.com/Effect-TS/effect-smol/commit/c15e16ad130d1fbde25d912b7ac55995066cb35b), [`01d00a3`](https://github.com/Effect-TS/effect-smol/commit/01d00a3abfbf1f37996cdbe738ea5137c646cdd7), [`8bd4589`](https://github.com/Effect-TS/effect-smol/commit/8bd458975a1b3a8ed042eccf317b93d28ded91e7), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`6e08428`](https://github.com/Effect-TS/effect-smol/commit/6e08428d980501b856f846ad3f3f0e4ea46e7786), [`388dcf9`](https://github.com/Effect-TS/effect-smol/commit/388dcf953f65d317547f34d40e6443c5f264205f), [`2b7ce2b`](https://github.com/Effect-TS/effect-smol/commit/2b7ce2b513e7ec2a77822f1116dc6ffb6ba93f4e), [`87bea7e`](https://github.com/Effect-TS/effect-smol/commit/87bea7e16259246f3bcdf565446394751abca953), [`ce38dc3`](https://github.com/Effect-TS/effect-smol/commit/ce38dc33bda805a684432cca071f4dc3c6b9a1ba), [`a807cd1`](https://github.com/Effect-TS/effect-smol/commit/a807cd170341deca8a1cfb52c4222585f2431bb9), [`fd8a356`](https://github.com/Effect-TS/effect-smol/commit/fd8a356f06a8c9ce4e7e0a13fc4021c178ed31de), [`c2a5edc`](https://github.com/Effect-TS/effect-smol/commit/c2a5edc3abd31ad5bc123362bc1213e03e4095c3), [`5946da3`](https://github.com/Effect-TS/effect-smol/commit/5946da3804a1be5e752b05b96bd058cdba50a1bf), [`4ae0c5f`](https://github.com/Effect-TS/effect-smol/commit/4ae0c5ffcbe6c56ddfcb05c639112a079483539e), [`5b2a0bc`](https://github.com/Effect-TS/effect-smol/commit/5b2a0bceea3a28a33a58555210c90a415dc74a76), [`72ac585`](https://github.com/Effect-TS/effect-smol/commit/72ac585884befde6af9208da738699a93f1bae79), [`5e8c1b8`](https://github.com/Effect-TS/effect-smol/commit/5e8c1b82bfafa121311f987a49ab75395e3647a7), [`0f9c078`](https://github.com/Effect-TS/effect-smol/commit/0f9c07841b04183f485ee6e6458de73b290b09f5)]:
- effect@4.0.0-beta.98
## 4.0.0-beta.97
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.97
## 4.0.0-beta.96
### Patch Changes
- Updated dependencies [[`1503f45`](https://github.com/Effect-TS/effect-smol/commit/1503f45cb5bb2a74f4705252ec505a1f0ade7e62), [`57fe793`](https://github.com/Effect-TS/effect-smol/commit/57fe79316ffbc380b30626a168981fb26ae97459), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`97f29df`](https://github.com/Effect-TS/effect-smol/commit/97f29df457f7ffd07cfb4b379315c12c086af805)]:
- effect@4.0.0-beta.96
## 4.0.0-beta.95
### Patch Changes
- Updated dependencies [[`a482442`](https://github.com/Effect-TS/effect-smol/commit/a482442abdeb490e9652b854ec3495e4aa7273e7), [`fbefa85`](https://github.com/Effect-TS/effect-smol/commit/fbefa850fab2f0a302c20614496aeaaa2a8b5590), [`0b4a32f`](https://github.com/Effect-TS/effect-smol/commit/0b4a32f4260f0d8500942a133001b0d349328102), [`18a49e1`](https://github.com/Effect-TS/effect-smol/commit/18a49e1786679456258002ff9397faf02f678c2d), [`266cb90`](https://github.com/Effect-TS/effect-smol/commit/266cb90bb2c17aabc40563c32db334f09ba3d74b), [`912f095`](https://github.com/Effect-TS/effect-smol/commit/912f095a34572bbd3cedf6edb27878443e3e4a95), [`a6718f9`](https://github.com/Effect-TS/effect-smol/commit/a6718f9e00a15ca903b0732da46116cbf3d6aca7), [`bef5154`](https://github.com/Effect-TS/effect-smol/commit/bef51540a243aa2f872a00c01d0cd58b7a769baa), [`18e0564`](https://github.com/Effect-TS/effect-smol/commit/18e0564bd0f8ebbdfcaf1e2c21529948e9e4a81d), [`fb50f14`](https://github.com/Effect-TS/effect-smol/commit/fb50f14fc3657c1973785aa5b72ecf0b0d28e0b2)]:
- effect@4.0.0-beta.95
## 4.0.0-beta.94
### Patch Changes
- Updated dependencies [[`95a0e9b`](https://github.com/Effect-TS/effect-smol/commit/95a0e9bb62797af0e81c9998773405f248f218c5), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63), [`f11ce73`](https://github.com/Effect-TS/effect-smol/commit/f11ce73af60823754dc24194f4ffc561b9ea1c2d), [`ff30b6e`](https://github.com/Effect-TS/effect-smol/commit/ff30b6e7c2c63ffc56a4c5818d6d86b01b5ad528), [`1caab3c`](https://github.com/Effect-TS/effect-smol/commit/1caab3cc30f626efbf15e59d74f539a487e5c85c), [`aa80c47`](https://github.com/Effect-TS/effect-smol/commit/aa80c4775a04db87553e5568764cab7e32a72814), [`c2ae4fc`](https://github.com/Effect-TS/effect-smol/commit/c2ae4fce2f03a4cd1861c2b1179da7df656e662d), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63)]:
- effect@4.0.0-beta.94
## 4.0.0-beta.93
### Patch Changes
- Updated dependencies [[`00652fe`](https://github.com/Effect-TS/effect-smol/commit/00652fe95c18f87208e91343eb8bf218faa2f677), [`6c58167`](https://github.com/Effect-TS/effect-smol/commit/6c5816746eaf91d2a3c7c899c5720809fa230ae3), [`2bc5415`](https://github.com/Effect-TS/effect-smol/commit/2bc541501a7ef89e542d7cb98e96beb53cd205cc), [`e11cccc`](https://github.com/Effect-TS/effect-smol/commit/e11cccc7d5fe631abccc7d6e3bd296938de0fa2e), [`ba7e77e`](https://github.com/Effect-TS/effect-smol/commit/ba7e77e046b8641a3a4e9750bb88ca4a1d063d3f), [`5713ee7`](https://github.com/Effect-TS/effect-smol/commit/5713ee7edbc3054efde407b2286bbfd45bbc6e1c)]:
- effect@4.0.0-beta.93
## 4.0.0-beta.92
### Patch Changes
- Updated dependencies [[`affdc13`](https://github.com/Effect-TS/effect-smol/commit/affdc139045cc325dce321a84a580fdc1b2da7b9)]:
- effect@4.0.0-beta.92
## 4.0.0-beta.91
### Patch Changes
- Updated dependencies [[`b135b25`](https://github.com/Effect-TS/effect-smol/commit/b135b2517fca9e7839734ace3699a7dfa75b9075), [`aaa21a3`](https://github.com/Effect-TS/effect-smol/commit/aaa21a369a171c600db294f2a4f640583043e150), [`3475ee6`](https://github.com/Effect-TS/effect-smol/commit/3475ee6c2bda6b05c6d7a12ce30c8bb840b5b1a6)]:
- effect@4.0.0-beta.91
## 4.0.0-beta.90
### Patch Changes
- Updated dependencies [[`d237fdf`](https://github.com/Effect-TS/effect-smol/commit/d237fdf726481f76eb52a6196e111b24122bc3d5)]:
- effect@4.0.0-beta.90
## 4.0.0-beta.89
### Patch Changes
- Updated dependencies [[`b7d46ab`](https://github.com/Effect-TS/effect-smol/commit/b7d46ab7e1a29d8711817bab583c9febf48a0dad), [`7777e15`](https://github.com/Effect-TS/effect-smol/commit/7777e1540fd3680dd8346723cffec812b9384669), [`5376197`](https://github.com/Effect-TS/effect-smol/commit/5376197ca8e50358a41b1fd3cec27bd1ec680ec6)]:
- effect@4.0.0-beta.89
## 4.0.0-beta.88
### Patch Changes
- Updated dependencies [[`911f1b8`](https://github.com/Effect-TS/effect-smol/commit/911f1b84790ce42b3a70c95b33e6f6fd9e74de8b), [`8beeeea`](https://github.com/Effect-TS/effect-smol/commit/8beeeea52879d8613a39468848f01c3092bd54d4), [`c306fcf`](https://github.com/Effect-TS/effect-smol/commit/c306fcfeb1ef38455156932a1faf49292b1318da)]:
- effect@4.0.0-beta.88
## 4.0.0-beta.87
### Patch Changes
- Updated dependencies [[`5a0c1a4`](https://github.com/Effect-TS/effect-smol/commit/5a0c1a4faee5707b5cc35e646ff1ffdad70f1956), [`1eea2ea`](https://github.com/Effect-TS/effect-smol/commit/1eea2ea3795ba47316b82b1ac8d4612c0ba389ed)]:
- effect@4.0.0-beta.87
## 4.0.0-beta.86
### Patch Changes
- Updated dependencies [[`0b5795a`](https://github.com/Effect-TS/effect-smol/commit/0b5795a0ab4395e8f15955d8d96f2303084bfc64), [`3e3a859`](https://github.com/Effect-TS/effect-smol/commit/3e3a859ec6351a9e0d31674aabbd48fcefabb12e), [`7dbec24`](https://github.com/Effect-TS/effect-smol/commit/7dbec240dbf3bca599a20c486632abce694ef5ab), [`d8c00a1`](https://github.com/Effect-TS/effect-smol/commit/d8c00a171ac7141e8adc08c332d1162d9a9d56fc), [`85b6317`](https://github.com/Effect-TS/effect-smol/commit/85b631701e935866f2762bd595237aa718370cd9), [`6d0fda0`](https://github.com/Effect-TS/effect-smol/commit/6d0fda0d0cbdfffc523c89c57dfdb1608f84fb12), [`108a933`](https://github.com/Effect-TS/effect-smol/commit/108a9335ff8571928197e5847a09c28ac83d6f46), [`7e1f455`](https://github.com/Effect-TS/effect-smol/commit/7e1f455fab5005d769b939c91e519d450f802cf9), [`46b3e79`](https://github.com/Effect-TS/effect-smol/commit/46b3e79944cfdae7901eb148135c85b7eb39834e)]:
- effect@4.0.0-beta.86
## 4.0.0-beta.85
### Patch Changes
- Updated dependencies [[`328d97c`](https://github.com/Effect-TS/effect-smol/commit/328d97cc53c0dcb89077a5623e35b095eaa59a8c), [`8441836`](https://github.com/Effect-TS/effect-smol/commit/8441836e6dde70e8ae2126be9cefe9b45798b134), [`074e436`](https://github.com/Effect-TS/effect-smol/commit/074e4361091289104cb0ab6959dc3b0ea7794a6a), [`c1dfd60`](https://github.com/Effect-TS/effect-smol/commit/c1dfd60663eb13a58916f3712d877499943b628a), [`2ba316b`](https://github.com/Effect-TS/effect-smol/commit/2ba316bd15fcbf1c50626500d44a2c9b3bec19f5), [`7ce7344`](https://github.com/Effect-TS/effect-smol/commit/7ce7344c41056c79e2ee19ee6a9346c0f1d227c1)]:
- effect@4.0.0-beta.85
## 4.0.0-beta.84
### Patch Changes
- Updated dependencies [[`87f52ba`](https://github.com/Effect-TS/effect-smol/commit/87f52ba16c4370ffa3f84bf8e53038e1419c284e), [`b8ee07f`](https://github.com/Effect-TS/effect-smol/commit/b8ee07ffda8903b5ec2e45a786ddcba59f128fda), [`867c0d7`](https://github.com/Effect-TS/effect-smol/commit/867c0d70a09079b040260d45a1e92ff04dbfbf2f), [`b93bc6c`](https://github.com/Effect-TS/effect-smol/commit/b93bc6c9cb27b909a41d094c97c4f9d25bbc6d6b), [`57d387f`](https://github.com/Effect-TS/effect-smol/commit/57d387f92c30ab63e15e3e641f0a903b65886610), [`bacca41`](https://github.com/Effect-TS/effect-smol/commit/bacca4141c2400effae1eabfdb36c89a459cf246), [`0f8ac79`](https://github.com/Effect-TS/effect-smol/commit/0f8ac7959d29ed68c68ce25aabd6bf0cb7e63ecc), [`25b4482`](https://github.com/Effect-TS/effect-smol/commit/25b448270c01317703f25107e1480d4cd0246d9a), [`9cf3a25`](https://github.com/Effect-TS/effect-smol/commit/9cf3a25c66b0c44a52be9829870c44517ea52db2), [`8def767`](https://github.com/Effect-TS/effect-smol/commit/8def7674b1787f91035298cda4d122937e87ef72)]:
- effect@4.0.0-beta.84
## 4.0.0-beta.83
### Patch Changes
- Updated dependencies [[`1f2e8ce`](https://github.com/Effect-TS/effect-smol/commit/1f2e8ceef09e0a791c850ed2ade01f97089596f9)]:
- effect@4.0.0-beta.83
## 4.0.0-beta.82
### Patch Changes
- Updated dependencies [[`193690b`](https://github.com/Effect-TS/effect-smol/commit/193690b642ea802bbed40d663bd677251bbe9dc3)]:
- effect@4.0.0-beta.82
## 4.0.0-beta.81
### Patch Changes
- Updated dependencies [[`93cb4f8`](https://github.com/Effect-TS/effect-smol/commit/93cb4f8fbfb9e07cb9dc86ce6b155fd1f8167914), [`60341d9`](https://github.com/Effect-TS/effect-smol/commit/60341d9ca744d0473ce3fab621ca9bd225af3a39), [`1105ab5`](https://github.com/Effect-TS/effect-smol/commit/1105ab56cb724212f7ea7b431396ce82e8fd0484), [`4500fbf`](https://github.com/Effect-TS/effect-smol/commit/4500fbfe00763d8a72af6e5d6c5988e8bd4ade36)]:
- effect@4.0.0-beta.81
## 4.0.0-beta.80
### Patch Changes
- Updated dependencies [[`d944330`](https://github.com/Effect-TS/effect-smol/commit/d94433090ee03f426d43e13b883abae4494e55e6), [`f48659f`](https://github.com/Effect-TS/effect-smol/commit/f48659fdcc84930ebc1e5b45b540c0f973389182), [`7652aaa`](https://github.com/Effect-TS/effect-smol/commit/7652aaa3bdbc39f241fe58b54b9a43b713e22e12), [`98630b7`](https://github.com/Effect-TS/effect-smol/commit/98630b7c8f679c352ba6796636c85688fa009d8d), [`90ae23c`](https://github.com/Effect-TS/effect-smol/commit/90ae23cf07284da5e1bcd9dffa882e85df7e617b)]:
- effect@4.0.0-beta.80
## 4.0.0-beta.79
### Patch Changes
- Updated dependencies [[`b9704dc`](https://github.com/Effect-TS/effect-smol/commit/b9704dc9de9f1649ad502371014fe869b69a49a3), [`a207113`](https://github.com/Effect-TS/effect-smol/commit/a207113f66837bb54416926718a9a7d66774d079), [`5e9b9e2`](https://github.com/Effect-TS/effect-smol/commit/5e9b9e217b164ebfd4a002dd4380b3b1563200c3), [`7c128ae`](https://github.com/Effect-TS/effect-smol/commit/7c128aef458a1e2d224712e51c483c9badad1d44), [`0ada457`](https://github.com/Effect-TS/effect-smol/commit/0ada457c0513d8d908254ab77ebb7d29d2b523d6), [`d7cc5a2`](https://github.com/Effect-TS/effect-smol/commit/d7cc5a2bede3de10943aa0c6bdb4f26836a91efd), [`aad63be`](https://github.com/Effect-TS/effect-smol/commit/aad63becf65e0a6b076e94f8973be7bbe7fbd46f), [`09809f6`](https://github.com/Effect-TS/effect-smol/commit/09809f60f19ec98232f98b33e33e02ecb7e4fbd6), [`2fddda5`](https://github.com/Effect-TS/effect-smol/commit/2fddda5311929f46b61e503f0ade4fc749e8c77d), [`5f21768`](https://github.com/Effect-TS/effect-smol/commit/5f2176833399757c4500d8875b7f2fba0393de75), [`f27003e`](https://github.com/Effect-TS/effect-smol/commit/f27003e00524ff83f20dd9909f62b2f8795efe03)]:
- effect@4.0.0-beta.79
## 4.0.0-beta.78
### Patch Changes
- Updated dependencies [[`7836b8e`](https://github.com/Effect-TS/effect-smol/commit/7836b8eb8bb0f3e04cdf554ee070caccf74f00c1), [`35d49a3`](https://github.com/Effect-TS/effect-smol/commit/35d49a3a09bdba6b513de87ddcead9e61a1042ba), [`4093258`](https://github.com/Effect-TS/effect-smol/commit/40932580e65bafab5f23c5f14b520cb411d0b2cd)]:
- effect@4.0.0-beta.78
## 4.0.0-beta.77
### Patch Changes
- Updated dependencies [[`6e9a5ca`](https://github.com/Effect-TS/effect-smol/commit/6e9a5ca62a61156fd67b2518ad3ab14ac0d25f23), [`302f398`](https://github.com/Effect-TS/effect-smol/commit/302f3984ce206e35d86ddd99d3b72be144850a51)]:
- effect@4.0.0-beta.77
## 4.0.0-beta.76
### Patch Changes
- Updated dependencies [[`016108a`](https://github.com/Effect-TS/effect-smol/commit/016108a472af7048ddbbfd05f233e67529fafe12), [`95c03d2`](https://github.com/Effect-TS/effect-smol/commit/95c03d2c55930668c215b5a41c23cf7742fead84), [`07299a3`](https://github.com/Effect-TS/effect-smol/commit/07299a33c09fd52faa9810d30835a2622c752386)]:
- effect@4.0.0-beta.76
## 4.0.0-beta.75
### Patch Changes
- Updated dependencies [[`81b187c`](https://github.com/Effect-TS/effect-smol/commit/81b187c17a0d8817b58232826939154010ae49d7), [`ad4b535`](https://github.com/Effect-TS/effect-smol/commit/ad4b535e17f94ce35261829d5a3675f0a7808b4e), [`a29c2e7`](https://github.com/Effect-TS/effect-smol/commit/a29c2e7e3570920156702671d6f3367cd0195f6c), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`ffea4ec`](https://github.com/Effect-TS/effect-smol/commit/ffea4ecf2925f6a4c9fd13079d47584cbf2bed00), [`4255c9b`](https://github.com/Effect-TS/effect-smol/commit/4255c9ba78bb98c7838fbe9dccdd8465e9da5427)]:
- effect@4.0.0-beta.75
## 4.0.0-beta.74
### Patch Changes
- Updated dependencies [[`b1fc6a4`](https://github.com/Effect-TS/effect-smol/commit/b1fc6a4b4d0ca7fa9fd162799ae17c86f2f7ee8e)]:
- effect@4.0.0-beta.74
## 4.0.0-beta.73
### Patch Changes
- Updated dependencies [[`361ca30`](https://github.com/Effect-TS/effect-smol/commit/361ca30eb6e134feece547d6e00f82be4cb23f75), [`b9598c6`](https://github.com/Effect-TS/effect-smol/commit/b9598c6a209e75bfdb87ee3b024ecd1e3923ff6e)]:
- effect@4.0.0-beta.73
## 4.0.0-beta.72
### Patch Changes
- Updated dependencies [[`73e67d1`](https://github.com/Effect-TS/effect-smol/commit/73e67d119a84d697773eaecb4865c6a71eb1a9cb), [`01d71ec`](https://github.com/Effect-TS/effect-smol/commit/01d71ec5a75f3c2747a8d3b1ad9701d1e27b7ce5), [`fcd707e`](https://github.com/Effect-TS/effect-smol/commit/fcd707e091a16e1b35343c901cc4052274e32239)]:
- effect@4.0.0-beta.72
## 4.0.0-beta.71
### Patch Changes
- Updated dependencies [[`d8ac76b`](https://github.com/Effect-TS/effect-smol/commit/d8ac76b5bad458c42cebe8a0c1b3843f955ac293), [`2c3c00a`](https://github.com/Effect-TS/effect-smol/commit/2c3c00af6faba7b7d422af26a7a2bbc35636d230), [`3751e7c`](https://github.com/Effect-TS/effect-smol/commit/3751e7cf353e7a54cd692c37401207d9afba1e63), [`fc5f25b`](https://github.com/Effect-TS/effect-smol/commit/fc5f25b03ada5fc2431987768a74d3d3e75ca485), [`7ccced4`](https://github.com/Effect-TS/effect-smol/commit/7ccced42867c14c013b01160b3d292f14c05bd04), [`a2e1fe5`](https://github.com/Effect-TS/effect-smol/commit/a2e1fe5835c98c8ee4393a091b1d11b75126e349), [`4a4a36b`](https://github.com/Effect-TS/effect-smol/commit/4a4a36b10e6e616cad07584a43908f6a7e07e618), [`d350292`](https://github.com/Effect-TS/effect-smol/commit/d3502922b4740fa9d745797cbc3775cb67839b6d), [`730afb6`](https://github.com/Effect-TS/effect-smol/commit/730afb66696adf9bd5a328cbca29df9c05968771), [`df1b008`](https://github.com/Effect-TS/effect-smol/commit/df1b008f370f414c2a67a7b8139ef747af8e5fba), [`6d469d5`](https://github.com/Effect-TS/effect-smol/commit/6d469d567a7c41d7e5343bdee21d45b07b0e8190)]:
- effect@4.0.0-beta.71
## 4.0.0-beta.70
### Patch Changes
- Updated dependencies [[`af7782d`](https://github.com/Effect-TS/effect-smol/commit/af7782d3008d08b043f3a3f261516001514b2b4e), [`7212d70`](https://github.com/Effect-TS/effect-smol/commit/7212d701a3eee7b3553ff502e2c066126e52e839)]:
- effect@4.0.0-beta.70
## 4.0.0-beta.69
### Patch Changes
- Updated dependencies [[`70ea04a`](https://github.com/Effect-TS/effect-smol/commit/70ea04aa96a2a7859d738d414e1f0e3ed081a27a), [`d0ea8b0`](https://github.com/Effect-TS/effect-smol/commit/d0ea8b03f7d73ae076c1db12666141e480d11178), [`a57674b`](https://github.com/Effect-TS/effect-smol/commit/a57674b64845e9e75a456cf907bfdcb858859118), [`59aa334`](https://github.com/Effect-TS/effect-smol/commit/59aa334fbd0a504dda3c36f6d2ef1be7449b4b8b), [`8f4208e`](https://github.com/Effect-TS/effect-smol/commit/8f4208ee83bc7bdaa6793b5429847b45aab72470)]:
- effect@4.0.0-beta.69
## 4.0.0-beta.68
### Patch Changes
- Updated dependencies [[`af8267f`](https://github.com/Effect-TS/effect-smol/commit/af8267f2f3588c3fb611e9286f6f933f29ce1217), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`f136bb7`](https://github.com/Effect-TS/effect-smol/commit/f136bb763048cbc6b17edd26496dba3e2415b9fa), [`6f38f07`](https://github.com/Effect-TS/effect-smol/commit/6f38f07d5941a211b251383aaab0f4f55e8a6557), [`aec9c40`](https://github.com/Effect-TS/effect-smol/commit/aec9c401a53db227f18bf5e0c84db7130ad862d6)]:
- effect@4.0.0-beta.68
## 4.0.0-beta.67
### Patch Changes
- Updated dependencies [[`a42ef66`](https://github.com/Effect-TS/effect-smol/commit/a42ef6632abbddfa820995ae310ccc84ae8d9b6f), [`35594f8`](https://github.com/Effect-TS/effect-smol/commit/35594f811cafe471acd490114b103a1f8392c8d8), [`8bddd62`](https://github.com/Effect-TS/effect-smol/commit/8bddd628cb623f9533d345082583ff51cead6836), [`4be4c8d`](https://github.com/Effect-TS/effect-smol/commit/4be4c8d60862aa963869ee2ed9ffa048ffac0527), [`0c9d3ab`](https://github.com/Effect-TS/effect-smol/commit/0c9d3ab43eb721a370ed8306260cbac218c27e87), [`b156acc`](https://github.com/Effect-TS/effect-smol/commit/b156accd2691b4a051f823affdece7c39923ce85), [`d16c034`](https://github.com/Effect-TS/effect-smol/commit/d16c03434ee3e6dcd3bfc82b65d99e881d89025b), [`b559d68`](https://github.com/Effect-TS/effect-smol/commit/b559d68845f848a10153395778f035682d399075), [`a3de5d9`](https://github.com/Effect-TS/effect-smol/commit/a3de5d9215e5cc4a62e2666efbd7c1bf595eb84f), [`7e6c12e`](https://github.com/Effect-TS/effect-smol/commit/7e6c12ec9b3a5945f6c26e272cc8f6390541ad3e), [`098167a`](https://github.com/Effect-TS/effect-smol/commit/098167a220fe07da6f14455818733ab1b269c9dd)]:
- effect@4.0.0-beta.67
## 4.0.0-beta.66
### Patch Changes
- Updated dependencies [[`ca2498e`](https://github.com/Effect-TS/effect-smol/commit/ca2498e702ac2d83fb7187707b7eb069bdb261a2), [`cd7d1fb`](https://github.com/Effect-TS/effect-smol/commit/cd7d1fba7e2e2c5ac3ad64e1be433440a5bda436), [`19a7033`](https://github.com/Effect-TS/effect-smol/commit/19a703367ec817cffc41d152da9b594827408e2b), [`33d26b4`](https://github.com/Effect-TS/effect-smol/commit/33d26b4210b2e974f146a71e7eed962f8ce00900), [`856766b`](https://github.com/Effect-TS/effect-smol/commit/856766b2c506aaed6d2df1d63bf3a5b1b062e1d4), [`079c7df`](https://github.com/Effect-TS/effect-smol/commit/079c7df82559bb9ce10a86dffb85d25e6ce07dc3)]:
- effect@4.0.0-beta.66
## 4.0.0-beta.65
### Patch Changes
- Updated dependencies [[`6f11454`](https://github.com/Effect-TS/effect-smol/commit/6f11454a9b6c3bd00f6b35fd7af14a2f2d63a0a2)]:
- effect@4.0.0-beta.65
## 4.0.0-beta.64
### Patch Changes
- Updated dependencies [[`7d4877a`](https://github.com/Effect-TS/effect-smol/commit/7d4877a1929cdb690280ea254326c04f2ec97ea5)]:
- effect@4.0.0-beta.64
## 4.0.0-beta.63
### Patch Changes
- Updated dependencies [[`7f927ff`](https://github.com/Effect-TS/effect-smol/commit/7f927ffb7a9801dcfc4096c29e369d13d65cd0ac), [`a696b3e`](https://github.com/Effect-TS/effect-smol/commit/a696b3e83a8504cdbe261a18c10a1cc0619ae102)]:
- effect@4.0.0-beta.63
## 4.0.0-beta.62
### Patch Changes
- Updated dependencies [[`4ab4b90`](https://github.com/Effect-TS/effect-smol/commit/4ab4b9007dc27a52ffabc6fcb37c96eeec795bf7)]:
- effect@4.0.0-beta.62
## 4.0.0-beta.61
### Patch Changes
- Updated dependencies [[`50790af`](https://github.com/Effect-TS/effect-smol/commit/50790af9b190c38d10fb0723837d49b66432638f), [`71f7c3d`](https://github.com/Effect-TS/effect-smol/commit/71f7c3df997deda92c84146d569696dab3bd645c), [`aae8797`](https://github.com/Effect-TS/effect-smol/commit/aae8797b9cb383be0c182dd58d03d787c354238b)]:
- effect@4.0.0-beta.61
## 4.0.0-beta.60
### Patch Changes
- Updated dependencies [[`f69d567`](https://github.com/Effect-TS/effect-smol/commit/f69d5675dcff9f4137295752baf066b7153fdc09), [`7909c95`](https://github.com/Effect-TS/effect-smol/commit/7909c954b8f6244a35a4b429f8dd0dff45dad620), [`bbb4dcc`](https://github.com/Effect-TS/effect-smol/commit/bbb4dcc6c406b83a416b4ad3541cc02037c420e4), [`7af2207`](https://github.com/Effect-TS/effect-smol/commit/7af2207901eabf3132c1b7010a69b3899c06fbbe), [`848b40a`](https://github.com/Effect-TS/effect-smol/commit/848b40a4bd4bf54a5098617d50c33c88eee8270a)]:
- effect@4.0.0-beta.60
## 4.0.0-beta.59
### Patch Changes
- Updated dependencies [[`56837ea`](https://github.com/Effect-TS/effect-smol/commit/56837ea2a338395b35550641374e9e589bd8b71d)]:
- effect@4.0.0-beta.59
## 4.0.0-beta.58
### Patch Changes
- Updated dependencies [[`11993d4`](https://github.com/Effect-TS/effect-smol/commit/11993d4934c66f5dc611b8bbf553f01d501ef8f7), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec)]:
- effect@4.0.0-beta.58
## 4.0.0-beta.57
### Patch Changes
- Updated dependencies [[`a971f5c`](https://github.com/Effect-TS/effect-smol/commit/a971f5cbd92dfe4274420bf0966595eb35531060), [`8e110c5`](https://github.com/Effect-TS/effect-smol/commit/8e110c5f02a429ccc43a91df8678e402138c0851)]:
- effect@4.0.0-beta.57
## 4.0.0-beta.56
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.56
## 4.0.0-beta.55
### Patch Changes
- Updated dependencies [[`42cc744`](https://github.com/Effect-TS/effect-smol/commit/42cc744570968deb365fb46d47b53d3277050c93), [`04855ce`](https://github.com/Effect-TS/effect-smol/commit/04855ceeca4d40c55a5750dd9893b691f8ea741a)]:
- effect@4.0.0-beta.55
## 4.0.0-beta.54
### Patch Changes
- Updated dependencies [[`e4b74f9`](https://github.com/Effect-TS/effect-smol/commit/e4b74f9c01a0e9b6cd58416de4af3a26d51da7c8), [`4c72808`](https://github.com/Effect-TS/effect-smol/commit/4c728081851c66dacf889a816535671bc841ae96)]:
- effect@4.0.0-beta.54
## 4.0.0-beta.53
### Patch Changes
- Updated dependencies [[`0768509`](https://github.com/Effect-TS/effect-smol/commit/07685094e931af07d104165195826a535b55fa7e), [`476aede`](https://github.com/Effect-TS/effect-smol/commit/476aede69c6efa06b5781ca5eb3e3b128ca29141), [`4f79c54`](https://github.com/Effect-TS/effect-smol/commit/4f79c542e7b508c235ff485d862cc8b29a8260c5), [`4be6a7c`](https://github.com/Effect-TS/effect-smol/commit/4be6a7cf35dab2a01d652f56dd35f0358c5a7e88), [`88927eb`](https://github.com/Effect-TS/effect-smol/commit/88927ebb896162cdba103b36553280b58e0facac)]:
- effect@4.0.0-beta.53
## 4.0.0-beta.52
### Patch Changes
- Updated dependencies [[`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`cf3a311`](https://github.com/Effect-TS/effect-smol/commit/cf3a311d863a8abb818840c3b80f847e621c43c1), [`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`131fdd5`](https://github.com/Effect-TS/effect-smol/commit/131fdd5b1f26531e265fe1a08f002002f47c276e)]:
- effect@4.0.0-beta.52
## 4.0.0-beta.51
### Patch Changes
- Updated dependencies [[`778d2af`](https://github.com/Effect-TS/effect-smol/commit/778d2afe9b5154bc1f9abae46d93ea7e54c87344), [`4e24dcf`](https://github.com/Effect-TS/effect-smol/commit/4e24dcf75037f65eebc1eb68623bc7cbf9d5512a), [`4b1c015`](https://github.com/Effect-TS/effect-smol/commit/4b1c0150e9bdb5559ed32d250deb66e17b4240c7), [`454f8ad`](https://github.com/Effect-TS/effect-smol/commit/454f8adad822929c3ef60f8280d0987226b049fd), [`6754a0c`](https://github.com/Effect-TS/effect-smol/commit/6754a0cd18626b06805a079cc5265525a5eb7d27), [`90f7fd5`](https://github.com/Effect-TS/effect-smol/commit/90f7fd5243871b30980964135db4512b8119fa82), [`d7e1519`](https://github.com/Effect-TS/effect-smol/commit/d7e151974934201fd93fa4c8a1192ee9a5d965a0), [`72a8122`](https://github.com/Effect-TS/effect-smol/commit/72a81228e09782bae512f7d041bbfbc78bc668d0)]:
- effect@4.0.0-beta.51
## 4.0.0-beta.50
### Patch Changes
- Updated dependencies [[`07be594`](https://github.com/Effect-TS/effect-smol/commit/07be594825de60f8e1b2102d21dbb9b8fc63b414), [`ae02433`](https://github.com/Effect-TS/effect-smol/commit/ae02433103ce28f53a0c9bfb4a44e75773289b7b)]:
- effect@4.0.0-beta.50
## 4.0.0-beta.49
### Patch Changes
- Updated dependencies [[`7d87873`](https://github.com/Effect-TS/effect-smol/commit/7d8787340ff549370f6f2a88b612e9ebbfd6ba45), [`c2f6f90`](https://github.com/Effect-TS/effect-smol/commit/c2f6f901b200a6e515b4f02c93ce8005b7bbf1c5), [`216f13c`](https://github.com/Effect-TS/effect-smol/commit/216f13c1fce454a21b489bb915714a17e791a1ac)]:
- effect@4.0.0-beta.49
## 4.0.0-beta.48
### Patch Changes
- Updated dependencies [[`4da56ec`](https://github.com/Effect-TS/effect-smol/commit/4da56ecff129b2da40137ffede23a73cc4e532d8), [`a5e6f77`](https://github.com/Effect-TS/effect-smol/commit/a5e6f774bab195cf50ecdc818240765f69a3bf4a), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070)]:
- effect@4.0.0-beta.48
## 4.0.0-beta.47
### Patch Changes
- Updated dependencies [[`c584726`](https://github.com/Effect-TS/effect-smol/commit/c58472674e750e6938df955044eab88feda95e45), [`86a91a4`](https://github.com/Effect-TS/effect-smol/commit/86a91a4f0c59286dfa9393232d8020dea70ed4db), [`131caf9`](https://github.com/Effect-TS/effect-smol/commit/131caf9525151a0cb29803a8f1dffa0f4f479d12), [`c3615c8`](https://github.com/Effect-TS/effect-smol/commit/c3615c88379b9daf252df0db72c6ac5a20326406)]:
- effect@4.0.0-beta.47
## 4.0.0-beta.46
### Patch Changes
- Updated dependencies [[`3a30b9e`](https://github.com/Effect-TS/effect-smol/commit/3a30b9e2ec2bd8b8193e1aa139f6878a07e3f5ee)]:
- effect@4.0.0-beta.46
## 4.0.0-beta.45
### Patch Changes
- Updated dependencies [[`5c3af6d`](https://github.com/Effect-TS/effect-smol/commit/5c3af6d554f60be34f8fc21d598d9a298ae11beb)]:
- effect@4.0.0-beta.45
## 4.0.0-beta.44
### Patch Changes
- [#1961](https://github.com/Effect-TS/effect-smol/pull/1961) [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970) Thanks @IMax153! - Rename the `ServiceMap` module to `Context` across exports, docs, and tests.
- Updated dependencies [[`e3f0621`](https://github.com/Effect-TS/effect-smol/commit/e3f0621454c3f5d11070d30619da27c9232cadc1), [`5b476ab`](https://github.com/Effect-TS/effect-smol/commit/5b476abc0bd7e9bb59135ea1bcad2e4936227ced), [`6b40e5a`](https://github.com/Effect-TS/effect-smol/commit/6b40e5a4a6bd2087c15a3d7374d25057fdedfa16), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`3b09fb3`](https://github.com/Effect-TS/effect-smol/commit/3b09fb31c40c2802b01f21c23bcdd1fe7fb0aa82), [`2370410`](https://github.com/Effect-TS/effect-smol/commit/237041062e5af4594d32db91597e34e70a632877), [`dabc272`](https://github.com/Effect-TS/effect-smol/commit/dabc272444a700eb629c07ba3e77671a841ca86e), [`08b63c3`](https://github.com/Effect-TS/effect-smol/commit/08b63c3df11bd35c9fd6090dbd166287fdc40664), [`dfff04c`](https://github.com/Effect-TS/effect-smol/commit/dfff04c4c2b1d352dfad83992a6dce1280c85cf9), [`9baed9e`](https://github.com/Effect-TS/effect-smol/commit/9baed9e17e84702e6e480fcef6f86404f9e24be9), [`7846792`](https://github.com/Effect-TS/effect-smol/commit/7846792adc7e1631d62d26d657bd7ba6139f369b), [`1556a24`](https://github.com/Effect-TS/effect-smol/commit/1556a247623636b7ebe438fb56d77f1a7bf957bb), [`7c11bc2`](https://github.com/Effect-TS/effect-smol/commit/7c11bc292ab8e46252fe8f7576fb685917bfb8b5), [`b5ea591`](https://github.com/Effect-TS/effect-smol/commit/b5ea5913ec1d45d0dd12a327b9dd966bda2f6d02), [`0853afa`](https://github.com/Effect-TS/effect-smol/commit/0853afaeb1633b2d7f8b66893bd01c3aa1ef2c22), [`ac845f3`](https://github.com/Effect-TS/effect-smol/commit/ac845f3ab40e0b8719576e7f9bc16ea2e0e02cd4), [`b80c462`](https://github.com/Effect-TS/effect-smol/commit/b80c46247480f47bb64fc480fab48a3f37bc8888), [`b3f535d`](https://github.com/Effect-TS/effect-smol/commit/b3f535d9a7ac13b5fb984c29f93561c57a081ff0), [`6fe2e93`](https://github.com/Effect-TS/effect-smol/commit/6fe2e93cc2f1b173ef89651d74b6a5d2626b3226), [`cda8004`](https://github.com/Effect-TS/effect-smol/commit/cda800451c1ffbdddfc08415aed7b2d91e0412ee), [`8335477`](https://github.com/Effect-TS/effect-smol/commit/8335477a8a936a24b5f3ee6203c1b268bd1bfc3c), [`8c836f9`](https://github.com/Effect-TS/effect-smol/commit/8c836f99ab1e896b9580a71d67773625baff2eaf), [`718ff6f`](https://github.com/Effect-TS/effect-smol/commit/718ff6fe3e3d3820cefd67d2bff1b2224fe08060), [`7eed84f`](https://github.com/Effect-TS/effect-smol/commit/7eed84fc33c5781a6fb11bf4fd189d424902ebd4), [`5df46fe`](https://github.com/Effect-TS/effect-smol/commit/5df46fe2f654d59ab5fc1578f4fc27fa40368ef9), [`82dd0f2`](https://github.com/Effect-TS/effect-smol/commit/82dd0f26c6442b07143762ef7bc33742d3978dd6), [`03ae41e`](https://github.com/Effect-TS/effect-smol/commit/03ae41e7304cffac9f18feea22b73468feafc43a), [`4677a0a`](https://github.com/Effect-TS/effect-smol/commit/4677a0a58f95eea38a211efcd3f345f237a9e44a), [`87e1fc8`](https://github.com/Effect-TS/effect-smol/commit/87e1fc8b67e4901d75f567b2fecc3841ab762cc4), [`c1af1b7`](https://github.com/Effect-TS/effect-smol/commit/c1af1b756f63291e9c0298cf95c98a6920a0c2a0), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`c8a877b`](https://github.com/Effect-TS/effect-smol/commit/c8a877b53e8f29616335719e5dd1c3992dddf780), [`7da961a`](https://github.com/Effect-TS/effect-smol/commit/7da961ae4916229d2246699a5d3b20e5b2dd2020)]:
- effect@4.0.0-beta.44
## 4.0.0-beta.43
### Patch Changes
- Updated dependencies [[`2ae33d0`](https://github.com/Effect-TS/effect-smol/commit/2ae33d050914915f7cb9c25ab0a020901e08d596), [`979811a`](https://github.com/Effect-TS/effect-smol/commit/979811a4c3f7ed21ed18ef560c49fb7f5569e80e), [`eb7dbef`](https://github.com/Effect-TS/effect-smol/commit/eb7dbeffa883386ad912815e62c0820cac1fdf8e), [`cf50eb4`](https://github.com/Effect-TS/effect-smol/commit/cf50eb49cb04706dae5185f624708117c413dee8), [`1d046fe`](https://github.com/Effect-TS/effect-smol/commit/1d046fe484560e23f3e22cb23eec6433f8f1fa02)]:
- effect@4.0.0-beta.43
## 4.0.0-beta.42
### Patch Changes
- Updated dependencies [[`924e216`](https://github.com/Effect-TS/effect-smol/commit/924e216caa7e0bbf22e994a0cd2ce8b1f0f0b3ee), [`80e7f0c`](https://github.com/Effect-TS/effect-smol/commit/80e7f0cd9116e811e97b0ce30a77a8d1ecd072aa), [`f8328bf`](https://github.com/Effect-TS/effect-smol/commit/f8328bf0314da3dc7f31d314f94a5840e8d5217f), [`66d1c06`](https://github.com/Effect-TS/effect-smol/commit/66d1c06039079129707a230f7ad8c676439d7133), [`bee800b`](https://github.com/Effect-TS/effect-smol/commit/bee800bf285192a01bec72a7b7b51bc1159434e6), [`8930441`](https://github.com/Effect-TS/effect-smol/commit/8930441dee6f94c59c583d18d3ebd677cf1f2623)]:
- effect@4.0.0-beta.42
## 4.0.0-beta.41
### Patch Changes
- Updated dependencies [[`36f5c21`](https://github.com/Effect-TS/effect-smol/commit/36f5c2174d31ab42c4598bf81f178f40d0802283), [`d8ce758`](https://github.com/Effect-TS/effect-smol/commit/d8ce758669d6297ae932ac3251d83e7b49b22f30), [`11aab4c`](https://github.com/Effect-TS/effect-smol/commit/11aab4c6d37d5691adafc2d33da1a631b28ce814), [`3bc1efb`](https://github.com/Effect-TS/effect-smol/commit/3bc1efb53dd75b4a40de46f1f80c7f8a7d50af86), [`70e724e`](https://github.com/Effect-TS/effect-smol/commit/70e724e604604d4be1061cd8da0d360494998c84), [`738dee7`](https://github.com/Effect-TS/effect-smol/commit/738dee7edfd70af82dc4d2376db3a8ebe603eb48), [`2111963`](https://github.com/Effect-TS/effect-smol/commit/2111963f19b4c28c800664a8fac9590c1321885f), [`198a553`](https://github.com/Effect-TS/effect-smol/commit/198a553d9ce45f6a00bfc4d65ed0640669602d95)]:
- effect@4.0.0-beta.41
## 4.0.0-beta.40
### Patch Changes
- Updated dependencies [[`f62860f`](https://github.com/Effect-TS/effect-smol/commit/f62860f0e5e45978fabf7256ae620a13152a772a), [`973f281`](https://github.com/Effect-TS/effect-smol/commit/973f2812529aadc1cc54598b2039799fa72b80f8)]:
- effect@4.0.0-beta.40
## 4.0.0-beta.39
### Patch Changes
- Updated dependencies [[`f91fd3d`](https://github.com/Effect-TS/effect-smol/commit/f91fd3db39fe5628439fd175fba201a65a1aa9d0), [`edaae9d`](https://github.com/Effect-TS/effect-smol/commit/edaae9d65f464f941d7eddd723cd33d324f4b071), [`b47db0b`](https://github.com/Effect-TS/effect-smol/commit/b47db0bd5802064b6a24b3ea27c6ff2e0520d513), [`82d3c8e`](https://github.com/Effect-TS/effect-smol/commit/82d3c8e4f3f49b00df611b25aa6f8f74ec21b59b), [`7c22b31`](https://github.com/Effect-TS/effect-smol/commit/7c22b315d198dcbf44ae8cdb8b37879e1c9e3996)]:
- effect@4.0.0-beta.39
## 4.0.0-beta.38
### Patch Changes
- Updated dependencies [[`f4dbe5b`](https://github.com/Effect-TS/effect-smol/commit/f4dbe5b26b9c2d33fae024bf44afbdf8541792cd), [`a71a607`](https://github.com/Effect-TS/effect-smol/commit/a71a607c89fb6669a12a562c2c23be81dfbe1adb), [`66a0494`](https://github.com/Effect-TS/effect-smol/commit/66a0494ed75cd12f2721dcbb1d8a072e3d9e14b6), [`5ef7218`](https://github.com/Effect-TS/effect-smol/commit/5ef7218fc559d57301fe929b8a0cab4033f4f1fd), [`472d260`](https://github.com/Effect-TS/effect-smol/commit/472d260655bc311fba5c2c6e23bb77d8f7e36ba0)]:
- effect@4.0.0-beta.38
## 4.0.0-beta.37
### Patch Changes
- Updated dependencies [[`f7a0b71`](https://github.com/Effect-TS/effect-smol/commit/f7a0b711da8fdd645597dee29cacc5619c6afcf2), [`1e223c3`](https://github.com/Effect-TS/effect-smol/commit/1e223c30ccf835dfbb21284535d78549efaeca80), [`53740f4`](https://github.com/Effect-TS/effect-smol/commit/53740f47aa76d114b7d535649fb50efc54a09608), [`8c7cf89`](https://github.com/Effect-TS/effect-smol/commit/8c7cf89f719e580cbce1bf6c24e6996f1992a0a6), [`b6b81a9`](https://github.com/Effect-TS/effect-smol/commit/b6b81a940eaafcbc792d25413d6c02c707de31b2), [`8f4c1f9`](https://github.com/Effect-TS/effect-smol/commit/8f4c1f97ed60f8810b0b327b50117ffb2d8260d4), [`f2479f9`](https://github.com/Effect-TS/effect-smol/commit/f2479f9d3113b1f012db17a3852b4e28f478cf9c), [`c919921`](https://github.com/Effect-TS/effect-smol/commit/c9199217fad65529421d2cf95ecfff41257090fd), [`7af90c2`](https://github.com/Effect-TS/effect-smol/commit/7af90c2e3c99038eafa39650433839523790e2fe), [`f3be185`](https://github.com/Effect-TS/effect-smol/commit/f3be18569e5ca57c25eabf00df3ca601ebab43c7)]:
- effect@4.0.0-beta.37
## 4.0.0-beta.36
### Patch Changes
- Updated dependencies [[`60fcbcc`](https://github.com/Effect-TS/effect-smol/commit/60fcbcc43d09471e8f7e0969955d99dcefc5be81), [`0a60837`](https://github.com/Effect-TS/effect-smol/commit/0a6083713124440e630030375bab367e8d7df24e), [`49164d2`](https://github.com/Effect-TS/effect-smol/commit/49164d2c20a8d21b66514992c4a15d8521f6b36e), [`334b6e4`](https://github.com/Effect-TS/effect-smol/commit/334b6e4f76fe11941b516d61f57e268bc31f0ca6), [`5700695`](https://github.com/Effect-TS/effect-smol/commit/5700695f76ae6da6b94c9c87d4dd2b8054fb829b), [`f8f4456`](https://github.com/Effect-TS/effect-smol/commit/f8f445644f3aa7ec093cab7445198a62ba18a480), [`969d24f`](https://github.com/Effect-TS/effect-smol/commit/969d24fdfa48c4838e811983848d9cb4e9b3b12c), [`851eda0`](https://github.com/Effect-TS/effect-smol/commit/851eda0533946e39bacaaf581896320d7a4f3e8c), [`8059c1c`](https://github.com/Effect-TS/effect-smol/commit/8059c1c3eba9a90af7cd889ea261bcb8fff0c185), [`6f83295`](https://github.com/Effect-TS/effect-smol/commit/6f8329546a73eaddc7cb5e85ea8e37e73fbfb611), [`65f7f57`](https://github.com/Effect-TS/effect-smol/commit/65f7f5737575fed668987462c96d29a446707c32), [`e7fabd2`](https://github.com/Effect-TS/effect-smol/commit/e7fabd2265db690eae5cfc9b83730c84699aef61), [`89c3e98`](https://github.com/Effect-TS/effect-smol/commit/89c3e985401eb38f33a3ae21a94ad27de3c1d28b), [`53794ab`](https://github.com/Effect-TS/effect-smol/commit/53794ab7af30aa5c5004ecf53659fafbe4b10542)]:
- effect@4.0.0-beta.36
## 4.0.0-beta.35
### Patch Changes
- Updated dependencies [[`9252b43`](https://github.com/Effect-TS/effect-smol/commit/9252b43560f507709c2985abcf52a7837b23ddf8), [`7daf387`](https://github.com/Effect-TS/effect-smol/commit/7daf3870a656882a488a60f67881e6808c8f4d04), [`e1664a3`](https://github.com/Effect-TS/effect-smol/commit/e1664a38bc31ef4ceb4e9324c7226e1e99bf9c07), [`fdaa6e0`](https://github.com/Effect-TS/effect-smol/commit/fdaa6e0a41b6b6605438fa8557441792135380a2), [`19aa47e`](https://github.com/Effect-TS/effect-smol/commit/19aa47ef7b470e427620edca8970dd9cdd551216), [`c667dad`](https://github.com/Effect-TS/effect-smol/commit/c667dad07777b860e4764a3ba9a6cc41c236cd98), [`764d150`](https://github.com/Effect-TS/effect-smol/commit/764d1501bc5026b60fc8aef6cb02a5a87c762801), [`3c27098`](https://github.com/Effect-TS/effect-smol/commit/3c27098b5685a63db2c2eff654a250c94d3fcfa7)]:
- effect@4.0.0-beta.35
## 4.0.0-beta.34
### Patch Changes
- Updated dependencies [[`f2f75ee`](https://github.com/Effect-TS/effect-smol/commit/f2f75ee564bce1cd95f5189c7bdeeed4f92dacb1), [`342fc4b`](https://github.com/Effect-TS/effect-smol/commit/342fc4b051739e32e7977159f26ff9541eda664f), [`5d704ee`](https://github.com/Effect-TS/effect-smol/commit/5d704ee10d20e8eb107e34bb8a21feb5aa4a7685), [`00add69`](https://github.com/Effect-TS/effect-smol/commit/00add69b59551e9df34772eb927638b093f6d71e), [`58217d3`](https://github.com/Effect-TS/effect-smol/commit/58217d318a7d716ccd707cce0f41573946939c28), [`f4e2aba`](https://github.com/Effect-TS/effect-smol/commit/f4e2aba01b76d1e3059b297e3cc942284dfeafb2), [`e3b44b6`](https://github.com/Effect-TS/effect-smol/commit/e3b44b6a2af9ee21dc5c1e928f0c20af857fa7a9), [`e1472b7`](https://github.com/Effect-TS/effect-smol/commit/e1472b7525c5d57a48bdec2353c3b742f7f916c0), [`7686320`](https://github.com/Effect-TS/effect-smol/commit/7686320cd123fa352b5c3d076fb18a3cac0a9bba)]:
- effect@4.0.0-beta.34
## 4.0.0-beta.33
### Patch Changes
- Updated dependencies [[`571447d`](https://github.com/Effect-TS/effect-smol/commit/571447da67334449f8ae3d6ecb3d77ea4e0c4295)]:
- effect@4.0.0-beta.33
## 4.0.0-beta.32
### Patch Changes
- Updated dependencies [[`bf8fff8`](https://github.com/Effect-TS/effect-smol/commit/bf8fff8a5f54b6df74cb7bbb42346fe9ba52435a), [`1af3ef3`](https://github.com/Effect-TS/effect-smol/commit/1af3ef3e3ca7fd417d0fc15f8ca8fe207eba4f74), [`27fea0f`](https://github.com/Effect-TS/effect-smol/commit/27fea0f66910de5905f40fd63f8ddbb6f7ac5aba), [`2ad6c1b`](https://github.com/Effect-TS/effect-smol/commit/2ad6c1b2c85a3a0fe351e3d56636a75eb76b4b4e), [`398ac3e`](https://github.com/Effect-TS/effect-smol/commit/398ac3e01cb75efce0e4e2913d1450cf65866732), [`51fe22f`](https://github.com/Effect-TS/effect-smol/commit/51fe22f3266e417b6c541aaed4b75d246fac91e7), [`4605db6`](https://github.com/Effect-TS/effect-smol/commit/4605db69cfacddbdbf1525865ddfde135158090c), [`f4de1b0`](https://github.com/Effect-TS/effect-smol/commit/f4de1b087c998d0bad1d9468f70b7d16c13b9f6f), [`60214f2`](https://github.com/Effect-TS/effect-smol/commit/60214f2080b2aeb091f691140eb20acb741691c3), [`c4b8b0f`](https://github.com/Effect-TS/effect-smol/commit/c4b8b0ffa8efb47c4cd7578a8943d6868509373f), [`6d9393a`](https://github.com/Effect-TS/effect-smol/commit/6d9393a0770a18722d23340e77f15455de341245), [`6de4efe`](https://github.com/Effect-TS/effect-smol/commit/6de4efe463c783614ceb0c094d77a336a899cbe0), [`4f969d1`](https://github.com/Effect-TS/effect-smol/commit/4f969d1563ba755ffa116c8ae409bb3436bd881d), [`6cc67c8`](https://github.com/Effect-TS/effect-smol/commit/6cc67c855e054ee3f3ac3485dca5f7805e79e8fb), [`8531a22`](https://github.com/Effect-TS/effect-smol/commit/8531a22ffbb52e11a030b09f358cafbfdf5edff7), [`b226760`](https://github.com/Effect-TS/effect-smol/commit/b22676067617f15c00722a3a63fd7c2c172c3d45), [`47a51ab`](https://github.com/Effect-TS/effect-smol/commit/47a51aba0ecdf3ef478bfa28a498bca188399bd4), [`1521d02`](https://github.com/Effect-TS/effect-smol/commit/1521d02e1f19f1d795edaaf862c1a1031d9c755e)]:
- effect@4.0.0-beta.32
## 4.0.0-beta.31
### Patch Changes
- Updated dependencies [[`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6f23f0e`](https://github.com/Effect-TS/effect-smol/commit/6f23f0ed4cba573cd9395c2e582f582fe7271544), [`654aaec`](https://github.com/Effect-TS/effect-smol/commit/654aaec593305521b65dd042c204d761cc6e8c28), [`2958a42`](https://github.com/Effect-TS/effect-smol/commit/2958a42078966a8713a98f00485ab36484d5eccf), [`95d27a2`](https://github.com/Effect-TS/effect-smol/commit/95d27a239ed5147302605ab0b3147a056541b0c7), [`0fbaea8`](https://github.com/Effect-TS/effect-smol/commit/0fbaea8f9555a8044cec31a770394db613fc78e2), [`21d5d5e`](https://github.com/Effect-TS/effect-smol/commit/21d5d5e0439fd4d9bb6e508377215b1087555d45), [`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6e49959`](https://github.com/Effect-TS/effect-smol/commit/6e499590357a104c81779b3176cd3f84e4f91064), [`8f5805d`](https://github.com/Effect-TS/effect-smol/commit/8f5805dbdd0d1bc0ff0727cc398c8d80e544edee), [`990df2c`](https://github.com/Effect-TS/effect-smol/commit/990df2c3ceeb32e659acc10cc9485617f7b3c423)]:
- effect@4.0.0-beta.31
## 4.0.0-beta.30
### Patch Changes
- Updated dependencies [[`c88e5b7`](https://github.com/Effect-TS/effect-smol/commit/c88e5b723ff09da4edaef6ce14d927ca01104a32), [`947d0e4`](https://github.com/Effect-TS/effect-smol/commit/947d0e4268ba5c4020ead380aa80812c7342408f), [`7517908`](https://github.com/Effect-TS/effect-smol/commit/75179085d159b88a1ab0bce70669d76dcf0d79a4), [`a49ecd5`](https://github.com/Effect-TS/effect-smol/commit/a49ecd5a183d7e7d33f47ff95e9d2dea5a12ead5), [`6993e33`](https://github.com/Effect-TS/effect-smol/commit/6993e3329122c834c20bacea72d8678232f4f103), [`514f2a2`](https://github.com/Effect-TS/effect-smol/commit/514f2a2ae54580fcacdbe2ea2196a83a852d0748), [`3214b47`](https://github.com/Effect-TS/effect-smol/commit/3214b47676de2d33fddc5fecfc2d226e6e83cc7b), [`95ec5ed`](https://github.com/Effect-TS/effect-smol/commit/95ec5ed345de77c893049e182d37a37cf164a268)]:
- effect@4.0.0-beta.30
## 4.0.0-beta.29
### Patch Changes
- Updated dependencies [[`9d93adb`](https://github.com/Effect-TS/effect-smol/commit/9d93adb1c1795d1978391b30d7d2972c88052662), [`b52721c`](https://github.com/Effect-TS/effect-smol/commit/b52721cf0d11a567722b060c8536e3bdd4161f07), [`a891c7b`](https://github.com/Effect-TS/effect-smol/commit/a891c7b12f415b2287613dd4b91a09dfd38ef30d), [`ef26cdf`](https://github.com/Effect-TS/effect-smol/commit/ef26cdfb65d9955fc7e161629191930c2cc2c63f), [`82fd3ed`](https://github.com/Effect-TS/effect-smol/commit/82fd3ed922063ee5a34f96f3993c15c7515e4f67)]:
- effect@4.0.0-beta.29
## 4.0.0-beta.28
### Patch Changes
- Updated dependencies [[`ff533f2`](https://github.com/Effect-TS/effect-smol/commit/ff533f203cd06302ad08032a27e01269b4a2d4c6), [`dc803ee`](https://github.com/Effect-TS/effect-smol/commit/dc803ee52ebd3e9f931118f0dfcb804542847556), [`d660b1c`](https://github.com/Effect-TS/effect-smol/commit/d660b1c99cb93d4f79715e91c7a4486801c0eefa), [`93a05e3`](https://github.com/Effect-TS/effect-smol/commit/93a05e3eaa624058b162aedd66aad70102837270), [`2a65cf6`](https://github.com/Effect-TS/effect-smol/commit/2a65cf6fd81ef63d944e6fb51f058d439bf4a834), [`a561a40`](https://github.com/Effect-TS/effect-smol/commit/a561a40cc41c548c2cf3153aca065ee92ee8aa57), [`29cd24d`](https://github.com/Effect-TS/effect-smol/commit/29cd24d1fe78480a72eeb38a90281ffddc0530bc), [`662a8e6`](https://github.com/Effect-TS/effect-smol/commit/662a8e6857dac64a7cd13bd8df4b0674654622f8), [`d2b52ba`](https://github.com/Effect-TS/effect-smol/commit/d2b52bae5b9336cf59729fbdcc4d7f09512b0cbf), [`407c3b4`](https://github.com/Effect-TS/effect-smol/commit/407c3b43a5d1414558e0e33b6f1fc0e6a6d489cc), [`42bc7ce`](https://github.com/Effect-TS/effect-smol/commit/42bc7ce5480f6f2953c39f8cb5c850d61df6f5a2), [`e741322`](https://github.com/Effect-TS/effect-smol/commit/e74132226cbfee24234311c7c1c13e6b7391384e), [`5c75fa8`](https://github.com/Effect-TS/effect-smol/commit/5c75fa8fb71163bc4c035ba1a215574dfd4badfc), [`747177b`](https://github.com/Effect-TS/effect-smol/commit/747177b0602f12d4461a843e953dfdffbeb0a429), [`326cd48`](https://github.com/Effect-TS/effect-smol/commit/326cd4828bce573fe985f35152155464bf4c5a70), [`627e922`](https://github.com/Effect-TS/effect-smol/commit/627e922b8d1e9521eae5e1caa5d667ad00b1619a), [`662287e`](https://github.com/Effect-TS/effect-smol/commit/662287e9abc76c941ccc2ee330aa07904d571341)]:
- effect@4.0.0-beta.28
## 4.0.0-beta.27
### Patch Changes
- Updated dependencies [[`903a839`](https://github.com/Effect-TS/effect-smol/commit/903a839e94239e6ec4568315af28e405bcad95f4), [`91a0168`](https://github.com/Effect-TS/effect-smol/commit/91a016836680a6669308ecf464d3584bcc4ae1b7), [`c890f9a`](https://github.com/Effect-TS/effect-smol/commit/c890f9a1b3a989ed22528bd5a43326342e05b142), [`1e985f2`](https://github.com/Effect-TS/effect-smol/commit/1e985f237d250b51b91de22dde77160c1e778ce7)]:
- effect@4.0.0-beta.27
## 4.0.0-beta.26
### Patch Changes
- Updated dependencies [[`fb21462`](https://github.com/Effect-TS/effect-smol/commit/fb21462642cdd5b1bada92f3eba18ae20445be42), [`2ed26b1`](https://github.com/Effect-TS/effect-smol/commit/2ed26b139805700e3df39efaa768ff01565e5c86), [`e832a57`](https://github.com/Effect-TS/effect-smol/commit/e832a57b570fe38f010c1fd99bceac5a325a9e07), [`7f01be7`](https://github.com/Effect-TS/effect-smol/commit/7f01be7f8db363d4b2e88e6b5571e96bb815786f), [`e965143`](https://github.com/Effect-TS/effect-smol/commit/e9651431e114479e6becf8ca7b1ed99ac7e91ccc), [`b9b80f1`](https://github.com/Effect-TS/effect-smol/commit/b9b80f1f15e152ceef0a727d150b7dc230abae99), [`98252aa`](https://github.com/Effect-TS/effect-smol/commit/98252aa0c0b17fc73fbdad65d0a1104965f9fc0f), [`56fbd94`](https://github.com/Effect-TS/effect-smol/commit/56fbd94311ad19a05001ad649d9e34ab00c74541), [`3faa109`](https://github.com/Effect-TS/effect-smol/commit/3faa109b7d093fbf14ad410d3e11d663f16e28f1), [`692ecfe`](https://github.com/Effect-TS/effect-smol/commit/692ecfed99fe58056b7a5afe001f4fcd1a61c446), [`1e70b72`](https://github.com/Effect-TS/effect-smol/commit/1e70b72d0b210474d0e96a15a5cfc279eae37e0c), [`ecf0782`](https://github.com/Effect-TS/effect-smol/commit/ecf07829ef2dfc01d8943c96c4fe9c1b44b97926)]:
- effect@4.0.0-beta.26
## 4.0.0-beta.25
### Patch Changes
- Updated dependencies [[`fa17bb5`](https://github.com/Effect-TS/effect-smol/commit/fa17bb5be9f2533d01e11322b14804c7dec43714), [`f46e5b5`](https://github.com/Effect-TS/effect-smol/commit/f46e5b5ca2a918ee4d9270167e79db223077c96f), [`ce4767c`](https://github.com/Effect-TS/effect-smol/commit/ce4767cadcacc6ce8ff4c3a0d0fbc82ede655f63), [`c830a8b`](https://github.com/Effect-TS/effect-smol/commit/c830a8b6c292a6528d7f9318759d34800b00372d)]:
- effect@4.0.0-beta.25
## 4.0.0-beta.24
### Patch Changes
- Updated dependencies [[`a909e1c`](https://github.com/Effect-TS/effect-smol/commit/a909e1c1ac2bc707527f5073776e3e7d239688d9), [`8814a4e`](https://github.com/Effect-TS/effect-smol/commit/8814a4ef78d67144d27689370af10099ea210399), [`3f942c5`](https://github.com/Effect-TS/effect-smol/commit/3f942c51cefa7b2ffa7c49e8c8a2c887570ba4c0), [`774ed59`](https://github.com/Effect-TS/effect-smol/commit/774ed59c52b2ab578bbb897c4f551f812231e1d2), [`f54b8d3`](https://github.com/Effect-TS/effect-smol/commit/f54b8d398fedad1815fd1f4c49814ab938cfc385)]:
- effect@4.0.0-beta.24
## 4.0.0-beta.23
### Patch Changes
- Updated dependencies [[`5c73c41`](https://github.com/Effect-TS/effect-smol/commit/5c73c41b69eaeab80fcd62c9bfda490b446d1966)]:
- effect@4.0.0-beta.23
## 4.0.0-beta.22
### Patch Changes
- Updated dependencies [[`0874332`](https://github.com/Effect-TS/effect-smol/commit/0874332f7c81118b06ac2eb105e0710211631479), [`c592dcd`](https://github.com/Effect-TS/effect-smol/commit/c592dcde0697e322065c8f418c0480ef910cb183), [`1dbe28d`](https://github.com/Effect-TS/effect-smol/commit/1dbe28dac8299cd3e218c9768450cfd173b5e294), [`564d730`](https://github.com/Effect-TS/effect-smol/commit/564d730b6bbf38dd8548a3b046e7a693b28699a4), [`3cfadc4`](https://github.com/Effect-TS/effect-smol/commit/3cfadc458b070c6cba6c5674b72a059f1e49118b), [`6634fd0`](https://github.com/Effect-TS/effect-smol/commit/6634fd07da067d80b8261fb2959d1a952b9e412e), [`d10dabe`](https://github.com/Effect-TS/effect-smol/commit/d10dabeb7af9a368f995829cd36ad08167cd8f95), [`f82f549`](https://github.com/Effect-TS/effect-smol/commit/f82f549a09e950e9d4987f279a800f4d953f0939), [`78a3382`](https://github.com/Effect-TS/effect-smol/commit/78a3382ddfbe034408f7480fa794733d9e82147b)]:
- effect@4.0.0-beta.22
## 4.0.0-beta.21
### Patch Changes
- Updated dependencies [[`e691909`](https://github.com/Effect-TS/effect-smol/commit/e691909495ccb162ea7bfa351dd74632b99997cb), [`d5f413f`](https://github.com/Effect-TS/effect-smol/commit/d5f413f3c8fc57f2413cc5649c2003d6d4e5a6d7), [`139d152`](https://github.com/Effect-TS/effect-smol/commit/139d152941e562a073b5be12e8d66c8a4d4a8a57), [`947e3d4`](https://github.com/Effect-TS/effect-smol/commit/947e3d436ab8a017efda9b29be523efd1ca8df28), [`84b2cce`](https://github.com/Effect-TS/effect-smol/commit/84b2ccefe2aa3a7413b86738a4dc33cdb311ca55), [`7f5305e`](https://github.com/Effect-TS/effect-smol/commit/7f5305e69f5a33309e77b08a576edb25d7daaee2), [`9e6fd84`](https://github.com/Effect-TS/effect-smol/commit/9e6fd8471c93a3c643929151a3bdb62cb9c0ca0e), [`fdb8a4b`](https://github.com/Effect-TS/effect-smol/commit/fdb8a4b172721fbefe98bd5aa6fe4f0efd1da3eb), [`0f986ef`](https://github.com/Effect-TS/effect-smol/commit/0f986ef22f196fe091a7afdbd179485a7d888882), [`9355fc0`](https://github.com/Effect-TS/effect-smol/commit/9355fc0ffb5b7382146a5aed9eea83974b10d007)]:
- effect@4.0.0-beta.21
## 4.0.0-beta.20
### Patch Changes
- Updated dependencies [[`842a624`](https://github.com/Effect-TS/effect-smol/commit/842a624f79d5e1407460b0ef3ab27d14d48ccf74), [`4785eef`](https://github.com/Effect-TS/effect-smol/commit/4785eef5d7cf1edb96ef2509aed2ba4d1edf3862), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`12ee8e2`](https://github.com/Effect-TS/effect-smol/commit/12ee8e27df7eb393d83a5e403390d0cfc82ca732), [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34), [`989d1cc`](https://github.com/Effect-TS/effect-smol/commit/989d1cca936fce0cc459057825ba40e3f5ef3827)]:
- effect@4.0.0-beta.20
## 4.0.0-beta.19
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.19
## 4.0.0-beta.18
### Patch Changes
- Updated dependencies [[`01e31fd`](https://github.com/Effect-TS/effect-smol/commit/01e31fdf8e5206849d23cbafd23a346f2f177ab8), [`0890aab`](https://github.com/Effect-TS/effect-smol/commit/0890aab15ed9c5ba52c383a72fdc6a444d7504d5), [`725260b`](https://github.com/Effect-TS/effect-smol/commit/725260b53f5142d6af7a93a2f9f464f974eda92d)]:
- effect@4.0.0-beta.18
## 4.0.0-beta.17
### Patch Changes
- Updated dependencies [[`8f59c32`](https://github.com/Effect-TS/effect-smol/commit/8f59c32922597a48392744f7203e284866747781)]:
- effect@4.0.0-beta.17
## 4.0.0-beta.16
### Patch Changes
- Updated dependencies [[`bf9096c`](https://github.com/Effect-TS/effect-smol/commit/bf9096c52a7d8791d93d232739e523eb84f6625a), [`29f81ca`](https://github.com/Effect-TS/effect-smol/commit/29f81ca07c67dba265804b140a7487fb15a5fc6b), [`68eb28c`](https://github.com/Effect-TS/effect-smol/commit/68eb28c2b0fc67a9f6204ade9bd16c5b37803bfb)]:
- effect@4.0.0-beta.16
## 4.0.0-beta.15
### Patch Changes
- Updated dependencies [[`24ae609`](https://github.com/Effect-TS/effect-smol/commit/24ae60995d2fd7d621be356cdfdfd328c79639ba), [`0e3c059`](https://github.com/Effect-TS/effect-smol/commit/0e3c059987caa55ebd0c134f7c7b147c639c328e), [`e843b0a`](https://github.com/Effect-TS/effect-smol/commit/e843b0a7d7e7b600a0b3bd477f24e2e4cd26bc8b), [`f4389a2`](https://github.com/Effect-TS/effect-smol/commit/f4389a2cca3c5bbf00d69779f52ce41255f15a28), [`5b73de0`](https://github.com/Effect-TS/effect-smol/commit/5b73de095b3402d0c5c74092ace6ce18ebfad566), [`595d2d6`](https://github.com/Effect-TS/effect-smol/commit/595d2d6e7d50419f3532bd39266191532ace38f2)]:
- effect@4.0.0-beta.15
## 4.0.0-beta.14
### Patch Changes
- Updated dependencies [[`c414700`](https://github.com/Effect-TS/effect-smol/commit/c414700ef1932e4b67d0102856de417336912350), [`a30c969`](https://github.com/Effect-TS/effect-smol/commit/a30c9699c0d736cf3952041e45d508b7d58907a9)]:
- effect@4.0.0-beta.14
## 4.0.0-beta.13
### Patch Changes
- Updated dependencies [[`368f4c3`](https://github.com/Effect-TS/effect-smol/commit/368f4c363dd117e6f5a19ad77b161176cfd29fdd), [`db8a579`](https://github.com/Effect-TS/effect-smol/commit/db8a579e93e93ff73b1e60712732e03b597b916b), [`668b703`](https://github.com/Effect-TS/effect-smol/commit/668b70337e9ddbb0d1ae2282a95c282ce404e562), [`d40e76b`](https://github.com/Effect-TS/effect-smol/commit/d40e76b973543979e60e04a6baca04a8c65bdfc2), [`6e18cf8`](https://github.com/Effect-TS/effect-smol/commit/6e18cf883e9905ca718a6697b6a2a4bbd42739aa), [`86062e8`](https://github.com/Effect-TS/effect-smol/commit/86062e8a0c61bca5412fc40d2cf151d676901f08), [`c27ce75`](https://github.com/Effect-TS/effect-smol/commit/c27ce75d34c74dcfc6dba1bf77f1ce88f410a0de), [`e2d4fbf`](https://github.com/Effect-TS/effect-smol/commit/e2d4fbfeeda6a5d2a4c5aeb0501d8240c248b9eb), [`114ab42`](https://github.com/Effect-TS/effect-smol/commit/114ab42ad0edc590d29169675a493e0e915aa58f), [`484caec`](https://github.com/Effect-TS/effect-smol/commit/484caec47cccac8b86db2910742e406dfc7173ab)]:
- effect@4.0.0-beta.13
## 4.0.0-beta.12
### Patch Changes
- Updated dependencies [[`70a74e8`](https://github.com/Effect-TS/effect-smol/commit/70a74e88a8767c9d4acdb9e5f25aec9a33588d07), [`b5b6e10`](https://github.com/Effect-TS/effect-smol/commit/b5b6e10621d54bf8c9857fec0d647ced78ecd857), [`f5ce5a9`](https://github.com/Effect-TS/effect-smol/commit/f5ce5a915359c6ebf254079e1da23cab6cde34fb), [`a29eb70`](https://github.com/Effect-TS/effect-smol/commit/a29eb702ffe3fc58bd28c4d7857298cd65d73668), [`c7b36e5`](https://github.com/Effect-TS/effect-smol/commit/c7b36e541a23e9a00f64e25b23851e51a37dfce5), [`9381d6d`](https://github.com/Effect-TS/effect-smol/commit/9381d6d4d9d819a81a46e56d0364c76e92a4fbca), [`88439f1`](https://github.com/Effect-TS/effect-smol/commit/88439f13ca13549f3e4822c48c4f019c14fc2bcc), [`e35307d`](https://github.com/Effect-TS/effect-smol/commit/e35307dbeb8eb26a9923f958b894a8eaaf259bf2), [`c7df4bc`](https://github.com/Effect-TS/effect-smol/commit/c7df4bce34009474c63d62a807abfdafb76971eb), [`accaf3b`](https://github.com/Effect-TS/effect-smol/commit/accaf3be7ac8da36e2334c509c23b8c9e88ea160), [`3e1c270`](https://github.com/Effect-TS/effect-smol/commit/3e1c2707bbdf67720af1509642b8ced195790882), [`6cd81f7`](https://github.com/Effect-TS/effect-smol/commit/6cd81f73baad86f5bbfa455a55d75cde71e9611a), [`f222da3`](https://github.com/Effect-TS/effect-smol/commit/f222da3cdb44554f3324c2c52d0d005ee575053e), [`61f901d`](https://github.com/Effect-TS/effect-smol/commit/61f901d830005b66e22d1de889fda132aeea97cd)]:
- effect@4.0.0-beta.12
## 4.0.0-beta.11
### Patch Changes
- Updated dependencies [[`88659ed`](https://github.com/Effect-TS/effect-smol/commit/88659edb26e3623d557dccfe914c2c949672da16), [`f2915e8`](https://github.com/Effect-TS/effect-smol/commit/f2915e8e2efe80d50c281e53f297b9701d6dc199), [`eb71ace`](https://github.com/Effect-TS/effect-smol/commit/eb71acebbe0f228e4920278013beee3b67d62310), [`2a16999`](https://github.com/Effect-TS/effect-smol/commit/2a169996c7513d377ac47adbfd68e1490457135c), [`d42dd52`](https://github.com/Effect-TS/effect-smol/commit/d42dd52f11203f8e749fb5d3ecf7153e4a5a6814), [`339adaf`](https://github.com/Effect-TS/effect-smol/commit/339adaf850a62a892adebcb208c2d9dddf3b97b3), [`de19645`](https://github.com/Effect-TS/effect-smol/commit/de1964526d01102dd1cb99c8cfdd3e8df1f49ef1), [`9b1dc3b`](https://github.com/Effect-TS/effect-smol/commit/9b1dc3bcf2a1b68d0a67e3465db5ad01a1a56997), [`e4cb2f5`](https://github.com/Effect-TS/effect-smol/commit/e4cb2f55b30f4771ec1bf613ced36d6d96464dd5), [`8bced95`](https://github.com/Effect-TS/effect-smol/commit/8bced954ecb35d4489197a57b0efe927e7d75f49), [`9431420`](https://github.com/Effect-TS/effect-smol/commit/94314207c8019918200fbcb97aec992219f801f0), [`948dca2`](https://github.com/Effect-TS/effect-smol/commit/948dca22e4f672ba7a6db57f9899272bec7c08b8), [`d18e327`](https://github.com/Effect-TS/effect-smol/commit/d18e32765a2665e31ffb31e746bf983fcfac34c5), [`ab512f7`](https://github.com/Effect-TS/effect-smol/commit/ab512f7be1c0e6b359da921e22cd4944e4c57d3e)]:
- effect@4.0.0-beta.11
## 4.0.0-beta.10
### Patch Changes
- Updated dependencies [[`371acab`](https://github.com/Effect-TS/effect-smol/commit/371acabb58d56f3a7a5e3e33d3d5fdc9f5573c74), [`856d774`](https://github.com/Effect-TS/effect-smol/commit/856d7741f1e296dd5048c6ff2b44b95d023e6ae4), [`b9e9202`](https://github.com/Effect-TS/effect-smol/commit/b9e92023c38caa322975d77cfe83e2d34ac9305a), [`1d1a974`](https://github.com/Effect-TS/effect-smol/commit/1d1a974bd280c81bff5d4505491cda03ba7a3f36), [`6bfe2a6`](https://github.com/Effect-TS/effect-smol/commit/6bfe2a659bc6335db75709931f405da45301cba2), [`b12c811`](https://github.com/Effect-TS/effect-smol/commit/b12c81157be287b1649c210616a244b50ec094d2), [`d17d98a`](https://github.com/Effect-TS/effect-smol/commit/d17d98ad78e2b44d95ef434adab79ac3c35e75ab), [`68c3c7c`](https://github.com/Effect-TS/effect-smol/commit/68c3c7cb1e06ed94fa5c4c123a234b4ccbfdecd8)]:
- effect@4.0.0-beta.10
## 4.0.0-beta.9
### Patch Changes
- Updated dependencies [[`3386557`](https://github.com/Effect-TS/effect-smol/commit/338655731564a7be9f8859dedbf4d5bcac6eb350), [`b6666e3`](https://github.com/Effect-TS/effect-smol/commit/b6666e3cf6bd44ba1a8704e65c256c30359cb422)]:
- effect@4.0.0-beta.9
## 4.0.0-beta.8
### Patch Changes
- Updated dependencies [[`246e672`](https://github.com/Effect-TS/effect-smol/commit/246e672dbbd7848d60e0c78fd66671b2f10b3752), [`807dec0`](https://github.com/Effect-TS/effect-smol/commit/807dec03801b4c58a6d00c237b6d98d6386911df)]:
- effect@4.0.0-beta.8
## 4.0.0-beta.7
### Patch Changes
- Updated dependencies [[`a2bda6d`](https://github.com/Effect-TS/effect-smol/commit/a2bda6d4ef6de9d9b0c53ae2df5434f778d6161a), [`1f95a2b`](https://github.com/Effect-TS/effect-smol/commit/1f95a2b5aa9524bb38f4437f4691a664bf463ca1), [`a8d5e79`](https://github.com/Effect-TS/effect-smol/commit/a8d5e792fec201a83af0eb92fc79928d055125fd), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`06d8a03`](https://github.com/Effect-TS/effect-smol/commit/06d8a0391631e6130e3ab25227e59817852e227f), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`f9e883e`](https://github.com/Effect-TS/effect-smol/commit/f9e883e266fbda870336ee62f46b7ac85ba3de6e), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430)]:
- effect@4.0.0-beta.7
## 4.0.0-beta.6
### Patch Changes
- Updated dependencies [[`3247da2`](https://github.com/Effect-TS/effect-smol/commit/3247da28331f345f68be5dbd2974a7e03d300fe1), [`f205705`](https://github.com/Effect-TS/effect-smol/commit/f2057050dbd034b8c186be2d40c3d03ee63a5a3b), [`f35022c`](https://github.com/Effect-TS/effect-smol/commit/f35022c212e4111527e1bb43f360a67b2b49fa85), [`8622721`](https://github.com/Effect-TS/effect-smol/commit/86227217b02d43680a3c6f3c21731b1d852c91f5), [`fc660ab`](https://github.com/Effect-TS/effect-smol/commit/fc660ab8b5ebae38b8d6b96cbf2f9b880cc09253), [`f37dc33`](https://github.com/Effect-TS/effect-smol/commit/f37dc335f64622fa9ce8d6d1d5dd8fc3f260257b), [`3662f32`](https://github.com/Effect-TS/effect-smol/commit/3662f328fcfa3b2fa01ffa79da40e12e93fcede8), [`a7d436f`](https://github.com/Effect-TS/effect-smol/commit/a7d436f438dcd7f49b9485e4e95a4511f31fad7d), [`6856a41`](https://github.com/Effect-TS/effect-smol/commit/6856a415d7eddd9d73d60919e976f1d071421be4), [`8c417d0`](https://github.com/Effect-TS/effect-smol/commit/8c417d03475e5e12d00dca0c4781d0af7e66b86c), [`5419570`](https://github.com/Effect-TS/effect-smol/commit/5419570ba47ce882a3a10882707b46f66e464906), [`449c5ed`](https://github.com/Effect-TS/effect-smol/commit/449c5ed5318e8a874e730420bcf52918fa2ec80f), [`4b5ec12`](https://github.com/Effect-TS/effect-smol/commit/4b5ec12f87f95f2a3cd8fe4d5b26c6eb0529381a), [`df87937`](https://github.com/Effect-TS/effect-smol/commit/df879375fc3b169c43f9c434b3775e12b80dffe4), [`5dbfca8`](https://github.com/Effect-TS/effect-smol/commit/5dbfca8d1dbb6d18d1605d4f8562e99c86e2ff11), [`e629497`](https://github.com/Effect-TS/effect-smol/commit/e6294973d55597ab6b6deca6babbe1e946b2c91d), [`981c991`](https://github.com/Effect-TS/effect-smol/commit/981c991cd78db34def815d5754379d737157f005), [`1ca2ed6`](https://github.com/Effect-TS/effect-smol/commit/1ca2ed67301a5dc40ae0ed94346b99f26fd22bbe), [`45722bd`](https://github.com/Effect-TS/effect-smol/commit/45722bde974458311f11ad237711363a10ec6894), [`eb2a85e`](https://github.com/Effect-TS/effect-smol/commit/eb2a85ed4dc162b2535d304799333a5a20477fd0)]:
- effect@4.0.0-beta.6
## 4.0.0-beta.5
### Patch Changes
- [#1314](https://github.com/Effect-TS/effect-smol/pull/1314) [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8) Thanks @zeyuri! - Port ReactHydration to effect-smol.
Add `Hydration` module to `effect/unstable/reactivity` with `dehydrate`, `hydrate`, and `toValues` for SSR state serialization. Add `HydrationBoundary` React component to `@effect/atom-react` with two-phase hydration (new atoms in render, existing atoms after commit).
- Updated dependencies [[`f6e133e`](https://github.com/Effect-TS/effect-smol/commit/f6e133e9a16b32317bd09ff08c12b97a0ae44600), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8), [`a88e206`](https://github.com/Effect-TS/effect-smol/commit/a88e206e44dc66ca5a2b45bedc797877c5dbb083), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8)]:
- effect@4.0.0-beta.5
## 4.0.0-beta.4
### Patch Changes
- Updated dependencies [[`c5a18ef`](https://github.com/Effect-TS/effect-smol/commit/c5a18ef44171e3880bf983faee74529908974b32), [`bc6b885`](https://github.com/Effect-TS/effect-smol/commit/bc6b885b94d887a200657c0775dfa874dc15bc0c)]:
- effect@4.0.0-beta.4
## 4.0.0-beta.3
### Patch Changes
- Updated dependencies [[`3a0cf36`](https://github.com/Effect-TS/effect-smol/commit/3a0cf36eff106ba48d74e133c1598cd40613e530), [`c4da328`](https://github.com/Effect-TS/effect-smol/commit/c4da328d32fad1d61e0e538f5d371edf61521d7e)]:
- effect@4.0.0-beta.3
## 4.0.0-beta.2
### Patch Changes
- Updated dependencies [[`a22ce73`](https://github.com/Effect-TS/effect-smol/commit/a22ce73b2bd9305b7ba665694d2255c0e6d5a8d0), [`ebdabf7`](https://github.com/Effect-TS/effect-smol/commit/ebdabf79ff4e62c8384aa8cf9a8d2787d536ee78), [`8f663bb`](https://github.com/Effect-TS/effect-smol/commit/8f663bb121021bf12bd264e8ae385187cb7a5dae)]:
- effect@4.0.0-beta.2
## 4.0.0-beta.1
### Patch Changes
- Updated dependencies [[`0fecf70`](https://github.com/Effect-TS/effect-smol/commit/0fecf70048057623eed7c584a06671773a2b1743), [`709569e`](https://github.com/Effect-TS/effect-smol/commit/709569ed76bead9ebb0670599e4d890a07ca5a43)]:
- effect@4.0.0-beta.1
## 4.0.0-beta.0
### Major Changes
- [#1183](https://github.com/Effect-TS/effect-smol/pull/1183) [`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66) Thanks @tim-smart! - v4 beta
### Patch Changes
- Updated dependencies [[`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66)]:
- effect@4.0.0-beta.0

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023-present The Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,7 @@
# `@effect/atom-react`
React bindings for the Effect Atom modules.
## Documentation
- **API Reference**: [View the full documentation](https://effect-ts.github.io/effect/docs/atom-react).

View File

@@ -0,0 +1,24 @@
{
"$schema": "../../../node_modules/@effect/docgen/schema.json",
"srcLink": "https://github.com/Effect-TS/effect/tree/main/packages/atom/react/src/",
"exclude": ["src/internal/**/*.ts"],
"examplesCompilerOptions": {
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"types": ["node"],
"rewriteRelativeImportExtensions": true,
"allowImportingTsExtensions": true,
"paths": {
"effect": ["../../../effect/src/index.js"],
"effect/*": ["../../../effect/src/*.js"]
},
"plugins": [
{ "name": "@effect/language-service", "includeSuggestionsInTsc": false }
]
}
}

View File

@@ -0,0 +1,78 @@
{
"name": "@effect/atom-react",
"version": "4.0.0-beta.99",
"type": "module",
"license": "MIT",
"description": "React bindings for the Effect Atom modules",
"homepage": "https://effect.website",
"repository": {
"type": "git",
"url": "https://github.com/Effect-TS/effect.git",
"directory": "packages/atom/react"
},
"bugs": {
"url": "https://github.com/Effect-TS/effect/issues"
},
"tags": [
"typescript",
"react",
"database"
],
"keywords": [
"typescript",
"react",
"database"
],
"sideEffects": [],
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts",
"./*": "./src/*.ts",
"./internal/*": null,
"./*/index": null
},
"files": [
"src/**/*.ts",
"dist/**/*.js",
"dist/**/*.js.map",
"dist/**/*.d.ts",
"dist/**/*.d.ts.map"
],
"publishConfig": {
"access": "public",
"provenance": true,
"exports": {
"./package.json": "./package.json",
".": "./dist/index.js",
"./*": "./dist/*.js",
"./internal/*": null,
"./*/index": null
}
},
"scripts": {
"build": "tsc -b tsconfig.json && pnpm babel",
"babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
"check": "tsc -b tsconfig.json",
"test": "vitest",
"coverage": "vitest --coverage"
},
"peerDependencies": {
"effect": "workspace:^",
"react": "^19.2.4",
"scheduler": "*"
},
"devDependencies": {
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.2",
"@types/scheduler": "^0.26.0",
"effect": "workspace:^",
"jsdom": "^29.1.1",
"react": "19.2.7",
"react-dom": "19.2.7",
"react-error-boundary": "^6.1.2",
"scheduler": "^0.27.0"
}
}

View File

@@ -0,0 +1,476 @@
/**
* React hooks for working with Effect atoms from components. The hooks read,
* write, mount, refresh, and subscribe to atoms from `RegistryContext`, handle
* `AsyncResult` atoms with React Suspense, and expose helpers for reading and
* deriving `AtomRef` values.
*
* @since 4.0.0
*/
"use client"
import * as Cause from "effect/Cause"
import * as Effect from "effect/Effect"
import * as Exit from "effect/Exit"
import type * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
import * as Atom from "effect/unstable/reactivity/Atom"
import type * as AtomRef from "effect/unstable/reactivity/AtomRef"
import * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry"
import * as React from "react"
import { RegistryContext } from "./RegistryContext.ts"
interface AtomStore<A> {
readonly subscribe: (f: () => void) => () => void
readonly snapshot: () => A
readonly getServerSnapshot: () => A
}
const storeRegistry = new WeakMap<AtomRegistry.AtomRegistry, WeakMap<Atom.Atom<any>, AtomStore<any>>>()
function makeStore<A>(registry: AtomRegistry.AtomRegistry, atom: Atom.Atom<A>): AtomStore<A> {
let stores = storeRegistry.get(registry)
if (stores === undefined) {
stores = new WeakMap()
storeRegistry.set(registry, stores)
}
const store = stores.get(atom)
if (store !== undefined) {
return store
}
const newStore: AtomStore<A> = {
subscribe(f) {
return registry.subscribe(atom, f)
},
snapshot() {
return registry.get(atom)
},
getServerSnapshot() {
return Atom.getServerValue(atom, registry)
}
}
stores.set(atom, newStore)
return newStore
}
function useStore<A>(registry: AtomRegistry.AtomRegistry, atom: Atom.Atom<A>): A {
const store = makeStore(registry, atom)
return React.useSyncExternalStore(store.subscribe, store.snapshot, store.getServerSnapshot)
}
const initialValuesSet = new WeakMap<AtomRegistry.AtomRegistry, WeakSet<Atom.Atom<any>>>()
/**
* Seeds initial atom values in the current React atom registry.
*
* **When to use**
*
* Use to seed atom values from a React component after the current registry
* already exists.
*
* **Gotchas**
*
* Each atom is initialized at most once for a given registry by this hook, so
* later calls for the same atom in that registry are ignored.
*
* @category hooks
* @since 4.0.0
*/
export const useAtomInitialValues = (initialValues: Iterable<readonly [Atom.Atom<any>, any]>): void => {
const registry = React.useContext(RegistryContext)
let set = initialValuesSet.get(registry)
if (set === undefined) {
set = new WeakSet()
initialValuesSet.set(registry, set)
}
for (const [atom, value] of initialValues) {
if (!set.has(atom)) {
set.add(atom)
;(registry as any).ensureNode(atom).setValue(value)
}
}
}
/**
* Subscribes to an atom in the current React registry and returns its current
* value, optionally mapped through a selector.
*
* **When to use**
*
* Use when a React component needs to render from an atom value without also
* returning a setter.
*
* **Details**
*
* When a selector is provided, the hook maps the atom before subscribing so the
* component reads the selected value from the current `RegistryContext`.
*
* @see {@link useAtom} for reading and updating a writable atom from one component
* @see {@link useAtomRef} for reading an `AtomRef` directly
*
* @category hooks
* @since 4.0.0
*/
export const useAtomValue: {
<A>(atom: Atom.Atom<A>): A
<A, B>(atom: Atom.Atom<A>, f: (_: A) => B): B
} = <A>(atom: Atom.Atom<A>, f?: (_: A) => A): A => {
const registry = React.useContext(RegistryContext)
if (f) {
const atomB = React.useMemo(() => Atom.map(atom, f), [atom, f])
return useStore(registry, atomB)
}
return useStore(registry, atom)
}
function mountAtom<A>(registry: AtomRegistry.AtomRegistry, atom: Atom.Atom<A>): void {
React.useEffect(() => registry.mount(atom), [atom, registry])
}
function setAtom<R, W, Mode extends "value" | "promise" | "promiseExit" = never>(
registry: AtomRegistry.AtomRegistry,
atom: Atom.Writable<R, W>,
options?: {
readonly mode?: ([R] extends [AsyncResult.AsyncResult<any, any>] ? Mode : "value") | undefined
}
): "promise" extends Mode ? (
(value: W) => Promise<AsyncResult.AsyncResult.Success<R>>
) :
"promiseExit" extends Mode ? (
(value: W) => Promise<Exit.Exit<AsyncResult.AsyncResult.Success<R>, AsyncResult.AsyncResult.Failure<R>>>
) :
((value: W | ((value: R) => W)) => void)
{
if (options?.mode === "promise" || options?.mode === "promiseExit") {
return React.useCallback((value: W) => {
registry.set(atom, value)
const promise = Effect.runPromiseExit(
AtomRegistry.getResult(registry, atom as Atom.Atom<AsyncResult.AsyncResult<any, any>>, {
suspendOnWaiting: true
})
)
return options!.mode === "promise" ? promise.then(flattenExit) : promise
}, [registry, atom, options.mode]) as any
}
return React.useCallback((value: W | ((value: R) => W)) => {
registry.set(atom, typeof value === "function" ? (value as any)(registry.get(atom)) : value)
}, [registry, atom]) as any
}
const flattenExit = <A, E>(exit: Exit.Exit<A, E>): A => {
if (Exit.isSuccess(exit)) return exit.value
throw Cause.squash(exit.cause)
}
/**
* Mounts an atom in the current React registry for the lifetime of the
* component.
*
* **When to use**
*
* Use to keep an atom mounted from a React component without reading, writing,
* or refreshing it.
*
* **Details**
*
* The hook uses the current `RegistryContext` and releases the mount through
* React effect cleanup when the component unmounts or when the registry or atom
* dependency changes.
*
* @see {@link useAtomSet} for mounting a writable atom while returning a setter
* @see {@link useAtomRefresh} for mounting an atom while returning a refresh callback
*
* @category hooks
* @since 4.0.0
*/
export const useAtomMount = <A>(atom: Atom.Atom<A>): void => {
const registry = React.useContext(RegistryContext)
mountAtom(registry, atom)
}
/**
* Mounts a writable atom and returns a setter without subscribing to its value.
*
* **When to use**
*
* Use when a React component needs to update a writable atom without rendering
* from that atom's value.
*
* **Details**
*
* The hook mounts the atom and returns a setter. In value mode the setter
* accepts a write value or updater function; for `AsyncResult` atoms, `promise`
* and `promiseExit` modes return a promise for the success value or full `Exit`.
*
* @see {@link useAtom} for reading and updating the same writable atom
*
* @category hooks
* @since 4.0.0
*/
export const useAtomSet = <
R,
W,
Mode extends "value" | "promise" | "promiseExit" = never
>(
atom: Atom.Writable<R, W>,
options?: {
readonly mode?: ([R] extends [AsyncResult.AsyncResult<any, any>] ? Mode : "value") | undefined
}
): "promise" extends Mode ? (
(value: W) => Promise<AsyncResult.AsyncResult.Success<R>>
) :
"promiseExit" extends Mode ? (
(value: W) => Promise<Exit.Exit<AsyncResult.AsyncResult.Success<R>, AsyncResult.AsyncResult.Failure<R>>>
) :
((value: W | ((value: R) => W)) => void) =>
{
const registry = React.useContext(RegistryContext)
mountAtom(registry, atom)
return setAtom(registry, atom, options)
}
/**
* Mounts an atom and returns a callback that refreshes it in the current React
* registry.
*
* **When to use**
*
* Use to expose a React callback that requests a refresh for an atom without
* reading or writing its value.
*
* **Details**
*
* The hook uses the current `RegistryContext`, mounts the atom for the
* component lifetime, and returns a callback that calls `registry.refresh`.
*
* @see {@link useAtomMount} for mounting an atom without returning a refresh callback
*
* @category hooks
* @since 4.0.0
*/
export const useAtomRefresh = <A>(atom: Atom.Atom<A>): () => void => {
const registry = React.useContext(RegistryContext)
mountAtom(registry, atom)
return React.useCallback(() => {
registry.refresh(atom)
}, [registry, atom])
}
/**
* Subscribes to a writable atom and returns its current value together with a
* setter for updating it.
*
* **When to use**
*
* Use when a React component needs both to render the current value of a
* writable atom and update it from the same component.
*
* @see {@link useAtomValue} for subscribing to an atom without a setter
* @see {@link useAtomSet} for updating a writable atom without subscribing to its value
*
* @category hooks
* @since 4.0.0
*/
export const useAtom = <R, W, const Mode extends "value" | "promise" | "promiseExit" = never>(
atom: Atom.Writable<R, W>,
options?: {
readonly mode?: ([R] extends [AsyncResult.AsyncResult<any, any>] ? Mode : "value") | undefined
}
): readonly [
value: R,
write: "promise" extends Mode ? (
(value: W) => Promise<AsyncResult.AsyncResult.Success<R>>
) :
"promiseExit" extends Mode ? (
(value: W) => Promise<Exit.Exit<AsyncResult.AsyncResult.Success<R>, AsyncResult.AsyncResult.Failure<R>>>
) :
((value: W | ((value: R) => W)) => void)
] => {
const registry = React.useContext(RegistryContext)
return [
useStore(registry, atom),
setAtom(registry, atom, options)
] as const
}
const atomPromiseMap = {
suspendOnWaiting: new Map<Atom.Atom<any>, Promise<void>>(),
default: new Map<Atom.Atom<any>, Promise<void>>()
}
function atomToPromise<A, E>(
registry: AtomRegistry.AtomRegistry,
atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>,
suspendOnWaiting: boolean
) {
const map = suspendOnWaiting ? atomPromiseMap.suspendOnWaiting : atomPromiseMap.default
let promise = map.get(atom)
if (promise !== undefined) {
return promise
}
promise = new Promise<void>((resolve) => {
const dispose = registry.subscribe(atom, (result) => {
if (result._tag === "Initial" || (suspendOnWaiting && result.waiting)) {
return
}
setTimeout(dispose, 1000)
resolve()
map.delete(atom)
})
})
map.set(atom, promise)
return promise
}
function atomResultOrSuspend<A, E>(
registry: AtomRegistry.AtomRegistry,
atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>,
suspendOnWaiting: boolean
) {
const value = useStore(registry, atom)
if (value._tag === "Initial" || (suspendOnWaiting && value.waiting)) {
throw atomToPromise(registry, atom, suspendOnWaiting)
}
return value
}
/**
* Reads an `AsyncResult` atom through React Suspense, suspending while the
* result is initial or configured as waiting.
*
* **When to use**
*
* Use when a React component should render only after an `AsyncResult` atom has
* left its initial state, with loading delegated to a Suspense boundary.
*
* **Details**
*
* `suspendOnWaiting` defaults to `false`. When `includeFailure` is `true`, a
* failure result is returned instead of being thrown.
*
* **Gotchas**
*
* Without `includeFailure`, failure results are thrown with
* `Cause.squash(result.cause)`, so callers need an error boundary for failures.
*
* @see {@link useAtomValue} for reading the raw `AsyncResult` value without Suspense
*
* @category hooks
* @since 4.0.0
*/
export const useAtomSuspense = <A, E, const IncludeFailure extends boolean = false>(
atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>,
options?: {
readonly suspendOnWaiting?: boolean | undefined
readonly includeFailure?: IncludeFailure | undefined
}
): AsyncResult.Success<A, E> | (IncludeFailure extends true ? AsyncResult.Failure<A, E> : never) => {
const registry = React.useContext(RegistryContext)
const result = atomResultOrSuspend(registry, atom, options?.suspendOnWaiting ?? false)
if (result._tag === "Failure" && !options?.includeFailure) {
throw Cause.squash(result.cause)
}
return result as any
}
/**
* Subscribes a callback to an atom in the current React registry for the
* component lifetime.
*
* **When to use**
*
* Use when a React component needs to run a callback for atom changes without
* reading the atom value during render.
*
* **Details**
*
* The subscription is installed in a React effect and cleaned up on unmount or
* dependency change. When `options.immediate` is enabled, the callback receives
* the current value when the effect subscribes.
*
* @see {@link useAtomValue} for reading an atom value during render instead of running a callback
*
* @category hooks
* @since 4.0.0
*/
export const useAtomSubscribe = <A>(
atom: Atom.Atom<A>,
f: (_: A) => void,
options?: { readonly immediate?: boolean }
): void => {
const registry = React.useContext(RegistryContext)
React.useEffect(
() => registry.subscribe(atom, f, options),
[registry, atom, f, options?.immediate]
)
}
/**
* Subscribes to an atom ref and returns its latest value.
*
* **When to use**
*
* Use when a React component should render from an `AtomRef.ReadonlyRef`
* directly instead of reading an atom through the current registry.
*
* **Details**
*
* The hook subscribes with `ref.subscribe`, triggers re-renders through React
* state, and returns the current `ref.value`.
*
* @see {@link useAtomValue} for reading an `Atom` from the current registry
* @see {@link useAtomRefPropValue} for reading a property ref value
*
* @category hooks
* @since 4.0.0
*/
export const useAtomRef = <A>(ref: AtomRef.ReadonlyRef<A>): A => {
const [, setValue] = React.useState(ref.value)
React.useEffect(() => ref.subscribe(setValue), [ref])
return ref.value
}
/**
* Returns a memoized atom ref for a property of another atom ref.
*
* **When to use**
*
* Use to derive an `AtomRef` for one property of an object-shaped atom ref.
*
* **Details**
*
* The hook memoizes `ref.prop(prop)` for the `[ref, prop]` dependency pair and
* returns the property ref so callers can read, set, update, or subscribe to
* that nested property.
*
* @see {@link useAtomRef} for subscribing to an atom ref value
* @see {@link useAtomRefPropValue} for subscribing directly to a property value
*
* @category hooks
* @since 4.0.0
*/
export const useAtomRefProp = <A, K extends keyof A>(ref: AtomRef.AtomRef<A>, prop: K): AtomRef.AtomRef<A[K]> =>
React.useMemo(() => ref.prop(prop), [ref, prop])
/**
* Subscribes to a property ref derived from an atom ref and returns its current
* value.
*
* **When to use**
*
* Use when a React component needs only the current value of one property from
* an object-shaped `AtomRef`.
*
* **Details**
*
* The hook composes `useAtomRefProp(ref, prop)` with `useAtomRef`, so the
* property ref is memoized for the `[ref, prop]` pair and then subscribed
* through `ref.subscribe`.
*
* @see {@link useAtomRefProp} for returning the property ref directly
* @see {@link useAtomRef} for subscribing to a whole atom ref value
*
* @category hooks
* @since 4.0.0
*/
export const useAtomRefPropValue = <A, K extends keyof A>(ref: AtomRef.AtomRef<A>, prop: K): A[K] =>
useAtomRef(useAtomRefProp(ref, prop))

View File

@@ -0,0 +1,109 @@
/**
* React helpers for applying dehydrated Effect Atom state to a React subtree.
* The `HydrationBoundary` component reads the nearest `RegistryContext`,
* hydrates new Atom values before children render, and delays updates for
* existing Atom values until after commit so React transitions do not update
* the current UI too early.
*
* @since 4.0.0
*/
"use client"
import * as Hydration from "effect/unstable/reactivity/Hydration"
import * as React from "react"
import { RegistryContext } from "./RegistryContext.ts"
/**
* Props for a boundary that applies dehydrated Atom values to the nearest
* {@link RegistryContext} while rendering its children.
*
* @category components
* @since 4.0.0
*/
export interface HydrationBoundaryProps {
state?: Iterable<Hydration.DehydratedAtom>
children?: React.ReactNode
}
/**
* Provides a React hydration boundary that loads dehydrated Atom values into
* the current Atom registry.
*
* **When to use**
*
* Use to apply dehydrated Atom state to a React subtree that reads from the
* nearest `RegistryContext`.
*
* **Details**
*
* New Atom values are hydrated during render so descendants can read them
* immediately, while values for existing Atoms are deferred until after commit
* so transition data does not update the current UI before React accepts it.
*
* @see {@link Hydration.dehydrate} for producing dehydrated Atom state
* @see {@link Hydration.hydrate} for lower-level non-React hydration
*
* @category components
* @since 4.0.0
*/
export const HydrationBoundary: React.FC<HydrationBoundaryProps> = ({
children,
state
}) => {
const registry = React.useContext(RegistryContext)
// This useMemo is for performance reasons only, everything inside it must
// be safe to run in every render and code here should be read as "in render".
//
// This code needs to happen during the render phase, because after initial
// SSR, hydration needs to happen _before_ children render. Also, if hydrating
// during a transition, we want to hydrate as much as is safe in render so
// we can prerender as much as possible.
//
// For any Atom values that already exist in the registry, we want to hold back on
// hydrating until _after_ the render phase. The reason for this is that during
// transitions, we don't want the existing Atom values and subscribers to update to
// the new data on the current page, only _after_ the transition is committed.
// If the transition is aborted, we will have hydrated any _new_ Atom values, but
// we throw away the fresh data for any existing ones to avoid unexpectedly
// updating the UI.
const hydrationQueue: Array<Hydration.DehydratedAtomValue> | undefined = React.useMemo(() => {
if (state) {
const dehydratedAtoms = Array.from(state) as Array<Hydration.DehydratedAtomValue>
const nodes = registry.getNodes()
const newDehydratedAtoms: Array<Hydration.DehydratedAtomValue> = []
const existingDehydratedAtoms: Array<Hydration.DehydratedAtomValue> = []
for (const dehydratedAtom of dehydratedAtoms) {
const existingNode = nodes.get(dehydratedAtom.key)
if (!existingNode) {
// This is a new Atom value, safe to hydrate immediately
newDehydratedAtoms.push(dehydratedAtom)
} else {
// This Atom value already exists, queue it for later hydration
existingDehydratedAtoms.push(dehydratedAtom)
}
}
if (newDehydratedAtoms.length > 0) {
// It's actually fine to call this with state that already exists
// in the registry, or is older. hydrate() is idempotent.
Hydration.hydrate(registry, newDehydratedAtoms)
}
if (existingDehydratedAtoms.length > 0) {
return existingDehydratedAtoms
}
}
return undefined
}, [registry, state])
React.useEffect(() => {
if (hydrationQueue) {
Hydration.hydrate(registry, hydrationQueue)
}
}, [registry, hydrationQueue])
return React.createElement(React.Fragment, {}, children)
}

View File

@@ -0,0 +1,108 @@
/**
* React context and provider for the Atom registry used by Effect Atom hooks.
* The registry stores atom values, schedules update work, and cleans up unused
* atoms. Sharing one registry through React context lets components in the same
* subtree read and write the same atom state.
*
* @since 4.0.0
*/
"use client"
import type * as Atom from "effect/unstable/reactivity/Atom"
import * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry"
import * as React from "react"
import * as Scheduler from "scheduler"
/**
* Schedules Atom registry work with React's scheduler at low priority and
* returns a cancellation function for the scheduled task.
*
* @category context
* @since 4.0.0
*/
export function scheduleTask(f: () => void): () => void {
const node = Scheduler.unstable_scheduleCallback(Scheduler.unstable_LowPriority, f)
return () => Scheduler.unstable_cancelCallback(node)
}
/**
* Provides a React context that supplies the `AtomRegistry` used by Atom hooks and
* hydration helpers, defaulting to a standalone registry when no provider is
* present.
*
* **When to use**
*
* Use to supply an existing `AtomRegistry` through React context when hooks or
* hydration helpers need to share registry state that is managed outside
* `RegistryProvider`.
*
* @see {@link RegistryProvider} for creating and providing a registry for a React subtree
*
* @category context
* @since 4.0.0
*/
export const RegistryContext = React.createContext<AtomRegistry.AtomRegistry>(AtomRegistry.make({
scheduleTask,
defaultIdleTTL: 400
}))
/**
* Provides a stable `AtomRegistry` to a React subtree, optionally seeding
* initial atom values and overriding registry scheduling or idle settings.
*
* **When to use**
*
* Use to scope atom state, scheduling, and idle cleanup to a React subtree.
*
* **Details**
*
* The provider creates one `AtomRegistry` with `AtomRegistry.make`, passes it
* through `RegistryContext.Provider`, and forwards `initialValues`,
* `scheduleTask`, `timeoutResolution`, and `defaultIdleTTL` only when that
* registry is created.
*
* **Gotchas**
*
* Option changes after the first render do not rebuild the registry. When the
* provider unmounts, registry disposal is delayed briefly and canceled if the
* provider remounts before the timeout fires.
*
* @see {@link RegistryContext} for the React context supplied by this provider
*
* @category context
* @since 4.0.0
*/
export const RegistryProvider = (options: {
readonly children?: React.ReactNode | undefined
readonly initialValues?: Iterable<readonly [Atom.Atom<any>, any]> | undefined
readonly scheduleTask?: ((f: () => void) => () => void) | undefined
readonly timeoutResolution?: number | undefined
readonly defaultIdleTTL?: number | undefined
}) => {
const ref = React.useRef<{
readonly registry: AtomRegistry.AtomRegistry
timeout?: number | undefined
}>(null)
if (ref.current === null) {
ref.current = {
registry: AtomRegistry.make({
scheduleTask: options.scheduleTask ?? scheduleTask,
initialValues: options.initialValues,
timeoutResolution: options.timeoutResolution,
defaultIdleTTL: options.defaultIdleTTL
})
}
}
React.useEffect(() => {
if (ref.current?.timeout !== undefined) {
clearTimeout(ref.current.timeout)
}
return () => {
ref.current!.timeout = setTimeout(() => {
ref.current?.registry.dispose()
ref.current = null
}, 500) as any
}
}, [ref])
return React.createElement(RegistryContext.Provider, { value: ref.current.registry }, options?.children)
}

View File

@@ -0,0 +1,151 @@
/**
* React helpers for creating Atom instances that belong to one component
* subtree. `make` returns a scoped atom with a provider, context, and `use`
* accessor. Each provider creates its own Atom once, so different subtrees can
* use the same scoped atom definition without sharing state.
*
* @since 4.0.0
*/
"use client"
import type * as Atom from "effect/unstable/reactivity/Atom"
import * as React from "react"
/**
* Literal type used as the `ScopedAtom` type identifier.
*
* **Details**
*
* Used as the computed property key and marker value stored on `ScopedAtom`
* objects.
*
* @category type IDs
* @since 4.0.0
*/
export type TypeId = "~@effect/atom-react/ScopedAtom"
/**
* Type identifier for ScopedAtom.
*
* **Details**
*
* Used as the computed property key and marker value stored on `ScopedAtom`
* objects.
*
* @category type IDs
* @since 4.0.0
*/
export const TypeId: TypeId = "~@effect/atom-react/ScopedAtom"
/**
* Scoped Atom interface with a provider-backed instance.
*
* **Example** (Providing and reading a scoped atom)
*
* ```ts
* import { make, useAtomValue } from "@effect/atom-react"
* import { Atom } from "effect/unstable/reactivity"
* import * as React from "react"
*
* const Counter = make(() => Atom.make(0))
*
* function View() {
* const atom = Counter.use()
* const value = useAtomValue(atom)
* return React.createElement("div", null, value)
* }
*
* export function App() {
* return React.createElement(Counter.Provider, null, React.createElement(View))
* }
* ```
*
* @category models
* @since 4.0.0
*/
export interface ScopedAtom<A extends Atom.Atom<any>, Input = never> {
readonly [TypeId]: TypeId
use(): A
Provider: [Input] extends [never] ? React.FC<{ readonly children?: React.ReactNode | undefined }>
: React.FC<{ readonly children?: React.ReactNode | undefined; readonly value: Input }>
Context: React.Context<A>
}
/**
* Creates a ScopedAtom from a factory function.
*
* **When to use**
*
* Use to create an atom instance that is owned by a React provider and scoped
* to a component subtree.
*
* **Details**
*
* The returned scoped atom includes a `Provider`, `Context`, and `use`
* accessor. The provider creates the atom once for its lifetime, passing the
* `value` prop to the factory when the scoped atom expects input.
*
* **Gotchas**
*
* `use` must run under the matching provider. Changing the provider `value`
* prop after mount does not recreate the atom.
*
* **Example** (Creating a scoped atom with input)
*
* ```ts
* import { make, useAtomValue } from "@effect/atom-react"
* import { Atom } from "effect/unstable/reactivity"
* import * as React from "react"
*
* const User = make((name: string) => Atom.make(name))
*
* function UserName() {
* const atom = User.use()
* const value = useAtomValue(atom)
* return React.createElement("span", null, value)
* }
*
* export function App() {
* return React.createElement(
* User.Provider,
* { value: "Ada" },
* React.createElement(UserName)
* )
* }
* ```
*
* @category constructors
* @since 4.0.0
*/
export const make = <A extends Atom.Atom<any>, Input = never>(
f: (() => A) | ((input: Input) => A)
): ScopedAtom<A, Input> => {
const Context = React.createContext<A>(undefined as unknown as A)
const use = (): A => {
const atom = React.useContext(Context)
if (atom === undefined) {
throw new Error("ScopedAtom used outside of its Provider")
}
return atom
}
const Provider: React.FC<{ readonly children?: React.ReactNode | undefined; readonly value?: Input }> = (props) => {
const atom = React.useRef<A | null>(null)
if (atom.current === null) {
if ("value" in props) {
atom.current = (f as (input: Input) => A)(props.value as Input)
} else {
atom.current = (f as () => A)()
}
}
return React.createElement(Context.Provider, { value: atom.current }, props.children)
}
return {
[TypeId]: TypeId,
use,
Provider: Provider as any,
Context
}
}

View File

@@ -0,0 +1,23 @@
/**
* @since 4.0.0
*/
/**
* @since 4.0.0
*/
export * from "./Hooks.ts"
/**
* @since 4.0.0
*/
export * from "./RegistryContext.ts"
/**
* @since 4.0.0
*/
export * from "./ReactHydration.ts"
/**
* @since 4.0.0
*/
export * from "./ScopedAtom.ts"

View File

@@ -0,0 +1,650 @@
// <reference types="@testing-library/jest-dom" />
import { act, render, screen, waitFor } from "@testing-library/react"
import { Cause, Context, Effect, Latch, Layer } from "effect"
import * as Schema from "effect/Schema"
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
import * as Atom from "effect/unstable/reactivity/Atom"
import * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry"
import * as Hydration from "effect/unstable/reactivity/Hydration"
import * as React from "react"
import { Suspense } from "react"
import { renderToString } from "react-dom/server"
import { ErrorBoundary } from "react-error-boundary"
import { beforeEach, describe, expect, it, test, vi } from "vitest"
import { HydrationBoundary, RegistryContext, RegistryProvider, useAtomSuspense, useAtomValue } from "../src/index.ts"
import * as ScopedAtom from "../src/ScopedAtom.ts"
describe("atom-react", () => {
let registry: AtomRegistry.AtomRegistry
beforeEach(() => {
registry = AtomRegistry.make()
})
describe("runtime", () => {
test("can inject test layers", () => {
class TheNumber extends Context.Service<TheNumber>()("TheNumber", {
make: Effect.succeed({ n: 42 as number })
}) {
static readonly layer = Layer.effect(this, this.make)
}
const runtime = Atom.runtime(TheNumber.layer)
const numberAtom = runtime.atom(TheNumber.use((_) => Effect.succeed(_.n)))
function TestComponent() {
const value = useAtomValue(numberAtom, AsyncResult.getOrThrow)
return <div data-testid="value">{value}</div>
}
render(
<RegistryProvider
initialValues={[
Atom.initialValue(
runtime.layer,
Layer.succeed(TheNumber, { n: 69 })
)
]}
>
<TestComponent />
</RegistryProvider>
)
expect(screen.getByTestId("value")).toHaveTextContent("69")
})
})
describe("useAtomValue", () => {
test("should read value from simple Atom", () => {
const atom = Atom.make(42)
function TestComponent() {
const value = useAtomValue(atom)
return <div data-testid="value">{value}</div>
}
render(<TestComponent />)
expect(screen.getByTestId("value")).toHaveTextContent("42")
})
test("should read value with transform function", () => {
const atom = Atom.make(42)
function TestComponent() {
const value = useAtomValue(atom, (x) => x * 2)
return <div data-testid="value">{value}</div>
}
render(<TestComponent />)
expect(screen.getByTestId("value")).toHaveTextContent("84")
})
test("should update when Atom value changes", async () => {
const atom = Atom.make("initial")
function TestComponent() {
const value = useAtomValue(atom)
return <div data-testid="value">{value}</div>
}
render(
<RegistryContext.Provider value={registry}>
<TestComponent />
</RegistryContext.Provider>
)
expect(screen.getByTestId("value")).toHaveTextContent("initial")
act(() => {
registry.set(atom, "updated")
})
await waitFor(() => {
expect(screen.getByTestId("value")).toHaveTextContent("updated")
})
})
test("should work with computed Atom", () => {
const baseAtom = Atom.make(10)
const computedAtom = Atom.make((get) => get(baseAtom) * 2)
function TestComponent() {
const value = useAtomValue(computedAtom)
return <div data-testid="value">{value}</div>
}
render(<TestComponent />)
expect(screen.getByTestId("value")).toHaveTextContent("20")
})
test("suspense success", () => {
const atom = Atom.make(Effect.never)
function TestComponent() {
const value = useAtomSuspense(atom).value
return <div data-testid="value">{value}</div>
}
render(
<Suspense fallback={<div data-testid="loading">Loading...</div>}>
<TestComponent />
</Suspense>
)
expect(screen.getByTestId("loading")).toBeInTheDocument()
})
})
describe("ScopedAtom", () => {
test("throws when used outside Provider", () => {
const counter = ScopedAtom.make(() => Atom.make(0))
function TestComponent() {
counter.use()
return <div>ok</div>
}
expect(() => render(<TestComponent />)).toThrow("ScopedAtom used outside of its Provider")
})
test("scopes atom instances per Provider", async () => {
const counter = ScopedAtom.make(() => Atom.make(0))
function Count() {
const atom = counter.use()
const value = useAtomValue(atom)
return <div data-testid="value">{value}</div>
}
function SetTo({ value }: { readonly value: number }) {
const atom = counter.use()
const registry = React.useContext(RegistryContext)
React.useEffect(() => {
registry.set(atom, value)
}, [registry, atom, value])
return null
}
render(
<div>
<counter.Provider>
<SetTo value={1} />
<Count />
</counter.Provider>
<counter.Provider>
<SetTo value={2} />
<Count />
</counter.Provider>
</div>
)
await waitFor(() => {
const values = screen.getAllByTestId("value")
expect(values[0]).toHaveTextContent("1")
expect(values[1]).toHaveTextContent("2")
})
})
test("input factory uses provider value once", () => {
const makeAtom = vi.fn((value: number) => Atom.make(value))
const scoped = ScopedAtom.make(makeAtom)
function Count() {
const atom = scoped.use()
const value = useAtomValue(atom)
return <div data-testid="value">{value}</div>
}
const { rerender } = render(
<scoped.Provider value={10}>
<Count />
</scoped.Provider>
)
expect(screen.getByTestId("value")).toHaveTextContent("10")
expect(makeAtom).toHaveBeenCalledTimes(1)
expect(makeAtom).toHaveBeenCalledWith(10)
rerender(
<scoped.Provider value={99}>
<Count />
</scoped.Provider>
)
expect(screen.getByTestId("value")).toHaveTextContent("10")
expect(makeAtom).toHaveBeenCalledTimes(1)
})
test("integrates with useAtomValue", async () => {
const scoped = ScopedAtom.make(() => Atom.make(0))
function Counter() {
const atom = scoped.use()
const value = useAtomValue(atom)
return <div data-testid="value">{value}</div>
}
function IncrementOnce() {
const atom = scoped.use()
const registry = React.useContext(RegistryContext)
React.useEffect(() => {
registry.set(atom, 1)
}, [registry, atom])
return null
}
render(
<scoped.Provider>
<IncrementOnce />
<Counter />
</scoped.Provider>
)
await waitFor(() => {
expect(screen.getByTestId("value")).toHaveTextContent("1")
})
})
})
test("suspense error", () => {
const atom = Atom.make(Effect.fail(new Error("test")))
function TestComponent() {
const value = useAtomSuspense(atom).value
return <div data-testid="value">{value}</div>
}
render(
<ErrorBoundary fallback={<div data-testid="error">Error</div>}>
<Suspense fallback={<div data-testid="loading">Loading...</div>}>
<TestComponent />
</Suspense>
</ErrorBoundary>,
{
onCaughtError: ((error: unknown) => {
if (error instanceof Error && error.message === "test") {
return
}
// eslint-disable-next-line no-console
console.error(error)
}) as unknown as undefined // todo: fix idk why the types are weird
}
)
expect(screen.getByTestId("error")).toBeInTheDocument()
})
describe("hydration", () => {
test("basic hydration with number atom and result atoms", () => {
const atomBasic = Atom.make(0).pipe(
Atom.serializable({
key: "basic",
schema: Schema.Number
})
)
const e: Effect.Effect<number, string> = Effect.never
const makeAtomResult = (key: string) =>
Atom.make(e).pipe(
Atom.serializable({
key,
schema: AsyncResult.Schema({
success: Schema.Number,
error: Schema.String
})
})
)
const atomResult1 = makeAtomResult("success")
const atomResult2 = makeAtomResult("errored")
const atomResult3 = makeAtomResult("pending")
// Use a server-side registry to generate properly encoded dehydrated state
const serverRegistry = AtomRegistry.make()
serverRegistry.mount(atomBasic)
serverRegistry.set(atomBasic, 1)
serverRegistry.mount(atomResult1)
;(serverRegistry.getNodes().get("success") as any).setValue(
AsyncResult.success(123)
)
serverRegistry.mount(atomResult2)
;(serverRegistry.getNodes().get("errored") as any).setValue(
AsyncResult.failure(Cause.fail("error"))
)
serverRegistry.mount(atomResult3)
// atomResult3 stays Initial (just mounted, effect is Effect.never)
const dehydratedState = Hydration.dehydrate(serverRegistry, {
encodeInitialAs: "value-only"
})
function Basic() {
const value = useAtomValue(atomBasic)
return <div data-testid="hydration-basic-value">{value}</div>
}
function Result1() {
const value = useAtomValue(atomResult1)
return AsyncResult.match(value, {
onSuccess: (result) => <div data-testid="value-1">{result.value}</div>,
onFailure: () => <div data-testid="error-1">Error</div>,
onInitial: () => <div data-testid="loading-1">Loading...</div>
})
}
function Result2() {
const value = useAtomValue(atomResult2)
return AsyncResult.match(value, {
onSuccess: (result) => <div data-testid="value-2">{result.value}</div>,
onFailure: () => <div data-testid="error-2">Error</div>,
onInitial: () => <div data-testid="loading-2">Loading...</div>
})
}
function Result3() {
const value = useAtomValue(atomResult3)
return AsyncResult.match(value, {
onSuccess: (result) => <div data-testid="value-3">{result.value}</div>,
onFailure: () => <div data-testid="error-3">Error</div>,
onInitial: () => <div data-testid="loading-3">Loading...</div>
})
}
render(
<RegistryContext.Provider value={AtomRegistry.make()}>
<HydrationBoundary state={dehydratedState}>
<Basic />
<Result1 />
<Result2 />
<Result3 />
</HydrationBoundary>
</RegistryContext.Provider>
)
expect(screen.getByTestId("hydration-basic-value")).toHaveTextContent("1")
expect(screen.getByTestId("value-1")).toHaveTextContent("123")
expect(screen.getByTestId("error-2")).toBeInTheDocument()
expect(screen.getByTestId("loading-3")).toBeInTheDocument()
})
test("hydration streaming with resultPromise", async () => {
const latch = Latch.makeUnsafe()
let start = 0
let stop = 0
const atom = Atom.make(
Effect.gen(function*() {
start = start + 1
yield* latch.await
stop = stop + 1
return 1
})
).pipe(
Atom.serializable({
key: "test",
schema: AsyncResult.Schema({
success: Schema.Number
})
})
)
registry.mount(atom)
expect(start).toBe(1)
expect(stop).toBe(0)
const dehydratedState = Hydration.dehydrate(registry, {
encodeInitialAs: "promise"
})
function TestComponent() {
const value = useAtomValue(atom)
return <div data-testid="value">{value._tag}</div>
}
render(
// provide a fresh registry each time to simulate hydration
<RegistryContext.Provider value={AtomRegistry.make()}>
<HydrationBoundary state={dehydratedState}>
<TestComponent />
</HydrationBoundary>
</RegistryContext.Provider>
)
expect(screen.getByTestId("value")).toHaveTextContent("Initial")
act(() => {
Effect.runSync(latch.open)
})
await Effect.runPromise(latch.await)
const result = registry.get(atom)
expect(result._tag).toBe("Success")
if (result._tag === "Success") {
expect(result.value).toBe(1)
}
expect(screen.getByTestId("value")).toHaveTextContent("Success")
expect(start).toBe(1)
expect(stop).toBe(1)
})
test("HydrationBoundary splits new vs existing atoms", () => {
const newAtom = Atom.make(0).pipe(
Atom.serializable({ key: "new-atom", schema: Schema.Number })
)
// Use a server registry to generate dehydrated state
const serverRegistry = AtomRegistry.make()
serverRegistry.mount(newAtom)
serverRegistry.set(newAtom, 99)
const dehydratedState = Hydration.dehydrate(serverRegistry)
function NewValue() {
const value = useAtomValue(newAtom)
return <div data-testid="new">{value}</div>
}
// Render with a fresh client registry (no pre-existing atoms)
render(
<RegistryContext.Provider value={AtomRegistry.make()}>
<HydrationBoundary state={dehydratedState}>
<NewValue />
</HydrationBoundary>
</RegistryContext.Provider>
)
// New atom should be hydrated immediately during render
expect(screen.getByTestId("new")).toHaveTextContent("99")
})
test("dehydrate with encodeInitialAs ignore (default)", () => {
const atom = Atom.make(Effect.never as Effect.Effect<number>).pipe(
Atom.serializable({
key: "initial-atom",
schema: AsyncResult.Schema({ success: Schema.Number })
})
)
registry.mount(atom)
// Default behavior: Initial values should be ignored
const state = Hydration.dehydrate(registry)
const values = Hydration.toValues(state)
expect(values.length).toBe(0)
})
test("dehydrate with encodeInitialAs value-only", () => {
const atom = Atom.make(Effect.never as Effect.Effect<number>).pipe(
Atom.serializable({
key: "initial-atom",
schema: AsyncResult.Schema({ success: Schema.Number })
})
)
registry.mount(atom)
// value-only: should encode the Initial value without a resultPromise
const state = Hydration.dehydrate(registry, {
encodeInitialAs: "value-only"
})
const values = Hydration.toValues(state)
expect(values.length).toBe(1)
expect(values[0].key).toBe("initial-atom")
expect(values[0].resultPromise).toBeUndefined()
})
test("serializable encode/decode survives JSON roundtrip (wire transfer)", () => {
const atom = Atom.make(0 as never).pipe(
Atom.serializable({
key: "wire-test",
schema: AsyncResult.Schema({
success: Schema.Struct({ name: Schema.String }),
error: Schema.String
})
})
)
const original = AsyncResult.success({ name: "hello" })
// Encode using the atom's serializable encode
const encoded = atom[Atom.SerializableTypeId].encode(original)
// Simulate wire transfer (seroval / JSON serialization roundtrip)
const wireTransferred = JSON.parse(JSON.stringify(encoded))
// Decode after wire transfer — this was the bug: decode would fail
// because the encoded value lost its AsyncResult prototype
const decoded = atom[Atom.SerializableTypeId].decode(wireTransferred)
expect(AsyncResult.isAsyncResult(decoded)).toBe(true)
expect(decoded._tag).toBe("Success")
if (AsyncResult.isSuccess(decoded)) {
expect(decoded.value).toEqual({ name: "hello" })
}
})
test("dehydrate + JSON roundtrip + hydrate works (SSR simulation)", () => {
const atom = Atom.make(Effect.never as Effect.Effect<number>).pipe(
Atom.serializable({
key: "ssr-wire",
schema: AsyncResult.Schema({ success: Schema.Number })
})
)
// Server: dehydrate
const serverRegistry = AtomRegistry.make()
serverRegistry.mount(atom)
;(serverRegistry.getNodes().get("ssr-wire") as any).setValue(
AsyncResult.success(42)
)
const dehydratedState = Hydration.dehydrate(serverRegistry)
// Simulate wire transfer (seroval / JSON)
const wireTransferred = JSON.parse(JSON.stringify(dehydratedState))
// Client: hydrate from wire-transferred state
function TestComponent() {
const value = useAtomValue(atom)
return (
<div data-testid="ssr-wire-value">
{AsyncResult.isSuccess(value) ? value.value : "not-success"}
</div>
)
}
render(
<RegistryContext.Provider value={AtomRegistry.make()}>
<HydrationBoundary state={wireTransferred}>
<TestComponent />
</HydrationBoundary>
</RegistryContext.Provider>
)
expect(screen.getByTestId("ssr-wire-value")).toHaveTextContent("42")
})
test("empty state is a no-op", () => {
function TestComponent() {
return <div data-testid="hydration-empty-state">OK</div>
}
render(
<HydrationBoundary state={[]}>
<TestComponent />
</HydrationBoundary>
)
expect(screen.getByTestId("hydration-empty-state")).toHaveTextContent("OK")
})
test("hydrate with no state is a no-op", () => {
function TestComponent() {
return <div data-testid="hydration-no-state">OK</div>
}
render(
<HydrationBoundary>
<TestComponent />
</HydrationBoundary>
)
expect(screen.getByTestId("hydration-no-state")).toHaveTextContent("OK")
})
})
describe("SSR", () => {
it("should run atom's during SSR by default", () => {
const getCount = vi.fn(() => 0)
const counterAtom = Atom.make(getCount)
function TestComponent() {
const count = useAtomValue(counterAtom)
return <div>{count}</div>
}
function App() {
return <TestComponent />
}
const ssrHtml = renderToString(<App />)
expect(getCount).toHaveBeenCalled()
expect(ssrHtml).toContain("0")
render(<App />)
expect(getCount).toHaveBeenCalled()
expect(screen.getByText("0")).toBeInTheDocument()
})
})
it("should not execute Atom effects during SSR when using withServerSnapshot", () => {
const mockFetchData = vi.fn(() => 0)
const userDataAtom = Atom.make(Effect.sync(() => mockFetchData())).pipe(
Atom.withServerValueInitial
)
function TestComponent() {
const result = useAtomValue(userDataAtom)
return <div>{result._tag}</div>
}
function App() {
return <TestComponent />
}
const ssrHtml = renderToString(<App />)
expect(mockFetchData).not.toHaveBeenCalled()
expect(ssrHtml).toContain("Initial")
render(<App />)
expect(mockFetchData).toHaveBeenCalled()
expect(screen.getByText("Success")).toBeInTheDocument()
})
})

View File

@@ -0,0 +1,8 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "../../../tsconfig.base.json",
"include": ["src"],
"references": [
{ "path": "../../effect" }
]
}

View File

@@ -0,0 +1,9 @@
import { mergeConfig } from "vitest/config"
import shared from "../../../vitest.shared.ts"
export default mergeConfig(shared, {
test: {
environment: "jsdom",
setupFiles: ["./vitest.setup.ts"]
}
})

View File

@@ -0,0 +1,8 @@
// oxlint-disable-next-line no-unassigned-import
import "@testing-library/jest-dom/vitest"
import { cleanup } from "@testing-library/react"
import { afterEach } from "vitest"
afterEach(() => {
cleanup()
})

View File

@@ -0,0 +1,707 @@
# @effect/atom-solid
## 4.0.0-beta.99
### Patch Changes
- Updated dependencies [[`8ce4795`](https://github.com/Effect-TS/effect/commit/8ce4795ccbaebca4292757db568c005a992546a4), [`80b539f`](https://github.com/Effect-TS/effect/commit/80b539f8aba68f478c75c35c2b4140c4ffc4fada), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`e6e6dba`](https://github.com/Effect-TS/effect/commit/e6e6dba6e9d86e7c2ad27dcedf289db76a19697f), [`bfb203e`](https://github.com/Effect-TS/effect/commit/bfb203e95aa439f731acad37fc3a9a831a190f1c), [`2e9a34a`](https://github.com/Effect-TS/effect/commit/2e9a34ac2bece4f3a206160480c991e3841dc67a), [`55d4eb3`](https://github.com/Effect-TS/effect/commit/55d4eb34f2c64d54f6a25a305b5c5438ebd7934e), [`bddb010`](https://github.com/Effect-TS/effect/commit/bddb010eac3d4436cb094edbbee7460c5440c162), [`a328835`](https://github.com/Effect-TS/effect/commit/a328835e50d76bc96648a1c1550456e8c9f81210), [`5560d05`](https://github.com/Effect-TS/effect/commit/5560d05aa6abdd29466d9c3412cc5e648b0adbde), [`8f6e3ad`](https://github.com/Effect-TS/effect/commit/8f6e3adb185b16e8820b98c509b308086f7ff1af), [`46997fa`](https://github.com/Effect-TS/effect/commit/46997fa60401f5e3c93daa4b61f7df8e31caaab4), [`9e6e12d`](https://github.com/Effect-TS/effect/commit/9e6e12d75c118cd265496f2880490d1f33a5c8bf), [`3394b93`](https://github.com/Effect-TS/effect/commit/3394b93d97d6f24fc38670641d1490289ffca7f1), [`febeabc`](https://github.com/Effect-TS/effect/commit/febeabc3f7c31094da000a23edeaabfe2ab00a38), [`54161c9`](https://github.com/Effect-TS/effect/commit/54161c98f6f3569e0c31842f54e6a257f9421c4c), [`385f7a4`](https://github.com/Effect-TS/effect/commit/385f7a4ee4a7359928597ea56d151dbaf5eb5802), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`7543afe`](https://github.com/Effect-TS/effect/commit/7543afea6f4d97d1f1ad876224323838a48daadd), [`44b9cf3`](https://github.com/Effect-TS/effect/commit/44b9cf3d240d726997b4bbcd0ede48e074d3c456), [`7eea4d0`](https://github.com/Effect-TS/effect/commit/7eea4d0b73ec554915d7066a71f46326ce2ba45f), [`0a8aa6a`](https://github.com/Effect-TS/effect/commit/0a8aa6acb90a72b91c24d17133c950e4cacd8abd), [`c8d9fcf`](https://github.com/Effect-TS/effect/commit/c8d9fcf7b030f7c474effbab2764ce7aee1c7209), [`9ca7f9a`](https://github.com/Effect-TS/effect/commit/9ca7f9a69363e4485645966d5a93b8f9597c5206), [`e7aca89`](https://github.com/Effect-TS/effect/commit/e7aca894bb32fbb785b5830837e6061c415a6015), [`55d7560`](https://github.com/Effect-TS/effect/commit/55d75609b8acf8a1b54c1b1c7fbbb65ec741aa3e), [`f809189`](https://github.com/Effect-TS/effect/commit/f809189ddf6b6011ba43a9901baaa734e315da2a), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`0ebdbe7`](https://github.com/Effect-TS/effect/commit/0ebdbe74463dc84385956d0b1e8c2b79ebab5400), [`7517d09`](https://github.com/Effect-TS/effect/commit/7517d09f12a0b183a81bd425962c4e280a68b05d), [`212493b`](https://github.com/Effect-TS/effect/commit/212493b9a1eb98cd1ef6959c707a2e5784a5ae91), [`88a54cc`](https://github.com/Effect-TS/effect/commit/88a54cc341006e3ebcb13482c618f62a680ce199), [`80ea8cb`](https://github.com/Effect-TS/effect/commit/80ea8cb9222ca73f564c8267ab2f82966fea027a), [`8df19f4`](https://github.com/Effect-TS/effect/commit/8df19f4fe81d90cc33ace88b9a77e5534f82d604)]:
- effect@4.0.0-beta.99
## 4.0.0-beta.98
### Patch Changes
- Updated dependencies [[`989603b`](https://github.com/Effect-TS/effect-smol/commit/989603b60ab1197b64acf214208e0d370cd1f842), [`214c458`](https://github.com/Effect-TS/effect-smol/commit/214c458084bb6995d543cd37d1055f24be3d454e), [`a037273`](https://github.com/Effect-TS/effect-smol/commit/a0372736ac34796969b051bbba4717d7983f1ebe), [`97fdaa9`](https://github.com/Effect-TS/effect-smol/commit/97fdaa9c1f522c65e579365d314a07878e2b904f), [`b24d248`](https://github.com/Effect-TS/effect-smol/commit/b24d248c8df44222ce642087cde2bd859a2dc709), [`19c222c`](https://github.com/Effect-TS/effect-smol/commit/19c222cac2353a3d7b7733caecb00556fffe9a5c), [`eec85dd`](https://github.com/Effect-TS/effect-smol/commit/eec85ddba09ea326fd268ee33eeffd47e50d4671), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`8849052`](https://github.com/Effect-TS/effect-smol/commit/884905232d1e9a365e046d8dde27bf9c5707f57f), [`c15e16a`](https://github.com/Effect-TS/effect-smol/commit/c15e16ad130d1fbde25d912b7ac55995066cb35b), [`01d00a3`](https://github.com/Effect-TS/effect-smol/commit/01d00a3abfbf1f37996cdbe738ea5137c646cdd7), [`8bd4589`](https://github.com/Effect-TS/effect-smol/commit/8bd458975a1b3a8ed042eccf317b93d28ded91e7), [`0082f4f`](https://github.com/Effect-TS/effect-smol/commit/0082f4f74fb139fd578f87f0a790e845133983dc), [`6e08428`](https://github.com/Effect-TS/effect-smol/commit/6e08428d980501b856f846ad3f3f0e4ea46e7786), [`388dcf9`](https://github.com/Effect-TS/effect-smol/commit/388dcf953f65d317547f34d40e6443c5f264205f), [`2b7ce2b`](https://github.com/Effect-TS/effect-smol/commit/2b7ce2b513e7ec2a77822f1116dc6ffb6ba93f4e), [`87bea7e`](https://github.com/Effect-TS/effect-smol/commit/87bea7e16259246f3bcdf565446394751abca953), [`ce38dc3`](https://github.com/Effect-TS/effect-smol/commit/ce38dc33bda805a684432cca071f4dc3c6b9a1ba), [`a807cd1`](https://github.com/Effect-TS/effect-smol/commit/a807cd170341deca8a1cfb52c4222585f2431bb9), [`fd8a356`](https://github.com/Effect-TS/effect-smol/commit/fd8a356f06a8c9ce4e7e0a13fc4021c178ed31de), [`c2a5edc`](https://github.com/Effect-TS/effect-smol/commit/c2a5edc3abd31ad5bc123362bc1213e03e4095c3), [`5946da3`](https://github.com/Effect-TS/effect-smol/commit/5946da3804a1be5e752b05b96bd058cdba50a1bf), [`4ae0c5f`](https://github.com/Effect-TS/effect-smol/commit/4ae0c5ffcbe6c56ddfcb05c639112a079483539e), [`5b2a0bc`](https://github.com/Effect-TS/effect-smol/commit/5b2a0bceea3a28a33a58555210c90a415dc74a76), [`72ac585`](https://github.com/Effect-TS/effect-smol/commit/72ac585884befde6af9208da738699a93f1bae79), [`5e8c1b8`](https://github.com/Effect-TS/effect-smol/commit/5e8c1b82bfafa121311f987a49ab75395e3647a7), [`0f9c078`](https://github.com/Effect-TS/effect-smol/commit/0f9c07841b04183f485ee6e6458de73b290b09f5)]:
- effect@4.0.0-beta.98
## 4.0.0-beta.97
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.97
## 4.0.0-beta.96
### Patch Changes
- Updated dependencies [[`1503f45`](https://github.com/Effect-TS/effect-smol/commit/1503f45cb5bb2a74f4705252ec505a1f0ade7e62), [`57fe793`](https://github.com/Effect-TS/effect-smol/commit/57fe79316ffbc380b30626a168981fb26ae97459), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`0c2f78f`](https://github.com/Effect-TS/effect-smol/commit/0c2f78f695ec474e1ff5474da183577975e418f5), [`97f29df`](https://github.com/Effect-TS/effect-smol/commit/97f29df457f7ffd07cfb4b379315c12c086af805)]:
- effect@4.0.0-beta.96
## 4.0.0-beta.95
### Patch Changes
- Updated dependencies [[`a482442`](https://github.com/Effect-TS/effect-smol/commit/a482442abdeb490e9652b854ec3495e4aa7273e7), [`fbefa85`](https://github.com/Effect-TS/effect-smol/commit/fbefa850fab2f0a302c20614496aeaaa2a8b5590), [`0b4a32f`](https://github.com/Effect-TS/effect-smol/commit/0b4a32f4260f0d8500942a133001b0d349328102), [`18a49e1`](https://github.com/Effect-TS/effect-smol/commit/18a49e1786679456258002ff9397faf02f678c2d), [`266cb90`](https://github.com/Effect-TS/effect-smol/commit/266cb90bb2c17aabc40563c32db334f09ba3d74b), [`912f095`](https://github.com/Effect-TS/effect-smol/commit/912f095a34572bbd3cedf6edb27878443e3e4a95), [`a6718f9`](https://github.com/Effect-TS/effect-smol/commit/a6718f9e00a15ca903b0732da46116cbf3d6aca7), [`bef5154`](https://github.com/Effect-TS/effect-smol/commit/bef51540a243aa2f872a00c01d0cd58b7a769baa), [`18e0564`](https://github.com/Effect-TS/effect-smol/commit/18e0564bd0f8ebbdfcaf1e2c21529948e9e4a81d), [`fb50f14`](https://github.com/Effect-TS/effect-smol/commit/fb50f14fc3657c1973785aa5b72ecf0b0d28e0b2)]:
- effect@4.0.0-beta.95
## 4.0.0-beta.94
### Patch Changes
- Updated dependencies [[`95a0e9b`](https://github.com/Effect-TS/effect-smol/commit/95a0e9bb62797af0e81c9998773405f248f218c5), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63), [`f11ce73`](https://github.com/Effect-TS/effect-smol/commit/f11ce73af60823754dc24194f4ffc561b9ea1c2d), [`ff30b6e`](https://github.com/Effect-TS/effect-smol/commit/ff30b6e7c2c63ffc56a4c5818d6d86b01b5ad528), [`1caab3c`](https://github.com/Effect-TS/effect-smol/commit/1caab3cc30f626efbf15e59d74f539a487e5c85c), [`aa80c47`](https://github.com/Effect-TS/effect-smol/commit/aa80c4775a04db87553e5568764cab7e32a72814), [`c2ae4fc`](https://github.com/Effect-TS/effect-smol/commit/c2ae4fce2f03a4cd1861c2b1179da7df656e662d), [`a0a3490`](https://github.com/Effect-TS/effect-smol/commit/a0a3490bbce765f199d8e077aceac504f0462e63)]:
- effect@4.0.0-beta.94
## 4.0.0-beta.93
### Patch Changes
- Updated dependencies [[`00652fe`](https://github.com/Effect-TS/effect-smol/commit/00652fe95c18f87208e91343eb8bf218faa2f677), [`6c58167`](https://github.com/Effect-TS/effect-smol/commit/6c5816746eaf91d2a3c7c899c5720809fa230ae3), [`2bc5415`](https://github.com/Effect-TS/effect-smol/commit/2bc541501a7ef89e542d7cb98e96beb53cd205cc), [`e11cccc`](https://github.com/Effect-TS/effect-smol/commit/e11cccc7d5fe631abccc7d6e3bd296938de0fa2e), [`ba7e77e`](https://github.com/Effect-TS/effect-smol/commit/ba7e77e046b8641a3a4e9750bb88ca4a1d063d3f), [`5713ee7`](https://github.com/Effect-TS/effect-smol/commit/5713ee7edbc3054efde407b2286bbfd45bbc6e1c)]:
- effect@4.0.0-beta.93
## 4.0.0-beta.92
### Patch Changes
- Updated dependencies [[`affdc13`](https://github.com/Effect-TS/effect-smol/commit/affdc139045cc325dce321a84a580fdc1b2da7b9)]:
- effect@4.0.0-beta.92
## 4.0.0-beta.91
### Patch Changes
- Updated dependencies [[`b135b25`](https://github.com/Effect-TS/effect-smol/commit/b135b2517fca9e7839734ace3699a7dfa75b9075), [`aaa21a3`](https://github.com/Effect-TS/effect-smol/commit/aaa21a369a171c600db294f2a4f640583043e150), [`3475ee6`](https://github.com/Effect-TS/effect-smol/commit/3475ee6c2bda6b05c6d7a12ce30c8bb840b5b1a6)]:
- effect@4.0.0-beta.91
## 4.0.0-beta.90
### Patch Changes
- Updated dependencies [[`d237fdf`](https://github.com/Effect-TS/effect-smol/commit/d237fdf726481f76eb52a6196e111b24122bc3d5)]:
- effect@4.0.0-beta.90
## 4.0.0-beta.89
### Patch Changes
- Updated dependencies [[`b7d46ab`](https://github.com/Effect-TS/effect-smol/commit/b7d46ab7e1a29d8711817bab583c9febf48a0dad), [`7777e15`](https://github.com/Effect-TS/effect-smol/commit/7777e1540fd3680dd8346723cffec812b9384669), [`5376197`](https://github.com/Effect-TS/effect-smol/commit/5376197ca8e50358a41b1fd3cec27bd1ec680ec6)]:
- effect@4.0.0-beta.89
## 4.0.0-beta.88
### Patch Changes
- Updated dependencies [[`911f1b8`](https://github.com/Effect-TS/effect-smol/commit/911f1b84790ce42b3a70c95b33e6f6fd9e74de8b), [`8beeeea`](https://github.com/Effect-TS/effect-smol/commit/8beeeea52879d8613a39468848f01c3092bd54d4), [`c306fcf`](https://github.com/Effect-TS/effect-smol/commit/c306fcfeb1ef38455156932a1faf49292b1318da)]:
- effect@4.0.0-beta.88
## 4.0.0-beta.87
### Patch Changes
- Updated dependencies [[`5a0c1a4`](https://github.com/Effect-TS/effect-smol/commit/5a0c1a4faee5707b5cc35e646ff1ffdad70f1956), [`1eea2ea`](https://github.com/Effect-TS/effect-smol/commit/1eea2ea3795ba47316b82b1ac8d4612c0ba389ed)]:
- effect@4.0.0-beta.87
## 4.0.0-beta.86
### Patch Changes
- Updated dependencies [[`0b5795a`](https://github.com/Effect-TS/effect-smol/commit/0b5795a0ab4395e8f15955d8d96f2303084bfc64), [`3e3a859`](https://github.com/Effect-TS/effect-smol/commit/3e3a859ec6351a9e0d31674aabbd48fcefabb12e), [`7dbec24`](https://github.com/Effect-TS/effect-smol/commit/7dbec240dbf3bca599a20c486632abce694ef5ab), [`d8c00a1`](https://github.com/Effect-TS/effect-smol/commit/d8c00a171ac7141e8adc08c332d1162d9a9d56fc), [`85b6317`](https://github.com/Effect-TS/effect-smol/commit/85b631701e935866f2762bd595237aa718370cd9), [`6d0fda0`](https://github.com/Effect-TS/effect-smol/commit/6d0fda0d0cbdfffc523c89c57dfdb1608f84fb12), [`108a933`](https://github.com/Effect-TS/effect-smol/commit/108a9335ff8571928197e5847a09c28ac83d6f46), [`7e1f455`](https://github.com/Effect-TS/effect-smol/commit/7e1f455fab5005d769b939c91e519d450f802cf9), [`46b3e79`](https://github.com/Effect-TS/effect-smol/commit/46b3e79944cfdae7901eb148135c85b7eb39834e)]:
- effect@4.0.0-beta.86
## 4.0.0-beta.85
### Patch Changes
- Updated dependencies [[`328d97c`](https://github.com/Effect-TS/effect-smol/commit/328d97cc53c0dcb89077a5623e35b095eaa59a8c), [`8441836`](https://github.com/Effect-TS/effect-smol/commit/8441836e6dde70e8ae2126be9cefe9b45798b134), [`074e436`](https://github.com/Effect-TS/effect-smol/commit/074e4361091289104cb0ab6959dc3b0ea7794a6a), [`c1dfd60`](https://github.com/Effect-TS/effect-smol/commit/c1dfd60663eb13a58916f3712d877499943b628a), [`2ba316b`](https://github.com/Effect-TS/effect-smol/commit/2ba316bd15fcbf1c50626500d44a2c9b3bec19f5), [`7ce7344`](https://github.com/Effect-TS/effect-smol/commit/7ce7344c41056c79e2ee19ee6a9346c0f1d227c1)]:
- effect@4.0.0-beta.85
## 4.0.0-beta.84
### Patch Changes
- Updated dependencies [[`87f52ba`](https://github.com/Effect-TS/effect-smol/commit/87f52ba16c4370ffa3f84bf8e53038e1419c284e), [`b8ee07f`](https://github.com/Effect-TS/effect-smol/commit/b8ee07ffda8903b5ec2e45a786ddcba59f128fda), [`867c0d7`](https://github.com/Effect-TS/effect-smol/commit/867c0d70a09079b040260d45a1e92ff04dbfbf2f), [`b93bc6c`](https://github.com/Effect-TS/effect-smol/commit/b93bc6c9cb27b909a41d094c97c4f9d25bbc6d6b), [`57d387f`](https://github.com/Effect-TS/effect-smol/commit/57d387f92c30ab63e15e3e641f0a903b65886610), [`bacca41`](https://github.com/Effect-TS/effect-smol/commit/bacca4141c2400effae1eabfdb36c89a459cf246), [`0f8ac79`](https://github.com/Effect-TS/effect-smol/commit/0f8ac7959d29ed68c68ce25aabd6bf0cb7e63ecc), [`25b4482`](https://github.com/Effect-TS/effect-smol/commit/25b448270c01317703f25107e1480d4cd0246d9a), [`9cf3a25`](https://github.com/Effect-TS/effect-smol/commit/9cf3a25c66b0c44a52be9829870c44517ea52db2), [`8def767`](https://github.com/Effect-TS/effect-smol/commit/8def7674b1787f91035298cda4d122937e87ef72)]:
- effect@4.0.0-beta.84
## 4.0.0-beta.83
### Patch Changes
- Updated dependencies [[`1f2e8ce`](https://github.com/Effect-TS/effect-smol/commit/1f2e8ceef09e0a791c850ed2ade01f97089596f9)]:
- effect@4.0.0-beta.83
## 4.0.0-beta.82
### Patch Changes
- Updated dependencies [[`193690b`](https://github.com/Effect-TS/effect-smol/commit/193690b642ea802bbed40d663bd677251bbe9dc3)]:
- effect@4.0.0-beta.82
## 4.0.0-beta.81
### Patch Changes
- Updated dependencies [[`93cb4f8`](https://github.com/Effect-TS/effect-smol/commit/93cb4f8fbfb9e07cb9dc86ce6b155fd1f8167914), [`60341d9`](https://github.com/Effect-TS/effect-smol/commit/60341d9ca744d0473ce3fab621ca9bd225af3a39), [`1105ab5`](https://github.com/Effect-TS/effect-smol/commit/1105ab56cb724212f7ea7b431396ce82e8fd0484), [`4500fbf`](https://github.com/Effect-TS/effect-smol/commit/4500fbfe00763d8a72af6e5d6c5988e8bd4ade36)]:
- effect@4.0.0-beta.81
## 4.0.0-beta.80
### Patch Changes
- Updated dependencies [[`d944330`](https://github.com/Effect-TS/effect-smol/commit/d94433090ee03f426d43e13b883abae4494e55e6), [`f48659f`](https://github.com/Effect-TS/effect-smol/commit/f48659fdcc84930ebc1e5b45b540c0f973389182), [`7652aaa`](https://github.com/Effect-TS/effect-smol/commit/7652aaa3bdbc39f241fe58b54b9a43b713e22e12), [`98630b7`](https://github.com/Effect-TS/effect-smol/commit/98630b7c8f679c352ba6796636c85688fa009d8d), [`90ae23c`](https://github.com/Effect-TS/effect-smol/commit/90ae23cf07284da5e1bcd9dffa882e85df7e617b)]:
- effect@4.0.0-beta.80
## 4.0.0-beta.79
### Patch Changes
- Updated dependencies [[`b9704dc`](https://github.com/Effect-TS/effect-smol/commit/b9704dc9de9f1649ad502371014fe869b69a49a3), [`a207113`](https://github.com/Effect-TS/effect-smol/commit/a207113f66837bb54416926718a9a7d66774d079), [`5e9b9e2`](https://github.com/Effect-TS/effect-smol/commit/5e9b9e217b164ebfd4a002dd4380b3b1563200c3), [`7c128ae`](https://github.com/Effect-TS/effect-smol/commit/7c128aef458a1e2d224712e51c483c9badad1d44), [`0ada457`](https://github.com/Effect-TS/effect-smol/commit/0ada457c0513d8d908254ab77ebb7d29d2b523d6), [`d7cc5a2`](https://github.com/Effect-TS/effect-smol/commit/d7cc5a2bede3de10943aa0c6bdb4f26836a91efd), [`aad63be`](https://github.com/Effect-TS/effect-smol/commit/aad63becf65e0a6b076e94f8973be7bbe7fbd46f), [`09809f6`](https://github.com/Effect-TS/effect-smol/commit/09809f60f19ec98232f98b33e33e02ecb7e4fbd6), [`2fddda5`](https://github.com/Effect-TS/effect-smol/commit/2fddda5311929f46b61e503f0ade4fc749e8c77d), [`5f21768`](https://github.com/Effect-TS/effect-smol/commit/5f2176833399757c4500d8875b7f2fba0393de75), [`f27003e`](https://github.com/Effect-TS/effect-smol/commit/f27003e00524ff83f20dd9909f62b2f8795efe03)]:
- effect@4.0.0-beta.79
## 4.0.0-beta.78
### Patch Changes
- Updated dependencies [[`7836b8e`](https://github.com/Effect-TS/effect-smol/commit/7836b8eb8bb0f3e04cdf554ee070caccf74f00c1), [`35d49a3`](https://github.com/Effect-TS/effect-smol/commit/35d49a3a09bdba6b513de87ddcead9e61a1042ba), [`4093258`](https://github.com/Effect-TS/effect-smol/commit/40932580e65bafab5f23c5f14b520cb411d0b2cd)]:
- effect@4.0.0-beta.78
## 4.0.0-beta.77
### Patch Changes
- Updated dependencies [[`6e9a5ca`](https://github.com/Effect-TS/effect-smol/commit/6e9a5ca62a61156fd67b2518ad3ab14ac0d25f23), [`302f398`](https://github.com/Effect-TS/effect-smol/commit/302f3984ce206e35d86ddd99d3b72be144850a51)]:
- effect@4.0.0-beta.77
## 4.0.0-beta.76
### Patch Changes
- Updated dependencies [[`016108a`](https://github.com/Effect-TS/effect-smol/commit/016108a472af7048ddbbfd05f233e67529fafe12), [`95c03d2`](https://github.com/Effect-TS/effect-smol/commit/95c03d2c55930668c215b5a41c23cf7742fead84), [`07299a3`](https://github.com/Effect-TS/effect-smol/commit/07299a33c09fd52faa9810d30835a2622c752386)]:
- effect@4.0.0-beta.76
## 4.0.0-beta.75
### Patch Changes
- Updated dependencies [[`81b187c`](https://github.com/Effect-TS/effect-smol/commit/81b187c17a0d8817b58232826939154010ae49d7), [`ad4b535`](https://github.com/Effect-TS/effect-smol/commit/ad4b535e17f94ce35261829d5a3675f0a7808b4e), [`a29c2e7`](https://github.com/Effect-TS/effect-smol/commit/a29c2e7e3570920156702671d6f3367cd0195f6c), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`1fdd9ae`](https://github.com/Effect-TS/effect-smol/commit/1fdd9aeed92b6bb70987c862e7f6f66ead0339b3), [`ffea4ec`](https://github.com/Effect-TS/effect-smol/commit/ffea4ecf2925f6a4c9fd13079d47584cbf2bed00), [`4255c9b`](https://github.com/Effect-TS/effect-smol/commit/4255c9ba78bb98c7838fbe9dccdd8465e9da5427)]:
- effect@4.0.0-beta.75
## 4.0.0-beta.74
### Patch Changes
- Updated dependencies [[`b1fc6a4`](https://github.com/Effect-TS/effect-smol/commit/b1fc6a4b4d0ca7fa9fd162799ae17c86f2f7ee8e)]:
- effect@4.0.0-beta.74
## 4.0.0-beta.73
### Patch Changes
- Updated dependencies [[`361ca30`](https://github.com/Effect-TS/effect-smol/commit/361ca30eb6e134feece547d6e00f82be4cb23f75), [`b9598c6`](https://github.com/Effect-TS/effect-smol/commit/b9598c6a209e75bfdb87ee3b024ecd1e3923ff6e)]:
- effect@4.0.0-beta.73
## 4.0.0-beta.72
### Patch Changes
- Updated dependencies [[`73e67d1`](https://github.com/Effect-TS/effect-smol/commit/73e67d119a84d697773eaecb4865c6a71eb1a9cb), [`01d71ec`](https://github.com/Effect-TS/effect-smol/commit/01d71ec5a75f3c2747a8d3b1ad9701d1e27b7ce5), [`fcd707e`](https://github.com/Effect-TS/effect-smol/commit/fcd707e091a16e1b35343c901cc4052274e32239)]:
- effect@4.0.0-beta.72
## 4.0.0-beta.71
### Patch Changes
- Updated dependencies [[`d8ac76b`](https://github.com/Effect-TS/effect-smol/commit/d8ac76b5bad458c42cebe8a0c1b3843f955ac293), [`2c3c00a`](https://github.com/Effect-TS/effect-smol/commit/2c3c00af6faba7b7d422af26a7a2bbc35636d230), [`3751e7c`](https://github.com/Effect-TS/effect-smol/commit/3751e7cf353e7a54cd692c37401207d9afba1e63), [`fc5f25b`](https://github.com/Effect-TS/effect-smol/commit/fc5f25b03ada5fc2431987768a74d3d3e75ca485), [`7ccced4`](https://github.com/Effect-TS/effect-smol/commit/7ccced42867c14c013b01160b3d292f14c05bd04), [`a2e1fe5`](https://github.com/Effect-TS/effect-smol/commit/a2e1fe5835c98c8ee4393a091b1d11b75126e349), [`4a4a36b`](https://github.com/Effect-TS/effect-smol/commit/4a4a36b10e6e616cad07584a43908f6a7e07e618), [`d350292`](https://github.com/Effect-TS/effect-smol/commit/d3502922b4740fa9d745797cbc3775cb67839b6d), [`730afb6`](https://github.com/Effect-TS/effect-smol/commit/730afb66696adf9bd5a328cbca29df9c05968771), [`df1b008`](https://github.com/Effect-TS/effect-smol/commit/df1b008f370f414c2a67a7b8139ef747af8e5fba), [`6d469d5`](https://github.com/Effect-TS/effect-smol/commit/6d469d567a7c41d7e5343bdee21d45b07b0e8190)]:
- effect@4.0.0-beta.71
## 4.0.0-beta.70
### Patch Changes
- Updated dependencies [[`af7782d`](https://github.com/Effect-TS/effect-smol/commit/af7782d3008d08b043f3a3f261516001514b2b4e), [`7212d70`](https://github.com/Effect-TS/effect-smol/commit/7212d701a3eee7b3553ff502e2c066126e52e839)]:
- effect@4.0.0-beta.70
## 4.0.0-beta.69
### Patch Changes
- Updated dependencies [[`70ea04a`](https://github.com/Effect-TS/effect-smol/commit/70ea04aa96a2a7859d738d414e1f0e3ed081a27a), [`d0ea8b0`](https://github.com/Effect-TS/effect-smol/commit/d0ea8b03f7d73ae076c1db12666141e480d11178), [`a57674b`](https://github.com/Effect-TS/effect-smol/commit/a57674b64845e9e75a456cf907bfdcb858859118), [`59aa334`](https://github.com/Effect-TS/effect-smol/commit/59aa334fbd0a504dda3c36f6d2ef1be7449b4b8b), [`8f4208e`](https://github.com/Effect-TS/effect-smol/commit/8f4208ee83bc7bdaa6793b5429847b45aab72470)]:
- effect@4.0.0-beta.69
## 4.0.0-beta.68
### Patch Changes
- Updated dependencies [[`af8267f`](https://github.com/Effect-TS/effect-smol/commit/af8267f2f3588c3fb611e9286f6f933f29ce1217), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`0176eaf`](https://github.com/Effect-TS/effect-smol/commit/0176eaf3ecd7c1b99a10268f2af02d7e8ce161e5), [`f136bb7`](https://github.com/Effect-TS/effect-smol/commit/f136bb763048cbc6b17edd26496dba3e2415b9fa), [`6f38f07`](https://github.com/Effect-TS/effect-smol/commit/6f38f07d5941a211b251383aaab0f4f55e8a6557), [`aec9c40`](https://github.com/Effect-TS/effect-smol/commit/aec9c401a53db227f18bf5e0c84db7130ad862d6)]:
- effect@4.0.0-beta.68
## 4.0.0-beta.67
### Patch Changes
- Updated dependencies [[`a42ef66`](https://github.com/Effect-TS/effect-smol/commit/a42ef6632abbddfa820995ae310ccc84ae8d9b6f), [`35594f8`](https://github.com/Effect-TS/effect-smol/commit/35594f811cafe471acd490114b103a1f8392c8d8), [`8bddd62`](https://github.com/Effect-TS/effect-smol/commit/8bddd628cb623f9533d345082583ff51cead6836), [`4be4c8d`](https://github.com/Effect-TS/effect-smol/commit/4be4c8d60862aa963869ee2ed9ffa048ffac0527), [`0c9d3ab`](https://github.com/Effect-TS/effect-smol/commit/0c9d3ab43eb721a370ed8306260cbac218c27e87), [`b156acc`](https://github.com/Effect-TS/effect-smol/commit/b156accd2691b4a051f823affdece7c39923ce85), [`d16c034`](https://github.com/Effect-TS/effect-smol/commit/d16c03434ee3e6dcd3bfc82b65d99e881d89025b), [`b559d68`](https://github.com/Effect-TS/effect-smol/commit/b559d68845f848a10153395778f035682d399075), [`a3de5d9`](https://github.com/Effect-TS/effect-smol/commit/a3de5d9215e5cc4a62e2666efbd7c1bf595eb84f), [`7e6c12e`](https://github.com/Effect-TS/effect-smol/commit/7e6c12ec9b3a5945f6c26e272cc8f6390541ad3e), [`098167a`](https://github.com/Effect-TS/effect-smol/commit/098167a220fe07da6f14455818733ab1b269c9dd)]:
- effect@4.0.0-beta.67
## 4.0.0-beta.66
### Patch Changes
- Updated dependencies [[`ca2498e`](https://github.com/Effect-TS/effect-smol/commit/ca2498e702ac2d83fb7187707b7eb069bdb261a2), [`cd7d1fb`](https://github.com/Effect-TS/effect-smol/commit/cd7d1fba7e2e2c5ac3ad64e1be433440a5bda436), [`19a7033`](https://github.com/Effect-TS/effect-smol/commit/19a703367ec817cffc41d152da9b594827408e2b), [`33d26b4`](https://github.com/Effect-TS/effect-smol/commit/33d26b4210b2e974f146a71e7eed962f8ce00900), [`856766b`](https://github.com/Effect-TS/effect-smol/commit/856766b2c506aaed6d2df1d63bf3a5b1b062e1d4), [`079c7df`](https://github.com/Effect-TS/effect-smol/commit/079c7df82559bb9ce10a86dffb85d25e6ce07dc3)]:
- effect@4.0.0-beta.66
## 4.0.0-beta.65
### Patch Changes
- Updated dependencies [[`6f11454`](https://github.com/Effect-TS/effect-smol/commit/6f11454a9b6c3bd00f6b35fd7af14a2f2d63a0a2)]:
- effect@4.0.0-beta.65
## 4.0.0-beta.64
### Patch Changes
- Updated dependencies [[`7d4877a`](https://github.com/Effect-TS/effect-smol/commit/7d4877a1929cdb690280ea254326c04f2ec97ea5)]:
- effect@4.0.0-beta.64
## 4.0.0-beta.63
### Patch Changes
- Updated dependencies [[`7f927ff`](https://github.com/Effect-TS/effect-smol/commit/7f927ffb7a9801dcfc4096c29e369d13d65cd0ac), [`a696b3e`](https://github.com/Effect-TS/effect-smol/commit/a696b3e83a8504cdbe261a18c10a1cc0619ae102)]:
- effect@4.0.0-beta.63
## 4.0.0-beta.62
### Patch Changes
- Updated dependencies [[`4ab4b90`](https://github.com/Effect-TS/effect-smol/commit/4ab4b9007dc27a52ffabc6fcb37c96eeec795bf7)]:
- effect@4.0.0-beta.62
## 4.0.0-beta.61
### Patch Changes
- Updated dependencies [[`50790af`](https://github.com/Effect-TS/effect-smol/commit/50790af9b190c38d10fb0723837d49b66432638f), [`71f7c3d`](https://github.com/Effect-TS/effect-smol/commit/71f7c3df997deda92c84146d569696dab3bd645c), [`aae8797`](https://github.com/Effect-TS/effect-smol/commit/aae8797b9cb383be0c182dd58d03d787c354238b)]:
- effect@4.0.0-beta.61
## 4.0.0-beta.60
### Patch Changes
- Updated dependencies [[`f69d567`](https://github.com/Effect-TS/effect-smol/commit/f69d5675dcff9f4137295752baf066b7153fdc09), [`7909c95`](https://github.com/Effect-TS/effect-smol/commit/7909c954b8f6244a35a4b429f8dd0dff45dad620), [`bbb4dcc`](https://github.com/Effect-TS/effect-smol/commit/bbb4dcc6c406b83a416b4ad3541cc02037c420e4), [`7af2207`](https://github.com/Effect-TS/effect-smol/commit/7af2207901eabf3132c1b7010a69b3899c06fbbe), [`848b40a`](https://github.com/Effect-TS/effect-smol/commit/848b40a4bd4bf54a5098617d50c33c88eee8270a)]:
- effect@4.0.0-beta.60
## 4.0.0-beta.59
### Patch Changes
- Updated dependencies [[`56837ea`](https://github.com/Effect-TS/effect-smol/commit/56837ea2a338395b35550641374e9e589bd8b71d)]:
- effect@4.0.0-beta.59
## 4.0.0-beta.58
### Patch Changes
- Updated dependencies [[`11993d4`](https://github.com/Effect-TS/effect-smol/commit/11993d4934c66f5dc611b8bbf553f01d501ef8f7), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec), [`96c8b22`](https://github.com/Effect-TS/effect-smol/commit/96c8b22c2057ccddbf10ed269d7697f22119b3ec)]:
- effect@4.0.0-beta.58
## 4.0.0-beta.57
### Patch Changes
- Updated dependencies [[`a971f5c`](https://github.com/Effect-TS/effect-smol/commit/a971f5cbd92dfe4274420bf0966595eb35531060), [`8e110c5`](https://github.com/Effect-TS/effect-smol/commit/8e110c5f02a429ccc43a91df8678e402138c0851)]:
- effect@4.0.0-beta.57
## 4.0.0-beta.56
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.56
## 4.0.0-beta.55
### Patch Changes
- Updated dependencies [[`42cc744`](https://github.com/Effect-TS/effect-smol/commit/42cc744570968deb365fb46d47b53d3277050c93), [`04855ce`](https://github.com/Effect-TS/effect-smol/commit/04855ceeca4d40c55a5750dd9893b691f8ea741a)]:
- effect@4.0.0-beta.55
## 4.0.0-beta.54
### Patch Changes
- Updated dependencies [[`e4b74f9`](https://github.com/Effect-TS/effect-smol/commit/e4b74f9c01a0e9b6cd58416de4af3a26d51da7c8), [`4c72808`](https://github.com/Effect-TS/effect-smol/commit/4c728081851c66dacf889a816535671bc841ae96)]:
- effect@4.0.0-beta.54
## 4.0.0-beta.53
### Patch Changes
- Updated dependencies [[`0768509`](https://github.com/Effect-TS/effect-smol/commit/07685094e931af07d104165195826a535b55fa7e), [`476aede`](https://github.com/Effect-TS/effect-smol/commit/476aede69c6efa06b5781ca5eb3e3b128ca29141), [`4f79c54`](https://github.com/Effect-TS/effect-smol/commit/4f79c542e7b508c235ff485d862cc8b29a8260c5), [`4be6a7c`](https://github.com/Effect-TS/effect-smol/commit/4be6a7cf35dab2a01d652f56dd35f0358c5a7e88), [`88927eb`](https://github.com/Effect-TS/effect-smol/commit/88927ebb896162cdba103b36553280b58e0facac)]:
- effect@4.0.0-beta.53
## 4.0.0-beta.52
### Patch Changes
- Updated dependencies [[`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`cf3a311`](https://github.com/Effect-TS/effect-smol/commit/cf3a311d863a8abb818840c3b80f847e621c43c1), [`8e04bfc`](https://github.com/Effect-TS/effect-smol/commit/8e04bfc95554b74eac205d67a20388e056b21499), [`131fdd5`](https://github.com/Effect-TS/effect-smol/commit/131fdd5b1f26531e265fe1a08f002002f47c276e)]:
- effect@4.0.0-beta.52
## 4.0.0-beta.51
### Patch Changes
- Updated dependencies [[`778d2af`](https://github.com/Effect-TS/effect-smol/commit/778d2afe9b5154bc1f9abae46d93ea7e54c87344), [`4e24dcf`](https://github.com/Effect-TS/effect-smol/commit/4e24dcf75037f65eebc1eb68623bc7cbf9d5512a), [`4b1c015`](https://github.com/Effect-TS/effect-smol/commit/4b1c0150e9bdb5559ed32d250deb66e17b4240c7), [`454f8ad`](https://github.com/Effect-TS/effect-smol/commit/454f8adad822929c3ef60f8280d0987226b049fd), [`6754a0c`](https://github.com/Effect-TS/effect-smol/commit/6754a0cd18626b06805a079cc5265525a5eb7d27), [`90f7fd5`](https://github.com/Effect-TS/effect-smol/commit/90f7fd5243871b30980964135db4512b8119fa82), [`d7e1519`](https://github.com/Effect-TS/effect-smol/commit/d7e151974934201fd93fa4c8a1192ee9a5d965a0), [`72a8122`](https://github.com/Effect-TS/effect-smol/commit/72a81228e09782bae512f7d041bbfbc78bc668d0)]:
- effect@4.0.0-beta.51
## 4.0.0-beta.50
### Patch Changes
- Updated dependencies [[`07be594`](https://github.com/Effect-TS/effect-smol/commit/07be594825de60f8e1b2102d21dbb9b8fc63b414), [`ae02433`](https://github.com/Effect-TS/effect-smol/commit/ae02433103ce28f53a0c9bfb4a44e75773289b7b)]:
- effect@4.0.0-beta.50
## 4.0.0-beta.49
### Patch Changes
- Updated dependencies [[`7d87873`](https://github.com/Effect-TS/effect-smol/commit/7d8787340ff549370f6f2a88b612e9ebbfd6ba45), [`c2f6f90`](https://github.com/Effect-TS/effect-smol/commit/c2f6f901b200a6e515b4f02c93ce8005b7bbf1c5), [`216f13c`](https://github.com/Effect-TS/effect-smol/commit/216f13c1fce454a21b489bb915714a17e791a1ac)]:
- effect@4.0.0-beta.49
## 4.0.0-beta.48
### Patch Changes
- Updated dependencies [[`4da56ec`](https://github.com/Effect-TS/effect-smol/commit/4da56ecff129b2da40137ffede23a73cc4e532d8), [`a5e6f77`](https://github.com/Effect-TS/effect-smol/commit/a5e6f774bab195cf50ecdc818240765f69a3bf4a), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070), [`f1ba5b8`](https://github.com/Effect-TS/effect-smol/commit/f1ba5b8584d325a541156928cecf041b37fd5070)]:
- effect@4.0.0-beta.48
## 4.0.0-beta.47
### Patch Changes
- Updated dependencies [[`c584726`](https://github.com/Effect-TS/effect-smol/commit/c58472674e750e6938df955044eab88feda95e45), [`86a91a4`](https://github.com/Effect-TS/effect-smol/commit/86a91a4f0c59286dfa9393232d8020dea70ed4db), [`131caf9`](https://github.com/Effect-TS/effect-smol/commit/131caf9525151a0cb29803a8f1dffa0f4f479d12), [`c3615c8`](https://github.com/Effect-TS/effect-smol/commit/c3615c88379b9daf252df0db72c6ac5a20326406)]:
- effect@4.0.0-beta.47
## 4.0.0-beta.46
### Patch Changes
- Updated dependencies [[`3a30b9e`](https://github.com/Effect-TS/effect-smol/commit/3a30b9e2ec2bd8b8193e1aa139f6878a07e3f5ee)]:
- effect@4.0.0-beta.46
## 4.0.0-beta.45
### Patch Changes
- Updated dependencies [[`5c3af6d`](https://github.com/Effect-TS/effect-smol/commit/5c3af6d554f60be34f8fc21d598d9a298ae11beb)]:
- effect@4.0.0-beta.45
## 4.0.0-beta.44
### Patch Changes
- [#1938](https://github.com/Effect-TS/effect-smol/pull/1938) [`23bbaac`](https://github.com/Effect-TS/effect-smol/commit/23bbaace8fd22a76e5f57aea8b4899374c40194e) Thanks @tim-smart! - allow atoms to be computed in solid bindings
- Updated dependencies [[`e3f0621`](https://github.com/Effect-TS/effect-smol/commit/e3f0621454c3f5d11070d30619da27c9232cadc1), [`5b476ab`](https://github.com/Effect-TS/effect-smol/commit/5b476abc0bd7e9bb59135ea1bcad2e4936227ced), [`6b40e5a`](https://github.com/Effect-TS/effect-smol/commit/6b40e5a4a6bd2087c15a3d7374d25057fdedfa16), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`3b09fb3`](https://github.com/Effect-TS/effect-smol/commit/3b09fb31c40c2802b01f21c23bcdd1fe7fb0aa82), [`2370410`](https://github.com/Effect-TS/effect-smol/commit/237041062e5af4594d32db91597e34e70a632877), [`dabc272`](https://github.com/Effect-TS/effect-smol/commit/dabc272444a700eb629c07ba3e77671a841ca86e), [`08b63c3`](https://github.com/Effect-TS/effect-smol/commit/08b63c3df11bd35c9fd6090dbd166287fdc40664), [`dfff04c`](https://github.com/Effect-TS/effect-smol/commit/dfff04c4c2b1d352dfad83992a6dce1280c85cf9), [`9baed9e`](https://github.com/Effect-TS/effect-smol/commit/9baed9e17e84702e6e480fcef6f86404f9e24be9), [`7846792`](https://github.com/Effect-TS/effect-smol/commit/7846792adc7e1631d62d26d657bd7ba6139f369b), [`1556a24`](https://github.com/Effect-TS/effect-smol/commit/1556a247623636b7ebe438fb56d77f1a7bf957bb), [`7c11bc2`](https://github.com/Effect-TS/effect-smol/commit/7c11bc292ab8e46252fe8f7576fb685917bfb8b5), [`b5ea591`](https://github.com/Effect-TS/effect-smol/commit/b5ea5913ec1d45d0dd12a327b9dd966bda2f6d02), [`0853afa`](https://github.com/Effect-TS/effect-smol/commit/0853afaeb1633b2d7f8b66893bd01c3aa1ef2c22), [`ac845f3`](https://github.com/Effect-TS/effect-smol/commit/ac845f3ab40e0b8719576e7f9bc16ea2e0e02cd4), [`b80c462`](https://github.com/Effect-TS/effect-smol/commit/b80c46247480f47bb64fc480fab48a3f37bc8888), [`b3f535d`](https://github.com/Effect-TS/effect-smol/commit/b3f535d9a7ac13b5fb984c29f93561c57a081ff0), [`6fe2e93`](https://github.com/Effect-TS/effect-smol/commit/6fe2e93cc2f1b173ef89651d74b6a5d2626b3226), [`cda8004`](https://github.com/Effect-TS/effect-smol/commit/cda800451c1ffbdddfc08415aed7b2d91e0412ee), [`8335477`](https://github.com/Effect-TS/effect-smol/commit/8335477a8a936a24b5f3ee6203c1b268bd1bfc3c), [`8c836f9`](https://github.com/Effect-TS/effect-smol/commit/8c836f99ab1e896b9580a71d67773625baff2eaf), [`718ff6f`](https://github.com/Effect-TS/effect-smol/commit/718ff6fe3e3d3820cefd67d2bff1b2224fe08060), [`7eed84f`](https://github.com/Effect-TS/effect-smol/commit/7eed84fc33c5781a6fb11bf4fd189d424902ebd4), [`5df46fe`](https://github.com/Effect-TS/effect-smol/commit/5df46fe2f654d59ab5fc1578f4fc27fa40368ef9), [`82dd0f2`](https://github.com/Effect-TS/effect-smol/commit/82dd0f26c6442b07143762ef7bc33742d3978dd6), [`03ae41e`](https://github.com/Effect-TS/effect-smol/commit/03ae41e7304cffac9f18feea22b73468feafc43a), [`4677a0a`](https://github.com/Effect-TS/effect-smol/commit/4677a0a58f95eea38a211efcd3f345f237a9e44a), [`87e1fc8`](https://github.com/Effect-TS/effect-smol/commit/87e1fc8b67e4901d75f567b2fecc3841ab762cc4), [`c1af1b7`](https://github.com/Effect-TS/effect-smol/commit/c1af1b756f63291e9c0298cf95c98a6920a0c2a0), [`7bb5dce`](https://github.com/Effect-TS/effect-smol/commit/7bb5dce60e1d904ef049a0287dec2b2e6113c970), [`c8a877b`](https://github.com/Effect-TS/effect-smol/commit/c8a877b53e8f29616335719e5dd1c3992dddf780), [`7da961a`](https://github.com/Effect-TS/effect-smol/commit/7da961ae4916229d2246699a5d3b20e5b2dd2020)]:
- effect@4.0.0-beta.44
## 4.0.0-beta.43
### Patch Changes
- Updated dependencies [[`2ae33d0`](https://github.com/Effect-TS/effect-smol/commit/2ae33d050914915f7cb9c25ab0a020901e08d596), [`979811a`](https://github.com/Effect-TS/effect-smol/commit/979811a4c3f7ed21ed18ef560c49fb7f5569e80e), [`eb7dbef`](https://github.com/Effect-TS/effect-smol/commit/eb7dbeffa883386ad912815e62c0820cac1fdf8e), [`cf50eb4`](https://github.com/Effect-TS/effect-smol/commit/cf50eb49cb04706dae5185f624708117c413dee8), [`1d046fe`](https://github.com/Effect-TS/effect-smol/commit/1d046fe484560e23f3e22cb23eec6433f8f1fa02)]:
- effect@4.0.0-beta.43
## 4.0.0-beta.42
### Patch Changes
- Updated dependencies [[`924e216`](https://github.com/Effect-TS/effect-smol/commit/924e216caa7e0bbf22e994a0cd2ce8b1f0f0b3ee), [`80e7f0c`](https://github.com/Effect-TS/effect-smol/commit/80e7f0cd9116e811e97b0ce30a77a8d1ecd072aa), [`f8328bf`](https://github.com/Effect-TS/effect-smol/commit/f8328bf0314da3dc7f31d314f94a5840e8d5217f), [`66d1c06`](https://github.com/Effect-TS/effect-smol/commit/66d1c06039079129707a230f7ad8c676439d7133), [`bee800b`](https://github.com/Effect-TS/effect-smol/commit/bee800bf285192a01bec72a7b7b51bc1159434e6), [`8930441`](https://github.com/Effect-TS/effect-smol/commit/8930441dee6f94c59c583d18d3ebd677cf1f2623)]:
- effect@4.0.0-beta.42
## 4.0.0-beta.41
### Patch Changes
- Updated dependencies [[`36f5c21`](https://github.com/Effect-TS/effect-smol/commit/36f5c2174d31ab42c4598bf81f178f40d0802283), [`d8ce758`](https://github.com/Effect-TS/effect-smol/commit/d8ce758669d6297ae932ac3251d83e7b49b22f30), [`11aab4c`](https://github.com/Effect-TS/effect-smol/commit/11aab4c6d37d5691adafc2d33da1a631b28ce814), [`3bc1efb`](https://github.com/Effect-TS/effect-smol/commit/3bc1efb53dd75b4a40de46f1f80c7f8a7d50af86), [`70e724e`](https://github.com/Effect-TS/effect-smol/commit/70e724e604604d4be1061cd8da0d360494998c84), [`738dee7`](https://github.com/Effect-TS/effect-smol/commit/738dee7edfd70af82dc4d2376db3a8ebe603eb48), [`2111963`](https://github.com/Effect-TS/effect-smol/commit/2111963f19b4c28c800664a8fac9590c1321885f), [`198a553`](https://github.com/Effect-TS/effect-smol/commit/198a553d9ce45f6a00bfc4d65ed0640669602d95)]:
- effect@4.0.0-beta.41
## 4.0.0-beta.40
### Patch Changes
- Updated dependencies [[`f62860f`](https://github.com/Effect-TS/effect-smol/commit/f62860f0e5e45978fabf7256ae620a13152a772a), [`973f281`](https://github.com/Effect-TS/effect-smol/commit/973f2812529aadc1cc54598b2039799fa72b80f8)]:
- effect@4.0.0-beta.40
## 4.0.0-beta.39
### Patch Changes
- Updated dependencies [[`f91fd3d`](https://github.com/Effect-TS/effect-smol/commit/f91fd3db39fe5628439fd175fba201a65a1aa9d0), [`edaae9d`](https://github.com/Effect-TS/effect-smol/commit/edaae9d65f464f941d7eddd723cd33d324f4b071), [`b47db0b`](https://github.com/Effect-TS/effect-smol/commit/b47db0bd5802064b6a24b3ea27c6ff2e0520d513), [`82d3c8e`](https://github.com/Effect-TS/effect-smol/commit/82d3c8e4f3f49b00df611b25aa6f8f74ec21b59b), [`7c22b31`](https://github.com/Effect-TS/effect-smol/commit/7c22b315d198dcbf44ae8cdb8b37879e1c9e3996)]:
- effect@4.0.0-beta.39
## 4.0.0-beta.38
### Patch Changes
- Updated dependencies [[`f4dbe5b`](https://github.com/Effect-TS/effect-smol/commit/f4dbe5b26b9c2d33fae024bf44afbdf8541792cd), [`a71a607`](https://github.com/Effect-TS/effect-smol/commit/a71a607c89fb6669a12a562c2c23be81dfbe1adb), [`66a0494`](https://github.com/Effect-TS/effect-smol/commit/66a0494ed75cd12f2721dcbb1d8a072e3d9e14b6), [`5ef7218`](https://github.com/Effect-TS/effect-smol/commit/5ef7218fc559d57301fe929b8a0cab4033f4f1fd), [`472d260`](https://github.com/Effect-TS/effect-smol/commit/472d260655bc311fba5c2c6e23bb77d8f7e36ba0)]:
- effect@4.0.0-beta.38
## 4.0.0-beta.37
### Patch Changes
- Updated dependencies [[`f7a0b71`](https://github.com/Effect-TS/effect-smol/commit/f7a0b711da8fdd645597dee29cacc5619c6afcf2), [`1e223c3`](https://github.com/Effect-TS/effect-smol/commit/1e223c30ccf835dfbb21284535d78549efaeca80), [`53740f4`](https://github.com/Effect-TS/effect-smol/commit/53740f47aa76d114b7d535649fb50efc54a09608), [`8c7cf89`](https://github.com/Effect-TS/effect-smol/commit/8c7cf89f719e580cbce1bf6c24e6996f1992a0a6), [`b6b81a9`](https://github.com/Effect-TS/effect-smol/commit/b6b81a940eaafcbc792d25413d6c02c707de31b2), [`8f4c1f9`](https://github.com/Effect-TS/effect-smol/commit/8f4c1f97ed60f8810b0b327b50117ffb2d8260d4), [`f2479f9`](https://github.com/Effect-TS/effect-smol/commit/f2479f9d3113b1f012db17a3852b4e28f478cf9c), [`c919921`](https://github.com/Effect-TS/effect-smol/commit/c9199217fad65529421d2cf95ecfff41257090fd), [`7af90c2`](https://github.com/Effect-TS/effect-smol/commit/7af90c2e3c99038eafa39650433839523790e2fe), [`f3be185`](https://github.com/Effect-TS/effect-smol/commit/f3be18569e5ca57c25eabf00df3ca601ebab43c7)]:
- effect@4.0.0-beta.37
## 4.0.0-beta.36
### Patch Changes
- Updated dependencies [[`60fcbcc`](https://github.com/Effect-TS/effect-smol/commit/60fcbcc43d09471e8f7e0969955d99dcefc5be81), [`0a60837`](https://github.com/Effect-TS/effect-smol/commit/0a6083713124440e630030375bab367e8d7df24e), [`49164d2`](https://github.com/Effect-TS/effect-smol/commit/49164d2c20a8d21b66514992c4a15d8521f6b36e), [`334b6e4`](https://github.com/Effect-TS/effect-smol/commit/334b6e4f76fe11941b516d61f57e268bc31f0ca6), [`5700695`](https://github.com/Effect-TS/effect-smol/commit/5700695f76ae6da6b94c9c87d4dd2b8054fb829b), [`f8f4456`](https://github.com/Effect-TS/effect-smol/commit/f8f445644f3aa7ec093cab7445198a62ba18a480), [`969d24f`](https://github.com/Effect-TS/effect-smol/commit/969d24fdfa48c4838e811983848d9cb4e9b3b12c), [`851eda0`](https://github.com/Effect-TS/effect-smol/commit/851eda0533946e39bacaaf581896320d7a4f3e8c), [`8059c1c`](https://github.com/Effect-TS/effect-smol/commit/8059c1c3eba9a90af7cd889ea261bcb8fff0c185), [`6f83295`](https://github.com/Effect-TS/effect-smol/commit/6f8329546a73eaddc7cb5e85ea8e37e73fbfb611), [`65f7f57`](https://github.com/Effect-TS/effect-smol/commit/65f7f5737575fed668987462c96d29a446707c32), [`e7fabd2`](https://github.com/Effect-TS/effect-smol/commit/e7fabd2265db690eae5cfc9b83730c84699aef61), [`89c3e98`](https://github.com/Effect-TS/effect-smol/commit/89c3e985401eb38f33a3ae21a94ad27de3c1d28b), [`53794ab`](https://github.com/Effect-TS/effect-smol/commit/53794ab7af30aa5c5004ecf53659fafbe4b10542)]:
- effect@4.0.0-beta.36
## 4.0.0-beta.35
### Patch Changes
- Updated dependencies [[`9252b43`](https://github.com/Effect-TS/effect-smol/commit/9252b43560f507709c2985abcf52a7837b23ddf8), [`7daf387`](https://github.com/Effect-TS/effect-smol/commit/7daf3870a656882a488a60f67881e6808c8f4d04), [`e1664a3`](https://github.com/Effect-TS/effect-smol/commit/e1664a38bc31ef4ceb4e9324c7226e1e99bf9c07), [`fdaa6e0`](https://github.com/Effect-TS/effect-smol/commit/fdaa6e0a41b6b6605438fa8557441792135380a2), [`19aa47e`](https://github.com/Effect-TS/effect-smol/commit/19aa47ef7b470e427620edca8970dd9cdd551216), [`c667dad`](https://github.com/Effect-TS/effect-smol/commit/c667dad07777b860e4764a3ba9a6cc41c236cd98), [`764d150`](https://github.com/Effect-TS/effect-smol/commit/764d1501bc5026b60fc8aef6cb02a5a87c762801), [`3c27098`](https://github.com/Effect-TS/effect-smol/commit/3c27098b5685a63db2c2eff654a250c94d3fcfa7)]:
- effect@4.0.0-beta.35
## 4.0.0-beta.34
### Patch Changes
- Updated dependencies [[`f2f75ee`](https://github.com/Effect-TS/effect-smol/commit/f2f75ee564bce1cd95f5189c7bdeeed4f92dacb1), [`342fc4b`](https://github.com/Effect-TS/effect-smol/commit/342fc4b051739e32e7977159f26ff9541eda664f), [`5d704ee`](https://github.com/Effect-TS/effect-smol/commit/5d704ee10d20e8eb107e34bb8a21feb5aa4a7685), [`00add69`](https://github.com/Effect-TS/effect-smol/commit/00add69b59551e9df34772eb927638b093f6d71e), [`58217d3`](https://github.com/Effect-TS/effect-smol/commit/58217d318a7d716ccd707cce0f41573946939c28), [`f4e2aba`](https://github.com/Effect-TS/effect-smol/commit/f4e2aba01b76d1e3059b297e3cc942284dfeafb2), [`e3b44b6`](https://github.com/Effect-TS/effect-smol/commit/e3b44b6a2af9ee21dc5c1e928f0c20af857fa7a9), [`e1472b7`](https://github.com/Effect-TS/effect-smol/commit/e1472b7525c5d57a48bdec2353c3b742f7f916c0), [`7686320`](https://github.com/Effect-TS/effect-smol/commit/7686320cd123fa352b5c3d076fb18a3cac0a9bba)]:
- effect@4.0.0-beta.34
## 4.0.0-beta.33
### Patch Changes
- Updated dependencies [[`571447d`](https://github.com/Effect-TS/effect-smol/commit/571447da67334449f8ae3d6ecb3d77ea4e0c4295)]:
- effect@4.0.0-beta.33
## 4.0.0-beta.32
### Patch Changes
- Updated dependencies [[`bf8fff8`](https://github.com/Effect-TS/effect-smol/commit/bf8fff8a5f54b6df74cb7bbb42346fe9ba52435a), [`1af3ef3`](https://github.com/Effect-TS/effect-smol/commit/1af3ef3e3ca7fd417d0fc15f8ca8fe207eba4f74), [`27fea0f`](https://github.com/Effect-TS/effect-smol/commit/27fea0f66910de5905f40fd63f8ddbb6f7ac5aba), [`2ad6c1b`](https://github.com/Effect-TS/effect-smol/commit/2ad6c1b2c85a3a0fe351e3d56636a75eb76b4b4e), [`398ac3e`](https://github.com/Effect-TS/effect-smol/commit/398ac3e01cb75efce0e4e2913d1450cf65866732), [`51fe22f`](https://github.com/Effect-TS/effect-smol/commit/51fe22f3266e417b6c541aaed4b75d246fac91e7), [`4605db6`](https://github.com/Effect-TS/effect-smol/commit/4605db69cfacddbdbf1525865ddfde135158090c), [`f4de1b0`](https://github.com/Effect-TS/effect-smol/commit/f4de1b087c998d0bad1d9468f70b7d16c13b9f6f), [`60214f2`](https://github.com/Effect-TS/effect-smol/commit/60214f2080b2aeb091f691140eb20acb741691c3), [`c4b8b0f`](https://github.com/Effect-TS/effect-smol/commit/c4b8b0ffa8efb47c4cd7578a8943d6868509373f), [`6d9393a`](https://github.com/Effect-TS/effect-smol/commit/6d9393a0770a18722d23340e77f15455de341245), [`6de4efe`](https://github.com/Effect-TS/effect-smol/commit/6de4efe463c783614ceb0c094d77a336a899cbe0), [`4f969d1`](https://github.com/Effect-TS/effect-smol/commit/4f969d1563ba755ffa116c8ae409bb3436bd881d), [`6cc67c8`](https://github.com/Effect-TS/effect-smol/commit/6cc67c855e054ee3f3ac3485dca5f7805e79e8fb), [`8531a22`](https://github.com/Effect-TS/effect-smol/commit/8531a22ffbb52e11a030b09f358cafbfdf5edff7), [`b226760`](https://github.com/Effect-TS/effect-smol/commit/b22676067617f15c00722a3a63fd7c2c172c3d45), [`47a51ab`](https://github.com/Effect-TS/effect-smol/commit/47a51aba0ecdf3ef478bfa28a498bca188399bd4), [`1521d02`](https://github.com/Effect-TS/effect-smol/commit/1521d02e1f19f1d795edaaf862c1a1031d9c755e)]:
- effect@4.0.0-beta.32
## 4.0.0-beta.31
### Patch Changes
- Updated dependencies [[`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6f23f0e`](https://github.com/Effect-TS/effect-smol/commit/6f23f0ed4cba573cd9395c2e582f582fe7271544), [`654aaec`](https://github.com/Effect-TS/effect-smol/commit/654aaec593305521b65dd042c204d761cc6e8c28), [`2958a42`](https://github.com/Effect-TS/effect-smol/commit/2958a42078966a8713a98f00485ab36484d5eccf), [`95d27a2`](https://github.com/Effect-TS/effect-smol/commit/95d27a239ed5147302605ab0b3147a056541b0c7), [`0fbaea8`](https://github.com/Effect-TS/effect-smol/commit/0fbaea8f9555a8044cec31a770394db613fc78e2), [`21d5d5e`](https://github.com/Effect-TS/effect-smol/commit/21d5d5e0439fd4d9bb6e508377215b1087555d45), [`5a84853`](https://github.com/Effect-TS/effect-smol/commit/5a8485397b7f321ae021640c1999821143659462), [`6e49959`](https://github.com/Effect-TS/effect-smol/commit/6e499590357a104c81779b3176cd3f84e4f91064), [`8f5805d`](https://github.com/Effect-TS/effect-smol/commit/8f5805dbdd0d1bc0ff0727cc398c8d80e544edee), [`990df2c`](https://github.com/Effect-TS/effect-smol/commit/990df2c3ceeb32e659acc10cc9485617f7b3c423)]:
- effect@4.0.0-beta.31
## 4.0.0-beta.30
### Patch Changes
- Updated dependencies [[`c88e5b7`](https://github.com/Effect-TS/effect-smol/commit/c88e5b723ff09da4edaef6ce14d927ca01104a32), [`947d0e4`](https://github.com/Effect-TS/effect-smol/commit/947d0e4268ba5c4020ead380aa80812c7342408f), [`7517908`](https://github.com/Effect-TS/effect-smol/commit/75179085d159b88a1ab0bce70669d76dcf0d79a4), [`a49ecd5`](https://github.com/Effect-TS/effect-smol/commit/a49ecd5a183d7e7d33f47ff95e9d2dea5a12ead5), [`6993e33`](https://github.com/Effect-TS/effect-smol/commit/6993e3329122c834c20bacea72d8678232f4f103), [`514f2a2`](https://github.com/Effect-TS/effect-smol/commit/514f2a2ae54580fcacdbe2ea2196a83a852d0748), [`3214b47`](https://github.com/Effect-TS/effect-smol/commit/3214b47676de2d33fddc5fecfc2d226e6e83cc7b), [`95ec5ed`](https://github.com/Effect-TS/effect-smol/commit/95ec5ed345de77c893049e182d37a37cf164a268)]:
- effect@4.0.0-beta.30
## 4.0.0-beta.29
### Patch Changes
- Updated dependencies [[`9d93adb`](https://github.com/Effect-TS/effect-smol/commit/9d93adb1c1795d1978391b30d7d2972c88052662), [`b52721c`](https://github.com/Effect-TS/effect-smol/commit/b52721cf0d11a567722b060c8536e3bdd4161f07), [`a891c7b`](https://github.com/Effect-TS/effect-smol/commit/a891c7b12f415b2287613dd4b91a09dfd38ef30d), [`ef26cdf`](https://github.com/Effect-TS/effect-smol/commit/ef26cdfb65d9955fc7e161629191930c2cc2c63f), [`82fd3ed`](https://github.com/Effect-TS/effect-smol/commit/82fd3ed922063ee5a34f96f3993c15c7515e4f67)]:
- effect@4.0.0-beta.29
## 4.0.0-beta.28
### Patch Changes
- Updated dependencies [[`ff533f2`](https://github.com/Effect-TS/effect-smol/commit/ff533f203cd06302ad08032a27e01269b4a2d4c6), [`dc803ee`](https://github.com/Effect-TS/effect-smol/commit/dc803ee52ebd3e9f931118f0dfcb804542847556), [`d660b1c`](https://github.com/Effect-TS/effect-smol/commit/d660b1c99cb93d4f79715e91c7a4486801c0eefa), [`93a05e3`](https://github.com/Effect-TS/effect-smol/commit/93a05e3eaa624058b162aedd66aad70102837270), [`2a65cf6`](https://github.com/Effect-TS/effect-smol/commit/2a65cf6fd81ef63d944e6fb51f058d439bf4a834), [`a561a40`](https://github.com/Effect-TS/effect-smol/commit/a561a40cc41c548c2cf3153aca065ee92ee8aa57), [`29cd24d`](https://github.com/Effect-TS/effect-smol/commit/29cd24d1fe78480a72eeb38a90281ffddc0530bc), [`662a8e6`](https://github.com/Effect-TS/effect-smol/commit/662a8e6857dac64a7cd13bd8df4b0674654622f8), [`d2b52ba`](https://github.com/Effect-TS/effect-smol/commit/d2b52bae5b9336cf59729fbdcc4d7f09512b0cbf), [`407c3b4`](https://github.com/Effect-TS/effect-smol/commit/407c3b43a5d1414558e0e33b6f1fc0e6a6d489cc), [`42bc7ce`](https://github.com/Effect-TS/effect-smol/commit/42bc7ce5480f6f2953c39f8cb5c850d61df6f5a2), [`e741322`](https://github.com/Effect-TS/effect-smol/commit/e74132226cbfee24234311c7c1c13e6b7391384e), [`5c75fa8`](https://github.com/Effect-TS/effect-smol/commit/5c75fa8fb71163bc4c035ba1a215574dfd4badfc), [`747177b`](https://github.com/Effect-TS/effect-smol/commit/747177b0602f12d4461a843e953dfdffbeb0a429), [`326cd48`](https://github.com/Effect-TS/effect-smol/commit/326cd4828bce573fe985f35152155464bf4c5a70), [`627e922`](https://github.com/Effect-TS/effect-smol/commit/627e922b8d1e9521eae5e1caa5d667ad00b1619a), [`662287e`](https://github.com/Effect-TS/effect-smol/commit/662287e9abc76c941ccc2ee330aa07904d571341)]:
- effect@4.0.0-beta.28
## 4.0.0-beta.27
### Patch Changes
- Updated dependencies [[`903a839`](https://github.com/Effect-TS/effect-smol/commit/903a839e94239e6ec4568315af28e405bcad95f4), [`91a0168`](https://github.com/Effect-TS/effect-smol/commit/91a016836680a6669308ecf464d3584bcc4ae1b7), [`c890f9a`](https://github.com/Effect-TS/effect-smol/commit/c890f9a1b3a989ed22528bd5a43326342e05b142), [`1e985f2`](https://github.com/Effect-TS/effect-smol/commit/1e985f237d250b51b91de22dde77160c1e778ce7)]:
- effect@4.0.0-beta.27
## 4.0.0-beta.26
### Patch Changes
- Updated dependencies [[`fb21462`](https://github.com/Effect-TS/effect-smol/commit/fb21462642cdd5b1bada92f3eba18ae20445be42), [`2ed26b1`](https://github.com/Effect-TS/effect-smol/commit/2ed26b139805700e3df39efaa768ff01565e5c86), [`e832a57`](https://github.com/Effect-TS/effect-smol/commit/e832a57b570fe38f010c1fd99bceac5a325a9e07), [`7f01be7`](https://github.com/Effect-TS/effect-smol/commit/7f01be7f8db363d4b2e88e6b5571e96bb815786f), [`e965143`](https://github.com/Effect-TS/effect-smol/commit/e9651431e114479e6becf8ca7b1ed99ac7e91ccc), [`b9b80f1`](https://github.com/Effect-TS/effect-smol/commit/b9b80f1f15e152ceef0a727d150b7dc230abae99), [`98252aa`](https://github.com/Effect-TS/effect-smol/commit/98252aa0c0b17fc73fbdad65d0a1104965f9fc0f), [`56fbd94`](https://github.com/Effect-TS/effect-smol/commit/56fbd94311ad19a05001ad649d9e34ab00c74541), [`3faa109`](https://github.com/Effect-TS/effect-smol/commit/3faa109b7d093fbf14ad410d3e11d663f16e28f1), [`692ecfe`](https://github.com/Effect-TS/effect-smol/commit/692ecfed99fe58056b7a5afe001f4fcd1a61c446), [`1e70b72`](https://github.com/Effect-TS/effect-smol/commit/1e70b72d0b210474d0e96a15a5cfc279eae37e0c), [`ecf0782`](https://github.com/Effect-TS/effect-smol/commit/ecf07829ef2dfc01d8943c96c4fe9c1b44b97926)]:
- effect@4.0.0-beta.26
## 4.0.0-beta.25
### Patch Changes
- Updated dependencies [[`fa17bb5`](https://github.com/Effect-TS/effect-smol/commit/fa17bb5be9f2533d01e11322b14804c7dec43714), [`f46e5b5`](https://github.com/Effect-TS/effect-smol/commit/f46e5b5ca2a918ee4d9270167e79db223077c96f), [`ce4767c`](https://github.com/Effect-TS/effect-smol/commit/ce4767cadcacc6ce8ff4c3a0d0fbc82ede655f63), [`c830a8b`](https://github.com/Effect-TS/effect-smol/commit/c830a8b6c292a6528d7f9318759d34800b00372d)]:
- effect@4.0.0-beta.25
## 4.0.0-beta.24
### Patch Changes
- Updated dependencies [[`a909e1c`](https://github.com/Effect-TS/effect-smol/commit/a909e1c1ac2bc707527f5073776e3e7d239688d9), [`8814a4e`](https://github.com/Effect-TS/effect-smol/commit/8814a4ef78d67144d27689370af10099ea210399), [`3f942c5`](https://github.com/Effect-TS/effect-smol/commit/3f942c51cefa7b2ffa7c49e8c8a2c887570ba4c0), [`774ed59`](https://github.com/Effect-TS/effect-smol/commit/774ed59c52b2ab578bbb897c4f551f812231e1d2), [`f54b8d3`](https://github.com/Effect-TS/effect-smol/commit/f54b8d398fedad1815fd1f4c49814ab938cfc385)]:
- effect@4.0.0-beta.24
## 4.0.0-beta.23
### Patch Changes
- Updated dependencies [[`5c73c41`](https://github.com/Effect-TS/effect-smol/commit/5c73c41b69eaeab80fcd62c9bfda490b446d1966)]:
- effect@4.0.0-beta.23
## 4.0.0-beta.22
### Patch Changes
- Updated dependencies [[`0874332`](https://github.com/Effect-TS/effect-smol/commit/0874332f7c81118b06ac2eb105e0710211631479), [`c592dcd`](https://github.com/Effect-TS/effect-smol/commit/c592dcde0697e322065c8f418c0480ef910cb183), [`1dbe28d`](https://github.com/Effect-TS/effect-smol/commit/1dbe28dac8299cd3e218c9768450cfd173b5e294), [`564d730`](https://github.com/Effect-TS/effect-smol/commit/564d730b6bbf38dd8548a3b046e7a693b28699a4), [`3cfadc4`](https://github.com/Effect-TS/effect-smol/commit/3cfadc458b070c6cba6c5674b72a059f1e49118b), [`6634fd0`](https://github.com/Effect-TS/effect-smol/commit/6634fd07da067d80b8261fb2959d1a952b9e412e), [`d10dabe`](https://github.com/Effect-TS/effect-smol/commit/d10dabeb7af9a368f995829cd36ad08167cd8f95), [`f82f549`](https://github.com/Effect-TS/effect-smol/commit/f82f549a09e950e9d4987f279a800f4d953f0939), [`78a3382`](https://github.com/Effect-TS/effect-smol/commit/78a3382ddfbe034408f7480fa794733d9e82147b)]:
- effect@4.0.0-beta.22
## 4.0.0-beta.21
### Patch Changes
- Updated dependencies [[`e691909`](https://github.com/Effect-TS/effect-smol/commit/e691909495ccb162ea7bfa351dd74632b99997cb), [`d5f413f`](https://github.com/Effect-TS/effect-smol/commit/d5f413f3c8fc57f2413cc5649c2003d6d4e5a6d7), [`139d152`](https://github.com/Effect-TS/effect-smol/commit/139d152941e562a073b5be12e8d66c8a4d4a8a57), [`947e3d4`](https://github.com/Effect-TS/effect-smol/commit/947e3d436ab8a017efda9b29be523efd1ca8df28), [`84b2cce`](https://github.com/Effect-TS/effect-smol/commit/84b2ccefe2aa3a7413b86738a4dc33cdb311ca55), [`7f5305e`](https://github.com/Effect-TS/effect-smol/commit/7f5305e69f5a33309e77b08a576edb25d7daaee2), [`9e6fd84`](https://github.com/Effect-TS/effect-smol/commit/9e6fd8471c93a3c643929151a3bdb62cb9c0ca0e), [`fdb8a4b`](https://github.com/Effect-TS/effect-smol/commit/fdb8a4b172721fbefe98bd5aa6fe4f0efd1da3eb), [`0f986ef`](https://github.com/Effect-TS/effect-smol/commit/0f986ef22f196fe091a7afdbd179485a7d888882), [`9355fc0`](https://github.com/Effect-TS/effect-smol/commit/9355fc0ffb5b7382146a5aed9eea83974b10d007)]:
- effect@4.0.0-beta.21
## 4.0.0-beta.20
### Patch Changes
- Updated dependencies [[`842a624`](https://github.com/Effect-TS/effect-smol/commit/842a624f79d5e1407460b0ef3ab27d14d48ccf74), [`4785eef`](https://github.com/Effect-TS/effect-smol/commit/4785eef5d7cf1edb96ef2509aed2ba4d1edf3862), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`12ee8e2`](https://github.com/Effect-TS/effect-smol/commit/12ee8e27df7eb393d83a5e403390d0cfc82ca732), [`e542c94`](https://github.com/Effect-TS/effect-smol/commit/e542c942bee4729138b02222f4421220a90a57d8), [`8fac95b`](https://github.com/Effect-TS/effect-smol/commit/8fac95bd9e0338b7a82da8da579c1ac22afa045c), [`6f4ebd1`](https://github.com/Effect-TS/effect-smol/commit/6f4ebd193c2595983394127dd808601b75430d34), [`989d1cc`](https://github.com/Effect-TS/effect-smol/commit/989d1cca936fce0cc459057825ba40e3f5ef3827)]:
- effect@4.0.0-beta.20
## 4.0.0-beta.19
### Patch Changes
- Updated dependencies []:
- effect@4.0.0-beta.19
## 4.0.0-beta.18
### Patch Changes
- Updated dependencies [[`01e31fd`](https://github.com/Effect-TS/effect-smol/commit/01e31fdf8e5206849d23cbafd23a346f2f177ab8), [`0890aab`](https://github.com/Effect-TS/effect-smol/commit/0890aab15ed9c5ba52c383a72fdc6a444d7504d5), [`725260b`](https://github.com/Effect-TS/effect-smol/commit/725260b53f5142d6af7a93a2f9f464f974eda92d)]:
- effect@4.0.0-beta.18
## 4.0.0-beta.17
### Patch Changes
- Updated dependencies [[`8f59c32`](https://github.com/Effect-TS/effect-smol/commit/8f59c32922597a48392744f7203e284866747781)]:
- effect@4.0.0-beta.17
## 4.0.0-beta.16
### Patch Changes
- Updated dependencies [[`bf9096c`](https://github.com/Effect-TS/effect-smol/commit/bf9096c52a7d8791d93d232739e523eb84f6625a), [`29f81ca`](https://github.com/Effect-TS/effect-smol/commit/29f81ca07c67dba265804b140a7487fb15a5fc6b), [`68eb28c`](https://github.com/Effect-TS/effect-smol/commit/68eb28c2b0fc67a9f6204ade9bd16c5b37803bfb)]:
- effect@4.0.0-beta.16
## 4.0.0-beta.15
### Patch Changes
- Updated dependencies [[`24ae609`](https://github.com/Effect-TS/effect-smol/commit/24ae60995d2fd7d621be356cdfdfd328c79639ba), [`0e3c059`](https://github.com/Effect-TS/effect-smol/commit/0e3c059987caa55ebd0c134f7c7b147c639c328e), [`e843b0a`](https://github.com/Effect-TS/effect-smol/commit/e843b0a7d7e7b600a0b3bd477f24e2e4cd26bc8b), [`f4389a2`](https://github.com/Effect-TS/effect-smol/commit/f4389a2cca3c5bbf00d69779f52ce41255f15a28), [`5b73de0`](https://github.com/Effect-TS/effect-smol/commit/5b73de095b3402d0c5c74092ace6ce18ebfad566), [`595d2d6`](https://github.com/Effect-TS/effect-smol/commit/595d2d6e7d50419f3532bd39266191532ace38f2)]:
- effect@4.0.0-beta.15
## 4.0.0-beta.14
### Patch Changes
- Updated dependencies [[`c414700`](https://github.com/Effect-TS/effect-smol/commit/c414700ef1932e4b67d0102856de417336912350), [`a30c969`](https://github.com/Effect-TS/effect-smol/commit/a30c9699c0d736cf3952041e45d508b7d58907a9)]:
- effect@4.0.0-beta.14
## 4.0.0-beta.13
### Patch Changes
- Updated dependencies [[`368f4c3`](https://github.com/Effect-TS/effect-smol/commit/368f4c363dd117e6f5a19ad77b161176cfd29fdd), [`db8a579`](https://github.com/Effect-TS/effect-smol/commit/db8a579e93e93ff73b1e60712732e03b597b916b), [`668b703`](https://github.com/Effect-TS/effect-smol/commit/668b70337e9ddbb0d1ae2282a95c282ce404e562), [`d40e76b`](https://github.com/Effect-TS/effect-smol/commit/d40e76b973543979e60e04a6baca04a8c65bdfc2), [`6e18cf8`](https://github.com/Effect-TS/effect-smol/commit/6e18cf883e9905ca718a6697b6a2a4bbd42739aa), [`86062e8`](https://github.com/Effect-TS/effect-smol/commit/86062e8a0c61bca5412fc40d2cf151d676901f08), [`c27ce75`](https://github.com/Effect-TS/effect-smol/commit/c27ce75d34c74dcfc6dba1bf77f1ce88f410a0de), [`e2d4fbf`](https://github.com/Effect-TS/effect-smol/commit/e2d4fbfeeda6a5d2a4c5aeb0501d8240c248b9eb), [`114ab42`](https://github.com/Effect-TS/effect-smol/commit/114ab42ad0edc590d29169675a493e0e915aa58f), [`484caec`](https://github.com/Effect-TS/effect-smol/commit/484caec47cccac8b86db2910742e406dfc7173ab)]:
- effect@4.0.0-beta.13
## 4.0.0-beta.12
### Patch Changes
- Updated dependencies [[`70a74e8`](https://github.com/Effect-TS/effect-smol/commit/70a74e88a8767c9d4acdb9e5f25aec9a33588d07), [`b5b6e10`](https://github.com/Effect-TS/effect-smol/commit/b5b6e10621d54bf8c9857fec0d647ced78ecd857), [`f5ce5a9`](https://github.com/Effect-TS/effect-smol/commit/f5ce5a915359c6ebf254079e1da23cab6cde34fb), [`a29eb70`](https://github.com/Effect-TS/effect-smol/commit/a29eb702ffe3fc58bd28c4d7857298cd65d73668), [`c7b36e5`](https://github.com/Effect-TS/effect-smol/commit/c7b36e541a23e9a00f64e25b23851e51a37dfce5), [`9381d6d`](https://github.com/Effect-TS/effect-smol/commit/9381d6d4d9d819a81a46e56d0364c76e92a4fbca), [`88439f1`](https://github.com/Effect-TS/effect-smol/commit/88439f13ca13549f3e4822c48c4f019c14fc2bcc), [`e35307d`](https://github.com/Effect-TS/effect-smol/commit/e35307dbeb8eb26a9923f958b894a8eaaf259bf2), [`c7df4bc`](https://github.com/Effect-TS/effect-smol/commit/c7df4bce34009474c63d62a807abfdafb76971eb), [`accaf3b`](https://github.com/Effect-TS/effect-smol/commit/accaf3be7ac8da36e2334c509c23b8c9e88ea160), [`3e1c270`](https://github.com/Effect-TS/effect-smol/commit/3e1c2707bbdf67720af1509642b8ced195790882), [`6cd81f7`](https://github.com/Effect-TS/effect-smol/commit/6cd81f73baad86f5bbfa455a55d75cde71e9611a), [`f222da3`](https://github.com/Effect-TS/effect-smol/commit/f222da3cdb44554f3324c2c52d0d005ee575053e), [`61f901d`](https://github.com/Effect-TS/effect-smol/commit/61f901d830005b66e22d1de889fda132aeea97cd)]:
- effect@4.0.0-beta.12
## 4.0.0-beta.11
### Patch Changes
- Updated dependencies [[`88659ed`](https://github.com/Effect-TS/effect-smol/commit/88659edb26e3623d557dccfe914c2c949672da16), [`f2915e8`](https://github.com/Effect-TS/effect-smol/commit/f2915e8e2efe80d50c281e53f297b9701d6dc199), [`eb71ace`](https://github.com/Effect-TS/effect-smol/commit/eb71acebbe0f228e4920278013beee3b67d62310), [`2a16999`](https://github.com/Effect-TS/effect-smol/commit/2a169996c7513d377ac47adbfd68e1490457135c), [`d42dd52`](https://github.com/Effect-TS/effect-smol/commit/d42dd52f11203f8e749fb5d3ecf7153e4a5a6814), [`339adaf`](https://github.com/Effect-TS/effect-smol/commit/339adaf850a62a892adebcb208c2d9dddf3b97b3), [`de19645`](https://github.com/Effect-TS/effect-smol/commit/de1964526d01102dd1cb99c8cfdd3e8df1f49ef1), [`9b1dc3b`](https://github.com/Effect-TS/effect-smol/commit/9b1dc3bcf2a1b68d0a67e3465db5ad01a1a56997), [`e4cb2f5`](https://github.com/Effect-TS/effect-smol/commit/e4cb2f55b30f4771ec1bf613ced36d6d96464dd5), [`8bced95`](https://github.com/Effect-TS/effect-smol/commit/8bced954ecb35d4489197a57b0efe927e7d75f49), [`9431420`](https://github.com/Effect-TS/effect-smol/commit/94314207c8019918200fbcb97aec992219f801f0), [`948dca2`](https://github.com/Effect-TS/effect-smol/commit/948dca22e4f672ba7a6db57f9899272bec7c08b8), [`d18e327`](https://github.com/Effect-TS/effect-smol/commit/d18e32765a2665e31ffb31e746bf983fcfac34c5), [`ab512f7`](https://github.com/Effect-TS/effect-smol/commit/ab512f7be1c0e6b359da921e22cd4944e4c57d3e)]:
- effect@4.0.0-beta.11
## 4.0.0-beta.10
### Patch Changes
- Updated dependencies [[`371acab`](https://github.com/Effect-TS/effect-smol/commit/371acabb58d56f3a7a5e3e33d3d5fdc9f5573c74), [`856d774`](https://github.com/Effect-TS/effect-smol/commit/856d7741f1e296dd5048c6ff2b44b95d023e6ae4), [`b9e9202`](https://github.com/Effect-TS/effect-smol/commit/b9e92023c38caa322975d77cfe83e2d34ac9305a), [`1d1a974`](https://github.com/Effect-TS/effect-smol/commit/1d1a974bd280c81bff5d4505491cda03ba7a3f36), [`6bfe2a6`](https://github.com/Effect-TS/effect-smol/commit/6bfe2a659bc6335db75709931f405da45301cba2), [`b12c811`](https://github.com/Effect-TS/effect-smol/commit/b12c81157be287b1649c210616a244b50ec094d2), [`d17d98a`](https://github.com/Effect-TS/effect-smol/commit/d17d98ad78e2b44d95ef434adab79ac3c35e75ab), [`68c3c7c`](https://github.com/Effect-TS/effect-smol/commit/68c3c7cb1e06ed94fa5c4c123a234b4ccbfdecd8)]:
- effect@4.0.0-beta.10
## 4.0.0-beta.9
### Patch Changes
- Updated dependencies [[`3386557`](https://github.com/Effect-TS/effect-smol/commit/338655731564a7be9f8859dedbf4d5bcac6eb350), [`b6666e3`](https://github.com/Effect-TS/effect-smol/commit/b6666e3cf6bd44ba1a8704e65c256c30359cb422)]:
- effect@4.0.0-beta.9
## 4.0.0-beta.8
### Patch Changes
- Updated dependencies [[`246e672`](https://github.com/Effect-TS/effect-smol/commit/246e672dbbd7848d60e0c78fd66671b2f10b3752), [`807dec0`](https://github.com/Effect-TS/effect-smol/commit/807dec03801b4c58a6d00c237b6d98d6386911df)]:
- effect@4.0.0-beta.8
## 4.0.0-beta.7
### Patch Changes
- Updated dependencies [[`a2bda6d`](https://github.com/Effect-TS/effect-smol/commit/a2bda6d4ef6de9d9b0c53ae2df5434f778d6161a), [`1f95a2b`](https://github.com/Effect-TS/effect-smol/commit/1f95a2b5aa9524bb38f4437f4691a664bf463ca1), [`a8d5e79`](https://github.com/Effect-TS/effect-smol/commit/a8d5e792fec201a83af0eb92fc79928d055125fd), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`a5386ba`](https://github.com/Effect-TS/effect-smol/commit/a5386ba67005dff697d45a45398f398773f58dcf), [`06d8a03`](https://github.com/Effect-TS/effect-smol/commit/06d8a0391631e6130e3ab25227e59817852e227f), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430), [`f9e883e`](https://github.com/Effect-TS/effect-smol/commit/f9e883e266fbda870336ee62f46b7ac85ba3de6e), [`8caac76`](https://github.com/Effect-TS/effect-smol/commit/8caac76a35821edfe03c75dab5eb056e8fc05430)]:
- effect@4.0.0-beta.7
## 4.0.0-beta.6
### Patch Changes
- Updated dependencies [[`3247da2`](https://github.com/Effect-TS/effect-smol/commit/3247da28331f345f68be5dbd2974a7e03d300fe1), [`f205705`](https://github.com/Effect-TS/effect-smol/commit/f2057050dbd034b8c186be2d40c3d03ee63a5a3b), [`f35022c`](https://github.com/Effect-TS/effect-smol/commit/f35022c212e4111527e1bb43f360a67b2b49fa85), [`8622721`](https://github.com/Effect-TS/effect-smol/commit/86227217b02d43680a3c6f3c21731b1d852c91f5), [`fc660ab`](https://github.com/Effect-TS/effect-smol/commit/fc660ab8b5ebae38b8d6b96cbf2f9b880cc09253), [`f37dc33`](https://github.com/Effect-TS/effect-smol/commit/f37dc335f64622fa9ce8d6d1d5dd8fc3f260257b), [`3662f32`](https://github.com/Effect-TS/effect-smol/commit/3662f328fcfa3b2fa01ffa79da40e12e93fcede8), [`a7d436f`](https://github.com/Effect-TS/effect-smol/commit/a7d436f438dcd7f49b9485e4e95a4511f31fad7d), [`6856a41`](https://github.com/Effect-TS/effect-smol/commit/6856a415d7eddd9d73d60919e976f1d071421be4), [`8c417d0`](https://github.com/Effect-TS/effect-smol/commit/8c417d03475e5e12d00dca0c4781d0af7e66b86c), [`5419570`](https://github.com/Effect-TS/effect-smol/commit/5419570ba47ce882a3a10882707b46f66e464906), [`449c5ed`](https://github.com/Effect-TS/effect-smol/commit/449c5ed5318e8a874e730420bcf52918fa2ec80f), [`4b5ec12`](https://github.com/Effect-TS/effect-smol/commit/4b5ec12f87f95f2a3cd8fe4d5b26c6eb0529381a), [`df87937`](https://github.com/Effect-TS/effect-smol/commit/df879375fc3b169c43f9c434b3775e12b80dffe4), [`5dbfca8`](https://github.com/Effect-TS/effect-smol/commit/5dbfca8d1dbb6d18d1605d4f8562e99c86e2ff11), [`e629497`](https://github.com/Effect-TS/effect-smol/commit/e6294973d55597ab6b6deca6babbe1e946b2c91d), [`981c991`](https://github.com/Effect-TS/effect-smol/commit/981c991cd78db34def815d5754379d737157f005), [`1ca2ed6`](https://github.com/Effect-TS/effect-smol/commit/1ca2ed67301a5dc40ae0ed94346b99f26fd22bbe), [`45722bd`](https://github.com/Effect-TS/effect-smol/commit/45722bde974458311f11ad237711363a10ec6894), [`eb2a85e`](https://github.com/Effect-TS/effect-smol/commit/eb2a85ed4dc162b2535d304799333a5a20477fd0)]:
- effect@4.0.0-beta.6
## 4.0.0-beta.5
### Patch Changes
- Updated dependencies [[`f6e133e`](https://github.com/Effect-TS/effect-smol/commit/f6e133e9a16b32317bd09ff08c12b97a0ae44600), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8), [`a88e206`](https://github.com/Effect-TS/effect-smol/commit/a88e206e44dc66ca5a2b45bedc797877c5dbb083), [`e3893cc`](https://github.com/Effect-TS/effect-smol/commit/e3893ccf2632338c7d8e745f639dcd825a9d42f8)]:
- effect@4.0.0-beta.5
## 4.0.0-beta.4
### Patch Changes
- Updated dependencies [[`c5a18ef`](https://github.com/Effect-TS/effect-smol/commit/c5a18ef44171e3880bf983faee74529908974b32), [`bc6b885`](https://github.com/Effect-TS/effect-smol/commit/bc6b885b94d887a200657c0775dfa874dc15bc0c)]:
- effect@4.0.0-beta.4
## 4.0.0-beta.3
### Patch Changes
- Updated dependencies [[`3a0cf36`](https://github.com/Effect-TS/effect-smol/commit/3a0cf36eff106ba48d74e133c1598cd40613e530), [`c4da328`](https://github.com/Effect-TS/effect-smol/commit/c4da328d32fad1d61e0e538f5d371edf61521d7e)]:
- effect@4.0.0-beta.3
## 4.0.0-beta.2
### Patch Changes
- Updated dependencies [[`a22ce73`](https://github.com/Effect-TS/effect-smol/commit/a22ce73b2bd9305b7ba665694d2255c0e6d5a8d0), [`ebdabf7`](https://github.com/Effect-TS/effect-smol/commit/ebdabf79ff4e62c8384aa8cf9a8d2787d536ee78), [`8f663bb`](https://github.com/Effect-TS/effect-smol/commit/8f663bb121021bf12bd264e8ae385187cb7a5dae)]:
- effect@4.0.0-beta.2
## 4.0.0-beta.1
### Patch Changes
- Updated dependencies [[`0fecf70`](https://github.com/Effect-TS/effect-smol/commit/0fecf70048057623eed7c584a06671773a2b1743), [`709569e`](https://github.com/Effect-TS/effect-smol/commit/709569ed76bead9ebb0670599e4d890a07ca5a43)]:
- effect@4.0.0-beta.1
## 4.0.0-beta.0
### Major Changes
- [#1183](https://github.com/Effect-TS/effect-smol/pull/1183) [`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66) Thanks @tim-smart! - v4 beta
### Patch Changes
- Updated dependencies [[`be642ab`](https://github.com/Effect-TS/effect-smol/commit/be642ab1b3b4cd49e53c9732d7aba1b367fddd66)]:
- effect@4.0.0-beta.0

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023-present The Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,7 @@
# `@effect/atom-solid`
SolidJS bindings for the Effect Atom modules.
## Documentation
- **API Reference**: [View the full documentation](https://effect-ts.github.io/effect/docs/atom-solid).

View File

@@ -0,0 +1,25 @@
{
"$schema": "../../../node_modules/@effect/docgen/schema.json",
"projectHomepage": "https://effect-ts.github.io/effect/docs/atom-solid",
"srcLink": "https://github.com/Effect-TS/effect/tree/main/packages/atom/solid/src/",
"enforceVersion": true,
"exclude": ["src/internal/**/*.ts"],
"examplesCompilerOptions": {
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"rewriteRelativeImportExtensions": true,
"allowImportingTsExtensions": true,
"paths": {
"effect": ["../../../effect/src/index.js"],
"effect/*": ["../../../effect/src/*.js"]
},
"plugins": [
{ "name": "@effect/language-service", "includeSuggestionsInTsc": false }
]
}
}

View File

@@ -0,0 +1,71 @@
{
"name": "@effect/atom-solid",
"version": "4.0.0-beta.99",
"type": "module",
"license": "MIT",
"description": "SolidJS bindings for the Effect Atom modules",
"homepage": "https://effect.website",
"repository": {
"type": "git",
"url": "https://github.com/Effect-TS/effect.git",
"directory": "packages/atom/solid"
},
"bugs": {
"url": "https://github.com/Effect-TS/effect/issues"
},
"tags": [
"typescript",
"solid",
"database"
],
"keywords": [
"typescript",
"solid",
"database"
],
"sideEffects": [],
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts",
"./*": "./src/*.ts",
"./internal/*": null,
"./*/index": null
},
"files": [
"src/**/*.ts",
"dist/**/*.js",
"dist/**/*.js.map",
"dist/**/*.d.ts",
"dist/**/*.d.ts.map"
],
"publishConfig": {
"access": "public",
"provenance": true,
"exports": {
"./package.json": "./package.json",
".": "./dist/index.js",
"./*": "./dist/*.js",
"./internal/*": null,
"./*/index": null
}
},
"scripts": {
"build": "tsc -b tsconfig.json && pnpm babel",
"babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
"check": "tsc -b tsconfig.json",
"test": "vitest",
"coverage": "vitest --coverage"
},
"peerDependencies": {
"effect": "workspace:^",
"solid-js": ">=1 <2"
},
"devDependencies": {
"@solidjs/testing-library": "^0.8.0",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"effect": "workspace:^",
"jsdom": "^29.1.1",
"solid-js": "^1.9.14"
}
}

View File

@@ -0,0 +1,359 @@
/**
* Solid hooks for using Effect Atoms from components and computations. The
* hooks read and write atoms through the current `RegistryContext`, mount atoms
* for cleanup, subscribe callbacks, seed initial values, expose `AsyncResult`
* atoms as Solid resources, and read values from `AtomRef` references.
*
* @since 4.0.0
*/
import * as Cause from "effect/Cause"
import * as Effect from "effect/Effect"
import * as Exit from "effect/Exit"
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
import * as Atom from "effect/unstable/reactivity/Atom"
import type * as AtomRef from "effect/unstable/reactivity/AtomRef"
import * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry"
import type { Accessor, ResourceOptions, ResourceReturn } from "solid-js"
import { createComputed, createEffect, createMemo, createResource, createSignal, onCleanup, useContext } from "solid-js"
import { RegistryContext } from "./RegistryContext.ts"
const initialValuesSet = new WeakMap<AtomRegistry.AtomRegistry, WeakSet<Atom.Atom<any>>>()
/**
* Seeds initial atom values in the current Solid atom registry.
*
* **When to use**
*
* Use to seed atom values from a Solid component after the current registry
* already exists.
*
* **Details**
*
* For each atom in the current registry, this hook applies the first value
* supplied through the hook. Later calls for the same atom in that registry are
* ignored.
*
* @category hooks
* @since 4.0.0
*/
export const useAtomInitialValues = (initialValues: Iterable<readonly [Atom.Atom<any>, any]>): void => {
const registry = useContext(RegistryContext)
let set = initialValuesSet.get(registry)
if (set === undefined) {
set = new WeakSet()
initialValuesSet.set(registry, set)
}
for (const [atom, value] of initialValues) {
if (!set.has(atom)) {
set.add(atom)
;(registry as any).ensureNode(atom).setValue(value)
}
}
}
/**
* Subscribes to an atom in the current Solid registry and returns its value as
* a Solid accessor.
*
* @category hooks
* @since 4.0.0
*/
export const useAtomValue: {
<A>(atom: () => Atom.Atom<A>): Accessor<A>
<A, B>(atom: () => Atom.Atom<A>, f: (_: A) => B): Accessor<B>
} = <A>(atom: () => Atom.Atom<A>, f?: (_: A) => A): Accessor<A> => {
const registry = useContext(RegistryContext)
return createAtomAccessor(registry, f ? () => Atom.map(atom(), f) : atom)
}
function createAtomAccessor<A>(registry: AtomRegistry.AtomRegistry, atom: () => Atom.Atom<A>): Accessor<A> {
const [value, setValue] = createSignal<A>(null as any)
createComputed(() => {
onCleanup(registry.subscribe(atom(), setValue as any, constImmediate))
})
return value
}
const constImmediate = { immediate: true }
function mountAtom<A>(registry: AtomRegistry.AtomRegistry, atom: () => Atom.Atom<A>): void {
createComputed(() => {
onCleanup(registry.mount(atom()))
})
}
function setAtom<R, W, Mode extends "value" | "promise" | "promiseExit" = never>(
registry: AtomRegistry.AtomRegistry,
atom: () => Atom.Writable<R, W>,
options?: {
readonly mode?: ([R] extends [AsyncResult.AsyncResult<any, any>] ? Mode : "value") | undefined
}
): "promise" extends Mode ? (
(value: W) => Promise<AsyncResult.AsyncResult.Success<R>>
) :
"promiseExit" extends Mode ? (
(value: W) => Promise<Exit.Exit<AsyncResult.AsyncResult.Success<R>, AsyncResult.AsyncResult.Failure<R>>>
) :
((value: W | ((value: R) => W)) => void)
{
const memo = createMemo(atom)
if (options?.mode === "promise" || options?.mode === "promiseExit") {
return ((value: W) => {
registry.set(memo(), value)
const promise = Effect.runPromiseExit(
AtomRegistry.getResult(registry, memo() as Atom.Atom<AsyncResult.AsyncResult<any, any>>, {
suspendOnWaiting: true
})
)
return options!.mode === "promise" ? promise.then(flattenExit) : promise
}) as any
}
return ((value: W | ((value: R) => W)) => {
registry.set(memo(), typeof value === "function" ? (value as any)(registry.get(memo())) : value)
}) as any
}
const flattenExit = <A, E>(exit: Exit.Exit<A, E>): A => {
if (Exit.isSuccess(exit)) return exit.value
throw Cause.squash(exit.cause)
}
/**
* Mounts an atom in the current Solid registry for the lifetime of the current
* Solid computation.
*
* **When to use**
*
* Use to keep an atom mounted from a Solid owner without reading, writing, or
* refreshing it.
*
* **Details**
*
* The hook uses the current `RegistryContext`, mounts inside a Solid
* computation, and releases the mount through Solid cleanup when the
* computation changes or the owner is disposed.
*
* @see {@link useAtomSet} for mounting a writable atom while returning a setter
* @see {@link useAtomRefresh} for mounting an atom while returning a refresh callback
*
* @category hooks
* @since 4.0.0
*/
export const useAtomMount = <A>(atom: () => Atom.Atom<A>): void => {
const registry = useContext(RegistryContext)
mountAtom(registry, atom)
}
/**
* Returns a setter for a writable atom without subscribing to its value.
*
* @category hooks
* @since 4.0.0
*/
export const useAtomSet = <
R,
W,
Mode extends "value" | "promise" | "promiseExit" = never
>(
atom: () => Atom.Writable<R, W>,
options?: {
readonly mode?: ([R] extends [AsyncResult.AsyncResult<any, any>] ? Mode : "value") | undefined
}
): "promise" extends Mode ? (
(value: W) => Promise<AsyncResult.AsyncResult.Success<R>>
) :
"promiseExit" extends Mode ? (
(value: W) => Promise<Exit.Exit<AsyncResult.AsyncResult.Success<R>, AsyncResult.AsyncResult.Failure<R>>>
) :
((value: W | ((value: R) => W)) => void) =>
{
const registry = useContext(RegistryContext)
mountAtom(registry, atom)
return setAtom(registry, atom, options)
}
/**
* Mounts an atom and returns a callback that refreshes the current atom.
*
* @category hooks
* @since 4.0.0
*/
export const useAtomRefresh = <A>(atom: () => Atom.Atom<A>): () => void => {
const registry = useContext(RegistryContext)
mountAtom(registry, atom)
const memo = createMemo(atom)
return () => registry.refresh(memo())
}
/**
* Returns a Solid accessor for a writable atom together with a setter for
* updating it.
*
* **When to use**
*
* Use when a Solid component or computation needs both a reactive accessor for
* a writable atom and a write function for that same atom.
*
* **Details**
*
* The setter accepts either a write value or an updater function. For
* `AsyncResult` atoms, `promise` and `promiseExit` modes return promises for the
* success value or full `Exit`.
*
* @see {@link useAtomValue} for subscribing to an atom without a setter
* @see {@link useAtomSet} for updating a writable atom without subscribing to its value
*
* @category hooks
* @since 4.0.0
*/
export const useAtom = <R, W, const Mode extends "value" | "promise" | "promiseExit" = never>(
atom: () => Atom.Writable<R, W>,
options?: {
readonly mode?: ([R] extends [AsyncResult.AsyncResult<any, any>] ? Mode : "value") | undefined
}
): readonly [
value: Accessor<R>,
write: "promise" extends Mode ? (
(value: W) => Promise<AsyncResult.AsyncResult.Success<R>>
) :
"promiseExit" extends Mode ? (
(value: W) => Promise<Exit.Exit<AsyncResult.AsyncResult.Success<R>, AsyncResult.AsyncResult.Failure<R>>>
) :
((value: W | ((value: R) => W)) => void)
] => {
const registry = useContext(RegistryContext)
return [
createAtomAccessor(registry, atom),
setAtom(registry, atom, options)
] as const
}
/**
* Subscribes a callback to an atom in the current Solid registry.
*
* @category hooks
* @since 4.0.0
*/
export const useAtomSubscribe = <A>(
atom: () => Atom.Atom<A>,
f: (_: A) => void,
options?: { readonly immediate?: boolean }
): void => {
const registry = useContext(RegistryContext)
createEffect(() => {
onCleanup(registry.subscribe(atom(), f, options))
})
}
/**
* Converts an `AsyncResult` atom into a Solid resource.
*
* @category hooks
* @since 4.0.0
*/
export const useAtomResource = <A, E>(
atom: () => Atom.Atom<AsyncResult.AsyncResult<A, E>>,
options?: ResourceOptions<A> & {
readonly suspendOnWaiting?: boolean | undefined
}
): ResourceReturn<A, void> => {
const result = useAtomValue(atom)
return createResource(result, (result) => {
if (AsyncResult.isInitial(result) || (options?.suspendOnWaiting && result.waiting)) {
return constUnresolvedPromise
} else if (AsyncResult.isSuccess(result)) {
return Promise.resolve(result.value)
}
return Promise.reject(Cause.squash(result.cause))
})
}
const constUnresolvedPromise = new Promise<never>(() => {})
/**
* Subscribes to an atom ref and returns its value as a Solid accessor.
*
* **When to use**
*
* Use when a Solid component or computation should render from an
* `AtomRef.ReadonlyRef` directly instead of reading an atom through the current
* registry.
*
* **Details**
*
* The hook accepts a thunk for the ref, reads `ref().value`, subscribes with
* `ref.subscribe`, and releases the subscription through Solid cleanup when
* the selected ref changes or the owner is disposed.
*
* @see {@link useAtomValue} for reading an `Atom` from the current registry
* @see {@link useAtomRefPropValue} for reading a property ref value
*
* @category hooks
* @since 4.0.0
*/
export const useAtomRef = <A>(ref: () => AtomRef.ReadonlyRef<A>): Accessor<A> => {
const [value, setValue] = createSignal(null as A)
createComputed(() => {
const r = ref()
setValue(r.value as any)
onCleanup(r.subscribe(setValue))
})
return value
}
/**
* Returns a Solid accessor for a property ref derived from an atom ref.
*
* **When to use**
*
* Use to derive an `AtomRef` for one property of an object-shaped atom ref in a
* Solid computation.
*
* **Details**
*
* The returned accessor memoizes `ref().prop(prop)`, updating when the source
* ref thunk produces a different ref.
*
* **Gotchas**
*
* The `prop` argument is captured as a plain value. Recreate the hook call when
* the property key should change.
*
* @see {@link useAtomRef} for subscribing to an atom ref value
* @see {@link useAtomRefPropValue} for subscribing directly to a property value
*
* @category hooks
* @since 4.0.0
*/
export const useAtomRefProp = <A, K extends keyof A>(
ref: () => AtomRef.AtomRef<A>,
prop: K
): Accessor<AtomRef.AtomRef<A[K]>> => createMemo(() => ref().prop(prop))
/**
* Returns a Solid accessor for the value of a property ref derived from an atom
* ref.
*
* **When to use**
*
* Use when a Solid component or computation needs the value of one property
* from an object-shaped `AtomRef` without keeping the intermediate property ref.
*
* **Details**
*
* The hook composes `useAtomRefProp(ref, prop)` with `useAtomRef`, returning a
* Solid accessor for the selected property value.
*
* **Gotchas**
*
* The `prop` argument is captured as a plain value. Recreate the hook call when
* the property key should change.
*
* @see {@link useAtomRef} for subscribing to a whole atom ref value
* @see {@link useAtomRefProp} for returning the property ref directly
*
* @category hooks
* @since 4.0.0
*/
export const useAtomRefPropValue = <A, K extends keyof A>(ref: () => AtomRef.AtomRef<A>, prop: K): Accessor<A[K]> =>
useAtomRef(useAtomRefProp(ref, prop))

View File

@@ -0,0 +1,80 @@
/**
* Solid context and provider for the Atom registry used by Effect Atom hooks.
* The registry stores atom values, schedules update work, and cleans up unused
* atoms. Sharing one registry through Solid context lets components and
* computations in the same owner tree read and write the same atom state.
*
* @since 4.0.0
*/
import type * as Atom from "effect/unstable/reactivity/Atom"
import * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry"
import type { JSX } from "solid-js"
import { createComponent, createContext, onCleanup } from "solid-js"
/**
* Provides a Solid context that carries the `AtomRegistry` used by atom hooks in the
* current owner tree.
*
* **When to use**
*
* Use when you need to integrate lower-level Solid context APIs, such as custom
* providers or hooks, instead of using the default atom hook setup.
*
* **Details**
*
* When no provider is present, the context uses a standalone default registry.
*
* @see {@link RegistryProvider} for creating and providing a registry for a Solid subtree
*
* @category context
* @since 4.0.0
*/
export const RegistryContext = createContext<AtomRegistry.AtomRegistry>(AtomRegistry.make())
/**
* Creates an `AtomRegistry` for a Solid subtree, optionally seeding initial atom
* values and scheduler settings, and disposes the registry when the owner is
* cleaned up.
*
* **When to use**
*
* Use to scope atom state, scheduling, and cleanup to a Solid subtree.
*
* **Details**
*
* The provider creates an `AtomRegistry` with `AtomRegistry.make`, forwards
* `initialValues`, `scheduleTask`, `timeoutResolution`, and
* `defaultIdleTTL`, and supplies the registry through `RegistryContext`.
*
* **Gotchas**
*
* Provider options are consumed when the registry is created; they are not
* reactive updates. A custom `scheduleTask` should return a cancellation
* function that is safe to call during Solid cleanup.
*
* @see {@link RegistryContext} for the context supplied by this provider
*
* @category context
* @since 4.0.0
*/
export const RegistryProvider = (options: {
readonly children?: JSX.Element | undefined
readonly initialValues?: Iterable<readonly [Atom.Atom<any>, any]> | undefined
readonly scheduleTask?: ((f: () => void) => () => void) | undefined
readonly timeoutResolution?: number | undefined
readonly defaultIdleTTL?: number | undefined
}) => {
const registry = AtomRegistry.make({
scheduleTask: options.scheduleTask,
initialValues: options.initialValues,
timeoutResolution: options.timeoutResolution,
defaultIdleTTL: options.defaultIdleTTL ?? 400
})
onCleanup(() => registry.dispose())
return createComponent(RegistryContext.Provider, {
value: registry,
get children() {
return options.children
}
})
}

View File

@@ -0,0 +1,13 @@
/**
* @since 4.0.0
*/
/**
* @since 4.0.0
*/
export * from "./Hooks.ts"
/**
* @since 4.0.0
*/
export * from "./RegistryContext.ts"

View File

@@ -0,0 +1,296 @@
import {
RegistryContext,
useAtom,
useAtomInitialValues,
useAtomRef,
useAtomRefProp,
useAtomRefPropValue,
useAtomResource,
useAtomValue
} from "@effect/atom-solid"
import { assert, describe, it } from "@effect/vitest"
import { AsyncResult, Atom, AtomRef, AtomRegistry } from "effect/unstable/reactivity"
import { type Accessor, createComponent, createEffect, createRoot, type Resource } from "solid-js"
describe("atom-solid", () => {
describe("useAtomValue", () => {
it("reads value from simple Atom", () => {
const atom = Atom.make(42)
let observed: number | undefined
const dispose = renderAtomValue(atom, (value) => {
observed = value
})
assert.strictEqual(observed, 42)
dispose()
})
it("reads value with transform function", () => {
const atom = Atom.make(42)
let observed: number | undefined
const dispose = renderAtomValue(atom, (value) => {
observed = value
}, { map: (value) => value * 2 })
assert.strictEqual(observed, 84)
dispose()
})
it("updates when Atom value changes", () => {
const registry = AtomRegistry.make()
const atom = Atom.make("initial")
let observed: string | undefined
const dispose = renderAtomValue(atom, (value) => {
observed = value
}, { registry })
assert.strictEqual(observed, "initial")
registry.set(atom, "updated")
assert.strictEqual(observed, "updated")
dispose()
})
it("works with computed Atom", () => {
const baseAtom = Atom.make(10)
const computedAtom = Atom.make((get) => get(baseAtom) * 2)
let observed: number | undefined
const dispose = renderAtomValue(computedAtom, (value) => {
observed = value
})
assert.strictEqual(observed, 20)
dispose()
})
})
describe("useAtom", () => {
it("updates value with setter", () => {
const atom = Atom.make(0)
let observed: number | undefined
const dispose = createRoot((dispose) => {
const [value, setValue] = useAtom(() => atom)
createEffect(() => {
observed = value()
})
createEffect(() => {
if (value() !== 0) {
return
}
setValue(1)
setValue((current) => current + 1)
})
return dispose
})
assert.strictEqual(observed, 2)
dispose()
})
})
describe("useAtomInitialValues", () => {
it("applies initial values once per registry", () => {
const registry = AtomRegistry.make()
const atom = Atom.make(0)
createRoot((dispose) => {
createComponent(RegistryContext.Provider, {
value: registry,
get children() {
useAtomInitialValues([[atom, 1]])
useAtomInitialValues([[atom, 2]])
assert.strictEqual(registry.get(atom), 1)
return null
}
})
return dispose
})
})
})
describe("AtomRef", () => {
it("updates when AtomRef changes", () => {
const ref = AtomRef.make(0)
let observed: number | undefined
const dispose = renderAtomRef(ref, (value) => {
observed = value
})
assert.strictEqual(observed, 0)
ref.set(1)
assert.strictEqual(observed, 1)
dispose()
})
it("updates when AtomRef prop changes", () => {
const ref = AtomRef.make({ count: 0, label: "a" })
const propRef = useAtomRefProp(() => ref, "count")
let observed: number | undefined
const dispose = renderAtomRef(propRef(), (value) => {
observed = value
})
assert.strictEqual(observed, 0)
ref.set({ count: 1, label: "a" })
assert.strictEqual(observed, 1)
dispose()
})
it("updates when AtomRef prop value changes", () => {
const ref = AtomRef.make({ count: 0, label: "a" })
let observed: number | undefined
const dispose = renderAccessor(() => useAtomRefPropValue(() => ref, "count"), (value) => {
observed = value
})
assert.strictEqual(observed, 0)
ref.set({ count: 2, label: "a" })
assert.strictEqual(observed, 2)
dispose()
})
})
describe("useAtomResource", () => {
it("suspends on Initial result", () => {
const atom = Atom.make(AsyncResult.initial<number, Error>())
const { resource, dispose } = renderAtomResource(() => atom)
assert.strictEqual(resource.loading, true)
assert.strictEqual(resource(), undefined)
dispose()
})
})
//
// it("suspends on waiting when suspendOnWaiting is true", () => {
// const atom = Atom.make(AsyncResult.success(1, { waiting: true }))
// const { resource, dispose } = renderAtomResource(atom, { suspendOnWaiting: true })
// assert.strictEqual(resource.loading, true)
// assert.strictEqual(resource(), undefined)
// dispose()
// })
//
// it("returns success value by default", async () => {
// const atom = Atom.make(AsyncResult.success(5, { waiting: true }))
// const { resource, dispose } = renderAtomResource(atom)
// await Promise.resolve()
// await Promise.resolve()
// assert.strictEqual(resource.loading, false)
// assert.strictEqual(resource(), 5)
// dispose()
// })
//
// it("surfaces failure via Cause.squash", async () => {
// const error = new Error("boom")
// const atom = Atom.make(AsyncResult.fail(error))
// let resource: ReturnType<typeof useAtomResource>[0] | undefined
// let caught: unknown
// const dispose = createRoot((dispose) => {
// catchError(() => {
// ;[resource] = useAtomResource(atom)
// createEffect(() => {
// resource?.()
// })
// }, (err) => {
// caught = err
// })
// return dispose
// })
// await Promise.resolve()
// await Promise.resolve()
// assert.ok(caught instanceof Error)
// assert.strictEqual(caught.message, "boom")
// assert.strictEqual(resource?.error, caught)
// assert.strictEqual(resource?.loading, false)
// dispose()
// })
//
// it("preserves success result when preserveResult is true", async () => {
// const atom = Atom.make(Effect.succeed(7))
// const { resource, dispose } = renderAtomResource(atom, { preserveResult: true })
// await Promise.resolve()
// await Promise.resolve()
// const result = resource()!
// assert.strictEqual(AsyncResult.isSuccess(result), true)
// if (AsyncResult.isSuccess(result)) {
// assert.strictEqual(result.value, 7)
// }
// assert.strictEqual(resource.error, undefined)
// dispose()
// })
//
// it("preserves failure result when preserveResult is true", async () => {
// const error = new Error("failure")
// const atom = Atom.make(Effect.fail(error))
// const { resource, dispose } = renderAtomResource(atom, { preserveResult: true })
// await Promise.resolve()
// await Promise.resolve()
// const result = resource()!
// assert.strictEqual(AsyncResult.isFailure(result), true)
// if (AsyncResult.isFailure(result)) {
// const squashed = Cause.squash(result.cause)
// assert.ok(squashed instanceof Error)
// assert.strictEqual(squashed.message, "failure")
// }
// assert.strictEqual(resource.error, undefined)
// dispose()
// })
// })
})
const renderAtomRef = function<A>(ref: AtomRef.ReadonlyRef<A>, onValue: (_: A) => void) {
return createRoot((dispose) => {
const accessor = useAtomRef(() => ref)
createEffect(() => {
onValue(accessor())
})
return dispose
})
}
const renderAccessor = function<A>(makeAccessor: () => Accessor<A>, onValue: (_: A) => void) {
return createRoot((dispose) => {
const accessor = makeAccessor()
createEffect(() => {
onValue(accessor())
})
return dispose
})
}
const renderAtomValue = function<A, B = A>(
atom: Atom.Atom<A>,
onValue: (_: B) => void,
options?: { readonly registry?: AtomRegistry.AtomRegistry; readonly map?: (_: A) => B }
) {
return createRoot((dispose) => {
const run = () => {
const accessor = options?.map ? useAtomValue(() => atom, options.map) : useAtomValue(() => atom)
createEffect(() => {
onValue(accessor() as B)
})
return null
}
if (options?.registry) {
createComponent(RegistryContext.Provider, {
value: options.registry,
get children() {
return run()
}
})
} else {
run()
}
return dispose
})
}
const renderAtomResource = function<A, E>(
atom: () => Atom.Atom<AsyncResult.AsyncResult<A, E>>,
options?: {
readonly suspendOnWaiting?: boolean | undefined
}
) {
let resource:
| Resource<A>
| undefined
const dispose = createRoot((dispose) => {
;[resource] = useAtomResource(atom, options)
createEffect(() => {
resource?.()
})
return dispose
})
return { resource: resource!, dispose }
}

View File

@@ -0,0 +1,8 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "../../../tsconfig.base.json",
"include": ["src"],
"references": [
{ "path": "../../effect" }
]
}

View File

@@ -0,0 +1,15 @@
import { mergeConfig } from "vitest/config"
import shared from "../../../vitest.shared.ts"
export default mergeConfig(shared, {
resolve: {
conditions: ["browser"]
},
esbuild: {
target: "es2022"
},
test: {
environment: "jsdom",
setupFiles: ["./vitest.setup.ts"]
}
})

View File

@@ -0,0 +1,8 @@
// oxlint-disable-next-line no-unassigned-import
import "@testing-library/jest-dom/vitest"
import { cleanup } from "@solidjs/testing-library"
import { afterEach } from "vitest"
afterEach(() => {
cleanup()
})

Some files were not shown because too many files have changed in this diff Show More