@omnicross/core 0.1.0 → 0.1.2

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 (272) hide show
  1. package/dist/ApiConverter.cjs +24 -0
  2. package/dist/ApiConverter.d.cts +82 -0
  3. package/dist/ApiConverter.d.ts +82 -0
  4. package/dist/ApiConverter.js +24 -0
  5. package/dist/BuiltinToolExecutor-BluWyeob.d.ts +81 -0
  6. package/dist/BuiltinToolExecutor-CS2WpXhM.d.cts +81 -0
  7. package/dist/CompletionService-D3a47vdU.d.cts +213 -0
  8. package/dist/CompletionService-DdWaAxq0.d.ts +213 -0
  9. package/dist/{ProviderProxy-f_8ziIhW.d.cts → ProviderProxy-C-xqrkKi.d.ts} +7 -2
  10. package/dist/{ProviderProxy-vjt8sQQk.d.ts → ProviderProxy-CnMQYN59.d.cts} +7 -2
  11. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +27 -60
  12. package/dist/auth/GeminiCodeAssistProjectResolver.js +5 -9
  13. package/dist/builtin-web-fetch-77JZUZGM.cjs +100 -0
  14. package/dist/builtin-web-fetch-IGLBX2XY.js +100 -0
  15. package/dist/chunk-2DCNB7DF.cjs +514 -0
  16. package/dist/chunk-2FEVTJWG.js +4400 -0
  17. package/dist/chunk-3MEACFK3.js +193 -0
  18. package/dist/chunk-3OPYJG76.cjs +266 -0
  19. package/dist/chunk-46RLHI7D.js +0 -0
  20. package/dist/chunk-46ZIFWYG.cjs +277 -0
  21. package/dist/chunk-4NBS6KPV.cjs +43 -0
  22. package/dist/chunk-4VAVYUZS.cjs +991 -0
  23. package/dist/chunk-5ERIZW3D.js +44 -0
  24. package/dist/chunk-5HTVET6E.js +514 -0
  25. package/dist/chunk-5ZQBEOMD.js +764 -0
  26. package/dist/chunk-6VIXXLMX.cjs +14 -0
  27. package/dist/chunk-745DV5FL.js +147 -0
  28. package/dist/chunk-74TMJA7Z.js +53 -0
  29. package/dist/chunk-7VU7V2E4.js +0 -0
  30. package/dist/chunk-7YN22L2H.cjs +87 -0
  31. package/dist/chunk-A2YMUCBT.cjs +105 -0
  32. package/dist/chunk-AQ5TNQB7.js +13 -0
  33. package/dist/chunk-AVYJ4YBN.js +58 -0
  34. package/dist/chunk-C72S6TTV.cjs +49 -0
  35. package/dist/chunk-C7PSERMH.js +87 -0
  36. package/dist/chunk-CDHS2QDC.js +179 -0
  37. package/dist/chunk-DK4A7DLE.js +266 -0
  38. package/dist/chunk-DRWHTIIZ.js +13 -0
  39. package/dist/chunk-DWKQZ2SK.cjs +254 -0
  40. package/dist/chunk-E3WHL7CO.js +14 -0
  41. package/dist/chunk-EYZYXJTJ.cjs +1 -0
  42. package/dist/chunk-FMOBD2OQ.js +39 -0
  43. package/dist/chunk-FTQ7IQUC.js +991 -0
  44. package/dist/chunk-FZ46M34D.cjs +1 -0
  45. package/dist/chunk-G2FUJNA2.cjs +193 -0
  46. package/dist/chunk-G2UTNSGU.js +277 -0
  47. package/dist/chunk-GBHYAGX3.cjs +26 -0
  48. package/dist/chunk-GMMT7RVN.cjs +39 -0
  49. package/dist/chunk-H5JUT3KV.js +105 -0
  50. package/dist/chunk-HQP3K7PU.cjs +431 -0
  51. package/dist/chunk-JO5NLTLY.js +46 -0
  52. package/dist/chunk-JWC6APFQ.js +23 -0
  53. package/dist/chunk-KUU2RNG6.cjs +46 -0
  54. package/dist/chunk-LKZJEL6E.cjs +124 -0
  55. package/dist/chunk-MNYKI4CI.js +94 -0
  56. package/dist/chunk-MZNPGW5Q.js +26 -0
  57. package/dist/chunk-N3V2J5ZO.cjs +53 -0
  58. package/dist/chunk-NYUNU75A.cjs +44 -0
  59. package/dist/chunk-NZYN7C3P.cjs +179 -0
  60. package/dist/chunk-O466Y272.js +235 -0
  61. package/dist/chunk-PXUJF5HS.js +124 -0
  62. package/dist/chunk-QBZJ7P2T.cjs +13 -0
  63. package/dist/chunk-QOCNX236.js +46 -0
  64. package/dist/chunk-QXD4MV2X.cjs +23 -0
  65. package/dist/chunk-R3HK6R4B.cjs +13 -0
  66. package/dist/chunk-RSJ3TWJQ.cjs +186 -0
  67. package/dist/chunk-S4WBV25P.js +913 -0
  68. package/dist/chunk-SN3YWBX7.cjs +4400 -0
  69. package/dist/chunk-SPVWWUHX.cjs +46 -0
  70. package/dist/chunk-SUEGJ75D.cjs +764 -0
  71. package/dist/chunk-SVNDB62D.cjs +58 -0
  72. package/dist/chunk-UYPEN5XE.cjs +235 -0
  73. package/dist/chunk-V5KPWNYX.cjs +147 -0
  74. package/dist/chunk-VVEHS2LI.js +431 -0
  75. package/dist/chunk-XBSYYZIY.cjs +94 -0
  76. package/dist/chunk-YGXJGRFI.cjs +913 -0
  77. package/dist/chunk-YMFAJFQT.cjs +173 -0
  78. package/dist/chunk-Z7LUNECE.js +49 -0
  79. package/dist/chunk-Z7Y2NPHY.js +186 -0
  80. package/dist/chunk-ZJZAOKI7.js +254 -0
  81. package/dist/chunk-ZLX3KGXX.js +173 -0
  82. package/dist/chunk-ZSVQT3PW.js +43 -0
  83. package/dist/completion/ApiKeyPoolService.cjs +23 -48
  84. package/dist/completion/ApiKeyPoolService.d.cts +150 -2
  85. package/dist/completion/ApiKeyPoolService.d.ts +150 -2
  86. package/dist/completion/BuiltinToolExecutor.cjs +12 -0
  87. package/dist/completion/BuiltinToolExecutor.d.cts +4 -0
  88. package/dist/completion/BuiltinToolExecutor.d.ts +4 -0
  89. package/dist/completion/BuiltinToolExecutor.js +12 -0
  90. package/dist/completion/CompletionService.cjs +38 -0
  91. package/dist/completion/CompletionService.d.cts +22 -0
  92. package/dist/completion/CompletionService.d.ts +22 -0
  93. package/dist/completion/CompletionService.js +38 -0
  94. package/dist/completion/NativeSearchInjector.cjs +12 -0
  95. package/dist/completion/NativeSearchInjector.d.cts +42 -0
  96. package/dist/completion/NativeSearchInjector.d.ts +42 -0
  97. package/dist/completion/NativeSearchInjector.js +12 -0
  98. package/dist/completion/ProviderSearchInjector.cjs +60 -0
  99. package/dist/completion/ProviderSearchInjector.d.cts +47 -0
  100. package/dist/completion/ProviderSearchInjector.d.ts +47 -0
  101. package/dist/completion/ProviderSearchInjector.js +60 -0
  102. package/dist/completion/native-search-types.cjs +14 -0
  103. package/dist/completion/native-search-types.d.cts +3 -0
  104. package/dist/completion/native-search-types.d.ts +3 -0
  105. package/dist/completion/native-search-types.js +14 -0
  106. package/dist/completion/openrouter-headers.cjs +16 -0
  107. package/dist/completion/openrouter-headers.d.cts +44 -0
  108. package/dist/completion/openrouter-headers.d.ts +44 -0
  109. package/dist/completion/openrouter-headers.js +16 -0
  110. package/dist/completion/openrouter-models.cjs +29 -0
  111. package/dist/completion/openrouter-models.d.cts +27 -0
  112. package/dist/completion/openrouter-models.d.ts +27 -0
  113. package/dist/completion/openrouter-models.js +29 -0
  114. package/dist/completion/types.cjs +1 -0
  115. package/dist/completion/types.d.cts +3 -0
  116. package/dist/completion/types.d.ts +3 -0
  117. package/dist/completion/types.js +0 -0
  118. package/dist/completion/url-builder.cjs +24 -0
  119. package/dist/completion/url-builder.d.cts +87 -0
  120. package/dist/completion/url-builder.d.ts +87 -0
  121. package/dist/completion/url-builder.js +24 -0
  122. package/dist/completion.cjs +55 -3989
  123. package/dist/completion.d.cts +150 -8
  124. package/dist/completion.d.ts +150 -8
  125. package/dist/completion.js +63 -3953
  126. package/dist/index.cjs +197 -10428
  127. package/dist/index.d.cts +35 -91
  128. package/dist/index.d.ts +35 -91
  129. package/dist/index.js +125 -10267
  130. package/dist/logger-4GvQNzhE.d.cts +22 -0
  131. package/dist/logger-4GvQNzhE.d.ts +22 -0
  132. package/dist/outbound-api/routeResolver.cjs +11 -0
  133. package/dist/outbound-api/routeResolver.d.cts +19 -0
  134. package/dist/outbound-api/routeResolver.d.ts +19 -0
  135. package/dist/outbound-api/routeResolver.js +11 -0
  136. package/dist/outbound-api/subscriptionRegistryPort.cjs +7 -37
  137. package/dist/outbound-api/subscriptionRegistryPort.d.cts +7 -3
  138. package/dist/outbound-api/subscriptionRegistryPort.d.ts +7 -3
  139. package/dist/outbound-api/subscriptionRegistryPort.js +4 -8
  140. package/dist/outbound-api/types.cjs +1 -0
  141. package/dist/{types-CbCN2NQP.d.ts → outbound-api/types.d.cts} +18 -3
  142. package/dist/{types-CGGrKqC_.d.cts → outbound-api/types.d.ts} +18 -3
  143. package/dist/outbound-api/types.js +0 -0
  144. package/dist/outbound-api.cjs +35 -5220
  145. package/dist/outbound-api.d.cts +16 -88
  146. package/dist/outbound-api.d.ts +16 -88
  147. package/dist/outbound-api.js +54 -5193
  148. package/dist/pipeline/AuthSource.cjs +1 -0
  149. package/dist/pipeline/AuthSource.d.cts +101 -0
  150. package/dist/pipeline/AuthSource.d.ts +101 -0
  151. package/dist/pipeline/AuthSource.js +0 -0
  152. package/dist/pipeline/LlmConfigProviderAuth.cjs +8 -0
  153. package/dist/pipeline/LlmConfigProviderAuth.d.cts +87 -0
  154. package/dist/pipeline/LlmConfigProviderAuth.d.ts +87 -0
  155. package/dist/pipeline/LlmConfigProviderAuth.js +8 -0
  156. package/dist/pipeline/SubscriptionAuthSource.cjs +6 -128
  157. package/dist/pipeline/SubscriptionAuthSource.d.cts +165 -3
  158. package/dist/pipeline/SubscriptionAuthSource.d.ts +165 -3
  159. package/dist/pipeline/SubscriptionAuthSource.js +5 -99
  160. package/dist/pipeline/SubscriptionAuthStrategy.cjs +1 -18
  161. package/dist/pipeline/executeProviderCall.cjs +6 -0
  162. package/dist/pipeline/executeProviderCall.d.cts +149 -0
  163. package/dist/pipeline/executeProviderCall.d.ts +149 -0
  164. package/dist/pipeline/executeProviderCall.js +6 -0
  165. package/dist/pipeline/resolveProviderChain.cjs +6 -0
  166. package/dist/pipeline/resolveProviderChain.d.cts +58 -0
  167. package/dist/pipeline/resolveProviderChain.d.ts +58 -0
  168. package/dist/pipeline/resolveProviderChain.js +6 -0
  169. package/dist/pipeline/resolveSubscriptionChain.cjs +6 -0
  170. package/dist/pipeline/resolveSubscriptionChain.d.cts +68 -0
  171. package/dist/pipeline/resolveSubscriptionChain.d.ts +68 -0
  172. package/dist/pipeline/resolveSubscriptionChain.js +6 -0
  173. package/dist/ports/gemini-code-assist-resolver.cjs +7 -37
  174. package/dist/ports/gemini-code-assist-resolver.js +4 -8
  175. package/dist/ports/pricing-store.cjs +1 -0
  176. package/dist/ports/pricing-store.d.cts +50 -0
  177. package/dist/ports/pricing-store.d.ts +50 -0
  178. package/dist/ports/pricing-store.js +0 -0
  179. package/dist/ports/provider-config-source.cjs +1 -0
  180. package/dist/ports/provider-config-source.d.cts +51 -0
  181. package/dist/ports/provider-config-source.d.ts +51 -0
  182. package/dist/ports/provider-config-source.js +0 -0
  183. package/dist/ports/usage-event-store.cjs +1 -0
  184. package/dist/ports/usage-event-store.d.cts +29 -0
  185. package/dist/ports/usage-event-store.d.ts +29 -0
  186. package/dist/ports/usage-event-store.js +0 -0
  187. package/dist/ports/web-search-backend.cjs +1 -0
  188. package/dist/ports/web-search-backend.d.cts +29 -0
  189. package/dist/ports/web-search-backend.d.ts +29 -0
  190. package/dist/ports/web-search-backend.js +0 -0
  191. package/dist/ports.cjs +1 -18
  192. package/dist/ports.d.cts +16 -8
  193. package/dist/ports.d.ts +16 -8
  194. package/dist/provider-proxy/ProviderProxy.cjs +40 -0
  195. package/dist/provider-proxy/ProviderProxy.d.cts +17 -0
  196. package/dist/provider-proxy/ProviderProxy.d.ts +17 -0
  197. package/dist/provider-proxy/ProviderProxy.js +40 -0
  198. package/dist/provider-proxy/ingress/providerProxyShared.cjs +35 -2941
  199. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +7 -3
  200. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +7 -3
  201. package/dist/provider-proxy/ingress/providerProxyShared.js +41 -2914
  202. package/dist/provider-proxy/matchText.cjs +11 -72
  203. package/dist/provider-proxy/matchText.js +6 -39
  204. package/dist/provider-proxy/types.cjs +1 -18
  205. package/dist/provider-proxy/types.d.cts +407 -8
  206. package/dist/provider-proxy/types.d.ts +407 -8
  207. package/dist/provider-proxy.cjs +35 -4654
  208. package/dist/provider-proxy.d.cts +10 -6
  209. package/dist/provider-proxy.d.ts +10 -6
  210. package/dist/provider-proxy.js +39 -4627
  211. package/dist/routeResolver-BrbK6ja9.d.cts +88 -0
  212. package/dist/routeResolver-HE-ZO0fO.d.ts +88 -0
  213. package/dist/serializeError.cjs +5 -81
  214. package/dist/serializeError.js +3 -54
  215. package/dist/sse-parser.cjs +7 -455
  216. package/dist/sse-parser.js +4 -426
  217. package/dist/transformer/TransformerChainExecutor.cjs +4 -318
  218. package/dist/transformer/TransformerChainExecutor.js +4 -291
  219. package/dist/transformer/TransformerService.cjs +5 -289
  220. package/dist/transformer/TransformerService.js +3 -262
  221. package/dist/transformer/anthropicBetaInject.cjs +8 -0
  222. package/dist/transformer/anthropicBetaInject.d.cts +20 -0
  223. package/dist/transformer/anthropicBetaInject.d.ts +20 -0
  224. package/dist/transformer/anthropicBetaInject.js +8 -0
  225. package/dist/transformer/transformers/AnthropicTransformer.cjs +6 -0
  226. package/dist/transformer/transformers/AnthropicTransformer.d.cts +148 -0
  227. package/dist/transformer/transformers/AnthropicTransformer.d.ts +148 -0
  228. package/dist/transformer/transformers/AnthropicTransformer.js +6 -0
  229. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +4 -1106
  230. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +7 -1079
  231. package/dist/transformer/transformers/GeminiTransformer.cjs +4 -1010
  232. package/dist/transformer/transformers/GeminiTransformer.js +4 -983
  233. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -535
  234. package/dist/transformer/transformers/OpenAIResponseTransformer.js +3 -510
  235. package/dist/transformer/transformers/OpenCodeGoTransformer.cjs +5 -72
  236. package/dist/transformer/transformers/OpenCodeGoTransformer.js +3 -45
  237. package/dist/transformer/transformers/ReasoningTransformer.cjs +6 -0
  238. package/dist/transformer/transformers/ReasoningTransformer.d.cts +47 -0
  239. package/dist/transformer/transformers/ReasoningTransformer.d.ts +47 -0
  240. package/dist/transformer/transformers/ReasoningTransformer.js +6 -0
  241. package/dist/transformer/transformers.cjs +39 -0
  242. package/dist/transformer/transformers.d.cts +100 -0
  243. package/dist/transformer/transformers.d.ts +100 -0
  244. package/dist/transformer/transformers.js +39 -0
  245. package/dist/transformer/types.cjs +1 -18
  246. package/dist/transformer.cjs +13 -3726
  247. package/dist/transformer.d.cts +8 -31
  248. package/dist/transformer.d.ts +8 -31
  249. package/dist/transformer.js +17 -3706
  250. package/dist/types-BScIHmPr.d.cts +153 -0
  251. package/dist/types-BScIHmPr.d.ts +153 -0
  252. package/dist/usage/pricing-engine.cjs +6 -0
  253. package/dist/usage/pricing-engine.d.cts +83 -0
  254. package/dist/usage/pricing-engine.d.ts +83 -0
  255. package/dist/usage/pricing-engine.js +6 -0
  256. package/dist/usage/usage-recorder.cjs +6 -0
  257. package/dist/usage/usage-recorder.d.cts +73 -0
  258. package/dist/usage/usage-recorder.d.ts +73 -0
  259. package/dist/usage/usage-recorder.js +6 -0
  260. package/dist/usage.cjs +11 -0
  261. package/dist/usage.d.cts +8 -0
  262. package/dist/usage.d.ts +8 -0
  263. package/dist/usage.js +11 -0
  264. package/package.json +3 -3
  265. package/dist/ApiKeyPoolService-BmMkau07.d.cts +0 -170
  266. package/dist/ApiKeyPoolService-BmMkau07.d.ts +0 -170
  267. package/dist/SubscriptionAuthSource-Cr4fVEYY.d.cts +0 -264
  268. package/dist/SubscriptionAuthSource-D89zmiSS.d.ts +0 -264
  269. package/dist/index-BTSmc9Sm.d.ts +0 -645
  270. package/dist/index-DXazdTzZ.d.cts +0 -645
  271. package/dist/types-DCzHkhJt.d.ts +0 -467
  272. package/dist/types-DZIQbgp0.d.cts +0 -467
@@ -0,0 +1,431 @@
1
+ // src/sse-parser.ts
2
+ var DEBUG_SSE = true;
3
+ function debugSSE(prefix, ...args) {
4
+ if (DEBUG_SSE) {
5
+ console.log(`[SSE-Parser] ${prefix}`, ...args);
6
+ }
7
+ }
8
+ function createSSEParser(format, callbacks) {
9
+ const state = {
10
+ buffer: "",
11
+ content: "",
12
+ reasoning: "",
13
+ usage: void 0,
14
+ isDone: false,
15
+ streamStartTime: void 0,
16
+ firstTokenTime: void 0,
17
+ streamEndTime: void 0,
18
+ blocks: [],
19
+ currentBlockIndex: -1,
20
+ currentBlockType: "",
21
+ inputJsonBuffer: "",
22
+ audios: [],
23
+ videos: []
24
+ };
25
+ function parseOpenAIEvent(data) {
26
+ if (data === "[DONE]") {
27
+ debugSSE("OpenAI [DONE] received, content length:", state.content.length);
28
+ state.isDone = true;
29
+ callbacks.onDone?.();
30
+ return;
31
+ }
32
+ try {
33
+ const json = JSON.parse(data);
34
+ callbacks.onRawEvent?.({ data: json, raw: data });
35
+ const delta = json.choices?.[0]?.delta;
36
+ const finishReason = json.choices?.[0]?.finish_reason;
37
+ if (finishReason) {
38
+ debugSSE("OpenAI finish_reason:", finishReason, "content length so far:", state.content.length);
39
+ }
40
+ if (delta?.content) {
41
+ if (!state.firstTokenTime) {
42
+ state.firstTokenTime = Date.now();
43
+ }
44
+ state.content += delta.content;
45
+ callbacks.onDelta?.(delta.content);
46
+ }
47
+ if (delta?.reasoning_content) {
48
+ state.reasoning += delta.reasoning_content;
49
+ callbacks.onReasoning?.(delta.reasoning_content);
50
+ }
51
+ if (delta?.audio) {
52
+ const audioData = delta.audio;
53
+ if (audioData.data) {
54
+ const mimeType = audioData.format ? `audio/${audioData.format}` : "audio/wav";
55
+ const audio = {
56
+ url: audioData.data.startsWith("data:") ? audioData.data : `data:${mimeType};base64,${audioData.data}`,
57
+ mimeType
58
+ };
59
+ state.audios.push(audio);
60
+ callbacks.onAudio?.(audio);
61
+ }
62
+ }
63
+ if (json.usage) {
64
+ debugSSE("OpenAI usage received:", JSON.stringify(json.usage));
65
+ debugSSE("OpenAI final chunk full data:", JSON.stringify(json));
66
+ state.usage = {
67
+ promptTokens: json.usage.prompt_tokens || 0,
68
+ completionTokens: json.usage.completion_tokens || 0,
69
+ totalTokens: json.usage.total_tokens || 0
70
+ };
71
+ callbacks.onUsage?.(state.usage);
72
+ }
73
+ if (finishReason === "stop" || finishReason === "end_turn" || finishReason === "length") {
74
+ debugSSE("OpenAI stream marked done due to finish_reason:", finishReason);
75
+ }
76
+ } catch {
77
+ }
78
+ }
79
+ function parseAnthropicEvent(data) {
80
+ try {
81
+ const json = JSON.parse(data);
82
+ callbacks.onRawEvent?.({ type: json.type, data: json, raw: data });
83
+ if (json.type === "content_block_start") {
84
+ const contentBlock = json.content_block;
85
+ const blockIndex = json.index ?? -1;
86
+ if (contentBlock?.type === "thinking") {
87
+ debugSSE("THINKING BLOCK STARTED!");
88
+ }
89
+ if (contentBlock?.type === "server_tool_use") {
90
+ state.currentBlockIndex = blockIndex;
91
+ state.currentBlockType = "server_tool_use";
92
+ state.inputJsonBuffer = "";
93
+ const toolUseBlock = {
94
+ id: contentBlock.id || `block_${Date.now()}`,
95
+ type: "tool_use",
96
+ toolId: contentBlock.id || "",
97
+ toolName: contentBlock.name || "web_search",
98
+ input: contentBlock.input || {},
99
+ status: "running"
100
+ };
101
+ state.blocks.push(toolUseBlock);
102
+ callbacks.onBlock?.(toolUseBlock);
103
+ }
104
+ if (contentBlock?.type === "web_search_tool_result") {
105
+ state.currentBlockIndex = blockIndex;
106
+ state.currentBlockType = "web_search_tool_result";
107
+ const searchResults = contentBlock.content;
108
+ let output = "";
109
+ if (Array.isArray(searchResults)) {
110
+ output = searchResults.filter((r) => r.type === "web_search_result").map(
111
+ (r) => `**${r.title || "Untitled"}**
112
+ ${r.url || ""}
113
+ ${r.encrypted_content ? "(encrypted)" : r.page_content || r.snippet || ""}`
114
+ ).join("\n\n");
115
+ }
116
+ const lastToolUse = [...state.blocks].reverse().find(
117
+ (b) => b.type === "tool_use"
118
+ );
119
+ const toolResultBlock = {
120
+ id: `result_${Date.now()}`,
121
+ type: "tool_result",
122
+ toolId: lastToolUse?.toolId || "",
123
+ toolName: lastToolUse?.toolName || "web_search",
124
+ output: output || "(no results)"
125
+ };
126
+ state.blocks.push(toolResultBlock);
127
+ callbacks.onBlock?.(toolResultBlock);
128
+ if (lastToolUse) {
129
+ lastToolUse.status = "completed";
130
+ callbacks.onBlock?.(lastToolUse);
131
+ }
132
+ }
133
+ }
134
+ if (json.type === "content_block_delta") {
135
+ const delta = json.delta;
136
+ if (delta?.type === "text_delta" && delta?.text) {
137
+ if (!state.firstTokenTime) {
138
+ state.firstTokenTime = Date.now();
139
+ }
140
+ state.content += delta.text;
141
+ callbacks.onDelta?.(delta.text);
142
+ }
143
+ if (delta?.type === "thinking_delta" && delta?.thinking) {
144
+ state.reasoning += delta.thinking;
145
+ callbacks.onReasoning?.(delta.thinking);
146
+ }
147
+ if (delta?.type === "input_json_delta" && delta?.partial_json) {
148
+ state.inputJsonBuffer += delta.partial_json;
149
+ }
150
+ }
151
+ if (json.type === "content_block_stop") {
152
+ if (state.currentBlockType === "server_tool_use" && state.inputJsonBuffer) {
153
+ const lastToolUse = [...state.blocks].reverse().find(
154
+ (b) => b.type === "tool_use"
155
+ );
156
+ if (lastToolUse) {
157
+ try {
158
+ lastToolUse.input = JSON.parse(state.inputJsonBuffer);
159
+ } catch {
160
+ lastToolUse.input = { raw: state.inputJsonBuffer };
161
+ }
162
+ callbacks.onBlock?.(lastToolUse);
163
+ }
164
+ }
165
+ state.currentBlockIndex = -1;
166
+ state.currentBlockType = "";
167
+ state.inputJsonBuffer = "";
168
+ }
169
+ if (json.type === "message_delta" && json.usage) {
170
+ state.usage = {
171
+ promptTokens: json.usage.input_tokens || 0,
172
+ completionTokens: json.usage.output_tokens || 0,
173
+ totalTokens: (json.usage.input_tokens || 0) + (json.usage.output_tokens || 0)
174
+ };
175
+ callbacks.onUsage?.(state.usage);
176
+ }
177
+ if (json.type === "message_stop") {
178
+ state.isDone = true;
179
+ callbacks.onDone?.();
180
+ }
181
+ if (json.type === "error") {
182
+ callbacks.onError?.(json.error?.message || "Unknown error");
183
+ }
184
+ } catch {
185
+ }
186
+ }
187
+ function parseGeminiEvent(data) {
188
+ try {
189
+ const json = JSON.parse(data);
190
+ callbacks.onRawEvent?.({ data: json, raw: data });
191
+ const candidates = json.candidates;
192
+ if (candidates && candidates.length > 0) {
193
+ const candidate = candidates[0];
194
+ const content = candidate.content;
195
+ if (content?.parts) {
196
+ for (const part of content.parts) {
197
+ if (part.thought === true && part.text) {
198
+ state.reasoning += part.text;
199
+ callbacks.onReasoning?.(part.text);
200
+ } else if (part.text) {
201
+ if (!state.firstTokenTime) {
202
+ state.firstTokenTime = Date.now();
203
+ }
204
+ state.content += part.text;
205
+ callbacks.onDelta?.(part.text);
206
+ }
207
+ }
208
+ }
209
+ const finishReason = candidate.finishReason;
210
+ if (finishReason === "STOP" || finishReason === "MAX_TOKENS" || finishReason === "SAFETY") {
211
+ debugSSE("Gemini finish reason:", finishReason);
212
+ }
213
+ }
214
+ const usage = json.usageMetadata;
215
+ if (usage) {
216
+ state.usage = {
217
+ promptTokens: usage.promptTokenCount || 0,
218
+ completionTokens: usage.candidatesTokenCount || 0,
219
+ totalTokens: usage.totalTokenCount || 0
220
+ };
221
+ callbacks.onUsage?.(state.usage);
222
+ debugSSE("Gemini usage:", state.usage);
223
+ }
224
+ if (json.error) {
225
+ callbacks.onError?.(json.error.message || "Gemini API error");
226
+ }
227
+ } catch {
228
+ }
229
+ }
230
+ function parseOpenAIResponseEvent(data) {
231
+ try {
232
+ const json = JSON.parse(data);
233
+ callbacks.onRawEvent?.({ type: json.type, data: json, raw: data });
234
+ switch (json.type) {
235
+ case "response.output_text.delta":
236
+ if (json.delta) {
237
+ if (!state.firstTokenTime) {
238
+ state.firstTokenTime = Date.now();
239
+ }
240
+ state.content += json.delta;
241
+ callbacks.onDelta?.(json.delta);
242
+ }
243
+ break;
244
+ case "response.reasoning_summary_text.delta":
245
+ if (json.delta) {
246
+ state.reasoning += json.delta;
247
+ callbacks.onReasoning?.(json.delta);
248
+ }
249
+ break;
250
+ case "response.completed": {
251
+ const response = json.response;
252
+ if (response?.usage) {
253
+ state.usage = {
254
+ promptTokens: response.usage.input_tokens || 0,
255
+ completionTokens: response.usage.output_tokens || 0,
256
+ totalTokens: (response.usage.input_tokens || 0) + (response.usage.output_tokens || 0)
257
+ };
258
+ callbacks.onUsage?.(state.usage);
259
+ }
260
+ state.isDone = true;
261
+ callbacks.onDone?.();
262
+ break;
263
+ }
264
+ case "error":
265
+ callbacks.onError?.(json.error?.message || json.message || "Unknown error");
266
+ break;
267
+ // Informational events — no-op
268
+ // response.created, response.in_progress, response.output_item.added,
269
+ // response.content_part.added, response.output_text.done,
270
+ // response.content_part.done, response.output_item.done, etc.
271
+ default:
272
+ break;
273
+ }
274
+ } catch {
275
+ }
276
+ }
277
+ function processEventBlock(eventBlock) {
278
+ const lines = eventBlock.split("\n");
279
+ const dataLines = [];
280
+ for (const line of lines) {
281
+ if (line.startsWith("data: ")) {
282
+ dataLines.push(line.slice(6));
283
+ } else if (line.trim() !== "" && !line.startsWith(":")) {
284
+ }
285
+ }
286
+ if (dataLines.length > 0) {
287
+ const data = dataLines.join("\n");
288
+ if (format === "openai") {
289
+ parseOpenAIEvent(data);
290
+ } else if (format === "gemini") {
291
+ parseGeminiEvent(data);
292
+ } else if (format === "openai-response") {
293
+ parseOpenAIResponseEvent(data);
294
+ } else {
295
+ parseAnthropicEvent(data);
296
+ }
297
+ }
298
+ }
299
+ return {
300
+ /**
301
+ * Push a chunk of data to the parser
302
+ * @param chunk - Raw SSE chunk from response stream
303
+ */
304
+ push(chunk) {
305
+ if (state.isDone) return;
306
+ if (!state.streamStartTime) {
307
+ state.streamStartTime = Date.now();
308
+ }
309
+ state.buffer += chunk;
310
+ const events = state.buffer.split("\n\n");
311
+ state.buffer = events.pop() || "";
312
+ for (const eventBlock of events) {
313
+ processEventBlock(eventBlock);
314
+ if (state.isDone) break;
315
+ }
316
+ },
317
+ /**
318
+ * Flush any remaining data in the buffer
319
+ */
320
+ flush() {
321
+ debugSSE("flush() called, buffer length:", state.buffer.length, "isDone:", state.isDone);
322
+ if (state.buffer.trim()) {
323
+ debugSSE("flush() processing remaining buffer:", state.buffer.substring(0, 200));
324
+ processEventBlock(state.buffer);
325
+ state.buffer = "";
326
+ }
327
+ state.streamEndTime = Date.now();
328
+ if (!state.isDone) {
329
+ debugSSE("flush() marking stream as done, final content length:", state.content.length);
330
+ state.isDone = true;
331
+ callbacks.onDone?.();
332
+ }
333
+ },
334
+ /**
335
+ * Get accumulated results
336
+ */
337
+ getResult() {
338
+ let metrics;
339
+ if (state.usage && state.firstTokenTime && state.streamEndTime) {
340
+ const timeCompletionMs = state.streamEndTime - state.firstTokenTime;
341
+ const timeFirstTokenMs = state.streamStartTime ? state.firstTokenTime - state.streamStartTime : void 0;
342
+ metrics = {
343
+ completionTokens: state.usage.completionTokens,
344
+ timeCompletionMs: timeCompletionMs > 0 ? timeCompletionMs : 1,
345
+ // Ensure at least 1ms
346
+ timeFirstTokenMs
347
+ };
348
+ }
349
+ if (state.reasoning) {
350
+ const thinkingBlock = {
351
+ id: `thinking_${Date.now()}`,
352
+ type: "thinking",
353
+ content: state.reasoning
354
+ };
355
+ state.blocks.unshift(thinkingBlock);
356
+ }
357
+ return {
358
+ content: state.content,
359
+ reasoning: state.reasoning,
360
+ usage: state.usage,
361
+ metrics,
362
+ blocks: state.blocks,
363
+ audios: state.audios,
364
+ videos: state.videos
365
+ };
366
+ },
367
+ /**
368
+ * Check if stream is complete
369
+ */
370
+ isDone() {
371
+ return state.isDone;
372
+ },
373
+ /**
374
+ * Reset parser state for reuse
375
+ */
376
+ reset() {
377
+ state.buffer = "";
378
+ state.content = "";
379
+ state.reasoning = "";
380
+ state.usage = void 0;
381
+ state.isDone = false;
382
+ state.streamStartTime = void 0;
383
+ state.firstTokenTime = void 0;
384
+ state.streamEndTime = void 0;
385
+ state.blocks = [];
386
+ state.currentBlockIndex = -1;
387
+ state.currentBlockType = "";
388
+ state.inputJsonBuffer = "";
389
+ state.audios = [];
390
+ state.videos = [];
391
+ }
392
+ };
393
+ }
394
+ async function streamSSEResponse(response, format, callbacks) {
395
+ debugSSE("streamSSEResponse started, format:", format);
396
+ const reader = response.body?.getReader();
397
+ if (!reader) {
398
+ callbacks.onError?.("No response body");
399
+ return { content: "", reasoning: "", blocks: [], audios: [], videos: [] };
400
+ }
401
+ const decoder = new TextDecoder();
402
+ const parser = createSSEParser(format, callbacks);
403
+ let chunkCount = 0;
404
+ try {
405
+ while (true) {
406
+ const { done, value } = await reader.read();
407
+ if (done) {
408
+ debugSSE("Reader done signal received after", chunkCount, "chunks");
409
+ break;
410
+ }
411
+ const chunk = decoder.decode(value, { stream: true });
412
+ chunkCount++;
413
+ parser.push(chunk);
414
+ if (parser.isDone()) {
415
+ debugSSE("Parser isDone after", chunkCount, "chunks");
416
+ break;
417
+ }
418
+ }
419
+ parser.flush();
420
+ const result = parser.getResult();
421
+ debugSSE("streamSSEResponse complete, content length:", result.content.length, "completionTokens:", result.usage?.completionTokens, "usage:", result.usage);
422
+ return result;
423
+ } finally {
424
+ reader.releaseLock();
425
+ }
426
+ }
427
+
428
+ export {
429
+ createSSEParser,
430
+ streamSSEResponse
431
+ };
@@ -0,0 +1,94 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/usage/usage-recorder.ts
2
+ var UsageRecorder = class {
3
+ constructor(store, pricing, logger, options = {}) {
4
+ this.store = store;
5
+ this.pricing = pricing;
6
+ this.logger = logger;
7
+ this.defer = _nullishCoalesce(options.defer, () => ( ((fn) => setTimeout(fn, 0))));
8
+ }
9
+
10
+
11
+
12
+
13
+ /**
14
+ * Record one LLM request. Returns immediately — the actual store insert is
15
+ * deferred so the caller's response path is unblocked.
16
+ *
17
+ * Errors during the insert are logged but never thrown.
18
+ */
19
+ record(input) {
20
+ this.defer(() => {
21
+ void this.recordAsync(input).catch((err) => {
22
+ this.logger.warn("[UsageRecorder] failed to persist usage event", {
23
+ error: err instanceof Error ? err.message : String(err)
24
+ });
25
+ });
26
+ });
27
+ }
28
+ /**
29
+ * Same as `record()` but awaitable — preferred in tests so they can assert
30
+ * after the row exists.
31
+ */
32
+ async recordAsync(input) {
33
+ const { costUsd, costSavedByCacheUsd } = await this.pricing.calculateCost(
34
+ input.providerId,
35
+ input.model,
36
+ input.usage
37
+ );
38
+ const row = {
39
+ messageId: _nullishCoalesce(input.messageId, () => ( null)),
40
+ parentMessageId: _nullishCoalesce(input.parentMessageId, () => ( null)),
41
+ sessionId: _nullishCoalesce(input.sessionId, () => ( null)),
42
+ providerId: input.providerId,
43
+ model: input.model,
44
+ apiKeyId: _nullishCoalesce(input.apiKeyId, () => ( null)),
45
+ engineOrigin: input.engineOrigin,
46
+ inputTokens: input.usage.inputTokens,
47
+ outputTokens: input.usage.outputTokens,
48
+ cacheReadTokens: input.usage.cacheReadTokens,
49
+ cacheCreationTokens: input.usage.cacheCreationTokens,
50
+ reasoningTokens: input.usage.reasoningTokens,
51
+ costUsd,
52
+ costSavedByCacheUsd,
53
+ rawUsage: input.rawUsage != null ? safeStringify(input.rawUsage) : null,
54
+ runId: _nullishCoalesce(input.runId, () => ( null)),
55
+ eventId: _nullishCoalesce(input.eventId, () => ( null))
56
+ };
57
+ try {
58
+ return await this.store.insert(row);
59
+ } catch (err) {
60
+ this.logger.warn("[UsageRecorder] store insert failed", {
61
+ error: err instanceof Error ? err.message : String(err)
62
+ });
63
+ return null;
64
+ }
65
+ }
66
+ // ===== Query delegates =====
67
+ getTotals(range) {
68
+ return this.store.getTotals(range);
69
+ }
70
+ getByModel(range) {
71
+ return this.store.getByModel(range);
72
+ }
73
+ getByApiKey(range) {
74
+ return this.store.getByApiKey(range);
75
+ }
76
+ getMessagesForSession(sessionId) {
77
+ return this.store.getMessagesForSession(sessionId);
78
+ }
79
+ /** Cumulative cache hit/miss stats for one session. */
80
+ getSessionCacheStats(sessionId) {
81
+ return this.store.getSessionCacheStats(sessionId);
82
+ }
83
+ };
84
+ var safeStringify = (value) => {
85
+ try {
86
+ return JSON.stringify(value);
87
+ } catch (e) {
88
+ return "";
89
+ }
90
+ };
91
+
92
+
93
+
94
+ exports.UsageRecorder = UsageRecorder;