From 56deaa3a3e4e3fa643e59985afb9a375fc4a8419 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 23 Dec 2025 14:25:49 +0900 Subject: [PATCH] Enable keyword detection on first message using direct parts transformation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, first messages were skipped entirely to avoid interfering with title generation. Now, keywords detected on the first message are injected directly into the message parts instead of using the hook message injection system, allowing keywords like 'ultrawork' to activate on the first message of a session. This change: - Removes the early return that skipped first message keyword detection - Moves keyword context generation before the isFirstMessage check - For first messages: transforms message parts directly by prepending keyword context - For subsequent messages: maintains existing hook message injection behavior 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) --- src/hooks/keyword-detector/index.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/hooks/keyword-detector/index.ts b/src/hooks/keyword-detector/index.ts index 4b57796..8c4cdb7 100644 --- a/src/hooks/keyword-detector/index.ts +++ b/src/hooks/keyword-detector/index.ts @@ -25,11 +25,6 @@ export function createKeywordDetectorHook() { const isFirstMessage = !sessionFirstMessageProcessed.has(input.sessionID) sessionFirstMessageProcessed.add(input.sessionID) - if (isFirstMessage) { - log("Skipping keyword detection on first message for title generation", { sessionID: input.sessionID }) - return - } - const promptText = extractPromptText(output.parts) const messages = detectKeywords(promptText) @@ -37,6 +32,19 @@ export function createKeywordDetectorHook() { return } + const context = messages.join("\n") + + // First message: transform parts directly (for title generation compatibility) + if (isFirstMessage) { + log(`Keywords detected on first message, transforming parts directly`, { sessionID: input.sessionID, keywordCount: messages.length }) + const idx = output.parts.findIndex((p) => p.type === "text" && p.text) + if (idx >= 0) { + output.parts[idx].text = `${context}\n\n---\n\n${output.parts[idx].text ?? ""}` + } + return + } + + // Subsequent messages: inject as separate message log(`Keywords detected: ${messages.length}`, { sessionID: input.sessionID }) const message = output.message as { @@ -46,7 +54,6 @@ export function createKeywordDetectorHook() { tools?: Record } - const context = messages.join("\n") log(`[keyword-detector] Injecting context for ${messages.length} keywords`, { sessionID: input.sessionID, contextLength: context.length }) const success = injectHookMessage(input.sessionID, context, { agent: message.agent,