feat(mobile): add Android agent notifications and Material You theming - #456
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
(cherry picked from commit 9eb4d71681dc7d002082db2f8b4bacf7614412f4)
SecureStore keeps connection credentials in the iOS Keychain. Declare the bundle-scoped access group explicitly so pairing does not fail with a missing entitlement. The group uses $(AppIdentifierPrefix), which Xcode resolves from the signing team, so Pylon still pins no Apple team or T3 identifier. Adopted from 02443335b155e46248f96d80e037603abc742a61 (#3665)
Co-authored-by: Pixel Perfect <me@pixp.cc> (cherry picked from commit 579266caa89238611ddb974ffebe9968c6a6e5d5)
Co-authored-by: Pixel Perfect <me@pixp.cc> (cherry picked from commit 4664c572a78231611491f63f677f0e007ebaab03)
…0859) (cherry picked from commit 1862686f9e42bf1d77e7f2ad03e24d7b0c7908f1)
…10416) Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> (cherry picked from commit 6c583620ff7ad3235b135af7107c0543467eecfa)
The Pylon scheme made one deep-link assertion exceed ktlint's 100-column limit.
…them Android builds without Firebase config and devices whose APNs or FCM token lookup failed still registered with the relay, so Settings showed Device Notifications and Ongoing Agent Activity as on while nothing could arrive. The app now publishes whether Android push is configured, keeps both switches off with an honest subtitle when it is not, and reads a switch as on only once the relay accepts a registration that carries a push token. Also signs the Keychain access group with the bundle ID the build actually uses, makes the Mobile clients page and sign-in prompt name Android's ongoing activity, documents the relay rollback hazard, and links the new notification docs from the index.
rynfar
force-pushed
the
upstream/2026-09-10-mobile-android
branch
from
September 11, 2026 01:28
ddb1f2f to
0b1bdf0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pylon Mobile was missing upstream's Android work from the 2026-09-10 cycle: Android agent alerts and ongoing activity through Pylon Connect, wallpaper colors and an optional Material You layout, the iOS Keychain access group that SecureStore needs, and the relay fix for queued APNs jobs. It also still carried the mobile provider setup screens that upstream has since removed.
How it was ported
Each source was cherry-picked with
-xin upstream order againstorigin/pylon(1e1a43d576, since rebased onto16a99685d8after #458), frozen at upstream6c583620ff7ad3235b135af7107c0543467eecfa. Conflicts were resolved by splicing only each source's hunks into Pylon's files. The Keychain change was applied by hand because Pylon's iOS config differs. The icon sources were compared with Pylon's own brand exporter instead of being imported.Sources
9eb4d71681dc7d002082db2f8b4bacf7614412f41d1bf50405ccca8fdb8b57879d9def379e27a550c0cad74bfaddf153c3adaaf4f78af2be9260c4c102443335b155e46248f96d80e037603abc742a61892de47f0625183edd111dd36df45b156185bbf2b28471567cebe20347205059bbbdb3efe1213528579266caa89238611ddb974ffebe9968c6a6e5d54664c572a78231611491f63f677f0e007ebaab031862686f9e42bf1d77e7f2ad03e24d7b0c7908f16c583620ff7ad3235b135af7107c0543467eecfaPylon adaptations
SettingsProviderSetupRouteScreen,ProviderSetupLinkandprovider-setup-statewere byte-identical to upstream's pre-removal files. They arrived with the Antigravity port (feat(providers): add the Antigravity setup surfaces #440), so they are not Pylon-original.ConnectionEnvironmentRowkeeps Pylon'sPrimeHostMaintenanceStatus, which already sends Prime host operations to web/desktop. Pylon's model picker, composer and queue paths never had upstream's "finish setup" alerts, so those hunks had nothing to change.docs/user/providers-antigravity.mdnow points setup to web or desktop. Pylon has no Antigravity section inremote-access.md.keychain-access-groupsuses$(AppIdentifierPrefix)${iosBundleIdentifier}: the bundle ID the build actually signs with, including aT3CODE_IOS_PERSONAL_TEAM_BUNDLE_IDoverride. Upstream uses the variant bundle ID, which is wrong for personal-team and custom-bundle builds. Xcode resolves the team at signing time, so no T3 team or bundle ID is pinned. The group is the app's own bundle-scoped group, not an App ID service, so no Apple Developer portal change is expected. That is unverified on a signed device build here.adaptive-*palette, so attention, delegation and compaction states look the same.ComposerSurfacekeeps Pylon's explicit shadow style and drops it for the Material You layout, matching upstream's intent. Pylon's thread rows keep their existing hooks and props, including plan progress and pins. Docs went todocs/user/mobile-appearance.md, since Pylon has nodocs/user/appearance.md. The generated Uniwind theme files match their generator (generate --check).PYLON_EAS_PROJECT_IDgate.T3CODE_MOBILE_UPDATES_ENABLED=0now also turns updates off.pylon-code. Settings copy says Pylon and Pylon Connect.Schema.TaggedErrorClass, because Pylon is still on Effect4.0.0-beta.103.docs/operations/connect-setup.md. Its Android Clerk redirect table went intodocs/internals/t3-connect.mdwithcom.pylon.code*callbacks.docs/operations/android-notifications.mdwas rewritten for Pylon: package IDs, Neon stages,-- --stagedeploy syntax, and the opt-in relay workflow.docs/user/mobile-notifications.mdis in Pylon voice and does not promise Android delivery in builds without push support. The ops doc documents the relay rollback hazard. Both are linked fromdocs/README.md.deploy-relay.ymlkeeps Pylon's workflow name, environment and targets. The only new line passesFCM_SERVICE_ACCOUNT.com.t3tools.t3code*bundle IDs. They are test data only, and the existing Pylon relay tests use the same values.notification_icon, generated from Pylon'sandroid-notification-icon.png.app.config.tspublishesextra.androidPushConfigured(true only whenT3CODE_ANDROID_GOOGLE_SERVICES_FILEis set). Android push support requires it.remoteRegistrationnow records whether the accepted registration carried a push token (getAgentAwarenessPushDeliveryReady). Device Notifications on both platforms, and Ongoing Agent Activity on Android, read On only then. The enable alerts say when a device registered without a token. iOS Live Activity Updates keep their registration gate, since they use push-to-start tokens.remoteRegistration.test.ts,httpResponse.cookieswith Hermes-style headers, was removed. It checks the Effect patch from #10851, which the parallel mobile-drafts lane is porting with its own test. The rest of that test (typed failure, no defect, no saved record) passes here.Duplicated-feature comparison (maintainer decision)
Pylon fixed Android launcher clipping independently (
eef9d3531c,2c99cfc0a4). Its exporter renders the Pylon mark at 352px on a 432px canvas, throws if the mark crosses the 132px safe circle, and uses the same layer for monochrome. Channel background colours are solid (#00639B,#7565C7,#000000). Upstream #10598 fixes the same crop differently. It adds a newexport-android-icons.tsthat renders T3's Icon Composer layers: a wordmark foreground plus full-bleed dev (blueprint grid and annotations) and nightly (sky and clouds) background images. The quick-actions shortcut gets the same background. Pylon's shortcut already uses the launcher's foreground and colour, and its notification icon already comes from Pylon's mark. Adopting the artwork layers would be a branding change, and it would bring back the dark preview tile that Pylon replaced with#7565C7on purpose. Nothing was ported.#10620 fixed a splash crop that Pylon's artwork does not have. With
imageWidth: 220, the 1024px icon is drawn at 880px on the 1152px Android 12+ splash canvas, and the circular mask has a 384px radius. Measured with sharp, Pylon's mark reaches 367.9px from the centre in the 1024px source, which is 316px on the splash, inside the mask. The rounded-square background covers the whole circle. Upstream's version draws the splash from its launcher layers. For Pylon that would mean the mark on a solid colour, which only makes sense if the launcher artwork decision above changes. These are geometry measurements, not an emulator render.Provisioning the maintainer must do (nothing is deployed or committed)
DEPLOY_RELAYistrue, so merging topylondeploys the relay. That applies the additive migration20260906042516_android_devices(adds nullableandroid_api_level, makesios_major_versionnullable) to Neon prod, creates the Cloudflare queuesRelayFcmDeliveryQueueandRelayFcmDeliveryDeadLetterQueue, and serves/v2/client/devicesnext to the frozen/v1. Only web and desktop list devices (the Mobile clients page), and builds from this branch call/v2. Mobile never lists devices. The relay deploys on merge, before those clients ship.BadDeviceTokenhandling clears them. Fix forward, or deleteplatform = 'android'rows fromrelay_mobile_devicesfirst. This is documented indocs/operations/android-notifications.md.productionenvironment secretFCM_SERVICE_ACCOUNT. This is the Firebase service-account JSON. It is optional: without it, deploys succeed and Android deliveries log "not configured" and are skipped.APNS_ENABLEDdefaults totrueand needs no change.com.pylon.code,com.pylon.code.previewandcom.pylon.code.dev, enable the FCM API, and create a service-account key. Never commitgoogle-services.json.T3CODE_ANDROID_GOOGLE_SERVICES_FILEper build environment. It must be available to fingerprint generation as well as the build.clerk://com.pylon.code[.preview|.dev].callbackin the mobile SSO redirect allowlist.t3-agent-notificationsmodule,minSdkVersion: 24,googleServicesFile, andexpo-notificationsbuilt from source. New iOS and Android binaries are required; OTA cannot deliver this to existing installs.Verification
vp test run, mobile, 98 tests in 9 files: Material You theme, storage, mobile theme, review diff adapter, Android notifications, notification permissions, remote registration, settings logic, thread settings sheet state. These include the unprovisioned Android build (switches off, no token lookup, no channels, registration without a token) and an iOS token-lookup failure (registered but not delivery-ready).MobileClientsUserProfilePage.logic.relay.managedRelay.@t3tools/mobile,t3code-relay,@t3tools/web,@t3tools/contracts,@t3tools/client-runtime.vp lintandvp fmt --checkon every changed TS/TSX/MD/YML file.vp run icons:check: 40 files current. Uniwind themegenerate --check: current.git grep PRIME_AGENT_DRIVER_KIND: 3 usages, same asorigin/pylon.vp run lint:mobileran, but ktlint, detekt and swiftlint are not installed here (no Java runtime), so it skipped all three. The Mobile Native Static Analysis CI job covers the new Kotlin. Its first run caught one test assertion pushed past 100 columns by the Pylon scheme; that is fixed inb147efcbc1and the job passes.Upstream evidence
Ported by Claude Opus 5 in Claude Code.