302 lines
16 KiB
Markdown
302 lines
16 KiB
Markdown
# Effect Service Dependency Graph — Simulated Routes
|
|
|
|
Generated for `createSimulatedRoutes` in `packages/opencode/src/server/routes/instance/httpapi/server.ts`.
|
|
|
|
## Notation
|
|
|
|
- `→ 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 (current, post-rebase)
|
|
|
|
```
|
|
─── External / Platform ─────────────────────────────────────────
|
|
NodePath (no app deps) provides Path.Path
|
|
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 — 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)
|
|
simulationShareNextLayer provides ShareNext (Layer.succeed override)
|
|
|
|
─── Simulation overrides ────────────────────────────────────────
|
|
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
|
|
|
|
─── 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, RuntimeFlags (NEW: RuntimeFlags)
|
|
Discovery → AppFileSystem, Path, HttpClient
|
|
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, 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, 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, RuntimeFlags (NEW: RuntimeFlags)
|
|
McpAuth → AppFileSystem
|
|
MCP → ChildProcessSpawner, McpAuth, Bus, Config
|
|
|
|
─── Session graph ───────────────────────────────────────────────
|
|
Todo → Bus
|
|
Question → Bus
|
|
SessionStatus → Bus
|
|
SessionRunState → BackgroundJob, SessionStatus (NEW: BackgroundJob)
|
|
Instruction → Config, AppFileSystem, Global, HttpClient,
|
|
RuntimeFlags (NEW: RuntimeFlags)
|
|
|
|
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, RuntimeFlags (CHANGED: Permission satisfied internally;
|
|
(Permission satisfied internally via .layer) RuntimeFlags is new)
|
|
|
|
Agent → Config, Auth, Plugin, Skill, Provider,
|
|
RuntimeFlags (NEW: RuntimeFlags)
|
|
Command → Config, MCP, Skill
|
|
|
|
SessionProcessor → Session, Config, Bus, Snapshot, Agent, LLM,
|
|
Permission, Plugin, SessionSummary,
|
|
SessionStatus, Image, EventV2Bridge,
|
|
RuntimeFlags, Scope (NEW: Image, EventV2Bridge, RuntimeFlags)
|
|
SessionCompaction → Bus, Config, Session, Agent, Plugin,
|
|
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,
|
|
Image, Reference, EventV2Bridge,
|
|
RuntimeFlags (NEW: Image, Reference, EventV2Bridge, RuntimeFlags)
|
|
|
|
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,
|
|
RuntimeFlags (NEW: RuntimeFlags)
|
|
Workspace → Auth, Session, SessionPrompt, HttpClient,
|
|
SyncEvent, Vcs, AppFileSystem, RuntimeFlags (NEW: AppFileSystem (explicit), RuntimeFlags)
|
|
|
|
─── Misc ────────────────────────────────────────────────────────
|
|
Installation → HttpClient, AppProcess (CHANGED: AppProcess instead of ChildProcessSpawner)
|
|
Pty → Config, Bus, Plugin
|
|
|
|
─── Instance lifecycle ──────────────────────────────────────────
|
|
InstanceBootstrap → Config, File, FileWatcher, Format, LSP, Plugin,
|
|
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, 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, Ripgrep, Account,
|
|
SyncEvent (needs RuntimeFlags + Bus)
|
|
|
|
Tier 2:
|
|
Npm, ModelsDev, Project, Installation, Storage, Vcs, SessionRunState
|
|
|
|
Tier 3:
|
|
Config, File, Simulation, Session
|
|
|
|
Tier 4:
|
|
Plugin, FileWatcher, Format, Snapshot, LSP, MCP, Skill, Instruction,
|
|
SimulationProvider (= Provider)
|
|
|
|
Tier 5:
|
|
Pty, ProviderAuth, SessionSummary, Agent, Command, LLM, SystemPrompt
|
|
|
|
Tier 6:
|
|
SessionRevert, SessionProcessor, SessionShare
|
|
|
|
Tier 7:
|
|
SessionCompaction, ToolRegistry
|
|
|
|
Tier 8:
|
|
SessionPrompt
|
|
|
|
Tier 9:
|
|
Workspace, InstanceBootstrap
|
|
|
|
Tier 10:
|
|
InstanceStore
|
|
|
|
Tier 11:
|
|
Worktree
|
|
```
|
|
|
|
## Potential cycles / hazards
|
|
|
|
```
|
|
Worktree → InstanceStore → InstanceBootstrap → Project → (back to Worktree?)
|
|
- InstanceBootstrap requires Project (yes)
|
|
- Project does NOT require Worktree directly
|
|
- Worktree requires InstanceStore at layer init
|
|
→ Worktree must be built AFTER InstanceStore.
|
|
|
|
SimulationProvider provides Provider tag, depends on Simulation.
|
|
Many downstream services depend on Provider — those resolve to
|
|
SimulationProvider in this layer chain.
|
|
|
|
SimulationGit provides Git tag, used by File, FileWatcher,
|
|
Storage, Vcs, Worktree, ToolRegistry tools.
|
|
|
|
LLM.layer pipes Layer.provide(Permission.defaultLayer) internally.
|
|
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 today
|
|
|
|
The current `server.ts` `Tier0Services` union lists:
|
|
```
|
|
AppFileSystem, FileSystem.FileSystem, ChildProcessSpawner, HttpClient,
|
|
SimulationNetwork, Path, Global, Env, Bus, AccountRepo, ShareNext,
|
|
SyncEvent, PtyTicket
|
|
```
|
|
|
|
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
|
|
|
|
- `dependency-graph.html` — interactive visualization of the same data.
|