@rho-workspace/rho 0.5.3 → 0.5.4

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 (216) hide show
  1. package/README.md +24 -5
  2. package/dist/capabilities.d.ts +27 -0
  3. package/dist/capabilities.js +73 -1
  4. package/dist/cli.js +150 -25
  5. package/dist/contract.generated.d.ts +112 -12
  6. package/dist/contracts/owners.generated.js +103 -8
  7. package/dist/conversation-presentation.d.ts +3 -1
  8. package/dist/conversation-presentation.js +16 -6
  9. package/dist/conversations.d.ts +10 -6
  10. package/dist/conversations.js +17 -13
  11. package/dist/installs.d.ts +11 -0
  12. package/dist/installs.js +179 -0
  13. package/dist/project-notes.js +2 -0
  14. package/dist/protocol.js +7 -5
  15. package/dist/screen-check-skill.d.ts +2 -0
  16. package/dist/screen-check-skill.js +39 -0
  17. package/dist/server.d.ts +2 -0
  18. package/dist/server.js +50 -7
  19. package/dist/web/.vite/manifest.json +51 -51
  20. package/dist/web/assets/{choices-B-y2OYvE.js → choices-DU9kHlyQ.js} +1 -1
  21. package/dist/web/assets/{console-e1P5qYQ5.js → console-Dbdo-5oO.js} +1 -1
  22. package/dist/web/assets/{dist-Dd3iAGFy.js → dist-B2V0VDO0.js} +1 -1
  23. package/dist/web/assets/{dist-CH56yNDn.js → dist-BV3hWfn_.js} +1 -1
  24. package/dist/web/assets/{dist-CBM2oq6g.js → dist-CLNF2g-E.js} +1 -1
  25. package/dist/web/assets/{dist-DEorbOW0.js → dist-D25Vn17i.js} +1 -1
  26. package/dist/web/assets/{explore-in-muWXOGOY.js → explore-in-8Q5ftt-E.js} +1 -1
  27. package/dist/web/assets/{graph-CK-df5lh.js → graph-hS2kvHTI.js} +1 -1
  28. package/dist/web/assets/{index-BYuKpyoi.js → index-BHQIaDsx.js} +220 -121
  29. package/dist/web/assets/index-Cj1_iqyK.css +1 -0
  30. package/dist/web/assets/{notes-meaning-B3HFbh84.js → notes-meaning-DdPbtNzJ.js} +1 -1
  31. package/dist/web/assets/{overview-D1Ev2OC_.js → overview-BV6ZO5TO.js} +3 -3
  32. package/dist/web/assets/{preview-HbmQKUGY.js → preview-n5lOOdjN.js} +1 -1
  33. package/dist/web/assets/{review-BVh9jWMB.js → review-CmWou4Iv.js} +1 -1
  34. package/dist/web/assets/{skills-DPaEYkln.js → skills-Dy7n3L9d.js} +1 -1
  35. package/dist/web/assets/{skills-work-dvjfy_tu.js → skills-work-Cj0W6b-I.js} +1 -1
  36. package/dist/web/assets/{studio-process-BYm8mjRJ.js → studio-process-QOY_n2_8.js} +1 -1
  37. package/dist/web/assets/{timeline-events-CDZ7wiJX.js → timeline-events-DmX1BCh3.js} +1 -1
  38. package/dist/web/assets/{work-turns-BeCt303c.js → work-turns-Co0C71rJ.js} +1 -1
  39. package/dist/web/assets/{workspace-d5Hw_ClZ.js → workspace-BKFefRfJ.js} +2 -2
  40. package/dist/web/composition.json +73 -73
  41. package/dist/web/index.html +2 -2
  42. package/dist/web/renderer.json +1 -1
  43. package/docs/FRONTEND.md +30 -14
  44. package/docs/HEADLESS.md +59 -13
  45. package/example/pa14-qs/.rho/rho/conversations/c-67f77cfebaba2cea.json +1 -1
  46. package/example/pa14-qs/.rho/rho/conversations/c-91aa2e46b1ac1a6c.json +1 -1
  47. package/example/pa14-qs/.rho/rho/conversations/c-fa24dfd80dfe4bcb.json +1 -1
  48. package/node_modules/@hono/node-server/dist/index.js +11 -0
  49. package/node_modules/@hono/node-server/dist/index.mjs +11 -0
  50. package/node_modules/@hono/node-server/dist/listener.js +11 -0
  51. package/node_modules/@hono/node-server/dist/listener.mjs +11 -0
  52. package/node_modules/@hono/node-server/dist/request.js +11 -0
  53. package/node_modules/@hono/node-server/dist/request.mjs +11 -0
  54. package/node_modules/@hono/node-server/dist/server.js +11 -0
  55. package/node_modules/@hono/node-server/dist/server.mjs +11 -0
  56. package/node_modules/@hono/node-server/dist/vercel.js +11 -0
  57. package/node_modules/@hono/node-server/dist/vercel.mjs +11 -0
  58. package/node_modules/@hono/node-server/package.json +1 -1
  59. package/node_modules/@rho-workspace/plugin-agent/README.md +3 -1
  60. package/node_modules/@rho-workspace/plugin-agent/dist/acp-conversation.js +14 -3
  61. package/node_modules/@rho-workspace/plugin-agent/dist/conversation.d.ts +1 -0
  62. package/node_modules/@rho-workspace/plugin-agent/dist/conversation.js +1 -0
  63. package/node_modules/@rho-workspace/plugin-agent/dist/generic-acp.d.ts +11 -0
  64. package/node_modules/@rho-workspace/plugin-agent/dist/generic-acp.js +7 -0
  65. package/node_modules/@rho-workspace/plugin-agent/dist/mcp.js +5 -1
  66. package/node_modules/@rho-workspace/plugin-agent/package.json +1 -1
  67. package/node_modules/@rho-workspace/plugin-annotations/package.json +1 -1
  68. package/node_modules/@rho-workspace/plugin-documents/README.md +4 -0
  69. package/node_modules/@rho-workspace/plugin-documents/dist/index.d.ts +3 -0
  70. package/node_modules/@rho-workspace/plugin-documents/dist/index.js +1 -1
  71. package/node_modules/@rho-workspace/plugin-documents/package.json +1 -1
  72. package/node_modules/@rho-workspace/plugin-kernel/README.md +71 -10
  73. package/node_modules/@rho-workspace/plugin-kernel/dist/code.d.ts +2 -0
  74. package/node_modules/@rho-workspace/plugin-kernel/dist/code.js +4 -1
  75. package/node_modules/@rho-workspace/plugin-kernel/dist/contract.js +5 -0
  76. package/node_modules/@rho-workspace/plugin-kernel/dist/index.d.ts +7 -0
  77. package/node_modules/@rho-workspace/plugin-kernel/dist/index.js +55 -8
  78. package/node_modules/@rho-workspace/plugin-kernel/dist/lineage.d.ts +9 -6
  79. package/node_modules/@rho-workspace/plugin-kernel/dist/lineage.js +18 -41
  80. package/node_modules/@rho-workspace/plugin-kernel/dist/operations.js +5 -2
  81. package/node_modules/@rho-workspace/plugin-kernel/dist/script-flow.d.ts +39 -0
  82. package/node_modules/@rho-workspace/plugin-kernel/dist/script-flow.js +661 -0
  83. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-base.d.ts +3 -0
  84. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-base.js +10 -0
  85. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-flow.d.ts +38 -4
  86. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-flow.js +194 -97
  87. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-notebook-work.js +1 -2
  88. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-notebook.d.ts +10 -2
  89. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-notebook.js +79 -18
  90. package/node_modules/@rho-workspace/plugin-kernel/dist/ui-styles.js +115 -45
  91. package/node_modules/@rho-workspace/plugin-kernel/dist/ui.d.ts +1 -1
  92. package/node_modules/@rho-workspace/plugin-kernel/dist/ui.js +1 -1
  93. package/node_modules/@rho-workspace/plugin-kernel/dist/value-graph.d.ts +63 -0
  94. package/node_modules/@rho-workspace/plugin-kernel/dist/value-graph.js +344 -0
  95. package/node_modules/@rho-workspace/plugin-kernel/package.json +1 -1
  96. package/node_modules/@rho-workspace/plugin-kernel/runners/runner.R +6 -3
  97. package/node_modules/@rho-workspace/plugin-kernel/runners/runner.py +6 -3
  98. package/node_modules/express-rate-limit/dist/index.cjs +1 -1
  99. package/node_modules/express-rate-limit/dist/index.mjs +1 -1
  100. package/node_modules/express-rate-limit/package.json +1 -1
  101. package/node_modules/ip-address/dist/ipv6.js +1 -1
  102. package/node_modules/ip-address/package.json +1 -1
  103. package/node_modules/playwright-core/LICENSE +202 -0
  104. package/node_modules/playwright-core/NOTICE +5 -0
  105. package/node_modules/playwright-core/ThirdPartyNotices.txt +13 -0
  106. package/node_modules/playwright-core/bin/install_media_pack.ps1 +5 -0
  107. package/node_modules/playwright-core/bin/install_webkit_wsl.ps1 +33 -0
  108. package/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh +42 -0
  109. package/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh +13 -0
  110. package/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 +24 -0
  111. package/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh +42 -0
  112. package/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh +12 -0
  113. package/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 +24 -0
  114. package/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh +48 -0
  115. package/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh +11 -0
  116. package/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 +23 -0
  117. package/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh +48 -0
  118. package/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh +11 -0
  119. package/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 +23 -0
  120. package/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh +48 -0
  121. package/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh +11 -0
  122. package/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 +24 -0
  123. package/node_modules/playwright-core/browsers.json +52 -0
  124. package/node_modules/playwright-core/cli.js +22 -0
  125. package/node_modules/playwright-core/index.js +17 -0
  126. package/node_modules/playwright-core/index.mjs +28 -0
  127. package/node_modules/playwright-core/lib/bootstrap.js +149 -0
  128. package/node_modules/playwright-core/lib/coreBundle.js +78041 -0
  129. package/node_modules/playwright-core/lib/entry/cliDaemon.js +5 -0
  130. package/node_modules/playwright-core/lib/entry/dashboardApp.js +3 -0
  131. package/node_modules/playwright-core/lib/entry/mcp.js +10 -0
  132. package/node_modules/playwright-core/lib/entry/oopBrowserDownload.js +3 -0
  133. package/node_modules/playwright-core/lib/package.js +50 -0
  134. package/node_modules/playwright-core/lib/server/chromium/appIcon.png +0 -0
  135. package/node_modules/playwright-core/lib/server/electron/loader.js +123 -0
  136. package/node_modules/playwright-core/lib/serverRegistry.js +1939 -0
  137. package/node_modules/playwright-core/lib/serverRegistry.js.LICENSE +65 -0
  138. package/node_modules/playwright-core/lib/tools/cli-client/channelSessions.js +141 -0
  139. package/node_modules/playwright-core/lib/tools/cli-client/cli.js +7 -0
  140. package/node_modules/playwright-core/lib/tools/cli-client/help.json +808 -0
  141. package/node_modules/playwright-core/lib/tools/cli-client/minimist.js +128 -0
  142. package/node_modules/playwright-core/lib/tools/cli-client/output.js +352 -0
  143. package/node_modules/playwright-core/lib/tools/cli-client/program.js +422 -0
  144. package/node_modules/playwright-core/lib/tools/cli-client/registry.js +180 -0
  145. package/node_modules/playwright-core/lib/tools/cli-client/session.js +261 -0
  146. package/node_modules/playwright-core/lib/tools/dashboard/appIcon.png +0 -0
  147. package/node_modules/playwright-core/lib/tools/utils/extension.js +112 -0
  148. package/node_modules/playwright-core/lib/tools/utils/socketConnection.js +108 -0
  149. package/node_modules/playwright-core/lib/utilsBundle.js +86078 -0
  150. package/node_modules/playwright-core/lib/utilsBundle.js.LICENSE +1890 -0
  151. package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule--QdMvsKi.css +1 -0
  152. package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule-CQ8RZGBm.js +32 -0
  153. package/node_modules/playwright-core/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
  154. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
  155. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
  156. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
  157. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-AwgwcYie.css +1 -0
  158. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-hRvO4yU2.js +12 -0
  159. package/node_modules/playwright-core/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
  160. package/node_modules/playwright-core/lib/vite/dashboard/index.html +29 -0
  161. package/node_modules/playwright-core/lib/vite/dashboard/playwright-logo.svg +24 -0
  162. package/node_modules/playwright-core/lib/vite/htmlReport/index.html +16 -0
  163. package/node_modules/playwright-core/lib/vite/htmlReport/report.css +2 -0
  164. package/node_modules/playwright-core/lib/vite/htmlReport/report.js +32 -0
  165. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
  166. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-DK72OMRi.js +32 -0
  167. package/node_modules/playwright-core/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
  168. package/node_modules/playwright-core/lib/vite/recorder/assets/index-BZpYJZ-P.css +1 -0
  169. package/node_modules/playwright-core/lib/vite/recorder/assets/index-Cn0mmDuv.js +129 -0
  170. package/node_modules/playwright-core/lib/vite/recorder/index.html +29 -0
  171. package/node_modules/playwright-core/lib/vite/recorder/playwright-logo.svg +9 -0
  172. package/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-BEB2e8M3.js +32 -0
  173. package/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-D-g2vrvf.js +184 -0
  174. package/node_modules/playwright-core/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
  175. package/node_modules/playwright-core/lib/vite/traceViewer/assets/xtermModule-B794rD2Z.js +7 -0
  176. package/node_modules/playwright-core/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
  177. package/node_modules/playwright-core/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  178. package/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.C8BeHuxd.css +1 -0
  179. package/node_modules/playwright-core/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
  180. package/node_modules/playwright-core/lib/vite/traceViewer/index.html +44 -0
  181. package/node_modules/playwright-core/lib/vite/traceViewer/index.oNry3Hjv.js +1 -0
  182. package/node_modules/playwright-core/lib/vite/traceViewer/manifest.webmanifest +16 -0
  183. package/node_modules/playwright-core/lib/vite/traceViewer/playwright-logo.svg +9 -0
  184. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
  185. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.html +10 -0
  186. package/node_modules/playwright-core/lib/vite/traceViewer/sw.bundle.js +4 -0
  187. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CYwC_gH1.js +5 -0
  188. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CyMfwkXJ.css +1 -0
  189. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +18 -0
  190. package/node_modules/playwright-core/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
  191. package/node_modules/playwright-core/lib/webp_codec.LICENSE +173 -0
  192. package/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
  193. package/node_modules/playwright-core/lib/xdg-open +1267 -0
  194. package/node_modules/playwright-core/package.json +34 -0
  195. package/package.json +10 -6
  196. package/protocol/index.json +17 -17
  197. package/protocol/operations/conversation.settings.check.json +147 -4
  198. package/protocol/operations/conversation.settings.read.json +145 -3
  199. package/protocol/operations/conversation.settings.update.json +166 -4
  200. package/protocol/operations/conversation.start.json +2 -1
  201. package/protocol/operations/kernel.interrupt.json +20 -0
  202. package/protocol/operations/kernel.read.json +30 -0
  203. package/protocol/operations/kernel.run.json +36 -1
  204. package/protocol/operations/kernel.stop.json +10 -0
  205. package/scripts/browser-checks.mjs +53 -0
  206. package/scripts/screen-check.mjs +193 -0
  207. package/vendor/composition.json +102 -102
  208. package/vendor/rho-workspace-plugin-agent-0.4.28.tgz +0 -0
  209. package/vendor/rho-workspace-plugin-annotations-0.5.2.tgz +0 -0
  210. package/vendor/rho-workspace-plugin-documents-0.4.11.tgz +0 -0
  211. package/vendor/rho-workspace-plugin-kernel-0.5.5.tgz +0 -0
  212. package/web/theme.css +17 -2
  213. package/dist/web/assets/index-DBd77u4a.css +0 -1
  214. package/vendor/rho-workspace-plugin-agent-0.4.27.tgz +0 -0
  215. package/vendor/rho-workspace-plugin-documents-0.4.10.tgz +0 -0
  216. package/vendor/rho-workspace-plugin-kernel-0.5.2.tgz +0 -0
@@ -52,6 +52,15 @@ var RequestError = class extends Error {
52
52
  this.name = "RequestError";
53
53
  }
54
54
  };
55
+ var validateRequestTarget = (target) => {
56
+ const backslash = target.indexOf("\\");
57
+ if (backslash !== -1) {
58
+ const query = target.indexOf("?");
59
+ if (query === -1 || backslash < query) {
60
+ throw new RequestError("Backslash in request path");
61
+ }
62
+ }
63
+ };
55
64
  var toRequestError = (e) => {
56
65
  if (e instanceof RequestError) {
57
66
  return e;
@@ -212,6 +221,7 @@ var newRequest = (incoming, defaultHostname) => {
212
221
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
213
222
  }
214
223
  try {
224
+ validateRequestTarget(incomingUrl);
215
225
  const url2 = new URL(incomingUrl);
216
226
  req[urlKey] = url2.href;
217
227
  } catch (e) {
@@ -232,6 +242,7 @@ var newRequest = (incoming, defaultHostname) => {
232
242
  } else {
233
243
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
234
244
  }
245
+ validateRequestTarget(incomingUrl);
235
246
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
236
247
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
237
248
  throw new RequestError("Invalid host header");
@@ -13,6 +13,15 @@ var RequestError = class extends Error {
13
13
  this.name = "RequestError";
14
14
  }
15
15
  };
16
+ var validateRequestTarget = (target) => {
17
+ const backslash = target.indexOf("\\");
18
+ if (backslash !== -1) {
19
+ const query = target.indexOf("?");
20
+ if (query === -1 || backslash < query) {
21
+ throw new RequestError("Backslash in request path");
22
+ }
23
+ }
24
+ };
16
25
  var toRequestError = (e) => {
17
26
  if (e instanceof RequestError) {
18
27
  return e;
@@ -173,6 +182,7 @@ var newRequest = (incoming, defaultHostname) => {
173
182
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
174
183
  }
175
184
  try {
185
+ validateRequestTarget(incomingUrl);
176
186
  const url2 = new URL(incomingUrl);
177
187
  req[urlKey] = url2.href;
178
188
  } catch (e) {
@@ -193,6 +203,7 @@ var newRequest = (incoming, defaultHostname) => {
193
203
  } else {
194
204
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
195
205
  }
206
+ validateRequestTarget(incomingUrl);
196
207
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
197
208
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
198
209
  throw new RequestError("Invalid host header");
@@ -44,6 +44,15 @@ var RequestError = class extends Error {
44
44
  this.name = "RequestError";
45
45
  }
46
46
  };
47
+ var validateRequestTarget = (target) => {
48
+ const backslash = target.indexOf("\\");
49
+ if (backslash !== -1) {
50
+ const query = target.indexOf("?");
51
+ if (query === -1 || backslash < query) {
52
+ throw new RequestError("Backslash in request path");
53
+ }
54
+ }
55
+ };
47
56
  var toRequestError = (e) => {
48
57
  if (e instanceof RequestError) {
49
58
  return e;
@@ -204,6 +213,7 @@ var newRequest = (incoming, defaultHostname) => {
204
213
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
205
214
  }
206
215
  try {
216
+ validateRequestTarget(incomingUrl);
207
217
  const url2 = new URL(incomingUrl);
208
218
  req[urlKey] = url2.href;
209
219
  } catch (e) {
@@ -224,6 +234,7 @@ var newRequest = (incoming, defaultHostname) => {
224
234
  } else {
225
235
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
226
236
  }
237
+ validateRequestTarget(incomingUrl);
227
238
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
228
239
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
229
240
  throw new RequestError("Invalid host header");
@@ -10,6 +10,15 @@ var RequestError = class extends Error {
10
10
  this.name = "RequestError";
11
11
  }
12
12
  };
13
+ var validateRequestTarget = (target) => {
14
+ const backslash = target.indexOf("\\");
15
+ if (backslash !== -1) {
16
+ const query = target.indexOf("?");
17
+ if (query === -1 || backslash < query) {
18
+ throw new RequestError("Backslash in request path");
19
+ }
20
+ }
21
+ };
13
22
  var toRequestError = (e) => {
14
23
  if (e instanceof RequestError) {
15
24
  return e;
@@ -170,6 +179,7 @@ var newRequest = (incoming, defaultHostname) => {
170
179
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
171
180
  }
172
181
  try {
182
+ validateRequestTarget(incomingUrl);
173
183
  const url2 = new URL(incomingUrl);
174
184
  req[urlKey] = url2.href;
175
185
  } catch (e) {
@@ -190,6 +200,7 @@ var newRequest = (incoming, defaultHostname) => {
190
200
  } else {
191
201
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
192
202
  }
203
+ validateRequestTarget(incomingUrl);
193
204
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
194
205
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
195
206
  throw new RequestError("Invalid host header");
@@ -38,6 +38,15 @@ var RequestError = class extends Error {
38
38
  this.name = "RequestError";
39
39
  }
40
40
  };
41
+ var validateRequestTarget = (target) => {
42
+ const backslash = target.indexOf("\\");
43
+ if (backslash !== -1) {
44
+ const query = target.indexOf("?");
45
+ if (query === -1 || backslash < query) {
46
+ throw new RequestError("Backslash in request path");
47
+ }
48
+ }
49
+ };
41
50
  var toRequestError = (e) => {
42
51
  if (e instanceof RequestError) {
43
52
  return e;
@@ -198,6 +207,7 @@ var newRequest = (incoming, defaultHostname) => {
198
207
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
199
208
  }
200
209
  try {
210
+ validateRequestTarget(incomingUrl);
201
211
  const url2 = new URL(incomingUrl);
202
212
  req[urlKey] = url2.href;
203
213
  } catch (e) {
@@ -218,6 +228,7 @@ var newRequest = (incoming, defaultHostname) => {
218
228
  } else {
219
229
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
220
230
  }
231
+ validateRequestTarget(incomingUrl);
221
232
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
222
233
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
223
234
  throw new RequestError("Invalid host header");
@@ -7,6 +7,15 @@ var RequestError = class extends Error {
7
7
  this.name = "RequestError";
8
8
  }
9
9
  };
10
+ var validateRequestTarget = (target) => {
11
+ const backslash = target.indexOf("\\");
12
+ if (backslash !== -1) {
13
+ const query = target.indexOf("?");
14
+ if (query === -1 || backslash < query) {
15
+ throw new RequestError("Backslash in request path");
16
+ }
17
+ }
18
+ };
10
19
  var toRequestError = (e) => {
11
20
  if (e instanceof RequestError) {
12
21
  return e;
@@ -167,6 +176,7 @@ var newRequest = (incoming, defaultHostname) => {
167
176
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
168
177
  }
169
178
  try {
179
+ validateRequestTarget(incomingUrl);
170
180
  const url2 = new URL(incomingUrl);
171
181
  req[urlKey] = url2.href;
172
182
  } catch (e) {
@@ -187,6 +197,7 @@ var newRequest = (incoming, defaultHostname) => {
187
197
  } else {
188
198
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
189
199
  }
200
+ validateRequestTarget(incomingUrl);
190
201
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
191
202
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
192
203
  throw new RequestError("Invalid host header");
@@ -48,6 +48,15 @@ var RequestError = class extends Error {
48
48
  this.name = "RequestError";
49
49
  }
50
50
  };
51
+ var validateRequestTarget = (target) => {
52
+ const backslash = target.indexOf("\\");
53
+ if (backslash !== -1) {
54
+ const query = target.indexOf("?");
55
+ if (query === -1 || backslash < query) {
56
+ throw new RequestError("Backslash in request path");
57
+ }
58
+ }
59
+ };
51
60
  var toRequestError = (e) => {
52
61
  if (e instanceof RequestError) {
53
62
  return e;
@@ -208,6 +217,7 @@ var newRequest = (incoming, defaultHostname) => {
208
217
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
209
218
  }
210
219
  try {
220
+ validateRequestTarget(incomingUrl);
211
221
  const url2 = new URL(incomingUrl);
212
222
  req[urlKey] = url2.href;
213
223
  } catch (e) {
@@ -228,6 +238,7 @@ var newRequest = (incoming, defaultHostname) => {
228
238
  } else {
229
239
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
230
240
  }
241
+ validateRequestTarget(incomingUrl);
231
242
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
232
243
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
233
244
  throw new RequestError("Invalid host header");
@@ -13,6 +13,15 @@ var RequestError = class extends Error {
13
13
  this.name = "RequestError";
14
14
  }
15
15
  };
16
+ var validateRequestTarget = (target) => {
17
+ const backslash = target.indexOf("\\");
18
+ if (backslash !== -1) {
19
+ const query = target.indexOf("?");
20
+ if (query === -1 || backslash < query) {
21
+ throw new RequestError("Backslash in request path");
22
+ }
23
+ }
24
+ };
16
25
  var toRequestError = (e) => {
17
26
  if (e instanceof RequestError) {
18
27
  return e;
@@ -173,6 +182,7 @@ var newRequest = (incoming, defaultHostname) => {
173
182
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
174
183
  }
175
184
  try {
185
+ validateRequestTarget(incomingUrl);
176
186
  const url2 = new URL(incomingUrl);
177
187
  req[urlKey] = url2.href;
178
188
  } catch (e) {
@@ -193,6 +203,7 @@ var newRequest = (incoming, defaultHostname) => {
193
203
  } else {
194
204
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
195
205
  }
206
+ validateRequestTarget(incomingUrl);
196
207
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
197
208
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
198
209
  throw new RequestError("Invalid host header");
@@ -46,6 +46,15 @@ var RequestError = class extends Error {
46
46
  this.name = "RequestError";
47
47
  }
48
48
  };
49
+ var validateRequestTarget = (target) => {
50
+ const backslash = target.indexOf("\\");
51
+ if (backslash !== -1) {
52
+ const query = target.indexOf("?");
53
+ if (query === -1 || backslash < query) {
54
+ throw new RequestError("Backslash in request path");
55
+ }
56
+ }
57
+ };
49
58
  var toRequestError = (e) => {
50
59
  if (e instanceof RequestError) {
51
60
  return e;
@@ -206,6 +215,7 @@ var newRequest = (incoming, defaultHostname) => {
206
215
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
207
216
  }
208
217
  try {
218
+ validateRequestTarget(incomingUrl);
209
219
  const url2 = new URL(incomingUrl);
210
220
  req[urlKey] = url2.href;
211
221
  } catch (e) {
@@ -226,6 +236,7 @@ var newRequest = (incoming, defaultHostname) => {
226
236
  } else {
227
237
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
228
238
  }
239
+ validateRequestTarget(incomingUrl);
229
240
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
230
241
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
231
242
  throw new RequestError("Invalid host header");
@@ -10,6 +10,15 @@ var RequestError = class extends Error {
10
10
  this.name = "RequestError";
11
11
  }
12
12
  };
13
+ var validateRequestTarget = (target) => {
14
+ const backslash = target.indexOf("\\");
15
+ if (backslash !== -1) {
16
+ const query = target.indexOf("?");
17
+ if (query === -1 || backslash < query) {
18
+ throw new RequestError("Backslash in request path");
19
+ }
20
+ }
21
+ };
13
22
  var toRequestError = (e) => {
14
23
  if (e instanceof RequestError) {
15
24
  return e;
@@ -170,6 +179,7 @@ var newRequest = (incoming, defaultHostname) => {
170
179
  throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
171
180
  }
172
181
  try {
182
+ validateRequestTarget(incomingUrl);
173
183
  const url2 = new URL(incomingUrl);
174
184
  req[urlKey] = url2.href;
175
185
  } catch (e) {
@@ -190,6 +200,7 @@ var newRequest = (incoming, defaultHostname) => {
190
200
  } else {
191
201
  scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
192
202
  }
203
+ validateRequestTarget(incomingUrl);
193
204
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
194
205
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
195
206
  throw new RequestError("Invalid host header");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hono/node-server",
3
- "version": "1.19.17",
3
+ "version": "1.19.18",
4
4
  "description": "Node.js Adapter for Hono",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -343,7 +343,9 @@ results. Results survive MCP restart. One call to the service may take
343
343
  `RHO_TRANSPORT_MS` (30 s), plus the `waitMs` it asks the service to wait (at most ten
344
344
  minutes, as for a Notebook cell); the call uses `node:http`, whose wait for a reply has
345
345
  no limit of its own. A transport overrun keeps the outcome uncertain and directs
346
- observation of the original identity, never replacement work.
346
+ observation of the original identity, never replacement work. A refused connection is the one
347
+ transport failure whose outcome is known: nothing reached the service, so the call
348
+ returns `unavailable` naming the address and saying nothing ran (`delivered: false`).
347
349
 
348
350
  The pure `./layered-contract` entry defines the four tool inputs and Agent note
349
351
  props. `./layered` provides the bounded complete-object cache and caller checks;
@@ -195,10 +195,21 @@ export class AcpConversation {
195
195
  let model;
196
196
  this.observationOrigin = this.sessionId ? 'history' : 'initial';
197
197
  if (this.sessionId) {
198
- if (!initialized.agentCapabilities?.loadSession)
198
+ const caps = initialized.agentCapabilities;
199
+ if (caps?.loadSession) {
200
+ const loaded = await connection.agent.request(acp.methods.agent.session.load, { ...params, sessionId: this.sessionId });
201
+ this.settings = loaded.configOptions ?? [];
202
+ }
203
+ else if (caps?.sessionCapabilities?.resume) {
204
+ // ACP session/resume (e.g. dsh): restore the persisted session on a fresh process. It composes
205
+ // the request's MCP connections and validates only the workspace, so the non-standard
206
+ // systemPrompt is omitted; history is restored from the Agent's own persistence, not replayed.
207
+ const resumed = await connection.agent.request(acp.methods.agent.session.resume, { cwd: o.cwd, mcpServers: o.mcpServers, sessionId: this.sessionId });
208
+ this.settings = resumed?.configOptions ?? [];
209
+ }
210
+ else {
199
211
  throw new Error('This Agent cannot load the original session. Nothing was resent.');
200
- const loaded = await connection.agent.request(acp.methods.agent.session.load, { ...params, sessionId: this.sessionId });
201
- this.settings = loaded.configOptions ?? [];
212
+ }
202
213
  }
203
214
  else {
204
215
  const created = await connection.agent.request(acp.methods.agent.session.new, params);
@@ -123,5 +123,6 @@ export declare function visibleError(error: unknown, env?: NodeJS.ProcessEnv): s
123
123
  export { ClaudeAcpConversation, type ClaudeAcpOptions } from './claude-acp.js';
124
124
  export { writeClaudePlugin, claudePluginLimits, type ClaudePlugin, type ClaudePluginSkill, type ClaudePluginHook } from './claude-plugin.js';
125
125
  export { CodexAcpConversation, type CodexAcpOptions } from './codex-acp.js';
126
+ export { GenericAcpConversation, type GenericAcpOptions } from './generic-acp.js';
126
127
  export { ClaudeCliConversation } from './claude-cli.js';
127
128
  export type { SessionObservation, SessionTool, ConfigOption, ConfigValue } from './session-observation.js';
@@ -25,4 +25,5 @@ export function visibleError(error, env = process.env) {
25
25
  export { ClaudeAcpConversation } from './claude-acp.js';
26
26
  export { writeClaudePlugin, claudePluginLimits } from './claude-plugin.js';
27
27
  export { CodexAcpConversation } from './codex-acp.js';
28
+ export { GenericAcpConversation } from './generic-acp.js';
28
29
  export { ClaudeCliConversation } from './claude-cli.js';
@@ -0,0 +1,11 @@
1
+ import { AcpConversation, type AcpConversationOptions } from './acp-conversation.js';
2
+ /** A generic ACP agent: any program that speaks ACP v1 over stdio. Rho starts the
3
+ * operator-selected command and drives it exactly as it drives Claude Code or Codex, so
4
+ * supporting another agent is configuration (`--acp-command`), not a new adapter. The
5
+ * command is a file plus its arguments and needs no per-agent environment. */
6
+ export interface GenericAcpOptions extends Omit<AcpConversationOptions, 'command' | 'sessionMeta'> {
7
+ command: AcpConversationOptions['command'];
8
+ }
9
+ export declare class GenericAcpConversation extends AcpConversation {
10
+ constructor(o: GenericAcpOptions);
11
+ }
@@ -0,0 +1,7 @@
1
+ import { AcpConversation } from './acp-conversation.js';
2
+ export class GenericAcpConversation extends AcpConversation {
3
+ constructor(o) {
4
+ // A supplied command skips the missing-client check: the operator named the program.
5
+ super({ ...o, command: o.command });
6
+ }
7
+ }
@@ -36,7 +36,11 @@ async function invoke(method, input = {}, contractRef) {
36
36
  const response = await new Promise((resolve, reject) => {
37
37
  const request = http.request(new URL('/api/v2/' + method, endpoint), { method: 'POST', signal: AbortSignal.timeout(allowance(input)),
38
38
  headers: { authorization: 'Bearer ' + c.token, 'content-type': 'application/json', 'content-length': Buffer.byteLength(body), ...(contractRef ? { 'x-rho-contract-ref': contractRef } : {}) } }, resolve);
39
- request.once('error', reject);
39
+ // A refused connection is the one failure whose outcome is known: nothing reached the
40
+ // service, so nothing ran. It is usually Rho not running, and the person can start it.
41
+ request.once('error', error => reject(error.code === 'ECONNREFUSED'
42
+ ? new Fault('unavailable', `Rho is not running at ${c.url}, so this call did not reach it and nothing ran. Ask the person to start Rho, then call again.`, { url: c.url, delivered: false })
43
+ : error));
40
44
  request.end(body);
41
45
  });
42
46
  const chunks = [];
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rho-workspace/plugin-agent",
3
- "version": "0.4.27",
3
+ "version": "0.4.28",
4
4
  "type": "module",
5
5
  "description": "Rho agent plugin",
6
6
  "license": "AGPL-3.0-only",
@@ -23,7 +23,7 @@
23
23
  "@rho-workspace/plugin-contracts": "0.4.0"
24
24
  },
25
25
  "peerDependencies": {
26
- "@rho-workspace/plugin-documents": "0.4.1 || 0.4.2 || 0.4.3 || 0.4.4 || 0.4.5 || 0.4.6 || 0.4.7 || 0.4.8 || 0.4.9 || 0.4.10",
26
+ "@rho-workspace/plugin-documents": "0.4.1 || 0.4.2 || 0.4.3 || 0.4.4 || 0.4.5 || 0.4.6 || 0.4.7 || 0.4.8 || 0.4.9 || 0.4.10 || 0.4.11",
27
27
  "react": "19.3.1",
28
28
  "react-dom": "19.3.1"
29
29
  },
@@ -157,3 +157,7 @@ Documents 0.4.7 adds a confirmed-text selection callback for Review and an optio
157
157
  excerpt, reads at most 1 MiB per version and previews at most 64 KiB without cutting
158
158
  a Unicode sequence. Buffer snapshots continue to identify their version/dirty
159
159
  state separately from disk captures. No comparison rewrites a buffer or its undo.
160
+
161
+ Documents 0.4.11 lets the editor view (`rho.editor`) keep a boolean `flow` beside its
162
+ `title`: an application that shows a script's data flow beside the editor saves the person's
163
+ switch with the page. The buffer, its undo and its saves are unchanged by it.
@@ -1095,6 +1095,9 @@ export declare const plugin: {
1095
1095
  type: string;
1096
1096
  minLength: number;
1097
1097
  };
1098
+ flow: {
1099
+ type: string;
1100
+ };
1098
1101
  };
1099
1102
  required: string[];
1100
1103
  };
@@ -499,5 +499,5 @@ export const plugin = {
499
499
  description: 'Change a project file that is open in Rho through its shared buffer (document.read, document.edit, document.save), so a person\'s unsaved text, undo and saves stay intact.' }],
500
500
  hooks: [{ id: 'documents.unsaved-text', event: 'PreToolUse', matcher: 'Edit|Write|MultiEdit', entry: './claude-hook', timeoutSeconds: 10 }]
501
501
  },
502
- components: [{ id: 'rho.editor', version: '0.2.0', owner: 'rho-plugins.documents', bindings: { document: 'document' }, ui: './ui', presentation: viewPresentation, propsSchema: { type: 'object', additionalProperties: false, properties: { title: { type: 'string', minLength: 1 } }, required: ['title'] } }]
502
+ components: [{ id: 'rho.editor', version: '0.2.0', owner: 'rho-plugins.documents', bindings: { document: 'document' }, ui: './ui', presentation: viewPresentation, propsSchema: { type: 'object', additionalProperties: false, properties: { title: { type: 'string', minLength: 1 }, flow: { type: 'boolean' } }, required: ['title'] } }]
503
503
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rho-workspace/plugin-documents",
3
- "version": "0.4.10",
3
+ "version": "0.4.11",
4
4
  "type": "module",
5
5
  "description": "Rho documents plugin",
6
6
  "license": "AGPL-3.0-only",
@@ -1,6 +1,6 @@
1
1
  # Notebook
2
2
 
3
- `@rho-workspace/plugin-kernel` 0.5.2 keeps a live R session and a live Python
3
+ `@rho-workspace/plugin-kernel` 0.5.4 keeps a live R session and a live Python
4
4
  session for a project, which an Agent and the person share, on this machine or on a
5
5
  server: one the person manages with serverctl, reached through it, or one reached with
6
6
  ssh.
@@ -71,6 +71,24 @@ once; Stop raises Ctrl+Break and then ends the process tree. R there cannot open
71
71
  so its answers come on a named pipe the host serves and names in `RHO_KERNEL_ANSWERS`. R and
72
72
  Python end printed lines with `\r\n` there; a cell keeps them as `\n`, as elsewhere.
73
73
 
74
+ A session on this machine runs `Rscript` or `python3` from PATH until the project names
75
+ another program. `kernel.run` takes `interpreter`, a program in a folder of the project
76
+ such as the python of a virtual environment made there (`.venv/bin/python`): its folder
77
+ must resolve inside the project, while the file may be the link a virtual environment makes
78
+ to the Python it was made from, and it is started by that name so the environment is the
79
+ one that runs. A path outside the project is refused (`scope`), as is one that is not a
80
+ program (`not_found`) and one named for a session on a server. The project keeps the last
81
+ program named for each language, so later sessions, the person's too, start with it; one
82
+ that is gone is forgotten and the default runs. A cell naming another program than the live
83
+ session's is refused while anyone else ran cells in that session; a session in which only
84
+ the caller ran cells, none of them running, is stopped (recorded as stopped by that caller)
85
+ and started again with the program named. Each session records the program it ran as it
86
+ reported it (`sys.executable`, R's `Rscript`), relative to the project when it is in it, and
87
+ each cell keeps the program and version that ran it, since a cell outlasts its session's
88
+ record. The Notebook and the Overview name such a session by its environment's folder
89
+ (`Python 3.13.5 · .venv`). Where one session ends as the next starts, at the same instant,
90
+ the Notebook lists the end first.
91
+
74
92
  A session can run on a server. A place names the server, a folder there (absolute
75
93
  or `~/…`) and setup lines run in that folder before a session starts (`module load R`,
76
94
  `conda activate env`). Setup lines that make the folder (`mkdir -p`) run in the home folder
@@ -135,7 +153,9 @@ Limits (`kernelLimits`, each configurable): one session per language, at most 16
135
153
  cells waiting in each, cells of at most 64 KiB of code, the first 256 KiB of each
136
154
  cell's output (the rest is counted and the cell marked cut), at most 8 plots of at
137
155
  most 4 MiB per cell, 500 kept cells (the oldest finished ones go first, with their
138
- plots), 200 listed variables, 32 files named per cell (`lineageLimits`) and a 10 minute wait for a cell. A session that is not
156
+ plots), 200 listed variables, 32 strings looked at as paths per cell (those that look like a
157
+ file's path first, so a script's labels do not crowd out the file it writes last), 24 files
158
+ named per cell (`lineageLimits`) and a 10 minute wait for a cell. A session that is not
139
159
  ready within 30 seconds (90 on a server) is ended. At most 16 places are named; a check
140
160
  ends after 60 seconds, a listing after 30 with at most 500 entries from 1 MiB, a signal
141
161
  after 15, and a read of serverctl's registry after 15; files larger than 64 MiB are not copied and a copy ends after 10 minutes; the
@@ -172,14 +192,55 @@ highlighting and Markdown; without them code stays plain and a server's skill sh
172
192
  written. The views add their own styles once, in the page's color and type variables, and
173
193
  use its base controls (`text-button`, `primary`, `secondary`, `inline-error`).
174
194
 
175
- `NotebookPage` is the Notebook as a page, `NotebookWorkSection` the newest cells for an
176
- overview, `useLiveValues` the sessions' values, and `askCell` and `showOnServer` bring the
177
- Notebook to a cell and Servers to a file. The pure `./code` entry finds the statement a
178
- script line belongs to (`statementAt`, `statements`, `unfinished`), writes the code that
179
- loads a project table or runs a script (`loadCode`, `sourceCode`), and makes Data flow's
180
- steps and lanes from each cell's `defined`, `used` and `files` (`lineage`, `lanes`).
181
- The views read at most 300 cells, show 14 lines of code and 12 of output before a click,
182
- keep 64 plots read, and list the 24 newest plots in Plots.
195
+ The Notebook names, under each cell, the values it read with the cell that made the version it
196
+ read ("Read co from R 3"), and for each value it made the later cells that read that version
197
+ ("ratio read in R 6", at most three, the rest counted); a cell named there goes to that cell and
198
+ marks it for a moment. Variables names the cell that made each value as it is now and the cells
199
+ that read it; on the Notebook's page these go to the cells too.
200
+
201
+ Data flow draws how each result came about as a graph of values, one node per value or file: the
202
+ files read at the top, the results at the bottom (the files written and the plots drawn, else the
203
+ values nothing reads), the values between in rows. A node is titled with the meaning its `# means:`
204
+ comment gives, with its name beneath; a value without one shows its name alone. Functions and
205
+ constants are not drawn; each value names those it uses, and so does a value that changes another
206
+ through a helper made from it (a row mask). A bar above names the results. Choosing one draws only
207
+ what leads to it, and when every result at once would put more than six values in a row, the first
208
+ is chosen to begin with. What leads to no result is named below the graph; choosing one draws what
209
+ leads to it. Choosing a value shows what it comes from and what comes of it in two colors, and names
210
+ how it was made, where, what it comes from, uses, leads to and which results it reaches; a session's
211
+ value can be looked at, a file opened, and the cell that made a value shown in the Notebook. In a
212
+ view of its own, or narrower than 640 px, the chosen value sits above the graph and stays in view;
213
+ wider, it sits beside it. A narrow view titles each node in up to three lines of its meaning, a wide
214
+ one in two. A cell that makes at least three values offers how they came about, in the same drawing.
215
+ `ScriptFlowView` draws a script's graph for a page that follows the chosen value (`selected`,
216
+ `onSelect`) and goes to where a value is made (`onGo`), as a script's editor does. At most 80 values
217
+ are drawn at once, those nearest the results first, and the bar names 8 results until asked for the
218
+ rest (`lineageViewLimits`).
219
+
220
+ `NotebookPage` is the Notebook as a page, `NotebookWorkSection` the newest cells for an overview,
221
+ `useLiveValues` the sessions' values, and `askCell` and `showOnServer` bring the Notebook to a cell
222
+ and Servers to a file. The pure `./code` entry finds the statement a script line belongs to
223
+ (`statementAt`, `statements`, `unfinished`), writes the code that loads a project table or runs a
224
+ script (`loadCode`, `sourceCode`), follows each cell's `defined`, `used` and `files` to the cell
225
+ that made each value it read (`lineage`, `cellRelations`), and makes Data flow's graph from a
226
+ session's cells (`sessionGraph`) or a script read as text (`scriptGraph`; `scriptFlow` gives a
227
+ script's values, files and their `# means:` comments, and `markersAbove` the comments above one
228
+ statement), with a value's path (`graphPath`), its rows (`graphRows`), the lines behind and in front
229
+ of it (`graphMarks`) and the value made at a line (`graphNodeAt`). In a session, a cell that makes
230
+ its values over several statements is read statement by statement, so each value comes from what its
231
+ own statements read, and a plot from what the statement that drew it read. A value made only from
232
+ literals and calls that put literals together (`c()`, `paste0()`, `dict()`, not a `read.csv()` of a
233
+ URL) is a constant. `scriptFlow` reads a script's values from its text alone, R or Python, in the
234
+ same shape: each top-level statement makes the values it assigns outside its functions, reads the
235
+ script's values it mentions (not what a function keeps for itself, a field after `$` or `.`, an
236
+ argument's name, the columns in `aes()`, `vars()` or a formula, or an import) and reads or writes
237
+ the files its strings name as the call they are given to does (`read.csv`, `write.csv`, `ggsave`,
238
+ `to_csv`, `open(…, "w")`, or a value holding the path). A statement that changes only what the step
239
+ before made, or makes something from nothing after a step that did, joins that step; one that makes
240
+ and writes nothing is counted, with the values it reads, and not drawn. Nothing runs, so names built
241
+ at run time and paths pasted from parts are not seen. A script over 512 KiB is not read and at most
242
+ 150 steps are drawn (`scriptFlowLimits`). The views read at most 300 cells, show 14 lines of code
243
+ and 12 of output before a click, keep 64 plots read, and list the 24 newest plots in Plots.
183
244
 
184
245
  ```sh
185
246
  npm run build
@@ -1,3 +1,5 @@
1
1
  export * from './statements.js';
2
2
  export * from './explore-code.js';
3
3
  export * from './lineage.js';
4
+ export * from './script-flow.js';
5
+ export * from './value-graph.js';
@@ -1,6 +1,9 @@
1
1
  // What the sessions know about code, for any page that hands code to them: the whole statement a
2
2
  // line belongs to, the code that loads a project table or runs a script, and how the values of a
3
- // session were made. Pure functions; nothing here runs code or reads the project.
3
+ // session, or of a script read as text, were made. Pure functions; nothing here runs code or reads
4
+ // the project.
4
5
  export * from './statements.js';
5
6
  export * from './explore-code.js';
6
7
  export * from './lineage.js';
8
+ export * from './script-flow.js';
9
+ export * from './value-graph.js';
@@ -68,6 +68,9 @@ export const sessionSchema = obj({
68
68
  cells: { type: 'integer', minimum: 0 },
69
69
  // Where it ran (null: this machine) and the machine's own name. Sessions recorded before have neither.
70
70
  place: maybe(sessionPlaceSchema), host: maybe({ type: 'string' }),
71
+ // The program it ran, as the session reported it: relative to the project when it is in it
72
+ // (.venv/bin/python). Sessions recorded before have none.
73
+ program: maybe({ type: 'string' }),
71
74
  }, ['sessionId', 'language', 'state', 'version', 'pid', 'startedAt', 'startedBy', 'endedAt', 'ending', 'stop', 'problem', 'variables', 'variablesOmitted', 'variablesAt', 'cells']);
72
75
  export const outputSchema = obj({ kind: { enum: ['stdout', 'stderr', 'warning', 'error', 'plot'] }, text: { type: 'string' }, plot: { type: 'integer', minimum: 1 }, width: { type: 'integer' }, height: { type: 'integer' } }, ['kind']);
73
76
  export const cellSchema = obj({
@@ -87,6 +90,8 @@ export const cellSchema = obj({
87
90
  // the project files and folders (ending in /) its strings name, as read or written. Cells
88
91
  // recorded before have neither.
89
92
  used: { type: 'array', items: text }, files: { type: 'array', items: obj({ path: text, how: { enum: ['read', 'wrote'] } }) },
93
+ // The program and version that ran it. Cells recorded before have neither.
94
+ program: maybe({ type: 'string' }), version: maybe({ type: 'string' }),
90
95
  }, ['cellId', 'changeId', 'by', 'sessionId', 'language', 'code', 'purpose', 'queuedAt', 'startedAt', 'endedAt', 'state', 'number', 'outputs', 'bytes', 'kept', 'cut', 'interrupt', 'problem']);
91
96
  // One value of a live session as its session describes it: the kind of thing it is, short facts,
92
97
  // and one page of its rows, its elements or its parts, each part with the code that reaches it.