@vercel/agent-runs 0.0.0-stage → 0.0.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 (129) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +77 -0
  3. package/README.md +251 -2
  4. package/dist/src/adapters/agent-transport.d.ts +9 -0
  5. package/dist/src/adapters/agent-transport.d.ts.map +1 -0
  6. package/dist/src/adapters/agent-transport.js +87 -0
  7. package/dist/src/adapters/agent-transport.js.map +1 -0
  8. package/dist/src/adapters/ai-sdk-payload.d.ts +16 -0
  9. package/dist/src/adapters/ai-sdk-payload.d.ts.map +1 -0
  10. package/dist/src/adapters/ai-sdk-payload.js +30 -0
  11. package/dist/src/adapters/ai-sdk-payload.js.map +1 -0
  12. package/dist/src/adapters/ai-sdk-telemetry.d.ts +15 -0
  13. package/dist/src/adapters/ai-sdk-telemetry.d.ts.map +1 -0
  14. package/dist/src/adapters/ai-sdk-telemetry.js +151 -0
  15. package/dist/src/adapters/ai-sdk-telemetry.js.map +1 -0
  16. package/dist/src/adapters/otel-error.d.ts +4 -0
  17. package/dist/src/adapters/otel-error.d.ts.map +1 -0
  18. package/dist/src/adapters/otel-error.js +32 -0
  19. package/dist/src/adapters/otel-error.js.map +1 -0
  20. package/dist/src/adapters/otel-ids.d.ts +20 -0
  21. package/dist/src/adapters/otel-ids.d.ts.map +1 -0
  22. package/dist/src/adapters/otel-ids.js +74 -0
  23. package/dist/src/adapters/otel-ids.js.map +1 -0
  24. package/dist/src/adapters/otel.d.ts +34 -0
  25. package/dist/src/adapters/otel.d.ts.map +1 -0
  26. package/dist/src/adapters/otel.js +147 -0
  27. package/dist/src/adapters/otel.js.map +1 -0
  28. package/dist/src/adapters/serialization.d.ts +37 -0
  29. package/dist/src/adapters/serialization.d.ts.map +1 -0
  30. package/dist/src/adapters/serialization.js +318 -0
  31. package/dist/src/adapters/serialization.js.map +1 -0
  32. package/dist/src/agent-run.d.ts +85 -0
  33. package/dist/src/agent-run.d.ts.map +1 -0
  34. package/dist/src/agent-run.js +213 -0
  35. package/dist/src/agent-run.js.map +1 -0
  36. package/dist/src/ai-sdk.d.ts +8 -0
  37. package/dist/src/ai-sdk.d.ts.map +1 -0
  38. package/dist/src/ai-sdk.js +8 -0
  39. package/dist/src/ai-sdk.js.map +1 -0
  40. package/dist/src/capture.d.ts +6 -0
  41. package/dist/src/capture.d.ts.map +1 -0
  42. package/dist/src/capture.js +9 -0
  43. package/dist/src/capture.js.map +1 -0
  44. package/dist/src/core/activation.d.ts +4 -0
  45. package/dist/src/core/activation.d.ts.map +1 -0
  46. package/dist/src/core/activation.js +31 -0
  47. package/dist/src/core/activation.js.map +1 -0
  48. package/dist/src/core/attributes.d.ts +15 -0
  49. package/dist/src/core/attributes.d.ts.map +1 -0
  50. package/dist/src/core/attributes.js +76 -0
  51. package/dist/src/core/attributes.js.map +1 -0
  52. package/dist/src/core/content-policy.d.ts +29 -0
  53. package/dist/src/core/content-policy.d.ts.map +1 -0
  54. package/dist/src/core/content-policy.js +94 -0
  55. package/dist/src/core/content-policy.js.map +1 -0
  56. package/dist/src/core/context.d.ts +4 -0
  57. package/dist/src/core/context.d.ts.map +1 -0
  58. package/dist/src/core/context.js +28 -0
  59. package/dist/src/core/context.js.map +1 -0
  60. package/dist/src/core/delegation.d.ts +14 -0
  61. package/dist/src/core/delegation.d.ts.map +1 -0
  62. package/dist/src/core/delegation.js +7 -0
  63. package/dist/src/core/delegation.js.map +1 -0
  64. package/dist/src/core/mcp.d.ts +25 -0
  65. package/dist/src/core/mcp.d.ts.map +1 -0
  66. package/dist/src/core/mcp.js +33 -0
  67. package/dist/src/core/mcp.js.map +1 -0
  68. package/dist/src/core/scopes.d.ts +60 -0
  69. package/dist/src/core/scopes.d.ts.map +1 -0
  70. package/dist/src/core/scopes.js +574 -0
  71. package/dist/src/core/scopes.js.map +1 -0
  72. package/dist/src/core/snapshot.d.ts +8 -0
  73. package/dist/src/core/snapshot.d.ts.map +1 -0
  74. package/dist/src/core/snapshot.js +207 -0
  75. package/dist/src/core/snapshot.js.map +1 -0
  76. package/dist/src/core/span-kinds.d.ts +13 -0
  77. package/dist/src/core/span-kinds.d.ts.map +1 -0
  78. package/dist/src/core/span-kinds.js +338 -0
  79. package/dist/src/core/span-kinds.js.map +1 -0
  80. package/dist/src/core/types.d.ts +298 -0
  81. package/dist/src/core/types.d.ts.map +1 -0
  82. package/dist/src/core/types.js +2 -0
  83. package/dist/src/core/types.js.map +1 -0
  84. package/dist/src/core/writer.d.ts +16 -0
  85. package/dist/src/core/writer.d.ts.map +1 -0
  86. package/dist/src/core/writer.js +77 -0
  87. package/dist/src/core/writer.js.map +1 -0
  88. package/dist/src/delegation.d.ts +3 -0
  89. package/dist/src/delegation.d.ts.map +1 -0
  90. package/dist/src/delegation.js +3 -0
  91. package/dist/src/delegation.js.map +1 -0
  92. package/dist/src/index.d.ts +7 -0
  93. package/dist/src/index.d.ts.map +1 -0
  94. package/dist/src/index.js +5 -0
  95. package/dist/src/index.js.map +1 -0
  96. package/dist/src/operations.d.ts +97 -0
  97. package/dist/src/operations.d.ts.map +1 -0
  98. package/dist/src/operations.js +185 -0
  99. package/dist/src/operations.js.map +1 -0
  100. package/dist/src/otel.d.ts +13 -0
  101. package/dist/src/otel.d.ts.map +1 -0
  102. package/dist/src/otel.js +13 -0
  103. package/dist/src/otel.js.map +1 -0
  104. package/package.json +75 -3
  105. package/src/adapters/agent-transport.ts +113 -0
  106. package/src/adapters/ai-sdk-payload.ts +44 -0
  107. package/src/adapters/ai-sdk-telemetry.ts +179 -0
  108. package/src/adapters/otel-error.ts +34 -0
  109. package/src/adapters/otel-ids.ts +82 -0
  110. package/src/adapters/otel.ts +232 -0
  111. package/src/adapters/serialization.ts +338 -0
  112. package/src/agent-run.ts +341 -0
  113. package/src/ai-sdk.ts +7 -0
  114. package/src/capture.ts +13 -0
  115. package/src/core/activation.ts +42 -0
  116. package/src/core/attributes.ts +85 -0
  117. package/src/core/content-policy.ts +116 -0
  118. package/src/core/context.ts +34 -0
  119. package/src/core/delegation.ts +20 -0
  120. package/src/core/mcp.ts +60 -0
  121. package/src/core/scopes.ts +761 -0
  122. package/src/core/snapshot.ts +245 -0
  123. package/src/core/span-kinds.ts +406 -0
  124. package/src/core/types.ts +304 -0
  125. package/src/core/writer.ts +135 -0
  126. package/src/delegation.ts +2 -0
  127. package/src/index.ts +44 -0
  128. package/src/operations.ts +342 -0
  129. package/src/otel.ts +18 -0
@@ -0,0 +1,185 @@
1
+ function report(onError, error, phase) {
2
+ try {
3
+ onError?.(error, { phase });
4
+ }
5
+ catch { }
6
+ }
7
+ export function wrappedOperation(start, fallback = { outcome: "completed" }, onError) {
8
+ async function invoke(input, execute) {
9
+ if (execute === undefined)
10
+ return start(input);
11
+ const handle = await start(input);
12
+ let completion = fallback;
13
+ try {
14
+ const value = await handle.run(() => execute(handle));
15
+ try {
16
+ completion =
17
+ input.describe?.(value) ?? fallback;
18
+ }
19
+ catch (error) {
20
+ report(onError, error, "complete");
21
+ }
22
+ return value;
23
+ }
24
+ catch (error) {
25
+ completion = {
26
+ outcome: "failed",
27
+ errorType: error instanceof Error ? error.name : "_OTHER",
28
+ error,
29
+ };
30
+ throw error;
31
+ }
32
+ finally {
33
+ try {
34
+ await handle.complete(completion);
35
+ }
36
+ catch (error) {
37
+ report(onError, error, "complete");
38
+ }
39
+ }
40
+ }
41
+ return invoke;
42
+ }
43
+ export function operationHandle(runtime, data, onError) {
44
+ const live = (handle) => Object.defineProperties(handle, {
45
+ finished: { get: () => runtime.finished },
46
+ capture: { get: () => runtime.capture },
47
+ parent: { get: () => runtime.parent },
48
+ });
49
+ const common = {
50
+ type: runtime.type,
51
+ reference: runtime.reference,
52
+ get startTimeMs() {
53
+ return runtime.startTimeMs;
54
+ },
55
+ get parent() {
56
+ return runtime.parent;
57
+ },
58
+ get finished() {
59
+ return runtime.finished;
60
+ },
61
+ get capture() {
62
+ return runtime.capture;
63
+ },
64
+ run: (execute, ceiling) => runtime.run(execute, ceiling),
65
+ attributes: (attributes) => runtime.attributes(attributes),
66
+ complete: (result) => runtime.complete(result),
67
+ fail: (error) => runtime.fail(error),
68
+ recordError: (error, errorType) => runtime.error(error, errorType),
69
+ };
70
+ const child = async (data, key, options) => operationHandle(await runtime.child(data, key, options), data, onError);
71
+ const tool = wrappedOperation(async ({ startTimeMs, ...options }) => child({ type: "tool", options }, undefined, { startTimeMs }), undefined, onError);
72
+ const found = (operation) => operation === undefined
73
+ ? undefined
74
+ : operationHandle(operation, operation.record().data, onError);
75
+ const memory = wrappedOperation(async (options) => child({ type: "memory", options }), undefined, onError);
76
+ if (data.type === "activation")
77
+ return live({
78
+ ...common,
79
+ memory,
80
+ links: (links) => runtime.update({ links }),
81
+ findAttempt: (input) => found(runtime.find({
82
+ type: "step",
83
+ options: { index: input.stepIndex, attempt: input.attempt },
84
+ })),
85
+ findTool: (callId) => found(findTool(runtime, callId)),
86
+ attempt: wrappedOperation(async (input) => child({
87
+ type: "step",
88
+ options: {
89
+ index: input.stepIndex,
90
+ attempt: input.attempt,
91
+ runtimeContext: input.runtimeContext,
92
+ channel: input.channel,
93
+ },
94
+ }, undefined, { links: input.links }), undefined, onError),
95
+ });
96
+ if (data.type === "step") {
97
+ const delegation = (kind) => wrappedOperation(async (input) => child({
98
+ type: "tool",
99
+ options: { callId: input.callId, name: input.agentName, kind },
100
+ }), undefined, onError);
101
+ const startModel = (options, key) => child({ type: "model", options }, key);
102
+ async function modelCall(input, execute) {
103
+ if (typeof execute !== "function")
104
+ return startModel(input, execute);
105
+ const handle = await startModel(input);
106
+ let result;
107
+ try {
108
+ result = await handle.run(execute);
109
+ }
110
+ catch (error) {
111
+ try {
112
+ await handle.fail(error);
113
+ }
114
+ catch (tracingError) {
115
+ report(onError, tracingError, "complete");
116
+ }
117
+ throw error;
118
+ }
119
+ try {
120
+ await handle.complete({ outcome: "completed", result });
121
+ }
122
+ catch (error) {
123
+ report(onError, error, "complete");
124
+ }
125
+ return result.result;
126
+ }
127
+ return live({
128
+ ...common,
129
+ memory,
130
+ tool,
131
+ callSubAgent: delegation("subagent-call"),
132
+ callRemoteAgent: delegation("remote-agent-call"),
133
+ modelCall,
134
+ async modelStream(input, execute) {
135
+ const handle = await startModel(input);
136
+ try {
137
+ const value = await handle.run(execute);
138
+ const completion = Promise.resolve(value.completion)
139
+ .then((result) => handle.complete({ outcome: "completed", result }), (error) => handle.fail(error))
140
+ .catch((error) => report(onError, error, "complete"));
141
+ runtime.waitUntil(completion);
142
+ return value.result;
143
+ }
144
+ catch (error) {
145
+ try {
146
+ await handle.fail(error);
147
+ }
148
+ catch (tracingError) {
149
+ report(onError, tracingError, "complete");
150
+ }
151
+ throw error;
152
+ }
153
+ },
154
+ });
155
+ }
156
+ if (data.type === "tool")
157
+ return live({
158
+ ...common,
159
+ memory,
160
+ tool,
161
+ findApproval: (requestId) => found(runtime.find({
162
+ type: "approval",
163
+ options: { requestId, callId: data.options.callId, toolName: data.options.name },
164
+ })),
165
+ approval: wrappedOperation(async (input) => child({
166
+ type: "approval",
167
+ options: { ...input, callId: data.options.callId, toolName: data.options.name },
168
+ }), { outcome: "ignored" }, onError),
169
+ });
170
+ return common;
171
+ }
172
+ /** Tool calls can nest, so a call ID is searched through every open call of the turn. */
173
+ function findTool(parent, callId) {
174
+ for (const next of parent.children) {
175
+ if (next.type === "tool" && next.callId === callId)
176
+ return next;
177
+ if (next.type === "step" || next.type === "tool") {
178
+ const found = findTool(next, callId);
179
+ if (found !== undefined)
180
+ return found;
181
+ }
182
+ }
183
+ return undefined;
184
+ }
185
+ //# sourceMappingURL=operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/operations.ts"],"names":[],"mappings":"AAiGA,SAAS,MAAM,CACb,OAAsC,EACtC,KAAc,EACd,KAA2B;IAE3B,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AACD,MAAM,UAAU,gBAAgB,CAC9B,KAA+B,EAC/B,QAAQ,GAAe,EAAE,OAAO,EAAE,WAAW,EAAE,EAC/C,OAA2B;IAO3B,KAAK,UAAU,MAAM,CACnB,KAAQ,EACR,OAA8C;QAE9C,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,UAAU,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YACtD,IAAI,CAAC;gBACH,UAAU;oBACP,KAAqD,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC;YACzF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YACrC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,UAAU,GAAG;gBACX,OAAO,EAAE,QAAQ;gBACjB,SAAS,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ;gBACzD,KAAK;aACN,CAAC;YACF,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YACpC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,OAAsB,EACtB,IAAe,EACf,OAA2B;IAE3B,MAAM,IAAI,GAAG,CAAsB,MAAS,EAAK,EAAE,CACjD,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE;QAC9B,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE;QACzC,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;QACvC,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE;KACtC,CAAC,CAAC;IACL,MAAM,MAAM,GAAc;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,IAAI,WAAW;YACb,OAAO,OAAO,CAAC,WAAW,CAAC;QAC7B,CAAC;QACD,IAAI,MAAM;YACR,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,CAAC;QACD,IAAI,QAAQ;YACV,OAAO,OAAO,CAAC,QAAQ,CAAC;QAC1B,CAAC;QACD,IAAI,OAAO;YACT,OAAO,OAAO,CAAC,OAAO,CAAC;QACzB,CAAC;QACD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;QACxD,UAAU,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;QAC1D,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC9C,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QACpC,WAAW,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;KACnE,CAAC;IACF,MAAM,KAAK,GAAG,KAAK,EACjB,IAAe,EACf,GAAY,EACZ,OAAgE,EAChE,EAAE,CAAC,eAAe,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,gBAAgB,CAC3B,KAAK,EAAE,EAAE,WAAW,EAAE,GAAG,OAAO,EAAa,EAAE,EAAE,CAC/C,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,CAA2B,EACxF,SAAS,EACT,OAAO,CACR,CAAC;IACF,MAAM,KAAK,GAAG,CAAI,SAAoC,EAAiB,EAAE,CACvE,SAAS,KAAK,SAAS;QACrB,CAAC,CAAC,SAAS;QACX,CAAC,CAAE,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,CAAO,CAAC;IAC1E,MAAM,MAAM,GAAG,gBAAgB,CAC7B,KAAK,EAAE,OAAoB,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAClE,SAAS,EACT,OAAO,CACR,CAAC;IACF,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;QAC5B,OAAO,IAAI,CAAC;YACV,GAAG,MAAM;YACT,MAAM;YACN,KAAK,EAAE,CAAC,KAA2B,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;YACjE,WAAW,EAAE,CAAC,KAA6C,EAAE,EAAE,CAC7D,KAAK,CACH,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;aAC5D,CAAC,CACH;YACH,QAAQ,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,KAAK,CAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC7E,OAAO,EAAE,gBAAgB,CACvB,KAAK,EAAE,KAAmB,EAAE,EAAE,CAC5B,KAAK,CACH;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,KAAK,EAAE,KAAK,CAAC,SAAS;oBACtB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,cAAc,EAAE,KAAK,CAAC,cAAc;oBACpC,OAAO,EAAE,KAAK,CAAC,OAAO;iBACvB;aACF,EACD,SAAS,EACT,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CACM,EAChC,SAAS,EACT,OAAO,CACR;SACF,CAAC,CAAC;IACL,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE,CAClC,gBAAgB,CACd,KAAK,EAAE,KAA4C,EAAE,EAAE,CACrD,KAAK,CAAC;YACJ,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE;SAC/D,CAA2B,EAC9B,SAAS,EACT,OAAO,CACR,CAAC;QACJ,MAAM,UAAU,GAAG,CAAC,OAAqB,EAAE,GAAY,EAAE,EAAE,CACzD,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;QAMzC,KAAK,UAAU,SAAS,CACtB,KAAmB,EACnB,OAA+E;YAE/E,IAAI,OAAO,OAAO,KAAK,UAAU;gBAAE,OAAO,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,MAA0B,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3B,CAAC;gBAAC,OAAO,YAAY,EAAE,CAAC;oBACtB,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;gBAC5C,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YACrC,CAAC;YACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QACD,OAAO,IAAI,CAAC;YACV,GAAG,MAAM;YACT,MAAM;YACN,IAAI;YACJ,YAAY,EAAE,UAAU,CAAC,eAAe,CAAC;YACzC,eAAe,EAAE,UAAU,CAAC,mBAAmB,CAAC;YAChD,SAAS;YACT,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO;gBAC9B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;gBACvC,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACxC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;yBACjD,IAAI,CACH,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,EAC7D,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAC9B;yBACA,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;oBACxD,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;oBAC9B,OAAO,KAAK,CAAC,MAAM,CAAC;gBACtB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC;wBACH,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC3B,CAAC;oBAAC,OAAO,YAAY,EAAE,CAAC;wBACtB,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;oBAC5C,CAAC;oBACD,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;SACkB,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QACtB,OAAO,IAAI,CAAC;YACV,GAAG,MAAM;YACT,MAAM;YACN,IAAI;YACJ,YAAY,EAAE,CAAC,SAAiB,EAAE,EAAE,CAClC,KAAK,CACH,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;aACjF,CAAC,CACH;YACH,QAAQ,EAAE,gBAAgB,CACxB,KAAK,EAAE,KAA+C,EAAE,EAAE,CACxD,KAAK,CAAC;gBACJ,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;aAChF,CAAC,EACJ,EAAE,OAAO,EAAE,SAAS,EAAE,EACtB,OAAO,CACR;SACe,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,yFAAyF;AACzF,SAAS,QAAQ,CAAC,MAAqB,EAAE,MAAc;IACrD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QAChE,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACrC,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC;QACxC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * OpenTelemetry plumbing for hosts that run their own spans beside agent
3
+ * tracing: active-operation lookup, capture context, content bounds, and MCP
4
+ * enrichment. Agent tracing itself needs only the package root.
5
+ */
6
+ export { activeTraceOperation, withErrorContent } from "./adapters/otel.js";
7
+ export { withCapture } from "./capture.js";
8
+ export { boundedPrincipalId, contentAttribute, telemetryByteLength, truncateTelemetryText, CONTENT_ATTRIBUTE_LIMIT, } from "./adapters/serialization.js";
9
+ export { withoutDeclinedContent, type ResolvedContentOptions } from "./core/content-policy.js";
10
+ export { mcpLifecycle, type McpLifecycle, type McpUpdate } from "./core/mcp.js";
11
+ export { invocationName } from "./core/span-kinds.js";
12
+ export { USAGE_FIELDS } from "./core/attributes.js";
13
+ //# sourceMappingURL=otel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel.d.ts","sourceRoot":"","sources":["../../src/otel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,KAAK,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * OpenTelemetry plumbing for hosts that run their own spans beside agent
3
+ * tracing: active-operation lookup, capture context, content bounds, and MCP
4
+ * enrichment. Agent tracing itself needs only the package root.
5
+ */
6
+ export { activeTraceOperation, withErrorContent } from "./adapters/otel.js";
7
+ export { withCapture } from "./capture.js";
8
+ export { boundedPrincipalId, contentAttribute, telemetryByteLength, truncateTelemetryText, CONTENT_ATTRIBUTE_LIMIT, } from "./adapters/serialization.js";
9
+ export { withoutDeclinedContent } from "./core/content-policy.js";
10
+ export { mcpLifecycle } from "./core/mcp.js";
11
+ export { invocationName } from "./core/span-kinds.js";
12
+ export { USAGE_FIELDS } from "./core/attributes.js";
13
+ //# sourceMappingURL=otel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel.js","sourceRoot":"","sources":["../../src/otel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAA+B,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAqC,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,78 @@
1
1
  {
2
2
  "name": "@vercel/agent-runs",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "description": "Framework-neutral agent run tracing with OpenTelemetry and durable checkpoints.",
6
+ "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/vercel/eve.git",
10
+ "directory": "packages/tracing"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "src",
15
+ "!src/**/*.test.ts",
16
+ "NOTICE"
17
+ ],
18
+ "type": "module",
19
+ "sideEffects": false,
20
+ "exports": {
21
+ ".": {
22
+ "eve-source": "./src/index.ts",
23
+ "types": "./dist/src/index.d.ts",
24
+ "default": "./dist/src/index.js"
25
+ },
26
+ "./delegation": {
27
+ "eve-source": "./src/delegation.ts",
28
+ "types": "./dist/src/delegation.d.ts",
29
+ "default": "./dist/src/delegation.js"
30
+ },
31
+ "./otel": {
32
+ "eve-source": "./src/otel.ts",
33
+ "types": "./dist/src/otel.d.ts",
34
+ "default": "./dist/src/otel.js"
35
+ },
36
+ "./ai-sdk": {
37
+ "eve-source": "./src/ai-sdk.ts",
38
+ "types": "./dist/src/ai-sdk.d.ts",
39
+ "default": "./dist/src/ai-sdk.js"
40
+ },
41
+ "./package.json": "./package.json"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "devDependencies": {
47
+ "@ai-sdk/harness": "1.0.148",
48
+ "@ai-sdk/provider-utils": "^5.0.58",
49
+ "@opentelemetry/api": "^1.9.0",
50
+ "@opentelemetry/context-async-hooks": "2.6.1",
51
+ "@opentelemetry/sdk-trace-base": "2.6.1",
52
+ "@types/node": "24.13.3",
53
+ "ai": "^7.0.137",
54
+ "typescript": "7.0.2",
55
+ "vitest": "5.0.2",
56
+ "zod": "4.5.4"
57
+ },
58
+ "peerDependencies": {
59
+ "@opentelemetry/api": "^1.9.0",
60
+ "ai": "^7.0.137"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "ai": {
64
+ "optional": true
65
+ }
66
+ },
67
+ "engines": {
68
+ "node": ">=24"
69
+ },
70
+ "scripts": {
71
+ "clean": "rm -rf dist",
72
+ "build": "tsc -p tsconfig.build.json",
73
+ "build:types": "tsc -p tsconfig.build.json --emitDeclarationOnly",
74
+ "test:unit": "vitest run --config vitest.unit.config.ts",
75
+ "test:integration": "vitest run --config vitest.integration.config.ts",
76
+ "typecheck": "tsc -p tsconfig.json --noEmit"
77
+ }
6
78
  }
@@ -0,0 +1,113 @@
1
+ import { currentAgentHandoff, withAgentHandoff, type AgentHandoff } from "../core/delegation.js";
2
+ const HANDOFF_BYTES = 8192;
3
+
4
+ const HEADER = "x-agent-tracing";
5
+ const encoder = new TextEncoder();
6
+ function isHexId(value: unknown, length: number): boolean {
7
+ return (
8
+ typeof value === "string" &&
9
+ value.length === length &&
10
+ /^[a-f0-9]+$/u.test(value) &&
11
+ !/^0+$/u.test(value)
12
+ );
13
+ }
14
+
15
+ /** Bind only to a client whose destinations the application has approved. */
16
+ function agentTraceFetch(fetcher: typeof fetch, maxBytes: number): typeof fetch {
17
+ return (request, init) => {
18
+ const handoff = currentAgentHandoff();
19
+ if (handoff === undefined) return fetcher(request, init);
20
+ const encoded = JSON.stringify(handoff);
21
+ if (encoder.encode(encoded).length > maxBytes) return fetcher(request, init);
22
+ const headers = new Headers(
23
+ init?.headers ?? (request instanceof Request ? request.headers : undefined),
24
+ );
25
+ headers.set(HEADER, encoded);
26
+ return fetcher(request, { ...init, headers, redirect: "error" });
27
+ };
28
+ }
29
+
30
+ /** The host validates provenance; well-formed trace metadata is not authorization. */
31
+ function receiveAgentTrace<T>(
32
+ headers: Headers,
33
+ trusted: (handoff: AgentHandoff) => boolean,
34
+ execute: (handoff?: AgentHandoff) => T,
35
+ maxBytes: number,
36
+ ): T {
37
+ const encoded = headers.get(HEADER);
38
+ if (encoded === null || encoded.length > maxBytes || encoder.encode(encoded).length > maxBytes)
39
+ return execute();
40
+ let handoff: AgentHandoff;
41
+ const decode = (): AgentHandoff | undefined => {
42
+ try {
43
+ handoff = JSON.parse(encoded) as AgentHandoff;
44
+ if (
45
+ handoff === null ||
46
+ typeof handoff !== "object" ||
47
+ ![
48
+ handoff.conversationId,
49
+ handoff.parentRunId,
50
+ handoff.parentCallId,
51
+ handoff.agentName,
52
+ ].every((value) => typeof value === "string" && value.length > 0 && value.length <= 1024)
53
+ )
54
+ return undefined;
55
+ if (
56
+ !isHexId(handoff.caller.traceId, 32) ||
57
+ !isHexId(handoff.caller.spanId, 16) ||
58
+ ![0, 1].includes(handoff.caller.traceFlags)
59
+ )
60
+ return undefined;
61
+ if (
62
+ handoff.caller.tracestate !== undefined &&
63
+ (typeof handoff.caller.tracestate !== "string" || handoff.caller.tracestate.length > 512)
64
+ )
65
+ return undefined;
66
+ if (
67
+ ![handoff.capture.emit, handoff.capture.recordInputs, handoff.capture.recordOutputs].every(
68
+ (value) => typeof value === "boolean",
69
+ ) ||
70
+ !trusted(handoff)
71
+ )
72
+ return undefined;
73
+ return handoff;
74
+ } catch {
75
+ return undefined;
76
+ }
77
+ };
78
+ const decoded = decode();
79
+ if (decoded === undefined) return execute();
80
+ const accepted = {
81
+ ...decoded,
82
+ remote: true,
83
+ capture: {
84
+ emit: decoded.capture.emit && decoded.caller.traceFlags === 1,
85
+ recordInputs:
86
+ decoded.capture.emit && decoded.caller.traceFlags === 1 && decoded.capture.recordInputs,
87
+ recordOutputs:
88
+ decoded.capture.emit && decoded.caller.traceFlags === 1 && decoded.capture.recordOutputs,
89
+ },
90
+ };
91
+ return withAgentHandoff(accepted, () => execute(accepted));
92
+ }
93
+
94
+ /** Host boundary for durable dispatch and authenticated remote transport. */
95
+ export function createAgentDelegationTransport(
96
+ fetcher: typeof fetch = (request, init) => globalThis.fetch(request, init),
97
+ ) {
98
+ const maxBytes = HANDOFF_BYTES;
99
+ return {
100
+ fetch: agentTraceFetch(fetcher, maxBytes),
101
+ transport: (fetcher: typeof fetch) => agentTraceFetch(fetcher, maxBytes),
102
+ receive<T>(
103
+ headers: Headers,
104
+ trusted: (handoff: AgentHandoff) => boolean,
105
+ execute: (handoff?: AgentHandoff) => T,
106
+ ) {
107
+ return receiveAgentTrace(headers, trusted, execute, maxBytes);
108
+ },
109
+ resume<T>(stored: AgentHandoff, execute: (handoff: AgentHandoff) => T): T {
110
+ return withAgentHandoff(stored, () => execute(stored));
111
+ },
112
+ };
113
+ }
@@ -0,0 +1,44 @@
1
+ import type { ContentPart, Usage } from "../core/types.js";
2
+
3
+ interface Result {
4
+ usage: {
5
+ inputTokens?: number;
6
+ outputTokens?: number;
7
+ inputTokenDetails?: { cacheReadTokens?: number; cacheWriteTokens?: number };
8
+ };
9
+ content: readonly unknown[];
10
+ }
11
+
12
+ export function modelUsage(usage: Result["usage"]): Usage {
13
+ return Object.freeze({
14
+ inputTokens: usage.inputTokens,
15
+ outputTokens: usage.outputTokens,
16
+ inputTokenDetails: Object.freeze({
17
+ cacheReadTokens: usage.inputTokenDetails?.cacheReadTokens,
18
+ cacheWriteTokens: usage.inputTokenDetails?.cacheWriteTokens,
19
+ }),
20
+ });
21
+ }
22
+
23
+ export function modelContent(content: Result["content"]): readonly ContentPart[] {
24
+ return content.flatMap((part): ContentPart[] => {
25
+ if (part === null || typeof part !== "object" || !("type" in part)) return [];
26
+ const value = part as {
27
+ type: string;
28
+ text?: string;
29
+ toolCallId?: string;
30
+ toolName?: string;
31
+ input?: unknown;
32
+ output?: unknown;
33
+ error?: unknown;
34
+ };
35
+ if ((value.type === "text" || value.type === "reasoning") && typeof value.text === "string")
36
+ return [{ type: value.type, text: value.text }];
37
+ if (typeof value.toolCallId !== "string" || typeof value.toolName !== "string") return [];
38
+ const tool = { callId: value.toolCallId, toolName: value.toolName, input: value.input };
39
+ if (value.type === "tool-call") return [{ type: value.type, ...tool }];
40
+ if (value.type === "tool-result") return [{ type: value.type, ...tool, output: value.output }];
41
+ if (value.type === "tool-error") return [{ type: value.type, ...tool, error: value.error }];
42
+ return [];
43
+ });
44
+ }
@@ -0,0 +1,179 @@
1
+ import type { Telemetry } from "ai";
2
+ import type { AgentRun, TurnInput } from "../agent-run.js";
3
+ import type {
4
+ AttemptOperation,
5
+ ModelOperation,
6
+ ToolOperation,
7
+ TurnOperation,
8
+ } from "../operations.js";
9
+ import { modelContent, modelUsage } from "./ai-sdk-payload.js";
10
+
11
+ type Event<K extends keyof Telemetry> = Parameters<NonNullable<Telemetry[K]>>[0];
12
+
13
+ export interface AiSdkTelemetryOptions {
14
+ /** The turn a generation records. Called once per AI SDK call. */
15
+ readonly turn: TurnInput | ((call: { readonly callId: string }) => TurnInput);
16
+ }
17
+
18
+ interface Generation {
19
+ readonly startTimeMs: number;
20
+ turn?: Promise<TurnOperation>;
21
+ attempt?: Promise<AttemptOperation>;
22
+ model?: Promise<ModelOperation>;
23
+ readonly tools: Map<string, Promise<ToolOperation>>;
24
+ }
25
+
26
+ const ABANDONED = { outcome: "abandoned" } as const;
27
+
28
+ /**
29
+ * An AI SDK telemetry integration that records each generation as a turn.
30
+ * Pass it to `telemetry.integrations` of `generateText`, `streamText`, or an
31
+ * agent such as `HarnessAgent`.
32
+ */
33
+ export function aiSdkTelemetry(run: AgentRun, options: AiSdkTelemetryOptions): Telemetry {
34
+ const generations = new Map<string, Generation>();
35
+
36
+ function generation(callId: string): Generation {
37
+ let state = generations.get(callId);
38
+ if (state === undefined) {
39
+ state = { startTimeMs: Date.now(), tools: new Map() };
40
+ generations.set(callId, state);
41
+ }
42
+ return state;
43
+ }
44
+
45
+ async function closeStep(state: Generation, failure?: unknown) {
46
+ const result =
47
+ failure === undefined ? ABANDONED : { outcome: "abandoned", failed: true, error: failure };
48
+ await (await state.model)?.complete(result);
49
+ for (const tool of state.tools.values()) await (await tool).complete(result);
50
+ state.model = undefined;
51
+ state.tools.clear();
52
+ const attempt = await state.attempt;
53
+ state.attempt = undefined;
54
+ if (failure === undefined) await attempt?.complete();
55
+ else await attempt?.fail(failure);
56
+ }
57
+
58
+ async function finish(
59
+ callId: string,
60
+ end: (turn: TurnOperation) => Promise<void>,
61
+ failure?: unknown,
62
+ ) {
63
+ const state = generations.get(callId);
64
+ generations.delete(callId);
65
+ if (state === undefined) return;
66
+ await closeStep(state, failure);
67
+ const turn = await state.turn;
68
+ if (turn !== undefined) await end(turn);
69
+ }
70
+
71
+ return {
72
+ onStart(event: Event<"onStart">) {
73
+ generation(event.callId);
74
+ },
75
+ async onStepStart(event: Event<"onStepStart">) {
76
+ const state = generation(event.callId);
77
+ await closeStep(state);
78
+ state.turn ??= run.turn({
79
+ startTimeMs: state.startTimeMs,
80
+ ...(typeof options.turn === "function"
81
+ ? options.turn({ callId: event.callId })
82
+ : options.turn),
83
+ });
84
+ const turn = await state.turn;
85
+ state.attempt = turn.attempt({ stepIndex: event.stepNumber, attempt: 0 });
86
+ },
87
+ async onLanguageModelCallStart(event: Event<"onLanguageModelCallStart">) {
88
+ const attempt = await generations.get(event.callId)?.attempt;
89
+ if (attempt === undefined) return;
90
+ generations.get(event.callId)!.model = attempt.modelCall({
91
+ provider: event.provider,
92
+ modelId: event.modelId,
93
+ messages: event.messages,
94
+ instructions: event.instructions,
95
+ tools: event.tools,
96
+ });
97
+ },
98
+ async executeLanguageModelCall({ callId, execute }) {
99
+ const model = await generations.get(callId)?.model;
100
+ if (model === undefined || model.finished) return execute();
101
+ try {
102
+ return await model.run(execute);
103
+ } catch (error) {
104
+ await model.fail(error);
105
+ throw error;
106
+ }
107
+ },
108
+ async onLanguageModelCallEnd(event: Event<"onLanguageModelCallEnd">) {
109
+ const state = generations.get(event.callId);
110
+ const model = await state?.model;
111
+ if (state === undefined || model === undefined) return;
112
+ state.model = undefined;
113
+ await model.complete({
114
+ outcome: "completed",
115
+ result: {
116
+ finishReason: event.finishReason,
117
+ usage: modelUsage(event.usage),
118
+ responseId: event.responseId,
119
+ responseModelId: event.modelId,
120
+ content: modelContent(event.content),
121
+ },
122
+ });
123
+ },
124
+ async onToolExecutionStart(event: Event<"onToolExecutionStart">) {
125
+ const state = generations.get(event.callId);
126
+ const attempt = await state?.attempt;
127
+ if (state === undefined || attempt === undefined) return;
128
+ const call = event.toolCall;
129
+ state.tools.set(
130
+ call.toolCallId,
131
+ attempt.tool({ callId: call.toolCallId, name: call.toolName, arguments: call.input }),
132
+ );
133
+ },
134
+ async executeTool({ callId, toolCallId, execute }) {
135
+ const tool = await generations.get(callId)?.tools.get(toolCallId);
136
+ return tool === undefined || tool.finished ? execute() : tool.run(execute);
137
+ },
138
+ async onToolExecutionEnd(event: Event<"onToolExecutionEnd">) {
139
+ const state = generations.get(event.callId);
140
+ const tool = await state?.tools.get(event.toolCall.toolCallId);
141
+ if (state === undefined || tool === undefined) return;
142
+ state.tools.delete(event.toolCall.toolCallId);
143
+ const output = event.toolOutput;
144
+ const completion =
145
+ output.type === "tool-error"
146
+ ? {
147
+ outcome: "failed",
148
+ errorType: output.error instanceof Error ? output.error.name : "tool_error",
149
+ error: output.error,
150
+ }
151
+ : { outcome: "completed", output: "output" in output ? output.output : undefined };
152
+ await tool.complete(completion);
153
+ },
154
+ async onStepEnd(event: Event<"onStepEnd">) {
155
+ const state = generations.get(event.callId);
156
+ if (state !== undefined) await closeStep(state);
157
+ },
158
+ async onEnd(event: Event<"onEnd">) {
159
+ await finish(event.callId, (turn) =>
160
+ turn.complete({
161
+ outcome: "completed",
162
+ usage: "totalUsage" in event ? modelUsage(event.totalUsage) : undefined,
163
+ }),
164
+ );
165
+ },
166
+ async onAbort(event: Event<"onAbort">) {
167
+ await finish(event.callId, (turn) => turn.complete({ outcome: "cancelled" }));
168
+ },
169
+ async onError(value: unknown) {
170
+ // Some agents report the bare error; it then belongs to every open call.
171
+ const { callId, error } =
172
+ value !== null && typeof value === "object" && "callId" in value && "error" in value
173
+ ? (value as { callId: string; error: unknown })
174
+ : { callId: undefined, error: value };
175
+ for (const id of callId === undefined ? [...generations.keys()] : [callId])
176
+ await finish(id, (turn) => turn.fail(error), error);
177
+ },
178
+ };
179
+ }