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