Skip to content

Additional Fixes to Make Junie Work - #48

Open
MatthewJones517 wants to merge 4 commits into
ai-hero-dev:mainfrom
MatthewJones517:junie_fixes
Open

Additional Fixes to Make Junie Work#48
MatthewJones517 wants to merge 4 commits into
ai-hero-dev:mainfrom
MatthewJones517:junie_fixes

Conversation

@MatthewJones517

Copy link
Copy Markdown

Fix Junie CLI support

tl;dr

JetBrains docs for Junie CLI lie. This PR is the result of testing stuff against the actual harness.

Overview

Fixes Junie CLI support, which was silently broken. The original #45 entry
pointed Junie at a documented proxies entry in ~/.junie/config.json.
Verified against a real Junie CLI install (build 1543.24): that mechanism is
never consulted, headless or interactive, regardless of kind — Junie just
keeps talking to its normal authenticated backend, with no error and an empty
logs folder.

This PR switches Junie to the mechanism that actually works — a Custom LLM
model profile
at ~/.junie/models/*.json, selected explicitly with
--model custom:<profile-name> — and fixes three more bugs found while
driving it end-to-end against a live proxy:

  1. 5f06839 — Switch from the broken proxies/config.json route to a
    working custom-model-profile route (~/.junie/models/request-logger.json,
    --model custom:request-logger). Also fixes the model profile's
    baseUrl, which must be the full endpoint path (/v1/messages or
    /v1/chat/completions), not a bare origin — Junie posts to it verbatim
    with no path appended.

  2. 4e33f22 — Fix blank [request-logger] upstream error: log lines.
    Node throws an AggregateError on a failed dual-stack connection (e.g. to
    localhost), and its .message is always empty — the real reasons are
    one level down in .errors[]. Added a describeError() helper that
    unpacks it, and wired connection failures into the proxy's existing
    burst-throttle so a stuck client retrying in a loop doesn't flood the
    console.

  3. b87cce8 — Stop setting anthropic-version in the model profile's
    extraHeaders. Junie's Anthropic client already sends that header
    itself; an extraHeaders entry with the same name doesn't override it,
    it's appended as a second occurrence, and the two get joined with a comma
    on the wire (2023-06-01,2023-06-01) — which Anthropic rejects with a
    400.

  4. 1c80009 — Send a real model ID in the profile's id field instead
    of the placeholder "request-logger". Junie sends id verbatim as the
    model field of every request, so a made-up name gets a 404 from the real
    backend. The wizard now asks for a real model ID up front (the same way it
    already does for Pi), discovered from /v1/models when available.

Every fix above was root-caused and confirmed against a real, installed
Junie CLI (build 1543.24) with a live proxy in front of it — not just against
JetBrains' published docs, which turned out to disagree with the real
client's behavior. request-logger/README.md documents this testing status
and explicitly warns against the documented-but-broken proxies route so
nobody rediscovers it the hard way.

Setup instructions for Junie users

  1. Run the wizard:

    npm run request-logger
  2. Pick Junie when asked which coding agent you use.

  3. Enter your backend's base URL — e.g. https://api.anthropic.com for a
    real Anthropic key, or a local server's URL.

  4. Pick the wire formatAnthropic-compatible or OpenAI-compatible,
    matching your backend.

  5. Pick a model ID — the wizard tries to discover one from /v1/models;
    if that fails (common for Anthropic, which requires auth to list models),
    type one by hand (e.g. claude-sonnet-4-5). This must be a real model
    your backend serves — Junie sends it verbatim as the model field of
    every request.

  6. The wizard prints a JSON block and tells you to save it to
    ~/.junie/models/request-logger.json. Do that, and replace the
    placeholder API key
    (YOUR_ANTHROPIC_API_KEY / Bearer YOUR_OPENAI_API_KEY) with your real key. This file holds a real
    credential in plaintext — don't commit it.

  7. Run Junie with the printed command, which selects the profile
    explicitly:

    junie --model custom:request-logger
  8. Every request now shows up as a readable Markdown file in
    request-logger/logs/.

If you change your backend or model later: re-run npm run request-logger -- --force to go through the wizard again, and update
~/.junie/models/request-logger.json by hand to match — the file is written
once at wizard time and isn't kept in sync automatically.

Do not use Junie's documented proxies entry in ~/.junie/config.json
for this — it's silently never consulted by the real client, and you'll get
an empty logs folder with no error.

MatthewJones517 and others added 4 commits August 26, 2026 10:42
…t proxy

Junie's documented `proxies` entry in `config.json` (kind: "Anthropic"/
"OpenAI") looks right per JetBrains' published docs, but driving it against
a real Junie CLI install (build 1543.24) showed it is never consulted --
Junie silently keeps using its normal authenticated backend regardless of
`kind`, headless or interactive, with an empty logs folder and no error.

Junie's separate Custom LLM models feature does work: a JSON profile under
~/.junie/models/*.json, selected explicitly with --model custom:<name>.
Verified end to end against a live proxy on both wire formats. The one
catch is that a profile's baseUrl is the full endpoint path, not an origin,
so the Anthropic and OpenAI provider entries now carry that suffix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Node throws an AggregateError when a connection to a dual-stack host (e.g.
"localhost") fails on every address it tries -- its own .message is always
"", with the real per-address reasons nested in .errors. The upstream error
handler was printing err.message directly, so every failed connection to
upstream showed up as a bare "[request-logger] upstream error:" with
nothing after the colon and no way to tell what was actually wrong.

Also route these errors through the existing burst guard: a dead upstream
fails every retry identically and fast, the same shape of storm the guard
already exists for on the success path, but the connection-error path had
never been wired into it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Junie's Anthropic client always sends its own anthropic-version header.
extraHeaders does not replace an existing header of the same name, it adds
a second occurrence, and the two get joined with a comma on the wire
(anthropic-version: 2023-06-01,2023-06-01) -- which Anthropic rejects as an
invalid version code. Every request was landing at request-logger as a 400
because of this, even with a valid key.

Confirmed live: dropping the header here produces a clean single
anthropic-version: 2023-06-01 on the wire, and the request reaches
Anthropic far enough to get a real 401 on a bad key instead of a 400 on the
header.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…placeholder

Junie sends a model profile's "id" field verbatim as the "model" field of
every request. The profile hard-coded id to "request-logger", which is not
a real model on any backend, so Anthropic rejected every request with a
404 ("model: request-logger"). Confirmed by reading Junie's own bundled
docs (Custom-LLM-models.md, from the installed CLI's jar) and by driving a
live proxy end to end.

Junie's custom target now asks for a real model ID the same way Pi's and
OpenCode's custom-OpenAI targets already do, and writes it into the
profile's id field. Verified live: the proxy's captured request now shows
the chosen model, and Anthropic returns 401 (invalid key) instead of 404.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant