feat(hooks): add ultrawork-mode hook for automatic agent orchestration guidance

When "ultrawork" or "ulw" keyword is detected in user prompt:
- Injects ULTRAWORK_CONTEXT with agent-agnostic guidance
- Executes AFTER CC hooks (UserPromptSubmit etc.)
- Follows existing hook pattern (think-mode style)

Key features:
- Agent orchestration principles (by capability, not name)
- Parallel execution rules
- TODO tracking enforcement
- Delegation guidance

Closes #31

🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2025-12-13 13:37:37 +09:00
parent 41a318df66
commit f57aa39d53
7 changed files with 193 additions and 0 deletions

View File

@@ -13,3 +13,4 @@ export { createClaudeCodeHooksHook } from "./claude-code-hooks";
export { createRulesInjectorHook } from "./rules-injector";
export { createBackgroundNotificationHook } from "./background-notification"
export { createAutoUpdateCheckerHook } from "./auto-update-checker";
export { createUltraworkModeHook } from "./ultrawork-mode";

View File

@@ -0,0 +1,48 @@
/** 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 = `<ultrawork-mode>
[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
</ultrawork-mode>
---
`

View File

@@ -0,0 +1,33 @@
import {
ULTRAWORK_PATTERNS,
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 {
const textWithoutCode = removeCodeBlocks(text)
return ULTRAWORK_PATTERNS.some((pattern) => pattern.test(textWithoutCode))
}
/**
* 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("")
}

View File

@@ -0,0 +1,84 @@
import { detectUltraworkKeyword, extractPromptText } from "./detector"
import { ULTRAWORK_CONTEXT } from "./constants"
import type { UltraworkModeState } from "./types"
import { log } from "../../shared"
export * from "./detector"
export * from "./constants"
export * from "./types"
const ultraworkModeState = new Map<string, UltraworkModeState>()
export function clearUltraworkModeState(sessionID: string): void {
ultraworkModeState.delete(sessionID)
}
export function createUltraworkModeHook() {
return {
/**
* chat.message hook - detect ultrawork/ulw keywords, inject context
*
* Execution timing: AFTER claudeCodeHooks["chat.message"]
* Behavior:
* 1. Extract text from user prompt
* 2. Detect ultrawork/ulw keywords (excluding code blocks)
* 3. If detected, prepend ULTRAWORK_CONTEXT to first text part
*/
"chat.message": async (
input: {
sessionID: string
agent?: string
model?: { providerID: string; modelID: string }
messageID?: string
},
output: {
message: Record<string, unknown>
parts: Array<{ type: string; text?: string; [key: string]: unknown }>
}
): Promise<void> => {
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 parts = output.parts as Array<{ type: string; text?: string }>
const idx = parts.findIndex((p) => p.type === "text" && p.text)
if (idx >= 0) {
parts[idx].text = `${ULTRAWORK_CONTEXT}${parts[idx].text ?? ""}`
state.injected = true
log("Ultrawork context injected", { 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)
}
}
},
}
}

View File

@@ -0,0 +1,20 @@
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
}