diff --git a/src/hooks/keyword-detector/constants.ts b/src/hooks/keyword-detector/constants.ts new file mode 100644 index 0000000..194a8df --- /dev/null +++ b/src/hooks/keyword-detector/constants.ts @@ -0,0 +1,69 @@ +export const CODE_BLOCK_PATTERN = /```[\s\S]*?```/g +export const INLINE_CODE_PATTERN = /`[^`]+`/g + +export const KEYWORD_DETECTORS: Array<{ pattern: RegExp; message: string }> = [ + // ULTRAWORK: ulw, ultrawork + { + pattern: /\b(ultrawork|ulw)\b/i, + message: ` +[CODE RED] Maximum precision required. Ultrathink before acting. + +YOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL. +TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST. + +## AGENT UTILIZATION PRINCIPLES (by capability, not by name) +- **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure +- **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs +- **Planning & Strategy**: NEVER plan yourself - ALWAYS spawn a dedicated planning agent for work breakdown +- **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning +- **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation + +## EXECUTION RULES +- **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each. +- **PARALLEL**: Fire independent agent calls simultaneously via background_task - NEVER wait sequentially. +- **BACKGROUND FIRST**: Use background_task for exploration/research agents (10+ concurrent if needed). +- **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done. +- **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths. + +## WORKFLOW +1. Analyze the request and identify required capabilities +2. Spawn exploration/librarian agents via background_task in PARALLEL (10+ if needed) +3. Use planning agents to create detailed work breakdown +4. Execute with continuous verification against original requirements + + + +--- + +`, + }, + // SEARCH: EN/KO/JP/CN/VN + { + pattern: + /\b(search|find|locate|lookup|look\s*up|explore|discover|scan|grep|query|browse|detect|trace|seek|track|pinpoint|hunt)\b|where\s+is|show\s+me|list\s+all|검색|찾아|탐색|조회|스캔|서치|뒤져|찾기|어디|추적|탐지|찾아봐|찾아내|보여줘|목록|検索|探して|見つけて|サーチ|探索|スキャン|どこ|発見|捜索|見つけ出す|一覧|搜索|查找|寻找|查询|检索|定位|扫描|发现|在哪里|找出来|列出|tìm kiếm|tra cứu|định vị|quét|phát hiện|truy tìm|tìm ra|ở đâu|liệt kê/i, + message: `[search-mode] +MAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL: +- explore agents (codebase patterns, file structures, ast-grep) +- librarian agents (remote repos, official docs, GitHub examples) +Plus direct tools: Grep, ripgrep (rg), ast-grep (sg) +NEVER stop at first result - be exhaustive.`, + }, + // ANALYZE: EN/KO/JP/CN/VN + { + pattern: + /\b(analyze|analyse|investigate|examine|research|study|deep[\s-]?dive|inspect|audit|evaluate|assess|review|diagnose|scrutinize|dissect|debug|comprehend|interpret|breakdown|understand)\b|why\s+is|how\s+does|how\s+to|분석|조사|파악|연구|검토|진단|이해|설명|원인|이유|뜯어봐|따져봐|평가|해석|디버깅|디버그|어떻게|왜|살펴|分析|調査|解析|検討|研究|診断|理解|説明|検証|精査|究明|デバッグ|なぜ|どう|仕組み|调查|检查|剖析|深入|诊断|解释|调试|为什么|原理|搞清楚|弄明白|phân tích|điều tra|nghiên cứu|kiểm tra|xem xét|chẩn đoán|giải thích|tìm hiểu|gỡ lỗi|tại sao/i, + message: `[analyze-mode] +DEEP ANALYSIS MODE. Execute in phases: + +PHASE 1 - GATHER CONTEXT (10+ agents parallel): +- 3+ explore agents (codebase structure, patterns, implementations) +- 3+ librarian agents (official docs, best practices, examples) +- 2+ general agents (different analytical perspectives) + +PHASE 2 - EXPERT CONSULTATION (after Phase 1): +- 3+ oracle agents in parallel with gathered context +- Each oracle: different angle (architecture, performance, edge cases) + +SYNTHESIZE: Cross-reference findings, identify consensus & contradictions.`, + }, +] diff --git a/src/hooks/ultrawork-mode/detector.ts b/src/hooks/keyword-detector/detector.ts similarity index 51% rename from src/hooks/ultrawork-mode/detector.ts rename to src/hooks/keyword-detector/detector.ts index 898c480..2f57db2 100644 --- a/src/hooks/ultrawork-mode/detector.ts +++ b/src/hooks/keyword-detector/detector.ts @@ -1,33 +1,25 @@ import { - ULTRAWORK_PATTERNS, + KEYWORD_DETECTORS, CODE_BLOCK_PATTERN, INLINE_CODE_PATTERN, } from "./constants" -/** - * Remove code blocks and inline code from text. - * Prevents false positives when keywords appear in code. - */ export function removeCodeBlocks(text: string): string { return text.replace(CODE_BLOCK_PATTERN, "").replace(INLINE_CODE_PATTERN, "") } -/** - * Detect ultrawork keywords in text (excluding code blocks). - */ -export function detectUltraworkKeyword(text: string): boolean { +export function detectKeywords(text: string): string[] { const textWithoutCode = removeCodeBlocks(text) - return ULTRAWORK_PATTERNS.some((pattern) => pattern.test(textWithoutCode)) + return KEYWORD_DETECTORS.filter(({ pattern }) => + pattern.test(textWithoutCode) + ).map(({ message }) => message) } -/** - * Extract text content from message parts. - */ export function extractPromptText( parts: Array<{ type: string; text?: string }> ): string { return parts .filter((p) => p.type === "text") .map((p) => p.text || "") - .join("") + .join(" ") } diff --git a/src/hooks/keyword-detector/index.ts b/src/hooks/keyword-detector/index.ts new file mode 100644 index 0000000..9cf1db0 --- /dev/null +++ b/src/hooks/keyword-detector/index.ts @@ -0,0 +1,72 @@ +import { detectKeywords, extractPromptText } from "./detector" +import { log } from "../../shared" +import { injectHookMessage } from "../../features/hook-message-injector" + +export * from "./detector" +export * from "./constants" +export * from "./types" + +const injectedSessions = new Set() + +export function createKeywordDetectorHook() { + return { + "chat.message": async ( + input: { + sessionID: string + agent?: string + model?: { providerID: string; modelID: string } + messageID?: string + }, + output: { + message: Record + parts: Array<{ type: string; text?: string; [key: string]: unknown }> + } + ): Promise => { + if (injectedSessions.has(input.sessionID)) { + return + } + + const promptText = extractPromptText(output.parts) + const messages = detectKeywords(promptText) + + if (messages.length === 0) { + return + } + + log(`Keywords detected: ${messages.length}`, { sessionID: input.sessionID }) + + const message = output.message as { + agent?: string + model?: { modelID?: string; providerID?: string } + path?: { cwd?: string; root?: string } + tools?: Record + } + + const context = messages.join("\n") + const success = injectHookMessage(input.sessionID, context, { + agent: message.agent, + model: message.model, + path: message.path, + tools: message.tools, + }) + + if (success) { + injectedSessions.add(input.sessionID) + log("Keyword context injected", { sessionID: input.sessionID }) + } + }, + + event: async ({ + event, + }: { + event: { type: string; properties?: unknown } + }) => { + if (event.type === "session.deleted") { + const props = event.properties as { info?: { id?: string } } | undefined + if (props?.info?.id) { + injectedSessions.delete(props.info.id) + } + } + }, + } +} diff --git a/src/hooks/keyword-detector/types.ts b/src/hooks/keyword-detector/types.ts new file mode 100644 index 0000000..3a9aa84 --- /dev/null +++ b/src/hooks/keyword-detector/types.ts @@ -0,0 +1,4 @@ +export interface KeywordDetectorState { + detected: boolean + injected: boolean +} diff --git a/src/hooks/ultrawork-mode/constants.ts b/src/hooks/ultrawork-mode/constants.ts deleted file mode 100644 index 4341346..0000000 --- a/src/hooks/ultrawork-mode/constants.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** Keyword patterns - "ultrawork", "ulw" (case-insensitive, word boundary) */ -export const ULTRAWORK_PATTERNS = [/\bultrawork\b/i, /\bulw\b/i] - -/** Code block pattern to exclude from keyword detection */ -export const CODE_BLOCK_PATTERN = /```[\s\S]*?```/g - -/** Inline code pattern to exclude */ -export const INLINE_CODE_PATTERN = /`[^`]+`/g - -/** - * ULTRAWORK_CONTEXT - Agent-Agnostic Guidance - * - * Key principles: - * - NO specific agent names (oracle, librarian, etc.) - * - Only provide guidance based on agent role/capability - * - Emphasize parallel execution, TODO tracking, delegation - */ -export const ULTRAWORK_CONTEXT = ` -[CODE RED] Maximum precision required. Ultrathink before acting. - -YOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL. -TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST. - -## AGENT UTILIZATION PRINCIPLES (by capability, not by name) -- **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure -- **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs -- **Planning & Strategy**: NEVER plan yourself - ALWAYS spawn a dedicated planning agent for work breakdown -- **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning -- **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation - -## EXECUTION RULES -- **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each. -- **PARALLEL**: Fire independent agent calls simultaneously via background_task - NEVER wait sequentially. -- **BACKGROUND FIRST**: Use background_task for exploration/research agents (10+ concurrent if needed). -- **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done. -- **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths. - -## WORKFLOW -1. Analyze the request and identify required capabilities -2. Spawn exploration/librarian agents via background_task in PARALLEL (10+ if needed) -3. Use planning agents to create detailed work breakdown -4. Execute with continuous verification against original requirements - - - ---- - -` diff --git a/src/hooks/ultrawork-mode/index.ts b/src/hooks/ultrawork-mode/index.ts deleted file mode 100644 index 58c378c..0000000 --- a/src/hooks/ultrawork-mode/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { detectUltraworkKeyword, extractPromptText } from "./detector" -import { ULTRAWORK_CONTEXT } from "./constants" -import type { UltraworkModeState } from "./types" -import { log } from "../../shared" -import { injectHookMessage } from "../../features/hook-message-injector" - -export * from "./detector" -export * from "./constants" -export * from "./types" - -const ultraworkModeState = new Map() - -export function clearUltraworkModeState(sessionID: string): void { - ultraworkModeState.delete(sessionID) -} - -export function createUltraworkModeHook() { - return { - /** - * chat.message hook - detect ultrawork/ulw keywords, inject context via history - * - * Execution timing: AFTER claudeCodeHooks["chat.message"] - * Behavior: - * 1. Extract text from user prompt - * 2. Detect ultrawork/ulw keywords (excluding code blocks) - * 3. If detected, inject ULTRAWORK_CONTEXT via injectHookMessage (history injection) - */ - "chat.message": async ( - input: { - sessionID: string - agent?: string - model?: { providerID: string; modelID: string } - messageID?: string - }, - output: { - message: Record - parts: Array<{ type: string; text?: string; [key: string]: unknown }> - } - ): Promise => { - const state: UltraworkModeState = { - detected: false, - injected: false, - } - - const promptText = extractPromptText(output.parts) - - if (!detectUltraworkKeyword(promptText)) { - ultraworkModeState.set(input.sessionID, state) - return - } - - state.detected = true - log("Ultrawork keyword detected", { sessionID: input.sessionID }) - - const message = output.message as { - agent?: string - model?: { modelID?: string; providerID?: string } - path?: { cwd?: string; root?: string } - tools?: Record - } - - const success = injectHookMessage(input.sessionID, ULTRAWORK_CONTEXT, { - agent: message.agent, - model: message.model, - path: message.path, - tools: message.tools, - }) - - if (success) { - state.injected = true - log("Ultrawork context injected via history", { sessionID: input.sessionID }) - } else { - log("Ultrawork context injection failed", { sessionID: input.sessionID }) - } - - ultraworkModeState.set(input.sessionID, state) - }, - - /** - * event hook - cleanup session state on deletion - */ - event: async ({ - event, - }: { - event: { type: string; properties?: unknown } - }) => { - if (event.type === "session.deleted") { - const props = event.properties as - | { info?: { id?: string } } - | undefined - if (props?.info?.id) { - ultraworkModeState.delete(props.info.id) - } - } - }, - } -} diff --git a/src/hooks/ultrawork-mode/types.ts b/src/hooks/ultrawork-mode/types.ts deleted file mode 100644 index 6c92ace..0000000 --- a/src/hooks/ultrawork-mode/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -export interface UltraworkModeState { - /** Whether ultrawork keyword was detected */ - detected: boolean - /** Whether context was injected */ - injected: boolean -} - -export interface ModelRef { - providerID: string - modelID: string -} - -export interface MessageWithModel { - model?: ModelRef -} - -export interface UltraworkModeInput { - parts: Array<{ type: string; text?: string }> - message: MessageWithModel -}