Summary
Several critical files have very deep import chains that create tight coupling across subsystems. This makes refactoring risky and increases the blast radius of changes.
Worst Offenders
src/agents/pi-embedded-runner/run/attempt.ts (915 lines, 50+ imports)
This file imports from nearly every subsystem:
auto-reply (heartbeat)
config (channel capabilities)
infra (machine name)
media (constants)
plugins (hook runner)
routing (session key)
signal (reaction level)
telegram (inline buttons, reaction level)
tts (system prompt hint)
utils (user path, message channel, provider utils)
- Plus 30+ imports from within
agents/
src/discord/monitor/message-handler.process.ts — 30 imports
src/discord/monitor/provider.ts — 29 imports
src/discord/monitor/message-handler.preflight.ts — 25 imports
Proposed Solution
Introduce a dependency injection pattern — a RunContext or AgentContext object that aggregates resolved config and services, passed into the runner rather than importing directly from every subsystem.
// Instead of 50 direct imports:
interface RunContext {
config: ResolvedConfig;
heartbeat: HeartbeatService;
channels: ChannelCapabilities;
media: MediaConfig;
tts: TtsConfig;
hooks: HookRunner;
// ...
}
async function runAttempt(ctx: RunContext, params: AttemptParams) {
// Use ctx instead of importing from 15 different directories
}
This would:
- Make dependencies explicit and testable
- Reduce import depth from 3-4 levels (
../../../auto-reply/heartbeat.js)
- Enable easier mocking in tests
- Reduce the blast radius of subsystem refactors
Context
Found during a codebase review of v2026.2.3. This is a longer-term architectural improvement that would pair well with the file size refactoring (#11512).
Summary
Several critical files have very deep import chains that create tight coupling across subsystems. This makes refactoring risky and increases the blast radius of changes.
Worst Offenders
src/agents/pi-embedded-runner/run/attempt.ts(915 lines, 50+ imports)This file imports from nearly every subsystem:
auto-reply(heartbeat)config(channel capabilities)infra(machine name)media(constants)plugins(hook runner)routing(session key)signal(reaction level)telegram(inline buttons, reaction level)tts(system prompt hint)utils(user path, message channel, provider utils)agents/src/discord/monitor/message-handler.process.ts— 30 importssrc/discord/monitor/provider.ts— 29 importssrc/discord/monitor/message-handler.preflight.ts— 25 importsProposed Solution
Introduce a dependency injection pattern — a
RunContextorAgentContextobject that aggregates resolved config and services, passed into the runner rather than importing directly from every subsystem.This would:
../../../auto-reply/heartbeat.js)Context
Found during a codebase review of v2026.2.3. This is a longer-term architectural improvement that would pair well with the file size refactoring (#11512).