Skip to content

Integrate Gemini PR 54 onto current main#58

Merged
aaditagrawal merged 6 commits intomainfrom
codex/pr-54-followup-fixes
Apr 11, 2026
Merged

Integrate Gemini PR 54 onto current main#58
aaditagrawal merged 6 commits intomainfrom
codex/pr-54-followup-fixes

Conversation

@aaditagrawal
Copy link
Copy Markdown
Owner

@aaditagrawal aaditagrawal commented Apr 11, 2026

Supersedes the conflicted cross-repo PR #54 with a fork-owned integration branch.

Why this exists:

Included here:

Validation:

  • bun fmt
  • bun lint
  • bun typecheck

Reference:

Summary by CodeRabbit

  • New Features
    • Enhanced multi-provider support, new per-provider model options/merging, and expanded model catalogs
  • Bug Fixes
    • Normalized legacy provider identifiers across persisted storage
    • Improved session interruption tracking and richer error summaries
    • More robust cross-platform command/CLI execution handling
  • Documentation
    • Updated CONTRIBUTING and README with clearer development setup and scope
  • Tests
    • Added migration, normalization, and spawn/behavior unit tests

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 711438fa-7a02-4ef8-af6c-6512d976568d

📥 Commits

Reviewing files that changed from the base of the PR and between 6c0dcb7 and abc8bcb.

📒 Files selected for processing (6)
  • CONTRIBUTING.md
  • apps/server/src/commandPath.ts
  • apps/server/src/open.test.ts
  • apps/web/src/components/chat/ProviderModelPicker.logic.test.ts
  • apps/web/src/components/settings/SettingsPanels.tsx
  • apps/web/src/providerModelOptions.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/web/src/components/chat/ProviderModelPicker.logic.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/server/src/commandPath.ts

📝 Walkthrough

Walkthrough

This PR centralizes cross-platform command resolution, refactors Gemini CLI process spawning and interrupt handling, normalizes legacy provider names across runtime and persistence (with migrations and tests), consolidates model-option logic for the web UI, and updates docs and contributor guidance.

Changes

Cohort / File(s) Summary
Docs & Repo Metadata
CONTRIBUTING.md, README.md
Rewrote contributing guidance and fork description; reorganized README sections (multi-provider, persistence/orchestration notes); removed prior contribution rejection guidance; added development setup and code style notes.
Package Manifests
apps/desktop/package.json, apps/server/package.json, package.json
Added trustedDependencies in app manifests (electron, node-pty) and removed root trustedDependencies.
Command resolution
apps/server/src/commandPath.ts, apps/server/src/open.ts, apps/server/src/open.test.ts
New commandPath.ts implements resolveCommandPath/isCommandAvailable; open.ts re-exports and delegates; tests cover Windows extension and PATHEXT behavior.
Gemini CLI spawn & manager
apps/server/src/geminiCliServerManager.ts, apps/server/src/geminiCliServerManager.test.ts
Added buildGeminiSpawnOptions and resolveGeminiSpawnPlan to produce cross-platform spawn plans (Windows shim/node rewrites), accumulate/truncate stderr, immediate stdin end, and track/handle interrupted turns; tests validate spawn option/plan behavior.
Provider kind normalization
apps/server/src/provider/providerKind.ts
New normalizePersistedProviderKindName mapping supported kinds and legacy aliases (claudeCodeclaudeAgent, geminigeminiCli).
Persistence & event replay normalization
apps/server/src/persistence/Layers/OrchestrationEventStore.ts, ...OrchestrationEventStore.test.ts
Generalized JSON and string-field normalization across many provider-related fields during event replay; added test for normalizing legacy provider to geminiCli.
Provider session directory
apps/server/src/provider/Layers/ProviderSessionDirectory.ts, ...ProviderSessionDirectory.test.ts
Validate/normalize persisted provider names via normalization utility; add per-thread semaphore-backed upsert locks; tests assert legacy session normalization.
Migrations & migration tests
apps/server/src/persistence/Migrations.ts, .../020_NormalizeLegacyProviderKinds.ts, .../020_*.test.ts, .../021_RepairProjectionThreadProposedPlanImplementationColumns.ts, .../021_*.test.ts
Added migration 020 to rewrite legacy provider names across JSON/text columns and migration 021 to conditionally add missing projection columns; included comprehensive effect-driven DB tests.
Orchestration & adapter changes
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts, apps/server/src/provider/Layers/CursorAdapter.ts
Replaced synchronous threadModelSelections map access with Effect-wrapped accessors; CursorAdapter: added optional turnId checks in completeTurn, extended stopSessionInternal exit metadata and interrupt-handling behavior.
Web model-option refactor
apps/web/src/providerModelOptions.ts, apps/web/src/components/chat/ProviderModelPicker.tsx, apps/web/src/components/chat/ProviderModelPicker.logic.test.ts, apps/web/src/components/ChatView.tsx
Introduced centralized provider model-option builder/merger (buildModelOptionsByProvider, mergeDiscoveredModels, resolveModelOptionsByProvider), moved picker logic to shared module, updated ChatView to consume merged model lists; added tests.
Web settings & UI tweaks
apps/web/src/components/settings/SettingsPanels.tsx, ...SettingsPanels.browser.tsx, apps/web/src/components/ui/sidebar.tsx, apps/web/src/routes/_chat.$environmentId.$threadId.tsx
Updated provider settings shapes (titlelabel, added customModelExample), changed provider summary and model-binding flows to use centralized model options, adjusted sidebar controlled/uncontrolled behavior and memoized resizable config; added a browser test ensuring provider labels render.
Shell env capture
packages/shared/src/shell.ts, packages/shared/src/shell.test.ts
Detect fish shells and use fish-safe PATH capture (`printf '%s\n' "$PATH"
Contracts & shared model updates
packages/contracts/src/model.ts, packages/shared/src/model.ts
Populated opencode/kilo model option lists and aliases, changed defaults to provider-qualified slugs, and exported EMPTY_MODEL_CAPABILITIES as fallback constant.
Misc tests & small edits
apps/server/src/open.test.ts, packages/shared/src/shell.test.ts, apps/web/...
Added/updated unit tests corresponding to new command resolution, shell handling, model-option behaviors, and migration expectations.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Manager as "GeminiCliServerManager"
participant Resolver as "resolveCommandPath / commandPath"
participant FS as "Filesystem"
participant OS as "OS / spawn"
participant Child as "Child Process"
Manager->>Resolver: compute spawn plan (binaryPath, args, cwd, env)
Resolver->>FS: probe PATH entries / PATHEXT / exists
FS-->>Resolver: resolved command path or undefined
Manager->>OS: spawn(resolvedCmd, args, stdio=piped, shell=false)
OS-->>Child: child process created
Child-->>Manager: stdout/stderr events (accumulate stderr)
alt interrupt requested
Manager->>OS: killGeminiChildProcess (taskkill on Windows or child.kill)
OS-->>Child: SIGINT/terminated
end
Child-->>Manager: close(exitCode, signal)
Manager->>Manager: update session state (interruptedTurnId, activeProcess), compute completed/failed turn, include truncated stderr

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through code and chased old names away,
I stitched spawn plans for Windows and the fray,
I nudged migrations, rewrote provider lore,
Fish shells sing PATHs and models bloom once more,
A tiny rabbit cheers — the repo’s brighter today!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objective—integrating Gemini PR 54 onto the current main branch—and clearly summarizes the primary change from the developer's perspective.
Description check ✅ Passed The description is comprehensive and well-structured, explaining the rationale, included changes, and validation performed. However, it does not follow the repository's template structure (missing the standard 'What Changed', 'Why', 'UI Changes', and 'Checklist' sections), though the content provided is substantive and appropriate for the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/pr-54-followup-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ effective changed lines (test files excluded in mixed PRs). labels Apr 11, 2026
@aaditagrawal aaditagrawal marked this pull request as ready for review April 11, 2026 06:35
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/web/src/components/ui/sidebar.tsx (1)

113-133: ⚠️ Potential issue | 🟡 Minor

Add openProp to setOpen dependencies to prevent stale closure during mode transitions.

setOpen reads openProp at line 120 to determine whether to update internal state, but openProp is missing from the useCallback dependency array. When openProp changes but open remains the same (e.g., during controlled ↔ uncontrolled transitions), the callback won't be recreated and will reference a stale openProp value.

Suggested fix
   const setOpen = React.useCallback(
     async (value: boolean | ((value: boolean) => boolean)) => {
       const openState = typeof value === "function" ? value(open) : value;
       if (setOpenProp) {
         setOpenProp(openState);
       }

       if (openProp === undefined) {
         _setOpen(openState);
       }

       // This sets the cookie to keep the sidebar state.
       await cookieStore.set({
         expires: Date.now() + SIDEBAR_COOKIE_MAX_AGE * 1000,
         name: SIDEBAR_COOKIE_NAME,
         path: "/",
         value: String(openState),
       });
     },
-    [setOpenProp, open],
+    [setOpenProp, open, openProp],
   );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/ui/sidebar.tsx` around lines 113 - 133, The setOpen
callback captures openProp but doesn’t include it in its dependency array,
causing a stale closure when controlled/uncontrolled mode changes; update the
dependency list of the React.useCallback that defines setOpen to include
openProp so the callback is recreated when openProp changes, ensuring the
conditional that calls _setOpen(openState) behaves correctly; keep the existing
logic that sets the cookie (cookieStore.set) and references like
SIDEBAR_COOKIE_MAX_AGE, SIDEBAR_COOKIE_NAME and _setOpen unchanged.
apps/web/src/components/settings/SettingsPanels.tsx (1)

762-772: ⚠️ Potential issue | 🟡 Minor

Built-in duplicate checks currently depend on a live snapshot.

This only looks at serverProviders, so a provider with no published model list can still save a built-in slug as “custom”. Now that providerModelOptions already carries the fallback catalog, use that merged list for the duplicate check instead of live models only.

💡 Proposed fix
-      if (
-        serverProviders
-          .find((candidate) => candidate.provider === provider)
-          ?.models.some((option) => !option.isCustom && option.slug === normalized)
-      ) {
+      if (
+        providerModelOptions[provider].some(
+          (option) => option.isCustom !== true && option.slug === normalized,
+        )
+      ) {
         setCustomModelErrorByProvider((existing) => ({
           ...existing,
           [provider]: "That model is already built in.",
         }));
         return;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/settings/SettingsPanels.tsx` around lines 762 - 772,
The duplicate-built-in check currently inspects only serverProviders; update it
to use the merged/fallback list found in providerModelOptions instead so
providers without a live published list still block built-in slugs. Replace the
search over serverProviders with a lookup into providerModelOptions for the
given provider (e.g., providerModelOptions[provider] or find by .provider) and
test its .models array for any non-custom option whose slug matches normalized,
then call setCustomModelErrorByProvider(...) as before if a match is found.
packages/contracts/src/model.ts (1)

369-397: 🛠️ Refactor suggestion | 🟠 Major

Move these provider model tables out of @t3tools/contracts.

The new opencode/kilo catalogs, defaults, and alias maps add more runtime provider metadata to the contracts package. That keeps pushing @t3tools/contracts beyond schemas/types and into runtime behavior, which makes the package boundary harder to maintain.

As per coding guidelines, packages/contracts/**/*.ts: Keep the @t3tools/contracts package schema-only — no runtime logic.

Also applies to: 410-413, 486-501

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/contracts/src/model.ts` around lines 369 - 397, The arrays opencode,
geminiCli, amp, kilo and the related catalog/default/alias maps are runtime
provider metadata and must be removed from the contracts package; extract these
constants into a new runtime package (e.g., a providers/provider-models package)
and export them from there, leaving only types/interfaces in packages/contracts
(keep contracts schema-only). Update all imports that referenced
opencode/geminiCli/amp/kilo or the alias maps to point to the new runtime
package, and ensure packages/contracts/src/model.ts retains only type
definitions (no runtime tables or default data).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/server/src/commandPath.ts`:
- Around line 42-61: The current logic drops the original command when it has an
extension not in PATHEXT; update the candidate generation in the
extension-present branch (variables: extension, normalizedExtension,
windowsPathExtensions, commandWithoutExtension) to always include the original
command string as a candidate. Concretely, when extension.length > 0, return a
Set that contains command plus the existing variants (`commandWithoutExtension +
normalizedExtension` and its lowercase) so explicit paths with unknown
extensions are preserved.

In `@apps/web/src/components/settings/SettingsPanels.tsx`:
- Around line 1215-1217: The current lookup uses PROVIDER_LABEL_BY_PROVIDER
which contains entries for every provider and therefore always overrides
providerCard.title; change the logic in the providerDisplayName assignment (the
providerDisplayName variable) to render providerCard.title directly (or flip the
precedence so providerCard.title is used before the map), or alternatively
update the shared PROVIDER_LABEL_BY_PROVIDER/PROVIDER_DISPLAY_NAMES mapping
before this render so the new exact-text labels are present; locate the
providerDisplayName assignment and replace the lookup with providerCard.title
(or swap the null-coalescing order) to ensure the renamed provider titles are
actually displayed.

In `@apps/web/src/providerModelOptions.ts`:
- Around line 59-69: The Copilot branch currently replaces the built-in fallback
catalog with only the discovered snapshot (enriched + customOnly), removing any
built-in models not present in discovery; instead merge the enriched snapshot
back into the existing catalog like other providers do: compute enriched as you
already do (using baseTiers and dedupedModels), then combine/merge that enriched
list with the originals from base[provider] (preserving built-in entries not in
dedupedModels) before assigning to result[provider] so the fallback copilot
models remain available. Reference: provider variable, baseTiers, enriched,
customOnly and result[provider].

In `@CONTRIBUTING.md`:
- Line 29: Update the example GitHub CLI command in CONTRIBUTING.md to
explicitly set the base branch to main by adding the --base main flag to the
provided gh pr create command (the current example is "gh pr create --repo
aaditagrawal/t3code"); modify that line so the command reads with --base main to
ensure PRs target the fork's main branch.

---

Outside diff comments:
In `@apps/web/src/components/settings/SettingsPanels.tsx`:
- Around line 762-772: The duplicate-built-in check currently inspects only
serverProviders; update it to use the merged/fallback list found in
providerModelOptions instead so providers without a live published list still
block built-in slugs. Replace the search over serverProviders with a lookup into
providerModelOptions for the given provider (e.g.,
providerModelOptions[provider] or find by .provider) and test its .models array
for any non-custom option whose slug matches normalized, then call
setCustomModelErrorByProvider(...) as before if a match is found.

In `@apps/web/src/components/ui/sidebar.tsx`:
- Around line 113-133: The setOpen callback captures openProp but doesn’t
include it in its dependency array, causing a stale closure when
controlled/uncontrolled mode changes; update the dependency list of the
React.useCallback that defines setOpen to include openProp so the callback is
recreated when openProp changes, ensuring the conditional that calls
_setOpen(openState) behaves correctly; keep the existing logic that sets the
cookie (cookieStore.set) and references like SIDEBAR_COOKIE_MAX_AGE,
SIDEBAR_COOKIE_NAME and _setOpen unchanged.

In `@packages/contracts/src/model.ts`:
- Around line 369-397: The arrays opencode, geminiCli, amp, kilo and the related
catalog/default/alias maps are runtime provider metadata and must be removed
from the contracts package; extract these constants into a new runtime package
(e.g., a providers/provider-models package) and export them from there, leaving
only types/interfaces in packages/contracts (keep contracts schema-only). Update
all imports that referenced opencode/geminiCli/amp/kilo or the alias maps to
point to the new runtime package, and ensure packages/contracts/src/model.ts
retains only type definitions (no runtime tables or default data).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a0b63d5-4111-44e2-848e-76078496bc93

📥 Commits

Reviewing files that changed from the base of the PR and between ae1ddd4 and 6c0dcb7.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (34)
  • CONTRIBUTING.md
  • README.md
  • apps/desktop/package.json
  • apps/server/package.json
  • apps/server/src/commandPath.ts
  • apps/server/src/geminiCliServerManager.test.ts
  • apps/server/src/geminiCliServerManager.ts
  • apps/server/src/open.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
  • apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts
  • apps/server/src/persistence/Layers/OrchestrationEventStore.ts
  • apps/server/src/persistence/Migrations.ts
  • apps/server/src/persistence/Migrations/020_NormalizeLegacyProviderKinds.test.ts
  • apps/server/src/persistence/Migrations/020_NormalizeLegacyProviderKinds.ts
  • apps/server/src/persistence/Migrations/021_RepairProjectionThreadProposedPlanImplementationColumns.test.ts
  • apps/server/src/persistence/Migrations/021_RepairProjectionThreadProposedPlanImplementationColumns.ts
  • apps/server/src/provider/Layers/CursorAdapter.ts
  • apps/server/src/provider/Layers/ProviderSessionDirectory.test.ts
  • apps/server/src/provider/Layers/ProviderSessionDirectory.ts
  • apps/server/src/provider/providerKind.ts
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/chat/ProviderModelPicker.logic.test.ts
  • apps/web/src/components/chat/ProviderModelPicker.tsx
  • apps/web/src/components/settings/SettingsPanels.browser.tsx
  • apps/web/src/components/settings/SettingsPanels.tsx
  • apps/web/src/components/ui/sidebar.tsx
  • apps/web/src/providerModelOptions.ts
  • apps/web/src/providerModels.ts
  • apps/web/src/routes/_chat.$environmentId.$threadId.tsx
  • package.json
  • packages/contracts/src/model.ts
  • packages/shared/src/model.ts
  • packages/shared/src/shell.test.ts
  • packages/shared/src/shell.ts

@aaditagrawal
Copy link
Copy Markdown
Owner Author

Pushed follow-up commit abc8bcb1 (fix pr 58 ci and review feedback).

Addressed here:

  • fixed the failing browser test by making Settings render the same provider labels as the chat picker (GitHub Copilot, Claude Code, Cursor Agent, AMPcode) via the per-card titles in SettingsPanels.tsx
  • preserved Copilot fallback catalog entries when discovery only returns a partial snapshot in providerModelOptions.ts
  • tightened Windows command resolution so explicit command paths are preserved while dotted bare commands still expand through PATHEXT in commandPath.ts
  • made the CONTRIBUTING example explicit with gh pr create --repo aaditagrawal/t3code --base main
  • added regression coverage in open.test.ts and ProviderModelPicker.logic.test.ts

Local verification:

  • bun run --cwd apps/web test:browser src/components/settings/SettingsPanels.browser.tsx
  • bun run --cwd apps/web test src/components/chat/ProviderModelPicker.logic.test.ts
  • bun run --cwd apps/server test src/open.test.ts -t isCommandAvailable
  • bun fmt
  • bun lint
  • bun typecheck

lint and typecheck still print the repo's existing warning-only baseline, but both exit cleanly.

@aaditagrawal aaditagrawal merged commit fc457dc into main Apr 11, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ effective changed lines (test files excluded in mixed PRs). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants