@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,124 @@
1
+ import { BetterAgentError } from "@better-agent/shared/errors";
2
+
3
+ //#region src/run/hooks.ts
4
+ /** Applies `onStep` hooks. */
5
+ const applyOnStep = async (params) => {
6
+ const prepared = { messages: [...params.messages] };
7
+ if (params.pluginRuntime?.hasOnStep) {
8
+ const pluginPrepared = await params.pluginRuntime.applyOnStep({
9
+ runId: params.runId,
10
+ agentName: params.agentName,
11
+ stepIndex: params.stepIndex,
12
+ maxSteps: params.maxSteps,
13
+ messages: prepared.messages,
14
+ conversationId: params.conversationId,
15
+ context: params.context,
16
+ previousStep: params.previousStep,
17
+ modelCaps: params.modelCaps
18
+ });
19
+ prepared.messages = pluginPrepared.messages;
20
+ if (pluginPrepared.toolChoice !== void 0) prepared.toolChoice = pluginPrepared.toolChoice;
21
+ if (pluginPrepared.activeTools !== void 0) prepared.activeTools = pluginPrepared.activeTools;
22
+ if (pluginPrepared.systemInstruction !== void 0) prepared.systemInstruction = pluginPrepared.systemInstruction;
23
+ }
24
+ if (!params.onStep) return prepared;
25
+ const baseContext = {
26
+ runId: params.runId,
27
+ agentName: params.agentName,
28
+ stepIndex: params.stepIndex,
29
+ maxSteps: params.maxSteps,
30
+ messages: prepared.messages,
31
+ conversationId: params.conversationId,
32
+ previousStep: params.previousStep,
33
+ updateMessages: (updater) => {
34
+ prepared.messages = updater([...prepared.messages]);
35
+ baseContext.messages = prepared.messages;
36
+ }
37
+ };
38
+ const supportsTools = params.modelCaps?.tools === true;
39
+ const withInstructionControl = (params.modelCaps === void 0 ? true : params.modelCaps.inputShape !== "prompt" && params.modelCaps.supportsInstruction === true) ? {
40
+ ...baseContext,
41
+ setSystemInstruction: (instruction) => {
42
+ prepared.systemInstruction = instruction;
43
+ }
44
+ } : baseContext;
45
+ const contextWithControls = supportsTools ? {
46
+ ...withInstructionControl,
47
+ setToolChoice: (choice) => {
48
+ prepared.toolChoice = choice;
49
+ },
50
+ setActiveTools: (names) => {
51
+ prepared.activeTools = [...names];
52
+ }
53
+ } : withInstructionControl;
54
+ const hookContext = params.context !== void 0 ? {
55
+ ...contextWithControls,
56
+ context: params.context
57
+ } : contextWithControls;
58
+ try {
59
+ await params.onStep(hookContext);
60
+ } catch (error) {
61
+ throw BetterAgentError.fromCode("HOOK_FAILED", "Agent onStep hook threw.", {
62
+ cause: error,
63
+ trace: [{ at: "core.run.applyOnStep" }]
64
+ });
65
+ }
66
+ return prepared;
67
+ };
68
+ /** Applies `onBeforeModelCall` hooks. */
69
+ const applyBeforeModelCall = async (params) => {
70
+ if (!params.pluginRuntime?.hasModelHooks) return {
71
+ input: [...params.input],
72
+ tools: [...params.tools],
73
+ toolChoice: params.toolChoice
74
+ };
75
+ return await params.pluginRuntime.applyBeforeModelCall({
76
+ runId: params.runId,
77
+ agentName: params.agentName,
78
+ stepIndex: params.stepIndex,
79
+ input: params.input,
80
+ tools: params.tools,
81
+ conversationId: params.conversationId,
82
+ toolChoice: params.toolChoice,
83
+ modelCaps: params.modelCaps
84
+ });
85
+ };
86
+ /** Applies `onAfterModelCall` hooks. */
87
+ const applyAfterModelCall = async (params) => {
88
+ if (!params.pluginRuntime?.hasModelHooks) return;
89
+ await params.pluginRuntime.applyAfterModelCall({
90
+ runId: params.runId,
91
+ agentName: params.agentName,
92
+ stepIndex: params.stepIndex,
93
+ response: params.response,
94
+ conversationId: params.conversationId
95
+ });
96
+ };
97
+ /** Applies `onStepFinish`. */
98
+ const applyOnStepFinish = async (params) => {
99
+ if (!params.onStepFinish) return;
100
+ const baseContext = {
101
+ runId: params.runId,
102
+ agentName: params.agentName,
103
+ stepIndex: params.stepIndex,
104
+ maxSteps: params.maxSteps,
105
+ result: params.result,
106
+ conversationId: params.conversationId
107
+ };
108
+ const hookContext = params.context !== void 0 ? {
109
+ ...baseContext,
110
+ context: params.context
111
+ } : baseContext;
112
+ try {
113
+ await params.onStepFinish(hookContext);
114
+ } catch (error) {
115
+ throw BetterAgentError.fromCode("HOOK_FAILED", "Agent onStepFinish hook threw.", {
116
+ cause: error,
117
+ trace: [{ at: "core.run.applyOnStepFinish" }]
118
+ });
119
+ }
120
+ };
121
+
122
+ //#endregion
123
+ export { applyAfterModelCall, applyBeforeModelCall, applyOnStep, applyOnStepFinish };
124
+ //# sourceMappingURL=hooks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.mjs","names":[],"sources":["../../src/run/hooks.ts"],"sourcesContent":["import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport type { Awaitable } from \"../internal/types\";\nimport type { PluginRuntime } from \"../plugins\";\nimport type {\n Capabilities,\n GenerativeModelInputItem,\n GenerativeModelInputMessageContent,\n GenerativeModelResponse,\n ToolChoice,\n} from \"../providers\";\nimport type { AgentToolDefinition } from \"../tools\";\nimport type {\n OnStepContext,\n OnStepContextBase,\n OnStepFinishContext,\n OnStepFinishContextBase,\n PreviousStepResult,\n} from \"./types\";\n\n/** Applies `onStep` hooks. */\nexport const applyOnStep = async <TContext, TModelCaps extends Capabilities = Capabilities>(\n params: {\n runId: string;\n agentName: string;\n conversationId?: string;\n stepIndex: number;\n maxSteps: number | undefined;\n context?: TContext;\n pluginRuntime?: PluginRuntime | null;\n /** Model caps for plugin controls. */\n modelCaps?: TModelCaps;\n } & {\n messages: GenerativeModelInputItem<TModelCaps>[];\n previousStep?: PreviousStepResult;\n onStep?: (context: OnStepContext<undefined, TContext, TModelCaps>) => Awaitable<void>;\n },\n): Promise<{\n messages: GenerativeModelInputItem<TModelCaps>[];\n toolChoice?: ToolChoice;\n activeTools?: string[];\n systemInstruction?: GenerativeModelInputMessageContent<TModelCaps>;\n}> => {\n const prepared: {\n messages: GenerativeModelInputItem<TModelCaps>[];\n toolChoice?: ToolChoice;\n activeTools?: string[];\n systemInstruction?: GenerativeModelInputMessageContent<TModelCaps>;\n } = {\n messages: [...params.messages],\n };\n\n if (params.pluginRuntime?.hasOnStep) {\n const pluginPrepared = await params.pluginRuntime.applyOnStep({\n runId: params.runId,\n agentName: params.agentName,\n stepIndex: params.stepIndex,\n maxSteps: params.maxSteps,\n messages: prepared.messages,\n conversationId: params.conversationId,\n context: params.context,\n previousStep: params.previousStep,\n modelCaps: params.modelCaps,\n });\n\n prepared.messages = pluginPrepared.messages;\n if (pluginPrepared.toolChoice !== undefined) {\n prepared.toolChoice = pluginPrepared.toolChoice;\n }\n if (pluginPrepared.activeTools !== undefined) {\n prepared.activeTools = pluginPrepared.activeTools;\n }\n if (pluginPrepared.systemInstruction !== undefined) {\n prepared.systemInstruction = pluginPrepared.systemInstruction;\n }\n }\n\n if (!params.onStep) return prepared;\n\n const baseContext: OnStepContextBase<TModelCaps> = {\n runId: params.runId,\n agentName: params.agentName,\n stepIndex: params.stepIndex,\n maxSteps: params.maxSteps,\n messages: prepared.messages,\n conversationId: params.conversationId,\n previousStep: params.previousStep,\n updateMessages: (updater) => {\n prepared.messages = updater([...prepared.messages]);\n (baseContext as typeof hookContext).messages = prepared.messages;\n },\n };\n\n const supportsTools = params.modelCaps?.tools === true;\n const canSetInstruction =\n params.modelCaps === undefined\n ? true\n : params.modelCaps.inputShape !== \"prompt\" &&\n params.modelCaps.supportsInstruction === true;\n const withInstructionControl = canSetInstruction\n ? {\n ...baseContext,\n setSystemInstruction: (\n instruction: GenerativeModelInputMessageContent<TModelCaps>,\n ) => {\n prepared.systemInstruction = instruction;\n },\n }\n : baseContext;\n const contextWithControls = supportsTools\n ? {\n ...withInstructionControl,\n setToolChoice: (choice: ToolChoice) => {\n prepared.toolChoice = choice;\n },\n setActiveTools: (names: readonly string[]) => {\n prepared.activeTools = [...names];\n },\n }\n : withInstructionControl;\n\n // Add `context` only when present.\n const hookContext =\n params.context !== undefined\n ? { ...contextWithControls, context: params.context }\n : contextWithControls;\n\n try {\n await params.onStep(hookContext as OnStepContext<undefined, TContext, TModelCaps>);\n } catch (error) {\n throw BetterAgentError.fromCode(\"HOOK_FAILED\", \"Agent onStep hook threw.\", {\n cause: error,\n trace: [{ at: \"core.run.applyOnStep\" }],\n });\n }\n return prepared;\n};\n\n/** Applies `onBeforeModelCall` hooks. */\nexport const applyBeforeModelCall = async (params: {\n runId: string;\n agentName: string;\n conversationId?: string;\n stepIndex: number;\n modelCaps?: Capabilities;\n input: GenerativeModelInputItem[];\n tools: AgentToolDefinition[];\n toolChoice?: ToolChoice;\n pluginRuntime?: PluginRuntime | null;\n}): Promise<{\n input: GenerativeModelInputItem[];\n tools: AgentToolDefinition[];\n toolChoice?: ToolChoice;\n}> => {\n if (!params.pluginRuntime?.hasModelHooks) {\n return {\n input: [...params.input],\n tools: [...params.tools],\n toolChoice: params.toolChoice,\n };\n }\n\n return await params.pluginRuntime.applyBeforeModelCall({\n runId: params.runId,\n agentName: params.agentName,\n stepIndex: params.stepIndex,\n input: params.input,\n tools: params.tools,\n conversationId: params.conversationId,\n toolChoice: params.toolChoice,\n modelCaps: params.modelCaps,\n });\n};\n\n/** Applies `onAfterModelCall` hooks. */\nexport const applyAfterModelCall = async (params: {\n runId: string;\n agentName: string;\n conversationId?: string;\n stepIndex: number;\n response: GenerativeModelResponse;\n pluginRuntime?: PluginRuntime | null;\n}): Promise<void> => {\n if (!params.pluginRuntime?.hasModelHooks) {\n return;\n }\n\n await params.pluginRuntime.applyAfterModelCall({\n runId: params.runId,\n agentName: params.agentName,\n stepIndex: params.stepIndex,\n response: params.response,\n conversationId: params.conversationId,\n });\n};\n\n/** Applies `onStepFinish`. */\nexport const applyOnStepFinish = async <TContext>(\n params: {\n runId: string;\n agentName: string;\n conversationId?: string;\n stepIndex: number;\n maxSteps: number | undefined;\n context?: TContext;\n } & {\n result: PreviousStepResult;\n onStepFinish?: (context: OnStepFinishContext<undefined, TContext>) => Awaitable<void>;\n },\n): Promise<void> => {\n if (!params.onStepFinish) return;\n\n const baseContext: OnStepFinishContextBase = {\n runId: params.runId,\n agentName: params.agentName,\n stepIndex: params.stepIndex,\n maxSteps: params.maxSteps,\n result: params.result,\n conversationId: params.conversationId,\n };\n\n // Add `context` only when present.\n const hookContext =\n params.context !== undefined ? { ...baseContext, context: params.context } : baseContext;\n\n try {\n await params.onStepFinish(hookContext as OnStepFinishContext<undefined, TContext>);\n } catch (error) {\n throw BetterAgentError.fromCode(\"HOOK_FAILED\", \"Agent onStepFinish hook threw.\", {\n cause: error,\n trace: [{ at: \"core.run.applyOnStepFinish\" }],\n });\n }\n};\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { BetterAgentRuntime, ConditionalContextField, ConditionalInstructionControlField, ConditionalToolControlField, ConversationReplayOptions, OnStepContext, OnStepContextBase, OnStepFinishContext, OnStepFinishContextBase, PreviousStepResult, ResumeConversationOptions, ResumeStreamOptions, RunAdvancedOptions, RunContext, RunOptions, RunOptionsForAgent, RunOutputOverrideForAgent, RunPersistenceOptions, RunResult, RunResultForAgent, StopWhen, StopWhenContext, StopWhenContextBase, StreamResult, StreamResultForAgent, StructuredOutputForAgentRun, SubmitToolApprovalParams, SubmitToolResultParams } from "./types.mjs";
2
+ import { createRuntime } from "./runtime.mjs";
3
+ import { pruneInputByCapabilities } from "./messages.mjs";
4
+ import { MissingTextOutputError, OnOutputError, OutputErrorBase, OutputErrorContext, OutputErrorMode, OutputErrorResult, ParseOutputError, RepairTextOutputAction, RepairValueOutputAction, SkipOutputAction, ThrowOutputAction, ValidationOutputError } from "./output-errors.mjs";
@@ -0,0 +1,8 @@
1
+ import { Capabilities } from "../providers/types/capabilities.mjs";
2
+ import { GenerativeModelInputItem } from "../providers/types/input.mjs";
3
+ //#region src/run/messages.d.ts
4
+ /** Removes replayed parts the model cannot accept. */
5
+ declare const pruneInputByCapabilities: (input: GenerativeModelInputItem[], caps: Capabilities) => GenerativeModelInputItem[];
6
+ //#endregion
7
+ export { pruneInputByCapabilities };
8
+ //# sourceMappingURL=messages.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.mts","names":[],"sources":["../../src/run/messages.ts"],"mappings":";;;;cAiHa,wBAAA,GAAwB,KAAA,EAC1B,wBAAA,IAA0B,IAAA,EAC3B,YAAA,KACP,wBAAA"}
@@ -0,0 +1,83 @@
1
+ //#region src/run/messages.ts
2
+ /** Converts run input into provider input items. */
3
+ const normalizeInputToMessages = (input, caps) => {
4
+ if (typeof input === "string") return [caps.inputShape === "prompt" ? {
5
+ type: "message",
6
+ content: input
7
+ } : {
8
+ type: "message",
9
+ role: "user",
10
+ content: input
11
+ }];
12
+ return [...input];
13
+ };
14
+ /** Converts run input into durable conversation items. */
15
+ const normalizeInputToConversationItems = (input, caps) => normalizeInputToMessages(input, caps).map((item) => item.type === "message" ? {
16
+ type: "message",
17
+ role: "role" in item ? item.role : "user",
18
+ content: item.content
19
+ } : item);
20
+ /** Projects durable conversation items back into provider input. */
21
+ const projectConversationItemsToInput = (items, caps) => items.flatMap((item) => {
22
+ switch (item.type) {
23
+ case "message": {
24
+ const projectedContent = typeof item.content === "string" ? item.content : item.content.map((part) => {
25
+ switch (part.type) {
26
+ case "text":
27
+ case "image":
28
+ case "audio":
29
+ case "video":
30
+ case "file":
31
+ case "embedding":
32
+ case "transcript":
33
+ case "reasoning": return part;
34
+ }
35
+ }).filter((part) => part !== null);
36
+ if (projectedContent === null) return [];
37
+ if (Array.isArray(projectedContent) && projectedContent.length === 0) return [];
38
+ return [caps.inputShape === "prompt" ? {
39
+ type: "message",
40
+ content: projectedContent
41
+ } : {
42
+ type: "message",
43
+ role: item.role,
44
+ content: projectedContent
45
+ }];
46
+ }
47
+ case "tool-call": return "result" in item ? [item] : [];
48
+ case "provider-tool-result": return [item];
49
+ }
50
+ });
51
+ /** Removes replayed parts the model cannot accept. */
52
+ const pruneInputByCapabilities = (input, caps) => {
53
+ const textSupported = caps.inputModalities?.text !== false;
54
+ const isSupportedPart = (part) => {
55
+ switch (part.type) {
56
+ case "text":
57
+ case "transcript":
58
+ case "reasoning": return textSupported;
59
+ case "image":
60
+ case "audio":
61
+ case "video":
62
+ case "file":
63
+ case "embedding": return caps.inputModalities?.[part.type] === true;
64
+ }
65
+ };
66
+ const pruneMessage = (message) => {
67
+ if (typeof message.content === "string") return textSupported ? [message] : [];
68
+ const content = message.content.filter(isSupportedPart);
69
+ if (content.length === 0) return [];
70
+ return [{
71
+ ...message,
72
+ content
73
+ }];
74
+ };
75
+ return input.flatMap((item) => {
76
+ if (item.type !== "message") return [item];
77
+ return pruneMessage(item);
78
+ });
79
+ };
80
+
81
+ //#endregion
82
+ export { normalizeInputToConversationItems, normalizeInputToMessages, projectConversationItemsToInput, pruneInputByCapabilities };
83
+ //# sourceMappingURL=messages.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.mjs","names":[],"sources":["../../src/run/messages.ts"],"sourcesContent":["import type {\n AudioContentBase,\n Capabilities,\n ConversationItem,\n ConversationMessage,\n EmbeddingContentBase,\n FileContentBase,\n GenerativeModelInput,\n GenerativeModelInputItem,\n GenerativeModelInputMessage,\n GenerativeModelInputMessageContent,\n GenerativeModelToolCallResult,\n ImageContentBase,\n ReasoningContentBase,\n TextContentBase,\n TranscriptContentBase,\n VideoContentBase,\n} from \"../providers\";\n\n/** Converts run input into provider input items. */\nexport const normalizeInputToMessages = (\n input: GenerativeModelInput,\n caps: Capabilities,\n): GenerativeModelInputItem[] => {\n if (typeof input === \"string\") {\n return [\n caps.inputShape === \"prompt\"\n ? {\n type: \"message\",\n content: input,\n }\n : {\n type: \"message\",\n role: \"user\",\n content: input,\n },\n ] as GenerativeModelInputItem[];\n }\n\n return [...input];\n};\n\n/** Converts run input into durable conversation items. */\nexport const normalizeInputToConversationItems = (\n input: GenerativeModelInput,\n caps: Capabilities,\n): ConversationItem[] =>\n normalizeInputToMessages(input, caps).map((item) =>\n item.type === \"message\"\n ? ({\n type: \"message\",\n role: \"role\" in item ? item.role : \"user\",\n content: item.content,\n } satisfies ConversationMessage)\n : item,\n );\n\n/** Projects durable conversation items back into provider input. */\nexport const projectConversationItemsToInput = (\n items: ConversationItem[],\n caps: Capabilities,\n): GenerativeModelInputItem[] =>\n items.flatMap((item) => {\n switch (item.type) {\n case \"message\": {\n const projectedContent =\n typeof item.content === \"string\"\n ? item.content\n : (item.content\n .map((part) => {\n switch (part.type) {\n case \"text\":\n case \"image\":\n case \"audio\":\n case \"video\":\n case \"file\":\n case \"embedding\":\n case \"transcript\":\n case \"reasoning\":\n return part;\n }\n })\n .filter(\n (part) => part !== null,\n ) as GenerativeModelInputMessageContent);\n if (projectedContent === null) {\n return [];\n }\n if (Array.isArray(projectedContent) && projectedContent.length === 0) {\n return [];\n }\n\n return [\n caps.inputShape === \"prompt\"\n ? ({\n type: \"message\",\n content: projectedContent,\n } as GenerativeModelInputItem)\n : ({\n type: \"message\",\n role: item.role,\n content: projectedContent,\n } as GenerativeModelInputItem),\n ];\n }\n case \"tool-call\":\n return \"result\" in item ? [item as GenerativeModelToolCallResult] : [];\n case \"provider-tool-result\":\n return [item];\n }\n });\n\n/** Removes replayed parts the model cannot accept. */\nexport const pruneInputByCapabilities = (\n input: GenerativeModelInputItem[],\n caps: Capabilities,\n): GenerativeModelInputItem[] => {\n const textSupported = caps.inputModalities?.text !== false;\n\n const isSupportedPart = (\n part:\n | TextContentBase\n | TranscriptContentBase\n | ReasoningContentBase\n | ImageContentBase\n | AudioContentBase\n | VideoContentBase\n | FileContentBase\n | EmbeddingContentBase,\n ): boolean => {\n switch (part.type) {\n case \"text\":\n case \"transcript\":\n case \"reasoning\":\n return textSupported;\n case \"image\":\n case \"audio\":\n case \"video\":\n case \"file\":\n case \"embedding\":\n return caps.inputModalities?.[part.type] === true;\n }\n };\n\n const pruneMessage = (message: GenerativeModelInputMessage): GenerativeModelInputItem[] => {\n if (typeof message.content === \"string\") {\n return textSupported ? [message] : [];\n }\n\n const content = message.content.filter(isSupportedPart);\n if (content.length === 0) {\n return [];\n }\n\n return [{ ...message, content }];\n };\n\n return input.flatMap((item) => {\n if (item.type !== \"message\") {\n return [item];\n }\n\n return pruneMessage(item);\n });\n};\n"],"mappings":";;AAoBA,MAAa,4BACT,OACA,SAC6B;AAC7B,KAAI,OAAO,UAAU,SACjB,QAAO,CACH,KAAK,eAAe,WACd;EACI,MAAM;EACN,SAAS;EACZ,GACD;EACI,MAAM;EACN,MAAM;EACN,SAAS;EACZ,CACV;AAGL,QAAO,CAAC,GAAG,MAAM;;;AAIrB,MAAa,qCACT,OACA,SAEA,yBAAyB,OAAO,KAAK,CAAC,KAAK,SACvC,KAAK,SAAS,YACP;CACG,MAAM;CACN,MAAM,UAAU,OAAO,KAAK,OAAO;CACnC,SAAS,KAAK;CACjB,GACD,KACT;;AAGL,MAAa,mCACT,OACA,SAEA,MAAM,SAAS,SAAS;AACpB,SAAQ,KAAK,MAAb;EACI,KAAK,WAAW;GACZ,MAAM,mBACF,OAAO,KAAK,YAAY,WAClB,KAAK,UACJ,KAAK,QACD,KAAK,SAAS;AACX,YAAQ,KAAK,MAAb;KACI,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK,YACD,QAAO;;KAEjB,CACD,QACI,SAAS,SAAS,KACtB;AACf,OAAI,qBAAqB,KACrB,QAAO,EAAE;AAEb,OAAI,MAAM,QAAQ,iBAAiB,IAAI,iBAAiB,WAAW,EAC/D,QAAO,EAAE;AAGb,UAAO,CACH,KAAK,eAAe,WACb;IACG,MAAM;IACN,SAAS;IACZ,GACA;IACG,MAAM;IACN,MAAM,KAAK;IACX,SAAS;IACZ,CACV;;EAEL,KAAK,YACD,QAAO,YAAY,OAAO,CAAC,KAAsC,GAAG,EAAE;EAC1E,KAAK,uBACD,QAAO,CAAC,KAAK;;EAEvB;;AAGN,MAAa,4BACT,OACA,SAC6B;CAC7B,MAAM,gBAAgB,KAAK,iBAAiB,SAAS;CAErD,MAAM,mBACF,SASU;AACV,UAAQ,KAAK,MAAb;GACI,KAAK;GACL,KAAK;GACL,KAAK,YACD,QAAO;GACX,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,YACD,QAAO,KAAK,kBAAkB,KAAK,UAAU;;;CAIzD,MAAM,gBAAgB,YAAqE;AACvF,MAAI,OAAO,QAAQ,YAAY,SAC3B,QAAO,gBAAgB,CAAC,QAAQ,GAAG,EAAE;EAGzC,MAAM,UAAU,QAAQ,QAAQ,OAAO,gBAAgB;AACvD,MAAI,QAAQ,WAAW,EACnB,QAAO,EAAE;AAGb,SAAO,CAAC;GAAE,GAAG;GAAS;GAAS,CAAC;;AAGpC,QAAO,MAAM,SAAS,SAAS;AAC3B,MAAI,KAAK,SAAS,UACd,QAAO,CAAC,KAAK;AAGjB,SAAO,aAAa,KAAK;GAC3B"}
@@ -0,0 +1,105 @@
1
+ import { BetterAgentError } from "@better-agent/shared/errors";
2
+
3
+ //#region src/run/model-strategy.ts
4
+ const getAssistantMessageIdFromEvent = (event) => {
5
+ if ("parentMessageId" in event && typeof event.parentMessageId === "string" && event.parentMessageId.length > 0) return event.parentMessageId;
6
+ if ("messageId" in event && typeof event.messageId === "string" && event.messageId.length > 0 && "role" in event && event.role === "assistant") return event.messageId;
7
+ };
8
+ const createRunModelCallStrategy = () => ({
9
+ mode: "run",
10
+ async call(params) {
11
+ const { options } = params;
12
+ let firstGeneratedMessageId;
13
+ let assistantMessageId;
14
+ const generateMessageId = () => {
15
+ const id = options.generateMessageId();
16
+ firstGeneratedMessageId ??= id;
17
+ return id;
18
+ };
19
+ const modelContext = {
20
+ runId: params.runId,
21
+ agentName: params.agentName,
22
+ providerId: options.agent.model.providerId,
23
+ modelId: options.agent.model.modelId,
24
+ signal: options.signal,
25
+ generateMessageId,
26
+ conversationId: params.conversationId
27
+ };
28
+ if (!options.agent.model.doGenerate) throw BetterAgentError.fromCode("NOT_IMPLEMENTED", `Model '${options.agent.model.modelId}' does not implement doGenerate().`, {
29
+ context: {
30
+ agentName: params.agentName,
31
+ modelId: options.agent.model.modelId
32
+ },
33
+ trace: [{ at: "core.run.runLoop.model.doGenerate" }]
34
+ });
35
+ const responseResult = await options.agent.model.doGenerate({
36
+ ...options.modelOptions ?? {},
37
+ input: params.modelInput,
38
+ modalities: options.modalities,
39
+ tools: params.tools.length > 0 ? params.tools : void 0,
40
+ toolChoice: params.toolChoice,
41
+ structured_output: options.structuredOutput
42
+ }, modelContext);
43
+ if (responseResult.isErr()) throw responseResult.error;
44
+ const { response, events } = responseResult.value;
45
+ for (const event of events ?? []) {
46
+ assistantMessageId = getAssistantMessageIdFromEvent(event) ?? assistantMessageId;
47
+ await options.emit({ ...event });
48
+ }
49
+ return {
50
+ response,
51
+ assistantMessageId: assistantMessageId ?? firstGeneratedMessageId ?? generateMessageId()
52
+ };
53
+ }
54
+ });
55
+ const createStreamModelCallStrategy = () => ({
56
+ mode: "stream",
57
+ async call(params) {
58
+ const { options } = params;
59
+ let firstGeneratedMessageId;
60
+ let assistantMessageId;
61
+ const generateMessageId = () => {
62
+ const id = options.generateMessageId();
63
+ firstGeneratedMessageId ??= id;
64
+ return id;
65
+ };
66
+ const modelContext = {
67
+ runId: params.runId,
68
+ agentName: params.agentName,
69
+ providerId: options.agent.model.providerId,
70
+ modelId: options.agent.model.modelId,
71
+ signal: options.signal,
72
+ generateMessageId,
73
+ conversationId: params.conversationId
74
+ };
75
+ if (!options.agent.model.doGenerateStream) throw BetterAgentError.fromCode("NOT_IMPLEMENTED", `Model '${options.agent.model.modelId}' does not implement doGenerateStream().`, {
76
+ context: {
77
+ agentName: params.agentName,
78
+ modelId: options.agent.model.modelId
79
+ },
80
+ trace: [{ at: "core.run.runStreamLoop.model.doGenerateStream" }]
81
+ });
82
+ const streamResult = await options.agent.model.doGenerateStream({
83
+ ...options.modelOptions ?? {},
84
+ input: params.modelInput,
85
+ modalities: options.modalities,
86
+ tools: params.tools.length > 0 ? params.tools : void 0,
87
+ toolChoice: params.toolChoice,
88
+ structured_output: options.structuredOutput
89
+ }, modelContext);
90
+ if (streamResult.isErr()) throw streamResult.error;
91
+ for await (const eventResult of streamResult.value.events) {
92
+ if (eventResult.isErr()) throw eventResult.error;
93
+ assistantMessageId = getAssistantMessageIdFromEvent(eventResult.value) ?? assistantMessageId;
94
+ await options.emit({ ...eventResult.value });
95
+ }
96
+ return {
97
+ response: await streamResult.value.final,
98
+ assistantMessageId: assistantMessageId ?? firstGeneratedMessageId ?? generateMessageId()
99
+ };
100
+ }
101
+ });
102
+
103
+ //#endregion
104
+ export { createRunModelCallStrategy, createStreamModelCallStrategy };
105
+ //# sourceMappingURL=model-strategy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-strategy.mjs","names":[],"sources":["../../src/run/model-strategy.ts"],"sourcesContent":["import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport type { Event } from \"../events\";\nimport type { ModelCallStrategy } from \"./types\";\n\nconst getAssistantMessageIdFromEvent = (event: Event): string | undefined => {\n if (\n \"parentMessageId\" in event &&\n typeof event.parentMessageId === \"string\" &&\n event.parentMessageId.length > 0\n ) {\n return event.parentMessageId;\n }\n\n if (\n \"messageId\" in event &&\n typeof event.messageId === \"string\" &&\n event.messageId.length > 0 &&\n \"role\" in event &&\n event.role === \"assistant\"\n ) {\n return event.messageId;\n }\n\n return undefined;\n};\n\nexport const createRunModelCallStrategy = <TContext>(): ModelCallStrategy<TContext> => ({\n mode: \"run\",\n async call(params) {\n const { options } = params;\n let firstGeneratedMessageId: string | undefined;\n let assistantMessageId: string | undefined;\n const generateMessageId = () => {\n const id = options.generateMessageId();\n firstGeneratedMessageId ??= id;\n return id;\n };\n\n const modelContext = {\n runId: params.runId,\n agentName: params.agentName,\n providerId: options.agent.model.providerId,\n modelId: options.agent.model.modelId,\n signal: options.signal,\n generateMessageId,\n conversationId: params.conversationId,\n };\n\n if (!options.agent.model.doGenerate) {\n throw BetterAgentError.fromCode(\n \"NOT_IMPLEMENTED\",\n `Model '${options.agent.model.modelId}' does not implement doGenerate().`,\n {\n context: {\n agentName: params.agentName,\n modelId: options.agent.model.modelId,\n },\n trace: [{ at: \"core.run.runLoop.model.doGenerate\" }],\n },\n );\n }\n\n const responseResult = await options.agent.model.doGenerate(\n {\n ...(options.modelOptions ?? {}),\n input: params.modelInput,\n modalities: options.modalities,\n tools: params.tools.length > 0 ? params.tools : undefined,\n toolChoice: params.toolChoice,\n structured_output: options.structuredOutput,\n },\n modelContext,\n );\n if (responseResult.isErr()) {\n throw responseResult.error;\n }\n\n const { response, events } = responseResult.value;\n for (const event of events ?? []) {\n assistantMessageId = getAssistantMessageIdFromEvent(event) ?? assistantMessageId;\n await options.emit({\n ...event,\n });\n }\n\n return {\n response,\n // Prefer the provider ID, then reuse or generate one.\n assistantMessageId:\n assistantMessageId ?? firstGeneratedMessageId ?? generateMessageId(),\n };\n },\n});\n\nexport const createStreamModelCallStrategy = <TContext>(): ModelCallStrategy<TContext> => ({\n mode: \"stream\",\n async call(params) {\n const { options } = params;\n let firstGeneratedMessageId: string | undefined;\n let assistantMessageId: string | undefined;\n const generateMessageId = () => {\n const id = options.generateMessageId();\n firstGeneratedMessageId ??= id;\n return id;\n };\n\n const modelContext = {\n runId: params.runId,\n agentName: params.agentName,\n providerId: options.agent.model.providerId,\n modelId: options.agent.model.modelId,\n signal: options.signal,\n generateMessageId,\n conversationId: params.conversationId,\n };\n\n if (!options.agent.model.doGenerateStream) {\n throw BetterAgentError.fromCode(\n \"NOT_IMPLEMENTED\",\n `Model '${options.agent.model.modelId}' does not implement doGenerateStream().`,\n {\n context: {\n agentName: params.agentName,\n modelId: options.agent.model.modelId,\n },\n trace: [{ at: \"core.run.runStreamLoop.model.doGenerateStream\" }],\n },\n );\n }\n\n const streamResult = await options.agent.model.doGenerateStream(\n {\n ...(options.modelOptions ?? {}),\n input: params.modelInput,\n modalities: options.modalities,\n tools: params.tools.length > 0 ? params.tools : undefined,\n toolChoice: params.toolChoice,\n structured_output: options.structuredOutput,\n },\n modelContext,\n );\n\n if (streamResult.isErr()) {\n throw streamResult.error;\n }\n\n for await (const eventResult of streamResult.value.events) {\n if (eventResult.isErr()) {\n throw eventResult.error;\n }\n\n assistantMessageId =\n getAssistantMessageIdFromEvent(eventResult.value) ?? assistantMessageId;\n await options.emit({\n ...eventResult.value,\n });\n }\n\n return {\n response: await streamResult.value.final,\n // Prefer the provider ID, then reuse or generate one.\n assistantMessageId:\n assistantMessageId ?? firstGeneratedMessageId ?? generateMessageId(),\n };\n },\n});\n"],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import { Awaitable } from "../internal/types.mjs";
2
+
3
+ //#region src/run/output-errors.d.ts
4
+ /**
5
+ * Default handling mode for structured output finalization failures.
6
+ */
7
+ type OutputErrorMode = "repair" | "throw";
8
+ /**
9
+ * Shared context for structured output finalization failures.
10
+ */
11
+ interface OutputErrorBase {
12
+ error: unknown;
13
+ }
14
+ /**
15
+ * The model did not return any non-empty text to parse as structured output.
16
+ */
17
+ interface MissingTextOutputError extends OutputErrorBase {
18
+ errorKind: "missing_text";
19
+ }
20
+ /**
21
+ * The model returned text, but it could not be parsed as valid JSON.
22
+ */
23
+ interface ParseOutputError extends OutputErrorBase {
24
+ errorKind: "parse";
25
+ text: string;
26
+ }
27
+ /**
28
+ * The model returned valid JSON text, but the parsed value failed schema validation.
29
+ */
30
+ interface ValidationOutputError extends OutputErrorBase {
31
+ errorKind: "validation";
32
+ text: string;
33
+ value: unknown;
34
+ }
35
+ /**
36
+ * Union of all recoverable structured output finalization failures.
37
+ */
38
+ type OutputErrorContext = MissingTextOutputError | ParseOutputError | ValidationOutputError;
39
+ /**
40
+ * Skips custom recovery and uses the runtime default behavior.
41
+ */
42
+ interface SkipOutputAction {
43
+ action: "skip";
44
+ }
45
+ /**
46
+ * Re-throws the original structured output finalization error.
47
+ */
48
+ interface ThrowOutputAction {
49
+ action: "throw";
50
+ }
51
+ /**
52
+ * Provides replacement JSON text to parse and validate again.
53
+ */
54
+ interface RepairTextOutputAction {
55
+ action: "repair_text";
56
+ text: string;
57
+ }
58
+ /**
59
+ * Provides a replacement parsed value to validate directly.
60
+ */
61
+ interface RepairValueOutputAction {
62
+ action: "repair_value";
63
+ value: unknown;
64
+ }
65
+ /**
66
+ * Actions that can be returned from {@link OnOutputError}.
67
+ */
68
+ type OutputErrorResult = SkipOutputAction | ThrowOutputAction | RepairTextOutputAction | RepairValueOutputAction | undefined;
69
+ /**
70
+ * Hook for customizing structured output finalization failures.
71
+ */
72
+ type OnOutputError = (context: OutputErrorContext) => Awaitable<OutputErrorResult>;
73
+ //#endregion
74
+ export { MissingTextOutputError, OnOutputError, OutputErrorBase, OutputErrorContext, OutputErrorMode, OutputErrorResult, ParseOutputError, RepairTextOutputAction, RepairValueOutputAction, SkipOutputAction, ThrowOutputAction, ValidationOutputError };
75
+ //# sourceMappingURL=output-errors.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-errors.d.mts","names":[],"sources":["../../src/run/output-errors.ts"],"mappings":";;;;;AAKA;KAAY,eAAA;;;;UAKK,eAAA;EACb,KAAA;AAAA;;;AAMJ;UAAiB,sBAAA,SAA+B,eAAA;EAC5C,SAAA;AAAA;;AAMJ;;UAAiB,gBAAA,SAAyB,eAAA;EACtC,SAAA;EACA,IAAA;AAAA;;;;UAMa,qBAAA,SAA8B,eAAA;EAC3C,SAAA;EACA,IAAA;EACA,KAAA;AAAA;;;;KAMQ,kBAAA,GAAqB,sBAAA,GAAyB,gBAAA,GAAmB,qBAAA;;AAA7E;;UAKiB,gBAAA;EACb,MAAA;AAAA;;;;UAMa,iBAAA;EACb,MAAA;AAAA;;;AARJ;UAciB,sBAAA;EACb,MAAA;EACA,IAAA;AAAA;AATJ;;;AAAA,UAeiB,uBAAA;EACb,MAAA;EACA,KAAA;AAAA;;;;KAMQ,iBAAA,GACN,gBAAA,GACA,iBAAA,GACA,sBAAA,GACA,uBAAA;;;;KAMM,aAAA,IAAiB,OAAA,EAAS,kBAAA,KAAuB,SAAA,CAAU,iBAAA"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,185 @@
1
+ import { BetterAgentError } from "@better-agent/shared/errors";
2
+
3
+ //#region src/run/pending-tools.ts
4
+ const createPendingToolRuntime = () => {
5
+ const pendingClientToolCalls = /* @__PURE__ */ new Map();
6
+ const pendingApprovals = /* @__PURE__ */ new Map();
7
+ const removePendingEntry = (entries, runId, toolCallId) => {
8
+ const runPending = entries.get(runId);
9
+ if (!runPending) return;
10
+ runPending.delete(toolCallId);
11
+ if (runPending.size === 0) entries.delete(runId);
12
+ };
13
+ return {
14
+ awaitClientToolResult(params) {
15
+ return new Promise((resolve, reject) => {
16
+ const timeoutMs = params.timeoutMs ?? 3e4;
17
+ const runPending = pendingClientToolCalls.get(params.runId) ?? /* @__PURE__ */ new Map();
18
+ pendingClientToolCalls.set(params.runId, runPending);
19
+ if (runPending.has(params.toolCallId)) {
20
+ reject(BetterAgentError.fromCode("VALIDATION_FAILED", `Client tool '${params.toolName}' call '${params.toolCallId}' is already pending.`, {
21
+ context: {
22
+ runId: params.runId,
23
+ toolName: params.toolName,
24
+ toolCallId: params.toolCallId
25
+ },
26
+ trace: [{ at: "core.run.pendingTools.awaitClientToolResult" }]
27
+ }));
28
+ return;
29
+ }
30
+ const onAbort = () => {
31
+ cleanup();
32
+ reject(createAbortError(`Run '${params.runId}' was aborted while waiting for client tool result for '${params.toolName}'.`, {
33
+ runId: params.runId,
34
+ toolName: params.toolName,
35
+ toolCallId: params.toolCallId
36
+ }));
37
+ };
38
+ const cleanup = () => {
39
+ clearTimeout(timeout);
40
+ params.signal?.removeEventListener("abort", onAbort);
41
+ removePendingEntry(pendingClientToolCalls, params.runId, params.toolCallId);
42
+ };
43
+ const timeout = setTimeout(() => {
44
+ cleanup();
45
+ reject(BetterAgentError.fromCode("TIMEOUT", `Timed out waiting for client tool result for '${params.toolName}'.`, {
46
+ context: {
47
+ runId: params.runId,
48
+ toolName: params.toolName,
49
+ toolCallId: params.toolCallId
50
+ },
51
+ trace: [{ at: "core.run.pendingTools.awaitClientToolResult" }]
52
+ }));
53
+ }, timeoutMs);
54
+ if (params.signal?.aborted) {
55
+ onAbort();
56
+ return;
57
+ }
58
+ params.signal?.addEventListener("abort", onAbort, { once: true });
59
+ runPending.set(params.toolCallId, {
60
+ resolve: (value) => {
61
+ cleanup();
62
+ resolve(value);
63
+ },
64
+ reject: (error) => {
65
+ cleanup();
66
+ reject(error);
67
+ }
68
+ });
69
+ });
70
+ },
71
+ awaitToolApproval(params) {
72
+ return new Promise((resolve, reject) => {
73
+ const timeoutMs = params.timeoutMs ?? 3e4;
74
+ const runPending = pendingApprovals.get(params.runId) ?? /* @__PURE__ */ new Map();
75
+ pendingApprovals.set(params.runId, runPending);
76
+ if (runPending.has(params.toolCallId)) {
77
+ reject(BetterAgentError.fromCode("VALIDATION_FAILED", `Tool '${params.toolName}' call '${params.toolCallId}' is already pending approval.`, {
78
+ context: {
79
+ runId: params.runId,
80
+ toolName: params.toolName,
81
+ toolCallId: params.toolCallId
82
+ },
83
+ trace: [{ at: "core.run.pendingTools.awaitToolApproval" }]
84
+ }));
85
+ return;
86
+ }
87
+ const cleanup = () => {
88
+ clearTimeout(timeout);
89
+ params.signal?.removeEventListener("abort", onAbort);
90
+ removePendingEntry(pendingApprovals, params.runId, params.toolCallId);
91
+ };
92
+ const onAbort = () => {
93
+ cleanup();
94
+ reject(createAbortError(`Run '${params.runId}' was aborted while waiting for approval of '${params.toolName}'.`, {
95
+ runId: params.runId,
96
+ toolName: params.toolName,
97
+ toolCallId: params.toolCallId
98
+ }));
99
+ };
100
+ const timeout = setTimeout(() => {
101
+ cleanup();
102
+ reject(BetterAgentError.fromCode("TIMEOUT", `Timed out waiting for approval of '${params.toolName}'.`, {
103
+ context: {
104
+ runId: params.runId,
105
+ toolName: params.toolName,
106
+ toolCallId: params.toolCallId
107
+ },
108
+ trace: [{ at: "core.run.pendingTools.awaitToolApproval" }]
109
+ }));
110
+ }, timeoutMs);
111
+ if (params.signal?.aborted) {
112
+ onAbort();
113
+ return;
114
+ }
115
+ params.signal?.addEventListener("abort", onAbort, { once: true });
116
+ runPending.set(params.toolCallId, {
117
+ resolve: (value) => {
118
+ cleanup();
119
+ resolve(value);
120
+ },
121
+ reject: (error) => {
122
+ cleanup();
123
+ reject(error);
124
+ }
125
+ });
126
+ });
127
+ },
128
+ submitToolResult(params) {
129
+ const runPending = pendingClientToolCalls.get(params.runId);
130
+ if (!runPending) return Promise.resolve(false);
131
+ const pending = runPending.get(params.toolCallId);
132
+ if (!pending) return Promise.resolve(false);
133
+ runPending.delete(params.toolCallId);
134
+ if (runPending.size === 0) pendingClientToolCalls.delete(params.runId);
135
+ if (params.status === "error") pending.reject(BetterAgentError.fromCode("TOOL_EXECUTION_FAILED", params.error, {
136
+ context: {
137
+ runId: params.runId,
138
+ toolCallId: params.toolCallId
139
+ },
140
+ trace: [{ at: "core.run.pendingTools.submitToolResult" }]
141
+ }));
142
+ else pending.resolve(params.result);
143
+ return Promise.resolve(true);
144
+ },
145
+ submitToolApproval(params) {
146
+ const runPending = pendingApprovals.get(params.runId);
147
+ if (!runPending) return Promise.resolve(false);
148
+ const pending = runPending.get(params.toolCallId);
149
+ if (!pending) return Promise.resolve(false);
150
+ runPending.delete(params.toolCallId);
151
+ if (runPending.size === 0) pendingApprovals.delete(params.runId);
152
+ const result = { decision: params.decision };
153
+ if (params.note !== void 0) result.note = params.note;
154
+ if (params.actorId !== void 0) result.actorId = params.actorId;
155
+ pending.resolve(result);
156
+ return Promise.resolve(true);
157
+ },
158
+ clearRun(runId, reason) {
159
+ const clientToolCalls = pendingClientToolCalls.get(runId);
160
+ if (clientToolCalls) {
161
+ for (const [toolCallId, pending] of clientToolCalls) pending.reject(createAbortError(`Run '${runId}' was cleared: ${reason}`, {
162
+ runId,
163
+ toolCallId
164
+ }));
165
+ pendingClientToolCalls.delete(runId);
166
+ }
167
+ const approvals = pendingApprovals.get(runId);
168
+ if (approvals) {
169
+ for (const [toolCallId, pending] of approvals) pending.reject(createAbortError(`Run '${runId}' was cleared: ${reason}`, {
170
+ runId,
171
+ toolCallId
172
+ }));
173
+ pendingApprovals.delete(runId);
174
+ }
175
+ }
176
+ };
177
+ };
178
+ const createAbortError = (message, context) => BetterAgentError.fromCode("ABORTED", message, {
179
+ context,
180
+ trace: [{ at: "core.run.pendingTools.clearRun" }]
181
+ });
182
+
183
+ //#endregion
184
+ export { createPendingToolRuntime };
185
+ //# sourceMappingURL=pending-tools.mjs.map