@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.
- package/README.md +3 -0
- package/dist/agent/constants.mjs +6 -0
- package/dist/agent/constants.mjs.map +1 -0
- package/dist/agent/define-agent.d.mts +29 -0
- package/dist/agent/define-agent.d.mts.map +1 -0
- package/dist/agent/define-agent.mjs +27 -0
- package/dist/agent/define-agent.mjs.map +1 -0
- package/dist/agent/index.d.mts +2 -0
- package/dist/agent/types.d.mts +216 -0
- package/dist/agent/types.d.mts.map +1 -0
- package/dist/agent/validation.mjs +64 -0
- package/dist/agent/validation.mjs.map +1 -0
- package/dist/api.d.mts +8 -0
- package/dist/api.d.mts.map +1 -0
- package/dist/api.mjs +63 -0
- package/dist/api.mjs.map +1 -0
- package/dist/app/config.mjs +43 -0
- package/dist/app/config.mjs.map +1 -0
- package/dist/app/create-app.d.mts +36 -0
- package/dist/app/create-app.d.mts.map +1 -0
- package/dist/app/create-app.mjs +132 -0
- package/dist/app/create-app.mjs.map +1 -0
- package/dist/app/registry.mjs +43 -0
- package/dist/app/registry.mjs.map +1 -0
- package/dist/app/types.d.mts +142 -0
- package/dist/app/types.d.mts.map +1 -0
- package/dist/events/constants.d.mts +49 -0
- package/dist/events/constants.d.mts.map +1 -0
- package/dist/events/constants.mjs +46 -0
- package/dist/events/constants.mjs.map +1 -0
- package/dist/events/index.d.mts +4 -0
- package/dist/events/index.mjs +3 -0
- package/dist/events/types.d.mts +289 -0
- package/dist/events/types.d.mts.map +1 -0
- package/dist/index.d.mts +23 -0
- package/dist/index.mjs +14 -0
- package/dist/internal/id.mjs +21 -0
- package/dist/internal/id.mjs.map +1 -0
- package/dist/internal/types.d.mts +11 -0
- package/dist/internal/types.d.mts.map +1 -0
- package/dist/mcp/error/mcp-client-error.d.mts +36 -0
- package/dist/mcp/error/mcp-client-error.d.mts.map +1 -0
- package/dist/mcp/error/mcp-client-error.mjs +33 -0
- package/dist/mcp/error/mcp-client-error.mjs.map +1 -0
- package/dist/mcp/index.d.mts +8 -0
- package/dist/mcp/index.mjs +9 -0
- package/dist/mcp/tool/json-rpc-message.d.mts +50 -0
- package/dist/mcp/tool/json-rpc-message.d.mts.map +1 -0
- package/dist/mcp/tool/json-rpc-message.mjs +84 -0
- package/dist/mcp/tool/json-rpc-message.mjs.map +1 -0
- package/dist/mcp/tool/mcp-client.d.mts +71 -0
- package/dist/mcp/tool/mcp-client.d.mts.map +1 -0
- package/dist/mcp/tool/mcp-client.mjs +304 -0
- package/dist/mcp/tool/mcp-client.mjs.map +1 -0
- package/dist/mcp/tool/mcp-http-transport.d.mts +62 -0
- package/dist/mcp/tool/mcp-http-transport.d.mts.map +1 -0
- package/dist/mcp/tool/mcp-http-transport.mjs +307 -0
- package/dist/mcp/tool/mcp-http-transport.mjs.map +1 -0
- package/dist/mcp/tool/mcp-tools.d.mts +20 -0
- package/dist/mcp/tool/mcp-tools.d.mts.map +1 -0
- package/dist/mcp/tool/mcp-tools.mjs +73 -0
- package/dist/mcp/tool/mcp-tools.mjs.map +1 -0
- package/dist/mcp/tool/mcp-transport.d.mts +81 -0
- package/dist/mcp/tool/mcp-transport.d.mts.map +1 -0
- package/dist/mcp/tool/mcp-transport.mjs +11 -0
- package/dist/mcp/tool/mcp-transport.mjs.map +1 -0
- package/dist/mcp/tool/types.d.mts +230 -0
- package/dist/mcp/tool/types.d.mts.map +1 -0
- package/dist/mcp/tool/types.mjs +19 -0
- package/dist/mcp/tool/types.mjs.map +1 -0
- package/dist/persistence/index.d.mts +3 -0
- package/dist/persistence/index.mjs +3 -0
- package/dist/persistence/memory.d.mts +21 -0
- package/dist/persistence/memory.d.mts.map +1 -0
- package/dist/persistence/memory.mjs +107 -0
- package/dist/persistence/memory.mjs.map +1 -0
- package/dist/persistence/types.d.mts +124 -0
- package/dist/persistence/types.d.mts.map +1 -0
- package/dist/plugins/index.d.mts +2 -0
- package/dist/plugins/runtime.d.mts +17 -0
- package/dist/plugins/runtime.d.mts.map +1 -0
- package/dist/plugins/runtime.mjs +456 -0
- package/dist/plugins/runtime.mjs.map +1 -0
- package/dist/plugins/types.d.mts +344 -0
- package/dist/plugins/types.d.mts.map +1 -0
- package/dist/providers/index.d.mts +9 -0
- package/dist/providers/index.mjs +0 -0
- package/dist/providers/types/capabilities.d.mts +153 -0
- package/dist/providers/types/capabilities.d.mts.map +1 -0
- package/dist/providers/types/content.d.mts +125 -0
- package/dist/providers/types/content.d.mts.map +1 -0
- package/dist/providers/types/conversation.d.mts +32 -0
- package/dist/providers/types/conversation.d.mts.map +1 -0
- package/dist/providers/types/index.d.mts +8 -0
- package/dist/providers/types/input.d.mts +74 -0
- package/dist/providers/types/input.d.mts.map +1 -0
- package/dist/providers/types/model.d.mts +68 -0
- package/dist/providers/types/model.d.mts.map +1 -0
- package/dist/providers/types/output.d.mts +29 -0
- package/dist/providers/types/output.d.mts.map +1 -0
- package/dist/providers/types/response.d.mts +35 -0
- package/dist/providers/types/response.d.mts.map +1 -0
- package/dist/providers/types/tool-calls.d.mts +51 -0
- package/dist/providers/types/tool-calls.d.mts.map +1 -0
- package/dist/run/agent-loop.mjs +231 -0
- package/dist/run/agent-loop.mjs.map +1 -0
- package/dist/run/event-queue.mjs +67 -0
- package/dist/run/event-queue.mjs.map +1 -0
- package/dist/run/execute-tool-calls.mjs +550 -0
- package/dist/run/execute-tool-calls.mjs.map +1 -0
- package/dist/run/execution.mjs +93 -0
- package/dist/run/execution.mjs.map +1 -0
- package/dist/run/helpers.mjs +466 -0
- package/dist/run/helpers.mjs.map +1 -0
- package/dist/run/hooks.mjs +124 -0
- package/dist/run/hooks.mjs.map +1 -0
- package/dist/run/index.d.mts +4 -0
- package/dist/run/messages.d.mts +8 -0
- package/dist/run/messages.d.mts.map +1 -0
- package/dist/run/messages.mjs +83 -0
- package/dist/run/messages.mjs.map +1 -0
- package/dist/run/model-strategy.mjs +105 -0
- package/dist/run/model-strategy.mjs.map +1 -0
- package/dist/run/output-errors.d.mts +75 -0
- package/dist/run/output-errors.d.mts.map +1 -0
- package/dist/run/pending-tools.d.mts +1 -0
- package/dist/run/pending-tools.mjs +185 -0
- package/dist/run/pending-tools.mjs.map +1 -0
- package/dist/run/registry.mjs +22 -0
- package/dist/run/registry.mjs.map +1 -0
- package/dist/run/runtime.d.mts +19 -0
- package/dist/run/runtime.d.mts.map +1 -0
- package/dist/run/runtime.mjs +491 -0
- package/dist/run/runtime.mjs.map +1 -0
- package/dist/run/stop-conditions.mjs +41 -0
- package/dist/run/stop-conditions.mjs.map +1 -0
- package/dist/run/types.d.mts +348 -0
- package/dist/run/types.d.mts.map +1 -0
- package/dist/schema/index.d.mts +2 -0
- package/dist/schema/resolve-json-schema.d.mts +12 -0
- package/dist/schema/resolve-json-schema.d.mts.map +1 -0
- package/dist/schema/resolve-json-schema.mjs +167 -0
- package/dist/schema/resolve-json-schema.mjs.map +1 -0
- package/dist/schema/types.d.mts +27 -0
- package/dist/schema/types.d.mts.map +1 -0
- package/dist/server/create-server.d.mts +21 -0
- package/dist/server/create-server.d.mts.map +1 -0
- package/dist/server/create-server.mjs +107 -0
- package/dist/server/create-server.mjs.map +1 -0
- package/dist/server/http.mjs +182 -0
- package/dist/server/http.mjs.map +1 -0
- package/dist/server/index.d.mts +3 -0
- package/dist/server/index.mjs +3 -0
- package/dist/server/routes.mjs +399 -0
- package/dist/server/routes.mjs.map +1 -0
- package/dist/server/types.d.mts +31 -0
- package/dist/server/types.d.mts.map +1 -0
- package/dist/tools/constants.d.mts +12 -0
- package/dist/tools/constants.d.mts.map +1 -0
- package/dist/tools/constants.mjs +13 -0
- package/dist/tools/constants.mjs.map +1 -0
- package/dist/tools/define-tool.d.mts +25 -0
- package/dist/tools/define-tool.d.mts.map +1 -0
- package/dist/tools/define-tool.mjs +76 -0
- package/dist/tools/define-tool.mjs.map +1 -0
- package/dist/tools/index.d.mts +5 -0
- package/dist/tools/lazy-tools.d.mts +49 -0
- package/dist/tools/lazy-tools.d.mts.map +1 -0
- package/dist/tools/lazy-tools.mjs +87 -0
- package/dist/tools/lazy-tools.mjs.map +1 -0
- package/dist/tools/resolve-tools.d.mts +12 -0
- package/dist/tools/resolve-tools.d.mts.map +1 -0
- package/dist/tools/resolve-tools.mjs +86 -0
- package/dist/tools/resolve-tools.mjs.map +1 -0
- package/dist/tools/types.d.mts +318 -0
- package/dist/tools/types.d.mts.map +1 -0
- package/dist/tools/validation.mjs +23 -0
- package/dist/tools/validation.mjs.map +1 -0
- 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
|