@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
@@ -0,0 +1,661 @@
1
+ import { statements } from './statements.js';
2
+ // The protected resource is the reader's page: a script larger than `bytes` is not read, and at
3
+ // most `steps` steps are drawn; the rest are counted.
4
+ export const scriptFlowLimits = { bytes: 512 * 1024, steps: 150 };
5
+ const rOps = ['<<-', '->>', ':::', '|>', '<-', '->', '<=', '>=', '==', '!=', '&&', '||', '::'];
6
+ const pyOps = ['**=', '//=', '>>=', '<<=', '...', '->', ':=', '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=', '@=', '==', '!=', '<=', '>=', '**', '//', '<<', '>>'];
7
+ const rName = /[\p{L}.][\p{L}\p{N}._]*/uy, pyName = /[\p{L}_][\p{L}\p{N}_]*/uy;
8
+ const rNumber = /(?:0[xX][0-9a-fA-F]+|(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)[Li]?/y;
9
+ const pyNumber = /(?:0[xXoObB][0-9a-fA-F_]+|(?:\d[\d_]*\.?[\d_]*|\.\d[\d_]*)(?:[eE][+-]?\d+)?)[jJ]?/y;
10
+ const pyString = /([rRbBuUfF]{0,2})("""|'''|"|')/y, rRaw = /[rR](["'])(-*)([([{])/y;
11
+ const at = (re, text, i) => { re.lastIndex = i; return re.exec(text); };
12
+ function tokenize(text, language) {
13
+ const out = [];
14
+ let i = 0, line = 1, head = true;
15
+ const push = (kind, value, f) => { out.push({ kind, text: value, line, head, ...f ? { f } : {} }); head = false; };
16
+ // A string's text runs to its closing quote; its lines count.
17
+ const quoted = (from, close, escapes) => {
18
+ let j = from;
19
+ while (j < text.length && !text.startsWith(close, j)) {
20
+ if (escapes && text[j] === '\\')
21
+ j++;
22
+ j++;
23
+ }
24
+ return j;
25
+ };
26
+ while (i < text.length) {
27
+ const c = text[i];
28
+ if (c === '\n') {
29
+ out.push({ kind: 'newline', text: '\n', line, head: false });
30
+ line++;
31
+ head = true;
32
+ i++;
33
+ continue;
34
+ }
35
+ if (c === ' ' || c === '\t' || c === '\r' || c === '\f') {
36
+ i++;
37
+ continue;
38
+ }
39
+ if (c === '#') {
40
+ while (i < text.length && text[i] !== '\n')
41
+ i++;
42
+ continue;
43
+ }
44
+ if (c === '\\' && language === 'python' && /^\\\r?\n/.test(text.slice(i, i + 3))) {
45
+ i = text.indexOf('\n', i) + 1;
46
+ line++;
47
+ continue;
48
+ }
49
+ let m;
50
+ if (language === 'r' && (m = at(rRaw, text, i))) {
51
+ const close = { '(': ')', '[': ']', '{': '}' }[m[3]] + m[2] + m[1];
52
+ const start = i + m[0].length, end = quoted(start, close, false), body = text.slice(start, end);
53
+ push('string', body);
54
+ line += body.split('\n').length - 1;
55
+ i = end + close.length;
56
+ continue;
57
+ }
58
+ if (language === 'python' && (m = at(pyString, text, i)) && (!m[1] || /^(?:[rRuUfFbB]|[rR][bBfF]|[bBfF][rR])$/.test(m[1]))) {
59
+ const start = i + m[0].length, end = quoted(start, m[2], !/[rR]/.test(m[1])), body = text.slice(start, end);
60
+ push('string', body, /[fF]/.test(m[1]));
61
+ line += body.split('\n').length - 1;
62
+ i = end + m[2].length;
63
+ continue;
64
+ }
65
+ if (c === '"' || c === "'" || (language === 'r' && c === '`')) {
66
+ const end = quoted(i + 1, c, true), body = text.slice(i + 1, end);
67
+ push(c === '`' ? 'name' : 'string', body);
68
+ line += body.split('\n').length - 1;
69
+ i = end + 1;
70
+ continue;
71
+ }
72
+ if ((m = at(language === 'r' ? rNumber : pyNumber, text, i)) && m[0] && (/\d/.test(c) || /^\.\d/.test(m[0]))) {
73
+ push('number', m[0]);
74
+ i += m[0].length;
75
+ continue;
76
+ }
77
+ if ((m = at(language === 'r' ? rName : pyName, text, i))) {
78
+ push('name', m[0]);
79
+ i += m[0].length;
80
+ continue;
81
+ }
82
+ if (language === 'r' && c === '%' && (m = at(/%[^%\n]*%/y, text, i))) {
83
+ push('op', m[0]);
84
+ i += m[0].length;
85
+ continue;
86
+ }
87
+ if ('([{'.includes(c)) {
88
+ push('open', c);
89
+ i++;
90
+ continue;
91
+ }
92
+ if (')]}'.includes(c)) {
93
+ push('close', c);
94
+ i++;
95
+ continue;
96
+ }
97
+ const op = (language === 'r' ? rOps : pyOps).find(o => text.startsWith(o, i)) ?? c;
98
+ push('op', op);
99
+ i += op.length;
100
+ }
101
+ return out;
102
+ }
103
+ // Each token's bracket depth (an open and its close share theirs), the innermost bracket around
104
+ // it and where that opened, and each bracket's partner.
105
+ function brackets(toks) {
106
+ const depth = [], inner = [], openAt = [], match = toks.map(() => -1), stack = [];
107
+ toks.forEach((t, k) => {
108
+ if (t.kind === 'close') {
109
+ const o = stack.pop();
110
+ if (o !== undefined) {
111
+ match[o] = k;
112
+ match[k] = o;
113
+ }
114
+ }
115
+ depth[k] = stack.length;
116
+ openAt[k] = stack.at(-1) ?? -1;
117
+ inner[k] = stack.length ? toks[stack.at(-1)].text : '';
118
+ if (t.kind === 'open')
119
+ stack.push(k);
120
+ });
121
+ return { depth, inner, openAt, match };
122
+ }
123
+ // A string that names a file: with a folder, any extension; alone, one of the usual ones.
124
+ const usual = /\.(csv|tsv|txt|tab|dat|gz|bz2|xz|zip|rds|rda|rdata|qs|json|jsonl|ya?ml|toml|xml|html?|md|xlsx?|parquet|feather|arrow|h5|hdf5|h5ad|loom|mtx|npy|npz|pkl|pickle|joblib|mat|sav|dta|sqlite|db|png|pdf|svg|jpe?g|tiff?|gif|eps|ps|r|py|ipynb|fasta|fa|fastq|fq|bam|sam|vcf|bed|gtf|gff3?|log)$/i;
125
+ export function looksLikePath(s) {
126
+ if (!s || s.length >= 512 || /[\n\r\t]|:\/\//.test(s) || !/^[\p{L}\p{N}_@~.\/\\: +-]+$/u.test(s))
127
+ return false;
128
+ return /\//.test(s) ? /[^/]\.[A-Za-z][A-Za-z0-9]{0,7}$/.test(s) : usual.test(s) && /\p{L}/u.test(s.replace(usual, ''));
129
+ }
130
+ // What a call does with a path it is given, by its name.
131
+ const builds = new Set(['file.path', 'paste0', 'paste', 'here', 'path', 'normalizePath', 'path.expand', 'join', 'Path', 'PurePath', 'joinpath', 'abspath', 'expanduser', 'normpath', 'fspath', 'str']);
132
+ const writes = /^(write|save|ggsave|export|dump|dput|sink|fwrite|png|pdf|svg|jpeg|tiff|bmp|cairo_pdf|cairo_ps|postscript|dev\.copy|dir\.create|file\.create|to_|savefig|savez|savetxt|imwrite|imsave|mkdir|makedirs)|_write$|[._](write|save)/i;
133
+ const reads = /^(read|load|fread|vroom|scan|source|import|open|imread|fromfile|genfromtxt|readRDS|readLines|readxl|Read10X|qread)|[._](read|load)/i;
134
+ // What one statement makes, reads and names. `paths` holds the script's values that are a file's
135
+ // path (out <- "results/x.csv"), so a call given one reads or writes that file.
136
+ function analyze(toks, language, lineIndent, paths) {
137
+ const { depth, inner, openAt, match } = brackets(toks);
138
+ const nextOf = (k) => { let j = k + 1; while (toks[j]?.kind === 'newline')
139
+ j++; return j; };
140
+ const prevOf = (k) => { let j = k - 1; while (toks[j]?.kind === 'newline')
141
+ j--; return j; };
142
+ const keywords = language === 'r' ? rKeywords : pyKeywords;
143
+ const isName = (k) => toks[k]?.kind === 'name' && !keywords.has(toks[k].text);
144
+ // Where an expression starting at k ends: a newline that ends a line (not one inside brackets or
145
+ // after an operator), a ; or , at its depth, or the bracket that closes around it.
146
+ const endOf = (k) => {
147
+ const d = depth[k];
148
+ for (let j = k; j < toks.length; j++) {
149
+ const t = toks[j];
150
+ if (t.kind === 'close' && depth[j] < d)
151
+ return j - 1;
152
+ if (depth[j] !== d)
153
+ continue;
154
+ if (t.text === ';' || t.text === ',')
155
+ return j - 1;
156
+ if (t.kind === 'newline' && (inner[j] === '{' || inner[j] === '') && j > k) {
157
+ const before = toks[prevOf(j)];
158
+ if (!(before && (before.kind === 'open' || (before.kind === 'op' && before.text !== '...'))))
159
+ return j - 1;
160
+ }
161
+ }
162
+ return toks.length - 1;
163
+ };
164
+ // Scopes: a function's (or lambda's, class's or comprehension's) tokens and the names it keeps.
165
+ const scopes = [];
166
+ const within = (k) => scopes.filter(s => k > s.from && k <= s.to);
167
+ // Assignments outside any scope: the name, whether it is bare (x <- …), where its target is and
168
+ // where the assignment ends.
169
+ const top = [];
170
+ const targets = new Set();
171
+ const assign = (name, k, bare, end, global = false) => {
172
+ const holders = within(k);
173
+ if (bare)
174
+ targets.add(k);
175
+ if (holders.length && !global)
176
+ for (const s of holders)
177
+ s.own.add(name);
178
+ else
179
+ top.push({ name, bare, at: k, end });
180
+ };
181
+ const functions = [];
182
+ if (language === 'r') {
183
+ for (let k = 0; k < toks.length; k++) {
184
+ const t = toks[k];
185
+ if (!((t.kind === 'name' && t.text === 'function') || (t.kind === 'op' && t.text === '\\')))
186
+ continue;
187
+ const open = nextOf(k);
188
+ if (toks[open]?.text !== '(' || match[open] < 0)
189
+ continue;
190
+ const close = match[open], own = new Set();
191
+ for (let j = open + 1; j < close; j++)
192
+ if (depth[j] === depth[open] + 1 && toks[j].kind === 'name' && [',', ')', '='].includes(toks[nextOf(j)]?.text ?? ''))
193
+ own.add(toks[j].text);
194
+ const body = nextOf(close);
195
+ const to = toks[body]?.text === '{' && match[body] >= 0 ? match[body] : endOf(body);
196
+ scopes.push({ from: k, to, own });
197
+ }
198
+ for (let k = 0; k < toks.length; k++) {
199
+ const t = toks[k];
200
+ if (t.kind === 'name' && t.text === 'for' && toks[nextOf(k)]?.text === '(') {
201
+ const v = nextOf(nextOf(k));
202
+ if (isName(v) && toks[nextOf(v)]?.text === 'in')
203
+ assign(toks[v].text, v, true, match[nextOf(k)]);
204
+ continue;
205
+ }
206
+ if (t.kind !== 'op' || !['<-', '<<-', '=', '->', '->>'].includes(t.text))
207
+ continue;
208
+ if (t.text === '=' && inner[k] !== '{' && inner[k] !== '')
209
+ continue;
210
+ let s, e;
211
+ if (t.text === '->' || t.text === '->>') {
212
+ s = nextOf(k);
213
+ e = s;
214
+ for (;;) {
215
+ const n = nextOf(e);
216
+ if (toks[n]?.kind === 'open' && toks[n].text !== '{' && match[n] >= 0)
217
+ e = match[n];
218
+ else if (['$', '@'].includes(toks[n]?.text ?? '') && toks[nextOf(n)])
219
+ e = nextOf(n);
220
+ else
221
+ break;
222
+ }
223
+ }
224
+ else {
225
+ e = prevOf(k);
226
+ s = e;
227
+ while (s >= 0) {
228
+ const u = toks[s];
229
+ if (u.kind === 'close') {
230
+ const o = match[s], before = toks[prevOf(o)];
231
+ if (o < 0 || (u.text === ')' && before && ['if', 'for', 'while', 'function'].includes(before.text)) || u.text === '}') {
232
+ s++;
233
+ break;
234
+ }
235
+ s = prevOf(o);
236
+ continue;
237
+ }
238
+ if (u.kind === 'name' || u.kind === 'string') {
239
+ const p = toks[prevOf(s)];
240
+ if (p && ['$', '@', '::', ':::'].includes(p.text)) {
241
+ s = prevOf(prevOf(s));
242
+ continue;
243
+ }
244
+ break;
245
+ }
246
+ s++;
247
+ break;
248
+ }
249
+ if (s < 0)
250
+ s = 0;
251
+ }
252
+ if (s > e || !toks[s])
253
+ continue;
254
+ const side = [];
255
+ for (let j = s; j <= e; j++)
256
+ if (toks[j].kind !== 'newline')
257
+ side.push(j);
258
+ const bare = side.length === 1 && (toks[s].kind === 'name' || toks[s].kind === 'string');
259
+ const named = bare ? s : side.find(j => toks[j].kind === 'name' && !keywords.has(toks[j].text) && toks[nextOf(j)]?.text !== '(' && !['$', '@', '::', ':::'].includes(toks[prevOf(j)]?.text ?? '') && !['::', ':::'].includes(toks[nextOf(j)]?.text ?? ''));
260
+ if (named === undefined)
261
+ continue;
262
+ const end = t.text.startsWith('-') ? e : endOf(nextOf(k));
263
+ assign(toks[named].text, named, bare, end, t.text === '<<-' || t.text === '->>');
264
+ const value = nextOf(k);
265
+ if (bare && !within(k).length && (toks[value]?.text === 'function' || (toks[value]?.kind === 'op' && toks[value].text === '\\')))
266
+ functions.push(toks[named].text);
267
+ }
268
+ }
269
+ else {
270
+ // The simple statements, each from its first token: a line's first token outside brackets,
271
+ // and what follows a ; or a block header's colon.
272
+ const compound = new Set(['if', 'elif', 'else', 'for', 'while', 'with', 'try', 'except', 'finally', 'def', 'class', 'async', 'match', 'case']);
273
+ const starts = [];
274
+ let from = -1;
275
+ for (let k = 0; k < toks.length; k++) {
276
+ const t = toks[k];
277
+ if (t.kind === 'newline') {
278
+ if (depth[k] === 0)
279
+ from = -1;
280
+ continue;
281
+ }
282
+ if (from < 0) {
283
+ from = k;
284
+ starts.push(k);
285
+ continue;
286
+ }
287
+ if (depth[k] === 0 && t.text === ';') {
288
+ from = -1;
289
+ continue;
290
+ }
291
+ if (depth[k] === 0 && t.text === ':' && compound.has(toks[from].text) && !toks.slice(from, k).some(u => u.text === 'lambda'))
292
+ from = -1;
293
+ }
294
+ const simple = starts.map((s, i) => {
295
+ let e = (starts[i + 1] ?? toks.length) - 1;
296
+ while (e > s && (toks[e].kind === 'newline' || (depth[e] === 0 && (toks[e].text === ';' || (toks[e].text === ':' && compound.has(toks[s].text))))))
297
+ e--;
298
+ return { s, e };
299
+ });
300
+ const indent = (k) => lineIndent[toks[k].line - 1] ?? 0;
301
+ // def and class: their parameters and their body, by indentation; lambdas; comprehensions.
302
+ for (const { s, e } of simple) {
303
+ let k = s;
304
+ if (toks[k].text === 'async')
305
+ k = nextOf(k);
306
+ if (toks[k].text !== 'def' && toks[k].text !== 'class')
307
+ continue;
308
+ const name = nextOf(k), own = new Set();
309
+ const open = nextOf(name);
310
+ if (toks[open]?.text === '(' && toks[k].text === 'def')
311
+ for (let j = open + 1; j < match[open]; j++)
312
+ if (depth[j] === depth[open] + 1 && toks[j].kind === 'name' && [',', ')', '=', ':'].includes(toks[nextOf(j)]?.text ?? ''))
313
+ own.add(toks[j].text);
314
+ let to = e;
315
+ for (let j = e + 1; j < toks.length; j++) {
316
+ const u = toks[j];
317
+ if (u.kind === 'newline')
318
+ continue;
319
+ if (u.head && depth[j] === 0 && indent(j) <= indent(s))
320
+ break;
321
+ to = j;
322
+ }
323
+ if (isName(name)) {
324
+ if (!within(name).length && toks[k].text === 'def')
325
+ functions.push(toks[name].text);
326
+ assign(toks[name].text, name, true, to);
327
+ }
328
+ scopes.push({ from: name, to, own });
329
+ }
330
+ for (let k = 0; k < toks.length; k++) {
331
+ const t = toks[k];
332
+ if (t.kind === 'name' && t.text === 'lambda') {
333
+ const own = new Set();
334
+ let j = k + 1;
335
+ for (; j < toks.length && !(toks[j].text === ':' && depth[j] === depth[k]); j++)
336
+ if (toks[j].kind === 'name')
337
+ own.add(toks[j].text);
338
+ scopes.push({ from: k, to: endOf(j + 1), own });
339
+ }
340
+ if (t.kind === 'open' && match[k] > k) {
341
+ const own = new Set();
342
+ for (let j = k + 1; j < match[k]; j++) {
343
+ if (depth[j] !== depth[k] + 1 || toks[j].text !== 'for')
344
+ continue;
345
+ for (let v = j + 1; v < match[k] && toks[v].text !== 'in'; v++)
346
+ if (toks[v].kind === 'name')
347
+ own.add(toks[v].text);
348
+ }
349
+ if (own.size)
350
+ scopes.push({ from: k, to: match[k], own });
351
+ }
352
+ }
353
+ // Targets: of =, augmented and annotated assignment, :=, for … in, with … as, except … as.
354
+ // Imports bind names that are not the script's values.
355
+ const declared = new Set();
356
+ const element = (a, b, end, change = false) => {
357
+ const parts = [];
358
+ let p = a;
359
+ for (let j = a; j <= b + 1; j++)
360
+ if (j > b || (toks[j].text === ',' && depth[j] === depth[a])) {
361
+ if (p <= j - 1)
362
+ parts.push([p, j - 1]);
363
+ p = j + 1;
364
+ }
365
+ for (let [x, y] of parts) {
366
+ while (toks[x]?.kind === 'newline')
367
+ x++;
368
+ if (toks[x]?.text === '*')
369
+ x++;
370
+ if (x > y)
371
+ continue;
372
+ if (toks[x].kind === 'open' && match[x] === y) {
373
+ element(x + 1, y - 1, end, change);
374
+ continue;
375
+ }
376
+ if (x === y && isName(x)) {
377
+ assign(toks[x].text, x, !change, end);
378
+ continue;
379
+ }
380
+ if (isName(x))
381
+ assign(toks[x].text, x, false, end);
382
+ }
383
+ };
384
+ for (const { s, e } of simple) {
385
+ const first = toks[s].text;
386
+ if (first === 'import' || first === 'from') {
387
+ for (let j = s; j <= e; j++)
388
+ if (isName(j) && toks[j - 1]?.text !== '.' && toks[j + 1]?.text !== '.') {
389
+ const inner = within(j);
390
+ for (const sc of inner)
391
+ sc.own.add(toks[j].text);
392
+ targets.add(j);
393
+ }
394
+ continue;
395
+ }
396
+ if (first === 'global' || first === 'nonlocal') {
397
+ for (let j = s + 1; j <= e; j++)
398
+ if (isName(j)) {
399
+ declared.add(toks[j].text);
400
+ targets.add(j);
401
+ }
402
+ continue;
403
+ }
404
+ let k = s;
405
+ if (first === 'async')
406
+ k = nextOf(k);
407
+ if (toks[k].text === 'for') {
408
+ let j = k + 1;
409
+ while (j <= e && toks[j].text !== 'in')
410
+ j++;
411
+ element(k + 1, j - 1, e);
412
+ continue;
413
+ }
414
+ if (toks[k].text === 'with' || toks[k].text === 'except') {
415
+ for (let j = k; j <= e; j++)
416
+ if (toks[j].text === 'as' && depth[j] === depth[k])
417
+ element(j + 1, Math.min(e, Math.max(j + 1, endOf(j + 1))), e);
418
+ continue;
419
+ }
420
+ for (let j = s; j <= e; j++)
421
+ if (toks[j].text === ':=' && isName(j - 1))
422
+ assign(toks[j - 1].text, j - 1, true, e);
423
+ if (compound.has(toks[k].text))
424
+ continue;
425
+ const ops = [];
426
+ for (let j = s; j <= e; j++)
427
+ if (depth[j] === depth[s] && toks[j].kind === 'op' && (toks[j].text === '=' || /^(?:[-+*/%&|^@]|\*\*|\/\/|>>|<<)=$/.test(toks[j].text)))
428
+ ops.push(j);
429
+ let a = s;
430
+ for (const op of ops) {
431
+ let b = op - 1;
432
+ // An annotation (x: int = …) leaves the name.
433
+ for (let j = a; j < op; j++)
434
+ if (toks[j].text === ':' && depth[j] === depth[s]) {
435
+ b = j - 1;
436
+ break;
437
+ }
438
+ element(a, b, e, toks[op].text !== '=');
439
+ a = op + 1;
440
+ }
441
+ }
442
+ for (const sc of scopes)
443
+ for (const name of declared)
444
+ sc.own.delete(name);
445
+ }
446
+ // In R, the names in aes() and vars() and in a formula's argument (y ~ x) are a table's columns.
447
+ const columns = new Set();
448
+ if (language === 'r')
449
+ for (let o = 0; o < toks.length; o++) {
450
+ if (toks[o].text !== '(' || match[o] < 0)
451
+ continue;
452
+ const aes = ['aes', 'aes_', 'vars'].includes(toks[prevOf(o)]?.text ?? '');
453
+ let a = o + 1;
454
+ for (let j = o + 1; j <= match[o]; j++) {
455
+ if (j < match[o] && !(toks[j].text === ',' && depth[j] === depth[o] + 1))
456
+ continue;
457
+ if (aes || toks.slice(a, j).some((u, i) => u.text === '~' && depth[a + i] === depth[o] + 1))
458
+ for (let x = a; x < j; x++)
459
+ columns.add(x);
460
+ a = j + 1;
461
+ }
462
+ }
463
+ // Reads: names outside what a scope keeps, not a field or an argument's name, not a target, and
464
+ // not one this statement assigned before (once that assignment ended).
465
+ const used = [];
466
+ for (let k = 0; k < toks.length; k++) {
467
+ if (!isName(k) || targets.has(k) || columns.has(k))
468
+ continue;
469
+ const name = toks[k].text, prev = toks[prevOf(k)], next = toks[nextOf(k)];
470
+ if (language === 'r' && prev && ['$', '@', '::', ':::'].includes(prev.text))
471
+ continue;
472
+ if (language === 'r' && next && ['::', ':::'].includes(next.text))
473
+ continue;
474
+ if (language === 'python' && toks[k - 1]?.text === '.')
475
+ continue;
476
+ if (next?.text === '=' && inner[k] === '(')
477
+ continue;
478
+ if (within(k).some(s => s.own.has(name)))
479
+ continue;
480
+ if (top.some(a => a.name === name && a.end < k && a.at !== k))
481
+ continue;
482
+ if (!used.includes(name))
483
+ used.push(name);
484
+ }
485
+ // The files its strings name, as read or written by the call they are given to.
486
+ const how = (k) => {
487
+ for (let o = openAt[k]; o >= 0; o = openAt[o]) {
488
+ const open = toks[o];
489
+ if (open.text !== '(')
490
+ return null;
491
+ const callee = toks[prevOf(o)];
492
+ if (!callee || callee.kind !== 'name')
493
+ return null;
494
+ if (builds.has(callee.text))
495
+ continue;
496
+ if (callee.text === 'open' && language === 'python') {
497
+ for (let j = o + 1; j < match[o]; j++)
498
+ if (j !== k && toks[j].kind === 'string' && depth[j] === depth[o] + 1 && /^[rwxabt+]{1,3}$/.test(toks[j].text))
499
+ return /[wxa]/.test(toks[j].text) ? 'wrote' : 'read';
500
+ return 'read';
501
+ }
502
+ const file = toks[prevOf(k)]?.text === '=' ? toks[prevOf(prevOf(k))]?.text : undefined;
503
+ if (file === 'file' && ['cat', 'capture.output', 'print'].includes(callee.text))
504
+ return 'wrote';
505
+ return writes.test(callee.text) ? 'wrote' : reads.test(callee.text) ? 'read' : null;
506
+ }
507
+ return null;
508
+ };
509
+ const files = [];
510
+ const name = (path, h) => { if (h && !files.some(f => f.path === path && f.how === h))
511
+ files.push({ path, how: h }); };
512
+ for (let k = 0; k < toks.length; k++) {
513
+ const t = toks[k];
514
+ if (t.kind === 'string' && !t.f && inner[k] !== '[' && !(language === 'python' && inner[k] === '{' && toks[nextOf(k)]?.text === ':') && looksLikePath(t.text.replace(/^\.\//, '')))
515
+ name(t.text.replace(/^\.\//, ''), how(k));
516
+ else if (isName(k) && paths.has(t.text) && !targets.has(k))
517
+ name(paths.get(t.text), how(k));
518
+ }
519
+ // A value that is a path: name <- "x/y.csv", or file.path("x", "y.csv").
520
+ const own = new Map();
521
+ for (const a of top) {
522
+ if (!a.bare)
523
+ continue;
524
+ const value = [];
525
+ for (let j = nextOf(nextOf(a.at)); j <= a.end && j < toks.length; j++)
526
+ if (toks[j].kind !== 'newline')
527
+ value.push(toks[j]);
528
+ const strings = value.filter(v => v.kind === 'string');
529
+ const joined = value.length === 1 && strings.length === 1 ? strings[0].text
530
+ : value[0]?.kind === 'name' && builds.has(value[0].text) && value[1]?.text === '(' && strings.length && value.every(v => v.kind === 'string' || [',', '(', ')'].includes(v.text) || v === value[0]) ? strings.map(s => s.text.replace(/\/$/, '')).join('/') : null;
531
+ if (joined && looksLikePath(joined))
532
+ own.set(a.name, joined);
533
+ }
534
+ for (const [n, p] of own)
535
+ paths.set(n, p);
536
+ const defined = [...new Set(top.map(a => a.name))];
537
+ const changed = new Set(top.filter(a => !a.bare || used.includes(a.name)).map(a => a.name));
538
+ for (const n of defined)
539
+ if (!own.has(n))
540
+ paths.delete(n);
541
+ return { defined, changed, used, files, functions: functions.filter(f => defined.includes(f)), paths: own };
542
+ }
543
+ const rKeywords = new Set(['if', 'else', 'repeat', 'while', 'function', 'for', 'in', 'next', 'break', 'TRUE', 'FALSE', 'NULL', 'Inf', 'NaN', 'NA', 'NA_integer_', 'NA_real_', 'NA_character_', 'NA_complex_', 'library', 'require', 'requireNamespace', 'suppressPackageStartupMessages']);
544
+ const pyKeywords = new Set(['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield', 'self']);
545
+ // What the code says a value or file is: a comment line `# means: …` directly above the statement
546
+ // that first makes the value or names the file, or `# means name: …` for the one value or file
547
+ // `name` in a statement that makes or names several. The words are the code's author's (an Agent's,
548
+ // mostly) and sit beside the code they describe. The first statement that makes or names a key
549
+ // decides its meaning, so a later change does not replace it. Nothing here runs code.
550
+ const meaningLimit = 200;
551
+ const markerLine = /^\s*#\s*means(?:\s+([^\s:#]+))?\s*:\s*(\S.*?)\s*$/i;
552
+ // The markers on the comment lines directly above the statement that starts at `line` (1-based).
553
+ export function markersAbove(lines, line) {
554
+ const block = [];
555
+ for (let i = line - 2; i >= 0 && /^\s*#/.test(lines[i]); i--)
556
+ block.unshift(lines[i]);
557
+ return block.flatMap(text => { const m = markerLine.exec(text); return m ? [{ name: m[1] ?? null, text: m[2].slice(0, meaningLimit) }] : []; });
558
+ }
559
+ // The unnamed marker above a statement, as the field a read carries (none when there is none).
560
+ const unnamedMeaning = (lines, line) => { const text = markersAbove(lines, line).find(m => !m.name)?.text; return text ? { means: text } : {}; };
561
+ // The script's steps, in order, with lines from each value (and written file) to the steps that
562
+ // read that version of it.
563
+ // `outside` names the values there before the script runs (a session's, for a cell's code): the
564
+ // script reads them too, until it makes its own.
565
+ export function scriptFlow(text, language, limits = scriptFlowLimits, outside = []) {
566
+ const empty = { steps: [], links: [], layers: 0, omitted: { values: 0, plots: 0, files: 0 }, quiet: 0, cut: 0, tooLong: false, outside: [], quietReads: [], means: new Map() };
567
+ if (new TextEncoder().encode(text).length > limits.bytes)
568
+ return { ...empty, tooLong: true };
569
+ const lines = text.split('\n'), lineIndent = lines.map(l => l.length - l.trimStart().length);
570
+ const toks = tokenize(text, language), paths = new Map();
571
+ let quiet = 0, t = 0;
572
+ // What the code says each value and file is (see markersAbove), and the keys already decided.
573
+ const means = new Map(), claimed = new Set();
574
+ const quietReads = [];
575
+ const groups = [], known = new Set(outside);
576
+ for (const statement of statements(text, language)) {
577
+ while (t < toks.length && toks[t].line < statement.from)
578
+ t++;
579
+ const start = t;
580
+ while (t < toks.length && toks[t].line <= statement.to)
581
+ t++;
582
+ const made = analyze(toks.slice(start, t), language, lineIndent, paths);
583
+ // The first statement that makes a value, or reads or writes a file, decides its meaning. A
584
+ // named marker goes to that value or file; an unnamed one to the values the statement makes, else
585
+ // to the files it reads or writes.
586
+ const marks = markersAbove(lines, statement.from);
587
+ for (const k of [...made.defined.map(name => ({ key: 'value:' + name, name, value: true })), ...made.files.map(f => ({ key: 'file:' + f.path, name: f.path, value: false }))]) {
588
+ if (claimed.has(k.key))
589
+ continue;
590
+ claimed.add(k.key);
591
+ const mark = marks.find(m => m.name === k.name) ?? (k.value === (made.defined.length > 0) ? marks.find(m => !m.name) : undefined);
592
+ if (mark)
593
+ means.set(k.key, mark.text);
594
+ }
595
+ // Only the script's own values are read from it; the rest are the session's or a package's.
596
+ const used = made.used.filter(n => known.has(n));
597
+ const wrote = made.files.filter(f => f.how === 'wrote').map(f => f.path), read = made.files.filter(f => f.how === 'read').map(f => f.path);
598
+ for (const n of made.defined)
599
+ known.add(n);
600
+ if (!made.defined.length && !wrote.length) {
601
+ quiet++;
602
+ if (used.length)
603
+ quietReads.push({ from: statement.from, to: statement.to, used, ...unnamedMeaning(lines, statement.from) });
604
+ continue;
605
+ }
606
+ const last = groups.at(-1);
607
+ const continues = last && !wrote.length && !last.wrote.length && (
608
+ // It changes only what the step made, or it makes something from nothing after a step that did.
609
+ made.defined.every(n => last.defined.includes(n) && made.changed.has(n)) ||
610
+ (!used.length && !read.length && !last.used.length && !last.reads.length && !made.defined.some(n => last.defined.includes(n))));
611
+ if (continues) {
612
+ last.to = statement.to;
613
+ for (const n of used)
614
+ if (!last.defined.includes(n) && !last.used.includes(n))
615
+ last.used.push(n);
616
+ for (const n of made.defined)
617
+ if (!last.defined.includes(n))
618
+ last.defined.push(n);
619
+ for (const p of read)
620
+ if (!last.reads.includes(p))
621
+ last.reads.push(p);
622
+ for (const f of made.functions)
623
+ if (!last.functions.includes(f))
624
+ last.functions.push(f);
625
+ continue;
626
+ }
627
+ groups.push({ from: statement.from, to: statement.to, defined: [...made.defined], changed: made.changed, used, reads: read, wrote, functions: made.functions });
628
+ }
629
+ const kept = groups.slice(0, limits.steps);
630
+ // Who made each value and wrote each file so far, as the steps go.
631
+ const maker = new Map(), writer = new Map(), links = [], before = [];
632
+ for (const n of outside)
633
+ maker.set(n, '');
634
+ const steps = kept.map(g => {
635
+ const id = 'lines:' + g.from;
636
+ const cell = { cellId: 'L' + g.from, number: g.from, state: 'done', code: lines.slice(g.from - 1, g.to).join('\n'), purpose: null, plots: 0, defined: g.defined, used: g.used, files: [...g.reads.map(path => ({ path, how: 'read' })), ...g.wrote.map(path => ({ path, how: 'wrote' }))] };
637
+ const reads = [];
638
+ for (const n of g.used) {
639
+ const from = maker.get(n);
640
+ if (from)
641
+ links.push({ from, to: id });
642
+ else if (from === '')
643
+ before.push({ name: n, to: id });
644
+ }
645
+ for (const p of g.reads) {
646
+ const from = writer.get(p);
647
+ if (from)
648
+ links.push({ from, to: id });
649
+ else
650
+ reads.push(p);
651
+ }
652
+ const changed = g.defined.filter(n => maker.has(n) && (g.changed.has(n) || g.used.includes(n)));
653
+ const nodes = [...g.defined.map(n => ({ id: `value:${n}@${g.from}`, kind: 'value', name: n, step: id })), ...g.wrote.map(p => ({ id: `wrote:${p}@${g.from}`, kind: 'file', name: p, step: id }))];
654
+ for (const n of g.defined)
655
+ maker.set(n, `value:${n}@${g.from}`);
656
+ for (const p of g.wrote)
657
+ writer.set(p, `wrote:${p}@${g.from}`);
658
+ return { id, kind: 'cell', cell, earlier: [], nodes, reads, latest: false, unknownInputs: false, stale: [], layer: 0, order: 0, from: g.from, to: g.to, changed, functions: g.functions };
659
+ });
660
+ return { steps, links, layers: 0, omitted: { values: 0, plots: 0, files: 0 }, quiet, cut: groups.length - kept.length, tooLong: false, outside: before, quietReads, means };
661
+ }
@@ -113,6 +113,9 @@ export interface KernelShell {
113
113
  export declare const ShellProvider: import("react").Provider<KernelShell>;
114
114
  export declare const useShell: () => KernelShell;
115
115
  export declare const withShell: (shell: KernelShell | undefined, node: ReactNode) => string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
116
+ type Session = KernelOutputs['kernel.read']['sessions'][number];
117
+ export declare const environmentOf: (session: Pick<Session, "program">) => string | null;
118
+ export declare const versionOf: (session: Pick<Session, "program" | "version" | "language">) => string;
116
119
  export declare const clock: (ms: number, seconds?: boolean) => string;
117
120
  export declare function durationText(ms: number): string;
118
121
  export declare const agentName: (client?: string | null) => "Codex" | "Claude Code" | "Agent";