@infinityi/engine-lib 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +488 -0
  3. package/dist/agent/agent-registry.d.ts +46 -0
  4. package/dist/agent/as-tool.d.ts +64 -0
  5. package/dist/agent/define.d.ts +35 -0
  6. package/dist/agent/handoff.d.ts +39 -0
  7. package/dist/agent/index.d.ts +20 -0
  8. package/dist/agent/index.js +38 -0
  9. package/dist/agent/registry.d.ts +27 -0
  10. package/dist/agent/types.d.ts +109 -0
  11. package/dist/context/index.d.ts +11 -0
  12. package/dist/context/index.js +21 -0
  13. package/dist/context/providers.d.ts +25 -0
  14. package/dist/context/types.d.ts +63 -0
  15. package/dist/context/window.d.ts +41 -0
  16. package/dist/errors.d.ts +93 -0
  17. package/dist/errors.js +24 -0
  18. package/dist/events/hub.d.ts +15 -0
  19. package/dist/events/index.d.ts +26 -0
  20. package/dist/events/index.js +24 -0
  21. package/dist/events/subscribers.d.ts +57 -0
  22. package/dist/events/telemetry.d.ts +61 -0
  23. package/dist/events/types.d.ts +39 -0
  24. package/dist/execution/index.d.ts +11 -0
  25. package/dist/execution/index.js +22 -0
  26. package/dist/execution/run.d.ts +35 -0
  27. package/dist/execution/types.d.ts +203 -0
  28. package/dist/execution/usage.d.ts +14 -0
  29. package/dist/index-02s1fjxr.js +226 -0
  30. package/dist/index-19pwq79t.js +0 -0
  31. package/dist/index-1p6mb2vz.js +32 -0
  32. package/dist/index-64tt9696.js +1796 -0
  33. package/dist/index-7690reng.js +96 -0
  34. package/dist/index-bqg01r42.js +354 -0
  35. package/dist/index-d4xz3abn.js +0 -0
  36. package/dist/index-dexgmwg6.js +148 -0
  37. package/dist/index-fkr3rcq9.js +97 -0
  38. package/dist/index-jg19te9v.js +0 -0
  39. package/dist/index-jp2b31xs.js +101 -0
  40. package/dist/index-jxgj4z08.js +68 -0
  41. package/dist/index-kte2h4k2.js +0 -0
  42. package/dist/index-pwr8179t.js +492 -0
  43. package/dist/index-rentvdpp.js +27 -0
  44. package/dist/index-vnby35rm.js +84 -0
  45. package/dist/index-w34cbktd.js +14 -0
  46. package/dist/index-xsv43c5j.js +39 -0
  47. package/dist/index-yrqrxwjt.js +148 -0
  48. package/dist/index-zfgr4xx3.js +90 -0
  49. package/dist/index.d.ts +45 -0
  50. package/dist/index.js +117 -0
  51. package/dist/lifecycle/component.d.ts +74 -0
  52. package/dist/lifecycle/index.d.ts +12 -0
  53. package/dist/lifecycle/index.js +72 -0
  54. package/dist/messages/factory.d.ts +24 -0
  55. package/dist/messages/index.d.ts +8 -0
  56. package/dist/messages/index.js +17 -0
  57. package/dist/messages/types.d.ts +52 -0
  58. package/dist/providers/adapter.d.ts +42 -0
  59. package/dist/providers/anthropic/index.d.ts +31 -0
  60. package/dist/providers/anthropic/map.d.ts +12 -0
  61. package/dist/providers/anthropic/stream.d.ts +9 -0
  62. package/dist/providers/google/index.d.ts +29 -0
  63. package/dist/providers/google/map.d.ts +13 -0
  64. package/dist/providers/google/stream.d.ts +11 -0
  65. package/dist/providers/http.d.ts +61 -0
  66. package/dist/providers/index.d.ts +32 -0
  67. package/dist/providers/index.js +35 -0
  68. package/dist/providers/openai/index.d.ts +34 -0
  69. package/dist/providers/openai/map.d.ts +10 -0
  70. package/dist/providers/openai/stream.d.ts +9 -0
  71. package/dist/providers/openai-compatible/index.d.ts +37 -0
  72. package/dist/providers/openai-compatible/map.d.ts +13 -0
  73. package/dist/providers/openai-compatible/stream.d.ts +11 -0
  74. package/dist/providers/shared.d.ts +34 -0
  75. package/dist/providers/sse.d.ts +19 -0
  76. package/dist/providers/stream.d.ts +69 -0
  77. package/dist/providers/types.d.ts +137 -0
  78. package/dist/runtime/index.d.ts +11 -0
  79. package/dist/runtime/index.js +11 -0
  80. package/dist/runtime/secret.d.ts +12 -0
  81. package/dist/runtime/types.d.ts +27 -0
  82. package/dist/schema/builder.d.ts +70 -0
  83. package/dist/schema/index.d.ts +13 -0
  84. package/dist/schema/index.js +15 -0
  85. package/dist/schema/json-schema.d.ts +19 -0
  86. package/dist/schema/types.d.ts +70 -0
  87. package/dist/schema/validate.d.ts +19 -0
  88. package/dist/session/index.d.ts +11 -0
  89. package/dist/session/index.js +8 -0
  90. package/dist/session/session.d.ts +31 -0
  91. package/dist/session/store.d.ts +20 -0
  92. package/dist/session/types.d.ts +55 -0
  93. package/dist/testing/conformance.d.ts +106 -0
  94. package/dist/testing/conformance.js +132 -0
  95. package/dist/testing/index.d.ts +84 -0
  96. package/dist/testing/index.js +31 -0
  97. package/dist/tools/define.d.ts +42 -0
  98. package/dist/tools/index.d.ts +11 -0
  99. package/dist/tools/index.js +15 -0
  100. package/dist/tools/result.d.ts +36 -0
  101. package/dist/tools/types.d.ts +85 -0
  102. package/docs/README.md +36 -0
  103. package/examples/README.md +24 -0
  104. package/examples/incident-analysis.ts +100 -0
  105. package/examples/lifecycle.ts +53 -0
  106. package/examples/multi-agent.ts +93 -0
  107. package/examples/terminal-coder.ts +80 -0
  108. package/package.json +114 -0
@@ -0,0 +1,101 @@
1
+ import {
2
+ createToolRegistry,
3
+ runAgent
4
+ } from "./index-pwr8179t.js";
5
+ import {
6
+ s
7
+ } from "./index-02s1fjxr.js";
8
+ import {
9
+ AgentError,
10
+ ExecutionError
11
+ } from "./index-7690reng.js";
12
+ import {
13
+ defineTool
14
+ } from "./index-w34cbktd.js";
15
+
16
+ // src/agent/define.ts
17
+ function defineAgent(def) {
18
+ if (typeof def.name !== "string" || def.name.trim() === "") {
19
+ throw new TypeError("defineAgent: `name` must be a non-empty string");
20
+ }
21
+ createToolRegistry(def.tools ?? []);
22
+ return def;
23
+ }
24
+ // src/agent/agent-registry.ts
25
+ function createAgentRegistry(agents = []) {
26
+ const byName = new Map;
27
+ const ordered = [];
28
+ const register = (agent) => {
29
+ if (byName.has(agent.name)) {
30
+ throw new ExecutionError(`duplicate agent name: "${agent.name}"`);
31
+ }
32
+ byName.set(agent.name, agent);
33
+ ordered.push(agent);
34
+ };
35
+ for (const agent of agents)
36
+ register(agent);
37
+ return {
38
+ get size() {
39
+ return ordered.length;
40
+ },
41
+ has(name) {
42
+ return byName.has(name);
43
+ },
44
+ get(name) {
45
+ return byName.get(name);
46
+ },
47
+ resolve(name) {
48
+ const agent = byName.get(name);
49
+ if (agent === undefined) {
50
+ throw new ExecutionError(`unknown agent: "${name}"`);
51
+ }
52
+ return agent;
53
+ },
54
+ list() {
55
+ return [...ordered];
56
+ },
57
+ register
58
+ };
59
+ }
60
+ // src/agent/as-tool.ts
61
+ var DEFAULT_PARAMETERS = s.object({ input: s.string() });
62
+ function childDepth(event) {
63
+ return event.type === "agent.child" ? event.depth + 1 : 1;
64
+ }
65
+ function asTool(agent, opts = {}) {
66
+ const parameters = opts.parameters ?? DEFAULT_PARAMETERS;
67
+ const toInput = opts.toInput ?? ((args) => args.input);
68
+ return defineTool({
69
+ name: opts.name ?? agent.name,
70
+ description: opts.description ?? `Delegate the task to the "${agent.name}" agent.`,
71
+ parameters,
72
+ execute: async (args, ctx) => {
73
+ const bridge = ctx.run;
74
+ try {
75
+ const result = await runAgent(agent, {
76
+ input: toInput(args),
77
+ ...ctx.telemetry !== undefined ? { telemetry: ctx.telemetry } : {},
78
+ ...ctx.logger !== undefined ? { logger: ctx.logger } : {},
79
+ ...ctx.signal !== undefined ? { signal: ctx.signal } : {},
80
+ ...bridge !== undefined ? {
81
+ onEvent: (event) => bridge.emit({
82
+ type: "agent.child",
83
+ agent: agent.name,
84
+ depth: childDepth(event),
85
+ event
86
+ })
87
+ } : {}
88
+ });
89
+ bridge?.reportUsage(result.usage);
90
+ return { ok: true, content: result.output };
91
+ } catch (err) {
92
+ if (err instanceof AgentError && err.usage !== undefined) {
93
+ bridge?.reportUsage(err.usage);
94
+ }
95
+ const message = err instanceof AgentError ? err.message : String(err);
96
+ return { ok: false, error: message };
97
+ }
98
+ }
99
+ });
100
+ }
101
+ export { defineAgent, createAgentRegistry, asTool };
@@ -0,0 +1,68 @@
1
+ // src/events/subscribers.ts
2
+ function loggingSubscriber(logger, opts = {}) {
3
+ const level = opts.level ?? "debug";
4
+ return (event) => {
5
+ logger[level](`agent.run ${event.type}`, eventFields(event));
6
+ };
7
+ }
8
+ function messageBusSubscriber(bus, opts = {}) {
9
+ const prefix = opts.typePrefix ?? "agent.";
10
+ return async (event) => {
11
+ await bus.publish({ type: `${prefix}${event.type}`, payload: eventPayload(event) });
12
+ };
13
+ }
14
+ function eventFields(event) {
15
+ switch (event.type) {
16
+ case "run.start":
17
+ return { agent: event.agent };
18
+ case "message":
19
+ return { role: event.message.role, parts: event.message.content.length };
20
+ case "token":
21
+ return { length: event.delta.length };
22
+ case "tool.call":
23
+ return { id: event.id, name: event.name };
24
+ case "tool.result":
25
+ return { id: event.id, name: event.name, ok: event.result.ok };
26
+ case "run.finish":
27
+ return {
28
+ finishReason: event.result.finishReason,
29
+ steps: event.result.steps,
30
+ totalTokens: event.result.usage.totalTokens
31
+ };
32
+ case "error":
33
+ return { name: event.error.name, message: event.error.message };
34
+ case "agent.child":
35
+ return { agent: event.agent, depth: event.depth, child: event.event.type };
36
+ case "agent.handoff":
37
+ return { from: event.from, to: event.to };
38
+ }
39
+ }
40
+ function eventPayload(event) {
41
+ switch (event.type) {
42
+ case "run.start":
43
+ return { agent: event.agent };
44
+ case "message":
45
+ return { message: event.message };
46
+ case "token":
47
+ return { delta: event.delta };
48
+ case "tool.call":
49
+ return { id: event.id, name: event.name, arguments: event.arguments };
50
+ case "tool.result":
51
+ return { id: event.id, name: event.name, result: event.result };
52
+ case "run.finish":
53
+ return {
54
+ output: event.result.output,
55
+ finishReason: event.result.finishReason,
56
+ steps: event.result.steps,
57
+ usage: event.result.usage,
58
+ messages: event.result.messages
59
+ };
60
+ case "error":
61
+ return { name: event.error.name, message: event.error.message };
62
+ case "agent.child":
63
+ return { agent: event.agent, depth: event.depth, event: eventPayload(event.event) };
64
+ case "agent.handoff":
65
+ return { from: event.from, to: event.to };
66
+ }
67
+ }
68
+ export { loggingSubscriber, messageBusSubscriber, eventFields, eventPayload };
File without changes
@@ -0,0 +1,492 @@
1
+ import {
2
+ applyContextWindow,
3
+ resolveContext
4
+ } from "./index-yrqrxwjt.js";
5
+ import {
6
+ SPAN_PROVIDER,
7
+ SPAN_RUN,
8
+ SPAN_TOOL,
9
+ createEventHub,
10
+ createRunTelemetry
11
+ } from "./index-fkr3rcq9.js";
12
+ import {
13
+ s
14
+ } from "./index-02s1fjxr.js";
15
+ import {
16
+ StreamAccumulator
17
+ } from "./index-zfgr4xx3.js";
18
+ import {
19
+ AgentError,
20
+ CancelledError,
21
+ ExecutionError,
22
+ MaxHandoffsExceededError,
23
+ MaxStepsExceededError
24
+ } from "./index-7690reng.js";
25
+ import {
26
+ toProviderTool,
27
+ toToolResultMessage
28
+ } from "./index-rentvdpp.js";
29
+ import {
30
+ system,
31
+ user
32
+ } from "./index-1p6mb2vz.js";
33
+
34
+ // src/agent/registry.ts
35
+ function createToolRegistry(tools) {
36
+ const byName = new Map;
37
+ const ordered = [];
38
+ for (const tool of tools) {
39
+ if (byName.has(tool.name)) {
40
+ throw new ExecutionError(`duplicate tool name: "${tool.name}"`);
41
+ }
42
+ byName.set(tool.name, tool);
43
+ ordered.push(tool);
44
+ }
45
+ return {
46
+ get size() {
47
+ return ordered.length;
48
+ },
49
+ has(name) {
50
+ return byName.has(name);
51
+ },
52
+ get(name) {
53
+ return byName.get(name);
54
+ },
55
+ list() {
56
+ return ordered;
57
+ },
58
+ toProviderTools() {
59
+ return ordered.map(toProviderTool);
60
+ }
61
+ };
62
+ }
63
+
64
+ // src/agent/handoff.ts
65
+ var HANDOFF_TOOL_PREFIX = "transfer_to_";
66
+ function handoffToolName(agentName) {
67
+ return `${HANDOFF_TOOL_PREFIX}${agentName}`;
68
+ }
69
+ var HANDOFF_PARAMETERS = s.object({}).jsonSchema;
70
+ function resolveHandoffTargets(agent, registry) {
71
+ const targets = new Map;
72
+ for (const entry of agent.handoffs ?? []) {
73
+ const target = typeof entry === "string" ? resolveByName(agent, entry, registry) : entry;
74
+ const toolName = handoffToolName(target.name);
75
+ if (targets.has(toolName)) {
76
+ throw new ExecutionError(`agent "${agent.name}" declares duplicate handoff target "${target.name}"`);
77
+ }
78
+ targets.set(toolName, target);
79
+ }
80
+ return targets;
81
+ }
82
+ function resolveByName(agent, name, registry) {
83
+ if (registry === undefined) {
84
+ throw new ExecutionError(`agent "${agent.name}" declares a string handoff "${name}" but no registry was ` + `provided; pass { registry } to runAgent or use a direct AgentDefinition target`);
85
+ }
86
+ return registry.resolve(name);
87
+ }
88
+ function handoffProviderTools(targets) {
89
+ return [...targets.entries()].map(([toolName, target]) => ({
90
+ name: toolName,
91
+ description: `Transfer the conversation to the "${target.name}" agent. ` + `Use this when the request is better handled by that agent; ` + `the full message history is preserved.`,
92
+ parameters: HANDOFF_PARAMETERS
93
+ }));
94
+ }
95
+
96
+ // src/execution/usage.ts
97
+ function emptyUsage() {
98
+ return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
99
+ }
100
+ function addUsage(a, b) {
101
+ if (b === undefined)
102
+ return a;
103
+ const reasoningTokens = a.reasoningTokens !== undefined || b.reasoningTokens !== undefined ? (a.reasoningTokens ?? 0) + (b.reasoningTokens ?? 0) : undefined;
104
+ const cachedInputTokens = a.cachedInputTokens !== undefined || b.cachedInputTokens !== undefined ? (a.cachedInputTokens ?? 0) + (b.cachedInputTokens ?? 0) : undefined;
105
+ return {
106
+ inputTokens: a.inputTokens + b.inputTokens,
107
+ outputTokens: a.outputTokens + b.outputTokens,
108
+ totalTokens: a.totalTokens + b.totalTokens,
109
+ ...reasoningTokens !== undefined ? { reasoningTokens } : {},
110
+ ...cachedInputTokens !== undefined ? { cachedInputTokens } : {}
111
+ };
112
+ }
113
+
114
+ // src/execution/run.ts
115
+ var DEFAULT_MAX_STEPS = 16;
116
+ var DEFAULT_MAX_HANDOFFS = 8;
117
+ function normalizeInput(input) {
118
+ if (input === undefined)
119
+ return [];
120
+ if (typeof input === "string")
121
+ return [user(input)];
122
+ if (Array.isArray(input))
123
+ return input;
124
+ return [input];
125
+ }
126
+ function extractText(message) {
127
+ return message.content.filter((p) => p.type === "text").map((p) => p.text).join("");
128
+ }
129
+ function toAgentError(err) {
130
+ if (err instanceof AgentError)
131
+ return err;
132
+ const message = err instanceof Error ? err.message : String(err);
133
+ return new ExecutionError(message, err instanceof Error ? { cause: err } : undefined);
134
+ }
135
+ function buildEngineContext(opts) {
136
+ return {
137
+ ...opts.telemetry !== undefined ? { telemetry: opts.telemetry } : {},
138
+ ...opts.logger !== undefined ? { logger: opts.logger } : {},
139
+ ...opts.signal !== undefined ? { signal: opts.signal } : {}
140
+ };
141
+ }
142
+ function buildRequest(agent, opts, providerTools, messages) {
143
+ const gen = { ...agent.generation, ...opts.generation };
144
+ return {
145
+ messages,
146
+ ...gen.model !== undefined ? { model: gen.model } : {},
147
+ ...providerTools !== undefined ? { tools: providerTools } : {},
148
+ ...gen.toolChoice !== undefined ? { toolChoice: gen.toolChoice } : {},
149
+ ...gen.temperature !== undefined ? { temperature: gen.temperature } : {},
150
+ ...gen.topP !== undefined ? { topP: gen.topP } : {},
151
+ ...gen.maxOutputTokens !== undefined ? { maxOutputTokens: gen.maxOutputTokens } : {},
152
+ ...gen.stopSequences !== undefined ? { stopSequences: gen.stopSequences } : {}
153
+ };
154
+ }
155
+ async function resolveInstructions(agent, engineCtx) {
156
+ const instr = agent.instructions;
157
+ if (instr === undefined)
158
+ return;
159
+ if (typeof instr === "string")
160
+ return instr;
161
+ const ctx = { ...engineCtx, agent };
162
+ return instr(ctx);
163
+ }
164
+ function throwIfAborted(signal) {
165
+ if (signal?.aborted)
166
+ throw new CancelledError("run cancelled");
167
+ }
168
+ async function* executeAgent(agent, opts, tel) {
169
+ const maxSteps = opts.maxSteps ?? DEFAULT_MAX_STEPS;
170
+ const maxHandoffs = opts.maxHandoffs ?? DEFAULT_MAX_HANDOFFS;
171
+ const stream = opts.stream === true;
172
+ const engineCtx = buildEngineContext(opts);
173
+ const activate = (agentDef) => {
174
+ const registry = createToolRegistry(agentDef.tools ?? []);
175
+ const handoffs = resolveHandoffTargets(agentDef, opts.registry);
176
+ for (const toolName of handoffs.keys()) {
177
+ if (registry.has(toolName)) {
178
+ throw new ExecutionError(`agent "${agentDef.name}" has a tool named "${toolName}" that collides with a handoff target`);
179
+ }
180
+ }
181
+ const advertised = [...registry.toProviderTools(), ...handoffProviderTools(handoffs)];
182
+ return {
183
+ agent: agentDef,
184
+ registry,
185
+ handoffs,
186
+ providerTools: advertised.length > 0 ? advertised : undefined
187
+ };
188
+ };
189
+ let active = activate(agent);
190
+ const runOneTool = async (call) => {
191
+ const events = [];
192
+ let usage2 = emptyUsage();
193
+ const bridge = {
194
+ emit: (event) => events.push(event),
195
+ reportUsage: (u) => {
196
+ usage2 = addUsage(usage2, u);
197
+ }
198
+ };
199
+ const tool = active.registry.get(call.name);
200
+ if (tool === undefined) {
201
+ return { result: { ok: false, error: `unknown tool: "${call.name}"` }, events, usage: usage2 };
202
+ }
203
+ const parsed = tool.parameters.safeParse(call.arguments);
204
+ if (!parsed.success) {
205
+ const detail = parsed.error.issues.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`).join("; ");
206
+ return {
207
+ result: { ok: false, error: `invalid arguments for "${call.name}": ${detail}` },
208
+ events,
209
+ usage: usage2
210
+ };
211
+ }
212
+ const toolCtx = {
213
+ ...engineCtx,
214
+ toolCallId: call.id,
215
+ agentName: active.agent.name,
216
+ run: bridge
217
+ };
218
+ const span = tel.startSpan(SPAN_TOOL, { "tool.name": call.name, "tool.call_id": call.id });
219
+ const startedAt = Date.now();
220
+ try {
221
+ const result = await tool.execute(parsed.data, toolCtx);
222
+ span.setAttributes({ "tool.ok": result.ok });
223
+ span.ok();
224
+ return { result, events, usage: usage2 };
225
+ } catch (err) {
226
+ const message = err instanceof Error ? err.message : String(err);
227
+ span.fail(message);
228
+ return { result: { ok: false, error: message }, events, usage: usage2 };
229
+ } finally {
230
+ span.end();
231
+ tel.recordTool({ "tool.name": call.name, "agent.name": active.agent.name }, Date.now() - startedAt);
232
+ }
233
+ };
234
+ let usage = emptyUsage();
235
+ try {
236
+ throwIfAborted(opts.signal);
237
+ yield { type: "run.start", agent: agent.name };
238
+ const instructions = await resolveInstructions(agent, engineCtx);
239
+ const contextMessages = await resolveContext(opts.context, engineCtx);
240
+ const prior = opts.session !== undefined ? await opts.session.messages() : opts.messages ?? [];
241
+ const inputMessages = normalizeInput(opts.input);
242
+ const messages = [];
243
+ if (instructions !== undefined && instructions !== "")
244
+ messages.push(system(instructions));
245
+ messages.push(...contextMessages);
246
+ messages.push(...prior);
247
+ messages.push(...inputMessages);
248
+ const newMessages = [...inputMessages];
249
+ await active.agent.hooks?.onStart?.({ agent: active.agent, messages: [...messages] }, engineCtx);
250
+ let finishReason = "stop";
251
+ let finalMessage = { role: "assistant", content: [] };
252
+ let steps = 0;
253
+ const handoffTrail = [];
254
+ while (steps < maxSteps) {
255
+ throwIfAborted(opts.signal);
256
+ steps++;
257
+ const provider = active.agent.provider;
258
+ const model = opts.generation?.model ?? active.agent.generation?.model ?? provider.defaultModel;
259
+ const requestMessages = await applyContextWindow(messages, opts.contextWindow, {
260
+ provider,
261
+ model,
262
+ engine: engineCtx
263
+ });
264
+ const req = buildRequest(active.agent, opts, active.providerTools, requestMessages);
265
+ const useStreaming = stream && provider.capabilities.streaming;
266
+ const providerSpan = tel.startSpan(SPAN_PROVIDER, {
267
+ "provider.name": provider.name,
268
+ "provider.model": model,
269
+ "provider.mode": useStreaming ? "stream" : "complete",
270
+ "agent.step": steps
271
+ });
272
+ let result;
273
+ try {
274
+ if (useStreaming) {
275
+ const acc = new StreamAccumulator;
276
+ let streamError;
277
+ for await (const event of provider.stream(req, engineCtx)) {
278
+ acc.push(event);
279
+ if (event.type === "text_delta" && event.text !== "") {
280
+ yield { type: "token", delta: event.text };
281
+ } else if (event.type === "error") {
282
+ streamError = event.error;
283
+ }
284
+ }
285
+ if (streamError !== undefined)
286
+ throw streamError;
287
+ result = acc.result(model);
288
+ } else {
289
+ result = await provider.complete(req, engineCtx);
290
+ if (stream) {
291
+ const buffered = extractText(result.message);
292
+ if (buffered !== "")
293
+ yield { type: "token", delta: buffered };
294
+ }
295
+ }
296
+ providerSpan.setAttributes({ "provider.finish_reason": result.finishReason });
297
+ providerSpan.ok();
298
+ } catch (err) {
299
+ providerSpan.fail(err instanceof Error ? err.message : String(err));
300
+ throw err;
301
+ } finally {
302
+ providerSpan.end();
303
+ }
304
+ usage = addUsage(usage, result.usage);
305
+ finishReason = result.finishReason;
306
+ finalMessage = result.message;
307
+ messages.push(result.message);
308
+ newMessages.push(result.message);
309
+ yield { type: "message", message: result.message };
310
+ await active.agent.hooks?.onStep?.({ step: steps, result }, engineCtx);
311
+ const calls = result.toolCalls;
312
+ if (calls.length === 0) {
313
+ const output = extractText(finalMessage);
314
+ const runResult = {
315
+ output,
316
+ finalMessage,
317
+ messages: [...messages],
318
+ finishReason,
319
+ steps,
320
+ usage,
321
+ agent: active.agent.name,
322
+ handoffs: [...handoffTrail]
323
+ };
324
+ await opts.session?.append(newMessages);
325
+ yield { type: "run.finish", result: runResult };
326
+ await active.agent.hooks?.onFinish?.({ output, usage }, engineCtx);
327
+ return runResult;
328
+ }
329
+ const handoffTargets = active.handoffs;
330
+ const regularCalls = calls.filter((call) => !handoffTargets.has(call.name));
331
+ const handoffCalls = calls.filter((call) => handoffTargets.has(call.name));
332
+ for (const call of calls) {
333
+ yield { type: "tool.call", id: call.id, name: call.name, arguments: call.arguments };
334
+ const tool = active.registry.get(call.name);
335
+ if (tool !== undefined)
336
+ await active.agent.hooks?.onToolCall?.({ call, tool }, engineCtx);
337
+ }
338
+ const settled = await Promise.all(regularCalls.map(async (call) => ({ call, outcome: await runOneTool(call) })));
339
+ for (const { outcome } of settled)
340
+ usage = addUsage(usage, outcome.usage);
341
+ throwIfAborted(opts.signal);
342
+ for (const { call, outcome } of settled) {
343
+ for (const childEvent of outcome.events)
344
+ yield childEvent;
345
+ const toolResult = outcome.result;
346
+ yield { type: "tool.result", id: call.id, name: call.name, result: toolResult };
347
+ await active.agent.hooks?.onToolResult?.({ call, result: toolResult }, engineCtx);
348
+ }
349
+ for (const { call, outcome } of settled) {
350
+ const message = toToolResultMessage(call.id, outcome.result);
351
+ messages.push(message);
352
+ newMessages.push(message);
353
+ yield { type: "message", message };
354
+ }
355
+ for (const call of handoffCalls) {
356
+ const target = handoffTargets.get(call.name);
357
+ if (target === undefined)
358
+ continue;
359
+ if (handoffTrail.length >= maxHandoffs) {
360
+ throw new MaxHandoffsExceededError(`exceeded max handoffs (${maxHandoffs})`, {
361
+ handoffs: maxHandoffs
362
+ });
363
+ }
364
+ const ack = { ok: true, content: `Transferred to "${target.name}".` };
365
+ const ackMessage = toToolResultMessage(call.id, ack);
366
+ messages.push(ackMessage);
367
+ newMessages.push(ackMessage);
368
+ yield { type: "tool.result", id: call.id, name: call.name, result: ack };
369
+ yield { type: "message", message: ackMessage };
370
+ const from = active.agent;
371
+ yield { type: "agent.handoff", from: from.name, to: target.name };
372
+ await from.hooks?.onHandoff?.({ from, to: target }, engineCtx);
373
+ active = activate(target);
374
+ handoffTrail.push(target.name);
375
+ const nextInstructions = await resolveInstructions(active.agent, engineCtx);
376
+ if (nextInstructions !== undefined && nextInstructions !== "") {
377
+ messages.push(system(nextInstructions));
378
+ }
379
+ }
380
+ }
381
+ throw new MaxStepsExceededError(`exceeded max steps (${maxSteps})`, { steps: maxSteps });
382
+ } catch (err) {
383
+ const agentError = toAgentError(err);
384
+ if (agentError.usage === undefined)
385
+ agentError.usage = usage;
386
+ yield { type: "error", error: agentError };
387
+ try {
388
+ await active.agent.hooks?.onError?.({ error: agentError }, engineCtx);
389
+ } catch {}
390
+ throw agentError;
391
+ }
392
+ }
393
+ function usageOfError(err) {
394
+ return err instanceof AgentError && err.usage !== undefined ? err.usage : emptyUsage();
395
+ }
396
+ function runResultAttrs(result) {
397
+ return {
398
+ "agent.steps": result.steps,
399
+ "agent.finish_reason": result.finishReason,
400
+ "agent.usage.total_tokens": result.usage.totalTokens
401
+ };
402
+ }
403
+ async function driveToCompletion(gen, hub, tel, agentName) {
404
+ const startedAt = Date.now();
405
+ try {
406
+ const result = await tel.withSpan(SPAN_RUN, { "agent.name": agentName }, async (span) => {
407
+ let next = await gen.next();
408
+ while (!next.done) {
409
+ await hub.emit(next.value);
410
+ next = await gen.next();
411
+ }
412
+ span.setAttributes(runResultAttrs(next.value));
413
+ span.ok();
414
+ return next.value;
415
+ });
416
+ tel.recordRun({ "agent.name": agentName, "agent.outcome": "ok" }, Date.now() - startedAt, result.usage);
417
+ return result;
418
+ } catch (err) {
419
+ tel.recordRun({ "agent.name": agentName, "agent.outcome": "error" }, Date.now() - startedAt, usageOfError(err));
420
+ throw err;
421
+ }
422
+ }
423
+ function makeHandle(gen, hub, tel, agentName) {
424
+ let resolveCompleted;
425
+ let rejectCompleted;
426
+ const completed = new Promise((resolve, reject) => {
427
+ resolveCompleted = resolve;
428
+ rejectCompleted = reject;
429
+ });
430
+ completed.catch(() => {});
431
+ const span = tel.startSpan(SPAN_RUN, { "agent.name": agentName });
432
+ const startedAt = Date.now();
433
+ async function* iterate() {
434
+ let settled = false;
435
+ try {
436
+ let next = await gen.next();
437
+ while (!next.done) {
438
+ await hub.emit(next.value);
439
+ yield next.value;
440
+ next = await gen.next();
441
+ }
442
+ span.setAttributes(runResultAttrs(next.value));
443
+ span.ok();
444
+ settled = true;
445
+ tel.recordRun({ "agent.name": agentName, "agent.outcome": "ok" }, Date.now() - startedAt, next.value.usage);
446
+ resolveCompleted(next.value);
447
+ } catch (err) {
448
+ span.fail(err instanceof Error ? err.message : String(err));
449
+ settled = true;
450
+ tel.recordRun({ "agent.name": agentName, "agent.outcome": "error" }, Date.now() - startedAt, usageOfError(err));
451
+ rejectCompleted(err);
452
+ throw err;
453
+ } finally {
454
+ if (!settled) {
455
+ const cancelled = new CancelledError("run stream abandoned before completion");
456
+ await gen.return(undefined).catch(() => {});
457
+ span.fail(cancelled.message);
458
+ tel.recordRun({ "agent.name": agentName, "agent.outcome": "incomplete" }, Date.now() - startedAt, emptyUsage());
459
+ rejectCompleted(cancelled);
460
+ }
461
+ span.end();
462
+ }
463
+ }
464
+ const iterator = iterate();
465
+ return {
466
+ [Symbol.asyncIterator]: () => iterator,
467
+ completed
468
+ };
469
+ }
470
+ function buildEventHub(opts) {
471
+ const logger = opts.logger ?? opts.telemetry?.log;
472
+ return createEventHub({
473
+ subscribers: [opts.onEvent, ...opts.subscribers ?? []],
474
+ onSubscriberError: (error, event, index) => {
475
+ logger?.warn("agent.run subscriber threw", {
476
+ event: event.type,
477
+ index,
478
+ error: error instanceof Error ? error.message : String(error)
479
+ });
480
+ }
481
+ });
482
+ }
483
+ function runAgent(agent, opts = {}) {
484
+ const tel = createRunTelemetry(opts.telemetry);
485
+ const hub = buildEventHub(opts);
486
+ const gen = executeAgent(agent, opts, tel);
487
+ if (opts.stream === true)
488
+ return makeHandle(gen, hub, tel, agent.name);
489
+ return driveToCompletion(gen, hub, tel, agent.name);
490
+ }
491
+
492
+ export { createToolRegistry, handoffToolName, resolveHandoffTargets, handoffProviderTools, emptyUsage, addUsage, DEFAULT_MAX_STEPS, DEFAULT_MAX_HANDOFFS, runAgent };
@@ -0,0 +1,27 @@
1
+ import {
2
+ text,
3
+ toolResult
4
+ } from "./index-1p6mb2vz.js";
5
+
6
+ // src/tools/result.ts
7
+ function renderToolContent(result) {
8
+ const value = result.ok ? result.content : result.error;
9
+ if (typeof value === "string")
10
+ return [text(value)];
11
+ if (value === undefined || value === null)
12
+ return [text("")];
13
+ return [text(JSON.stringify(value))];
14
+ }
15
+ function toToolResultMessage(toolCallId, result) {
16
+ const content = renderToolContent(result);
17
+ return result.ok ? toolResult(toolCallId, content) : toolResult(toolCallId, content, { isError: true });
18
+ }
19
+ function toProviderTool(tool) {
20
+ return {
21
+ name: tool.name,
22
+ ...tool.description !== undefined ? { description: tool.description } : {},
23
+ parameters: tool.parameters.jsonSchema
24
+ };
25
+ }
26
+
27
+ export { renderToolContent, toToolResultMessage, toProviderTool };