@mastra/client-js 1.20.1-alpha.0 → 1.21.0-alpha.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/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from './tools.js';
4
4
  export type { ChannelPlatformInfo, ChannelInstallationInfo, ChannelConnectOAuth, ChannelConnectDeepLink, ChannelConnectImmediate, ChannelConnectResult, } from './resources/channels.js';
5
5
  export type { AgentCardSignatureKeyProviderInput, AgentCardVerificationKey, GetAgentCardOptions, VerifyAgentCardSignatureOptions, } from './resources/a2a.js';
6
6
  export { RequestContext } from '@mastra/core/request-context';
7
+ export type { ObservabilityCollector } from './observability/types.js';
7
8
  export type { UIMessageWithMetadata } from '@mastra/core/agent';
8
9
  export type { Body, Client, ClientMethod, ClientPath, ClientRequest, ClientResponse, ClientResponseKind, ClientRoute, PathParams, QueryParams, RouteKey, RouteRequest, RouteResponse, RouteResponseType, RouteTypes, } from './route-types.generated.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EACnB,+BAA+B,GAChC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EACV,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,UAAU,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,UAAU,GACX,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EACnB,+BAA+B,GAChC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EACV,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,UAAU,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,UAAU,GACX,MAAM,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -10,6 +10,210 @@ import canonicalize from 'canonicalize';
10
10
  import { base64url, decodeProtectedHeader, compactVerify, importX509, importSPKI, importJWK } from 'jose';
11
11
 
12
12
  // src/resources/agent.ts
13
+
14
+ // src/observability/collector.ts
15
+ var TRACEPARENT_RE = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
16
+ var ZERO_TRACE_ID = "00000000000000000000000000000000";
17
+ var ZERO_SPAN_ID = "0000000000000000";
18
+ var LEVEL_TO_SEVERITY_NUMBER = {
19
+ debug: 5,
20
+ info: 9,
21
+ warn: 13,
22
+ error: 17,
23
+ fatal: 21
24
+ };
25
+ var LEVEL_TO_SEVERITY_TEXT = {
26
+ debug: "DEBUG",
27
+ info: "INFO",
28
+ warn: "WARN",
29
+ error: "ERROR",
30
+ fatal: "FATAL"
31
+ };
32
+ function nowNs() {
33
+ return BigInt(Date.now()) * 1000000n;
34
+ }
35
+ function isValidTraceparentMatch(parsed) {
36
+ const version = parsed[1];
37
+ const traceId = parsed[2];
38
+ const spanId = parsed[3];
39
+ return version !== "ff" && traceId !== ZERO_TRACE_ID && spanId !== ZERO_SPAN_ID;
40
+ }
41
+ function randomSpanIdHex() {
42
+ if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.getRandomValues) {
43
+ const bytes = new Uint8Array(8);
44
+ globalThis.crypto.getRandomValues(bytes);
45
+ let out2 = "";
46
+ for (const b of bytes) out2 += b.toString(16).padStart(2, "0");
47
+ return out2;
48
+ }
49
+ let out = "";
50
+ for (let i = 0; i < 16; i++) out += Math.floor(Math.random() * 16).toString(16);
51
+ return out;
52
+ }
53
+ function attributesToOtlp(attrs) {
54
+ const out = [];
55
+ for (const [key, raw] of Object.entries(attrs)) {
56
+ if (raw === void 0 || raw === null) continue;
57
+ if (typeof raw === "string") {
58
+ out.push({ key, value: { stringValue: raw } });
59
+ } else if (typeof raw === "boolean") {
60
+ out.push({ key, value: { boolValue: raw } });
61
+ } else if (typeof raw === "number") {
62
+ if (Number.isInteger(raw)) {
63
+ out.push({ key, value: { intValue: raw } });
64
+ } else {
65
+ out.push({ key, value: { doubleValue: raw } });
66
+ }
67
+ } else {
68
+ try {
69
+ out.push({ key, value: { stringValue: JSON.stringify(raw) } });
70
+ } catch {
71
+ }
72
+ }
73
+ }
74
+ return out;
75
+ }
76
+ var ObservabilityCollectorImpl = class {
77
+ parentContext;
78
+ #traceId;
79
+ #rootSpanId;
80
+ #spans = [];
81
+ #logs = [];
82
+ #spanStack = [];
83
+ /** Wall-clock execution timing, captured by withContext. */
84
+ #executionStartMs;
85
+ #executionEndMs;
86
+ #flushed = false;
87
+ constructor(parentContext) {
88
+ this.parentContext = parentContext;
89
+ const parsed = TRACEPARENT_RE.exec(parentContext.traceparent);
90
+ if (!parsed || !isValidTraceparentMatch(parsed)) {
91
+ this.#traceId = ZERO_TRACE_ID;
92
+ this.#rootSpanId = ZERO_SPAN_ID;
93
+ return;
94
+ }
95
+ this.#traceId = parsed[2];
96
+ this.#rootSpanId = parsed[3];
97
+ }
98
+ async withContext(fn) {
99
+ const executionStartMs = this.#executionStartMs ?? Date.now();
100
+ this.#executionStartMs = executionStartMs;
101
+ this.#spanStack.push(this.#rootSpanId);
102
+ try {
103
+ return await fn();
104
+ } finally {
105
+ this.#spanStack.pop();
106
+ this.#executionEndMs = Date.now();
107
+ }
108
+ }
109
+ async span(name, fn, attributes) {
110
+ const spanId = randomSpanIdHex();
111
+ const spanStack = this.#getSpanStack();
112
+ const parentSpanId = spanStack[spanStack.length - 1] ?? this.#rootSpanId;
113
+ const startTimeNs = nowNs();
114
+ spanStack.push(spanId);
115
+ let statusCode = 1;
116
+ let statusMessage;
117
+ try {
118
+ return await fn();
119
+ } catch (err) {
120
+ statusCode = 2;
121
+ statusMessage = err instanceof Error ? err.message : String(err);
122
+ throw err;
123
+ } finally {
124
+ spanStack.pop();
125
+ this.#spans.push({
126
+ spanId,
127
+ parentSpanId,
128
+ traceId: this.#traceId,
129
+ name,
130
+ startTimeNs,
131
+ endTimeNs: nowNs(),
132
+ attributes: attributes ?? {},
133
+ statusCode,
134
+ statusMessage
135
+ });
136
+ }
137
+ }
138
+ log(level, message, data) {
139
+ const spanStack = this.#getSpanStack();
140
+ const spanId = spanStack[spanStack.length - 1] ?? this.#rootSpanId;
141
+ this.#logs.push({
142
+ spanId,
143
+ traceId: this.#traceId,
144
+ timestampNs: nowNs(),
145
+ level,
146
+ message,
147
+ data
148
+ });
149
+ }
150
+ #getSpanStack() {
151
+ return this.#spanStack;
152
+ }
153
+ flush() {
154
+ if (this.#flushed) {
155
+ return {};
156
+ }
157
+ this.#flushed = true;
158
+ const payload = {};
159
+ if (this.#executionStartMs !== void 0 && this.#executionEndMs !== void 0) {
160
+ payload.executionDurationMs = this.#executionEndMs - this.#executionStartMs;
161
+ }
162
+ if (this.#spans.length > 0) {
163
+ payload.spans = {
164
+ resourceSpans: [
165
+ {
166
+ scopeSpans: [
167
+ {
168
+ scope: { name: "@mastra/client-js/observability", version: "1" },
169
+ spans: this.#spans.map((s) => ({
170
+ traceId: s.traceId,
171
+ spanId: s.spanId,
172
+ parentSpanId: s.parentSpanId,
173
+ name: s.name,
174
+ // OTLP/JSON allows nanosecond timestamps as decimal
175
+ // strings to avoid JS number precision loss for
176
+ // uint64. Use string form.
177
+ startTimeUnixNano: s.startTimeNs.toString(),
178
+ endTimeUnixNano: s.endTimeNs.toString(),
179
+ attributes: attributesToOtlp(s.attributes),
180
+ status: { code: s.statusCode, ...s.statusMessage ? { message: s.statusMessage } : {} },
181
+ // OTLP requires `kind`; default to INTERNAL = 1.
182
+ kind: 1
183
+ }))
184
+ }
185
+ ]
186
+ }
187
+ ]
188
+ };
189
+ }
190
+ if (this.#logs.length > 0) {
191
+ payload.logs = {
192
+ resourceLogs: [
193
+ {
194
+ scopeLogs: [
195
+ {
196
+ scope: { name: "@mastra/client-js/observability", version: "1" },
197
+ logRecords: this.#logs.map((l) => ({
198
+ timeUnixNano: l.timestampNs.toString(),
199
+ observedTimeUnixNano: l.timestampNs.toString(),
200
+ severityNumber: LEVEL_TO_SEVERITY_NUMBER[l.level],
201
+ severityText: LEVEL_TO_SEVERITY_TEXT[l.level],
202
+ body: { stringValue: l.message },
203
+ traceId: l.traceId,
204
+ spanId: l.spanId,
205
+ attributes: l.data ? attributesToOtlp(l.data) : []
206
+ }))
207
+ }
208
+ ]
209
+ }
210
+ ]
211
+ };
212
+ }
213
+ return payload;
214
+ }
215
+ };
216
+ var createObservabilityCollector = (parentContext) => new ObservabilityCollectorImpl(parentContext);
13
217
  function normalizeRoutePath(path) {
14
218
  let normalized = path.trim();
15
219
  if (normalized.includes("..") || normalized.includes("?") || normalized.includes("#")) {
@@ -290,6 +494,49 @@ var BaseResource = class {
290
494
  };
291
495
 
292
496
  // src/resources/agent.ts
497
+ var noopClientToolObserve = {
498
+ async span(_name, fn) {
499
+ return fn();
500
+ },
501
+ log() {
502
+ }
503
+ };
504
+ function getClientToolObservabilityContext(toolCall) {
505
+ const candidate = toolCall;
506
+ return candidate?.payload?.observability ?? candidate?.observability;
507
+ }
508
+ async function executeClientToolWithObservability({
509
+ clientTool,
510
+ args,
511
+ toolName,
512
+ parentContext,
513
+ executeContext
514
+ }) {
515
+ const collector = parentContext ? createObservabilityCollector(parentContext) : void 0;
516
+ const observe = collector ? {
517
+ span: collector.span.bind(collector),
518
+ log: collector.log.bind(collector)
519
+ } : noopClientToolObserve;
520
+ const runExecute = () => clientTool.execute(args, {
521
+ ...executeContext,
522
+ observe
523
+ });
524
+ const result = collector ? await collector.withContext(runExecute) : await runExecute();
525
+ if (!parentContext) {
526
+ return { result };
527
+ }
528
+ const flushed = collector?.flush();
529
+ if (flushed) {
530
+ flushed.toolName = toolName;
531
+ }
532
+ return {
533
+ result,
534
+ observability: {
535
+ parentContext,
536
+ ...flushed ? { payload: flushed } : {}
537
+ }
538
+ };
539
+ }
293
540
  async function executeToolCallAndRespond({
294
541
  response,
295
542
  params,
@@ -307,31 +554,39 @@ async function executeToolCallAndRespond({
307
554
  for (const toolCall of toolCalls) {
308
555
  const clientTool = params.clientTools?.[toolCall.payload.toolName];
309
556
  if (clientTool && clientTool.execute) {
310
- const result = await clientTool.execute(toolCall?.payload.args, {
311
- requestContext,
312
- tracingContext: { currentSpan: void 0 },
313
- agent: {
314
- agentId,
315
- messages: response.messages,
316
- toolCallId: toolCall?.payload.toolCallId,
317
- suspend: async () => {
318
- },
319
- threadId,
320
- resourceId
557
+ const { result, observability } = await executeClientToolWithObservability({
558
+ clientTool,
559
+ args: toolCall?.payload.args,
560
+ toolName: toolCall.payload.toolName,
561
+ parentContext: getClientToolObservabilityContext(toolCall),
562
+ executeContext: {
563
+ requestContext,
564
+ tracingContext: { currentSpan: void 0 },
565
+ agent: {
566
+ agentId,
567
+ messages: response.messages,
568
+ toolCallId: toolCall?.payload.toolCallId,
569
+ suspend: async () => {
570
+ },
571
+ threadId,
572
+ resourceId
573
+ }
321
574
  }
322
575
  });
576
+ const toolResultContent = {
577
+ type: "tool-result",
578
+ toolCallId: toolCall.payload.toolCallId,
579
+ toolName: toolCall.payload.toolName,
580
+ result
581
+ };
582
+ if (observability) {
583
+ toolResultContent.__mastraObservability = observability;
584
+ }
323
585
  const newMessages = [
324
586
  ...response.response.messages || [],
325
587
  {
326
588
  role: "tool",
327
- content: [
328
- {
329
- type: "tool-result",
330
- toolCallId: toolCall.payload.toolCallId,
331
- toolName: toolCall.payload.toolName,
332
- result
333
- }
334
- ]
589
+ content: [toolResultContent]
335
590
  }
336
591
  ];
337
592
  const updatedMessages = threadId ? newMessages : [...Array.isArray(params.messages) ? params.messages : [], ...newMessages];
@@ -654,17 +909,23 @@ var Agent = class extends BaseResource {
654
909
  for (const toolCall of toolCalls) {
655
910
  const clientTool = params.clientTools?.[toolCall.toolName];
656
911
  if (clientTool && clientTool.execute) {
657
- const result = await clientTool.execute(toolCall?.args, {
658
- requestContext,
659
- tracingContext: { currentSpan: void 0 },
660
- agent: {
661
- agentId: this.agentId,
662
- messages: response.messages,
663
- toolCallId: toolCall?.toolCallId,
664
- suspend: async () => {
665
- },
666
- threadId,
667
- resourceId
912
+ const { result, observability } = await executeClientToolWithObservability({
913
+ clientTool,
914
+ args: toolCall?.args,
915
+ toolName: toolCall.toolName,
916
+ parentContext: getClientToolObservabilityContext(toolCall),
917
+ executeContext: {
918
+ requestContext,
919
+ tracingContext: { currentSpan: void 0 },
920
+ agent: {
921
+ agentId: this.agentId,
922
+ messages: response.messages,
923
+ toolCallId: toolCall?.toolCallId,
924
+ suspend: async () => {
925
+ },
926
+ threadId,
927
+ resourceId
928
+ }
668
929
  }
669
930
  });
670
931
  const updatedMessages = [
@@ -676,7 +937,8 @@ var Agent = class extends BaseResource {
676
937
  type: "tool-result",
677
938
  toolCallId: toolCall.toolCallId,
678
939
  toolName: toolCall.toolName,
679
- result
940
+ result,
941
+ ...observability ? { __mastraObservability: observability } : {}
680
942
  }
681
943
  ]
682
944
  }
@@ -876,14 +1138,17 @@ var Agent = class extends BaseResource {
876
1138
  text: "",
877
1139
  step,
878
1140
  toolName: value.toolName,
879
- index: message.toolInvocations.length
1141
+ index: message.toolInvocations.length,
1142
+ observability: getClientToolObservabilityContext(value)
880
1143
  };
1144
+ const observability = getClientToolObservabilityContext(value);
881
1145
  const invocation = {
882
1146
  state: "partial-call",
883
1147
  step,
884
1148
  toolCallId: value.toolCallId,
885
1149
  toolName: value.toolName,
886
- args: void 0
1150
+ args: void 0,
1151
+ ...observability ? { observability } : {}
887
1152
  };
888
1153
  message.toolInvocations.push(invocation);
889
1154
  updateToolInvocationPart(value.toolCallId, invocation);
@@ -898,7 +1163,8 @@ var Agent = class extends BaseResource {
898
1163
  step: partialToolCall.step,
899
1164
  toolCallId: value.toolCallId,
900
1165
  toolName: partialToolCall.toolName,
901
- args: partialArgs
1166
+ args: partialArgs,
1167
+ ...partialToolCall.observability ? { observability: partialToolCall.observability } : {}
902
1168
  };
903
1169
  message.toolInvocations[partialToolCall.index] = invocation;
904
1170
  updateToolInvocationPart(value.toolCallId, invocation);
@@ -1200,14 +1466,17 @@ var Agent = class extends BaseResource {
1200
1466
  text: "",
1201
1467
  step,
1202
1468
  toolName: chunk.payload.toolName,
1203
- index: message.toolInvocations.length
1469
+ index: message.toolInvocations.length,
1470
+ observability: getClientToolObservabilityContext(chunk)
1204
1471
  };
1472
+ const observability = getClientToolObservabilityContext(chunk);
1205
1473
  const invocation = {
1206
1474
  state: "partial-call",
1207
1475
  step,
1208
1476
  toolCallId: chunk.payload.toolCallId,
1209
1477
  toolName: chunk.payload.toolName,
1210
- args: chunk.payload.args
1478
+ args: chunk.payload.args,
1479
+ ...observability ? { observability } : {}
1211
1480
  };
1212
1481
  message.toolInvocations.push(invocation);
1213
1482
  updateToolInvocationPart(chunk.payload.toolCallId, invocation);
@@ -1223,7 +1492,8 @@ var Agent = class extends BaseResource {
1223
1492
  step: partialToolCall.step,
1224
1493
  toolCallId: chunk.payload.toolCallId,
1225
1494
  toolName: partialToolCall.toolName,
1226
- args: partialArgs
1495
+ args: partialArgs,
1496
+ ...partialToolCall.observability ? { observability: partialToolCall.observability } : {}
1227
1497
  };
1228
1498
  message.toolInvocations[partialToolCall.index] = invocation;
1229
1499
  updateToolInvocationPart(chunk.payload.toolCallId, invocation);
@@ -1342,25 +1612,37 @@ var Agent = class extends BaseResource {
1342
1612
  if (finishReason === "tool-calls") {
1343
1613
  const toolCall = [...message?.parts ?? []].reverse().find((part) => part.type === "tool-invocation")?.toolInvocation;
1344
1614
  if (toolCall) {
1345
- toolCalls.push(toolCall);
1615
+ const toolInvocationWithMetadata = message?.toolInvocations?.find(
1616
+ (invocation) => invocation.toolCallId === toolCall.toolCallId
1617
+ );
1618
+ toolCalls.push({
1619
+ ...toolInvocationWithMetadata,
1620
+ ...toolCall,
1621
+ ...!getClientToolObservabilityContext(toolCall) && toolInvocationWithMetadata ? { observability: getClientToolObservabilityContext(toolInvocationWithMetadata) } : {}
1622
+ });
1346
1623
  }
1347
1624
  let shouldExecuteClientTool = false;
1348
1625
  for (const toolCall2 of toolCalls) {
1349
1626
  const clientTool = processedParams.clientTools?.[toolCall2.toolName];
1350
1627
  if (clientTool && clientTool.execute) {
1351
1628
  shouldExecuteClientTool = true;
1352
- const result = await clientTool.execute(toolCall2?.args, {
1353
- requestContext: processedParams.requestContext,
1354
- // TODO: Pass proper tracing context when client-js supports tracing
1355
- tracingContext: { currentSpan: void 0 },
1356
- agent: {
1357
- agentId: this.agentId,
1358
- messages: response.messages,
1359
- toolCallId: toolCall2?.toolCallId,
1360
- suspend: async () => {
1361
- },
1362
- threadId,
1363
- resourceId
1629
+ const { result, observability } = await executeClientToolWithObservability({
1630
+ clientTool,
1631
+ args: toolCall2?.args,
1632
+ toolName: toolCall2.toolName,
1633
+ parentContext: getClientToolObservabilityContext(toolCall2),
1634
+ executeContext: {
1635
+ requestContext: processedParams.requestContext,
1636
+ tracingContext: { currentSpan: void 0 },
1637
+ agent: {
1638
+ agentId: this.agentId,
1639
+ messages: response.messages,
1640
+ toolCallId: toolCall2?.toolCallId,
1641
+ suspend: async () => {
1642
+ },
1643
+ threadId,
1644
+ resourceId
1645
+ }
1364
1646
  }
1365
1647
  });
1366
1648
  const lastMessageRaw = messages[messages.length - 1];
@@ -1372,7 +1654,8 @@ var Agent = class extends BaseResource {
1372
1654
  toolInvocationPart.toolInvocation = {
1373
1655
  ...toolInvocationPart.toolInvocation,
1374
1656
  state: "result",
1375
- result
1657
+ result,
1658
+ ...observability ? { __mastraObservability: observability } : {}
1376
1659
  };
1377
1660
  }
1378
1661
  const toolInvocation = lastMessage?.toolInvocations?.find(
@@ -1381,6 +1664,9 @@ var Agent = class extends BaseResource {
1381
1664
  if (toolInvocation) {
1382
1665
  toolInvocation.state = "result";
1383
1666
  toolInvocation.result = result;
1667
+ if (observability) {
1668
+ toolInvocation.__mastraObservability = observability;
1669
+ }
1384
1670
  }
1385
1671
  const newMessages = lastMessage != null ? [...messages.filter((m) => m.id !== lastMessage.id), lastMessage] : [...messages];
1386
1672
  const updatedMessages = threadId ? newMessages : [...Array.isArray(processedParams.messages) ? processedParams.messages : [], ...newMessages];
@@ -1815,23 +2101,35 @@ var Agent = class extends BaseResource {
1815
2101
  if (finishReason === "tool-calls") {
1816
2102
  const toolCall = [...message?.parts ?? []].reverse().find((part) => part.type === "tool-invocation")?.toolInvocation;
1817
2103
  if (toolCall) {
1818
- toolCalls.push(toolCall);
2104
+ const toolInvocationWithMetadata = message?.toolInvocations?.find(
2105
+ (invocation) => invocation.toolCallId === toolCall.toolCallId
2106
+ );
2107
+ toolCalls.push({
2108
+ ...toolInvocationWithMetadata,
2109
+ ...toolCall,
2110
+ ...!getClientToolObservabilityContext(toolCall) && toolInvocationWithMetadata ? { observability: getClientToolObservabilityContext(toolInvocationWithMetadata) } : {}
2111
+ });
1819
2112
  }
1820
2113
  for (const toolCall2 of toolCalls) {
1821
2114
  const clientTool = processedParams.clientTools?.[toolCall2.toolName];
1822
2115
  if (clientTool && clientTool.execute) {
1823
- const result = await clientTool.execute(toolCall2?.args, {
1824
- requestContext: processedParams.requestContext,
1825
- // TODO: Pass proper tracing context when client-js supports tracing
1826
- tracingContext: { currentSpan: void 0 },
1827
- agent: {
1828
- agentId: this.agentId,
1829
- messages: response.messages,
1830
- toolCallId: toolCall2?.toolCallId,
1831
- suspend: async () => {
1832
- },
1833
- threadId,
1834
- resourceId
2116
+ const { result, observability } = await executeClientToolWithObservability({
2117
+ clientTool,
2118
+ args: toolCall2?.args,
2119
+ toolName: toolCall2.toolName,
2120
+ parentContext: getClientToolObservabilityContext(toolCall2),
2121
+ executeContext: {
2122
+ requestContext: processedParams.requestContext,
2123
+ tracingContext: { currentSpan: void 0 },
2124
+ agent: {
2125
+ agentId: this.agentId,
2126
+ messages: response.messages,
2127
+ toolCallId: toolCall2?.toolCallId,
2128
+ suspend: async () => {
2129
+ },
2130
+ threadId,
2131
+ resourceId
2132
+ }
1835
2133
  }
1836
2134
  });
1837
2135
  const lastMessage = JSON.parse(JSON.stringify(messages[messages.length - 1]));
@@ -1842,7 +2140,8 @@ var Agent = class extends BaseResource {
1842
2140
  toolInvocationPart.toolInvocation = {
1843
2141
  ...toolInvocationPart.toolInvocation,
1844
2142
  state: "result",
1845
- result
2143
+ result,
2144
+ ...observability ? { __mastraObservability: observability } : {}
1846
2145
  };
1847
2146
  }
1848
2147
  const toolInvocation = lastMessage?.toolInvocations?.find(
@@ -1851,6 +2150,9 @@ var Agent = class extends BaseResource {
1851
2150
  if (toolInvocation) {
1852
2151
  toolInvocation.state = "result";
1853
2152
  toolInvocation.result = result;
2153
+ if (observability) {
2154
+ toolInvocation.__mastraObservability = observability;
2155
+ }
1854
2156
  }
1855
2157
  const writer = writable.getWriter();
1856
2158
  try {