Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: levelcodeai/levelcode
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: faa8eb5
Choose a base ref
...
head repository: levelcodeai/levelcode
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a0850f4
Choose a head ref
  • 7 commits
  • 9 files changed
  • 2 contributors

Commits on Jul 25, 2026

  1. fix(branding): point the product license link at HEAD, not the missin…

    …g main branch
    
    product.overlay.json set licenseUrl/serverLicenseUrl to
    github.com/levelcodeai/levelcode/blob/main/LICENSE, but there is no `main` branch
    — the default is `develop` — so the license link baked into the app's About /
    license metadata 404'd. Use /blob/HEAD/LICENSE: GitHub resolves HEAD to whatever
    the default branch is, so it works on develop today and survives a future rename
    to main.
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    ndemianc and claude committed Jul 25, 2026
    Configuration menu
    Copy the full SHA
    d9755a6 View commit details
    Browse the repository at this point in the history
  2. docs(license): keep LICENSE pure MIT so GitHub detects it; move attri…

    …bution to NOTICE
    
    GitHub's license API reported NOASSERTION (not MIT) for this repo: the derivative
    and Microsoft-trademark paragraph appended after the MIT text pushed the file
    below the detector's template-match threshold, so the repo carried no MIT label.
    
    Split it the way upstream VS Code does — LICENSE is now verbatim MIT (the grant
    and the copyright line are unchanged), and the Code-OSS provenance + trademark
    disclaimer move to a dedicated NOTICE file. README's License section points at
    both. Nothing is lost; MIT now detects.
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    ndemianc and claude committed Jul 25, 2026
    Configuration menu
    Copy the full SHA
    cbf4f4f View commit details
    Browse the repository at this point in the history
  3. Merge pull request #44 from levelcodeai/fix/license-link-and-notice

    fix(license): repair the 404 license link, and make GitHub detect MIT
    ndemianc authored Jul 25, 2026
    Configuration menu
    Copy the full SHA
    85df68b View commit details
    Browse the repository at this point in the history
  4. fix(ai): stop mislabeling gateway errors as "OpenAI" and dumping raw …

    …HTML into chat
    
    A gateway run that hit an upstream 502 surfaced, verbatim:
    
        OpenAI API 502: <html> ... <center><h1>502 Bad Gateway</h1></center> ... </html>
    
    Two defects in one line:
    
    1. Mislabeled. The gateway resolves to providerId 'openai' to reuse the OpenAI-
       compatible adapter, so streamAgentTurn stamped the error with the OpenAI provider
       row's label — even for Opus 5 over LevelCode Cloud. prepProviderRequest already
       computes the right label ('LevelCode Cloud'); it was just never threaded past the
       provider lookup. Thread req.label through runAgent/turnOpts, doStream, and compact,
       and have the router prefer o.label over p.label. BYOK still falls back to the
       provider's own label, so an OpenRouter failure still reads "OpenRouter".
    
    2. Raw HTML dumped. The three throw sites appended the raw response body; a proxy 5xx
       is an HTML page, not JSON, so the whole nginx document landed in the transcript.
       Two pure helpers in openaiCompat: extractApiError() returns a provider's JSON
       {error:{message}} when present, '' for an HTML page, and a hard-capped string
       otherwise; httpError() composes "<label> API <status>: <detail>", falling back to
       the status reason ("Bad Gateway") when there's no usable message, and sets e.status.
    
    The 502 itself is a transient upstream blip we can't fix — this is about surfacing it
    honestly. The same failure now reads:
    
        LevelCode Cloud API 502: Bad Gateway
    
    providers.test.js +10 (extractApiError / httpError, incl. the exact nginx body).
    Verified end-to-end with a stubbed fetch: the label threads through the real
    index.js -> openaiCompat.js chain and BYOK's p.label fallback is intact.
    Full gate: 24 suites, 0 failures.
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    ndemianc and claude committed Jul 25, 2026
    Configuration menu
    Copy the full SHA
    8a22f05 View commit details
    Browse the repository at this point in the history
  5. feat(ai): retry a transient upstream 5xx once, before anything stream…

    …s, so the run survives
    
    The 502 that killed the run in the screenshot was a transient upstream blip — the proxy
    in front of the model briefly couldn't reach a healthy backend. Reporting it cleanly (the
    previous commit) is good; recovering from it is better.
    
    New postChat() centralizes POST /chat/completions for all three OpenAI-shaped entry points
    (stream, complete, agent turn) and retries ONCE on 502/503/504. It is safe because it runs
    BEFORE any SSE line is read: on a transient status the response carries no model output, so
    nothing has streamed or been metered and a retry cannot duplicate output or double-bill the
    UI. Deliberately NOT retried: 429 (needs Retry-After), 500 (usually a real error), other
    4xx, and thrown network/abort errors. A 401 still throws straight through to the agent's
    existing token-refresh path.
    
    The backoff wakes early on abort so Stop stays instant. The agent surfaces a visible
    "upstream busy (502) — retrying…" status via a new onRetry hook (threaded through the
    router) rather than a mystery pause; chat/complete retry silently.
    
    providers.test.js +6 (recover / exhaust / no-retry-on-4xx / onRetry / clean-200 /
    abort-not-retried). Verified end-to-end with a stubbed fetch: an agent turn that gets a 502
    then a good SSE stream retries once and streams the text, onRetry carrying 502. Full gate:
    24 suites, 0 failures.
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    ndemianc and claude committed Jul 25, 2026
    Configuration menu
    Copy the full SHA
    a38092e View commit details
    Browse the repository at this point in the history
  6. docs(ai): declare label?/onRetry? in the provider-dispatch typedefs (PR

    #45 review)
    
    streamChat/complete/streamAgentTurn read o.label and o.onRetry, and pass onRetry as an
    object literal into the openaiCompat adapters — but the @PARAM typedefs for both didn't
    list them. Under // @ts-check that is 9 real diagnostics: TS2339 (property does not exist)
    on each o.label / o.onRetry read, plus TS2353 (excess property) on each adapter literal.
    
    Added label?:string and onRetry?:(info:{attempt,retries,status})=>void to the three
    router typedefs, and onRetry? to the three adapter typedefs (they already carried label?).
    The reviewer flagged label; onRetry has the same defect (added by the retry commit) and is
    fixed in the same pass.
    
    Verified with a real tsc 5.6 checkJs run — and not the vacuous kind: a synthetic probe
    first confirmed tsc actually enforces TS2339/TS2353 here (an earlier npx form was silently
    not running tsc at all), then stashing the fix gave BEFORE=9 label/onRetry errors, restoring
    it gave AFTER=0. JSDoc-only; runtime unchanged (full gate 24 suites, 28 provider tests).
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    ndemianc and claude committed Jul 25, 2026
    Configuration menu
    Copy the full SHA
    c0ca4ed View commit details
    Browse the repository at this point in the history
  7. Merge pull request #45 from levelcodeai/fix/gateway-error-label

    fix(ai): gateway error handling — relabel, sanitize the body, and retry transient 5xx
    ndemianc authored Jul 25, 2026
    Configuration menu
    Copy the full SHA
    a0850f4 View commit details
    Browse the repository at this point in the history
Loading