@agentuity/runtime 2.0.11 → 3.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (415) hide show
  1. package/dist/index.d.ts +37 -65
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +59 -61
  4. package/dist/index.js.map +1 -1
  5. package/package.json +9 -38
  6. package/src/index.ts +58 -259
  7. package/AGENTS.md +0 -116
  8. package/dist/_config.d.ts +0 -100
  9. package/dist/_config.d.ts.map +0 -1
  10. package/dist/_config.js +0 -147
  11. package/dist/_config.js.map +0 -1
  12. package/dist/_context.d.ts +0 -80
  13. package/dist/_context.d.ts.map +0 -1
  14. package/dist/_context.js +0 -160
  15. package/dist/_context.js.map +0 -1
  16. package/dist/_events.d.ts +0 -64
  17. package/dist/_events.d.ts.map +0 -1
  18. package/dist/_events.js +0 -92
  19. package/dist/_events.js.map +0 -1
  20. package/dist/_globals.d.ts +0 -58
  21. package/dist/_globals.d.ts.map +0 -1
  22. package/dist/_globals.js +0 -71
  23. package/dist/_globals.js.map +0 -1
  24. package/dist/_idle.d.ts +0 -7
  25. package/dist/_idle.d.ts.map +0 -1
  26. package/dist/_idle.js +0 -10
  27. package/dist/_idle.js.map +0 -1
  28. package/dist/_metadata.d.ts +0 -117
  29. package/dist/_metadata.d.ts.map +0 -1
  30. package/dist/_metadata.js +0 -268
  31. package/dist/_metadata.js.map +0 -1
  32. package/dist/_process-protection.d.ts +0 -27
  33. package/dist/_process-protection.d.ts.map +0 -1
  34. package/dist/_process-protection.js +0 -56
  35. package/dist/_process-protection.js.map +0 -1
  36. package/dist/_server.d.ts +0 -50
  37. package/dist/_server.d.ts.map +0 -1
  38. package/dist/_server.js +0 -89
  39. package/dist/_server.js.map +0 -1
  40. package/dist/_services.d.ts +0 -25
  41. package/dist/_services.d.ts.map +0 -1
  42. package/dist/_services.js +0 -286
  43. package/dist/_services.js.map +0 -1
  44. package/dist/_standalone.d.ts +0 -212
  45. package/dist/_standalone.d.ts.map +0 -1
  46. package/dist/_standalone.js +0 -556
  47. package/dist/_standalone.js.map +0 -1
  48. package/dist/_tokens.d.ts +0 -12
  49. package/dist/_tokens.d.ts.map +0 -1
  50. package/dist/_tokens.js +0 -97
  51. package/dist/_tokens.js.map +0 -1
  52. package/dist/_util.d.ts +0 -16
  53. package/dist/_util.d.ts.map +0 -1
  54. package/dist/_util.js +0 -54
  55. package/dist/_util.js.map +0 -1
  56. package/dist/_validation.d.ts +0 -89
  57. package/dist/_validation.d.ts.map +0 -1
  58. package/dist/_validation.js +0 -29
  59. package/dist/_validation.js.map +0 -1
  60. package/dist/_waituntil.d.ts +0 -32
  61. package/dist/_waituntil.d.ts.map +0 -1
  62. package/dist/_waituntil.js +0 -156
  63. package/dist/_waituntil.js.map +0 -1
  64. package/dist/agent.d.ts +0 -1262
  65. package/dist/agent.d.ts.map +0 -1
  66. package/dist/agent.js +0 -981
  67. package/dist/agent.js.map +0 -1
  68. package/dist/app.d.ts +0 -514
  69. package/dist/app.d.ts.map +0 -1
  70. package/dist/app.js +0 -228
  71. package/dist/app.js.map +0 -1
  72. package/dist/bootstrap.d.ts +0 -44
  73. package/dist/bootstrap.d.ts.map +0 -1
  74. package/dist/bootstrap.js +0 -259
  75. package/dist/bootstrap.js.map +0 -1
  76. package/dist/bun-s3-patch.d.ts +0 -37
  77. package/dist/bun-s3-patch.d.ts.map +0 -1
  78. package/dist/bun-s3-patch.js +0 -142
  79. package/dist/bun-s3-patch.js.map +0 -1
  80. package/dist/cors.d.ts +0 -42
  81. package/dist/cors.d.ts.map +0 -1
  82. package/dist/cors.js +0 -117
  83. package/dist/cors.js.map +0 -1
  84. package/dist/dev-patches/aisdk.d.ts +0 -17
  85. package/dist/dev-patches/aisdk.d.ts.map +0 -1
  86. package/dist/dev-patches/aisdk.js +0 -160
  87. package/dist/dev-patches/aisdk.js.map +0 -1
  88. package/dist/dev-patches/gateway.d.ts +0 -16
  89. package/dist/dev-patches/gateway.d.ts.map +0 -1
  90. package/dist/dev-patches/gateway.js +0 -54
  91. package/dist/dev-patches/gateway.js.map +0 -1
  92. package/dist/dev-patches/index.d.ts +0 -21
  93. package/dist/dev-patches/index.d.ts.map +0 -1
  94. package/dist/dev-patches/index.js +0 -33
  95. package/dist/dev-patches/index.js.map +0 -1
  96. package/dist/dev-patches/otel-llm.d.ts +0 -12
  97. package/dist/dev-patches/otel-llm.d.ts.map +0 -1
  98. package/dist/dev-patches/otel-llm.js +0 -352
  99. package/dist/dev-patches/otel-llm.js.map +0 -1
  100. package/dist/devmode.d.ts +0 -3
  101. package/dist/devmode.d.ts.map +0 -1
  102. package/dist/devmode.js +0 -167
  103. package/dist/devmode.js.map +0 -1
  104. package/dist/eval.d.ts +0 -91
  105. package/dist/eval.d.ts.map +0 -1
  106. package/dist/eval.js +0 -16
  107. package/dist/eval.js.map +0 -1
  108. package/dist/handlers/_route-meta.d.ts +0 -22
  109. package/dist/handlers/_route-meta.d.ts.map +0 -1
  110. package/dist/handlers/_route-meta.js +0 -25
  111. package/dist/handlers/_route-meta.js.map +0 -1
  112. package/dist/handlers/cron.d.ts +0 -73
  113. package/dist/handlers/cron.d.ts.map +0 -1
  114. package/dist/handlers/cron.js +0 -43
  115. package/dist/handlers/cron.js.map +0 -1
  116. package/dist/handlers/index.d.ts +0 -6
  117. package/dist/handlers/index.d.ts.map +0 -1
  118. package/dist/handlers/index.js +0 -6
  119. package/dist/handlers/index.js.map +0 -1
  120. package/dist/handlers/sse.d.ts +0 -163
  121. package/dist/handlers/sse.d.ts.map +0 -1
  122. package/dist/handlers/sse.js +0 -175
  123. package/dist/handlers/sse.js.map +0 -1
  124. package/dist/handlers/stream.d.ts +0 -52
  125. package/dist/handlers/stream.d.ts.map +0 -1
  126. package/dist/handlers/stream.js +0 -108
  127. package/dist/handlers/stream.js.map +0 -1
  128. package/dist/handlers/webrtc.d.ts +0 -49
  129. package/dist/handlers/webrtc.d.ts.map +0 -1
  130. package/dist/handlers/webrtc.js +0 -109
  131. package/dist/handlers/webrtc.js.map +0 -1
  132. package/dist/handlers/websocket.d.ts +0 -88
  133. package/dist/handlers/websocket.d.ts.map +0 -1
  134. package/dist/handlers/websocket.js +0 -161
  135. package/dist/handlers/websocket.js.map +0 -1
  136. package/dist/logger/console.d.ts +0 -70
  137. package/dist/logger/console.d.ts.map +0 -1
  138. package/dist/logger/console.js +0 -278
  139. package/dist/logger/console.js.map +0 -1
  140. package/dist/logger/index.d.ts +0 -3
  141. package/dist/logger/index.d.ts.map +0 -1
  142. package/dist/logger/index.js +0 -3
  143. package/dist/logger/index.js.map +0 -1
  144. package/dist/logger/internal.d.ts +0 -79
  145. package/dist/logger/internal.d.ts.map +0 -1
  146. package/dist/logger/internal.js +0 -133
  147. package/dist/logger/internal.js.map +0 -1
  148. package/dist/logger/logger.d.ts +0 -41
  149. package/dist/logger/logger.d.ts.map +0 -1
  150. package/dist/logger/logger.js +0 -2
  151. package/dist/logger/logger.js.map +0 -1
  152. package/dist/logger/user.d.ts +0 -8
  153. package/dist/logger/user.d.ts.map +0 -1
  154. package/dist/logger/user.js +0 -7
  155. package/dist/logger/user.js.map +0 -1
  156. package/dist/logger/util.d.ts +0 -11
  157. package/dist/logger/util.d.ts.map +0 -1
  158. package/dist/logger/util.js +0 -77
  159. package/dist/logger/util.js.map +0 -1
  160. package/dist/middleware.d.ts +0 -105
  161. package/dist/middleware.d.ts.map +0 -1
  162. package/dist/middleware.js +0 -763
  163. package/dist/middleware.js.map +0 -1
  164. package/dist/otel/config.d.ts +0 -19
  165. package/dist/otel/config.d.ts.map +0 -1
  166. package/dist/otel/config.js +0 -26
  167. package/dist/otel/config.js.map +0 -1
  168. package/dist/otel/console.d.ts +0 -33
  169. package/dist/otel/console.d.ts.map +0 -1
  170. package/dist/otel/console.js +0 -86
  171. package/dist/otel/console.js.map +0 -1
  172. package/dist/otel/exporters/index.d.ts +0 -4
  173. package/dist/otel/exporters/index.d.ts.map +0 -1
  174. package/dist/otel/exporters/index.js +0 -4
  175. package/dist/otel/exporters/index.js.map +0 -1
  176. package/dist/otel/exporters/jsonl-log-exporter.d.ts +0 -36
  177. package/dist/otel/exporters/jsonl-log-exporter.d.ts.map +0 -1
  178. package/dist/otel/exporters/jsonl-log-exporter.js +0 -103
  179. package/dist/otel/exporters/jsonl-log-exporter.js.map +0 -1
  180. package/dist/otel/exporters/jsonl-metric-exporter.d.ts +0 -40
  181. package/dist/otel/exporters/jsonl-metric-exporter.d.ts.map +0 -1
  182. package/dist/otel/exporters/jsonl-metric-exporter.js +0 -104
  183. package/dist/otel/exporters/jsonl-metric-exporter.js.map +0 -1
  184. package/dist/otel/exporters/jsonl-trace-exporter.d.ts +0 -36
  185. package/dist/otel/exporters/jsonl-trace-exporter.d.ts.map +0 -1
  186. package/dist/otel/exporters/jsonl-trace-exporter.js +0 -111
  187. package/dist/otel/exporters/jsonl-trace-exporter.js.map +0 -1
  188. package/dist/otel/fetch.d.ts +0 -12
  189. package/dist/otel/fetch.d.ts.map +0 -1
  190. package/dist/otel/fetch.js +0 -82
  191. package/dist/otel/fetch.js.map +0 -1
  192. package/dist/otel/http.d.ts +0 -16
  193. package/dist/otel/http.d.ts.map +0 -1
  194. package/dist/otel/http.js +0 -44
  195. package/dist/otel/http.js.map +0 -1
  196. package/dist/otel/logger.d.ts +0 -37
  197. package/dist/otel/logger.d.ts.map +0 -1
  198. package/dist/otel/logger.js +0 -265
  199. package/dist/otel/logger.js.map +0 -1
  200. package/dist/otel/otel.d.ts +0 -68
  201. package/dist/otel/otel.d.ts.map +0 -1
  202. package/dist/otel/otel.js +0 -245
  203. package/dist/otel/otel.js.map +0 -1
  204. package/dist/otel/tracestate.d.ts +0 -44
  205. package/dist/otel/tracestate.d.ts.map +0 -1
  206. package/dist/otel/tracestate.js +0 -84
  207. package/dist/otel/tracestate.js.map +0 -1
  208. package/dist/router.d.ts +0 -66
  209. package/dist/router.d.ts.map +0 -1
  210. package/dist/router.js +0 -44
  211. package/dist/router.js.map +0 -1
  212. package/dist/services/evalrun/composite.d.ts +0 -21
  213. package/dist/services/evalrun/composite.d.ts.map +0 -1
  214. package/dist/services/evalrun/composite.js +0 -26
  215. package/dist/services/evalrun/composite.js.map +0 -1
  216. package/dist/services/evalrun/http.d.ts +0 -24
  217. package/dist/services/evalrun/http.d.ts.map +0 -1
  218. package/dist/services/evalrun/http.js +0 -115
  219. package/dist/services/evalrun/http.js.map +0 -1
  220. package/dist/services/evalrun/index.d.ts +0 -5
  221. package/dist/services/evalrun/index.d.ts.map +0 -1
  222. package/dist/services/evalrun/index.js +0 -5
  223. package/dist/services/evalrun/index.js.map +0 -1
  224. package/dist/services/evalrun/json.d.ts +0 -21
  225. package/dist/services/evalrun/json.d.ts.map +0 -1
  226. package/dist/services/evalrun/json.js +0 -38
  227. package/dist/services/evalrun/json.js.map +0 -1
  228. package/dist/services/evalrun/local.d.ts +0 -19
  229. package/dist/services/evalrun/local.d.ts.map +0 -1
  230. package/dist/services/evalrun/local.js +0 -22
  231. package/dist/services/evalrun/local.js.map +0 -1
  232. package/dist/services/local/_db.d.ts +0 -4
  233. package/dist/services/local/_db.d.ts.map +0 -1
  234. package/dist/services/local/_db.js +0 -281
  235. package/dist/services/local/_db.js.map +0 -1
  236. package/dist/services/local/_router.d.ts +0 -3
  237. package/dist/services/local/_router.d.ts.map +0 -1
  238. package/dist/services/local/_router.js +0 -28
  239. package/dist/services/local/_router.js.map +0 -1
  240. package/dist/services/local/_util.d.ts +0 -18
  241. package/dist/services/local/_util.d.ts.map +0 -1
  242. package/dist/services/local/_util.js +0 -44
  243. package/dist/services/local/_util.js.map +0 -1
  244. package/dist/services/local/email.d.ts +0 -24
  245. package/dist/services/local/email.d.ts.map +0 -1
  246. package/dist/services/local/email.js +0 -58
  247. package/dist/services/local/email.js.map +0 -1
  248. package/dist/services/local/index.d.ts +0 -10
  249. package/dist/services/local/index.d.ts.map +0 -1
  250. package/dist/services/local/index.js +0 -10
  251. package/dist/services/local/index.js.map +0 -1
  252. package/dist/services/local/keyvalue.d.ts +0 -17
  253. package/dist/services/local/keyvalue.d.ts.map +0 -1
  254. package/dist/services/local/keyvalue.js +0 -133
  255. package/dist/services/local/keyvalue.js.map +0 -1
  256. package/dist/services/local/queue.d.ts +0 -10
  257. package/dist/services/local/queue.d.ts.map +0 -1
  258. package/dist/services/local/queue.js +0 -96
  259. package/dist/services/local/queue.js.map +0 -1
  260. package/dist/services/local/stream.d.ts +0 -12
  261. package/dist/services/local/stream.d.ts.map +0 -1
  262. package/dist/services/local/stream.js +0 -266
  263. package/dist/services/local/stream.js.map +0 -1
  264. package/dist/services/local/task.d.ts +0 -55
  265. package/dist/services/local/task.d.ts.map +0 -1
  266. package/dist/services/local/task.js +0 -1248
  267. package/dist/services/local/task.js.map +0 -1
  268. package/dist/services/local/vector.d.ts +0 -17
  269. package/dist/services/local/vector.d.ts.map +0 -1
  270. package/dist/services/local/vector.js +0 -303
  271. package/dist/services/local/vector.js.map +0 -1
  272. package/dist/services/sandbox/http.d.ts +0 -23
  273. package/dist/services/sandbox/http.d.ts.map +0 -1
  274. package/dist/services/sandbox/http.js +0 -327
  275. package/dist/services/sandbox/http.js.map +0 -1
  276. package/dist/services/sandbox/index.d.ts +0 -2
  277. package/dist/services/sandbox/index.d.ts.map +0 -1
  278. package/dist/services/sandbox/index.js +0 -2
  279. package/dist/services/sandbox/index.js.map +0 -1
  280. package/dist/services/session/composite.d.ts +0 -21
  281. package/dist/services/session/composite.d.ts.map +0 -1
  282. package/dist/services/session/composite.js +0 -26
  283. package/dist/services/session/composite.js.map +0 -1
  284. package/dist/services/session/http.d.ts +0 -34
  285. package/dist/services/session/http.d.ts.map +0 -1
  286. package/dist/services/session/http.js +0 -124
  287. package/dist/services/session/http.js.map +0 -1
  288. package/dist/services/session/index.d.ts +0 -5
  289. package/dist/services/session/index.d.ts.map +0 -1
  290. package/dist/services/session/index.js +0 -5
  291. package/dist/services/session/index.js.map +0 -1
  292. package/dist/services/session/json.d.ts +0 -22
  293. package/dist/services/session/json.d.ts.map +0 -1
  294. package/dist/services/session/json.js +0 -35
  295. package/dist/services/session/json.js.map +0 -1
  296. package/dist/services/session/local.d.ts +0 -19
  297. package/dist/services/session/local.d.ts.map +0 -1
  298. package/dist/services/session/local.js +0 -23
  299. package/dist/services/session/local.js.map +0 -1
  300. package/dist/services/thread/local.d.ts +0 -20
  301. package/dist/services/thread/local.d.ts.map +0 -1
  302. package/dist/services/thread/local.js +0 -158
  303. package/dist/services/thread/local.js.map +0 -1
  304. package/dist/session.d.ts +0 -734
  305. package/dist/session.d.ts.map +0 -1
  306. package/dist/session.js +0 -1140
  307. package/dist/session.js.map +0 -1
  308. package/dist/signature.d.ts +0 -22
  309. package/dist/signature.d.ts.map +0 -1
  310. package/dist/signature.js +0 -63
  311. package/dist/signature.js.map +0 -1
  312. package/dist/validator.d.ts +0 -142
  313. package/dist/validator.d.ts.map +0 -1
  314. package/dist/validator.js +0 -149
  315. package/dist/validator.js.map +0 -1
  316. package/dist/version-check.d.ts +0 -20
  317. package/dist/version-check.d.ts.map +0 -1
  318. package/dist/version-check.js +0 -157
  319. package/dist/version-check.js.map +0 -1
  320. package/dist/web.d.ts +0 -8
  321. package/dist/web.d.ts.map +0 -1
  322. package/dist/web.js +0 -67
  323. package/dist/web.js.map +0 -1
  324. package/dist/webrtc-signaling.d.ts +0 -80
  325. package/dist/webrtc-signaling.d.ts.map +0 -1
  326. package/dist/webrtc-signaling.js +0 -237
  327. package/dist/webrtc-signaling.js.map +0 -1
  328. package/dist/workbench.d.ts +0 -17
  329. package/dist/workbench.d.ts.map +0 -1
  330. package/dist/workbench.js +0 -605
  331. package/dist/workbench.js.map +0 -1
  332. package/src/_config.ts +0 -163
  333. package/src/_context.ts +0 -240
  334. package/src/_events.ts +0 -142
  335. package/src/_globals.ts +0 -92
  336. package/src/_idle.ts +0 -10
  337. package/src/_metadata.ts +0 -407
  338. package/src/_process-protection.ts +0 -71
  339. package/src/_server.ts +0 -109
  340. package/src/_services.ts +0 -379
  341. package/src/_standalone.ts +0 -710
  342. package/src/_tokens.ts +0 -114
  343. package/src/_util.ts +0 -62
  344. package/src/_validation.ts +0 -119
  345. package/src/_waituntil.ts +0 -188
  346. package/src/agent.ts +0 -2739
  347. package/src/app.ts +0 -769
  348. package/src/bootstrap.ts +0 -321
  349. package/src/bun-s3-patch.ts +0 -224
  350. package/src/cors.ts +0 -137
  351. package/src/dev-patches/aisdk.ts +0 -169
  352. package/src/dev-patches/gateway.ts +0 -68
  353. package/src/dev-patches/index.ts +0 -37
  354. package/src/dev-patches/otel-llm.ts +0 -405
  355. package/src/devmode.ts +0 -171
  356. package/src/eval.ts +0 -109
  357. package/src/globals.d.ts +0 -28
  358. package/src/handlers/_route-meta.ts +0 -33
  359. package/src/handlers/cron.ts +0 -141
  360. package/src/handlers/index.ts +0 -18
  361. package/src/handlers/sse.ts +0 -358
  362. package/src/handlers/stream.ts +0 -121
  363. package/src/handlers/webrtc.ts +0 -125
  364. package/src/handlers/websocket.ts +0 -203
  365. package/src/logger/console.ts +0 -323
  366. package/src/logger/index.ts +0 -2
  367. package/src/logger/internal.ts +0 -165
  368. package/src/logger/logger.ts +0 -44
  369. package/src/logger/user.ts +0 -15
  370. package/src/logger/util.ts +0 -80
  371. package/src/middleware.ts +0 -1095
  372. package/src/otel/config.ts +0 -47
  373. package/src/otel/console.ts +0 -91
  374. package/src/otel/exporters/README.md +0 -217
  375. package/src/otel/exporters/index.ts +0 -3
  376. package/src/otel/exporters/jsonl-log-exporter.ts +0 -113
  377. package/src/otel/exporters/jsonl-metric-exporter.ts +0 -120
  378. package/src/otel/exporters/jsonl-trace-exporter.ts +0 -121
  379. package/src/otel/fetch.ts +0 -105
  380. package/src/otel/http.ts +0 -53
  381. package/src/otel/logger.ts +0 -293
  382. package/src/otel/otel.ts +0 -354
  383. package/src/otel/tracestate.ts +0 -108
  384. package/src/router.ts +0 -75
  385. package/src/services/evalrun/composite.ts +0 -34
  386. package/src/services/evalrun/http.ts +0 -167
  387. package/src/services/evalrun/index.ts +0 -4
  388. package/src/services/evalrun/json.ts +0 -46
  389. package/src/services/evalrun/local.ts +0 -28
  390. package/src/services/local/README.md +0 -1576
  391. package/src/services/local/_db.ts +0 -353
  392. package/src/services/local/_router.ts +0 -40
  393. package/src/services/local/_util.ts +0 -55
  394. package/src/services/local/email.ts +0 -91
  395. package/src/services/local/index.ts +0 -9
  396. package/src/services/local/keyvalue.ts +0 -174
  397. package/src/services/local/queue.ts +0 -145
  398. package/src/services/local/stream.ts +0 -358
  399. package/src/services/local/task.ts +0 -1711
  400. package/src/services/local/vector.ts +0 -438
  401. package/src/services/sandbox/http.ts +0 -522
  402. package/src/services/sandbox/index.ts +0 -1
  403. package/src/services/session/composite.ts +0 -33
  404. package/src/services/session/http.ts +0 -167
  405. package/src/services/session/index.ts +0 -4
  406. package/src/services/session/json.ts +0 -42
  407. package/src/services/session/local.ts +0 -33
  408. package/src/services/thread/local.ts +0 -199
  409. package/src/session.ts +0 -1960
  410. package/src/signature.ts +0 -82
  411. package/src/validator.ts +0 -283
  412. package/src/version-check.ts +0 -184
  413. package/src/web.ts +0 -76
  414. package/src/webrtc-signaling.ts +0 -288
  415. package/src/workbench.ts +0 -725
@@ -1,763 +0,0 @@
1
- /**
2
- * Middleware factories for Vite-native architecture
3
- * Extracted from _server.ts to be used by generated entry files
4
- */
5
- import { createMiddleware } from 'hono/factory';
6
- import { cors } from 'hono/cors';
7
- import { compress } from 'hono/compress';
8
- import { setSignedCookie } from 'hono/cookie';
9
- import { createTrustedCorsOrigin } from './cors';
10
- import { generateId } from './session';
11
- import { runInHTTPContext } from './_context';
12
- import { DURATION_HEADER, TOKENS_HEADER } from './_tokens';
13
- import { extractTraceContextFromRequest } from './otel/http';
14
- import { enrichContextWithTraceState } from './otel/tracestate';
15
- import { context, SpanKind, SpanStatusCode, trace, propagation } from '@opentelemetry/api';
16
- import * as runtimeConfig from './_config';
17
- import { getSessionEventProvider } from './_services';
18
- import { internal } from './logger/internal';
19
- import { STREAM_DONE_PROMISE_KEY, IS_STREAMING_RESPONSE_KEY } from './handlers/sse';
20
- import { WS_DONE_PROMISE_KEY } from './handlers/websocket';
21
- import { loadBuildMetadata } from './_metadata';
22
- const SESSION_HEADER = 'x-session-id';
23
- const THREAD_HEADER = 'x-thread-id';
24
- const DEPLOYMENT_HEADER = 'x-deployment';
25
- /**
26
- * Paths that should skip OTEL session event tracking.
27
- * These routes still get thread/session setup but won't create session start/complete events.
28
- */
29
- const OTEL_SESSION_EVENT_SKIP_PATHS = new Set([
30
- '/_agentuity/workbench/ws',
31
- '/_agentuity/workbench/sample',
32
- '/_agentuity/workbench/state',
33
- '/_agentuity/workbench/metadata.json',
34
- '/_agentuity/webanalytics/analytics.js',
35
- '/_agentuity/webanalytics/session.js',
36
- ]);
37
- /**
38
- * Paths that should skip thread/session setup entirely.
39
- * These are lightweight endpoints that don't need any context.
40
- */
41
- const OTEL_FULL_SKIP_PATHS = new Set([
42
- '/_agentuity/workbench/metadata.json',
43
- '/_agentuity/webanalytics/analytics.js',
44
- '/_agentuity/webanalytics/session.js',
45
- ]);
46
- export const AGENT_CONTEXT_PROPERTIES = [
47
- 'logger',
48
- 'tracer',
49
- 'sessionId',
50
- 'kv',
51
- 'stream',
52
- 'vector',
53
- 'sandbox',
54
- 'queue',
55
- 'email',
56
- 'schedule',
57
- 'task',
58
- 'state',
59
- 'thread',
60
- 'session',
61
- 'config',
62
- 'app',
63
- ];
64
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
- function installContextPropertyHelpers(c) {
66
- for (const property of AGENT_CONTEXT_PROPERTIES) {
67
- if (Object.hasOwn(c, property)) {
68
- continue;
69
- }
70
- Object.defineProperty(c, property, {
71
- get() {
72
- throw new Error(`In route handlers, use c.var.${property} instead of c.${property}. ` +
73
- `The property '${property}' is available on AgentContext (for agent handlers) ` +
74
- `but must be accessed via c.var in HonoContext (route handlers).`);
75
- },
76
- configurable: true,
77
- enumerable: false,
78
- });
79
- }
80
- }
81
- /**
82
- * Create base middleware that sets up context variables
83
- */
84
- export function createBaseMiddleware(config) {
85
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
- return createMiddleware(async (c, next) => {
87
- c.set('logger', config.logger);
88
- c.set('tracer', config.tracer);
89
- c.set('meter', config.meter);
90
- // Import services dynamically to avoid circular deps
91
- const { getServices } = await import('./_services');
92
- const services = getServices();
93
- c.set('kv', services.kv);
94
- c.set('stream', services.stream);
95
- c.set('vector', services.vector);
96
- c.set('sandbox', services.sandbox);
97
- c.set('queue', services.queue);
98
- c.set('email', services.email);
99
- c.set('schedule', services.schedule);
100
- c.set('task', services.task);
101
- installContextPropertyHelpers(c);
102
- const isWebSocket = c.req.header('upgrade')?.toLowerCase() === 'websocket';
103
- const skipLogging = c.req.path.startsWith('/_agentuity/');
104
- const started = performance.now();
105
- if (!skipLogging) {
106
- config.logger.debug('%s %s started', c.req.method, c.req.path);
107
- }
108
- await runInHTTPContext(c, next);
109
- if (!isWebSocket) {
110
- const endTime = performance.now();
111
- const duration = ((endTime - started) / 1000).toFixed(1);
112
- c.header(DURATION_HEADER, `${duration}s`);
113
- // Set deployment header for all routes
114
- const deploymentId = runtimeConfig.getDeploymentId();
115
- if (deploymentId) {
116
- c.header(DEPLOYMENT_HEADER, deploymentId);
117
- }
118
- }
119
- if (!skipLogging && !isWebSocket) {
120
- config.logger.debug('%s %s completed (%d) in %sms', c.req.method, c.req.path, c.res.status, Number(performance.now() - started).toFixed(2));
121
- }
122
- });
123
- }
124
- /**
125
- * Create CORS middleware with lazy config resolution.
126
- *
127
- * Handles Cross-Origin Resource Sharing (CORS) headers for API routes.
128
- * Config is resolved at request time, allowing it to be set via createApp().
129
- * Static options passed here take precedence over app config.
130
- *
131
- * Default behavior:
132
- * - Reflects the request origin (allows any origin)
133
- * - Allows common headers: Content-Type, Authorization, Accept, Origin, X-Requested-With
134
- * - Allows all standard HTTP methods
135
- * - Enables credentials
136
- * - Sets max-age to 600 seconds (10 minutes)
137
- *
138
- * @param staticOptions - Optional static CORS options that override app config
139
- *
140
- * @example
141
- * ```typescript
142
- * // Use with default settings
143
- * app.use('/api/*', createCorsMiddleware());
144
- *
145
- * // Or configure via createApp
146
- * const app = await createApp({
147
- * cors: {
148
- * origin: 'https://example.com',
149
- * allowHeaders: ['Content-Type', 'Authorization', 'X-Custom-Header'],
150
- * maxAge: 3600,
151
- * }
152
- * });
153
- *
154
- * // Or pass static options directly (overrides app config)
155
- * app.use('/api/*', createCorsMiddleware({
156
- * origin: ['https://app.example.com', 'https://admin.example.com'],
157
- * credentials: true,
158
- * }));
159
- * ```
160
- */
161
- export function createCorsMiddleware(staticOptions) {
162
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
- return createMiddleware(async (c, next) => {
164
- const corsOptions = { ...staticOptions };
165
- // Extract Agentuity-specific options
166
- const { sameOrigin, allowedOrigins, ...honoCorsOptions } = corsOptions;
167
- // Determine origin handler based on sameOrigin setting
168
- let originHandler;
169
- if (sameOrigin) {
170
- // Use trusted origins (env vars + allowedOrigins + same-origin)
171
- originHandler = createTrustedCorsOrigin({ allowedOrigins });
172
- }
173
- else if (honoCorsOptions.origin !== undefined) {
174
- // Use explicitly provided origin
175
- originHandler = honoCorsOptions.origin;
176
- }
177
- else {
178
- // Default: reflect any origin (backwards compatible)
179
- originHandler = (origin) => origin;
180
- }
181
- // Required headers that must always be allowed/exposed for runtime functionality
182
- const requiredAllowHeaders = [THREAD_HEADER];
183
- const requiredExposeHeaders = [
184
- TOKENS_HEADER,
185
- DURATION_HEADER,
186
- THREAD_HEADER,
187
- SESSION_HEADER,
188
- DEPLOYMENT_HEADER,
189
- ];
190
- // Default headers to allow (used if none specified)
191
- const defaultAllowHeaders = [
192
- 'Content-Type',
193
- 'Authorization',
194
- 'Accept',
195
- 'Origin',
196
- 'X-Requested-With',
197
- ];
198
- // Default headers to expose (used if none specified)
199
- const defaultExposeHeaders = ['Content-Length'];
200
- const finalAllowHeaders = [
201
- ...(honoCorsOptions.allowHeaders ?? defaultAllowHeaders),
202
- ...requiredAllowHeaders,
203
- ];
204
- const corsMiddleware = cors({
205
- ...honoCorsOptions,
206
- origin: originHandler,
207
- // Always include required headers, merge with user-provided or defaults
208
- allowHeaders: finalAllowHeaders,
209
- allowMethods: honoCorsOptions.allowMethods ?? [
210
- 'POST',
211
- 'GET',
212
- 'OPTIONS',
213
- 'HEAD',
214
- 'PUT',
215
- 'DELETE',
216
- 'PATCH',
217
- ],
218
- // Always include required headers, merge with user-provided or defaults
219
- exposeHeaders: [
220
- ...(honoCorsOptions.exposeHeaders ?? defaultExposeHeaders),
221
- ...requiredExposeHeaders,
222
- ],
223
- maxAge: honoCorsOptions.maxAge ?? 600,
224
- credentials: honoCorsOptions.credentials ?? originHandler !== '*',
225
- });
226
- return corsMiddleware(c, next);
227
- });
228
- }
229
- /**
230
- * Create OpenTelemetry middleware for session/thread tracking
231
- * This is the critical middleware that creates AgentContext
232
- */
233
- export function createOtelMiddleware() {
234
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
235
- return createMiddleware(async (c, next) => {
236
- // Skip thread/session setup entirely for lightweight endpoints
237
- if (OTEL_FULL_SKIP_PATHS.has(c.req.path)) {
238
- return next();
239
- }
240
- // Check if we should skip session events (but still set up thread/session)
241
- const skipSessionEvents = OTEL_SESSION_EVENT_SKIP_PATHS.has(c.req.path);
242
- // Import providers dynamically to avoid circular deps
243
- const { getThreadProvider, getSessionProvider } = await import('./_services');
244
- const WaitUntilHandler = (await import('./_waituntil')).default;
245
- const extractedContext = extractTraceContextFromRequest(c.req.raw);
246
- const method = c.req.method;
247
- const url = new URL(c.req.url);
248
- const threadProvider = getThreadProvider();
249
- const sessionProvider = getSessionProvider();
250
- await context.with(extractedContext, async () => {
251
- const tracer = trace.getTracer('http-server');
252
- // Build enriched traceState BEFORE span creation so the
253
- // recording span inherits it and it gets exported to OTLP.
254
- // Previously, traceState was set on a NonRecordingSpan *after*
255
- // the recording span was created, which meant it was propagated
256
- // to outbound requests but never appeared in the exported span
257
- // data (ClickHouse TraceState column was empty).
258
- const projectId = runtimeConfig.getProjectId();
259
- const orgId = runtimeConfig.getOrganizationId();
260
- const deploymentId = runtimeConfig.getDeploymentId();
261
- const isDevMode = runtimeConfig.isDevMode();
262
- internal.info('[session] config: orgId=%s, projectId=%s, deploymentId=%s, isDevMode=%s', orgId ?? 'NOT SET (AGENTUITY_CLOUD_ORG_ID)', projectId ?? 'NOT SET (AGENTUITY_CLOUD_PROJECT_ID)', deploymentId ?? 'none', isDevMode);
263
- const enrichedContext = enrichContextWithTraceState(context.active(), {
264
- pid: projectId,
265
- oid: orgId,
266
- did: deploymentId,
267
- d: isDevMode ? '1' : undefined,
268
- });
269
- await tracer.startActiveSpan(`${method} ${url.pathname}`, {
270
- kind: SpanKind.SERVER,
271
- attributes: {
272
- 'http.method': method,
273
- 'http.host': url.host,
274
- 'http.user_agent': c.req.header('user-agent') || '',
275
- 'http.path': url.pathname,
276
- },
277
- }, enrichedContext, async (span) => {
278
- // Track request duration from the SDK's perspective
279
- const requestStartTime = performance.now();
280
- const sctx = span.spanContext();
281
- const sessionId = sctx?.traceId ? `sess_${sctx.traceId}` : generateId('sess');
282
- const thread = await threadProvider.restore(c);
283
- const session = await sessionProvider.restore(thread, sessionId);
284
- const handler = new WaitUntilHandler(tracer);
285
- const isWsUpgrade = c.req.header('upgrade')?.toLowerCase() === 'websocket';
286
- c.set('sessionId', sessionId);
287
- c.set('thread', thread);
288
- c.set('session', session);
289
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
290
- c.set('waitUntilHandler', handler);
291
- const agentIds = new Set();
292
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
293
- c.set('agentIds', agentIds);
294
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
295
- c.set('trigger', isWsUpgrade ? 'websocket' : 'api');
296
- // Send session start event (so evalruns can reference this session)
297
- // The provider decides whether to send based on available data (orgId, projectId, etc.)
298
- // Skip for workbench routes that don't need session tracking
299
- const sessionEventProvider = getSessionEventProvider();
300
- if (sessionEventProvider && !skipSessionEvents) {
301
- try {
302
- // Look up routeId from build metadata by matching method and path
303
- // We need to do this here because the router wrapper hasn't run yet
304
- const metadata = loadBuildMetadata();
305
- const methodUpper = c.req.method.toUpperCase();
306
- // Normalize paths: trim trailing slashes for consistent matching
307
- const normalizePath = (p) => {
308
- const decoded = decodeURIComponent(p);
309
- return decoded.endsWith('/') && decoded.length > 1
310
- ? decoded.slice(0, -1)
311
- : decoded;
312
- };
313
- const requestPath = normalizePath(c.req.path);
314
- // Helper to check if requestPath ends with routePath at a segment boundary
315
- // e.g., "/api/translate" matches "/translate" but "/api/translate-v2" does not
316
- const matchesAtSegmentBoundary = (reqPath, routePath) => {
317
- if (reqPath === routePath)
318
- return true;
319
- if (!reqPath.endsWith(routePath))
320
- return false;
321
- // Check that the character before the match is a path separator
322
- const charBeforeMatch = reqPath[reqPath.length - routePath.length - 1];
323
- return charBeforeMatch === '/';
324
- };
325
- // Try matching by exact normalized path first
326
- let route = metadata?.routes?.find((r) => r.method.toUpperCase() === methodUpper &&
327
- normalizePath(r.path) === requestPath);
328
- // Fall back to segment-boundary matching (handles /api/translate matching /translate)
329
- if (!route) {
330
- route = metadata?.routes?.find((r) => r.method.toUpperCase() === methodUpper &&
331
- matchesAtSegmentBoundary(requestPath, normalizePath(r.path)));
332
- }
333
- const routeId = route?.id || '';
334
- await sessionEventProvider.start({
335
- id: sessionId,
336
- threadId: thread.id,
337
- orgId: orgId || '',
338
- projectId: projectId || '',
339
- deploymentId: deploymentId || undefined,
340
- devmode: isDevMode,
341
- trigger: isWsUpgrade ? 'websocket' : 'api',
342
- routeId,
343
- environment: runtimeConfig.getEnvironment(),
344
- url: c.req.path,
345
- method: c.req.method,
346
- });
347
- }
348
- catch (_ex) {
349
- // Silently ignore session start errors - don't block request
350
- }
351
- }
352
- // Factor out finalization logic so it can run synchronously or deferred
353
- const finalizeSession = async (statusCode, error) => {
354
- internal.info('[session] saving session %s (thread: %s) (error: %s)', sessionId, thread.id, error);
355
- await sessionProvider.save(session);
356
- internal.info('[session] session saved, now saving thread');
357
- await threadProvider.save(thread);
358
- internal.info('[session] thread saved');
359
- // Send session complete event (skip for workbench routes)
360
- if (sessionEventProvider && !skipSessionEvents) {
361
- try {
362
- const userData = session.serializeUserData();
363
- internal.info('[session] sending session complete event, userData: %s', userData ? `${userData.length} bytes` : 'none');
364
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
365
- const agentIdsSet = c.get('agentIds');
366
- const agentIds = agentIdsSet ? [...agentIdsSet].filter(Boolean) : undefined;
367
- internal.info('[session] agentIds: %o', agentIds);
368
- const isEmpty = await thread.empty();
369
- await sessionEventProvider.complete({
370
- id: sessionId,
371
- threadId: isEmpty ? null : thread.id,
372
- statusCode: statusCode ?? c.res?.status ?? 200,
373
- error,
374
- agentIds: agentIds?.length ? agentIds : undefined,
375
- userData,
376
- });
377
- internal.info('[session] session complete event sent');
378
- }
379
- catch (ex) {
380
- internal.info('[session] session complete event failed: %s', ex instanceof Error ? ex.message : ex);
381
- // Silently ignore session complete errors - don't block response
382
- }
383
- }
384
- };
385
- // Track state for finalization
386
- let responseStatus = 200;
387
- let errorMessage;
388
- let handlerDurationMs = 0;
389
- // Track whether span should be ended in finally block (false for streaming - ended in waitUntil)
390
- let shouldEndSpanInFinally = true;
391
- try {
392
- internal.info('[request] %s %s - handler starting (session: %s)', method, url.pathname, sessionId);
393
- await next();
394
- // Capture timing immediately after next() returns - this is when the handler completed
395
- // This is the HTTP response time we want to report (excludes waitUntil/finalization)
396
- handlerDurationMs = performance.now() - requestStartTime;
397
- internal.info('[request] %s %s - handler completed in %sms (session: %s)', method, url.pathname, handlerDurationMs.toFixed(2), sessionId);
398
- // Check if this is a streaming response that needs deferred finalization
399
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
400
- const streamDone = c.get(STREAM_DONE_PROMISE_KEY);
401
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
402
- const isStreaming = Boolean(c.get(IS_STREAMING_RESPONSE_KEY));
403
- // Check if this is a WebSocket response that needs deferred finalization
404
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
405
- const wsDone = c.get(WS_DONE_PROMISE_KEY);
406
- // Check if Hono caught an error (c.error is set by Hono's error handler)
407
- // or if the response status indicates an error
408
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
409
- const honoError = c.error;
410
- responseStatus = c.res?.status ?? 200;
411
- const isError = honoError || responseStatus >= 500;
412
- internal.info('[request] %s %s - status: %d, streaming: %s, websocket: %s, error: %s (session: %s)', method, url.pathname, responseStatus, isStreaming, Boolean(wsDone), isError, sessionId);
413
- if (isError) {
414
- // Capture error message for finalization
415
- errorMessage = honoError
416
- ? (honoError.stack ?? honoError.message)
417
- : `HTTP ${responseStatus}`;
418
- span.setStatus({
419
- code: SpanStatusCode.ERROR,
420
- message: honoError?.message ?? errorMessage,
421
- });
422
- if (honoError) {
423
- span.recordException(honoError);
424
- }
425
- }
426
- else {
427
- span.setStatus({ code: SpanStatusCode.OK });
428
- }
429
- // For streaming responses, defer everything until stream completes
430
- if (isStreaming && streamDone) {
431
- internal.info('[request] %s %s - streaming response, deferring finalization (session: %s)', method, url.pathname, sessionId);
432
- // For streaming, we end the span inside waitUntil after setting attributes
433
- shouldEndSpanInFinally = false;
434
- // Capture pending promises BEFORE adding finalization waitUntil to avoid deadlock
435
- const pendingPromises = handler.getPendingSnapshot();
436
- const hasPendingTasks = pendingPromises.length > 0;
437
- if (hasPendingTasks) {
438
- internal.info('[request] %s %s - %d pending waitUntil tasks to wait for after stream (session: %s)', method, url.pathname, pendingPromises.length, sessionId);
439
- }
440
- // Capture values needed for span attributes (responseStatus already captured above)
441
- const capturedResponseStatus = responseStatus;
442
- const capturedErrorMessage = errorMessage;
443
- // Use waitUntil to handle stream completion and finalization
444
- // This runs AFTER the response is sent to the client
445
- // Note: We intentionally do NOT use noSpan here - the waitUntil span helps
446
- // track the streaming finalization work in telemetry
447
- handler.waitUntil(async () => {
448
- // Track if stream ended with error so we can update finalization status
449
- let streamError = undefined;
450
- try {
451
- await streamDone;
452
- internal.info('[request] %s %s - stream completed (session: %s)', method, url.pathname, sessionId);
453
- }
454
- catch (ex) {
455
- streamError = ex;
456
- internal.info('[request] %s %s - stream ended with error: %s (session: %s)', method, url.pathname, ex, sessionId);
457
- }
458
- // Record duration now that stream is complete - set attributes BEFORE ending span
459
- const streamDurationMs = performance.now() - requestStartTime;
460
- const durationNs = Math.round(streamDurationMs * 1_000_000);
461
- internal.info('[request] %s %s - recording stream duration: %sms (session: %s)', method, url.pathname, streamDurationMs.toFixed(2), sessionId);
462
- // Determine final status - use stream error if present
463
- const finalStatus = streamError ? 500 : capturedResponseStatus;
464
- const finalErrorMessage = streamError
465
- ? streamError instanceof Error
466
- ? (streamError.stack ?? streamError.message)
467
- : String(streamError)
468
- : capturedErrorMessage;
469
- try {
470
- // Wait for pending tasks (evals, etc.) captured BEFORE this waitUntil was added
471
- if (hasPendingTasks) {
472
- internal.info('[request] %s %s - waiting for %d pending waitUntil tasks (session: %s)', method, url.pathname, pendingPromises.length, sessionId);
473
- const logger = c.get('logger');
474
- await handler.waitForPromises(pendingPromises, logger, sessionId);
475
- internal.info('[request] %s %s - all waitUntil tasks complete (session: %s)', method, url.pathname, sessionId);
476
- }
477
- // Finalize session after stream completes and evals finish
478
- await finalizeSession(finalStatus >= 500 ? finalStatus : undefined, finalErrorMessage);
479
- internal.info('[request] %s %s - stream session finalization complete (session: %s)', method, url.pathname, sessionId);
480
- }
481
- finally {
482
- // Set span attributes and end span AFTER all work is done
483
- span.setAttribute('@agentuity/request.duration', durationNs);
484
- span.setAttribute('http.status_code', finalStatus);
485
- // Set span status based on whether there was an error
486
- if (streamError) {
487
- span.setStatus({
488
- code: SpanStatusCode.ERROR,
489
- message: finalErrorMessage ?? 'Stream ended with error',
490
- });
491
- if (streamError instanceof Error) {
492
- span.recordException(streamError);
493
- }
494
- }
495
- else {
496
- span.setStatus({ code: SpanStatusCode.OK });
497
- }
498
- span.end();
499
- internal.info('[request] %s %s - stream span ended (session: %s)', method, url.pathname, sessionId);
500
- // Note: We don't call waitUntilAll() here because this waitUntil callback
501
- // IS the final cleanup task. Calling waitUntilAll() would deadlock since
502
- // it would wait for this very promise to complete.
503
- }
504
- });
505
- }
506
- else if (wsDone) {
507
- // WebSocket upgrade — end the span immediately (short-lived upgrade span)
508
- // Per OTel conventions, spans should be short-lived. The HTTP upgrade
509
- // request is a discrete event that completes in milliseconds. Keeping
510
- // a span open for the entire WS connection lifetime (minutes/hours) is
511
- // non-standard and causes issues with OTel backends.
512
- internal.info('[request] %s %s - websocket upgrade, ending span immediately (session: %s)', method, url.pathname, sessionId);
513
- // End the upgrade span now with the upgrade duration
514
- const upgradeDurationNs = Math.round(handlerDurationMs * 1_000_000);
515
- span.setAttribute('@agentuity/request.duration', upgradeDurationNs);
516
- span.setAttribute('http.status_code', responseStatus);
517
- span.setStatus({ code: SpanStatusCode.OK });
518
- span.end();
519
- shouldEndSpanInFinally = false; // already ended
520
- // Session finalization still defers until WS close, but without holding a span
521
- const pendingPromises = handler.getPendingSnapshot();
522
- const hasPendingTasks = pendingPromises.length > 0;
523
- if (hasPendingTasks) {
524
- internal.info('[request] %s %s - %d pending waitUntil tasks to wait for after websocket close (session: %s)', method, url.pathname, pendingPromises.length, sessionId);
525
- }
526
- handler.waitUntil(async () => {
527
- let wsError = undefined;
528
- try {
529
- await wsDone;
530
- internal.info('[request] %s %s - websocket closed (session: %s)', method, url.pathname, sessionId);
531
- }
532
- catch (ex) {
533
- wsError = ex;
534
- internal.info('[request] %s %s - websocket closed with error: %s (session: %s)', method, url.pathname, ex, sessionId);
535
- }
536
- const finalStatus = wsError ? 500 : responseStatus;
537
- const finalErrorMessage = wsError
538
- ? wsError instanceof Error
539
- ? (wsError.stack ?? wsError.message)
540
- : String(wsError)
541
- : errorMessage;
542
- // Wait for pending tasks captured BEFORE this waitUntil was added
543
- if (hasPendingTasks) {
544
- internal.info('[request] %s %s - waiting for %d pending waitUntil tasks (session: %s)', method, url.pathname, pendingPromises.length, sessionId);
545
- const logger = c.get('logger');
546
- await handler.waitForPromises(pendingPromises, logger, sessionId);
547
- internal.info('[request] %s %s - all waitUntil tasks complete (session: %s)', method, url.pathname, sessionId);
548
- }
549
- // Finalize session after WebSocket closes
550
- await finalizeSession(finalStatus >= 500 ? finalStatus : undefined, finalErrorMessage);
551
- internal.info('[request] %s %s - websocket session finalization complete (session: %s)', method, url.pathname, sessionId);
552
- });
553
- }
554
- else {
555
- // Non-streaming: record duration immediately
556
- const durationNs = Math.round(handlerDurationMs * 1_000_000);
557
- internal.info('[request] %s %s - recording duration: %sms (%dns) (session: %s)', method, url.pathname, handlerDurationMs.toFixed(2), durationNs, sessionId);
558
- span.setAttribute('@agentuity/request.duration', durationNs);
559
- span.setAttribute('http.status_code', responseStatus);
560
- // Capture pending promises BEFORE adding finalization waitUntil to avoid deadlock.
561
- // If we called waitUntilAll inside waitUntil, it would wait for itself.
562
- const pendingPromises = handler.getPendingSnapshot();
563
- const hasPendingTasks = pendingPromises.length > 0;
564
- if (hasPendingTasks) {
565
- internal.info('[request] %s %s - %d pending waitUntil tasks to wait for (session: %s)', method, url.pathname, pendingPromises.length, sessionId);
566
- }
567
- // Capture values for use in waitUntil callback
568
- const capturedResponseStatus = responseStatus;
569
- const capturedErrorMessage = errorMessage;
570
- // Defer session finalization to run AFTER response is sent
571
- // Use noSpan: true since finalizeSession creates its own Session End span
572
- handler.waitUntil(async () => {
573
- // Wait for the snapshot of pending tasks (evals, etc.) captured BEFORE this waitUntil was added
574
- if (hasPendingTasks) {
575
- internal.info('[request] %s %s - waiting for %d pending waitUntil tasks (session: %s)', method, url.pathname, pendingPromises.length, sessionId);
576
- const logger = c.get('logger');
577
- await handler.waitForPromises(pendingPromises, logger, sessionId);
578
- internal.info('[request] %s %s - all waitUntil tasks complete (session: %s)', method, url.pathname, sessionId);
579
- }
580
- // Finalize session - this is the actual work
581
- internal.info('[request] %s %s - starting session finalization (session: %s)', method, url.pathname, sessionId);
582
- try {
583
- await finalizeSession(capturedResponseStatus >= 500 ? capturedResponseStatus : undefined, capturedErrorMessage);
584
- internal.info('[request] %s %s - session finalization complete (session: %s)', method, url.pathname, sessionId);
585
- }
586
- catch (ex) {
587
- internal.error('[request] %s %s - session finalization failed: %s (session: %s)', method, url.pathname, ex, sessionId);
588
- }
589
- // Note: We don't call waitUntilAll() here because this waitUntil callback
590
- // IS the final cleanup task. Calling waitUntilAll() would deadlock since
591
- // it would wait for this very promise to complete.
592
- }, { noSpan: true });
593
- }
594
- }
595
- catch (ex) {
596
- // Record request metrics even on exceptions (500 status)
597
- const exceptionDurationMs = performance.now() - requestStartTime;
598
- const durationNs = Math.round(exceptionDurationMs * 1_000_000);
599
- internal.info('[request] %s %s - recording exception duration: %sms (session: %s)', method, url.pathname, exceptionDurationMs.toFixed(2), sessionId);
600
- span.setAttribute('@agentuity/request.duration', durationNs);
601
- span.setAttribute('http.status_code', 500);
602
- if (ex instanceof Error) {
603
- span.recordException(ex);
604
- }
605
- errorMessage = ex instanceof Error ? (ex.stack ?? ex.message) : String(ex);
606
- responseStatus = 500;
607
- span.setStatus({
608
- code: SpanStatusCode.ERROR,
609
- message: ex instanceof Error ? ex.message : String(ex),
610
- });
611
- // Capture error message for use in waitUntil callback
612
- const capturedErrorMessage = errorMessage;
613
- // Capture pending promises BEFORE adding finalization waitUntil to avoid deadlock
614
- const pendingPromises = handler.getPendingSnapshot();
615
- const hasPendingTasks = pendingPromises.length > 0;
616
- if (hasPendingTasks) {
617
- internal.info('[request] %s %s - %d pending waitUntil tasks to wait for after error (session: %s)', method, url.pathname, pendingPromises.length, sessionId);
618
- }
619
- // Still defer finalization even on error
620
- // Use noSpan: true since finalizeSession creates its own Session End span
621
- handler.waitUntil(async () => {
622
- // Wait for pending tasks (evals, etc.) captured BEFORE this waitUntil was added
623
- if (hasPendingTasks) {
624
- internal.info('[request] %s %s - waiting for %d pending waitUntil tasks (session: %s)', method, url.pathname, pendingPromises.length, sessionId);
625
- const logger = c.get('logger');
626
- await handler.waitForPromises(pendingPromises, logger, sessionId);
627
- internal.info('[request] %s %s - all waitUntil tasks complete (session: %s)', method, url.pathname, sessionId);
628
- }
629
- try {
630
- await finalizeSession(500, capturedErrorMessage);
631
- }
632
- catch (finalizeEx) {
633
- internal.error('[request] %s %s - error session finalization failed: %s (session: %s)', method, url.pathname, finalizeEx, sessionId);
634
- }
635
- // Note: We don't call waitUntilAll() here because this waitUntil callback
636
- // IS the final cleanup task. Calling waitUntilAll() would deadlock since
637
- // it would wait for this very promise to complete.
638
- }, { noSpan: true });
639
- throw ex;
640
- }
641
- finally {
642
- // Set response headers - this is the only thing that should block the response
643
- const headers = {};
644
- propagation.inject(context.active(), headers);
645
- for (const key of Object.keys(headers)) {
646
- c.header(key, headers[key]);
647
- }
648
- const traceId = sctx?.traceId || sessionId.replace(/^sess_/, '');
649
- c.header(SESSION_HEADER, `sess_${traceId}`);
650
- internal.info('[request] %s %s - response ready, duration: %sms (session: %s)', method, url.pathname, handlerDurationMs.toFixed(2), sessionId);
651
- // Only end span here for non-streaming responses
652
- // For streaming, span is ended in the waitUntil callback after setting duration attributes
653
- if (shouldEndSpanInFinally) {
654
- span.end();
655
- }
656
- }
657
- });
658
- });
659
- });
660
- }
661
- /**
662
- * Create compression middleware with lazy config resolution.
663
- *
664
- * Compresses response bodies using gzip or deflate based on the Accept-Encoding header.
665
- * Config is resolved at request time, allowing it to be set via createApp().
666
- *
667
- * @param staticConfig - Optional static config that overrides app config
668
- *
669
- * @example
670
- * ```typescript
671
- * // Use with default settings
672
- * app.use('*', createCompressionMiddleware());
673
- *
674
- * // Or configure via createApp
675
- * const app = await createApp({
676
- * compression: {
677
- * threshold: 2048,
678
- * }
679
- * });
680
- * ```
681
- */
682
- export function createCompressionMiddleware(staticConfig) {
683
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
684
- return createMiddleware(async (c, next) => {
685
- // Check if compression is explicitly disabled
686
- if (staticConfig === false || staticConfig?.enabled === false) {
687
- return next();
688
- }
689
- const config = { ...staticConfig };
690
- const { enabled = true, threshold = 1024, filter, honoOptions } = config;
691
- // Skip if explicitly disabled
692
- if (!enabled) {
693
- return next();
694
- }
695
- // Skip WebSocket upgrade requests
696
- const upgrade = c.req.header('upgrade');
697
- if (upgrade && upgrade.toLowerCase() === 'websocket') {
698
- return next();
699
- }
700
- // Skip if no Accept-Encoding header
701
- const acceptEncoding = c.req.header('accept-encoding');
702
- if (!acceptEncoding) {
703
- return next();
704
- }
705
- // Check custom filter
706
- if (filter && !filter(c)) {
707
- return next();
708
- }
709
- // Create and run the Hono compress middleware
710
- const compressMiddleware = compress({
711
- threshold,
712
- ...honoOptions,
713
- });
714
- await compressMiddleware(c, next);
715
- });
716
- }
717
- /**
718
- * Create lightweight thread middleware for web routes (analytics).
719
- *
720
- * Sets thread cookie that persists across page views for client-side analytics.
721
- * This middleware does NOT:
722
- * - Create or track sessions (no session ID)
723
- * - Set session/thread response headers
724
- * - Send events to Catalyst sessions table
725
- *
726
- * This is intentionally separate from createOtelMiddleware to avoid
727
- * polluting the sessions table with web browsing activity.
728
- *
729
- * - Thread cookie (atid_a): Analytics-readable copy, 1-week expiry
730
- */
731
- export function createWebSessionMiddleware() {
732
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
733
- return createMiddleware(async (c, next) => {
734
- // Import providers dynamically to avoid circular deps
735
- const { getThreadProvider } = await import('./_services');
736
- const secret = getSessionSecret();
737
- // Use ThreadProvider.restore() to get/create thread (handles header, cookie, generation)
738
- const threadProvider = getThreadProvider();
739
- const thread = await threadProvider.restore(c);
740
- // Set thread cookie for analytics
741
- // httpOnly: false so beacon script can read it
742
- const isSecure = c.req.url.startsWith('https://');
743
- await setSignedCookie(c, 'atid_a', thread.id, secret, {
744
- httpOnly: false, // Readable by JavaScript for analytics
745
- secure: isSecure,
746
- sameSite: 'Lax',
747
- path: '/',
748
- maxAge: 604800, // 1 week
749
- });
750
- // Store in context for handler to access in same request
751
- // (cookies aren't readable until the next request)
752
- c.set('_webThreadId', thread.id);
753
- await next();
754
- });
755
- }
756
- /**
757
- * Get the secret used for signing session/thread cookies.
758
- * Uses AGENTUITY_SDK_KEY if available, falls back to 'agentuity'.
759
- */
760
- export function getSessionSecret() {
761
- return process.env.AGENTUITY_SDK_KEY || 'agentuity';
762
- }
763
- //# sourceMappingURL=middleware.js.map