@tangle-network/agent-core 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -0
  3. package/dist/auth/browser.d.ts +22 -0
  4. package/dist/auth/browser.d.ts.map +1 -0
  5. package/dist/auth/browser.js +43 -0
  6. package/dist/auth/browser.js.map +1 -0
  7. package/dist/auth/index.d.ts +430 -0
  8. package/dist/auth/index.d.ts.map +1 -0
  9. package/dist/auth/index.js +841 -0
  10. package/dist/auth/index.js.map +1 -0
  11. package/dist/computer-use/index.d.ts +122 -0
  12. package/dist/computer-use/index.d.ts.map +1 -0
  13. package/dist/computer-use/index.js +422 -0
  14. package/dist/computer-use/index.js.map +1 -0
  15. package/dist/errors-DJ6U6cHY.js +146 -0
  16. package/dist/errors-DJ6U6cHY.js.map +1 -0
  17. package/dist/events/index.d.ts +2 -0
  18. package/dist/events/index.js +2 -0
  19. package/dist/events-CUWh9qrv.js +263 -0
  20. package/dist/events-CUWh9qrv.js.map +1 -0
  21. package/dist/index-CFA8kgHJ.d.ts +352 -0
  22. package/dist/index-CFA8kgHJ.d.ts.map +1 -0
  23. package/dist/index-CtebBodu.d.ts +108 -0
  24. package/dist/index-CtebBodu.d.ts.map +1 -0
  25. package/dist/index-DiQX9bjq.d.ts +55 -0
  26. package/dist/index-DiQX9bjq.d.ts.map +1 -0
  27. package/dist/index-DlPznmKA.d.ts +158 -0
  28. package/dist/index-DlPznmKA.d.ts.map +1 -0
  29. package/dist/index-z2wPdzFb.d.ts +133 -0
  30. package/dist/index-z2wPdzFb.d.ts.map +1 -0
  31. package/dist/index.d.ts +565 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +822 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/resilience/index.d.ts +2 -0
  36. package/dist/resilience/index.js +2 -0
  37. package/dist/resilience-BQzDfw_C.js +221 -0
  38. package/dist/resilience-BQzDfw_C.js.map +1 -0
  39. package/dist/sse/index.d.ts +174 -0
  40. package/dist/sse/index.d.ts.map +1 -0
  41. package/dist/sse/index.js +303 -0
  42. package/dist/sse/index.js.map +1 -0
  43. package/dist/transport/index.d.ts +2 -0
  44. package/dist/transport/index.js +2 -0
  45. package/dist/transport-mKLoQep5.js +427 -0
  46. package/dist/transport-mKLoQep5.js.map +1 -0
  47. package/dist/types/index.d.ts +2 -0
  48. package/dist/types/index.js +2 -0
  49. package/dist/types-D5VLaol0.js +31 -0
  50. package/dist/types-D5VLaol0.js.map +1 -0
  51. package/dist/types-DC6OJ1um.js +331 -0
  52. package/dist/types-DC6OJ1um.js.map +1 -0
  53. package/dist/types-DiDSGM8K.d.ts +320 -0
  54. package/dist/types-DiDSGM8K.d.ts.map +1 -0
  55. package/package.json +132 -0
@@ -0,0 +1,303 @@
1
+ //#region src/sse/index.ts
2
+ /**
3
+ * Parse raw SSE data string into structured event data.
4
+ *
5
+ * Handles the standard SSE format:
6
+ * ```
7
+ * event: eventType
8
+ * data: {"json": "payload"}
9
+ * ```
10
+ */
11
+ function parseSSEData(rawData) {
12
+ try {
13
+ const lines = rawData.split("\n");
14
+ let eventType;
15
+ let data;
16
+ for (const line of lines) if (line.startsWith("event: ")) eventType = line.slice(7).trim();
17
+ else if (line.startsWith("data: ")) data = line.slice(6);
18
+ if (data) {
19
+ const parsed = JSON.parse(data);
20
+ return {
21
+ type: eventType || parsed.type || "unknown",
22
+ ...parsed
23
+ };
24
+ }
25
+ } catch {}
26
+ return null;
27
+ }
28
+ /**
29
+ * Incremental SSE parser for chunked streams.
30
+ * Feed decoded string chunks via push(); call flush() on stream end.
31
+ */
32
+ var SSEChunkParser = class {
33
+ buffer = "";
34
+ currentEvent = {};
35
+ options;
36
+ constructor(options = {}) {
37
+ this.options = options;
38
+ }
39
+ push(chunk) {
40
+ this.buffer += chunk;
41
+ const lines = this.buffer.split("\n");
42
+ this.buffer = lines.pop() ?? "";
43
+ return this.processLines(lines);
44
+ }
45
+ flush() {
46
+ const lines = this.buffer ? [this.buffer] : [];
47
+ this.buffer = "";
48
+ const events = this.processLines(lines);
49
+ const finalEvent = this.parseCurrentEvent();
50
+ if (finalEvent) {
51
+ events.push(finalEvent);
52
+ this.currentEvent = {};
53
+ }
54
+ return events;
55
+ }
56
+ processLines(lines) {
57
+ const events = [];
58
+ for (const rawLine of lines) {
59
+ const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
60
+ if (line.startsWith(":")) continue;
61
+ if (line === "") {
62
+ const parsed = this.parseCurrentEvent();
63
+ if (parsed) events.push(parsed);
64
+ this.currentEvent = {};
65
+ continue;
66
+ }
67
+ if (line.startsWith("id:")) {
68
+ this.currentEvent.id = line.slice(3).trim();
69
+ continue;
70
+ }
71
+ if (line.startsWith("event:")) {
72
+ this.currentEvent.event = line.slice(6).trim();
73
+ continue;
74
+ }
75
+ if (line.startsWith("data:")) {
76
+ let value = line.slice(5);
77
+ if (value.startsWith(" ")) value = value.slice(1);
78
+ this.currentEvent.data = this.currentEvent.data !== void 0 ? `${this.currentEvent.data}\n${value}` : value;
79
+ }
80
+ }
81
+ return events;
82
+ }
83
+ parseCurrentEvent() {
84
+ if (this.currentEvent.data === void 0) return null;
85
+ const rawData = this.currentEvent.data.trim();
86
+ if (!rawData) return null;
87
+ let data;
88
+ if (this.options.transform) {
89
+ const transformed = this.options.transform(rawData);
90
+ if (transformed === null) {
91
+ if (this.options.logMalformed) console.warn("SSE transform returned null:", rawData.slice(0, 100));
92
+ return null;
93
+ }
94
+ data = transformed;
95
+ } else try {
96
+ data = JSON.parse(rawData);
97
+ } catch {
98
+ if (this.options.logMalformed) console.warn("SSE parse failed:", rawData.slice(0, 100));
99
+ data = rawData;
100
+ }
101
+ return {
102
+ data,
103
+ rawData,
104
+ eventId: this.currentEvent.id,
105
+ eventType: this.currentEvent.event
106
+ };
107
+ }
108
+ };
109
+ /**
110
+ * Parse SSE stream into typed events via async iteration.
111
+ */
112
+ async function* parseSSEStream(stream, options = {}) {
113
+ const reader = stream.getReader();
114
+ const decoder = new TextDecoder();
115
+ const parser = new SSEChunkParser(options);
116
+ let chunkCount = 0;
117
+ let totalBytes = 0;
118
+ try {
119
+ while (true) {
120
+ const { done, value } = await reader.read();
121
+ if (done) {
122
+ console.log(`[agent-core:sse] Stream reader done after ${chunkCount} chunks, ${totalBytes} bytes`);
123
+ break;
124
+ }
125
+ chunkCount++;
126
+ totalBytes += value?.length ?? 0;
127
+ const chunk = decoder.decode(value, { stream: true });
128
+ if (chunkCount <= 3 || chunkCount % 10 === 0) console.log(`[agent-core:sse] Chunk ${chunkCount}: ${value?.length ?? 0} bytes, preview: ${chunk.slice(0, 100).replace(/\n/g, "\\n")}`);
129
+ for (const event of parser.push(chunk)) yield event;
130
+ }
131
+ for (const event of parser.flush()) yield event;
132
+ } finally {
133
+ reader.releaseLock();
134
+ }
135
+ }
136
+ /**
137
+ * Consume SSE stream with callbacks.
138
+ */
139
+ async function consumeSSEStream(stream, onEvent, onError, options = {}) {
140
+ let eventCount = 0;
141
+ try {
142
+ for await (const event of parseSSEStream(stream, options)) {
143
+ eventCount++;
144
+ onEvent(event);
145
+ }
146
+ console.log(`[agent-core:sse] Stream ended normally, total events: ${eventCount}`);
147
+ } catch (error) {
148
+ const normalizedError = error instanceof Error ? error : new Error(String(error));
149
+ if (normalizedError.name === "AbortError" || normalizedError.message.toLowerCase().includes("abort")) {
150
+ console.log(`[agent-core:sse] Stream aborted normally after ${eventCount} events`);
151
+ onError(normalizedError);
152
+ return;
153
+ }
154
+ console.error(`[agent-core:sse] Stream error after ${eventCount} events:`, normalizedError);
155
+ onError(normalizedError);
156
+ }
157
+ }
158
+ /** Event types that contain token information (Anthropic SDK format) */
159
+ const TOKEN_EVENTS = new Set(["message.stop", "content_block_stop"]);
160
+ /**
161
+ * StreamUsageExtractor - Accumulates token usage from SSE events.
162
+ *
163
+ * Usage:
164
+ * ```typescript
165
+ * const extractor = createStreamUsageExtractor();
166
+ *
167
+ * // In your stream callback
168
+ * for await (const event of stream) {
169
+ * extractor.processEvent(event);
170
+ * // ... handle event
171
+ * }
172
+ *
173
+ * const usage = extractor.finalize();
174
+ * billingService.recordUsage({ usage: usage.usage, ... });
175
+ * ```
176
+ */
177
+ var StreamUsageExtractor = class {
178
+ accumulator;
179
+ finalized = false;
180
+ constructor() {
181
+ this.accumulator = {
182
+ usage: {
183
+ inputTokens: 0,
184
+ outputTokens: 0
185
+ },
186
+ responseCount: 0,
187
+ toolCallCount: 0,
188
+ startedAt: /* @__PURE__ */ new Date()
189
+ };
190
+ }
191
+ /**
192
+ * Process a raw SSE string (event: xxx\ndata: {...}).
193
+ */
194
+ processRawSSE(raw) {
195
+ const parsed = parseSSEData(raw);
196
+ if (parsed) this.processEvent(parsed);
197
+ }
198
+ /**
199
+ * Process a parsed SSE event object.
200
+ */
201
+ processEvent(event) {
202
+ if (this.finalized) throw new Error("StreamUsageExtractor already finalized");
203
+ const eventType = event.type ?? event.type;
204
+ if (eventType === "message.part.updated") {
205
+ const part = event.part;
206
+ const partType = part?.type;
207
+ if (partType === "text" || partType === "reasoning") {
208
+ this.extractTokens(event);
209
+ this.accumulator.responseCount++;
210
+ }
211
+ if (partType === "tool" && part?.tool) this.accumulator.toolCallCount++;
212
+ return;
213
+ }
214
+ if (TOKEN_EVENTS.has(eventType)) {
215
+ this.extractTokens(event);
216
+ this.accumulator.responseCount++;
217
+ }
218
+ if (!this.accumulator.modelId && event.model) this.accumulator.modelId = String(event.model);
219
+ if (eventType === "usage" || event.usage) this.extractUsageSummary(event);
220
+ if (eventType === "message_stop" && event.usage) this.extractUsageSummary(event);
221
+ }
222
+ /**
223
+ * Finalize and return accumulated usage.
224
+ * Sets duration and marks extractor as complete.
225
+ */
226
+ finalize() {
227
+ if (this.finalized) return this.accumulator;
228
+ this.finalized = true;
229
+ this.accumulator.durationMs = Date.now() - this.accumulator.startedAt.getTime();
230
+ return this.accumulator;
231
+ }
232
+ /**
233
+ * Get current accumulated usage (without finalizing).
234
+ */
235
+ current() {
236
+ return this.accumulator;
237
+ }
238
+ /**
239
+ * Reset the extractor for reuse.
240
+ */
241
+ reset() {
242
+ this.accumulator = {
243
+ usage: {
244
+ inputTokens: 0,
245
+ outputTokens: 0
246
+ },
247
+ responseCount: 0,
248
+ toolCallCount: 0,
249
+ startedAt: /* @__PURE__ */ new Date()
250
+ };
251
+ this.finalized = false;
252
+ }
253
+ extractTokens(event) {
254
+ if (typeof event.tokens === "number") this.accumulator.usage.outputTokens += event.tokens;
255
+ if (typeof event.outputTokens === "number") this.accumulator.usage.outputTokens += event.outputTokens;
256
+ if (typeof event.output_tokens === "number") this.accumulator.usage.outputTokens += event.output_tokens;
257
+ if (typeof event.inputTokens === "number") this.accumulator.usage.inputTokens = Math.max(this.accumulator.usage.inputTokens, event.inputTokens);
258
+ if (typeof event.input_tokens === "number") this.accumulator.usage.inputTokens = Math.max(this.accumulator.usage.inputTokens, event.input_tokens);
259
+ if (typeof event.cache_read_input_tokens === "number") this.accumulator.usage.cacheReadTokens = (this.accumulator.usage.cacheReadTokens ?? 0) + event.cache_read_input_tokens;
260
+ if (typeof event.cache_creation_input_tokens === "number") this.accumulator.usage.cacheWriteTokens = (this.accumulator.usage.cacheWriteTokens ?? 0) + event.cache_creation_input_tokens;
261
+ }
262
+ extractUsageSummary(event) {
263
+ const usage = event.usage ?? event;
264
+ if (typeof usage.input_tokens === "number") this.accumulator.usage.inputTokens = Math.max(this.accumulator.usage.inputTokens, usage.input_tokens);
265
+ if (typeof usage.output_tokens === "number") this.accumulator.usage.outputTokens = Math.max(this.accumulator.usage.outputTokens, usage.output_tokens);
266
+ if (typeof usage.cache_read_input_tokens === "number") this.accumulator.usage.cacheReadTokens = usage.cache_read_input_tokens;
267
+ if (typeof usage.cache_creation_input_tokens === "number") this.accumulator.usage.cacheWriteTokens = usage.cache_creation_input_tokens;
268
+ }
269
+ };
270
+ /**
271
+ * Create a new StreamUsageExtractor.
272
+ */
273
+ function createStreamUsageExtractor() {
274
+ return new StreamUsageExtractor();
275
+ }
276
+ /**
277
+ * Create a callback wrapper that extracts usage while forwarding events.
278
+ *
279
+ * Usage:
280
+ * ```typescript
281
+ * const { callback, getUsage } = createUsageCallback((event) => {
282
+ * // your event handler
283
+ * });
284
+ *
285
+ * await orchestrator.executeAgentStream(projectRef, request, callback);
286
+ * const usage = getUsage();
287
+ * ```
288
+ */
289
+ function createUsageCallback(forward) {
290
+ const extractor = createStreamUsageExtractor();
291
+ return {
292
+ callback: (event) => {
293
+ extractor.processEvent(event);
294
+ forward?.(event);
295
+ },
296
+ getUsage: () => extractor.finalize(),
297
+ extractor
298
+ };
299
+ }
300
+ //#endregion
301
+ export { SSEChunkParser, StreamUsageExtractor, consumeSSEStream, createStreamUsageExtractor, createUsageCallback, parseSSEData, parseSSEStream };
302
+
303
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/sse/index.ts"],"sourcesContent":["/**\n * SSE Utilities\n *\n * Shared SSE parsing and stream usage extraction for the SDK.\n * Used by sdk-telemetry, sdk-memory, and other consumers.\n */\n\n/** Raw SSE event data from stream */\nexport interface SSEEventData {\n type: string;\n // Tool events\n toolName?: string;\n name?: string;\n callId?: string;\n input?: unknown;\n arguments?: unknown;\n output?: unknown;\n result?: unknown;\n durationMs?: number;\n // Error events\n error?: string;\n message?: string;\n code?: string;\n // Status events\n status?: string;\n // Token/LLM events\n tokens?: number;\n model?: string;\n // Usage fields (Anthropic format)\n inputTokens?: number;\n outputTokens?: number;\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n // Usage object (some providers wrap in usage field)\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n // Generic\n [key: string]: unknown;\n}\n\n/**\n * Parse raw SSE data string into structured event data.\n *\n * Handles the standard SSE format:\n * ```\n * event: eventType\n * data: {\"json\": \"payload\"}\n * ```\n */\nexport function parseSSEData(rawData: string): SSEEventData | null {\n try {\n const lines = rawData.split(\"\\n\");\n let eventType: string | undefined;\n let data: string | undefined;\n\n for (const line of lines) {\n if (line.startsWith(\"event: \")) {\n eventType = line.slice(7).trim();\n } else if (line.startsWith(\"data: \")) {\n data = line.slice(6);\n }\n }\n\n if (data) {\n const parsed = JSON.parse(data);\n return {\n type: eventType || parsed.type || \"unknown\",\n ...parsed,\n };\n }\n } catch {\n // Ignore parse errors (heartbeats, malformed events)\n }\n return null;\n}\n\n// ============================================================================\n// Stream Parsing (chunked SSE)\n// ============================================================================\n\nexport interface SSEParserOptions<T = unknown> {\n /** Log malformed data lines (default: false) */\n logMalformed?: boolean;\n /** Custom data transformer */\n transform?: (raw: string) => T | null;\n}\n\nexport interface ParsedSSEEvent<T = unknown> {\n data: T;\n rawData: string;\n eventId?: string;\n eventType?: string;\n}\n\n/**\n * Incremental SSE parser for chunked streams.\n * Feed decoded string chunks via push(); call flush() on stream end.\n */\nexport class SSEChunkParser<T = unknown> {\n private buffer = \"\";\n private currentEvent: { id?: string; event?: string; data?: string } = {};\n private options: SSEParserOptions<T>;\n\n constructor(options: SSEParserOptions<T> = {}) {\n this.options = options;\n }\n\n push(chunk: string): ParsedSSEEvent<T>[] {\n this.buffer += chunk;\n const lines = this.buffer.split(\"\\n\");\n this.buffer = lines.pop() ?? \"\";\n return this.processLines(lines);\n }\n\n flush(): ParsedSSEEvent<T>[] {\n const lines = this.buffer ? [this.buffer] : [];\n this.buffer = \"\";\n const events = this.processLines(lines);\n const finalEvent = this.parseCurrentEvent();\n if (finalEvent) {\n events.push(finalEvent);\n this.currentEvent = {};\n }\n return events;\n }\n\n private processLines(lines: string[]): ParsedSSEEvent<T>[] {\n const events: ParsedSSEEvent<T>[] = [];\n\n for (const rawLine of lines) {\n const line = rawLine.endsWith(\"\\r\") ? rawLine.slice(0, -1) : rawLine;\n\n if (line.startsWith(\":\")) {\n continue;\n }\n\n if (line === \"\") {\n const parsed = this.parseCurrentEvent();\n if (parsed) {\n events.push(parsed);\n }\n this.currentEvent = {};\n continue;\n }\n\n if (line.startsWith(\"id:\")) {\n this.currentEvent.id = line.slice(3).trim();\n continue;\n }\n\n if (line.startsWith(\"event:\")) {\n this.currentEvent.event = line.slice(6).trim();\n continue;\n }\n\n if (line.startsWith(\"data:\")) {\n let value = line.slice(5);\n if (value.startsWith(\" \")) {\n value = value.slice(1);\n }\n this.currentEvent.data =\n this.currentEvent.data !== undefined\n ? `${this.currentEvent.data}\\n${value}`\n : value;\n }\n }\n\n return events;\n }\n\n private parseCurrentEvent(): ParsedSSEEvent<T> | null {\n if (this.currentEvent.data === undefined) {\n return null;\n }\n\n const rawData = this.currentEvent.data.trim();\n if (!rawData) {\n return null;\n }\n\n let data: T;\n if (this.options.transform) {\n const transformed = this.options.transform(rawData);\n if (transformed === null) {\n if (this.options.logMalformed) {\n console.warn(\"SSE transform returned null:\", rawData.slice(0, 100));\n }\n return null;\n }\n data = transformed;\n } else {\n try {\n data = JSON.parse(rawData) as T;\n } catch {\n if (this.options.logMalformed) {\n console.warn(\"SSE parse failed:\", rawData.slice(0, 100));\n }\n data = rawData as unknown as T;\n }\n }\n\n return {\n data,\n rawData,\n eventId: this.currentEvent.id,\n eventType: this.currentEvent.event,\n };\n }\n}\n\n/**\n * Parse SSE stream into typed events via async iteration.\n */\nexport async function* parseSSEStream<T = unknown>(\n stream: ReadableStream<Uint8Array>,\n options: SSEParserOptions<T> = {},\n): AsyncGenerator<ParsedSSEEvent<T>> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n const parser = new SSEChunkParser<T>(options);\n let chunkCount = 0;\n let totalBytes = 0;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n console.log(\n `[agent-core:sse] Stream reader done after ${chunkCount} chunks, ${totalBytes} bytes`,\n );\n break;\n }\n\n chunkCount++;\n totalBytes += value?.length ?? 0;\n const chunk = decoder.decode(value, { stream: true });\n\n // Log every chunk for debugging\n if (chunkCount <= 3 || chunkCount % 10 === 0) {\n console.log(\n `[agent-core:sse] Chunk ${chunkCount}: ${value?.length ?? 0} bytes, preview: ${chunk.slice(0, 100).replace(/\\n/g, \"\\\\n\")}`,\n );\n }\n\n for (const event of parser.push(chunk)) {\n yield event;\n }\n }\n\n for (const event of parser.flush()) {\n yield event;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Consume SSE stream with callbacks.\n */\nexport async function consumeSSEStream<T = unknown>(\n stream: ReadableStream<Uint8Array>,\n onEvent: (event: ParsedSSEEvent<T>) => void,\n onError: (error: Error) => void,\n options: SSEParserOptions<T> = {},\n): Promise<void> {\n let eventCount = 0;\n try {\n for await (const event of parseSSEStream<T>(stream, options)) {\n eventCount++;\n onEvent(event);\n }\n // Stream finished normally\n console.log(\n `[agent-core:sse] Stream ended normally, total events: ${eventCount}`,\n );\n } catch (error) {\n const normalizedError =\n error instanceof Error ? error : new Error(String(error));\n const isAbortError =\n normalizedError.name === \"AbortError\" ||\n normalizedError.message.toLowerCase().includes(\"abort\");\n\n if (isAbortError) {\n console.log(\n `[agent-core:sse] Stream aborted normally after ${eventCount} events`,\n );\n onError(normalizedError);\n return;\n }\n\n console.error(\n `[agent-core:sse] Stream error after ${eventCount} events:`,\n normalizedError,\n );\n onError(normalizedError);\n }\n}\n\n// ============================================================================\n// Stream Usage Extraction\n// ============================================================================\n\n/** Token usage extracted from stream */\nexport interface StreamTokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n}\n\n/** Accumulated usage from a stream session */\nexport interface StreamUsageAccumulator {\n /** Total tokens from all events */\n usage: StreamTokenUsage;\n /** Number of LLM response events */\n responseCount: number;\n /** Number of tool calls */\n toolCallCount: number;\n /** Model ID if detected from events */\n modelId?: string;\n /** Start time of accumulation */\n startedAt: Date;\n /** Duration in ms (set on finalize) */\n durationMs?: number;\n}\n\n/** Event types that contain token information (Anthropic SDK format) */\nconst TOKEN_EVENTS = new Set([\"message.stop\", \"content_block_stop\"]);\n\n/** Event types for tool calls - now handled via message.part.updated */\nconst _TOOL_CALL_EVENTS = new Set<string>();\n\n/**\n * StreamUsageExtractor - Accumulates token usage from SSE events.\n *\n * Usage:\n * ```typescript\n * const extractor = createStreamUsageExtractor();\n *\n * // In your stream callback\n * for await (const event of stream) {\n * extractor.processEvent(event);\n * // ... handle event\n * }\n *\n * const usage = extractor.finalize();\n * billingService.recordUsage({ usage: usage.usage, ... });\n * ```\n */\nexport class StreamUsageExtractor {\n private accumulator: StreamUsageAccumulator;\n private finalized = false;\n\n constructor() {\n this.accumulator = {\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n responseCount: 0,\n toolCallCount: 0,\n startedAt: new Date(),\n };\n }\n\n /**\n * Process a raw SSE string (event: xxx\\ndata: {...}).\n */\n processRawSSE(raw: string): void {\n const parsed = parseSSEData(raw);\n if (parsed) {\n this.processEvent(parsed);\n }\n }\n\n /**\n * Process a parsed SSE event object.\n */\n processEvent(event: SSEEventData | Record<string, unknown>): void {\n if (this.finalized) {\n throw new Error(\"StreamUsageExtractor already finalized\");\n }\n\n const eventType = (event as SSEEventData).type ?? event.type;\n\n // Handle message.part.updated (canonical event for all part types)\n if (eventType === \"message.part.updated\") {\n const part = (event as { part?: { type?: string; tool?: string } }).part;\n const partType = part?.type;\n\n // Text and reasoning parts count as LLM responses\n if (partType === \"text\" || partType === \"reasoning\") {\n this.extractTokens(event);\n this.accumulator.responseCount++;\n }\n\n // Tool parts count as tool calls\n if (partType === \"tool\" && part?.tool) {\n this.accumulator.toolCallCount++;\n }\n\n return;\n }\n\n // Extract token counts from Anthropic SDK format events\n if (TOKEN_EVENTS.has(eventType as string)) {\n this.extractTokens(event);\n this.accumulator.responseCount++;\n }\n\n // Extract model ID if present\n if (!this.accumulator.modelId && event.model) {\n this.accumulator.modelId = String(event.model);\n }\n\n // Handle usage summary events (some providers send final usage)\n if (eventType === \"usage\" || event.usage) {\n this.extractUsageSummary(event);\n }\n\n // Handle message_stop with usage (Anthropic format)\n if (eventType === \"message_stop\" && event.usage) {\n this.extractUsageSummary(event);\n }\n }\n\n /**\n * Finalize and return accumulated usage.\n * Sets duration and marks extractor as complete.\n */\n finalize(): StreamUsageAccumulator {\n if (this.finalized) {\n return this.accumulator;\n }\n\n this.finalized = true;\n this.accumulator.durationMs =\n Date.now() - this.accumulator.startedAt.getTime();\n\n return this.accumulator;\n }\n\n /**\n * Get current accumulated usage (without finalizing).\n */\n current(): Readonly<StreamUsageAccumulator> {\n return this.accumulator;\n }\n\n /**\n * Reset the extractor for reuse.\n */\n reset(): void {\n this.accumulator = {\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n responseCount: 0,\n toolCallCount: 0,\n startedAt: new Date(),\n };\n this.finalized = false;\n }\n\n private extractTokens(event: Record<string, unknown>): void {\n // Direct token count (simple format)\n if (typeof event.tokens === \"number\") {\n this.accumulator.usage.outputTokens += event.tokens;\n }\n\n // Output tokens (explicit)\n if (typeof event.outputTokens === \"number\") {\n this.accumulator.usage.outputTokens += event.outputTokens;\n }\n if (typeof event.output_tokens === \"number\") {\n this.accumulator.usage.outputTokens += event.output_tokens;\n }\n\n // Input tokens (usually from final summary)\n if (typeof event.inputTokens === \"number\") {\n this.accumulator.usage.inputTokens = Math.max(\n this.accumulator.usage.inputTokens,\n event.inputTokens,\n );\n }\n if (typeof event.input_tokens === \"number\") {\n this.accumulator.usage.inputTokens = Math.max(\n this.accumulator.usage.inputTokens,\n event.input_tokens,\n );\n }\n\n // Cache tokens (Anthropic format)\n if (typeof event.cache_read_input_tokens === \"number\") {\n this.accumulator.usage.cacheReadTokens =\n (this.accumulator.usage.cacheReadTokens ?? 0) +\n event.cache_read_input_tokens;\n }\n if (typeof event.cache_creation_input_tokens === \"number\") {\n this.accumulator.usage.cacheWriteTokens =\n (this.accumulator.usage.cacheWriteTokens ?? 0) +\n event.cache_creation_input_tokens;\n }\n }\n\n private extractUsageSummary(event: Record<string, unknown>): void {\n const usage = (event.usage as Record<string, unknown>) ?? event;\n\n if (typeof usage.input_tokens === \"number\") {\n this.accumulator.usage.inputTokens = Math.max(\n this.accumulator.usage.inputTokens,\n usage.input_tokens,\n );\n }\n if (typeof usage.output_tokens === \"number\") {\n this.accumulator.usage.outputTokens = Math.max(\n this.accumulator.usage.outputTokens,\n usage.output_tokens,\n );\n }\n if (typeof usage.cache_read_input_tokens === \"number\") {\n this.accumulator.usage.cacheReadTokens = usage.cache_read_input_tokens;\n }\n if (typeof usage.cache_creation_input_tokens === \"number\") {\n this.accumulator.usage.cacheWriteTokens =\n usage.cache_creation_input_tokens;\n }\n }\n}\n\n/**\n * Create a new StreamUsageExtractor.\n */\nexport function createStreamUsageExtractor(): StreamUsageExtractor {\n return new StreamUsageExtractor();\n}\n\n/**\n * Create a callback wrapper that extracts usage while forwarding events.\n *\n * Usage:\n * ```typescript\n * const { callback, getUsage } = createUsageCallback((event) => {\n * // your event handler\n * });\n *\n * await orchestrator.executeAgentStream(projectRef, request, callback);\n * const usage = getUsage();\n * ```\n */\nexport function createUsageCallback<T extends Record<string, unknown>>(\n forward?: (event: T) => void,\n): {\n callback: (event: T) => void;\n getUsage: () => StreamUsageAccumulator;\n extractor: StreamUsageExtractor;\n} {\n const extractor = createStreamUsageExtractor();\n\n return {\n callback: (event: T) => {\n extractor.processEvent(event);\n forward?.(event);\n },\n getUsage: () => extractor.finalize(),\n extractor,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { S as TransportMode, _ as StreamOptions, a as RecordedRequest, b as TransportEvents, c as TransportAdapter, d as ConnectionQuality, f as ConnectionState, g as SSEEvent, h as RequestOptions, i as MockTransportConfig, l as ConnectionManager, m as ReconnectionConfig, n as MockStreamEvent, o as BaseTransportAdapter, p as DEFAULT_RECONNECTION_CONFIG, r as MockTransportAdapter, s as Subscription, t as MockResponse, u as ConnectionManagerConfig, v as SubscriptionState, x as TransportMetrics, y as TransportConfig } from "../index-CFA8kgHJ.js";
2
+ export { BaseTransportAdapter, ConnectionManager, ConnectionManagerConfig, ConnectionQuality, ConnectionState, DEFAULT_RECONNECTION_CONFIG, MockResponse, MockStreamEvent, MockTransportAdapter, MockTransportConfig, ReconnectionConfig, RecordedRequest, RequestOptions, SSEEvent, StreamOptions, Subscription, SubscriptionState, TransportAdapter, TransportConfig, TransportEvents, TransportMetrics, TransportMode };
@@ -0,0 +1,2 @@
1
+ import { i as DEFAULT_RECONNECTION_CONFIG, n as BaseTransportAdapter, r as ConnectionManager, t as MockTransportAdapter } from "../transport-mKLoQep5.js";
2
+ export { BaseTransportAdapter, ConnectionManager, DEFAULT_RECONNECTION_CONFIG, MockTransportAdapter };