@congzhen/changewayguard 6.8.12

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 (329) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +270 -0
  3. package/dashboard-dist/api/104.index.js +1420 -0
  4. package/dashboard-dist/api/104.index.js.map +1 -0
  5. package/dashboard-dist/api/113.index.js +496 -0
  6. package/dashboard-dist/api/113.index.js.map +1 -0
  7. package/dashboard-dist/api/18.index.js +67 -0
  8. package/dashboard-dist/api/18.index.js.map +1 -0
  9. package/dashboard-dist/api/217.index.js +44 -0
  10. package/dashboard-dist/api/217.index.js.map +1 -0
  11. package/dashboard-dist/api/222.index.js +90 -0
  12. package/dashboard-dist/api/222.index.js.map +1 -0
  13. package/dashboard-dist/api/25.index.js +3562 -0
  14. package/dashboard-dist/api/25.index.js.map +1 -0
  15. package/dashboard-dist/api/280.index.js +206 -0
  16. package/dashboard-dist/api/280.index.js.map +1 -0
  17. package/dashboard-dist/api/369.index.js +115 -0
  18. package/dashboard-dist/api/369.index.js.map +1 -0
  19. package/dashboard-dist/api/377.index.js +1176 -0
  20. package/dashboard-dist/api/377.index.js.map +1 -0
  21. package/dashboard-dist/api/411.index.js +4250 -0
  22. package/dashboard-dist/api/411.index.js.map +1 -0
  23. package/dashboard-dist/api/424.index.js +135 -0
  24. package/dashboard-dist/api/424.index.js.map +1 -0
  25. package/dashboard-dist/api/573.index.js +806 -0
  26. package/dashboard-dist/api/573.index.js.map +1 -0
  27. package/dashboard-dist/api/598.index.js +328 -0
  28. package/dashboard-dist/api/598.index.js.map +1 -0
  29. package/dashboard-dist/api/62.index.js +4151 -0
  30. package/dashboard-dist/api/62.index.js.map +1 -0
  31. package/dashboard-dist/api/67.index.js +23383 -0
  32. package/dashboard-dist/api/67.index.js.map +1 -0
  33. package/dashboard-dist/api/678.index.js +2734 -0
  34. package/dashboard-dist/api/678.index.js.map +1 -0
  35. package/dashboard-dist/api/698.index.js +1896 -0
  36. package/dashboard-dist/api/698.index.js.map +1 -0
  37. package/dashboard-dist/api/720.index.js +98 -0
  38. package/dashboard-dist/api/720.index.js.map +1 -0
  39. package/dashboard-dist/api/830.index.js +95 -0
  40. package/dashboard-dist/api/830.index.js.map +1 -0
  41. package/dashboard-dist/api/831.index.js +99 -0
  42. package/dashboard-dist/api/831.index.js.map +1 -0
  43. package/dashboard-dist/api/84.index.js +64 -0
  44. package/dashboard-dist/api/84.index.js.map +1 -0
  45. package/dashboard-dist/api/900.index.js +65 -0
  46. package/dashboard-dist/api/900.index.js.map +1 -0
  47. package/dashboard-dist/api/917.index.js +88 -0
  48. package/dashboard-dist/api/917.index.js.map +1 -0
  49. package/dashboard-dist/api/948.index.js +64 -0
  50. package/dashboard-dist/api/948.index.js.map +1 -0
  51. package/dashboard-dist/api/953.index.js +67 -0
  52. package/dashboard-dist/api/953.index.js.map +1 -0
  53. package/dashboard-dist/api/975.index.js +374 -0
  54. package/dashboard-dist/api/975.index.js.map +1 -0
  55. package/dashboard-dist/api/drizzle/sqlite/0000_short_captain_stacy.sql +70 -0
  56. package/dashboard-dist/api/drizzle/sqlite/0001_closed_magus.sql +10 -0
  57. package/dashboard-dist/api/drizzle/sqlite/0002_agent_capability_observation.sql +38 -0
  58. package/dashboard-dist/api/drizzle/sqlite/0003_auth_magic_link.sql +28 -0
  59. package/dashboard-dist/api/drizzle/sqlite/0004_static_scan_fields.sql +8 -0
  60. package/dashboard-dist/api/drizzle/sqlite/0005_gateway_activity.sql +24 -0
  61. package/dashboard-dist/api/drizzle/sqlite/0006_sour_marauders.sql +41 -0
  62. package/dashboard-dist/api/drizzle/sqlite/meta/0000_snapshot.json +460 -0
  63. package/dashboard-dist/api/drizzle/sqlite/meta/0001_snapshot.json +536 -0
  64. package/dashboard-dist/api/drizzle/sqlite/meta/0006_snapshot.json +1249 -0
  65. package/dashboard-dist/api/drizzle/sqlite/meta/_journal.json +55 -0
  66. package/dashboard-dist/api/index.js +27340 -0
  67. package/dashboard-dist/api/index.js.map +1 -0
  68. package/dashboard-dist/api/package.json +16 -0
  69. package/dashboard-dist/api/sourcemap-register.cjs +1 -0
  70. package/dashboard-dist/web/assets/index-CqWIeBTD.js +158 -0
  71. package/dashboard-dist/web/assets/index-Dw7--9q4.css +1 -0
  72. package/dashboard-dist/web/changeway-logo.png +0 -0
  73. package/dashboard-dist/web/favicon.svg +29 -0
  74. package/dashboard-dist/web/index.html +14 -0
  75. package/dashboard-dist/web/logo.svg +16 -0
  76. package/dist/agent/auth.d.ts +37 -0
  77. package/dist/agent/auth.d.ts.map +1 -0
  78. package/dist/agent/auth.js +151 -0
  79. package/dist/agent/auth.js.map +1 -0
  80. package/dist/agent/behavior-detector.d.ts +150 -0
  81. package/dist/agent/behavior-detector.d.ts.map +1 -0
  82. package/dist/agent/behavior-detector.js +573 -0
  83. package/dist/agent/behavior-detector.js.map +1 -0
  84. package/dist/agent/business-reporter.d.ts +114 -0
  85. package/dist/agent/business-reporter.d.ts.map +1 -0
  86. package/dist/agent/business-reporter.js +359 -0
  87. package/dist/agent/business-reporter.js.map +1 -0
  88. package/dist/agent/config-sync.d.ts +70 -0
  89. package/dist/agent/config-sync.d.ts.map +1 -0
  90. package/dist/agent/config-sync.js +133 -0
  91. package/dist/agent/config-sync.js.map +1 -0
  92. package/dist/agent/config.d.ts +97 -0
  93. package/dist/agent/config.d.ts.map +1 -0
  94. package/dist/agent/config.js +359 -0
  95. package/dist/agent/config.js.map +1 -0
  96. package/dist/agent/content-injection-scanner.d.ts +35 -0
  97. package/dist/agent/content-injection-scanner.d.ts.map +1 -0
  98. package/dist/agent/content-injection-scanner.js +270 -0
  99. package/dist/agent/content-injection-scanner.js.map +1 -0
  100. package/dist/agent/engine-log-writer.d.ts +6 -0
  101. package/dist/agent/engine-log-writer.d.ts.map +1 -0
  102. package/dist/agent/engine-log-writer.js +18 -0
  103. package/dist/agent/engine-log-writer.js.map +1 -0
  104. package/dist/agent/env.d.ts +19 -0
  105. package/dist/agent/env.d.ts.map +1 -0
  106. package/dist/agent/env.js +43 -0
  107. package/dist/agent/env.js.map +1 -0
  108. package/dist/agent/event-reporter.d.ts +87 -0
  109. package/dist/agent/event-reporter.d.ts.map +1 -0
  110. package/dist/agent/event-reporter.js +315 -0
  111. package/dist/agent/event-reporter.js.map +1 -0
  112. package/dist/agent/file-watcher.d.ts +50 -0
  113. package/dist/agent/file-watcher.d.ts.map +1 -0
  114. package/dist/agent/file-watcher.js +135 -0
  115. package/dist/agent/file-watcher.js.map +1 -0
  116. package/dist/agent/fs-utils.d.ts +22 -0
  117. package/dist/agent/fs-utils.d.ts.map +1 -0
  118. package/dist/agent/fs-utils.js +41 -0
  119. package/dist/agent/fs-utils.js.map +1 -0
  120. package/dist/agent/gateway-manager.d.ts +59 -0
  121. package/dist/agent/gateway-manager.d.ts.map +1 -0
  122. package/dist/agent/gateway-manager.js +583 -0
  123. package/dist/agent/gateway-manager.js.map +1 -0
  124. package/dist/agent/hook-types.d.ts +276 -0
  125. package/dist/agent/hook-types.d.ts.map +1 -0
  126. package/dist/agent/hook-types.js +51 -0
  127. package/dist/agent/hook-types.js.map +1 -0
  128. package/dist/agent/index.d.ts +8 -0
  129. package/dist/agent/index.d.ts.map +1 -0
  130. package/dist/agent/index.js +8 -0
  131. package/dist/agent/index.js.map +1 -0
  132. package/dist/agent/prompt-gate.d.ts +13 -0
  133. package/dist/agent/prompt-gate.d.ts.map +1 -0
  134. package/dist/agent/prompt-gate.js +28 -0
  135. package/dist/agent/prompt-gate.js.map +1 -0
  136. package/dist/agent/prompt-input.d.ts +9 -0
  137. package/dist/agent/prompt-input.d.ts.map +1 -0
  138. package/dist/agent/prompt-input.js +158 -0
  139. package/dist/agent/prompt-input.js.map +1 -0
  140. package/dist/agent/prompt-output.d.ts +4 -0
  141. package/dist/agent/prompt-output.d.ts.map +1 -0
  142. package/dist/agent/prompt-output.js +19 -0
  143. package/dist/agent/prompt-output.js.map +1 -0
  144. package/dist/agent/runner.d.ts +23 -0
  145. package/dist/agent/runner.d.ts.map +1 -0
  146. package/dist/agent/runner.js +154 -0
  147. package/dist/agent/runner.js.map +1 -0
  148. package/dist/agent/sanitizer.d.ts +10 -0
  149. package/dist/agent/sanitizer.d.ts.map +1 -0
  150. package/dist/agent/sanitizer.js +175 -0
  151. package/dist/agent/sanitizer.js.map +1 -0
  152. package/dist/agent/scan-activity.d.ts +18 -0
  153. package/dist/agent/scan-activity.d.ts.map +1 -0
  154. package/dist/agent/scan-activity.js +32 -0
  155. package/dist/agent/scan-activity.js.map +1 -0
  156. package/dist/agent/types.d.ts +177 -0
  157. package/dist/agent/types.d.ts.map +1 -0
  158. package/dist/agent/types.js +5 -0
  159. package/dist/agent/types.js.map +1 -0
  160. package/dist/agent/workspace-scanner.d.ts +35 -0
  161. package/dist/agent/workspace-scanner.d.ts.map +1 -0
  162. package/dist/agent/workspace-scanner.js +137 -0
  163. package/dist/agent/workspace-scanner.js.map +1 -0
  164. package/dist/dashboard-launcher.d.ts +52 -0
  165. package/dist/dashboard-launcher.d.ts.map +1 -0
  166. package/dist/dashboard-launcher.js +363 -0
  167. package/dist/dashboard-launcher.js.map +1 -0
  168. package/dist/gateway/activity.d.ts +52 -0
  169. package/dist/gateway/activity.d.ts.map +1 -0
  170. package/dist/gateway/activity.js +111 -0
  171. package/dist/gateway/activity.js.map +1 -0
  172. package/dist/gateway/config.d.ts +50 -0
  173. package/dist/gateway/config.d.ts.map +1 -0
  174. package/dist/gateway/config.js +200 -0
  175. package/dist/gateway/config.js.map +1 -0
  176. package/dist/gateway/gateway/activity.d.ts +52 -0
  177. package/dist/gateway/gateway/activity.d.ts.map +1 -0
  178. package/dist/gateway/gateway/activity.js +111 -0
  179. package/dist/gateway/gateway/activity.js.map +1 -0
  180. package/dist/gateway/gateway/config.d.ts +50 -0
  181. package/dist/gateway/gateway/config.d.ts.map +1 -0
  182. package/dist/gateway/gateway/config.js +200 -0
  183. package/dist/gateway/gateway/config.js.map +1 -0
  184. package/dist/gateway/gateway/handlers/anthropic.d.ts +12 -0
  185. package/dist/gateway/gateway/handlers/anthropic.d.ts.map +1 -0
  186. package/dist/gateway/gateway/handlers/anthropic.js +254 -0
  187. package/dist/gateway/gateway/handlers/anthropic.js.map +1 -0
  188. package/dist/gateway/gateway/handlers/gemini.d.ts +12 -0
  189. package/dist/gateway/gateway/handlers/gemini.d.ts.map +1 -0
  190. package/dist/gateway/gateway/handlers/gemini.js +101 -0
  191. package/dist/gateway/gateway/handlers/gemini.js.map +1 -0
  192. package/dist/gateway/gateway/handlers/models.d.ts +4 -0
  193. package/dist/gateway/gateway/handlers/models.d.ts.map +1 -0
  194. package/dist/gateway/gateway/handlers/models.js +36 -0
  195. package/dist/gateway/gateway/handlers/models.js.map +1 -0
  196. package/dist/gateway/gateway/handlers/openai.d.ts +16 -0
  197. package/dist/gateway/gateway/handlers/openai.d.ts.map +1 -0
  198. package/dist/gateway/gateway/handlers/openai.js +254 -0
  199. package/dist/gateway/gateway/handlers/openai.js.map +1 -0
  200. package/dist/gateway/gateway/index.d.ts +27 -0
  201. package/dist/gateway/gateway/index.d.ts.map +1 -0
  202. package/dist/gateway/gateway/index.js +293 -0
  203. package/dist/gateway/gateway/index.js.map +1 -0
  204. package/dist/gateway/gateway/mapping-store.d.ts +38 -0
  205. package/dist/gateway/gateway/mapping-store.d.ts.map +1 -0
  206. package/dist/gateway/gateway/mapping-store.js +74 -0
  207. package/dist/gateway/gateway/mapping-store.js.map +1 -0
  208. package/dist/gateway/gateway/restorer.d.ts +63 -0
  209. package/dist/gateway/gateway/restorer.d.ts.map +1 -0
  210. package/dist/gateway/gateway/restorer.js +284 -0
  211. package/dist/gateway/gateway/restorer.js.map +1 -0
  212. package/dist/gateway/gateway/sanitizer.d.ts +17 -0
  213. package/dist/gateway/gateway/sanitizer.d.ts.map +1 -0
  214. package/dist/gateway/gateway/sanitizer.js +228 -0
  215. package/dist/gateway/gateway/sanitizer.js.map +1 -0
  216. package/dist/gateway/gateway/types.d.ts +53 -0
  217. package/dist/gateway/gateway/types.d.ts.map +1 -0
  218. package/dist/gateway/gateway/types.js +5 -0
  219. package/dist/gateway/gateway/types.js.map +1 -0
  220. package/dist/gateway/handlers/anthropic.d.ts +12 -0
  221. package/dist/gateway/handlers/anthropic.d.ts.map +1 -0
  222. package/dist/gateway/handlers/anthropic.js +254 -0
  223. package/dist/gateway/handlers/anthropic.js.map +1 -0
  224. package/dist/gateway/handlers/gemini.d.ts +12 -0
  225. package/dist/gateway/handlers/gemini.d.ts.map +1 -0
  226. package/dist/gateway/handlers/gemini.js +101 -0
  227. package/dist/gateway/handlers/gemini.js.map +1 -0
  228. package/dist/gateway/handlers/models.d.ts +4 -0
  229. package/dist/gateway/handlers/models.d.ts.map +1 -0
  230. package/dist/gateway/handlers/models.js +36 -0
  231. package/dist/gateway/handlers/models.js.map +1 -0
  232. package/dist/gateway/handlers/openai.d.ts +16 -0
  233. package/dist/gateway/handlers/openai.d.ts.map +1 -0
  234. package/dist/gateway/handlers/openai.js +254 -0
  235. package/dist/gateway/handlers/openai.js.map +1 -0
  236. package/dist/gateway/index.d.ts +27 -0
  237. package/dist/gateway/index.d.ts.map +1 -0
  238. package/dist/gateway/index.js +293 -0
  239. package/dist/gateway/index.js.map +1 -0
  240. package/dist/gateway/mapping-store.d.ts +38 -0
  241. package/dist/gateway/mapping-store.d.ts.map +1 -0
  242. package/dist/gateway/mapping-store.js +74 -0
  243. package/dist/gateway/mapping-store.js.map +1 -0
  244. package/dist/gateway/restorer.d.ts +63 -0
  245. package/dist/gateway/restorer.d.ts.map +1 -0
  246. package/dist/gateway/restorer.js +284 -0
  247. package/dist/gateway/restorer.js.map +1 -0
  248. package/dist/gateway/sanitizer.d.ts +17 -0
  249. package/dist/gateway/sanitizer.d.ts.map +1 -0
  250. package/dist/gateway/sanitizer.js +228 -0
  251. package/dist/gateway/sanitizer.js.map +1 -0
  252. package/dist/gateway/types.d.ts +53 -0
  253. package/dist/gateway/types.d.ts.map +1 -0
  254. package/dist/gateway/types.js +5 -0
  255. package/dist/gateway/types.js.map +1 -0
  256. package/dist/index.d.ts +19 -0
  257. package/dist/index.d.ts.map +1 -0
  258. package/dist/index.js +2084 -0
  259. package/dist/index.js.map +1 -0
  260. package/dist/memory/index.d.ts +5 -0
  261. package/dist/memory/index.d.ts.map +1 -0
  262. package/dist/memory/index.js +5 -0
  263. package/dist/memory/index.js.map +1 -0
  264. package/dist/memory/store.d.ts +82 -0
  265. package/dist/memory/store.d.ts.map +1 -0
  266. package/dist/memory/store.js +194 -0
  267. package/dist/memory/store.js.map +1 -0
  268. package/dist/platform-client/index.d.ts +63 -0
  269. package/dist/platform-client/index.d.ts.map +1 -0
  270. package/dist/platform-client/index.js +294 -0
  271. package/dist/platform-client/index.js.map +1 -0
  272. package/dist/platform-client/types.d.ts +109 -0
  273. package/dist/platform-client/types.d.ts.map +1 -0
  274. package/dist/platform-client/types.js +3 -0
  275. package/dist/platform-client/types.js.map +1 -0
  276. package/gateway/activity.d.ts +52 -0
  277. package/gateway/activity.d.ts.map +1 -0
  278. package/gateway/activity.js +111 -0
  279. package/gateway/activity.js.map +1 -0
  280. package/gateway/config.d.ts +50 -0
  281. package/gateway/config.d.ts.map +1 -0
  282. package/gateway/config.js +200 -0
  283. package/gateway/config.js.map +1 -0
  284. package/gateway/handlers/anthropic.d.ts +12 -0
  285. package/gateway/handlers/anthropic.d.ts.map +1 -0
  286. package/gateway/handlers/anthropic.js +254 -0
  287. package/gateway/handlers/anthropic.js.map +1 -0
  288. package/gateway/handlers/gemini.d.ts +12 -0
  289. package/gateway/handlers/gemini.d.ts.map +1 -0
  290. package/gateway/handlers/gemini.js +101 -0
  291. package/gateway/handlers/gemini.js.map +1 -0
  292. package/gateway/handlers/models.d.ts +4 -0
  293. package/gateway/handlers/models.d.ts.map +1 -0
  294. package/gateway/handlers/models.js +36 -0
  295. package/gateway/handlers/models.js.map +1 -0
  296. package/gateway/handlers/openai.d.ts +16 -0
  297. package/gateway/handlers/openai.d.ts.map +1 -0
  298. package/gateway/handlers/openai.js +254 -0
  299. package/gateway/handlers/openai.js.map +1 -0
  300. package/gateway/index.d.ts +27 -0
  301. package/gateway/index.d.ts.map +1 -0
  302. package/gateway/index.js +293 -0
  303. package/gateway/index.js.map +1 -0
  304. package/gateway/mapping-store.d.ts +38 -0
  305. package/gateway/mapping-store.d.ts.map +1 -0
  306. package/gateway/mapping-store.js +74 -0
  307. package/gateway/mapping-store.js.map +1 -0
  308. package/gateway/restorer.d.ts +63 -0
  309. package/gateway/restorer.d.ts.map +1 -0
  310. package/gateway/restorer.js +284 -0
  311. package/gateway/restorer.js.map +1 -0
  312. package/gateway/sanitizer.d.ts +17 -0
  313. package/gateway/sanitizer.d.ts.map +1 -0
  314. package/gateway/sanitizer.js +228 -0
  315. package/gateway/sanitizer.js.map +1 -0
  316. package/gateway/types.d.ts +53 -0
  317. package/gateway/types.d.ts.map +1 -0
  318. package/gateway/types.js +5 -0
  319. package/gateway/types.js.map +1 -0
  320. package/openclaw.plugin.json +86 -0
  321. package/package.json +74 -0
  322. package/samples/Untitled +1 -0
  323. package/samples/clean-email.txt +20 -0
  324. package/samples/test-document.md +53 -0
  325. package/samples/test-email-popup.txt +44 -0
  326. package/samples/test-email.txt +32 -0
  327. package/samples/test-webpage.html +51 -0
  328. package/scripts/enterprise-enroll.sh +89 -0
  329. package/scripts/enterprise-unenroll.sh +75 -0
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Gateway configuration management
3
+ */
4
+ import { readFileSync, existsSync } from "node:fs";
5
+ import { homedir } from "node:os";
6
+ import { join } from "node:path";
7
+ const DEFAULT_CONFIG_PATH = join(homedir(), ".openclaw", "extensions", "moltguard", "data", "gateway.json");
8
+ /**
9
+ * Load gateway configuration from file or environment
10
+ */
11
+ export function loadConfig(configPath) {
12
+ const path = configPath || DEFAULT_CONFIG_PATH;
13
+ // Default configuration
14
+ const defaultConfig = {
15
+ port: parseInt(process.env.GATEWAY_PORT || "53669", 10),
16
+ backends: {},
17
+ };
18
+ // Try to load from file
19
+ if (existsSync(path)) {
20
+ try {
21
+ const fileContent = readFileSync(path, "utf-8");
22
+ const fileConfig = JSON.parse(fileContent);
23
+ return mergeConfig(defaultConfig, fileConfig);
24
+ }
25
+ catch (error) {
26
+ console.warn(`[ai-security-gateway] Failed to load config from ${path}:`, error);
27
+ }
28
+ }
29
+ // Load from environment variables
30
+ return loadFromEnv(defaultConfig);
31
+ }
32
+ /**
33
+ * Load backend configs from environment variables
34
+ */
35
+ function loadFromEnv(config) {
36
+ // Anthropic
37
+ if (process.env.ANTHROPIC_API_KEY) {
38
+ config.backends.anthropic = {
39
+ baseUrl: process.env.ANTHROPIC_BASE_URL || "https://api.anthropic.com",
40
+ apiKey: process.env.ANTHROPIC_API_KEY,
41
+ type: "anthropic",
42
+ };
43
+ }
44
+ // OpenAI
45
+ if (process.env.OPENAI_API_KEY) {
46
+ config.backends.openai = {
47
+ baseUrl: process.env.OPENAI_BASE_URL || "https://api.openai.com",
48
+ apiKey: process.env.OPENAI_API_KEY,
49
+ type: "openai",
50
+ };
51
+ }
52
+ // Kimi (Moonshot) — only set if openai backend not already configured
53
+ if ((process.env.KIMI_API_KEY || process.env.MOONSHOT_API_KEY) &&
54
+ !config.backends.openai) {
55
+ config.backends.kimi = {
56
+ baseUrl: process.env.KIMI_BASE_URL || "https://api.moonshot.cn",
57
+ apiKey: process.env.KIMI_API_KEY || process.env.MOONSHOT_API_KEY || "",
58
+ type: "openai",
59
+ };
60
+ }
61
+ // Gemini
62
+ if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) {
63
+ config.backends.gemini = {
64
+ baseUrl: process.env.GEMINI_BASE_URL ||
65
+ "https://generativelanguage.googleapis.com",
66
+ apiKey: process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY || "",
67
+ type: "gemini",
68
+ };
69
+ }
70
+ // OpenRouter
71
+ if (process.env.OPENROUTER_API_KEY) {
72
+ config.backends.openrouter = {
73
+ baseUrl: process.env.OPENROUTER_BASE_URL || "https://openrouter.ai/api",
74
+ apiKey: process.env.OPENROUTER_API_KEY,
75
+ type: "openai",
76
+ ...(process.env.OPENROUTER_REFERER && {
77
+ referer: process.env.OPENROUTER_REFERER,
78
+ }),
79
+ ...(process.env.OPENROUTER_TITLE && {
80
+ title: process.env.OPENROUTER_TITLE,
81
+ }),
82
+ };
83
+ }
84
+ return config;
85
+ }
86
+ /**
87
+ * Merge file config with default config
88
+ */
89
+ function mergeConfig(defaultConfig, fileConfig) {
90
+ return {
91
+ port: fileConfig.port ?? defaultConfig.port,
92
+ backends: {
93
+ ...defaultConfig.backends,
94
+ ...fileConfig.backends,
95
+ },
96
+ routing: fileConfig.routing,
97
+ defaultBackends: fileConfig.defaultBackends,
98
+ };
99
+ }
100
+ /**
101
+ * Validate configuration
102
+ */
103
+ export function validateConfig(config) {
104
+ if (config.port < 1 || config.port > 65535) {
105
+ throw new Error(`Invalid port: ${config.port}`);
106
+ }
107
+ // Note: Backends are now optional. Gateway will act as transparent proxy.
108
+ // If no backends configured, gateway will forward requests based on routing rules
109
+ // or pass through to the original target.
110
+ // Validate each backend (if any)
111
+ for (const [name, backend] of Object.entries(config.backends)) {
112
+ if (!backend.baseUrl) {
113
+ throw new Error(`Backend ${name} missing baseUrl`);
114
+ }
115
+ if (!backend.apiKey) {
116
+ throw new Error(`Backend ${name} missing apiKey`);
117
+ }
118
+ }
119
+ }
120
+ /**
121
+ * Infer API type from backend name
122
+ */
123
+ export function inferApiType(name) {
124
+ const lower = name.toLowerCase();
125
+ if (lower.includes("anthropic") || lower.includes("claude")) {
126
+ return "anthropic";
127
+ }
128
+ if (lower.includes("gemini") || lower.includes("google")) {
129
+ return "gemini";
130
+ }
131
+ // Default to OpenAI-compatible for everything else
132
+ return "openai";
133
+ }
134
+ /**
135
+ * Get API type for a backend
136
+ */
137
+ export function getBackendApiType(name, config) {
138
+ const backend = config.backends[name];
139
+ if (backend?.type) {
140
+ return backend.type;
141
+ }
142
+ return inferApiType(name);
143
+ }
144
+ /**
145
+ * Find backend by API key
146
+ */
147
+ export function findBackendByApiKey(apiKey, config) {
148
+ for (const [name, backend] of Object.entries(config.backends)) {
149
+ if (backend.apiKey === apiKey) {
150
+ return { name, backend };
151
+ }
152
+ }
153
+ return null;
154
+ }
155
+ /**
156
+ * Find default backend for an API type
157
+ */
158
+ export function findDefaultBackend(apiType, config) {
159
+ // Check explicit default first
160
+ const defaultName = config.defaultBackends?.[apiType];
161
+ if (defaultName && config.backends[defaultName]) {
162
+ return { name: defaultName, backend: config.backends[defaultName] };
163
+ }
164
+ // Find first backend matching the API type
165
+ for (const [name, backend] of Object.entries(config.backends)) {
166
+ if (getBackendApiType(name, config) === apiType) {
167
+ return { name, backend };
168
+ }
169
+ }
170
+ return null;
171
+ }
172
+ /**
173
+ * Find backend by request path prefix
174
+ * Matches the longest pathPrefix that is a prefix of the request path
175
+ */
176
+ export function findBackendByPathPrefix(requestPath, config) {
177
+ let bestMatch = null;
178
+ let bestMatchLength = 0;
179
+ for (const [name, backend] of Object.entries(config.backends)) {
180
+ if (backend.pathPrefix && requestPath.startsWith(backend.pathPrefix)) {
181
+ if (backend.pathPrefix.length > bestMatchLength) {
182
+ bestMatch = { name, backend };
183
+ bestMatchLength = backend.pathPrefix.length;
184
+ }
185
+ }
186
+ }
187
+ return bestMatch;
188
+ }
189
+ /**
190
+ * Find backend by model name
191
+ */
192
+ export function findBackendByModel(modelName, config) {
193
+ for (const [name, backend] of Object.entries(config.backends)) {
194
+ if (backend.models?.includes(modelName)) {
195
+ return { name, backend };
196
+ }
197
+ }
198
+ return null;
199
+ }
200
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * AI Security Gateway - Anthropic Messages API handler
3
+ *
4
+ * Handles POST /v1/messages requests in Anthropic's native format.
5
+ */
6
+ import type { IncomingMessage, ServerResponse } from "node:http";
7
+ import type { BackendConfig } from "../types.js";
8
+ /**
9
+ * Handle Anthropic API request
10
+ */
11
+ export declare function handleAnthropicRequest(req: IncomingMessage, res: ServerResponse, backend: BackendConfig): Promise<void>;
12
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/handlers/anthropic.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAC;AAK/D;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAwGf"}
@@ -0,0 +1,254 @@
1
+ /**
2
+ * AI Security Gateway - Anthropic Messages API handler
3
+ *
4
+ * Handles POST /v1/messages requests in Anthropic's native format.
5
+ */
6
+ import { sanitize } from "../sanitizer.js";
7
+ import { restore, createStreamRestorer } from "../restorer.js";
8
+ import { generateRequestId, logSanitizeEvent, logRestoreEvent } from "../activity.js";
9
+ /**
10
+ * Handle Anthropic API request
11
+ */
12
+ export async function handleAnthropicRequest(req, res, backend) {
13
+ try {
14
+ const requestId = generateRequestId();
15
+ const sanitizeStart = Date.now();
16
+ // 1. Parse request body
17
+ const body = await readBody(req);
18
+ const requestData = JSON.parse(body);
19
+ const { model, messages, system, tools, max_tokens, temperature, stream = false, ...rest } = requestData;
20
+ // 2. Sanitize messages
21
+ const { sanitized: sanitizedMessages, mappingTable, redactionCount } = sanitize(messages);
22
+ // 3. Sanitize system prompt if present
23
+ let systemRedactionCount = 0;
24
+ const sanitizedSystem = system
25
+ ? (() => {
26
+ const result = sanitize(system);
27
+ systemRedactionCount = result.redactionCount;
28
+ return result.sanitized;
29
+ })()
30
+ : system;
31
+ const totalRedactionCount = redactionCount + systemRedactionCount;
32
+ // Log sanitization event
33
+ if (totalRedactionCount > 0) {
34
+ logSanitizeEvent({
35
+ requestId,
36
+ backend: "anthropic",
37
+ endpoint: "/v1/messages",
38
+ model,
39
+ mappingTable,
40
+ redactionCount: totalRedactionCount,
41
+ durationMs: Date.now() - sanitizeStart,
42
+ });
43
+ }
44
+ // Note: We reuse the same mapping table so placeholders are consistent
45
+ // Debug: log what was sanitized
46
+ if (totalRedactionCount > 0) {
47
+ console.log(`[ai-security-gateway] Sanitized ${totalRedactionCount} items`);
48
+ }
49
+ // 4. Build sanitized request
50
+ const sanitizedRequest = {
51
+ model,
52
+ messages: sanitizedMessages,
53
+ ...(system && { system: sanitizedSystem }),
54
+ ...(tools && { tools }),
55
+ max_tokens,
56
+ ...(temperature !== undefined && { temperature }),
57
+ stream,
58
+ ...rest,
59
+ };
60
+ // 5. Forward to real Anthropic API
61
+ // Note: baseUrl already includes the full path prefix (e.g., /v1)
62
+ const apiUrl = `${backend.baseUrl}/messages`;
63
+ const response = await fetch(apiUrl, {
64
+ method: "POST",
65
+ headers: {
66
+ "Content-Type": "application/json",
67
+ "anthropic-version": req.headers["anthropic-version"] || "2023-06-01",
68
+ "x-api-key": backend.apiKey,
69
+ },
70
+ body: JSON.stringify(sanitizedRequest),
71
+ });
72
+ if (!response.ok) {
73
+ // Forward error response
74
+ res.writeHead(response.status, { "Content-Type": "application/json" });
75
+ const errorBody = await response.text();
76
+ res.end(errorBody);
77
+ return;
78
+ }
79
+ // 7. Handle streaming or non-streaming response
80
+ if (stream) {
81
+ await handleAnthropicStream(response, res, mappingTable, requestId, model);
82
+ }
83
+ else {
84
+ await handleAnthropicNonStream(response, res, mappingTable, requestId, model);
85
+ }
86
+ }
87
+ catch (error) {
88
+ console.error("[ai-security-gateway] Anthropic handler error:", error);
89
+ res.writeHead(500, { "Content-Type": "application/json" });
90
+ res.end(JSON.stringify({
91
+ error: "Internal gateway error",
92
+ message: error instanceof Error ? error.message : String(error),
93
+ }));
94
+ }
95
+ }
96
+ /**
97
+ * Handle streaming response with smart placeholder restoration
98
+ *
99
+ * Uses StreamRestorer to detect `__` and buffer potential placeholders.
100
+ * Only buffers when necessary, maintaining streaming UX.
101
+ */
102
+ async function handleAnthropicStream(response, res, mappingTable, requestId, model) {
103
+ const restoreStart = Date.now();
104
+ // Debug: log mapping table size
105
+ if (mappingTable.size > 0) {
106
+ console.log(`[ai-security-gateway] Streaming with ${mappingTable.size} placeholders to restore`);
107
+ }
108
+ // Set SSE headers
109
+ res.writeHead(200, {
110
+ "Content-Type": "text/event-stream",
111
+ "Cache-Control": "no-cache",
112
+ "Connection": "keep-alive",
113
+ });
114
+ const reader = response.body?.getReader();
115
+ if (!reader) {
116
+ res.end();
117
+ return;
118
+ }
119
+ const decoder = new TextDecoder();
120
+ let lineBuffer = "";
121
+ // Create stream restorer for text content
122
+ const streamRestorer = createStreamRestorer(mappingTable);
123
+ try {
124
+ while (true) {
125
+ const { done, value } = await reader.read();
126
+ if (done)
127
+ break;
128
+ // Decode chunk
129
+ lineBuffer += decoder.decode(value, { stream: true });
130
+ // Process complete lines
131
+ const lines = lineBuffer.split("\n");
132
+ lineBuffer = lines.pop() || ""; // Keep incomplete line in buffer
133
+ for (const line of lines) {
134
+ if (!line.trim()) {
135
+ res.write("\n");
136
+ continue;
137
+ }
138
+ // Handle event lines (pass through)
139
+ if (line.startsWith("event:")) {
140
+ res.write(line + "\n");
141
+ continue;
142
+ }
143
+ // Handle data lines
144
+ if (!line.startsWith("data: ")) {
145
+ res.write(line + "\n");
146
+ continue;
147
+ }
148
+ const dataContent = line.slice(6);
149
+ try {
150
+ const parsed = JSON.parse(dataContent);
151
+ // Check for text delta
152
+ if (parsed.type === "content_block_delta" && parsed.delta?.type === "text_delta") {
153
+ const textContent = parsed.delta.text;
154
+ if (textContent !== undefined && mappingTable.size > 0) {
155
+ // Process text through stream restorer
156
+ const restored = streamRestorer.process(textContent);
157
+ if (restored.length > 0) {
158
+ // We have restorable content - output it
159
+ const restoredChunk = {
160
+ ...parsed,
161
+ delta: { ...parsed.delta, text: restored },
162
+ };
163
+ res.write(`data: ${JSON.stringify(restoredChunk)}\n`);
164
+ }
165
+ // If restorer is buffering, don't output anything yet
166
+ }
167
+ else {
168
+ // No text content or no mappings - pass through
169
+ res.write(line + "\n");
170
+ }
171
+ }
172
+ else {
173
+ // Non-text events - pass through
174
+ res.write(line + "\n");
175
+ }
176
+ }
177
+ catch {
178
+ // Not valid JSON, pass through
179
+ res.write(line + "\n");
180
+ }
181
+ }
182
+ }
183
+ // Write any remaining line buffer
184
+ if (lineBuffer.trim()) {
185
+ res.write(lineBuffer + "\n");
186
+ }
187
+ // Finalize stream restorer - flush any remaining buffered content
188
+ const finalContent = streamRestorer.finalize();
189
+ if (finalContent.length > 0) {
190
+ // Create a final text delta chunk with remaining content
191
+ const finalChunk = {
192
+ type: "content_block_delta",
193
+ index: 0,
194
+ delta: { type: "text_delta", text: finalContent },
195
+ };
196
+ res.write(`data: ${JSON.stringify(finalChunk)}\n`);
197
+ }
198
+ // Log restoration event
199
+ if (mappingTable.size > 0) {
200
+ logRestoreEvent({
201
+ requestId,
202
+ backend: "anthropic",
203
+ endpoint: "/v1/messages",
204
+ model,
205
+ mappingTable,
206
+ restorationCount: mappingTable.size,
207
+ durationMs: Date.now() - restoreStart,
208
+ });
209
+ }
210
+ res.end();
211
+ }
212
+ catch (error) {
213
+ console.error("[ai-security-gateway] Stream error:", error);
214
+ res.end();
215
+ }
216
+ }
217
+ /**
218
+ * Handle non-streaming response
219
+ */
220
+ async function handleAnthropicNonStream(response, res, mappingTable, requestId, model) {
221
+ const restoreStart = Date.now();
222
+ const responseBody = await response.text();
223
+ const responseData = JSON.parse(responseBody);
224
+ // Restore placeholders in response
225
+ const restoredData = restore(responseData, mappingTable);
226
+ // Log restoration event
227
+ if (mappingTable.size > 0) {
228
+ logRestoreEvent({
229
+ requestId,
230
+ backend: "anthropic",
231
+ endpoint: "/v1/messages",
232
+ model,
233
+ mappingTable,
234
+ restorationCount: mappingTable.size,
235
+ durationMs: Date.now() - restoreStart,
236
+ });
237
+ }
238
+ res.writeHead(200, { "Content-Type": "application/json" });
239
+ res.end(JSON.stringify(restoredData));
240
+ }
241
+ /**
242
+ * Read request body as string
243
+ */
244
+ function readBody(req) {
245
+ return new Promise((resolve, reject) => {
246
+ let body = "";
247
+ req.on("data", (chunk) => {
248
+ body += chunk.toString();
249
+ });
250
+ req.on("end", () => resolve(body));
251
+ req.on("error", reject);
252
+ });
253
+ }
254
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/handlers/anthropic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * AI Security Gateway - Google Gemini API handler
3
+ *
4
+ * Handles POST /v1/models/:model:generateContent requests in Gemini's format.
5
+ */
6
+ import type { IncomingMessage, ServerResponse } from "node:http";
7
+ import type { BackendConfig } from "../types.js";
8
+ /**
9
+ * Handle Gemini API request
10
+ */
11
+ export declare function handleGeminiRequest(req: IncomingMessage, res: ServerResponse, backend: BackendConfig, modelName: string): Promise<void>;
12
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/handlers/gemini.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAC;AAK/D;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAuFf"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * AI Security Gateway - Google Gemini API handler
3
+ *
4
+ * Handles POST /v1/models/:model:generateContent requests in Gemini's format.
5
+ */
6
+ import { sanitize } from "../sanitizer.js";
7
+ import { restore } from "../restorer.js";
8
+ import { generateRequestId, logSanitizeEvent, logRestoreEvent } from "../activity.js";
9
+ /**
10
+ * Handle Gemini API request
11
+ */
12
+ export async function handleGeminiRequest(req, res, backend, modelName) {
13
+ try {
14
+ const requestId = generateRequestId();
15
+ const sanitizeStart = Date.now();
16
+ // 1. Parse request body
17
+ const body = await readBody(req);
18
+ const requestData = JSON.parse(body);
19
+ const { contents, tools, generationConfig, ...rest } = requestData;
20
+ // 2. Sanitize contents (Gemini uses "contents" instead of "messages")
21
+ const { sanitized: sanitizedContents, mappingTable, redactionCount } = sanitize(contents);
22
+ // Log sanitization event
23
+ if (redactionCount > 0) {
24
+ logSanitizeEvent({
25
+ requestId,
26
+ backend: "gemini",
27
+ endpoint: `/v1/models/${modelName}:generateContent`,
28
+ model: modelName,
29
+ mappingTable,
30
+ redactionCount,
31
+ durationMs: Date.now() - sanitizeStart,
32
+ });
33
+ }
34
+ // 3. Build sanitized request
35
+ const sanitizedRequest = {
36
+ contents: sanitizedContents,
37
+ ...(tools && { tools }),
38
+ ...(generationConfig && { generationConfig }),
39
+ ...rest,
40
+ };
41
+ // 4. Forward to Gemini API
42
+ const apiUrl = `${backend.baseUrl}/v1/models/${modelName}:generateContent`;
43
+ const response = await fetch(apiUrl, {
44
+ method: "POST",
45
+ headers: {
46
+ "Content-Type": "application/json",
47
+ "x-goog-api-key": backend.apiKey,
48
+ },
49
+ body: JSON.stringify(sanitizedRequest),
50
+ });
51
+ if (!response.ok) {
52
+ // Forward error response
53
+ res.writeHead(response.status, { "Content-Type": "application/json" });
54
+ const errorBody = await response.text();
55
+ res.end(errorBody);
56
+ return;
57
+ }
58
+ // 6. Handle response (Gemini typically doesn't stream in same way)
59
+ const restoreStart = Date.now();
60
+ const responseBody = await response.text();
61
+ const responseData = JSON.parse(responseBody);
62
+ // Restore placeholders in response
63
+ const restoredData = restore(responseData, mappingTable);
64
+ // Log restoration event
65
+ if (mappingTable.size > 0) {
66
+ logRestoreEvent({
67
+ requestId,
68
+ backend: "gemini",
69
+ endpoint: `/v1/models/${modelName}:generateContent`,
70
+ model: modelName,
71
+ mappingTable,
72
+ restorationCount: mappingTable.size,
73
+ durationMs: Date.now() - restoreStart,
74
+ });
75
+ }
76
+ res.writeHead(200, { "Content-Type": "application/json" });
77
+ res.end(JSON.stringify(restoredData));
78
+ }
79
+ catch (error) {
80
+ console.error("[ai-security-gateway] Gemini handler error:", error);
81
+ res.writeHead(500, { "Content-Type": "application/json" });
82
+ res.end(JSON.stringify({
83
+ error: "Internal gateway error",
84
+ message: error instanceof Error ? error.message : String(error),
85
+ }));
86
+ }
87
+ }
88
+ /**
89
+ * Read request body as string
90
+ */
91
+ function readBody(req) {
92
+ return new Promise((resolve, reject) => {
93
+ let body = "";
94
+ req.on("data", (chunk) => {
95
+ body += chunk.toString();
96
+ });
97
+ req.on("end", () => resolve(body));
98
+ req.on("error", reject);
99
+ });
100
+ }
101
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/handlers/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ServerResponse } from "node:http";
2
+ import type { GatewayConfig } from "../types.js";
3
+ export declare function handleModelsRequest(res: ServerResponse, config: GatewayConfig): Promise<void>;
4
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/handlers/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAqCf"}