beatrina 0.9.43 → 1.0.0

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 (44) hide show
  1. package/app/Beatrina.app/Contents/Info.plist +86 -0
  2. package/app/Beatrina.app/Contents/MacOS/beatrina +0 -0
  3. package/app/Beatrina.app/Contents/Resources/icon.icns +0 -0
  4. package/app/beatrina.png +0 -0
  5. package/app/linux-arm64/beatrina +0 -0
  6. package/app/win-x64/Beatrina-setup.exe +0 -0
  7. package/beatrina_V1.0.0.html +1906 -0
  8. package/beatrina_V1.0.0.html.inputs.json +1 -0
  9. package/bin/beatrina.mjs +200 -12
  10. package/bin/cli.mjs +8 -3
  11. package/bin/finder.mjs +1 -1
  12. package/bin/shortcut.mjs +15 -15
  13. package/build-info.json +1 -1
  14. package/host/engine-node-job.mjs +35 -0
  15. package/host/engine-pool.mjs +153 -26
  16. package/host/engine-r.mjs +8 -1
  17. package/host/jobs/document-child.mjs +271 -0
  18. package/host/journal-store.mjs +19 -3
  19. package/host/latex-compile.mjs +673 -0
  20. package/host/main.mjs +58 -18
  21. package/host/planes/analyze.mjs +18 -2
  22. package/host/planes/choose.mjs +13 -2
  23. package/host/planes/expect-term.mjs +102 -0
  24. package/host/planes/jobs.mjs +38 -5
  25. package/host/planes/sessions.mjs +5 -1
  26. package/host/planes/terminal.mjs +23 -9
  27. package/host/pwa/icon-192.png +0 -0
  28. package/host/pwa/icon-512.png +0 -0
  29. package/host/quarto.mjs +118 -0
  30. package/host/server.mjs +83 -2
  31. package/host/worker-plane.mjs +7 -1
  32. package/kernel/check/acceptance.mjs +43 -12
  33. package/kernel/check/knit-file.mjs +300 -52
  34. package/kernel/check/session.mjs +19 -4
  35. package/kernel/kernel-version +1 -1
  36. package/kernel/knitr-run.R +8 -1
  37. package/kernel/mcp/beatrina-mcp.mjs +6 -5
  38. package/kernel/worker.R +21 -1
  39. package/lib/engine-labels.js +7 -1
  40. package/menu/Beatrina Menu.app/Contents/Info.plist +2 -2
  41. package/menu/Beatrina Menu.app/Contents/MacOS/Beatrina Menu +0 -0
  42. package/package.json +4 -3
  43. package/beatrina_V0.9.43.html +0 -1885
  44. package/beatrina_V0.9.43.html.inputs.json +0 -1
@@ -71,7 +71,14 @@ run_document_cell <- function(id, source, document, dims = NULL, srcname = NULL)
71
71
  if (identical(frame$type, "stdout") && !is.null(options$comment) && nzchar(options$comment)) {
72
72
  frame$text <- paste0(options$comment, " ", strsplit(frame$text, "\n", fixed = TRUE)[[1L]], collapse = "\n")
73
73
  }
74
- if (identical(frame$type, "plot") && save_figures) {
74
+ # A figure FILE is written only when the author asked for one by
75
+ # setting fig.path (a chunk option or the setup chunk's opts_chunk).
76
+ # knitr's own default, "figure/", is not a request: every plot of an
77
+ # ordinary run used to land as figure/<label>-1.png in the working
78
+ # directory, a folder nobody made (FINDINGS 2026-09-22 B17). The
79
+ # plot itself travels in the frame either way; nothing reads the file.
80
+ wants_file <- !identical(options$fig.path, KNIT_BASE$fig.path)
81
+ if (identical(frame$type, "plot") && save_figures && wants_file) {
75
82
  plot_n <<- plot_n + 1L
76
83
  suffix <- if (identical(frame$mime, "image/svg+xml")) ".svg" else ".png"
77
84
  target <- paste0(options$fig.path, options$label, "-", plot_n, suffix)
@@ -437,11 +437,12 @@ const TOOLS = [
437
437
  description:
438
438
  "Run one chunk in the user's live session (its own engine: R, or Python where the session runs it) and return its output "
439
439
  + "(stdout, messages, errors, table/plot summaries). The run is visible "
440
- + "in the notebook exactly as if the user pressed Run. REFUSED while the "
441
- + "document is in Writing mode — R is quiet there and nothing runs, not "
442
- + "even for an agent; the error says so. Do not retry: ask the user to "
443
- + "switch the document to Develop. Reading (notebook_read, chunk_read) and "
444
- + "authoring (chunk_insert, chunk_update) still work in Writing mode. "
440
+ + "in the notebook exactly as if the user pressed Run. If the document is in "
441
+ + "Writing mode the run first switches it to Develop — visibly, exactly as "
442
+ + "pressing the Develop segment — and the reply says so (`modeChanged: "
443
+ + "\"writing→development\"`); only when the page refuses that switch is the "
444
+ + "run refused, and the error says to ask the user. Reading (notebook_read, "
445
+ + "chunk_read) and authoring (chunk_insert, chunk_update) never change the mode. "
445
446
  + "A chunk with cache=TRUE and an unchanged source is RESTORED from knitr's "
446
447
  + "cache, not executed — the reply says so (`cached: true`) and none of the "
447
448
  + "chunk's side effects (setwd(), files written, seeds) happen; pass `force` "
package/kernel/worker.R CHANGED
@@ -166,6 +166,13 @@ MAX_VIEW_COLS <- 100L
166
166
  MAX_VIEW_BYTES <- 512L * 1024L
167
167
  MAX_VIEW_CELL_CHARS <- 512L
168
168
  MAX_VIEW_LABEL_CHARS <- 128L
169
+ # The viewer's page size, the same number as lib/panel.js's PAGE (pinned by
170
+ # spike/test-ide.R). View() pushes its first page unasked, and it
171
+ # used to take the `view` op's protocol default of 200, so the grid opened on
172
+ # "1–200 of N" and every page it asked for itself — next, search, clear — was
173
+ # 50 (N11, app-monkey soak 2026-09-22). The protocol default stays 200 for
174
+ # clients that name no limit; the push names the viewer's.
175
+ VIEWER_PAGE_ROWS <- 50L
169
176
  MAX_STRUCT_CHILDREN <- 200L
170
177
  MAX_COMPLETIONS <- 200L
171
178
 
@@ -2680,6 +2687,14 @@ emit_dataframe <- function(id, df, source = NULL) {
2680
2687
  # R whether names are automatic without materialising them; explicit names
2681
2688
  # are sliced from the raw attribute only AFTER the 10-row preview is taken.
2682
2689
  explicit_rownames <- .row_names_info(df, type = 1L) > 0L
2690
+ # head(df) and df[1:n, ] store their row names EXPLICITLY as the integers
2691
+ # 1..n — automatic in all but storage. Shown, they were a "rowname" column of
2692
+ # 1, 2, 3 and the header said 5 x 3 for a 5 x 2 frame (FINDINGS 2026-09-22
2693
+ # B10). Only integer names are tested, so a character vector is never built.
2694
+ if (explicit_rownames) {
2695
+ raw_names <- attr(df, "row.names", exact = TRUE)
2696
+ if (is.integer(raw_names) && identical(raw_names, seq_len(total_rows))) explicit_rownames <- FALSE
2697
+ }
2683
2698
  total_cols <- data_cols + as.integer(explicit_rownames)
2684
2699
  data_col_cap <- max(0L, preview_cols - as.integer(explicit_rownames))
2685
2700
  shown_cols <- if (data_cols && data_col_cap) {
@@ -2768,6 +2783,11 @@ emit_dataframe <- function(id, df, source = NULL) {
2768
2783
  columns = I(names(head_df)),
2769
2784
  types = I(source_types),
2770
2785
  nrow = total_rows, ncol = total_cols,
2786
+ # The frame's OWN width: row names are labels, not a variable, so the
2787
+ # "n x m" a reader sees is nrow x dataCols (mtcars is 32 x 11, not 12).
2788
+ # `ncol` keeps counting the displayed row-name column, which is what the
2789
+ # column pager and `truncated` measure against.
2790
+ dataCols = data_cols,
2771
2791
  shown = nrow(head_df), shownCols = ncol(head_df),
2772
2792
  truncated = total_rows > nrow(head_df) || total_cols > ncol(head_df),
2773
2793
  # jsonlite drops a NULL, so a frame with no name is byte-identical to what
@@ -3721,7 +3741,7 @@ beatrina_tools$View <- function(x, title = NULL) {
3721
3741
  # mtcars lives in the datasets package rather than the global environment.
3722
3742
  label <- if (!is.null(title)) title else deparse(substitute(x))
3723
3743
  assign(".beatrina_view", x, envir = globalenv())
3724
- emit_view("view-request", ".beatrina_view", label = label)
3744
+ emit_view("view-request", ".beatrina_view", label = label, limit = VIEWER_PAGE_ROWS)
3725
3745
  invisible(NULL)
3726
3746
  }
3727
3747
  attach(beatrina_tools, name = "beatrina:tools", warn.conflicts = FALSE)
@@ -118,6 +118,8 @@ export function versionMenuLabel(engine) {
118
118
  */
119
119
  export function kernelLanguage(info) {
120
120
  const declared = info && typeof info.language === "string" ? info.language.trim() : "";
121
+ // A host running no default engine (host-ready) runs no language: "".
122
+ if (!declared && info && info.host_only) return "";
121
123
  return declared ? engineKey(declared) : DEFAULT_ENGINE;
122
124
  }
123
125
 
@@ -154,6 +156,8 @@ export function kernelVersion(info) {
154
156
  * has always shown for a listener that named no version.
155
157
  */
156
158
  export function kernelDisplay(info) {
159
+ // The HOST is attached and no engine is its own (plans/getting_rid_of_R.md K2).
160
+ if (!kernelLanguage(info) && info) return "Beatrina";
157
161
  const label = engineLabel(kernelLanguage(info));
158
162
  const version = kernelVersion(info);
159
163
  return version ? `${label} ${version}` : `${label} session`;
@@ -216,6 +220,8 @@ export function reportedEngines(info) {
216
220
  if (row && !rows.some((seen) => seen.name === row.name)) rows.push(row);
217
221
  });
218
222
  if (!rows.length) return [];
223
+ // A host with no language of its own adds none.
224
+ if (!language) return rows;
219
225
  // The kernel's own language is always one of its engines — a session that
220
226
  // would not run its own language is not a thing, and a list that omitted it
221
227
  // would strand every chunk in the notebook.
@@ -239,7 +245,7 @@ export function reportedEngines(info) {
239
245
  */
240
246
  export function declaredEngines(info) {
241
247
  const language = kernelLanguage(info);
242
- const out = [language];
248
+ const out = language ? [language] : [];
243
249
  reportedEngines(info).forEach((row) => { if (!out.includes(row.name)) out.push(row.name); });
244
250
  return out;
245
251
  }
@@ -6,8 +6,8 @@
6
6
  <key>CFBundleExecutable</key><string>Beatrina Menu</string>
7
7
  <key>CFBundleIdentifier</key><string>me.saqr.beatrina.menu</string>
8
8
  <key>CFBundlePackageType</key><string>APPL</string>
9
- <key>CFBundleShortVersionString</key><string>0.9.43</string>
10
- <key>CFBundleVersion</key><string>0.9.43</string>
9
+ <key>CFBundleShortVersionString</key><string>1.0.0</string>
10
+ <key>CFBundleVersion</key><string>1.0.0</string>
11
11
  <key>LSMinimumSystemVersion</key><string>13.0</string>
12
12
  <!-- Menu bar only: no Dock tile, no window, nothing to close by accident. -->
13
13
  <key>LSUIElement</key><true/>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beatrina",
3
- "version": "0.9.43",
3
+ "version": "1.0.0",
4
4
  "description": "Beatrina is a modern, powerful, feature-rich integrated development environment (IDE) for R, Python, and JavaScript.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,9 +23,10 @@
23
23
  "failsafe",
24
24
  "lib",
25
25
  "menu",
26
+ "app",
26
27
  "build-info.json",
27
- "beatrina_V0.9.43.html",
28
- "beatrina_V0.9.43.html.inputs.json",
28
+ "beatrina_V1.0.0.html",
29
+ "beatrina_V1.0.0.html.inputs.json",
29
30
  "README.md",
30
31
  "LICENSE",
31
32
  "NOTICES"