format: apply prettier to index.ts
🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
387
src/index.ts
387
src/index.ts
@@ -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);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user