@rho-workspace/rho 0.5.3 → 0.5.5

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 (277) hide show
  1. package/README.md +24 -5
  2. package/dist/browser-access.js +3 -2
  3. package/dist/capabilities.d.ts +29 -2
  4. package/dist/capabilities.js +79 -2
  5. package/dist/cli.js +237 -99
  6. package/dist/contract.generated.d.ts +441 -16
  7. package/dist/contract.generated.js +1 -1
  8. package/dist/contracts/owners.generated.js +459 -10
  9. package/dist/conversation-presentation.d.ts +3 -1
  10. package/dist/conversation-presentation.js +16 -6
  11. package/dist/conversations.d.ts +10 -6
  12. package/dist/conversations.js +17 -13
  13. package/dist/discovery.d.ts +1 -0
  14. package/dist/discovery.js +3 -3
  15. package/dist/extension-contract.d.ts +99 -0
  16. package/dist/extension-contract.js +52 -0
  17. package/dist/extension-directory.d.ts +9 -0
  18. package/dist/extension-directory.js +11 -0
  19. package/dist/extension-worker.d.ts +1 -0
  20. package/dist/extension-worker.js +36 -0
  21. package/dist/extensions.d.ts +157 -0
  22. package/dist/extensions.js +349 -0
  23. package/dist/installs.d.ts +11 -0
  24. package/dist/installs.js +179 -0
  25. package/dist/plugin-cli.d.ts +1 -0
  26. package/dist/plugin-cli.js +139 -0
  27. package/dist/plugin-inventory.json +18 -0
  28. package/dist/plugins.d.ts +3 -3
  29. package/dist/project-notes.js +2 -0
  30. package/dist/project-work.d.ts +3 -1
  31. package/dist/project-work.js +15 -2
  32. package/dist/protocol.d.ts +7 -0
  33. package/dist/protocol.js +11 -7
  34. package/dist/screen-check-skill.d.ts +2 -0
  35. package/dist/screen-check-skill.js +39 -0
  36. package/dist/server.d.ts +6 -1
  37. package/dist/server.js +105 -15
  38. package/dist/web/.vite/manifest.json +65 -65
  39. package/dist/web/assets/{canvas-BXhC8RDZ.js → canvas-D8rDdfDz.js} +1 -1
  40. package/dist/web/assets/choices-b0XhrGQV.js +1 -0
  41. package/dist/web/assets/{console-e1P5qYQ5.js → console-BSjLGe0T.js} +1 -1
  42. package/dist/web/assets/{dist-Dd3iAGFy.js → dist-Buk0lwzI.js} +2 -2
  43. package/dist/web/assets/dist-Cw8hRIlT.js +1 -0
  44. package/dist/web/assets/dist-Tzoe_zm-.js +3 -0
  45. package/dist/web/assets/{dist-DEorbOW0.js → dist-foH9IKc6.js} +1 -1
  46. package/dist/web/assets/explore-in-BVUy3ZW_.js +1 -0
  47. package/dist/web/assets/graph-1OdIJ9l7.js +2 -0
  48. package/dist/web/assets/index-CsC3sTRq.css +1 -0
  49. package/dist/web/assets/{index-BYuKpyoi.js → index-CxmItXqa.js} +220 -121
  50. package/dist/web/assets/{notes-meaning-B3HFbh84.js → notes-meaning-pVbbQUGP.js} +1 -1
  51. package/dist/web/assets/overview-B9UtVJ32.js +6 -0
  52. package/dist/web/assets/preview-CksD_5KS.js +1 -0
  53. package/dist/web/assets/{review-BVh9jWMB.js → review-CMxQlQ-C.js} +1 -1
  54. package/dist/web/assets/{skills-DPaEYkln.js → skills-BFNSyrnD.js} +1 -1
  55. package/dist/web/assets/{skills-work-dvjfy_tu.js → skills-work-BGPSnF_I.js} +1 -1
  56. package/dist/web/assets/{studio-process-BYm8mjRJ.js → studio-process-CsRoTHOh.js} +2 -2
  57. package/dist/web/assets/{timeline-events-CDZ7wiJX.js → timeline-events-BbuuFWHV.js} +1 -1
  58. package/dist/web/assets/{work-turns-BeCt303c.js → work-turns-BvJlIMmA.js} +1 -1
  59. package/dist/web/assets/workspace-CWlkjLNx.js +5 -0
  60. package/dist/web/composition.json +80 -80
  61. package/dist/web/index.html +3 -3
  62. package/dist/web/renderer.json +1 -1
  63. package/dist/web-assets.d.ts +2 -1
  64. package/dist/web-assets.js +3 -2
  65. package/dist/work-contract.js +2 -2
  66. package/docs/FRONTEND.md +30 -14
  67. package/docs/HEADLESS.md +60 -14
  68. package/docs/PLUGIN-AUTHORING.md +4 -0
  69. package/docs/THIRD-PARTY-PLUGINS.md +190 -0
  70. package/example/pa14-qs/.rho/rho/conversations/c-67f77cfebaba2cea.json +1 -1
  71. package/example/pa14-qs/.rho/rho/conversations/c-91aa2e46b1ac1a6c.json +1 -1
  72. package/example/pa14-qs/.rho/rho/conversations/c-fa24dfd80dfe4bcb.json +1 -1
  73. package/node_modules/@hono/node-server/dist/index.js +11 -0
  74. package/node_modules/@hono/node-server/dist/index.mjs +11 -0
  75. package/node_modules/@hono/node-server/dist/listener.js +11 -0
  76. package/node_modules/@hono/node-server/dist/listener.mjs +11 -0
  77. package/node_modules/@hono/node-server/dist/request.js +11 -0
  78. package/node_modules/@hono/node-server/dist/request.mjs +11 -0
  79. package/node_modules/@hono/node-server/dist/server.js +11 -0
  80. package/node_modules/@hono/node-server/dist/server.mjs +11 -0
  81. package/node_modules/@hono/node-server/dist/vercel.js +11 -0
  82. package/node_modules/@hono/node-server/dist/vercel.mjs +11 -0
  83. package/node_modules/@hono/node-server/package.json +1 -1
  84. package/node_modules/@rho-workspace/plugin-agent/README.md +42 -1
  85. package/node_modules/@rho-workspace/plugin-agent/dist/acp-conversation.js +14 -3
  86. package/node_modules/@rho-workspace/plugin-agent/dist/activity-normalize.d.ts +1 -0
  87. package/node_modules/@rho-workspace/plugin-agent/dist/activity-normalize.js +2 -2
  88. package/node_modules/@rho-workspace/plugin-agent/dist/conversation.d.ts +1 -0
  89. package/node_modules/@rho-workspace/plugin-agent/dist/conversation.js +1 -0
  90. package/node_modules/@rho-workspace/plugin-agent/dist/dsh-session.d.ts +6 -0
  91. package/node_modules/@rho-workspace/plugin-agent/dist/dsh-session.js +174 -0
  92. package/node_modules/@rho-workspace/plugin-agent/dist/external-session-contract.d.ts +82 -0
  93. package/node_modules/@rho-workspace/plugin-agent/dist/external-session-contract.js +15 -0
  94. package/node_modules/@rho-workspace/plugin-agent/dist/external-session.d.ts +73 -0
  95. package/node_modules/@rho-workspace/plugin-agent/dist/external-session.js +190 -0
  96. package/node_modules/@rho-workspace/plugin-agent/dist/generic-acp.d.ts +11 -0
  97. package/node_modules/@rho-workspace/plugin-agent/dist/generic-acp.js +7 -0
  98. package/node_modules/@rho-workspace/plugin-agent/dist/index.d.ts +373 -0
  99. package/node_modules/@rho-workspace/plugin-agent/dist/index.js +1 -0
  100. package/node_modules/@rho-workspace/plugin-agent/dist/mcp.js +5 -1
  101. package/node_modules/@rho-workspace/plugin-agent/dist/operations.d.ts +33 -0
  102. package/node_modules/@rho-workspace/plugin-agent/dist/operations.js +3 -0
  103. package/node_modules/@rho-workspace/plugin-agent/dist/presentation.d.ts +14 -0
  104. package/node_modules/@rho-workspace/plugin-agent/dist/presentation.js +2 -0
  105. package/node_modules/@rho-workspace/plugin-agent/dist/ui-external-session.d.ts +15 -0
  106. package/node_modules/@rho-workspace/plugin-agent/dist/ui-external-session.js +37 -0
  107. package/node_modules/@rho-workspace/plugin-agent/package.json +5 -1
  108. package/node_modules/@rho-workspace/plugin-annotations/package.json +1 -1
  109. package/node_modules/@rho-workspace/plugin-documents/README.md +4 -0
  110. package/node_modules/@rho-workspace/plugin-documents/dist/index.d.ts +3 -0
  111. package/node_modules/@rho-workspace/plugin-documents/dist/index.js +1 -1
  112. package/node_modules/@rho-workspace/plugin-documents/package.json +1 -1
  113. package/node_modules/@rho-workspace/plugin-kernel/README.md +71 -10
  114. package/node_modules/@rho-workspace/plugin-kernel/dist/code.d.ts +2 -0
  115. package/node_modules/@rho-workspace/plugin-kernel/dist/code.js +4 -1
  116. package/node_modules/@rho-workspace/plugin-kernel/dist/contract.js +5 -0
  117. package/node_modules/@rho-workspace/plugin-kernel/dist/index.d.ts +7 -0
  118. package/node_modules/@rho-workspace/plugin-kernel/dist/index.js +55 -8
  119. package/node_modules/@rho-workspace/plugin-kernel/dist/lineage.d.ts +9 -6
  120. package/node_modules/@rho-workspace/plugin-kernel/dist/lineage.js +18 -41
  121. package/node_modules/@rho-workspace/plugin-kernel/dist/operations.js +5 -2
  122. package/node_modules/@rho-workspace/plugin-kernel/dist/script-flow.d.ts +39 -0
  123. package/node_modules/@rho-workspace/plugin-kernel/dist/script-flow.js +661 -0
  124. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-base.d.ts +3 -0
  125. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-base.js +10 -0
  126. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-flow.d.ts +38 -4
  127. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-flow.js +194 -97
  128. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-notebook-work.js +1 -2
  129. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-notebook.d.ts +10 -2
  130. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-notebook.js +79 -18
  131. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-styles.js +115 -45
  132. package/node_modules/@rho-workspace/plugin-kernel/dist/ui.d.ts +1 -1
  133. package/node_modules/@rho-workspace/plugin-kernel/dist/ui.js +1 -1
  134. package/node_modules/@rho-workspace/plugin-kernel/dist/value-graph.d.ts +63 -0
  135. package/node_modules/@rho-workspace/plugin-kernel/dist/value-graph.js +344 -0
  136. package/node_modules/@rho-workspace/plugin-kernel/package.json +1 -1
  137. package/node_modules/@rho-workspace/plugin-kernel/runners/runner.R +6 -3
  138. package/node_modules/@rho-workspace/plugin-kernel/runners/runner.py +6 -3
  139. package/node_modules/express-rate-limit/dist/index.cjs +1 -1
  140. package/node_modules/express-rate-limit/dist/index.mjs +1 -1
  141. package/node_modules/express-rate-limit/package.json +1 -1
  142. package/node_modules/ip-address/dist/ipv6.js +1 -1
  143. package/node_modules/ip-address/package.json +1 -1
  144. package/node_modules/playwright-core/LICENSE +202 -0
  145. package/node_modules/playwright-core/NOTICE +5 -0
  146. package/node_modules/playwright-core/ThirdPartyNotices.txt +13 -0
  147. package/node_modules/playwright-core/bin/install_media_pack.ps1 +5 -0
  148. package/node_modules/playwright-core/bin/install_webkit_wsl.ps1 +33 -0
  149. package/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh +42 -0
  150. package/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh +13 -0
  151. package/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 +24 -0
  152. package/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh +42 -0
  153. package/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh +12 -0
  154. package/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 +24 -0
  155. package/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh +48 -0
  156. package/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh +11 -0
  157. package/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 +23 -0
  158. package/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh +48 -0
  159. package/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh +11 -0
  160. package/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 +23 -0
  161. package/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh +48 -0
  162. package/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh +11 -0
  163. package/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 +24 -0
  164. package/node_modules/playwright-core/browsers.json +52 -0
  165. package/node_modules/playwright-core/cli.js +22 -0
  166. package/node_modules/playwright-core/index.js +17 -0
  167. package/node_modules/playwright-core/index.mjs +28 -0
  168. package/node_modules/playwright-core/lib/bootstrap.js +149 -0
  169. package/node_modules/playwright-core/lib/coreBundle.js +78041 -0
  170. package/node_modules/playwright-core/lib/entry/cliDaemon.js +5 -0
  171. package/node_modules/playwright-core/lib/entry/dashboardApp.js +3 -0
  172. package/node_modules/playwright-core/lib/entry/mcp.js +10 -0
  173. package/node_modules/playwright-core/lib/entry/oopBrowserDownload.js +3 -0
  174. package/node_modules/playwright-core/lib/package.js +50 -0
  175. package/node_modules/playwright-core/lib/server/chromium/appIcon.png +0 -0
  176. package/node_modules/playwright-core/lib/server/electron/loader.js +123 -0
  177. package/node_modules/playwright-core/lib/serverRegistry.js +1939 -0
  178. package/node_modules/playwright-core/lib/serverRegistry.js.LICENSE +65 -0
  179. package/node_modules/playwright-core/lib/tools/cli-client/channelSessions.js +141 -0
  180. package/node_modules/playwright-core/lib/tools/cli-client/cli.js +7 -0
  181. package/node_modules/playwright-core/lib/tools/cli-client/help.json +808 -0
  182. package/node_modules/playwright-core/lib/tools/cli-client/minimist.js +128 -0
  183. package/node_modules/playwright-core/lib/tools/cli-client/output.js +352 -0
  184. package/node_modules/playwright-core/lib/tools/cli-client/program.js +422 -0
  185. package/node_modules/playwright-core/lib/tools/cli-client/registry.js +180 -0
  186. package/node_modules/playwright-core/lib/tools/cli-client/session.js +261 -0
  187. package/node_modules/playwright-core/lib/tools/dashboard/appIcon.png +0 -0
  188. package/node_modules/playwright-core/lib/tools/utils/extension.js +112 -0
  189. package/node_modules/playwright-core/lib/tools/utils/socketConnection.js +108 -0
  190. package/node_modules/playwright-core/lib/utilsBundle.js +86078 -0
  191. package/node_modules/playwright-core/lib/utilsBundle.js.LICENSE +1890 -0
  192. package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule--QdMvsKi.css +1 -0
  193. package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule-CQ8RZGBm.js +32 -0
  194. package/node_modules/playwright-core/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
  195. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
  196. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
  197. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
  198. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-AwgwcYie.css +1 -0
  199. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-hRvO4yU2.js +12 -0
  200. package/node_modules/playwright-core/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
  201. package/node_modules/playwright-core/lib/vite/dashboard/index.html +29 -0
  202. package/node_modules/playwright-core/lib/vite/dashboard/playwright-logo.svg +24 -0
  203. package/node_modules/playwright-core/lib/vite/htmlReport/index.html +16 -0
  204. package/node_modules/playwright-core/lib/vite/htmlReport/report.css +2 -0
  205. package/node_modules/playwright-core/lib/vite/htmlReport/report.js +32 -0
  206. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
  207. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-DK72OMRi.js +32 -0
  208. package/node_modules/playwright-core/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
  209. package/node_modules/playwright-core/lib/vite/recorder/assets/index-BZpYJZ-P.css +1 -0
  210. package/node_modules/playwright-core/lib/vite/recorder/assets/index-Cn0mmDuv.js +129 -0
  211. package/node_modules/playwright-core/lib/vite/recorder/index.html +29 -0
  212. package/node_modules/playwright-core/lib/vite/recorder/playwright-logo.svg +9 -0
  213. package/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-BEB2e8M3.js +32 -0
  214. package/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-D-g2vrvf.js +184 -0
  215. package/node_modules/playwright-core/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
  216. package/node_modules/playwright-core/lib/vite/traceViewer/assets/xtermModule-B794rD2Z.js +7 -0
  217. package/node_modules/playwright-core/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
  218. package/node_modules/playwright-core/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  219. package/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.C8BeHuxd.css +1 -0
  220. package/node_modules/playwright-core/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
  221. package/node_modules/playwright-core/lib/vite/traceViewer/index.html +44 -0
  222. package/node_modules/playwright-core/lib/vite/traceViewer/index.oNry3Hjv.js +1 -0
  223. package/node_modules/playwright-core/lib/vite/traceViewer/manifest.webmanifest +16 -0
  224. package/node_modules/playwright-core/lib/vite/traceViewer/playwright-logo.svg +9 -0
  225. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
  226. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.html +10 -0
  227. package/node_modules/playwright-core/lib/vite/traceViewer/sw.bundle.js +4 -0
  228. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CYwC_gH1.js +5 -0
  229. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CyMfwkXJ.css +1 -0
  230. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +18 -0
  231. package/node_modules/playwright-core/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
  232. package/node_modules/playwright-core/lib/webp_codec.LICENSE +173 -0
  233. package/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
  234. package/node_modules/playwright-core/lib/xdg-open +1267 -0
  235. package/node_modules/playwright-core/package.json +34 -0
  236. package/package.json +13 -7
  237. package/protocol/index.json +75 -21
  238. package/protocol/operations/agent.sessions.list.json +100 -0
  239. package/protocol/operations/agent.sessions.read.json +266 -0
  240. package/protocol/operations/conversation.settings.check.json +147 -4
  241. package/protocol/operations/conversation.settings.read.json +145 -3
  242. package/protocol/operations/conversation.settings.update.json +166 -4
  243. package/protocol/operations/conversation.start.json +2 -1
  244. package/protocol/operations/extension.call.json +132 -0
  245. package/protocol/operations/extension.content.json +78 -0
  246. package/protocol/operations/extension.describe.json +195 -0
  247. package/protocol/operations/extension.install.json +198 -0
  248. package/protocol/operations/extension.list.json +123 -0
  249. package/protocol/operations/extension.manage.json +55 -0
  250. package/protocol/operations/extension.read.json +112 -0
  251. package/protocol/operations/kernel.interrupt.json +20 -0
  252. package/protocol/operations/kernel.read.json +30 -0
  253. package/protocol/operations/kernel.run.json +36 -1
  254. package/protocol/operations/kernel.stop.json +10 -0
  255. package/protocol/operations/project.work.read.json +3 -2
  256. package/protocol/operations/session.grant.json +9 -0
  257. package/scripts/browser-checks.mjs +53 -0
  258. package/scripts/screen-check.mjs +193 -0
  259. package/scripts/third-party-acceptance.mjs +77 -0
  260. package/vendor/composition.json +111 -111
  261. package/vendor/rho-workspace-plugin-agent-0.4.29.tgz +0 -0
  262. package/vendor/rho-workspace-plugin-annotations-0.5.2.tgz +0 -0
  263. package/vendor/rho-workspace-plugin-documents-0.4.11.tgz +0 -0
  264. package/vendor/rho-workspace-plugin-kernel-0.5.5.tgz +0 -0
  265. package/web/theme.css +17 -2
  266. package/dist/web/assets/choices-B-y2OYvE.js +0 -1
  267. package/dist/web/assets/dist-CBM2oq6g.js +0 -1
  268. package/dist/web/assets/dist-CH56yNDn.js +0 -3
  269. package/dist/web/assets/explore-in-muWXOGOY.js +0 -1
  270. package/dist/web/assets/graph-CK-df5lh.js +0 -2
  271. package/dist/web/assets/index-DBd77u4a.css +0 -1
  272. package/dist/web/assets/overview-D1Ev2OC_.js +0 -6
  273. package/dist/web/assets/preview-HbmQKUGY.js +0 -1
  274. package/dist/web/assets/workspace-d5Hw_ClZ.js +0 -5
  275. package/vendor/rho-workspace-plugin-agent-0.4.27.tgz +0 -0
  276. package/vendor/rho-workspace-plugin-documents-0.4.10.tgz +0 -0
  277. package/vendor/rho-workspace-plugin-kernel-0.5.2.tgz +0 -0
@@ -0,0 +1,344 @@
1
+ import { cellLabel, lineage } from './lineage.js';
2
+ import { scriptFlow } from './script-flow.js';
3
+ import { statements } from './statements.js';
4
+ const escaped = (name) => name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
5
+ const assignment = (name) => new RegExp('^\\s*`?' + escaped(name) + '`?\\s*(?::[^=\\n]*)?(?:<<-|<-|=(?!=))\\s*');
6
+ // What the statement that assigns a name gives it, as text.
7
+ function assigned(code, name, language) {
8
+ const lines = code.split('\n'), re = assignment(name);
9
+ for (const s of statements(code, language)) {
10
+ const m = re.exec(lines[s.from - 1]);
11
+ if (m)
12
+ return [lines[s.from - 1].slice(m[0].length), ...lines.slice(s.from, s.to)].join('\n').trim();
13
+ }
14
+ return null;
15
+ }
16
+ // One line on how a value is made: what its assignment gives it, else the statement's first line.
17
+ function howOf(code, name, language) {
18
+ const first = (code.split('\n').find(l => l.trim() && !/^\s*#/.test(l)) ?? '').trim();
19
+ const rest = assigned(code, name, language);
20
+ if (rest === null) {
21
+ const def = language === 'python' && code.split('\n').find(l => new RegExp('^\\s*(?:async\\s+)?def\\s+' + escaped(name) + '\\b').test(l));
22
+ return def ? def.trim().replace(/:\s*$/, '') : first;
23
+ }
24
+ if (/^(?:function\s*\(|\\\()/.test(rest))
25
+ return 'function' + (rest.match(/\([^)]*\)/)?.[0] ?? '()');
26
+ return rest.split('\n').map(l => l.trim()).join(' ');
27
+ }
28
+ // Where in a step that makes several values one of them is made: the statement that assigns it,
29
+ // else the whole step.
30
+ function narrowed(making, name, language) {
31
+ const lines = making.code.split('\n'), re = assignment(name);
32
+ for (const s of statements(making.code, language))
33
+ if (re.test(lines[s.from - 1]))
34
+ return { ...making, from: making.from + s.from - 1, to: making.from + s.to - 1, code: lines.slice(s.from - 1, s.to).join('\n') };
35
+ return making;
36
+ }
37
+ // The line that names a file, else the statement's first line.
38
+ const howFile = (code, path) => code.split('\n').find(l => l.includes(path))?.trim() ?? (code.split('\n').find(l => l.trim() && !/^\s*#/.test(l)) ?? '').trim();
39
+ // A constant: its assignment gives it only literals, and calls that are given only literals and do
40
+ // not read anything (c(), paste0(), theme(), dict(); not read.csv() of a URL).
41
+ const literalNames = new Set(['TRUE', 'FALSE', 'T', 'F', 'NULL', 'NA', 'Inf', 'NaN', 'pi', 'LETTERS', 'letters', 'month.name', 'month.abb', 'True', 'False', 'None']);
42
+ const fetches = /read|load|fetch|download|scan|query|import|open|connect|request|url|get$|^get|^data$|^source$/i;
43
+ function literal(code, name, language) {
44
+ const rest = assigned(code, name, language);
45
+ if (rest === null)
46
+ return false;
47
+ const plain = rest.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g, '""').replace(/#.*$/gm, '');
48
+ for (const w of plain.matchAll(/([\p{L}_.][\p{L}\p{N}_.]*)\s*(\(|=(?!=))?/gu)) {
49
+ if (/^\.?\d/.test(w[1]) || w[2] === '=' || (w[2] === '(' ? !fetches.test(w[1]) : literalNames.has(w[1])))
50
+ continue;
51
+ return false;
52
+ }
53
+ return true;
54
+ }
55
+ function builder(language) {
56
+ const nodes = new Map();
57
+ const node = (id, kind, name, how) => {
58
+ let n = nodes.get(id);
59
+ if (!n)
60
+ nodes.set(id, n = { id, kind, name, how, made: [], uses: [], parents: [], children: [], fn: false, language });
61
+ else if (how && !n.how)
62
+ n.how = how;
63
+ return n;
64
+ };
65
+ const make = (id, kind, name, making, how, parents, fn = false, stale = []) => {
66
+ const n = node(id, kind, name, how);
67
+ if (stale.length)
68
+ n.stale = [...new Set([...n.stale ?? [], ...stale])];
69
+ if (making && !n.made.some(m => m.from === making.from && m.cell?.cellId === making.cell?.cellId))
70
+ n.made.push(making);
71
+ if (fn)
72
+ n.fn = true;
73
+ for (const p of parents) {
74
+ if (p === id || n.parents.includes(p))
75
+ continue;
76
+ n.parents.push(p);
77
+ if (p.startsWith('in:'))
78
+ node(p, 'input', p.slice(3), '');
79
+ }
80
+ };
81
+ // What the code says a node is: the first meaning given, where it has none yet.
82
+ const means = (id, text) => { const n = nodes.get(id); if (n && text && !n.means)
83
+ n.means = text; };
84
+ const finish = (rest) => {
85
+ for (const n of nodes.values())
86
+ n.parents = n.parents.filter(p => nodes.has(p));
87
+ const relink = () => {
88
+ for (const n of nodes.values())
89
+ n.children = [];
90
+ for (const n of nodes.values())
91
+ for (const p of n.parents)
92
+ nodes.get(p).children.push(n.id);
93
+ };
94
+ relink();
95
+ // Functions and constants something uses become what its users use.
96
+ const folded = new Map();
97
+ const gone = new Set([...nodes.values()].filter(n => n.kind === 'value' && n.children.length > 0
98
+ && (n.fn || (n.parents.length === 0 && n.made.length === 1 && literal(n.made[0].code, n.name, n.language)))).map(n => n.id));
99
+ const expand = (ids, seen = new Set()) => {
100
+ const parents = [], uses = [];
101
+ for (const id of ids) {
102
+ if (!gone.has(id)) {
103
+ parents.push(id);
104
+ continue;
105
+ }
106
+ if (seen.has(id))
107
+ continue;
108
+ seen.add(id);
109
+ const n = nodes.get(id), inner = expand(n.parents, seen);
110
+ uses.push(n.name, ...inner.uses);
111
+ parents.push(...inner.parents);
112
+ }
113
+ return { parents, uses };
114
+ };
115
+ for (const n of nodes.values()) {
116
+ if (gone.has(n.id))
117
+ continue;
118
+ const { parents, uses } = expand(n.parents);
119
+ n.parents = [...new Set(parents)].filter(p => p !== n.id);
120
+ n.uses = [...new Set([...n.uses, ...uses])];
121
+ }
122
+ for (const id of gone) {
123
+ const n = nodes.get(id);
124
+ folded.set(n.name, { made: n.made, means: n.means });
125
+ nodes.delete(id);
126
+ }
127
+ relink();
128
+ // A value made from one other and used only to change it is part of that one.
129
+ for (let again = true; again;) {
130
+ again = false;
131
+ for (const v of nodes.values()) {
132
+ if (v.kind !== 'value' || v.children.length !== 1)
133
+ continue;
134
+ const t = nodes.get(v.children[0]);
135
+ if (t.kind !== 'value' || !v.parents.length || !v.parents.every(p => p === t.id))
136
+ continue;
137
+ t.uses = [...new Set([...t.uses, v.name, ...v.uses])];
138
+ t.parents = t.parents.filter(p => p !== v.id);
139
+ folded.set(v.name, { made: v.made, means: v.means });
140
+ nodes.delete(v.id);
141
+ relink();
142
+ again = true;
143
+ break;
144
+ }
145
+ }
146
+ const all = [...nodes.values()];
147
+ const made = all.filter(n => n.kind === 'output' || n.kind === 'plot').map(n => n.id);
148
+ const ends = all.filter(n => n.kind === 'value' && !n.children.length).map(n => n.id);
149
+ const results = made.length ? made : ends;
150
+ const behind = new Set();
151
+ const up = (id) => { if (behind.has(id))
152
+ return; behind.add(id); for (const p of nodes.get(id).parents)
153
+ up(p); };
154
+ for (const r of results)
155
+ up(r);
156
+ return { nodes: new Map(all.map(({ fn: _, language: __, ...n }) => [n.id, n])), results, inputs: all.filter(n => n.kind === 'input').map(n => n.id),
157
+ others: all.filter(n => !behind.has(n.id)).map(n => n.id), folded, ...rest };
158
+ };
159
+ return { make, means, finish };
160
+ }
161
+ // A script read as text: each step makes its values and the files it writes, from what the step
162
+ // reads.
163
+ export function scriptGraph(flow, language) {
164
+ const b = builder(language);
165
+ const idOf = (link) => (link.startsWith('wrote:') ? 'out:' : 'v:') + link.slice(6).replace(/@\d+$/, '');
166
+ for (const step of flow.steps) {
167
+ const making = { from: step.from, to: step.to, code: step.cell.code };
168
+ const parents = [...flow.links.filter(l => l.to === step.id).map(l => idOf(l.from)), ...step.reads.map(p => 'in:' + p)];
169
+ for (const n of step.nodes) {
170
+ const file = n.kind === 'file', own = step.nodes.length > 1 && !file ? narrowed(making, n.name, language) : making, id = (file ? 'out:' : 'v:') + n.name;
171
+ b.make(id, file ? 'output' : 'value', n.name, own, file ? howFile(step.cell.code, n.name) : howOf(step.cell.code, n.name, language), parents, step.functions.includes(n.name));
172
+ b.means(id, flow.means.get((file ? 'file:' : 'value:') + n.name));
173
+ }
174
+ for (const p of step.reads)
175
+ b.means('in:' + p, flow.means.get('file:' + p));
176
+ }
177
+ return b.finish(flow);
178
+ }
179
+ export function sessionGraph(cells, values, language) {
180
+ const graph = lineage(cells, values.map(v => v.name)), b = builder(language);
181
+ // What an earlier cell's code says its values are, read once per cell.
182
+ const meaningsOfCell = new Map();
183
+ const meanOfCell = (c) => { if (!meaningsOfCell.has(c.cellId))
184
+ meaningsOfCell.set(c.cellId, scriptFlow(c.code, language).means); return meaningsOfCell.get(c.cellId); };
185
+ const functions = new Set(values.filter(v => v.type === 'function' || v.type === 'closure').map(v => v.name));
186
+ const written = new Set(graph.steps.flatMap(s => s.nodes.filter(n => n.id.startsWith('wrote:')).map(n => n.name)));
187
+ const fileNode = (path) => (written.has(path) ? 'out:' : 'in:') + path;
188
+ const idOf = (link) => (link.startsWith('wrote:') ? 'out:' : 'v:') + link.slice(6);
189
+ for (const step of graph.steps) {
190
+ if (!step.cell) {
191
+ for (const n of step.nodes)
192
+ b.make('v:' + n.name, 'input', n.name, null, 'Already in the session', []);
193
+ continue;
194
+ }
195
+ const cell = step.cell, where = (c) => ({ cellId: c.cellId, number: c.number, label: cellLabel(c) });
196
+ const whole = (c) => ({ from: 1, to: c.code.split('\n').length, code: c.code, cell: where(c) });
197
+ const into = [...graph.links.filter(l => l.to === step.id).map(l => idOf(l.from)), ...step.reads.map(fileNode)];
198
+ const current = new Set(step.nodes.map(n => n.name));
199
+ const flow = scriptFlow(cell.code, cell.language, undefined, cell.used ?? []);
200
+ const stepOf = (link) => flow.steps.find(s => s.id === 'lines:' + link.slice(link.lastIndexOf('@') + 1));
201
+ // What a statement read: the session's values and files as the record has them, and what the
202
+ // statements before it made, through what this cell made that the session no longer holds.
203
+ const partsOf = (s, seen = new Set()) => {
204
+ if (seen.has(s.id))
205
+ return [];
206
+ seen.add(s.id);
207
+ return [...flow.links.filter(l => l.to === s.id).flatMap(l => {
208
+ const name = l.from.slice(6).replace(/@\d+$/, ''), before = stepOf(l.from);
209
+ return l.from.startsWith('wrote:') ? [fileNode(name)] : current.has(name) ? ['v:' + name] : before ? partsOf(before, seen) : [];
210
+ }), ...flow.outside.filter(o => o.to === s.id).map(o => 'v:' + o.name).filter(id => into.includes(id)), ...s.reads.map(fileNode)];
211
+ };
212
+ const own = new Map(), key = (kind, name) => (kind === 'file' ? 'f:' : 'v:') + name;
213
+ if (flow.steps.length > 1)
214
+ for (const s of flow.steps)
215
+ for (const n of s.nodes)
216
+ own.set(key(n.kind, n.name), [...own.get(key(n.kind, n.name)) ?? [], s]);
217
+ const seen = new Set([...own.values()].flat().flatMap(s => partsOf(s)));
218
+ const unseen = into.filter(id => !seen.has(id)), readInCell = new Set(flow.links.map(l => l.from));
219
+ const ends = [];
220
+ for (const n of step.nodes) {
221
+ if (n.kind === 'plot')
222
+ continue;
223
+ const kind = n.kind === 'value' ? 'value' : 'output', id = (kind === 'value' ? 'v:' : 'out:') + n.name, meant = flow.means.get((kind === 'value' ? 'value:' : 'file:') + n.name);
224
+ const steps = own.get(key(n.kind, n.name));
225
+ for (const c of step.earlier)
226
+ if (c.defined?.includes(n.name)) {
227
+ b.make(id, kind, n.name, whole(c), kind === 'value' ? howOf(c.code, n.name, cell.language) : howFile(c.code, n.name), []);
228
+ b.means(id, meanOfCell(c).get('value:' + n.name));
229
+ }
230
+ if (steps) {
231
+ const first = steps[0], last = steps.at(-1), how = kind === 'value' ? howOf(first.cell.code, n.name, cell.language) : howFile(first.cell.code, n.name);
232
+ for (const s of steps) {
233
+ const making = { from: s.from, to: s.to, code: s.cell.code, cell: where(cell) };
234
+ b.make(id, kind, n.name, s.nodes.length > 1 && kind === 'value' ? narrowed(making, n.name, cell.language) : making, how, [...partsOf(s), ...unseen], functions.has(n.name) || s.functions.includes(n.name), step.stale);
235
+ }
236
+ b.means(id, meant);
237
+ if (kind === 'value' && !readInCell.has(`value:${n.name}@${last.from}`))
238
+ ends.push(id);
239
+ }
240
+ else {
241
+ const how = flow.steps.length === 1 ? (kind === 'value' ? howOf(cell.code, n.name, cell.language) : howFile(cell.code, n.name)) : cell.purpose ?? cellLabel(cell);
242
+ b.make(id, kind, n.name, whole(cell), how, into, functions.has(n.name), step.stale);
243
+ b.means(id, meant);
244
+ if (kind === 'value')
245
+ ends.push(id);
246
+ }
247
+ }
248
+ for (const p of step.reads)
249
+ b.means(fileNode(p), flow.means.get('file:' + p));
250
+ // A plot comes from what the statements that make nothing read (plot(fit), print(p); not rm()
251
+ // or a check), as the statements before them made it; else from what the cell made last, else
252
+ // what it read.
253
+ const lines = cell.code.split('\n');
254
+ const drawing = flow.quietReads.filter(q => !/^\s*(?:rm|remove|del|stopifnot|assert|message|cat|warning|stop)\b/.test(lines[q.from - 1] ?? '')).map(q => ({ ...q, parts: q.used.flatMap(name => {
255
+ const before = [...flow.steps].reverse().find(s => s.from < q.from && s.nodes.some(n => n.kind === 'value' && n.name === name));
256
+ return !before ? (into.includes('v:' + name) ? ['v:' + name] : []) : current.has(name) ? ['v:' + name] : partsOf(before);
257
+ }) })).filter(q => q.parts.length);
258
+ for (const n of step.nodes)
259
+ if (n.kind === 'plot') {
260
+ b.make(n.id, 'plot', `${n.name} · ${cell.language === 'r' ? 'R' : 'Python'} ${cell.number}`, whole(cell), drawing.length ? lines.slice(drawing.at(-1).from - 1, drawing.at(-1).to).join(' ').trim() : cell.purpose ?? cellLabel(cell), drawing.length ? drawing.flatMap(q => q.parts) : ends.length ? ends : into, false, step.stale);
261
+ b.means(n.id, drawing.at(-1)?.means);
262
+ }
263
+ }
264
+ // The newest results first.
265
+ const done = b.finish({ quiet: 0, cut: 0, tooLong: false }), ran = (id) => Math.max(0, ...done.nodes.get(id).made.map(m => m.cell?.number ?? 0));
266
+ return { ...done, results: [...done.results].sort((x, y) => ran(y) - ran(x)), omitted: graph.omitted };
267
+ }
268
+ // What a node comes from and what comes of it, each holding the node.
269
+ export function graphPath(graph, id) {
270
+ const reach = (next) => {
271
+ const seen = new Set([id]), queue = [id];
272
+ while (queue.length)
273
+ for (const o of next(graph.nodes.get(queue.pop())))
274
+ if (!seen.has(o) && graph.nodes.has(o)) {
275
+ seen.add(o);
276
+ queue.push(o);
277
+ }
278
+ return seen;
279
+ };
280
+ return { up: reach(n => n.parents), down: reach(n => n.children) };
281
+ }
282
+ // Rows from the data down: a node sits one row below the lowest of what it comes from; within a
283
+ // row, nodes sit near the middle of what they come from, else in the order they were made.
284
+ export function graphRows(graph, shown) {
285
+ const depth = new Map(), visiting = new Set();
286
+ const parents = (id) => graph.nodes.get(id).parents.filter(p => shown.has(p));
287
+ const rowOf = (id) => {
288
+ if (depth.has(id))
289
+ return depth.get(id);
290
+ if (visiting.has(id))
291
+ return 0;
292
+ visiting.add(id);
293
+ const d = Math.max(-1, ...parents(id).map(rowOf)) + 1;
294
+ visiting.delete(id);
295
+ depth.set(id, d);
296
+ return d;
297
+ };
298
+ const at = (n) => n.made[0] ? (n.made[0].cell?.number ?? 0) * 1e5 + n.made[0].from : -1;
299
+ const ordered = [...shown].map(id => graph.nodes.get(id)).sort((a, b) => at(a) - at(b) || a.name.localeCompare(b.name));
300
+ const rows = [];
301
+ for (const n of ordered)
302
+ (rows[rowOf(n.id)] ??= []).push(n.id);
303
+ const kept = rows.filter(Boolean), place = new Map();
304
+ kept.forEach(row => row.forEach((id, i) => place.set(id, i / Math.max(1, row.length - 1))));
305
+ for (const row of kept.slice(1)) {
306
+ const middle = (id) => { const ps = parents(id).map(p => place.get(p)); return ps.length ? ps.reduce((s, x) => s + x, 0) / ps.length : place.get(id); };
307
+ row.sort((a, b) => middle(a) - middle(b));
308
+ row.forEach((id, i) => place.set(id, i / Math.max(1, row.length - 1)));
309
+ }
310
+ return kept;
311
+ }
312
+ export function graphMarks(graph, id) {
313
+ const node = graph.nodes.get(id);
314
+ if (!node)
315
+ return [];
316
+ const { up, down } = graphPath(graph, id), out = [];
317
+ const add = (kind, made) => { for (const m of made)
318
+ out.push({ ...m, kind }); };
319
+ add('here', node.made);
320
+ for (const n of up) {
321
+ const u = graph.nodes.get(n);
322
+ if (n !== id)
323
+ add('from', u.made);
324
+ for (const use of u.uses)
325
+ add('from', graph.folded.get(use)?.made ?? []);
326
+ }
327
+ for (const n of down)
328
+ if (n !== id)
329
+ add('into', graph.nodes.get(n).made);
330
+ return out;
331
+ }
332
+ // The node made at a line (of a cell's code, when it names one), if any: of those, the one made in
333
+ // the fewest lines there.
334
+ export function graphNodeAt(graph, line, cellId) {
335
+ let best = null, span = Infinity;
336
+ for (const n of graph.nodes.values())
337
+ for (const m of n.made) {
338
+ if (m.cell?.cellId !== cellId || line < m.from || line > m.to || m.to - m.from >= span)
339
+ continue;
340
+ best = n;
341
+ span = m.to - m.from;
342
+ }
343
+ return best;
344
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rho-workspace/plugin-kernel",
3
- "version": "0.5.2",
3
+ "version": "0.5.5",
4
4
  "type": "module",
5
5
  "description": "Rho live session plugin: an R and a Python session the Agent and the person run code in, kept with each cell's output, plots and the session's variables",
6
6
  "license": "AGPL-3.0-only",
@@ -98,11 +98,14 @@ lineage_of <- function(code) {
98
98
  list(mentioned = unique(words), assigned = unique(assigned), strings = unique(substring(quoted, 2, nchar(quoted) - 1)))
99
99
  }
100
100
  # The strings that name a place in the project, each as its project path, with the file's or
101
- # folder's size and time before the cell. A path outside the project is not followed.
101
+ # folder's size and time before the cell. A path outside the project is not followed. At most
102
+ # `most` strings are looked at; those that look like a file's path (a folder or an extension)
103
+ # come first, so a script's many labels do not crowd out the file it writes at its end.
102
104
  project_paths <- function(strings, most = 32L) {
103
105
  # Paths are compared with / as their separator, which Windows also takes (C:/data/x.csv).
104
106
  root <- normalizePath(getwd(), winslash = "/")
105
- s <- utils::head(strings[nchar(strings) > 0 & nchar(strings) < 512 & !grepl("[\n\r\t]", strings)], most)
107
+ s <- strings[nchar(strings) > 0 & nchar(strings) < 512 & !grepl("[\n\r\t]", strings)]
108
+ s <- utils::head(s[order(!grepl("/|\\.[A-Za-z][A-Za-z0-9]{0,7}$", s))], most)
106
109
  out <- list()
107
110
  for (p in s) {
108
111
  full <- if (grepl("^(/|~|[A-Za-z]:[/\\\\])", p)) path.expand(p) else file.path(root, p)
@@ -378,7 +381,7 @@ inspect <- function(msg) {
378
381
  error = function(e) reply(list(state = "failed", problem = conditionMessage(e))))
379
382
  }
380
383
 
381
- emit(list(kind = "ready", version = R.version.string, pid = Sys.getpid(), host = Sys.info()[["nodename"]], folder = getwd(), variables = variables(200)))
384
+ emit(list(kind = "ready", version = R.version.string, executable = file.path(R.home("bin"), if (.Platform$OS.type == "windows") "Rscript.exe" else "Rscript"), pid = Sys.getpid(), host = Sys.info()[["nodename"]], folder = getwd(), variables = variables(200)))
382
385
  repeat {
383
386
  line <- tryCatch(readLines(input, n = 1), interrupt = function(e) NA)
384
387
  if (identical(line, NA)) next
@@ -4,7 +4,7 @@
4
4
  # that value, as a notebook does. Figures made with matplotlib are saved after each cell. An
5
5
  # interrupt (SIGINT; on Windows a Ctrl+C or Ctrl+Break on the session's console) stops the cell
6
6
  # that is running and leaves the session and its variables.
7
- import ast, base64, io, json, linecache, os, platform, signal, sys, tempfile, traceback, types
7
+ import ast, base64, io, json, linecache, os, platform, re, signal, sys, tempfile, traceback, types
8
8
 
9
9
  root = sys.argv[1]
10
10
  os.chdir(root)
@@ -174,9 +174,12 @@ def stamp(path):
174
174
  return ('folder', info.st_mtime_ns) if os.path.isdir(path) else (info.st_size, info.st_mtime_ns)
175
175
  except OSError: return None
176
176
 
177
+ # At most `most` strings are looked at; those that look like a file's path (a folder or an
178
+ # extension) come first, so a script's many labels do not crowd out the file it writes at its end.
177
179
  def project_paths(strings, most=32):
178
180
  root, out = os.path.realpath(os.getcwd()), {}
179
- for text in [t for t in strings if 0 < len(t) < 512 and not any(c in t for c in '\n\r\t')][:most]:
181
+ kept = [t for t in strings if 0 < len(t) < 512 and not any(c in t for c in '\n\r\t')]
182
+ for text in sorted(kept, key=lambda t: not re.search(r'/|\.[A-Za-z][A-Za-z0-9]{0,7}$', t))[:most]:
180
183
  full = os.path.expanduser(text) if text.startswith(('/', '~')) else os.path.join(root, text)
181
184
  # The folder may not be there yet: one the cell makes before it writes into it.
182
185
  folder = os.path.realpath(os.path.dirname(full))
@@ -442,7 +445,7 @@ def inspect_value(msg):
442
445
  except Exception as error:
443
446
  reply({'state': 'failed', 'problem': f'{type(error).__name__}: {error}'})
444
447
 
445
- emit({'kind': 'ready', 'version': 'Python ' + sys.version.split()[0], 'pid': os.getpid(), 'host': platform.node(), 'folder': os.getcwd(), 'variables': variables(200)})
448
+ emit({'kind': 'ready', 'version': 'Python ' + sys.version.split()[0], 'executable': sys.executable, 'pid': os.getpid(), 'host': platform.node(), 'folder': os.getcwd(), 'variables': variables(200)})
446
449
  while True:
447
450
  try:
448
451
  line = requests.readline()
@@ -1061,7 +1061,7 @@ var rateLimit = (passedOptions) => {
1061
1061
  const retryAfter = await retrieveRetryAfter;
1062
1062
  setRetryAfterHeader(response, info, config.windowMs, retryAfter);
1063
1063
  }
1064
- config.handler(request, response, next, options);
1064
+ await config.handler(request, response, next, options);
1065
1065
  return;
1066
1066
  }
1067
1067
  next();
@@ -1018,7 +1018,7 @@ var rateLimit = (passedOptions) => {
1018
1018
  const retryAfter = await retrieveRetryAfter;
1019
1019
  setRetryAfterHeader(response, info, config.windowMs, retryAfter);
1020
1020
  }
1021
- config.handler(request, response, next, options);
1021
+ await config.handler(request, response, next, options);
1022
1022
  return;
1023
1023
  }
1024
1024
  next();
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-rate-limit",
3
- "version": "8.7.2",
3
+ "version": "8.7.3",
4
4
  "description": "Basic IP rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.",
5
5
  "author": {
6
6
  "name": "Nathan Friedly",
@@ -733,7 +733,7 @@ class Address6 {
733
733
  address = this.parse4in6(address);
734
734
  const badCharacters = address.match(constants6.RE_BAD_CHARACTERS);
735
735
  if (badCharacters) {
736
- throw new address_error_1.AddressError(`Bad character${badCharacters.length > 1 ? 's' : ''} detected in address: ${badCharacters.join('')}`, address.replace(constants6.RE_BAD_CHARACTERS, '<span class="parse-error">$1</span>'));
736
+ throw new address_error_1.AddressError(`Bad character${badCharacters.length > 1 ? 's' : ''} detected in address: ${badCharacters.join('')}`, address.replace(constants6.RE_BAD_CHARACTERS, (character) => `<span class="parse-error">${helpers.escapeHtml(character)}</span>`));
737
737
  }
738
738
  const badAddress = address.match(constants6.RE_BAD_ADDRESS);
739
739
  if (badAddress) {
@@ -16,7 +16,7 @@
16
16
  "bigint",
17
17
  "browser"
18
18
  ],
19
- "version": "10.7.5",
19
+ "version": "10.7.6",
20
20
  "author": "Beau Gunderson <beau@beaugunderson.com> (https://beaugunderson.com/)",
21
21
  "license": "MIT",
22
22
  "main": "dist/ip-address.js",