diff --git a/src/create-managers.test.ts b/src/create-managers.test.ts
index 56f6e8cfc..e246e1dcb 100644
--- a/src/create-managers.test.ts
+++ b/src/create-managers.test.ts
@@ -1,49 +1,23 @@
///
-import { afterAll, beforeEach, describe, expect, it, mock } from "bun:test"
+import { beforeEach, describe, expect, it, mock } from "bun:test"
-const markServerRunningInProcess = mock(() => {})
+import { createManagers } from "./create-managers"
-mock.module("./features/background-agent", () => ({
- BackgroundManager: class BackgroundManager {
- constructor(..._args: unknown[]) {}
- },
-}))
+class MockBackgroundManager {
+ constructor(..._args: unknown[]) {}
+}
-mock.module("./features/skill-mcp-manager", () => ({
- SkillMcpManager: class SkillMcpManager {
- constructor(..._args: unknown[]) {}
- },
-}))
+class MockSkillMcpManager {
+ constructor(..._args: unknown[]) {}
+}
-mock.module("./features/task-toast-manager", () => ({
- initTaskToastManager: mock(() => {}),
-}))
+class MockTmuxSessionManager {
+ constructor(..._args: unknown[]) {}
-mock.module("./features/tmux-subagent", () => ({
- TmuxSessionManager: class TmuxSessionManager {
- constructor(..._args: unknown[]) {}
-
- async cleanup(): Promise {}
- async onSessionCreated(..._args: unknown[]): Promise {}
- },
-}))
-
-mock.module("./features/background-agent/process-cleanup", () => ({
- registerManagerForCleanup: mock(() => {}),
-}))
-
-mock.module("./plugin-handlers", () => ({
- createConfigHandler: mock(() => ({ kind: "config-handler" })),
-}))
-
-mock.module("./shared/tmux/tmux-utils/server-health", () => ({
- isServerRunning: mock(async () => true),
- markServerRunningInProcess,
- resetServerCheck: mock(() => {}),
-}))
-
-const { createManagers } = await import("./create-managers")
+ async cleanup(): Promise {}
+ async onSessionCreated(..._args: unknown[]): Promise {}
+}
function createTmuxConfig(enabled: boolean) {
return {
@@ -57,23 +31,47 @@ function createTmuxConfig(enabled: boolean) {
}
describe("createManagers", () => {
+ const markServerRunningInProcess = mock(() => {})
+ const initTaskToastManager = mock(() => ({}) as never)
+ const registerManagerForCleanup = mock(() => {})
+ const createConfigHandler = mock(() => (async () => {}) as never)
+
+ function createMockArgs(enabled: boolean): Parameters[0] {
+ return {
+ ctx: {
+ directory: "/tmp",
+ client: {} as never,
+ project: {} as never,
+ worktree: "/tmp",
+ serverUrl: new URL("https://example.com"),
+ $: Bun.$,
+ },
+ pluginConfig: {} as never,
+ tmuxConfig: createTmuxConfig(enabled),
+ modelCacheState: {} as never,
+ backgroundNotificationHookEnabled: false,
+ deps: {
+ BackgroundManagerClass: MockBackgroundManager as never,
+ SkillMcpManagerClass: MockSkillMcpManager as never,
+ TmuxSessionManagerClass: MockTmuxSessionManager as never,
+ initTaskToastManagerFn: initTaskToastManager,
+ registerManagerForCleanupFn: registerManagerForCleanup,
+ createConfigHandlerFn: createConfigHandler,
+ markServerRunningInProcessFn: markServerRunningInProcess,
+ },
+ }
+ }
+
beforeEach(() => {
markServerRunningInProcess.mockClear()
- })
-
- afterAll(() => {
- mock.restore()
+ initTaskToastManager.mockClear()
+ registerManagerForCleanup.mockClear()
+ createConfigHandler.mockClear()
})
it("#given tmux integration is disabled #when managers are created #then it does not mark the tmux server as running", () => {
// #given
- const args = {
- ctx: { directory: "/tmp", client: {} },
- pluginConfig: {},
- tmuxConfig: createTmuxConfig(false),
- modelCacheState: {},
- backgroundNotificationHookEnabled: false,
- } as Parameters[0]
+ const args = createMockArgs(false)
// #when
createManagers(args)
@@ -84,13 +82,7 @@ describe("createManagers", () => {
it("#given tmux integration is enabled #when managers are created #then it marks the tmux server as running", () => {
// #given
- const args = {
- ctx: { directory: "/tmp", client: {} },
- pluginConfig: {},
- tmuxConfig: createTmuxConfig(true),
- modelCacheState: {},
- backgroundNotificationHookEnabled: false,
- } as Parameters[0]
+ const args = createMockArgs(true)
// #when
createManagers(args)
diff --git a/src/create-managers.ts b/src/create-managers.ts
index 14e8873c4..51b93270e 100644
--- a/src/create-managers.ts
+++ b/src/create-managers.ts
@@ -12,6 +12,26 @@ import { createConfigHandler } from "./plugin-handlers"
import { log } from "./shared"
import { markServerRunningInProcess } from "./shared/tmux/tmux-utils/server-health"
+type CreateManagersDeps = {
+ BackgroundManagerClass: typeof BackgroundManager
+ SkillMcpManagerClass: typeof SkillMcpManager
+ TmuxSessionManagerClass: typeof TmuxSessionManager
+ initTaskToastManagerFn: typeof initTaskToastManager
+ registerManagerForCleanupFn: typeof registerManagerForCleanup
+ createConfigHandlerFn: typeof createConfigHandler
+ markServerRunningInProcessFn: typeof markServerRunningInProcess
+}
+
+const defaultCreateManagersDeps: CreateManagersDeps = {
+ BackgroundManagerClass: BackgroundManager,
+ SkillMcpManagerClass: SkillMcpManager,
+ TmuxSessionManagerClass: TmuxSessionManager,
+ initTaskToastManagerFn: initTaskToastManager,
+ registerManagerForCleanupFn: registerManagerForCleanup,
+ createConfigHandlerFn: createConfigHandler,
+ markServerRunningInProcessFn: markServerRunningInProcess,
+}
+
export type Managers = {
tmuxSessionManager: TmuxSessionManager
backgroundManager: BackgroundManager
@@ -25,15 +45,17 @@ export function createManagers(args: {
tmuxConfig: TmuxConfig
modelCacheState: ModelCacheState
backgroundNotificationHookEnabled: boolean
+ deps?: Partial
}): Managers {
const { ctx, pluginConfig, tmuxConfig, modelCacheState, backgroundNotificationHookEnabled } = args
+ const deps = { ...defaultCreateManagersDeps, ...args.deps }
if (tmuxConfig.enabled) {
- markServerRunningInProcess()
+ deps.markServerRunningInProcessFn()
}
- const tmuxSessionManager = new TmuxSessionManager(ctx, tmuxConfig)
+ const tmuxSessionManager = new deps.TmuxSessionManagerClass(ctx, tmuxConfig)
- registerManagerForCleanup({
+ deps.registerManagerForCleanupFn({
shutdown: async () => {
await tmuxSessionManager.cleanup().catch((error) => {
log("[create-managers] tmux cleanup error during process shutdown:", error)
@@ -41,7 +63,7 @@ export function createManagers(args: {
},
})
- const backgroundManager = new BackgroundManager(
+ const backgroundManager = new deps.BackgroundManagerClass(
ctx,
pluginConfig.background_task,
{
@@ -75,11 +97,11 @@ export function createManagers(args: {
},
)
- initTaskToastManager(ctx.client)
+ deps.initTaskToastManagerFn(ctx.client)
- const skillMcpManager = new SkillMcpManager()
+ const skillMcpManager = new deps.SkillMcpManagerClass()
- const configHandler = createConfigHandler({
+ const configHandler = deps.createConfigHandlerFn({
ctx: { directory: ctx.directory, client: ctx.client },
pluginConfig,
modelCacheState,