Skip to content

bump effect to latest beta#1866

Open
juliusmarminge wants to merge 18 commits intomainfrom
t3code/bump-effect-beta
Open

bump effect to latest beta#1866
juliusmarminge wants to merge 18 commits intomainfrom
t3code/bump-effect-beta

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented Apr 9, 2026

Summary

  • Migrates server service tags from ServiceMap.Service to Context.Service and updates runtime plumbing to use Effect Context APIs.
  • Fixes CLI boolean precedence so explicit false flags override env and bootstrap defaults, and adds coverage for canonical --no-<flag> negation.
  • Refactors the web chat composer into dedicated components and hooks, while preserving draft targeting and trigger state across prompt resets.
  • Updates cache and runtime helpers to match current Effect APIs and adds/adjusts tests across CLI, git, provider, and desktop build flows.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test

Note

Medium Risk
Broad Effect beta migration touches many core server service tags, cache construction, and branded ID creation, so regressions are possible despite being mostly mechanical. CLI config precedence semantics change (explicit false flags now win), which may alter startup behavior in some environments.

Overview
Bumps usage to newer Effect beta APIs by migrating many server service tags from ServiceMap.Service to Context.Service, updating call sites to use Context-based runtime plumbing, and adjusting Cache.makeWith/Effect.tryPromise usage to match new signatures.

Fixes resolveServerConfig boolean option precedence so explicit CLI false values (and canonical --no-<flag> negations) are preserved over env/bootstrap defaults, and adds/updates CLI tests to cover this behavior.

Replaces widespread branded-id constructors from *.makeUnsafe(...) to *.make(...) across server/desktop code and tests (e.g., EventId, ThreadId, TurnId, CheckpointRef, AuthSessionId).

Reviewed by Cursor Bugbot for commit b6e4505. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Bump Effect ecosystem dependencies to beta.45 and migrate service classes to Context.Service

  • Updates effect and all @effect/* packages from 4.0.0-beta.43 to 4.0.0-beta.45 in package.json.
  • Migrates ~40 service class declarations from ServiceMap.Service to Context.Service across the server, matching the new Effect API.
  • Replaces Effect.services() with Effect.context<never>() and updates Layer.effectServices/ServiceMap.make to Layer.effectContext/Context.make at all affected call sites.
  • Updates Cache.makeWith call signatures to pass the lookup function as the first argument and remaining options as a second object.
  • Converts Schema.withDecodingDefault and Schema.withConstructorDefault thunks (e.g. () => false) to Effect.succeed(false) across contracts schemas.
  • Replaces all *.makeUnsafe(...) branded ID constructors with *.make(...) throughout production code and tests.
  • Fixes resolveBooleanFlag in scripts/build-desktop-artifact.ts and resolveServerConfig in apps/server/src/cli.ts so explicit false CLI flags are no longer overridden by env or bootstrap values.
  • Behavioral Change: UserInputQuestion schema constructor default for its boolean field now resolves to false instead of Option.some(false).

Macroscope summarized b6e4505.

juliusmarminge and others added 11 commits April 9, 2026 11:52
Typing in the composer caused the entire ChatView (~4900 lines) to
re-render on every keystroke because `useComposerThreadDraft` subscribed
to the full draft including `prompt`. This cascaded to MessagesTimeline,
ChatHeader, BranchToolbar, PlanSidebar, and terminal drawers.

- Extract `ChatComposer` (memo'd) that owns the prompt/images/terminal
  context store subscriptions, all composer-local state, and derived
  values (menu items, provider state, send state, debounced queries).
  ChatView now uses granular store selectors for only `runtimeMode`,
  `interactionMode`, and `activeProvider` — none of which change on
  keystroke.

- Extract `ExpandedImageDialog` (memo'd) for the image preview modal.

- Wrap `BranchToolbar` in `memo` and stabilize `onRevertUserMessage`
  with `useCallback` so already-memo'd children (MessagesTimeline,
  ChatHeader) properly skip re-renders.

- Expose `ChatComposerHandle` for cross-cutting operations (focus,
  cursor reset, terminal context insertion, send context).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…-extraction

# Conflicts:
#	apps/web/src/components/ChatView.tsx
- Use the resolved composer draft target when clearing and restoring state
- Keep draft images and terminal contexts intact across sends
- Make Enter send while Shift+Enter inserts a newline
- Split footer composer controls into memoized subcomponents
- Separate reusable new-thread logic from route-aware hook
- Add composer draft model selector and thread-jump hint cleanup
- Pass prompt context into cursor resets
- Recompute trigger after send/retry mutations
- Use the composer's send context as the source of truth
- Remove fallback to stale selected provider state
- Migrate service tags and context access to Effect `Context`
- Fix boolean flag precedence so explicit `false` overrides env/bootstrap
- Update related caches, tests, and CLI negation handling
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1c7b858a-230b-43e0-a101-f378b97ac972

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/bump-effect-beta

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

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 9, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Nested Effect in mock unref property value
    • Replaced Effect.succeed(Effect.void) with Effect.void to avoid creating a nested Effect<Effect<void>> in the mock.

Create PR

Or push these changes by commenting:

@cursor push 1e8c525414
Preview (1e8c525414)
diff --git a/apps/server/src/provider/Layers/ProviderRegistry.test.ts b/apps/server/src/provider/Layers/ProviderRegistry.test.ts
--- a/apps/server/src/provider/Layers/ProviderRegistry.test.ts
+++ b/apps/server/src/provider/Layers/ProviderRegistry.test.ts
@@ -44,7 +44,7 @@
     exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(result.code)),
     isRunning: Effect.succeed(false),
     kill: () => Effect.void,
-    unref: Effect.succeed(Effect.void),
+    unref: Effect.void,
     stdin: Sink.drain,
     stdout: Stream.make(encoder.encode(result.stdout)),
     stderr: Stream.make(encoder.encode(result.stderr)),

You can send follow-ups to the cloud agent here.

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 9, 2026

Approvability

Verdict: Needs human review

Diff is too large for automated approval analysis. A human reviewer should evaluate this PR.

No code changes detected at b6e4505. Prior analysis still applies.

You can customize Macroscope's approvability policy. Learn more.

@github-actions github-actions bot added size:XL 500-999 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Apr 9, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Redundant lockedProvider computation creates subtle guard mismatch
    • Removed the redundant deriveLockedProvider re-derivation and effectiveLockedProvider merge in ChatComposer, so it now uses the parent's lockedProvider prop directly as the single source of truth, eliminating the potential divergence with the parent's callback guard.

Create PR

Or push these changes by commenting:

@cursor push 0db96d6396
Preview (0db96d6396)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx
--- a/apps/web/src/components/chat/ChatComposer.tsx
+++ b/apps/web/src/components/chat/ChatComposer.tsx
@@ -39,12 +39,8 @@
   expandCollapsedComposerCursor,
   replaceTextRange,
 } from "../../composer-logic";
+import { deriveComposerSendState, readFileAsDataUrl } from "../ChatView.logic";
 import {
-  deriveComposerSendState,
-  deriveLockedProvider,
-  readFileAsDataUrl,
-} from "../ChatView.logic";
-import {
   type ComposerImageAttachment,
   type DraftId,
   type PersistedComposerImageAttachment,
@@ -546,18 +542,11 @@
     const selectedProviderByThreadId = composerDraft.activeProvider ?? null;
     const threadProvider =
       activeThreadModelSelection?.provider ?? activeProjectDefaultModelSelection?.provider ?? null;
-    const computedLockedProvider = deriveLockedProvider({
-      thread: activeThread,
-      selectedProvider: selectedProviderByThreadId,
-      threadProvider,
-    });
-    const effectiveLockedProvider = lockedProvider ?? computedLockedProvider;
-
     const unlockedSelectedProvider = resolveSelectableProvider(
       providerStatuses,
       selectedProviderByThreadId ?? threadProvider ?? "codex",
     );
-    const selectedProvider: ProviderKind = effectiveLockedProvider ?? unlockedSelectedProvider;
+    const selectedProvider: ProviderKind = lockedProvider ?? unlockedSelectedProvider;
 
     const { modelOptions: composerModelOptions, selectedModel } = useEffectiveComposerModelState({
       threadRef: composerDraftTarget,
@@ -612,7 +601,7 @@
     const searchableModelOptions = useMemo(
       () =>
         AVAILABLE_PROVIDER_OPTIONS.filter(
-          (option) => effectiveLockedProvider === null || option.value === effectiveLockedProvider,
+          (option) => lockedProvider === null || option.value === lockedProvider,
         ).flatMap((option) =>
           modelOptionsByProvider[option.value].map(({ slug, name }) => ({
             provider: option.value,
@@ -624,7 +613,7 @@
             searchProvider: option.label.toLowerCase(),
           })),
         ),
-      [effectiveLockedProvider, modelOptionsByProvider],
+      [lockedProvider, modelOptionsByProvider],
     );
 
     // ------------------------------------------------------------------
@@ -1825,7 +1814,7 @@
                     compact={isComposerFooterCompact}
                     provider={selectedProvider}
                     model={selectedModelForPickerWithCustomFallback}
-                    lockedProvider={effectiveLockedProvider}
+                    lockedProvider={lockedProvider}
                     providers={providerStatuses}
                     modelOptionsByProvider={modelOptionsByProvider}
                     {...(composerProviderState.modelPickerIconClassName

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 333b878. Configure here.

macroscopeapp[bot]
macroscopeapp bot previously approved these changes Apr 9, 2026
- Replace `makeUnsafe` calls with validated `make` constructors
- Update affected integration and unit tests to match the safer ID flow
@macroscopeapp macroscopeapp bot dismissed their stale review April 10, 2026 00:14

Dismissing prior approval to re-evaluate ca0d44f

@juliusmarminge juliusmarminge changed the title Adopt Effect Context services and tighten composer state bump effect to latest beta Apr 10, 2026
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Low

const runtime = ManagedRuntime.make(layer);

The runtime variable declared at line 238 shadows the module-level runtime declared at line 69, so the cleanup in afterEach (lines 82-85) disposes the wrong (uninitialized) variable while the actual ManagedRuntime created by each test is leaked. This causes SQLite connections and other resources to accumulate across tests.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts around line 238:

The `runtime` variable declared at line 238 shadows the module-level `runtime` declared at line 69, so the cleanup in `afterEach` (lines 82-85) disposes the wrong (uninitialized) variable while the actual `ManagedRuntime` created by each test is leaked. This causes SQLite connections and other resources to accumulate across tests.

Evidence trail:
- apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts lines 69-72 (REVIEWED_COMMIT): module-level `let runtime = null`
- apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts lines 82-85 (REVIEWED_COMMIT): `afterEach` disposes `runtime` which is always null
- apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts line 238 (REVIEWED_COMMIT): `const runtime = ManagedRuntime.make(layer)` - local declaration shadows module-level
- apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts lines 273-288 (REVIEWED_COMMIT): `createHarness` returns object without runtime, runtime is never assigned to module-level variable
- git_grep results: only assignments are line 85 (`runtime = null`) and line 238 (`const runtime = ...`), confirming no assignment to module-level runtime

juliusmarminge and others added 4 commits April 9, 2026 17:41
- Switch the test fixture to `EnvironmentId.make`
- Keep replay recovery coverage aligned with validated IDs
- Read bootstrap envelope once and reuse it
- Preserve headless startup overrides while simplifying precedence checks
- Use bootstrap values directly for observability settings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). 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.

1 participant