diff --git a/.changeset/great-eyes-buy.md b/.changeset/great-eyes-buy.md deleted file mode 100644 index cc3e582e742..00000000000 --- a/.changeset/great-eyes-buy.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -"@effect/ai-amazon-bedrock": minor -"@effect/ai-openrouter": minor -"@effect/ai-anthropic": minor -"@effect/ai-google": minor -"@effect/ai-openai": minor -"@effect/ai": minor ---- - -Remove `Either` / `EitherEncoded` from tool call results. - -Specifically, the encoding of tool call results as an `Either` / `EitherEncoded` has been removed and is replaced by encoding the tool call success / failure directly into the `result` property. - -To allow type-safe discrimination between a tool call result which was a success vs. one that was a failure, an `isFailure` property has also been added to the `"tool-result"` part. If `isFailure` is `true`, then the tool call handler result was an error. - -```ts -import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient" -import * as AnthropicLanguageModel from "@effect/ai-anthropic/AnthropicLanguageModel" -import * as LanguageModel from "@effect/ai/LanguageModel" -import * as Tool from "@effect/ai/Tool" -import * as Toolkit from "@effect/ai/Toolkit" -import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient" -import { Config, Effect, Layer, Schema, Stream } from "effect" - -const Claude = AnthropicLanguageModel.model("claude-4-sonnet-20250514") - -const MyTool = Tool.make("MyTool", { - description: "An example of a tool with success and failure types", - failureMode: "return", // Return errors in the response - parameters: { bar: Schema.Number }, - success: Schema.Number, - failure: Schema.Struct({ reason: Schema.Literal("reason-1", "reason-2") }) -}) - -const MyToolkit = Toolkit.make(MyTool) - -const MyToolkitLayer = MyToolkit.toLayer({ - MyTool: () => Effect.succeed(42) -}) - -const program = LanguageModel.streamText({ - prompt: "Tell me about the meaning of life", - toolkit: MyToolkit -}).pipe( - Stream.runForEach((part) => { - if (part.type === "tool-result" && part.name === "MyTool") { - // The `isFailure` property can be used to discriminate whether the result - // of a tool call is a success or a failure - if (part.isFailure) { - part.result - // ^? { readonly reason: "reason-1" | "reason-2"; } - } else { - part.result - // ^? number - } - } - return Effect.void - }), - Effect.provide(Claude) -) - -const Anthropic = AnthropicClient.layerConfig({ - apiKey: Config.redacted("ANTHROPIC_API_KEY") -}).pipe(Layer.provide(NodeHttpClient.layerUndici)) - -program.pipe( - Effect.provide([Anthropic, MyToolkitLayer]), - Effect.runPromise -) -``` diff --git a/packages/ai/ai/CHANGELOG.md b/packages/ai/ai/CHANGELOG.md index f86267614a9..de32edec51f 100644 --- a/packages/ai/ai/CHANGELOG.md +++ b/packages/ai/ai/CHANGELOG.md @@ -1,5 +1,68 @@ # @effect/ai +## 0.31.0 + +### Minor Changes + +- [#5621](https://github.com/Effect-TS/effect/pull/5621) [`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825) Thanks @IMax153! - Remove `Either` / `EitherEncoded` from tool call results. + + Specifically, the encoding of tool call results as an `Either` / `EitherEncoded` has been removed and is replaced by encoding the tool call success / failure directly into the `result` property. + + To allow type-safe discrimination between a tool call result which was a success vs. one that was a failure, an `isFailure` property has also been added to the `"tool-result"` part. If `isFailure` is `true`, then the tool call handler result was an error. + + ```ts + import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient" + import * as AnthropicLanguageModel from "@effect/ai-anthropic/AnthropicLanguageModel" + import * as LanguageModel from "@effect/ai/LanguageModel" + import * as Tool from "@effect/ai/Tool" + import * as Toolkit from "@effect/ai/Toolkit" + import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient" + import { Config, Effect, Layer, Schema, Stream } from "effect" + + const Claude = AnthropicLanguageModel.model("claude-4-sonnet-20250514") + + const MyTool = Tool.make("MyTool", { + description: "An example of a tool with success and failure types", + failureMode: "return", // Return errors in the response + parameters: { bar: Schema.Number }, + success: Schema.Number, + failure: Schema.Struct({ reason: Schema.Literal("reason-1", "reason-2") }) + }) + + const MyToolkit = Toolkit.make(MyTool) + + const MyToolkitLayer = MyToolkit.toLayer({ + MyTool: () => Effect.succeed(42) + }) + + const program = LanguageModel.streamText({ + prompt: "Tell me about the meaning of life", + toolkit: MyToolkit + }).pipe( + Stream.runForEach((part) => { + if (part.type === "tool-result" && part.name === "MyTool") { + // The `isFailure` property can be used to discriminate whether the result + // of a tool call is a success or a failure + if (part.isFailure) { + part.result + // ^? { readonly reason: "reason-1" | "reason-2"; } + } else { + part.result + // ^? number + } + } + return Effect.void + }), + Effect.provide(Claude) + ) + + const Anthropic = AnthropicClient.layerConfig({ + apiKey: Config.redacted("ANTHROPIC_API_KEY") + }).pipe(Layer.provide(NodeHttpClient.layerUndici)) + + program.pipe(Effect.provide([Anthropic, MyToolkitLayer]), Effect.runPromise) + ``` + ## 0.30.0 ### Minor Changes diff --git a/packages/ai/ai/package.json b/packages/ai/ai/package.json index 94aed1f66d0..a8f5d8f884e 100644 --- a/packages/ai/ai/package.json +++ b/packages/ai/ai/package.json @@ -1,7 +1,7 @@ { "name": "@effect/ai", "type": "module", - "version": "0.30.0", + "version": "0.31.0", "license": "MIT", "description": "Effect modules for working with AI apis", "homepage": "https://effect.website", diff --git a/packages/ai/amazon-bedrock/CHANGELOG.md b/packages/ai/amazon-bedrock/CHANGELOG.md index ca9cd16ca7f..eee4461aff8 100644 --- a/packages/ai/amazon-bedrock/CHANGELOG.md +++ b/packages/ai/amazon-bedrock/CHANGELOG.md @@ -1,5 +1,74 @@ # @effect/ai-amazon-bedrock +## 0.11.0 + +### Minor Changes + +- [#5621](https://github.com/Effect-TS/effect/pull/5621) [`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825) Thanks @IMax153! - Remove `Either` / `EitherEncoded` from tool call results. + + Specifically, the encoding of tool call results as an `Either` / `EitherEncoded` has been removed and is replaced by encoding the tool call success / failure directly into the `result` property. + + To allow type-safe discrimination between a tool call result which was a success vs. one that was a failure, an `isFailure` property has also been added to the `"tool-result"` part. If `isFailure` is `true`, then the tool call handler result was an error. + + ```ts + import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient" + import * as AnthropicLanguageModel from "@effect/ai-anthropic/AnthropicLanguageModel" + import * as LanguageModel from "@effect/ai/LanguageModel" + import * as Tool from "@effect/ai/Tool" + import * as Toolkit from "@effect/ai/Toolkit" + import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient" + import { Config, Effect, Layer, Schema, Stream } from "effect" + + const Claude = AnthropicLanguageModel.model("claude-4-sonnet-20250514") + + const MyTool = Tool.make("MyTool", { + description: "An example of a tool with success and failure types", + failureMode: "return", // Return errors in the response + parameters: { bar: Schema.Number }, + success: Schema.Number, + failure: Schema.Struct({ reason: Schema.Literal("reason-1", "reason-2") }) + }) + + const MyToolkit = Toolkit.make(MyTool) + + const MyToolkitLayer = MyToolkit.toLayer({ + MyTool: () => Effect.succeed(42) + }) + + const program = LanguageModel.streamText({ + prompt: "Tell me about the meaning of life", + toolkit: MyToolkit + }).pipe( + Stream.runForEach((part) => { + if (part.type === "tool-result" && part.name === "MyTool") { + // The `isFailure` property can be used to discriminate whether the result + // of a tool call is a success or a failure + if (part.isFailure) { + part.result + // ^? { readonly reason: "reason-1" | "reason-2"; } + } else { + part.result + // ^? number + } + } + return Effect.void + }), + Effect.provide(Claude) + ) + + const Anthropic = AnthropicClient.layerConfig({ + apiKey: Config.redacted("ANTHROPIC_API_KEY") + }).pipe(Layer.provide(NodeHttpClient.layerUndici)) + + program.pipe(Effect.provide([Anthropic, MyToolkitLayer]), Effect.runPromise) + ``` + +### Patch Changes + +- Updated dependencies [[`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825)]: + - @effect/ai-anthropic@0.21.0 + - @effect/ai@0.31.0 + ## 0.10.0 ### Minor Changes diff --git a/packages/ai/amazon-bedrock/package.json b/packages/ai/amazon-bedrock/package.json index a94995960f5..66eb46308bf 100644 --- a/packages/ai/amazon-bedrock/package.json +++ b/packages/ai/amazon-bedrock/package.json @@ -1,7 +1,7 @@ { "name": "@effect/ai-amazon-bedrock", "type": "module", - "version": "0.10.0", + "version": "0.11.0", "license": "MIT", "description": "Effect modules for working with Amazon Bedrock AI apis", "homepage": "https://effect.website", diff --git a/packages/ai/anthropic/CHANGELOG.md b/packages/ai/anthropic/CHANGELOG.md index aba262675e8..340a61ab09a 100644 --- a/packages/ai/anthropic/CHANGELOG.md +++ b/packages/ai/anthropic/CHANGELOG.md @@ -1,5 +1,73 @@ # @effect/ai-anthropic +## 0.21.0 + +### Minor Changes + +- [#5621](https://github.com/Effect-TS/effect/pull/5621) [`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825) Thanks @IMax153! - Remove `Either` / `EitherEncoded` from tool call results. + + Specifically, the encoding of tool call results as an `Either` / `EitherEncoded` has been removed and is replaced by encoding the tool call success / failure directly into the `result` property. + + To allow type-safe discrimination between a tool call result which was a success vs. one that was a failure, an `isFailure` property has also been added to the `"tool-result"` part. If `isFailure` is `true`, then the tool call handler result was an error. + + ```ts + import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient" + import * as AnthropicLanguageModel from "@effect/ai-anthropic/AnthropicLanguageModel" + import * as LanguageModel from "@effect/ai/LanguageModel" + import * as Tool from "@effect/ai/Tool" + import * as Toolkit from "@effect/ai/Toolkit" + import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient" + import { Config, Effect, Layer, Schema, Stream } from "effect" + + const Claude = AnthropicLanguageModel.model("claude-4-sonnet-20250514") + + const MyTool = Tool.make("MyTool", { + description: "An example of a tool with success and failure types", + failureMode: "return", // Return errors in the response + parameters: { bar: Schema.Number }, + success: Schema.Number, + failure: Schema.Struct({ reason: Schema.Literal("reason-1", "reason-2") }) + }) + + const MyToolkit = Toolkit.make(MyTool) + + const MyToolkitLayer = MyToolkit.toLayer({ + MyTool: () => Effect.succeed(42) + }) + + const program = LanguageModel.streamText({ + prompt: "Tell me about the meaning of life", + toolkit: MyToolkit + }).pipe( + Stream.runForEach((part) => { + if (part.type === "tool-result" && part.name === "MyTool") { + // The `isFailure` property can be used to discriminate whether the result + // of a tool call is a success or a failure + if (part.isFailure) { + part.result + // ^? { readonly reason: "reason-1" | "reason-2"; } + } else { + part.result + // ^? number + } + } + return Effect.void + }), + Effect.provide(Claude) + ) + + const Anthropic = AnthropicClient.layerConfig({ + apiKey: Config.redacted("ANTHROPIC_API_KEY") + }).pipe(Layer.provide(NodeHttpClient.layerUndici)) + + program.pipe(Effect.provide([Anthropic, MyToolkitLayer]), Effect.runPromise) + ``` + +### Patch Changes + +- Updated dependencies [[`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825)]: + - @effect/ai@0.31.0 + ## 0.20.0 ### Minor Changes diff --git a/packages/ai/anthropic/package.json b/packages/ai/anthropic/package.json index 907351eed01..c030d8a4804 100644 --- a/packages/ai/anthropic/package.json +++ b/packages/ai/anthropic/package.json @@ -1,7 +1,7 @@ { "name": "@effect/ai-anthropic", "type": "module", - "version": "0.20.0", + "version": "0.21.0", "license": "MIT", "description": "Effect modules for working with AI apis", "homepage": "https://effect.website", diff --git a/packages/ai/google/CHANGELOG.md b/packages/ai/google/CHANGELOG.md index 35780f23c15..dd8bec7f280 100644 --- a/packages/ai/google/CHANGELOG.md +++ b/packages/ai/google/CHANGELOG.md @@ -1,5 +1,73 @@ # @effect/ai-google +## 0.10.0 + +### Minor Changes + +- [#5621](https://github.com/Effect-TS/effect/pull/5621) [`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825) Thanks @IMax153! - Remove `Either` / `EitherEncoded` from tool call results. + + Specifically, the encoding of tool call results as an `Either` / `EitherEncoded` has been removed and is replaced by encoding the tool call success / failure directly into the `result` property. + + To allow type-safe discrimination between a tool call result which was a success vs. one that was a failure, an `isFailure` property has also been added to the `"tool-result"` part. If `isFailure` is `true`, then the tool call handler result was an error. + + ```ts + import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient" + import * as AnthropicLanguageModel from "@effect/ai-anthropic/AnthropicLanguageModel" + import * as LanguageModel from "@effect/ai/LanguageModel" + import * as Tool from "@effect/ai/Tool" + import * as Toolkit from "@effect/ai/Toolkit" + import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient" + import { Config, Effect, Layer, Schema, Stream } from "effect" + + const Claude = AnthropicLanguageModel.model("claude-4-sonnet-20250514") + + const MyTool = Tool.make("MyTool", { + description: "An example of a tool with success and failure types", + failureMode: "return", // Return errors in the response + parameters: { bar: Schema.Number }, + success: Schema.Number, + failure: Schema.Struct({ reason: Schema.Literal("reason-1", "reason-2") }) + }) + + const MyToolkit = Toolkit.make(MyTool) + + const MyToolkitLayer = MyToolkit.toLayer({ + MyTool: () => Effect.succeed(42) + }) + + const program = LanguageModel.streamText({ + prompt: "Tell me about the meaning of life", + toolkit: MyToolkit + }).pipe( + Stream.runForEach((part) => { + if (part.type === "tool-result" && part.name === "MyTool") { + // The `isFailure` property can be used to discriminate whether the result + // of a tool call is a success or a failure + if (part.isFailure) { + part.result + // ^? { readonly reason: "reason-1" | "reason-2"; } + } else { + part.result + // ^? number + } + } + return Effect.void + }), + Effect.provide(Claude) + ) + + const Anthropic = AnthropicClient.layerConfig({ + apiKey: Config.redacted("ANTHROPIC_API_KEY") + }).pipe(Layer.provide(NodeHttpClient.layerUndici)) + + program.pipe(Effect.provide([Anthropic, MyToolkitLayer]), Effect.runPromise) + ``` + +### Patch Changes + +- Updated dependencies [[`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825)]: + - @effect/ai@0.31.0 + ## 0.9.0 ### Minor Changes diff --git a/packages/ai/google/package.json b/packages/ai/google/package.json index d8ae6fd3a6b..507eb2da68d 100644 --- a/packages/ai/google/package.json +++ b/packages/ai/google/package.json @@ -1,7 +1,7 @@ { "name": "@effect/ai-google", "type": "module", - "version": "0.9.0", + "version": "0.10.0", "license": "MIT", "description": "Effect modules for working with AI apis", "homepage": "https://effect.website", diff --git a/packages/ai/openai/CHANGELOG.md b/packages/ai/openai/CHANGELOG.md index 5e1a6fbe540..001658f7fb3 100644 --- a/packages/ai/openai/CHANGELOG.md +++ b/packages/ai/openai/CHANGELOG.md @@ -1,5 +1,73 @@ # @effect/ai-openai +## 0.34.0 + +### Minor Changes + +- [#5621](https://github.com/Effect-TS/effect/pull/5621) [`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825) Thanks @IMax153! - Remove `Either` / `EitherEncoded` from tool call results. + + Specifically, the encoding of tool call results as an `Either` / `EitherEncoded` has been removed and is replaced by encoding the tool call success / failure directly into the `result` property. + + To allow type-safe discrimination between a tool call result which was a success vs. one that was a failure, an `isFailure` property has also been added to the `"tool-result"` part. If `isFailure` is `true`, then the tool call handler result was an error. + + ```ts + import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient" + import * as AnthropicLanguageModel from "@effect/ai-anthropic/AnthropicLanguageModel" + import * as LanguageModel from "@effect/ai/LanguageModel" + import * as Tool from "@effect/ai/Tool" + import * as Toolkit from "@effect/ai/Toolkit" + import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient" + import { Config, Effect, Layer, Schema, Stream } from "effect" + + const Claude = AnthropicLanguageModel.model("claude-4-sonnet-20250514") + + const MyTool = Tool.make("MyTool", { + description: "An example of a tool with success and failure types", + failureMode: "return", // Return errors in the response + parameters: { bar: Schema.Number }, + success: Schema.Number, + failure: Schema.Struct({ reason: Schema.Literal("reason-1", "reason-2") }) + }) + + const MyToolkit = Toolkit.make(MyTool) + + const MyToolkitLayer = MyToolkit.toLayer({ + MyTool: () => Effect.succeed(42) + }) + + const program = LanguageModel.streamText({ + prompt: "Tell me about the meaning of life", + toolkit: MyToolkit + }).pipe( + Stream.runForEach((part) => { + if (part.type === "tool-result" && part.name === "MyTool") { + // The `isFailure` property can be used to discriminate whether the result + // of a tool call is a success or a failure + if (part.isFailure) { + part.result + // ^? { readonly reason: "reason-1" | "reason-2"; } + } else { + part.result + // ^? number + } + } + return Effect.void + }), + Effect.provide(Claude) + ) + + const Anthropic = AnthropicClient.layerConfig({ + apiKey: Config.redacted("ANTHROPIC_API_KEY") + }).pipe(Layer.provide(NodeHttpClient.layerUndici)) + + program.pipe(Effect.provide([Anthropic, MyToolkitLayer]), Effect.runPromise) + ``` + +### Patch Changes + +- Updated dependencies [[`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825)]: + - @effect/ai@0.31.0 + ## 0.33.0 ### Minor Changes diff --git a/packages/ai/openai/package.json b/packages/ai/openai/package.json index 3017ad8d54e..196380f6552 100644 --- a/packages/ai/openai/package.json +++ b/packages/ai/openai/package.json @@ -1,7 +1,7 @@ { "name": "@effect/ai-openai", "type": "module", - "version": "0.33.0", + "version": "0.34.0", "license": "MIT", "description": "Effect modules for working with AI apis", "homepage": "https://effect.website", diff --git a/packages/ai/openrouter/CHANGELOG.md b/packages/ai/openrouter/CHANGELOG.md index b57baf1ffbf..e3bb3d8604b 100644 --- a/packages/ai/openrouter/CHANGELOG.md +++ b/packages/ai/openrouter/CHANGELOG.md @@ -1,5 +1,73 @@ # @effect/ai-openrouter +## 0.5.0 + +### Minor Changes + +- [#5621](https://github.com/Effect-TS/effect/pull/5621) [`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825) Thanks @IMax153! - Remove `Either` / `EitherEncoded` from tool call results. + + Specifically, the encoding of tool call results as an `Either` / `EitherEncoded` has been removed and is replaced by encoding the tool call success / failure directly into the `result` property. + + To allow type-safe discrimination between a tool call result which was a success vs. one that was a failure, an `isFailure` property has also been added to the `"tool-result"` part. If `isFailure` is `true`, then the tool call handler result was an error. + + ```ts + import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient" + import * as AnthropicLanguageModel from "@effect/ai-anthropic/AnthropicLanguageModel" + import * as LanguageModel from "@effect/ai/LanguageModel" + import * as Tool from "@effect/ai/Tool" + import * as Toolkit from "@effect/ai/Toolkit" + import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient" + import { Config, Effect, Layer, Schema, Stream } from "effect" + + const Claude = AnthropicLanguageModel.model("claude-4-sonnet-20250514") + + const MyTool = Tool.make("MyTool", { + description: "An example of a tool with success and failure types", + failureMode: "return", // Return errors in the response + parameters: { bar: Schema.Number }, + success: Schema.Number, + failure: Schema.Struct({ reason: Schema.Literal("reason-1", "reason-2") }) + }) + + const MyToolkit = Toolkit.make(MyTool) + + const MyToolkitLayer = MyToolkit.toLayer({ + MyTool: () => Effect.succeed(42) + }) + + const program = LanguageModel.streamText({ + prompt: "Tell me about the meaning of life", + toolkit: MyToolkit + }).pipe( + Stream.runForEach((part) => { + if (part.type === "tool-result" && part.name === "MyTool") { + // The `isFailure` property can be used to discriminate whether the result + // of a tool call is a success or a failure + if (part.isFailure) { + part.result + // ^? { readonly reason: "reason-1" | "reason-2"; } + } else { + part.result + // ^? number + } + } + return Effect.void + }), + Effect.provide(Claude) + ) + + const Anthropic = AnthropicClient.layerConfig({ + apiKey: Config.redacted("ANTHROPIC_API_KEY") + }).pipe(Layer.provide(NodeHttpClient.layerUndici)) + + program.pipe(Effect.provide([Anthropic, MyToolkitLayer]), Effect.runPromise) + ``` + +### Patch Changes + +- Updated dependencies [[`4c3bdfb`](https://github.com/Effect-TS/effect/commit/4c3bdfbcbc2dcd7ecd6321df3e4a504af19de825)]: + - @effect/ai@0.31.0 + ## 0.4.0 ### Minor Changes diff --git a/packages/ai/openrouter/package.json b/packages/ai/openrouter/package.json index 2a5355e505c..68410a38210 100644 --- a/packages/ai/openrouter/package.json +++ b/packages/ai/openrouter/package.json @@ -1,7 +1,7 @@ { "name": "@effect/ai-openrouter", "type": "module", - "version": "0.4.0", + "version": "0.5.0", "license": "MIT", "description": "Effect modules for working with AI apis", "homepage": "https://effect.website",