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.
- package/LICENSE +92 -0
- package/NOTICES +72 -0
- package/README.md +124 -0
- package/bin/beatrina.mjs +223 -0
- package/bin/cli.mjs +80 -0
- package/bin/failsafe.mjs +74 -0
- package/bin/identity.mjs +45 -0
- package/bin/prova-post.mjs +51 -0
- package/bin/sessions.mjs +95 -0
- package/bin/shortcut.mjs +151 -0
- package/bin/update-check.mjs +55 -0
- package/bin/upgrade.mjs +76 -0
- package/build-info.json +1 -0
- package/carmar_V0.8.6.html +1310 -0
- package/check/acceptance.mjs +278 -0
- package/check/session.mjs +215 -0
- package/engines/js/document-exec.mjs +82 -0
- package/engines/js/persist.mjs +214 -0
- package/engines/js/worker.mjs +424 -0
- package/engines/python/adapter.py +577 -0
- package/engines/python/analyze.py +814 -0
- package/engines/python/bootstrap.py +309 -0
- package/engines/python/dataview.py +735 -0
- package/engines/python/debugger.py +346 -0
- package/engines/python/document_exec.py +158 -0
- package/engines/python/engine.json +28 -0
- package/engines/python/handoff.py +118 -0
- package/engines/python/worker.py +564 -0
- package/engines/r/engine.json +25 -0
- package/engines/r/handoff.R +92 -0
- package/failsafe/ai-policy.R +255 -0
- package/failsafe/ai-store.R +373 -0
- package/failsafe/cite.R +418 -0
- package/failsafe/journal.R +684 -0
- package/failsafe/plugins.R +809 -0
- package/failsafe/serve.R +5500 -0
- package/host/ai-policy.mjs +218 -0
- package/host/deployment.mjs +160 -0
- package/host/engine-js.mjs +98 -0
- package/host/engine-pool.mjs +383 -0
- package/host/engine-python.mjs +228 -0
- package/host/engine-r.mjs +206 -0
- package/host/engine-stdio.mjs +401 -0
- package/host/journal-store.mjs +749 -0
- package/host/main.mjs +503 -0
- package/host/planes/README.md +41 -0
- package/host/planes/ai-store.mjs +327 -0
- package/host/planes/ai.mjs +467 -0
- package/host/planes/analyze.mjs +397 -0
- package/host/planes/cite.mjs +517 -0
- package/host/planes/files.mjs +0 -0
- package/host/planes/jobs.mjs +704 -0
- package/host/planes/journal.mjs +53 -0
- package/host/planes/latex.mjs +201 -0
- package/host/planes/mcp.mjs +493 -0
- package/host/planes/pair.mjs +325 -0
- package/host/planes/pipe-term.mjs +122 -0
- package/host/planes/plugins.mjs +112 -0
- package/host/planes/proc-tree.mjs +76 -0
- package/host/planes/sessions.mjs +434 -0
- package/host/planes/settings.mjs +164 -0
- package/host/planes/terminal.mjs +286 -0
- package/host/planes/test-file.mjs +80 -0
- package/host/planes/update.mjs +214 -0
- package/host/plugin-store.mjs +838 -0
- package/host/server.mjs +441 -0
- package/host/settings.mjs +379 -0
- package/host/update-record.mjs +59 -0
- package/host/user-dirs.mjs +117 -0
- package/host/windows-runtime.mjs +145 -0
- package/host/worker-plane.mjs +713 -0
- package/host/ws.mjs +190 -0
- package/kernel/analyze.R +668 -0
- package/kernel/deployment.R +165 -0
- package/kernel/examples/NOTICE.md +38 -0
- package/kernel/examples/tna-complete-tutorial.Rmd +210 -0
- package/kernel/fileio.R +656 -0
- package/kernel/index.html +96 -0
- package/kernel/job-run.R +391 -0
- package/kernel/jobs.R +276 -0
- package/kernel/kernel-protocol +1 -0
- package/kernel/kernel-version +1 -0
- package/kernel/kernel.R +671 -0
- package/kernel/knitr-run.R +245 -0
- package/kernel/latex.R +609 -0
- package/kernel/mcp/carmar-mcp.mjs +516 -0
- package/kernel/notebook-page.R +67 -0
- package/kernel/plugins/csl/apa/apa.csl +2273 -0
- package/kernel/plugins/csl/apa/plugin.json +19 -0
- package/kernel/plugins/csl/chicago-author-date/chicago-author-date.csl +4216 -0
- package/kernel/plugins/csl/chicago-author-date/plugin.json +19 -0
- package/kernel/plugins/csl/harvard-cite-them-right/harvard-cite-them-right.csl +316 -0
- package/kernel/plugins/csl/harvard-cite-them-right/plugin.json +19 -0
- package/kernel/plugins/csl/ieee/ieee.csl +519 -0
- package/kernel/plugins/csl/ieee/plugin.json +19 -0
- package/kernel/plugins/csl/modern-language-association/modern-language-association.csl +1184 -0
- package/kernel/plugins/csl/modern-language-association/plugin.json +19 -0
- package/kernel/plugins/csl/nature/nature.csl +189 -0
- package/kernel/plugins/csl/nature/plugin.json +19 -0
- package/kernel/plugins/latex/apa7/apa7.json +14 -0
- package/kernel/plugins/latex/apa7/plugin.json +19 -0
- package/kernel/plugins/latex/elsarticle/elsarticle.json +14 -0
- package/kernel/plugins/latex/elsarticle/plugin.json +19 -0
- package/kernel/plugins/latex/ieeetran/ieeetran.json +10 -0
- package/kernel/plugins/latex/ieeetran/plugin.json +19 -0
- package/kernel/project.R +131 -0
- package/kernel/settings.R +410 -0
- package/kernel/sniff.R +769 -0
- package/kernel/worker-boot.R +22 -0
- package/kernel/worker.R +3496 -0
- package/lib/agent-authoring-contract.js +547 -0
- package/lib/cell-kinds.js +108 -0
- package/lib/engine-labels.js +324 -0
- 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.";
|