chore(sync): upstream freellmapi @ b235b7e (v0.9.0) #25

Closed
epistemophiliac wants to merge 0 commits from upstream into develop

Automated sync with upstream freellmapi.

Upstream: b235b7e (v0.9.0)

This PR was created by Jenkins. Review and merge to apply upstream bug fixes and features.

Note: This merge has conflicts that need manual resolution (router.ts, compression.test.ts). Aexora customizations should win on conflict.

Changes since last sync (e70d130..b235b7e):

  • Add release-notes template with the tagged premium footer (#1058)
  • Bump desktop to v0.9.0 (#1044)
  • Credit hiiamwaffledev, w0fv1 and oppih in the contributors list (#1043)
  • Inject an estimated usage frame when a streaming upstream omits usage (#686)
  • Add an opt-in Fetch Relay outbound transport (#975)
  • Chown the data dir on PaaS runtimes via a root entrypoint (#972)
  • Notarize the DMG itself, not just the app inside it (#1036)
  • Mac builds are signed and notarized — closes #373 #943 (#1035)
  • Notarize the Mac build with an App Store Connect key, not an app password (#1034)
  • Loosen the compression timing caps off CI (#1030)
Automated sync with upstream freellmapi. Upstream: b235b7e (v0.9.0) This PR was created by Jenkins. Review and merge to apply upstream bug fixes and features. **Note:** This merge has conflicts that need manual resolution (router.ts, compression.test.ts). Aexora customizations should win on conflict. Changes since last sync (e70d130..b235b7e): - Add release-notes template with the tagged premium footer (#1058) - Bump desktop to v0.9.0 (#1044) - Credit hiiamwaffledev, w0fv1 and oppih in the contributors list (#1043) - Inject an estimated usage frame when a streaming upstream omits usage (#686) - Add an opt-in Fetch Relay outbound transport (#975) - Chown the data dir on PaaS runtimes via a root entrypoint (#972) - Notarize the DMG itself, not just the app inside it (#1036) - Mac builds are signed and notarized — closes #373 #943 (#1035) - Notarize the Mac build with an App Store Connect key, not an app password (#1034) - Loosen the compression timing caps off CI (#1030)
71 strings in fr.json still held their English source text, so the dashboard fell back to English in the middle of an otherwise French UI. The Backups section and the update notice were the most visible cases: every one of their strings rendered in English.

These are strings added after the French locale landed in #314, whose English values were never followed by a translation. Terminology follows what fr.json already settled: healthy -> sain, export -> exporter, remove -> supprimer, release -> version, /mo -> /mois; pool, token and cooldown stay in English because the file already keeps them that way. Strings legitimately identical in French (format templates, acronyms, API parameter names, endonyms, product names) are left untouched.

Maintainer pass on top: six strings polished (the update notice's X is a permanent dismiss, so its aria-label is Ignorer; texte-vidéo to match texte-image; a dangling en dehors; three agreement/wording fixes) and @Patrickleondev added to the README contributors.

No keys added or removed, key order preserved, check:i18n passes.
A chain created from the dashboard starts empty — "Start empty" is checked by
default — and an empty chain had no rows in profile_models. Every consumer read
zero rows as "no chain configured" and quietly used the single global
fallback_config table instead, which is where all three complaints in #1021
come from. The Models page showed the whole catalog switched on for a chain
that held nothing. Saving could never put the first model into it, because the
write was an UPDATE that matched no row and then landed in the global table.
And two empty chains, both aliased onto that same table, showed each other's
configuration: build one, switch, and there it was again.

So a profile is now authoritative whenever one is active. Reading a chain
returns the whole catalog seen through it: the models it names keep their
stored order and on/off flag, the ones it does not are listed switched off
after them. An empty chain reads as "the catalog, nothing turned on yet",
which is the opt-in behaviour the chain was asked for, and needs no new UI.
Saving upserts into the chain, so turning a row on is what puts it there, and
the global table is only touched on an install that has no profiles at all.
Routing follows the same rule: an empty active chain routes nothing, and a
request for "auto" is told the chain is empty instead of being spread across
models nobody put in it — the answer "auto:<name>" already gave.

The dashboard had a matching version of the same bug. The routing table read
one cache entry for every chain, so switching re-rendered the previous chain's
rows and a save then wrote them into the newly activated one; it is keyed on
the active chain now, and staged edits remember which chain they belong to.
The Playground could only send 'auto', which left a freshly built chain with
nowhere to be tried; every custom chain is offered in the picker as the
auto:<name> id that /v1/models already advertises.
The wall-clock caps in compression.test.ts are calibrated to GitHub's hosted
runners, where they gate every push. Run anywhere slower they only produce
false failures: an outside verification of the suite on Node 22 inside Docker
measured a 10-11 ms median against the 8 ms cap and 252-277 ms against the
250 ms linearity cap, with every functional test green.

Multiply the caps by three when CI is not set. CI keeps the exact numbers, so
the guard that actually catches regressions is unchanged.
The macOS release job offered three notarization credentials and picked the
wrong one. electron-builder's getNotarizeOptions checks APPLE_ID first and
returns the moment it is set, so with both pairs configured the App Store
Connect API key was dead config — the build would always have taken the
app-specific-password path, which expires and cannot be minted headlessly.

The API key was also wired up in a way that could never have worked. notarytool
takes it as `--key <path>`, a file, but the workflow passed the secret's PEM
text straight through as APPLE_API_KEY, so notarytool would have been handed a
private key where it expected a filename.

Write the key to $RUNNER_TEMP/AuthKey.p8 in its own step and export the path
through $GITHUB_ENV — deliberately not through the package step's `env:`, which
would override it with the text again. The APPLE_ID pair is gone rather than
kept as a fallback: it cannot coexist with the key it shadows. APPLE_TEAM_ID
stays required alongside the key so codesign resolves the right identity.

This is the CI half of the "damaged" Gatekeeper reports (#373, #943). The other
half is a Developer ID Application certificate in MACOS_CSC_LINK; until that
secret exists the job still warns and ships an unsigned DMG, unchanged.
A Developer ID Application certificate now exists for the team, so
MACOS_CSC_LINK and MACOS_CSC_KEY_PASSWORD are configured and the release job
takes its signing path instead of the unsigned fallback. Notarization goes
through the App Store Connect API key wired up in #1034.

That clears the "damaged" Gatekeeper block reported in #373: the DMG through
v0.8.7 was ad-hoc signed, which macOS refuses to open from a quarantined
download. A notarized, stapled DMG opens normally.

Bumps desktop/package.json and desktop/package-lock.json to 0.8.8 together —
the tagged run compares them against the tag and fails if they drift, which is
the mislabeling #943 hit.
v0.8.8 signed and notarized FreeLLMAPI.app correctly — stapler validates it and
spctl calls it "Notarized Developer ID". The DMG wrapping it was neither signed
nor notarized:

  $ spctl -a -vv -t install FreeLLMAPI-0.8.8-arm64.dmg
  rejected
  source=no usable signature

The DMG is the file people download, so it is the file macOS quarantines and
assesses. electron-builder only ever submits the .app, which leaves the
container unsigned and the "damaged" report in #373 only half answered.

dmg.sign makes electron-builder sign the DMG, which is also what makes it
eligible to submit; it runs before the blockmap and latest-mac.yml are written,
so those describe the signed file. The release job then submits and staples it.

Stapling rewrites the DMG in place, after electron-builder has hashed it, so
the release would otherwise ship a latest-mac.yml whose sha512 describes the
pre-staple bytes — electron-updater verifies that hash, so it would break
updates for every installed copy. refresh-mac-update-metadata.mjs re-stamps the
manifest and the blockmap is regenerated with the same app-builder binary
electron-builder uses.

The rewrite is a line-level edit rather than a YAML round trip, which would
reorder keys and restyle quoting in every future release diff. Verified against
the published v0.8.8 artifacts: recomputing over the unstapled DMG reproduces
the shipped manifest byte for byte.
Add release-notes template with the tagged premium footer (#1058)
Some checks failed
Desktop release / Build (ubuntu-latest) (pull_request) Has been cancelled
Desktop release / Build (macos-latest) (pull_request) Has been cancelled
Desktop release / Build (windows-2022) (pull_request) Has been cancelled
b235b7e879
Every release page now ends with a Go Premium link tagged
utm_source=github&utm_medium=release&utm_campaign=premium and the tag as
utm_content; this template keeps future tags in step.

Co-authored-by: Claude Fable 5 <[email protected]>
Merge upstream v0.9.0 into develop (resolve conflicts)
Some checks failed
CI / Test & build (Node 20) (pull_request) Has been cancelled
CI / Test & build (Node 22) (pull_request) Has been cancelled
Desktop release / Build (ubuntu-latest) (pull_request) Has been cancelled
Desktop release / Build (macos-latest) (pull_request) Has been cancelled
Desktop release / Build (windows-2022) (pull_request) Has been cancelled
Docker / Build (linux/amd64) (pull_request) Has been cancelled
Docker / Build (linux/arm64) (pull_request) Has been cancelled
Docker / Merge manifest and push (pull_request) Has been cancelled
614e95c624
- Keep both activeChainOrThrow (upstream) and orderByCost/orderByCheapAware (develop)
- Use develop's compression test assertions (linearity ratio vs absolute)
epistemophiliac closed this pull request 2026-08-28 12:55:39 +00:00
Some checks failed
CI / Test & build (Node 20) (pull_request) Has been cancelled
CI / Test & build (Node 22) (pull_request) Has been cancelled
Desktop release / Build (ubuntu-latest) (pull_request) Has been cancelled
Desktop release / Build (macos-latest) (pull_request) Has been cancelled
Desktop release / Build (windows-2022) (pull_request) Has been cancelled
Docker / Build (linux/amd64) (pull_request) Has been cancelled
Docker / Build (linux/arm64) (pull_request) Has been cancelled
Docker / Merge manifest and push (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
epistemophiliac/LLMAPI!25
No description provided.