mulmoclaude 0.5.1 → 0.5.3
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/Dockerfile.sandbox +100 -0
- package/bin/mulmoclaude.js +1 -1
- package/bin/prepare-dist.js +18 -2
- package/client/assets/{html2canvas-Cx501zZr-BORHg-NU.js → html2canvas-Cx501zZr-Bug0qRNv.js} +1 -1
- package/client/assets/{index-BeeoDtvq.js → index-DbTz2Mfs.js} +6 -6
- package/client/assets/{index.es-D4YyL_Dg-CB_ogqQG.js → index.es-D4YyL_Dg-BgT6a3Nd.js} +1 -1
- package/client/index.html +1 -1
- package/package.json +4 -2
- package/sandbox-entrypoint.sh +106 -0
- package/server/api/routes/pdf.ts +18 -10
- package/src/plugins/presentHtml/View.vue +6 -1
- package/src/utils/image/rewriteHtmlImageRefs.ts +50 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
FROM node:22-slim
|
|
2
|
+
|
|
3
|
+
# Sandbox tool set (see #162). Grouped into layers by purpose so the
|
|
4
|
+
# rationale is obvious from the diff:
|
|
5
|
+
#
|
|
6
|
+
# 1. Core CLI — read local git history, fetch over HTTP, pipeline JSON,
|
|
7
|
+
# run Makefile-driven workspaces, handle archives, query SQLite.
|
|
8
|
+
# `ca-certificates` is needed because `node:22-slim` ships without
|
|
9
|
+
# a trust store. `ripgrep` backs Claude's grep tool.
|
|
10
|
+
# 2. Data analysis + plotting — Python with pandas/numpy/matplotlib
|
|
11
|
+
# and `requests` for API fetches. Graphviz for structural diagrams.
|
|
12
|
+
# ImageMagick for raster ops. Covers the "investment / data / chart"
|
|
13
|
+
# and "visualize this workflow" use cases in the issue.
|
|
14
|
+
# 3. Document + media conversion — pandoc bridges Markdown ↔ PDF/DOCX/
|
|
15
|
+
# HTML/EPUB for report output. ffmpeg covers audio/video transcode
|
|
16
|
+
# and probing. poppler-utils extracts text / images from PDFs.
|
|
17
|
+
# 4. Small extras — `tree` for directory listing, `bc` for arbitrary-
|
|
18
|
+
# precision arithmetic, `less` for pagers.
|
|
19
|
+
#
|
|
20
|
+
# Deferred on purpose:
|
|
21
|
+
#
|
|
22
|
+
# - `@mermaid-js/mermaid-cli` — pulls in headless Chromium (~300MB).
|
|
23
|
+
# Revisit as a separate layer if diagram generation becomes common.
|
|
24
|
+
# - `texlive-*` — ~150MB+ for marginal PDF quality gains over pandoc's
|
|
25
|
+
# default LaTeX-free path; add when a user actually needs math/
|
|
26
|
+
# journal-style typesetting.
|
|
27
|
+
# - `gh` CLI — now installed (Layer 1b). Auth via SANDBOX_MOUNT_CONFIGS=gh
|
|
28
|
+
# which mounts ~/.config/gh:ro into the container (#259).
|
|
29
|
+
#
|
|
30
|
+
# Runtime `pip install` is intentionally NOT wired up. Everything the
|
|
31
|
+
# agent might need for data work is preinstalled at build time so
|
|
32
|
+
# supply-chain risk stays out of the sandbox.
|
|
33
|
+
|
|
34
|
+
# Layer 1: core CLI + SSH client (needed for SSH agent forwarding #259)
|
|
35
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
36
|
+
git \
|
|
37
|
+
curl \
|
|
38
|
+
jq \
|
|
39
|
+
make \
|
|
40
|
+
ca-certificates \
|
|
41
|
+
openssh-client \
|
|
42
|
+
sqlite3 \
|
|
43
|
+
zip \
|
|
44
|
+
unzip \
|
|
45
|
+
ripgrep \
|
|
46
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
47
|
+
|
|
48
|
+
# Layer 1b: GitHub CLI (#164). Installed from the official apt repo.
|
|
49
|
+
# Auth is provided at runtime via SANDBOX_MOUNT_CONFIGS=gh which
|
|
50
|
+
# bind-mounts ~/.config/gh:ro (#259). On macOS where the token lives
|
|
51
|
+
# in the system keyring, the server falls back to GH_TOKEN env var.
|
|
52
|
+
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
|
|
53
|
+
-o /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
|
54
|
+
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
|
|
55
|
+
> /etc/apt/sources.list.d/github-cli.list \
|
|
56
|
+
&& apt-get update && apt-get install -y --no-install-recommends gh \
|
|
57
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
58
|
+
|
|
59
|
+
# Layer 2: data analysis + plotting
|
|
60
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
61
|
+
python3 \
|
|
62
|
+
python3-pip \
|
|
63
|
+
graphviz \
|
|
64
|
+
imagemagick \
|
|
65
|
+
&& rm -rf /var/lib/apt/lists/* \
|
|
66
|
+
&& pip3 install --no-cache-dir --break-system-packages \
|
|
67
|
+
pandas \
|
|
68
|
+
numpy \
|
|
69
|
+
matplotlib \
|
|
70
|
+
requests
|
|
71
|
+
|
|
72
|
+
# Layer 3: document + media conversion
|
|
73
|
+
# LibreOffice core + Impress + Writer enable server-side PPTX→PDF and
|
|
74
|
+
# DOCX→PDF conversion for the attachment pipeline (#386). Only the
|
|
75
|
+
# headless renderer is used (`--headless --convert-to pdf`).
|
|
76
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
77
|
+
pandoc \
|
|
78
|
+
ffmpeg \
|
|
79
|
+
poppler-utils \
|
|
80
|
+
libreoffice-core \
|
|
81
|
+
libreoffice-impress \
|
|
82
|
+
libreoffice-writer \
|
|
83
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
84
|
+
|
|
85
|
+
# Layer 4: small extras
|
|
86
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
87
|
+
tree \
|
|
88
|
+
bc \
|
|
89
|
+
less \
|
|
90
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
91
|
+
|
|
92
|
+
RUN npm install -g @anthropic-ai/claude-code tsx
|
|
93
|
+
|
|
94
|
+
COPY sandbox-entrypoint.sh /sandbox-entrypoint.sh
|
|
95
|
+
RUN chmod +x /sandbox-entrypoint.sh
|
|
96
|
+
|
|
97
|
+
# No `USER node` — the entrypoint starts as root to fix /etc/passwd
|
|
98
|
+
# and socket permissions, then drops to HOST_UID:HOST_GID via setpriv.
|
|
99
|
+
WORKDIR /home/node/mulmoclaude
|
|
100
|
+
ENTRYPOINT ["/sandbox-entrypoint.sh"]
|
package/bin/mulmoclaude.js
CHANGED
package/bin/prepare-dist.js
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// ── Publish ───────────────────────────────────────────────────
|
|
32
32
|
// cd packages/mulmoclaude && npm publish --access public
|
|
33
33
|
|
|
34
|
-
import { cpSync, existsSync, rmSync } from "fs";
|
|
34
|
+
import { copyFileSync, cpSync, existsSync, rmSync } from "fs";
|
|
35
35
|
import { join, dirname } from "path";
|
|
36
36
|
import { fileURLToPath } from "url";
|
|
37
37
|
|
|
@@ -42,11 +42,16 @@ const rootDir = join(pkgDir, "..", "..");
|
|
|
42
42
|
// ── Clean ───────────────────────────────────────────────────
|
|
43
43
|
|
|
44
44
|
// Include `dist` so leftovers from the older pre-built-JS layout are
|
|
45
|
-
// wiped on re-run.
|
|
45
|
+
// wiped on re-run. Stale sandbox files are removed too so a renamed
|
|
46
|
+
// or deleted source file doesn't ride along into the tarball.
|
|
46
47
|
for (const dir of ["dist", "client", "server", "src"]) {
|
|
47
48
|
const target = join(pkgDir, dir);
|
|
48
49
|
if (existsSync(target)) rmSync(target, { recursive: true });
|
|
49
50
|
}
|
|
51
|
+
for (const file of ["Dockerfile.sandbox", "sandbox-entrypoint.sh"]) {
|
|
52
|
+
const target = join(pkgDir, file);
|
|
53
|
+
if (existsSync(target)) rmSync(target);
|
|
54
|
+
}
|
|
50
55
|
|
|
51
56
|
// ── Client dist (Vite build output) ─────────────────────────
|
|
52
57
|
// Copied to `client/` (not `dist/client/`) so the server's
|
|
@@ -89,5 +94,16 @@ cpSync(join(rootDir, "src"), join(pkgDir, "src"), {
|
|
|
89
94
|
});
|
|
90
95
|
console.log("✓ shared src/");
|
|
91
96
|
|
|
97
|
+
// ── Sandbox build context ───────────────────────────────────
|
|
98
|
+
// `server/system/docker.ts` builds the sandbox image via `docker build
|
|
99
|
+
// -f Dockerfile.sandbox .` with cwd = pkgDir. The Dockerfile in turn
|
|
100
|
+
// `COPY`s `sandbox-entrypoint.sh`, so both files must sit at pkgDir
|
|
101
|
+
// or sandbox mode silently falls back to unrestricted execution.
|
|
102
|
+
|
|
103
|
+
for (const file of ["Dockerfile.sandbox", "sandbox-entrypoint.sh"]) {
|
|
104
|
+
copyFileSync(join(rootDir, file), join(pkgDir, file));
|
|
105
|
+
}
|
|
106
|
+
console.log("✓ sandbox build context");
|
|
107
|
+
|
|
92
108
|
console.log("\nReady to publish. Run:");
|
|
93
109
|
console.log(" cd packages/mulmoclaude && npm publish --access public");
|