assistant-cloud 0.2.1 → 0.2.3

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 (91) hide show
  1. package/README.md +24 -8
  2. package/dist/AssistantCloud.d.ts +16 -19
  3. package/dist/AssistantCloud.d.ts.map +1 -1
  4. package/dist/AssistantCloud.js +7 -2
  5. package/dist/AssistantCloud.js.map +1 -1
  6. package/dist/AssistantCloudAPI.d.ts +74 -72
  7. package/dist/AssistantCloudAPI.d.ts.map +1 -1
  8. package/dist/AssistantCloudAPI.js.map +1 -1
  9. package/dist/AssistantCloudAuthStrategy.d.ts +29 -32
  10. package/dist/AssistantCloudAuthStrategy.d.ts.map +1 -1
  11. package/dist/AssistantCloudAuthTokens.d.ts +7 -9
  12. package/dist/AssistantCloudAuthTokens.d.ts.map +1 -1
  13. package/dist/AssistantCloudEvents.d.ts +35 -29
  14. package/dist/AssistantCloudEvents.d.ts.map +1 -1
  15. package/dist/AssistantCloudEvents.js +66 -17
  16. package/dist/AssistantCloudEvents.js.map +1 -1
  17. package/dist/AssistantCloudFiles.d.ts +27 -29
  18. package/dist/AssistantCloudFiles.d.ts.map +1 -1
  19. package/dist/AssistantCloudProjectThreadMessages.d.ts +11 -13
  20. package/dist/AssistantCloudProjectThreadMessages.d.ts.map +1 -1
  21. package/dist/AssistantCloudProjectThreads.d.ts +12 -14
  22. package/dist/AssistantCloudProjectThreads.d.ts.map +1 -1
  23. package/dist/AssistantCloudProjects.d.ts +4 -7
  24. package/dist/AssistantCloudProjects.d.ts.map +1 -1
  25. package/dist/AssistantCloudRuns.d.ts +67 -56
  26. package/dist/AssistantCloudRuns.d.ts.map +1 -1
  27. package/dist/AssistantCloudRuns.js +9 -4
  28. package/dist/AssistantCloudRuns.js.map +1 -1
  29. package/dist/AssistantCloudScores.d.ts +20 -23
  30. package/dist/AssistantCloudScores.d.ts.map +1 -1
  31. package/dist/AssistantCloudThreadMessages.d.ts +41 -38
  32. package/dist/AssistantCloudThreadMessages.d.ts.map +1 -1
  33. package/dist/AssistantCloudThreadMessages.js +16 -4
  34. package/dist/AssistantCloudThreadMessages.js.map +1 -1
  35. package/dist/AssistantCloudThreads.d.ts +42 -44
  36. package/dist/AssistantCloudThreads.d.ts.map +1 -1
  37. package/dist/CloudEngagementReporter.d.ts +56 -58
  38. package/dist/CloudEngagementReporter.d.ts.map +1 -1
  39. package/dist/CloudEngagementReporter.js +4 -1
  40. package/dist/CloudEngagementReporter.js.map +1 -1
  41. package/dist/CloudMessagePersistence.d.ts +56 -58
  42. package/dist/CloudMessagePersistence.d.ts.map +1 -1
  43. package/dist/CloudMessagePersistence.js +3 -0
  44. package/dist/CloudMessagePersistence.js.map +1 -1
  45. package/dist/CloudRunReporter.d.ts +10 -13
  46. package/dist/CloudRunReporter.d.ts.map +1 -1
  47. package/dist/CloudRunReporter.js +13 -4
  48. package/dist/CloudRunReporter.js.map +1 -1
  49. package/dist/FormattedCloudPersistence.d.ts +36 -39
  50. package/dist/FormattedCloudPersistence.d.ts.map +1 -1
  51. package/dist/ai-sdk/index.d.ts +14 -17
  52. package/dist/ai-sdk/index.d.ts.map +1 -1
  53. package/dist/cloudResponse.d.ts +14 -17
  54. package/dist/cloudResponse.d.ts.map +1 -1
  55. package/dist/generateThreadTitle.d.ts +9 -12
  56. package/dist/generateThreadTitle.d.ts.map +1 -1
  57. package/dist/index.d.ts +18 -17
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/instrumentMcpSampling.d.ts +36 -39
  60. package/dist/instrumentMcpSampling.d.ts.map +1 -1
  61. package/dist/runTelemetry.d.ts +101 -94
  62. package/dist/runTelemetry.d.ts.map +1 -1
  63. package/dist/runTelemetry.js +57 -15
  64. package/dist/runTelemetry.js.map +1 -1
  65. package/dist/telemetry/index.d.ts +20 -23
  66. package/dist/telemetry/index.d.ts.map +1 -1
  67. package/dist/version.d.ts +1 -4
  68. package/dist/version.d.ts.map +1 -1
  69. package/dist/version.js +1 -1
  70. package/package.json +10 -9
  71. package/src/AssistantCloud.ts +17 -2
  72. package/src/AssistantCloudAPI.ts +4 -0
  73. package/src/AssistantCloudEvents.test.ts +157 -0
  74. package/src/AssistantCloudEvents.ts +82 -20
  75. package/src/AssistantCloudRuns.ts +35 -5
  76. package/src/AssistantCloudThreadMessages.test.ts +53 -2
  77. package/src/AssistantCloudThreadMessages.ts +34 -2
  78. package/src/BackendTranscriptCopy.test.ts +79 -0
  79. package/src/CloudEngagementReporter.ts +9 -3
  80. package/src/CloudMessagePersistence.ts +4 -0
  81. package/src/CloudRunReporter.ts +16 -4
  82. package/src/ai-sdk/index.test.ts +2 -2
  83. package/src/runTelemetry.test.ts +226 -2
  84. package/src/runTelemetry.ts +121 -17
  85. package/src/tests/AssistantCloud.test.ts +22 -0
  86. package/src/tests/AssistantCloudRuns.test.ts +28 -0
  87. package/src/tests/CloudEngagementReporter.test.ts +45 -0
  88. package/src/tests/CloudRunReporter.test.ts +49 -2
  89. package/dist/tests/setup.d.ts +0 -1
  90. package/dist/tests/setup.js +0 -7
  91. package/dist/tests/setup.js.map +0 -1
@@ -1,4 +1,3 @@
1
- //#region src/instrumentMcpSampling.d.ts
2
1
  /**
3
2
  * MCP sampling instrumentation utility.
4
3
  *
@@ -6,40 +5,40 @@
6
5
  * (sampling/createMessage requests) made during tool execution.
7
6
  * The captured data can be reported as child generation spans.
8
7
  */
9
- type SamplingCallData = {
10
- model_id?: string;
11
- input_tokens?: number;
12
- output_tokens?: number;
13
- reasoning_tokens?: number;
14
- cached_input_tokens?: number;
15
- duration_ms?: number;
8
+ export type SamplingCallData = {
9
+ model_id?: string;
10
+ input_tokens?: number;
11
+ output_tokens?: number;
12
+ reasoning_tokens?: number;
13
+ cached_input_tokens?: number;
14
+ duration_ms?: number;
16
15
  };
17
- type McpSamplingHandler = (request: McpSamplingRequest) => Promise<McpSamplingResponse>;
18
- type McpSamplingRequest = {
19
- method: "sampling/createMessage";
20
- params: {
21
- messages: unknown[];
22
- modelPreferences?: {
23
- hints?: {
24
- name?: string;
25
- }[];
16
+ export type McpSamplingHandler = (request: McpSamplingRequest) => Promise<McpSamplingResponse>;
17
+ export type McpSamplingRequest = {
18
+ method: "sampling/createMessage";
19
+ params: {
20
+ messages: unknown[];
21
+ modelPreferences?: {
22
+ hints?: {
23
+ name?: string;
24
+ }[];
25
+ };
26
+ maxTokens?: number;
27
+ [key: string]: unknown;
26
28
  };
27
- maxTokens?: number;
28
- [key: string]: unknown;
29
- };
30
29
  };
31
- type McpSamplingResponse = {
32
- model?: string;
33
- content: unknown;
34
- usage?: {
35
- inputTokens?: number;
36
- outputTokens?: number;
37
- promptTokens?: number;
38
- completionTokens?: number;
39
- reasoningTokens?: number;
40
- cachedInputTokens?: number;
41
- };
42
- [key: string]: unknown;
30
+ export type McpSamplingResponse = {
31
+ model?: string;
32
+ content: unknown;
33
+ usage?: {
34
+ inputTokens?: number;
35
+ outputTokens?: number;
36
+ promptTokens?: number;
37
+ completionTokens?: number;
38
+ reasoningTokens?: number;
39
+ cachedInputTokens?: number;
40
+ };
41
+ [key: string]: unknown;
43
42
  };
44
43
  /**
45
44
  * Wraps an MCP sampling handler to intercept and measure sampling calls.
@@ -59,7 +58,7 @@ type McpSamplingResponse = {
59
58
  * // After tool execution, `samplingCalls` contains metrics for all nested LLM calls
60
59
  * ```
61
60
  */
62
- declare function wrapSamplingHandler(handler: McpSamplingHandler, onSamplingCall: (data: SamplingCallData) => void): McpSamplingHandler;
61
+ export declare function wrapSamplingHandler(handler: McpSamplingHandler, onSamplingCall: (data: SamplingCallData) => void): McpSamplingHandler;
63
62
  /**
64
63
  * Creates a collector that accumulates sampling call data during tool execution.
65
64
  * Use with `wrapSamplingHandler` to capture all sampling calls for a tool invocation.
@@ -72,11 +71,9 @@ declare function wrapSamplingHandler(handler: McpSamplingHandler, onSamplingCall
72
71
  * const calls = collector.getCalls(); // SamplingCallData[]
73
72
  * ```
74
73
  */
75
- declare function createSamplingCollector(): {
76
- collect: (data: SamplingCallData) => number;
77
- getCalls: () => SamplingCallData[];
78
- reset: () => void;
74
+ export declare function createSamplingCollector(): {
75
+ collect: (data: SamplingCallData) => number;
76
+ getCalls: () => SamplingCallData[];
77
+ reset: () => void;
79
78
  };
80
- //#endregion
81
- export { McpSamplingHandler, McpSamplingRequest, McpSamplingResponse, SamplingCallData, createSamplingCollector, wrapSamplingHandler };
82
79
  //# sourceMappingURL=instrumentMcpSampling.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentMcpSampling.d.ts","names":[],"sources":["../src/instrumentMcpSampling.ts"],"mappings":";;;;;;;;KAQY;EACV;EACA;EACA;EACA;EACA;EACA;;KAGU,sBACV,SAAS,uBACN,QAAQ;KAED;EACV;EACA;IACE;IACA;MAAqB;QAAU;;;IAC/B;KACC;;;KAIO;EACV;EACA;EACA;IACE;IACA;IACA;IACA;IACA;IACA;;GAED;;;;;;;;;;;;;;;;;;;;iBA8Ba,oBACd,SAAS,oBACT,iBAAiB,MAAM,4BACtB;;;;;;;;;;;;;iBAkDa;EAGI,UAAA,MAAA;kBAAA"}
1
+ {"version":3,"file":"instrumentMcpSampling.d.ts","sourceRoot":"","sources":["../src/instrumentMcpSampling.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,kBAAkB,KACxB,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAElC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE;QACN,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,gBAAgB,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE;gBAAE,IAAI,CAAC,EAAE,MAAM,CAAA;aAAE,EAAE,CAAA;SAAE,CAAC;QACnD,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAWF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAC/C,kBAAkB,CAoCpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB;oBAGnB,gBAAgB;;;EAMnC"}
@@ -1,61 +1,60 @@
1
- import { SamplingCallData } from "./instrumentMcpSampling.js";
2
- import { AssistantCloudRunReport } from "./AssistantCloudRuns.js";
3
- //#region src/runTelemetry.d.ts
4
- type AssistantCloudRunReportToolCall = {
5
- tool_name: string;
6
- tool_call_id: string;
7
- tool_args?: string;
8
- tool_result?: string;
9
- tool_source?: "mcp" | "frontend" | "backend";
10
- start_ms?: number;
11
- end_ms?: number;
12
- sampling_calls?: SamplingCallData[];
1
+ import type { SamplingCallData } from "./instrumentMcpSampling.js";
2
+ import type { AssistantCloudRunReport } from "./AssistantCloudRuns.js";
3
+ export type AssistantCloudRunReportToolCall = {
4
+ tool_name: string;
5
+ tool_call_id: string;
6
+ tool_args?: string;
7
+ tool_result?: string;
8
+ tool_source?: "mcp" | "frontend" | "backend";
9
+ start_ms?: number;
10
+ end_ms?: number;
11
+ sampling_calls?: SamplingCallData[];
13
12
  };
14
- type RunReportOutcome = "aborted" | "disconnected" | "length" | "content_filter";
13
+ export type RunReportOutcome = "aborted" | "disconnected" | "length" | "content_filter";
15
14
  /**
16
15
  * Maps a finish event to the report status and outcome. `fallbackStatus`
17
16
  * applies when the event carries neither a finish reason nor a failure flag.
18
17
  */
19
- declare function deriveRunOutcome(input: {
20
- finishReason?: string | undefined;
21
- isAbort?: boolean | undefined;
22
- isDisconnect?: boolean | undefined;
23
- isError?: boolean | undefined;
18
+ export declare function deriveRunOutcome(input: {
19
+ finishReason?: string | undefined;
20
+ isAbort?: boolean | undefined;
21
+ isDisconnect?: boolean | undefined;
22
+ isError?: boolean | undefined;
24
23
  }, fallbackStatus?: "completed" | "incomplete"): {
25
- status: "completed" | "incomplete" | "error";
26
- outcome?: RunReportOutcome;
24
+ status: "completed" | "incomplete" | "error";
25
+ outcome?: RunReportOutcome;
27
26
  };
28
27
  /**
29
28
  * Reads the message and code the runs endpoint stores for a failed run. The
30
29
  * code is the error's `code` when it has one, else its class name.
31
30
  */
32
- declare function describeRunError(error: unknown): {
33
- error?: string;
34
- errorCode?: string;
31
+ export declare function describeRunError(error: unknown): {
32
+ error?: string;
33
+ errorCode?: string;
35
34
  };
36
35
  /**
37
36
  * Clamps a string to the size the runs endpoint accepts for a single span
38
37
  * field.
39
38
  */
40
- declare function truncateRunTelemetryText(value: string): string;
41
- type RunTelemetryToolCallInit = {
42
- toolName: string;
43
- toolCallId: string;
44
- args?: unknown;
45
- /**
46
- * Pre-serialized arguments, used in place of serializing `args`. Values over
47
- * the span size are clamped before they are included in the report.
48
- */
49
- argsText?: string | undefined;
50
- result?: unknown;
51
- toolSource?: "mcp" | "frontend" | "backend" | undefined;
39
+ export declare function truncateRunTelemetryText(value: string): string;
40
+ export type RunTelemetryToolCallInit = {
41
+ toolName: string;
42
+ toolCallId: string;
43
+ args?: unknown;
44
+ /**
45
+ * Pre-serialized arguments, used in place of serializing `args`. Values over
46
+ * the span size are clamped before they are included in the report.
47
+ */
48
+ argsText?: string | undefined;
49
+ result?: unknown;
50
+ toolSource?: "mcp" | "frontend" | "backend" | undefined;
52
51
  };
53
52
  /**
54
53
  * Serializes one tool call into the shape the runs endpoint accepts. An `mcp`
55
54
  * source has its result summarized, because MCP content blocks carry inline
56
55
  * base64 image and audio payloads that would otherwise dominate the report.
57
56
  */
58
- declare function createRunTelemetryToolCall(init: RunTelemetryToolCallInit): AssistantCloudRunReportToolCall;
57
+ export declare function createRunTelemetryToolCall(init: RunTelemetryToolCallInit): AssistantCloudRunReportToolCall;
59
58
  /**
60
59
  * Resolves the model ID a run reports, in the order an app can supply it: an
61
60
  * explicit `modelId`, the `custom` bag, then the per-step `response.modelId`
@@ -63,78 +62,86 @@ declare function createRunTelemetryToolCall(init: RunTelemetryToolCallInit): Ass
63
62
  * The AI SDK puts no model ID on a UI message part, so message metadata is the
64
63
  * only channel one arrives on.
65
64
  */
66
- declare function extractRunTelemetryModelId(metadata: Record<string, unknown> | undefined): string | undefined;
67
- type RunTelemetryUsage = {
68
- inputTokens?: number | undefined;
69
- outputTokens?: number | undefined;
70
- reasoningTokens?: number | undefined;
71
- cachedInputTokens?: number | undefined;
65
+ export declare function extractRunTelemetryModelId(metadata: Record<string, unknown> | undefined): string | undefined;
66
+ export type RunTelemetryUsage = {
67
+ inputTokens?: number | undefined;
68
+ outputTokens?: number | undefined;
69
+ reasoningTokens?: number | undefined;
70
+ cachedInputTokens?: number | undefined;
72
71
  };
73
- type RunTelemetryUsageInit = RunTelemetryUsage & {
74
- promptTokens?: number | undefined;
75
- completionTokens?: number | undefined;
76
- inputTokenDetails?: {
77
- cacheReadTokens?: number;
78
- };
79
- outputTokenDetails?: {
80
- reasoningTokens?: number;
81
- };
72
+ export type RunTelemetryUsageInit = RunTelemetryUsage & {
73
+ promptTokens?: number | undefined;
74
+ completionTokens?: number | undefined;
75
+ inputTokenDetails?: {
76
+ cacheReadTokens?: number;
77
+ };
78
+ outputTokenDetails?: {
79
+ reasoningTokens?: number;
80
+ };
82
81
  };
83
- type RunReportStepInit = {
84
- usage?: RunTelemetryUsageInit | undefined;
85
- toolCalls?: AssistantCloudRunReportToolCall[] | undefined;
86
- startMs?: number | undefined;
87
- endMs?: number | undefined;
88
- finishReason?: string | undefined;
82
+ export type RunReportStepInit = {
83
+ usage?: RunTelemetryUsageInit | undefined;
84
+ toolCalls?: AssistantCloudRunReportToolCall[] | undefined;
85
+ startMs?: number | undefined;
86
+ endMs?: number | undefined;
87
+ finishReason?: string | undefined;
88
+ input?: string | undefined;
89
89
  };
90
90
  /**
91
91
  * The run report fields read from the messages of one run, in whichever
92
92
  * format they were stored: the status the messages imply, the tool calls, the
93
93
  * steps, the text, the usage and the model.
94
94
  */
95
- type RunMessageTelemetry = {
96
- assistantMessageId?: string;
97
- status: "completed" | "incomplete";
98
- toolCalls?: AssistantCloudRunReportToolCall[];
99
- steps?: RunReportStepInit[];
100
- totalSteps?: number;
101
- outputText?: string;
102
- usage?: RunTelemetryUsage;
103
- modelId?: string;
104
- metadata?: Record<string, unknown>;
95
+ export type RunMessageTelemetry = {
96
+ assistantMessageId?: string;
97
+ status: "completed" | "incomplete";
98
+ toolCalls?: AssistantCloudRunReportToolCall[];
99
+ steps?: RunReportStepInit[];
100
+ totalSteps?: number;
101
+ outputText?: string;
102
+ usage?: RunTelemetryUsage;
103
+ modelId?: string;
104
+ metadata?: Record<string, unknown>;
105
105
  };
106
- type RunReportInit = {
107
- threadId: string;
108
- status: AssistantCloudRunReport["status"];
109
- outcome?: RunReportOutcome | undefined;
110
- errorCode?: string | undefined;
111
- error?: string | undefined;
112
- messageId?: string | undefined;
113
- traceId?: string | undefined;
114
- modelId?: string | undefined;
115
- provider?: string | undefined;
116
- usage?: RunTelemetryUsageInit | undefined;
117
- steps?: RunReportStepInit[] | undefined;
118
- totalSteps?: number | undefined;
119
- toolCalls?: AssistantCloudRunReportToolCall[] | undefined;
120
- durationMs?: number | undefined;
121
- firstTokenMs?: number | undefined;
122
- outputText?: string | undefined;
123
- metadata?: Record<string, unknown> | undefined;
124
- telemetry?: {
125
- environment?: string | undefined;
126
- release?: string | undefined;
127
- tags?: readonly string[] | undefined;
128
- };
106
+ export type RunReportInit = {
107
+ threadId: string;
108
+ status: AssistantCloudRunReport["status"];
109
+ outcome?: AssistantCloudRunReport["outcome_type"] | undefined;
110
+ errorCode?: string | undefined;
111
+ error?: string | undefined;
112
+ messageId?: string | undefined;
113
+ traceId?: string | undefined;
114
+ rootSpanId?: string | undefined;
115
+ modelId?: string | undefined;
116
+ provider?: string | undefined;
117
+ usage?: RunTelemetryUsageInit | undefined;
118
+ steps?: RunReportStepInit[] | undefined;
119
+ totalSteps?: number | undefined;
120
+ toolCalls?: AssistantCloudRunReportToolCall[] | undefined;
121
+ durationMs?: number | undefined;
122
+ firstTokenMs?: number | undefined;
123
+ costUsd?: number | undefined;
124
+ costDetails?: {
125
+ input?: number | undefined;
126
+ inputCachedTokens?: number | undefined;
127
+ output?: number | undefined;
128
+ total?: number | undefined;
129
+ } | undefined;
130
+ outputText?: string | undefined;
131
+ attributes?: Record<string, unknown> | undefined;
132
+ metadata?: Record<string, unknown> | undefined;
133
+ telemetry?: {
134
+ environment?: string | undefined;
135
+ release?: string | undefined;
136
+ tags?: readonly string[] | undefined;
137
+ };
129
138
  };
130
- declare function createRunReport(init: RunReportInit): AssistantCloudRunReport;
139
+ export declare function createRunReport(init: RunReportInit): AssistantCloudRunReport;
131
140
  /**
132
141
  * Resolves the token counts a provider reports under any of the names the AI
133
142
  * SDK has used: the current top-level ones, the legacy prompt/completion pair,
134
143
  * and the v7 token detail objects. Returns undefined when no count is present,
135
144
  * so callers can tell an empty usage object from a zeroed one.
136
145
  */
137
- declare function normalizeRunTelemetryUsage(usage: RunTelemetryUsageInit): RunTelemetryUsage | undefined;
138
- //#endregion
139
- export { AssistantCloudRunReportToolCall, RunMessageTelemetry, RunReportInit, RunReportOutcome, RunReportStepInit, RunTelemetryToolCallInit, RunTelemetryUsage, RunTelemetryUsageInit, createRunReport, createRunTelemetryToolCall, deriveRunOutcome, describeRunError, extractRunTelemetryModelId, normalizeRunTelemetryUsage, truncateRunTelemetryText };
146
+ export declare function normalizeRunTelemetryUsage(usage: RunTelemetryUsageInit): RunTelemetryUsage | undefined;
140
147
  //# sourceMappingURL=runTelemetry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runTelemetry.d.ts","names":[],"sources":["../src/runTelemetry.ts"],"mappings":";;;KAOY;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB;;KAGP;;;;;iBAUI,iBACd;EACE;EACA;EACA;EACA;GAEF;EAEA;EACA,UAAU;;;;;;iBA+BI,iBAAiB;EAC/B;EACA;;;;;;iBA+Bc,yBAAyB;KAwC7B;EACV;EACA;EACA;;;;;EAKA;EACA;EACA;;;;;;;iBAQc,2BACd,MAAM,2BACL;;;;;;;;iBAuBa,2BACd,UAAU;KAmBA;EACV;EACA;EACA;EACA;;KAGU,wBAAwB;EAClC;EACA;EACA;IAAsB;;EACtB;IAAuB;;;KAGb;EACV,QAAQ;EACR,YAAY;EACZ;EACA;EACA;;;;;;;KAQU;EACV;EACA;EACA,YAAY;EACZ,QAAQ;EACR;EACA;EACA,QAAQ;EACR;EACA,WAAW;;KAGD;EACV;EACA,QAAQ;EACR,UAAU;EACV;EACA;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR,QAAQ;EACR;EACA,YAAY;EACZ;EACA;EACA;EACA,WAAW;EACX;IACE;IACA;IACA;;;iBAuEY,gBAAgB,MAAM,gBAAgB;;;;;;;iBAiDtC,2BACd,OAAO,wBACN"}
1
+ {"version":3,"file":"runTelemetry.d.ts","sourceRoot":"","sources":["../src/runTelemetry.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  //#region src/runTelemetry.ts
2
2
  const MAX_TELEMETRY_TEXT_LENGTH = 5e4;
3
- const BASE64_PATTERN = /^[A-Za-z0-9+/]{100,}={0,2}$/;
3
+ const BASE64_PATTERN = /^[A-Za-z0-9+/]+={0,2}$/;
4
4
  /**
5
5
  * Maps a finish event to the report status and outcome. `fallbackStatus`
6
6
  * applies when the event carries neither a finish reason nor a failure flag.
@@ -65,24 +65,42 @@ function safeStringify(value) {
65
65
  return;
66
66
  }
67
67
  }
68
+ const base64SizeKB = (value) => (value.length * 3 / 4 / 1024).toFixed(1);
69
+ const isInlineBase64 = (value) => {
70
+ if (typeof value !== "string") return false;
71
+ const head = value.slice(0, 200);
72
+ return head.length > 0 && head.length % 4 === 0 && BASE64_PATTERN.test(head);
73
+ };
74
+ function summarizeMcpContentBlock(item) {
75
+ if (!item || typeof item !== "object") return item;
76
+ const block = item;
77
+ if ((block.type === "image" || block.type === "audio") && isInlineBase64(block.data)) return {
78
+ ...block,
79
+ data: `[${String(block.type)}: ${base64SizeKB(block.data)}KB]`
80
+ };
81
+ if (block.type === "resource" && block.resource && typeof block.resource === "object") {
82
+ const resource = block.resource;
83
+ if (isInlineBase64(resource.blob)) return {
84
+ ...block,
85
+ resource: {
86
+ ...resource,
87
+ blob: `[resource: ${base64SizeKB(resource.blob)}KB]`
88
+ }
89
+ };
90
+ }
91
+ return item;
92
+ }
68
93
  function summarizeMcpResult(value) {
69
94
  if (value == null) return void 0;
70
95
  try {
71
96
  const parsed = typeof value === "string" ? JSON.parse(value) : value;
72
- if (Array.isArray(parsed)) {
73
- const summarized = parsed.map((item) => {
74
- if (item && typeof item === "object" && item.type) {
75
- if ((item.type === "image" || item.type === "audio") && typeof item.data === "string" && BASE64_PATTERN.test(item.data.slice(0, 200))) {
76
- const sizeKB = (item.data.length * 3 / 4 / 1024).toFixed(1);
77
- return {
78
- ...item,
79
- data: `[${item.type}: ${sizeKB}KB]`
80
- };
81
- }
82
- }
83
- return item;
84
- });
85
- return truncateRunTelemetryText(JSON.stringify(summarized));
97
+ if (Array.isArray(parsed)) return truncateRunTelemetryText(JSON.stringify(parsed.map(summarizeMcpContentBlock)));
98
+ if (typeof parsed === "object") {
99
+ const content = parsed.content;
100
+ if (Array.isArray(content)) return truncateRunTelemetryText(JSON.stringify({
101
+ ...parsed,
102
+ content: content.map(summarizeMcpContentBlock)
103
+ }));
86
104
  }
87
105
  } catch {}
88
106
  return safeStringify(value);
@@ -147,6 +165,7 @@ function createRunReportStep(init) {
147
165
  if (init.startMs !== void 0) step.start_ms = init.startMs;
148
166
  if (init.endMs !== void 0) step.end_ms = init.endMs;
149
167
  if (init.finishReason !== void 0) step.finish_reason = init.finishReason.slice(0, 32);
168
+ if (init.input !== void 0) step.input = truncateRunTelemetryText(init.input);
150
169
  return step;
151
170
  }
152
171
  function normalizeRunReportTags(tags) {
@@ -166,6 +185,23 @@ function normalizeRunReportMilliseconds(value) {
166
185
  if (value === void 0 || !Number.isFinite(value)) return void 0;
167
186
  return Math.max(0, Math.round(value));
168
187
  }
188
+ function normalizeRunReportCost(value) {
189
+ if (value === void 0 || !Number.isFinite(value) || value < 0) return;
190
+ return value;
191
+ }
192
+ function assignCostDetails(report, costDetails) {
193
+ if (!costDetails) return;
194
+ const normalized = {};
195
+ const input = normalizeRunReportCost(costDetails.input);
196
+ if (input !== void 0) normalized.input = input;
197
+ const inputCachedTokens = normalizeRunReportCost(costDetails.inputCachedTokens);
198
+ if (inputCachedTokens !== void 0) normalized.input_cached_tokens = inputCachedTokens;
199
+ const output = normalizeRunReportCost(costDetails.output);
200
+ if (output !== void 0) normalized.output = output;
201
+ const total = normalizeRunReportCost(costDetails.total);
202
+ if (total !== void 0) normalized.total = total;
203
+ if (Object.keys(normalized).length > 0) report.cost_details = normalized;
204
+ }
169
205
  function createRunReport(init) {
170
206
  const report = {
171
207
  thread_id: init.threadId,
@@ -173,6 +209,8 @@ function createRunReport(init) {
173
209
  };
174
210
  const traceId = init.traceId?.toLowerCase();
175
211
  if (traceId && /^[0-9a-f]{32}$/.test(traceId)) report.trace_id = traceId;
212
+ const rootSpanId = init.rootSpanId?.toLowerCase();
213
+ if (rootSpanId && /^[0-9a-f]{16}$/.test(rootSpanId)) report.root_span_id = rootSpanId;
176
214
  if (init.outcome !== void 0) report.outcome_type = init.outcome;
177
215
  if (init.errorCode !== void 0) report.error_code = init.errorCode;
178
216
  if (init.error !== void 0) report.error = init.error;
@@ -192,7 +230,11 @@ function createRunReport(init) {
192
230
  if (durationMs !== void 0) report.duration_ms = durationMs;
193
231
  const firstTokenMs = normalizeRunReportMilliseconds(init.firstTokenMs);
194
232
  if (firstTokenMs !== void 0) report.first_token_ms = firstTokenMs;
233
+ const costUsd = normalizeRunReportCost(init.costUsd);
234
+ if (costUsd !== void 0) report.cost_usd = costUsd;
235
+ assignCostDetails(report, init.costDetails);
195
236
  if (init.outputText !== void 0) report.output_text = truncateRunTelemetryText(init.outputText);
237
+ if (init.attributes !== void 0) report.attributes = init.attributes;
196
238
  if (init.metadata !== void 0) report.metadata = init.metadata;
197
239
  if (init.telemetry?.environment !== void 0) report.environment = init.telemetry.environment;
198
240
  if (init.telemetry?.release !== void 0) report.release = init.telemetry.release;
@@ -1 +1 @@
1
- {"version":3,"file":"runTelemetry.js","names":[],"sources":["../src/runTelemetry.ts"],"sourcesContent":["import type { SamplingCallData } from \"./instrumentMcpSampling\";\nimport type { AssistantCloudRunReport } from \"./AssistantCloudRuns\";\n\nconst MAX_TELEMETRY_TEXT_LENGTH = 50_000;\n\nconst BASE64_PATTERN = /^[A-Za-z0-9+/]{100,}={0,2}$/;\n\nexport type AssistantCloudRunReportToolCall = {\n tool_name: string;\n tool_call_id: string;\n tool_args?: string;\n tool_result?: string;\n tool_source?: \"mcp\" | \"frontend\" | \"backend\";\n start_ms?: number;\n end_ms?: number;\n sampling_calls?: SamplingCallData[];\n};\n\nexport type RunReportOutcome =\n | \"aborted\"\n | \"disconnected\"\n | \"length\"\n | \"content_filter\";\n\n/**\n * Maps a finish event to the report status and outcome. `fallbackStatus`\n * applies when the event carries neither a finish reason nor a failure flag.\n */\nexport function deriveRunOutcome(\n input: {\n finishReason?: string | undefined;\n isAbort?: boolean | undefined;\n isDisconnect?: boolean | undefined;\n isError?: boolean | undefined;\n },\n fallbackStatus: \"completed\" | \"incomplete\" = \"completed\",\n): {\n status: \"completed\" | \"incomplete\" | \"error\";\n outcome?: RunReportOutcome;\n} {\n if (input.isError) return { status: \"error\" };\n if (input.isAbort) return { status: \"incomplete\", outcome: \"aborted\" };\n if (input.isDisconnect) {\n return { status: \"incomplete\", outcome: \"disconnected\" };\n }\n switch (input.finishReason) {\n case \"length\":\n return { status: \"incomplete\", outcome: \"length\" };\n case \"content-filter\":\n case \"content_filter\":\n return { status: \"incomplete\", outcome: \"content_filter\" };\n case \"cancelled\":\n return { status: \"incomplete\", outcome: \"aborted\" };\n case \"error\":\n return { status: \"error\" };\n default:\n return {\n status: input.finishReason === undefined ? fallbackStatus : \"completed\",\n };\n }\n}\n\nconst MAX_RUN_ERROR_CODE_LENGTH = 64;\nconst MAX_RUN_ERROR_LENGTH = 2048;\n\n/**\n * Reads the message and code the runs endpoint stores for a failed run. The\n * code is the error's `code` when it has one, else its class name.\n */\nexport function describeRunError(error: unknown): {\n error?: string;\n errorCode?: string;\n} {\n if (error == null) return {};\n const record =\n typeof error === \"object\" ? (error as Record<string, unknown>) : undefined;\n const message =\n typeof error === \"string\"\n ? error\n : typeof record?.message === \"string\"\n ? record.message\n : undefined;\n const code =\n typeof record?.code === \"string\"\n ? record.code\n : typeof record?.name === \"string\" && record.name !== \"Error\"\n ? record.name\n : undefined;\n return {\n ...(message\n ? { error: message.slice(0, MAX_RUN_ERROR_LENGTH) }\n : undefined),\n ...(code\n ? { errorCode: code.slice(0, MAX_RUN_ERROR_CODE_LENGTH) }\n : undefined),\n };\n}\n\n/**\n * Clamps a string to the size the runs endpoint accepts for a single span\n * field.\n */\nexport function truncateRunTelemetryText(value: string): string {\n if (value.length <= MAX_TELEMETRY_TEXT_LENGTH) return value;\n return value.slice(0, MAX_TELEMETRY_TEXT_LENGTH);\n}\n\nfunction safeStringify(value: unknown): string | undefined {\n if (value == null) return undefined;\n try {\n return truncateRunTelemetryText(JSON.stringify(value));\n } catch {\n return undefined;\n }\n}\n\nfunction summarizeMcpResult(value: unknown): string | undefined {\n if (value == null) return undefined;\n try {\n const parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n if (Array.isArray(parsed)) {\n const summarized = parsed.map((item) => {\n if (item && typeof item === \"object\" && item.type) {\n if (\n (item.type === \"image\" || item.type === \"audio\") &&\n typeof item.data === \"string\" &&\n BASE64_PATTERN.test(item.data.slice(0, 200))\n ) {\n const sizeKB = ((item.data.length * 3) / 4 / 1024).toFixed(1);\n return { ...item, data: `[${item.type}: ${sizeKB}KB]` };\n }\n }\n return item;\n });\n return truncateRunTelemetryText(JSON.stringify(summarized));\n }\n } catch {\n // not JSON array, fall through\n }\n return safeStringify(value);\n}\n\nexport type RunTelemetryToolCallInit = {\n toolName: string;\n toolCallId: string;\n args?: unknown;\n /**\n * Pre-serialized arguments, used in place of serializing `args`. Values over\n * the span size are clamped before they are included in the report.\n */\n argsText?: string | undefined;\n result?: unknown;\n toolSource?: \"mcp\" | \"frontend\" | \"backend\" | undefined;\n};\n\n/**\n * Serializes one tool call into the shape the runs endpoint accepts. An `mcp`\n * source has its result summarized, because MCP content blocks carry inline\n * base64 image and audio payloads that would otherwise dominate the report.\n */\nexport function createRunTelemetryToolCall(\n init: RunTelemetryToolCallInit,\n): AssistantCloudRunReportToolCall {\n const { toolName, toolCallId, args, argsText, result, toolSource } = init;\n const call: AssistantCloudRunReportToolCall = {\n tool_name: toolName,\n tool_call_id: toolCallId,\n };\n const toolArgs =\n argsText != null ? truncateRunTelemetryText(argsText) : safeStringify(args);\n if (toolArgs !== undefined) call.tool_args = toolArgs;\n const toolResult =\n toolSource === \"mcp\" ? summarizeMcpResult(result) : safeStringify(result);\n if (toolResult !== undefined) call.tool_result = toolResult;\n if (toolSource) call.tool_source = toolSource;\n return call;\n}\n\n/**\n * Resolves the model ID a run reports, in the order an app can supply it: an\n * explicit `modelId`, the `custom` bag, then the per-step `response.modelId`\n * that a `messageMetadata` callback copies off the AI SDK's finish-step part.\n * The AI SDK puts no model ID on a UI message part, so message metadata is the\n * only channel one arrives on.\n */\nexport function extractRunTelemetryModelId(\n metadata: Record<string, unknown> | undefined,\n): string | undefined {\n if (!metadata) return undefined;\n if (typeof metadata.modelId === \"string\") return metadata.modelId;\n const custom = metadata.custom as Record<string, unknown> | undefined;\n if (typeof custom?.modelId === \"string\") return custom.modelId;\n\n const steps: unknown = metadata.steps;\n if (!Array.isArray(steps)) return undefined;\n for (const step of steps as unknown[]) {\n if (!step || typeof step !== \"object\") continue;\n const response = (step as Record<string, unknown>).response;\n if (!response || typeof response !== \"object\") continue;\n const modelId = (response as Record<string, unknown>).modelId;\n if (typeof modelId === \"string\") return modelId;\n }\n return undefined;\n}\n\nexport type RunTelemetryUsage = {\n inputTokens?: number | undefined;\n outputTokens?: number | undefined;\n reasoningTokens?: number | undefined;\n cachedInputTokens?: number | undefined;\n};\n\nexport type RunTelemetryUsageInit = RunTelemetryUsage & {\n promptTokens?: number | undefined;\n completionTokens?: number | undefined;\n inputTokenDetails?: { cacheReadTokens?: number };\n outputTokenDetails?: { reasoningTokens?: number };\n};\n\nexport type RunReportStepInit = {\n usage?: RunTelemetryUsageInit | undefined;\n toolCalls?: AssistantCloudRunReportToolCall[] | undefined;\n startMs?: number | undefined;\n endMs?: number | undefined;\n finishReason?: string | undefined;\n};\n\n/**\n * The run report fields read from the messages of one run, in whichever\n * format they were stored: the status the messages imply, the tool calls, the\n * steps, the text, the usage and the model.\n */\nexport type RunMessageTelemetry = {\n assistantMessageId?: string;\n status: \"completed\" | \"incomplete\";\n toolCalls?: AssistantCloudRunReportToolCall[];\n steps?: RunReportStepInit[];\n totalSteps?: number;\n outputText?: string;\n usage?: RunTelemetryUsage;\n modelId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type RunReportInit = {\n threadId: string;\n status: AssistantCloudRunReport[\"status\"];\n outcome?: RunReportOutcome | undefined;\n errorCode?: string | undefined;\n error?: string | undefined;\n messageId?: string | undefined;\n traceId?: string | undefined;\n modelId?: string | undefined;\n provider?: string | undefined;\n usage?: RunTelemetryUsageInit | undefined;\n steps?: RunReportStepInit[] | undefined;\n totalSteps?: number | undefined;\n toolCalls?: AssistantCloudRunReportToolCall[] | undefined;\n durationMs?: number | undefined;\n firstTokenMs?: number | undefined;\n outputText?: string | undefined;\n metadata?: Record<string, unknown> | undefined;\n telemetry?: {\n environment?: string | undefined;\n release?: string | undefined;\n tags?: readonly string[] | undefined;\n };\n};\n\nfunction assignUsage(\n report: AssistantCloudRunReport,\n usage: RunTelemetryUsageInit | undefined,\n): void {\n if (!usage) return;\n const normalized = normalizeRunTelemetryUsage(usage);\n if (!normalized) return;\n if (normalized.inputTokens !== undefined) {\n report.input_tokens = normalized.inputTokens;\n }\n if (normalized.outputTokens !== undefined) {\n report.output_tokens = normalized.outputTokens;\n }\n if (normalized.reasoningTokens !== undefined) {\n report.reasoning_tokens = normalized.reasoningTokens;\n }\n if (normalized.cachedInputTokens !== undefined) {\n report.cached_input_tokens = normalized.cachedInputTokens;\n }\n}\n\nfunction createRunReportStep(\n init: RunReportStepInit,\n): NonNullable<AssistantCloudRunReport[\"steps\"]>[number] {\n const step: NonNullable<AssistantCloudRunReport[\"steps\"]>[number] = {};\n const usage = init.usage ? normalizeRunTelemetryUsage(init.usage) : undefined;\n if (usage?.inputTokens !== undefined) step.input_tokens = usage.inputTokens;\n if (usage?.outputTokens !== undefined)\n step.output_tokens = usage.outputTokens;\n if (usage?.reasoningTokens !== undefined) {\n step.reasoning_tokens = usage.reasoningTokens;\n }\n if (usage?.cachedInputTokens !== undefined) {\n step.cached_input_tokens = usage.cachedInputTokens;\n }\n if (init.toolCalls !== undefined) step.tool_calls = init.toolCalls;\n if (init.startMs !== undefined) step.start_ms = init.startMs;\n if (init.endMs !== undefined) step.end_ms = init.endMs;\n if (init.finishReason !== undefined) {\n step.finish_reason = init.finishReason.slice(0, 32);\n }\n return step;\n}\n\nfunction normalizeRunReportTags(\n tags: readonly string[] | undefined,\n): string[] | undefined {\n if (!tags) return undefined;\n const result: string[] = [];\n const seen = new Set<string>();\n for (const tag of tags) {\n const normalized = tag.trim().slice(0, 64).trim();\n if (!normalized || seen.has(normalized)) continue;\n seen.add(normalized);\n result.push(normalized);\n if (result.length === 20) break;\n }\n return result.length > 0 ? result : undefined;\n}\n\nfunction normalizeRunReportMilliseconds(\n value: number | undefined,\n): number | undefined {\n if (value === undefined || !Number.isFinite(value)) return undefined;\n return Math.max(0, Math.round(value));\n}\n\nexport function createRunReport(init: RunReportInit): AssistantCloudRunReport {\n const report: AssistantCloudRunReport = {\n thread_id: init.threadId,\n status: init.status,\n };\n const traceId = init.traceId?.toLowerCase();\n if (traceId && /^[0-9a-f]{32}$/.test(traceId)) report.trace_id = traceId;\n if (init.outcome !== undefined) report.outcome_type = init.outcome;\n if (init.errorCode !== undefined) report.error_code = init.errorCode;\n if (init.error !== undefined) report.error = init.error;\n if (init.messageId !== undefined) report.message_id = init.messageId;\n if (init.modelId !== undefined) report.model_id = init.modelId;\n if (init.provider !== undefined) {\n report.provider = init.provider;\n report.provider_type = init.provider;\n }\n assignUsage(report, init.usage);\n if (init.steps !== undefined) {\n report.steps = init.steps.map(createRunReportStep);\n report.total_steps = init.steps.length;\n } else if (init.totalSteps !== undefined) {\n report.total_steps = init.totalSteps;\n }\n if (init.toolCalls !== undefined) report.tool_calls = init.toolCalls;\n const durationMs = normalizeRunReportMilliseconds(init.durationMs);\n if (durationMs !== undefined) report.duration_ms = durationMs;\n const firstTokenMs = normalizeRunReportMilliseconds(init.firstTokenMs);\n if (firstTokenMs !== undefined) report.first_token_ms = firstTokenMs;\n if (init.outputText !== undefined) {\n report.output_text = truncateRunTelemetryText(init.outputText);\n }\n if (init.metadata !== undefined) report.metadata = init.metadata;\n if (init.telemetry?.environment !== undefined) {\n report.environment = init.telemetry.environment;\n }\n if (init.telemetry?.release !== undefined) {\n report.release = init.telemetry.release;\n }\n const tags = normalizeRunReportTags(init.telemetry?.tags);\n if (tags !== undefined) report.tags = tags;\n return report;\n}\n\n/**\n * Resolves the token counts a provider reports under any of the names the AI\n * SDK has used: the current top-level ones, the legacy prompt/completion pair,\n * and the v7 token detail objects. Returns undefined when no count is present,\n * so callers can tell an empty usage object from a zeroed one.\n */\nexport function normalizeRunTelemetryUsage(\n usage: RunTelemetryUsageInit,\n): RunTelemetryUsage | undefined {\n const inputTokens = usage.inputTokens ?? usage.promptTokens;\n const outputTokens = usage.outputTokens ?? usage.completionTokens;\n // AI SDK v7 moved these under token detail objects; v6 kept them top-level.\n const reasoningTokens =\n usage.reasoningTokens ?? usage.outputTokenDetails?.reasoningTokens;\n const cachedInputTokens =\n usage.cachedInputTokens ?? usage.inputTokenDetails?.cacheReadTokens;\n\n if (\n inputTokens == null &&\n outputTokens == null &&\n reasoningTokens == null &&\n cachedInputTokens == null\n ) {\n return undefined;\n }\n\n return {\n ...(inputTokens != null ? { inputTokens } : undefined),\n ...(outputTokens != null ? { outputTokens } : undefined),\n ...(reasoningTokens != null ? { reasoningTokens } : undefined),\n ...(cachedInputTokens != null ? { cachedInputTokens } : undefined),\n };\n}\n"],"mappings":";AAGA,MAAM,4BAA4B;AAElC,MAAM,iBAAiB;;;;;AAuBvB,SAAgB,iBACd,OAMA,iBAA6C,aAI7C;CACA,IAAI,MAAM,SAAS,OAAO,EAAE,QAAQ,QAAQ;CAC5C,IAAI,MAAM,SAAS,OAAO;EAAE,QAAQ;EAAc,SAAS;CAAU;CACrE,IAAI,MAAM,cACR,OAAO;EAAE,QAAQ;EAAc,SAAS;CAAe;CAEzD,QAAQ,MAAM,cAAd;EACE,KAAK,UACH,OAAO;GAAE,QAAQ;GAAc,SAAS;EAAS;EACnD,KAAK;EACL,KAAK,kBACH,OAAO;GAAE,QAAQ;GAAc,SAAS;EAAiB;EAC3D,KAAK,aACH,OAAO;GAAE,QAAQ;GAAc,SAAS;EAAU;EACpD,KAAK,SACH,OAAO,EAAE,QAAQ,QAAQ;EAC3B,SACE,OAAO,EACL,QAAQ,MAAM,iBAAiB,KAAA,IAAY,iBAAiB,YAC9D;CACJ;AACF;AAEA,MAAM,4BAA4B;AAClC,MAAM,uBAAuB;;;;;AAM7B,SAAgB,iBAAiB,OAG/B;CACA,IAAI,SAAS,MAAM,OAAO,CAAC;CAC3B,MAAM,SACJ,OAAO,UAAU,WAAY,QAAoC,KAAA;CACnE,MAAM,UACJ,OAAO,UAAU,WACb,QACA,OAAO,QAAQ,YAAY,WACzB,OAAO,UACP,KAAA;CACR,MAAM,OACJ,OAAO,QAAQ,SAAS,WACpB,OAAO,OACP,OAAO,QAAQ,SAAS,YAAY,OAAO,SAAS,UAClD,OAAO,OACP,KAAA;CACR,OAAO;EACL,GAAI,UACA,EAAE,OAAO,QAAQ,MAAM,GAAG,oBAAoB,EAAE,IAChD,KAAA;EACJ,GAAI,OACA,EAAE,WAAW,KAAK,MAAM,GAAG,yBAAyB,EAAE,IACtD,KAAA;CACN;AACF;;;;;AAMA,SAAgB,yBAAyB,OAAuB;CAC9D,IAAI,MAAM,UAAU,2BAA2B,OAAO;CACtD,OAAO,MAAM,MAAM,GAAG,yBAAyB;AACjD;AAEA,SAAS,cAAc,OAAoC;CACzD,IAAI,SAAS,MAAM,OAAO,KAAA;CAC1B,IAAI;EACF,OAAO,yBAAyB,KAAK,UAAU,KAAK,CAAC;CACvD,QAAQ;EACN;CACF;AACF;AAEA,SAAS,mBAAmB,OAAoC;CAC9D,IAAI,SAAS,MAAM,OAAO,KAAA;CAC1B,IAAI;EACF,MAAM,SAAS,OAAO,UAAU,WAAW,KAAK,MAAM,KAAK,IAAI;EAC/D,IAAI,MAAM,QAAQ,MAAM,GAAG;GACzB,MAAM,aAAa,OAAO,KAAK,SAAS;IACtC,IAAI,QAAQ,OAAO,SAAS,YAAY,KAAK,MAExC;UAAA,KAAK,SAAS,WAAW,KAAK,SAAS,YACxC,OAAO,KAAK,SAAS,YACrB,eAAe,KAAK,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,GAC3C;MACA,MAAM,UAAW,KAAK,KAAK,SAAS,IAAK,IAAI,KAAA,CAAM,QAAQ,CAAC;MAC5D,OAAO;OAAE,GAAG;OAAM,MAAM,IAAI,KAAK,KAAK,IAAI,OAAO;MAAK;KACxD;;IAEF,OAAO;GACT,CAAC;GACD,OAAO,yBAAyB,KAAK,UAAU,UAAU,CAAC;EAC5D;CACF,QAAQ,CAER;CACA,OAAO,cAAc,KAAK;AAC5B;;;;;;AAoBA,SAAgB,2BACd,MACiC;CACjC,MAAM,EAAE,UAAU,YAAY,MAAM,UAAU,QAAQ,eAAe;CACrE,MAAM,OAAwC;EAC5C,WAAW;EACX,cAAc;CAChB;CACA,MAAM,WACJ,YAAY,OAAO,yBAAyB,QAAQ,IAAI,cAAc,IAAI;CAC5E,IAAI,aAAa,KAAA,GAAW,KAAK,YAAY;CAC7C,MAAM,aACJ,eAAe,QAAQ,mBAAmB,MAAM,IAAI,cAAc,MAAM;CAC1E,IAAI,eAAe,KAAA,GAAW,KAAK,cAAc;CACjD,IAAI,YAAY,KAAK,cAAc;CACnC,OAAO;AACT;;;;;;;;AASA,SAAgB,2BACd,UACoB;CACpB,IAAI,CAAC,UAAU,OAAO,KAAA;CACtB,IAAI,OAAO,SAAS,YAAY,UAAU,OAAO,SAAS;CAC1D,MAAM,SAAS,SAAS;CACxB,IAAI,OAAO,QAAQ,YAAY,UAAU,OAAO,OAAO;CAEvD,MAAM,QAAiB,SAAS;CAChC,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,KAAA;CAClC,KAAK,MAAM,QAAQ,OAAoB;EACrC,IAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;EACvC,MAAM,WAAY,KAAiC;EACnD,IAAI,CAAC,YAAY,OAAO,aAAa,UAAU;EAC/C,MAAM,UAAW,SAAqC;EACtD,IAAI,OAAO,YAAY,UAAU,OAAO;CAC1C;AAEF;AAkEA,SAAS,YACP,QACA,OACM;CACN,IAAI,CAAC,OAAO;CACZ,MAAM,aAAa,2BAA2B,KAAK;CACnD,IAAI,CAAC,YAAY;CACjB,IAAI,WAAW,gBAAgB,KAAA,GAC7B,OAAO,eAAe,WAAW;CAEnC,IAAI,WAAW,iBAAiB,KAAA,GAC9B,OAAO,gBAAgB,WAAW;CAEpC,IAAI,WAAW,oBAAoB,KAAA,GACjC,OAAO,mBAAmB,WAAW;CAEvC,IAAI,WAAW,sBAAsB,KAAA,GACnC,OAAO,sBAAsB,WAAW;AAE5C;AAEA,SAAS,oBACP,MACuD;CACvD,MAAM,OAA8D,CAAC;CACrE,MAAM,QAAQ,KAAK,QAAQ,2BAA2B,KAAK,KAAK,IAAI,KAAA;CACpE,IAAI,OAAO,gBAAgB,KAAA,GAAW,KAAK,eAAe,MAAM;CAChE,IAAI,OAAO,iBAAiB,KAAA,GAC1B,KAAK,gBAAgB,MAAM;CAC7B,IAAI,OAAO,oBAAoB,KAAA,GAC7B,KAAK,mBAAmB,MAAM;CAEhC,IAAI,OAAO,sBAAsB,KAAA,GAC/B,KAAK,sBAAsB,MAAM;CAEnC,IAAI,KAAK,cAAc,KAAA,GAAW,KAAK,aAAa,KAAK;CACzD,IAAI,KAAK,YAAY,KAAA,GAAW,KAAK,WAAW,KAAK;CACrD,IAAI,KAAK,UAAU,KAAA,GAAW,KAAK,SAAS,KAAK;CACjD,IAAI,KAAK,iBAAiB,KAAA,GACxB,KAAK,gBAAgB,KAAK,aAAa,MAAM,GAAG,EAAE;CAEpD,OAAO;AACT;AAEA,SAAS,uBACP,MACsB;CACtB,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,MAAM,SAAmB,CAAC;CAC1B,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,aAAa,IAAI,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK;EAChD,IAAI,CAAC,cAAc,KAAK,IAAI,UAAU,GAAG;EACzC,KAAK,IAAI,UAAU;EACnB,OAAO,KAAK,UAAU;EACtB,IAAI,OAAO,WAAW,IAAI;CAC5B;CACA,OAAO,OAAO,SAAS,IAAI,SAAS,KAAA;AACtC;AAEA,SAAS,+BACP,OACoB;CACpB,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,SAAS,KAAK,GAAG,OAAO,KAAA;CAC3D,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC;AACtC;AAEA,SAAgB,gBAAgB,MAA8C;CAC5E,MAAM,SAAkC;EACtC,WAAW,KAAK;EAChB,QAAQ,KAAK;CACf;CACA,MAAM,UAAU,KAAK,SAAS,YAAY;CAC1C,IAAI,WAAW,iBAAiB,KAAK,OAAO,GAAG,OAAO,WAAW;CACjE,IAAI,KAAK,YAAY,KAAA,GAAW,OAAO,eAAe,KAAK;CAC3D,IAAI,KAAK,cAAc,KAAA,GAAW,OAAO,aAAa,KAAK;CAC3D,IAAI,KAAK,UAAU,KAAA,GAAW,OAAO,QAAQ,KAAK;CAClD,IAAI,KAAK,cAAc,KAAA,GAAW,OAAO,aAAa,KAAK;CAC3D,IAAI,KAAK,YAAY,KAAA,GAAW,OAAO,WAAW,KAAK;CACvD,IAAI,KAAK,aAAa,KAAA,GAAW;EAC/B,OAAO,WAAW,KAAK;EACvB,OAAO,gBAAgB,KAAK;CAC9B;CACA,YAAY,QAAQ,KAAK,KAAK;CAC9B,IAAI,KAAK,UAAU,KAAA,GAAW;EAC5B,OAAO,QAAQ,KAAK,MAAM,IAAI,mBAAmB;EACjD,OAAO,cAAc,KAAK,MAAM;CAClC,OAAO,IAAI,KAAK,eAAe,KAAA,GAC7B,OAAO,cAAc,KAAK;CAE5B,IAAI,KAAK,cAAc,KAAA,GAAW,OAAO,aAAa,KAAK;CAC3D,MAAM,aAAa,+BAA+B,KAAK,UAAU;CACjE,IAAI,eAAe,KAAA,GAAW,OAAO,cAAc;CACnD,MAAM,eAAe,+BAA+B,KAAK,YAAY;CACrE,IAAI,iBAAiB,KAAA,GAAW,OAAO,iBAAiB;CACxD,IAAI,KAAK,eAAe,KAAA,GACtB,OAAO,cAAc,yBAAyB,KAAK,UAAU;CAE/D,IAAI,KAAK,aAAa,KAAA,GAAW,OAAO,WAAW,KAAK;CACxD,IAAI,KAAK,WAAW,gBAAgB,KAAA,GAClC,OAAO,cAAc,KAAK,UAAU;CAEtC,IAAI,KAAK,WAAW,YAAY,KAAA,GAC9B,OAAO,UAAU,KAAK,UAAU;CAElC,MAAM,OAAO,uBAAuB,KAAK,WAAW,IAAI;CACxD,IAAI,SAAS,KAAA,GAAW,OAAO,OAAO;CACtC,OAAO;AACT;;;;;;;AAQA,SAAgB,2BACd,OAC+B;CAC/B,MAAM,cAAc,MAAM,eAAe,MAAM;CAC/C,MAAM,eAAe,MAAM,gBAAgB,MAAM;CAEjD,MAAM,kBACJ,MAAM,mBAAmB,MAAM,oBAAoB;CACrD,MAAM,oBACJ,MAAM,qBAAqB,MAAM,mBAAmB;CAEtD,IACE,eAAe,QACf,gBAAgB,QAChB,mBAAmB,QACnB,qBAAqB,MAErB;CAGF,OAAO;EACL,GAAI,eAAe,OAAO,EAAE,YAAY,IAAI,KAAA;EAC5C,GAAI,gBAAgB,OAAO,EAAE,aAAa,IAAI,KAAA;EAC9C,GAAI,mBAAmB,OAAO,EAAE,gBAAgB,IAAI,KAAA;EACpD,GAAI,qBAAqB,OAAO,EAAE,kBAAkB,IAAI,KAAA;CAC1D;AACF"}
1
+ {"version":3,"file":"runTelemetry.js","names":[],"sources":["../src/runTelemetry.ts"],"sourcesContent":["import type { SamplingCallData } from \"./instrumentMcpSampling\";\nimport type { AssistantCloudRunReport } from \"./AssistantCloudRuns\";\n\nconst MAX_TELEMETRY_TEXT_LENGTH = 50_000;\n\nconst BASE64_PATTERN = /^[A-Za-z0-9+/]+={0,2}$/;\n\nexport type AssistantCloudRunReportToolCall = {\n tool_name: string;\n tool_call_id: string;\n tool_args?: string;\n tool_result?: string;\n tool_source?: \"mcp\" | \"frontend\" | \"backend\";\n start_ms?: number;\n end_ms?: number;\n sampling_calls?: SamplingCallData[];\n};\n\nexport type RunReportOutcome =\n | \"aborted\"\n | \"disconnected\"\n | \"length\"\n | \"content_filter\";\n\n/**\n * Maps a finish event to the report status and outcome. `fallbackStatus`\n * applies when the event carries neither a finish reason nor a failure flag.\n */\nexport function deriveRunOutcome(\n input: {\n finishReason?: string | undefined;\n isAbort?: boolean | undefined;\n isDisconnect?: boolean | undefined;\n isError?: boolean | undefined;\n },\n fallbackStatus: \"completed\" | \"incomplete\" = \"completed\",\n): {\n status: \"completed\" | \"incomplete\" | \"error\";\n outcome?: RunReportOutcome;\n} {\n if (input.isError) return { status: \"error\" };\n if (input.isAbort) return { status: \"incomplete\", outcome: \"aborted\" };\n if (input.isDisconnect) {\n return { status: \"incomplete\", outcome: \"disconnected\" };\n }\n switch (input.finishReason) {\n case \"length\":\n return { status: \"incomplete\", outcome: \"length\" };\n case \"content-filter\":\n case \"content_filter\":\n return { status: \"incomplete\", outcome: \"content_filter\" };\n case \"cancelled\":\n return { status: \"incomplete\", outcome: \"aborted\" };\n case \"error\":\n return { status: \"error\" };\n default:\n return {\n status: input.finishReason === undefined ? fallbackStatus : \"completed\",\n };\n }\n}\n\nconst MAX_RUN_ERROR_CODE_LENGTH = 64;\nconst MAX_RUN_ERROR_LENGTH = 2048;\n\n/**\n * Reads the message and code the runs endpoint stores for a failed run. The\n * code is the error's `code` when it has one, else its class name.\n */\nexport function describeRunError(error: unknown): {\n error?: string;\n errorCode?: string;\n} {\n if (error == null) return {};\n const record =\n typeof error === \"object\" ? (error as Record<string, unknown>) : undefined;\n const message =\n typeof error === \"string\"\n ? error\n : typeof record?.message === \"string\"\n ? record.message\n : undefined;\n const code =\n typeof record?.code === \"string\"\n ? record.code\n : typeof record?.name === \"string\" && record.name !== \"Error\"\n ? record.name\n : undefined;\n return {\n ...(message\n ? { error: message.slice(0, MAX_RUN_ERROR_LENGTH) }\n : undefined),\n ...(code\n ? { errorCode: code.slice(0, MAX_RUN_ERROR_CODE_LENGTH) }\n : undefined),\n };\n}\n\n/**\n * Clamps a string to the size the runs endpoint accepts for a single span\n * field.\n */\nexport function truncateRunTelemetryText(value: string): string {\n if (value.length <= MAX_TELEMETRY_TEXT_LENGTH) return value;\n return value.slice(0, MAX_TELEMETRY_TEXT_LENGTH);\n}\n\nfunction safeStringify(value: unknown): string | undefined {\n if (value == null) return undefined;\n try {\n return truncateRunTelemetryText(JSON.stringify(value));\n } catch {\n return undefined;\n }\n}\n\nconst base64SizeKB = (value: string) =>\n ((value.length * 3) / 4 / 1024).toFixed(1);\n\n// Both call sites read a field the MCP content grammar already defines as\n// base64, so the test only has to recognise the encoding's own shape: its\n// alphabet, and a length that is a multiple of four. A size floor would leave\n// a short payload — `aGk=` is a whole image in this repo's own fixtures —\n// serialized raw.\nconst isInlineBase64 = (value: unknown): value is string => {\n if (typeof value !== \"string\") return false;\n const head = value.slice(0, 200);\n return head.length > 0 && head.length % 4 === 0 && BASE64_PATTERN.test(head);\n};\n\nfunction summarizeMcpContentBlock(item: unknown): unknown {\n if (!item || typeof item !== \"object\") return item;\n const block = item as {\n type?: unknown;\n data?: unknown;\n resource?: unknown;\n };\n if (\n (block.type === \"image\" || block.type === \"audio\") &&\n isInlineBase64(block.data)\n ) {\n return {\n ...block,\n data: `[${String(block.type)}: ${base64SizeKB(block.data)}KB]`,\n };\n }\n // An EmbeddedResource is the third inline carrier: a binary resource arrives\n // as base64 under `resource.blob` rather than as a top-level `data` field.\n if (\n block.type === \"resource\" &&\n block.resource &&\n typeof block.resource === \"object\"\n ) {\n const resource = block.resource as { blob?: unknown };\n if (isInlineBase64(resource.blob)) {\n return {\n ...block,\n resource: {\n ...resource,\n blob: `[resource: ${base64SizeKB(resource.blob)}KB]`,\n },\n };\n }\n }\n return item;\n}\n\nfunction summarizeMcpResult(value: unknown): string | undefined {\n if (value == null) return undefined;\n try {\n const parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n if (Array.isArray(parsed)) {\n return truncateRunTelemetryText(\n JSON.stringify(parsed.map(summarizeMcpContentBlock)),\n );\n }\n // `callTool` resolves to a CallToolResult, so the blocks carrying base64\n // arrive under `content` rather than as the result itself.\n if (typeof parsed === \"object\") {\n const content = (parsed as { content?: unknown }).content;\n if (Array.isArray(content)) {\n return truncateRunTelemetryText(\n JSON.stringify({\n ...(parsed as Record<string, unknown>),\n content: content.map(summarizeMcpContentBlock),\n }),\n );\n }\n }\n } catch {\n // not a shape with summarizable content, fall through\n }\n return safeStringify(value);\n}\n\nexport type RunTelemetryToolCallInit = {\n toolName: string;\n toolCallId: string;\n args?: unknown;\n /**\n * Pre-serialized arguments, used in place of serializing `args`. Values over\n * the span size are clamped before they are included in the report.\n */\n argsText?: string | undefined;\n result?: unknown;\n toolSource?: \"mcp\" | \"frontend\" | \"backend\" | undefined;\n};\n\n/**\n * Serializes one tool call into the shape the runs endpoint accepts. An `mcp`\n * source has its result summarized, because MCP content blocks carry inline\n * base64 image and audio payloads that would otherwise dominate the report.\n */\nexport function createRunTelemetryToolCall(\n init: RunTelemetryToolCallInit,\n): AssistantCloudRunReportToolCall {\n const { toolName, toolCallId, args, argsText, result, toolSource } = init;\n const call: AssistantCloudRunReportToolCall = {\n tool_name: toolName,\n tool_call_id: toolCallId,\n };\n const toolArgs =\n argsText != null ? truncateRunTelemetryText(argsText) : safeStringify(args);\n if (toolArgs !== undefined) call.tool_args = toolArgs;\n const toolResult =\n toolSource === \"mcp\" ? summarizeMcpResult(result) : safeStringify(result);\n if (toolResult !== undefined) call.tool_result = toolResult;\n if (toolSource) call.tool_source = toolSource;\n return call;\n}\n\n/**\n * Resolves the model ID a run reports, in the order an app can supply it: an\n * explicit `modelId`, the `custom` bag, then the per-step `response.modelId`\n * that a `messageMetadata` callback copies off the AI SDK's finish-step part.\n * The AI SDK puts no model ID on a UI message part, so message metadata is the\n * only channel one arrives on.\n */\nexport function extractRunTelemetryModelId(\n metadata: Record<string, unknown> | undefined,\n): string | undefined {\n if (!metadata) return undefined;\n if (typeof metadata.modelId === \"string\") return metadata.modelId;\n const custom = metadata.custom as Record<string, unknown> | undefined;\n if (typeof custom?.modelId === \"string\") return custom.modelId;\n\n const steps: unknown = metadata.steps;\n if (!Array.isArray(steps)) return undefined;\n for (const step of steps as unknown[]) {\n if (!step || typeof step !== \"object\") continue;\n const response = (step as Record<string, unknown>).response;\n if (!response || typeof response !== \"object\") continue;\n const modelId = (response as Record<string, unknown>).modelId;\n if (typeof modelId === \"string\") return modelId;\n }\n return undefined;\n}\n\nexport type RunTelemetryUsage = {\n inputTokens?: number | undefined;\n outputTokens?: number | undefined;\n reasoningTokens?: number | undefined;\n cachedInputTokens?: number | undefined;\n};\n\nexport type RunTelemetryUsageInit = RunTelemetryUsage & {\n promptTokens?: number | undefined;\n completionTokens?: number | undefined;\n inputTokenDetails?: { cacheReadTokens?: number };\n outputTokenDetails?: { reasoningTokens?: number };\n};\n\nexport type RunReportStepInit = {\n usage?: RunTelemetryUsageInit | undefined;\n toolCalls?: AssistantCloudRunReportToolCall[] | undefined;\n startMs?: number | undefined;\n endMs?: number | undefined;\n finishReason?: string | undefined;\n input?: string | undefined;\n};\n\n/**\n * The run report fields read from the messages of one run, in whichever\n * format they were stored: the status the messages imply, the tool calls, the\n * steps, the text, the usage and the model.\n */\nexport type RunMessageTelemetry = {\n assistantMessageId?: string;\n status: \"completed\" | \"incomplete\";\n toolCalls?: AssistantCloudRunReportToolCall[];\n steps?: RunReportStepInit[];\n totalSteps?: number;\n outputText?: string;\n usage?: RunTelemetryUsage;\n modelId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type RunReportInit = {\n threadId: string;\n status: AssistantCloudRunReport[\"status\"];\n outcome?: AssistantCloudRunReport[\"outcome_type\"] | undefined;\n errorCode?: string | undefined;\n error?: string | undefined;\n messageId?: string | undefined;\n traceId?: string | undefined;\n rootSpanId?: string | undefined;\n modelId?: string | undefined;\n provider?: string | undefined;\n usage?: RunTelemetryUsageInit | undefined;\n steps?: RunReportStepInit[] | undefined;\n totalSteps?: number | undefined;\n toolCalls?: AssistantCloudRunReportToolCall[] | undefined;\n durationMs?: number | undefined;\n firstTokenMs?: number | undefined;\n costUsd?: number | undefined;\n costDetails?:\n | {\n input?: number | undefined;\n inputCachedTokens?: number | undefined;\n output?: number | undefined;\n total?: number | undefined;\n }\n | undefined;\n outputText?: string | undefined;\n attributes?: Record<string, unknown> | undefined;\n metadata?: Record<string, unknown> | undefined;\n telemetry?: {\n environment?: string | undefined;\n release?: string | undefined;\n tags?: readonly string[] | undefined;\n };\n};\n\nfunction assignUsage(\n report: AssistantCloudRunReport,\n usage: RunTelemetryUsageInit | undefined,\n): void {\n if (!usage) return;\n const normalized = normalizeRunTelemetryUsage(usage);\n if (!normalized) return;\n if (normalized.inputTokens !== undefined) {\n report.input_tokens = normalized.inputTokens;\n }\n if (normalized.outputTokens !== undefined) {\n report.output_tokens = normalized.outputTokens;\n }\n if (normalized.reasoningTokens !== undefined) {\n report.reasoning_tokens = normalized.reasoningTokens;\n }\n if (normalized.cachedInputTokens !== undefined) {\n report.cached_input_tokens = normalized.cachedInputTokens;\n }\n}\n\nfunction createRunReportStep(\n init: RunReportStepInit,\n): NonNullable<AssistantCloudRunReport[\"steps\"]>[number] {\n const step: NonNullable<AssistantCloudRunReport[\"steps\"]>[number] = {};\n const usage = init.usage ? normalizeRunTelemetryUsage(init.usage) : undefined;\n if (usage?.inputTokens !== undefined) step.input_tokens = usage.inputTokens;\n if (usage?.outputTokens !== undefined)\n step.output_tokens = usage.outputTokens;\n if (usage?.reasoningTokens !== undefined) {\n step.reasoning_tokens = usage.reasoningTokens;\n }\n if (usage?.cachedInputTokens !== undefined) {\n step.cached_input_tokens = usage.cachedInputTokens;\n }\n if (init.toolCalls !== undefined) step.tool_calls = init.toolCalls;\n if (init.startMs !== undefined) step.start_ms = init.startMs;\n if (init.endMs !== undefined) step.end_ms = init.endMs;\n if (init.finishReason !== undefined) {\n step.finish_reason = init.finishReason.slice(0, 32);\n }\n if (init.input !== undefined) {\n step.input = truncateRunTelemetryText(init.input);\n }\n return step;\n}\n\nfunction normalizeRunReportTags(\n tags: readonly string[] | undefined,\n): string[] | undefined {\n if (!tags) return undefined;\n const result: string[] = [];\n const seen = new Set<string>();\n for (const tag of tags) {\n const normalized = tag.trim().slice(0, 64).trim();\n if (!normalized || seen.has(normalized)) continue;\n seen.add(normalized);\n result.push(normalized);\n if (result.length === 20) break;\n }\n return result.length > 0 ? result : undefined;\n}\n\nfunction normalizeRunReportMilliseconds(\n value: number | undefined,\n): number | undefined {\n if (value === undefined || !Number.isFinite(value)) return undefined;\n return Math.max(0, Math.round(value));\n}\n\nfunction normalizeRunReportCost(value: number | undefined): number | undefined {\n if (value === undefined || !Number.isFinite(value) || value < 0) {\n return undefined;\n }\n return value;\n}\n\nfunction assignCostDetails(\n report: AssistantCloudRunReport,\n costDetails: RunReportInit[\"costDetails\"],\n): void {\n if (!costDetails) return;\n const normalized: NonNullable<AssistantCloudRunReport[\"cost_details\"]> = {};\n const input = normalizeRunReportCost(costDetails.input);\n if (input !== undefined) normalized.input = input;\n const inputCachedTokens = normalizeRunReportCost(\n costDetails.inputCachedTokens,\n );\n if (inputCachedTokens !== undefined) {\n normalized.input_cached_tokens = inputCachedTokens;\n }\n const output = normalizeRunReportCost(costDetails.output);\n if (output !== undefined) normalized.output = output;\n const total = normalizeRunReportCost(costDetails.total);\n if (total !== undefined) normalized.total = total;\n if (Object.keys(normalized).length > 0) report.cost_details = normalized;\n}\n\nexport function createRunReport(init: RunReportInit): AssistantCloudRunReport {\n const report: AssistantCloudRunReport = {\n thread_id: init.threadId,\n status: init.status,\n };\n const traceId = init.traceId?.toLowerCase();\n if (traceId && /^[0-9a-f]{32}$/.test(traceId)) report.trace_id = traceId;\n const rootSpanId = init.rootSpanId?.toLowerCase();\n if (rootSpanId && /^[0-9a-f]{16}$/.test(rootSpanId)) {\n report.root_span_id = rootSpanId;\n }\n if (init.outcome !== undefined) report.outcome_type = init.outcome;\n if (init.errorCode !== undefined) report.error_code = init.errorCode;\n if (init.error !== undefined) report.error = init.error;\n if (init.messageId !== undefined) report.message_id = init.messageId;\n if (init.modelId !== undefined) report.model_id = init.modelId;\n if (init.provider !== undefined) {\n report.provider = init.provider;\n report.provider_type = init.provider;\n }\n assignUsage(report, init.usage);\n if (init.steps !== undefined) {\n report.steps = init.steps.map(createRunReportStep);\n report.total_steps = init.steps.length;\n } else if (init.totalSteps !== undefined) {\n report.total_steps = init.totalSteps;\n }\n if (init.toolCalls !== undefined) report.tool_calls = init.toolCalls;\n const durationMs = normalizeRunReportMilliseconds(init.durationMs);\n if (durationMs !== undefined) report.duration_ms = durationMs;\n const firstTokenMs = normalizeRunReportMilliseconds(init.firstTokenMs);\n if (firstTokenMs !== undefined) report.first_token_ms = firstTokenMs;\n const costUsd = normalizeRunReportCost(init.costUsd);\n if (costUsd !== undefined) report.cost_usd = costUsd;\n assignCostDetails(report, init.costDetails);\n if (init.outputText !== undefined) {\n report.output_text = truncateRunTelemetryText(init.outputText);\n }\n if (init.attributes !== undefined) report.attributes = init.attributes;\n if (init.metadata !== undefined) report.metadata = init.metadata;\n if (init.telemetry?.environment !== undefined) {\n report.environment = init.telemetry.environment;\n }\n if (init.telemetry?.release !== undefined) {\n report.release = init.telemetry.release;\n }\n const tags = normalizeRunReportTags(init.telemetry?.tags);\n if (tags !== undefined) report.tags = tags;\n return report;\n}\n\n/**\n * Resolves the token counts a provider reports under any of the names the AI\n * SDK has used: the current top-level ones, the legacy prompt/completion pair,\n * and the v7 token detail objects. Returns undefined when no count is present,\n * so callers can tell an empty usage object from a zeroed one.\n */\nexport function normalizeRunTelemetryUsage(\n usage: RunTelemetryUsageInit,\n): RunTelemetryUsage | undefined {\n const inputTokens = usage.inputTokens ?? usage.promptTokens;\n const outputTokens = usage.outputTokens ?? usage.completionTokens;\n // AI SDK v7 moved these under token detail objects; v6 kept them top-level.\n const reasoningTokens =\n usage.reasoningTokens ?? usage.outputTokenDetails?.reasoningTokens;\n const cachedInputTokens =\n usage.cachedInputTokens ?? usage.inputTokenDetails?.cacheReadTokens;\n\n if (\n inputTokens == null &&\n outputTokens == null &&\n reasoningTokens == null &&\n cachedInputTokens == null\n ) {\n return undefined;\n }\n\n return {\n ...(inputTokens != null ? { inputTokens } : undefined),\n ...(outputTokens != null ? { outputTokens } : undefined),\n ...(reasoningTokens != null ? { reasoningTokens } : undefined),\n ...(cachedInputTokens != null ? { cachedInputTokens } : undefined),\n };\n}\n"],"mappings":"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"}