diff --git a/src/create-hooks.ts b/src/create-hooks.ts index 436f8e2b9..510f702ca 100644 --- a/src/create-hooks.ts +++ b/src/create-hooks.ts @@ -59,6 +59,7 @@ export function createHooks(args: { ctx, pluginConfig, modelCacheState, + backgroundManager, modelFallbackControllerAccessor, isHookEnabled, safeHookEnabled, diff --git a/src/hooks/ralph-loop/ralph-loop-event-handler.ts b/src/hooks/ralph-loop/ralph-loop-event-handler.ts index 0093e890a..73aa73c43 100644 --- a/src/hooks/ralph-loop/ralph-loop-event-handler.ts +++ b/src/hooks/ralph-loop/ralph-loop-event-handler.ts @@ -25,7 +25,7 @@ type LoopStateController = { setVerificationSessionID: (sessionID: string, verificationSessionID: string) => RalphLoopState | null restartAfterFailedVerification: (sessionID: string, messageCountAtStart?: number) => RalphLoopState | null } -type RalphLoopEventHandlerOptions = { directory: string; apiTimeoutMs: number; getTranscriptPath: (sessionID: string) => string | undefined; checkSessionExists?: RalphLoopOptions["checkSessionExists"]; sessionRecovery: SessionRecovery; loopState: LoopStateController } +type RalphLoopEventHandlerOptions = { directory: string; apiTimeoutMs: number; getTranscriptPath: (sessionID: string) => string | undefined; checkSessionExists?: RalphLoopOptions["checkSessionExists"]; backgroundManager?: RalphLoopOptions["backgroundManager"]; sessionRecovery: SessionRecovery; loopState: LoopStateController } export function createRalphLoopEventHandler( ctx: PluginInput, @@ -59,6 +59,15 @@ export function createRalphLoopEventHandler( return } + const hasRunningBackgroundTasks = options.backgroundManager + ? options.backgroundManager.getTasksByParentSession(sessionID).some((task: { status: string }) => task.status === "running") + : false + + if (hasRunningBackgroundTasks) { + log(`[${HOOK_NAME}] Skipped: background tasks running`, { sessionID }) + return + } + const verificationSessionID = state.verification_pending ? state.verification_session_id : undefined diff --git a/src/hooks/ralph-loop/ralph-loop-hook.ts b/src/hooks/ralph-loop/ralph-loop-hook.ts index 9e0ee3d04..9c3293a2e 100644 --- a/src/hooks/ralph-loop/ralph-loop-hook.ts +++ b/src/hooks/ralph-loop/ralph-loop-hook.ts @@ -46,6 +46,7 @@ export function createRalphLoopHook( const getTranscriptPath = options?.getTranscriptPath ?? getDefaultTranscriptPath const apiTimeout = options?.apiTimeout ?? DEFAULT_API_TIMEOUT const checkSessionExists = options?.checkSessionExists + const backgroundManager = options?.backgroundManager const loopState = createLoopStateController({ directory: ctx.directory, @@ -59,6 +60,7 @@ export function createRalphLoopHook( apiTimeoutMs: apiTimeout, getTranscriptPath, checkSessionExists, + backgroundManager, sessionRecovery, loopState, }) diff --git a/src/hooks/ralph-loop/types.ts b/src/hooks/ralph-loop/types.ts index 0c19a1f9b..4c8470707 100644 --- a/src/hooks/ralph-loop/types.ts +++ b/src/hooks/ralph-loop/types.ts @@ -22,4 +22,5 @@ export interface RalphLoopOptions { getTranscriptPath?: (sessionId: string) => string apiTimeout?: number checkSessionExists?: (sessionId: string) => Promise + backgroundManager?: { getTasksByParentSession: (sessionId: string) => Array<{ status: string }> } } diff --git a/src/plugin/hooks/create-core-hooks.ts b/src/plugin/hooks/create-core-hooks.ts index 5a36aa026..4b3f6b0fb 100644 --- a/src/plugin/hooks/create-core-hooks.ts +++ b/src/plugin/hooks/create-core-hooks.ts @@ -1,4 +1,5 @@ import type { HookName, OhMyOpenCodeConfig } from "../../config" +import type { BackgroundManager } from "../../features/background-agent" import type { ModelFallbackControllerAccessor } from "../../hooks/model-fallback" import type { PluginContext } from "../types" import type { ModelCacheState } from "../../plugin-state" @@ -11,16 +12,18 @@ export function createCoreHooks(args: { ctx: PluginContext pluginConfig: OhMyOpenCodeConfig modelCacheState: ModelCacheState + backgroundManager: BackgroundManager modelFallbackControllerAccessor?: ModelFallbackControllerAccessor isHookEnabled: (hookName: HookName) => boolean safeHookEnabled: boolean }) { - const { ctx, pluginConfig, modelCacheState, modelFallbackControllerAccessor, isHookEnabled, safeHookEnabled } = args + const { ctx, pluginConfig, modelCacheState, backgroundManager, modelFallbackControllerAccessor, isHookEnabled, safeHookEnabled } = args const session = createSessionHooks({ ctx, pluginConfig, modelCacheState, + backgroundManager, modelFallbackControllerAccessor, isHookEnabled, safeHookEnabled, diff --git a/src/plugin/hooks/create-session-hooks.ts b/src/plugin/hooks/create-session-hooks.ts index 9d437bc75..ae2d7bb11 100644 --- a/src/plugin/hooks/create-session-hooks.ts +++ b/src/plugin/hooks/create-session-hooks.ts @@ -1,4 +1,5 @@ import type { OhMyOpenCodeConfig, HookName } from "../../config" +import type { BackgroundManager } from "../../features/background-agent" import type { ModelFallbackControllerAccessor } from "../../hooks/model-fallback" import type { ModelCacheState } from "../../plugin-state" import type { PluginContext } from "../types" @@ -70,11 +71,12 @@ export function createSessionHooks(args: { ctx: PluginContext pluginConfig: OhMyOpenCodeConfig modelCacheState: ModelCacheState + backgroundManager: BackgroundManager modelFallbackControllerAccessor?: ModelFallbackControllerAccessor isHookEnabled: (hookName: HookName) => boolean safeHookEnabled: boolean }): SessionHooks { - const { ctx, pluginConfig, modelCacheState, modelFallbackControllerAccessor, isHookEnabled, safeHookEnabled } = args + const { ctx, pluginConfig, modelCacheState, backgroundManager, modelFallbackControllerAccessor, isHookEnabled, safeHookEnabled } = args const safeHook = (hookName: HookName, factory: () => T): T | null => safeCreateHook(hookName, factory, { enabled: safeHookEnabled }) @@ -211,6 +213,7 @@ export function createSessionHooks(args: { createRalphLoopHook(ctx, { config: pluginConfig.ralph_loop, checkSessionExists: async (sessionId) => await sessionExists(sessionId), + backgroundManager, })) : null