@better-agent/core 0.1.0-beta.1

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 (179) hide show
  1. package/README.md +3 -0
  2. package/dist/agent/constants.mjs +6 -0
  3. package/dist/agent/constants.mjs.map +1 -0
  4. package/dist/agent/define-agent.d.mts +29 -0
  5. package/dist/agent/define-agent.d.mts.map +1 -0
  6. package/dist/agent/define-agent.mjs +27 -0
  7. package/dist/agent/define-agent.mjs.map +1 -0
  8. package/dist/agent/index.d.mts +2 -0
  9. package/dist/agent/types.d.mts +216 -0
  10. package/dist/agent/types.d.mts.map +1 -0
  11. package/dist/agent/validation.mjs +64 -0
  12. package/dist/agent/validation.mjs.map +1 -0
  13. package/dist/api.d.mts +8 -0
  14. package/dist/api.d.mts.map +1 -0
  15. package/dist/api.mjs +63 -0
  16. package/dist/api.mjs.map +1 -0
  17. package/dist/app/config.mjs +43 -0
  18. package/dist/app/config.mjs.map +1 -0
  19. package/dist/app/create-app.d.mts +36 -0
  20. package/dist/app/create-app.d.mts.map +1 -0
  21. package/dist/app/create-app.mjs +132 -0
  22. package/dist/app/create-app.mjs.map +1 -0
  23. package/dist/app/registry.mjs +43 -0
  24. package/dist/app/registry.mjs.map +1 -0
  25. package/dist/app/types.d.mts +142 -0
  26. package/dist/app/types.d.mts.map +1 -0
  27. package/dist/events/constants.d.mts +49 -0
  28. package/dist/events/constants.d.mts.map +1 -0
  29. package/dist/events/constants.mjs +46 -0
  30. package/dist/events/constants.mjs.map +1 -0
  31. package/dist/events/index.d.mts +4 -0
  32. package/dist/events/index.mjs +3 -0
  33. package/dist/events/types.d.mts +289 -0
  34. package/dist/events/types.d.mts.map +1 -0
  35. package/dist/index.d.mts +23 -0
  36. package/dist/index.mjs +14 -0
  37. package/dist/internal/id.mjs +21 -0
  38. package/dist/internal/id.mjs.map +1 -0
  39. package/dist/internal/types.d.mts +11 -0
  40. package/dist/internal/types.d.mts.map +1 -0
  41. package/dist/mcp/error/mcp-client-error.d.mts +36 -0
  42. package/dist/mcp/error/mcp-client-error.d.mts.map +1 -0
  43. package/dist/mcp/error/mcp-client-error.mjs +33 -0
  44. package/dist/mcp/error/mcp-client-error.mjs.map +1 -0
  45. package/dist/mcp/index.d.mts +8 -0
  46. package/dist/mcp/index.mjs +9 -0
  47. package/dist/mcp/tool/json-rpc-message.d.mts +50 -0
  48. package/dist/mcp/tool/json-rpc-message.d.mts.map +1 -0
  49. package/dist/mcp/tool/json-rpc-message.mjs +84 -0
  50. package/dist/mcp/tool/json-rpc-message.mjs.map +1 -0
  51. package/dist/mcp/tool/mcp-client.d.mts +71 -0
  52. package/dist/mcp/tool/mcp-client.d.mts.map +1 -0
  53. package/dist/mcp/tool/mcp-client.mjs +304 -0
  54. package/dist/mcp/tool/mcp-client.mjs.map +1 -0
  55. package/dist/mcp/tool/mcp-http-transport.d.mts +62 -0
  56. package/dist/mcp/tool/mcp-http-transport.d.mts.map +1 -0
  57. package/dist/mcp/tool/mcp-http-transport.mjs +307 -0
  58. package/dist/mcp/tool/mcp-http-transport.mjs.map +1 -0
  59. package/dist/mcp/tool/mcp-tools.d.mts +20 -0
  60. package/dist/mcp/tool/mcp-tools.d.mts.map +1 -0
  61. package/dist/mcp/tool/mcp-tools.mjs +73 -0
  62. package/dist/mcp/tool/mcp-tools.mjs.map +1 -0
  63. package/dist/mcp/tool/mcp-transport.d.mts +81 -0
  64. package/dist/mcp/tool/mcp-transport.d.mts.map +1 -0
  65. package/dist/mcp/tool/mcp-transport.mjs +11 -0
  66. package/dist/mcp/tool/mcp-transport.mjs.map +1 -0
  67. package/dist/mcp/tool/types.d.mts +230 -0
  68. package/dist/mcp/tool/types.d.mts.map +1 -0
  69. package/dist/mcp/tool/types.mjs +19 -0
  70. package/dist/mcp/tool/types.mjs.map +1 -0
  71. package/dist/persistence/index.d.mts +3 -0
  72. package/dist/persistence/index.mjs +3 -0
  73. package/dist/persistence/memory.d.mts +21 -0
  74. package/dist/persistence/memory.d.mts.map +1 -0
  75. package/dist/persistence/memory.mjs +107 -0
  76. package/dist/persistence/memory.mjs.map +1 -0
  77. package/dist/persistence/types.d.mts +124 -0
  78. package/dist/persistence/types.d.mts.map +1 -0
  79. package/dist/plugins/index.d.mts +2 -0
  80. package/dist/plugins/runtime.d.mts +17 -0
  81. package/dist/plugins/runtime.d.mts.map +1 -0
  82. package/dist/plugins/runtime.mjs +456 -0
  83. package/dist/plugins/runtime.mjs.map +1 -0
  84. package/dist/plugins/types.d.mts +344 -0
  85. package/dist/plugins/types.d.mts.map +1 -0
  86. package/dist/providers/index.d.mts +9 -0
  87. package/dist/providers/index.mjs +0 -0
  88. package/dist/providers/types/capabilities.d.mts +153 -0
  89. package/dist/providers/types/capabilities.d.mts.map +1 -0
  90. package/dist/providers/types/content.d.mts +125 -0
  91. package/dist/providers/types/content.d.mts.map +1 -0
  92. package/dist/providers/types/conversation.d.mts +32 -0
  93. package/dist/providers/types/conversation.d.mts.map +1 -0
  94. package/dist/providers/types/index.d.mts +8 -0
  95. package/dist/providers/types/input.d.mts +74 -0
  96. package/dist/providers/types/input.d.mts.map +1 -0
  97. package/dist/providers/types/model.d.mts +68 -0
  98. package/dist/providers/types/model.d.mts.map +1 -0
  99. package/dist/providers/types/output.d.mts +29 -0
  100. package/dist/providers/types/output.d.mts.map +1 -0
  101. package/dist/providers/types/response.d.mts +35 -0
  102. package/dist/providers/types/response.d.mts.map +1 -0
  103. package/dist/providers/types/tool-calls.d.mts +51 -0
  104. package/dist/providers/types/tool-calls.d.mts.map +1 -0
  105. package/dist/run/agent-loop.mjs +231 -0
  106. package/dist/run/agent-loop.mjs.map +1 -0
  107. package/dist/run/event-queue.mjs +67 -0
  108. package/dist/run/event-queue.mjs.map +1 -0
  109. package/dist/run/execute-tool-calls.mjs +550 -0
  110. package/dist/run/execute-tool-calls.mjs.map +1 -0
  111. package/dist/run/execution.mjs +93 -0
  112. package/dist/run/execution.mjs.map +1 -0
  113. package/dist/run/helpers.mjs +466 -0
  114. package/dist/run/helpers.mjs.map +1 -0
  115. package/dist/run/hooks.mjs +124 -0
  116. package/dist/run/hooks.mjs.map +1 -0
  117. package/dist/run/index.d.mts +4 -0
  118. package/dist/run/messages.d.mts +8 -0
  119. package/dist/run/messages.d.mts.map +1 -0
  120. package/dist/run/messages.mjs +83 -0
  121. package/dist/run/messages.mjs.map +1 -0
  122. package/dist/run/model-strategy.mjs +105 -0
  123. package/dist/run/model-strategy.mjs.map +1 -0
  124. package/dist/run/output-errors.d.mts +75 -0
  125. package/dist/run/output-errors.d.mts.map +1 -0
  126. package/dist/run/pending-tools.d.mts +1 -0
  127. package/dist/run/pending-tools.mjs +185 -0
  128. package/dist/run/pending-tools.mjs.map +1 -0
  129. package/dist/run/registry.mjs +22 -0
  130. package/dist/run/registry.mjs.map +1 -0
  131. package/dist/run/runtime.d.mts +19 -0
  132. package/dist/run/runtime.d.mts.map +1 -0
  133. package/dist/run/runtime.mjs +491 -0
  134. package/dist/run/runtime.mjs.map +1 -0
  135. package/dist/run/stop-conditions.mjs +41 -0
  136. package/dist/run/stop-conditions.mjs.map +1 -0
  137. package/dist/run/types.d.mts +348 -0
  138. package/dist/run/types.d.mts.map +1 -0
  139. package/dist/schema/index.d.mts +2 -0
  140. package/dist/schema/resolve-json-schema.d.mts +12 -0
  141. package/dist/schema/resolve-json-schema.d.mts.map +1 -0
  142. package/dist/schema/resolve-json-schema.mjs +167 -0
  143. package/dist/schema/resolve-json-schema.mjs.map +1 -0
  144. package/dist/schema/types.d.mts +27 -0
  145. package/dist/schema/types.d.mts.map +1 -0
  146. package/dist/server/create-server.d.mts +21 -0
  147. package/dist/server/create-server.d.mts.map +1 -0
  148. package/dist/server/create-server.mjs +107 -0
  149. package/dist/server/create-server.mjs.map +1 -0
  150. package/dist/server/http.mjs +182 -0
  151. package/dist/server/http.mjs.map +1 -0
  152. package/dist/server/index.d.mts +3 -0
  153. package/dist/server/index.mjs +3 -0
  154. package/dist/server/routes.mjs +399 -0
  155. package/dist/server/routes.mjs.map +1 -0
  156. package/dist/server/types.d.mts +31 -0
  157. package/dist/server/types.d.mts.map +1 -0
  158. package/dist/tools/constants.d.mts +12 -0
  159. package/dist/tools/constants.d.mts.map +1 -0
  160. package/dist/tools/constants.mjs +13 -0
  161. package/dist/tools/constants.mjs.map +1 -0
  162. package/dist/tools/define-tool.d.mts +25 -0
  163. package/dist/tools/define-tool.d.mts.map +1 -0
  164. package/dist/tools/define-tool.mjs +76 -0
  165. package/dist/tools/define-tool.mjs.map +1 -0
  166. package/dist/tools/index.d.mts +5 -0
  167. package/dist/tools/lazy-tools.d.mts +49 -0
  168. package/dist/tools/lazy-tools.d.mts.map +1 -0
  169. package/dist/tools/lazy-tools.mjs +87 -0
  170. package/dist/tools/lazy-tools.mjs.map +1 -0
  171. package/dist/tools/resolve-tools.d.mts +12 -0
  172. package/dist/tools/resolve-tools.d.mts.map +1 -0
  173. package/dist/tools/resolve-tools.mjs +86 -0
  174. package/dist/tools/resolve-tools.mjs.map +1 -0
  175. package/dist/tools/types.d.mts +318 -0
  176. package/dist/tools/types.d.mts.map +1 -0
  177. package/dist/tools/validation.mjs +23 -0
  178. package/dist/tools/validation.mjs.map +1 -0
  179. package/package.json +72 -0
@@ -0,0 +1,5 @@
1
+ import { TOOL_CLEANUP, TOOL_JSON_SCHEMA } from "./constants.mjs";
2
+ import { AgentToolDefinition, BoundToolApprovalConfig, ClientToolDefinition, ExecutionToolError, ExecutionToolErrorResult, HostedToolDefinition, LazyToolLoader, LazyToolSource, LazyToolSourceResult, OnToolError, OpenString, ParseToolError, ParseToolErrorResult, RepairAction, ResultAction, RetryAction, SendToModelAction, ServerToolDefinition, SkipAction, ThrowAction, ToolApprovalConfig, ToolApprovalDecision, ToolApprovalState, ToolContract, ToolContractConfig, ToolDefinitionTarget, ToolErrorBase, ToolErrorContext, ToolErrorMode, ToolErrorPayload, ToolErrorResultFor, ToolHandler, ToolListFactory, ToolNameOf, ToolNamesOf, ToolRunContext, ToolSource, ToolSourceResult, ToolTarget, ValidationToolError, ValidationToolErrorResult } from "./types.mjs";
3
+ import { defineTool } from "./define-tool.mjs";
4
+ import { lazyTools } from "./lazy-tools.mjs";
5
+ import { isCallableToolDefinition } from "./resolve-tools.mjs";
@@ -0,0 +1,49 @@
1
+ import { Awaitable } from "../internal/types.mjs";
2
+ import { LazyToolSource } from "./types.mjs";
3
+
4
+ //#region src/tools/lazy-tools.d.ts
5
+ type AnyLazyToolLoader = (...args: readonly unknown[]) => Awaitable<unknown>;
6
+ type InferLazyToolContext<TLoader extends AnyLazyToolLoader> = Parameters<TLoader> extends [] ? unknown : Exclude<Parameters<TLoader>[0], undefined>;
7
+ /**
8
+ * Creates a lifecycle-aware tool source that loads once, caches successes, and can be explicitly disposed.
9
+ *
10
+ * Useful for remote or expensive tool providers such as MCP servers where you want
11
+ * to reuse a client across runs instead of reconnecting every time.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { defineAgent, lazyTools } from "@better-agent/core";
16
+ * import { convertMCPTools, createMCPClient } from "@better-agent/core/mcp";
17
+ *
18
+ * const context7Tools = lazyTools(async () => {
19
+ * const client = await createMCPClient({
20
+ * transport: {
21
+ * type: "http",
22
+ * url: process.env.CONTEXT7_MCP_URL ?? "https://mcp.context7.com/mcp",
23
+ * },
24
+ * });
25
+ *
26
+ * const listed = await client.listTools();
27
+ *
28
+ * return {
29
+ * tools: convertMCPTools(client, listed.tools, { prefix: "context7" }),
30
+ * dispose: async () => {
31
+ * await client.close?.();
32
+ * },
33
+ * };
34
+ * });
35
+ *
36
+ * const agent = defineAgent({
37
+ * name: "docs",
38
+ * model: openai.text("gpt-5.4-mini"),
39
+ * tools: context7Tools,
40
+ * });
41
+ * ```
42
+ *
43
+ * Call `source.dispose()` when cached provider resources should be released, or
44
+ * `source.reload(...)` to force a refresh.
45
+ */
46
+ declare const lazyTools: <TLoader extends AnyLazyToolLoader>(loader: TLoader) => LazyToolSource<InferLazyToolContext<TLoader>>;
47
+ //#endregion
48
+ export { lazyTools };
49
+ //# sourceMappingURL=lazy-tools.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy-tools.d.mts","names":[],"sources":["../../src/tools/lazy-tools.ts"],"mappings":";;;;KAGK,iBAAA,OAAwB,IAAA,yBAA6B,SAAA;AAAA,KAErD,oBAAA,iBAAqC,iBAAA,IAAqB,UAAA,CAAW,OAAA,yBAEpE,OAAA,CAAQ,UAAA,CAAW,OAAA;AANgE;;;;;AAEtB;;;;;;;;;;;;;;;;;;;;AA6CnE;;;;;;;;;;;;;;AA/CyF,cA+C5E,SAAA,mBAA6B,iBAAA,EAAiB,MAAA,EAC/C,OAAA,KACT,cAAA,CAAe,oBAAA,CAAqB,OAAA"}
@@ -0,0 +1,87 @@
1
+ //#region src/tools/lazy-tools.ts
2
+ /**
3
+ * Creates a lifecycle-aware tool source that loads once, caches successes, and can be explicitly disposed.
4
+ *
5
+ * Useful for remote or expensive tool providers such as MCP servers where you want
6
+ * to reuse a client across runs instead of reconnecting every time.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { defineAgent, lazyTools } from "@better-agent/core";
11
+ * import { convertMCPTools, createMCPClient } from "@better-agent/core/mcp";
12
+ *
13
+ * const context7Tools = lazyTools(async () => {
14
+ * const client = await createMCPClient({
15
+ * transport: {
16
+ * type: "http",
17
+ * url: process.env.CONTEXT7_MCP_URL ?? "https://mcp.context7.com/mcp",
18
+ * },
19
+ * });
20
+ *
21
+ * const listed = await client.listTools();
22
+ *
23
+ * return {
24
+ * tools: convertMCPTools(client, listed.tools, { prefix: "context7" }),
25
+ * dispose: async () => {
26
+ * await client.close?.();
27
+ * },
28
+ * };
29
+ * });
30
+ *
31
+ * const agent = defineAgent({
32
+ * name: "docs",
33
+ * model: openai.text("gpt-5.4-mini"),
34
+ * tools: context7Tools,
35
+ * });
36
+ * ```
37
+ *
38
+ * Call `source.dispose()` when cached provider resources should be released, or
39
+ * `source.reload(...)` to force a refresh.
40
+ */
41
+ const lazyTools = (loader) => {
42
+ let loadedPromise;
43
+ let loadedDispose;
44
+ const load = async (context) => {
45
+ if (!loadedPromise) loadedPromise = (async () => {
46
+ try {
47
+ const value = await loader(context);
48
+ const resolved = typeof value === "object" && value !== null && "tools" in value ? (() => {
49
+ const result = value;
50
+ return {
51
+ tools: Array.isArray(result.tools) ? [...result.tools] : [result.tools],
52
+ dispose: result.dispose
53
+ };
54
+ })() : {
55
+ tools: Array.isArray(value) ? [...value] : [value],
56
+ dispose: void 0
57
+ };
58
+ loadedDispose = resolved.dispose;
59
+ return resolved;
60
+ } catch (error) {
61
+ loadedPromise = void 0;
62
+ loadedDispose = void 0;
63
+ throw error;
64
+ }
65
+ })();
66
+ return await loadedPromise;
67
+ };
68
+ const dispose = async () => {
69
+ const disposer = loadedDispose;
70
+ loadedPromise = void 0;
71
+ loadedDispose = void 0;
72
+ await disposer?.();
73
+ };
74
+ return {
75
+ kind: "lazy",
76
+ resolve: load,
77
+ dispose,
78
+ reload: async (context) => {
79
+ await dispose();
80
+ return await load(context);
81
+ }
82
+ };
83
+ };
84
+
85
+ //#endregion
86
+ export { lazyTools };
87
+ //# sourceMappingURL=lazy-tools.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy-tools.mjs","names":[],"sources":["../../src/tools/lazy-tools.ts"],"sourcesContent":["import type { Awaitable } from \"../internal/types\";\nimport type { AgentToolDefinition, LazyToolSource, LazyToolSourceResult } from \"./types\";\n\ntype AnyLazyToolLoader = (...args: readonly unknown[]) => Awaitable<unknown>;\n\ntype InferLazyToolContext<TLoader extends AnyLazyToolLoader> = Parameters<TLoader> extends []\n ? unknown\n : Exclude<Parameters<TLoader>[0], undefined>;\n\n/**\n * Creates a lifecycle-aware tool source that loads once, caches successes, and can be explicitly disposed.\n *\n * Useful for remote or expensive tool providers such as MCP servers where you want\n * to reuse a client across runs instead of reconnecting every time.\n *\n * @example\n * ```ts\n * import { defineAgent, lazyTools } from \"@better-agent/core\";\n * import { convertMCPTools, createMCPClient } from \"@better-agent/core/mcp\";\n *\n * const context7Tools = lazyTools(async () => {\n * const client = await createMCPClient({\n * transport: {\n * type: \"http\",\n * url: process.env.CONTEXT7_MCP_URL ?? \"https://mcp.context7.com/mcp\",\n * },\n * });\n *\n * const listed = await client.listTools();\n *\n * return {\n * tools: convertMCPTools(client, listed.tools, { prefix: \"context7\" }),\n * dispose: async () => {\n * await client.close?.();\n * },\n * };\n * });\n *\n * const agent = defineAgent({\n * name: \"docs\",\n * model: openai.text(\"gpt-5.4-mini\"),\n * tools: context7Tools,\n * });\n * ```\n *\n * Call `source.dispose()` when cached provider resources should be released, or\n * `source.reload(...)` to force a refresh.\n */\nexport const lazyTools = <TLoader extends AnyLazyToolLoader>(\n loader: TLoader,\n): LazyToolSource<InferLazyToolContext<TLoader>> => {\n type TContext = InferLazyToolContext<TLoader>;\n\n let loadedPromise: Promise<LazyToolSourceResult> | undefined;\n let loadedDispose: (() => Awaitable<void>) | undefined;\n\n const load = async (context: TContext | undefined): Promise<LazyToolSourceResult> => {\n if (!loadedPromise) {\n loadedPromise = (async (): Promise<LazyToolSourceResult> => {\n try {\n const value = await (\n loader as (context: TContext | undefined) => Awaitable<unknown>\n )(context);\n const resolved =\n typeof value === \"object\" && value !== null && \"tools\" in value\n ? (() => {\n const result = value as LazyToolSourceResult;\n const tools = Array.isArray(result.tools)\n ? [...result.tools]\n : [result.tools];\n\n return {\n tools,\n dispose: result.dispose,\n };\n })()\n : {\n tools: Array.isArray(value)\n ? [...(value as readonly AgentToolDefinition<unknown>[])]\n : [value as AgentToolDefinition<unknown>],\n dispose: undefined,\n };\n loadedDispose = resolved.dispose;\n return resolved;\n } catch (error) {\n loadedPromise = undefined;\n loadedDispose = undefined;\n throw error;\n }\n })();\n }\n\n return await loadedPromise;\n };\n\n const dispose = async () => {\n const disposer = loadedDispose;\n loadedPromise = undefined;\n loadedDispose = undefined;\n await disposer?.();\n };\n\n return {\n kind: \"lazy\",\n resolve: load,\n dispose,\n reload: async (context) => {\n await dispose();\n return await load(context);\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,MAAa,aACT,WACgD;CAGhD,IAAI;CACJ,IAAI;CAEJ,MAAM,OAAO,OAAO,YAAiE;AACjF,MAAI,CAAC,cACD,kBAAiB,YAA2C;AACxD,OAAI;IACA,MAAM,QAAQ,MACV,OACF,QAAQ;IACV,MAAM,WACF,OAAO,UAAU,YAAY,UAAU,QAAQ,WAAW,eAC7C;KACH,MAAM,SAAS;AAKf,YAAO;MACH,OALU,MAAM,QAAQ,OAAO,MAAM,GACnC,CAAC,GAAG,OAAO,MAAM,GACjB,CAAC,OAAO,MAAM;MAIhB,SAAS,OAAO;MACnB;QACD,GACJ;KACI,OAAO,MAAM,QAAQ,MAAM,GACrB,CAAC,GAAI,MAAkD,GACvD,CAAC,MAAsC;KAC7C,SAAS;KACZ;AACX,oBAAgB,SAAS;AACzB,WAAO;YACF,OAAO;AACZ,oBAAgB;AAChB,oBAAgB;AAChB,UAAM;;MAEV;AAGR,SAAO,MAAM;;CAGjB,MAAM,UAAU,YAAY;EACxB,MAAM,WAAW;AACjB,kBAAgB;AAChB,kBAAgB;AAChB,QAAM,YAAY;;AAGtB,QAAO;EACH,MAAM;EACN,SAAS;EACT;EACA,QAAQ,OAAO,YAAY;AACvB,SAAM,SAAS;AACf,UAAO,MAAM,KAAK,QAAQ;;EAEjC"}
@@ -0,0 +1,12 @@
1
+ import { AgentToolDefinition } from "./types.mjs";
2
+
3
+ //#region src/tools/resolve-tools.d.ts
4
+ /**
5
+ * Checks whether a tool is directly callable by the runtime.
6
+ */
7
+ declare const isCallableToolDefinition: <TContext>(tool: AgentToolDefinition<TContext>) => tool is Exclude<AgentToolDefinition<TContext>, {
8
+ kind: "hosted";
9
+ }>;
10
+ //#endregion
11
+ export { isCallableToolDefinition };
12
+ //# sourceMappingURL=resolve-tools.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-tools.d.mts","names":[],"sources":["../../src/tools/resolve-tools.ts"],"mappings":";;;;;;cAqLa,wBAAA,aAAoC,IAAA,EACvC,mBAAA,CAAoB,QAAA,MAC3B,IAAA,IAAQ,OAAA,CAAQ,mBAAA,CAAoB,QAAA;EAAa,IAAA;AAAA"}
@@ -0,0 +1,86 @@
1
+ import { TOOL_CLEANUP } from "./constants.mjs";
2
+ import { BetterAgentError } from "@better-agent/shared/errors";
3
+
4
+ //#region src/tools/resolve-tools.ts
5
+ /**
6
+ * Resolves all tools available for a run and collects cleanup hooks.
7
+ */
8
+ const resolveToolsForRun = async (params) => {
9
+ const cleanup = /* @__PURE__ */ new Set();
10
+ const normalize = (value) => Array.isArray(value) ? [...value] : [value];
11
+ const isLazyToolSourceResult = (value) => typeof value === "object" && value !== null && "tools" in value;
12
+ const resolveSource = async (source, context) => {
13
+ const resolved = typeof source === "function" ? await source(context) : typeof source === "object" && source !== null && "kind" in source && source.kind === "lazy" ? await source.resolve(context) : await source;
14
+ if (isLazyToolSourceResult(resolved)) return normalize(resolved.tools);
15
+ return normalize(resolved);
16
+ };
17
+ const resolveList = async (sources, context) => {
18
+ if (!sources) return [];
19
+ const list = Array.isArray(sources) ? sources : [sources];
20
+ return (await Promise.all(list.map((source) => resolveSource(source, context)))).flat();
21
+ };
22
+ const collectCleanup = (tools) => {
23
+ for (const tool of tools) {
24
+ const fn = tool[TOOL_CLEANUP];
25
+ if (fn) cleanup.add(fn);
26
+ }
27
+ };
28
+ const appTools = params.appTools ?? [];
29
+ const agentTools = await resolveList(params.agentTools, params.context);
30
+ collectCleanup(appTools);
31
+ collectCleanup(agentTools);
32
+ const resolvedTools = [...appTools, ...agentTools];
33
+ const seenToolNames = /* @__PURE__ */ new Set();
34
+ for (const [index, tool] of resolvedTools.entries()) {
35
+ if (!tool || typeof tool !== "object" || !("kind" in tool) || tool.kind !== "server" && tool.kind !== "client" && tool.kind !== "hosted") throw BetterAgentError.fromCode("VALIDATION_FAILED", "Invalid tool entry. Pass tool implementations, client tools, or hosted tools.", {
36
+ context: { index },
37
+ trace: [{
38
+ at: "core.tools.resolveToolsForRun.validate.invalidEntry",
39
+ data: {
40
+ index,
41
+ toolType: typeof tool
42
+ }
43
+ }]
44
+ });
45
+ const toolName = tool.kind === "hosted" ? typeof tool.name === "string" && tool.name.length > 0 ? tool.name : typeof tool.type === "string" && tool.type.length > 0 ? tool.type : void 0 : typeof tool.name === "string" && tool.name.length > 0 ? tool.name : void 0;
46
+ if (!toolName) throw BetterAgentError.fromCode("VALIDATION_FAILED", tool.kind === "hosted" ? "Hosted tools must define a non-empty type or name." : "Tool name must be a non-empty string.", {
47
+ context: { index },
48
+ trace: [{
49
+ at: "core.tools.resolveToolsForRun.validate.invalidName",
50
+ data: {
51
+ index,
52
+ kind: tool.kind
53
+ }
54
+ }]
55
+ });
56
+ if (seenToolNames.has(toolName)) throw BetterAgentError.fromCode("VALIDATION_FAILED", `Duplicate tool name '${toolName}' in tools list.`, {
57
+ context: { toolName },
58
+ trace: [{
59
+ at: "core.tools.resolveToolsForRun.validate.duplicateName",
60
+ data: {
61
+ index,
62
+ toolName
63
+ }
64
+ }]
65
+ });
66
+ seenToolNames.add(toolName);
67
+ }
68
+ const runCleanup = async () => {
69
+ if (cleanup.size === 0) return;
70
+ const tasks = Array.from(cleanup, async (fn) => await fn());
71
+ cleanup.clear();
72
+ await Promise.allSettled(tasks);
73
+ };
74
+ return {
75
+ tools: resolvedTools,
76
+ runCleanup
77
+ };
78
+ };
79
+ /**
80
+ * Checks whether a tool is directly callable by the runtime.
81
+ */
82
+ const isCallableToolDefinition = (tool) => tool.kind !== "hosted";
83
+
84
+ //#endregion
85
+ export { isCallableToolDefinition, resolveToolsForRun };
86
+ //# sourceMappingURL=resolve-tools.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-tools.mjs","names":[],"sources":["../../src/tools/resolve-tools.ts"],"sourcesContent":["import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport type { Awaitable } from \"../internal/types\";\nimport { TOOL_CLEANUP } from \"./constants\";\nimport type { AgentToolDefinition, LazyToolSourceResult, ToolSource } from \"./types\";\n\n/**\n * Resolves all tools available for a run and collects cleanup hooks.\n */\nexport const resolveToolsForRun = async <TContext>(params: {\n appTools?: readonly AgentToolDefinition[];\n agentTools?: ToolSource<TContext> | readonly ToolSource<TContext>[];\n context?: TContext;\n}): Promise<{\n /** Tools available for this run. */\n tools: AgentToolDefinition[];\n /** Runs cleanup hooks registered via {@link TOOL_CLEANUP}. */\n runCleanup: () => Awaitable<void>;\n}> => {\n const cleanup = new Set<() => Promise<void> | void>();\n\n const normalize = (value: readonly AgentToolDefinition[] | AgentToolDefinition) =>\n Array.isArray(value) ? [...value] : [value];\n\n const isLazyToolSourceResult = (value: unknown): value is LazyToolSourceResult =>\n typeof value === \"object\" && value !== null && \"tools\" in value;\n\n const resolveSource = async (\n source: ToolSource<TContext>,\n context: TContext | undefined,\n ): Promise<AgentToolDefinition[]> => {\n const resolved =\n typeof source === \"function\"\n ? await (source as (context: TContext | undefined) => Awaitable<unknown>)(context)\n : typeof source === \"object\" &&\n source !== null &&\n \"kind\" in source &&\n source.kind === \"lazy\"\n ? await source.resolve(context)\n : await (source as Awaitable<unknown>);\n\n if (isLazyToolSourceResult(resolved)) {\n return normalize(\n resolved.tools as readonly AgentToolDefinition[] | AgentToolDefinition,\n );\n }\n\n return normalize(resolved as readonly AgentToolDefinition[] | AgentToolDefinition);\n };\n\n const resolveList = async (\n sources: ToolSource<TContext> | readonly ToolSource<TContext>[] | undefined,\n context: TContext | undefined,\n ) => {\n if (!sources) return [];\n const list = Array.isArray(sources) ? sources : [sources];\n const resolved = await Promise.all(list.map((source) => resolveSource(source, context)));\n return resolved.flat();\n };\n\n const collectCleanup = (tools: readonly AgentToolDefinition[]) => {\n for (const tool of tools) {\n const fn = tool[TOOL_CLEANUP];\n if (fn) cleanup.add(fn);\n }\n };\n\n const appTools = params.appTools ?? [];\n const agentTools = await resolveList(params.agentTools, params.context);\n\n collectCleanup(appTools);\n collectCleanup(agentTools);\n\n const resolvedTools = [...appTools, ...agentTools];\n const seenToolNames = new Set<string>();\n\n for (const [index, tool] of resolvedTools.entries()) {\n if (\n !tool ||\n typeof tool !== \"object\" ||\n !(\"kind\" in tool) ||\n (tool.kind !== \"server\" && tool.kind !== \"client\" && tool.kind !== \"hosted\")\n ) {\n throw BetterAgentError.fromCode(\n \"VALIDATION_FAILED\",\n \"Invalid tool entry. Pass tool implementations, client tools, or hosted tools.\",\n {\n context: { index },\n trace: [\n {\n at: \"core.tools.resolveToolsForRun.validate.invalidEntry\",\n data: {\n index,\n toolType: typeof tool,\n },\n },\n ],\n },\n );\n }\n\n const toolName =\n tool.kind === \"hosted\"\n ? typeof tool.name === \"string\" && tool.name.length > 0\n ? tool.name\n : typeof tool.type === \"string\" && tool.type.length > 0\n ? tool.type\n : undefined\n : typeof tool.name === \"string\" && tool.name.length > 0\n ? tool.name\n : undefined;\n\n if (!toolName) {\n throw BetterAgentError.fromCode(\n \"VALIDATION_FAILED\",\n tool.kind === \"hosted\"\n ? \"Hosted tools must define a non-empty type or name.\"\n : \"Tool name must be a non-empty string.\",\n {\n context: { index },\n trace: [\n {\n at: \"core.tools.resolveToolsForRun.validate.invalidName\",\n data: { index, kind: tool.kind },\n },\n ],\n },\n );\n }\n\n if (seenToolNames.has(toolName)) {\n throw BetterAgentError.fromCode(\n \"VALIDATION_FAILED\",\n `Duplicate tool name '${toolName}' in tools list.`,\n {\n context: { toolName },\n trace: [\n {\n at: \"core.tools.resolveToolsForRun.validate.duplicateName\",\n data: {\n index,\n toolName,\n },\n },\n ],\n },\n );\n }\n\n seenToolNames.add(toolName);\n }\n\n const runCleanup = async () => {\n if (cleanup.size === 0) return;\n const tasks = Array.from(cleanup, async (fn) => await fn());\n cleanup.clear();\n await Promise.allSettled(tasks);\n };\n\n return {\n tools: resolvedTools,\n runCleanup,\n };\n};\n\n/**\n * Checks whether a tool is a server tool definition.\n */\nexport const isServerToolDefinition = <TContext>(\n tool: AgentToolDefinition<TContext>,\n): tool is Extract<AgentToolDefinition<TContext>, { kind: \"server\" }> => tool.kind === \"server\";\n\n/**\n * Checks whether a tool is a client tool definition.\n */\nexport const isClientToolDefinition = <TContext>(\n tool: AgentToolDefinition<TContext>,\n): tool is Extract<AgentToolDefinition<TContext>, { kind: \"client\" }> => tool.kind === \"client\";\n\n/**\n * Checks whether a tool is directly callable by the runtime.\n */\nexport const isCallableToolDefinition = <TContext>(\n tool: AgentToolDefinition<TContext>,\n): tool is Exclude<AgentToolDefinition<TContext>, { kind: \"hosted\" }> => tool.kind !== \"hosted\";\n"],"mappings":";;;;;;;AAQA,MAAa,qBAAqB,OAAiB,WAS7C;CACF,MAAM,0BAAU,IAAI,KAAiC;CAErD,MAAM,aAAa,UACf,MAAM,QAAQ,MAAM,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,MAAM;CAE/C,MAAM,0BAA0B,UAC5B,OAAO,UAAU,YAAY,UAAU,QAAQ,WAAW;CAE9D,MAAM,gBAAgB,OAClB,QACA,YACiC;EACjC,MAAM,WACF,OAAO,WAAW,aACZ,MAAO,OAAiE,QAAQ,GAChF,OAAO,WAAW,YAChB,WAAW,QACX,UAAU,UACV,OAAO,SAAS,SAChB,MAAM,OAAO,QAAQ,QAAQ,GAC7B,MAAO;AAEnB,MAAI,uBAAuB,SAAS,CAChC,QAAO,UACH,SAAS,MACZ;AAGL,SAAO,UAAU,SAAiE;;CAGtF,MAAM,cAAc,OAChB,SACA,YACC;AACD,MAAI,CAAC,QAAS,QAAO,EAAE;EACvB,MAAM,OAAO,MAAM,QAAQ,QAAQ,GAAG,UAAU,CAAC,QAAQ;AAEzD,UADiB,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,cAAc,QAAQ,QAAQ,CAAC,CAAC,EACxE,MAAM;;CAG1B,MAAM,kBAAkB,UAA0C;AAC9D,OAAK,MAAM,QAAQ,OAAO;GACtB,MAAM,KAAK,KAAK;AAChB,OAAI,GAAI,SAAQ,IAAI,GAAG;;;CAI/B,MAAM,WAAW,OAAO,YAAY,EAAE;CACtC,MAAM,aAAa,MAAM,YAAY,OAAO,YAAY,OAAO,QAAQ;AAEvE,gBAAe,SAAS;AACxB,gBAAe,WAAW;CAE1B,MAAM,gBAAgB,CAAC,GAAG,UAAU,GAAG,WAAW;CAClD,MAAM,gCAAgB,IAAI,KAAa;AAEvC,MAAK,MAAM,CAAC,OAAO,SAAS,cAAc,SAAS,EAAE;AACjD,MACI,CAAC,QACD,OAAO,SAAS,YAChB,EAAE,UAAU,SACX,KAAK,SAAS,YAAY,KAAK,SAAS,YAAY,KAAK,SAAS,SAEnE,OAAM,iBAAiB,SACnB,qBACA,iFACA;GACI,SAAS,EAAE,OAAO;GAClB,OAAO,CACH;IACI,IAAI;IACJ,MAAM;KACF;KACA,UAAU,OAAO;KACpB;IACJ,CACJ;GACJ,CACJ;EAGL,MAAM,WACF,KAAK,SAAS,WACR,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,IAChD,KAAK,OACL,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,IAClD,KAAK,OACL,SACN,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,IAClD,KAAK,OACL;AAEZ,MAAI,CAAC,SACD,OAAM,iBAAiB,SACnB,qBACA,KAAK,SAAS,WACR,uDACA,yCACN;GACI,SAAS,EAAE,OAAO;GAClB,OAAO,CACH;IACI,IAAI;IACJ,MAAM;KAAE;KAAO,MAAM,KAAK;KAAM;IACnC,CACJ;GACJ,CACJ;AAGL,MAAI,cAAc,IAAI,SAAS,CAC3B,OAAM,iBAAiB,SACnB,qBACA,wBAAwB,SAAS,mBACjC;GACI,SAAS,EAAE,UAAU;GACrB,OAAO,CACH;IACI,IAAI;IACJ,MAAM;KACF;KACA;KACH;IACJ,CACJ;GACJ,CACJ;AAGL,gBAAc,IAAI,SAAS;;CAG/B,MAAM,aAAa,YAAY;AAC3B,MAAI,QAAQ,SAAS,EAAG;EACxB,MAAM,QAAQ,MAAM,KAAK,SAAS,OAAO,OAAO,MAAM,IAAI,CAAC;AAC3D,UAAQ,OAAO;AACf,QAAM,QAAQ,WAAW,MAAM;;AAGnC,QAAO;EACH,OAAO;EACP;EACH;;;;;AAoBL,MAAa,4BACT,SACqE,KAAK,SAAS"}
@@ -0,0 +1,318 @@
1
+ import { Awaitable, BivariantFn } from "../internal/types.mjs";
2
+ import { InferSchemaInput, ResolvableSchema } from "../schema/types.mjs";
3
+ import { TOOL_CLEANUP, TOOL_JSON_SCHEMA } from "./constants.mjs";
4
+ import { Event } from "../events/types.mjs";
5
+ //#region src/tools/types.d.ts
6
+ /**
7
+ * Runtime location where a tool executes.
8
+ */
9
+ type ToolTarget = "server" | "client" | "hosted";
10
+ /**
11
+ * Approval state for a tool call.
12
+ */
13
+ type ToolApprovalState = "requested" | "approved" | "denied" | "expired";
14
+ /**
15
+ * Approval decisions that can be submitted for a pending tool call.
16
+ */
17
+ type ToolApprovalDecision = Extract<ToolApprovalState, "approved" | "denied">;
18
+ /**
19
+ * Default handling mode for recoverable tool failures.
20
+ */
21
+ type ToolErrorMode = "tool_error" | "throw";
22
+ /**
23
+ * Preserves autocomplete for known string literals while allowing arbitrary strings.
24
+ */
25
+ type OpenString<TKnown extends string> = TKnown | (string & {});
26
+ /**
27
+ * Extracts the static `name` from a tool definition.
28
+ */
29
+ type ToolNameOf<TTool> = TTool extends {
30
+ name: infer TName extends string;
31
+ } ? TName : never;
32
+ type AwaitedToolValue<TValue> = TValue extends PromiseLike<infer TResolved> ? AwaitedToolValue<TResolved> : TValue;
33
+ /**
34
+ * Extracts tool-name literals from tool definitions or factories.
35
+ */
36
+ type ToolNamesOf<TValue> = AwaitedToolValue<TValue> extends readonly (infer TItem)[] ? ToolNamesOf<TItem> : AwaitedToolValue<TValue> extends ((...args: infer _TArgs) => infer TResult) ? ToolNamesOf<TResult> : ToolNameOf<AwaitedToolValue<TValue>>;
37
+ /**
38
+ * Tool error payload sent back to the model.
39
+ */
40
+ interface ToolErrorPayload {
41
+ type: "tool_error";
42
+ toolName: string;
43
+ errorKind: "parse" | "validation" | "execution";
44
+ message: string;
45
+ retryable?: boolean;
46
+ }
47
+ /**
48
+ * Shared context available to all tool error hooks.
49
+ */
50
+ interface ToolErrorBase {
51
+ toolName: string;
52
+ toolCallId: string;
53
+ error: unknown;
54
+ rawArguments: string;
55
+ }
56
+ /**
57
+ * Parse error context for tool argument JSON failures.
58
+ */
59
+ interface ParseToolError extends ToolErrorBase {
60
+ errorKind: "parse";
61
+ }
62
+ /**
63
+ * Validation error context for schema validation failures.
64
+ */
65
+ interface ValidationToolError extends ToolErrorBase {
66
+ errorKind: "validation";
67
+ input: unknown;
68
+ }
69
+ /**
70
+ * Execution error context for handler, client, or MCP failures.
71
+ */
72
+ interface ExecutionToolError extends ToolErrorBase {
73
+ errorKind: "execution";
74
+ input: unknown;
75
+ }
76
+ /**
77
+ * Union of all recoverable tool error contexts.
78
+ */
79
+ type ToolErrorContext = ParseToolError | ValidationToolError | ExecutionToolError;
80
+ /**
81
+ * Sends a structured tool error result back to the model.
82
+ */
83
+ interface SendToModelAction {
84
+ action: "send_to_model";
85
+ message?: string;
86
+ retryable?: boolean;
87
+ }
88
+ /**
89
+ * Skips the current hook layer and falls through.
90
+ */
91
+ interface SkipAction {
92
+ action: "skip";
93
+ }
94
+ /**
95
+ * Re-throws the original recoverable tool failure and stops the run.
96
+ */
97
+ interface ThrowAction {
98
+ action: "throw";
99
+ }
100
+ /**
101
+ * Provides replacement tool input to validate and execute again.
102
+ */
103
+ interface RepairAction {
104
+ action: "repair";
105
+ input: unknown;
106
+ }
107
+ /**
108
+ * Retries the tool handler with the same validated input.
109
+ *
110
+ * Valid only for execution errors.
111
+ */
112
+ interface RetryAction {
113
+ action: "retry";
114
+ maxAttempts?: number;
115
+ }
116
+ /**
117
+ * Provides a successful fallback tool result.
118
+ *
119
+ * Valid only for execution errors.
120
+ */
121
+ interface ResultAction {
122
+ action: "result";
123
+ value: unknown;
124
+ }
125
+ /**
126
+ * Allowed return values for parse error hooks.
127
+ */
128
+ type ParseToolErrorResult = SendToModelAction | ThrowAction | RepairAction | SkipAction | undefined;
129
+ /**
130
+ * Allowed return values for schema validation error hooks.
131
+ */
132
+ type ValidationToolErrorResult = SendToModelAction | ThrowAction | RepairAction | SkipAction | undefined;
133
+ /**
134
+ * Allowed return values for execution error hooks.
135
+ */
136
+ type ExecutionToolErrorResult = SendToModelAction | SkipAction | ThrowAction | RepairAction | RetryAction | ResultAction | undefined;
137
+ type ToolErrorResultFor<T extends ToolErrorContext> = T extends ParseToolError ? ParseToolErrorResult : T extends ValidationToolError ? ValidationToolErrorResult : T extends ExecutionToolError ? ExecutionToolErrorResult : never;
138
+ /**
139
+ * Hook for customizing recoverable tool error behavior.
140
+ */
141
+ type OnToolError = <T extends ToolErrorContext>(context: T) => Awaitable<ToolErrorResultFor<T>>;
142
+ /**
143
+ * Approval policy for a tool.
144
+ */
145
+ type ToolApprovalConfig<TContext = any, TInput = unknown> = {
146
+ /** Whether approval is required before executing this tool. */required?: boolean; /** Optional timeout for approval in milliseconds. */
147
+ timeoutMs?: number; /** Optional metadata forwarded to approval UI or policy systems. */
148
+ meta?: Record<string, unknown>; /** Dynamic approval resolver based on context and input. */
149
+ resolve?: BivariantFn<[{
150
+ context: TContext;
151
+ input: TInput;
152
+ runId: string;
153
+ toolCallId: string;
154
+ toolName: string;
155
+ toolTarget: Exclude<ToolTarget, "hosted">;
156
+ }], Awaitable<{
157
+ required?: boolean;
158
+ timeoutMs?: number;
159
+ meta?: Record<string, unknown>;
160
+ }>>;
161
+ };
162
+ /**
163
+ * Approval config specialized to a validated tool input schema and run context.
164
+ */
165
+ type BoundToolApprovalConfig<TContext, TSchema extends ResolvableSchema> = ToolApprovalConfig<TContext, InferSchemaInput<TSchema>>;
166
+ /**
167
+ * Extra context passed to a tool handler at call time.
168
+ */
169
+ interface ToolRunContext {
170
+ /** Abort signal for cancelling the active run. */
171
+ signal: AbortSignal;
172
+ /** Emits runtime events while the tool is running. */
173
+ emit: (event: Event) => Awaitable<void>;
174
+ }
175
+ /**
176
+ * Tool handler.
177
+ *
178
+ * @typeParam TInput Parsed and validated tool input type.
179
+ */
180
+ type ToolHandler<TInput, TResult = unknown> = BivariantFn<[TInput, ToolRunContext], Awaitable<TResult>>;
181
+ /**
182
+ * Shared tool contract shape without a concrete runtime implementation.
183
+ */
184
+ interface ToolContractConfig<TSchema extends ResolvableSchema, TName extends string = string, TContext = any> {
185
+ /** Stable tool name exposed to the model. */
186
+ name: TName;
187
+ /** Short description shown to the model. */
188
+ description?: string;
189
+ /** Input schema used for validation and model-facing tool definitions. */
190
+ schema: TSchema;
191
+ /** When true, input validation should be strict when supported by the runtime. */
192
+ strict?: boolean;
193
+ /** Optional approval policy for this tool call. */
194
+ approval?: BoundToolApprovalConfig<TContext, TSchema>;
195
+ /** Optional default handling mode for recoverable tool failures. */
196
+ toolErrorMode?: ToolErrorMode;
197
+ /** Optional hook for customizing recoverable tool failures. */
198
+ onToolError?: OnToolError;
199
+ /** Optional per-run cleanup hook collected via {@link TOOL_CLEANUP}. */
200
+ [TOOL_CLEANUP]?: () => Awaitable<void>;
201
+ /** Optional pre-resolved JSON Schema. Skips conversion when present. */
202
+ [TOOL_JSON_SCHEMA]?: Record<string, unknown>;
203
+ }
204
+ /**
205
+ * Tool contract returned by `defineTool(...)`.
206
+ */
207
+ type ToolContract<TSchema extends ResolvableSchema, TName extends string = string, TContext = any> = ToolContractConfig<TSchema, TName, TContext> & {
208
+ [TOOL_JSON_SCHEMA]: Record<string, unknown>;
209
+ /**
210
+ * Creates a server-executed implementation.
211
+ */
212
+ server: <TAs extends string | undefined = undefined, TResult = unknown>(handler: ToolHandler<InferSchemaInput<TSchema>, TResult>, options?: {
213
+ /**
214
+ * Override for the final tool `name`.
215
+ */
216
+ as?: TAs;
217
+ }) => ServerToolDefinition<TSchema, TAs extends string ? TAs : TName, TResult, TContext>;
218
+ /**
219
+ * Creates a client-executed declaration.
220
+ */
221
+ client: <TAs extends string | undefined = undefined>(options?: {
222
+ /**
223
+ * Override for the final tool `name`.
224
+ */
225
+ as?: TAs;
226
+ }) => ClientToolDefinition<TSchema, TAs extends string ? TAs : TName, TContext>;
227
+ };
228
+ /**
229
+ * Server tool definition executed by the Better Agent runtime.
230
+ */
231
+ type ServerToolDefinition<TSchema extends ResolvableSchema = ResolvableSchema, TName extends string = string, TResult = unknown, TContext = any> = {
232
+ /** Discriminator for server-executed tools. */kind: "server"; /** Stable tool name exposed to the model. */
233
+ name: TName; /** Short description shown to the model. */
234
+ description?: string; /** Original schema value kept for reference. */
235
+ schema: TSchema; /** When true, input validation should be strict when supported by the runtime. */
236
+ strict?: boolean; /** Optional approval policy for this tool call. */
237
+ approval?: BoundToolApprovalConfig<TContext, TSchema>; /** Optional default handling mode for recoverable tool failures. */
238
+ toolErrorMode?: ToolErrorMode; /** Optional hook for customizing recoverable tool failures. */
239
+ onToolError?: OnToolError; /** Tool implementation. Receives validated input and runtime context. */
240
+ handler: ToolHandler<InferSchemaInput<TSchema>, TResult>; /** Optional per-run cleanup hook collected via {@link TOOL_CLEANUP}. */
241
+ [TOOL_CLEANUP]?: () => Awaitable<void>; /** Resolved JSON Schema for the tool input. */
242
+ [TOOL_JSON_SCHEMA]: Record<string, unknown>;
243
+ };
244
+ /**
245
+ * Provider-hosted tool definition.
246
+ */
247
+ type HostedToolDefinition<TProvider extends string = string, TType extends string = string, TConfig extends Record<string, unknown> = Record<string, unknown>> = {
248
+ /** Discriminator for provider-executed tools. */kind: "hosted"; /** Provider id that understands this hosted tool shape. */
249
+ provider: TProvider; /** Provider-native tool type identifier. */
250
+ type: TType; /** Provider-native config payload forwarded by provider mappers. */
251
+ config: TConfig; /** Optional display or metadata name. */
252
+ name?: string; /** Optional display or metadata description. */
253
+ description?: string; /** Optional per-run cleanup hook collected via {@link TOOL_CLEANUP}. */
254
+ [TOOL_CLEANUP]?: () => Awaitable<void>;
255
+ };
256
+ /**
257
+ * Client tool definition exposed by the server runtime and executed by the client app.
258
+ */
259
+ type ClientToolDefinition<TSchema extends ResolvableSchema = ResolvableSchema, TName extends string = string, TContext = any> = {
260
+ /** Discriminator for client-executed tools. */kind: "client"; /** Stable tool name exposed to the model. */
261
+ name: TName; /** Short description shown to the model. */
262
+ description?: string; /** Original schema value kept for reference. */
263
+ schema: TSchema; /** When true, input validation should be strict when supported by the runtime. */
264
+ strict?: boolean; /** Optional approval policy for this tool call. */
265
+ approval?: BoundToolApprovalConfig<TContext, TSchema>; /** Optional default handling mode for recoverable tool failures. */
266
+ toolErrorMode?: ToolErrorMode; /** Optional hook for customizing recoverable tool failures. */
267
+ onToolError?: OnToolError; /** Optional per-run cleanup hook collected via {@link TOOL_CLEANUP}. */
268
+ [TOOL_CLEANUP]?: () => Awaitable<void>; /** Resolved JSON Schema for the tool input. */
269
+ [TOOL_JSON_SCHEMA]: Record<string, unknown>;
270
+ };
271
+ /**
272
+ * Tool union used by agent and runtime APIs.
273
+ */
274
+ type AgentToolDefinition<TContext = any> = ServerToolDefinition<any, string, unknown, TContext> | ClientToolDefinition<any, string, TContext> | HostedToolDefinition;
275
+ /**
276
+ * Tool definitions returned by one source.
277
+ */
278
+ type ToolSourceResult = readonly AgentToolDefinition[] | AgentToolDefinition;
279
+ /**
280
+ * Tool definitions plus optional provider-lifecycle disposal.
281
+ */
282
+ interface LazyToolSourceResult {
283
+ tools: ToolSourceResult;
284
+ /** Optional disposer for cached provider resources such as MCP clients. */
285
+ dispose?: () => Awaitable<void>;
286
+ }
287
+ /**
288
+ * Loader used by {@link LazyToolSource} to populate and cache tools.
289
+ */
290
+ type LazyToolLoader<TContext = unknown> = BivariantFn<[] | [TContext | undefined], Awaitable<ToolSourceResult | LazyToolSourceResult>>;
291
+ /**
292
+ * Lifecycle-aware tool source that caches a resolved tool set across runs.
293
+ */
294
+ interface LazyToolSource<TContext = unknown> {
295
+ /** Internal discriminator for lazy tool sources. */
296
+ readonly kind: "lazy";
297
+ /** Resolves and caches tool definitions. Concurrent calls share one load. */
298
+ resolve(context: TContext | undefined): Promise<LazyToolSourceResult>;
299
+ /** Disposes cached resources and clears the cache. Safe to call multiple times. */
300
+ dispose(): Promise<void>;
301
+ /** Forces a reload by disposing the current cache before resolving again. */
302
+ reload(context: TContext | undefined): Promise<LazyToolSourceResult>;
303
+ }
304
+ /**
305
+ * Creates tool definitions from context.
306
+ */
307
+ type ToolListFactory<TContext> = BivariantFn<[TContext | undefined], Awaitable<ToolSourceResult>>;
308
+ /**
309
+ * Tool source accepted by agents and runtimes.
310
+ */
311
+ type ToolSource<TContext> = LazyToolSource<TContext> | ToolListFactory<TContext> | Awaitable<ToolSourceResult>;
312
+ /**
313
+ * Resolves the runtime target for a tool definition.
314
+ */
315
+ type ToolDefinitionTarget<TTool extends AgentToolDefinition = AgentToolDefinition> = TTool["kind"] extends ToolTarget ? TTool["kind"] : ToolTarget;
316
+ //#endregion
317
+ export { AgentToolDefinition, BoundToolApprovalConfig, ClientToolDefinition, ExecutionToolError, ExecutionToolErrorResult, HostedToolDefinition, LazyToolLoader, LazyToolSource, LazyToolSourceResult, OnToolError, OpenString, ParseToolError, ParseToolErrorResult, RepairAction, ResultAction, RetryAction, SendToModelAction, ServerToolDefinition, SkipAction, ThrowAction, ToolApprovalConfig, ToolApprovalDecision, ToolApprovalState, ToolContract, ToolContractConfig, ToolDefinitionTarget, ToolErrorBase, ToolErrorContext, ToolErrorMode, ToolErrorPayload, ToolErrorResultFor, ToolHandler, ToolListFactory, ToolNameOf, ToolNamesOf, ToolRunContext, ToolSource, ToolSourceResult, ToolTarget, ValidationToolError, ValidationToolErrorResult };
318
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../src/tools/types.ts"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { resolveToJsonSchema } from "../schema/resolve-json-schema.mjs";
2
+ import { TOOL_JSON_SCHEMA } from "./constants.mjs";
3
+ import { BetterAgentError } from "@better-agent/shared/errors";
4
+
5
+ //#region src/tools/validation.ts
6
+ /**
7
+ * Validates a tool definition and returns the resolved JSON Schema used at runtime.
8
+ */
9
+ const validateToolDefinition = (def) => {
10
+ if (typeof def.name !== "string" || def.name.length === 0) throw BetterAgentError.fromCode("VALIDATION_FAILED", "Tool name must be a non-empty string.", { trace: [{ at: "core.tools.validateToolDefinition.name" }] });
11
+ const existingSchema = def[TOOL_JSON_SCHEMA];
12
+ if (existingSchema !== void 0) return existingSchema;
13
+ const jsonSchema = resolveToJsonSchema(def.schema);
14
+ if (jsonSchema.isErr()) throw jsonSchema.error.at({
15
+ at: "core.tools.validateToolDefinition.schema",
16
+ data: { toolName: def.name }
17
+ });
18
+ return jsonSchema.value;
19
+ };
20
+
21
+ //#endregion
22
+ export { validateToolDefinition };
23
+ //# sourceMappingURL=validation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.mjs","names":[],"sources":["../../src/tools/validation.ts"],"sourcesContent":["import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport { resolveToJsonSchema } from \"../schema\";\nimport type { ResolvableSchema } from \"../schema\";\nimport { TOOL_JSON_SCHEMA } from \"./constants\";\n\ntype ToolValidationTarget = {\n name?: unknown;\n schema: ResolvableSchema;\n [TOOL_JSON_SCHEMA]?: Record<string, unknown>;\n};\n\n/**\n * Validates a tool definition and returns the resolved JSON Schema used at runtime.\n */\nexport const validateToolDefinition = <const TTool extends ToolValidationTarget>(\n def: TTool,\n): Record<string, unknown> => {\n if (typeof def.name !== \"string\" || def.name.length === 0) {\n throw BetterAgentError.fromCode(\n \"VALIDATION_FAILED\",\n \"Tool name must be a non-empty string.\",\n {\n trace: [{ at: \"core.tools.validateToolDefinition.name\" }],\n },\n );\n }\n\n const existingSchema = def[TOOL_JSON_SCHEMA];\n if (existingSchema !== undefined) {\n return existingSchema;\n }\n\n const jsonSchema = resolveToJsonSchema(def.schema);\n if (jsonSchema.isErr()) {\n throw jsonSchema.error.at({\n at: \"core.tools.validateToolDefinition.schema\",\n data: { toolName: def.name },\n });\n }\n\n return jsonSchema.value;\n};\n"],"mappings":";;;;;;;;AAcA,MAAa,0BACT,QAC0B;AAC1B,KAAI,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,WAAW,EACpD,OAAM,iBAAiB,SACnB,qBACA,yCACA,EACI,OAAO,CAAC,EAAE,IAAI,0CAA0C,CAAC,EAC5D,CACJ;CAGL,MAAM,iBAAiB,IAAI;AAC3B,KAAI,mBAAmB,OACnB,QAAO;CAGX,MAAM,aAAa,oBAAoB,IAAI,OAAO;AAClD,KAAI,WAAW,OAAO,CAClB,OAAM,WAAW,MAAM,GAAG;EACtB,IAAI;EACJ,MAAM,EAAE,UAAU,IAAI,MAAM;EAC/B,CAAC;AAGN,QAAO,WAAW"}