Tags

Tags give the ability to mark specific points in history as being important
  • v5.4.1

    v5.4.1
    
    **Fixes `claudebox-*` models silently answering from pibox-zai instead of Claude when called through the gateway.**
    
    - `claudebox-*` models failed through the gateway unless `CLAUDEBOX_API_TOKEN` was set in `.env`. The claudebox container falls back to `AIGATE_TOKEN` for its API token, but LiteLLM read `CLAUDEBOX_API_TOKEN` with no fallback, sent an empty key, and got `401`. The request then moved down the fallback chain to `pibox-zai-glm-5.3-flash` or `pibox-zai-glm-5.3` and still returned `200`, so the only sign was the `model` field in the response. LiteLLM now gets `CLAUDEBOX_API_TOKEN` and `PIBOX_ZAI_API_TOKEN` with the same `AIGATE_TOKEN` fallback the agent services use. `PIBOX_ZAI_API_TOKEN` had the same gap and only worked when set explicitly.
    - Recreate the `litellm` container to pick up the change.
  • v5.4.0

    v5.4.0
    
    **Moves claudebox to `v2.4.5` and both pibox services to `v0.18.4`. Streaming chat completions on all three can now carry the agent's native event records.**
    
    - Streaming requests to `/claudebox/openai/v1/chat/completions`, `/pibox-zai/openai/v1/chat/completions`, and `/pibox/openai/v1/chat/completions` accept `"stream_options": {"include_aicodebox_events": true}`. The response then adds named `aicodebox.native` SSE events next to the normal OpenAI chunks, each wrapping a raw record from the agent. Content chunks and `[DONE]` are unchanged, and a stream without the option carries no extra events. Sending the option without `"stream": true` returns `400`. See `docs/services/claudebox.md`.
    
    - claudebox image bumped `v2.3.10` to `v2.4.5`. A container created from the new image installs Claude Code `2.1.280` on first start. Claude Code lives in the container filesystem, not the config volume, so the new version arrives when the container is recreated.
    - pibox image bumped `v0.16.2` to `v0.18.4` for both `pibox-zai` and `pibox`. This updates pi-coding-agent to `0.85.1`.
    - No environment variables changed. Existing `.env` files work as they are.
  • v5.3.0

    **Adds five current OpenRouter free models to the gateway.**
    
    - `or-nemotron-ultra`, backed by NVIDIA Nemotron 3 Ultra.
    - `or-qwen3.8-27b`, backed by Qwen 3.8 27B.
    - `or-ling-3-vl`, `or-gemma-4-31b`, and `or-inkling` for multimodal requests.
    - General and multimodal fallback chains for the new aliases.
  • v5.2.0

    **Gives `pibox` the same tailnet egress wiring `claudebox` and `pibox-zai`
    already had.**
    
    - `pibox` joins the tailnet egress overlay, so it gets the split DNS and route
      helper the other two agent containers get when `TAILSCALE=1` is on. Without
      it the service reached the tailnet only on hosts that already route
      `100.64.0.0/10` themselves, and had no tailnet access at all on a host that is
      not a tailnet node.
  • v5.1.1

    **Bumps both pibox services to `v0.16.2`, which fixes every advertised model
    except the default one failing on each request.**
    
    - pibox image bumped `v0.16.1` to `v0.16.2`. On v0.16.1 only
      `PIBOX_PROVIDER_MODEL` was registered in Pi's provider model list, so any
      other model in `PIBOX_AVAILABLE_MODELS` fell back to Pi's default API shape,
      disagreed with the configured provider base URL, and failed with
      `Stream ended without finish_reason`. Both services shipped in v5.1.0 with
      this fault: `pibox-zai` served `glm-5.3-flash` but not `glm-5.3`, and `pibox`
      served only its default model out of everything listed in `PIBOX_MODELS`.
      Picking a model from the advertised list is the point of these services, so
      v5.1.0 should be skipped. v0.16.2 registers every advertised model under the
      configured `PIBOX_PROVIDER_API`, and warns at startup when the provider base
      URL and API protocol describe different protocols rather than surfacing the
      mismatch as a truncated stream at request time.
  • v5.1.0

    **Adds `pibox`, an agent that runs on the models this stack already serves. No
    extra provider account and no second subscription. A local Ollama or vLLM model,
    or a free cloud model, drives the agent loop.**
    
    - `pibox` service, opt-in with `PIBOX=1`, reachable at `/pibox/` with its MCP
      server at `/pibox/mcp/`. It is [pi-coding-agent](https://github.com/earendil-works/pi-mono)
      in API mode with its upstream pointed at this stack's own LiteLLM, so any model
      in `/v1/models` becomes an agent backend with shell, file, and MCP tool use. It
      exposes the same REST API, OpenAI-compatible endpoint, `/files/*` CRUD, and MCP
      server as pibox-zai, in its own container with its own workspace.
      - `PIBOX_MODELS` lists the models it offers and `PIBOX_DEFAULT_MODEL` picks the
        one used when a caller names none. Both ship with defaults spanning groq,
        Ollama CUDA, Cohere, HuggingFace, and OpenRouter. Trim them to what you have
        enabled.
      - A listed model has to be able to call tools. The agent loop is tool driven,
        so a model that answers with text instead of a tool call stalls on the first
        turn. Capability does not track size: `local-ollama-cuda-qwen3-8b` calls
        tools and the larger `local-ollama-cuda-qwen3-30b-a3b` does not, while
        `local-ollama-cuda-deepseek-coder-v2-16b` predates Ollama's tool support and
        reports no `tools` capability at all. `ollama show <model>` lists what a
        given model supports.
      - No GPU is required. Tool capability belongs to the model file, so a
        `local-ollama-cpu-*` model calls tools exactly as well as the CUDA copy of
        the same tag and only speed differs. An agent loop is many turns, so a CPU
        run is slow rather than impossible. llamacpp and vllm cannot back this
        agent: llamacpp serves only an OCR model, and vllm serves a 0.6B chat model
        and an embedding model.
      - **Do not list `claudebox-*`, `pibox-*`, or any model whose fallback chain
        reaches one.** Those route back into an agent and the run recurses.
      - `PIBOX_UPSTREAM_KEY` sets the key the agent presents to LiteLLM. It defaults
        to `LITELLM_MASTER_KEY`, which itself defaults to `AIGATE_TOKEN`, so it works
        unconfigured. Point it at a LiteLLM virtual key to track this agent's
        requests and spend separately from the rest of the gateway.
    
    - pibox image bumped `v0.15.12` to `v0.16.1` for both services. v0.16.0 added
      generic upstream provider configuration, which is what lets an agent target a
      LiteLLM endpoint.
    - pibox-zai moved from the `ANTHROPIC_*` variables to `PIBOX_PROVIDER_*`. Same
      endpoint, same models, same Anthropic Messages protocol. The new path keeps an
      environment-variable reference to the key in Pi's provider config instead of
      writing the key value into `models.json`. `PIBOX_ZAI_BASE_URL` overrides the
      endpoint; z.ai also serves an OpenAI-compatible Coding Plan endpoint at
      `https://api.z.ai/api/coding/paas/v4`.
    
    - `make down` now tears down the `piston`, `llamacpp`, and `llamacpp-cuda`
      profiles. They were never listed, so those containers survived a `make down`
      and had to be stopped by hand.
    - `make limits` sizes the new `pibox` service. Without it the service would have
      kept the fixed compose fallback on every machine while every other service got
      limits scaled to the host.
  • v5.0.0

    **Reverses the `docker-compose.yml` change from v4.0.0. The base compose file is
    tracked again, and local changes belong in `docker-compose.override.yml`.**
    
    v4.0.0 made `docker-compose.yml` a local untracked file so an update could not
    overwrite it. That was the wrong mechanism for this file. It carries 46 service
    definitions, 22 nginx routes, and 19 rate-limit zones that have to move together
    with the provider configs, the Makefile profiles, and the LiteLLM config
    builder. A frozen copy silently breaks: a later release adds a service, ships
    its provider YAML and profile flag, and the local compose has no matching
    service, so LiteLLM registers a model pointing at a host that does not resolve
    and nginx has no route for it.
    
    Compose already solves this with an override file, which is what this release
    uses.
    
    - **`docker-compose.yml` is tracked again and an update overwrites edits to it.**
      Put local changes in `docker-compose.override.yml`, which is gitignored and
      merged last, so it wins over the base and over any bundled overlay. Write only
      the keys being changed:
    
      ```yaml
      services:
        claudebox:
          mem_limit: 8g
      ```
    
      **Upgrading from v4.0.0 needs one manual step.** v4.0.0 left an untracked
      `docker-compose.yml` in the working tree and this release adds that same path
      as a tracked file, so Git refuses the checkout with `untracked working tree
      file would be overwritten`. Move the file aside first, then pull, then port
      any edits into `docker-compose.override.yml`:
    
      ```bash
      mv docker-compose.yml docker-compose.yml.mine
      git pull
      diff -u docker-compose.yml docker-compose.yml.mine   # port what you changed
      ```
    
      Upgrading from v3.24.0 or earlier needs nothing; the file is tracked in both.
    - **`docker-compose.yml.example` is removed.** The base file is the shipped
      default again, so the copy served no purpose.
    
    - `COMPOSE_FILE` is now assembled by the Makefile in merge order: the base file,
      then `docker-compose.tailscale.yml` when `TAILSCALE=1`, then
      `docker-compose.override.yml` when it exists. Compose only auto-loads an
      override file when `COMPOSE_FILE` is unset, and the tailnet overlay sets it, so
      the override is appended explicitly rather than relying on that default.
    - `make bootstrap` creates `.env` from `.env.example` and prints the active
      compose file chain. It no longer creates `docker-compose.yml`.
    - `.env` is unchanged: still created from `.env.example` on first run, still
      gitignored. That file is settings rather than wiring, so a local copy cannot
      drift out of step with the rest of the repository.
  • v4.0.0

    **`docker-compose.yml` and `.env` are now local files created from tracked
    `.example` copies, so an update never overwrites them. Every cloud provider's
    model list was audited against the live APIs and the dead entries removed.**
    
    - **`docker-compose.yml` is no longer tracked.** The repository ships
      `docker-compose.yml.example`; `make` copies it to `docker-compose.yml` on
      first run, and `.gitignore` covers the copy. Pulling this release deletes the
      tracked file from your checkout. If you had local edits to it, save them
      first, then reapply them after any `make` target recreates the file. To change
      the shipped defaults for everyone, edit `docker-compose.yml.example` instead;
      edits to `docker-compose.yml` cannot be committed.
    - **Model aliases removed.** Each of these returned a result before and no
      longer resolves. The ones marked as already failing answered with a fallback
      model behind an HTTP 200 rather than an error, so callers may not have
      noticed.
      - pibox-zai, all of which worked because z.ai auto-routed them:
        `pibox-zai-glm-5.2`, `pibox-zai-glm-5.1`, `pibox-zai-glm-5-turbo`,
        `pibox-zai-glm-5`, `pibox-zai-glm-4.7`, `pibox-zai-glm-4.6`,
        `pibox-zai-glm-4.5`, `pibox-zai-glm-4.5-air`. Replace with
        `pibox-zai-glm-5.3` (for 5.2, 5.1, 5) or `pibox-zai-glm-5.3-flash` (for 4.7
        and below).
      - OpenRouter, already failing: `or-hermes-3-405b`, `or-qwen3-coder`,
        `or-qwen3-80b`, `or-llama-3.3-70b`, `or-gpt-oss-120b`, `or-gpt-oss-20b`,
        `or-nemotron-ultra-550b`, `or-nemotron-nano-9b`, `or-nemotron-nano-30b`.
      - HuggingFace, already failing: `hf-qwq-32b`, replaced by `hf-qwen3-32b`, and
        `hf-qwen3-vl-8b`, replaced by `hf-gemma-3-27b`.
      - Cerebras, archived upstream: `cerebras-glm-4.7`.
    - **`PIBOX_ZAI_AVAILABLE_MODELS` and `PIBOX_ZAI_DEFAULT_MODEL` defaults
      changed** to `glm-5.3,glm-5.3-flash` and `glm-5.3-flash`. An `.env` pinning
      the old values will fail. Drop the override or set the new ids.
    
    - `make bootstrap` creates `.env` and `docker-compose.yml` from their `.example`
      files. Every other target seeds them first, so `make run` on a fresh clone
      works with no manual copy step. The copy runs while `make` parses the
      Makefile, before it reads `.env`, so profile flags in a freshly created `.env`
      take effect on that same invocation.
    - OpenRouter: nine free models replacing the nine that no longer resolve.
      `or-nemotron-lightning` (1M context), `or-nemotron-120b`, `or-dots-3-note`
      (text and image), `or-nemotron-omni-30b` (omni, reasoning),
      `or-north-mini-code`, `or-lfm-2.5-2.6b`, `or-ling-3-sante`, `or-ling-3-fin`,
      and `or-nemotron-content-safety`. The last three answer by name but stay out
      of the general fallback chains, where a domain-tuned model or a classifier
      would answer off-target.
    - Groq: `groq-qwen3.8-27b`, `groq-allam-2-7b` for Arabic, and the
      `groq-prompt-guard-22m` and `groq-prompt-guard-86m` prompt-injection
      classifiers, which return a probability score rather than chat text.
    - Cohere: `cohere-command-a-plus`, `cohere-command-a-reasoning`,
      `cohere-command-a-vision`, `cohere-command-a-translate`,
      `cohere-north-mini-code`, `cohere-command-r7b-arabic`,
      `cohere-aya-vision-32b`, and `cohere-tiny-aya-global`, `-earth`, `-fire`,
      `-water`.
    - HuggingFace: `hf-qwen3-235b` and `hf-gemma-3-27b`.
    - Cerebras: `cerebras-qwen3.8-27b` and `cerebras-gemma-4-31b`.
    
    - **`groq-compound` and `groq-compound-mini` reached the wrong vendor.** Groq
      namespaced both ids under `groq/` upstream, so the old pins stopped resolving
      and the fallback chain answered with a Cohere model behind an HTTP 200. The
      pins are now `groq/groq/compound` and `groq/groq/compound-mini`: the first
      `groq/` selects the provider, the second belongs to the model id.
    - Fallback chains no longer point at models that do not exist. Every chain key
      and every fallback target resolves to a registered model. That includes
      `local-talkies-cuda-qwen3-tts-0.6b`, a long-standing typo for
      `local-talkies-cuda-qwen3-tts`.
    
    - pibox-zai is documented as running on a [GLM Coding
      Plan](https://z.ai/subscribe) rather than generic z.ai credits, and the plan's
      two models are the only exposed aliases. The provider page carries the
      token-to-credit formula and the per-model rates, with a note that those rates
      are conversion factors and not multipliers against an older baseline.
    - The routing tier previously called "flat-rate" is now "subscription". The
      claim that it costs the subscription with "no extra per-call charge" is
      replaced with the accurate statement that the allowance is metered.
    - Cerebras is documented as requiring a paid plan. At the last audit every model
      returned `Payment required to access this resource` on a free account, so the
      free-tier claims in the README, the provider page, and `.env.example` were
      wrong.
  • v3.24.0

    **Bump the claudebox and pibox agent images. Both are rebuilt on the aicodebox
    v0.14.6 base, which adds native full-event retention on `POST /run`.**
    
    - claudebox image bumped `v2.0.13` to `v2.3.10`. As of the image's v2.3.0,
      Claude Code is no longer baked into the image (Anthropic's CLI carries no
      redistribution grant); it installs from npm on first container start, so a
      fresh claudebox needs outbound network and a few extra seconds on first boot.
      The version is pinned via `CLAUDEBOX_CLAUDE_VERSION` and warm restarts skip
      the install. The v0.14.6 base adds native full-event retention on `POST /run`
      (`eventMode`) and Claude Code's native `--json-schema` flag, and the chain
      since v2.0.13 inherited an API-mode restart-loop fix (the agent subprocess is
      spawned in its own session, so its signals no longer reach the uvicorn PID 1).
    - pibox image bumped `v0.15.11` to `v0.15.12`, rebuilt on the same aicodebox
      v0.14.6 base for native full-event retention on `POST /run`.
  • v3.23.0

    **Outbound tailnet access for the claudebox and pibox-zai agent containers.
    When `TAILSCALE=1` runs alongside `CLAUDEBOX=1` or `PIBOX_ZAI=1`, those
    containers can reach machines on your tailnet over any protocol, on top of the
    existing inbound `tailscale serve` proxy.**
    
    - Tailnet egress overlay (`docker-compose.tailscale.yml`), loaded by the
      Makefile only when `TAILSCALE=1`. It routes the `100.64.0.0/10` Tailscale
      CGNAT range out through the existing tailscale node and configures split DNS,
      so claudebox and pibox-zai resolve tailnet names and connect to tailnet peers
      while public and sibling-container names keep resolving. Both containers stay
      on the bridge, so nginx and LiteLLM still reach them.
      - The tailscale container becomes a NAT gateway (`MASQUERADE` on `tailscale0`,
        kept present by a sidecar). Each agent container gets the tailnet route
        installed in its network namespace by a per-container sidecar that re-adds it
        after a restart. All egress sidecars run with `no-new-privileges:true` and
        `cap_drop: [ALL]`, adding back only `NET_ADMIN` (plus `NET_RAW` on the
        gateway sidecar for the NAT rule).
      - DNS: Tailscale MagicDNS (`100.100.100.100`) answers tailnet names and
        SERVFAILs everything else; Docker's embedded resolver falls through to a
        public resolver for public names.
    - `TS_MAGICDNS_SUFFIX` (optional): your tailnet's MagicDNS suffix, so the agent
      containers resolve bare tailnet names in addition to FQDNs. Leave unset to
      require fully-qualified names.
    - `TS_FALLBACK_DNS` (optional, default `1.1.1.1`): resolver the agent containers
      use for non-tailnet names. Set your own to keep public DNS on your
      infrastructure.
    
    Scope: IPv4 tailnet peers by their `100.64.0.0/10` address or MagicDNS name. A
    LAN behind a subnet router and tailnet IPv6 are not routed. See
    [docs/services/tailscale.md](docs/services/tailscale.md).
  • v3.22.0

    **Bump talkies `v0.16.0` → `v0.17.0`, which adds two phoneme-recognition ASR
    models. The CPU profile now serves 13 models, the CUDA profile 22.**
    
    - Two phoneme ASR models on `/v1/audio/transcriptions`, in both the CPU and
      CUDA images. They carry no language model and no lexicon, so a mispronunciation
      comes back as the phones actually spoken rather than corrected to the nearest
      real word. `text` is a space-separated IPA phone stream, and per-phone
      timestamps come through `verbose_json`, `srt`, `vtt`, and
      `timestamp_granularities` the same way the word-level models do.
      - `local-talkies-wav2vec2-xlsr-53-espeak` (and its `-cuda-` alias) is a
        multilingual wav2vec2 CTC model that emits eSpeak IPA, the same alphabet the
        Kokoro G2P path uses.
      - `local-talkies-zipa-ipa` (and its `-cuda-` alias) is a Zipformer IPA CTC
        model served through the sherpa-onnx offline runtime, a 71 MB int8 download
        that decodes a whole file in one pass.
    - Verified end to end through LiteLLM: both return IPA for spoken input on the
      CPU and CUDA routes.
  • v3.21.0

    v3.21.0 — talkies v0.16.0 adds the TALKIES_CHATTERBOX_WATERMARK opt-out for the chatterbox-turbo neural watermark.
  • v3.20.1

    v3.20.1 — pibox v0.15.11 fixes the GLM upstream-auth regression from v3.20.0 (pi 0.84.0 sends apiKey literally; pibox now writes the resolved token). Restart-loop fix carried forward.
  • v3.20.0

    v3.20.0 — pibox v0.15.10 fixes the pibox-zai restart loop (agent runs in its own session); GLM model list corrected for z.ai's aliasing (glm-5.1/glm-5 -> GLM-5.2, glm-4.5-air -> GLM-4.7).
  • v3.19.3

    v3.19.3 — correct documentation claims the repo does not support
    
    Removes the last Speaches references, corrects the mcp_tools activation set
    (PISTON does not enable it), fixes the mailbox and sd.cpp health routes, and
    drops the https:// promise for Tailscale, which forwards at L4 over plain HTTP.
    Documentation only — no code, compose or config changes.
  • v3.19.2

    v3.19.2 — sdcpp wrapper moves to slogging v1.7.0
    
    v1.7.0 rebuilt slogging's handler API, but the wrapper uses the blank import and
    never names a handler type, so its logging behaves exactly as before. No compose
    service, model registry or provider config changes.
  • v3.19.1

    v3.19.1 — sdcpp wrapper follows slog-configurator to slogging/slogconf
    
    Exported names are unchanged, so the wrapper's logging behaves exactly as
    before. No compose service, model registry or provider config changes.
  • v3.19.0

    v3.19.0 — talkies v0.15.2, Chatterbox Turbo expressive TTS with inline emotion tags on the CUDA profile
  • v3.18.0

    v3.18.0 — talkies v0.14.0 per-model concurrency, no same-container fallback, searxng key moved to .env
  • v3.17.2

    v3.17.2 — talkies v0.13.3 (Sherpa word-output fixes) + Codex manifest version correction