My personal website where I post my blogs / about me and resume.
Copilot JRPG chat
/jrpg streams stateful turns through Seobeo and Deita to a local Python
Copilot SDK/CLI runtime. The SDK uses a loopback LiteLLM Proxy configured with
the github_copilot provider.
Python, Copilot CLI, LiteLLM, the web server, and their lockfiles are all managed by Bazel. Do not create a virtualenv or install packages with pip.
Authenticate LiteLLM once with the GitHub Copilot device flow:
export GITHUB_COPILOT_TOKEN_DIR="$HOME/.local/state/mrjunejune/inference/litellm-copilot"
bazel run //mrjunejune/inference:litellm_proxy -- \
--authenticate \
--token-dir "$GITHUB_COPILOT_TOKEN_DIR"
Then start the complete local stack with one Bazel command:
LITELLM_MASTER_KEY='<local proxy key>' \
MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE=1 \
bazel run //mrjunejune:run_inference_stack
For UI work, start the same Seobeo, Deita, inference bridge, and SSE path with deterministic mock responses. This mode does not require Copilot authentication or a LiteLLM key:
bazel run //mrjunejune:run_inference_stack -- --mock
Send !hello, !response, !tool, !plan, or !error to run a scripted
event sequence. Edit mrjunejune/inference/mock_responses.json to add commands,
ordered SSE event payloads, per-event timing, and response chunks. Custom event
types pass through Seobeo and are published by the page as
mjj-jrpg-stream-event, ready for future tool-call and plan-view components.
Mock conversations use a separate database under the inference state directory.
Keep GITHUB_COPILOT_TOKEN_DIR exported when starting the stack so it reads the
same tokens. Without an override, both commands use
$XDG_STATE_HOME/mrjunejune/inference/litellm-copilot, or
~/.local/state/mrjunejune/inference/litellm-copilot when XDG_STATE_HOME is
unset. MRJUNEJUNE_INFERENCE_STATE moves all service-owned state. Internal
processes bind to loopback. Provider keys, OAuth tokens, conversation IDs,
prompts, and model output must not be committed or logged.
Anonymous inference is disabled unless
MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE=1 is explicitly set. Enabling it exposes
paid inference without user authentication; keep the Seobeo rate/concurrency
limits and LiteLLM budget enabled.
The production bundle includes the pinned Python environment, Copilot CLI, LiteLLM, JRPG assets, and C server:
bazel build -c opt //mrjunejune:mrjunejune_server_bundle
WebP assets
Raster source images live under mrjunejune/assets/png/ and assets/png/.
Bazel converts them to WebP before they enter the server runfiles or release
bundle:
bazel build //mrjunejune:generated_webp_assets
bazel build //mrjunejune:mrjunejune_server_bundle
The deployed site contains no PNG files. Add new PNG source assets to the
corresponding list in mrjunejune/BUILD or assets/BUILD, then reference the
generated .webp URL from the site.
HLS player
/tools/hls_player is a dependency-free JavaScript HLS player. It uses native
HLS where available and a MediaSource fallback for unencrypted VOD playlists
with fragmented MP4 segments. A VP9/Opus HLS sample is bundled at:
/public/hls-sample/master.m3u8
The sample is generated from mrjunejune/assets/video/sample_hls.mp4 through
the restored FFmpeg CLI wrapper:
bazel run //mrjunejune:generate_hls_sample
bazel test //mrjunejune/test:hls_player_test
bazel test //mrjunejune/test:theme_and_webp_test
LaTeX editor
/tools/latex_editor sends source to the C server, which compiles it with the
offline Tectonic runtime from //third_party/tectonic:runtime and returns the
PDF directly to the browser. Bazel pins the static compiler, prewarms common
packages, and includes both in the server runfiles and release bundle.
The compiler child uses restricted TeX file access, Linux Landlock, a seccomp network filter, and CPU, memory, file-size, process, and wall-clock limits. Compilation fails closed when the Linux sandbox cannot be applied.
bazel test //mrjunejune/test:latex_renderer_test
bazel test //mrjunejune/test:latex_editor_test
TODO
- Add caching layer
- Update talk to be part
- Update test to automatically tests all paths for blogs.