beatrina 0.8.6

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 (114) hide show
  1. package/LICENSE +92 -0
  2. package/NOTICES +72 -0
  3. package/README.md +124 -0
  4. package/bin/beatrina.mjs +223 -0
  5. package/bin/cli.mjs +80 -0
  6. package/bin/failsafe.mjs +74 -0
  7. package/bin/identity.mjs +45 -0
  8. package/bin/prova-post.mjs +51 -0
  9. package/bin/sessions.mjs +95 -0
  10. package/bin/shortcut.mjs +151 -0
  11. package/bin/update-check.mjs +55 -0
  12. package/bin/upgrade.mjs +76 -0
  13. package/build-info.json +1 -0
  14. package/carmar_V0.8.6.html +1310 -0
  15. package/check/acceptance.mjs +278 -0
  16. package/check/session.mjs +215 -0
  17. package/engines/js/document-exec.mjs +82 -0
  18. package/engines/js/persist.mjs +214 -0
  19. package/engines/js/worker.mjs +424 -0
  20. package/engines/python/adapter.py +577 -0
  21. package/engines/python/analyze.py +814 -0
  22. package/engines/python/bootstrap.py +309 -0
  23. package/engines/python/dataview.py +735 -0
  24. package/engines/python/debugger.py +346 -0
  25. package/engines/python/document_exec.py +158 -0
  26. package/engines/python/engine.json +28 -0
  27. package/engines/python/handoff.py +118 -0
  28. package/engines/python/worker.py +564 -0
  29. package/engines/r/engine.json +25 -0
  30. package/engines/r/handoff.R +92 -0
  31. package/failsafe/ai-policy.R +255 -0
  32. package/failsafe/ai-store.R +373 -0
  33. package/failsafe/cite.R +418 -0
  34. package/failsafe/journal.R +684 -0
  35. package/failsafe/plugins.R +809 -0
  36. package/failsafe/serve.R +5500 -0
  37. package/host/ai-policy.mjs +218 -0
  38. package/host/deployment.mjs +160 -0
  39. package/host/engine-js.mjs +98 -0
  40. package/host/engine-pool.mjs +383 -0
  41. package/host/engine-python.mjs +228 -0
  42. package/host/engine-r.mjs +206 -0
  43. package/host/engine-stdio.mjs +401 -0
  44. package/host/journal-store.mjs +749 -0
  45. package/host/main.mjs +503 -0
  46. package/host/planes/README.md +41 -0
  47. package/host/planes/ai-store.mjs +327 -0
  48. package/host/planes/ai.mjs +467 -0
  49. package/host/planes/analyze.mjs +397 -0
  50. package/host/planes/cite.mjs +517 -0
  51. package/host/planes/files.mjs +0 -0
  52. package/host/planes/jobs.mjs +704 -0
  53. package/host/planes/journal.mjs +53 -0
  54. package/host/planes/latex.mjs +201 -0
  55. package/host/planes/mcp.mjs +493 -0
  56. package/host/planes/pair.mjs +325 -0
  57. package/host/planes/pipe-term.mjs +122 -0
  58. package/host/planes/plugins.mjs +112 -0
  59. package/host/planes/proc-tree.mjs +76 -0
  60. package/host/planes/sessions.mjs +434 -0
  61. package/host/planes/settings.mjs +164 -0
  62. package/host/planes/terminal.mjs +286 -0
  63. package/host/planes/test-file.mjs +80 -0
  64. package/host/planes/update.mjs +214 -0
  65. package/host/plugin-store.mjs +838 -0
  66. package/host/server.mjs +441 -0
  67. package/host/settings.mjs +379 -0
  68. package/host/update-record.mjs +59 -0
  69. package/host/user-dirs.mjs +117 -0
  70. package/host/windows-runtime.mjs +145 -0
  71. package/host/worker-plane.mjs +713 -0
  72. package/host/ws.mjs +190 -0
  73. package/kernel/analyze.R +668 -0
  74. package/kernel/deployment.R +165 -0
  75. package/kernel/examples/NOTICE.md +38 -0
  76. package/kernel/examples/tna-complete-tutorial.Rmd +210 -0
  77. package/kernel/fileio.R +656 -0
  78. package/kernel/index.html +96 -0
  79. package/kernel/job-run.R +391 -0
  80. package/kernel/jobs.R +276 -0
  81. package/kernel/kernel-protocol +1 -0
  82. package/kernel/kernel-version +1 -0
  83. package/kernel/kernel.R +671 -0
  84. package/kernel/knitr-run.R +245 -0
  85. package/kernel/latex.R +609 -0
  86. package/kernel/mcp/carmar-mcp.mjs +516 -0
  87. package/kernel/notebook-page.R +67 -0
  88. package/kernel/plugins/csl/apa/apa.csl +2273 -0
  89. package/kernel/plugins/csl/apa/plugin.json +19 -0
  90. package/kernel/plugins/csl/chicago-author-date/chicago-author-date.csl +4216 -0
  91. package/kernel/plugins/csl/chicago-author-date/plugin.json +19 -0
  92. package/kernel/plugins/csl/harvard-cite-them-right/harvard-cite-them-right.csl +316 -0
  93. package/kernel/plugins/csl/harvard-cite-them-right/plugin.json +19 -0
  94. package/kernel/plugins/csl/ieee/ieee.csl +519 -0
  95. package/kernel/plugins/csl/ieee/plugin.json +19 -0
  96. package/kernel/plugins/csl/modern-language-association/modern-language-association.csl +1184 -0
  97. package/kernel/plugins/csl/modern-language-association/plugin.json +19 -0
  98. package/kernel/plugins/csl/nature/nature.csl +189 -0
  99. package/kernel/plugins/csl/nature/plugin.json +19 -0
  100. package/kernel/plugins/latex/apa7/apa7.json +14 -0
  101. package/kernel/plugins/latex/apa7/plugin.json +19 -0
  102. package/kernel/plugins/latex/elsarticle/elsarticle.json +14 -0
  103. package/kernel/plugins/latex/elsarticle/plugin.json +19 -0
  104. package/kernel/plugins/latex/ieeetran/ieeetran.json +10 -0
  105. package/kernel/plugins/latex/ieeetran/plugin.json +19 -0
  106. package/kernel/project.R +131 -0
  107. package/kernel/settings.R +410 -0
  108. package/kernel/sniff.R +769 -0
  109. package/kernel/worker-boot.R +22 -0
  110. package/kernel/worker.R +3496 -0
  111. package/lib/agent-authoring-contract.js +547 -0
  112. package/lib/cell-kinds.js +108 -0
  113. package/lib/engine-labels.js +324 -0
  114. package/package.json +32 -0
@@ -0,0 +1,145 @@
1
+ // windows-runtime.mjs — what a Windows machine needs that no POSIX one does.
2
+ //
3
+ // Beyza's first Windows run (2026-09-15) and a reading of the host found four
4
+ // places where the host was quietly POSIX-shaped, each with a Windows answer
5
+ // that already exists in the R world:
6
+ //
7
+ // · WHERE R IS. A Windows R lives in `C:\Program Files\R\R-4.x.y\bin` and the
8
+ // installer does not put it on PATH, so a PATH search finds nothing on a
9
+ // default machine. R_HOME, then Program Files, then the per-user install.
10
+ //
11
+ // · AN INTERACTIVE R. `R --interactive` is a shell script on Unix; Windows
12
+ // has no such flag. `Rterm.exe --ess` asserts interactive use with a piped
13
+ // stdin — it is what ESS has driven on Windows for twenty years — so
14
+ // `readline()`, `menu()` and `browser()` work there instead of returning "".
15
+ //
16
+ // · STOP. Node's `proc.kill("SIGINT")` on Windows TERMINATES the process
17
+ // (Node's documentation: every signal but a few is ignored, and those kill
18
+ // "forcefully and abruptly"). So Stop was Force Stop there, and the session
19
+ // was lost. Windows interrupts a console program with a console control
20
+ // event, which only a process attached to the SAME console can send.
21
+ // processx ships exactly that program, `interrupt.exe <pid> c`
22
+ // (processx/src/tools/interrupt.c: FreeConsole → AttachConsole(pid) →
23
+ // ignore Ctrl+C itself → GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)), and
24
+ // processx is already a dependency of the carmar package, so the helper is
25
+ // on every machine that installed it. For the event to reach the worker
26
+ // and not the host, the worker needs a console of its own: it is spawned
27
+ // with `windowsHide` (CREATE_NO_WINDOW), the flag processx uses too.
28
+ //
29
+ // · FORCE STOP. `proc.kill()` ends the worker and orphans what it started
30
+ // (a `system()` child keeps running). `taskkill /T /F` ends the tree, as
31
+ // host/planes/jobs.mjs already does for a job.
32
+ //
33
+ // Every function takes the platform, the environment and the file system as
34
+ // arguments, so the Windows branches are exercised on any machine
35
+ // (test/windows-runtime.test.mjs). What that test cannot prove is what
36
+ // Windows DOES with them; tools/beatrina/acceptance.mjs is the check that runs
37
+ // on the real machine.
38
+
39
+ import fs from "node:fs";
40
+ import path from "node:path";
41
+
42
+ const defaultFs = {
43
+ exists: (p) => { try { return fs.existsSync(p); } catch { return false; } },
44
+ readdir: (p) => { try { return fs.readdirSync(p); } catch { return []; } },
45
+ };
46
+
47
+ /** Numeric sort key for `R-4.5.2` / `4.5` directory names (newest first). */
48
+ function versionKey(name) {
49
+ const m = String(name).match(/(\d+)\.(\d+)(?:\.(\d+))?/);
50
+ return m ? Number(m[1]) * 1e6 + Number(m[2]) * 1e3 + Number(m[3] || 0) : -1;
51
+ }
52
+ const newestFirst = (names) => [...names].sort((a, b) => versionKey(b) - versionKey(a));
53
+
54
+ /**
55
+ * Every Rscript.exe worth trying on Windows, in preference order, each with
56
+ * the reason it was considered.
57
+ * @returns {Array<{path: string, why: string}>}
58
+ */
59
+ export function windowsRscriptCandidates(env = process.env, io = defaultFs) {
60
+ const w = path.win32;
61
+ const out = [];
62
+ const add = (p, why) => { if (p && !out.some((c) => c.path === p)) out.push({ path: p, why }); };
63
+ if (env.R_HOME) add(w.join(env.R_HOME, "bin", "Rscript.exe"), "R_HOME");
64
+ const roots = [
65
+ [env.ProgramW6432 || env.ProgramFiles || "C:\\Program Files", "Program Files"],
66
+ [env["ProgramFiles(x86)"] || "", "Program Files (x86)"],
67
+ [env.LOCALAPPDATA ? w.join(env.LOCALAPPDATA, "Programs") : "", "a per-user install"],
68
+ ];
69
+ for (const [root, why] of roots) {
70
+ if (!root) continue;
71
+ const base = w.join(root, "R");
72
+ for (const dir of newestFirst(io.readdir(base).filter((d) => /^R-\d/.test(d)))) {
73
+ add(w.join(base, dir, "bin", "Rscript.exe"), `${why} (${dir})`);
74
+ }
75
+ }
76
+ for (const dir of String(env.PATH || env.Path || "").split(";")) {
77
+ if (dir) add(w.join(dir, "Rscript.exe"), "PATH");
78
+ }
79
+ return out;
80
+ }
81
+
82
+ /** The first Windows Rscript.exe that exists, or "". */
83
+ export function detectWindowsRscript(env = process.env, io = defaultFs) {
84
+ const hit = windowsRscriptCandidates(env, io).find((c) => io.exists(c.path));
85
+ return hit ? hit.path : "";
86
+ }
87
+
88
+ /**
89
+ * Rterm.exe beside an Rscript.exe. `bin\Rscript.exe` is a launcher; the
90
+ * console program lives in `bin\x64\` (and in `bin\` itself in some layouts).
91
+ */
92
+ export function detectRterm(rscript, io = defaultFs) {
93
+ if (!rscript) return "";
94
+ const w = path.win32;
95
+ const dir = w.dirname(rscript);
96
+ const cands = [w.join(dir, "x64", "Rterm.exe"), w.join(dir, "Rterm.exe")];
97
+ return cands.find((p) => io.exists(p)) || "";
98
+ }
99
+
100
+ /**
101
+ * The arguments that make Rterm an interactive worker with a piped stdin —
102
+ * the Windows twin of `R --interactive --no-echo …`.
103
+ */
104
+ export const RTERM_INTERACTIVE_ARGS = Object.freeze(["--ess", "--no-echo", "--no-save", "--no-restore", "--no-site-file"]);
105
+
106
+ /**
107
+ * Where processx's `interrupt.exe` is. `CARMAR_WIN_INTERRUPT` first (the R
108
+ * launcher sets it from `system.file(package = "processx")`, which knows every
109
+ * library path), then a helper shipped beside the host, then the libraries a
110
+ * default install writes to: the R installation's own, R_LIBS_USER, and
111
+ * `%LOCALAPPDATA%\R\win-library\<x.y>`.
112
+ * @returns {string} a path, or "" when none exists
113
+ */
114
+ export function findInterruptTool({ env = process.env, rscript = "", hostRoot = "", io = defaultFs } = {}) {
115
+ const w = path.win32;
116
+ const tail = ["processx", "bin", "x64", "interrupt.exe"];
117
+ const cands = [];
118
+ if (env.CARMAR_WIN_INTERRUPT) cands.push(env.CARMAR_WIN_INTERRUPT);
119
+ if (hostRoot) cands.push(w.join(hostRoot, "bin", "interrupt.exe"));
120
+ if (rscript) cands.push(w.join(w.dirname(w.dirname(rscript)), "library", ...tail));
121
+ if (env.R_HOME) cands.push(w.join(env.R_HOME, "library", ...tail));
122
+ for (const lib of String(env.R_LIBS_USER || "").split(";")) if (lib) cands.push(w.join(lib, ...tail));
123
+ for (const lib of String(env.R_LIBS || "").split(";")) if (lib) cands.push(w.join(lib, ...tail));
124
+ if (env.LOCALAPPDATA) {
125
+ const base = w.join(env.LOCALAPPDATA, "R", "win-library");
126
+ for (const v of newestFirst(io.readdir(base))) cands.push(w.join(base, v, ...tail));
127
+ }
128
+ return cands.find((p) => io.exists(p)) || "";
129
+ }
130
+
131
+ /** How to interrupt `pid` with the helper: Ctrl+C, the event R treats as a user break. */
132
+ export function windowsInterruptPlan(pid, tool) {
133
+ if (!tool || !pid) return null;
134
+ return { bin: tool, args: [String(pid), "c"] };
135
+ }
136
+
137
+ /** How to end a process and everything it started. */
138
+ export function windowsKillPlan(pid) {
139
+ return { bin: "taskkill", args: ["/T", "/F", "/PID", String(pid)] };
140
+ }
141
+
142
+ /** The sentence a Windows Stop says when there is no helper to send the event. */
143
+ export const NO_INTERRUPT_TOOL = "Stop cannot interrupt R on this Windows computer: processx's interrupt helper "
144
+ + "(interrupt.exe) was not found. The chunk keeps running. Reinstall processx (install.packages(\"processx\")), "
145
+ + "or use Force Stop, which restarts R and loses the session's variables.";