diff --git a/src/config/schema.ts b/src/config/schema.ts index 5a2010b..b6fd60b 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -115,6 +115,11 @@ export const SisyphusAgentConfigSchema = z.object({ replace_plan: z.boolean().optional(), }) +export const CommentCheckerConfigSchema = z.object({ + /** Custom prompt to replace the default warning message. Use {{comments}} placeholder for detected comments XML. */ + custom_prompt: z.string().optional(), +}) + export const DynamicContextPruningConfigSchema = z.object({ /** Enable dynamic context pruning (default: false) */ enabled: z.boolean().default(false), @@ -175,6 +180,7 @@ export const OhMyOpenCodeConfigSchema = z.object({ claude_code: ClaudeCodeConfigSchema.optional(), google_auth: z.boolean().optional(), sisyphus_agent: SisyphusAgentConfigSchema.optional(), + comment_checker: CommentCheckerConfigSchema.optional(), experimental: ExperimentalConfigSchema.optional(), auto_update: z.boolean().optional(), }) @@ -185,6 +191,7 @@ export type AgentOverrides = z.infer export type AgentName = z.infer export type HookName = z.infer export type SisyphusAgentConfig = z.infer +export type CommentCheckerConfig = z.infer export type ExperimentalConfig = z.infer export type DynamicContextPruningConfig = z.infer diff --git a/src/hooks/comment-checker/index.ts b/src/hooks/comment-checker/index.ts index 033d4b9..834f685 100644 --- a/src/hooks/comment-checker/index.ts +++ b/src/hooks/comment-checker/index.ts @@ -1,5 +1,6 @@ import type { PendingCall } from "./types" import { runCommentChecker, getCommentCheckerPath, startBackgroundInit, type HookInput } from "./cli" +import type { CommentCheckerConfig } from "../../config/schema" import * as fs from "fs" import { existsSync } from "fs" @@ -32,8 +33,8 @@ function cleanupOldPendingCalls(): void { setInterval(cleanupOldPendingCalls, 10_000) -export function createCommentCheckerHooks() { - debugLog("createCommentCheckerHooks called") +export function createCommentCheckerHooks(config?: CommentCheckerConfig) { + debugLog("createCommentCheckerHooks called", { config }) // Start background CLI initialization (may trigger lazy download) startBackgroundInit() @@ -123,7 +124,7 @@ export function createCommentCheckerHooks() { // CLI mode only debugLog("using CLI:", cliPath) - await processWithCli(input, pendingCall, output, cliPath) + await processWithCli(input, pendingCall, output, cliPath, config?.custom_prompt) } catch (err) { debugLog("tool.execute.after failed:", err) } @@ -135,7 +136,8 @@ async function processWithCli( input: { tool: string; sessionID: string; callID: string }, pendingCall: PendingCall, output: { output: string }, - cliPath: string + cliPath: string, + customPrompt?: string ): Promise { debugLog("using CLI mode with path:", cliPath) @@ -154,7 +156,7 @@ async function processWithCli( }, } - const result = await runCommentChecker(hookInput, cliPath) + const result = await runCommentChecker(hookInput, cliPath, customPrompt) if (result.hasComments && result.message) { debugLog("CLI detected comments, appending message") diff --git a/src/hooks/thinking-block-validator/index.ts b/src/hooks/thinking-block-validator/index.ts index 463d3a8..8e92738 100644 --- a/src/hooks/thinking-block-validator/index.ts +++ b/src/hooks/thinking-block-validator/index.ts @@ -51,14 +51,15 @@ function isExtendedThinkingModel(modelID: string): boolean { } /** - * Check if a message has tool parts (tool_use) + * Check if a message has any content parts (tool_use, text, or other non-thinking content) */ -function hasToolParts(parts: Part[]): boolean { +function hasContentParts(parts: Part[]): boolean { if (!parts || parts.length === 0) return false return parts.some((part: Part) => { const type = part.type as string - return type === "tool" || type === "tool_use" + // Include tool parts and text parts (anything that's not thinking/reasoning) + return type === "tool" || type === "tool_use" || type === "text" }) } @@ -154,8 +155,8 @@ export function createThinkingBlockValidatorHook(): MessagesTransformHook { // Only check assistant messages if (msg.info.role !== "assistant") continue - // Check if message has tool parts but doesn't start with thinking - if (hasToolParts(msg.parts) && !startsWithThinkingBlock(msg.parts)) { + // Check if message has content parts but doesn't start with thinking + if (hasContentParts(msg.parts) && !startsWithThinkingBlock(msg.parts)) { // Find thinking content from previous turns const previousThinking = findPreviousThinkingContent(messages, i)