Skip to content

Merge upstream: Auto runtime mode, t3.json config, glass-surface redesign#8

Merged
jetblk merged 21 commits into
mainfrom
t3code/upstream-merge-20260723
Jul 23, 2026
Merged

Merge upstream: Auto runtime mode, t3.json config, glass-surface redesign#8
jetblk merged 21 commits into
mainfrom
t3code/upstream-merge-20260723

Conversation

@jetblk

@jetblk jetblk commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Brings in 20 new commits from pingdotgg/t3code main (origin/main..upstream/main, up to 4d8343641), evaluated per the fork's upstream-merge workflow. Full merge (no cherry-pick) to keep the RPC contract in sync.

Highlights

Commit Summary
fbd77420f (pingdotgg#4272) "Auto" runtime mode — AI-reviewed tool-call approvals for Codex & Claude
1c9a6de26 (pingdotgg#4317) Shared t3.json project configuration support
16491a84b (pingdotgg#4276) Fix: new-thread defaults ignored for remote environments
b44ed835c / 9c9916aef Sync provider banner dismissal + redesign review fixes
~15 commits Web "glass surfaces" visual redesign (dialogs, glass-opacity slider, command palette / model picker / tooltip styling, light/dark)

Conflicts

None. Auto-merge succeeded on all 6 overlap files (server.ts, server.test.ts, ChatComposer.tsx, ModelPickerContent.tsx, SettingsSidebarNav.tsx, contracts/index.ts); provider-usage wiring preserved in each. No fork-identity files touched. pingdotgg#4272's provider changes don't collide with the fork's usage layers or driver baseEnv threading.

Verification

  • Typecheck clean: @t3tools/contracts, t3 (server), @t3tools/web
  • Tests green: contracts 203, client-runtime 453, server provider-usage suites 156

After squash-merge

Squashing breaks upstream ancestry; will follow with a git merge -s ours upstream/main reconciliation so the next merge stays clean.

🤖 Generated with Claude Code

Note

Add auto runtime mode, t3.json config support, and glass-surface UI redesign

  • Adds an auto runtime mode across contracts, Claude adapter, Codex runtime, and all composer/composer-menu UIs; in auto mode, permissionMode is set to 'auto' and approvals are routed to auto_review.
  • Introduces t3.json project file support: a new schema (t3ProjectFile.ts), server-side loader (T3ProjectFileLoader.ts), and a marketing endpoint serving the JSON Schema for LSP/editor consumption.
  • ProjectFaviconResolver now reads iconPath from t3.json before falling back to well-known icon locations.
  • Scripts declared in t3.json can be imported directly into the project actions UI via ProjectScriptsControl; on failure, the add-action dialog pre-fills for correction.
  • Overhauls UI surfaces with translucent glass effects (backdrop-filter, color-mix) for composer, alerts, dropdowns, and dialogs; sidebar color tokens are unified to a zinc-based hierarchy for both v1 and v2.
  • Adds a user-adjustable glassOpacity setting (range 40–100, default 80) persisted to client settings and applied via --glass-opacity CSS variable in real time.
  • Provider status banners in the chat view are now dismissible and rendered as an overlay, preventing content height shifts.
  • SVG definition IDs in SidebarStageBackdrop components are now generated with useId to prevent collisions when rendered multiple times.
  • New thread defaults (defaultThreadEnvMode, newWorktreesStartFromOrigin) are now sourced from the primary server's settings rather than the target environment's server configs.
  • Risk: The glass/backdrop-filter effects are visually significant and affect many surfaces; reduced-transparency environments fall back to opaque backgrounds, but intermediate system configurations may show unexpected blending.
📊 Macroscope summarized c6b76cd. 63 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

maria-rcks and others added 21 commits July 23, 2026 01:13
Co-authored-by: codex <codex@users.noreply.github.com>
…tgg#4276)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…laude (pingdotgg#4272)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- Restore light-mode glass, dialog, dropdown, and composer colors
- Refine provider wizard, changed-file cards, sidebar controls, and buttons
- Update wizard step tests for the new list structure
Co-authored-by: codex <codex@users.noreply.github.com>
@jetblk
jetblk merged commit a7f2315 into main Jul 23, 2026
1 check passed
jetblk added a commit that referenced this pull request Jul 23, 2026
Records upstream/main (4d83436) as merged. Its content already landed in
main via the squash-merge of #8; this commit only restores git ancestry so
the fork stays 'fully merged' and future upstream merges don't re-present
these commits. No file changes (tree identical to origin/main).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
updateSettings({ glassOpacity });
}
}}
step={5}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium settings/SettingsPanels.tsx:613

The glass opacity slider uses step={5}, but the settings contract accepts every integer from MIN_GLASS_OPACITY through MAX_GLASS_OPACITY. For a valid persisted value like 72, the range input has a step-mismatched value — the browser may render the thumb at the nearest valid step (e.g. 70), while the adjacent output and custom fill are calculated from 72. The next interaction can then overwrite the valid 72 with the rounded value. Consider using step={1} so the slider can represent every valid value, or restrict the schema to multiples of five.

Suggested change
step={5}
step={1}
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/settings/SettingsPanels.tsx around line 613:

The glass opacity slider uses `step={5}`, but the settings contract accepts every integer from `MIN_GLASS_OPACITY` through `MAX_GLASS_OPACITY`. For a valid persisted value like `72`, the range input has a step-mismatched value — the browser may render the thumb at the nearest valid step (e.g. `70`), while the adjacent output and custom fill are calculated from `72`. The next interaction can then overwrite the valid `72` with the rounded value. Consider using `step={1}` so the slider can represent every valid value, or restrict the schema to multiples of five.

Comment thread t3.json
"scripts": [
{
"name": "Setup Worktree",
"command": "vp i && ln -sf $T3CODE_PROJECT_ROOT/.env .env && ln -sf $T3CODE_PROJECT_ROOT/infra/relay/.env infra/relay/.env",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium t3.json:7

The Setup Worktree command expands $T3CODE_PROJECT_ROOT without quotes in both ln source paths. If the project root contains spaces, shell word splitting passes multiple operands to ln, so the first link fails and, due to &&, neither .env link is created. Quote each expanded source path, e.g. "$T3CODE_PROJECT_ROOT/.env".

Suggested change
"command": "vp i && ln -sf $T3CODE_PROJECT_ROOT/.env .env && ln -sf $T3CODE_PROJECT_ROOT/infra/relay/.env infra/relay/.env",
vp i && ln -sf "$T3CODE_PROJECT_ROOT/.env" .env && ln -sf "$T3CODE_PROJECT_ROOT/infra/relay/.env" infra/relay/.env
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @t3.json around line 7:

The `Setup Worktree` command expands `$T3CODE_PROJECT_ROOT` without quotes in both `ln` source paths. If the project root contains spaces, shell word splitting passes multiple operands to `ln`, so the first link fails and, due to `&&`, neither `.env` link is created. Quote each expanded source path, e.g. `"$T3CODE_PROJECT_ROOT/.env"`.

return currentIndex < threadIds.length - 1 ? (threadIds[currentIndex + 1] ?? null) : null;
}

export function shouldNavigateAfterProjectRemoval(input: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium components/Sidebar.logic.ts:381

shouldNavigateAfterProjectRemoval returns false for a server route whose thread was added to the project after the projectThreads snapshot was captured — for example, a thread synced while the delete confirmation is pending. After the project is actually removed, the UI stays on that route instead of navigating away, because the thread's environmentId/id match the current route but were not present in the stale snapshot. Consider computing project ownership from current thread state at call time (after the await), or retaining the removed project id and comparing it against the route's project rather than relying on the pre-removal thread list.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/Sidebar.logic.ts around line 381:

`shouldNavigateAfterProjectRemoval` returns `false` for a server route whose thread was added to the project after the `projectThreads` snapshot was captured — for example, a thread synced while the delete confirmation is pending. After the project is actually removed, the UI stays on that route instead of navigating away, because the thread's `environmentId`/`id` match the current route but were not present in the stale snapshot. Consider computing project ownership from current thread state at call time (after the await), or retaining the removed project id and comparing it against the route's project rather than relying on the pre-removal thread list.

const api = readLocalApi();
if (!api) return;

const projectThreads = threads.filter(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High components/SidebarV2.tsx:854

handleRemoveProject filters threads (live shells only) to compute projectThreads, then shows the user a confirmation dialog saying exactly projectThreads.length thread histories will be deleted. But the deleteProject call passes force: true, which makes the server delete all threads in the project including archived ones. Archived threads are not in the live shell list, so the dialog undercounts: it says "delete its 1 thread" while the server actually deletes every archived history too. Consider counting archived threads for the project (or wording the confirmation to account for archived histories) so the dialog reflects what force: true actually removes.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/SidebarV2.tsx around line 854:

`handleRemoveProject` filters `threads` (live shells only) to compute `projectThreads`, then shows the user a confirmation dialog saying exactly `projectThreads.length` thread histories will be deleted. But the `deleteProject` call passes `force: true`, which makes the server delete *all* threads in the project including archived ones. Archived threads are not in the live shell list, so the dialog undercounts: it says "delete its 1 thread" while the server actually deletes every archived history too. Consider counting archived threads for the project (or wording the confirmation to account for archived histories) so the dialog reflects what `force: true` actually removes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants