cli-jaw 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (607) hide show
  1. package/README.ko.md +3 -2
  2. package/README.md +41 -12
  3. package/dist/bin/_http-client.js +34 -0
  4. package/dist/bin/_http-client.js.map +1 -0
  5. package/dist/bin/cli-jaw.js +10 -5
  6. package/dist/bin/cli-jaw.js.map +1 -1
  7. package/dist/bin/commands/browser-web-ai.js +155 -38
  8. package/dist/bin/commands/browser-web-ai.js.map +1 -1
  9. package/dist/bin/commands/browser.js +265 -37
  10. package/dist/bin/commands/browser.js.map +1 -1
  11. package/dist/bin/commands/chat.js +18 -14
  12. package/dist/bin/commands/chat.js.map +1 -1
  13. package/dist/bin/commands/clone.js +3 -2
  14. package/dist/bin/commands/clone.js.map +1 -1
  15. package/dist/bin/commands/dashboard.js +22 -18
  16. package/dist/bin/commands/dashboard.js.map +1 -1
  17. package/dist/bin/commands/dispatch.js +9 -11
  18. package/dist/bin/commands/dispatch.js.map +1 -1
  19. package/dist/bin/commands/doctor.js +26 -14
  20. package/dist/bin/commands/doctor.js.map +1 -1
  21. package/dist/bin/commands/employee.js +12 -7
  22. package/dist/bin/commands/employee.js.map +1 -1
  23. package/dist/bin/commands/init.js +9 -9
  24. package/dist/bin/commands/init.js.map +1 -1
  25. package/dist/bin/commands/launchd.js +17 -7
  26. package/dist/bin/commands/launchd.js.map +1 -1
  27. package/dist/bin/commands/mcp.js +7 -4
  28. package/dist/bin/commands/mcp.js.map +1 -1
  29. package/dist/bin/commands/memory.js +7 -5
  30. package/dist/bin/commands/memory.js.map +1 -1
  31. package/dist/bin/commands/orchestrate.js +6 -3
  32. package/dist/bin/commands/orchestrate.js.map +1 -1
  33. package/dist/bin/commands/reset.js +4 -3
  34. package/dist/bin/commands/reset.js.map +1 -1
  35. package/dist/bin/commands/serve.js +3 -2
  36. package/dist/bin/commands/serve.js.map +1 -1
  37. package/dist/bin/commands/service.js +2 -2
  38. package/dist/bin/commands/service.js.map +1 -1
  39. package/dist/bin/commands/status.js +10 -9
  40. package/dist/bin/commands/status.js.map +1 -1
  41. package/dist/bin/commands/tui/api.js +26 -18
  42. package/dist/bin/commands/tui/api.js.map +1 -1
  43. package/dist/bin/commands/tui/overlays.js +3 -1
  44. package/dist/bin/commands/tui/overlays.js.map +1 -1
  45. package/dist/bin/commands/tui/simple-mode.js +1 -1
  46. package/dist/bin/commands/tui/simple-mode.js.map +1 -1
  47. package/dist/bin/commands/tui/types.js.map +1 -1
  48. package/dist/bin/postinstall.js +153 -65
  49. package/dist/bin/postinstall.js.map +1 -1
  50. package/dist/bin/star-prompt.js +4 -3
  51. package/dist/bin/star-prompt.js.map +1 -1
  52. package/dist/lib/mcp/format-converters.js +15 -10
  53. package/dist/lib/mcp/format-converters.js.map +1 -1
  54. package/dist/lib/mcp/mcp-install.js +2 -2
  55. package/dist/lib/mcp/mcp-install.js.map +1 -1
  56. package/dist/lib/mcp/skills-distribution.js +2 -2
  57. package/dist/lib/mcp/skills-distribution.js.map +1 -1
  58. package/dist/lib/mcp/skills-reset.js +5 -4
  59. package/dist/lib/mcp/skills-reset.js.map +1 -1
  60. package/dist/lib/mcp/skills-symlinks.js +9 -9
  61. package/dist/lib/mcp/skills-symlinks.js.map +1 -1
  62. package/dist/lib/mcp/skills-utils.js +5 -4
  63. package/dist/lib/mcp/skills-utils.js.map +1 -1
  64. package/dist/lib/mcp/unified-config.js +3 -2
  65. package/dist/lib/mcp/unified-config.js.map +1 -1
  66. package/dist/lib/mime-detect.js +65 -0
  67. package/dist/lib/mime-detect.js.map +1 -0
  68. package/dist/lib/quota-copilot.js +12 -10
  69. package/dist/lib/quota-copilot.js.map +1 -1
  70. package/dist/lib/stt.js +3 -3
  71. package/dist/lib/stt.js.map +1 -1
  72. package/dist/lib/upload.js +14 -5
  73. package/dist/lib/upload.js.map +1 -1
  74. package/dist/scripts/i18n-registry.js +4 -4
  75. package/dist/scripts/i18n-registry.js.map +1 -1
  76. package/dist/server.js +61 -57
  77. package/dist/server.js.map +1 -1
  78. package/dist/src/agent/alert-escalation.js +61 -0
  79. package/dist/src/agent/alert-escalation.js.map +1 -0
  80. package/dist/src/agent/args.js +71 -2
  81. package/dist/src/agent/args.js.map +1 -1
  82. package/dist/src/agent/error-classifier.js +9 -4
  83. package/dist/src/agent/error-classifier.js.map +1 -1
  84. package/dist/src/agent/events.js +130 -101
  85. package/dist/src/agent/events.js.map +1 -1
  86. package/dist/src/agent/lifecycle-handler.js +44 -19
  87. package/dist/src/agent/lifecycle-handler.js.map +1 -1
  88. package/dist/src/agent/live-run-state.js +7 -3
  89. package/dist/src/agent/live-run-state.js.map +1 -1
  90. package/dist/src/agent/memory-flush-controller.js +6 -4
  91. package/dist/src/agent/memory-flush-controller.js.map +1 -1
  92. package/dist/src/agent/opencode-diagnostics.js +7 -6
  93. package/dist/src/agent/opencode-diagnostics.js.map +1 -1
  94. package/dist/src/agent/session-persistence.js +1 -1
  95. package/dist/src/agent/session-persistence.js.map +1 -1
  96. package/dist/src/agent/spawn-env.js +33 -16
  97. package/dist/src/agent/spawn-env.js.map +1 -1
  98. package/dist/src/agent/spawn.js +176 -110
  99. package/dist/src/agent/spawn.js.map +1 -1
  100. package/dist/src/agent/watchdog.js +56 -0
  101. package/dist/src/agent/watchdog.js.map +1 -0
  102. package/dist/src/browser/actions.js +179 -70
  103. package/dist/src/browser/actions.js.map +1 -1
  104. package/dist/src/browser/connection.js +296 -19
  105. package/dist/src/browser/connection.js.map +1 -1
  106. package/dist/src/browser/index.js +4 -1
  107. package/dist/src/browser/index.js.map +1 -1
  108. package/dist/src/browser/launch-policy.js +1 -1
  109. package/dist/src/browser/launch-policy.js.map +1 -1
  110. package/dist/src/browser/primitives.js +11 -7
  111. package/dist/src/browser/primitives.js.map +1 -1
  112. package/dist/src/browser/runtime-diagnostics.js +45 -0
  113. package/dist/src/browser/runtime-diagnostics.js.map +1 -0
  114. package/dist/src/browser/runtime-orphans.js +127 -0
  115. package/dist/src/browser/runtime-orphans.js.map +1 -0
  116. package/dist/src/browser/runtime-owner-store.js +51 -0
  117. package/dist/src/browser/runtime-owner-store.js.map +1 -0
  118. package/dist/src/browser/runtime-owner.js +2 -2
  119. package/dist/src/browser/runtime-owner.js.map +1 -1
  120. package/dist/src/browser/tab-lifecycle.js +157 -0
  121. package/dist/src/browser/tab-lifecycle.js.map +1 -0
  122. package/dist/src/browser/vision.js +35 -11
  123. package/dist/src/browser/vision.js.map +1 -1
  124. package/dist/src/browser/web-ai/action-breadth.js +56 -0
  125. package/dist/src/browser/web-ai/action-breadth.js.map +1 -0
  126. package/dist/src/browser/web-ai/action-cache.js +9 -8
  127. package/dist/src/browser/web-ai/action-cache.js.map +1 -1
  128. package/dist/src/browser/web-ai/action-intent.js +64 -0
  129. package/dist/src/browser/web-ai/action-intent.js.map +1 -0
  130. package/dist/src/browser/web-ai/action-memory.js +82 -0
  131. package/dist/src/browser/web-ai/action-memory.js.map +1 -0
  132. package/dist/src/browser/web-ai/action-trace.js +11 -6
  133. package/dist/src/browser/web-ai/action-trace.js.map +1 -1
  134. package/dist/src/browser/web-ai/annotated-screenshot.js +2 -1
  135. package/dist/src/browser/web-ai/annotated-screenshot.js.map +1 -1
  136. package/dist/src/browser/web-ai/answer-artifact.js +97 -0
  137. package/dist/src/browser/web-ai/answer-artifact.js.map +1 -0
  138. package/dist/src/browser/web-ai/ax-snapshot.js +3 -2
  139. package/dist/src/browser/web-ai/ax-snapshot.js.map +1 -1
  140. package/dist/src/browser/web-ai/browser-primitives.js +10 -7
  141. package/dist/src/browser/web-ai/browser-primitives.js.map +1 -1
  142. package/dist/src/browser/web-ai/capability-registry.js +1 -1
  143. package/dist/src/browser/web-ai/capability-registry.js.map +1 -1
  144. package/dist/src/browser/web-ai/chatgpt-composer.js +12 -12
  145. package/dist/src/browser/web-ai/chatgpt-composer.js.map +1 -1
  146. package/dist/src/browser/web-ai/chatgpt-model.js +469 -50
  147. package/dist/src/browser/web-ai/chatgpt-model.js.map +1 -1
  148. package/dist/src/browser/web-ai/chatgpt-response.js +82 -10
  149. package/dist/src/browser/web-ai/chatgpt-response.js.map +1 -1
  150. package/dist/src/browser/web-ai/chatgpt.js +325 -49
  151. package/dist/src/browser/web-ai/chatgpt.js.map +1 -1
  152. package/dist/src/browser/web-ai/churn-log.js +1 -1
  153. package/dist/src/browser/web-ai/churn-log.js.map +1 -1
  154. package/dist/src/browser/web-ai/cli-sessions.js +42 -26
  155. package/dist/src/browser/web-ai/cli-sessions.js.map +1 -1
  156. package/dist/src/browser/web-ai/context-pack/builder.js +1 -1
  157. package/dist/src/browser/web-ai/context-pack/builder.js.map +1 -1
  158. package/dist/src/browser/web-ai/context-pack/file-selector.js +2 -2
  159. package/dist/src/browser/web-ai/context-pack/file-selector.js.map +1 -1
  160. package/dist/src/browser/web-ai/context-pack/report.js +1 -1
  161. package/dist/src/browser/web-ai/context-pack/report.js.map +1 -1
  162. package/dist/src/browser/web-ai/copy-markdown.js +25 -5
  163. package/dist/src/browser/web-ai/copy-markdown.js.map +1 -1
  164. package/dist/src/browser/web-ai/diagnostics.js +17 -14
  165. package/dist/src/browser/web-ai/diagnostics.js.map +1 -1
  166. package/dist/src/browser/web-ai/doctor.js +10 -6
  167. package/dist/src/browser/web-ai/doctor.js.map +1 -1
  168. package/dist/src/browser/web-ai/dom-hash.js.map +1 -1
  169. package/dist/src/browser/web-ai/errors.js +5 -22
  170. package/dist/src/browser/web-ai/errors.js.map +1 -1
  171. package/dist/src/browser/web-ai/gemini-live.js +7 -6
  172. package/dist/src/browser/web-ai/gemini-live.js.map +1 -1
  173. package/dist/src/browser/web-ai/grok-live.js +9 -5
  174. package/dist/src/browser/web-ai/grok-live.js.map +1 -1
  175. package/dist/src/browser/web-ai/index.js +5 -0
  176. package/dist/src/browser/web-ai/index.js.map +1 -1
  177. package/dist/src/browser/web-ai/observation-bundle.js +90 -0
  178. package/dist/src/browser/web-ai/observation-bundle.js.map +1 -0
  179. package/dist/src/browser/web-ai/observe-actions.js +186 -0
  180. package/dist/src/browser/web-ai/observe-actions.js.map +1 -0
  181. package/dist/src/browser/web-ai/observe-targets.js +6 -1
  182. package/dist/src/browser/web-ai/observe-targets.js.map +1 -1
  183. package/dist/src/browser/web-ai/planner-contract.js +18 -0
  184. package/dist/src/browser/web-ai/planner-contract.js.map +1 -0
  185. package/dist/src/browser/web-ai/post-action-assert.js +8 -7
  186. package/dist/src/browser/web-ai/post-action-assert.js.map +1 -1
  187. package/dist/src/browser/web-ai/product-surfaces.js +2 -1
  188. package/dist/src/browser/web-ai/product-surfaces.js.map +1 -1
  189. package/dist/src/browser/web-ai/provider-adapter.js.map +1 -1
  190. package/dist/src/browser/web-ai/question.js +14 -7
  191. package/dist/src/browser/web-ai/question.js.map +1 -1
  192. package/dist/src/browser/web-ai/ref-registry.js.map +1 -1
  193. package/dist/src/browser/web-ai/self-heal.js +20 -14
  194. package/dist/src/browser/web-ai/self-heal.js.map +1 -1
  195. package/dist/src/browser/web-ai/session-store.js +61 -1
  196. package/dist/src/browser/web-ai/session-store.js.map +1 -1
  197. package/dist/src/browser/web-ai/session.js +43 -2
  198. package/dist/src/browser/web-ai/session.js.map +1 -1
  199. package/dist/src/browser/web-ai/source-audit.js +116 -0
  200. package/dist/src/browser/web-ai/source-audit.js.map +1 -0
  201. package/dist/src/browser/web-ai/tab-finalizer.js +18 -0
  202. package/dist/src/browser/web-ai/tab-finalizer.js.map +1 -0
  203. package/dist/src/browser/web-ai/tab-lease-store.js +390 -0
  204. package/dist/src/browser/web-ai/tab-lease-store.js.map +1 -0
  205. package/dist/src/browser/web-ai/tab-pool.js +44 -0
  206. package/dist/src/browser/web-ai/tab-pool.js.map +1 -0
  207. package/dist/src/browser/web-ai/target-resolver.js +31 -0
  208. package/dist/src/browser/web-ai/target-resolver.js.map +1 -0
  209. package/dist/src/browser/web-ai/trace-persistence.js +4 -2
  210. package/dist/src/browser/web-ai/trace-persistence.js.map +1 -1
  211. package/dist/src/browser/web-ai/vendor-editor-contract.js.map +1 -1
  212. package/dist/src/browser/web-ai/watcher.js +8 -7
  213. package/dist/src/browser/web-ai/watcher.js.map +1 -1
  214. package/dist/src/cli/acp-client.js +40 -26
  215. package/dist/src/cli/acp-client.js.map +1 -1
  216. package/dist/src/cli/command-context.js +3 -3
  217. package/dist/src/cli/command-context.js.map +1 -1
  218. package/dist/src/cli/commands.js +25 -16
  219. package/dist/src/cli/commands.js.map +1 -1
  220. package/dist/src/cli/compact.js.map +1 -1
  221. package/dist/src/cli/handlers-completions.js +6 -4
  222. package/dist/src/cli/handlers-completions.js.map +1 -1
  223. package/dist/src/cli/handlers-runtime.js +45 -38
  224. package/dist/src/cli/handlers-runtime.js.map +1 -1
  225. package/dist/src/cli/handlers.js +44 -36
  226. package/dist/src/cli/handlers.js.map +1 -1
  227. package/dist/src/cli/readiness.js +3 -1
  228. package/dist/src/cli/readiness.js.map +1 -1
  229. package/dist/src/cli/registry.js +1 -1
  230. package/dist/src/cli/registry.js.map +1 -1
  231. package/dist/src/cli/tui/overlay.js +4 -1
  232. package/dist/src/cli/tui/overlay.js.map +1 -1
  233. package/dist/src/cli/types.js +4 -0
  234. package/dist/src/cli/types.js.map +1 -0
  235. package/dist/src/command-contract/catalog.js +1 -1
  236. package/dist/src/command-contract/catalog.js.map +1 -1
  237. package/dist/src/command-contract/help-renderer.js +1 -1
  238. package/dist/src/command-contract/help-renderer.js.map +1 -1
  239. package/dist/src/core/browser-open-default.js +13 -0
  240. package/dist/src/core/browser-open-default.js.map +1 -0
  241. package/dist/src/core/browser-open.js +41 -0
  242. package/dist/src/core/browser-open.js.map +1 -0
  243. package/dist/src/core/bus.js +13 -2
  244. package/dist/src/core/bus.js.map +1 -1
  245. package/dist/src/core/compact.js +5 -4
  246. package/dist/src/core/compact.js.map +1 -1
  247. package/dist/src/core/config.js +51 -52
  248. package/dist/src/core/config.js.map +1 -1
  249. package/dist/src/core/db.js +48 -6
  250. package/dist/src/core/db.js.map +1 -1
  251. package/dist/src/core/employees.js +9 -8
  252. package/dist/src/core/employees.js.map +1 -1
  253. package/dist/src/core/instance.js +7 -6
  254. package/dist/src/core/instance.js.map +1 -1
  255. package/dist/src/core/logger.js +1 -1
  256. package/dist/src/core/logger.js.map +1 -1
  257. package/dist/src/core/main-session.js +7 -7
  258. package/dist/src/core/main-session.js.map +1 -1
  259. package/dist/src/core/path-expand.js +10 -0
  260. package/dist/src/core/path-expand.js.map +1 -0
  261. package/dist/src/core/runtime-path.js +1 -1
  262. package/dist/src/core/runtime-path.js.map +1 -1
  263. package/dist/src/core/runtime-settings.js +13 -13
  264. package/dist/src/core/runtime-settings.js.map +1 -1
  265. package/dist/src/core/settings-merge.js +14 -14
  266. package/dist/src/core/settings-merge.js.map +1 -1
  267. package/dist/src/core/strip-undefined.js +13 -0
  268. package/dist/src/core/strip-undefined.js.map +1 -0
  269. package/dist/src/core/tcc.js +1 -1
  270. package/dist/src/core/tcc.js.map +1 -1
  271. package/dist/src/discord/bot.js +19 -18
  272. package/dist/src/discord/bot.js.map +1 -1
  273. package/dist/src/discord/channel-types.js +14 -0
  274. package/dist/src/discord/channel-types.js.map +1 -0
  275. package/dist/src/discord/commands.js +7 -6
  276. package/dist/src/discord/commands.js.map +1 -1
  277. package/dist/src/discord/discord-file.js.map +1 -1
  278. package/dist/src/discord/forwarder.js +3 -3
  279. package/dist/src/discord/forwarder.js.map +1 -1
  280. package/dist/src/http/error-middleware.js +3 -3
  281. package/dist/src/http/error-middleware.js.map +1 -1
  282. package/dist/src/http/response.js +2 -2
  283. package/dist/src/http/response.js.map +1 -1
  284. package/dist/src/ide/diff.js +7 -7
  285. package/dist/src/ide/diff.js.map +1 -1
  286. package/dist/src/manager/board/routes.js +28 -27
  287. package/dist/src/manager/board/routes.js.map +1 -1
  288. package/dist/src/manager/dashboard-home.js +3 -5
  289. package/dist/src/manager/dashboard-home.js.map +1 -1
  290. package/dist/src/manager/dashboard-service.js +2 -2
  291. package/dist/src/manager/dashboard-service.js.map +1 -1
  292. package/dist/src/manager/health-history.js +10 -9
  293. package/dist/src/manager/health-history.js.map +1 -1
  294. package/dist/src/manager/launchd-service.js +2 -2
  295. package/dist/src/manager/launchd-service.js.map +1 -1
  296. package/dist/src/manager/lifecycle-helpers.js +7 -6
  297. package/dist/src/manager/lifecycle-helpers.js.map +1 -1
  298. package/dist/src/manager/lifecycle.js +7 -6
  299. package/dist/src/manager/lifecycle.js.map +1 -1
  300. package/dist/src/manager/logs.js +18 -18
  301. package/dist/src/manager/logs.js.map +1 -1
  302. package/dist/src/manager/metadata.js +10 -2
  303. package/dist/src/manager/metadata.js.map +1 -1
  304. package/dist/src/manager/notes/assets.js +216 -0
  305. package/dist/src/manager/notes/assets.js.map +1 -0
  306. package/dist/src/manager/notes/capabilities.js +56 -0
  307. package/dist/src/manager/notes/capabilities.js.map +1 -0
  308. package/dist/src/manager/notes/constants.js +11 -0
  309. package/dist/src/manager/notes/constants.js.map +1 -0
  310. package/dist/src/manager/notes/frontmatter.js +120 -0
  311. package/dist/src/manager/notes/frontmatter.js.map +1 -0
  312. package/dist/src/manager/notes/link-resolver.js +96 -0
  313. package/dist/src/manager/notes/link-resolver.js.map +1 -0
  314. package/dist/src/manager/notes/path-guards.js +4 -0
  315. package/dist/src/manager/notes/path-guards.js.map +1 -1
  316. package/dist/src/manager/notes/remote-assets.js +128 -0
  317. package/dist/src/manager/notes/remote-assets.js.map +1 -0
  318. package/dist/src/manager/notes/routes.js +63 -13
  319. package/dist/src/manager/notes/routes.js.map +1 -1
  320. package/dist/src/manager/notes/store.js +3 -2
  321. package/dist/src/manager/notes/store.js.map +1 -1
  322. package/dist/src/manager/notes/system-trash.js +3 -3
  323. package/dist/src/manager/notes/system-trash.js.map +1 -1
  324. package/dist/src/manager/notes/vault-index.js +220 -0
  325. package/dist/src/manager/notes/vault-index.js.map +1 -0
  326. package/dist/src/manager/notes/watcher.js +27 -0
  327. package/dist/src/manager/notes/watcher.js.map +1 -0
  328. package/dist/src/manager/notes/wiki-links.js +109 -0
  329. package/dist/src/manager/notes/wiki-links.js.map +1 -0
  330. package/dist/src/manager/process-verify.js +29 -0
  331. package/dist/src/manager/process-verify.js.map +1 -1
  332. package/dist/src/manager/profiles.js +3 -2
  333. package/dist/src/manager/profiles.js.map +1 -1
  334. package/dist/src/manager/registry.js +60 -58
  335. package/dist/src/manager/registry.js.map +1 -1
  336. package/dist/src/manager/routes/electron-metrics.js +22 -22
  337. package/dist/src/manager/routes/electron-metrics.js.map +1 -1
  338. package/dist/src/manager/scan.js +2 -2
  339. package/dist/src/manager/scan.js.map +1 -1
  340. package/dist/src/manager/schedule/routes.js +24 -23
  341. package/dist/src/manager/schedule/routes.js.map +1 -1
  342. package/dist/src/manager/server.js +28 -28
  343. package/dist/src/manager/server.js.map +1 -1
  344. package/dist/src/manager/systemd-service.js +1 -1
  345. package/dist/src/manager/systemd-service.js.map +1 -1
  346. package/dist/src/memory/bootstrap.js +5 -4
  347. package/dist/src/memory/bootstrap.js.map +1 -1
  348. package/dist/src/memory/heartbeat-schedule.js +10 -10
  349. package/dist/src/memory/heartbeat-schedule.js.map +1 -1
  350. package/dist/src/memory/heartbeat.js +23 -22
  351. package/dist/src/memory/heartbeat.js.map +1 -1
  352. package/dist/src/memory/indexing.js.map +1 -1
  353. package/dist/src/memory/keyword-expand.js +1 -1
  354. package/dist/src/memory/keyword-expand.js.map +1 -1
  355. package/dist/src/memory/memory.js +2 -2
  356. package/dist/src/memory/memory.js.map +1 -1
  357. package/dist/src/memory/runtime.js +6 -5
  358. package/dist/src/memory/runtime.js.map +1 -1
  359. package/dist/src/memory/shared.js +2 -1
  360. package/dist/src/memory/shared.js.map +1 -1
  361. package/dist/src/memory/worklog.js +1 -1
  362. package/dist/src/memory/worklog.js.map +1 -1
  363. package/dist/src/messaging/runtime.js +13 -10
  364. package/dist/src/messaging/runtime.js.map +1 -1
  365. package/dist/src/messaging/send.js +16 -15
  366. package/dist/src/messaging/send.js.map +1 -1
  367. package/dist/src/orchestrator/collect.js +6 -6
  368. package/dist/src/orchestrator/collect.js.map +1 -1
  369. package/dist/src/orchestrator/distribute.js +112 -77
  370. package/dist/src/orchestrator/distribute.js.map +1 -1
  371. package/dist/src/orchestrator/gateway.js +6 -5
  372. package/dist/src/orchestrator/gateway.js.map +1 -1
  373. package/dist/src/orchestrator/pipeline.js +42 -42
  374. package/dist/src/orchestrator/pipeline.js.map +1 -1
  375. package/dist/src/orchestrator/state-machine.js +3 -3
  376. package/dist/src/orchestrator/state-machine.js.map +1 -1
  377. package/dist/src/orchestrator/worker-registry.js +4 -3
  378. package/dist/src/orchestrator/worker-registry.js.map +1 -1
  379. package/dist/src/prompt/builder.js +24 -19
  380. package/dist/src/prompt/builder.js.map +1 -1
  381. package/dist/src/prompt/templates/a1-system.md +15 -10
  382. package/dist/src/prompt/templates/control-system.md +9 -7
  383. package/dist/src/prompt/templates/employee.md +5 -4
  384. package/dist/src/prompt/templates/vision-click.md +1 -1
  385. package/dist/src/routes/_http-error.js +15 -0
  386. package/dist/src/routes/_http-error.js.map +1 -0
  387. package/dist/src/routes/avatar.js +6 -5
  388. package/dist/src/routes/avatar.js.map +1 -1
  389. package/dist/src/routes/browser.js +132 -45
  390. package/dist/src/routes/browser.js.map +1 -1
  391. package/dist/src/routes/employees.js +28 -21
  392. package/dist/src/routes/employees.js.map +1 -1
  393. package/dist/src/routes/heartbeat.js +12 -9
  394. package/dist/src/routes/heartbeat.js.map +1 -1
  395. package/dist/src/routes/i18n.js +13 -7
  396. package/dist/src/routes/i18n.js.map +1 -1
  397. package/dist/src/routes/jaw-memory.js +15 -11
  398. package/dist/src/routes/jaw-memory.js.map +1 -1
  399. package/dist/src/routes/memory.js +25 -20
  400. package/dist/src/routes/memory.js.map +1 -1
  401. package/dist/src/routes/messaging.js +50 -29
  402. package/dist/src/routes/messaging.js.map +1 -1
  403. package/dist/src/routes/orchestrate.js +38 -24
  404. package/dist/src/routes/orchestrate.js.map +1 -1
  405. package/dist/src/routes/quota.js +81 -17
  406. package/dist/src/routes/quota.js.map +1 -1
  407. package/dist/src/routes/settings.js +28 -18
  408. package/dist/src/routes/settings.js.map +1 -1
  409. package/dist/src/routes/skills.js +22 -13
  410. package/dist/src/routes/skills.js.map +1 -1
  411. package/dist/src/routes/traces.js +77 -0
  412. package/dist/src/routes/traces.js.map +1 -0
  413. package/dist/src/security/path-guards.js +2 -1
  414. package/dist/src/security/path-guards.js.map +1 -1
  415. package/dist/src/shared/tool-log-sanitize.js +191 -0
  416. package/dist/src/shared/tool-log-sanitize.js.map +1 -0
  417. package/dist/src/telegram/bot.js +65 -55
  418. package/dist/src/telegram/bot.js.map +1 -1
  419. package/dist/src/telegram/forwarder.js +5 -9
  420. package/dist/src/telegram/forwarder.js.map +1 -1
  421. package/dist/src/telegram/telegram-file.js +28 -24
  422. package/dist/src/telegram/telegram-file.js.map +1 -1
  423. package/dist/src/telegram/voice.js +4 -3
  424. package/dist/src/telegram/voice.js.map +1 -1
  425. package/dist/src/trace/redact.js +50 -0
  426. package/dist/src/trace/redact.js.map +1 -0
  427. package/dist/src/trace/store.js +162 -0
  428. package/dist/src/trace/store.js.map +1 -0
  429. package/dist/src/trace/types.js +2 -0
  430. package/dist/src/trace/types.js.map +1 -0
  431. package/dist/src/types/cli-engine.js +34 -0
  432. package/dist/src/types/cli-engine.js.map +1 -0
  433. package/dist/src/types/cli-events.js +31 -0
  434. package/dist/src/types/cli-events.js.map +1 -0
  435. package/package.json +22 -2
  436. package/public/css/tool-ui.css +3 -1
  437. package/public/css/trace-drawer.css +48 -0
  438. package/public/dist/assets/{AdvancedExport-3WAYIabE.js → AdvancedExport-DJZ2VmBR.js} +1 -1
  439. package/public/dist/assets/Agent-CgpLT8IY.js +1 -0
  440. package/public/dist/assets/Browser-CrkiQoB8.js +1 -0
  441. package/public/dist/assets/{ChannelsDiscord-UzFPlWT4.js → ChannelsDiscord-CVUC22D4.js} +1 -1
  442. package/public/dist/assets/{ChannelsTelegram-DNWtPX0w.js → ChannelsTelegram-DEatIQNM.js} +1 -1
  443. package/public/dist/assets/{DashboardMeta-Y_6nVeJO.js → DashboardMeta-BKoxRc7i.js} +1 -1
  444. package/public/dist/assets/{Display-D8vGOl4s.js → Display-DnNGV9Km.js} +1 -1
  445. package/public/dist/assets/{Employees-YR_sIRK4.js → Employees-DZ2iJYKy.js} +1 -1
  446. package/public/dist/assets/{HealthBadge-CPePajyU.js → HealthBadge-Cq2c7G9s.js} +1 -1
  447. package/public/dist/assets/{Heartbeat-DTpAULQR.js → Heartbeat-BML6eTXZ.js} +1 -1
  448. package/public/dist/assets/{Mcp-DM-PgG6z.js → Mcp-BlEviQ3h.js} +1 -1
  449. package/public/dist/assets/{Memory-C_LvJnkn.js → Memory-BRyH80He.js} +1 -1
  450. package/public/dist/assets/MilkdownWysiwygEditor-Cm3uXfWf.js +52 -0
  451. package/public/dist/assets/ModelProvider-DxyR7EL9.js +1 -0
  452. package/public/dist/assets/Network-DDOOESh1.js +1 -0
  453. package/public/dist/assets/{Permissions-B1naJjjw.js → Permissions-Br0eSbKb.js} +1 -1
  454. package/public/dist/assets/{Permissions-BKffrMJD.js → Permissions-QHkzStqQ.js} +1 -1
  455. package/public/dist/assets/{Profile-DIqjSe2C.js → Profile-C79NKumk.js} +1 -1
  456. package/public/dist/assets/{Prompts-BMfbV6Y4.js → Prompts-BmiIDiXW.js} +1 -1
  457. package/public/dist/assets/{SpeechKeys-DjiQTzSL.js → SpeechKeys-B8304XJK.js} +1 -1
  458. package/public/dist/assets/app-Be58Cs3Y.js +32 -0
  459. package/public/dist/assets/{app-BzvwJJiv.css → app-CphocJzo.css} +1 -1
  460. package/public/dist/assets/{dist-DTvxN3ux.js → dist-BD0UXfgF2.js} +1 -1
  461. package/public/dist/assets/{dist-CASeq-Tl.js → dist-BNfXO3Yr.js} +1 -1
  462. package/public/dist/assets/{dist-BMPiaUzF.js → dist-BUnPYbK3.js} +1 -1
  463. package/public/dist/assets/{dist-CT_X3hVT.js → dist-BZosRD2u.js} +1 -1
  464. package/public/dist/assets/{dist-4J6YbNXv.js → dist-Bd9PlnQm.js} +1 -1
  465. package/public/dist/assets/{dist-BcZjyn5g.js → dist-BsT5UdNP.js} +1 -1
  466. package/public/dist/assets/{dist-BfBhOPR-.js → dist-CIuXW-sc.js} +1 -1
  467. package/public/dist/assets/{dist-BMiCig3A2.js → dist-CL4PTYWf.js} +1 -1
  468. package/public/dist/assets/{dist-VyP6-HLb.js → dist-Ch5VAlV9.js} +1 -1
  469. package/public/dist/assets/dist-ClqO40BE.js +1 -0
  470. package/public/dist/assets/{dist-c98Tp7bP.js → dist-Cp42cMcI.js} +1 -1
  471. package/public/dist/assets/{dist-CIlYL1qe.js → dist-CpUK8ypo.js} +1 -1
  472. package/public/dist/assets/dist-CxeLAw2Y.js +1 -0
  473. package/public/dist/assets/dist-D2SH8nxa.js +1 -0
  474. package/public/dist/assets/{dist-84fwQ7bO.js → dist-D6cUXP7K.js} +1 -1
  475. package/public/dist/assets/{dist-BOCcQAyF.js → dist-D7bCuS3f.js} +1 -1
  476. package/public/dist/assets/{dist-DMmpfLVP.js → dist-DFYRUAjN.js} +1 -1
  477. package/public/dist/assets/{dist-DdY6pTJr.js → dist-DZsFVYF4.js} +1 -1
  478. package/public/dist/assets/{dist-B0p3Eyme.js → dist-Db16ogVk.js} +1 -1
  479. package/public/dist/assets/{dist-DlnNtr6L.js → dist-DfodGES_.js} +1 -1
  480. package/public/dist/assets/{dist-DO9so2a2.js → dist-SU-YTAIg.js} +1 -1
  481. package/public/dist/assets/{dist-DUjXiMLP.js → dist-UYn7T-GH.js} +1 -1
  482. package/public/dist/assets/{dist-BW1409rz.js → dist-W51oDoeA.js} +1 -1
  483. package/public/dist/assets/{dist-BimBQZx1.js → dist-eU7TyC86.js} +1 -1
  484. package/public/dist/assets/dist-l9HH00ip.js +1 -0
  485. package/public/dist/assets/{dist-BrOPNxdH.js → dist-urPTQzXL.js} +1 -1
  486. package/public/dist/assets/{dist-AloEV3J52.js → dist-yHP6L0Ty.js} +1 -1
  487. package/public/dist/assets/{employees-Bbabvbyx.js → employees-CxdghzoD.js} +7 -7
  488. package/public/dist/assets/{error-normalize-DdvKGLt_.js → error-normalize-5n-zlEQ3.js} +1 -1
  489. package/public/dist/assets/insert-image-markdown-DIEa-zjk.js +22 -0
  490. package/public/dist/assets/{manager-DyB2ZUr9.css → manager-DEiyrWDP.css} +1 -1
  491. package/public/dist/assets/manager-UEXd1_9T.js +25 -0
  492. package/public/dist/assets/{memory-B_plvcuQ.js → memory-CsMNkYtv.js} +9 -9
  493. package/public/dist/assets/memory-DXad_DPO.js +1 -0
  494. package/public/dist/assets/{page-shell-DML_HneX.js → page-shell-D5tbivHH.js} +1 -1
  495. package/public/dist/assets/{render-DEhbfUAW.js → render-DGQX46ei.js} +2 -2
  496. package/public/dist/assets/{settings-D7F-_kYG.js → settings-BH213Yv3.js} +14 -14
  497. package/public/dist/assets/settings-DXT87G2U.js +1 -0
  498. package/public/dist/assets/settings-client-ajlwI-oK.js +1 -0
  499. package/public/dist/assets/skills-5o_1v0nz.js +1 -0
  500. package/public/dist/assets/{skills-DoGJOc0D.js → skills-CQtCtHPA.js} +6 -6
  501. package/public/dist/assets/slash-commands-D4-hrrmh.js +1 -0
  502. package/public/dist/assets/{slash-commands-khNFPOyF.js → slash-commands-Dzk1xHWS.js} +1 -1
  503. package/public/dist/assets/trace-drawer-SRKcfm2S.js +15 -0
  504. package/public/dist/assets/ui-CdRKN2S6.js +141 -0
  505. package/public/dist/assets/ui-n43jmg_f.js +1 -0
  506. package/public/dist/assets/{ws-B2aJ-nD2.js → ws-CTHQFzM1.js} +8 -8
  507. package/public/dist/index.html +2 -2
  508. package/public/dist/manager/index.html +2 -2
  509. package/public/index.html +1 -0
  510. package/public/js/constants.ts +5 -5
  511. package/public/js/diagram/iframe-renderer.ts +11 -11
  512. package/public/js/features/chat.ts +1 -1
  513. package/public/js/features/memory.ts +10 -10
  514. package/public/js/features/pending-queue.ts +2 -2
  515. package/public/js/features/process-block.ts +257 -29
  516. package/public/js/features/process-step-match.ts +18 -0
  517. package/public/js/features/settings-cli-status.ts +1 -1
  518. package/public/js/features/settings-stt.ts +37 -11
  519. package/public/js/features/settings-templates.ts +2 -2
  520. package/public/js/features/slash-commands.ts +1 -1
  521. package/public/js/features/tool-ui.ts +13 -7
  522. package/public/js/features/trace-drawer.ts +122 -0
  523. package/public/js/icons.ts +1 -1
  524. package/public/js/main.ts +28 -28
  525. package/public/js/provider-icons.ts +1 -1
  526. package/public/js/render.ts +29 -27
  527. package/public/js/sanitizer.ts +4 -0
  528. package/public/js/ui.ts +234 -68
  529. package/public/js/virtual-scroll.ts +19 -33
  530. package/public/js/ws.ts +22 -10
  531. package/public/manager/src/App.tsx +34 -6
  532. package/public/manager/src/api.ts +55 -1
  533. package/public/manager/src/components/ActivityTimeline.tsx +1 -1
  534. package/public/manager/src/components/InstanceDetailPanel.tsx +2 -2
  535. package/public/manager/src/components/InstanceGroups.tsx +5 -5
  536. package/public/manager/src/components/InstanceListContent.tsx +1 -1
  537. package/public/manager/src/dashboard-features.ts +1 -1
  538. package/public/manager/src/manager-notes.css +49 -2
  539. package/public/manager/src/notes/MarkdownEditor.tsx +7 -3
  540. package/public/manager/src/notes/NotesFileTree.tsx +45 -6
  541. package/public/manager/src/notes/NotesSidebar.tsx +24 -55
  542. package/public/manager/src/notes/NotesWorkspace.tsx +50 -3
  543. package/public/manager/src/notes/image-assets/clipboard-images.ts +100 -0
  544. package/public/manager/src/notes/image-assets/insert-image-markdown.ts +85 -0
  545. package/public/manager/src/notes/notes-api.ts +2 -0
  546. package/public/manager/src/notes/notes-types.ts +8 -1
  547. package/public/manager/src/notes/rendering/MarkdownRenderer.tsx +6 -0
  548. package/public/manager/src/notes/rendering/markdown-render-security.ts +19 -1
  549. package/public/manager/src/notes/rich-markdown/paste-policy.ts +6 -2
  550. package/public/manager/src/notes/rich-markdown/rich-markdown-extension.ts +5 -5
  551. package/public/manager/src/notes/rich-markdown/rich-widget.ts +8 -8
  552. package/public/manager/src/notes/useNotesExternalSync.ts +37 -0
  553. package/public/manager/src/notes/useNotesModel.ts +91 -0
  554. package/public/manager/src/notes/wysiwyg/MilkdownWysiwygEditor.tsx +157 -17
  555. package/public/manager/src/notes/wysiwyg/milkdown-block-keymap.ts +14 -2
  556. package/public/manager/src/notes/wysiwyg/milkdown-code-block-view.ts +20 -20
  557. package/public/manager/src/notes/wysiwyg/milkdown-heading-source-view.ts +8 -8
  558. package/public/manager/src/notes/wysiwyg/milkdown-math.ts +25 -25
  559. package/public/manager/src/settings/pages/Browser.tsx +38 -20
  560. package/public/manager/src/settings/pages/ModelProvider.tsx +11 -9
  561. package/public/manager/src/settings/pages/Network.tsx +10 -10
  562. package/public/manager/src/settings/pages/components/HealthBadge.tsx +12 -12
  563. package/public/manager/src/settings/pages/components/agent/runtime-employees-helpers.ts +12 -10
  564. package/public/manager/src/settings/pages/components/employees-helpers.ts +9 -9
  565. package/public/manager/src/settings/pages/components/heartbeat-helpers.ts +13 -13
  566. package/public/manager/src/settings/pages/components/memory-helpers.ts +4 -4
  567. package/public/manager/src/settings/pages/mcp-helpers.ts +7 -7
  568. package/public/manager/src/settings/settings-client.ts +4 -3
  569. package/public/manager/src/sync/IframeBridge.tsx +29 -0
  570. package/public/manager/src/sync/VisibilityBridge.tsx +24 -0
  571. package/public/manager/src/sync/invalidation-bus.ts +30 -0
  572. package/public/manager/src/sync/useInvalidationSubscription.ts +19 -0
  573. package/public/manager/src/types.ts +101 -0
  574. package/scripts/check-strict-baseline.mjs +255 -0
  575. package/scripts/claim-audit.mjs +159 -0
  576. package/scripts/i18n-registry.ts +4 -4
  577. package/scripts/install-officecli.sh +2 -2
  578. package/scripts/install-wsl.sh +2 -1
  579. package/scripts/release-gates.mjs +347 -0
  580. package/scripts/release-preview.sh +3 -0
  581. package/scripts/release.sh +4 -0
  582. package/scripts/smoke/opencode-external-dir-smoke.ts +14 -5
  583. package/public/dist/assets/Agent-BYdzZwD0.js +0 -1
  584. package/public/dist/assets/Browser-CkGeczuN.js +0 -1
  585. package/public/dist/assets/MilkdownWysiwygEditor-B7k9bAey.js +0 -52
  586. package/public/dist/assets/ModelProvider-CX3Qhowu.js +0 -1
  587. package/public/dist/assets/Network-DfPLFAvw.js +0 -1
  588. package/public/dist/assets/app-DLYoRkU9.js +0 -32
  589. package/public/dist/assets/dist-8zNAQAIa.js +0 -1
  590. package/public/dist/assets/dist-BgeY6nvK.js +0 -1
  591. package/public/dist/assets/dist-BzDGGxHQ.js +0 -1
  592. package/public/dist/assets/dist-D3YKbVi-.js +0 -1
  593. package/public/dist/assets/manager-CUSgFbMO.js +0 -25
  594. package/public/dist/assets/markdown-render-security-DJfJPWO-.js +0 -22
  595. package/public/dist/assets/memory-DQ6dU0qs.js +0 -1
  596. package/public/dist/assets/settings-DxLPUbpj.js +0 -1
  597. package/public/dist/assets/settings-client-CGf3uPPf.js +0 -1
  598. package/public/dist/assets/skills-yMfNYJ8m.js +0 -1
  599. package/public/dist/assets/slash-commands-CZcwr1W6.js +0 -1
  600. package/public/dist/assets/ui-04YlOMgn.js +0 -136
  601. package/public/dist/assets/ui-D6hlMjRq.js +0 -1
  602. /package/public/dist/assets/{InlineWarn-CqgWEC41.js → InlineWarn-BooBRm7o.js} +0 -0
  603. /package/public/dist/assets/{agent-meta-puNn13DV.js → agent-meta-DHddpWHQ.js} +0 -0
  604. /package/public/dist/assets/{fields-DH9JS3mb.js → fields-BtncIZYA.js} +0 -0
  605. /package/public/dist/assets/{mermaid-loader-6XC0y10y.js → mermaid-loader-BEFIOoJn.js} +0 -0
  606. /package/public/dist/assets/{path-utils-CtsDDGZg.js → path-utils-BuEEtj9w.js} +0 -0
  607. /package/public/dist/assets/{w3c-keyname-VSld09PZ.js → w3c-keyname-IiiZScED.js} +0 -0
@@ -0,0 +1,122 @@
1
+ import { api } from '../api.js';
2
+ import { escapeHtml } from '../render.js';
3
+
4
+ interface TraceSummary {
5
+ id: string; cli: string; model: string; agentLabel: string; status: string;
6
+ rawRetentionStatus: string; eventCount: number; byteCount: number; startedAt: number;
7
+ }
8
+ interface TraceEventListItem {
9
+ seq: number; source: string; event_type?: string; eventType?: string; preview?: string;
10
+ bytes?: number; retention_status?: string; retentionStatus?: string; created_at?: number; createdAt?: number;
11
+ }
12
+ interface TraceEventDetail extends TraceEventListItem { runId: string; raw: string; }
13
+ interface TraceEventsPage { total: number; events: TraceEventListItem[]; }
14
+
15
+ const PAGE_SIZE = 80;
16
+ let currentRunId = '';
17
+ let loadedCount = 0;
18
+ let totalCount = 0;
19
+ let loading = false;
20
+
21
+ function eventTypeOf(event: TraceEventListItem): string { return event.eventType || event.event_type || 'event'; }
22
+
23
+ function ensureDrawer(): HTMLElement {
24
+ let overlay = document.getElementById('traceDrawerOverlay') as HTMLElement | null;
25
+ if (overlay) return overlay;
26
+ overlay = document.createElement('div');
27
+ overlay.id = 'traceDrawerOverlay';
28
+ overlay.className = 'trace-drawer-overlay';
29
+ overlay.innerHTML = `<aside class="trace-drawer" role="dialog" aria-modal="true" aria-labelledby="traceDrawerTitle">
30
+ <header class="trace-drawer-header">
31
+ <div><p class="trace-drawer-kicker">Raw trace</p><h2 id="traceDrawerTitle">Trace</h2></div>
32
+ <button class="trace-drawer-close" type="button" aria-label="Close trace drawer">×</button>
33
+ </header>
34
+ <section class="trace-drawer-meta" id="traceDrawerMeta"></section>
35
+ <section class="trace-drawer-body">
36
+ <div class="trace-event-list" id="traceEventList"></div>
37
+ <pre class="trace-event-raw" id="traceEventRaw">Select an event.</pre>
38
+ </section>
39
+ <footer class="trace-drawer-footer"><button class="trace-load-more" type="button">Load more</button></footer>
40
+ </aside>`;
41
+ document.body.appendChild(overlay);
42
+ overlay.addEventListener('click', event => {
43
+ const target = event.target as HTMLElement | null;
44
+ if (!target) return;
45
+ if (target === overlay || target.closest('.trace-drawer-close')) closeTraceDrawer();
46
+ const row = target.closest('.trace-event-row') as HTMLElement | null;
47
+ if (row) void loadEventDetail(row.dataset['runId'] || '', Number(row.dataset['seq'] || 0));
48
+ if (target.closest('.trace-load-more')) void loadNextPage();
49
+ });
50
+ document.addEventListener('keydown', event => {
51
+ if (event.key === 'Escape' && overlay?.classList.contains('open')) closeTraceDrawer();
52
+ });
53
+ return overlay;
54
+ }
55
+
56
+ function setRaw(text: string): void {
57
+ const raw = document.getElementById('traceEventRaw');
58
+ if (raw) raw.textContent = text;
59
+ }
60
+ function closeTraceDrawer(): void { document.getElementById('traceDrawerOverlay')?.classList.remove('open'); }
61
+
62
+ function renderSummary(summary: TraceSummary): void {
63
+ const title = document.getElementById('traceDrawerTitle');
64
+ if (title) title.textContent = `${summary.cli || 'agent'} trace`;
65
+ const meta = document.getElementById('traceDrawerMeta');
66
+ if (!meta) return;
67
+ meta.innerHTML = [
68
+ ['run', summary.id], ['model', summary.model || '-'], ['agent', summary.agentLabel || '-'],
69
+ ['status', summary.status], ['events', `${summary.eventCount}`], ['bytes', `${summary.byteCount}`],
70
+ ['retention', summary.rawRetentionStatus],
71
+ ].map(([label, value]) => `<span><b>${escapeHtml(label)}</b>${escapeHtml(value)}</span>`).join('');
72
+ }
73
+
74
+ function renderEventRows(events: TraceEventListItem[]): void {
75
+ const list = document.getElementById('traceEventList');
76
+ if (!list) return;
77
+ const html = events.map(event => {
78
+ const seq = Number(event.seq || 0);
79
+ return `<button class="trace-event-row" type="button" data-run-id="${escapeHtml(currentRunId)}" data-seq="${seq}">
80
+ <span class="trace-event-seq">#${seq}</span><span class="trace-event-source">${escapeHtml(event.source || 'trace')}</span>
81
+ <span class="trace-event-type">${escapeHtml(eventTypeOf(event))}</span><span class="trace-event-preview">${escapeHtml(event.preview || '')}</span>
82
+ </button>`;
83
+ }).join('');
84
+ list.insertAdjacentHTML('beforeend', html);
85
+ }
86
+
87
+ async function loadNextPage(): Promise<void> {
88
+ if (!currentRunId || loading || (loadedCount >= totalCount && totalCount > 0)) return;
89
+ loading = true;
90
+ const page = await api<TraceEventsPage>(`/api/traces/${encodeURIComponent(currentRunId)}/events?offset=${loadedCount}&limit=${PAGE_SIZE}`);
91
+ loading = false;
92
+ if (!page) { setRaw('Trace events could not be loaded.'); return; }
93
+ totalCount = page.total || 0;
94
+ loadedCount += page.events.length;
95
+ renderEventRows(page.events);
96
+ const more = document.querySelector('.trace-load-more') as HTMLButtonElement | null;
97
+ if (more) more.disabled = loadedCount >= totalCount;
98
+ }
99
+
100
+ async function loadEventDetail(runId: string, seq: number): Promise<void> {
101
+ if (!runId || !Number.isInteger(seq) || seq < 1) return;
102
+ setRaw('Loading event...');
103
+ const detail = await api<TraceEventDetail>(`/api/traces/${encodeURIComponent(runId)}/events/${seq}`);
104
+ setRaw(detail?.raw || (detail ? '(empty trace event)' : 'Trace event could not be loaded.'));
105
+ }
106
+
107
+ export async function openTraceDrawer(runId: string, seq?: number): Promise<void> {
108
+ const overlay = ensureDrawer();
109
+ currentRunId = runId;
110
+ loadedCount = 0;
111
+ totalCount = 0;
112
+ const list = document.getElementById('traceEventList');
113
+ if (list) list.innerHTML = '';
114
+ setRaw('Loading trace...');
115
+ overlay.classList.add('open');
116
+ const summary = await api<TraceSummary>(`/api/traces/${encodeURIComponent(runId)}`);
117
+ if (!summary) { setRaw('Trace is unavailable or internal-only.'); return; }
118
+ renderSummary(summary);
119
+ totalCount = summary.eventCount || 0;
120
+ await loadNextPage();
121
+ if (seq) await loadEventDetail(runId, seq);
122
+ }
@@ -269,7 +269,7 @@ export function emojiToStatus(emoji: string): 'done' | 'error' | null {
269
269
  export function hydrateIcons(root: Element = document.body): void {
270
270
  const els = root.querySelectorAll<HTMLElement>('[data-icon]');
271
271
  for (const el of els) {
272
- const name = el.dataset.icon as IconName;
272
+ const name = el.dataset['icon'] as IconName;
273
273
  if (name && ICONS[name]) {
274
274
  el.innerHTML = ICONS[name];
275
275
  el.classList.add('icon-hydrated');
package/public/js/main.ts CHANGED
@@ -112,7 +112,7 @@ initPendingQueue();
112
112
  document.getElementById('filePreviewClear')?.addEventListener('click', clearAttachedFiles);
113
113
  document.getElementById('filePreviewList')?.addEventListener('click', (e) => {
114
114
  const btn = (e.target as HTMLElement)?.closest('[data-file-idx]') as HTMLElement | null;
115
- if (btn) removeAttachedFile(+(btn.dataset.fileIdx || '0'));
115
+ if (btn) removeAttachedFile(+(btn.dataset['fileIdx'] || '0'));
116
116
  });
117
117
  document.querySelector('.btn-attach')?.addEventListener('click', () => {
118
118
  (document.getElementById('fileInput') as HTMLInputElement | null)?.click();
@@ -158,14 +158,14 @@ document.querySelector('[data-action="addEmployee"]')?.addEventListener('click',
158
158
  // ── Employees (Event Delegation) ──
159
159
  document.getElementById('employeesList')?.addEventListener('click', (e) => {
160
160
  const del = (e.target as HTMLElement)?.closest('[data-emp-delete]') as HTMLElement | null;
161
- if (del) { deleteEmployee(del.dataset.empDelete || ''); return; }
161
+ if (del) { deleteEmployee(del.dataset['empDelete'] || ''); return; }
162
162
  });
163
163
  document.getElementById('employeesList')?.addEventListener('change', (e) => {
164
164
  const tgt = e.target as HTMLSelectElement;
165
165
  const name = tgt.closest('[data-emp-name]') as HTMLElement | null;
166
- if (name) { updateEmployee(name.dataset.empName || '', { name: tgt.value }); return; }
166
+ if (name) { updateEmployee(name.dataset['empName'] || '', { name: tgt.value }); return; }
167
167
  const cli = tgt.closest('[data-emp-cli]') as HTMLElement | null;
168
- if (cli) { onEmpCliChange(cli.dataset.empCli || '', tgt.value); return; }
168
+ if (cli) { onEmpCliChange(cli.dataset['empCli'] || '', tgt.value); return; }
169
169
  const model = tgt.closest('[data-emp-model]') as HTMLElement | null;
170
170
  if (model) {
171
171
  if (tgt.value === '__custom__') {
@@ -176,29 +176,29 @@ document.getElementById('employeesList')?.addEventListener('change', (e) => {
176
176
  const customOpt = tgt.querySelector('option[value="__custom__"]');
177
177
  if (customOpt) tgt.insertBefore(opt, customOpt);
178
178
  tgt.value = val.trim();
179
- updateEmployee(model.dataset.empModel || '', { model: val.trim() });
179
+ updateEmployee(model.dataset['empModel'] || '', { model: val.trim() });
180
180
  } else { tgt.value = 'default'; }
181
- } else { updateEmployee(model.dataset.empModel || '', { model: tgt.value }); }
181
+ } else { updateEmployee(model.dataset['empModel'] || '', { model: tgt.value }); }
182
182
  return;
183
183
  }
184
184
  const role = tgt.closest('[data-emp-role]') as HTMLElement | null;
185
- if (role) { onEmpRoleChange(role.dataset.empRole || '', tgt.value); return; }
185
+ if (role) { onEmpRoleChange(role.dataset['empRole'] || '', tgt.value); return; }
186
186
  const custom = tgt.closest('[data-emp-custom]') as HTMLElement | null;
187
- if (custom) { updateEmployee(custom.dataset.empCustom || '', { role: tgt.value }); return; }
187
+ if (custom) { updateEmployee(custom.dataset['empCustom'] || '', { role: tgt.value }); return; }
188
188
  });
189
189
 
190
190
  // ── Skills Tab (Event Delegation) ──
191
191
  document.getElementById('skillsList')?.addEventListener('click', (e) => {
192
192
  const toggle = (e.target as HTMLElement)?.closest('[data-skill-id]') as HTMLElement | null;
193
193
  if (toggle) {
194
- toggleSkill(toggle.dataset.skillId || '', toggle.dataset.skillEnabled === 'true');
194
+ toggleSkill(toggle.dataset['skillId'] || '', toggle.dataset['skillEnabled'] === 'true');
195
195
  }
196
196
  });
197
197
  // Skill filter buttons (event delegation)
198
198
  document.querySelector('#tabSkills')?.addEventListener('click', (e) => {
199
199
  const filterBtn = (e.target as HTMLElement)?.closest('.skill-filter') as HTMLElement | null;
200
200
  if (filterBtn) {
201
- const cat = filterBtn.dataset.filter || 'all';
201
+ const cat = filterBtn.dataset['filter'] || 'all';
202
202
  filterSkills(cat, filterBtn);
203
203
  }
204
204
  });
@@ -344,32 +344,32 @@ document.querySelector('[data-action="addHeartbeat"]')?.addEventListener('click'
344
344
  // Heartbeat jobs (event delegation)
345
345
  document.getElementById('hbJobsList')?.addEventListener('click', (e) => {
346
346
  const toggle = (e.target as HTMLElement)?.closest('[data-hb-toggle]') as HTMLElement | null;
347
- if (toggle) { toggleHeartbeatJob(+(toggle.dataset.hbToggle || '0')); return; }
347
+ if (toggle) { toggleHeartbeatJob(+(toggle.dataset['hbToggle'] || '0')); return; }
348
348
  const remove = (e.target as HTMLElement)?.closest('[data-hb-remove]') as HTMLElement | null;
349
- if (remove) { removeHeartbeatJob(+(remove.dataset.hbRemove || '0')); return; }
349
+ if (remove) { removeHeartbeatJob(+(remove.dataset['hbRemove'] || '0')); return; }
350
350
  });
351
351
  document.getElementById('hbJobsList')?.addEventListener('change', (e) => {
352
352
  const tgt = e.target as HTMLInputElement | HTMLSelectElement;
353
353
  const name = tgt.closest('[data-hb-name]') as HTMLElement | null;
354
- if (name) { state.heartbeatJobs[+(name.dataset.hbName || '0')].name = tgt.value; saveHeartbeatJobs(); return; }
354
+ if (name) { state.heartbeatJobs[+(name.dataset['hbName'] || '0')].name = tgt.value; saveHeartbeatJobs(); return; }
355
355
  const kind = tgt.closest('[data-hb-kind]') as HTMLElement | null;
356
356
  if (kind) {
357
- const i = +(kind.dataset.hbKind || '0');
357
+ const i = +(kind.dataset['hbKind'] || '0');
358
358
  const current = state.heartbeatJobs[i]?.schedule as Record<string, unknown> | undefined;
359
- const timeZone = typeof current?.timeZone === 'string' ? current.timeZone : undefined;
359
+ const timeZone = typeof current?.['timeZone'] === 'string' ? current['timeZone'] : undefined;
360
360
  state.heartbeatJobs[i].schedule = tgt.value === 'cron'
361
- ? { kind: 'cron', cron: typeof current?.cron === 'string' && current.cron.trim() ? current.cron : '0 9 * * *', ...(timeZone ? { timeZone } : {}) }
362
- : { kind: 'every', minutes: typeof current?.minutes === 'number' && current.minutes > 0 ? Math.floor(current.minutes) : 5, ...(timeZone ? { timeZone } : {}) };
361
+ ? { kind: 'cron', cron: typeof current?.['cron'] === 'string' && current['cron'].trim() ? current['cron'] : '0 9 * * *', ...(timeZone ? { timeZone } : {}) }
362
+ : { kind: 'every', minutes: typeof current?.['minutes'] === 'number' && current['minutes'] > 0 ? Math.floor(current['minutes']) : 5, ...(timeZone ? { timeZone } : {}) };
363
363
  renderHeartbeatJobs();
364
364
  saveHeartbeatJobs();
365
365
  return;
366
366
  }
367
367
  const min = tgt.closest('[data-hb-minutes]') as HTMLElement | null;
368
368
  if (min) {
369
- const i = +(min.dataset.hbMinutes || '0');
369
+ const i = +(min.dataset['hbMinutes'] || '0');
370
370
  const current = state.heartbeatJobs[i]?.schedule as Record<string, unknown> | undefined;
371
371
  const minutes = Math.max(1, Math.floor(Number(tgt.value) || 5));
372
- const timeZone = typeof current?.timeZone === 'string' ? current.timeZone : undefined;
372
+ const timeZone = typeof current?.['timeZone'] === 'string' ? current['timeZone'] : undefined;
373
373
  state.heartbeatJobs[i].schedule = { kind: 'every', minutes, ...(timeZone ? { timeZone } : {}) };
374
374
  renderHeartbeatJobs();
375
375
  saveHeartbeatJobs();
@@ -377,9 +377,9 @@ document.getElementById('hbJobsList')?.addEventListener('change', (e) => {
377
377
  }
378
378
  const cron = tgt.closest('[data-hb-cron]') as HTMLElement | null;
379
379
  if (cron) {
380
- const i = +(cron.dataset.hbCron || '0');
380
+ const i = +(cron.dataset['hbCron'] || '0');
381
381
  const current = state.heartbeatJobs[i]?.schedule as Record<string, unknown> | undefined;
382
- const timeZone = typeof current?.timeZone === 'string' ? current.timeZone : undefined;
382
+ const timeZone = typeof current?.['timeZone'] === 'string' ? current['timeZone'] : undefined;
383
383
  const cronExpr = tgt.value.trim().replace(/\s+/g, ' ');
384
384
  state.heartbeatJobs[i].schedule = { kind: 'cron', cron: cronExpr, ...(timeZone ? { timeZone } : {}) };
385
385
  renderHeartbeatJobs();
@@ -388,18 +388,18 @@ document.getElementById('hbJobsList')?.addEventListener('change', (e) => {
388
388
  }
389
389
  const timeZone = tgt.closest('[data-hb-timezone]') as HTMLElement | null;
390
390
  if (timeZone) {
391
- const i = +(timeZone.dataset.hbTimezone || '0');
391
+ const i = +(timeZone.dataset['hbTimezone'] || '0');
392
392
  const current = state.heartbeatJobs[i]?.schedule as Record<string, unknown> | undefined;
393
- if (current?.kind === 'cron') {
393
+ if (current?.['kind'] === 'cron') {
394
394
  state.heartbeatJobs[i].schedule = {
395
395
  kind: 'cron',
396
- cron: typeof current.cron === 'string' && current.cron.trim() ? current.cron : '0 9 * * *',
396
+ cron: typeof current['cron'] === 'string' && current['cron'].trim() ? current['cron'] : '0 9 * * *',
397
397
  ...(tgt.value.trim() ? { timeZone: tgt.value.trim() } : {}),
398
398
  };
399
399
  } else {
400
400
  state.heartbeatJobs[i].schedule = {
401
401
  kind: 'every',
402
- minutes: typeof current?.minutes === 'number' && current.minutes > 0 ? Math.floor(current.minutes) : 5,
402
+ minutes: typeof current?.['minutes'] === 'number' && current['minutes'] > 0 ? Math.floor(current['minutes']) : 5,
403
403
  ...(tgt.value.trim() ? { timeZone: tgt.value.trim() } : {}),
404
404
  };
405
405
  }
@@ -408,7 +408,7 @@ document.getElementById('hbJobsList')?.addEventListener('change', (e) => {
408
408
  return;
409
409
  }
410
410
  const prompt = tgt.closest('[data-hb-prompt]') as HTMLElement | null;
411
- if (prompt) { state.heartbeatJobs[+(prompt.dataset.hbPrompt || '0')].prompt = tgt.value; saveHeartbeatJobs(); return; }
411
+ if (prompt) { state.heartbeatJobs[+(prompt.dataset['hbPrompt'] || '0')].prompt = tgt.value; saveHeartbeatJobs(); return; }
412
412
  });
413
413
 
414
414
  // ── Memory Modal ──
@@ -437,9 +437,9 @@ bindAdvancedProviderUi();
437
437
  // Memory files (event delegation)
438
438
  document.getElementById('basicMemoryFiles')?.addEventListener('click', (e) => {
439
439
  const del = (e.target as HTMLElement)?.closest('[data-mem-delete]') as HTMLElement | null;
440
- if (del) { e.stopPropagation(); deleteMemFile(del.dataset.memDelete || ''); return; }
440
+ if (del) { e.stopPropagation(); deleteMemFile(del.dataset['memDelete'] || ''); return; }
441
441
  const view = (e.target as HTMLElement)?.closest('[data-mem-view]') as HTMLElement | null;
442
- if (view) { viewMemFile(view.dataset.memView || ''); return; }
442
+ if (view) { viewMemFile(view.dataset['memView'] || ''); return; }
443
443
  const back = (e.target as HTMLElement)?.closest('[data-mem-back]');
444
444
  if (back) { openMemoryModal(); return; }
445
445
  });
@@ -62,7 +62,7 @@ export function providerIcon(slug: string, variant: 'color' | 'mono' = 'color'):
62
62
  export function hydrateProviderIcons(root: Element = document.body): void {
63
63
  const els = root.querySelectorAll<HTMLElement>('[data-provider]');
64
64
  for (const el of els) {
65
- const slug = el.dataset.provider || '';
65
+ const slug = el.dataset['provider'] || '';
66
66
  const svg = providerIcon(slug);
67
67
  if (svg) {
68
68
  el.innerHTML = svg;
@@ -32,7 +32,9 @@ import {
32
32
  extractTopLevelSvg,
33
33
  } from './diagram/types.js';
34
34
 
35
- const DOMPurify = getDOMPurify();
35
+ function purifier() {
36
+ return getDOMPurify();
37
+ }
36
38
 
37
39
  // Register hljs languages (core-only import: ~25KB vs ~1MB full)
38
40
  hljs.registerLanguage('javascript', javascript);
@@ -134,7 +136,7 @@ function applyMermaidTheme() {
134
136
  // Mermaid is configured with htmlLabels:false so labels use SVG <text>,
135
137
  // not <foreignObject> + HTML. This avoids DOMPurify namespace issues.
136
138
  function sanitizeMermaidSvg(svg: string): string {
137
- const clean = DOMPurify.sanitize(svg, {
139
+ const clean = purifier().sanitize(svg, {
138
140
  USE_PROFILES: { svg: true, svgFilters: true },
139
141
  FORBID_TAGS: [
140
142
  'script', 'iframe', 'object', 'embed', 'form', 'input',
@@ -163,7 +165,7 @@ export function escapeHtml(str: string): string {
163
165
 
164
166
  // ── XSS sanitization (hardened for inline SVG — Phase 1) ──
165
167
  export function sanitizeHtml(html: string): string {
166
- return DOMPurify.sanitize(html, {
168
+ return purifier().sanitize(html, {
167
169
  USE_PROFILES: { html: true, svg: true, svgFilters: true },
168
170
  FORBID_TAGS: [
169
171
  'script', 'style', 'iframe', 'object', 'embed', 'form', 'input',
@@ -284,7 +286,7 @@ export async function rerenderMermaidDiagrams(): Promise<void> {
284
286
  const mm = await ensureMermaidLoaded();
285
287
  for (const el of rendered) {
286
288
  const htmlEl = el as HTMLElement;
287
- const code = htmlEl.dataset.mermaidCode;
289
+ const code = htmlEl.dataset['mermaidCode'];
288
290
  if (!code || !htmlEl.isConnected) continue;
289
291
  const id = `mermaid-${++mermaidId}`;
290
292
  try {
@@ -361,17 +363,17 @@ function renderMermaidError(el: HTMLElement, code: string, errMsg: string): void
361
363
 
362
364
  async function renderSingleMermaidImpl(el: HTMLElement): Promise<void> {
363
365
  if (!el.isConnected) {
364
- delete el.dataset.mermaidQueued;
365
- delete el.dataset.mermaidInflight;
366
+ delete el.dataset['mermaidQueued'];
367
+ delete el.dataset['mermaidInflight'];
366
368
  return;
367
369
  }
368
370
  el.classList.remove('mermaid-pending');
369
371
  // Phase 127-F1: raw source lives in data attribute (skeleton DOM has no source text).
370
- const encoded = el.dataset.mermaidCodeRaw || '';
372
+ const encoded = el.dataset['mermaidCodeRaw'] || '';
371
373
  const code = encoded ? decodeURIComponent(encoded) : (el.textContent || '');
372
- el.dataset.mermaidCode = code;
374
+ el.dataset['mermaidCode'] = code;
373
375
  const id = `mermaid-${++mermaidId}`;
374
- el.dataset.mermaidInflight = '1';
376
+ el.dataset['mermaidInflight'] = '1';
375
377
  try {
376
378
  const mm = await ensureMermaidLoaded();
377
379
  // Apply theme immediately before render — no intermediate parse()
@@ -383,7 +385,7 @@ async function renderSingleMermaidImpl(el: HTMLElement): Promise<void> {
383
385
  }
384
386
  el.innerHTML = sanitizeMermaidSvg(svg);
385
387
  el.classList.add('mermaid-rendered');
386
- delete el.dataset.mermaidCodeRaw;
388
+ delete el.dataset['mermaidCodeRaw'];
387
389
  appendMermaidActionBtns(el);
388
390
  bindDiagramZoom(el);
389
391
  } catch (err: unknown) {
@@ -391,8 +393,8 @@ async function renderSingleMermaidImpl(el: HTMLElement): Promise<void> {
391
393
  || (err as { str?: string })?.str || 'Unknown error';
392
394
  renderMermaidError(el, code, errMsg);
393
395
  } finally {
394
- delete el.dataset.mermaidQueued;
395
- delete el.dataset.mermaidInflight;
396
+ delete el.dataset['mermaidQueued'];
397
+ delete el.dataset['mermaidInflight'];
396
398
  }
397
399
  }
398
400
 
@@ -402,8 +404,8 @@ function renderSingleMermaid(el: HTMLElement): void {
402
404
  // Phase 127-N2: synchronous queued guard prevents duplicate enqueueing when
403
405
  // renderMermaidBlocks immediate mode fires repeatedly (e.g. VS onPostRender
404
406
  // on every scroll). Class/dataset is set right away so the next pass skips.
405
- if (el.dataset.mermaidQueued === '1') return;
406
- el.dataset.mermaidQueued = '1';
407
+ if (el.dataset['mermaidQueued'] === '1') return;
408
+ el.dataset['mermaidQueued'] = '1';
407
409
  // Phase 127-F6: .catch tail keeps the queue alive after any rejection so
408
410
  // one bad render cannot permanently block subsequent diagrams.
409
411
  mermaidQueue = mermaidQueue
@@ -430,7 +432,7 @@ export async function renderMermaidBlocks(
430
432
  if (!pending.length) return;
431
433
  ensureMermaidObserver();
432
434
  for (const el of pending) {
433
- if (el.dataset.mermaidQueued === '1') continue; // N2 guard
435
+ if (el.dataset['mermaidQueued'] === '1') continue; // N2 guard
434
436
  if (opts.immediate) {
435
437
  const rect = el.getBoundingClientRect();
436
438
  const vh = window.innerHeight || document.documentElement.clientHeight;
@@ -457,11 +459,11 @@ export function releaseMermaidNodes(scope: HTMLElement): void {
457
459
  scope.querySelectorAll<HTMLElement>(selector).forEach((el) => nodes.push(el));
458
460
  for (const el of nodes) {
459
461
  mermaidObserver.unobserve(el);
460
- delete el.dataset.mermaidQueued;
461
- delete el.dataset.mermaidQueuedAt;
462
- delete el.dataset.mermaidInflight;
462
+ delete el.dataset['mermaidQueued'];
463
+ delete el.dataset['mermaidQueuedAt'];
464
+ delete el.dataset['mermaidInflight'];
463
465
  if (!el.classList.contains('mermaid-rendered')
464
- && (el.dataset.mermaidCodeRaw || el.dataset.mermaidCode)) {
466
+ && (el.dataset['mermaidCodeRaw'] || el.dataset['mermaidCode'])) {
465
467
  el.classList.add('mermaid-pending');
466
468
  }
467
469
  }
@@ -540,7 +542,7 @@ function ensureMarked(): boolean {
540
542
  export function rehighlightAll(scope?: HTMLElement | Document): void {
541
543
  const root = scope || document;
542
544
  root.querySelectorAll('.code-block pre code, .code-block-wrapper pre code').forEach(el => {
543
- if ((el as HTMLElement).dataset.highlighted === 'yes') return;
545
+ if ((el as HTMLElement).dataset['highlighted'] === 'yes') return;
544
546
  const lang = [...el.classList].find(c => c.startsWith('language-'))?.replace('language-', '');
545
547
  const raw = el.textContent || '';
546
548
  try {
@@ -549,7 +551,7 @@ export function rehighlightAll(scope?: HTMLElement | Document): void {
549
551
  } else {
550
552
  el.innerHTML = hljs.highlightAuto(raw).value;
551
553
  }
552
- (el as HTMLElement).dataset.highlighted = 'yes';
554
+ (el as HTMLElement).dataset['highlighted'] = 'yes';
553
555
  } catch { /* ignore */ }
554
556
  });
555
557
  }
@@ -763,8 +765,8 @@ function ensureDiagramActionDelegation(): void {
763
765
  const container = diagCopyBtn.closest('.diagram-container') as HTMLElement | null;
764
766
  if (!container) return;
765
767
  let text = '';
766
- if (container.dataset.widgetHtml) {
767
- try { text = decodeURIComponent(escape(atob(container.dataset.widgetHtml))); }
768
+ if (container.dataset['widgetHtml']) {
769
+ try { text = decodeURIComponent(escape(atob(container.dataset['widgetHtml']))); }
768
770
  catch { return; }
769
771
  } else {
770
772
  const svgEl = container.querySelector('svg');
@@ -778,7 +780,7 @@ function ensureDiagramActionDelegation(): void {
778
780
  if (mermaidCopyBtn) {
779
781
  const container = mermaidCopyBtn.closest('.mermaid-container') as HTMLElement | null;
780
782
  if (!container) return;
781
- const code = container.dataset.mermaidCode || '';
783
+ const code = container.dataset['mermaidCode'] || '';
782
784
  if (code) btnFeedback(mermaidCopyBtn, code, 'copy');
783
785
  return;
784
786
  }
@@ -789,7 +791,7 @@ function ensureDiagramActionDelegation(): void {
789
791
  const container = diagSaveBtn.closest('.diagram-container') as HTMLElement | null;
790
792
  if (!container) return;
791
793
  // Widget: request screenshot via bridge
792
- if (container.dataset.widgetHtml) {
794
+ if (container.dataset['widgetHtml']) {
793
795
  const iframe = container.querySelector('iframe') as HTMLIFrameElement | null;
794
796
  if (iframe?.contentWindow) {
795
797
  iframe.contentWindow.postMessage({ type: 'jaw-request-screenshot' }, '*');
@@ -929,8 +931,8 @@ function unshieldSvgBlocks(html: string, blocks: SvgBlock[]): string {
929
931
  export function bindDiagramZoom(scope?: HTMLElement | Document): void {
930
932
  const root = scope || document;
931
933
  root.querySelectorAll('.diagram-zoom-btn, .mermaid-zoom-btn').forEach(btn => {
932
- if ((btn as HTMLElement).dataset.bound) return;
933
- (btn as HTMLElement).dataset.bound = '1';
934
+ if ((btn as HTMLElement).dataset['bound']) return;
935
+ (btn as HTMLElement).dataset['bound'] = '1';
934
936
  btn.addEventListener('click', () => {
935
937
  if (btn.closest('.diagram-widget')) return;
936
938
  const container = btn.closest('.diagram-container, .mermaid-container');
@@ -77,3 +77,7 @@ export function getDOMPurify(): DOMPurifyLike {
77
77
  registerAttributeHook(purifySingleton);
78
78
  return purifySingleton;
79
79
  }
80
+
81
+ export function resetDOMPurifyForTests(): void {
82
+ purifySingleton = null;
83
+ }