@effect/ai 0.28.0 → 0.28.2

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.
package/src/Prompt.ts CHANGED
@@ -51,9 +51,13 @@
51
51
  *
52
52
  * @since 1.0.0
53
53
  */
54
+ import * as Arr from "effect/Array"
54
55
  import { constFalse, dual } from "effect/Function"
56
+ import * as ParseResult from "effect/ParseResult"
57
+ import { type Pipeable, pipeArguments } from "effect/Pipeable"
55
58
  import * as Predicate from "effect/Predicate"
56
59
  import * as Schema from "effect/Schema"
60
+ import type * as AST from "effect/SchemaAST"
57
61
  import type * as Response from "./Response.js"
58
62
 
59
63
  const constEmptyObject = () => ({})
@@ -726,6 +730,22 @@ export const makeMessage = <const Role extends Message["role"]>(
726
730
  options: params.options ?? {}
727
731
  }) as any)
728
732
 
733
+ /**
734
+ * Schema for decoding message content (i.e. an array containing a single
735
+ * `TextPart`) from a string.
736
+ *
737
+ * @since 1.0.0
738
+ * @category Schemas
739
+ */
740
+ export const MessageContentFromString: Schema.Schema<
741
+ Arr.NonEmptyReadonlyArray<TextPart>,
742
+ string
743
+ > = Schema.transform(Schema.String, Schema.NonEmptyArray(Schema.typeSchema(TextPart)), {
744
+ strict: true,
745
+ decode: (text) => Arr.of(makePart("text", { text })),
746
+ encode: (content) => content[0].text
747
+ })
748
+
729
749
  // =============================================================================
730
750
  // System Message
731
751
  // =============================================================================
@@ -851,7 +871,7 @@ export interface UserMessageEncoded extends BaseMessageEncoded<"user", UserMessa
851
871
  /**
852
872
  * Array of content parts that make up the user's message.
853
873
  */
854
- readonly content: ReadonlyArray<UserMessagePartEncoded>
874
+ readonly content: string | ReadonlyArray<UserMessagePartEncoded>
855
875
  }
856
876
 
857
877
  /**
@@ -879,7 +899,10 @@ export interface UserMessageOptions extends ProviderOptions {}
879
899
  */
880
900
  export const UserMessage: Schema.Schema<UserMessage, UserMessageEncoded> = Schema.Struct({
881
901
  role: Schema.Literal("user"),
882
- content: Schema.Array(Schema.Union(TextPart, FilePart)),
902
+ content: Schema.Union(
903
+ MessageContentFromString,
904
+ Schema.Array(Schema.Union(TextPart, FilePart))
905
+ ),
883
906
  options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
884
907
  }).pipe(
885
908
  Schema.attachPropertySignature(MessageTypeId, MessageTypeId),
@@ -950,7 +973,7 @@ export type AssistantMessagePart =
950
973
  * @category Models
951
974
  */
952
975
  export interface AssistantMessageEncoded extends BaseMessageEncoded<"assistant", AssistantMessageOptions> {
953
- readonly content: ReadonlyArray<AssistantMessagePartEncoded>
976
+ readonly content: string | ReadonlyArray<AssistantMessagePartEncoded>
954
977
  }
955
978
 
956
979
  /**
@@ -983,7 +1006,10 @@ export interface AssistantMessageOptions extends ProviderOptions {}
983
1006
  */
984
1007
  export const AssistantMessage: Schema.Schema<AssistantMessage, AssistantMessageEncoded> = Schema.Struct({
985
1008
  role: Schema.Literal("assistant"),
986
- content: Schema.Array(Schema.Union(TextPart, FilePart, ReasoningPart, ToolCallPart, ToolResultPart)),
1009
+ content: Schema.Union(
1010
+ MessageContentFromString,
1011
+ Schema.Array(Schema.Union(TextPart, FilePart, ReasoningPart, ToolCallPart, ToolResultPart))
1012
+ ),
987
1013
  options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
988
1014
  }).pipe(
989
1015
  Schema.attachPropertySignature(MessageTypeId, MessageTypeId),
@@ -1157,7 +1183,7 @@ export const isPrompt = (u: unknown): u is Prompt => Predicate.hasProperty(u, Ty
1157
1183
  * @since 1.0.0
1158
1184
  * @category Models
1159
1185
  */
1160
- export interface Prompt {
1186
+ export interface Prompt extends Pipeable {
1161
1187
  readonly [TypeId]: TypeId
1162
1188
  /**
1163
1189
  * Array of messages that make up the conversation.
@@ -1178,18 +1204,57 @@ export interface PromptEncoded {
1178
1204
  readonly content: ReadonlyArray<MessageEncoded>
1179
1205
  }
1180
1206
 
1207
+ /**
1208
+ * Describes a schema that represents a `Prompt` instance.
1209
+ *
1210
+ * @since 1.0.0
1211
+ * @category Schemas
1212
+ */
1213
+ export class PromptFromSelf extends Schema.declare(
1214
+ (u) => isPrompt(u),
1215
+ {
1216
+ identifier: "PromptFromSelf",
1217
+ description: "a Prompt instance"
1218
+ }
1219
+ ) {}
1220
+
1181
1221
  /**
1182
1222
  * Schema for validation and encoding of prompts.
1183
1223
  *
1184
1224
  * @since 1.0.0
1185
1225
  * @category Schemas
1186
1226
  */
1187
- export const Prompt: Schema.Schema<Prompt, PromptEncoded> = Schema.Struct({
1188
- content: Schema.Array(Message)
1189
- }).pipe(
1190
- Schema.attachPropertySignature(TypeId, TypeId),
1191
- Schema.annotations({ identifier: "Prompt" })
1192
- )
1227
+ export const Prompt: Schema.Schema<Prompt, PromptEncoded> = Schema.transformOrFail(
1228
+ Schema.Struct({ content: Schema.Array(Schema.encodedSchema(Message)) }),
1229
+ PromptFromSelf,
1230
+ {
1231
+ strict: true,
1232
+ decode: (i, _, ast) => decodePrompt(i, ast),
1233
+ encode: (a, _, ast) => encodePrompt(a, ast)
1234
+ }
1235
+ ).annotations({ identifier: "Prompt" })
1236
+
1237
+ const decodeMessages = ParseResult.decodeEither(Schema.Array(Message))
1238
+ const encodeMessages = ParseResult.encodeEither(Schema.Array(Message))
1239
+
1240
+ const decodePrompt = (input: PromptEncoded, ast: AST.AST) =>
1241
+ ParseResult.mapBoth(decodeMessages(input.content), {
1242
+ onFailure: () => new ParseResult.Type(ast, input, `Unable to decode ${JSON.stringify(input)} into a Prompt`),
1243
+ onSuccess: makePrompt
1244
+ })
1245
+
1246
+ const encodePrompt = (input: Prompt, ast: AST.AST) =>
1247
+ ParseResult.mapBoth(encodeMessages(input.content), {
1248
+ onFailure: () => new ParseResult.Type(ast, input, `Failed to encode Prompt`),
1249
+ onSuccess: (messages) => ({ content: messages })
1250
+ })
1251
+
1252
+ // export const Prompt: Schema.Schema<Prompt, PromptEncoded> = Schema.Struct({
1253
+ // content: Schema.Array(Message)
1254
+ // }).pipe(
1255
+ // Schema.attachPropertySignature(TypeId, TypeId),
1256
+ // Schema.annotations({ identifier: "Prompt" })
1257
+ // )
1193
1258
 
1194
1259
  /**
1195
1260
  * Schema for parsing a Prompt from JSON strings.
@@ -1231,10 +1296,17 @@ export type RawInput =
1231
1296
  | Iterable<MessageEncoded>
1232
1297
  | Prompt
1233
1298
 
1234
- const makePrompt = (content: ReadonlyArray<Message>): Prompt => ({
1299
+ const Proto = {
1235
1300
  [TypeId]: TypeId,
1236
- content
1237
- })
1301
+ pipe() {
1302
+ return pipeArguments(this, arguments)
1303
+ }
1304
+ }
1305
+
1306
+ const makePrompt = (content: ReadonlyArray<Message>): Prompt =>
1307
+ Object.assign(Object.create(Proto), {
1308
+ content
1309
+ })
1238
1310
 
1239
1311
  const decodeMessagesSync = Schema.decodeSync(Schema.Array(Message))
1240
1312
 
@@ -1289,7 +1361,7 @@ export const make = (input: RawInput): Prompt => {
1289
1361
  }
1290
1362
 
1291
1363
  if (Predicate.isIterable(input)) {
1292
- return makePrompt(decodeMessagesSync(Array.from(input), {
1364
+ return makePrompt(decodeMessagesSync(Arr.fromIterable(input), {
1293
1365
  errors: "all"
1294
1366
  }))
1295
1367
  }
@@ -1482,10 +1554,10 @@ export const fromResponseParts = (parts: ReadonlyArray<Response.AnyPart>): Promp
1482
1554
  // =============================================================================
1483
1555
 
1484
1556
  /**
1485
- * Merges two prompts by concatenating their messages.
1557
+ * Merges a prompt with additional raw input by concatenating messages.
1486
1558
  *
1487
- * Creates a new prompt containing all messages from both prompts, maintaining
1488
- * the order of messages within each prompt.
1559
+ * Creates a new prompt containing all messages from both the original prompt,
1560
+ * and the provided raw input, maintaining the order of messages.
1489
1561
  *
1490
1562
  * @example
1491
1563
  * ```ts
@@ -1496,9 +1568,7 @@ export const fromResponseParts = (parts: ReadonlyArray<Response.AnyPart>): Promp
1496
1568
  * content: "You are a helpful assistant."
1497
1569
  * }])
1498
1570
  *
1499
- * const userPrompt = Prompt.make("Hello, world!")
1500
- *
1501
- * const merged = Prompt.merge(systemPrompt, userPrompt)
1571
+ * const merged = Prompt.merge(systemPrompt, "Hello, world!")
1502
1572
  * ```
1503
1573
  *
1504
1574
  * @since 1.0.0
@@ -1510,10 +1580,10 @@ export const merge: {
1510
1580
  // =============================================================================
1511
1581
 
1512
1582
  /**
1513
- * Merges two prompts by concatenating their messages.
1583
+ * Merges a prompt with additional raw input by concatenating messages.
1514
1584
  *
1515
- * Creates a new prompt containing all messages from both prompts, maintaining
1516
- * the order of messages within each prompt.
1585
+ * Creates a new prompt containing all messages from both the original prompt,
1586
+ * and the provided raw input, maintaining the order of messages.
1517
1587
  *
1518
1588
  * @example
1519
1589
  * ```ts
@@ -1524,24 +1594,22 @@ export const merge: {
1524
1594
  * content: "You are a helpful assistant."
1525
1595
  * }])
1526
1596
  *
1527
- * const userPrompt = Prompt.make("Hello, world!")
1528
- *
1529
- * const merged = Prompt.merge(systemPrompt, userPrompt)
1597
+ * const merged = Prompt.merge(systemPrompt, "Hello, world!")
1530
1598
  * ```
1531
1599
  *
1532
1600
  * @since 1.0.0
1533
1601
  * @category Combinators
1534
1602
  */
1535
- (other: Prompt): (self: Prompt) => Prompt
1603
+ (other: RawInput): (self: Prompt) => Prompt
1536
1604
  // =============================================================================
1537
1605
  // Merging Prompts
1538
1606
  // =============================================================================
1539
1607
 
1540
1608
  /**
1541
- * Merges two prompts by concatenating their messages.
1609
+ * Merges a prompt with additional raw input by concatenating messages.
1542
1610
  *
1543
- * Creates a new prompt containing all messages from both prompts, maintaining
1544
- * the order of messages within each prompt.
1611
+ * Creates a new prompt containing all messages from both the original prompt,
1612
+ * and the provided raw input, maintaining the order of messages.
1545
1613
  *
1546
1614
  * @example
1547
1615
  * ```ts
@@ -1552,25 +1620,63 @@ export const merge: {
1552
1620
  * content: "You are a helpful assistant."
1553
1621
  * }])
1554
1622
  *
1555
- * const userPrompt = Prompt.make("Hello, world!")
1556
- *
1557
- * const merged = Prompt.merge(systemPrompt, userPrompt)
1623
+ * const merged = Prompt.merge(systemPrompt, "Hello, world!")
1558
1624
  * ```
1559
1625
  *
1560
1626
  * @since 1.0.0
1561
1627
  * @category Combinators
1562
1628
  */
1563
- (self: Prompt, other: Prompt): Prompt
1564
- } = dual<
1629
+ (self: Prompt, other: RawInput): Prompt
1630
+ } = dual(2, (self: Prompt, other: RawInput): Prompt =>
1631
+ fromMessages([
1632
+ ...self.content,
1633
+ ...make(other).content
1634
+ ]))
1635
+
1636
+ // =============================================================================
1637
+ // Manipulating Prompts
1638
+ // =============================================================================
1639
+
1640
+ /**
1641
+ * Creates a new prompt from the specified prompt with the system message set
1642
+ * to the specified text content.
1643
+ *
1644
+ * **NOTE**: This method will remove and replace any previous system message
1645
+ * from the prompt.
1646
+ *
1647
+ * @example
1648
+ * ```ts
1649
+ * import { Prompt } from "@effect/ai"
1650
+ *
1651
+ * const systemPrompt = Prompt.make([{
1652
+ * role: "system",
1653
+ * content: "You are a helpful assistant."
1654
+ * }])
1655
+ *
1656
+ * const userPrompt = Prompt.make("Hello, world!")
1657
+ *
1658
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1659
+ *
1660
+ * const replaced = Prompt.setSystem(
1661
+ * prompt,
1662
+ * "You are an expert in programming"
1663
+ * )
1664
+ * ```
1665
+ *
1666
+ * @since 1.0.0
1667
+ * @category Combinators
1668
+ */
1669
+ export const setSystem: {
1565
1670
  // =============================================================================
1566
- // Merging Prompts
1671
+ // Manipulating Prompts
1567
1672
  // =============================================================================
1568
1673
 
1569
1674
  /**
1570
- * Merges two prompts by concatenating their messages.
1675
+ * Creates a new prompt from the specified prompt with the system message set
1676
+ * to the specified text content.
1571
1677
  *
1572
- * Creates a new prompt containing all messages from both prompts, maintaining
1573
- * the order of messages within each prompt.
1678
+ * **NOTE**: This method will remove and replace any previous system message
1679
+ * from the prompt.
1574
1680
  *
1575
1681
  * @example
1576
1682
  * ```ts
@@ -1583,22 +1689,28 @@ export const merge: {
1583
1689
  *
1584
1690
  * const userPrompt = Prompt.make("Hello, world!")
1585
1691
  *
1586
- * const merged = Prompt.merge(systemPrompt, userPrompt)
1692
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1693
+ *
1694
+ * const replaced = Prompt.setSystem(
1695
+ * prompt,
1696
+ * "You are an expert in programming"
1697
+ * )
1587
1698
  * ```
1588
1699
  *
1589
1700
  * @since 1.0.0
1590
1701
  * @category Combinators
1591
1702
  */
1592
- (other: Prompt) => (self: Prompt) => Prompt,
1703
+ (content: string): (self: Prompt) => Prompt
1593
1704
  // =============================================================================
1594
- // Merging Prompts
1705
+ // Manipulating Prompts
1595
1706
  // =============================================================================
1596
1707
 
1597
1708
  /**
1598
- * Merges two prompts by concatenating their messages.
1709
+ * Creates a new prompt from the specified prompt with the system message set
1710
+ * to the specified text content.
1599
1711
  *
1600
- * Creates a new prompt containing all messages from both prompts, maintaining
1601
- * the order of messages within each prompt.
1712
+ * **NOTE**: This method will remove and replace any previous system message
1713
+ * from the prompt.
1602
1714
  *
1603
1715
  * @example
1604
1716
  * ```ts
@@ -1611,11 +1723,234 @@ export const merge: {
1611
1723
  *
1612
1724
  * const userPrompt = Prompt.make("Hello, world!")
1613
1725
  *
1614
- * const merged = Prompt.merge(systemPrompt, userPrompt)
1726
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1727
+ *
1728
+ * const replaced = Prompt.setSystem(
1729
+ * prompt,
1730
+ * "You are an expert in programming"
1731
+ * )
1615
1732
  * ```
1616
1733
  *
1617
1734
  * @since 1.0.0
1618
1735
  * @category Combinators
1619
1736
  */
1620
- (self: Prompt, other: Prompt) => Prompt
1621
- >(2, (self, other) => fromMessages([...self.content, ...other.content]))
1737
+ (self: Prompt, content: string): Prompt
1738
+ } = dual(2, (self: Prompt, content: string): Prompt => {
1739
+ const messages: Array<Message> = [makeMessage("system", { content })]
1740
+ for (const message of self.content) {
1741
+ if (message.role !== "system") {
1742
+ messages.push(message)
1743
+ }
1744
+ }
1745
+ return makePrompt(messages)
1746
+ })
1747
+
1748
+ /**
1749
+ * Creates a new prompt from the specified prompt with the provided text content
1750
+ * prepended to the start of existing system message content.
1751
+ *
1752
+ * If no system message exists in the specified prompt, the provided content
1753
+ * will be used to create a system message.
1754
+ *
1755
+ * @example
1756
+ * ```ts
1757
+ * import { Prompt } from "@effect/ai"
1758
+ *
1759
+ * const systemPrompt = Prompt.make([{
1760
+ * role: "system",
1761
+ * content: "You are an expert in programming."
1762
+ * }])
1763
+ *
1764
+ * const userPrompt = Prompt.make("Hello, world!")
1765
+ *
1766
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1767
+ *
1768
+ * const replaced = Prompt.prependSystem(
1769
+ * prompt,
1770
+ * "You are a helpful assistant. "
1771
+ * )
1772
+ * ```
1773
+ *
1774
+ * @since 1.0.0
1775
+ * @category Combinators
1776
+ */
1777
+ export const prependSystem: {
1778
+ /**
1779
+ * Creates a new prompt from the specified prompt with the provided text content
1780
+ * prepended to the start of existing system message content.
1781
+ *
1782
+ * If no system message exists in the specified prompt, the provided content
1783
+ * will be used to create a system message.
1784
+ *
1785
+ * @example
1786
+ * ```ts
1787
+ * import { Prompt } from "@effect/ai"
1788
+ *
1789
+ * const systemPrompt = Prompt.make([{
1790
+ * role: "system",
1791
+ * content: "You are an expert in programming."
1792
+ * }])
1793
+ *
1794
+ * const userPrompt = Prompt.make("Hello, world!")
1795
+ *
1796
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1797
+ *
1798
+ * const replaced = Prompt.prependSystem(
1799
+ * prompt,
1800
+ * "You are a helpful assistant. "
1801
+ * )
1802
+ * ```
1803
+ *
1804
+ * @since 1.0.0
1805
+ * @category Combinators
1806
+ */
1807
+ (content: string): (self: Prompt) => Prompt
1808
+ /**
1809
+ * Creates a new prompt from the specified prompt with the provided text content
1810
+ * prepended to the start of existing system message content.
1811
+ *
1812
+ * If no system message exists in the specified prompt, the provided content
1813
+ * will be used to create a system message.
1814
+ *
1815
+ * @example
1816
+ * ```ts
1817
+ * import { Prompt } from "@effect/ai"
1818
+ *
1819
+ * const systemPrompt = Prompt.make([{
1820
+ * role: "system",
1821
+ * content: "You are an expert in programming."
1822
+ * }])
1823
+ *
1824
+ * const userPrompt = Prompt.make("Hello, world!")
1825
+ *
1826
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1827
+ *
1828
+ * const replaced = Prompt.prependSystem(
1829
+ * prompt,
1830
+ * "You are a helpful assistant. "
1831
+ * )
1832
+ * ```
1833
+ *
1834
+ * @since 1.0.0
1835
+ * @category Combinators
1836
+ */
1837
+ (self: Prompt, content: string): Prompt
1838
+ } = dual(2, (self: Prompt, content: string): Prompt => {
1839
+ const messages: Array<Message> = []
1840
+ for (const message of self.content) {
1841
+ if (message.role === "system") {
1842
+ const system = makeMessage("system", {
1843
+ content: content + message.content
1844
+ })
1845
+ messages.push(system)
1846
+ } else {
1847
+ messages.push(message)
1848
+ }
1849
+ }
1850
+ return makePrompt(messages)
1851
+ })
1852
+
1853
+ /**
1854
+ * Creates a new prompt from the specified prompt with the provided text content
1855
+ * appended to the end of existing system message content.
1856
+ *
1857
+ * If no system message exists in the specified prompt, the provided content
1858
+ * will be used to create a system message.
1859
+ *
1860
+ * @example
1861
+ * ```ts
1862
+ * import { Prompt } from "@effect/ai"
1863
+ *
1864
+ * const systemPrompt = Prompt.make([{
1865
+ * role: "system",
1866
+ * content: "You are a helpful assistant."
1867
+ * }])
1868
+ *
1869
+ * const userPrompt = Prompt.make("Hello, world!")
1870
+ *
1871
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1872
+ *
1873
+ * const replaced = Prompt.appendSystem(
1874
+ * prompt,
1875
+ * " You are an expert in programming."
1876
+ * )
1877
+ * ```
1878
+ *
1879
+ * @since 1.0.0
1880
+ * @category Combinators
1881
+ */
1882
+ export const appendSystem: {
1883
+ /**
1884
+ * Creates a new prompt from the specified prompt with the provided text content
1885
+ * appended to the end of existing system message content.
1886
+ *
1887
+ * If no system message exists in the specified prompt, the provided content
1888
+ * will be used to create a system message.
1889
+ *
1890
+ * @example
1891
+ * ```ts
1892
+ * import { Prompt } from "@effect/ai"
1893
+ *
1894
+ * const systemPrompt = Prompt.make([{
1895
+ * role: "system",
1896
+ * content: "You are a helpful assistant."
1897
+ * }])
1898
+ *
1899
+ * const userPrompt = Prompt.make("Hello, world!")
1900
+ *
1901
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1902
+ *
1903
+ * const replaced = Prompt.appendSystem(
1904
+ * prompt,
1905
+ * " You are an expert in programming."
1906
+ * )
1907
+ * ```
1908
+ *
1909
+ * @since 1.0.0
1910
+ * @category Combinators
1911
+ */
1912
+ (content: string): (self: Prompt) => Prompt
1913
+ /**
1914
+ * Creates a new prompt from the specified prompt with the provided text content
1915
+ * appended to the end of existing system message content.
1916
+ *
1917
+ * If no system message exists in the specified prompt, the provided content
1918
+ * will be used to create a system message.
1919
+ *
1920
+ * @example
1921
+ * ```ts
1922
+ * import { Prompt } from "@effect/ai"
1923
+ *
1924
+ * const systemPrompt = Prompt.make([{
1925
+ * role: "system",
1926
+ * content: "You are a helpful assistant."
1927
+ * }])
1928
+ *
1929
+ * const userPrompt = Prompt.make("Hello, world!")
1930
+ *
1931
+ * const prompt = Prompt.merge(systemPrompt, userPrompt)
1932
+ *
1933
+ * const replaced = Prompt.appendSystem(
1934
+ * prompt,
1935
+ * " You are an expert in programming."
1936
+ * )
1937
+ * ```
1938
+ *
1939
+ * @since 1.0.0
1940
+ * @category Combinators
1941
+ */
1942
+ (self: Prompt, content: string): Prompt
1943
+ } = dual(2, (self: Prompt, content: string): Prompt => {
1944
+ const messages: Array<Message> = []
1945
+ for (const message of self.content) {
1946
+ if (message.role === "system") {
1947
+ const system = makeMessage("system", {
1948
+ content: message.content + content
1949
+ })
1950
+ messages.push(system)
1951
+ } else {
1952
+ messages.push(message)
1953
+ }
1954
+ }
1955
+ return makePrompt(messages)
1956
+ })
package/src/Tool.ts CHANGED
@@ -687,7 +687,8 @@ export interface HandlerResult<Tool extends Any> {
687
687
  * @category Utility Types
688
688
  */
689
689
  export type HandlersFor<Tools extends Record<string, Any>> = {
690
- [K in keyof Tools]: Handler<Tools[K]["name"]>
690
+ [Name in keyof Tools]: RequiresHandler<Tools[Name]> extends true ? Handler<Tools[Name]["name"]>
691
+ : never
691
692
  }[keyof Tools]
692
693
 
693
694
  /**