Skip to content

Architecture: reduce import coupling in pi-embedded-runner/attempt.ts (50+ imports) and discord monitor (30 imports) #11517

@Jdharris06

Description

@Jdharris06

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.ts30 imports

src/discord/monitor/provider.ts29 imports

src/discord/monitor/message-handler.preflight.ts25 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:

  1. Make dependencies explicit and testable
  2. Reduce import depth from 3-4 levels (../../../auto-reply/heartbeat.js)
  3. Enable easier mocking in tests
  4. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions