feat(rhema-code): add the colors setting with four palettes
The stored `colors` key names a palette — rhema (the default, Jadeite), aquamarine, black-and-white, or dracula — and the Appearance page of /settings cycles it live, like the theme and icon toggles beside it. Each palette carries a dark and a light appearance under the existing `theme` key; dracula's light side is derived, the official palette ships only dark. The appearance decision moves off token comparison: Theme now answers is_dark() from the ground/text luminance, so palettes beyond the original two get the right per-profile fallback tones.
This commit is contained in:
commit
81da26b955
159 files changed
+50628
No files matched your search
@@ -0,0 +1,85 @@
|
||||
# rhema-claw: the resident forge-watching daemon.
|
||||
# Build from the repo root (the context is the repo):
|
||||
# docker build -f deploy/docker/claw.Dockerfile .
|
||||
|
||||
# The builder tag tracks rust-toolchain.toml: the pinned channel is what
|
||||
# every commit is tested against. The full image (not -slim) carries the C
|
||||
# toolchain rusqlite's bundled SQLite build needs.
|
||||
FROM rust:1.98.1 AS builder
|
||||
WORKDIR /build
|
||||
|
||||
# Manifests first: the registry cache this populates survives source edits.
|
||||
COPY Cargo.toml Cargo.lock rust-toolchain.toml ./
|
||||
COPY crates/rhema-acp/Cargo.toml crates/rhema-acp/Cargo.toml
|
||||
COPY crates/rhema-agent-tools/Cargo.toml crates/rhema-agent-tools/Cargo.toml
|
||||
COPY crates/rhema-autonomous-agent/Cargo.toml crates/rhema-autonomous-agent/Cargo.toml
|
||||
COPY crates/rhema-claw/Cargo.toml crates/rhema-claw/Cargo.toml
|
||||
COPY crates/rhema-code/Cargo.toml crates/rhema-code/Cargo.toml
|
||||
COPY crates/rhema-coding-agent/Cargo.toml crates/rhema-coding-agent/Cargo.toml
|
||||
COPY crates/rhema-config/Cargo.toml crates/rhema-config/Cargo.toml
|
||||
COPY crates/rhema-core/Cargo.toml crates/rhema-core/Cargo.toml
|
||||
COPY crates/rhema-identity/Cargo.toml crates/rhema-identity/Cargo.toml
|
||||
COPY crates/rhema-memory/Cargo.toml crates/rhema-memory/Cargo.toml
|
||||
COPY crates/rhema-provider/Cargo.toml crates/rhema-provider/Cargo.toml
|
||||
COPY crates/rhema-provider-anthropic/Cargo.toml crates/rhema-provider-anthropic/Cargo.toml
|
||||
COPY crates/rhema-provider-copilot/Cargo.toml crates/rhema-provider-copilot/Cargo.toml
|
||||
COPY crates/rhema-provider-google/Cargo.toml crates/rhema-provider-google/Cargo.toml
|
||||
COPY crates/rhema-provider-llama-cpp/Cargo.toml crates/rhema-provider-llama-cpp/Cargo.toml
|
||||
COPY crates/rhema-provider-openai-compatible/Cargo.toml crates/rhema-provider-openai-compatible/Cargo.toml
|
||||
COPY crates/rhema-provider-openrouter/Cargo.toml crates/rhema-provider-openrouter/Cargo.toml
|
||||
COPY crates/rhema-rsd/Cargo.toml crates/rhema-rsd/Cargo.toml
|
||||
COPY integrations/rhema-calendar-integration/Cargo.toml integrations/rhema-calendar-integration/Cargo.toml
|
||||
COPY integrations/rhema-forge-integration/Cargo.toml integrations/rhema-forge-integration/Cargo.toml
|
||||
|
||||
# Resolution reads the vendored crossterm (the root manifest path-patches
|
||||
# to it) even though the image builds the daemon, which does not link it.
|
||||
COPY vendor/ vendor/
|
||||
|
||||
# Cargo validates explicit target
|
||||
# paths at manifest-parse time, so the fetch needs stub files at every
|
||||
# declared target path: src/ for every member, plus examples/tests/benches
|
||||
# as declared (default path from the target name, or the explicit `path`).
|
||||
# The loop drives off the crates/*/ and integrations/*/ globs because
|
||||
# neither glob's */src matches anything until the stub exists — an
|
||||
# unmatched glob would hand mkdir a literal path. The real sources land
|
||||
# below. (The awk program must stay on one line: a Dockerfile line not
|
||||
# ending in a backslash ends the RUN.)
|
||||
RUN for crate in crates/*/ integrations/*/; do \
|
||||
mkdir -p "$crate/src"; \
|
||||
touch "$crate/src/lib.rs" "$crate/src/main.rs"; \
|
||||
awk -F'"' '/^\[/ { d = ""; p = 0; if ($0 == "[[example]]") { d = "examples" } else if ($0 == "[[test]]") { d = "tests" } else if ($0 == "[[bench]]") { d = "benches" }; next } d == "" { next } /^name = / && p == 0 { print d "/" $2 ".rs" } /^path = / { p = 1; print $2 }' "$crate/Cargo.toml" \
|
||||
| while IFS= read -r target; do \
|
||||
mkdir -p "$crate$(dirname "$target")"; \
|
||||
touch "$crate$target"; \
|
||||
done; \
|
||||
done \
|
||||
&& cargo fetch
|
||||
|
||||
# Sources. target/ and .git never land here: the repo-root .dockerignore
|
||||
# keeps them out of the context.
|
||||
COPY . .
|
||||
RUN cargo build --release -p rhema-claw
|
||||
|
||||
FROM debian:stable-slim
|
||||
|
||||
# bash and git are load-bearing, not conveniences: the coding agent shells
|
||||
# out via `bash -c` and clones/fetches in its per-thread workspaces.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends bash git ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Numeric USER: Kubernetes cannot verify runAsNonRoot against a name.
|
||||
RUN useradd --uid 1000 --user-group --create-home claw \
|
||||
&& install -d -o 1000 -g 1000 /config /data
|
||||
|
||||
COPY --from=builder /build/target/release/rhema-claw /usr/local/bin/rhema-claw
|
||||
|
||||
# The chart passes --config /config/claw.yaml (the ConfigMap mount) and
|
||||
# mounts the state PVC at /data; these defaults serve a bare `docker run`.
|
||||
ENV XDG_CONFIG_HOME=/config \
|
||||
XDG_STATE_HOME=/data/state
|
||||
VOLUME /data
|
||||
EXPOSE 7799
|
||||
|
||||
USER 1000:1000
|
||||
ENTRYPOINT ["/usr/local/bin/rhema-claw"]
|
||||
@@ -0,0 +1,40 @@
|
||||
# rhema-claw-ui: the web UI's static bundle behind nginx.
|
||||
# Build from the repo root (the context is the repo):
|
||||
# docker build -f deploy/docker/ui.Dockerfile -t rhema-claw-ui .
|
||||
|
||||
# The build: the Nuxt app generates a fully static bundle (ssr is off —
|
||||
# the UI is a client of the claw's API, nothing server-side to run).
|
||||
FROM node:22-alpine AS build
|
||||
WORKDIR /web
|
||||
COPY web/claw/package.json web/claw/package-lock.json ./
|
||||
# The lock file pins the tree; ci is the reproducible install.
|
||||
RUN npm ci
|
||||
COPY web/claw ./
|
||||
RUN npm run build
|
||||
|
||||
# The runtime: nginx serves the bundle with an SPA fallback — the app is
|
||||
# one page, but a browser hitting a stale deep link must land on it, not
|
||||
# on a 404. Index is served no-cache (a new deploy must not be masked by
|
||||
# the browser), the hashed _nuxt assets are forever-cacheable.
|
||||
FROM nginx:alpine
|
||||
COPY <<'NGINX' /etc/nginx/conf.d/default.conf
|
||||
server {
|
||||
listen 80;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location /_nuxt/ {
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
try_files $uri =404;
|
||||
}
|
||||
location / {
|
||||
add_header Cache-Control "no-cache";
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
NGINX
|
||||
COPY --from=build /web/.output/public /usr/share/nginx/html
|
||||
|
||||
# The UI is stateless static files: any number of replicas, no PVC, and
|
||||
# the claw's single-node invariant does not apply here.
|
||||
EXPOSE 80
|
||||
Reference in new issue
Block a user