Skip to content

Commit 3f9a0fb

Browse files
Merge branch 'main' into fix/macos-home-end-composer
2 parents d540f1c + 7b8d126 commit 3f9a0fb

1,944 files changed

Lines changed: 198124 additions & 91598 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.cursor/rules/cursor-cloud.mdc‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
description: Cursor Cloud environment setup and run notes for T3 Code (Cursor-specific; not for other editors/CI)
3+
alwaysApply: true
4+
---
5+
6+
# Cursor Cloud specific instructions
7+
8+
These notes apply only to Cursor Cloud agents (kept out of the shared `AGENTS.md` since T3 Code is
9+
developed in many places). They cover the pre-provisioned VM environment and non-obvious run caveats.
10+
11+
## Toolchain
12+
13+
Pre-installed and wired into login shells (`~/.bashrc`/`~/.profile`): Node 24 (via nvm), the global
14+
`vp` (Vite+) CLI, and its bundled pnpm. `vp` is the package manager + task runner for this repo
15+
(`vp i`, `vp check`, `vp run typecheck`, `vp test`, `vp run --filter <pkg> <script>`).
16+
17+
- Node gotcha: the base image also ships an older Node on `/exec-daemon` that wins on `PATH` in
18+
non-login shells. Run commands in a login shell (`bash -lc '...'`) or prepend
19+
`$HOME/.nvm/versions/node/v24.13.1/bin` so Node 24 (`engines.node: ^24.13.1`) is used.
20+
- `vp check` also runs the formatter (not just lint); markdown edits must be formatter-clean. Run
21+
`vp check --fix` before committing.
22+
23+
## Running the web app
24+
25+
- `npm run dev` (from repo root) starts contracts (watch), web (Vite, port 5733), and the server
26+
(`node --watch`, port 13773) together, auto-wiring `VITE_HTTP_URL`/`VITE_WS_URL`. Use
27+
`npm run dev:server` / `npm run dev:web` for one side. If base ports are taken it auto-offsets to
28+
the next free pair, so read the actual ports from stdout. Avoid production `build`/`start` in dev.
29+
- Auth/pairing: the server is unauthenticated by default and prints a pairing URL to stdout on startup
30+
(e.g. `http://localhost:5733/pair#token=XXXX`). Open that URL in the browser to pair before the web
31+
UI can talk to the server. Server state (SQLite, auth, projects) lives under `~/.t3`
32+
(`T3CODE_HOME`); multiple `npm run dev` instances bind different ports but share that same DB.
33+
- Agent providers are external CLIs (`codex`, `claude`, `cursor-agent`, `opencode`) probed on `PATH`.
34+
Without one installed the UI loads but no agent can run. Claude Code
35+
(`npm i -g @anthropic-ai/claude-code`) works headlessly using `ANTHROPIC_API_KEY` from the
36+
environment (the server forwards `process.env` to the child; no interactive `claude auth login`
37+
needed). Provider probing runs at startup and refreshes roughly every 5 minutes — restart the dev
38+
server to pick up a newly installed provider CLI immediately.
39+
40+
## Android native builds (apps/mobile)
41+
42+
The Android toolchain is pre-installed and wired into login shells: OpenJDK 17
43+
(`JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64`; the base image's default `java` is 21, so builds must
44+
use `JAVA_HOME`), and the Android SDK at `$HOME/Android/Sdk` (`ANDROID_HOME`/`ANDROID_SDK_ROOT`) with
45+
platform-tools, `platforms;android-36`, `build-tools;36.0.0`, `ndk;27.1.12297006`, and `cmake;3.22.1`.
46+
Gradle auto-downloads any additional pinned SDK packages on demand.
47+
48+
- Generate the native project first: from `apps/mobile`,
49+
`EXPO_NO_GIT_STATUS=1 APP_VARIANT=development npx expo prebuild --clean --platform android`
50+
(the `android/` folder is generated, not committed). RN 0.85 defaults: compileSdk/targetSdk 36,
51+
minSdk 24, NDK `27.1.12297006` (see `react-native/gradle/libs.versions.toml`).
52+
- Build with Gradle from `apps/mobile/android`, e.g. `./gradlew :app:assembleDebug`. First build is
53+
slow (Kotlin + C++/NDK codegen). Limit ABIs to speed things up, e.g.
54+
`-PreactNativeArchitectures=arm64-v8a`. Verified working end-to-end on a native module:
55+
`./gradlew :react-native-worklets:assembleDebug` compiles Kotlin + C++ and emits an AAR + `.so`s.
56+
- No emulator: this VM has no `/dev/kvm` (nested virtualization), so a hardware-accelerated Android
57+
emulator will not run. Use a physical device (`adb`) or EAS cloud builds (`vp run eas:android:*`) to
58+
actually run the app. The full IDE GUI is unnecessary here — the SDK/NDK/Gradle toolchain that
59+
Android Studio bundles is what is installed.
60+
- Known blocker for the full-app `:app:assembleDebug` (pre-existing, app-level — not the environment):
61+
`:react-native-screens:compileDebugKotlin` fails because `patches/[email protected]`
62+
adds new codegen props (`subtitle`, `largeSubtitle`, `navigationItemStyle`,
63+
`headerCenterBarButtonItems`, `headerToolbarItems`) to the JS spec + iOS native code but includes no
64+
Android Kotlin setters, so the generated `ScreenStackHeaderConfigManagerInterface` is unimplemented.
65+
The mobile README documents only iOS for local builds and routes Android through EAS. Fixing local
66+
Android app builds requires an app/patch change (add the Android Kotlin setters), which is out of
67+
scope for environment setup.
68+
69+
## Known flaky tests (unrelated to setup)
70+
71+
- `apps/server/src/git/GitManager.test.ts` (cross-repo PR metadata, can time out at 12s).
72+
- `apps/server/src/provider/Layers/ProviderRegistry.test.ts` (codex binaryPath re-probe ordering).

‎.env.example‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
# T3CODE_CLERK_JWT_TEMPLATE=t3-relay
99
# T3CODE_CLERK_CLI_OAUTH_CLIENT_ID=oauthapp_...
1010

11+
# Optional: signed macOS passkey builds. The RP domain defaults to the Frontend API
12+
# hostname encoded in T3CODE_CLERK_PUBLISHABLE_KEY. Set the override only when Clerk
13+
# returns a different RP ID or when multiple domains must be entitled.
14+
# T3CODE_APPLE_TEAM_ID=ABC1234567
15+
# T3CODE_MACOS_PROVISIONING_PROFILE=/absolute/path/to/t3code.provisionprofile
16+
# T3CODE_CLERK_PASSKEY_RP_DOMAINS=example.clerk.accounts.dev,clerk.example.com
17+
1118
# Get this from your relay deployment. `infra/relay` deploys update it automatically.
1219
# T3CODE_RELAY_URL=https://relay.example.com
1320

‎.github/workflows/ci.yml‎

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ jobs:
3838
run: |
3939
test -f apps/desktop/dist-electron/preload.cjs
4040
grep -nE "desktopBridge|getLocalEnvironmentBootstrap|PICK_FOLDER_CHANNEL|wsUrl" apps/desktop/dist-electron/preload.cjs
41+
grep -n "__clerk_internal_electron_passkeys" apps/desktop/dist-electron/preload.cjs
4142
4243
test:
4344
name: Test
@@ -60,52 +61,6 @@ jobs:
6061
- name: Test
6162
run: vp run test
6263

63-
test_browser:
64-
name: Test Browser
65-
runs-on: blacksmith-8vcpu-ubuntu-2404
66-
timeout-minutes: 10
67-
steps:
68-
- name: Checkout
69-
uses: actions/checkout@v6
70-
71-
- name: Setup Vite+
72-
uses: voidzero-dev/setup-vp@v1
73-
with:
74-
node-version-file: package.json
75-
cache: true
76-
run-install: true
77-
78-
- name: Cache Playwright browsers
79-
uses: actions/cache@v5
80-
with:
81-
path: ~/.cache/ms-playwright
82-
key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }}
83-
restore-keys: |
84-
${{ runner.os }}-playwright-
85-
86-
- name: Install browser test runtime
87-
run: vp run --filter @t3tools/web test:browser:install
88-
89-
- name: Browser test / Chat view
90-
working-directory: apps/web
91-
run: vp test run --mode browser --browser=chromium src/components/ChatView.browser.tsx
92-
93-
- name: Browser test / Chat markdown
94-
working-directory: apps/web
95-
run: vp test run --mode browser --browser=chromium src/components/ChatMarkdown.browser.tsx
96-
97-
- name: Browser test / Components
98-
working-directory: apps/web
99-
run: |
100-
vp test run --mode browser --browser=chromium \
101-
src/components/GitActionsControl.browser.tsx \
102-
src/components/KeybindingsToast.browser.tsx \
103-
src/components/ThreadTerminalDrawer.browser.tsx \
104-
src/components/chat/MessagesTimeline.browser.tsx \
105-
src/components/chat/ProviderModelPicker.browser.tsx \
106-
src/components/chat/CompactComposerControlsMenu.browser.tsx \
107-
src/components/settings/SettingsPanels.browser.tsx
108-
10964
mobile_native_static_analysis:
11065
name: Mobile Native Static Analysis
11166
runs-on: blacksmith-12vcpu-macos-26

‎.github/workflows/mobile-eas-preview.yml‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ name: Mobile EAS Preview
22

33
on:
44
pull_request:
5+
types: [opened, reopened, synchronize, labeled, unlabeled]
56

67
jobs:
78
preview:
89
name: EAS Preview
10+
if: contains(github.event.pull_request.labels.*.name, '🚀 Mobile Continuous Deployment')
911
runs-on: blacksmith-8vcpu-ubuntu-2404
1012
permissions:
1113
contents: read
@@ -55,7 +57,10 @@ jobs:
5557
with:
5658
eas-version: latest
5759
token: ${{ secrets.EXPO_TOKEN }}
58-
packager: pnpm
60+
# npm, not pnpm: this only installs eas-cli into the action's own
61+
# tool dir, and pnpm 11 hard-fails that install on dtrace-provider's
62+
# ignored build script (no allowBuilds config outside the repo).
63+
packager: npm
5964

6065
- name: Pull preview environment variables
6166
if: steps.expo-token.outputs.present == 'true'
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Mobile EAS Production
2+
3+
# Production builds and OTA updates run from CI (Linux) — never from a laptop.
4+
# Under the fingerprint runtime-version policy the fingerprint must be computed
5+
# in the same OS/pnpm as the EAS build; a macOS `eas build` computes a different
6+
# fingerprint (platform-specific deps + pnpm version) and errors. On this Linux
7+
# runner, with corepack pinning pnpm 10.24 in eas.json, local == build.
8+
on:
9+
workflow_dispatch:
10+
inputs:
11+
mode:
12+
description: "build (+ auto-submit to TestFlight) or update (OTA)"
13+
required: true
14+
type: choice
15+
default: build
16+
options:
17+
- build
18+
- update
19+
platform:
20+
description: "Target platform"
21+
required: true
22+
type: choice
23+
default: ios
24+
options:
25+
- ios
26+
- android
27+
- all
28+
message:
29+
description: "OTA update message (mode=update only)"
30+
required: false
31+
type: string
32+
33+
jobs:
34+
production:
35+
name: EAS Production ${{ inputs.mode }}
36+
runs-on: blacksmith-8vcpu-ubuntu-2404
37+
permissions:
38+
contents: read
39+
env:
40+
APP_VARIANT: production
41+
NODE_OPTIONS: --max-old-space-size=8192
42+
steps:
43+
- id: expo-token
44+
name: Check for EXPO_TOKEN
45+
env:
46+
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
47+
run: |
48+
if [ -n "$EXPO_TOKEN" ]; then
49+
echo "present=true" >> "$GITHUB_OUTPUT"
50+
else
51+
echo "present=false" >> "$GITHUB_OUTPUT"
52+
echo "EXPO_TOKEN is not available; skipping EAS production job."
53+
fi
54+
55+
- name: Checkout
56+
if: steps.expo-token.outputs.present == 'true'
57+
uses: actions/checkout@v6
58+
with:
59+
fetch-depth: 0
60+
61+
- name: Setup Vite+
62+
if: steps.expo-token.outputs.present == 'true'
63+
uses: voidzero-dev/setup-vp@v1
64+
with:
65+
node-version-file: package.json
66+
cache: true
67+
run-install: true
68+
69+
- name: Expose pnpm
70+
if: steps.expo-token.outputs.present == 'true'
71+
run: |
72+
pnpm_version="$(node --print "require('./package.json').packageManager.split('@').pop()")"
73+
vp_pnpm_bin="$HOME/.vite-plus/package_manager/pnpm/$pnpm_version/pnpm/bin"
74+
echo "$vp_pnpm_bin" >> "$GITHUB_PATH"
75+
"$vp_pnpm_bin/pnpm" --version
76+
77+
- name: Setup EAS
78+
if: steps.expo-token.outputs.present == 'true'
79+
uses: expo/expo-github-action@v8
80+
with:
81+
eas-version: latest
82+
token: ${{ secrets.EXPO_TOKEN }}
83+
# npm, not pnpm: this only installs eas-cli into the action's own
84+
# tool dir, and pnpm 11 hard-fails that install on dtrace-provider's
85+
# ignored build script (no allowBuilds config outside the repo).
86+
packager: npm
87+
88+
- name: Pull production environment variables
89+
if: steps.expo-token.outputs.present == 'true'
90+
working-directory: apps/mobile
91+
env:
92+
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
93+
run: eas env:pull production --non-interactive
94+
95+
- name: Build and submit
96+
if: steps.expo-token.outputs.present == 'true' && inputs.mode == 'build'
97+
working-directory: apps/mobile
98+
env:
99+
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
100+
run: eas build --platform ${{ inputs.platform }} --profile production --auto-submit --non-interactive --no-wait
101+
102+
- name: Publish OTA update
103+
if: steps.expo-token.outputs.present == 'true' && inputs.mode == 'update'
104+
working-directory: apps/mobile
105+
env:
106+
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
107+
run: |
108+
eas update \
109+
--channel production \
110+
--environment production \
111+
--platform ${{ inputs.platform }} \
112+
--message "${{ inputs.message || format('Production OTA ({0})', github.sha) }}" \
113+
--non-interactive

0 commit comments

Comments
 (0)