@tangle-network/agent-core 0.9.4 → 0.9.6

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 (78) hide show
  1. package/dist/auth/browser.d.ts +2 -22
  2. package/dist/auth/browser.js +1 -42
  3. package/dist/auth/index.d.ts +3 -17
  4. package/dist/auth/index.d.ts.map +1 -1
  5. package/dist/auth/index.js +8 -45
  6. package/dist/auth/index.js.map +1 -1
  7. package/dist/computer-use/index.d.ts.map +1 -1
  8. package/dist/computer-use/index.js +4 -3
  9. package/dist/computer-use/index.js.map +1 -1
  10. package/dist/{errors-DJ6U6cHY.js → errors-GuWACHTg.js} +11 -8
  11. package/dist/{errors-DJ6U6cHY.js.map → errors-GuWACHTg.js.map} +1 -1
  12. package/dist/events/index.d.ts +2 -2
  13. package/dist/events/index.js +1 -1
  14. package/dist/{events-CUWh9qrv.js → events-U7kxNUpM.js} +7 -5
  15. package/dist/{events-CUWh9qrv.js.map → events-U7kxNUpM.js.map} +1 -1
  16. package/dist/{index-D59fZ7n3.d.ts → index-BFYASYJk.d.ts} +1 -1
  17. package/dist/index-BFYASYJk.d.ts.map +1 -0
  18. package/dist/{index-Bgao-NCe.d.ts → index-BvjA5i93.d.ts} +1 -1
  19. package/dist/index-BvjA5i93.d.ts.map +1 -0
  20. package/dist/{index-HMlPCgTI.d.ts → index-CKDeaS7l.d.ts} +2 -3
  21. package/dist/index-CKDeaS7l.d.ts.map +1 -0
  22. package/dist/{index-CDLuQTT2.d.ts → index-CQPGv8jg.d.ts} +10 -11
  23. package/dist/index-CQPGv8jg.d.ts.map +1 -0
  24. package/dist/{index-C_1MnL24.d.ts → index-CuBvSsBf.d.ts} +1 -1
  25. package/dist/index-CuBvSsBf.d.ts.map +1 -0
  26. package/dist/{index-B4yy8ghH.d.ts → index-Dq6SfGaX.d.ts} +1 -1
  27. package/dist/index-Dq6SfGaX.d.ts.map +1 -0
  28. package/dist/index.d.ts +8 -9
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +11 -8
  31. package/dist/index.js.map +1 -1
  32. package/dist/interactions/index.d.ts +1 -2
  33. package/dist/interactions/index.d.ts.map +1 -1
  34. package/dist/interactions/index.js +2 -2
  35. package/dist/interactions/index.js.map +1 -1
  36. package/dist/interactions/mcp-server.d.ts +1 -2
  37. package/dist/interactions/mcp-server.d.ts.map +1 -1
  38. package/dist/interactions/mcp-server.js +3 -2
  39. package/dist/interactions/mcp-server.js.map +1 -1
  40. package/dist/{lifecycle-CXKYetbu.js → lifecycle-BljLcnY5.js} +1 -1
  41. package/dist/{lifecycle-CXKYetbu.js.map → lifecycle-BljLcnY5.js.map} +1 -1
  42. package/dist/resilience/index.d.ts +2 -2
  43. package/dist/resilience/index.js +1 -1
  44. package/dist/{resilience-BQzDfw_C.js → resilience-CFKHZSub.js} +4 -2
  45. package/dist/{resilience-BQzDfw_C.js.map → resilience-CFKHZSub.js.map} +1 -1
  46. package/dist/sse/index.d.ts.map +1 -1
  47. package/dist/sse/index.js +1 -1
  48. package/dist/sse/index.js.map +1 -1
  49. package/dist/telemetry/index.d.ts +2 -2
  50. package/dist/telemetry/index.js +1 -1
  51. package/dist/{telemetry-x1wNw1P4.js → telemetry-DTOiMSzM.js} +1 -1
  52. package/dist/{telemetry-x1wNw1P4.js.map → telemetry-DTOiMSzM.js.map} +1 -1
  53. package/dist/{types-Cd5jUzcr.d.ts → tokens-browser-DCV3-WHc.d.ts} +28 -10
  54. package/dist/tokens-browser-DCV3-WHc.d.ts.map +1 -0
  55. package/dist/{tools-D-I3A7Us.d.ts → tools-DeZkIW3h.d.ts} +1 -2
  56. package/dist/tools-DeZkIW3h.d.ts.map +1 -0
  57. package/dist/transport/index.d.ts +2 -2
  58. package/dist/transport/index.js +1 -1
  59. package/dist/{transport-XLxpQmUW.js → transport-DAfw3oL0.js} +5 -4
  60. package/dist/{transport-XLxpQmUW.js.map → transport-DAfw3oL0.js.map} +1 -1
  61. package/dist/types/index.d.ts +2 -2
  62. package/dist/types/index.js +1 -1
  63. package/dist/{types-DC6OJ1um.js → types--u-Om3vE.js} +56 -3
  64. package/dist/types--u-Om3vE.js.map +1 -0
  65. package/dist/{types-Ci7hcTnp.js → types-DVN5qATk.js} +1 -1
  66. package/dist/{types-Ci7hcTnp.js.map → types-DVN5qATk.js.map} +1 -1
  67. package/package.json +7 -7
  68. package/dist/auth/browser.d.ts.map +0 -1
  69. package/dist/auth/browser.js.map +0 -1
  70. package/dist/index-B4yy8ghH.d.ts.map +0 -1
  71. package/dist/index-Bgao-NCe.d.ts.map +0 -1
  72. package/dist/index-CDLuQTT2.d.ts.map +0 -1
  73. package/dist/index-C_1MnL24.d.ts.map +0 -1
  74. package/dist/index-D59fZ7n3.d.ts.map +0 -1
  75. package/dist/index-HMlPCgTI.d.ts.map +0 -1
  76. package/dist/tools-D-I3A7Us.d.ts.map +0 -1
  77. package/dist/types-Cd5jUzcr.d.ts.map +0 -1
  78. package/dist/types-DC6OJ1um.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.js","names":[],"sources":["../../src/interactions/mcp-server.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport { createServer, type Server } from \"node:http\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n type EventStore,\n StreamableHTTPServerTransport,\n} from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport {\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n type JSONRPCMessage,\n type MessageExtraInfo,\n type RequestId,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { z } from \"zod\";\nimport {\n closeHttpServer,\n SerializedTransportLifecycle,\n waitForSettled,\n} from \"./lifecycle.js\";\nimport type {\n AskUserBridge,\n PermissionPromptBridge,\n RequestPermissionBridge,\n RequestPlanBridge,\n} from \"./tools.js\";\n\nexport const DEFAULT_INTERACTION_MCP_SERVER_NAME = \"tangle-interaction\";\nconst MAX_MCP_BODY_BYTES = 4 * 1024 * 1024;\nconst MAX_MCP_REPLAY_EVENTS = 1_024;\n\ntype StoredMcpEvent = {\n id: string;\n streamId: string;\n message: JSONRPCMessage;\n};\n\nclass BoundedMcpEventStore implements EventStore {\n private readonly events: StoredMcpEvent[] = [];\n private sequence = 0;\n\n async storeEvent(\n streamId: string,\n message: JSONRPCMessage,\n ): Promise<string> {\n const id = `${streamId}:${this.sequence++}`;\n this.events.push({ id, streamId, message });\n if (this.events.length > MAX_MCP_REPLAY_EVENTS) this.events.shift();\n return id;\n }\n\n async getStreamIdForEventId(eventId: string): Promise<string | undefined> {\n return this.events.find((event) => event.id === eventId)?.streamId;\n }\n\n async replayEventsAfter(\n lastEventId: string,\n options: {\n send: (eventId: string, message: JSONRPCMessage) => Promise<void>;\n },\n ): Promise<string> {\n const index = this.events.findIndex((event) => event.id === lastEventId);\n if (index < 0) return \"\";\n const streamId = this.events[index]?.streamId ?? \"\";\n for (const event of this.events.slice(index + 1)) {\n if (event.streamId === streamId) {\n await options.send(event.id, event.message);\n }\n }\n return streamId;\n }\n}\n\ntype McpRequestGeneration = {\n completion: Promise<void>;\n generationId: string;\n id: RequestId;\n settle: () => void;\n signal?: AbortSignal;\n superseded: boolean;\n};\n\n/**\n * Prevent a disconnected response from replacing a retry with the same ID.\n *\n * The MCP transport keeps request-to-stream state until it sends the response.\n * A retry can replace that state before the old callback settles. The protocol\n * response keeps this async context, so stale responses can be discarded.\n */\nclass RetrySafeStreamableHttpTransport extends StreamableHTTPServerTransport {\n private readonly responseContext =\n new AsyncLocalStorage<McpRequestGeneration>();\n private readonly currentGeneration = new Map<\n RequestId,\n McpRequestGeneration\n >();\n private readonly activeGenerations = new Set<McpRequestGeneration>();\n private messageHandler?: (\n message: JSONRPCMessage,\n extra?: MessageExtraInfo,\n ) => void;\n\n constructor(\n private readonly currentRequestSignal: () => AbortSignal | undefined,\n options?: ConstructorParameters<typeof StreamableHTTPServerTransport>[0],\n ) {\n super(options);\n }\n\n override set onmessage(\n handler:\n | ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void)\n | undefined,\n ) {\n this.messageHandler = handler;\n super.onmessage = handler\n ? (message, extra) => {\n if (!isJSONRPCRequest(message)) {\n handler(message, extra);\n return;\n }\n const previous = this.currentGeneration.get(message.id);\n if (previous) previous.superseded = true;\n let settle: () => void = () => {};\n const completion = new Promise<void>((resolve) => {\n settle = resolve;\n });\n const generation: McpRequestGeneration = {\n completion,\n generationId: randomUUID(),\n id: message.id,\n settle,\n signal: this.currentRequestSignal(),\n superseded: false,\n };\n this.activeGenerations.add(generation);\n this.currentGeneration.set(message.id, generation);\n const dispatch = () => {\n if (generation.superseded || generation.signal?.aborted) {\n this.finishGeneration(generation);\n return;\n }\n this.responseContext.run(generation, () =>\n handler(message, extra),\n );\n };\n if (!previous) {\n dispatch();\n return;\n }\n void previous.completion\n .then(dispatch)\n .catch((error) =>\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n ),\n );\n }\n : undefined;\n }\n\n override get onmessage():\n | ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void)\n | undefined {\n return this.messageHandler;\n }\n\n get requestGenerationId(): string | undefined {\n return this.responseContext.getStore()?.generationId;\n }\n\n override async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId },\n ): Promise<void> {\n const responseId =\n isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)\n ? message.id\n : undefined;\n const generation = this.responseContext.getStore();\n if (responseId !== undefined && generation?.id === responseId) {\n try {\n if (generation.superseded || generation.signal?.aborted) return;\n await super.send(message, options);\n } finally {\n this.finishGeneration(generation);\n }\n return;\n }\n await super.send(message, options);\n }\n\n override async close(): Promise<void> {\n for (const generation of [...this.activeGenerations]) {\n generation.superseded = true;\n this.finishGeneration(generation);\n }\n await super.close();\n }\n\n private finishGeneration(generation: McpRequestGeneration): void {\n this.activeGenerations.delete(generation);\n if (this.currentGeneration.get(generation.id) === generation) {\n this.currentGeneration.delete(generation.id);\n }\n generation.settle();\n }\n}\n\nfunction mcpOperationId(\n serverName: string,\n toolName: string,\n sessionId: string | undefined,\n requestId: RequestId,\n generationId: string,\n): string {\n return `mcp-${createHash(\"sha256\")\n .update(\n `${serverName}\\u0000${toolName}\\u0000${sessionId ?? \"\"}\\u0000${String(requestId)}\\u0000${generationId}`,\n )\n .digest(\"hex\")}`;\n}\n\n/** Build the full tool name that a runner uses for an MCP tool. */\nexport function interactionMcpToolName(\n serverName: string,\n tool: string,\n): string {\n return `mcp__${serverName}__${tool}`;\n}\n\nexport interface InteractionMcpServerConfig {\n serverName?: string;\n onStop: () => void | Promise<void>;\n permission?: PermissionPromptBridge;\n askUser?: AskUserBridge;\n requestPermission?: RequestPermissionBridge;\n requestPlan?: RequestPlanBridge;\n}\n\nconst optionSchema = z.union([\n z.string().transform((label) => ({ label })),\n z.object({ label: z.string(), description: z.string().optional() }),\n]);\n\nconst questionItemSchema = z.object({\n question: z.string(),\n options: z.array(optionSchema).optional(),\n multiSelect: z.boolean().optional(),\n});\n\nconst questionsSchema = {\n // Some runners encode complex MCP arguments as a JSON string.\n questions: z.preprocess((value) => {\n if (typeof value !== \"string\") return value;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }, z.array(questionItemSchema)),\n};\n\n/**\n * Per-execution loopback MCP server for questions, permissions, and plans.\n *\n * The server listens only on 127.0.0.1 and requires an ephemeral bearer token.\n */\nexport class InteractionMcpServer {\n private readonly server: McpServer;\n private readonly transport: RetrySafeStreamableHttpTransport;\n private readonly onStop: () => void | Promise<void>;\n private readonly lifecycle = new SerializedTransportLifecycle();\n private readonly requestSignal = new AsyncLocalStorage<AbortSignal>();\n private readonly activePostRequests = new Set<Promise<void>>();\n private httpServer?: Server;\n private portValue = 0;\n readonly serverName: string;\n readonly token = randomBytes(24).toString(\"hex\");\n\n constructor(config: InteractionMcpServerConfig) {\n this.serverName = config.serverName ?? DEFAULT_INTERACTION_MCP_SERVER_NAME;\n this.onStop = config.onStop;\n this.server = new McpServer(\n { name: this.serverName, version: \"1.0.0\" },\n { capabilities: { tools: {} } },\n );\n this.transport = new RetrySafeStreamableHttpTransport(\n () => this.requestSignal.getStore(),\n {\n sessionIdGenerator: () => randomUUID(),\n eventStore: new BoundedMcpEventStore(),\n },\n );\n\n if (config.permission) {\n const decide = config.permission;\n this.server.registerTool(\n \"permission\",\n {\n title: \"Permission prompt\",\n description:\n \"Ask the user to approve a runner tool call before it executes.\",\n inputSchema: {\n tool_name: z.string(),\n input: z.record(z.string(), z.unknown()).optional(),\n tool_use_id: z.string(),\n },\n },\n async (args, extra) => {\n const result = await decide({\n tool_name: args.tool_name,\n input: args.input ?? {},\n tool_use_id: args.tool_use_id,\n operationId: this.operationId(\n \"permission\",\n extra.sessionId,\n extra.requestId,\n ),\n signal: this.operationSignal(extra.signal),\n });\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result) }],\n };\n },\n );\n }\n\n if (config.askUser) {\n const askUser = config.askUser;\n this.server.registerTool(\n \"ask_user\",\n {\n title: \"Ask the user\",\n description:\n \"Ask a clarifying question when a user decision is required.\",\n inputSchema: questionsSchema,\n },\n async (args, extra) => {\n const answers = await askUser({\n questions: args.questions,\n operationId: this.operationId(\n \"ask_user\",\n extra.sessionId,\n extra.requestId,\n ),\n signal: this.operationSignal(extra.signal),\n });\n const text = answers\n ? answers.map((slot) => slot.join(\", \")).join(\"\\n\") || \"(no answer)\"\n : \"No answer was provided.\";\n return { content: [{ type: \"text\" as const, text }] };\n },\n );\n }\n\n if (config.requestPermission) {\n const requestPermission = config.requestPermission;\n this.server.registerTool(\n \"request_permission\",\n {\n title: \"Request permission\",\n description:\n \"Ask the user to approve an action before the action starts.\",\n inputSchema: {\n tool_name: z.string(),\n input: z.record(z.string(), z.unknown()).optional(),\n },\n },\n async (args, extra) => {\n const result = await requestPermission({\n tool_name: args.tool_name,\n input: args.input ?? {},\n operationId: this.operationId(\n \"request_permission\",\n extra.sessionId,\n extra.requestId,\n ),\n signal: this.operationSignal(extra.signal),\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: result.allowed\n ? \"ALLOWED\"\n : `DENIED${result.message ? `: ${result.message}` : \"\"}`,\n },\n ],\n };\n },\n );\n }\n\n if (config.requestPlan) {\n const requestPlan = config.requestPlan;\n this.server.registerTool(\n \"request_plan\",\n {\n title: \"Request plan approval\",\n description:\n \"Submit a complete plan for review, then end the current turn.\",\n inputSchema: { plan: z.string().trim().min(1) },\n },\n async (args) => {\n const sourceToolCallId = `request-plan:${createHash(\"sha256\")\n .update(args.plan.trim())\n .digest(\"hex\")}`;\n const submitted = await requestPlan({\n plan: args.plan,\n sourceToolCallId,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: `PLAN_SUBMITTED ${submitted.id}. End this turn now.`,\n },\n ],\n };\n },\n );\n }\n }\n\n get port(): number {\n return this.portValue;\n }\n\n get url(): string {\n return `http://127.0.0.1:${this.portValue}/mcp`;\n }\n\n async start(): Promise<void> {\n return this.lifecycle.start(async () => {\n await this.server.connect(this.transport);\n const httpServer = createServer((request, response) => {\n const fail = (status: number, message?: string) => {\n if (response.writableEnded) return;\n try {\n response.writeHead(status).end(message);\n } catch {\n // The connection already closed.\n }\n };\n\n const path = new URL(request.url ?? \"/\", \"http://127.0.0.1\").pathname;\n if (path !== \"/mcp\") {\n fail(404);\n return;\n }\n if (request.headers.authorization !== `Bearer ${this.token}`) {\n fail(401);\n return;\n }\n\n const handle = (body?: unknown) => {\n const controller = new AbortController();\n const abort = () => controller.abort();\n const abortIfIncomplete = () => {\n if (!response.writableFinished) abort();\n };\n request.once(\"aborted\", abort);\n response.once(\"close\", abortIfIncomplete);\n const handled = this.requestSignal\n .run(controller.signal, () =>\n this.transport.handleRequest(request, response, body),\n )\n .catch(() => fail(500))\n .finally(() => {\n request.off(\"aborted\", abort);\n response.off(\"close\", abortIfIncomplete);\n });\n if (request.method === \"POST\") {\n this.activePostRequests.add(handled);\n void handled.finally(() =>\n this.activePostRequests.delete(handled),\n );\n }\n return handled;\n };\n\n if (request.method !== \"POST\") {\n void handle();\n return;\n }\n\n const chunks: Buffer[] = [];\n let size = 0;\n request.on(\"error\", () => fail(400));\n request.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_MCP_BODY_BYTES) {\n fail(413, \"payload too large\");\n request.destroy();\n return;\n }\n chunks.push(chunk);\n });\n request.on(\"end\", () => {\n if (response.writableEnded) return;\n let body: unknown;\n try {\n const raw = Buffer.concat(chunks).toString(\"utf8\");\n body = raw ? JSON.parse(raw) : undefined;\n } catch {\n fail(400, \"invalid json\");\n return;\n }\n void handle(body);\n });\n });\n\n try {\n await new Promise<void>((resolve, reject) => {\n httpServer.once(\"error\", reject);\n httpServer.listen(0, \"127.0.0.1\", resolve);\n });\n } catch (error) {\n httpServer.closeAllConnections?.();\n await this.server.close().catch(() => undefined);\n throw error;\n }\n const address = httpServer.address();\n this.portValue =\n address && typeof address === \"object\" ? address.port : 0;\n this.httpServer = httpServer;\n });\n }\n\n async stop(): Promise<void> {\n return this.lifecycle.stop(async () => {\n await this.onStop();\n await waitForSettled(this.activePostRequests);\n const httpServer = this.httpServer;\n this.httpServer = undefined;\n this.portValue = 0;\n await this.server.close().catch(() => undefined);\n if (httpServer) await closeHttpServer(httpServer);\n });\n }\n\n private operationSignal(protocolSignal: AbortSignal): AbortSignal {\n const httpSignal = this.requestSignal.getStore();\n return httpSignal\n ? AbortSignal.any([protocolSignal, httpSignal])\n : protocolSignal;\n }\n\n private operationId(\n toolName: string,\n sessionId: string | undefined,\n requestId: RequestId,\n ): string {\n return mcpOperationId(\n this.serverName,\n toolName,\n sessionId,\n requestId,\n this.requestGenerationId(),\n );\n }\n\n private requestGenerationId(): string {\n const generationId = this.transport.requestGenerationId;\n if (!generationId) throw new Error(\"MCP request generation is missing\");\n return generationId;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp-server.js","names":[],"sources":["../../src/interactions/mcp-server.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport { createServer, type Server } from \"node:http\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n type EventStore,\n StreamableHTTPServerTransport,\n} from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport {\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n type JSONRPCMessage,\n type MessageExtraInfo,\n type RequestId,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { z } from \"zod\";\nimport {\n closeHttpServer,\n SerializedTransportLifecycle,\n waitForSettled,\n} from \"./lifecycle.js\";\nimport type {\n AskUserBridge,\n PermissionPromptBridge,\n RequestPermissionBridge,\n RequestPlanBridge,\n} from \"./tools.js\";\n\nexport const DEFAULT_INTERACTION_MCP_SERVER_NAME = \"tangle-interaction\";\nconst MAX_MCP_BODY_BYTES = 4 * 1024 * 1024;\nconst MAX_MCP_REPLAY_EVENTS = 1_024;\n\ntype StoredMcpEvent = {\n id: string;\n streamId: string;\n message: JSONRPCMessage;\n};\n\nclass BoundedMcpEventStore implements EventStore {\n private readonly events: StoredMcpEvent[] = [];\n private sequence = 0;\n\n async storeEvent(\n streamId: string,\n message: JSONRPCMessage,\n ): Promise<string> {\n const id = `${streamId}:${this.sequence++}`;\n this.events.push({ id, streamId, message });\n if (this.events.length > MAX_MCP_REPLAY_EVENTS) this.events.shift();\n return id;\n }\n\n async getStreamIdForEventId(eventId: string): Promise<string | undefined> {\n return this.events.find((event) => event.id === eventId)?.streamId;\n }\n\n async replayEventsAfter(\n lastEventId: string,\n options: {\n send: (eventId: string, message: JSONRPCMessage) => Promise<void>;\n },\n ): Promise<string> {\n const index = this.events.findIndex((event) => event.id === lastEventId);\n if (index < 0) return \"\";\n const streamId = this.events[index]?.streamId ?? \"\";\n for (const event of this.events.slice(index + 1)) {\n if (event.streamId === streamId) {\n await options.send(event.id, event.message);\n }\n }\n return streamId;\n }\n}\n\ntype McpRequestGeneration = {\n completion: Promise<void>;\n generationId: string;\n id: RequestId;\n settle: () => void;\n signal?: AbortSignal;\n superseded: boolean;\n};\n\n/**\n * Prevent a disconnected response from replacing a retry with the same ID.\n *\n * The MCP transport keeps request-to-stream state until it sends the response.\n * A retry can replace that state before the old callback settles. The protocol\n * response keeps this async context, so stale responses can be discarded.\n */\nclass RetrySafeStreamableHttpTransport extends StreamableHTTPServerTransport {\n private readonly responseContext =\n new AsyncLocalStorage<McpRequestGeneration>();\n private readonly currentGeneration = new Map<\n RequestId,\n McpRequestGeneration\n >();\n private readonly activeGenerations = new Set<McpRequestGeneration>();\n private messageHandler?: (\n message: JSONRPCMessage,\n extra?: MessageExtraInfo,\n ) => void;\n\n constructor(\n private readonly currentRequestSignal: () => AbortSignal | undefined,\n options?: ConstructorParameters<typeof StreamableHTTPServerTransport>[0],\n ) {\n super(options);\n }\n\n override set onmessage(\n handler:\n | ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void)\n | undefined,\n ) {\n this.messageHandler = handler;\n super.onmessage = handler\n ? (message, extra) => {\n if (!isJSONRPCRequest(message)) {\n handler(message, extra);\n return;\n }\n const previous = this.currentGeneration.get(message.id);\n if (previous) previous.superseded = true;\n let settle: () => void = () => {};\n const completion = new Promise<void>((resolve) => {\n settle = resolve;\n });\n const generation: McpRequestGeneration = {\n completion,\n generationId: randomUUID(),\n id: message.id,\n settle,\n signal: this.currentRequestSignal(),\n superseded: false,\n };\n this.activeGenerations.add(generation);\n this.currentGeneration.set(message.id, generation);\n const dispatch = () => {\n if (generation.superseded || generation.signal?.aborted) {\n this.finishGeneration(generation);\n return;\n }\n this.responseContext.run(generation, () =>\n handler(message, extra),\n );\n };\n if (!previous) {\n dispatch();\n return;\n }\n void previous.completion\n .then(dispatch)\n .catch((error) =>\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n ),\n );\n }\n : undefined;\n }\n\n override get onmessage():\n | ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void)\n | undefined {\n return this.messageHandler;\n }\n\n get requestGenerationId(): string | undefined {\n return this.responseContext.getStore()?.generationId;\n }\n\n override async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId },\n ): Promise<void> {\n const responseId =\n isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)\n ? message.id\n : undefined;\n const generation = this.responseContext.getStore();\n if (responseId !== undefined && generation?.id === responseId) {\n try {\n if (generation.superseded || generation.signal?.aborted) return;\n await super.send(message, options);\n } finally {\n this.finishGeneration(generation);\n }\n return;\n }\n await super.send(message, options);\n }\n\n override async close(): Promise<void> {\n for (const generation of [...this.activeGenerations]) {\n generation.superseded = true;\n this.finishGeneration(generation);\n }\n await super.close();\n }\n\n private finishGeneration(generation: McpRequestGeneration): void {\n this.activeGenerations.delete(generation);\n if (this.currentGeneration.get(generation.id) === generation) {\n this.currentGeneration.delete(generation.id);\n }\n generation.settle();\n }\n}\n\nfunction mcpOperationId(\n serverName: string,\n toolName: string,\n sessionId: string | undefined,\n requestId: RequestId,\n generationId: string,\n): string {\n return `mcp-${createHash(\"sha256\")\n .update(\n `${serverName}\\u0000${toolName}\\u0000${sessionId ?? \"\"}\\u0000${String(requestId)}\\u0000${generationId}`,\n )\n .digest(\"hex\")}`;\n}\n\n/** Build the full tool name that a runner uses for an MCP tool. */\nexport function interactionMcpToolName(\n serverName: string,\n tool: string,\n): string {\n return `mcp__${serverName}__${tool}`;\n}\n\nexport interface InteractionMcpServerConfig {\n serverName?: string;\n onStop: () => void | Promise<void>;\n permission?: PermissionPromptBridge;\n askUser?: AskUserBridge;\n requestPermission?: RequestPermissionBridge;\n requestPlan?: RequestPlanBridge;\n}\n\nconst optionSchema = z.union([\n z.string().transform((label) => ({ label })),\n z.object({ label: z.string(), description: z.string().optional() }),\n]);\n\nconst questionItemSchema = z.object({\n question: z.string(),\n options: z.array(optionSchema).optional(),\n multiSelect: z.boolean().optional(),\n});\n\nconst questionsSchema = {\n // Some runners encode complex MCP arguments as a JSON string.\n questions: z.preprocess((value) => {\n if (typeof value !== \"string\") return value;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }, z.array(questionItemSchema)),\n};\n\n/**\n * Per-execution loopback MCP server for questions, permissions, and plans.\n *\n * The server listens only on 127.0.0.1 and requires an ephemeral bearer token.\n */\nexport class InteractionMcpServer {\n private readonly server: McpServer;\n private readonly transport: RetrySafeStreamableHttpTransport;\n private readonly onStop: () => void | Promise<void>;\n private readonly lifecycle = new SerializedTransportLifecycle();\n private readonly requestSignal = new AsyncLocalStorage<AbortSignal>();\n private readonly activePostRequests = new Set<Promise<void>>();\n private httpServer?: Server;\n private portValue = 0;\n readonly serverName: string;\n readonly token = randomBytes(24).toString(\"hex\");\n\n constructor(config: InteractionMcpServerConfig) {\n this.serverName = config.serverName ?? DEFAULT_INTERACTION_MCP_SERVER_NAME;\n this.onStop = config.onStop;\n this.server = new McpServer(\n { name: this.serverName, version: \"1.0.0\" },\n { capabilities: { tools: {} } },\n );\n this.transport = new RetrySafeStreamableHttpTransport(\n () => this.requestSignal.getStore(),\n {\n sessionIdGenerator: () => randomUUID(),\n eventStore: new BoundedMcpEventStore(),\n },\n );\n\n if (config.permission) {\n const decide = config.permission;\n this.server.registerTool(\n \"permission\",\n {\n title: \"Permission prompt\",\n description:\n \"Ask the user to approve a runner tool call before it executes.\",\n inputSchema: {\n tool_name: z.string(),\n input: z.record(z.string(), z.unknown()).optional(),\n tool_use_id: z.string(),\n },\n },\n async (args, extra) => {\n const result = await decide({\n tool_name: args.tool_name,\n input: args.input ?? {},\n tool_use_id: args.tool_use_id,\n operationId: this.operationId(\n \"permission\",\n extra.sessionId,\n extra.requestId,\n ),\n signal: this.operationSignal(extra.signal),\n });\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result) }],\n };\n },\n );\n }\n\n if (config.askUser) {\n const askUser = config.askUser;\n this.server.registerTool(\n \"ask_user\",\n {\n title: \"Ask the user\",\n description:\n \"Ask a clarifying question when a user decision is required.\",\n inputSchema: questionsSchema,\n },\n async (args, extra) => {\n const answers = await askUser({\n questions: args.questions,\n operationId: this.operationId(\n \"ask_user\",\n extra.sessionId,\n extra.requestId,\n ),\n signal: this.operationSignal(extra.signal),\n });\n const text = answers\n ? answers.map((slot) => slot.join(\", \")).join(\"\\n\") || \"(no answer)\"\n : \"No answer was provided.\";\n return { content: [{ type: \"text\" as const, text }] };\n },\n );\n }\n\n if (config.requestPermission) {\n const requestPermission = config.requestPermission;\n this.server.registerTool(\n \"request_permission\",\n {\n title: \"Request permission\",\n description:\n \"Ask the user to approve an action before the action starts.\",\n inputSchema: {\n tool_name: z.string(),\n input: z.record(z.string(), z.unknown()).optional(),\n },\n },\n async (args, extra) => {\n const result = await requestPermission({\n tool_name: args.tool_name,\n input: args.input ?? {},\n operationId: this.operationId(\n \"request_permission\",\n extra.sessionId,\n extra.requestId,\n ),\n signal: this.operationSignal(extra.signal),\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: result.allowed\n ? \"ALLOWED\"\n : `DENIED${result.message ? `: ${result.message}` : \"\"}`,\n },\n ],\n };\n },\n );\n }\n\n if (config.requestPlan) {\n const requestPlan = config.requestPlan;\n this.server.registerTool(\n \"request_plan\",\n {\n title: \"Request plan approval\",\n description:\n \"Submit a complete plan for review, then end the current turn.\",\n inputSchema: { plan: z.string().trim().min(1) },\n },\n async (args) => {\n const sourceToolCallId = `request-plan:${createHash(\"sha256\")\n .update(args.plan.trim())\n .digest(\"hex\")}`;\n const submitted = await requestPlan({\n plan: args.plan,\n sourceToolCallId,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: `PLAN_SUBMITTED ${submitted.id}. End this turn now.`,\n },\n ],\n };\n },\n );\n }\n }\n\n get port(): number {\n return this.portValue;\n }\n\n get url(): string {\n return `http://127.0.0.1:${this.portValue}/mcp`;\n }\n\n async start(): Promise<void> {\n return this.lifecycle.start(async () => {\n await this.server.connect(this.transport);\n const httpServer = createServer((request, response) => {\n const fail = (status: number, message?: string) => {\n if (response.writableEnded) return;\n try {\n response.writeHead(status).end(message);\n } catch {\n // The connection already closed.\n }\n };\n\n const path = new URL(request.url ?? \"/\", \"http://127.0.0.1\").pathname;\n if (path !== \"/mcp\") {\n fail(404);\n return;\n }\n if (request.headers.authorization !== `Bearer ${this.token}`) {\n fail(401);\n return;\n }\n\n const handle = (body?: unknown) => {\n const controller = new AbortController();\n const abort = () => controller.abort();\n const abortIfIncomplete = () => {\n if (!response.writableFinished) abort();\n };\n request.once(\"aborted\", abort);\n response.once(\"close\", abortIfIncomplete);\n const handled = this.requestSignal\n .run(controller.signal, () =>\n this.transport.handleRequest(request, response, body),\n )\n .catch(() => fail(500))\n .finally(() => {\n request.off(\"aborted\", abort);\n response.off(\"close\", abortIfIncomplete);\n });\n if (request.method === \"POST\") {\n this.activePostRequests.add(handled);\n void handled.finally(() =>\n this.activePostRequests.delete(handled),\n );\n }\n return handled;\n };\n\n if (request.method !== \"POST\") {\n void handle();\n return;\n }\n\n const chunks: Buffer[] = [];\n let size = 0;\n request.on(\"error\", () => fail(400));\n request.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_MCP_BODY_BYTES) {\n fail(413, \"payload too large\");\n request.destroy();\n return;\n }\n chunks.push(chunk);\n });\n request.on(\"end\", () => {\n if (response.writableEnded) return;\n let body: unknown;\n try {\n const raw = Buffer.concat(chunks).toString(\"utf8\");\n body = raw ? JSON.parse(raw) : undefined;\n } catch {\n fail(400, \"invalid json\");\n return;\n }\n void handle(body);\n });\n });\n\n try {\n await new Promise<void>((resolve, reject) => {\n httpServer.once(\"error\", reject);\n httpServer.listen(0, \"127.0.0.1\", resolve);\n });\n } catch (error) {\n httpServer.closeAllConnections?.();\n await this.server.close().catch(() => undefined);\n throw error;\n }\n const address = httpServer.address();\n this.portValue =\n address && typeof address === \"object\" ? address.port : 0;\n this.httpServer = httpServer;\n });\n }\n\n async stop(): Promise<void> {\n return this.lifecycle.stop(async () => {\n await this.onStop();\n await waitForSettled(this.activePostRequests);\n const httpServer = this.httpServer;\n this.httpServer = undefined;\n this.portValue = 0;\n await this.server.close().catch(() => undefined);\n if (httpServer) await closeHttpServer(httpServer);\n });\n }\n\n private operationSignal(protocolSignal: AbortSignal): AbortSignal {\n const httpSignal = this.requestSignal.getStore();\n return httpSignal\n ? AbortSignal.any([protocolSignal, httpSignal])\n : protocolSignal;\n }\n\n private operationId(\n toolName: string,\n sessionId: string | undefined,\n requestId: RequestId,\n ): string {\n return mcpOperationId(\n this.serverName,\n toolName,\n sessionId,\n requestId,\n this.requestGenerationId(),\n );\n }\n\n private requestGenerationId(): string {\n const generationId = this.transport.requestGenerationId;\n if (!generationId) throw new Error(\"MCP request generation is missing\");\n return generationId;\n }\n}\n"],"mappings":"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"}
@@ -65,4 +65,4 @@ async function waitForSettled(promises, graceMs = 1e3) {
65
65
  //#endregion
66
66
  export { closeHttpServer as n, waitForSettled as r, SerializedTransportLifecycle as t };
67
67
 
68
- //# sourceMappingURL=lifecycle-CXKYetbu.js.map
68
+ //# sourceMappingURL=lifecycle-BljLcnY5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-CXKYetbu.js","names":[],"sources":["../src/interactions/lifecycle.ts"],"sourcesContent":["type LifecycleState = \"idle\" | \"starting\" | \"running\" | \"stopping\" | \"stopped\";\n\n/** Serialize one transport's single-use start and stop operations. */\nexport class SerializedTransportLifecycle {\n private state: LifecycleState = \"idle\";\n private tail: Promise<void> = Promise.resolve();\n\n start(open: () => Promise<void>): Promise<void> {\n return this.enqueue(async () => {\n if (this.state !== \"idle\") {\n throw new Error(`Interaction transport cannot start while ${this.state}`);\n }\n this.state = \"starting\";\n try {\n await open();\n this.state = \"running\";\n } catch (error) {\n this.state = \"stopped\";\n throw error;\n }\n });\n }\n\n stop(close: () => Promise<void>): Promise<void> {\n return this.enqueue(async () => {\n if (this.state === \"idle\" || this.state === \"stopped\") return;\n this.state = \"stopping\";\n try {\n await close();\n } finally {\n this.state = \"stopped\";\n }\n });\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n const result = this.tail.then(operation);\n this.tail = result.catch(() => undefined);\n return result;\n }\n}\n\n/** Close active requests gracefully, then force-close a stuck local socket. */\nexport async function closeHttpServer(\n server: import(\"node:http\").Server,\n graceMs = 1_000,\n): Promise<void> {\n await new Promise<void>((resolve) => {\n let finished = false;\n const finish = () => {\n if (finished) return;\n finished = true;\n clearTimeout(forceClose);\n resolve();\n };\n const forceClose = setTimeout(() => {\n server.closeAllConnections?.();\n finish();\n }, graceMs);\n server.close(finish);\n server.closeIdleConnections?.();\n });\n}\n\n/** Give active work a bounded grace period before transport shutdown. */\nexport async function waitForSettled(\n promises: Iterable<Promise<unknown>>,\n graceMs = 1_000,\n): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n Promise.allSettled([...promises]),\n new Promise<void>((resolve) => {\n timer = setTimeout(resolve, graceMs);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n"],"mappings":";;AAGA,IAAa,+BAAb,MAA0C;CACxC,QAAgC;CAChC,OAA8B,QAAQ,SAAS;CAE/C,MAAM,MAA0C;AAC9C,SAAO,KAAK,QAAQ,YAAY;AAC9B,OAAI,KAAK,UAAU,OACjB,OAAM,IAAI,MAAM,4CAA4C,KAAK,QAAQ;AAE3E,QAAK,QAAQ;AACb,OAAI;AACF,UAAM,MAAM;AACZ,SAAK,QAAQ;YACN,OAAO;AACd,SAAK,QAAQ;AACb,UAAM;;IAER;;CAGJ,KAAK,OAA2C;AAC9C,SAAO,KAAK,QAAQ,YAAY;AAC9B,OAAI,KAAK,UAAU,UAAU,KAAK,UAAU,UAAW;AACvD,QAAK,QAAQ;AACb,OAAI;AACF,UAAM,OAAO;aACL;AACR,SAAK,QAAQ;;IAEf;;CAGJ,QAAgB,WAA+C;EAC7D,MAAM,SAAS,KAAK,KAAK,KAAK,UAAU;AACxC,OAAK,OAAO,OAAO,YAAY,KAAA,EAAU;AACzC,SAAO;;;;AAKX,eAAsB,gBACpB,QACA,UAAU,KACK;AACf,OAAM,IAAI,SAAe,YAAY;EACnC,IAAI,WAAW;EACf,MAAM,eAAe;AACnB,OAAI,SAAU;AACd,cAAW;AACX,gBAAa,WAAW;AACxB,YAAS;;EAEX,MAAM,aAAa,iBAAiB;AAClC,UAAO,uBAAuB;AAC9B,WAAQ;KACP,QAAQ;AACX,SAAO,MAAM,OAAO;AACpB,SAAO,wBAAwB;GAC/B;;;AAIJ,eAAsB,eACpB,UACA,UAAU,KACK;CACf,IAAI;AACJ,KAAI;AACF,QAAM,QAAQ,KAAK,CACjB,QAAQ,WAAW,CAAC,GAAG,SAAS,CAAC,EACjC,IAAI,SAAe,YAAY;AAC7B,WAAQ,WAAW,SAAS,QAAQ;IACpC,CACH,CAAC;WACM;AACR,MAAI,MAAO,cAAa,MAAM"}
1
+ {"version":3,"file":"lifecycle-BljLcnY5.js","names":[],"sources":["../src/interactions/lifecycle.ts"],"sourcesContent":["type LifecycleState = \"idle\" | \"starting\" | \"running\" | \"stopping\" | \"stopped\";\n\n/** Serialize one transport's single-use start and stop operations. */\nexport class SerializedTransportLifecycle {\n private state: LifecycleState = \"idle\";\n private tail: Promise<void> = Promise.resolve();\n\n start(open: () => Promise<void>): Promise<void> {\n return this.enqueue(async () => {\n if (this.state !== \"idle\") {\n throw new Error(`Interaction transport cannot start while ${this.state}`);\n }\n this.state = \"starting\";\n try {\n await open();\n this.state = \"running\";\n } catch (error) {\n this.state = \"stopped\";\n throw error;\n }\n });\n }\n\n stop(close: () => Promise<void>): Promise<void> {\n return this.enqueue(async () => {\n if (this.state === \"idle\" || this.state === \"stopped\") return;\n this.state = \"stopping\";\n try {\n await close();\n } finally {\n this.state = \"stopped\";\n }\n });\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n const result = this.tail.then(operation);\n this.tail = result.catch(() => undefined);\n return result;\n }\n}\n\n/** Close active requests gracefully, then force-close a stuck local socket. */\nexport async function closeHttpServer(\n server: import(\"node:http\").Server,\n graceMs = 1_000,\n): Promise<void> {\n await new Promise<void>((resolve) => {\n let finished = false;\n const finish = () => {\n if (finished) return;\n finished = true;\n clearTimeout(forceClose);\n resolve();\n };\n const forceClose = setTimeout(() => {\n server.closeAllConnections?.();\n finish();\n }, graceMs);\n server.close(finish);\n server.closeIdleConnections?.();\n });\n}\n\n/** Give active work a bounded grace period before transport shutdown. */\nexport async function waitForSettled(\n promises: Iterable<Promise<unknown>>,\n graceMs = 1_000,\n): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n Promise.allSettled([...promises]),\n new Promise<void>((resolve) => {\n timer = setTimeout(resolve, graceMs);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n"],"mappings":";;AAGA,IAAa,+BAAb,MAA0C;CACxC,QAAgC;CAChC,OAA8B,QAAQ,QAAQ;CAE9C,MAAM,MAA0C;EAC9C,OAAO,KAAK,QAAQ,YAAY;GAC9B,IAAI,KAAK,UAAU,QACjB,MAAM,IAAI,MAAM,4CAA4C,KAAK,OAAO;GAE1E,KAAK,QAAQ;GACb,IAAI;IACF,MAAM,KAAK;IACX,KAAK,QAAQ;GACf,SAAS,OAAO;IACd,KAAK,QAAQ;IACb,MAAM;GACR;EACF,CAAC;CACH;CAEA,KAAK,OAA2C;EAC9C,OAAO,KAAK,QAAQ,YAAY;GAC9B,IAAI,KAAK,UAAU,UAAU,KAAK,UAAU,WAAW;GACvD,KAAK,QAAQ;GACb,IAAI;IACF,MAAM,MAAM;GACd,UAAU;IACR,KAAK,QAAQ;GACf;EACF,CAAC;CACH;CAEA,QAAgB,WAA+C;EAC7D,MAAM,SAAS,KAAK,KAAK,KAAK,SAAS;EACvC,KAAK,OAAO,OAAO,YAAY,KAAA,CAAS;EACxC,OAAO;CACT;AACF;;AAGA,eAAsB,gBACpB,QACA,UAAU,KACK;CACf,MAAM,IAAI,SAAe,YAAY;EACnC,IAAI,WAAW;EACf,MAAM,eAAe;GACnB,IAAI,UAAU;GACd,WAAW;GACX,aAAa,UAAU;GACvB,QAAQ;EACV;EACA,MAAM,aAAa,iBAAiB;GAClC,OAAO,sBAAsB;GAC7B,OAAO;EACT,GAAG,OAAO;EACV,OAAO,MAAM,MAAM;EACnB,OAAO,uBAAuB;CAChC,CAAC;AACH;;AAGA,eAAsB,eACpB,UACA,UAAU,KACK;CACf,IAAI;CACJ,IAAI;EACF,MAAM,QAAQ,KAAK,CACjB,QAAQ,WAAW,CAAC,GAAG,QAAQ,CAAC,GAChC,IAAI,SAAe,YAAY;GAC7B,QAAQ,WAAW,SAAS,OAAO;EACrC,CAAC,CACH,CAAC;CACH,UAAU;EACR,IAAI,OAAO,aAAa,KAAK;CAC/B;AACF"}
@@ -1,2 +1,2 @@
1
- import { a as ProtectionOptions, c as CircuitBreaker, d as CircuitOpenError, f as CircuitState, i as withTimeout, l as CircuitBreakerConfig, n as createTimeoutController, o as createProtectedFn, r as sleep, s as withProtection, t as TimeoutError, u as CircuitBreakerStats } from "../index-HMlPCgTI.js";
2
- export { CircuitBreaker, CircuitBreakerConfig, CircuitBreakerStats, CircuitOpenError, CircuitState, ProtectionOptions, TimeoutError, createProtectedFn, createTimeoutController, sleep, withProtection, withTimeout };
1
+ import { a as ProtectionOptions, c as CircuitBreaker, d as CircuitOpenError, f as CircuitState, i as withTimeout, l as CircuitBreakerConfig, n as createTimeoutController, o as createProtectedFn, r as sleep, s as withProtection, t as TimeoutError, u as CircuitBreakerStats } from "../index-CKDeaS7l.js";
2
+ export { CircuitBreaker, type CircuitBreakerConfig, type CircuitBreakerStats, CircuitOpenError, type CircuitState, type ProtectionOptions, TimeoutError, createProtectedFn, createTimeoutController, sleep, withProtection, withTimeout };
@@ -1,2 +1,2 @@
1
- import { a as sleep, c as CircuitOpenError, i as createTimeoutController, n as withProtection, o as withTimeout, r as TimeoutError, s as CircuitBreaker, t as createProtectedFn } from "../resilience-BQzDfw_C.js";
1
+ import { a as sleep, c as CircuitOpenError, i as createTimeoutController, n as withProtection, o as withTimeout, r as TimeoutError, s as CircuitBreaker, t as createProtectedFn } from "../resilience-CFKHZSub.js";
2
2
  export { CircuitBreaker, CircuitOpenError, TimeoutError, createProtectedFn, createTimeoutController, sleep, withProtection, withTimeout };
@@ -1,4 +1,4 @@
1
- import { t as SDKError } from "./errors-DJ6U6cHY.js";
1
+ import { t as SDKError } from "./errors-GuWACHTg.js";
2
2
  //#region src/resilience/circuit-breaker.ts
3
3
  /**
4
4
  * Circuit Breaker
@@ -28,6 +28,8 @@ var CircuitOpenError = class extends SDKError {
28
28
  }
29
29
  };
30
30
  var CircuitBreaker = class {
31
+ name;
32
+ config;
31
33
  state = "closed";
32
34
  failures = 0;
33
35
  successes = 0;
@@ -218,4 +220,4 @@ function createProtectedFn(fn, options) {
218
220
  //#endregion
219
221
  export { sleep as a, CircuitOpenError as c, createTimeoutController as i, withProtection as n, withTimeout as o, TimeoutError as r, CircuitBreaker as s, createProtectedFn as t };
220
222
 
221
- //# sourceMappingURL=resilience-BQzDfw_C.js.map
223
+ //# sourceMappingURL=resilience-CFKHZSub.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resilience-BQzDfw_C.js","names":[],"sources":["../src/resilience/circuit-breaker.ts","../src/resilience/timeout.ts","../src/resilience/protection.ts"],"sourcesContent":["/**\n * Circuit Breaker\n *\n * Implements the circuit breaker pattern for fail-fast behavior when\n * downstream services are unhealthy. Prevents cascade failures by\n * stopping requests to failing services.\n *\n * States:\n * - CLOSED: Normal operation, requests pass through\n * - OPEN: Service unhealthy, requests fail immediately\n * - HALF_OPEN: Testing if service recovered\n */\n\nimport { SDKError } from \"../errors/index.js\";\n\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\nexport interface CircuitBreakerConfig {\n /** Number of failures before opening circuit */\n failureThreshold: number;\n /** Time in ms to wait before testing recovery (half-open) */\n resetTimeoutMs: number;\n /** Number of successes in half-open state to close circuit */\n successThreshold: number;\n /** Optional: Only count these error types as failures */\n failureFilter?: (error: unknown) => boolean;\n}\n\nexport interface CircuitBreakerStats {\n state: CircuitState;\n failures: number;\n successes: number;\n lastFailureTime: number | null;\n totalFailures: number;\n totalSuccesses: number;\n totalRejected: number;\n}\n\nexport class CircuitOpenError extends SDKError {\n readonly circuitName: string;\n readonly resetAfterMs: number;\n\n constructor(name: string, resetAfterMs: number) {\n super(`Circuit breaker '${name}' is open`, {\n code: \"SERVER\",\n retryable: true,\n retryAfterMs: resetAfterMs,\n context: { circuitName: name },\n });\n this.name = \"CircuitOpenError\";\n this.circuitName = name;\n this.resetAfterMs = resetAfterMs;\n }\n}\n\nexport class CircuitBreaker {\n private state: CircuitState = \"closed\";\n private failures = 0;\n private successes = 0;\n private lastFailureTime: number | null = null;\n\n // Lifetime stats\n private totalFailures = 0;\n private totalSuccesses = 0;\n private totalRejected = 0;\n\n constructor(\n private readonly name: string,\n private readonly config: CircuitBreakerConfig,\n ) {\n if (config.failureThreshold < 1) {\n throw new Error(\"failureThreshold must be >= 1\");\n }\n if (config.resetTimeoutMs < 0) {\n throw new Error(\"resetTimeoutMs must be >= 0\");\n }\n if (config.successThreshold < 1) {\n throw new Error(\"successThreshold must be >= 1\");\n }\n }\n\n /**\n * Execute a function through the circuit breaker.\n * Throws CircuitOpenError if circuit is open.\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check if we should transition from open to half-open\n if (this.state === \"open\") {\n const timeSinceFailure = this.lastFailureTime\n ? Date.now() - this.lastFailureTime\n : Number.POSITIVE_INFINITY;\n\n if (timeSinceFailure >= this.config.resetTimeoutMs) {\n this.state = \"half-open\";\n this.successes = 0;\n } else {\n this.totalRejected++;\n throw new CircuitOpenError(\n this.name,\n this.config.resetTimeoutMs - timeSinceFailure,\n );\n }\n }\n\n try {\n const result = await fn();\n this.onSuccess();\n return result;\n } catch (error) {\n this.onFailure(error);\n throw error;\n }\n }\n\n private onSuccess(): void {\n this.totalSuccesses++;\n\n if (this.state === \"half-open\") {\n this.successes++;\n if (this.successes >= this.config.successThreshold) {\n // Service recovered, close circuit\n this.state = \"closed\";\n this.failures = 0;\n this.successes = 0;\n }\n } else if (this.state === \"closed\") {\n // Reset failure count on success\n this.failures = 0;\n }\n }\n\n private onFailure(error: unknown): void {\n // Check if this error should count as a failure\n if (this.config.failureFilter && !this.config.failureFilter(error)) {\n return;\n }\n\n this.totalFailures++;\n this.failures++;\n this.lastFailureTime = Date.now();\n this.successes = 0;\n\n if (this.state === \"half-open\") {\n // Any failure in half-open returns to open\n this.state = \"open\";\n } else if (\n this.state === \"closed\" &&\n this.failures >= this.config.failureThreshold\n ) {\n // Threshold exceeded, open circuit\n this.state = \"open\";\n }\n }\n\n /** Get current circuit state */\n getState(): CircuitState {\n return this.state;\n }\n\n /** Get circuit statistics */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n lastFailureTime: this.lastFailureTime,\n totalFailures: this.totalFailures,\n totalSuccesses: this.totalSuccesses,\n totalRejected: this.totalRejected,\n };\n }\n\n /** Check if circuit is allowing requests */\n isAllowingRequests(): boolean {\n if (this.state === \"closed\" || this.state === \"half-open\") {\n return true;\n }\n\n // Check if reset timeout has passed\n const timeSinceFailure = this.lastFailureTime\n ? Date.now() - this.lastFailureTime\n : Number.POSITIVE_INFINITY;\n\n return timeSinceFailure >= this.config.resetTimeoutMs;\n }\n\n /** Manually reset the circuit to closed state */\n reset(): void {\n this.state = \"closed\";\n this.failures = 0;\n this.successes = 0;\n this.lastFailureTime = null;\n }\n\n /** Manually open the circuit */\n open(): void {\n this.state = \"open\";\n this.lastFailureTime = Date.now();\n }\n}\n","/**\n * Timeout Utilities\n *\n * Promise-based timeout handling with proper cleanup.\n */\n\nimport { SDKError } from \"../errors/index.js\";\n\nexport class TimeoutError extends SDKError {\n readonly timeoutMs: number;\n\n constructor(message: string, timeoutMs: number) {\n super(message, {\n code: \"TIMEOUT\",\n retryable: true,\n context: { timeoutMs },\n });\n this.name = \"TimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Wrap a promise with a timeout.\n * Rejects with TimeoutError if the promise doesn't resolve in time.\n */\nexport function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message?: string,\n): Promise<T> {\n if (timeoutMs <= 0) {\n return promise;\n }\n\n let timeoutId: ReturnType<typeof setTimeout>;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(\n new TimeoutError(\n message || `Operation timed out after ${timeoutMs}ms`,\n timeoutMs,\n ),\n );\n }, timeoutMs);\n });\n\n return Promise.race([promise, timeoutPromise]).finally(() => {\n clearTimeout(timeoutId);\n });\n}\n\n/**\n * Create an AbortController that auto-aborts after a timeout.\n * Returns the controller and a cleanup function.\n */\nexport function createTimeoutController(timeoutMs: number): {\n controller: AbortController;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n if (timeoutMs > 0) {\n timeoutId = setTimeout(() => {\n controller.abort(new TimeoutError(\"Request timeout\", timeoutMs));\n }, timeoutMs);\n }\n\n return {\n controller,\n cleanup: () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n },\n };\n}\n\n/**\n * Sleep for a specified duration.\n * Optionally accepts an AbortSignal for cancellation.\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const timeoutId = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timeoutId);\n reject(signal.reason);\n },\n { once: true },\n );\n });\n}\n","/**\n * Combines timeout + circuit breaker into a single request guard.\n */\n\nimport type { CircuitBreaker } from \"./circuit-breaker.js\";\nimport { withTimeout } from \"./timeout.js\";\n\nexport interface ProtectionOptions {\n /** Timeout in milliseconds (0 or undefined = no timeout) */\n timeoutMs?: number;\n /** Circuit breaker instance (optional) */\n breaker?: CircuitBreaker;\n /** Operation name for error messages */\n operationName?: string;\n}\n\n/**\n * Execute a function with timeout and circuit breaker protection.\n *\n * Order of execution:\n * 1. Circuit breaker check (fail fast if open)\n * 2. Timeout wrapper\n * 3. Execute function\n * 4. Update circuit breaker state\n */\nexport async function withProtection<T>(\n fn: () => Promise<T>,\n options: ProtectionOptions = {},\n): Promise<T> {\n const { timeoutMs, breaker, operationName = \"operation\" } = options;\n\n const execute = async (): Promise<T> => {\n if (timeoutMs && timeoutMs > 0) {\n return withTimeout(fn(), timeoutMs, `${operationName} timed out`);\n }\n return fn();\n };\n\n if (breaker) {\n return breaker.execute(execute);\n }\n\n return execute();\n}\n\n/**\n * Create a protected function that always applies the same protection options.\n */\nexport function createProtectedFn<TArgs extends unknown[], TResult>(\n fn: (...args: TArgs) => Promise<TResult>,\n options: ProtectionOptions,\n): (...args: TArgs) => Promise<TResult> {\n return (...args: TArgs) => withProtection(() => fn(...args), options);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resilience-CFKHZSub.js","names":[],"sources":["../src/resilience/circuit-breaker.ts","../src/resilience/timeout.ts","../src/resilience/protection.ts"],"sourcesContent":["/**\n * Circuit Breaker\n *\n * Implements the circuit breaker pattern for fail-fast behavior when\n * downstream services are unhealthy. Prevents cascade failures by\n * stopping requests to failing services.\n *\n * States:\n * - CLOSED: Normal operation, requests pass through\n * - OPEN: Service unhealthy, requests fail immediately\n * - HALF_OPEN: Testing if service recovered\n */\n\nimport { SDKError } from \"../errors/index.js\";\n\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\nexport interface CircuitBreakerConfig {\n /** Number of failures before opening circuit */\n failureThreshold: number;\n /** Time in ms to wait before testing recovery (half-open) */\n resetTimeoutMs: number;\n /** Number of successes in half-open state to close circuit */\n successThreshold: number;\n /** Optional: Only count these error types as failures */\n failureFilter?: (error: unknown) => boolean;\n}\n\nexport interface CircuitBreakerStats {\n state: CircuitState;\n failures: number;\n successes: number;\n lastFailureTime: number | null;\n totalFailures: number;\n totalSuccesses: number;\n totalRejected: number;\n}\n\nexport class CircuitOpenError extends SDKError {\n readonly circuitName: string;\n readonly resetAfterMs: number;\n\n constructor(name: string, resetAfterMs: number) {\n super(`Circuit breaker '${name}' is open`, {\n code: \"SERVER\",\n retryable: true,\n retryAfterMs: resetAfterMs,\n context: { circuitName: name },\n });\n this.name = \"CircuitOpenError\";\n this.circuitName = name;\n this.resetAfterMs = resetAfterMs;\n }\n}\n\nexport class CircuitBreaker {\n private state: CircuitState = \"closed\";\n private failures = 0;\n private successes = 0;\n private lastFailureTime: number | null = null;\n\n // Lifetime stats\n private totalFailures = 0;\n private totalSuccesses = 0;\n private totalRejected = 0;\n\n constructor(\n private readonly name: string,\n private readonly config: CircuitBreakerConfig,\n ) {\n if (config.failureThreshold < 1) {\n throw new Error(\"failureThreshold must be >= 1\");\n }\n if (config.resetTimeoutMs < 0) {\n throw new Error(\"resetTimeoutMs must be >= 0\");\n }\n if (config.successThreshold < 1) {\n throw new Error(\"successThreshold must be >= 1\");\n }\n }\n\n /**\n * Execute a function through the circuit breaker.\n * Throws CircuitOpenError if circuit is open.\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check if we should transition from open to half-open\n if (this.state === \"open\") {\n const timeSinceFailure = this.lastFailureTime\n ? Date.now() - this.lastFailureTime\n : Number.POSITIVE_INFINITY;\n\n if (timeSinceFailure >= this.config.resetTimeoutMs) {\n this.state = \"half-open\";\n this.successes = 0;\n } else {\n this.totalRejected++;\n throw new CircuitOpenError(\n this.name,\n this.config.resetTimeoutMs - timeSinceFailure,\n );\n }\n }\n\n try {\n const result = await fn();\n this.onSuccess();\n return result;\n } catch (error) {\n this.onFailure(error);\n throw error;\n }\n }\n\n private onSuccess(): void {\n this.totalSuccesses++;\n\n if (this.state === \"half-open\") {\n this.successes++;\n if (this.successes >= this.config.successThreshold) {\n // Service recovered, close circuit\n this.state = \"closed\";\n this.failures = 0;\n this.successes = 0;\n }\n } else if (this.state === \"closed\") {\n // Reset failure count on success\n this.failures = 0;\n }\n }\n\n private onFailure(error: unknown): void {\n // Check if this error should count as a failure\n if (this.config.failureFilter && !this.config.failureFilter(error)) {\n return;\n }\n\n this.totalFailures++;\n this.failures++;\n this.lastFailureTime = Date.now();\n this.successes = 0;\n\n if (this.state === \"half-open\") {\n // Any failure in half-open returns to open\n this.state = \"open\";\n } else if (\n this.state === \"closed\" &&\n this.failures >= this.config.failureThreshold\n ) {\n // Threshold exceeded, open circuit\n this.state = \"open\";\n }\n }\n\n /** Get current circuit state */\n getState(): CircuitState {\n return this.state;\n }\n\n /** Get circuit statistics */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n lastFailureTime: this.lastFailureTime,\n totalFailures: this.totalFailures,\n totalSuccesses: this.totalSuccesses,\n totalRejected: this.totalRejected,\n };\n }\n\n /** Check if circuit is allowing requests */\n isAllowingRequests(): boolean {\n if (this.state === \"closed\" || this.state === \"half-open\") {\n return true;\n }\n\n // Check if reset timeout has passed\n const timeSinceFailure = this.lastFailureTime\n ? Date.now() - this.lastFailureTime\n : Number.POSITIVE_INFINITY;\n\n return timeSinceFailure >= this.config.resetTimeoutMs;\n }\n\n /** Manually reset the circuit to closed state */\n reset(): void {\n this.state = \"closed\";\n this.failures = 0;\n this.successes = 0;\n this.lastFailureTime = null;\n }\n\n /** Manually open the circuit */\n open(): void {\n this.state = \"open\";\n this.lastFailureTime = Date.now();\n }\n}\n","/**\n * Timeout Utilities\n *\n * Promise-based timeout handling with proper cleanup.\n */\n\nimport { SDKError } from \"../errors/index.js\";\n\nexport class TimeoutError extends SDKError {\n readonly timeoutMs: number;\n\n constructor(message: string, timeoutMs: number) {\n super(message, {\n code: \"TIMEOUT\",\n retryable: true,\n context: { timeoutMs },\n });\n this.name = \"TimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Wrap a promise with a timeout.\n * Rejects with TimeoutError if the promise doesn't resolve in time.\n */\nexport function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message?: string,\n): Promise<T> {\n if (timeoutMs <= 0) {\n return promise;\n }\n\n let timeoutId: ReturnType<typeof setTimeout>;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(\n new TimeoutError(\n message || `Operation timed out after ${timeoutMs}ms`,\n timeoutMs,\n ),\n );\n }, timeoutMs);\n });\n\n return Promise.race([promise, timeoutPromise]).finally(() => {\n clearTimeout(timeoutId);\n });\n}\n\n/**\n * Create an AbortController that auto-aborts after a timeout.\n * Returns the controller and a cleanup function.\n */\nexport function createTimeoutController(timeoutMs: number): {\n controller: AbortController;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n if (timeoutMs > 0) {\n timeoutId = setTimeout(() => {\n controller.abort(new TimeoutError(\"Request timeout\", timeoutMs));\n }, timeoutMs);\n }\n\n return {\n controller,\n cleanup: () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n },\n };\n}\n\n/**\n * Sleep for a specified duration.\n * Optionally accepts an AbortSignal for cancellation.\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const timeoutId = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timeoutId);\n reject(signal.reason);\n },\n { once: true },\n );\n });\n}\n","/**\n * Combines timeout + circuit breaker into a single request guard.\n */\n\nimport type { CircuitBreaker } from \"./circuit-breaker.js\";\nimport { withTimeout } from \"./timeout.js\";\n\nexport interface ProtectionOptions {\n /** Timeout in milliseconds (0 or undefined = no timeout) */\n timeoutMs?: number;\n /** Circuit breaker instance (optional) */\n breaker?: CircuitBreaker;\n /** Operation name for error messages */\n operationName?: string;\n}\n\n/**\n * Execute a function with timeout and circuit breaker protection.\n *\n * Order of execution:\n * 1. Circuit breaker check (fail fast if open)\n * 2. Timeout wrapper\n * 3. Execute function\n * 4. Update circuit breaker state\n */\nexport async function withProtection<T>(\n fn: () => Promise<T>,\n options: ProtectionOptions = {},\n): Promise<T> {\n const { timeoutMs, breaker, operationName = \"operation\" } = options;\n\n const execute = async (): Promise<T> => {\n if (timeoutMs && timeoutMs > 0) {\n return withTimeout(fn(), timeoutMs, `${operationName} timed out`);\n }\n return fn();\n };\n\n if (breaker) {\n return breaker.execute(execute);\n }\n\n return execute();\n}\n\n/**\n * Create a protected function that always applies the same protection options.\n */\nexport function createProtectedFn<TArgs extends unknown[], TResult>(\n fn: (...args: TArgs) => Promise<TResult>,\n options: ProtectionOptions,\n): (...args: TArgs) => Promise<TResult> {\n return (...args: TArgs) => withProtection(() => fn(...args), options);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/sse/index.ts"],"mappings":";;AAQA;;;;;;UAAiB,YAAA;EACf,IAAA;EAEA,QAAA;EACA,IAAA;EACA,MAAA;EACA,KAAA;EACA,SAAA;EACA,MAAA;EACA,MAAA;EACA,UAAA;EAEA,KAAA;EACA,OAAA;EACA,IAAA;EAEA,MAAA;EAEA,MAAA;EACA,KAAA;EAEA,WAAA;EACA,YAAA;EACA,YAAA;EACA,aAAA;EACA,uBAAA;EACA,2BAAA;EAEA,KAAA;IACE,YAAA;IACA,aAAA;IACA,uBAAA;IACA,2BAAA;EAAA;EAAA,CAGD,GAAA;AAAA;;;AA2CH;;;;;;;iBA/BgB,YAAA,CAAa,OAAA,WAAkB,YAAA;AAAA,UA+B9B,gBAAA;EAIe;EAF9B,YAAA;EAKe;EAHf,SAAA,IAAa,GAAA,aAAgB,CAAA;AAAA;AAAA,UAGd,cAAA;EACf,IAAA,EAAM,CAAA;EACN,OAAA;EACA,OAAA;EACA,SAAA;AAAA;;;;AAOF;cAAa,cAAA;EAAA,QACH,MAAA;EAAA,QACA,YAAA;EAAA,QACA,OAAA;cAEI,OAAA,GAAS,gBAAA,CAAiB,CAAA;EAItC,IAAA,CAAK,KAAA,WAAgB,cAAA,CAAe,CAAA;EAOpC,KAAA,CAAA,GAAS,cAAA,CAAe,CAAA;EAAA,QAYhB,YAAA;EAAA,QA4CA,iBAAA;AAAA;;;;iBA2Ca,cAAA,aAAA,CACrB,MAAA,EAAQ,cAAA,CAAe,UAAA,GACvB,OAAA,GAAS,gBAAA,CAAiB,CAAA,IACzB,cAAA,CAAe,cAAA,CAAe,CAAA;;;;iBA4CX,gBAAA,aAAA,CACpB,MAAA,EAAQ,cAAA,CAAe,UAAA,GACvB,OAAA,GAAU,KAAA,EAAO,cAAA,CAAe,CAAA,YAChC,OAAA,GAAU,KAAA,EAAO,KAAA,WACjB,OAAA,GAAS,gBAAA,CAAiB,CAAA,IACzB,OAAA;;UAuCc,gBAAA;EACf,WAAA;EACA,YAAA;EACA,eAAA;EACA,gBAAA;AAAA;;UAIe,sBAAA;EA9IU;EAgJzB,KAAA,EAAO,gBAAA;EArGc;EAuGrB,aAAA;EAvGmC;EAyGnC,aAAA;EAxGQ;EA0GR,OAAA;EAzGS;EA2GT,SAAA,EAAW,IAAA;EA1GK;EA4GhB,UAAA;AAAA;;;;;;;;;;;;;;AAhEF;;;;cA0Fa,oBAAA;EAAA,QACH,WAAA;EAAA,QACA,SAAA;;EAxFkB;;;EAyG1B,aAAA,CAAc,GAAA;EAxGN;;;EAkHR,YAAA,CAAa,KAAA,EAAO,YAAA,GAAe,MAAA;EAtHnC;;;;EA0KA,QAAA,CAAA,GAAY,sBAAA;EAxKK;;;EAuLjB,OAAA,CAAA,GAAW,QAAA,CAAS,sBAAA;EAtLM;;;EA6L1B,KAAA,CAAA;EAAA,QAaQ,aAAA;EAAA,QAyCA,mBAAA;AAAA;;;;iBA4BM,0BAAA,CAAA,GAA8B,oBAAA;;;;;AA/N9C;;;;;;;;;iBAgPgB,mBAAA,WAA8B,MAAA,kBAAA,CAC5C,OAAA,IAAW,KAAA,EAAO,CAAA;EAElB,QAAA,GAAW,KAAA,EAAO,CAAA;EAClB,QAAA,QAAgB,sBAAA;EAChB,SAAA,EAAW,oBAAA;AAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/sse/index.ts"],"mappings":";;;;;;;;UAQiB;EACf;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EAEA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;IACE;IACA;IACA;IACA;;GAGD;;;;;;;;;;;iBAYa,aAAa,kBAAkB;UA+B9B,iBAAiB;;EAEhC;;EAEA,aAAa,gBAAgB;;UAGd,eAAe;EAC9B,MAAM;EACN;EACA;EACA;;;;;;cAOW,eAAe;UAClB;UACA;UACA;EAER,YAAY,UAAS,iBAAiB;EAItC,KAAK,gBAAgB,eAAe;EAOpC,SAAS,eAAe;UAYhB;UA4CA;;;;;iBA2Ca,eAAe,aACpC,QAAQ,eAAe,aACvB,UAAS,iBAAiB,KACzB,eAAe,eAAe;;;;iBA4CX,iBAAiB,aACrC,QAAQ,eAAe,aACvB,UAAU,OAAO,eAAe,aAChC,UAAU,OAAO,gBACjB,UAAS,iBAAiB,KACzB;;UAuCc;EACf;EACA;EACA;EACA;;;UAIe;;EAEf,OAAO;;EAEP;;EAEA;;EAEA;;EAEA,WAAW;;EAEX;;;;;;;;;;;;;;;;;;;cA0BW;UACH;UACA;EAER;;;;EAeA,cAAc;;;;EAUd,aAAa,OAAO,eAAe;;;;;EAoDnC,YAAY;;;;EAeZ,WAAW,SAAS;;;;EAOpB;UAaQ;UAyCA;;;;;iBA4BM,8BAA8B;;;;;;;;;;;;;;iBAiB9B,oBAAoB,UAAU,yBAC5C,WAAW,OAAO;EAElB,WAAW,OAAO;EAClB,gBAAgB;EAChB,WAAW"}
package/dist/sse/index.js CHANGED
@@ -156,7 +156,7 @@ async function consumeSSEStream(stream, onEvent, onError, options = {}) {
156
156
  }
157
157
  }
158
158
  /** Event types that contain token information (Anthropic SDK format) */
159
- const TOKEN_EVENTS = new Set(["message.stop", "content_block_stop"]);
159
+ const TOKEN_EVENTS = /* @__PURE__ */ new Set(["message.stop", "content_block_stop"]);
160
160
  /**
161
161
  * StreamUsageExtractor - Accumulates token usage from SSE events.
162
162
  *
@@ -1 +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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"}
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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"}
@@ -1,2 +1,2 @@
1
- import { $ as CONTENT_KEY_FIELD, A as TANGLE_SUBJECT_KEY, B as GEN_AI_MODEL_KEYS, C as RUN_KEY_ATTRS, D as TANGLE_RUN_ID_KEY, E as TANGLE_RUN_ID_CAMEL_KEY, F as TRIGGER_ID_ATTRS, G as GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, H as GEN_AI_OUTPUT_TOKEN_KEYS, I as TRIGGER_SOURCE_ATTRS, J as GEN_AI_USAGE_OUTPUT_TOKENS, K as GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, L as WORKFLOW_MARKER_ATTRS, M as TANGLE_TRIGGER_KIND_KEY, N as TANGLE_TRIGGER_SOURCE_KEY, O as TANGLE_RUN_KIND_KEY, P as TANGLE_WORKFLOW_ID_KEY, Q as CONTENT_KEYS, R as GEN_AI_CONVERSATION_ID, S as PARENT_RUN_KEY_ATTRS, T as SUBJECT_KEY_ATTRS, U as GEN_AI_REQUEST_MODEL, V as GEN_AI_OPERATION_NAME, W as GEN_AI_RESPONSE_MODEL, X as genAiUsageAttributes, Y as GenAiUsage, Z as CONTENT_COMPLETION_KEY, _ as promptTokens, a as TOKEN_USAGE_CACHE_READ_INCLUSIVE_KEYS, at as DeclaredIntentMatch, b as tokenCount, c as TOKEN_USAGE_COST_KEYS, ct as asContentField, d as TOKEN_USAGE_OUTPUT_KEYS, dt as declaredTaskText, et as CONTENT_PROMPT_KEY, f as TokenUsageCounts, ft as extractContent, g as firstUsageCostUsd, gt as resolveDeclaredIntent, h as firstTokenCount, ht as normalizeContentAttributes, i as TOKEN_USAGE_CACHE_READ_EXCLUSIVE_KEYS, it as ContentField, j as TANGLE_TRIGGER_ID_KEY, k as TANGLE_RUN_PARENT_ID_KEY, l as TOKEN_USAGE_DETAIL_KEYS, lt as asContentString, m as cacheHitRate, mt as logRecordContentBag, n as TOKEN_USAGE_CACHE_BAG_READ_KEYS, nt as CONTENT_TOOL_NAME_KEY, o as TOKEN_USAGE_CACHE_WRITE_EXCLUSIVE_KEYS, ot as INDEXED_CONTENT_KEY_LIKE_PATTERNS, p as addTokenUsage, pt as hasContent, q as GEN_AI_USAGE_INPUT_TOKENS, r as TOKEN_USAGE_CACHE_BAG_WRITE_KEYS, rt as CONTENT_TOOL_RESULT_KEY, s as TOKEN_USAGE_CACHE_WRITE_INCLUSIVE_KEYS, st as NormalizedContent, t as TOKEN_USAGE_CACHE_BAG_KEYS, tt as CONTENT_TOOL_ARGS_KEY, u as TOKEN_USAGE_INPUT_KEYS, ut as classifyAgent, v as readTokenCostUsd, w as RUN_KIND_ATTRS, x as tokenUsageSource, y as readTokenUsage, z as GEN_AI_INPUT_TOKEN_KEYS } from "../index-Bgao-NCe.js";
2
- export { CONTENT_COMPLETION_KEY, CONTENT_KEYS, CONTENT_KEY_FIELD, CONTENT_PROMPT_KEY, CONTENT_TOOL_ARGS_KEY, CONTENT_TOOL_NAME_KEY, CONTENT_TOOL_RESULT_KEY, ContentField, DeclaredIntentMatch, GEN_AI_CONVERSATION_ID, GEN_AI_INPUT_TOKEN_KEYS, GEN_AI_MODEL_KEYS, GEN_AI_OPERATION_NAME, GEN_AI_OUTPUT_TOKEN_KEYS, GEN_AI_REQUEST_MODEL, GEN_AI_RESPONSE_MODEL, GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, GenAiUsage, INDEXED_CONTENT_KEY_LIKE_PATTERNS, NormalizedContent, PARENT_RUN_KEY_ATTRS, RUN_KEY_ATTRS, RUN_KIND_ATTRS, SUBJECT_KEY_ATTRS, TANGLE_RUN_ID_CAMEL_KEY, TANGLE_RUN_ID_KEY, TANGLE_RUN_KIND_KEY, TANGLE_RUN_PARENT_ID_KEY, TANGLE_SUBJECT_KEY, TANGLE_TRIGGER_ID_KEY, TANGLE_TRIGGER_KIND_KEY, TANGLE_TRIGGER_SOURCE_KEY, TANGLE_WORKFLOW_ID_KEY, TOKEN_USAGE_CACHE_BAG_KEYS, TOKEN_USAGE_CACHE_BAG_READ_KEYS, TOKEN_USAGE_CACHE_BAG_WRITE_KEYS, TOKEN_USAGE_CACHE_READ_EXCLUSIVE_KEYS, TOKEN_USAGE_CACHE_READ_INCLUSIVE_KEYS, TOKEN_USAGE_CACHE_WRITE_EXCLUSIVE_KEYS, TOKEN_USAGE_CACHE_WRITE_INCLUSIVE_KEYS, TOKEN_USAGE_COST_KEYS, TOKEN_USAGE_DETAIL_KEYS, TOKEN_USAGE_INPUT_KEYS, TOKEN_USAGE_OUTPUT_KEYS, TRIGGER_ID_ATTRS, TRIGGER_SOURCE_ATTRS, TokenUsageCounts, WORKFLOW_MARKER_ATTRS, addTokenUsage, asContentField, asContentString, cacheHitRate, classifyAgent, declaredTaskText, extractContent, firstTokenCount, firstUsageCostUsd, genAiUsageAttributes, hasContent, logRecordContentBag, normalizeContentAttributes, promptTokens, readTokenCostUsd, readTokenUsage, resolveDeclaredIntent, tokenCount, tokenUsageSource };
1
+ import { $ as CONTENT_KEY_FIELD, A as TANGLE_SUBJECT_KEY, B as GEN_AI_MODEL_KEYS, C as RUN_KEY_ATTRS, D as TANGLE_RUN_ID_KEY, E as TANGLE_RUN_ID_CAMEL_KEY, F as TRIGGER_ID_ATTRS, G as GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, H as GEN_AI_OUTPUT_TOKEN_KEYS, I as TRIGGER_SOURCE_ATTRS, J as GEN_AI_USAGE_OUTPUT_TOKENS, K as GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, L as WORKFLOW_MARKER_ATTRS, M as TANGLE_TRIGGER_KIND_KEY, N as TANGLE_TRIGGER_SOURCE_KEY, O as TANGLE_RUN_KIND_KEY, P as TANGLE_WORKFLOW_ID_KEY, Q as CONTENT_KEYS, R as GEN_AI_CONVERSATION_ID, S as PARENT_RUN_KEY_ATTRS, T as SUBJECT_KEY_ATTRS, U as GEN_AI_REQUEST_MODEL, V as GEN_AI_OPERATION_NAME, W as GEN_AI_RESPONSE_MODEL, X as genAiUsageAttributes, Y as GenAiUsage, Z as CONTENT_COMPLETION_KEY, _ as promptTokens, a as TOKEN_USAGE_CACHE_READ_INCLUSIVE_KEYS, at as DeclaredIntentMatch, b as tokenCount, c as TOKEN_USAGE_COST_KEYS, ct as asContentField, d as TOKEN_USAGE_OUTPUT_KEYS, dt as declaredTaskText, et as CONTENT_PROMPT_KEY, f as TokenUsageCounts, ft as extractContent, g as firstUsageCostUsd, gt as resolveDeclaredIntent, h as firstTokenCount, ht as normalizeContentAttributes, i as TOKEN_USAGE_CACHE_READ_EXCLUSIVE_KEYS, it as ContentField, j as TANGLE_TRIGGER_ID_KEY, k as TANGLE_RUN_PARENT_ID_KEY, l as TOKEN_USAGE_DETAIL_KEYS, lt as asContentString, m as cacheHitRate, mt as logRecordContentBag, n as TOKEN_USAGE_CACHE_BAG_READ_KEYS, nt as CONTENT_TOOL_NAME_KEY, o as TOKEN_USAGE_CACHE_WRITE_EXCLUSIVE_KEYS, ot as INDEXED_CONTENT_KEY_LIKE_PATTERNS, p as addTokenUsage, pt as hasContent, q as GEN_AI_USAGE_INPUT_TOKENS, r as TOKEN_USAGE_CACHE_BAG_WRITE_KEYS, rt as CONTENT_TOOL_RESULT_KEY, s as TOKEN_USAGE_CACHE_WRITE_INCLUSIVE_KEYS, st as NormalizedContent, t as TOKEN_USAGE_CACHE_BAG_KEYS, tt as CONTENT_TOOL_ARGS_KEY, u as TOKEN_USAGE_INPUT_KEYS, ut as classifyAgent, v as readTokenCostUsd, w as RUN_KIND_ATTRS, x as tokenUsageSource, y as readTokenUsage, z as GEN_AI_INPUT_TOKEN_KEYS } from "../index-BvjA5i93.js";
2
+ export { CONTENT_COMPLETION_KEY, CONTENT_KEYS, CONTENT_KEY_FIELD, CONTENT_PROMPT_KEY, CONTENT_TOOL_ARGS_KEY, CONTENT_TOOL_NAME_KEY, CONTENT_TOOL_RESULT_KEY, type ContentField, type DeclaredIntentMatch, GEN_AI_CONVERSATION_ID, GEN_AI_INPUT_TOKEN_KEYS, GEN_AI_MODEL_KEYS, GEN_AI_OPERATION_NAME, GEN_AI_OUTPUT_TOKEN_KEYS, GEN_AI_REQUEST_MODEL, GEN_AI_RESPONSE_MODEL, GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, type GenAiUsage, INDEXED_CONTENT_KEY_LIKE_PATTERNS, type NormalizedContent, PARENT_RUN_KEY_ATTRS, RUN_KEY_ATTRS, RUN_KIND_ATTRS, SUBJECT_KEY_ATTRS, TANGLE_RUN_ID_CAMEL_KEY, TANGLE_RUN_ID_KEY, TANGLE_RUN_KIND_KEY, TANGLE_RUN_PARENT_ID_KEY, TANGLE_SUBJECT_KEY, TANGLE_TRIGGER_ID_KEY, TANGLE_TRIGGER_KIND_KEY, TANGLE_TRIGGER_SOURCE_KEY, TANGLE_WORKFLOW_ID_KEY, TOKEN_USAGE_CACHE_BAG_KEYS, TOKEN_USAGE_CACHE_BAG_READ_KEYS, TOKEN_USAGE_CACHE_BAG_WRITE_KEYS, TOKEN_USAGE_CACHE_READ_EXCLUSIVE_KEYS, TOKEN_USAGE_CACHE_READ_INCLUSIVE_KEYS, TOKEN_USAGE_CACHE_WRITE_EXCLUSIVE_KEYS, TOKEN_USAGE_CACHE_WRITE_INCLUSIVE_KEYS, TOKEN_USAGE_COST_KEYS, TOKEN_USAGE_DETAIL_KEYS, TOKEN_USAGE_INPUT_KEYS, TOKEN_USAGE_OUTPUT_KEYS, TRIGGER_ID_ATTRS, TRIGGER_SOURCE_ATTRS, type TokenUsageCounts, WORKFLOW_MARKER_ATTRS, addTokenUsage, asContentField, asContentString, cacheHitRate, classifyAgent, declaredTaskText, extractContent, firstTokenCount, firstUsageCostUsd, genAiUsageAttributes, hasContent, logRecordContentBag, normalizeContentAttributes, promptTokens, readTokenCostUsd, readTokenUsage, resolveDeclaredIntent, tokenCount, tokenUsageSource };
@@ -1,2 +1,2 @@
1
- import { $ as CONTENT_TOOL_ARGS_KEY, A as TANGLE_TRIGGER_ID_KEY, B as GEN_AI_OPERATION_NAME, C as RUN_KIND_ATTRS, D as TANGLE_RUN_KIND_KEY, E as TANGLE_RUN_ID_KEY, F as TRIGGER_SOURCE_ATTRS, G as GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, H as GEN_AI_REQUEST_MODEL, I as WORKFLOW_MARKER_ATTRS, J as genAiUsageAttributes, K as GEN_AI_USAGE_INPUT_TOKENS, L as GEN_AI_CONVERSATION_ID, M as TANGLE_TRIGGER_SOURCE_KEY, N as TANGLE_WORKFLOW_ID_KEY, O as TANGLE_RUN_PARENT_ID_KEY, P as TRIGGER_ID_ATTRS, Q as CONTENT_PROMPT_KEY, R as GEN_AI_INPUT_TOKEN_KEYS, S as RUN_KEY_ATTRS, T as TANGLE_RUN_ID_CAMEL_KEY, U as GEN_AI_RESPONSE_MODEL, V as GEN_AI_OUTPUT_TOKEN_KEYS, W as GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, X as CONTENT_KEYS, Y as CONTENT_COMPLETION_KEY, Z as CONTENT_KEY_FIELD, _ as readTokenCostUsd, a as TOKEN_USAGE_CACHE_READ_INCLUSIVE_KEYS, at as classifyAgent, b as tokenUsageSource, c as TOKEN_USAGE_COST_KEYS, ct as hasContent, d as TOKEN_USAGE_OUTPUT_KEYS, dt as resolveDeclaredIntent, et as CONTENT_TOOL_NAME_KEY, f as addTokenUsage, g as promptTokens, h as firstUsageCostUsd, i as TOKEN_USAGE_CACHE_READ_EXCLUSIVE_KEYS, it as asContentString, j as TANGLE_TRIGGER_KIND_KEY, k as TANGLE_SUBJECT_KEY, l as TOKEN_USAGE_DETAIL_KEYS, lt as logRecordContentBag, m as firstTokenCount, n as TOKEN_USAGE_CACHE_BAG_READ_KEYS, nt as INDEXED_CONTENT_KEY_LIKE_PATTERNS, o as TOKEN_USAGE_CACHE_WRITE_EXCLUSIVE_KEYS, ot as declaredTaskText, p as cacheHitRate, q as GEN_AI_USAGE_OUTPUT_TOKENS, r as TOKEN_USAGE_CACHE_BAG_WRITE_KEYS, rt as asContentField, s as TOKEN_USAGE_CACHE_WRITE_INCLUSIVE_KEYS, st as extractContent, t as TOKEN_USAGE_CACHE_BAG_KEYS, tt as CONTENT_TOOL_RESULT_KEY, u as TOKEN_USAGE_INPUT_KEYS, ut as normalizeContentAttributes, v as readTokenUsage, w as SUBJECT_KEY_ATTRS, x as PARENT_RUN_KEY_ATTRS, y as tokenCount, z as GEN_AI_MODEL_KEYS } from "../telemetry-x1wNw1P4.js";
1
+ import { $ as CONTENT_TOOL_ARGS_KEY, A as TANGLE_TRIGGER_ID_KEY, B as GEN_AI_OPERATION_NAME, C as RUN_KIND_ATTRS, D as TANGLE_RUN_KIND_KEY, E as TANGLE_RUN_ID_KEY, F as TRIGGER_SOURCE_ATTRS, G as GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, H as GEN_AI_REQUEST_MODEL, I as WORKFLOW_MARKER_ATTRS, J as genAiUsageAttributes, K as GEN_AI_USAGE_INPUT_TOKENS, L as GEN_AI_CONVERSATION_ID, M as TANGLE_TRIGGER_SOURCE_KEY, N as TANGLE_WORKFLOW_ID_KEY, O as TANGLE_RUN_PARENT_ID_KEY, P as TRIGGER_ID_ATTRS, Q as CONTENT_PROMPT_KEY, R as GEN_AI_INPUT_TOKEN_KEYS, S as RUN_KEY_ATTRS, T as TANGLE_RUN_ID_CAMEL_KEY, U as GEN_AI_RESPONSE_MODEL, V as GEN_AI_OUTPUT_TOKEN_KEYS, W as GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, X as CONTENT_KEYS, Y as CONTENT_COMPLETION_KEY, Z as CONTENT_KEY_FIELD, _ as readTokenCostUsd, a as TOKEN_USAGE_CACHE_READ_INCLUSIVE_KEYS, at as classifyAgent, b as tokenUsageSource, c as TOKEN_USAGE_COST_KEYS, ct as hasContent, d as TOKEN_USAGE_OUTPUT_KEYS, dt as resolveDeclaredIntent, et as CONTENT_TOOL_NAME_KEY, f as addTokenUsage, g as promptTokens, h as firstUsageCostUsd, i as TOKEN_USAGE_CACHE_READ_EXCLUSIVE_KEYS, it as asContentString, j as TANGLE_TRIGGER_KIND_KEY, k as TANGLE_SUBJECT_KEY, l as TOKEN_USAGE_DETAIL_KEYS, lt as logRecordContentBag, m as firstTokenCount, n as TOKEN_USAGE_CACHE_BAG_READ_KEYS, nt as INDEXED_CONTENT_KEY_LIKE_PATTERNS, o as TOKEN_USAGE_CACHE_WRITE_EXCLUSIVE_KEYS, ot as declaredTaskText, p as cacheHitRate, q as GEN_AI_USAGE_OUTPUT_TOKENS, r as TOKEN_USAGE_CACHE_BAG_WRITE_KEYS, rt as asContentField, s as TOKEN_USAGE_CACHE_WRITE_INCLUSIVE_KEYS, st as extractContent, t as TOKEN_USAGE_CACHE_BAG_KEYS, tt as CONTENT_TOOL_RESULT_KEY, u as TOKEN_USAGE_INPUT_KEYS, ut as normalizeContentAttributes, v as readTokenUsage, w as SUBJECT_KEY_ATTRS, x as PARENT_RUN_KEY_ATTRS, y as tokenCount, z as GEN_AI_MODEL_KEYS } from "../telemetry-DTOiMSzM.js";
2
2
  export { CONTENT_COMPLETION_KEY, CONTENT_KEYS, CONTENT_KEY_FIELD, CONTENT_PROMPT_KEY, CONTENT_TOOL_ARGS_KEY, CONTENT_TOOL_NAME_KEY, CONTENT_TOOL_RESULT_KEY, GEN_AI_CONVERSATION_ID, GEN_AI_INPUT_TOKEN_KEYS, GEN_AI_MODEL_KEYS, GEN_AI_OPERATION_NAME, GEN_AI_OUTPUT_TOKEN_KEYS, GEN_AI_REQUEST_MODEL, GEN_AI_RESPONSE_MODEL, GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, INDEXED_CONTENT_KEY_LIKE_PATTERNS, PARENT_RUN_KEY_ATTRS, RUN_KEY_ATTRS, RUN_KIND_ATTRS, SUBJECT_KEY_ATTRS, TANGLE_RUN_ID_CAMEL_KEY, TANGLE_RUN_ID_KEY, TANGLE_RUN_KIND_KEY, TANGLE_RUN_PARENT_ID_KEY, TANGLE_SUBJECT_KEY, TANGLE_TRIGGER_ID_KEY, TANGLE_TRIGGER_KIND_KEY, TANGLE_TRIGGER_SOURCE_KEY, TANGLE_WORKFLOW_ID_KEY, TOKEN_USAGE_CACHE_BAG_KEYS, TOKEN_USAGE_CACHE_BAG_READ_KEYS, TOKEN_USAGE_CACHE_BAG_WRITE_KEYS, TOKEN_USAGE_CACHE_READ_EXCLUSIVE_KEYS, TOKEN_USAGE_CACHE_READ_INCLUSIVE_KEYS, TOKEN_USAGE_CACHE_WRITE_EXCLUSIVE_KEYS, TOKEN_USAGE_CACHE_WRITE_INCLUSIVE_KEYS, TOKEN_USAGE_COST_KEYS, TOKEN_USAGE_DETAIL_KEYS, TOKEN_USAGE_INPUT_KEYS, TOKEN_USAGE_OUTPUT_KEYS, TRIGGER_ID_ATTRS, TRIGGER_SOURCE_ATTRS, WORKFLOW_MARKER_ATTRS, addTokenUsage, asContentField, asContentString, cacheHitRate, classifyAgent, declaredTaskText, extractContent, firstTokenCount, firstUsageCostUsd, genAiUsageAttributes, hasContent, logRecordContentBag, normalizeContentAttributes, promptTokens, readTokenCostUsd, readTokenUsage, resolveDeclaredIntent, tokenCount, tokenUsageSource };
@@ -1093,4 +1093,4 @@ function cacheHitRate(usage) {
1093
1093
  //#endregion
1094
1094
  export { CONTENT_TOOL_ARGS_KEY as $, TANGLE_TRIGGER_ID_KEY as A, GEN_AI_OPERATION_NAME as B, RUN_KIND_ATTRS as C, TANGLE_RUN_KIND_KEY as D, TANGLE_RUN_ID_KEY as E, TRIGGER_SOURCE_ATTRS as F, GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS as G, GEN_AI_REQUEST_MODEL as H, WORKFLOW_MARKER_ATTRS as I, genAiUsageAttributes as J, GEN_AI_USAGE_INPUT_TOKENS as K, GEN_AI_CONVERSATION_ID as L, TANGLE_TRIGGER_SOURCE_KEY as M, TANGLE_WORKFLOW_ID_KEY as N, TANGLE_RUN_PARENT_ID_KEY as O, TRIGGER_ID_ATTRS as P, CONTENT_PROMPT_KEY as Q, GEN_AI_INPUT_TOKEN_KEYS as R, RUN_KEY_ATTRS as S, TANGLE_RUN_ID_CAMEL_KEY as T, GEN_AI_RESPONSE_MODEL as U, GEN_AI_OUTPUT_TOKEN_KEYS as V, GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS as W, CONTENT_KEYS as X, CONTENT_COMPLETION_KEY as Y, CONTENT_KEY_FIELD as Z, readTokenCostUsd as _, TOKEN_USAGE_CACHE_READ_INCLUSIVE_KEYS as a, classifyAgent as at, tokenUsageSource as b, TOKEN_USAGE_COST_KEYS as c, hasContent as ct, TOKEN_USAGE_OUTPUT_KEYS as d, resolveDeclaredIntent as dt, CONTENT_TOOL_NAME_KEY as et, addTokenUsage as f, promptTokens as g, firstUsageCostUsd as h, TOKEN_USAGE_CACHE_READ_EXCLUSIVE_KEYS as i, asContentString as it, TANGLE_TRIGGER_KIND_KEY as j, TANGLE_SUBJECT_KEY as k, TOKEN_USAGE_DETAIL_KEYS as l, logRecordContentBag as lt, firstTokenCount as m, TOKEN_USAGE_CACHE_BAG_READ_KEYS as n, INDEXED_CONTENT_KEY_LIKE_PATTERNS as nt, TOKEN_USAGE_CACHE_WRITE_EXCLUSIVE_KEYS as o, declaredTaskText as ot, cacheHitRate as p, GEN_AI_USAGE_OUTPUT_TOKENS as q, TOKEN_USAGE_CACHE_BAG_WRITE_KEYS as r, asContentField as rt, TOKEN_USAGE_CACHE_WRITE_INCLUSIVE_KEYS as s, extractContent as st, TOKEN_USAGE_CACHE_BAG_KEYS as t, CONTENT_TOOL_RESULT_KEY as tt, TOKEN_USAGE_INPUT_KEYS as u, normalizeContentAttributes as ut, readTokenUsage as v, SUBJECT_KEY_ATTRS as w, PARENT_RUN_KEY_ATTRS as x, tokenCount as y, GEN_AI_MODEL_KEYS as z };
1095
1095
 
1096
- //# sourceMappingURL=telemetry-x1wNw1P4.js.map
1096
+ //# sourceMappingURL=telemetry-DTOiMSzM.js.map