format: apply prettier to index.ts

🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2026-02-02 15:04:53 +09:00
parent e969ca5573
commit 418cf35886

View File

@@ -19,7 +19,6 @@ import {
createAgentUsageReminderHook, createAgentUsageReminderHook,
createNonInteractiveEnvHook, createNonInteractiveEnvHook,
createInteractiveBashSessionHook, createInteractiveBashSessionHook,
createThinkingBlockValidatorHook, createThinkingBlockValidatorHook,
createCategorySkillReminderHook, createCategorySkillReminderHook,
createRalphLoopHook, createRalphLoopHook,
@@ -41,7 +40,11 @@ import {
contextCollector, contextCollector,
createContextInjectorMessagesTransformHook, createContextInjectorMessagesTransformHook,
} from "./features/context-injector"; } from "./features/context-injector";
import { applyAgentVariant, resolveAgentVariant, resolveVariantForModel } from "./shared/agent-variant"; import {
applyAgentVariant,
resolveAgentVariant,
resolveVariantForModel,
} from "./shared/agent-variant";
import { createFirstMessageVariantGate } from "./shared/first-message-variant"; import { createFirstMessageVariantGate } from "./shared/first-message-variant";
import { import {
discoverUserClaudeSkills, discoverUserClaudeSkills,
@@ -84,13 +87,24 @@ import { initTaskToastManager } from "./features/task-toast-manager";
import { TmuxSessionManager } from "./features/tmux-subagent"; import { TmuxSessionManager } from "./features/tmux-subagent";
import { clearBoulderState } from "./features/boulder-state"; import { clearBoulderState } from "./features/boulder-state";
import { type HookName } from "./config"; import { type HookName } from "./config";
import { log, detectExternalNotificationPlugin, getNotificationConflictWarning, resetMessageCursor, hasConnectedProvidersCache, getOpenCodeVersion, isOpenCodeVersionAtLeast, OPENCODE_NATIVE_AGENTS_INJECTION_VERSION } from "./shared"; import {
log,
detectExternalNotificationPlugin,
getNotificationConflictWarning,
resetMessageCursor,
hasConnectedProvidersCache,
getOpenCodeVersion,
isOpenCodeVersionAtLeast,
OPENCODE_NATIVE_AGENTS_INJECTION_VERSION,
} from "./shared";
import { loadPluginConfig } from "./plugin-config"; import { loadPluginConfig } from "./plugin-config";
import { createModelCacheState } from "./plugin-state"; import { createModelCacheState } from "./plugin-state";
import { createConfigHandler } from "./plugin-handlers"; import { createConfigHandler } from "./plugin-handlers";
const OhMyOpenCodePlugin: Plugin = async (ctx) => { const OhMyOpenCodePlugin: Plugin = async (ctx) => {
log("[OhMyOpenCodePlugin] ENTRY - plugin loading", { directory: ctx.directory }) log("[OhMyOpenCodePlugin] ENTRY - plugin loading", {
directory: ctx.directory,
});
// Start background tmux check immediately // Start background tmux check immediately
startTmuxCheck(); startTmuxCheck();
@@ -100,7 +114,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const tmuxConfig = { const tmuxConfig = {
enabled: pluginConfig.tmux?.enabled ?? false, enabled: pluginConfig.tmux?.enabled ?? false,
layout: pluginConfig.tmux?.layout ?? 'main-vertical', layout: pluginConfig.tmux?.layout ?? "main-vertical",
main_pane_size: pluginConfig.tmux?.main_pane_size ?? 60, main_pane_size: pluginConfig.tmux?.main_pane_size ?? 60,
main_pane_min_width: pluginConfig.tmux?.main_pane_min_width ?? 120, main_pane_min_width: pluginConfig.tmux?.main_pane_min_width ?? 120,
agent_pane_min_width: pluginConfig.tmux?.agent_pane_min_width ?? 40, agent_pane_min_width: pluginConfig.tmux?.agent_pane_min_width ?? 40,
@@ -113,15 +127,17 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
? createContextWindowMonitorHook(ctx) ? createContextWindowMonitorHook(ctx)
: null; : null;
const sessionRecovery = isHookEnabled("session-recovery") const sessionRecovery = isHookEnabled("session-recovery")
? createSessionRecoveryHook(ctx, { experimental: pluginConfig.experimental }) ? createSessionRecoveryHook(ctx, {
experimental: pluginConfig.experimental,
})
: null; : null;
// Check for conflicting notification plugins before creating session-notification // Check for conflicting notification plugins before creating session-notification
let sessionNotification = null; let sessionNotification = null;
if (isHookEnabled("session-notification")) { if (isHookEnabled("session-notification")) {
const forceEnable = pluginConfig.notification?.force_enable ?? false; const forceEnable = pluginConfig.notification?.force_enable ?? false;
const externalNotifier = detectExternalNotificationPlugin(ctx.directory); const externalNotifier = detectExternalNotificationPlugin(ctx.directory);
if (externalNotifier.detected && !forceEnable) { if (externalNotifier.detected && !forceEnable) {
// External notification plugin detected - skip our notification to avoid conflicts // External notification plugin detected - skip our notification to avoid conflicts
log(getNotificationConflictWarning(externalNotifier.pluginName!)); log(getNotificationConflictWarning(externalNotifier.pluginName!));
@@ -146,14 +162,18 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
let directoryAgentsInjector = null; let directoryAgentsInjector = null;
if (isHookEnabled("directory-agents-injector")) { if (isHookEnabled("directory-agents-injector")) {
const currentVersion = getOpenCodeVersion(); const currentVersion = getOpenCodeVersion();
const hasNativeSupport = currentVersion !== null && const hasNativeSupport =
currentVersion !== null &&
isOpenCodeVersionAtLeast(OPENCODE_NATIVE_AGENTS_INJECTION_VERSION); isOpenCodeVersionAtLeast(OPENCODE_NATIVE_AGENTS_INJECTION_VERSION);
if (hasNativeSupport) { if (hasNativeSupport) {
log("directory-agents-injector auto-disabled due to native OpenCode support", { log(
currentVersion, "directory-agents-injector auto-disabled due to native OpenCode support",
nativeVersion: OPENCODE_NATIVE_AGENTS_INJECTION_VERSION, {
}); currentVersion,
nativeVersion: OPENCODE_NATIVE_AGENTS_INJECTION_VERSION,
},
);
} else { } else {
directoryAgentsInjector = createDirectoryAgentsInjectorHook(ctx); directoryAgentsInjector = createDirectoryAgentsInjectorHook(ctx);
} }
@@ -161,20 +181,23 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const directoryReadmeInjector = isHookEnabled("directory-readme-injector") const directoryReadmeInjector = isHookEnabled("directory-readme-injector")
? createDirectoryReadmeInjectorHook(ctx) ? createDirectoryReadmeInjectorHook(ctx)
: null; : null;
const emptyTaskResponseDetector = isHookEnabled("empty-task-response-detector") const emptyTaskResponseDetector = isHookEnabled(
"empty-task-response-detector",
)
? createEmptyTaskResponseDetectorHook(ctx) ? createEmptyTaskResponseDetectorHook(ctx)
: null; : null;
const thinkMode = isHookEnabled("think-mode") ? createThinkModeHook() : null; const thinkMode = isHookEnabled("think-mode") ? createThinkModeHook() : null;
const claudeCodeHooks = createClaudeCodeHooksHook( const claudeCodeHooks = createClaudeCodeHooksHook(
ctx, ctx,
{ {
disabledHooks: (pluginConfig.claude_code?.hooks ?? true) ? undefined : true, disabledHooks:
(pluginConfig.claude_code?.hooks ?? true) ? undefined : true,
keywordDetectorDisabled: !isHookEnabled("keyword-detector"), keywordDetectorDisabled: !isHookEnabled("keyword-detector"),
}, },
contextCollector contextCollector,
); );
const anthropicContextWindowLimitRecovery = isHookEnabled( const anthropicContextWindowLimitRecovery = isHookEnabled(
"anthropic-context-window-limit-recovery" "anthropic-context-window-limit-recovery",
) )
? createAnthropicContextWindowLimitRecoveryHook(ctx, { ? createAnthropicContextWindowLimitRecoveryHook(ctx, {
experimental: pluginConfig.experimental, experimental: pluginConfig.experimental,
@@ -247,32 +270,36 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const tmuxSessionManager = new TmuxSessionManager(ctx, tmuxConfig); const tmuxSessionManager = new TmuxSessionManager(ctx, tmuxConfig);
const backgroundManager = new BackgroundManager(ctx, pluginConfig.background_task, { const backgroundManager = new BackgroundManager(
tmuxConfig, ctx,
onSubagentSessionCreated: async (event) => { pluginConfig.background_task,
log("[index] onSubagentSessionCreated callback received", { {
sessionID: event.sessionID, tmuxConfig,
parentID: event.parentID, onSubagentSessionCreated: async (event) => {
title: event.title, log("[index] onSubagentSessionCreated callback received", {
}); sessionID: event.sessionID,
await tmuxSessionManager.onSessionCreated({ parentID: event.parentID,
type: "session.created", title: event.title,
properties: { });
info: { await tmuxSessionManager.onSessionCreated({
id: event.sessionID, type: "session.created",
parentID: event.parentID, properties: {
title: event.title, info: {
id: event.sessionID,
parentID: event.parentID,
title: event.title,
},
}, },
}, });
}); log("[index] onSubagentSessionCreated callback completed");
log("[index] onSubagentSessionCreated callback completed"); },
onShutdown: () => {
tmuxSessionManager.cleanup().catch((error) => {
log("[index] tmux cleanup error during shutdown:", error);
});
},
}, },
onShutdown: () => { );
tmuxSessionManager.cleanup().catch((error) => {
log("[index] tmux cleanup error during shutdown:", error)
})
},
});
const atlasHook = isHookEnabled("atlas") const atlasHook = isHookEnabled("atlas")
? createAtlasHook(ctx, { directory: ctx.directory, backgroundManager }) ? createAtlasHook(ctx, { directory: ctx.directory, backgroundManager })
@@ -297,36 +324,40 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const unstableAgentBabysitter = isHookEnabled("unstable-agent-babysitter") const unstableAgentBabysitter = isHookEnabled("unstable-agent-babysitter")
? createUnstableAgentBabysitterHook( ? createUnstableAgentBabysitterHook(
{ {
directory: ctx.directory, directory: ctx.directory,
client: { client: {
session: { session: {
messages: async (args) => { messages: async (args) => {
const result = await ctx.client.session.messages(args) const result = await ctx.client.session.messages(args);
if (Array.isArray(result)) return result if (Array.isArray(result)) return result;
if (typeof result === "object" && result !== null && "data" in result) { if (
const record = result as Record<string, unknown> typeof result === "object" &&
return { data: record.data } result !== null &&
} "data" in result
return [] ) {
}, const record = result as Record<string, unknown>;
prompt: async (args) => { return { data: record.data };
await ctx.client.session.prompt(args) }
}, return [];
},
prompt: async (args) => {
await ctx.client.session.prompt(args);
}, },
}, },
}, },
{ },
backgroundManager, {
config: pluginConfig.babysitting, backgroundManager,
} config: pluginConfig.babysitting,
) },
: null; )
: null;
if (sessionRecovery && todoContinuationEnforcer) { if (sessionRecovery && todoContinuationEnforcer) {
sessionRecovery.setOnAbortCallback(todoContinuationEnforcer.markRecovering); sessionRecovery.setOnAbortCallback(todoContinuationEnforcer.markRecovering);
sessionRecovery.setOnRecoveryCompleteCallback( sessionRecovery.setOnRecoveryCompleteCallback(
todoContinuationEnforcer.markRecoveryComplete todoContinuationEnforcer.markRecoveryComplete,
); );
} }
@@ -337,10 +368,11 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const callOmoAgent = createCallOmoAgent(ctx, backgroundManager); const callOmoAgent = createCallOmoAgent(ctx, backgroundManager);
const isMultimodalLookerEnabled = !(pluginConfig.disabled_agents ?? []).some( const isMultimodalLookerEnabled = !(pluginConfig.disabled_agents ?? []).some(
(agent) => agent.toLowerCase() === "multimodal-looker" (agent) => agent.toLowerCase() === "multimodal-looker",
); );
const lookAt = isMultimodalLookerEnabled ? createLookAt(ctx) : null; const lookAt = isMultimodalLookerEnabled ? createLookAt(ctx) : null;
const browserProvider = pluginConfig.browser_automation_engine?.provider ?? "playwright"; const browserProvider =
pluginConfig.browser_automation_engine?.provider ?? "playwright";
const delegateTask = createDelegateTask({ const delegateTask = createDelegateTask({
manager: backgroundManager, manager: backgroundManager,
client: ctx.client, client: ctx.client,
@@ -369,29 +401,32 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
}); });
const disabledSkills = new Set(pluginConfig.disabled_skills ?? []); const disabledSkills = new Set(pluginConfig.disabled_skills ?? []);
const systemMcpNames = getSystemMcpServerNames(); const systemMcpNames = getSystemMcpServerNames();
const builtinSkills = createBuiltinSkills({ browserProvider }).filter((skill) => { const builtinSkills = createBuiltinSkills({ browserProvider }).filter(
if (disabledSkills.has(skill.name as never)) return false; (skill) => {
if (skill.mcpConfig) { if (disabledSkills.has(skill.name as never)) return false;
for (const mcpName of Object.keys(skill.mcpConfig)) { if (skill.mcpConfig) {
if (systemMcpNames.has(mcpName)) return false; for (const mcpName of Object.keys(skill.mcpConfig)) {
if (systemMcpNames.has(mcpName)) return false;
}
} }
} return true;
return true; },
}); );
const includeClaudeSkills = pluginConfig.claude_code?.skills !== false; const includeClaudeSkills = pluginConfig.claude_code?.skills !== false;
const [userSkills, globalSkills, projectSkills, opencodeProjectSkills] = await Promise.all([ const [userSkills, globalSkills, projectSkills, opencodeProjectSkills] =
includeClaudeSkills ? discoverUserClaudeSkills() : Promise.resolve([]), await Promise.all([
discoverOpencodeGlobalSkills(), includeClaudeSkills ? discoverUserClaudeSkills() : Promise.resolve([]),
includeClaudeSkills ? discoverProjectClaudeSkills() : Promise.resolve([]), discoverOpencodeGlobalSkills(),
discoverOpencodeProjectSkills(), includeClaudeSkills ? discoverProjectClaudeSkills() : Promise.resolve([]),
]); discoverOpencodeProjectSkills(),
]);
const mergedSkills = mergeSkills( const mergedSkills = mergeSkills(
builtinSkills, builtinSkills,
pluginConfig.skills, pluginConfig.skills,
userSkills, userSkills,
globalSkills, globalSkills,
projectSkills, projectSkills,
opencodeProjectSkills opencodeProjectSkills,
); );
const skillMcpManager = new SkillMcpManager(); const skillMcpManager = new SkillMcpManager();
const getSessionIDForMcp = () => getMainSessionID() || ""; const getSessionIDForMcp = () => getMainSessionID() || "";
@@ -424,12 +459,14 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
}); });
const newTaskSystemEnabled = pluginConfig.new_task_system_enabled ?? false; const newTaskSystemEnabled = pluginConfig.new_task_system_enabled ?? false;
const taskToolsRecord: Record<string, ToolDefinition> = newTaskSystemEnabled ? { const taskToolsRecord: Record<string, ToolDefinition> = newTaskSystemEnabled
task_create: createTaskCreateTool(pluginConfig), ? {
task_get: createTaskGetTool(pluginConfig), task_create: createTaskCreateTool(pluginConfig, ctx),
task_list: createTaskList(pluginConfig), task_get: createTaskGetTool(pluginConfig),
task_update: createTaskUpdateTool(pluginConfig), task_list: createTaskList(pluginConfig),
} : {}; task_update: createTaskUpdateTool(pluginConfig, ctx),
}
: {};
return { return {
tool: { tool: {
@@ -450,23 +487,28 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
setSessionAgent(input.sessionID, input.agent); setSessionAgent(input.sessionID, input.agent);
} }
const message = (output as { message: { variant?: string } }).message const message = (output as { message: { variant?: string } }).message;
if (firstMessageVariantGate.shouldOverride(input.sessionID)) { if (firstMessageVariantGate.shouldOverride(input.sessionID)) {
const variant = input.model && input.agent const variant =
? resolveVariantForModel(pluginConfig, input.agent, input.model) input.model && input.agent
: resolveAgentVariant(pluginConfig, input.agent) ? resolveVariantForModel(pluginConfig, input.agent, input.model)
: resolveAgentVariant(pluginConfig, input.agent);
if (variant !== undefined) { if (variant !== undefined) {
message.variant = variant message.variant = variant;
} }
firstMessageVariantGate.markApplied(input.sessionID) firstMessageVariantGate.markApplied(input.sessionID);
} else { } else {
if (input.model && input.agent && message.variant === undefined) { if (input.model && input.agent && message.variant === undefined) {
const variant = resolveVariantForModel(pluginConfig, input.agent, input.model) const variant = resolveVariantForModel(
pluginConfig,
input.agent,
input.model,
);
if (variant !== undefined) { if (variant !== undefined) {
message.variant = variant message.variant = variant;
} }
} else { } else {
applyAgentVariant(pluginConfig, input.agent, message) applyAgentVariant(pluginConfig, input.agent, message);
} }
} }
@@ -477,14 +519,17 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
await startWork?.["chat.message"]?.(input, output); await startWork?.["chat.message"]?.(input, output);
if (!hasConnectedProvidersCache()) { if (!hasConnectedProvidersCache()) {
ctx.client.tui.showToast({ ctx.client.tui
body: { .showToast({
title: "⚠️ Provider Cache Missing", body: {
message: "Model filtering disabled. RESTART OpenCode to enable full functionality.", title: "⚠️ Provider Cache Missing",
variant: "warning" as const, message:
duration: 6000, "Model filtering disabled. RESTART OpenCode to enable full functionality.",
}, variant: "warning" as const,
}).catch(() => {}); duration: 6000,
},
})
.catch(() => {});
} }
if (ralphLoop) { if (ralphLoop) {
@@ -502,12 +547,12 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
promptText.includes("You are starting a Ralph Loop") && promptText.includes("You are starting a Ralph Loop") &&
promptText.includes("<user-task>"); promptText.includes("<user-task>");
const isCancelRalphTemplate = promptText.includes( const isCancelRalphTemplate = promptText.includes(
"Cancel the currently active Ralph Loop" "Cancel the currently active Ralph Loop",
); );
if (isRalphLoopTemplate) { if (isRalphLoopTemplate) {
const taskMatch = promptText.match( const taskMatch = promptText.match(
/<user-task>\s*([\s\S]*?)\s*<\/user-task>/i /<user-task>\s*([\s\S]*?)\s*<\/user-task>/i,
); );
const rawTask = taskMatch?.[1]?.trim() || ""; const rawTask = taskMatch?.[1]?.trim() || "";
@@ -519,7 +564,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const maxIterMatch = rawTask.match(/--max-iterations=(\d+)/i); const maxIterMatch = rawTask.match(/--max-iterations=(\d+)/i);
const promiseMatch = rawTask.match( const promiseMatch = rawTask.match(
/--completion-promise=["']?([^"'\s]+)["']?/i /--completion-promise=["']?([^"'\s]+)["']?/i,
); );
log("[ralph-loop] Starting loop from chat.message", { log("[ralph-loop] Starting loop from chat.message", {
@@ -543,15 +588,16 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
"experimental.chat.messages.transform": async ( "experimental.chat.messages.transform": async (
input: Record<string, never>, input: Record<string, never>,
output: { messages: Array<{ info: unknown; parts: unknown[] }> } output: { messages: Array<{ info: unknown; parts: unknown[] }> },
) => { ) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
await contextInjectorMessagesTransform?.["experimental.chat.messages.transform"]?.(input, output as any); await contextInjectorMessagesTransform?.[
"experimental.chat.messages.transform"
]?.(input, output as any);
await thinkingBlockValidator?.[ await thinkingBlockValidator?.[
"experimental.chat.messages.transform" "experimental.chat.messages.transform"
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
]?.(input, output as any); ]?.(input, output as any);
}, },
config: configHandler, config: configHandler,
@@ -579,36 +625,41 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const { event } = input; const { event } = input;
const props = event.properties as Record<string, unknown> | undefined; const props = event.properties as Record<string, unknown> | undefined;
if (event.type === "session.created") { if (event.type === "session.created") {
const sessionInfo = props?.info as const sessionInfo = props?.info as
| { id?: string; title?: string; parentID?: string } | { id?: string; title?: string; parentID?: string }
| undefined; | undefined;
log("[event] session.created", { sessionInfo, props }); log("[event] session.created", { sessionInfo, props });
if (!sessionInfo?.parentID) { if (!sessionInfo?.parentID) {
setMainSession(sessionInfo?.id); setMainSession(sessionInfo?.id);
} }
firstMessageVariantGate.markSessionCreated(sessionInfo); firstMessageVariantGate.markSessionCreated(sessionInfo);
await tmuxSessionManager.onSessionCreated( await tmuxSessionManager.onSessionCreated(
event as { type: string; properties?: { info?: { id?: string; parentID?: string; title?: string } } } event as {
); type: string;
} properties?: {
info?: { id?: string; parentID?: string; title?: string };
};
},
);
}
if (event.type === "session.deleted") { if (event.type === "session.deleted") {
const sessionInfo = props?.info as { id?: string } | undefined; const sessionInfo = props?.info as { id?: string } | undefined;
if (sessionInfo?.id === getMainSessionID()) { if (sessionInfo?.id === getMainSessionID()) {
setMainSession(undefined); setMainSession(undefined);
} }
if (sessionInfo?.id) { if (sessionInfo?.id) {
clearSessionAgent(sessionInfo.id); clearSessionAgent(sessionInfo.id);
resetMessageCursor(sessionInfo.id); resetMessageCursor(sessionInfo.id);
firstMessageVariantGate.clear(sessionInfo.id); firstMessageVariantGate.clear(sessionInfo.id);
await skillMcpManager.disconnectSession(sessionInfo.id); await skillMcpManager.disconnectSession(sessionInfo.id);
await lspManager.cleanupTempDirectoryClients(); await lspManager.cleanupTempDirectoryClients();
await tmuxSessionManager.onSessionDeleted({ await tmuxSessionManager.onSessionDeleted({
sessionID: sessionInfo.id, sessionID: sessionInfo.id,
}); });
} }
} }
if (event.type === "message.updated") { if (event.type === "message.updated") {
const info = props?.info as Record<string, unknown> | undefined; const info = props?.info as Record<string, unknown> | undefined;
@@ -669,7 +720,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const args = output.args as Record<string, unknown>; const args = output.args as Record<string, unknown>;
const subagentType = args.subagent_type as string; const subagentType = args.subagent_type as string;
const isExploreOrLibrarian = ["explore", "librarian"].some( const isExploreOrLibrarian = ["explore", "librarian"].some(
(name) => name.toLowerCase() === (subagentType ?? "").toLowerCase() (name) => name.toLowerCase() === (subagentType ?? "").toLowerCase(),
); );
args.tools = { args.tools = {
@@ -695,7 +746,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const maxIterMatch = rawArgs.match(/--max-iterations=(\d+)/i); const maxIterMatch = rawArgs.match(/--max-iterations=(\d+)/i);
const promiseMatch = rawArgs.match( const promiseMatch = rawArgs.match(
/--completion-promise=["']?([^"'\s]+)["']?/i /--completion-promise=["']?([^"'\s]+)["']?/i,
); );
ralphLoop.startLoop(sessionID, prompt, { ralphLoop.startLoop(sessionID, prompt, {
@@ -704,30 +755,30 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
: undefined, : undefined,
completionPromise: promiseMatch?.[1], completionPromise: promiseMatch?.[1],
}); });
} else if (command === "cancel-ralph" && sessionID) { } else if (command === "cancel-ralph" && sessionID) {
ralphLoop.cancelLoop(sessionID); ralphLoop.cancelLoop(sessionID);
} else if (command === "ulw-loop" && sessionID) { } else if (command === "ulw-loop" && sessionID) {
const rawArgs = const rawArgs =
args?.command?.replace(/^\/?(ulw-loop)\s*/i, "") || ""; args?.command?.replace(/^\/?(ulw-loop)\s*/i, "") || "";
const taskMatch = rawArgs.match(/^["'](.+?)["']/); const taskMatch = rawArgs.match(/^["'](.+?)["']/);
const prompt = const prompt =
taskMatch?.[1] || taskMatch?.[1] ||
rawArgs.split(/\s+--/)[0]?.trim() || rawArgs.split(/\s+--/)[0]?.trim() ||
"Complete the task as instructed"; "Complete the task as instructed";
const maxIterMatch = rawArgs.match(/--max-iterations=(\d+)/i); const maxIterMatch = rawArgs.match(/--max-iterations=(\d+)/i);
const promiseMatch = rawArgs.match( const promiseMatch = rawArgs.match(
/--completion-promise=["']?([^"'\s]+)["']?/i /--completion-promise=["']?([^"'\s]+)["']?/i,
); );
ralphLoop.startLoop(sessionID, prompt, { ralphLoop.startLoop(sessionID, prompt, {
ultrawork: true, ultrawork: true,
maxIterations: maxIterMatch maxIterations: maxIterMatch
? parseInt(maxIterMatch[1], 10) ? parseInt(maxIterMatch[1], 10)
: undefined, : undefined,
completionPromise: promiseMatch?.[1], completionPromise: promiseMatch?.[1],
}); });
} }
} }
if (input.tool === "slashcommand") { if (input.tool === "slashcommand") {
@@ -740,7 +791,9 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
todoContinuationEnforcer?.cancelAllCountdowns(); todoContinuationEnforcer?.cancelAllCountdowns();
ralphLoop?.cancelLoop(sessionID); ralphLoop?.cancelLoop(sessionID);
clearBoulderState(ctx.directory); clearBoulderState(ctx.directory);
log("[stop-continuation] All continuation mechanisms stopped", { sessionID }); log("[stop-continuation] All continuation mechanisms stopped", {
sessionID,
});
} }
} }
}, },
@@ -761,9 +814,9 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
await agentUsageReminder?.["tool.execute.after"](input, output); await agentUsageReminder?.["tool.execute.after"](input, output);
await categorySkillReminder?.["tool.execute.after"](input, output); await categorySkillReminder?.["tool.execute.after"](input, output);
await interactiveBashSession?.["tool.execute.after"](input, output); await interactiveBashSession?.["tool.execute.after"](input, output);
await editErrorRecovery?.["tool.execute.after"](input, output); await editErrorRecovery?.["tool.execute.after"](input, output);
await delegateTaskRetry?.["tool.execute.after"](input, output); await delegateTaskRetry?.["tool.execute.after"](input, output);
await atlasHook?.["tool.execute.after"]?.(input, output); await atlasHook?.["tool.execute.after"]?.(input, output);
await taskResumeInfo["tool.execute.after"](input, output); await taskResumeInfo["tool.execute.after"](input, output);
}, },