@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 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap";:root{--bg: #12141a;--bg-accent: #14161d;--bg-elevated: #1a1d25;--bg-hover: #262a35;--bg-muted: #262a35;--card: #181b22;--card-foreground: #f4f4f5;--card-highlight: rgba(255, 255, 255, .05);--popover: #181b22;--popover-foreground: #f4f4f5;--panel: #12141a;--panel-strong: #1a1d25;--panel-hover: #262a35;--chrome: rgba(18, 20, 26, .95);--chrome-strong: rgba(18, 20, 26, .98);--text: #e4e4e7;--text-strong: #fafafa;--muted: #71717a;--muted-strong: #52525b;--muted-foreground: #71717a;--border: #27272a;--border-strong: #3f3f46;--border-hover: #52525b;--input: #27272a;--ring: #2E5BFF;--accent: #2E5BFF;--accent-hover: #4A73FF;--accent-muted: #2E5BFF;--accent-subtle: rgba(46, 91, 255, .15);--accent-foreground: #fafafa;--accent-glow: rgba(46, 91, 255, .25);--primary: #2E5BFF;--primary-foreground: #ffffff;--secondary: #1e2028;--secondary-foreground: #f4f4f5;--accent-2: #14b8a6;--accent-2-muted: rgba(20, 184, 166, .7);--accent-2-subtle: rgba(20, 184, 166, .15);--ok: #22c55e;--ok-muted: rgba(34, 197, 94, .75);--ok-subtle: rgba(34, 197, 94, .12);--destructive: #ef4444;--destructive-foreground: #fafafa;--warn: #f59e0b;--warn-muted: rgba(245, 158, 11, .75);--warn-subtle: rgba(245, 158, 11, .12);--danger: #ef4444;--danger-muted: rgba(239, 68, 68, .75);--danger-subtle: rgba(239, 68, 68, .12);--info: #3b82f6;--focus: rgba(46, 91, 255, .25);--focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--ring);--focus-glow: 0 0 0 2px var(--bg), 0 0 0 4px var(--ring), 0 0 20px var(--accent-glow);--grid-line: rgba(255, 255, 255, .04);--theme-switch-x: 50%;--theme-switch-y: 50%;--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace;--font-body: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-display: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .2);--shadow-md: 0 4px 12px rgba(0, 0, 0, .25), 0 0 0 1px rgba(255, 255, 255, .03);--shadow-lg: 0 12px 28px rgba(0, 0, 0, .35), 0 0 0 1px rgba(255, 255, 255, .03);--shadow-xl: 0 24px 48px rgba(0, 0, 0, .4), 0 0 0 1px rgba(255, 255, 255, .03);--shadow-glow: 0 0 30px var(--accent-glow);--radius-sm: 6px;--radius-md: 8px;--radius-lg: 12px;--radius-xl: 16px;--radius-full: 9999px;--radius: 8px;--ease-out: cubic-bezier(.16, 1, .3, 1);--ease-in-out: cubic-bezier(.4, 0, .2, 1);--ease-spring: cubic-bezier(.34, 1.56, .64, 1);--duration-fast: .12s;--duration-normal: .2s;--duration-slow: .35s;color-scheme:dark}:root[data-theme=light]{--bg: #fafafa;--bg-accent: #f5f5f5;--bg-elevated: #ffffff;--bg-hover: #f0f0f0;--bg-muted: #f0f0f0;--bg-content: #f5f5f5;--card: #ffffff;--card-foreground: #18181b;--card-highlight: rgba(0, 0, 0, .03);--popover: #ffffff;--popover-foreground: #18181b;--panel: #fafafa;--panel-strong: #f5f5f5;--panel-hover: #ebebeb;--chrome: rgba(250, 250, 250, .95);--chrome-strong: rgba(250, 250, 250, .98);--text: #3f3f46;--text-strong: #18181b;--muted: #71717a;--muted-strong: #52525b;--muted-foreground: #71717a;--border: #e4e4e7;--border-strong: #d4d4d8;--border-hover: #a1a1aa;--input: #e4e4e7;--accent: #1E40AF;--accent-hover: #2563EB;--accent-muted: #1E40AF;--accent-subtle: rgba(30, 64, 175, .12);--accent-foreground: #ffffff;--accent-glow: rgba(30, 64, 175, .15);--primary: #1E40AF;--primary-foreground: #ffffff;--secondary: #f4f4f5;--secondary-foreground: #3f3f46;--accent-2: #0d9488;--accent-2-muted: rgba(13, 148, 136, .75);--accent-2-subtle: rgba(13, 148, 136, .12);--ok: #16a34a;--ok-muted: rgba(22, 163, 74, .75);--ok-subtle: rgba(22, 163, 74, .1);--destructive: #dc2626;--destructive-foreground: #fafafa;--warn: #d97706;--warn-muted: rgba(217, 119, 6, .75);--warn-subtle: rgba(217, 119, 6, .1);--danger: #dc2626;--danger-muted: rgba(220, 38, 38, .75);--danger-subtle: rgba(220, 38, 38, .1);--info: #2563eb;--focus: rgba(30, 64, 175, .2);--focus-glow: 0 0 0 2px var(--bg), 0 0 0 4px var(--ring), 0 0 16px var(--accent-glow);--grid-line: rgba(0, 0, 0, .05);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .06);--shadow-md: 0 4px 12px rgba(0, 0, 0, .08), 0 0 0 1px rgba(0, 0, 0, .04);--shadow-lg: 0 12px 28px rgba(0, 0, 0, .12), 0 0 0 1px rgba(0, 0, 0, .04);--shadow-xl: 0 24px 48px rgba(0, 0, 0, .15), 0 0 0 1px rgba(0, 0, 0, .04);--shadow-glow: 0 0 24px var(--accent-glow);color-scheme:light}*{box-sizing:border-box}html,body{height:100%}body{margin:0;font:400 14px/1.55 var(--font-body);letter-spacing:-.02em;background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#root{min-height:100vh}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}button,input,textarea,select{font:inherit;color:inherit}::selection{background:var(--accent-subtle);color:var(--text-strong)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius-full)}::-webkit-scrollbar-thumb:hover{background:var(--border-strong)}@keyframes rise{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes scale-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes dashboard-enter{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}@keyframes pulse-subtle{0%,to{opacity:1}50%{opacity:.7}}@keyframes glow-pulse{0%,to{box-shadow:0 0 #2e5bff00}50%{box-shadow:0 0 20px var(--accent-glow)}}.stagger-1{animation-delay:0ms}.stagger-2{animation-delay:50ms}.stagger-3{animation-delay:.1s}.stagger-4{animation-delay:.15s}.stagger-5{animation-delay:.2s}.stagger-6{animation-delay:.25s}:focus-visible{outline:none;box-shadow:var(--focus-ring)}.shell{--shell-pad: 16px;--shell-gap: 16px;--shell-nav-width: 220px;--shell-topbar-height: 56px;height:100vh;display:grid;grid-template-columns:var(--shell-nav-width) minmax(0,1fr);grid-template-rows:var(--shell-topbar-height) 1fr;grid-template-areas:"topbar topbar" "nav content";gap:0;animation:dashboard-enter .4s var(--ease-out);overflow:hidden}@supports (height: 100dvh){.shell{height:100dvh}}.topbar{grid-area:topbar;position:sticky;top:0;z-index:40;display:flex;justify-content:space-between;align-items:center;gap:16px;padding:0 20px;height:var(--shell-topbar-height);border-bottom:1px solid var(--border);background:var(--bg)}.topbar-left{display:flex;align-items:center;gap:12px}.brand{display:flex;align-items:center;gap:10px;text-decoration:none}.brand:hover{text-decoration:none}.brand-logo{width:28px;height:28px;flex-shrink:0}.brand-logo img{width:100%;height:100%;object-fit:contain}.brand-text{display:flex;flex-direction:column;gap:1px}.brand-title{font-size:16px;font-weight:700;letter-spacing:-.03em;line-height:1.1;color:var(--text-strong)}.brand-sub{font-size:10px;font-weight:500;color:var(--muted);letter-spacing:.05em;text-transform:uppercase;line-height:1}.topbar-status{display:flex;align-items:center;gap:8px}.topbar-status .pill{padding:6px 10px;gap:6px;font-size:12px;font-weight:500;height:32px;box-sizing:border-box}.topbar-status .statusDot{width:6px;height:6px}.topbar-status .theme-toggle{--theme-item: 24px;--theme-gap: 2px;--theme-pad: 3px}.topbar-status .theme-icon{width:12px;height:12px}.nav{grid-area:nav;overflow-y:auto;overflow-x:hidden;padding:16px 12px;background:var(--bg);scrollbar-width:none;min-height:0}.nav::-webkit-scrollbar{display:none}.nav-group{margin-bottom:20px;display:grid;gap:2px}.nav-group:last-child{margin-bottom:0}.nav-group__items{display:grid;gap:1px}.nav-label{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;font-size:11px;font-weight:500;color:var(--muted);margin-bottom:4px;background:transparent;border:none;text-align:left;text-transform:uppercase;letter-spacing:.04em}.nav-item{position:relative;display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:var(--radius-md);border:1px solid transparent;background:transparent;color:var(--muted);cursor:pointer;text-decoration:none;transition:border-color var(--duration-fast) ease,background var(--duration-fast) ease,color var(--duration-fast) ease}.nav-item__icon{width:16px;height:16px;display:flex;align-items:center;justify-content:center;flex-shrink:0;opacity:.7;transition:opacity var(--duration-fast) ease}.nav-item__text{font-size:13px;font-weight:500;white-space:nowrap}.nav-item:hover{color:var(--text);background:var(--bg-hover);text-decoration:none}.nav-item:hover .nav-item__icon{opacity:1}.nav-item.active{color:var(--text-strong);background:var(--accent-subtle)}.nav-item.active .nav-item__icon{opacity:1;color:var(--accent)}.content{grid-area:content;padding:12px 16px 32px;display:block;min-height:0;overflow-y:auto;overflow-x:hidden}.content>*+*{margin-top:24px}:root[data-theme=light] .content{background:var(--bg-content)}.content-header{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;padding:4px 8px}.page-title{font-size:26px;font-weight:700;letter-spacing:-.035em;line-height:1.15;color:var(--text-strong)}.page-sub{color:var(--muted);font-size:14px;font-weight:400;margin-top:6px;letter-spacing:-.01em}.page-meta{display:flex;gap:8px}.grid{display:grid;gap:20px}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.stat-grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}.row{display:flex;gap:12px;align-items:center}.stack{display:grid;gap:12px;grid-template-columns:minmax(0,1fr)}.filters{display:flex;flex-wrap:wrap;gap:8px;align-items:center}@media(max-width:1100px){.shell{--shell-pad: 12px;--shell-gap: 12px;grid-template-columns:1fr;grid-template-rows:auto auto 1fr;grid-template-areas:"topbar" "nav" "content"}.nav{position:static;max-height:none;display:flex;flex-direction:row;flex-wrap:nowrap;gap:4px;overflow-x:auto;border-bottom:1px solid var(--border);padding:10px 14px;-webkit-overflow-scrolling:touch}.nav-group,.nav-group__items{display:contents}.nav-label{display:none}.nav-item{padding:8px 14px;white-space:nowrap;flex-shrink:0}.grid-cols-2,.grid-cols-3{grid-template-columns:1fr}.topbar{position:static;padding:12px 14px;gap:10px}}@media(max-width:600px){.shell{--shell-pad: 8px;--shell-gap: 8px}.topbar{padding:10px 12px;gap:8px}.brand{flex:1;min-width:0}.brand-title{font-size:14px}.brand-sub{display:none}.topbar-status{gap:6px}.nav{padding:8px 10px;gap:4px}.nav-item{padding:6px 10px;font-size:12px}.content-header{display:none}.content{padding:4px 4px 16px;gap:12px}}@media(max-width:400px){.shell{--shell-pad: 4px}.topbar{padding:8px 10px}.brand-title{font-size:13px}.nav{padding:6px 8px}.nav-item{padding:6px 8px;font-size:11px}.content{padding:4px 4px 12px;gap:10px}}.card{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);padding:20px;animation:rise .35s var(--ease-out) backwards;transition:border-color var(--duration-normal) var(--ease-out),box-shadow var(--duration-normal) var(--ease-out),transform var(--duration-normal) var(--ease-out);box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.card:hover{border-color:var(--border-strong);box-shadow:var(--shadow-md),inset 0 1px 0 var(--card-highlight)}.card-title{font-size:15px;font-weight:600;letter-spacing:-.02em;color:var(--text-strong)}.card-sub{color:var(--muted);font-size:13px;margin-top:6px;line-height:1.5}.stat{background:var(--card);border-radius:var(--radius-md);padding:14px 16px;border:1px solid var(--border);transition:border-color var(--duration-normal) var(--ease-out),box-shadow var(--duration-normal) var(--ease-out);box-shadow:inset 0 1px 0 var(--card-highlight)}.stat:hover{border-color:var(--border-strong);box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.stat-label{color:var(--muted);font-size:11px;font-weight:500;text-transform:uppercase;letter-spacing:.04em}.stat-value{font-size:24px;font-weight:700;margin-top:6px;letter-spacing:-.03em;line-height:1.1}.stat-value.ok{color:var(--ok)}.stat-value.warn{color:var(--warn)}.stat-card{display:grid;gap:6px}.label{color:var(--muted);font-size:12px;font-weight:500}.pill{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--border);padding:6px 12px;border-radius:var(--radius-full);background:var(--secondary);font-size:13px;font-weight:500;transition:border-color var(--duration-fast) ease}.pill:hover{border-color:var(--border-strong)}.pill.danger{border-color:var(--danger-subtle);background:var(--danger-subtle);color:var(--danger)}.theme-toggle{--theme-item: 28px;--theme-gap: 2px;--theme-pad: 4px;position:relative}.theme-toggle__track{position:relative;display:grid;grid-template-columns:repeat(3,var(--theme-item));gap:var(--theme-gap);padding:var(--theme-pad);border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary)}.theme-toggle__indicator{position:absolute;top:50%;left:var(--theme-pad);width:var(--theme-item);height:var(--theme-item);border-radius:var(--radius-full);transform:translateY(-50%) translate(calc(var(--theme-index, 0) * (var(--theme-item) + var(--theme-gap))));background:var(--accent);transition:transform var(--duration-normal) var(--ease-out);z-index:0}.theme-toggle__button{height:var(--theme-item);width:var(--theme-item);display:grid;place-items:center;border:0;border-radius:var(--radius-full);background:transparent;color:var(--muted);cursor:pointer;position:relative;z-index:1;transition:color var(--duration-fast) ease}.theme-toggle__button:hover{color:var(--text)}.theme-toggle__button.active{color:var(--accent-foreground)}.theme-icon{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.statusDot{width:8px;height:8px;border-radius:var(--radius-full);background:var(--danger);box-shadow:0 0 8px #ef444480;animation:pulse-subtle 2s ease-in-out infinite}.statusDot.ok{background:var(--ok);box-shadow:0 0 8px #22c55e80;animation:none}.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:1px solid var(--border);background:var(--bg-elevated);padding:9px 16px;border-radius:var(--radius-md);font-size:13px;font-weight:500;letter-spacing:-.01em;cursor:pointer;transition:border-color var(--duration-fast) var(--ease-out),background var(--duration-fast) var(--ease-out),box-shadow var(--duration-fast) var(--ease-out),transform var(--duration-fast) var(--ease-out)}.btn:hover{background:var(--bg-hover);border-color:var(--border-strong);transform:translateY(-1px);box-shadow:var(--shadow-sm)}.btn:active{background:var(--secondary);transform:translateY(0);box-shadow:none}.btn.primary{border-color:var(--accent);background:var(--accent);color:var(--primary-foreground);box-shadow:0 1px 2px #0003}.btn.primary:hover{background:var(--accent-hover);border-color:var(--accent-hover);box-shadow:var(--shadow-md),0 0 20px var(--accent-glow)}.btn.active{border-color:var(--accent);background:var(--accent-subtle);color:var(--accent)}.btn.danger{border-color:transparent;background:var(--danger-subtle);color:var(--danger)}.btn.danger:hover{background:#ef444426}.btn--sm{padding:6px 10px;font-size:12px}.btn:disabled{opacity:.5;cursor:not-allowed}.field{display:grid;gap:6px}.field.full{grid-column:1 / -1}.field span{color:var(--muted);font-size:13px;font-weight:500}.field input,.field textarea,.field select{border:1px solid var(--input);background:var(--card);border-radius:var(--radius-md);padding:8px 12px;outline:none;box-shadow:inset 0 1px 0 var(--card-highlight);transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.field input:focus,.field textarea:focus,.field select:focus{border-color:var(--ring);box-shadow:var(--focus-ring)}.field input::placeholder,.field textarea::placeholder{color:var(--muted);opacity:.7}.callout{border-radius:var(--radius-md);padding:12px 16px;border:1px solid var(--border);background:var(--secondary);font-size:13px;line-height:1.5}.callout.info{border-color:#3b82f64d;background:#3b82f614;color:var(--info)}.callout.danger{border-color:var(--danger-subtle);background:var(--danger-subtle);color:var(--danger)}.callout.success{border-color:var(--ok-subtle);background:var(--ok-subtle);color:var(--ok)}.mono{font-family:var(--mono);font-size:12px}.list-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;align-items:center;padding:12px 14px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--card);transition:border-color var(--duration-fast) ease}.list-item:hover{border-color:var(--border-strong)}.list-title{font-weight:600;font-size:14px}.list-sub{color:var(--muted);font-size:12px;margin-top:2px}.list-meta{display:flex;gap:8px;align-items:center;min-width:fit-content}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--secondary);font-size:11px;font-weight:500}.chip.ok{color:var(--ok);border-color:var(--ok-subtle)}.chip.warn{color:var(--warn);border-color:var(--warn-subtle)}.chip.danger{color:var(--danger);border-color:var(--danger-subtle)}.agents-grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}.agent-card{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);padding:20px;cursor:pointer;transition:border-color var(--duration-normal) var(--ease-out),box-shadow var(--duration-normal) var(--ease-out),transform var(--duration-normal) var(--ease-out);box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight);animation:rise .35s var(--ease-out) backwards;text-decoration:none;color:inherit;display:block}.agent-card:hover{border-color:var(--accent);box-shadow:var(--shadow-md),inset 0 1px 0 var(--card-highlight);transform:translateY(-2px);text-decoration:none}.agent-card__header{display:flex;align-items:center;gap:14px}.agent-card__avatar{width:48px;height:48px;border-radius:50%;background:var(--accent-subtle);display:grid;place-items:center;font-size:22px;flex-shrink:0;overflow:hidden}.agent-card__avatar-img{width:100%;height:100%;object-fit:cover;border-radius:50%}.agent-card__info{min-width:0}.agent-card__name{font-size:16px;font-weight:700;letter-spacing:-.02em;color:var(--text-strong)}.agent-card__creature{color:var(--muted);font-size:12px;margin-top:2px}.agent-card__model{margin-top:12px;display:flex;align-items:center;gap:8px;font-family:var(--mono);font-size:12px;color:var(--muted)}.agent-card__channels{margin-top:8px;display:flex;flex-wrap:wrap;gap:4px}.agent-card__owner{margin-top:6px;font-size:12px;color:var(--muted)}.channel-pill{display:inline-flex;align-items:center;padding:1px 7px;border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary);font-size:10px;font-weight:500;color:var(--muted)}.agent-card__skills{margin-top:12px;display:flex;flex-wrap:wrap;gap:6px}.skill-pill{display:inline-flex;align-items:center;padding:3px 10px;border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary);font-size:11px;font-weight:500;color:var(--text)}.skill-pill.overflow{color:var(--muted);border-style:dashed}.agent-card__footer{margin-top:14px;display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--muted)}.profile-waterfall{display:grid;gap:20px;max-width:800px;animation:rise .35s var(--ease-out) backwards}.profile-hero{display:flex;align-items:center;gap:20px;border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);padding:28px 24px;box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.profile-hero__avatar{width:72px;height:72px;border-radius:50%;background:var(--accent-subtle);display:grid;place-items:center;font-size:32px;flex-shrink:0;border:3px solid var(--accent);overflow:hidden}.profile-hero__avatar-img{width:100%;height:100%;object-fit:cover;border-radius:50%}.profile-hero__info{min-width:0}.profile-hero__name{font-size:24px;font-weight:700;letter-spacing:-.03em;line-height:1.15;color:var(--text-strong);margin:0}.profile-hero__creature{color:var(--accent);font-size:14px;font-weight:500;margin-top:4px}.profile-hero__vibe{color:var(--muted);font-size:13px;margin-top:4px;font-style:italic}.profile-hero__model{margin-top:10px;color:var(--muted)}.profile-hero__owner{display:flex;align-items:center;gap:8px;margin-top:8px;font-size:13px}.profile-hero__owner-label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.profile-hero__owner-name{font-weight:500;color:var(--text-strong)}.profile-hero__owner-tz{display:inline-flex;align-items:center;padding:2px 8px;border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary);font-size:11px;font-weight:500;color:var(--muted)}.profile-hero__channels{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}.profile-card__path{margin-top:16px;padding:8px 12px;border-radius:var(--radius-md);background:var(--secondary);font-family:var(--mono);font-size:11px;color:var(--muted);word-break:break-all;text-align:left}.profile-section{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);padding:20px;box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.profile-section__title{font-size:14px;font-weight:600;color:var(--text-strong);margin-bottom:14px;text-transform:uppercase;letter-spacing:.04em}.profile-section__grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}.profile-section__pills{display:flex;flex-wrap:wrap;gap:8px}.profile-section__list{display:grid;gap:8px}.profile-section__list-item{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--secondary);font-size:13px}.profile-section__list-item .mono{color:var(--muted);font-size:11px}.profile-summary__content{margin-top:12px;padding:16px;border-radius:var(--radius-md);border:1px dashed var(--border-strong);background:var(--secondary);font-size:14px;line-height:1.65;color:var(--text);white-space:pre-wrap}.profile-summary__content.loading{background:linear-gradient(90deg,var(--secondary) 25%,var(--bg-hover) 50%,var(--secondary) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;min-height:80px}.profile-summary__empty{text-align:center;padding:24px;color:var(--muted)}.profile-back{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-size:13px;font-weight:500;text-decoration:none;margin-bottom:8px;transition:color var(--duration-fast) ease}.profile-back:hover{color:var(--accent);text-decoration:none}.identity-grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fill,minmax(380px,1fr))}.identity-card{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);padding:0;overflow:hidden;box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight);animation:rise .35s var(--ease-out) backwards;transition:border-color var(--duration-normal) var(--ease-out),box-shadow var(--duration-normal) var(--ease-out)}.identity-card:hover{border-color:var(--border-strong);box-shadow:var(--shadow-md),inset 0 1px 0 var(--card-highlight)}.identity-card__header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:16px 20px;border:none;background:transparent;cursor:pointer;text-align:left;color:inherit;transition:background var(--duration-fast) ease}.identity-card__header:hover{background:var(--bg-hover)}.identity-card__title{display:flex;align-items:baseline;gap:10px}.identity-card__name{font-size:16px;font-weight:700;letter-spacing:-.02em;color:var(--text-strong)}.identity-card__category{font-size:11px;color:var(--muted)}.identity-card__chevron{font-size:10px;color:var(--muted)}.identity-card__stats{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;padding:0 20px 14px}.identity-stat{display:flex;flex-direction:column;gap:2px}.identity-stat__label{font-size:10px;font-weight:500;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.identity-stat__value{font-size:14px;font-weight:600;color:var(--text-strong)}.identity-card__pills{padding:0 20px 14px;display:flex;flex-wrap:wrap;gap:6px}.identity-card__targets{padding:0 20px 16px;display:flex;flex-wrap:wrap;gap:6px}.identity-card__detail{border-top:1px solid var(--border);padding:16px 20px;display:grid;gap:16px;animation:rise .2s var(--ease-out)}.identity-detail__section{display:grid;gap:8px}.identity-detail__heading{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.identity-detail__agents{display:grid;gap:6px}.identity-agent-row{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--secondary);font-size:13px}.identity-agent-row__avatar{font-size:16px}.identity-agent-row__name{font-weight:500}.identity-detail__tools{display:grid;gap:4px}.identity-tool-row{display:flex;align-items:center;gap:10px;padding:6px 12px;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--secondary);font-size:12px}.identity-tool-row__count{margin-left:auto;color:var(--muted);font-family:var(--mono);font-size:11px}.ig-wrap{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--secondary);height:480px;overflow:hidden}.ig-wrap--empty{display:grid;place-items:center;background:transparent;border:none;height:auto}.ig-flow .react-flow__pane{cursor:grab}.ig-flow .react-flow__edge-path{stroke:var(--border, #334155)!important;stroke-width:1.5}.ig-handle{opacity:0!important;width:1px!important;height:1px!important;min-width:0!important;min-height:0!important}.ig-node{position:relative;display:flex;flex-direction:column;gap:6px;padding:10px 14px 12px;border-radius:12px;background:var(--card, #1e293b);border:1.5px solid var(--border, #334155);box-shadow:0 2px 6px #00000040,0 0 0 1px #ffffff08 inset;transition:border-color .15s ease,box-shadow .15s ease;color:var(--text, #cbd5e1);font-size:12px}.ig-node:hover{border-color:var(--accent, #6366f1);box-shadow:0 4px 14px #00000059,0 0 0 1px #ffffff0a inset}.ig-tag{display:inline-block;align-self:flex-start;padding:1px 8px;border-radius:20px;font-size:9px;font-weight:700;letter-spacing:.05em;line-height:1.5;border:1px solid;margin-bottom:2px}.ig-tag--agent{background:#6366f126;color:#818cf8;border-color:#6366f14d}.ig-tag--owner{background:#94a3b81f;color:var(--muted, #94a3b8);border-color:#94a3b840}.ig-tag--system{background:#3b82f61f;color:#60a5fa;border-color:#3b82f640}.ig-tag--tool{background:#94a3b814;color:var(--muted, #94a3b8);border-color:#94a3b833}.ig-node__row{display:flex;align-items:center;gap:10px}.ig-node__body{min-width:0;overflow:hidden}.ig-node__name{font-size:13px;font-weight:700;color:var(--text-strong, #e2e8f0);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3}.ig-node__sub{font-size:10px;color:var(--muted, #64748b);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ig-node__icon{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;font-size:16px;flex-shrink:0}.ig-node__icon--agent{background:var(--accent-subtle, rgba(99,102,241,.12));border:1.5px solid var(--accent, #6366f1)}.ig-node__icon--owner{background:#94a3b81a;border:1.5px solid var(--border, #334155)}.ig-node__icon--system{background:#3b82f61a;border:1.5px solid rgba(59,130,246,.25)}.ig-node__icon--tool{width:24px;height:24px;font-size:12px;background:#94a3b814;border:1px solid var(--border, #334155)}.ig-node__footer{display:flex;align-items:center;gap:8px;justify-content:space-between}.ig-risk{display:inline-flex;align-items:center;padding:2px 8px;border-radius:20px;font-size:9px;font-weight:700;letter-spacing:.03em;flex-shrink:0}.ig-risk--high{background:#ef444426;color:#f87171}.ig-risk--medium{background:#f59e0b26;color:#fbbf24}.ig-risk--low{background:#22c55e26;color:#4ade80}.ig-node--agent{width:220px;border-color:var(--accent, #6366f1);border-width:2px}.ig-node--owner{width:170px}.ig-node--system{width:190px}.ig-node--tool{width:155px;padding:8px 10px;gap:4px}.ig-node--overflow{border-style:dashed;opacity:.65}.ig-node__tool-name{font-size:10px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.perm-table-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight);animation:rise .35s var(--ease-out) backwards}.profile-section .perm-table-wrap{border:none;box-shadow:none;animation:none;border-radius:0}.perm-table{width:100%;border-collapse:collapse;font-size:13px}.perm-th{padding:10px 14px;text-align:left;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);border-bottom:1px solid var(--border);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color var(--duration-fast) ease}.perm-th:hover{color:var(--text-strong)}.perm-row{transition:background var(--duration-fast) ease}.perm-row:hover{background:var(--bg-hover)}.perm-td{padding:10px 14px;border-bottom:1px solid var(--border);vertical-align:middle}.perm-td--num{text-align:right;font-family:var(--mono);font-size:12px}.perm-td--date{white-space:nowrap;font-size:12px;color:var(--muted)}.perm-agent{display:inline-flex;align-items:center;gap:6px;font-size:12px}.perm-targets{display:inline-flex;flex-wrap:wrap;gap:4px}.access-pill{display:inline-flex;align-items:center;padding:2px 8px;border-radius:var(--radius-full);font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.03em}.access-pill.read{color:var(--info);background:#3b82f61f;border:1px solid rgba(59,130,246,.25)}.access-pill.write{color:var(--warn);background:var(--warn-subtle);border:1px solid rgba(245,158,11,.25)}.access-pill.admin{color:var(--danger);background:var(--danger-subtle);border:1px solid rgba(239,68,68,.25)}.access-pill.unknown{color:var(--muted);background:var(--secondary);border:1px solid var(--border)}.anomaly-dot{display:inline-block;width:8px;height:8px;border-radius:var(--radius-full);background:var(--accent);box-shadow:0 0 8px var(--accent-glow);animation:pulse-subtle 2s ease-in-out infinite}.profile-tabs{display:flex;gap:0;border-bottom:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg) var(--radius-lg) 0 0;overflow:hidden}.profile-tab{flex:1;padding:12px 20px;border:none;background:transparent;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer;border-bottom:2px solid transparent;transition:color var(--duration-fast) ease,border-color var(--duration-fast) ease,background var(--duration-fast) ease;text-align:center;letter-spacing:.02em}.profile-tab:hover{color:var(--text-strong);background:var(--bg-hover)}.profile-tab--active{color:var(--accent);border-bottom-color:var(--accent)}.profile-subtab-toggle{display:inline-flex;border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary);overflow:hidden;margin-bottom:16px}.profile-subtab{padding:6px 16px;border:none;background:transparent;font-size:12px;font-weight:600;color:var(--muted);cursor:pointer;transition:color var(--duration-fast) ease,background var(--duration-fast) ease}.profile-subtab:hover{color:var(--text-strong)}.profile-subtab--active{background:var(--accent);color:var(--text-on-accent, #fff);border-radius:var(--radius-full)}.profile-tab-content,.profile-view,.tasks-view,.identities-view{display:grid;gap:16px}.persona-headline{font-size:18px;font-weight:600;color:var(--text-strong);line-height:1.4;margin-bottom:16px}.persona-section{margin-top:14px}.persona-section__label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin-bottom:8px}.persona-traits{display:flex;flex-wrap:wrap;gap:8px}.persona-trait-pill{display:inline-flex;align-items:center;padding:5px 12px;border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary);font-size:12px;font-weight:500;color:var(--text);line-height:1.4}.persona-boundaries{margin:0;padding-left:20px;list-style:disc;font-size:13px;line-height:1.7;color:var(--text)}.persona-boundaries li{margin-bottom:4px}.skill-category{margin-bottom:16px}.skill-category:last-child{margin-bottom:0}.skill-category__label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-bottom:8px}.skill-grid{display:flex;flex-wrap:wrap;gap:8px}.skill-card{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary);font-size:11px;font-weight:500;color:var(--text);transition:border-color var(--duration-fast) ease,background var(--duration-fast) ease;cursor:default}.skill-card:hover{border-color:var(--border-strong);background:var(--bg-hover)}.skill-card--workspace{background:var(--accent-subtle);border-color:var(--accent)}.skill-card__emoji{font-size:13px;line-height:1}.skill-card__name{white-space:nowrap}.skill-card__badge{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--accent);padding:1px 5px;border-radius:var(--radius-full);background:rgba(var(--accent-rgb, 99, 102, 241),.1)}.profile-section__count{font-size:12px;font-weight:500;color:var(--muted);margin-left:8px}.profile-section__subtitle{font-size:11px;font-weight:400;text-transform:none;letter-spacing:0;color:var(--muted);margin-left:10px}.possessed-subsection{margin-top:16px}.possessed-subsection__label{font-size:12px;font-weight:600;color:var(--text-strong);margin-bottom:10px}.possessed-hierarchy-hint{font-family:var(--mono);font-size:10px;color:var(--muted);margin-bottom:12px;letter-spacing:.02em}[data-tip]{position:relative}[data-tip]:after{content:attr(data-tip);position:absolute;left:50%;bottom:calc(100% + 8px);transform:translate(-50%);padding:8px 12px;border-radius:var(--radius-md);background:var(--text-strong);color:var(--bg, #fff);font-size:12px;font-weight:400;line-height:1.5;white-space:normal;max-width:300px;width:max-content;text-transform:none;letter-spacing:0;pointer-events:none;opacity:0;transition:opacity var(--duration-fast) ease;z-index:100;box-shadow:var(--shadow-md)}[data-tip]:hover:after{opacity:1}[data-tip]:before{content:"";position:absolute;left:50%;bottom:calc(100% + 3px);transform:translate(-50%);border:5px solid transparent;border-top-color:var(--text-strong);pointer-events:none;opacity:0;transition:opacity var(--duration-fast) ease;z-index:100}[data-tip]:hover:before{opacity:1}[data-tip=""]:after,[data-tip=""]:before{display:none}.raw-files-list{display:grid;gap:8px}.raw-file-viewer{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden}.raw-file-viewer__header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:10px 14px;border:none;background:var(--secondary);cursor:pointer;font-size:13px;font-weight:600;color:var(--text-strong);text-align:left;transition:background var(--duration-fast) ease}.raw-file-viewer__header:hover{background:var(--bg-hover)}.raw-file-viewer__chevron{font-size:10px;color:var(--muted)}.raw-file-viewer__content{max-height:400px;overflow-y:auto;padding:14px;background:var(--card);border-top:1px solid var(--border)}.raw-file-viewer__content pre{margin:0;font-family:var(--mono);font-size:12px;line-height:1.6;color:var(--text);white-space:pre-wrap;word-break:break-word}.risk-table-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight);animation:rise .35s var(--ease-out) backwards}.inspection-section{margin-top:20px;display:grid;gap:10px}.inspection-section__header{display:grid;gap:2px}.inspection-modal-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:300;background:#00000073;display:grid;place-items:center;padding:20px}.inspection-modal{width:min(900px,100%);max-height:85vh;overflow:hidden;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);box-shadow:var(--shadow-md),inset 0 1px 0 var(--card-highlight);display:grid;grid-template-rows:auto auto minmax(0,1fr)}.inspection-modal__header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;border-bottom:1px solid var(--border)}.inspection-modal__header h3{margin:0;font-size:15px;color:var(--text-strong)}.inspection-modal__meta{padding:12px 16px;display:grid;gap:6px;font-size:13px;color:var(--text);border-bottom:1px solid var(--border)}.inspection-modal__content{margin:0;padding:14px 16px;font-family:var(--mono);font-size:12px;line-height:1.6;color:var(--text);white-space:pre-wrap;word-break:break-word;overflow:auto}.access-pill.risk-high{color:var(--danger);background:var(--danger-subtle);border:1px solid rgba(239,68,68,.25)}.access-pill.risk-medium{color:var(--warn);background:var(--warn-subtle);border:1px solid rgba(245,158,11,.25)}.access-pill.risk-low{color:var(--info);background:#3b82f61f;border:1px solid rgba(59,130,246,.25)}.graph-page-wrap{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight);animation:rise .35s var(--ease-out) backwards;overflow:hidden}.graph-page-wrap .ig-wrap{height:560px;border:none;border-radius:0;box-shadow:none}@media(max-width:900px){.agents-grid,.identity-grid{grid-template-columns:1fr}.identity-card__stats{grid-template-columns:repeat(2,1fr);gap:8px}.profile-hero{flex-direction:column;text-align:center}.profile-tabs{overflow-x:auto}.profile-tab{white-space:nowrap;padding:10px 14px;font-size:12px}}.stats-grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));margin-bottom:24px}.stat-card-link{text-decoration:none;color:inherit;display:block}.stat-card-link:hover .stat-card{border-color:var(--accent);box-shadow:var(--shadow-md),inset 0 1px 0 var(--card-highlight);transform:translateY(-2px)}.stat-card{display:flex;align-items:center;gap:16px;padding:20px;border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight);transition:border-color var(--duration-normal) var(--ease-out),box-shadow var(--duration-normal) var(--ease-out),transform var(--duration-normal) var(--ease-out)}.stat-card__icon{width:48px;height:48px;border-radius:50%;display:grid;place-items:center;flex-shrink:0;color:var(--muted);background:var(--secondary)}.stat-card--success .stat-card__icon{color:var(--success);background:#22c55e1a}.stat-card--warning .stat-card__icon{color:var(--warn);background:var(--warn-subtle)}.stat-card--danger .stat-card__icon{color:var(--danger);background:var(--danger-subtle)}.stat-card__content{min-width:0}.stat-card__value{font-size:28px;font-weight:700;letter-spacing:-.03em;color:var(--text-strong);line-height:1.1}.stat-card__label{font-size:13px;color:var(--muted);margin-top:4px}.overview-section{margin-bottom:24px}.overview-section__header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.overview-section__title{font-size:14px;font-weight:600;color:var(--text-strong);text-transform:uppercase;letter-spacing:.04em;margin:0}.overview-section__link{font-size:13px;color:var(--accent);text-decoration:none;font-weight:500}.overview-section__link:hover{text-decoration:underline}.events-list{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.event-item{display:flex;align-items:center;gap:16px;padding:14px 20px;border-bottom:1px solid var(--border);transition:background var(--duration-fast) ease}.event-item:last-child{border-bottom:none}.event-item:hover{background:var(--bg-hover)}.event-item__risk{flex-shrink:0;width:70px}.event-item__content{flex:1;min-width:0}.event-item__agent{font-size:14px;font-weight:500;color:var(--text-strong);margin-bottom:4px}.event-item__categories{display:flex;flex-wrap:wrap;gap:4px}.event-item__time{font-size:12px;color:var(--muted);white-space:nowrap}.activity-summary{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.activity-summary__item{display:flex;align-items:center;gap:14px;padding:14px 20px;border-bottom:1px solid var(--border);text-decoration:none;color:inherit;transition:background var(--duration-fast) ease}.activity-summary__item:last-child{border-bottom:none}.activity-summary__item:hover{background:var(--bg-hover)}.activity-summary__avatar{width:40px;height:40px;border-radius:50%;background:var(--accent-subtle);display:grid;place-items:center;font-size:18px;flex-shrink:0}.activity-summary__info{flex:1;min-width:0}.activity-summary__name{font-size:14px;font-weight:600;color:var(--text-strong)}.activity-summary__stats{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted);margin-top:2px}.activity-summary__dot{width:3px;height:3px;border-radius:50%;background:var(--border-strong)}.activity-summary__blocked{color:var(--warn)}.activity-summary__status{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}.timeline{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.timeline-item{display:flex;gap:16px;padding:16px 20px;border-bottom:1px solid var(--border);transition:background var(--duration-fast) ease}.timeline-item:last-child{border-bottom:none}.timeline-item:hover{background:var(--bg-hover)}.timeline-item--blocked{background:var(--danger-subtle)}.timeline-item--blocked:hover{background:#ef444414}.timeline-item__marker{flex-shrink:0;padding-top:4px}.timeline-dot{display:block;width:10px;height:10px;border-radius:50%}.timeline-dot.allowed{background:var(--success);box-shadow:0 0 6px #22c55e66}.timeline-dot.blocked{background:var(--danger);box-shadow:0 0 6px #ef444466}.timeline-item__content{flex:1;min-width:0}.timeline-item__header{display:flex;align-items:center;gap:10px;margin-bottom:6px}.timeline-item__tool{font-size:14px;font-weight:600;color:var(--text-strong)}.timeline-item__status{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.03em;padding:2px 8px;border-radius:var(--radius-full)}.timeline-item__status.allowed{color:var(--success);background:#22c55e1f}.timeline-item__status.blocked{color:var(--danger);background:var(--danger-subtle)}.timeline-item__meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.timeline-item__agent{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--text)}.timeline-item__error{margin-top:8px;padding:8px 12px;border-radius:var(--radius-md);background:var(--danger-subtle);font-size:12px;color:var(--danger);font-family:var(--mono)}.timeline-item__time{flex-shrink:0;text-align:right}.timeline-item__timestamp{display:block;font-size:12px;color:var(--text)}.timeline-item__relative{display:block;font-size:11px;color:var(--muted);margin-top:2px}.filter-tabs{display:inline-flex;border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary);overflow:hidden}.filter-tab{padding:6px 14px;border:none;background:transparent;font-size:12px;font-weight:600;color:var(--muted);cursor:pointer;transition:color var(--duration-fast) ease,background var(--duration-fast) ease}.filter-tab:hover{color:var(--text-strong)}.filter-tab.active{background:var(--accent);color:var(--text-on-accent, #fff)}.secrets-grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));margin-bottom:24px}.secrets-card{display:flex;align-items:center;gap:16px;padding:20px;border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.secrets-card__icon{width:44px;height:44px;border-radius:var(--radius-md);display:grid;place-items:center;background:var(--secondary);color:var(--muted);flex-shrink:0}.secrets-card__content{flex:1;min-width:0}.secrets-card__label{font-size:14px;font-weight:600;color:var(--text-strong)}.secrets-card__description{font-size:12px;color:var(--muted);margin-top:2px}.secrets-card__count{flex-shrink:0}.secrets-card__badge{display:inline-flex;align-items:center;justify-content:center;min-width:28px;height:28px;padding:0 8px;border-radius:var(--radius-full);font-size:14px;font-weight:700}.secrets-card__badge.ok{background:#22c55e1f;color:var(--success)}.secrets-card__badge.warn{background:var(--warn-subtle);color:var(--warn)}.secrets-section{margin-bottom:24px}.secrets-section__title{font-size:14px;font-weight:600;color:var(--text-strong);text-transform:uppercase;letter-spacing:.04em;margin:0 0 12px}.scanner-list{display:grid;gap:12px}.scanner-item{padding:16px 20px;border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm)}.scanner-item__header{display:flex;align-items:center;gap:10px;margin-bottom:6px}.scanner-item__id{font-size:11px;padding:2px 6px;border-radius:var(--radius-sm);background:var(--secondary);color:var(--muted)}.scanner-item__name{font-size:14px;font-weight:600;color:var(--text-strong)}.scanner-item__description{font-size:13px;color:var(--muted);margin-bottom:8px}.scanner-item__count{font-size:12px;color:var(--muted)}.detections-list{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.detection-item{display:flex;align-items:flex-start;gap:16px;padding:14px 20px;border-bottom:1px solid var(--border)}.detection-item:last-child{border-bottom:none}.detection-item__risk{flex-shrink:0;width:70px}.detection-item__content{flex:1;min-width:0}.detection-item__agent{font-size:14px;font-weight:500;color:var(--text-strong);margin-bottom:4px}.detection-item__categories{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:6px}.detection-item__findings{display:flex;flex-wrap:wrap;gap:4px}.detection-finding{font-size:11px;padding:2px 8px;border-radius:var(--radius-full);background:var(--secondary);color:var(--muted)}.detection-finding.more{border-style:dashed;border:1px dashed var(--border)}.detection-item__time{font-size:12px;color:var(--muted);white-space:nowrap}.settings-container{max-width:700px}.settings-section{padding:24px;border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);margin-bottom:20px;box-shadow:var(--shadow-sm),inset 0 1px 0 var(--card-highlight)}.settings-section__title{font-size:16px;font-weight:600;color:var(--text-strong);margin:0 0 8px}.settings-section__description{font-size:13px;color:var(--muted);margin:0 0 20px}.connection-status{display:flex;align-items:center;gap:16px;padding:16px;border-radius:var(--radius-md);background:var(--secondary)}.connection-status__indicator{flex-shrink:0}.connection-status__info{flex:1;min-width:0}.connection-status__label{font-size:14px;font-weight:500;color:var(--text-strong)}.connection-status__description{font-size:12px;color:var(--muted);margin-top:2px}.text-success{color:var(--success)}.text-danger{color:var(--danger)}.text-muted{color:var(--muted)}.spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.settings-grid{display:grid;gap:20px;grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}.settings-field{display:flex;flex-direction:column;gap:6px}.settings-field__label{font-size:13px;font-weight:600;color:var(--text-strong)}.settings-field__input input{width:100%;padding:10px 14px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg);font-size:14px;color:var(--text);transition:border-color var(--duration-fast) ease}.settings-field__input input:focus{outline:none;border-color:var(--accent)}.settings-field__help{font-size:12px;color:var(--muted)}.security-levels{display:grid;gap:12px}.security-level{display:block;width:100%;padding:16px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg);cursor:pointer;text-align:left;transition:border-color var(--duration-fast) ease,background var(--duration-fast) ease}.security-level:hover{border-color:var(--border-strong)}.security-level.active{border-color:var(--accent);background:var(--accent-subtle)}.security-level__header{display:flex;align-items:center;justify-content:space-between;margin-bottom:4px}.security-level__label{font-size:14px;font-weight:600;color:var(--text-strong)}.security-level__check{color:var(--accent)}.security-level__description{font-size:13px;color:var(--muted)}.settings-actions{display:flex;gap:12px}.btn{padding:10px 20px;border-radius:var(--radius-md);font-size:14px;font-weight:600;cursor:pointer;transition:background var(--duration-fast) ease,border-color var(--duration-fast) ease}.btn-primary{background:var(--accent);color:var(--text-on-accent, #fff);border:1px solid var(--accent)}.btn-primary:hover{background:var(--accent-hover, var(--accent))}.btn-primary:disabled{opacity:.6;cursor:not-allowed}.btn-secondary{background:var(--secondary);color:var(--text);border:1px solid var(--border)}.btn-secondary:hover{background:var(--bg-hover)}.btn-secondary:disabled{opacity:.6;cursor:not-allowed}.access-pill.risk-critical{color:#dc2626;background:#dc26261f;border:1px solid rgba(220,38,38,.25)}@media(max-width:768px){.stats-grid{grid-template-columns:repeat(2,1fr)}.stat-card{flex-direction:column;text-align:center;gap:12px}.timeline-item{flex-direction:column;gap:12px}.timeline-item__time{text-align:left}.settings-grid{grid-template-columns:1fr}}
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="_图层_1" data-name="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16">
3
+ <defs>
4
+ <style>
5
+ .cls-1 {
6
+ fill: none;
7
+ }
8
+
9
+ .cls-2 {
10
+ fill: #2c5bff;
11
+ }
12
+
13
+ .cls-3 {
14
+ fill: #fff;
15
+ }
16
+
17
+ .cls-4 {
18
+ clip-path: url(#clippath);
19
+ }
20
+ </style>
21
+ <clipPath id="clippath">
22
+ <rect class="cls-1" x="2.13" y="4.35" width="11.74" height="7.31"/>
23
+ </clipPath>
24
+ </defs>
25
+ <circle class="cls-2" cx="8" cy="8" r="8"/>
26
+ <g class="cls-4">
27
+ <path class="cls-3" d="M13.55,7.25h-3.03c-.17,0-.31.14-.31.31v1.27c0,.17.14.31.31.31h1.28c-.17.29-.52.53-1.12.52-.77-.01-1.32-.55-1.39-1.32,0-.06,0-.13,0-.21,0-.99-.31-1.85-.84-2.5.09.03.2.01.28-.05.52-.4,1.18-.61,1.98-.61.73,0,1.44.25,2.02.69l-.51.58c-.47-.35-1.17-.49-1.53-.48-.67,0-1.19.24-1.54.68-.11.14-.09.33.05.44.14.11.33.09.44-.05.23-.29.59-.44,1.05-.44.31,0,1.04.15,1.29.49.06.08.14.12.23.13,0,0,.01,0,.02,0,.09,0,.18-.04.24-.11l.94-1.07c.11-.13.1-.32-.02-.44-.74-.68-1.69-1.06-2.68-1.06-.93,0-1.75.26-2.37.74-.07.05-.11.13-.12.21,0,.03,0,.06,0,.09-.63-.64-1.51-1.01-2.52-1.01-2.11,0-3.58,1.5-3.58,3.64s1.47,3.64,3.58,3.64c.81,0,1.55-.21,2.14-.61.11-.07.12-.19.13-.24.01-.06,0-.12-.03-.17.12.12.24.23.38.33,0,0,.01,0,.01.01.59.44,1.32.67,2.11.67.62,0,1.14-.12,1.65-.39v.02c0,.17.14.31.31.31h1.13c.17,0,.31-.14.31-.31v-3.7c0-.17-.14-.31-.31-.31M7.6,10.46c-.05.02-.08.03-.13.06l-.03.02c-.47.3-1.06.45-1.73.45-1.74,0-2.91-1.2-2.91-2.98s1.17-2.98,2.91-2.98,2.92,1.27,2.92,3.1c0,.19.02.32.05.43.16,1.03.93,1.72,1.99,1.74h.02c1.18,0,1.78-.71,1.85-1.42,0-.09-.02-.18-.08-.24-.06-.07-.14-.1-.23-.1l-1.39-.02v-.64h2.4v3.07h-.5v-.27c0-.12-.07-.23-.17-.28-.11-.05-.23-.04-.33.03-.57.41-1.09.58-1.78.58-.65,0-1.24-.18-1.72-.53,0,0-.02-.01-.02-.02-.15-.11-.28-.22-.4-.35-.41-.45-.67-1.21-.67-1.96,0-.15.01-.4.03-.55.02-.17-.1-.33-.27-.36-.17-.02-.33.09-.35.27-.03.19-.04.46-.04.64,0,.89.31,1.78.8,2.35-.05-.03-.1-.05-.16-.05-.01,0-.05,0-.07,0"/>
28
+ </g>
29
+ </svg>
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="icon" type="image/svg+xml" href="/dashboard/favicon.svg" />
7
+ <title>changewayGuard</title>
8
+ <script type="module" crossorigin src="/dashboard/assets/index-CqWIeBTD.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/dashboard/assets/index-Dw7--9q4.css">
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="_图层_2" data-name="图层_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 184.71">
3
+ <defs>
4
+ <style>
5
+ .cls-1 {
6
+ fill: #2e5bff;
7
+ }
8
+ </style>
9
+ </defs>
10
+ <g id="_图层_1-2" data-name="图层_1">
11
+ <g>
12
+ <path class="cls-1" d="M173.16,23.57c13.3-8.11,29.18-12.23,47.18-12.23,20.45,0,40.19,7.15,56.16,20.23l-16.64,18.97c-11.85-10.18-31.13-13.68-40.03-13.36-16.71.19-25.91,5.7-32.7,11.06-2.46,1.94-2.88,5.51-.94,7.97,1.94,2.46,5.51,2.88,7.97.94,5.18-4.09,11.87-8.46,25.8-8.62,10.16.1,28.76,4.74,35.53,13.82,1.02,1.37,2.61,2.21,4.32,2.27.07,0,.15,0,.22,0,1.63,0,3.18-.7,4.26-1.93l24.48-27.92c2.03-2.31,1.84-5.82-.42-7.9C269.63,9.54,245.47,0,220.34,0c-20.12,0-37.98,4.67-53.09,13.88-2.67,1.63-3.52,5.12-1.89,7.8,1.63,2.67,5.13,3.51,7.8,1.89Z"/>
13
+ <path class="cls-1" d="M294.33,75.46h-78.86c-3.13,0-5.67,2.54-5.67,5.67v32.98c0,3.11,2.5,5.64,5.61,5.67l37.27.4c-3.58,9.56-13.72,18.38-33.15,18.21-23.28-.34-38.92-17.02-38.92-41.51,0-.34-.05-2.4-.05-3.08C180.55,39.24,143.36.93,90.25.93S0,38.72,0,92.82s37.11,91.89,90.25,91.89c19.59,0,35.09-3.79,48.77-11.92,1.85-1.1,2.07-3.07,2.17-4.02.37-2.21-.74-3.97-1.78-4.91-1.3-1.15-2.89-1.28-3.52-1.28-.41,0-.78.05-1.1.14l-.39.11c-.8.22-.91.27-1.73.69l-.92.5c-.38.21-.8.44-.97.52-10.96,5.25-21.56,8.51-40.53,8.51-47.01,0-78.59-32.24-78.59-80.23S43.24,12.59,90.25,12.59s78.85,34.29,78.85,83.38c0,2.43.14,4.59.4,6.46,2.33,27.73,22.18,46.9,49.87,47.3,29.16.56,44.31-17.07,46.04-34.59.16-1.58-.36-3.16-1.42-4.34-1.06-1.18-2.57-1.87-4.16-1.89l-38.68-.42v-21.7h67.52v84.93h-18.06v-9.56c0-2.13-1.19-4.08-3.09-5.05-1.89-.97-4.18-.8-5.9.45-15.36,11.08-29.18,15.59-47.7,15.59-17.42,0-33.38-4.94-46.2-14.3-.18-.17-.38-.33-.58-.47-4.07-2.87-7.7-6.06-10.78-9.46-10.94-12.1-18.01-32.78-18.01-52.68,0-4.05.31-10.59.89-14.73.43-3.1-1.73-5.97-4.83-6.4-3.13-.44-5.97,1.73-6.4,4.83-.66,4.7-1,11.76-1,16.3,0,22.9,8.02,46,20.94,60.29,3.51,3.88,7.58,7.49,12.12,10.74.13.11.26.22.4.32,14.87,11.05,33.36,16.9,53.46,16.9,17.2,0,31.27-3.61,45.34-11.85v4.75c0,3.13,2.54,5.67,5.67,5.67h29.41c3.13,0,5.67-2.54,5.67-5.67v-96.27c0-3.13-2.54-5.67-5.67-5.67Z"/>
14
+ </g>
15
+ </g>
16
+ </svg>
@@ -0,0 +1,37 @@
1
+ import { type NetworkInterfaceInfo } from "node:os";
2
+ export declare const CHANGEWAY_OPEN_PREFIX = "/changeway-open";
3
+ export declare function pickPrimaryMacAddress(interfaces?: NodeJS.Dict<NetworkInterfaceInfo[]>): string | null;
4
+ export declare function getLocalMacAddress(): string;
5
+ export declare function getLocalHostname(): string;
6
+ export declare function clearCachedMacAddressForTests(): void;
7
+ export declare function setCachedMacAddressForTests(mac: string): void;
8
+ export declare function getAuthorizationHeaderValue(): string;
9
+ export declare function getLocalAgentId(): string;
10
+ export type GenerateRequestSignOptions = {
11
+ mac?: string;
12
+ hostname?: string;
13
+ timestamp: number;
14
+ nonce: string;
15
+ method?: string;
16
+ path?: string;
17
+ body?: unknown;
18
+ };
19
+ export declare function generateRequestSign(options: GenerateRequestSignOptions): string;
20
+ export declare function withChangewayOpenPrefix(urlOrPath: string): string;
21
+ export declare function extractPathFromUrl(urlOrPath: string): string;
22
+ export type BuildSignedAuthHeadersOptions = {
23
+ method: string;
24
+ path: string;
25
+ body?: unknown;
26
+ mac?: string;
27
+ hostname?: string;
28
+ timestamp?: number;
29
+ nonce?: string;
30
+ authorization?: string | null;
31
+ };
32
+ export declare function buildSignedAuthHeaders(options: BuildSignedAuthHeadersOptions): Record<string, string>;
33
+ export type BuildSignedAuthHeadersForUrlOptions = Omit<BuildSignedAuthHeadersOptions, "path"> & {
34
+ url: string;
35
+ };
36
+ export declare function buildSignedAuthHeadersForUrl(options: BuildSignedAuthHeadersForUrlOptions): Record<string, string>;
37
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../agent/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAA+B,KAAK,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGjF,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AASvD,wBAAgB,qBAAqB,CACnC,UAAU,GAAE,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAuB,GACpE,MAAM,GAAG,IAAI,CAUf;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAIzC;AAED,wBAAgB,6BAA6B,IAAI,IAAI,CAGpD;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE7D;AAED,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IAEd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM,CAW/E;AAyBD,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBjE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAU5D;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,6BAA6B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAuCrG;AAED,MAAM,MAAM,mCAAmC,GAAG,IAAI,CAAC,6BAA6B,EAAE,MAAM,CAAC,GAAG;IAC9F,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,mCAAmC,GAC3C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKxB"}
@@ -0,0 +1,151 @@
1
+ import { createHash } from "node:crypto";
2
+ import { hostname, networkInterfaces } from "node:os";
3
+ const FALLBACK_MAC = "00:00:00:00:00:00";
4
+ export const CHANGEWAY_OPEN_PREFIX = "/changeway-open";
5
+ let cachedMacAddress = null;
6
+ let cachedHostname = null;
7
+ function normalizeMacAddress(mac) {
8
+ return mac.toLowerCase();
9
+ }
10
+ export function pickPrimaryMacAddress(interfaces = networkInterfaces()) {
11
+ for (const infos of Object.values(interfaces)) {
12
+ if (!infos)
13
+ continue;
14
+ for (const info of infos) {
15
+ if (info.internal)
16
+ continue;
17
+ if (!info.mac || info.mac === "00:00:00:00:00:00")
18
+ continue;
19
+ return normalizeMacAddress(info.mac);
20
+ }
21
+ }
22
+ return null;
23
+ }
24
+ export function getLocalMacAddress() {
25
+ if (cachedMacAddress)
26
+ return cachedMacAddress;
27
+ cachedMacAddress = pickPrimaryMacAddress() ?? FALLBACK_MAC;
28
+ return cachedMacAddress;
29
+ }
30
+ export function getLocalHostname() {
31
+ if (cachedHostname)
32
+ return cachedHostname;
33
+ cachedHostname = hostname();
34
+ return cachedHostname;
35
+ }
36
+ export function clearCachedMacAddressForTests() {
37
+ cachedMacAddress = null;
38
+ cachedHostname = null;
39
+ }
40
+ export function setCachedMacAddressForTests(mac) {
41
+ cachedMacAddress = normalizeMacAddress(mac);
42
+ }
43
+ export function getAuthorizationHeaderValue() {
44
+ return `Bearer ${getLocalMacAddress()}`;
45
+ }
46
+ export function getLocalAgentId() {
47
+ return `mac-${getLocalMacAddress().replace(/:/g, "")}`;
48
+ }
49
+ export function generateRequestSign(options) {
50
+ const mac = (options.mac ?? getLocalMacAddress()).toLowerCase();
51
+ const host = options.hostname ?? getLocalHostname();
52
+ const signContent = [
53
+ mac,
54
+ host,
55
+ String(options.timestamp),
56
+ options.nonce,
57
+ ].join("\n");
58
+ return createHash("sha256").update(signContent).digest("hex");
59
+ }
60
+ function createNonce(length = 8) {
61
+ let nonce = "";
62
+ while (nonce.length < length) {
63
+ nonce += Math.random().toString(36).slice(2);
64
+ }
65
+ return nonce.slice(0, length);
66
+ }
67
+ function isAlreadyPrefixed(pathname) {
68
+ return pathname === CHANGEWAY_OPEN_PREFIX || pathname.startsWith(`${CHANGEWAY_OPEN_PREFIX}/`);
69
+ }
70
+ function ensurePrefixedPath(pathname) {
71
+ const normalizedPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
72
+ if (isAlreadyPrefixed(normalizedPath))
73
+ return normalizedPath;
74
+ return `${CHANGEWAY_OPEN_PREFIX}${normalizedPath}`;
75
+ }
76
+ function isLoopbackHost(hostnameValue) {
77
+ const normalized = hostnameValue.toLowerCase();
78
+ return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1";
79
+ }
80
+ export function withChangewayOpenPrefix(urlOrPath) {
81
+ try {
82
+ const parsed = new URL(urlOrPath);
83
+ if (isLoopbackHost(parsed.hostname)) {
84
+ return parsed.toString();
85
+ }
86
+ parsed.pathname = ensurePrefixedPath(parsed.pathname);
87
+ return parsed.toString();
88
+ }
89
+ catch {
90
+ try {
91
+ const parsed = new URL(urlOrPath, "http://localhost");
92
+ return `${ensurePrefixedPath(parsed.pathname)}${parsed.search}${parsed.hash}`;
93
+ }
94
+ catch {
95
+ return ensurePrefixedPath(urlOrPath);
96
+ }
97
+ }
98
+ }
99
+ export function extractPathFromUrl(urlOrPath) {
100
+ try {
101
+ return new URL(urlOrPath).pathname;
102
+ }
103
+ catch {
104
+ try {
105
+ return new URL(urlOrPath, "http://localhost").pathname;
106
+ }
107
+ catch {
108
+ return urlOrPath.startsWith("/") ? urlOrPath : `/${urlOrPath}`;
109
+ }
110
+ }
111
+ }
112
+ export function buildSignedAuthHeaders(options) {
113
+ const mac = (options.mac ?? getLocalMacAddress()).toLowerCase();
114
+ const host = options.hostname ?? getLocalHostname();
115
+ const timestamp = options.timestamp ?? Math.floor(Date.now() / 1000);
116
+ const nonce = options.nonce ?? createNonce();
117
+ const sign = generateRequestSign({
118
+ mac,
119
+ hostname: host,
120
+ timestamp,
121
+ nonce,
122
+ method: options.method,
123
+ path: options.path,
124
+ body: options.body,
125
+ });
126
+ const headers = {
127
+ "X-MAC": mac,
128
+ "X-HOSTNAME": host,
129
+ "X-TIMESTAMP": String(timestamp),
130
+ "X-NONCE": nonce,
131
+ "X-SIGN": sign,
132
+ };
133
+ if (options.authorization !== null) {
134
+ headers.Authorization = options.authorization ?? getAuthorizationHeaderValue();
135
+ }
136
+ console.info("[moltguard] Auth headers", JSON.stringify({
137
+ "X-MAC": headers["X-MAC"],
138
+ "X-HOSTNAME": headers["X-HOSTNAME"],
139
+ "X-TIMESTAMP": headers["X-TIMESTAMP"],
140
+ "X-NONCE": headers["X-NONCE"],
141
+ "X-SIGN": headers["X-SIGN"],
142
+ }));
143
+ return headers;
144
+ }
145
+ export function buildSignedAuthHeadersForUrl(options) {
146
+ return buildSignedAuthHeaders({
147
+ ...options,
148
+ path: extractPathFromUrl(options.url),
149
+ });
150
+ }
151
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../agent/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Behavioral anomaly detector — runs at before_tool_call.
3
+ *
4
+ * Responsibilities:
5
+ * 1. Collect high-risk tool calls (file read, shell, web fetch) and send to Core
6
+ * 2. Record completed tool calls in the chain history
7
+ * 3. Core does all classification, signal computation, and risk decisions
8
+ * 4. Fail-open: if Core is unavailable, allow execution
9
+ */
10
+ import type { CoreCredentials } from "./config.js";
11
+ import type { PromptScanResponse, Logger, DetectionFinding } from "./types.js";
12
+ export declare const FILE_READ_TOOLS: Set<string>;
13
+ export declare const SHELL_TOOLS: Set<string>;
14
+ export declare const WEB_FETCH_TOOLS: Set<string>;
15
+ export type BlockDecision = {
16
+ block: true;
17
+ blockReason: string;
18
+ findings?: DetectionFinding[];
19
+ };
20
+ export type DetectionConfig = {
21
+ coreUrl: string;
22
+ /** Timeout for Core assess call (ms). Capped at ~3s to avoid holding up agent. */
23
+ assessTimeoutMs: number;
24
+ blockOnRisk: boolean;
25
+ pluginVersion: string;
26
+ };
27
+ /** Response from Core content scan API */
28
+ export type ContentScanResult = {
29
+ detected: boolean;
30
+ action?: "allow" | "alert" | "block";
31
+ riskLevel?: "no_risk" | "low" | "medium" | "high" | "critical";
32
+ confidence?: number;
33
+ explanation?: string;
34
+ categories: string[];
35
+ findings: Array<{
36
+ scanner: string;
37
+ name: string;
38
+ matchedText: string;
39
+ confidence: "high" | "medium" | "low";
40
+ }>;
41
+ summary: string;
42
+ latency_ms: number;
43
+ };
44
+ /** Response when quota is exceeded - still a success but no verdict */
45
+ export type QuotaExceededInfo = {
46
+ quotaExceeded: true;
47
+ quotaUsed: number;
48
+ quotaTotal: number;
49
+ /** true = autonomous mode (no email), false = human managed mode (email verified) */
50
+ isAutonomous: boolean;
51
+ resetAt: string | null;
52
+ upgradeUrl: string;
53
+ message: string;
54
+ /** Persuasive message for the agent to convince the user to purchase */
55
+ recommendation: string;
56
+ };
57
+ /** Callback for quota exceeded notification */
58
+ export type OnQuotaExceededCallback = (info: QuotaExceededInfo) => void;
59
+ export declare class BehaviorDetector {
60
+ private sessions;
61
+ private coreCredentials;
62
+ private config;
63
+ private log;
64
+ /** HTTP status codes we've already warned about — avoid log spam */
65
+ private warnedStatuses;
66
+ /** Track if we've already notified about quota exceeded (avoid spam) */
67
+ private quotaExceededNotified;
68
+ /** Callback for quota exceeded notification */
69
+ private onQuotaExceeded;
70
+ /** Pending quota exceeded message to append to next tool result */
71
+ private pendingQuotaMessage;
72
+ /** Callback for secret detection (business reporting) */
73
+ private onSecretDetected;
74
+ private formatEngineLogPayload;
75
+ private logEngineRequest;
76
+ private logEngineResponse;
77
+ private logEngineError;
78
+ constructor(config: DetectionConfig, log: Logger);
79
+ setCredentials(creds: CoreCredentials | null): void;
80
+ /** Set callback for when quota is exceeded */
81
+ setOnQuotaExceeded(callback: OnQuotaExceededCallback | null): void;
82
+ /** Set callback for when secrets are detected in params (business reporting) */
83
+ setOnSecretDetected(callback: ((typeCounts: Record<string, number>) => void) | null): void;
84
+ /** Reset quota exceeded notification flag (e.g., on new day) */
85
+ resetQuotaExceededNotification(): void;
86
+ /** Get and clear pending quota message (for appending to tool results) */
87
+ consumePendingQuotaMessage(): QuotaExceededInfo | null;
88
+ setUserIntent(sessionKey: string, message: string): void;
89
+ clearSession(sessionKey: string): void;
90
+ /**
91
+ * Read-and-clear latest prompt block decision for a session.
92
+ * Used by message_sending to terminate output immediately when user input
93
+ * was classified as block.
94
+ */
95
+ consumePromptBlockDecision(sessionKey: string): PromptScanResponse | null;
96
+ /**
97
+ * Read current prompt block decision without consuming it.
98
+ * Useful when upstream hooks need to render a risk message while preserving
99
+ * the block decision for downstream enforcement.
100
+ */
101
+ getPendingPromptBlockDecision(sessionKey: string): PromptScanResponse | null;
102
+ /**
103
+ * Read current prompt alert decision without consuming it.
104
+ * Alert remains pending until user explicitly confirms.
105
+ */
106
+ getPendingPromptAlertDecision(sessionKey: string): PromptScanResponse | null;
107
+ /**
108
+ * Confirm and clear pending prompt alert for a session.
109
+ */
110
+ confirmPendingPromptAlert(sessionKey: string): PromptScanResponse | null;
111
+ consumeConfirmedPromptReplay(sessionKey: string): string | null;
112
+ /**
113
+ * Called at before_tool_call. Returns a block decision or undefined (allow).
114
+ *
115
+ * All tool calls are sent to Core to build a complete tool chain.
116
+ * If Core is unavailable, fail-open (allow).
117
+ */
118
+ onBeforeToolCall(ctx: {
119
+ sessionKey: string;
120
+ agentId?: string;
121
+ }, event: {
122
+ toolName: string;
123
+ params: Record<string, unknown>;
124
+ }): Promise<BlockDecision | undefined>;
125
+ /**
126
+ * Called at after_tool_call. Records the completed tool in the chain.
127
+ */
128
+ onAfterToolCall(ctx: {
129
+ sessionKey: string;
130
+ }, event: {
131
+ toolName: string;
132
+ params: Record<string, unknown>;
133
+ result?: unknown;
134
+ error?: string;
135
+ durationMs?: number;
136
+ }): void;
137
+ /**
138
+ * Scan tool result content for injection patterns via Core API.
139
+ * Returns scan result or null if scan failed/unavailable.
140
+ */
141
+ scanContent(sessionKey: string, toolName: string, content: string): Promise<ContentScanResult | null>;
142
+ /**
143
+ * Scan raw user prompt content at message_received(user).
144
+ * Stores latest decision in session state for optional enforcement during before_tool_call.
145
+ */
146
+ scanPrompt(sessionKey: string, prompt: string): Promise<PromptScanResponse | null>;
147
+ private getOrCreate;
148
+ private callAssessApi;
149
+ }
150
+ //# sourceMappingURL=behavior-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior-detector.d.ts","sourceRoot":"","sources":["../../agent/behavior-detector.ts"],"names":[],"mappings":"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"}