@effect/ai 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/Chat/package.json +6 -0
  2. package/EmbeddingModel/package.json +6 -0
  3. package/IdGenerator/package.json +6 -0
  4. package/LanguageModel/package.json +6 -0
  5. package/Model/package.json +6 -0
  6. package/Prompt/package.json +6 -0
  7. package/Response/package.json +6 -0
  8. package/Telemetry/package.json +6 -0
  9. package/Tool/package.json +6 -0
  10. package/Toolkit/package.json +6 -0
  11. package/dist/cjs/AiError.js +575 -11
  12. package/dist/cjs/AiError.js.map +1 -1
  13. package/dist/cjs/Chat.js +302 -0
  14. package/dist/cjs/Chat.js.map +1 -0
  15. package/dist/cjs/EmbeddingModel.js +184 -0
  16. package/dist/cjs/EmbeddingModel.js.map +1 -0
  17. package/dist/cjs/IdGenerator.js +255 -0
  18. package/dist/cjs/IdGenerator.js.map +1 -0
  19. package/dist/cjs/LanguageModel.js +584 -0
  20. package/dist/cjs/LanguageModel.js.map +1 -0
  21. package/dist/cjs/McpServer.js +12 -4
  22. package/dist/cjs/McpServer.js.map +1 -1
  23. package/dist/cjs/Model.js +118 -0
  24. package/dist/cjs/Model.js.map +1 -0
  25. package/dist/cjs/Prompt.js +649 -0
  26. package/dist/cjs/Prompt.js.map +1 -0
  27. package/dist/cjs/Response.js +635 -0
  28. package/dist/cjs/Response.js.map +1 -0
  29. package/dist/cjs/Telemetry.js +176 -0
  30. package/dist/cjs/Telemetry.js.map +1 -0
  31. package/dist/cjs/Tokenizer.js +87 -8
  32. package/dist/cjs/Tokenizer.js.map +1 -1
  33. package/dist/cjs/Tool.js +556 -0
  34. package/dist/cjs/Tool.js.map +1 -0
  35. package/dist/cjs/Toolkit.js +279 -0
  36. package/dist/cjs/Toolkit.js.map +1 -0
  37. package/dist/cjs/index.js +21 -19
  38. package/dist/dts/AiError.d.ts +577 -9
  39. package/dist/dts/AiError.d.ts.map +1 -1
  40. package/dist/dts/Chat.d.ts +356 -0
  41. package/dist/dts/Chat.d.ts.map +1 -0
  42. package/dist/dts/EmbeddingModel.d.ts +153 -0
  43. package/dist/dts/EmbeddingModel.d.ts.map +1 -0
  44. package/dist/dts/IdGenerator.d.ts +272 -0
  45. package/dist/dts/IdGenerator.d.ts.map +1 -0
  46. package/dist/dts/LanguageModel.d.ts +458 -0
  47. package/dist/dts/LanguageModel.d.ts.map +1 -0
  48. package/dist/dts/McpSchema.d.ts +25 -25
  49. package/dist/dts/McpServer.d.ts +6 -4
  50. package/dist/dts/McpServer.d.ts.map +1 -1
  51. package/dist/dts/Model.d.ts +124 -0
  52. package/dist/dts/Model.d.ts.map +1 -0
  53. package/dist/dts/Prompt.d.ts +1119 -0
  54. package/dist/dts/Prompt.d.ts.map +1 -0
  55. package/dist/dts/Response.d.ts +1519 -0
  56. package/dist/dts/Response.d.ts.map +1 -0
  57. package/dist/dts/Telemetry.d.ts +520 -0
  58. package/dist/dts/Telemetry.d.ts.map +1 -0
  59. package/dist/dts/Tokenizer.d.ts +131 -13
  60. package/dist/dts/Tokenizer.d.ts.map +1 -1
  61. package/dist/dts/Tool.d.ts +876 -0
  62. package/dist/dts/Tool.d.ts.map +1 -0
  63. package/dist/dts/Toolkit.d.ts +310 -0
  64. package/dist/dts/Toolkit.d.ts.map +1 -0
  65. package/dist/dts/index.d.ts +498 -13
  66. package/dist/dts/index.d.ts.map +1 -1
  67. package/dist/esm/AiError.js +570 -10
  68. package/dist/esm/AiError.js.map +1 -1
  69. package/dist/esm/Chat.js +291 -0
  70. package/dist/esm/Chat.js.map +1 -0
  71. package/dist/esm/EmbeddingModel.js +173 -0
  72. package/dist/esm/EmbeddingModel.js.map +1 -0
  73. package/dist/esm/IdGenerator.js +245 -0
  74. package/dist/esm/IdGenerator.js.map +1 -0
  75. package/dist/esm/LanguageModel.js +572 -0
  76. package/dist/esm/LanguageModel.js.map +1 -0
  77. package/dist/esm/McpServer.js +12 -4
  78. package/dist/esm/McpServer.js.map +1 -1
  79. package/dist/esm/Model.js +108 -0
  80. package/dist/esm/Model.js.map +1 -0
  81. package/dist/esm/Prompt.js +633 -0
  82. package/dist/esm/Prompt.js.map +1 -0
  83. package/dist/esm/Response.js +619 -0
  84. package/dist/esm/Response.js.map +1 -0
  85. package/dist/esm/Telemetry.js +166 -0
  86. package/dist/esm/Telemetry.js.map +1 -0
  87. package/dist/esm/Tokenizer.js +87 -8
  88. package/dist/esm/Tokenizer.js.map +1 -1
  89. package/dist/esm/Tool.js +534 -0
  90. package/dist/esm/Tool.js.map +1 -0
  91. package/dist/esm/Toolkit.js +269 -0
  92. package/dist/esm/Toolkit.js.map +1 -0
  93. package/dist/esm/index.js +498 -13
  94. package/dist/esm/index.js.map +1 -1
  95. package/package.json +76 -68
  96. package/src/AiError.ts +739 -9
  97. package/src/Chat.ts +546 -0
  98. package/src/EmbeddingModel.ts +311 -0
  99. package/src/IdGenerator.ts +320 -0
  100. package/src/LanguageModel.ts +1074 -0
  101. package/src/McpServer.ts +337 -194
  102. package/src/Model.ts +155 -0
  103. package/src/Prompt.ts +1616 -0
  104. package/src/Response.ts +2131 -0
  105. package/src/Telemetry.ts +655 -0
  106. package/src/Tokenizer.ts +145 -24
  107. package/src/Tool.ts +1267 -0
  108. package/src/Toolkit.ts +516 -0
  109. package/src/index.ts +499 -13
  110. package/AiChat/package.json +0 -6
  111. package/AiEmbeddingModel/package.json +0 -6
  112. package/AiInput/package.json +0 -6
  113. package/AiLanguageModel/package.json +0 -6
  114. package/AiModel/package.json +0 -6
  115. package/AiResponse/package.json +0 -6
  116. package/AiTelemetry/package.json +0 -6
  117. package/AiTool/package.json +0 -6
  118. package/AiToolkit/package.json +0 -6
  119. package/dist/cjs/AiChat.js +0 -122
  120. package/dist/cjs/AiChat.js.map +0 -1
  121. package/dist/cjs/AiEmbeddingModel.js +0 -109
  122. package/dist/cjs/AiEmbeddingModel.js.map +0 -1
  123. package/dist/cjs/AiInput.js +0 -458
  124. package/dist/cjs/AiInput.js.map +0 -1
  125. package/dist/cjs/AiLanguageModel.js +0 -351
  126. package/dist/cjs/AiLanguageModel.js.map +0 -1
  127. package/dist/cjs/AiModel.js +0 -37
  128. package/dist/cjs/AiModel.js.map +0 -1
  129. package/dist/cjs/AiResponse.js +0 -681
  130. package/dist/cjs/AiResponse.js.map +0 -1
  131. package/dist/cjs/AiTelemetry.js +0 -58
  132. package/dist/cjs/AiTelemetry.js.map +0 -1
  133. package/dist/cjs/AiTool.js +0 -150
  134. package/dist/cjs/AiTool.js.map +0 -1
  135. package/dist/cjs/AiToolkit.js +0 -157
  136. package/dist/cjs/AiToolkit.js.map +0 -1
  137. package/dist/cjs/internal/common.js +0 -21
  138. package/dist/cjs/internal/common.js.map +0 -1
  139. package/dist/dts/AiChat.d.ts +0 -101
  140. package/dist/dts/AiChat.d.ts.map +0 -1
  141. package/dist/dts/AiEmbeddingModel.d.ts +0 -65
  142. package/dist/dts/AiEmbeddingModel.d.ts.map +0 -1
  143. package/dist/dts/AiInput.d.ts +0 -590
  144. package/dist/dts/AiInput.d.ts.map +0 -1
  145. package/dist/dts/AiLanguageModel.d.ts +0 -302
  146. package/dist/dts/AiLanguageModel.d.ts.map +0 -1
  147. package/dist/dts/AiModel.d.ts +0 -25
  148. package/dist/dts/AiModel.d.ts.map +0 -1
  149. package/dist/dts/AiResponse.d.ts +0 -863
  150. package/dist/dts/AiResponse.d.ts.map +0 -1
  151. package/dist/dts/AiTelemetry.d.ts +0 -242
  152. package/dist/dts/AiTelemetry.d.ts.map +0 -1
  153. package/dist/dts/AiTool.d.ts +0 -334
  154. package/dist/dts/AiTool.d.ts.map +0 -1
  155. package/dist/dts/AiToolkit.d.ts +0 -96
  156. package/dist/dts/AiToolkit.d.ts.map +0 -1
  157. package/dist/dts/internal/common.d.ts +0 -2
  158. package/dist/dts/internal/common.d.ts.map +0 -1
  159. package/dist/esm/AiChat.js +0 -111
  160. package/dist/esm/AiChat.js.map +0 -1
  161. package/dist/esm/AiEmbeddingModel.js +0 -98
  162. package/dist/esm/AiEmbeddingModel.js.map +0 -1
  163. package/dist/esm/AiInput.js +0 -433
  164. package/dist/esm/AiInput.js.map +0 -1
  165. package/dist/esm/AiLanguageModel.js +0 -340
  166. package/dist/esm/AiLanguageModel.js.map +0 -1
  167. package/dist/esm/AiModel.js +0 -29
  168. package/dist/esm/AiModel.js.map +0 -1
  169. package/dist/esm/AiResponse.js +0 -657
  170. package/dist/esm/AiResponse.js.map +0 -1
  171. package/dist/esm/AiTelemetry.js +0 -48
  172. package/dist/esm/AiTelemetry.js.map +0 -1
  173. package/dist/esm/AiTool.js +0 -134
  174. package/dist/esm/AiTool.js.map +0 -1
  175. package/dist/esm/AiToolkit.js +0 -147
  176. package/dist/esm/AiToolkit.js.map +0 -1
  177. package/dist/esm/internal/common.js +0 -14
  178. package/dist/esm/internal/common.js.map +0 -1
  179. package/src/AiChat.ts +0 -251
  180. package/src/AiEmbeddingModel.ts +0 -169
  181. package/src/AiInput.ts +0 -602
  182. package/src/AiLanguageModel.ts +0 -685
  183. package/src/AiModel.ts +0 -53
  184. package/src/AiResponse.ts +0 -986
  185. package/src/AiTelemetry.ts +0 -333
  186. package/src/AiTool.ts +0 -579
  187. package/src/AiToolkit.ts +0 -265
  188. package/src/internal/common.ts +0 -12
package/src/Tool.ts ADDED
@@ -0,0 +1,1267 @@
1
+ /**
2
+ * The `Tool` module provides functionality for defining and managing tools
3
+ * that language models can call to augment their capabilities.
4
+ *
5
+ * This module enables creation of both user-defined and provider-defined tools,
6
+ * with full schema validation, type safety, and handler support. Tools allow
7
+ * AI models to perform actions like searching databases, calling APIs, or
8
+ * executing code within your application context.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { Tool } from "@effect/ai"
13
+ * import { Schema } from "effect"
14
+ *
15
+ * // Define a simple calculator tool
16
+ * const Calculator = Tool.make("Calculator", {
17
+ * description: "Performs basic arithmetic operations",
18
+ * parameters: {
19
+ * operation: Schema.Literal("add", "subtract", "multiply", "divide"),
20
+ * a: Schema.Number,
21
+ * b: Schema.Number
22
+ * },
23
+ * success: Schema.Number
24
+ * })
25
+ * ```
26
+ *
27
+ * @since 1.0.0
28
+ */
29
+ import * as Context from "effect/Context"
30
+ import * as Effect from "effect/Effect"
31
+ import { constFalse, constTrue, identity } from "effect/Function"
32
+ import * as JsonSchema from "effect/JSONSchema"
33
+ import * as Option from "effect/Option"
34
+ import type { Pipeable } from "effect/Pipeable"
35
+ import { pipeArguments } from "effect/Pipeable"
36
+ import * as Predicate from "effect/Predicate"
37
+ import * as Schema from "effect/Schema"
38
+ import * as AST from "effect/SchemaAST"
39
+ import type { Covariant } from "effect/Types"
40
+ import * as AiError from "./AiError.js"
41
+
42
+ // =============================================================================
43
+ // Type Ids
44
+ // =============================================================================
45
+
46
+ /**
47
+ * Unique identifier for user-defined tools.
48
+ *
49
+ * @since 1.0.0
50
+ * @category Type Ids
51
+ */
52
+ export const TypeId = "~@effect/ai/Tool"
53
+
54
+ /**
55
+ * Type-level representation of the user-defined tool identifier.
56
+ *
57
+ * @since 1.0.0
58
+ * @category Type Ids
59
+ */
60
+ export type TypeId = typeof TypeId
61
+
62
+ /**
63
+ * Unique identifier for provider-defined tools.
64
+ *
65
+ * @since 1.0.0
66
+ * @category Type Ids
67
+ */
68
+ export const ProviderDefinedTypeId = "~@effect/ai/Tool/ProviderDefined"
69
+
70
+ /**
71
+ * Type-level representation of the provider-defined tool identifier.
72
+ *
73
+ * @since 1.0.0
74
+ * @category Type Ids
75
+ */
76
+ export type ProviderDefinedTypeId = typeof ProviderDefinedTypeId
77
+
78
+ // =============================================================================
79
+ // Models
80
+ // =============================================================================
81
+
82
+ /**
83
+ * A user-defined tool that language models can call to perform actions.
84
+ *
85
+ * Tools represent actionable capabilities that large language models can invoke
86
+ * to extend their functionality beyond text generation. Each tool has a defined
87
+ * schema for parameters, results, and failures.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * import { Tool } from "@effect/ai"
92
+ * import { Schema } from "effect"
93
+ *
94
+ * // Create a weather lookup tool
95
+ * const GetWeather = Tool.make("GetWeather", {
96
+ * description: "Get current weather for a location",
97
+ * parameters: {
98
+ * location: Schema.String,
99
+ * units: Schema.Literal("celsius", "fahrenheit")
100
+ * },
101
+ * success: Schema.Struct({
102
+ * temperature: Schema.Number,
103
+ * condition: Schema.String,
104
+ * humidity: Schema.Number
105
+ * })
106
+ * })
107
+ * ```
108
+ *
109
+ * @since 1.0.0
110
+ * @category Models
111
+ */
112
+ export interface Tool<
113
+ Name extends string,
114
+ Config extends {
115
+ readonly parameters: AnyStructSchema
116
+ readonly success: Schema.Schema.Any
117
+ readonly failure: Schema.Schema.All
118
+ } = {
119
+ readonly parameters: Schema.Struct<{}>
120
+ readonly success: typeof Schema.Void
121
+ readonly failure: typeof Schema.Never
122
+ },
123
+ Requirements = never
124
+ > extends Tool.Variance<Requirements> {
125
+ /**
126
+ * The tool identifier which is used to uniquely identify the tool. */
127
+ readonly id: string
128
+
129
+ /**
130
+ * The name of the tool.
131
+ */
132
+ readonly name: Name
133
+
134
+ /**
135
+ * The optional description of the tool.
136
+ */
137
+ readonly description?: string | undefined
138
+
139
+ /**
140
+ * A `Schema` representing the parameters that a tool must be called with.
141
+ */
142
+ readonly parametersSchema: Config["parameters"]
143
+
144
+ /**
145
+ * A `Schema` representing the value that a tool must return when called if
146
+ * the tool call is successful.
147
+ */
148
+ readonly successSchema: Config["success"]
149
+
150
+ /**
151
+ * A `Schema` representing the value that a tool must return when called if
152
+ * it fails.
153
+ */
154
+ readonly failureSchema: Config["failure"]
155
+
156
+ /**
157
+ * A `Context` object containing tool annotations which can store metadata
158
+ * about the tool.
159
+ */
160
+ readonly annotations: Context.Context<never>
161
+
162
+ /**
163
+ * Adds a _request-level_ dependency which must be provided before the tool
164
+ * call handler can be executed.
165
+ *
166
+ * This can be useful when you want to enforce that a particular dependency
167
+ * **MUST** be provided to each request to the large language model provider
168
+ * instead of being provided when creating the tool call handler layer.
169
+ */
170
+ addDependency<Identifier, Service>(tag: Context.Tag<Identifier, Service>): Tool<
171
+ Name,
172
+ Config,
173
+ Identifier | Requirements
174
+ >
175
+
176
+ /**
177
+ * Set the schema to use to validate the result of a tool call when successful.
178
+ */
179
+ setParameters<ParametersSchema extends Schema.Struct<any> | Schema.Struct.Fields>(
180
+ schema: ParametersSchema
181
+ ): Tool<Name, {
182
+ readonly parameters: ParametersSchema extends Schema.Struct<infer _> ? ParametersSchema
183
+ : ParametersSchema extends Schema.Struct.Fields ? Schema.Struct<ParametersSchema>
184
+ : never
185
+ readonly success: Config["success"]
186
+ readonly failure: Config["failure"]
187
+ }, Requirements>
188
+
189
+ /**
190
+ * Set the schema to use to validate the result of a tool call when successful.
191
+ */
192
+ setSuccess<SuccessSchema extends Schema.Schema.Any>(schema: SuccessSchema): Tool<Name, {
193
+ readonly parameters: Config["parameters"]
194
+ readonly success: SuccessSchema
195
+ readonly failure: Config["failure"]
196
+ }, Requirements>
197
+
198
+ /**
199
+ * Set the schema to use to validate the result of a tool call when it fails.
200
+ */
201
+ setFailure<FailureSchema extends Schema.Schema.Any>(schema: FailureSchema): Tool<Name, {
202
+ readonly parameters: Config["parameters"]
203
+ readonly success: Config["success"]
204
+ readonly failure: FailureSchema
205
+ }, Requirements>
206
+
207
+ /**
208
+ * Add an annotation to the tool.
209
+ */
210
+ annotate<I, S>(tag: Context.Tag<I, S>, value: S): Tool<
211
+ Name,
212
+ Config,
213
+ Requirements
214
+ >
215
+
216
+ /**
217
+ * Add many annotations to the tool.
218
+ */
219
+ annotateContext<I>(context: Context.Context<I>): Tool<
220
+ Name,
221
+ Config,
222
+ Requirements
223
+ >
224
+ }
225
+
226
+ /**
227
+ * A provider-defined tool is a tool which is built into a large language model
228
+ * provider (e.g. web search, code execution).
229
+ *
230
+ * These tools are executed by the large language model provider rather than
231
+ * by your application. However, they can optionally require custom handlers
232
+ * implemented in your application to process provider generated results.
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * import { Tool } from "@effect/ai"
237
+ * import { Schema } from "effect"
238
+ *
239
+ * // Define a web search tool provided by OpenAI
240
+ * const WebSearch = Tool.providerDefined({
241
+ * id: "openai.web_search",
242
+ * toolkitName: "WebSearch",
243
+ * providerName: "web_search",
244
+ * args: {
245
+ * query: Schema.String
246
+ * },
247
+ * success: Schema.Struct({
248
+ * results: Schema.Array(Schema.Struct({
249
+ * title: Schema.String,
250
+ * url: Schema.String,
251
+ * snippet: Schema.String
252
+ * }))
253
+ * })
254
+ * })
255
+ * ```
256
+ *
257
+ * @since 1.0.0
258
+ * @category Models
259
+ */
260
+ export interface ProviderDefined<
261
+ Name extends string,
262
+ Config extends {
263
+ readonly args: AnyStructSchema
264
+ readonly parameters: AnyStructSchema
265
+ readonly success: Schema.Schema.Any
266
+ readonly failure: Schema.Schema.All
267
+ } = {
268
+ readonly args: Schema.Struct<{}>
269
+ readonly parameters: Schema.Struct<{}>
270
+ readonly success: typeof Schema.Void
271
+ readonly failure: typeof Schema.Never
272
+ },
273
+ RequiresHandler extends boolean = false
274
+ > extends
275
+ Tool<Name, {
276
+ readonly parameters: Config["parameters"]
277
+ success: RequiresHandler extends true ? Config["success"]
278
+ : Schema.Either<Config["success"], Config["failure"]>
279
+ failure: RequiresHandler extends true ? Config["failure"]
280
+ : typeof Schema.Never
281
+ }>,
282
+ Tool.ProviderDefinedProto
283
+ {
284
+ /**
285
+ * The arguments passed to the provider-defined tool.
286
+ */
287
+ readonly args: Config["args"]["Encoded"]
288
+
289
+ /**
290
+ * A `Schema` representing the arguments provided by the end-user which will
291
+ * be used to configure the behavior of the provider-defined tool.
292
+ */
293
+ readonly argsSchema: Config["args"]
294
+
295
+ /**
296
+ * Name of the tool as recognized by the large language model provider.
297
+ */
298
+ readonly providerName: string
299
+
300
+ /**
301
+ * If set to `true`, this provider-defined tool will require a user-defined
302
+ * tool call handler to be provided when converting the `Toolkit` containing
303
+ * this tool into a `Layer`.
304
+ */
305
+ readonly requiresHandler: RequiresHandler
306
+
307
+ /**
308
+ * Decodes the result received after the provider-defined tool is called.
309
+ */
310
+ decodeResult(args: unknown): Effect.Effect<Config["success"]["Type"], AiError.AiError>
311
+ }
312
+
313
+ /**
314
+ * @since 1.0.0
315
+ */
316
+ export declare namespace Tool {
317
+ /**
318
+ * @since 1.0.0
319
+ * @category Models
320
+ */
321
+ export interface Variance<out Requirements> extends Pipeable {
322
+ readonly [TypeId]: VarianceStruct<Requirements>
323
+ }
324
+
325
+ /**
326
+ * @since 1.0.0
327
+ * @category Models
328
+ */
329
+ export interface VarianceStruct<out Requirements> {
330
+ readonly _Requirements: Covariant<Requirements>
331
+ }
332
+
333
+ /**
334
+ * @since 1.0.0
335
+ * @category Models
336
+ */
337
+ export interface ProviderDefinedProto {
338
+ readonly [ProviderDefinedTypeId]: ProviderDefinedTypeId
339
+ }
340
+ }
341
+
342
+ // =============================================================================
343
+ // Type Guards
344
+ // =============================================================================
345
+
346
+ /**
347
+ * Type guard to check if a value is a user-defined tool.
348
+ *
349
+ * @example
350
+ * ```ts
351
+ * import { Tool } from "@effect/ai"
352
+ * import { Schema } from "effect"
353
+ *
354
+ * const UserDefinedTool = Tool.make("Calculator", {
355
+ * description: "Performs basic arithmetic operations",
356
+ * parameters: {
357
+ * operation: Schema.Literal("add", "subtract", "multiply", "divide"),
358
+ * a: Schema.Number,
359
+ * b: Schema.Number
360
+ * },
361
+ * success: Schema.Number
362
+ * })
363
+ *
364
+ * const ProviderDefinedTool = Tool.providerDefined({
365
+ * id: "openai.web_search",
366
+ * toolkitName: "WebSearch",
367
+ * providerName: "web_search",
368
+ * args: {
369
+ * query: Schema.String
370
+ * },
371
+ * success: Schema.Struct({
372
+ * results: Schema.Array(Schema.Struct({
373
+ * title: Schema.String,
374
+ * url: Schema.String,
375
+ * snippet: Schema.String
376
+ * }))
377
+ * })
378
+ * })
379
+ *
380
+ * console.log(Tool.isUserDefined(UserDefinedTool)) // true
381
+ * console.log(Tool.isUserDefined(ProviderDefinedTool)) // false
382
+ * ```
383
+ *
384
+ * @since 1.0.0
385
+ * @category Guards
386
+ */
387
+ export const isUserDefined = (u: unknown): u is Tool<string, any, any> =>
388
+ Predicate.hasProperty(u, TypeId) && !isProviderDefined(u)
389
+
390
+ /**
391
+ * Type guard to check if a value is a provider-defined tool.
392
+ *
393
+ * @param u - The value to check
394
+ * @returns `true` if the value is a provider-defined `Tool`, `false` otherwise
395
+ *
396
+ * @example
397
+ * ```ts
398
+ * import { Tool } from "@effect/ai"
399
+ * import { Schema } from "effect"
400
+ *
401
+ * const UserDefinedTool = Tool.make("Calculator", {
402
+ * description: "Performs basic arithmetic operations",
403
+ * parameters: {
404
+ * operation: Schema.Literal("add", "subtract", "multiply", "divide"),
405
+ * a: Schema.Number,
406
+ * b: Schema.Number
407
+ * },
408
+ * success: Schema.Number
409
+ * })
410
+ *
411
+ * const ProviderDefinedTool = Tool.providerDefined({
412
+ * id: "openai.web_search",
413
+ * toolkitName: "WebSearch",
414
+ * providerName: "web_search",
415
+ * args: {
416
+ * query: Schema.String
417
+ * },
418
+ * success: Schema.Struct({
419
+ * results: Schema.Array(Schema.Struct({
420
+ * title: Schema.String,
421
+ * url: Schema.String,
422
+ * snippet: Schema.String
423
+ * }))
424
+ * })
425
+ * })
426
+ *
427
+ * console.log(Tool.isUserDefined(UserDefinedTool)) // false
428
+ * console.log(Tool.isUserDefined(ProviderDefinedTool)) // true
429
+ * ```
430
+ *
431
+ * @since 1.0.0
432
+ * @category Guards
433
+ */
434
+ export const isProviderDefined = (u: unknown): u is ProviderDefined<string, any> =>
435
+ Predicate.hasProperty(u, ProviderDefinedTypeId)
436
+
437
+ // =============================================================================
438
+ // Utility Types
439
+ // =============================================================================
440
+
441
+ /**
442
+ * A type which represents any `Tool`.
443
+ *
444
+ * @since 1.0.0
445
+ * @category Utility Types
446
+ */
447
+ export interface Any extends Pipeable {
448
+ readonly [TypeId]: {
449
+ readonly _Requirements: Covariant<any>
450
+ }
451
+ readonly id: string
452
+ readonly name: string
453
+ readonly description?: string | undefined
454
+ readonly parametersSchema: AnyStructSchema
455
+ readonly successSchema: Schema.Schema.Any
456
+ readonly failureSchema: Schema.Schema.All
457
+ readonly annotations: Context.Context<never>
458
+ }
459
+
460
+ /**
461
+ * A type which represents any provider-defined `Tool`.
462
+ *
463
+ * @since 1.0.0
464
+ * @category Utility Types
465
+ */
466
+ export interface AnyProviderDefined extends Any {
467
+ readonly args: any
468
+ readonly argsSchema: AnyStructSchema
469
+ readonly requiresHandler: boolean
470
+ readonly providerName: string
471
+ readonly decodeResult: (result: unknown) => Effect.Effect<any, AiError.AiError>
472
+ }
473
+
474
+ /**
475
+ * @since 1.0.0
476
+ * @category Utility Types
477
+ */
478
+ export interface AnyStructSchema extends Pipeable {
479
+ readonly [Schema.TypeId]: any
480
+ readonly make: any
481
+ readonly Type: any
482
+ readonly Encoded: any
483
+ readonly Context: any
484
+ readonly ast: AST.AST
485
+ readonly fields: Schema.Struct.Fields
486
+ readonly annotations: any
487
+ }
488
+
489
+ /**
490
+ * @since 1.0.0
491
+ * @category Utility Types
492
+ */
493
+ export interface AnyTaggedRequestSchema extends AnyStructSchema {
494
+ readonly _tag: string
495
+ readonly success: Schema.Schema.Any
496
+ readonly failure: Schema.Schema.All
497
+ }
498
+
499
+ /**
500
+ * A utility type to convert a `Schema.TaggedRequest` into an `Tool`.
501
+ *
502
+ * @since 1.0.0
503
+ * @category Utility Types
504
+ */
505
+ export interface FromTaggedRequest<S extends AnyTaggedRequestSchema> extends
506
+ Tool<
507
+ S["_tag"],
508
+ {
509
+ readonly parameters: S
510
+ readonly success: S["success"]
511
+ readonly failure: S["failure"]
512
+ }
513
+ >
514
+ {}
515
+
516
+ /**
517
+ * A utility type to extract the `Name` type from an `Tool`.
518
+ *
519
+ * @since 1.0.0
520
+ * @category Utility Types
521
+ */
522
+ export type Name<T> = T extends Tool<
523
+ infer _Name,
524
+ infer _Config,
525
+ infer _Requirements
526
+ > ? _Name :
527
+ never
528
+
529
+ /**
530
+ * A utility type to extract the type of the tool call parameters.
531
+ *
532
+ * @since 1.0.0
533
+ * @category Utility Types
534
+ */
535
+ export type Parameters<T> = T extends Tool<
536
+ infer _Name,
537
+ infer _Config,
538
+ infer _Requirements
539
+ > ? Schema.Struct.Type<_Config["parameters"]["fields"]> :
540
+ never
541
+
542
+ /**
543
+ * A utility type to extract the encoded type of the tool call parameters.
544
+ *
545
+ * @since 1.0.0
546
+ * @category Utility Types
547
+ */
548
+ export type ParametersEncoded<T> = T extends Tool<
549
+ infer _Name,
550
+ infer _Config,
551
+ infer _Requirements
552
+ > ? Schema.Schema.Encoded<_Config["parameters"]> :
553
+ never
554
+
555
+ /**
556
+ * A utility type to extract the schema for the parameters which an `Tool`
557
+ * must be called with.
558
+ *
559
+ * @since 1.0.0
560
+ * @category Utility Types
561
+ */
562
+ export type ParametersSchema<T> = T extends Tool<
563
+ infer _Name,
564
+ infer _Config,
565
+ infer _Requirements
566
+ > ? _Config["parameters"] :
567
+ never
568
+
569
+ /**
570
+ * A utility type to extract the type of the tool call result when it succeeds.
571
+ *
572
+ * @since 1.0.0
573
+ * @category Utility Types
574
+ */
575
+ export type Success<T> = T extends Tool<
576
+ infer _Name,
577
+ infer _Config,
578
+ infer _Requirements
579
+ > ? Schema.Schema.Type<_Config["success"]> :
580
+ never
581
+
582
+ /**
583
+ * A utility type to extract the encoded type of the tool call result when
584
+ * it succeeds.
585
+ *
586
+ * @since 1.0.0
587
+ * @category Utility Types
588
+ */
589
+ export type SuccessEncoded<T> = T extends Tool<
590
+ infer _Name,
591
+ infer _Config,
592
+ infer _Requirements
593
+ > ? Schema.Schema.Encoded<_Config["success"]> :
594
+ never
595
+
596
+ /**
597
+ * A utility type to extract the schema for the return type of a tool call when
598
+ * the tool call succeeds.
599
+ *
600
+ * @since 1.0.0
601
+ * @category Utility Types
602
+ */
603
+ export type SuccessSchema<T> = T extends Tool<
604
+ infer _Name,
605
+ infer _Config,
606
+ infer _Requirements
607
+ > ? _Config["success"] :
608
+ never
609
+
610
+ /**
611
+ * A utility type to extract the type of the tool call result when it fails.
612
+ *
613
+ * @since 1.0.0
614
+ * @category Utility Types
615
+ */
616
+ export type Failure<T> = T extends Tool<
617
+ infer _Name,
618
+ infer _Config,
619
+ infer _Requirements
620
+ > ? Schema.Schema.Type<_Config["failure"]> :
621
+ never
622
+
623
+ /**
624
+ * A utility type to extract the encoded type of the tool call result when
625
+ * it fails.
626
+ *
627
+ * @since 1.0.0
628
+ * @category Utility Types
629
+ */
630
+ export type FailureEncoded<T> = T extends Tool<
631
+ infer _Name,
632
+ infer _Config,
633
+ infer _Requirements
634
+ > ? Schema.Schema.Encoded<_Config["failure"]> :
635
+ never
636
+
637
+ /**
638
+ * A utility type to extract the requirements of an `Tool`.
639
+ *
640
+ * @since 1.0.0
641
+ * @category Utility Types
642
+ */
643
+ export type Requirements<T> = T extends Tool<
644
+ infer _Name,
645
+ infer _Config,
646
+ infer _Requirements
647
+ > ? _Config["parameters"]["Context"] | _Config["success"]["Context"] | _Config["failure"]["Context"] | _Requirements :
648
+ never
649
+
650
+ /**
651
+ * Represents an `Tool` that has been implemented within the application.
652
+ *
653
+ * @since 1.0.0
654
+ * @category Models
655
+ */
656
+ export interface Handler<Name extends string> {
657
+ readonly _: unique symbol
658
+ readonly name: Name
659
+ readonly context: Context.Context<never>
660
+ readonly handler: (params: any) => Effect.Effect<any, any>
661
+ }
662
+
663
+ /**
664
+ * Represents the result of calling the handler for a particular `Tool`.
665
+ *
666
+ * @since 1.0.0
667
+ * @category Models
668
+ */
669
+ export interface HandlerResult<Tool extends Any> {
670
+ /**
671
+ * The result of executing the handler for a particular tool.
672
+ */
673
+ readonly result: Success<Tool>
674
+ /**
675
+ * The pre-encoded tool call result of executing the handler for a particular
676
+ * tool as a JSON-serializable value. The encoded result can be incorporated
677
+ * into subsequent requests to the large language model.
678
+ */
679
+ readonly encodedResult: unknown
680
+ }
681
+
682
+ /**
683
+ * A utility type to create a union of `Handler` types for all tools in a
684
+ * record.
685
+ *
686
+ * @since 1.0.0
687
+ * @category Utility Types
688
+ */
689
+ export type HandlersFor<Tools extends Record<string, Any>> = {
690
+ [K in keyof Tools]: Handler<Tools[K]["name"]>
691
+ }[keyof Tools]
692
+
693
+ /**
694
+ * A utility type to determine if the specified tool requires a user-defined
695
+ * handler to be implemented.
696
+ *
697
+ * @since 1.0.0
698
+ * @category Utility Types
699
+ */
700
+ export type RequiresHandler<Tool extends Any> = Tool extends
701
+ ProviderDefined<infer _Name, infer _Config, infer _RequiresHandler> ? _RequiresHandler : true
702
+
703
+ // =============================================================================
704
+ // Constructors
705
+ // =============================================================================
706
+
707
+ const Proto = {
708
+ [TypeId]: { _Requirements: identity },
709
+ pipe() {
710
+ return pipeArguments(this, arguments)
711
+ },
712
+ addDependency(this: Any) {
713
+ return userDefinedProto({ ...this })
714
+ },
715
+ setParameters(this: Any, parametersSchema: Schema.Struct<any> | Schema.Struct.Fields) {
716
+ return userDefinedProto({
717
+ ...this,
718
+ parametersSchema: Schema.isSchema(parametersSchema)
719
+ ? parametersSchema as any
720
+ : Schema.Struct(parametersSchema as any)
721
+ })
722
+ },
723
+ setSuccess(this: Any, successSchema: Schema.Schema.Any) {
724
+ return userDefinedProto({
725
+ ...this,
726
+ successSchema
727
+ })
728
+ },
729
+ setFailure(this: Any, failureSchema: Schema.Schema.All) {
730
+ return userDefinedProto({
731
+ ...this,
732
+ failureSchema
733
+ })
734
+ },
735
+ annotate<I, S>(this: Any, tag: Context.Tag<I, S>, value: S) {
736
+ return userDefinedProto({
737
+ ...this,
738
+ annotations: Context.add(this.annotations, tag, value)
739
+ })
740
+ },
741
+ annotateContext<I>(this: Any, context: Context.Context<I>) {
742
+ return userDefinedProto({
743
+ ...this,
744
+ annotations: Context.merge(this.annotations, context)
745
+ })
746
+ }
747
+ }
748
+
749
+ const ProviderDefinedProto = {
750
+ ...Proto,
751
+ [ProviderDefinedTypeId]: ProviderDefinedTypeId,
752
+ decodeResult(this: AnyProviderDefined, result: unknown) {
753
+ return Schema.decodeUnknown(this.successSchema)(result).pipe(
754
+ Effect.orElse(() => Schema.decodeUnknown(this.failureSchema as any)(result)),
755
+ Effect.mapError((cause) =>
756
+ new AiError.MalformedOutput({
757
+ module: "Tool",
758
+ method: "ProviderDefined.decodeResult",
759
+ description: `Failed to decode the result of provider-defined tool '${this.name}'`,
760
+ cause
761
+ })
762
+ )
763
+ )
764
+ }
765
+ }
766
+
767
+ const userDefinedProto = <
768
+ const Name extends string,
769
+ Parameters extends AnyStructSchema,
770
+ Success extends Schema.Schema.Any,
771
+ Failure extends Schema.Schema.All
772
+ >(options: {
773
+ readonly name: Name
774
+ readonly description?: string | undefined
775
+ readonly parametersSchema: Parameters
776
+ readonly successSchema: Success
777
+ readonly failureSchema: Failure
778
+ readonly annotations: Context.Context<never>
779
+ }): Tool<
780
+ Name,
781
+ {
782
+ readonly parameters: Parameters
783
+ readonly success: Success
784
+ readonly failure: Failure
785
+ }
786
+ > => {
787
+ const self = Object.assign(Object.create(Proto), options)
788
+ self.id = `@effect/ai/Tool/${options.name}`
789
+ return self
790
+ }
791
+
792
+ const providerDefinedProto = <
793
+ const Name extends string,
794
+ Args extends AnyStructSchema,
795
+ Parameters extends AnyStructSchema,
796
+ Success extends Schema.Schema.Any,
797
+ Failure extends Schema.Schema.All,
798
+ RequiresHandler extends boolean
799
+ >(options: {
800
+ readonly id: string
801
+ readonly name: Name
802
+ readonly providerName: string
803
+ readonly args: Args["Encoded"]
804
+ readonly argsSchema: Args
805
+ readonly requiresHandler: RequiresHandler
806
+ readonly parametersSchema: Parameters
807
+ readonly successSchema: Success
808
+ readonly failureSchema: Failure
809
+ }): ProviderDefined<
810
+ Name,
811
+ {
812
+ readonly args: Args
813
+ readonly parameters: Parameters
814
+ readonly success: Success
815
+ readonly failure: Failure
816
+ },
817
+ RequiresHandler
818
+ > => Object.assign(Object.create(ProviderDefinedProto), options)
819
+
820
+ const constEmptyStruct = Schema.Struct({})
821
+
822
+ /**
823
+ * Creates a user-defined tool with the specified name and configuration.
824
+ *
825
+ * This is the primary constructor for creating custom tools that AI models
826
+ * can call. The tool definition includes parameter validation, success/failure
827
+ * schemas, and optional service dependencies.
828
+ *
829
+ * @example
830
+ * ```ts
831
+ * import { Tool } from "@effect/ai"
832
+ * import { Schema } from "effect"
833
+ *
834
+ * // Simple tool with no parameters
835
+ * const GetCurrentTime = Tool.make("GetCurrentTime", {
836
+ * description: "Returns the current timestamp",
837
+ * success: Schema.Number
838
+ * })
839
+ * ```
840
+ *
841
+ * @since 1.0.0
842
+ * @category Constructors
843
+ */
844
+ export const make = <
845
+ const Name extends string,
846
+ Parameters extends Schema.Struct.Fields = {},
847
+ Success extends Schema.Schema.Any = typeof Schema.Void,
848
+ Failure extends Schema.Schema.All = typeof Schema.Never,
849
+ Dependencies extends Array<Context.Tag<any, any>> = []
850
+ >(
851
+ /**
852
+ * The unique name identifier for this tool.
853
+ */
854
+ name: Name,
855
+ options?: {
856
+ /**
857
+ * An optional description explaining what the tool does.
858
+ */
859
+ readonly description?: string | undefined
860
+ /**
861
+ * Schema defining the parameters this tool accepts.
862
+ */
863
+ readonly parameters?: Parameters | undefined
864
+ /**
865
+ * Schema for successful tool execution results.
866
+ */
867
+ readonly success?: Success | undefined
868
+ /**
869
+ * Schema for tool execution failures.
870
+ */
871
+ readonly failure?: Failure | undefined
872
+ /**
873
+ * Service dependencies required by the tool handler.
874
+ */
875
+ readonly dependencies?: Dependencies | undefined
876
+ }
877
+ ): Tool<
878
+ Name,
879
+ {
880
+ readonly parameters: Schema.Struct<Parameters>
881
+ readonly success: Success
882
+ readonly failure: Failure
883
+ },
884
+ Context.Tag.Identifier<Dependencies[number]>
885
+ > => {
886
+ const successSchema = options?.success ?? Schema.Void
887
+ const failureSchema = options?.failure ?? Schema.Never
888
+ return userDefinedProto({
889
+ name,
890
+ description: options?.description,
891
+ parametersSchema: options?.parameters
892
+ ? Schema.Struct(options?.parameters as any)
893
+ : constEmptyStruct,
894
+ successSchema,
895
+ failureSchema,
896
+ annotations: Context.empty()
897
+ }) as any
898
+ }
899
+
900
+ /**
901
+ * Creates a provider-defined tool which leverages functionality built into a
902
+ * large language model provider (e.g. web search, code execution).
903
+ *
904
+ * These tools are executed by the large language model provider rather than
905
+ * by your application. However, they can optionally require custom handlers
906
+ * implemented in your application to process provider generated results.
907
+ *
908
+ * @example
909
+ * ```ts
910
+ * import { Tool } from "@effect/ai"
911
+ * import { Schema } from "effect"
912
+ *
913
+ * // Web search tool provided by OpenAI
914
+ * const WebSearch = Tool.providerDefined({
915
+ * id: "openai.web_search",
916
+ * toolkitName: "WebSearch",
917
+ * providerName: "web_search",
918
+ * args: {
919
+ * query: Schema.String
920
+ * },
921
+ * success: Schema.Struct({
922
+ * results: Schema.Array(Schema.Struct({
923
+ * title: Schema.String,
924
+ * url: Schema.String,
925
+ * content: Schema.String
926
+ * }))
927
+ * })
928
+ * })
929
+ * ```
930
+ *
931
+ * @since 1.0.0
932
+ * @category Constructors
933
+ */
934
+ export const providerDefined = <
935
+ const Name extends string,
936
+ Args extends Schema.Struct.Fields = {},
937
+ Parameters extends Schema.Struct.Fields = {},
938
+ Success extends Schema.Schema.Any = typeof Schema.Void,
939
+ Failure extends Schema.Schema.All = typeof Schema.Never,
940
+ RequiresHandler extends boolean = false
941
+ >(options: {
942
+ /**
943
+ * Unique identifier following format `<provider>.<tool-name>`.
944
+ */
945
+ readonly id: `${string}.${string}`
946
+ /**
947
+ * Name used by the Toolkit to identify this tool.
948
+ */
949
+ readonly toolkitName: Name
950
+ /**
951
+ * Name of the tool as recognized by the AI provider.
952
+ */
953
+ readonly providerName: string
954
+ /**
955
+ * Schema for user-provided configuration arguments.
956
+ */
957
+ readonly args: Args
958
+ /**
959
+ * Whether this tool requires a custom handler implementation.
960
+ */
961
+ readonly requiresHandler?: RequiresHandler | undefined
962
+ /**
963
+ * Schema for parameters the provider sends when calling the tool.
964
+ */
965
+ readonly parameters?: Parameters | undefined
966
+ /**
967
+ * Schema for successful tool execution results.
968
+ */
969
+ readonly success?: Success | undefined
970
+ /**
971
+ * Schema for failed tool execution results.
972
+ */
973
+ readonly failure?: Failure | undefined
974
+ }) =>
975
+ (args: Schema.Simplify<Schema.Struct.Encoded<Args>>): ProviderDefined<
976
+ Name,
977
+ {
978
+ readonly args: Schema.Struct<Args>
979
+ readonly parameters: Schema.Struct<Parameters>
980
+ readonly success: Success
981
+ readonly failure: Failure
982
+ },
983
+ RequiresHandler
984
+ > => {
985
+ const successSchema = options?.success ?? Schema.Void
986
+ const failureSchema = options?.failure ?? Schema.Never
987
+ const resultSchema = Schema.EitherFromUnion({ right: successSchema, left: failureSchema })
988
+ return providerDefinedProto({
989
+ id: options.id,
990
+ name: options.toolkitName,
991
+ providerName: options.providerName,
992
+ args,
993
+ argsSchema: Schema.Struct(options.args as any),
994
+ requiresHandler: options.requiresHandler ?? false,
995
+ parametersSchema: options?.parameters
996
+ ? Schema.Struct(options?.parameters as any)
997
+ : constEmptyStruct,
998
+ successSchema: options.requiresHandler === true ? successSchema : resultSchema,
999
+ failureSchema: options.requiresHandler === true ? failureSchema : Schema.Never
1000
+ }) as any
1001
+ }
1002
+
1003
+ /**
1004
+ * Creates a Tool from a Schema.TaggedRequest.
1005
+ *
1006
+ * This utility function converts Effect's TaggedRequest schemas into Tool
1007
+ * definitions, automatically mapping the request parameters, success, and
1008
+ * failure schemas.
1009
+ *
1010
+ * @example
1011
+ * ```ts
1012
+ * import { Tool } from "@effect/ai"
1013
+ * import { Schema } from "effect"
1014
+ *
1015
+ * // Define a tagged request for user operations
1016
+ * class GetUser extends Schema.TaggedRequest<GetUser>()("GetUser", {
1017
+ * success: Schema.Struct({
1018
+ * id: Schema.Number,
1019
+ * name: Schema.String,
1020
+ * email: Schema.String
1021
+ * }),
1022
+ * failure: Schema.Struct({
1023
+ * error: Schema.Literal("UserNotFound", "DatabaseError"),
1024
+ * message: Schema.String
1025
+ * }),
1026
+ * payload: {
1027
+ * userId: Schema.Number
1028
+ * }
1029
+ * }) {}
1030
+ *
1031
+ * // Convert to a Tool
1032
+ * const getUserTool = Tool.fromTaggedRequest(GetUser)
1033
+ * ```
1034
+ *
1035
+ * @since 1.0.0
1036
+ * @category Constructors
1037
+ */
1038
+ export const fromTaggedRequest = <S extends AnyTaggedRequestSchema>(
1039
+ schema: S
1040
+ ): FromTaggedRequest<S> =>
1041
+ userDefinedProto({
1042
+ name: schema._tag,
1043
+ description: Option.getOrUndefined(AST.getDescriptionAnnotation((schema.ast as any).to)),
1044
+ parametersSchema: schema,
1045
+ successSchema: schema.success,
1046
+ failureSchema: schema.failure,
1047
+ annotations: Context.empty()
1048
+ }) as any
1049
+
1050
+ // =============================================================================
1051
+ // Utilities
1052
+ // =============================================================================
1053
+
1054
+ /**
1055
+ * Extracts the description from a tool's metadata.
1056
+ *
1057
+ * Returns the tool's description if explicitly set, otherwise attempts to
1058
+ * extract it from the parameter schema's AST annotations.
1059
+ *
1060
+ * @example
1061
+ * ```ts
1062
+ * import { Tool } from "@effect/ai"
1063
+ *
1064
+ * const myTool = Tool.make("example", {
1065
+ * description: "This is an example tool"
1066
+ * })
1067
+ *
1068
+ * const description = Tool.getDescription(myTool)
1069
+ * console.log(description) // "This is an example tool"
1070
+ * ```
1071
+ *
1072
+ * @since 1.0.0
1073
+ * @category Utilities
1074
+ */
1075
+ export const getDescription = <
1076
+ Name extends string,
1077
+ Config extends {
1078
+ readonly parameters: AnyStructSchema
1079
+ readonly success: Schema.Schema.Any
1080
+ readonly failure: Schema.Schema.All
1081
+ }
1082
+ >(
1083
+ /**
1084
+ * The tool to get the description from.
1085
+ */
1086
+ tool: Tool<Name, Config>
1087
+ ): string | undefined => {
1088
+ if (Predicate.isNotUndefined(tool.description)) {
1089
+ return tool.description
1090
+ }
1091
+ return getDescriptionFromSchemaAst(tool.parametersSchema.ast)
1092
+ }
1093
+
1094
+ /**
1095
+ * @since 1.0.0
1096
+ * @category Utilities
1097
+ */
1098
+ export const getDescriptionFromSchemaAst = (ast: AST.AST): string | undefined => {
1099
+ const annotations = ast._tag === "Transformation" ?
1100
+ {
1101
+ ...ast.to.annotations,
1102
+ ...ast.annotations
1103
+ } :
1104
+ ast.annotations
1105
+ return AST.DescriptionAnnotationId in annotations
1106
+ ? annotations[AST.DescriptionAnnotationId] as string :
1107
+ undefined
1108
+ }
1109
+
1110
+ /**
1111
+ * Generates a JSON Schema for a tool.
1112
+ *
1113
+ * This function creates a JSON Schema representation that can be used by
1114
+ * large language models to indicate the structure and type of the parameters
1115
+ * that a given tool call should receive.
1116
+ *
1117
+ * @example
1118
+ * ```ts
1119
+ * import { Tool } from "@effect/ai"
1120
+ * import { Schema } from "effect"
1121
+ *
1122
+ * const weatherTool = Tool.make("get_weather", {
1123
+ * parameters: {
1124
+ * location: Schema.String,
1125
+ * units: Schema.optional(Schema.Literal("celsius", "fahrenheit"))
1126
+ * }
1127
+ * })
1128
+ *
1129
+ * const jsonSchema = Tool.getJsonSchema(weatherTool)
1130
+ * console.log(jsonSchema)
1131
+ * // {
1132
+ * // type: "object",
1133
+ * // properties: {
1134
+ * // location: { type: "string" },
1135
+ * // units: { type: "string", enum: ["celsius", "fahrenheit"] }
1136
+ * // },
1137
+ * // required: ["location"]
1138
+ * // }
1139
+ * ```
1140
+ *
1141
+ * @since 1.0.0
1142
+ * @category Utilities
1143
+ */
1144
+ export const getJsonSchema = <
1145
+ Name extends string,
1146
+ Config extends {
1147
+ readonly parameters: AnyStructSchema
1148
+ readonly success: Schema.Schema.Any
1149
+ readonly failure: Schema.Schema.All
1150
+ }
1151
+ >(tool: Tool<Name, Config>): JsonSchema.JsonSchema7 => getJsonSchemaFromSchemaAst(tool.parametersSchema.ast)
1152
+
1153
+ /**
1154
+ * @since 1.0.0
1155
+ * @category Utilities
1156
+ */
1157
+ export const getJsonSchemaFromSchemaAst = (ast: AST.AST): JsonSchema.JsonSchema7 => {
1158
+ const props = AST.getPropertySignatures(ast)
1159
+ if (props.length === 0) {
1160
+ return {
1161
+ type: "object",
1162
+ properties: {},
1163
+ required: [],
1164
+ additionalProperties: false
1165
+ }
1166
+ }
1167
+ const $defs = {}
1168
+ const schema = JsonSchema.fromAST(ast, {
1169
+ definitions: $defs,
1170
+ topLevelReferenceStrategy: "skip"
1171
+ })
1172
+ if (Object.keys($defs).length === 0) return schema
1173
+ ;(schema as any).$defs = $defs
1174
+ return schema
1175
+ }
1176
+
1177
+ // =============================================================================
1178
+ // Annotations
1179
+ // =============================================================================
1180
+
1181
+ /**
1182
+ * Annotation for providing a human-readable title for tools.
1183
+ *
1184
+ * @example
1185
+ * ```ts
1186
+ * import { Tool } from "@effect/ai"
1187
+ *
1188
+ * const myTool = Tool.make("calculate_tip")
1189
+ * .annotate(Tool.Title, "Tip Calculator")
1190
+ * ```
1191
+ *
1192
+ * @since 1.0.0
1193
+ * @category Annotations
1194
+ */
1195
+ export class Title extends Context.Tag("@effect/ai/Tool/Title")<Title, string>() {}
1196
+
1197
+ /**
1198
+ * Annotation indicating whether a tool only reads data without making changes.
1199
+ *
1200
+ * @example
1201
+ * ```ts
1202
+ * import { Tool } from "@effect/ai"
1203
+ *
1204
+ * const readOnlyTool = Tool.make("get_user_info")
1205
+ * .annotate(Tool.Readonly, true)
1206
+ * ```
1207
+ *
1208
+ * @since 1.0.0
1209
+ * @category Annotations
1210
+ */
1211
+ export class Readonly extends Context.Reference<Readonly>()("@effect/ai/Tool/Readonly", {
1212
+ defaultValue: constFalse
1213
+ }) {}
1214
+
1215
+ /**
1216
+ * Annotation indicating whether a tool performs destructive operations.
1217
+ *
1218
+ * @example
1219
+ * ```ts
1220
+ * import { Tool } from "@effect/ai"
1221
+ *
1222
+ * const safeTool = Tool.make("search_database")
1223
+ * .annotate(Tool.Destructive, false)
1224
+ * ```
1225
+ *
1226
+ * @since 1.0.0
1227
+ * @category Annotations
1228
+ */
1229
+ export class Destructive extends Context.Reference<Destructive>()("@effect/ai/Tool/Destructive", {
1230
+ defaultValue: constTrue
1231
+ }) {}
1232
+
1233
+ /**
1234
+ * Annotation indicating whether a tool can be called multiple times safely.
1235
+ *
1236
+ * @example
1237
+ * ```ts
1238
+ * import { Tool } from "@effect/ai"
1239
+ *
1240
+ * const idempotentTool = Tool.make("get_current_time")
1241
+ * .annotate(Tool.Idempotent, true)
1242
+ * ```
1243
+ *
1244
+ * @since 1.0.0
1245
+ * @category Annotations
1246
+ */
1247
+ export class Idempotent extends Context.Reference<Idempotent>()("@effect/ai/Tool/Idempotent", {
1248
+ defaultValue: constFalse
1249
+ }) {}
1250
+
1251
+ /**
1252
+ * Annotation indicating whether a tool can handle arbitrary external data.
1253
+ *
1254
+ * @example
1255
+ * ```ts
1256
+ * import { Tool } from "@effect/ai"
1257
+ *
1258
+ * const restrictedTool = Tool.make("internal_operation")
1259
+ * .annotate(Tool.OpenWorld, false)
1260
+ * ```
1261
+ *
1262
+ * @since 1.0.0
1263
+ * @category Annotations
1264
+ */
1265
+ export class OpenWorld extends Context.Reference<OpenWorld>()("@effect/ai/Tool/OpenWorld", {
1266
+ defaultValue: constTrue
1267
+ }) {}