This round focused on upgrading the embedded copilot-proxy, restoring client compatibility, polishing the GUI workflow, and shipping v0.2.9.
- Upgraded embedded
copilot-proxyto upstreamv0.3.0 - Added a local compatibility fix for Anthropic
/v1/messagesrequests that omitmax_tokens - Submitted the upstream PR for the
max_tokenscompatibility fix - Added Claude model auto-sync to
~/.claude/settings.jsonwhen persistent Claude config already exists - Added a dedicated model refresh button on the main screen
- Added model refresh activity to Verbose logs
- Fixed
pushLog is not definedby promotingpushLog()to module scope - Updated the usage refresh button text/icon
- Updated the settings button icon
- Bumped the app version to
0.2.9 - Updated release notes and README
- Built, smoke-tested, tagged, pushed, and published
v0.2.9
- Rebuilt the frontend multiple times successfully with Vite
- Repeatedly launched the Electron app in local dev mode successfully
- Verified a real
/v1/messagesrequest withoutmax_tokensreturned200 - Verified the final
v0.2.9tag and GitHub release were created successfully
To allow v0.2.9 to ship before the upstream PR is merged, the git submodule source was temporarily switched from upstream to the fork:
- temporary submodule URL:
https://github.com/kylefu8/copilot-proxy.git - temporary pinned commit includes the compatibility fix
- Change
.gitmodulesback tohttps://github.com/Jer-y/copilot-proxy.git - Point the
copilot-proxysubmodule at the official upstream merged commit - Sync submodule config and verify fresh clone/submodule init still works
- GUI release:
v0.2.9 - Embedded proxy baseline: upstream
v0.3.0
This round focused on addressing upstream review feedback for the max_tokens compatibility PR, validating the exact Claude Code + gpt-5.4 proxy path locally, and updating the fork branch that backs the upstream PR.
The upstream author reviewed the PR and requested two concrete changes:
- narrow the schema change so it only accepts omitted
max_tokens, notmax_tokens: null - add a route-level regression test that verifies handler-side backfill behavior instead of only schema acceptance
- Tightened
AnthropicMessagesPayloadSchema.max_tokensfromnullable().optional()tooptional() - Tightened the corresponding Anthropic request type from
number | nullto optionalnumber - Kept handler-side
max_tokensbackfill when the field is missing - Added a route-level regression test for
/v1/messagesrequests that omitmax_tokens - Added a targeted regression test for
gpt-5.4via/v1/messages, verifying the request is routed to/responsesand thatmax_output_tokensis backfilled from model limits
- Ran
bun test tests/messages-error.test.ts - Ran
bun test tests/anthropic-request.test.ts tests/messages-error.test.ts - Launched the local GUI and tested the real Claude Code flow against the local proxy
- Confirmed the
gpt-5.4Claude Code scenario no longer failed due to missingmax_tokens
- Updated fork branch:
kylef/max-tokens-compat - Original compatibility fix commit:
e8428d5 - Review follow-up commit:
2bca804 - The upstream PR now includes the narrowed contract and the stronger regression coverage
After the upstream PR is merged:
- Change
.gitmodulesback tohttps://github.com/Jer-y/copilot-proxy.git - Point the
copilot-proxysubmodule at the upstream merged commit instead of the fork commit - Sync submodule config and verify fresh clone/submodule init still works
This round validated the published npm package @jer-y/copilot-proxy@0.3.1 through an isolated GUI-based test environment to determine whether the upstream release had already fixed the Claude Code + gpt-5.4 + missing max_tokens issue.
- Verified npm metadata for
@jer-y/copilot-proxy@0.3.1 - Downloaded and unpacked the published npm tarball
- Inspected the shipped
dist/main.jsbuild for Anthropic schema and routing behavior - Created an isolated GUI worktree and injected the published
0.3.1proxy build into itsbuild/directory - Launched the GUI from the isolated worktree and tested the real Claude Code flow
The published 0.3.1 package still fails the target scenario.
- Anthropic
/v1/messagesvalidation still requiresmax_tokens - The package still throws
Request validation failed: max_tokens: Invalid input: expected number, received undefined - Therefore the upstream
0.3.1release does not contain the local compatibility fix for missingmax_tokens
- Do not create a prerelease based on upstream
0.3.1 - Keep using the current fork-based fix in the GUI for now
- Wait for the upstream PR to be merged before switching the submodule back to upstream
Addressed the final review blocker on the upstream PR: an unused init parameter in the test mock that caused bun run lint to fail.
- Removed unused
init?: RequestInitparameter fromfetchMockintests/messages-error.test.ts - Pushed lint-fix commit
f84933cto the PR source branch - Posted Chinese PR comment requesting re-review
The upstream author (Jer-y) merged PR #2 into Jer-y/copilot-proxy main. The GUI repo submodule has been restored to point at the official upstream.
- PR:
Jer-y/copilot-proxy#2 - Merge commit:
b162b63f40a9f61a37c36cc6315b7a85820e2919 - Merged by: Jer-y
- Merged at: 2026-03-12T03:20:38Z
.gitmodulesURL changed back fromkylefu8/copilot-proxy.gittoJer-y/copilot-proxy.git- Submodule pointer updated from fork commit
e8428d5to upstream merge commitb162b63 - Ran
git submodule syncto propagate the URL change - Committed as
647f04e
All three items from the v0.2.9 follow-up list are now resolved:
- ✅
.gitmodulesrestored to upstream URL - ✅ Submodule pointed at official upstream merged commit
- ✅ Submodule config synced
This release integrates the upstream-merged compatibility fix, adds UX refinements, and fixes Windows window height issues.
- Upstream PR
Jer-y/copilot-proxy#2merged by Jer-y on 2026-03-12 .gitmodulesrestored to upstreamJer-y/copilot-proxy.git- Submodule now points at upstream merge commit
b162b63(ahead of upstreamv0.3.1)
- Auto-refresh usage data on first panel expand after app launch (subsequent expands require manual refresh)
- About page logo replaced from 🚀 emoji to the actual app icon
- Fixed excessive bottom whitespace on Windows:
resizeWindownow compensates for title bar / border frame dimensions - Platform-specific CSS padding: Windows gets
10px, macOS keeps30px - Applied to Main view, Settings page, and About page
- GUI release:
v0.3.0 - Embedded proxy: upstream
main@b162b63(post-v0.3.1)
Hotfix for macOS window height regression introduced in v0.3.0 and CI workflow fixes.
- The
resizeWindowframe compensation added for Windows also affected macOS, making the window taller than intended - Fixed by skipping frame compensation on macOS (
process.platform === 'darwin'), whereuseContentSize: truealready handles it correctly
create-releasejob now checks if the release already exists before creating- Replaced
softprops/action-gh-releaseupload steps withgh release upload --clobberto avoid "Finalizing release" failures
- GUI release:
v0.3.1 - Embedded proxy: upstream
main@b162b63(post-v0.3.1)
New feature: conversation recording with a built-in conversation viewer. Records full request/response content flowing through the proxy to local JSON files, with session tracking, client identification, and a dedicated viewer window.
- New
conversation-log.tsutility in proxy emits[CONV]structured lines to stdout - Hooks in all 3 route handlers: chat-completions, messages, responses
- Supports both non-streaming and streaming (assembled after stream ends)
- Client detection: Claude Code, Cursor, Continue, Cline, generic OpenAI/Anthropic
- Session tracking by (clientType + model) with 15-min timeout heuristic
- Electron intercepts
[CONV]lines, stores per-session JSON files in{userData}/conversations/ - Controlled by
conversationLogconfig toggle (default off, requires service restart) COPILOT_PROXY_CONVERSATION_LOG=1env var passed to proxy child process
- Dedicated Electron window with sidebar (sessions) + main area (messages)
- Sessions grouped by date (Today / Yesterday / date)
- Content search with debounce, text highlighting, and auto-scroll to first match
- Multi-select sessions with checkbox + batch delete
- Clear all button
- Full i18n (Chinese/English) with real-time language switching
- Theme sync: follows app theme changes in real-time
- Real-time: new conversations pushed to open viewer via IPC
- Header button order: theme, lang, conversations, logs, settings, about
- Recording toggle moved to Settings page (Service Config section)
- Settings checkbox alignment fix
- GUI release:
v0.3.2 - Embedded proxy: upstream
main@b162b63(post-v0.3.1)
Refactored conversation recording from handler-level hooks to a single Hono middleware. This eliminates upstream merge conflicts when handler code changes, reducing fork maintenance from 4 modified files to 2 (1 new file + 2 lines in server.ts).
- Replaced
conversation-log.ts+ 3 handler hooks withconversation-middleware.ts - Middleware intercepts requests/responses at the Hono layer, before/after handlers
- Non-streaming: clones response and reads JSON
- Streaming: uses
ReadableStream.tee()to observe SSE chunks without affecting client delivery - Only
server.tsmodified (+2 lines: import + use), zero handler changes
- v0.3.2 handler hooks conflicted with upstream updates to the same files
- Middleware approach means upstream can freely change handlers without affecting our conversation recording
- Evaluated and rejected log-parsing approach (upstream logs truncate payloads to 400 chars, no full content)
- GUI release:
v0.3.3 - Embedded proxy: fork
conv-middlewarebranch based on upstreamb162b63
Upgraded embedded copilot-proxy from upstream v0.3.1 base (b162b63) to upstream v0.4.1 (29ab862). Conversation recording middleware cherry-picked cleanly onto the new base with zero conflicts.
8b6b998feat: add upstream HTTP resilience controls with Copilot timeout defaults and SSE keepalive55c1bb6fix: improve Anthropic Messages protocol compatibilitycb71c60fix: tighten Anthropic protocol compat and close review follow-upse97d5f8fix: propagate JSONResponseError in count_tokens instead of swallowing it
- Cherry-picked
conversation-middleware.ts+server.ts2 lines fromconv-middlewarebranch onto v0.4.1 base - Zero conflicts — server.ts structure unchanged between v0.3.1 and v0.4.1
- Fork branch:
conv-middleware-v041(614e530)
- GUI release:
v0.3.4 - Embedded proxy: fork
conv-middleware-v041based on upstream v0.4.1 (29ab862)
Fixed two platform-specific bugs on macOS: Claude Code CLI detection failure caused by nvm/npm_config_prefix conflict, and missing default-model conversations in the conversation viewer due to stdout line splitting across pipe buffer boundaries.
- Root cause: Electron inherits
npm_config_prefixfrom npm when launched in dev mode; nvm refuses to initialize when this variable is set, so the interactive login shell fails to add nvm-managed paths to PATH - Symptom:
claude --versionexits with code 127, GUI shows "Claude Code not installed" - Fix: strip
npm_config_prefixfrom the environment passed to the detection shell spawn - Also affects packaged builds when
npm_config_prefixis set system-wide
- Root cause:
stdout.on('data')chunks are not guaranteed to align with line boundaries; macOS pipe buffer (~16KB) splits large[CONV]JSON lines across multiple chunks - Symptom: default-model conversations (longer responses → larger JSON) fail
JSON.parse()because the line is split; fast-model conversations (shorter) fit in one chunk and work fine - Fix: introduced
stdoutLineBufferto accumulate partial lines across chunks, splitting only on complete\nboundaries - Also flushes remaining buffer on process exit to avoid losing the last entry
- Windows unaffected: pipe buffering behavior differs, but the fix is safe on all platforms
- GUI release:
v0.3.5 - Embedded proxy: fork
conv-middleware-v041based on upstream v0.4.1 (29ab862)
New feature: added a --dangerously-skip-permissions option for launching Claude Code. This allows users to opt-in to skipping all permission confirmation dialogs in Claude Code, with two-stage safety confirmation (settings toggle + launch-time dialog). Also upgraded embedded proxy to upstream v0.4.2.
- Upgraded embedded copilot-proxy from v0.4.1 base (614e530) to v0.4.2 (a9ac227)
- Upstream
e3f6538fix: Claude Code stalls on Anthropic messages - Conversation recording middleware cherry-picked onto v0.4.2 base with zero conflicts
- New
skipPermissionsconfig key (defaultfalse) inconfig-store.js - Settings page: red-highlighted checkbox to enable skip-permissions mode; toggling ON opens a danger confirmation dialog, toggling OFF is immediate
- Main view: when
skipPermissionsis enabled, clicking "Launch Claude Code" first shows a second danger confirmation dialog before proceeding - Shared
DangerConfirmDialogcomponent used by both settings and main view - Full i18n: Chinese and English translations for all danger dialog texts
- Red-themed danger dialog CSS (
.danger-dialog,.danger-btn-confirm,.checkbox-danger) usingvar(--red)for automatic theme adaptation service-manager.js:launchClaudeCodenow acceptsoptions.skipPermissionsand passes it via IPCelectron/main.cjs: appends--dangerously-skip-permissionsto theclaudecommand on both Windows (PowerShell) and macOS (Terminal.app) when the flag is set
src/core/config-store.js— addedskipPermissions: falsetodefaultConfigsrc/core/i18n.jsx— added 9 new zh/en translation keys for danger dialogssrc/features/main/DangerConfirmDialog.jsx— new shared dialog componentsrc/features/settings/SettingsPage.jsx— added checkbox + on-enable confirmation dialogsrc/features/main/MainView.jsx— added launch-time confirmation dialogsrc/core/service-manager.js— addedskipPermissionsparameter passthroughelectron/main.cjs— added--dangerously-skip-permissionsflag to claude commandsrc/styles.css— added danger dialog styles
- GUI release:
v0.3.6 - Embedded proxy: fork
conv-middleware-v042based on upstream v0.4.2