@aion0/bastion 0.1.7

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 (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +183 -0
  3. package/README.zh.md +468 -0
  4. package/config/default.yaml +73 -0
  5. package/dist/cli/commands/config.d.ts +3 -0
  6. package/dist/cli/commands/config.d.ts.map +1 -0
  7. package/dist/cli/commands/config.js +31 -0
  8. package/dist/cli/commands/config.js.map +1 -0
  9. package/dist/cli/commands/env.d.ts +3 -0
  10. package/dist/cli/commands/env.d.ts.map +1 -0
  11. package/dist/cli/commands/env.js +83 -0
  12. package/dist/cli/commands/env.js.map +1 -0
  13. package/dist/cli/commands/health.d.ts +3 -0
  14. package/dist/cli/commands/health.d.ts.map +1 -0
  15. package/dist/cli/commands/health.js +45 -0
  16. package/dist/cli/commands/health.js.map +1 -0
  17. package/dist/cli/commands/openclaw.d.ts +3 -0
  18. package/dist/cli/commands/openclaw.d.ts.map +1 -0
  19. package/dist/cli/commands/openclaw.js +1062 -0
  20. package/dist/cli/commands/openclaw.js.map +1 -0
  21. package/dist/cli/commands/proxy.d.ts +8 -0
  22. package/dist/cli/commands/proxy.d.ts.map +1 -0
  23. package/dist/cli/commands/proxy.js +433 -0
  24. package/dist/cli/commands/proxy.js.map +1 -0
  25. package/dist/cli/commands/start.d.ts +3 -0
  26. package/dist/cli/commands/start.d.ts.map +1 -0
  27. package/dist/cli/commands/start.js +62 -0
  28. package/dist/cli/commands/start.js.map +1 -0
  29. package/dist/cli/commands/stats.d.ts +3 -0
  30. package/dist/cli/commands/stats.d.ts.map +1 -0
  31. package/dist/cli/commands/stats.js +32 -0
  32. package/dist/cli/commands/stats.js.map +1 -0
  33. package/dist/cli/commands/stop.d.ts +3 -0
  34. package/dist/cli/commands/stop.d.ts.map +1 -0
  35. package/dist/cli/commands/stop.js +28 -0
  36. package/dist/cli/commands/stop.js.map +1 -0
  37. package/dist/cli/commands/token.d.ts +3 -0
  38. package/dist/cli/commands/token.d.ts.map +1 -0
  39. package/dist/cli/commands/token.js +32 -0
  40. package/dist/cli/commands/token.js.map +1 -0
  41. package/dist/cli/commands/trust-ca.d.ts +3 -0
  42. package/dist/cli/commands/trust-ca.d.ts.map +1 -0
  43. package/dist/cli/commands/trust-ca.js +44 -0
  44. package/dist/cli/commands/trust-ca.js.map +1 -0
  45. package/dist/cli/commands/wrap.d.ts +3 -0
  46. package/dist/cli/commands/wrap.d.ts.map +1 -0
  47. package/dist/cli/commands/wrap.js +70 -0
  48. package/dist/cli/commands/wrap.js.map +1 -0
  49. package/dist/cli/daemon.d.ts +11 -0
  50. package/dist/cli/daemon.d.ts.map +1 -0
  51. package/dist/cli/daemon.js +82 -0
  52. package/dist/cli/daemon.js.map +1 -0
  53. package/dist/cli/index.d.ts +3 -0
  54. package/dist/cli/index.d.ts.map +1 -0
  55. package/dist/cli/index.js +35 -0
  56. package/dist/cli/index.js.map +1 -0
  57. package/dist/config/index.d.ts +3 -0
  58. package/dist/config/index.d.ts.map +1 -0
  59. package/dist/config/index.js +60 -0
  60. package/dist/config/index.js.map +1 -0
  61. package/dist/config/manager.d.ts +12 -0
  62. package/dist/config/manager.d.ts.map +1 -0
  63. package/dist/config/manager.js +73 -0
  64. package/dist/config/manager.js.map +1 -0
  65. package/dist/config/paths.d.ts +10 -0
  66. package/dist/config/paths.d.ts.map +1 -0
  67. package/dist/config/paths.js +16 -0
  68. package/dist/config/paths.js.map +1 -0
  69. package/dist/config/schema.d.ts +85 -0
  70. package/dist/config/schema.d.ts.map +1 -0
  71. package/dist/config/schema.js +3 -0
  72. package/dist/config/schema.js.map +1 -0
  73. package/dist/dashboard/api-routes.d.ts +6 -0
  74. package/dist/dashboard/api-routes.d.ts.map +1 -0
  75. package/dist/dashboard/api-routes.js +671 -0
  76. package/dist/dashboard/api-routes.js.map +1 -0
  77. package/dist/dashboard/api.d.ts +4 -0
  78. package/dist/dashboard/api.d.ts.map +1 -0
  79. package/dist/dashboard/api.js +25 -0
  80. package/dist/dashboard/api.js.map +1 -0
  81. package/dist/dashboard/page.d.ts +3 -0
  82. package/dist/dashboard/page.d.ts.map +1 -0
  83. package/dist/dashboard/page.js +1622 -0
  84. package/dist/dashboard/page.js.map +1 -0
  85. package/dist/dlp/actions.d.ts +13 -0
  86. package/dist/dlp/actions.d.ts.map +1 -0
  87. package/dist/dlp/actions.js +3 -0
  88. package/dist/dlp/actions.js.map +1 -0
  89. package/dist/dlp/ai-validator.d.ts +28 -0
  90. package/dist/dlp/ai-validator.d.ts.map +1 -0
  91. package/dist/dlp/ai-validator.js +214 -0
  92. package/dist/dlp/ai-validator.js.map +1 -0
  93. package/dist/dlp/engine.d.ts +34 -0
  94. package/dist/dlp/engine.d.ts.map +1 -0
  95. package/dist/dlp/engine.js +342 -0
  96. package/dist/dlp/engine.js.map +1 -0
  97. package/dist/dlp/entropy.d.ts +22 -0
  98. package/dist/dlp/entropy.d.ts.map +1 -0
  99. package/dist/dlp/entropy.js +43 -0
  100. package/dist/dlp/entropy.js.map +1 -0
  101. package/dist/dlp/message-cache.d.ts +45 -0
  102. package/dist/dlp/message-cache.d.ts.map +1 -0
  103. package/dist/dlp/message-cache.js +251 -0
  104. package/dist/dlp/message-cache.js.map +1 -0
  105. package/dist/dlp/patterns/context-aware.d.ts +4 -0
  106. package/dist/dlp/patterns/context-aware.d.ts.map +1 -0
  107. package/dist/dlp/patterns/context-aware.js +45 -0
  108. package/dist/dlp/patterns/context-aware.js.map +1 -0
  109. package/dist/dlp/patterns/high-confidence.d.ts +4 -0
  110. package/dist/dlp/patterns/high-confidence.d.ts.map +1 -0
  111. package/dist/dlp/patterns/high-confidence.js +140 -0
  112. package/dist/dlp/patterns/high-confidence.js.map +1 -0
  113. package/dist/dlp/patterns/prompt-injection.d.ts +4 -0
  114. package/dist/dlp/patterns/prompt-injection.d.ts.map +1 -0
  115. package/dist/dlp/patterns/prompt-injection.js +244 -0
  116. package/dist/dlp/patterns/prompt-injection.js.map +1 -0
  117. package/dist/dlp/patterns/validated.d.ts +4 -0
  118. package/dist/dlp/patterns/validated.d.ts.map +1 -0
  119. package/dist/dlp/patterns/validated.js +21 -0
  120. package/dist/dlp/patterns/validated.js.map +1 -0
  121. package/dist/dlp/remote-sync.d.ts +47 -0
  122. package/dist/dlp/remote-sync.d.ts.map +1 -0
  123. package/dist/dlp/remote-sync.js +252 -0
  124. package/dist/dlp/remote-sync.js.map +1 -0
  125. package/dist/dlp/semantics.d.ts +27 -0
  126. package/dist/dlp/semantics.d.ts.map +1 -0
  127. package/dist/dlp/semantics.js +93 -0
  128. package/dist/dlp/semantics.js.map +1 -0
  129. package/dist/dlp/structure.d.ts +25 -0
  130. package/dist/dlp/structure.d.ts.map +1 -0
  131. package/dist/dlp/structure.js +86 -0
  132. package/dist/dlp/structure.js.map +1 -0
  133. package/dist/dlp/validators.d.ts +6 -0
  134. package/dist/dlp/validators.d.ts.map +1 -0
  135. package/dist/dlp/validators.js +46 -0
  136. package/dist/dlp/validators.js.map +1 -0
  137. package/dist/index.d.ts +2 -0
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/index.js +200 -0
  140. package/dist/index.js.map +1 -0
  141. package/dist/license/verify.d.ts +18 -0
  142. package/dist/license/verify.d.ts.map +1 -0
  143. package/dist/license/verify.js +71 -0
  144. package/dist/license/verify.js.map +1 -0
  145. package/dist/metrics/collector.d.ts +11 -0
  146. package/dist/metrics/collector.d.ts.map +1 -0
  147. package/dist/metrics/collector.js +17 -0
  148. package/dist/metrics/collector.js.map +1 -0
  149. package/dist/metrics/dashboard.d.ts +6 -0
  150. package/dist/metrics/dashboard.d.ts.map +1 -0
  151. package/dist/metrics/dashboard.js +66 -0
  152. package/dist/metrics/dashboard.js.map +1 -0
  153. package/dist/metrics/pricing.d.ts +10 -0
  154. package/dist/metrics/pricing.d.ts.map +1 -0
  155. package/dist/metrics/pricing.js +62 -0
  156. package/dist/metrics/pricing.js.map +1 -0
  157. package/dist/optimizer/cache.d.ts +14 -0
  158. package/dist/optimizer/cache.d.ts.map +1 -0
  159. package/dist/optimizer/cache.js +58 -0
  160. package/dist/optimizer/cache.js.map +1 -0
  161. package/dist/optimizer/estimator.d.ts +6 -0
  162. package/dist/optimizer/estimator.d.ts.map +1 -0
  163. package/dist/optimizer/estimator.js +12 -0
  164. package/dist/optimizer/estimator.js.map +1 -0
  165. package/dist/optimizer/reorder.d.ts +9 -0
  166. package/dist/optimizer/reorder.d.ts.map +1 -0
  167. package/dist/optimizer/reorder.js +27 -0
  168. package/dist/optimizer/reorder.js.map +1 -0
  169. package/dist/optimizer/trimmer.d.ts +9 -0
  170. package/dist/optimizer/trimmer.d.ts.map +1 -0
  171. package/dist/optimizer/trimmer.js +47 -0
  172. package/dist/optimizer/trimmer.js.map +1 -0
  173. package/dist/plugin-api/index.d.ts +3 -0
  174. package/dist/plugin-api/index.d.ts.map +1 -0
  175. package/dist/plugin-api/index.js +6 -0
  176. package/dist/plugin-api/index.js.map +1 -0
  177. package/dist/plugin-api/types.d.ts +77 -0
  178. package/dist/plugin-api/types.d.ts.map +1 -0
  179. package/dist/plugin-api/types.js +6 -0
  180. package/dist/plugin-api/types.js.map +1 -0
  181. package/dist/plugins/adapter.d.ts +12 -0
  182. package/dist/plugins/adapter.d.ts.map +1 -0
  183. package/dist/plugins/adapter.js +116 -0
  184. package/dist/plugins/adapter.js.map +1 -0
  185. package/dist/plugins/builtin/audit-logger.d.ts +9 -0
  186. package/dist/plugins/builtin/audit-logger.d.ts.map +1 -0
  187. package/dist/plugins/builtin/audit-logger.js +53 -0
  188. package/dist/plugins/builtin/audit-logger.js.map +1 -0
  189. package/dist/plugins/builtin/dlp-scanner.d.ts +19 -0
  190. package/dist/plugins/builtin/dlp-scanner.d.ts.map +1 -0
  191. package/dist/plugins/builtin/dlp-scanner.js +284 -0
  192. package/dist/plugins/builtin/dlp-scanner.js.map +1 -0
  193. package/dist/plugins/builtin/metrics-collector.d.ts +4 -0
  194. package/dist/plugins/builtin/metrics-collector.d.ts.map +1 -0
  195. package/dist/plugins/builtin/metrics-collector.js +111 -0
  196. package/dist/plugins/builtin/metrics-collector.js.map +1 -0
  197. package/dist/plugins/builtin/token-optimizer.d.ts +10 -0
  198. package/dist/plugins/builtin/token-optimizer.d.ts.map +1 -0
  199. package/dist/plugins/builtin/token-optimizer.js +120 -0
  200. package/dist/plugins/builtin/token-optimizer.js.map +1 -0
  201. package/dist/plugins/builtin/tool-guard.d.ts +20 -0
  202. package/dist/plugins/builtin/tool-guard.d.ts.map +1 -0
  203. package/dist/plugins/builtin/tool-guard.js +259 -0
  204. package/dist/plugins/builtin/tool-guard.js.map +1 -0
  205. package/dist/plugins/context.d.ts +8 -0
  206. package/dist/plugins/context.d.ts.map +1 -0
  207. package/dist/plugins/context.js +33 -0
  208. package/dist/plugins/context.js.map +1 -0
  209. package/dist/plugins/event-bus.d.ts +9 -0
  210. package/dist/plugins/event-bus.d.ts.map +1 -0
  211. package/dist/plugins/event-bus.js +25 -0
  212. package/dist/plugins/event-bus.js.map +1 -0
  213. package/dist/plugins/index.d.ts +18 -0
  214. package/dist/plugins/index.d.ts.map +1 -0
  215. package/dist/plugins/index.js +148 -0
  216. package/dist/plugins/index.js.map +1 -0
  217. package/dist/plugins/loader.d.ts +14 -0
  218. package/dist/plugins/loader.d.ts.map +1 -0
  219. package/dist/plugins/loader.js +98 -0
  220. package/dist/plugins/loader.js.map +1 -0
  221. package/dist/plugins/types.d.ts +91 -0
  222. package/dist/plugins/types.d.ts.map +1 -0
  223. package/dist/plugins/types.js +3 -0
  224. package/dist/plugins/types.js.map +1 -0
  225. package/dist/proxy/certs.d.ts +10 -0
  226. package/dist/proxy/certs.d.ts.map +1 -0
  227. package/dist/proxy/certs.js +110 -0
  228. package/dist/proxy/certs.js.map +1 -0
  229. package/dist/proxy/connect.d.ts +11 -0
  230. package/dist/proxy/connect.d.ts.map +1 -0
  231. package/dist/proxy/connect.js +298 -0
  232. package/dist/proxy/connect.js.map +1 -0
  233. package/dist/proxy/forwarder.d.ts +14 -0
  234. package/dist/proxy/forwarder.d.ts.map +1 -0
  235. package/dist/proxy/forwarder.js +342 -0
  236. package/dist/proxy/forwarder.js.map +1 -0
  237. package/dist/proxy/passthrough.d.ts +4 -0
  238. package/dist/proxy/passthrough.d.ts.map +1 -0
  239. package/dist/proxy/passthrough.js +68 -0
  240. package/dist/proxy/passthrough.js.map +1 -0
  241. package/dist/proxy/providers/anthropic.d.ts +4 -0
  242. package/dist/proxy/providers/anthropic.d.ts.map +1 -0
  243. package/dist/proxy/providers/anthropic.js +46 -0
  244. package/dist/proxy/providers/anthropic.js.map +1 -0
  245. package/dist/proxy/providers/classify.d.ts +14 -0
  246. package/dist/proxy/providers/classify.d.ts.map +1 -0
  247. package/dist/proxy/providers/classify.js +37 -0
  248. package/dist/proxy/providers/classify.js.map +1 -0
  249. package/dist/proxy/providers/claude-web.d.ts +8 -0
  250. package/dist/proxy/providers/claude-web.d.ts.map +1 -0
  251. package/dist/proxy/providers/claude-web.js +50 -0
  252. package/dist/proxy/providers/claude-web.js.map +1 -0
  253. package/dist/proxy/providers/gemini.d.ts +4 -0
  254. package/dist/proxy/providers/gemini.d.ts.map +1 -0
  255. package/dist/proxy/providers/gemini.js +38 -0
  256. package/dist/proxy/providers/gemini.js.map +1 -0
  257. package/dist/proxy/providers/index.d.ts +27 -0
  258. package/dist/proxy/providers/index.d.ts.map +1 -0
  259. package/dist/proxy/providers/index.js +32 -0
  260. package/dist/proxy/providers/index.js.map +1 -0
  261. package/dist/proxy/providers/messaging.d.ts +2 -0
  262. package/dist/proxy/providers/messaging.d.ts.map +1 -0
  263. package/dist/proxy/providers/messaging.js +53 -0
  264. package/dist/proxy/providers/messaging.js.map +1 -0
  265. package/dist/proxy/providers/openai.d.ts +4 -0
  266. package/dist/proxy/providers/openai.d.ts.map +1 -0
  267. package/dist/proxy/providers/openai.js +38 -0
  268. package/dist/proxy/providers/openai.js.map +1 -0
  269. package/dist/proxy/providers/telegram.d.ts +8 -0
  270. package/dist/proxy/providers/telegram.d.ts.map +1 -0
  271. package/dist/proxy/providers/telegram.js +35 -0
  272. package/dist/proxy/providers/telegram.js.map +1 -0
  273. package/dist/proxy/router.d.ts +12 -0
  274. package/dist/proxy/router.d.ts.map +1 -0
  275. package/dist/proxy/router.js +26 -0
  276. package/dist/proxy/router.js.map +1 -0
  277. package/dist/proxy/safety.d.ts +13 -0
  278. package/dist/proxy/safety.d.ts.map +1 -0
  279. package/dist/proxy/safety.js +58 -0
  280. package/dist/proxy/safety.js.map +1 -0
  281. package/dist/proxy/server.d.ts +8 -0
  282. package/dist/proxy/server.d.ts.map +1 -0
  283. package/dist/proxy/server.js +126 -0
  284. package/dist/proxy/server.js.map +1 -0
  285. package/dist/proxy/streaming.d.ts +21 -0
  286. package/dist/proxy/streaming.d.ts.map +1 -0
  287. package/dist/proxy/streaming.js +70 -0
  288. package/dist/proxy/streaming.js.map +1 -0
  289. package/dist/storage/database.d.ts +6 -0
  290. package/dist/storage/database.d.ts.map +1 -0
  291. package/dist/storage/database.js +44 -0
  292. package/dist/storage/database.js.map +1 -0
  293. package/dist/storage/encryption.d.ts +11 -0
  294. package/dist/storage/encryption.d.ts.map +1 -0
  295. package/dist/storage/encryption.js +47 -0
  296. package/dist/storage/encryption.js.map +1 -0
  297. package/dist/storage/migrations.d.ts +3 -0
  298. package/dist/storage/migrations.d.ts.map +1 -0
  299. package/dist/storage/migrations.js +265 -0
  300. package/dist/storage/migrations.js.map +1 -0
  301. package/dist/storage/repositories/audit-log.d.ts +115 -0
  302. package/dist/storage/repositories/audit-log.d.ts.map +1 -0
  303. package/dist/storage/repositories/audit-log.js +586 -0
  304. package/dist/storage/repositories/audit-log.js.map +1 -0
  305. package/dist/storage/repositories/cache.d.ts +26 -0
  306. package/dist/storage/repositories/cache.d.ts.map +1 -0
  307. package/dist/storage/repositories/cache.js +44 -0
  308. package/dist/storage/repositories/cache.js.map +1 -0
  309. package/dist/storage/repositories/dlp-config-history.d.ts +17 -0
  310. package/dist/storage/repositories/dlp-config-history.d.ts.map +1 -0
  311. package/dist/storage/repositories/dlp-config-history.js +30 -0
  312. package/dist/storage/repositories/dlp-config-history.js.map +1 -0
  313. package/dist/storage/repositories/dlp-events.d.ts +35 -0
  314. package/dist/storage/repositories/dlp-events.d.ts.map +1 -0
  315. package/dist/storage/repositories/dlp-events.js +57 -0
  316. package/dist/storage/repositories/dlp-events.js.map +1 -0
  317. package/dist/storage/repositories/dlp-patterns.d.ts +70 -0
  318. package/dist/storage/repositories/dlp-patterns.d.ts.map +1 -0
  319. package/dist/storage/repositories/dlp-patterns.js +187 -0
  320. package/dist/storage/repositories/dlp-patterns.js.map +1 -0
  321. package/dist/storage/repositories/optimizer-events.d.ts +28 -0
  322. package/dist/storage/repositories/optimizer-events.d.ts.map +1 -0
  323. package/dist/storage/repositories/optimizer-events.js +49 -0
  324. package/dist/storage/repositories/optimizer-events.js.map +1 -0
  325. package/dist/storage/repositories/plugin-events.d.ts +34 -0
  326. package/dist/storage/repositories/plugin-events.d.ts.map +1 -0
  327. package/dist/storage/repositories/plugin-events.js +64 -0
  328. package/dist/storage/repositories/plugin-events.js.map +1 -0
  329. package/dist/storage/repositories/requests.d.ts +68 -0
  330. package/dist/storage/repositories/requests.d.ts.map +1 -0
  331. package/dist/storage/repositories/requests.js +113 -0
  332. package/dist/storage/repositories/requests.js.map +1 -0
  333. package/dist/storage/repositories/sessions.d.ts +23 -0
  334. package/dist/storage/repositories/sessions.d.ts.map +1 -0
  335. package/dist/storage/repositories/sessions.js +42 -0
  336. package/dist/storage/repositories/sessions.js.map +1 -0
  337. package/dist/storage/repositories/tool-calls.d.ts +49 -0
  338. package/dist/storage/repositories/tool-calls.d.ts.map +1 -0
  339. package/dist/storage/repositories/tool-calls.js +61 -0
  340. package/dist/storage/repositories/tool-calls.js.map +1 -0
  341. package/dist/storage/repositories/tool-guard-rules.d.ts +50 -0
  342. package/dist/storage/repositories/tool-guard-rules.d.ts.map +1 -0
  343. package/dist/storage/repositories/tool-guard-rules.js +120 -0
  344. package/dist/storage/repositories/tool-guard-rules.js.map +1 -0
  345. package/dist/tool-guard/alert.d.ts +30 -0
  346. package/dist/tool-guard/alert.d.ts.map +1 -0
  347. package/dist/tool-guard/alert.js +113 -0
  348. package/dist/tool-guard/alert.js.map +1 -0
  349. package/dist/tool-guard/extractor.d.ts +10 -0
  350. package/dist/tool-guard/extractor.d.ts.map +1 -0
  351. package/dist/tool-guard/extractor.js +309 -0
  352. package/dist/tool-guard/extractor.js.map +1 -0
  353. package/dist/tool-guard/rules.d.ts +18 -0
  354. package/dist/tool-guard/rules.d.ts.map +1 -0
  355. package/dist/tool-guard/rules.js +255 -0
  356. package/dist/tool-guard/rules.js.map +1 -0
  357. package/dist/tool-guard/streaming-guard.d.ts +57 -0
  358. package/dist/tool-guard/streaming-guard.d.ts.map +1 -0
  359. package/dist/tool-guard/streaming-guard.js +389 -0
  360. package/dist/tool-guard/streaming-guard.js.map +1 -0
  361. package/dist/utils/hash.d.ts +2 -0
  362. package/dist/utils/hash.d.ts.map +1 -0
  363. package/dist/utils/hash.js +8 -0
  364. package/dist/utils/hash.js.map +1 -0
  365. package/dist/utils/logger.d.ts +11 -0
  366. package/dist/utils/logger.d.ts.map +1 -0
  367. package/dist/utils/logger.js +54 -0
  368. package/dist/utils/logger.js.map +1 -0
  369. package/dist/utils/timeout.d.ts +5 -0
  370. package/dist/utils/timeout.d.ts.map +1 -0
  371. package/dist/utils/timeout.js +26 -0
  372. package/dist/utils/timeout.js.map +1 -0
  373. package/dist/version.d.ts +5 -0
  374. package/dist/version.d.ts.map +1 -0
  375. package/dist/version.js +23 -0
  376. package/dist/version.js.map +1 -0
  377. package/package.json +67 -0
@@ -0,0 +1,298 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getSessionForSocket = getSessionForSocket;
37
+ exports.setupConnectHandler = setupConnectHandler;
38
+ const node_http_1 = require("node:http");
39
+ const node_https_1 = require("node:https");
40
+ const tls = __importStar(require("node:tls"));
41
+ const net = __importStar(require("node:net"));
42
+ const certs_js_1 = require("./certs.js");
43
+ const router_js_1 = require("./router.js");
44
+ const forwarder_js_1 = require("./forwarder.js");
45
+ const logger_js_1 = require("../utils/logger.js");
46
+ const log = (0, logger_js_1.createLogger)('connect');
47
+ // API domains to MITM intercept — only these get decrypted
48
+ // LLM providers + messaging platforms (for OpenClaw integration)
49
+ const INTERCEPT_HOSTS = new Set([
50
+ // LLM providers
51
+ 'api.anthropic.com',
52
+ 'api.openai.com',
53
+ 'generativelanguage.googleapis.com',
54
+ 'claude.ai',
55
+ 'chatgpt.com', // ChatGPT Web (OpenAI OAuth mode)
56
+ // Messaging platforms
57
+ 'api.telegram.org',
58
+ 'discord.com',
59
+ 'gateway.discord.gg',
60
+ 'api.slack.com',
61
+ 'slack.com',
62
+ 'graph.facebook.com', // WhatsApp Business API
63
+ 'api.line.me',
64
+ ]);
65
+ // Map socket → session ID for session tracking across CONNECT tunnels
66
+ const socketSessionMap = new WeakMap();
67
+ function getSessionForSocket(socket) {
68
+ return socketSessionMap.get(socket);
69
+ }
70
+ /**
71
+ * Parse session ID from Proxy-Authorization header.
72
+ * When wrap.ts sets HTTPS_PROXY=http://<uuid>@host:port, Node.js sends
73
+ * a Proxy-Authorization: Basic <base64(uuid:)> header in the CONNECT request.
74
+ */
75
+ function parseSessionFromProxy(req) {
76
+ const authHeader = req.headers['proxy-authorization'];
77
+ if (!authHeader)
78
+ return undefined;
79
+ const match = authHeader.match(/^Basic\s+(.+)$/i);
80
+ if (!match)
81
+ return undefined;
82
+ try {
83
+ const decoded = Buffer.from(match[1], 'base64').toString('utf-8');
84
+ // Format is "username:password" — session UUID is the username
85
+ const username = decoded.split(':')[0];
86
+ // Validate it looks like a UUID
87
+ if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(username)) {
88
+ return username;
89
+ }
90
+ }
91
+ catch {
92
+ // Invalid base64
93
+ }
94
+ return undefined;
95
+ }
96
+ /**
97
+ * Attach CONNECT handler to an existing HTTP server.
98
+ * - API hosts: MITM decrypt → plugin pipeline → forward to real upstream
99
+ * - All other hosts: plain TCP tunnel (no inspection)
100
+ */
101
+ function setupConnectHandler(server, config, pluginManager) {
102
+ const ca = (0, certs_js_1.ensureCA)();
103
+ server.on('connect', (req, clientSocket, head) => {
104
+ const [hostname, portStr] = (req.url ?? '').split(':');
105
+ const port = parseInt(portStr, 10) || 443;
106
+ // Extract session ID from proxy auth header, or auto-generate for intercepted hosts
107
+ let sessionId = parseSessionFromProxy(req);
108
+ const source = sessionId ? 'wrap' : 'auto';
109
+ if (!sessionId && INTERCEPT_HOSTS.has(hostname)) {
110
+ sessionId = crypto.randomUUID();
111
+ }
112
+ if (sessionId) {
113
+ socketSessionMap.set(clientSocket, sessionId);
114
+ log.debug('Session mapped', { sessionId, hostname, source });
115
+ }
116
+ if (INTERCEPT_HOSTS.has(hostname)) {
117
+ log.info('CONNECT', { hostname, port, sessionId, source });
118
+ }
119
+ else {
120
+ log.debug('CONNECT tunnel', { hostname, port });
121
+ }
122
+ if (INTERCEPT_HOSTS.has(hostname)) {
123
+ handleMITM(hostname, port, clientSocket, head, ca, config, pluginManager, sessionId, source);
124
+ }
125
+ else {
126
+ handleTunnel(hostname, port, clientSocket, head);
127
+ }
128
+ });
129
+ log.info('CONNECT handler registered', {
130
+ interceptHosts: [...INTERCEPT_HOSTS],
131
+ caCert: (0, certs_js_1.getCACertPath)(),
132
+ });
133
+ }
134
+ /**
135
+ * Plain TCP tunnel — no inspection, no modification.
136
+ * Used for OAuth flows, browser traffic, etc.
137
+ */
138
+ function handleTunnel(hostname, port, clientSocket, head) {
139
+ const serverSocket = net.connect(port, hostname, () => {
140
+ clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
141
+ if (head.length > 0)
142
+ serverSocket.write(head);
143
+ serverSocket.pipe(clientSocket);
144
+ clientSocket.pipe(serverSocket);
145
+ });
146
+ serverSocket.on('error', (err) => {
147
+ log.error('Tunnel error', { hostname, error: err.message });
148
+ clientSocket.end();
149
+ });
150
+ clientSocket.on('error', () => {
151
+ serverSocket.end();
152
+ });
153
+ clientSocket.on('close', () => {
154
+ serverSocket.end();
155
+ });
156
+ }
157
+ /**
158
+ * MITM interception for API hosts.
159
+ * 1. Accept TLS from client using host cert signed by our CA
160
+ * 2. Decrypt the HTTP request
161
+ * 3. Run through plugin pipeline (DLP, metrics, optimizer)
162
+ * 4. Forward to real upstream
163
+ */
164
+ function handleMITM(hostname, port, clientSocket, head, ca, config, pluginManager, sessionId, sessionSource) {
165
+ const hostCert = (0, certs_js_1.getHostCert)(hostname);
166
+ // Tell client the tunnel is established
167
+ clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
168
+ // Wrap client socket with TLS (we act as the target server)
169
+ const tlsSocket = new tls.TLSSocket(clientSocket, {
170
+ isServer: true,
171
+ key: hostCert.key,
172
+ cert: hostCert.cert,
173
+ });
174
+ // Create a per-connection HTTP server to parse the decrypted request
175
+ const handler = createMITMRequestHandler(hostname, config, pluginManager, sessionId, sessionSource);
176
+ const fakeServer = (0, node_http_1.createServer)(handler);
177
+ // Inject the TLS socket as a "connection" to the HTTP server
178
+ fakeServer.emit('connection', tlsSocket);
179
+ if (head.length > 0) {
180
+ tlsSocket.unshift(head);
181
+ }
182
+ tlsSocket.on('error', (err) => {
183
+ log.debug('MITM TLS error', { hostname, error: err.message });
184
+ });
185
+ clientSocket.on('error', () => {
186
+ tlsSocket.destroy();
187
+ });
188
+ clientSocket.on('close', () => {
189
+ fakeServer.close();
190
+ });
191
+ }
192
+ /**
193
+ * Create a request handler for MITM-intercepted connections.
194
+ * Knows the target hostname, so non-provider paths are forwarded directly.
195
+ */
196
+ /**
197
+ * Create a fallback ProviderConfig for intercepted hosts where no
198
+ * registered provider prefix matches. Ensures all POST traffic from
199
+ * MITM'd hosts still flows through the plugin pipeline (DLP, audit).
200
+ */
201
+ function createFallbackProvider(hostname) {
202
+ return {
203
+ name: hostname.replace(/\./g, '-'),
204
+ baseUrl: `https://${hostname}`,
205
+ authHeader: '',
206
+ transformHeaders(headers) {
207
+ const result = {};
208
+ for (const [key, value] of Object.entries(headers)) {
209
+ const lower = key.toLowerCase();
210
+ if (lower !== 'host' && lower !== 'connection' && lower !== 'transfer-encoding') {
211
+ result[key] = value;
212
+ }
213
+ }
214
+ return result;
215
+ },
216
+ extractModel() { return hostname; },
217
+ extractUsage() {
218
+ return { inputTokens: 0, outputTokens: 0 };
219
+ },
220
+ };
221
+ }
222
+ function createMITMRequestHandler(hostname, config, pluginManager, sessionId, sessionSource) {
223
+ return async (req, res) => {
224
+ // Redact secrets from logged paths (e.g., Telegram bot tokens)
225
+ const safePath = (req.url ?? '/').replace(/\/bot[^/]+\//, '/bot****/');
226
+ log.debug('MITM request', { method: req.method, hostname, path: safePath, sessionId });
227
+ // Try to match a known provider route
228
+ const route = (0, router_js_1.resolveRoute)(req);
229
+ // If scanMethods is configured and non-empty, only scan listed methods
230
+ const scanMethods = config.server.scanMethods ?? [];
231
+ const shouldScan = scanMethods.length === 0 || scanMethods.includes(req.method ?? '');
232
+ if (shouldScan) {
233
+ const provider = route?.provider ?? createFallbackProvider(hostname);
234
+ const upstreamUrl = route
235
+ ? route.upstreamUrl
236
+ : `https://${hostname}${req.url ?? '/'}`;
237
+ try {
238
+ await (0, forwarder_js_1.forwardRequest)(req, res, {
239
+ provider,
240
+ upstreamUrl,
241
+ upstreamTimeout: config.timeouts.upstream,
242
+ pluginManager,
243
+ sessionId,
244
+ sessionSource,
245
+ });
246
+ }
247
+ catch (err) {
248
+ log.error('MITM forward failed', { error: err.message });
249
+ if (!res.headersSent) {
250
+ (0, router_js_1.sendError)(res, 500, 'Internal gateway error');
251
+ }
252
+ }
253
+ }
254
+ else {
255
+ // Method excluded from scanning — forward directly
256
+ directForward(req, res, hostname, config.timeouts.upstream);
257
+ }
258
+ };
259
+ }
260
+ /**
261
+ * Forward a request directly to a known hostname via HTTPS.
262
+ * Used for non-API-endpoint requests on API domains (e.g., model listing, health checks).
263
+ */
264
+ function directForward(req, res, hostname, timeout) {
265
+ const path = req.url ?? '/';
266
+ // Copy headers, fix host
267
+ const headers = { ...req.headers };
268
+ headers['host'] = hostname;
269
+ delete headers['connection'];
270
+ const upstreamReq = (0, node_https_1.request)({
271
+ hostname,
272
+ port: 443,
273
+ path,
274
+ method: req.method,
275
+ headers,
276
+ timeout,
277
+ }, (upstreamRes) => {
278
+ log.info('MITM direct response', { hostname, path, status: upstreamRes.statusCode });
279
+ res.writeHead(upstreamRes.statusCode ?? 502, upstreamRes.headers);
280
+ upstreamRes.pipe(res);
281
+ });
282
+ upstreamReq.on('error', (err) => {
283
+ log.error('MITM direct forward failed', { hostname, error: err.message });
284
+ if (!res.headersSent) {
285
+ res.writeHead(502, { 'content-type': 'application/json' });
286
+ res.end(JSON.stringify({ error: { message: 'Upstream request failed', type: 'gateway_error' } }));
287
+ }
288
+ });
289
+ upstreamReq.on('timeout', () => {
290
+ upstreamReq.destroy();
291
+ if (!res.headersSent) {
292
+ res.writeHead(504, { 'content-type': 'application/json' });
293
+ res.end(JSON.stringify({ error: { message: 'Upstream request timed out', type: 'gateway_error' } }));
294
+ }
295
+ });
296
+ req.pipe(upstreamReq);
297
+ }
298
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/proxy/connect.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,kDAEC;AAiCD,kDAuCC;AA/GD,yCAAwG;AACxG,2CAAqD;AACrD,8CAAgC;AAChC,8CAAgC;AAGhC,yCAAkE;AAClE,2CAAsD;AACtD,iDAAgD;AAGhD,kDAAkD;AAElD,MAAM,GAAG,GAAG,IAAA,wBAAY,EAAC,SAAS,CAAC,CAAC;AAEpC,2DAA2D;AAC3D,iEAAiE;AACjE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,gBAAgB;IAChB,mBAAmB;IACnB,gBAAgB;IAChB,mCAAmC;IACnC,WAAW;IACX,aAAa,EAAe,kCAAkC;IAC9D,sBAAsB;IACtB,kBAAkB;IAClB,aAAa;IACb,oBAAoB;IACpB,eAAe;IACf,WAAW;IACX,oBAAoB,EAAQ,wBAAwB;IACpD,aAAa;CACd,CAAC,CAAC;AAEH,sEAAsE;AACtE,MAAM,gBAAgB,GAAG,IAAI,OAAO,EAAsB,CAAC;AAE3D,SAAgB,mBAAmB,CAAC,MAAkB;IACpD,OAAO,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,SAAS,qBAAqB,CAAC,GAAoB;IACjD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACtD,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAElC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClE,+DAA+D;QAC/D,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,gCAAgC;QAChC,IAAI,iEAAiE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrF,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB,CACjC,MAAkB,EAClB,MAAqB,EACrB,aAA4B;IAE5B,MAAM,EAAE,GAAG,IAAA,mBAAQ,GAAE,CAAC;IAEtB,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAoB,EAAE,YAAwB,EAAE,IAAY,EAAE,EAAE;QACpF,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;QAE1C,oFAAoF;QACpF,IAAI,SAAS,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3C,IAAI,CAAC,SAAS,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChD,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAClC,CAAC;QACD,IAAI,SAAS,EAAE,CAAC;YACd,gBAAgB,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;YAC9C,GAAG,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAC/F,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,4BAA4B,EAAE;QACrC,cAAc,EAAE,CAAC,GAAG,eAAe,CAAC;QACpC,MAAM,EAAE,IAAA,wBAAa,GAAE;KACxB,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,QAAgB,EAAE,IAAY,EAAE,YAAwB,EAAE,IAAY;IAC1F,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE;QACpD,YAAY,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAClE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAChC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QAC/B,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,YAAY,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAC5B,YAAY,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAC5B,YAAY,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAS,UAAU,CACjB,QAAgB,EAChB,IAAY,EACZ,YAAwB,EACxB,IAAY,EACZ,EAAiC,EACjC,MAAqB,EACrB,aAA4B,EAC5B,SAAkB,EAClB,aAAsB;IAEtB,MAAM,QAAQ,GAAG,IAAA,sBAAW,EAAC,QAAQ,CAAC,CAAC;IAEvC,wCAAwC;IACxC,YAAY,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAElE,4DAA4D;IAC5D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE;QAChD,QAAQ,EAAE,IAAI;QACd,GAAG,EAAE,QAAQ,CAAC,GAAG;QACjB,IAAI,EAAE,QAAQ,CAAC,IAAI;KACpB,CAAC,CAAC;IAEH,qEAAqE;IACrE,MAAM,OAAO,GAAG,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;IACpG,MAAM,UAAU,GAAG,IAAA,wBAAgB,EAAC,OAAO,CAAC,CAAC;IAE7C,6DAA6D;IAC7D,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IAEzC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAC5B,SAAS,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAC5B,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH;;;;GAIG;AACH,SAAS,sBAAsB,CAAC,QAAgB;IAC9C,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;QAClC,OAAO,EAAE,WAAW,QAAQ,EAAE;QAC9B,UAAU,EAAE,EAAE;QACd,gBAAgB,CAAC,OAA+B;YAC9C,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnD,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;gBAChC,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,mBAAmB,EAAE,CAAC;oBAChF,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACtB,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,YAAY,KAAa,OAAO,QAAQ,CAAC,CAAC,CAAC;QAC3C,YAAY;YACV,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;QAC7C,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,QAAgB,EAChB,MAAqB,EACrB,aAA4B,EAC5B,SAAkB,EAClB,aAAsB;IAEtB,OAAO,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAE,EAAE;QACzD,+DAA+D;QAC/D,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QACvE,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QAEvF,sCAAsC;QACtC,MAAM,KAAK,GAAG,IAAA,wBAAY,EAAC,GAAG,CAAC,CAAC;QAEhC,uEAAuE;QACvE,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QAEtF,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAQ,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC;YACrE,MAAM,WAAW,GAAG,KAAK;gBACvB,CAAC,CAAC,KAAK,CAAC,WAAW;gBACnB,CAAC,CAAC,WAAW,QAAQ,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YAE3C,IAAI,CAAC;gBACH,MAAM,IAAA,6BAAc,EAAC,GAAG,EAAE,GAAG,EAAE;oBAC7B,QAAQ;oBACR,WAAW;oBACX,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;oBACzC,aAAa;oBACb,SAAS;oBACT,aAAa;iBACd,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;gBACpE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,IAAA,qBAAS,EAAC,GAAG,EAAE,GAAG,EAAE,wBAAwB,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,mDAAmD;YACnD,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CACpB,GAAoB,EACpB,GAAmB,EACnB,QAAgB,EAChB,OAAe;IAEf,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;IAE5B,yBAAyB;IACzB,MAAM,OAAO,GAAkD,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IAClF,OAAO,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC;IAC3B,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAE7B,MAAM,WAAW,GAAG,IAAA,oBAAY,EAC9B;QACE,QAAQ;QACR,IAAI,EAAE,GAAG;QACT,IAAI;QACJ,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,OAAO;QACP,OAAO;KACR,EACD,CAAC,WAAW,EAAE,EAAE;QACd,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;QACrF,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,UAAU,IAAI,GAAG,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;QAClE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC,CACF,CAAC;IAEF,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QAC9B,GAAG,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC;QACpG,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QAC7B,WAAW,CAAC,OAAO,EAAE,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,4BAA4B,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC;QACvG,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { ProviderConfig } from './providers/index.js';
3
+ import type { PluginManager } from '../plugins/index.js';
4
+ import type { RequestContext } from '../plugins/types.js';
5
+ export interface ForwardOptions {
6
+ provider: ProviderConfig;
7
+ upstreamUrl: string;
8
+ upstreamTimeout: number;
9
+ pluginManager: PluginManager;
10
+ sessionId?: string;
11
+ sessionSource?: string;
12
+ }
13
+ export declare function forwardRequest(req: IncomingMessage, res: ServerResponse, options: ForwardOptions): Promise<RequestContext>;
14
+ //# sourceMappingURL=forwarder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forwarder.d.ts","sourceRoot":"","sources":["../../src/proxy/forwarder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAqD,MAAM,qBAAqB,CAAC;AAO7G,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAmBD,wBAAsB,cAAc,CAClC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CAsJzB"}
@@ -0,0 +1,342 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.forwardRequest = forwardRequest;
4
+ const node_https_1 = require("node:https");
5
+ const node_http_1 = require("node:http");
6
+ const node_crypto_1 = require("node:crypto");
7
+ const streaming_js_1 = require("./streaming.js");
8
+ const streaming_guard_js_1 = require("../tool-guard/streaming-guard.js");
9
+ const logger_js_1 = require("../utils/logger.js");
10
+ const log = (0, logger_js_1.createLogger)('forwarder');
11
+ function computeApiKeyHash(headers) {
12
+ // Check common auth headers
13
+ const authHeader = headers['authorization'] || headers['x-api-key'];
14
+ if (!authHeader)
15
+ return undefined;
16
+ const key = authHeader.replace(/^Bearer\s+/i, '');
17
+ return (0, node_crypto_1.createHash)('sha256').update(key).digest('hex').slice(0, 16);
18
+ }
19
+ function bufferBody(req) {
20
+ return new Promise((resolve, reject) => {
21
+ const chunks = [];
22
+ req.on('data', (chunk) => chunks.push(chunk));
23
+ req.on('end', () => resolve(Buffer.concat(chunks)));
24
+ req.on('error', reject);
25
+ });
26
+ }
27
+ async function forwardRequest(req, res, options) {
28
+ const { provider, upstreamUrl, upstreamTimeout, pluginManager, sessionId, sessionSource } = options;
29
+ const startTime = Date.now();
30
+ const requestId = crypto.randomUUID();
31
+ // Buffer the request body
32
+ const rawBody = await bufferBody(req);
33
+ let bodyStr = rawBody.toString('utf-8');
34
+ let parsedBody = {};
35
+ try {
36
+ parsedBody = JSON.parse(bodyStr);
37
+ }
38
+ catch {
39
+ // Not JSON, use as-is
40
+ }
41
+ const model = provider.extractModel(parsedBody);
42
+ const isStreaming = Boolean(parsedBody.stream);
43
+ const reqHeaders = req.headers;
44
+ const apiKeyHash = computeApiKeyHash(reqHeaders);
45
+ // Build request context
46
+ const requestContext = {
47
+ id: requestId,
48
+ provider: provider.name,
49
+ model,
50
+ method: req.method ?? 'POST',
51
+ path: req.url ?? '/',
52
+ headers: reqHeaders,
53
+ body: bodyStr,
54
+ parsedBody,
55
+ isStreaming,
56
+ startTime,
57
+ sessionId,
58
+ sessionSource,
59
+ apiKeyHash,
60
+ };
61
+ // Run onRequest plugins
62
+ const pluginResult = await pluginManager.runOnRequest(requestContext);
63
+ // If a plugin short-circuited with a response (e.g., cache hit)
64
+ if (pluginResult.shortCircuit) {
65
+ const cached = pluginResult.shortCircuit;
66
+ res.writeHead(cached.statusCode, cached.headers);
67
+ res.end(cached.body);
68
+ return requestContext;
69
+ }
70
+ // If a plugin blocked the request (e.g., DLP)
71
+ if (pluginResult.blocked) {
72
+ res.writeHead(403, { 'content-type': 'application/json' });
73
+ res.end(JSON.stringify({
74
+ error: {
75
+ message: pluginResult.blocked.reason,
76
+ type: 'gateway_blocked',
77
+ },
78
+ }));
79
+ return requestContext;
80
+ }
81
+ // If a plugin crashed in fail-closed mode
82
+ if (pluginResult.pluginError) {
83
+ res.writeHead(502, { 'content-type': 'application/json' });
84
+ res.end(JSON.stringify({
85
+ error: {
86
+ message: 'Security pipeline error',
87
+ detail: `Plugin ${pluginResult.pluginError.pluginName} failed`,
88
+ type: 'gateway_pipeline_error',
89
+ },
90
+ }));
91
+ return requestContext;
92
+ }
93
+ // Use modified body if plugins changed it
94
+ if (pluginResult.modifiedBody) {
95
+ bodyStr = pluginResult.modifiedBody;
96
+ }
97
+ // Forward to upstream
98
+ const url = new URL(upstreamUrl);
99
+ const isHttps = url.protocol === 'https:';
100
+ const outgoingHeaders = provider.transformHeaders(req.headers);
101
+ outgoingHeaders['host'] = url.host;
102
+ const hasBody = req.method !== 'GET' && req.method !== 'HEAD';
103
+ if (hasBody) {
104
+ outgoingHeaders['content-length'] = Buffer.byteLength(bodyStr).toString();
105
+ }
106
+ const makeRequest = isHttps ? node_https_1.request : node_http_1.request;
107
+ return new Promise((resolve) => {
108
+ const upstreamReq = makeRequest({
109
+ hostname: url.hostname,
110
+ port: url.port || (isHttps ? 443 : 80),
111
+ path: url.pathname + url.search,
112
+ method: req.method,
113
+ headers: outgoingHeaders,
114
+ timeout: upstreamTimeout,
115
+ }, (upstreamRes) => {
116
+ const statusCode = upstreamRes.statusCode ?? 500;
117
+ // Copy upstream response headers
118
+ const responseHeaders = {};
119
+ for (const [key, value] of Object.entries(upstreamRes.headers)) {
120
+ if (value)
121
+ responseHeaders[key] = Array.isArray(value) ? value.join(', ') : value;
122
+ }
123
+ if (isStreaming) {
124
+ // Streaming: send headers immediately, forward chunks in real-time
125
+ res.writeHead(statusCode, responseHeaders);
126
+ handleStreamingResponse(upstreamRes, res, requestContext, pluginManager, provider, startTime)
127
+ .then(() => resolve(requestContext));
128
+ }
129
+ else {
130
+ // Non-streaming: buffer response, run onResponse hook, then send
131
+ handleBufferedResponse(upstreamRes, res, statusCode, responseHeaders, requestContext, pluginManager, provider, startTime)
132
+ .then(() => resolve(requestContext));
133
+ }
134
+ });
135
+ upstreamReq.on('error', (err) => {
136
+ log.error('Upstream request failed', { error: err.message, provider: provider.name });
137
+ if (!res.headersSent) {
138
+ res.writeHead(502, { 'content-type': 'application/json' });
139
+ res.end(JSON.stringify({
140
+ error: { message: 'Upstream request failed', type: 'gateway_error' },
141
+ }));
142
+ }
143
+ resolve(requestContext);
144
+ });
145
+ upstreamReq.on('timeout', () => {
146
+ upstreamReq.destroy();
147
+ if (!res.headersSent) {
148
+ res.writeHead(504, { 'content-type': 'application/json' });
149
+ res.end(JSON.stringify({
150
+ error: { message: 'Upstream request timed out', type: 'gateway_error' },
151
+ }));
152
+ }
153
+ resolve(requestContext);
154
+ });
155
+ if (hasBody) {
156
+ upstreamReq.write(bodyStr);
157
+ }
158
+ upstreamReq.end();
159
+ });
160
+ }
161
+ // Cap accumulated body for post-send plugin processing.
162
+ // Client always receives the full stream; only onResponseComplete sees the truncated body.
163
+ const MAX_STREAMING_BODY = 2 * 1024 * 1024; // 2MB
164
+ async function handleStreamingResponse(upstreamRes, clientRes, context, pluginManager, provider, startTime) {
165
+ let fullResponseData = '';
166
+ let bodyCapReached = false;
167
+ const sseEvents = [];
168
+ // Streaming tool guard: intercept tool_use SSE blocks when action=block
169
+ const useGuard = Boolean(context._toolGuardStreamBlock);
170
+ const guard = useGuard
171
+ ? new streaming_guard_js_1.StreamingToolGuard({ blockMinSeverity: context._toolGuardStreamBlock, rules: context._toolGuardRules }, (data) => clientRes.write(data))
172
+ : null;
173
+ // Accumulate raw events for the guard (keyed by parse position)
174
+ let rawEventBuffer = '';
175
+ const parser = new streaming_js_1.SSEParser((event) => {
176
+ const data = (0, streaming_js_1.parseSSEData)(event);
177
+ if (data) {
178
+ sseEvents.push(data);
179
+ }
180
+ if (guard) {
181
+ // Reconstruct the raw SSE text for this event
182
+ const rawEvent = (event.event ? `event: ${event.event}\n` : '') +
183
+ `data: ${event.data}\n\n`;
184
+ guard.processEvent(rawEvent, data);
185
+ }
186
+ });
187
+ return new Promise((resolve) => {
188
+ upstreamRes.on('data', (chunk) => {
189
+ const chunkStr = chunk.toString('utf-8');
190
+ // Cap accumulated body for post-send analysis; client still gets all data
191
+ if (!bodyCapReached) {
192
+ fullResponseData += chunkStr;
193
+ if (fullResponseData.length > MAX_STREAMING_BODY) {
194
+ bodyCapReached = true;
195
+ }
196
+ }
197
+ if (guard) {
198
+ // Let the parser drive the guard (events are processed in the SSEParser callback)
199
+ parser.feed(chunkStr);
200
+ }
201
+ else {
202
+ // No guard: forward raw bytes unmodified, parse for inspection only
203
+ clientRes.write(chunk);
204
+ parser.feed(chunkStr);
205
+ }
206
+ });
207
+ upstreamRes.on('end', async () => {
208
+ parser.flush();
209
+ if (guard)
210
+ guard.flush();
211
+ clientRes.end();
212
+ // Propagate streaming guard block results to request context
213
+ if (guard && guard.results.length > 0) {
214
+ const blocked = guard.results.filter(r => r.blocked);
215
+ if (blocked.length > 0) {
216
+ context.toolGuardHit = true;
217
+ context.toolGuardFindings = blocked.length;
218
+ }
219
+ }
220
+ const latencyMs = Date.now() - startTime;
221
+ // Extract usage by merging across all SSE events (take max per field).
222
+ // Anthropic splits usage: input_tokens in message_start, output_tokens in message_delta.
223
+ const usage = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
224
+ for (const event of sseEvents) {
225
+ const extracted = provider.extractUsage(event);
226
+ if (extracted.inputTokens > usage.inputTokens)
227
+ usage.inputTokens = extracted.inputTokens;
228
+ if (extracted.outputTokens > usage.outputTokens)
229
+ usage.outputTokens = extracted.outputTokens;
230
+ if ((extracted.cacheCreationTokens ?? 0) > usage.cacheCreationTokens)
231
+ usage.cacheCreationTokens = extracted.cacheCreationTokens ?? 0;
232
+ if ((extracted.cacheReadTokens ?? 0) > usage.cacheReadTokens)
233
+ usage.cacheReadTokens = extracted.cacheReadTokens ?? 0;
234
+ }
235
+ const completeContext = {
236
+ request: context,
237
+ statusCode: upstreamRes.statusCode ?? 200,
238
+ body: fullResponseData,
239
+ parsedBody: null,
240
+ usage,
241
+ latencyMs,
242
+ isStreaming: true,
243
+ sseEvents,
244
+ };
245
+ await pluginManager.runOnResponseComplete(completeContext);
246
+ resolve();
247
+ });
248
+ upstreamRes.on('error', () => {
249
+ if (guard)
250
+ guard.flush();
251
+ clientRes.end();
252
+ resolve();
253
+ });
254
+ });
255
+ }
256
+ async function handleBufferedResponse(upstreamRes, clientRes, statusCode, responseHeaders, context, pluginManager, provider, startTime) {
257
+ return new Promise((resolve) => {
258
+ const chunks = [];
259
+ upstreamRes.on('data', (chunk) => {
260
+ chunks.push(chunk);
261
+ });
262
+ upstreamRes.on('end', async () => {
263
+ const body = Buffer.concat(chunks);
264
+ let bodyStr = body.toString('utf-8');
265
+ const latencyMs = Date.now() - startTime;
266
+ let parsedBody = null;
267
+ try {
268
+ parsedBody = JSON.parse(bodyStr);
269
+ }
270
+ catch {
271
+ // Not JSON
272
+ }
273
+ // Run onResponse hook (pre-send interception)
274
+ const interceptContext = {
275
+ request: context,
276
+ statusCode,
277
+ headers: responseHeaders,
278
+ body: bodyStr,
279
+ parsedBody,
280
+ isStreaming: false,
281
+ };
282
+ const hookResult = await pluginManager.runOnResponse(interceptContext);
283
+ if (hookResult.blocked) {
284
+ // Block: send error to client instead of the LLM response
285
+ clientRes.writeHead(403, { 'content-type': 'application/json' });
286
+ clientRes.end(JSON.stringify({
287
+ error: {
288
+ message: hookResult.blocked.reason,
289
+ type: 'gateway_response_blocked',
290
+ },
291
+ }));
292
+ }
293
+ else if (hookResult.pluginError) {
294
+ // Plugin crashed in fail-closed mode
295
+ clientRes.writeHead(502, { 'content-type': 'application/json' });
296
+ clientRes.end(JSON.stringify({
297
+ error: {
298
+ message: 'Security pipeline error',
299
+ detail: `Plugin ${hookResult.pluginError.pluginName} failed`,
300
+ type: 'gateway_pipeline_error',
301
+ },
302
+ }));
303
+ }
304
+ else {
305
+ // Send response (original or modified)
306
+ if (hookResult.modifiedBody) {
307
+ bodyStr = hookResult.modifiedBody;
308
+ }
309
+ // We buffered the response, so set exact content-length and remove chunked encoding
310
+ delete responseHeaders['transfer-encoding'];
311
+ responseHeaders['content-length'] = Buffer.byteLength(bodyStr).toString();
312
+ clientRes.writeHead(statusCode, responseHeaders);
313
+ clientRes.write(bodyStr);
314
+ clientRes.end();
315
+ }
316
+ const usage = parsedBody
317
+ ? provider.extractUsage(parsedBody)
318
+ : { inputTokens: 0, outputTokens: 0 };
319
+ const completeContext = {
320
+ request: context,
321
+ statusCode,
322
+ body: bodyStr,
323
+ parsedBody,
324
+ usage: {
325
+ inputTokens: usage.inputTokens,
326
+ outputTokens: usage.outputTokens,
327
+ cacheCreationTokens: usage.cacheCreationTokens ?? 0,
328
+ cacheReadTokens: usage.cacheReadTokens ?? 0,
329
+ },
330
+ latencyMs,
331
+ isStreaming: false,
332
+ };
333
+ await pluginManager.runOnResponseComplete(completeContext);
334
+ resolve();
335
+ });
336
+ upstreamRes.on('error', () => {
337
+ clientRes.end();
338
+ resolve();
339
+ });
340
+ });
341
+ }
342
+ //# sourceMappingURL=forwarder.js.map