Skip to content

fix(server): share global memoMap in TCP listener to dedupe singleton services#28152

Open
sjawhar wants to merge 1 commit into
anomalyco:devfrom
sjawhar:fix/server-listener-shared-memomap
Open

fix(server): share global memoMap in TCP listener to dedupe singleton services#28152
sjawhar wants to merge 1 commit into
anomalyco:devfrom
sjawhar:fix/server-listener-shared-memomap

Conversation

@sjawhar
Copy link
Copy Markdown

@sjawhar sjawhar commented May 18, 2026

Issue for this PR

Closes #28037

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

#28037 has the full root-cause writeup. The fix is small: startListener was calling Layer.makeMemoMapUnsafe(), so the TCP listener's singleton services lived in a different memoMap from Server.Default() / AppRuntime. This PR passes the shared memoMap from @opencode-ai/core/effect/memo-map to Layer.buildWithMemoMap instead.

The function-call layers inside listenerLayer (HttpRouter.serve(...), serverLayer({port, hostname}), ConfigProvider.layer(...)) return fresh Layer references per call, so they stay listener-local — only the Service-tagged singletons get deduplicated.

Beyond #28037's permission-reply symptom, the same bug also produces parallel SessionRunState runners for one session under heavy use: pressing Esc cancels one runner while a second keeps streaming, eventually accumulating two trailing assistant messages.

How did you verify your code works?

  • Running on a custom build across 9 active TUI sessions for several hours — the parallel-streams symptom no longer reproduces.
  • Regression tests in test/effect/run-service.test.ts assert that Layer.buildWithMemoMap(SessionRunState.defaultLayer, memoMap, scope) resolves to the same Service instance as AppRuntime.runPromise(SessionRunState.Service), and that a fresh MemoMap produces a separate instance.
  • bun typecheck clean. bun test test/effect/ passes. The session/server suites show no fix-induced regressions; remaining timeouts are pre-existing flakes on dev, confirmed by running the same tests isolated against the parent commit.

Screenshots / recordings

N/A — server-internal layer wiring.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@legion-implementer legion-implementer Bot force-pushed the fix/server-listener-shared-memomap branch from f3f4f8e to bb7bba1 Compare May 26, 2026 08:09
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.

Plugin permission replies via SDK client are silently dropped on v1.14.51+ (Server.Default and TCP listener use different memoMaps)

1 participant