main
20
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9e665491ec |
context: Tuned for you — each agent's settings worked out from the user's own calls, for the fewest tokens, put in on a click and undone on another
The Context tab now replays the period's calls of each agent against the
settings that decide what they cost, and shows, per agent and per model,
the value that would have used the fewest tokens for how this user works:
Claude Code's auto-compact window per model (modelSettings.<model>.
autoCompactWindow), its main and subagent prompt cache lifetimes
(promptCacheTtl, subagentPromptCacheTtl: 5m or 1h), and Codex's
model_auto_compact_token_limit. Each row says where the value comes from
now (the agent's default, the user's own setting, one magpie set, or a
variable that comes first and locks it), why (how fast conversations grow,
what a compaction leaves, how long the user pauses), the cost curve, and
the saving. Nothing is written until "Use …" is clicked; what was there is
stashed and Undo puts it back, unless the user changed it since. A window
the user set past the model's own is shown capped, as Claude Code caps it
(min(setting, model window)), so no saving is claimed that wouldn't happen.
Advice under a 3% saving is "already the leanest".
On the owner's 7 days (88K Claude Code calls, 956 Codex): opus keeps 200K
(their 500K is capped to it), fable 5.1 200K → 160K saves 5% (2.56M
tokens), both cache lifetimes and Codex's 272K are already the leanest.
Run: go vet ./... and go test ./... pass (internal/tune, internal/agent
TestTune*: user-set values kept, env locks, undo after a user edit, TOML
key order). context-tune.test.cjs passes in Chromium and WebKit, en/zh/
zh-TW/ja/de, at 360 and 1100px (22); context-window, context-scroll-end
pass. Full GUI suite: library-servers-bulk and market-have failed once
under load and pass alone; market-have fails on origin/main
|
||
|
|
c9b8263378 |
sessions, gateway: Sessions lists gateway sessions, and can keep their text on this computer when turned on (#1355, mu-zi-lee)
What changed: the Sessions page lists sessions seen only through the gateway (from the usage ledger, read-only, a native session of the same id wins), and shows in gateway mode. A Sessions switch, off by default and confirmed before it turns on, records each gateway exchange's text under the config dir (scrubbed, at most 7 days and 256 MiB, cleaned hourly). Settings sync and restore can't turn it on; POST /api/sessions/recording turns it on or off and can clear what was kept. Why: users of magpie as a gateway (gateway mode, LAN clients) had no way to see their conversations; the owner chose this design on the PR. Squashed from PR head 6a343ba1 onto origin/main. Conflicts: gui-shell.md (kept main's placeMenu text, took the PR's Sessions in gateway mode) and settings_keep_test.go (main's fields plus GatewayConversations). Run: go build ./..., go vet on gateway, gui, sessions, settings, usage; go test -race -timeout 900s on those five packages: all ok. |
||
|
|
b4bdd59f72 |
gui: a long app menu stays in the window and scrolls inside itself, so the last removed group can be brought back (#1437, Hipple)
With 28 found groups removed, Routing's "28 found groups removed" menu ran
off the bottom of a ~717px WebView2 window and couldn't be scrolled.
openRowMenu had no height cap (max-height: none, and .pop clips with
overflow: hidden), it only flipped up when the whole menu fit above, and any
scroll, even one inside the menu, closed it.
What changed:
- placeMenu (app.js) places every app menu: under its anchor, over it when
the window runs out below, and one that fits neither way takes the larger
room with its height held to it. openProtoMenu's placement moved into it
unchanged; openRowMenu (agent rows, model chips, Routing's removed groups
and its other row menus) and openSessCombo (the Sessions/Usage filters,
which could run off the bottom the same way) now use it too.
- .row-menu scrolls inside itself (overflow-y: auto, overscroll-behavior:
contain), and openRowMenu closes only on a scroll outside the menu, as
openProtoMenu and openSessCombo already did.
- docs/subsystems/gui-shell.md names placeMenu.
Verified:
- New removed-groups-menu-scroll.test.cjs: 30 removed groups, 1100x700 and
560x700, en and zh, Chromium and WebKit, 8/8 pass. It wheels the page to
the line, clicks it where it is, checks the menu is inside the window and
scrolls, wheels the menu until the last entry shows inside it, clicks it
(posts groups/show auto-gone-30), and checks the page never scrolled and
has no sideways scroll.
- Broken by hand three ways, each red in every case: the old app.js/app.css
("the menu stays in the window": bottom 1494 of 700), the old
scroll-closes-menu handler ("scrolling the menu doesn't close it"), and no
overflow-y on .row-menu ("the last entry is scrolled into view inside the
menu").
- The 63 GUI test files that open app menus or guard click-scroll, both
engines: 595 pass, 1 fail: search-api.test.cjs webkit zh, at page load
(the row is redrawn between waitFor and scrollIntoViewIfNeeded) before any
menu opens; it passes 5/5 alone. Not run: the rest of the GUI suite, and
gui-zh-tw/ja/de (no new strings).
- gofmt (no Go changed), go vet ./internal/gui (darwin, GOOS=windows),
GOOS=linux and GOOS=windows go vet -tags nogui ./internal/gui, and
go test -tags nogui ./... under a sandbox HOME: all pass.
- Not tried in a real Windows WebView2 window.
|
||
|
|
3cd0b5f78d |
gui: lightweight mode no longer lets go of a main window that is open under another app's, so Command-Tab back to magpie finds it there (#1381, ttmouse)
Cause: lightweight mode (#580) let go of the main window once two of its 30 s looks found it "not shown", and it asked Wails' IsVisible, which on the Mac is the window's occlusion state. A window the user had Command-Tabbed away from, covered by the other app's window, counted as closed: 30-60 s later its webview was dropped and the window closed, and Command-Tab back to magpie found a blank shell or no window at all. Hidden with magpie (Command-H) it went the same way, since hiding orders every window out. Change: windowUp says whether a window is up as the user sees it: ordered in on any Space, covered or not, minimised, or open as magpie was hidden (watchHide records those on NSApplicationWillHideNotification). Only a window magpie closed itself is down. lighten (through lightShown) and mainShown use it, so the Dock-while-open setting and a restart to update also keep a covered window as open. Elsewhere windowUp is IsVisible as before (visible there covers covered and minimised). Run: - Reproduced with a sandbox build of origin/main (own HOME and CFFIXED_USER_HOME, port 3481, dock+lightweight on): with the open window covered by a full-screen window of a helper process for 70 s the log said "the main window's webview let go" and the window was a blank white shell. With this change, the same run let go only the closed panel and the window kept its page (screenshot of the window). - Activation itself was checked by handing activation from the helper to magpie (NSRunningApplication activateFromApplication): with the window there it came forward. A real Command-Tab keystroke was not sent. - New TestCoveredWindowStaysUp (AppKit, own process): open, covered by another window (until IsVisible says false), hidden with the app, minimised -> up; closed by magpie, also with the app hidden -> down. With windowUp put back to IsVisible it fails: "open: the window counts as up=false, want true"; without the hidden clause: "hidden with magpie: the window counts as up=false, want true". Passes -count=10. - gofmt -l; go vet ./internal/gui; GOOS=linux go vet -tags nogui and GOOS=windows go vet (with and without nogui) ./internal/gui; go build, GOOS=linux go build -tags nogui, GOOS=windows go build; go test ./internal/gui and go test -tags nogui ./internal/gui under a temp HOME: ok. |
||
|
|
2018882e47 |
davsync, gui: a server file that isn't a backup is said as what it is, and can be replaced by this computer's setup (JasonLeeForOnly on Discord)
JasonLeeForOnly's WebDAV sync failed with only "not a magpie backup" for
several versions, and nothing on the page got past it. A WebDAV GET of the
backup can come back as a body that isn't the file in several ways; each is
now reproduced with an httptest server that answers the way the real one
does:
Unpacked (WebDAV and S3): gzip with or without Content-Encoding (a proxy
that drops the header), x-gzip, zstd with or without the header, deflate
(zlib or raw), and a header that says gzip over a plain body. Bodies are
told by magic number; a backup is JSON, so either magic is never the file.
Brotli (br) can't be unpacked and is said as itself, with what to turn off.
Said, with no upload offered: an HTML page answered with 200 (Nextcloud
login after a redirect, Cloudflare Access, an AList/OpenList web app, an
rclone directory listing, a captive portal), with its <title> and the
host/path a redirect ended at (query, fragment and user dropped), and
where the WebDAV address is for 坚果云 and Nextcloud; an XML answer, by its
root element.
Said, with Upload as the way out: an empty (0-byte) file, a backup cut
short or damaged (the automatic rebuild is unchanged and still goes first
when its rules allow), another app's file ("format": "…"), other JSON,
and any other file by its content type. Messages carry the size, kind and a
page title only, never the file's contents.
backup.Open now tells ErrNotBackup (doesn't begin like a backup) from
ErrCorrupt (begins like one, cut short). The status carries the kind as
serverFile; Settings › Sync and backup says it in the reader's language,
wraps it whole, and shows "Upload this computer's setup" only when the file
may be replaced. davsync.Upload (POST /api/davsync/upload, `magpie webdav
upload`, `magpie s3 upload`) asks first in the GUI, re-reads the file,
refuses a backup this computer opens, one sealed with another passphrase,
a newer magpie's, a page and an XML answer, keeps the server's copy in the
sync folder (0600, newest 5) and writes nothing if that fails, then writes
with If-Match on the version read. New strings in en, zh, zh-TW, ja, de.
Verified: internal/davsync/not_backup_test.go (TestReadCompressedBackup,
TestReadBrotliSaid, TestServerAnswerSaid, TestCutBackupSaidAndUploaded,
TestS3ReadCompressedObject; Upload-only parts stripped to compile) fails
on
|
||
|
|
55544f09f6 |
routing, gui: a provider's accounts and a group in the group fold on the Routing page, long ones folded at first, what the reader picks kept (Aiirobyte on Discord)
Aiirobyte: a routing group of many accounts took so much of the page that editing the groups below it was a long scroll. The stage folded only runs of three or more API keys (#1319). Now: - Three or more accounts of one provider side by side for one model fold into one row the way keys do: the count, the lit one and what it does, how many are available and resting. A request to a folded account flies to the fold. - A group in the group's heading folds from a click, Enter or Space (it is a button now, with a chevron). Folded, it says "{n} on" and what its seats do together; requests under it fly to the heading and a failure tags it. - Accounts and keys sums a provider's accounts up in one row too. - Keys start folded as before. Accounts and group headings start open under six, folded from six. What the reader opens is kept in magpie.routingKeysOpen as before, what they fold in the new magpie.routingFolded, so both directions survive a reload. - Redraws go through steady(), so a click keeps the page where it is. - Strings in en, zh, zh-TW, ja, de. Display only: the gateway's order and choice don't change. routing-account-order now opens the relay's key fold by :not(.open), since the account folds there start open. Run: new internal/gui/tests/routing-group-fold.test.cjs (defaults, click and Enter in place with the page not moving, kept across reloads both ways, a live request to a folded group heading with its tag, Accounts and keys folds, 420px fit) in Chromium and WebKit, en/zh/zh-TW/ja/de, 40/40. On origin/main's assets it fails (no account fold, heading not foldable). All routing-* tests, panel-routing, click-scroll, gui-ja, gui-de, gui-zh-tw and i18n-keys: 255/255 in Chromium and 255/255 in WebKit. Not tried in the real window with a live gateway. |
||
|
|
8db24fd62f |
gui: Routing folds three or more of a provider's keys for one model into one row that shows the count and their state, and opens in place to each key (#1319, tkhs101)
53 agnes-3.0-flash keys were 53 near-identical stage rows and 53 rows under Accounts and keys. Now three or more keys of one provider standing together for one model (same fixed effort, fallback and group-in-group heading) fold into one stage row: "Agnes 53 keys agnes-3.0-flash", then the lit key and what it does, "51 available · 2 resting". A request on a folded key flies to the fold; a key failing and the next answering show there (its 429 tag too). A click, Enter or Space opens it in place: each key keeps its own row, state and wire, drawn from the fold. Accounts and keys folds the provider's keys into one row with their summed tally and models, and opens the same way. Open folds are kept per reader in localStorage magpie.routingKeysOpen. Two keys stay two rows; one key is as before. Display only: the gateway's order and choice don't change. New strings in zh, zh-TW, ja and de. docs/subsystems/gui-shell.md says how. routing-account-order's relay has three keys, so it now opens their fold to read their order. Run: routing-keys-fold.test.cjs (32: folded, open/persist/Enter, live updates folded and open, Accounts and keys, 440px; Chromium and WebKit; en, zh, ja, de) — fails on main (no fold). All routing-*.test.cjs, panel-routing, click-scroll, fold-show-grip, gui-ja, gui-de, gui-zh-tw, i18n-keys: 409 pass. Every other test that opens Routing (29 files, 152 tests) passes but purpose-filter's WebKit "returning focus does not scroll the page", which fails the same alone on origin/main (off by 1px). go vet -tags nogui ./internal/gui (darwin, GOOS=linux, GOOS=windows). |
||
|
|
d226f87e4c |
gui: on KDE Plasma's Wayland session the quick panel has no KWin title bar or frame, as the main window has none (#1283)
GTK 3, which the Linux builds link, announces server-side decorations over org_kde_kwin_server_decoration for every window that isn't client-decorated, an undecorated (frameless) one too (gtkwindow.c realize: announce_ssd), and KWin then draws its title bar on it. The main window escapes it through plainTitlebar's hidden titlebar widget. The panel now announces client-side decorations after each realize (ownFrame: gdk_wayland_window_announce_csd), at start and when lightweight mode makes it again. GTK 4 already asks for none, X11 and compositors without the protocol never see it. Run: on real KWin 6.3.6 Wayland (kwin_wayland --virtual with Breeze, Debian trixie arm64 container, -tags gtk3 test binary): WAYLAND_DEBUG shows request_mode(1) and KWin answers mode(1); a KWin script reads the panel's frame 440x520 = its client 440x520. With ownFrame skipped: request_mode(2), frame 442x557 over client 440x520 (KWin's title bar and borders, the reporter's picture). go vet -tags gtk3 ./internal/gui ok there; macOS go vet/go build ok; GOOS=linux/windows go vet -tags nogui ./internal/gui ok. Not tried: the reporter's Manjaro Plasma session, a GTK 4 build, GNOME/Hyprland (no KDE protocol there, so unchanged). |
||
|
|
23cd1bb609 |
gui: closing the quick panel from its title bar (or Alt+F4, a window manager's close key) hides it as Escape does, so the tray icon opens it again; it was closed for good and the icon did nothing until a restart (#1283, KDE Wayland)
The system's close reaches Wails as WindowClosing, which destroyed the panel while h.panel and the tray still held it. makePanel now hooks WindowClosing: the panel cancels and hides; one lightweight mode let go (h.panel no longer it) still closes. Run: TestPanelCloseHidesIt (AppKit, new) passes; with the hook's check forced to let the close through it fails "panel close: the panel closed for good; the tray icon can't open it again". On real KWin 6.3.6 Wayland (kwin_wayland --virtual, Debian trixie container, GTK 3 build) a KWin script closeWindow() on the panel (what its title bar X does): with the hook alive=true and a second Show is visible; without it alive=false and Show shows nothing. go test ./internal/gui ok (darwin, GUI tag); go vet, go build ok; GOOS=linux/windows go vet -tags nogui ./internal/gui ok, GOOS=windows go vet ./internal/gui ok. go test -tags nogui ./...: all ok but internal/agent (11m timeout) and internal/plugin TestHostRunsAsMagpieBun under load average ~110; neither imports internal/gui, and TestHostRunsAsMagpieBun passes alone. Not tried: the reporter's own Manjaro Plasma session; Windows' Alt+F4 on the box. |
||
|
|
f00ed2901c |
routing: filter by several purposes with checkboxes (#1247)
* routing: filter by several purposes with checkboxes Ticking a purpose immediately shows the union of the selected purposes while keeping the menu open. All purposes, Clear filter and removing the last selection restore every purpose. Counts, the story and history follow the same list. Live menus ignore renderer-induced scrolling while deliberate outside scrolling still dismisses them. Update the GUI shell reference and browser coverage for multi-purpose counts, keyboard toggling, history, aliases and narrow windows in five languages. Verified 115 isolated Playwright checks in Chromium and WebKit, JavaScript syntax and git diff --check. The new checkbox case fails against the old assets with 0 checkbox choices instead of 5; restoring the old menu scroll handler separately detaches the menu during selection in WebKit. * routing: All purposes returns keyboard focus to its button Address the keyboard-focus regression reported in PR #1247. Choosing All purposes closes its menu and focuses the purpose button without scrolling. Unticking the last purpose keeps the live menu and its checkbox focused. The expanded checkbox test fails without the focus restoration in Chromium and WebKit: All purposes returns keyboard focus to the purpose button (false !== true). With the fix, 162 isolated Playwright checks pass across both engines, including five locales, narrow widths, purpose state, history, request/session grouping, Usage and scroll/menu regressions. JavaScript syntax and git diff --check pass. The full GUI/Go suites and the packaged desktop app were not run. |
||
|
|
586f2bce8f |
context: magpie inspects the context window of every request, session and agent
The gateway reads each request's prompt into its parts (system prompt, tools and MCP servers, memory, files, tool results, chat), measured against the model's window and calibrated to the tokens the vendor counted. Routing shows a request's window as a card: a 400-cell grid by part, a hover naming what is largest in a cell, and the contents by part. The Usage page's Context tab scores each agent out of 100 (cache reuse, how lean it starts, how fast it grows, how reliably it answers), tags it (lean, cache-friendly, mcp-heavy, compacts, near-full…), and draws each session's growth with its latest request's card. Older Safari (15) gets media-query and solid-colour fallbacks for the card's container queries and color-mix. |
||
|
|
aff4f9f22c |
gui, tray, alerts, settings: magpie speaks Traditional Chinese (繁體中文) with Taiwan wording, picked on its own for a zh-TW, zh-HK or zh-Hant system
Settings → Language offers 繁體中文 beside 简体中文. On System, a browser or OS locale of zh-TW, zh-HK, zh-MO or zh-Hant (zh_TW.UTF-8 too) shows zh-TW; zh-CN, zh-SG and zh-Hans-HK keep Simplified. The tray menu and quota alerts follow the same choice. Release notes fall back to Simplified. The zh-TW strings are generated from the zh strings with opencc (cn→twp), then corrected to Taiwan wording: 設定, 檔案, 帳號, 伺服器, 預設, 閘道, 連接埠, 參數, 選單, 透過, 取得, 用戶端, 存取, 終端機, 「」 quotes. A quota window is 時段 and a context window stays 上下文視窗. Number units use 萬/億, and #unitsRow is shown for zh-TW. Verified: - New gui-zh-tw.test.cjs, in Chromium and WebKit: - key parity, placeholders and tags against zh; - no Simplified characters; - the Taiwan words; - locale detection for each system tag; - <html lang>, nav labels, fmtN units, the picker; - Settings Language at 1000px and 440px. With the sysLocale zh-TW line removed, it fails. On the base assets, all 3 fail. - gui-ja, gui-de and i18n-keys pass. - go vet, and go test -tags nogui for ./internal/gui and ./internal/settings, pass. That includes the new zh-TW cases in TestTrayLang / TestTrayLabels / quota_alert_test, which fail without the zh-TW branches. |
||
|
|
89b3a20f5d |
gui tests: a test run leaves no gui.test folder in the real ~/Library/WebKit or ~/Library/Caches (waitingsnow) (#1047)
TestTrayCellClickReleasedPanel shows its panel in the test binary run
again as a child. The package's TestMain gives the tests testenv's HOME,
but WebKit takes the home from the account's record, so every run wrote
the child's WebKit data to ~/Library/WebKit/gui.test and its caches to
~/Library/Caches/gui.test in the real home.
The child now starts through runAppKit (appkit_darwin_test.go). It sets
CFFIXED_USER_HOME, which CoreFoundation reads before the account's
record, to a temporary folder, so WebKit's data and caches go there. It
runs the binary under a name of its own, through a hard link: WebKit
names its folders after the process, whose name comes from the file, not
argv[0]. The test fails when a folder of that name is left in the real
~/Library/WebKit or ~/Library/Caches. The empty folders WebKit makes
under the name in the account's temporary folder (NSTemporaryDirectory,
which TMPDIR doesn't move) are removed. Wails v3 beta.24 offers no
non-persistent WKWebsiteDataStore: its windowNew makes a plain
WKWebViewConfiguration, which uses WebKit's default store.
CFFIXED_USER_HOME doesn't move the account's settings: cfprefsd still
serves the global domain and com.apple.universalaccess, where dark mode
and Increase Contrast are kept. A probe window read the same appearance,
Increase Contrast, Reduce Transparency, layout direction, languages and
non-default values (AppleShowScrollBars, AppleReduceDesktopTinting, the
zoom factor) with and without it, on macOS 26.7.1. Nothing is written
to the temporary home after the child exits.
Without CFFIXED_USER_HOME the test fails:
trayusage_panel_darwin_test.go:20: the windows' process left /Users/wei/Library/WebKit/gui.test-1791307161567260000 in the account's real home
trayusage_panel_darwin_test.go:20: the windows' process left /Users/wei/Library/Caches/gui.test-1791307161567260000 in the account's real home
--- FAIL: TestTrayCellClickReleasedPanel (0.45s)
With it, it passes, and nothing new appears in the real ~/Library or in
the temporary folder.
PR #1042's TestMainWindowCorners and TestMainWindowRightToLeft, moved
onto runAppKit at its head f89991b1, pass and print the same with and
without CFFIXED_USER_HOME: corners 16.00pt (plain 16.00, toolbar
26.00), lights [[26 26] [49 26] [72 26]], title bar 66pt, a sheet 66pt
below the top, right to left lights [[874 26] [851 26] [828 26]].
Without it, both fail the same way.
go vet ./..., go build ./..., GOOS=linux go build -tags nogui ./...,
GOOS=windows go build ./..., go test -tags nogui ./..., go test
-count=1 ./internal/gui/... and gofmt -l pass under a temp HOME with
Go's caches pinned. docs/subsystems/gui-shell.md says it. Tests only.
|
||
|
|
29f4909262 |
fonts: list upright styles before slanted faces at the same weight (#1030)
Follow up on the Menlo style ordering noted in PR #1007. Compare normal, italic and oblique explicitly after weight, retaining the existing width and name tie-breakers. The Menlo regression fails before the change with Italic, Regular, Bold Italic, Bold, and passes with Regular, Italic, Bold, Bold Italic. Group/tie-break tests, fresh Windows native discovery, focused nogui GUI/font tests, go vet and Windows/Linux nogui builds pass. |
||
|
|
bd33e575f1 |
gui: let users choose installed interface and code fonts (#1007)
* gui: choose installed interface and code fonts and styles Discover installed styles through DirectWrite, CoreText and Fontconfig. Keep choices per computer, apply them before paint and notify both desktop webviews after saving; defaults retain platform and Omarchy fallbacks. Verified seven focused Go tests, including real Windows discovery (90 families, 276 styles), 14 font browser cases in Chromium/WebKit, 68 settings/zoom/Omarchy/web cases, go vet, Windows amd64/arm64 and Linux nogui builds. Against the original assets, the new UI test fails with Settings must offer an interface font picker (0 != 1). Full Windows suites have separately reproduced upstream failures; macOS/Linux native discovery is covered by the added CI step. * gui: retain bundled Mac fonts and variable style precision Only filter an undownloaded CoreText face when it is explicitly downloadable; bundled fonts are installed without being downloaded. Use resolved font names when descriptors omit them. Preserve fractional weights and nonnegative CSS widths for named variable styles. * gui: restore the authored font cascade when returning to defaults Apply family-only trait overrides only while a custom face is active. The browser regression catches code under a bold parent becoming 700 instead of its original 400. Keep the compatibility shim first, and apply boot fonts before visible content. * gui: keep font picker review separate from CI integration Leave the native test sources and manual verification command with the feature. Move the added workflow step to a follow-up so the font picker can take the normal review path requested on PR #1007. |
||
|
|
490d2ea362 | gui: the tray panel's Allowances tab hides subscriptions and moves them, from an Arrange at its foot (H20 on Discord: "菜单栏的详情页能不能选择某些不显示,有点额度并不想看到或者可以调整顺序,目前的还不行") — the panel's tab already followed the Usage page's order (usageOrder, byUsageOrder), but it could be set only by dragging a card's logo on the window's Usage page, which nothing in the panel said, and there was no way to leave a subscription out of the panel at all. The tab's foot now has Arrange, and "{n} hidden" beside it when some are: Arrange lists a row a subscription (balances too) in the shared order, its logo the handle (a drag, or Alt+arrows; the grip by it on hover only, as on the Usage page) and a Hide/Show pill, under a note that hiding is the panel's only and the order is the Usage page's too; Done draws the cards again. What's hidden is kept in magpie's settings (settings.PanelUsageHidden, panelUsageHidden), not the browser: routing, caps, the Usage page and the menu bar's cells still have it, and a menu bar cell for a hidden subscription still opens its card (panelPeek) until the panel is put away or the tab left. POST /api/usage/arrange takes order and panelHidden and changes only the one it is sent (both were whole-order before; an order alone still works), and the Settings save keeps panelUsageHidden as it does usageOrder. Saves draw at once and are put back with the error if they fail; no click moves the page (the view's scroll is kept across the redraw); no native select, no left-border stripe. Which allowances the menu bar shows beside its icon stays Settings' pick (trayUsages). New t() strings have zh, ja and de. TestUsageArrangePanelHidden (each field set and cleared on its own, a Settings save between) passes -race -count=20, TestSettingsSaveKeepsWhatItDoesNotSend's fixture names the field. panel-arrange.test.cjs (440px: the hidden card left out and counted, Arrange keeping the reader's scroll, the rows and note, the hover-only grip, no stripe, no sideways overflow, Show/Hide posting panelHidden without a scroll and a failed save put back, Alt+arrow and a drag posting the order, Done's cards in it, a menu bar cell opening a hidden card until the panel hides, the Usage page keeping the hidden card) passes on Chromium and WebKit in en, zh, ja and de; click-scroll, gui-ja, gui-de, i18n-keys, panel-fold, panel-usage, quota-*, routing-quota-left, tray-cell-click, tray-inuse, tray-logos, tray-usages, usage-accounts(-fold), usage-arrange, usage-fold, usage-quota-head, usage-card-refresh, usage-stale-answer, usage-remote-cards, api-key-usage, claude-usage-asked and usage-checkin pass on both. go test -tags nogui ./internal/... under a temp HOME, go vet, gofmt -l, linux (nogui) and windows builds pass. Not tried in the real tray panel on a Mac. docs/reference.md and docs/subsystems/gui-shell.md say it. | ||
|
|
f109b270c0 |
gui: the main window opens as it was last left — maximised again if it was, at its last size otherwise (#995)
On a MacBook the window had last been zoomed. magpie skipped a maximised window when it saved the size, so it reopened at an older, nearly full size: 1712×1083 at (8,34) on a 1728×1084 work area, neither full nor the size it was given nor the default. settings.WindowMaximised (this computer's own, KeepOwn) now records whether the window was maximised when it settled; Window stays the size it restores to (settle). A window not shown yet, let go, full screen or minimised, or on Linux hidden, records nothing. Reopened maximised: on the Mac and Windows placeMain maximises the made window just before its first Show (on Windows once its page has come); Wails' StartState is undone by the Mac's centring and shows a Windows window before its page. The least size Maximise drops is put back. On Linux makeMain sets StartState, since GTK can't be asked about a window not mapped yet. A size kept on a larger screen: Windows fits the window to the work area and centres it, title bar in reach, and keeps the larger size for the larger screen (fitted); the Mac fits and zooms it itself, and magpie doesn't zoom it again, so it can still be restored. TestSettle fails with upstream's rule (5 of 9 cases); TestOpenSize, TestFitRoom, TestWindowMaximisedKeptAndOwn; the Mac's real build under a sandbox HOME, 11 cases. |
||
|
|
db55bc8b7a |
gui: reject unknown Codex auto-review models from known providers (#938) (#943)
Resolve deliberately accepts arbitrary model names under an existing provider. The auto-review setting consequently accepted fake/missing and fake/, replacing a valid reviewer with one that fails when Codex requests approval. Validate against the served catalog at the settings endpoint. Keep model and group choices, unlisted providers, whitespace trimming and clearing. Rejected values leave the saved reviewer and model-list tag unchanged. TestCodexAutoReviewSetting fails against the upstream API with fake/missing and fake/ returning 200, and passes with the fix. Focused auto-review tests, go vet ./..., the Windows build and Linux nogui build pass. The full Windows suite has failures also reproduced with upstream production code; details are recorded in the PR. |
||
|
|
2cc663d0a2 |
gui: protect unsaved edits and confirm destructive actions (#820)
* gui: edited forms ask before they are discarded, removals ask before they take effect, and the header keeps its first layout — Cancel, Escape, the backdrop and a page change could throw away a provider's draft, and several account, key, plugin and library removals took effect at once. Modified provider, settings, library and routing forms now ask before discarding; unmodified forms still close without asking, and refresh or closing the browser tab uses its leave confirmation. Removal and discard confirmations are in-app dialogs over the intact editor, centered, with Cancel focused first, Tab kept inside, Escape canceling and focus returned afterwards; destructive buttons have readable foregrounds in light and dark themes. Text and connection settings have Save/Cancel rather than saving on blur; simple switches still save at once. Editors associate labels and help with fields, make the background inert while open and keep focus through redraws; navigation keeps browser back/forward history and its current-page state, errors remain until dismissed or replaced, and focus and validation can scroll into view. Mobile settings tabs have larger targets, fields use 16px text and page zoom stays available. layout.js applies mode and platform before the header paints, theme.js applies the saved text size before styles, and mode-specific window controls stay hidden while app.js downloads. zh/ja/de strings added. routing-shape's global .rt-day selector selected the hidden By session button on WebKit; its history click now stays in .rt-days. ux-safety covers unchanged and modified closes, canceled and confirmed removals, Escape, backdrop, modal focus, light/dark centering and button contrast, explicit saves, browser history and sync-form discard. Rebased onto upstream/main |
||
|
|
a5df344e43 |
docs: code-standards gets the acceptance criteria a change must show before merge or release and the PR review patterns, and docs/subsystems covers gateway routing, agent wiring, providers and accounts, the library and the GUI shell (Junjie Zhou on Discord)
code-standards.md: a failing test before the change (a real FAIL, not a compile error), tests under a temp HOME with GOPATH/GOMODCACHE/GOCACHE pinned and never a live agent config, vet/build (linux nogui, windows)/test with pipefail, GUI tests in Chromium and WebKit with gui-ja/gui-de, real-account checks in a sandbox, the UI rules; a PR merges only after it is run merged onto main and with --match-head-commit; a release counts only with the tag on main, 16 assets and Latest. The review section is distilled from recent PR reviews (#706–#931). New references, each following the README's format and linking real source: gateway-routing.md (plan/planGroup, rests, sink, affinity, attempt/translate), agent-wiring.md (Agent fields, ConnectHow, applied.json drift, stash, DisconnectPreview, Reseat/Rewire, WSL twins and ListsFor), providers-accounts.md (providers.json, keys, Accounts, token refresh, logins, groups, Quotas), library.md (change/sync, instructions, MCP formats, skills link/copy, backups, RTK), gui-shell.md (Run, startBackend, Handler/held/revalidated, magpie web, gateway mode, nogui). Every link and backticked identifier was checked against the tree at origin/main. Docs only. |