|
|
@@ -4,43 +4,42 @@ Generated for `createSimulatedRoutes` in `packages/opencode/src/server/routes/in
|
|
|
|
|
|
## Notation
|
|
|
|
|
|
-- `→ X` means "yields `X.Service` from its `Effect.gen` body"
|
|
|
+- `→ X` means "yields `X.Service` from its `Effect.gen` body at layer init (a true `RIn` of `.layer`)"
|
|
|
- `(lazy)` means "uses `InstanceState.context` or similar at call time, not at layer construction"
|
|
|
- `(opt)` means "uses `Effect.serviceOption(X)` — not strictly required"
|
|
|
+- `(internal)` means "satisfied internally by the `.layer` itself via `Layer.provide(...)`, NOT a residual requirement"
|
|
|
|
|
|
-## Service → Dependencies
|
|
|
+## Service → Dependencies (current, post-rebase)
|
|
|
|
|
|
```
|
|
|
─── External / Platform ─────────────────────────────────────────
|
|
|
NodePath (no app deps) provides Path.Path
|
|
|
-HttpClient (FetchHttp) (no app deps) provides HttpClient.HttpClient
|
|
|
+FetchHttpClient (no app deps) provides HttpClient.HttpClient
|
|
|
HttpServer.layerServices (no app deps)
|
|
|
ChildProcessSpawner (from SimulationSpawner) (no app deps)
|
|
|
|
|
|
─── Leaf services (no app deps) ─────────────────────────────────
|
|
|
Global (no app deps)
|
|
|
-Env (no app deps)
|
|
|
-Bus (lazy via InstanceState)
|
|
|
-SyncEvent (lazy via InstanceState)
|
|
|
-AccountRepo (uses Database directly)
|
|
|
-PtyTicket (Cache only)
|
|
|
-Truncate → AppFileSystem (+ Config opt)
|
|
|
+Env (no app deps — uses InstanceState.make, no Service yields)
|
|
|
+Bus (no app deps — uses InstanceState.make, no Service yields)
|
|
|
+SyncEvent → RuntimeFlags, Bus (NEW — previously listed as leaf/lazy)
|
|
|
+AccountRepo (no app deps — pure DB closures)
|
|
|
+PtyTicket (no app deps — Cache only)
|
|
|
+Truncate → AppFileSystem
|
|
|
|
|
|
─── Middleware/route layers (no app service deps) ───────────────
|
|
|
errorLayer
|
|
|
compressionLayer → HttpServerRequest (builtin)
|
|
|
corsVaryFix
|
|
|
fenceLayer → HttpServerRequest (builtin)
|
|
|
-runtime
|
|
|
simulationShareNextLayer provides ShareNext (Layer.succeed override)
|
|
|
|
|
|
─── Simulation overrides ────────────────────────────────────────
|
|
|
-simulationBoundary:
|
|
|
- SimulationFileSystem provides AppFileSystem + FileSystem.FileSystem(noop)
|
|
|
- SimulationSpawner provides ChildProcessSpawner
|
|
|
- SimulationNetwork provides SimulationNetwork.Service + HttpClient
|
|
|
- (httpClientLayer → SimulationNetwork)
|
|
|
-
|
|
|
+SimulationFileSystem provides AppFileSystem (does NOT provide FileSystem.FileSystem;
|
|
|
+ tier0 also merges FileSystem.layerNoop({}) for that tag)
|
|
|
+SimulationSpawner provides ChildProcessSpawner (Layer.succeed; no deps)
|
|
|
+SimulationNetwork provides SimulationNetwork.Service + HttpClient.HttpClient
|
|
|
+ (httpClientLayer composed inside `layer(options)`)
|
|
|
SimulationGit → AppFileSystem (overrides Git tag)
|
|
|
SimulationProvider → Simulation (overrides Provider tag)
|
|
|
Simulation → AppFileSystem, SimulationNetwork
|
|
|
@@ -48,31 +47,34 @@ Simulation → AppFileSystem, SimulationNetwork
|
|
|
─── Core services ───────────────────────────────────────────────
|
|
|
EffectFlock → Global, AppFileSystem
|
|
|
Auth → AppFileSystem
|
|
|
+McpAuth → AppFileSystem
|
|
|
Account → AccountRepo, HttpClient
|
|
|
Npm → AppFileSystem, Global, FileSystem.FileSystem, EffectFlock
|
|
|
Config → AppFileSystem, Auth, Account, Env, Npm
|
|
|
Permission → Bus
|
|
|
-Plugin → Bus, Config
|
|
|
+Plugin → Bus, Config, RuntimeFlags (NEW: RuntimeFlags)
|
|
|
Discovery → AppFileSystem, Path, HttpClient
|
|
|
-Skill → Discovery, Config, Bus, AppFileSystem, Global
|
|
|
+Skill → Discovery, Config, Bus, AppFileSystem, Global,
|
|
|
+ RuntimeFlags (NEW: RuntimeFlags)
|
|
|
SystemPrompt → Skill
|
|
|
|
|
|
─── File / git ──────────────────────────────────────────────────
|
|
|
Ripgrep → AppFileSystem, HttpClient, ChildProcessSpawner
|
|
|
File → AppFileSystem, Ripgrep, Git, Scope
|
|
|
FileWatcher → Config, Git
|
|
|
-Format → Config, ChildProcessSpawner
|
|
|
-Snapshot → AppFileSystem, ChildProcessSpawner, Config
|
|
|
+Format → Config, AppProcess, RuntimeFlags (CHANGED: was ChildProcessSpawner; now AppProcess + RuntimeFlags)
|
|
|
+Snapshot → AppFileSystem, AppProcess, Config (CHANGED: was ChildProcessSpawner)
|
|
|
Storage → AppFileSystem, Git
|
|
|
Vcs → Git, Bus, Scope
|
|
|
-Worktree → Scope, AppFileSystem, Path, ChildProcessSpawner,
|
|
|
- Git, Project, InstanceStore
|
|
|
-Project → AppFileSystem, Path, ChildProcessSpawner, Bus
|
|
|
+Worktree → Scope, AppFileSystem, Path, AppProcess,
|
|
|
+ Git, Project, InstanceStore (CHANGED: AppProcess instead of ChildProcessSpawner)
|
|
|
+Project → AppFileSystem, Path, ChildProcessSpawner,
|
|
|
+ Bus, RuntimeFlags (NEW: RuntimeFlags)
|
|
|
|
|
|
─── Provider / LSP / MCP ────────────────────────────────────────
|
|
|
ModelsDev → AppFileSystem, HttpClient
|
|
|
ProviderAuth → Auth, Plugin
|
|
|
-LSP → Config
|
|
|
+LSP → Config, RuntimeFlags (NEW: RuntimeFlags)
|
|
|
McpAuth → AppFileSystem
|
|
|
MCP → ChildProcessSpawner, McpAuth, Bus, Config
|
|
|
|
|
|
@@ -80,98 +82,146 @@ MCP → ChildProcessSpawner, McpAuth, Bus, Config
|
|
|
Todo → Bus
|
|
|
Question → Bus
|
|
|
SessionStatus → Bus
|
|
|
-SessionRunState → SessionStatus
|
|
|
-Instruction → Config, AppFileSystem, Global, HttpClient
|
|
|
+SessionRunState → BackgroundJob, SessionStatus (NEW: BackgroundJob)
|
|
|
+Instruction → Config, AppFileSystem, Global, HttpClient,
|
|
|
+ RuntimeFlags (NEW: RuntimeFlags)
|
|
|
|
|
|
-Session → Bus, Storage, SyncEvent
|
|
|
+Session → BackgroundJob, Bus, Storage, SyncEvent,
|
|
|
+ RuntimeFlags (NEW: BackgroundJob, RuntimeFlags)
|
|
|
SessionSummary → Session, Snapshot, Storage, Bus
|
|
|
|
|
|
SessionRevert → Session, Snapshot, Storage, Bus,
|
|
|
SessionSummary, SessionRunState, SyncEvent
|
|
|
-LLM → Auth, Config, Provider, Plugin, Permission
|
|
|
+LLM → Auth, Config, Provider, Plugin, RuntimeFlags (CHANGED: Permission satisfied internally;
|
|
|
+ (Permission satisfied internally via .layer) RuntimeFlags is new)
|
|
|
|
|
|
-Agent → Config, Auth, Plugin, Skill, Provider
|
|
|
+Agent → Config, Auth, Plugin, Skill, Provider,
|
|
|
+ RuntimeFlags (NEW: RuntimeFlags)
|
|
|
Command → Config, MCP, Skill
|
|
|
|
|
|
SessionProcessor → Session, Config, Bus, Snapshot, Agent, LLM,
|
|
|
- Permission, Plugin, SessionSummary, Scope,
|
|
|
- SessionStatus
|
|
|
+ Permission, Plugin, SessionSummary,
|
|
|
+ SessionStatus, Image, EventV2Bridge,
|
|
|
+ RuntimeFlags, Scope (NEW: Image, EventV2Bridge, RuntimeFlags)
|
|
|
SessionCompaction → Bus, Config, Session, Agent, Plugin,
|
|
|
- SessionProcessor, Provider
|
|
|
+ SessionProcessor, Provider, EventV2Bridge,
|
|
|
+ RuntimeFlags (NEW: EventV2Bridge, RuntimeFlags)
|
|
|
SessionPrompt → Bus, SessionStatus, Session, Agent, Provider,
|
|
|
SessionProcessor, SessionCompaction, Plugin,
|
|
|
Command, Config, Permission, AppFileSystem,
|
|
|
MCP, LSP, ToolRegistry, Truncate,
|
|
|
ChildProcessSpawner, Scope, Instruction,
|
|
|
SessionRunState, SessionRevert,
|
|
|
- SessionSummary, SystemPrompt, LLM
|
|
|
+ SessionSummary, SystemPrompt, LLM,
|
|
|
+ Image, Reference, EventV2Bridge,
|
|
|
+ RuntimeFlags (NEW: Image, Reference, EventV2Bridge, RuntimeFlags)
|
|
|
|
|
|
-ToolRegistry → Config, Plugin, Agent, Skill, Truncate (+ many
|
|
|
- tool deps: Question, Todo, Session, Provider,
|
|
|
- Git, LSP, Instruction, AppFileSystem, Bus,
|
|
|
- HttpClient, ChildProcessSpawner, Ripgrep,
|
|
|
- Format, Truncate)
|
|
|
+ToolRegistry → Config, Plugin, Question, Todo, Agent, Skill,
|
|
|
+ Session, SessionStatus, BackgroundJob,
|
|
|
+ Provider, Git, Reference, LSP, Instruction,
|
|
|
+ AppFileSystem, Bus, HttpClient,
|
|
|
+ ChildProcessSpawner, Ripgrep, Format,
|
|
|
+ Truncate, RuntimeFlags (NEW: BackgroundJob, Reference, RuntimeFlags)
|
|
|
|
|
|
─── Share / Workspace ───────────────────────────────────────────
|
|
|
ShareNext (provided by simulationShareNextLayer in sim)
|
|
|
-SessionShare → Config, Session, ShareNext, Scope, SyncEvent
|
|
|
+SessionShare → Config, Session, ShareNext, Scope, SyncEvent,
|
|
|
+ RuntimeFlags (NEW: RuntimeFlags)
|
|
|
Workspace → Auth, Session, SessionPrompt, HttpClient,
|
|
|
- SyncEvent, Vcs
|
|
|
- (also uses InstanceStore/Bootstrap via
|
|
|
- Effect.provide inside runInWorkspace)
|
|
|
+ SyncEvent, Vcs, AppFileSystem, RuntimeFlags (NEW: AppFileSystem (explicit), RuntimeFlags)
|
|
|
|
|
|
─── Misc ────────────────────────────────────────────────────────
|
|
|
-Installation → HttpClient, ChildProcessSpawner
|
|
|
+Installation → HttpClient, AppProcess (CHANGED: AppProcess instead of ChildProcessSpawner)
|
|
|
Pty → Config, Bus, Plugin
|
|
|
|
|
|
─── Instance lifecycle ──────────────────────────────────────────
|
|
|
InstanceBootstrap → Config, File, FileWatcher, Format, LSP, Plugin,
|
|
|
- Project, ShareNext, Snapshot, Vcs
|
|
|
+ Project, Reference, ShareNext, Snapshot, Vcs (NEW: Reference)
|
|
|
InstanceStore → Project, InstanceBootstrap, Scope
|
|
|
|
|
|
Observability (no app deps; provides Logger + tracer)
|
|
|
```
|
|
|
|
|
|
+## NEW dependencies introduced since previous graph
|
|
|
+
|
|
|
+The rebase pulled in several new cross-cutting services that need to be
|
|
|
+satisfied somewhere in tier0/tier1 of the simulated chain. They are NOT yet
|
|
|
+listed in the `Tier*Services` unions or merged into any tier in `server.ts`:
|
|
|
+
|
|
|
+```
|
|
|
+RuntimeFlags.Service — yielded by ~17 services (Plugin, Skill, Project,
|
|
|
+ Session, SyncEvent, Format, LSP, Instruction,
|
|
|
+ Agent, LLM, SessionShare, SessionProcessor,
|
|
|
+ SessionCompaction, ToolRegistry, SessionPrompt,
|
|
|
+ Workspace, SessionRunState).
|
|
|
+ Source: `@/effect/runtime-flags`.
|
|
|
+
|
|
|
+AppProcess.Service — yielded by Installation, Format, Snapshot,
|
|
|
+ Worktree (and prod Git, but sim uses SimulationGit).
|
|
|
+ Source: presumed `@opencode-ai/core/app-process`
|
|
|
+ or similar — needs `AppProcess.defaultLayer`.
|
|
|
+
|
|
|
+BackgroundJob.Service — yielded by Session, SessionRunState, ToolRegistry.
|
|
|
+ Needs `BackgroundJob.defaultLayer`.
|
|
|
+
|
|
|
+Image.Service — yielded by SessionProcessor, SessionPrompt.
|
|
|
+
|
|
|
+EventV2Bridge.Service — yielded by SessionProcessor, SessionCompaction,
|
|
|
+ SessionPrompt. Source: `@/event-v2-bridge` (already
|
|
|
+ imported in server.ts but never added to a tier).
|
|
|
+
|
|
|
+Reference.Service — yielded by ToolRegistry, SessionPrompt,
|
|
|
+ InstanceBootstrap.
|
|
|
+```
|
|
|
+
|
|
|
## Dependency Tiers (topological order)
|
|
|
|
|
|
Roughly, build order from leaves to roots:
|
|
|
|
|
|
```
|
|
|
Tier 0 (no deps):
|
|
|
- Global, Env, NodePath, AccountRepo, PtyTicket, Bus (lazy),
|
|
|
- SyncEvent (lazy), AppFileSystem (sim), ChildProcessSpawner (sim),
|
|
|
- HttpClient (sim), SimulationNetwork, errorLayer, compressionLayer,
|
|
|
- corsVaryFix, fenceLayer, runtime, simulationShareNextLayer
|
|
|
+ Global, Env, NodePath, AccountRepo, PtyTicket, Bus, SyncEvent,
|
|
|
+ AppFileSystem (sim), ChildProcessSpawner (sim), HttpClient (sim),
|
|
|
+ SimulationNetwork, FileSystem.layerNoop, simulationShareNextLayer
|
|
|
+ + (NEW REQUIRED) RuntimeFlags, AppProcess, BackgroundJob, Image,
|
|
|
+ EventV2Bridge, Reference
|
|
|
+ (SyncEvent now depends on RuntimeFlags + Bus, so it's actually tier 1.)
|
|
|
|
|
|
Tier 1:
|
|
|
Auth, Truncate, EffectFlock, Permission, Todo, Question,
|
|
|
- SessionStatus, McpAuth, Discovery, SimulationGit, Simulation,
|
|
|
- Ripgrep, Storage, Vcs
|
|
|
+ SessionStatus, McpAuth, Discovery, SimulationGit, Ripgrep, Account,
|
|
|
+ SyncEvent (needs RuntimeFlags + Bus)
|
|
|
|
|
|
Tier 2:
|
|
|
- Account, Npm, LSP, Skill, SessionRunState, ModelsDev, File,
|
|
|
- Project, Worktree (needs InstanceStore — cycle hint), MCP,
|
|
|
- Installation, Pty, SystemPrompt
|
|
|
+ Npm, ModelsDev, Project, Installation, Storage, Vcs, SessionRunState
|
|
|
|
|
|
Tier 3:
|
|
|
- Config, FileWatcher, Format, Snapshot, ProviderAuth, Session,
|
|
|
- SessionShare, SessionSummary
|
|
|
+ Config, File, Simulation, Session
|
|
|
|
|
|
Tier 4:
|
|
|
- Plugin, Agent, Command, LLM, SessionRevert,
|
|
|
+ Plugin, FileWatcher, Format, Snapshot, LSP, MCP, Skill, Instruction,
|
|
|
SimulationProvider (= Provider)
|
|
|
|
|
|
Tier 5:
|
|
|
- SessionProcessor, SessionCompaction, Workspace
|
|
|
+ Pty, ProviderAuth, SessionSummary, Agent, Command, LLM, SystemPrompt
|
|
|
|
|
|
Tier 6:
|
|
|
- SessionPrompt, ToolRegistry
|
|
|
+ SessionRevert, SessionProcessor, SessionShare
|
|
|
|
|
|
Tier 7:
|
|
|
- InstanceBootstrap (needs many of the above)
|
|
|
+ SessionCompaction, ToolRegistry
|
|
|
|
|
|
Tier 8:
|
|
|
- InstanceStore (needs InstanceBootstrap + Project)
|
|
|
+ SessionPrompt
|
|
|
+
|
|
|
+Tier 9:
|
|
|
+ Workspace, InstanceBootstrap
|
|
|
+
|
|
|
+Tier 10:
|
|
|
+ InstanceStore
|
|
|
+
|
|
|
+Tier 11:
|
|
|
+ Worktree
|
|
|
```
|
|
|
|
|
|
## Potential cycles / hazards
|
|
|
@@ -180,8 +230,7 @@ Tier 8:
|
|
|
Worktree → InstanceStore → InstanceBootstrap → Project → (back to Worktree?)
|
|
|
- InstanceBootstrap requires Project (yes)
|
|
|
- Project does NOT require Worktree directly
|
|
|
- - Worktree requires InstanceStore — only used inside its methods,
|
|
|
- but yielded at layer init, so it's a true requirement
|
|
|
+ - Worktree requires InstanceStore at layer init
|
|
|
→ Worktree must be built AFTER InstanceStore.
|
|
|
|
|
|
SimulationProvider provides Provider tag, depends on Simulation.
|
|
|
@@ -189,26 +238,63 @@ SimulationProvider provides Provider tag, depends on Simulation.
|
|
|
SimulationProvider in this layer chain.
|
|
|
|
|
|
SimulationGit provides Git tag, used by File, FileWatcher,
|
|
|
- Storage, Vcs, Worktree, ToolRegistry tools, Project (no — Project
|
|
|
- uses ChildProcessSpawner instead).
|
|
|
+ Storage, Vcs, Worktree, ToolRegistry tools.
|
|
|
|
|
|
LLM.layer pipes Layer.provide(Permission.defaultLayer) internally.
|
|
|
- That means LLM brings its own Permission — beware double-providing
|
|
|
- Permission (sim chain also provides Permission.layer separately).
|
|
|
+ So LLM's residual requirements no longer include Permission, BUT the
|
|
|
+ sim chain still provides Permission.layer separately (correct — used by
|
|
|
+ SessionProcessor, SessionPrompt directly).
|
|
|
```
|
|
|
|
|
|
-## Why the simulated chain fails with stepwise `provideMerge`
|
|
|
-
|
|
|
-`Layer.provideMerge(self, that)` builds `that` independently and uses it to satisfy `self`'s reqs. `that` cannot see services already provided inside `self`. So when you write:
|
|
|
+## Why the simulated chain fails today
|
|
|
|
|
|
-```ts
|
|
|
-withCoreAppServices // contains Config.layer, Plugin.layer, ...
|
|
|
- .pipe(Layer.provideMerge(Npm.layer)) // Npm needs EffectFlock
|
|
|
+The current `server.ts` `Tier0Services` union lists:
|
|
|
+```
|
|
|
+AppFileSystem, FileSystem.FileSystem, ChildProcessSpawner, HttpClient,
|
|
|
+SimulationNetwork, Path, Global, Env, Bus, AccountRepo, ShareNext,
|
|
|
+SyncEvent, PtyTicket
|
|
|
```
|
|
|
|
|
|
-`Npm.layer` is built in isolation and its `EffectFlock` requirement must be filled from OUTSIDE the entire pipe — not from inside `withCoreAppServices`. Same for every other "consumer added later" combination.
|
|
|
-
|
|
|
-Production avoids this because every service is added via `Layer.provide([... defaultLayer, defaultLayer, ...])` — flat mergeAll of self-contained layers, all visible to each other.
|
|
|
+But the actual `Layer.mergeAll(...)` body at tier0 has residual requirements
|
|
|
+beyond that union. The TS error says
|
|
|
+`Layer<..., never, Service | Service>` — those two unresolved `Service`s
|
|
|
+are members of the NEW dependencies table above.
|
|
|
+
|
|
|
+The most likely culprits, in order of leakage:
|
|
|
+
|
|
|
+1. **`SyncEvent.layer`** now yields `RuntimeFlags` and `Bus`. `Bus` is in tier0
|
|
|
+ already, but `RuntimeFlags` is not provided anywhere in `createSimulatedRoutes`.
|
|
|
+ So `SyncEvent` leaks `RuntimeFlags` into tier0's `RIn`.
|
|
|
+
|
|
|
+2. Downstream tiers also leak `RuntimeFlags`, `AppProcess`, `BackgroundJob`,
|
|
|
+ `Image`, `EventV2Bridge`, `Reference` — these cascade through every higher
|
|
|
+ tier as `Service | Service | ...` in the error type.
|
|
|
+
|
|
|
+## Fix strategy
|
|
|
+
|
|
|
+The minimal change to make tier0 type-check:
|
|
|
+
|
|
|
+1. Add `RuntimeFlags.defaultLayer` to tier0 and `RuntimeFlags.Service` to
|
|
|
+ `Tier0Services`. This satisfies `SyncEvent`'s new dep and unblocks every
|
|
|
+ service that yields `RuntimeFlags`.
|
|
|
+2. Add `AppProcess.defaultLayer` (or a simulated equivalent) to tier0 and
|
|
|
+ `AppProcess.Service` to `Tier0Services`. Needed by `Installation`, `Format`,
|
|
|
+ `Snapshot`, `Worktree`.
|
|
|
+3. Add `BackgroundJob.defaultLayer` to tier0 and `BackgroundJob.Service` to
|
|
|
+ `Tier0Services`. Needed by `Session`, `SessionRunState`, `ToolRegistry`.
|
|
|
+4. Add `Image.defaultLayer` to tier0 (or wherever it fits) and `Image.Service`
|
|
|
+ to `Tier0Services`. Needed by `SessionProcessor`, `SessionPrompt`.
|
|
|
+5. Add `EventV2Bridge.defaultLayer` to tier0 and `EventV2Bridge.Service` to
|
|
|
+ `Tier0Services`. (Note: `EventV2Bridge` is already imported in `server.ts`
|
|
|
+ for the production routes but is not in any simulated tier.)
|
|
|
+6. Add `Reference.defaultLayer` to a tier that satisfies its deps (it's a leaf
|
|
|
+ wrt the listed graph above) and `Reference.Service` to the corresponding
|
|
|
+ tier union. Needed by `ToolRegistry`, `SessionPrompt`, `InstanceBootstrap`.
|
|
|
+
|
|
|
+Production routes (`createProductionRoutes`) already include
|
|
|
+`RuntimeFlags.defaultLayer` and `EventV2Bridge.defaultLayer` in the flat
|
|
|
+`Layer.provide([...])` list — they were simply never carried over to the
|
|
|
+simulated chain after the rebase.
|
|
|
|
|
|
## See also
|
|
|
|