feat(hooks): add Claude Code hooks type definitions

🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2025-12-09 17:36:12 +09:00
parent fef7f4ca03
commit a27cac96d5
2 changed files with 201 additions and 7 deletions

View File

@@ -431,3 +431,38 @@ All tasks execution STARTED: Thu Dec 4 16:52:57 KST 2025
---
## [2025-12-09 17:34] - Task 1: types.ts 포팅
### DISCOVERED ISSUES
- Stub types.ts had `PluginConfig` interface needed by hook-disabled.ts (from Task 0)
- Full types.ts from opencode-cc-plugin did NOT have `PluginConfig`
- Typecheck initially failed: Module has no exported member 'PluginConfig'
### IMPLEMENTATION DECISIONS
- Copied full types.ts (181 lines) from opencode-cc-plugin → oh-my-opencode
- Preserved ALL types: ClaudeHooksConfig, HookMatcher, PreToolUseInput/Output, PostToolUseInput/Output
- Preserved deprecated decision fields: `decision?: "allow" | "deny" | "approve" | "block" | "ask"`
- Added `PluginConfig` interface at end (oh-my-opencode specific type needed by hook-disabled.ts)
- Kept line 150 comment (`// "pending" | "in_progress" | "completed"`) - existing source comment
### PROBLEMS FOR NEXT TASKS
- PluginConfig is now available for all subsequent tasks
- Full type definitions ready for Task 2, 3, 4+ to use
### VERIFICATION RESULTS
- Ran: `bun run typecheck` → exit 0, no errors
- Verified: ClaudeHooksConfig, HookMatcher, HookCommand types exist
- Verified: PreToolUseInput/Output, PostToolUseInput/Output types exist
- Verified: deprecated decision field (approve/block) included in PreToolUseOutput
- Verified: PluginConfig export added (fixes hook-disabled.ts import)
### LEARNINGS
- opencode-cc-plugin types.ts: 181 lines, no PluginConfig
- oh-my-opencode requires PluginConfig for hook disabling functionality
- Stub-to-full replacement pattern works: stub allows Task 0 typecheck, Task 1 replaces with full implementation
- Must preserve project-specific types (PluginConfig) when porting from different codebases
소요 시간: ~2분
---

View File

@@ -1,16 +1,24 @@
// Temporary stub types for Task 0 - will be fully implemented in Task 1
// These are minimal definitions to allow shared utilities to type-check
/**
* Claude Code Hooks Type Definitions
* Maps Claude Code hook concepts to OpenCode plugin events
*/
export interface HookCommand {
type: string
command: string
}
export type ClaudeHookEvent =
| "PreToolUse"
| "PostToolUse"
| "UserPromptSubmit"
| "Stop"
export interface HookMatcher {
matcher: string
hooks: HookCommand[]
}
export interface HookCommand {
type: "command"
command: string
}
export interface ClaudeHooksConfig {
PreToolUse?: HookMatcher[]
PostToolUse?: HookMatcher[]
@@ -18,7 +26,158 @@ export interface ClaudeHooksConfig {
Stop?: HookMatcher[]
}
export type ClaudeHookEvent = "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop"
export interface PreToolUseInput {
session_id: string
transcript_path?: string
cwd: string
permission_mode?: PermissionMode
hook_event_name: "PreToolUse"
tool_name: string
tool_input: Record<string, unknown>
tool_use_id?: string
hook_source?: HookSource
}
export interface PostToolUseInput {
session_id: string
transcript_path?: string
cwd: string
permission_mode?: PermissionMode
hook_event_name: "PostToolUse"
tool_name: string
tool_input: Record<string, unknown>
tool_response: {
title?: string
output?: string
[key: string]: unknown
}
tool_use_id?: string
hook_source?: HookSource
}
export interface UserPromptSubmitInput {
session_id: string
cwd: string
permission_mode?: PermissionMode
hook_event_name: "UserPromptSubmit"
prompt: string
session?: {
id: string
}
hook_source?: HookSource
}
export type PermissionMode = "default" | "plan" | "acceptEdits" | "bypassPermissions"
export type HookSource = "opencode-plugin"
export interface StopInput {
session_id: string
transcript_path?: string
cwd: string
permission_mode?: PermissionMode
hook_event_name: "Stop"
stop_hook_active: boolean
todo_path?: string
hook_source?: HookSource
}
export type PermissionDecision = "allow" | "deny" | "ask"
/**
* Common JSON fields for all hook outputs (Claude Code spec)
*/
export interface HookCommonOutput {
/** If false, Claude stops entirely */
continue?: boolean
/** Message shown to user when continue=false */
stopReason?: string
/** Suppress output from transcript */
suppressOutput?: boolean
/** Warning/message displayed to user */
systemMessage?: string
}
export interface PreToolUseOutput extends HookCommonOutput {
/** Deprecated: use hookSpecificOutput.permissionDecision instead */
decision?: "allow" | "deny" | "approve" | "block" | "ask"
/** Deprecated: use hookSpecificOutput.permissionDecisionReason instead */
reason?: string
hookSpecificOutput?: {
hookEventName: "PreToolUse"
permissionDecision: PermissionDecision
permissionDecisionReason?: string
updatedInput?: Record<string, unknown>
}
}
export interface PostToolUseOutput extends HookCommonOutput {
decision?: "block"
reason?: string
hookSpecificOutput?: {
hookEventName: "PostToolUse"
/** Additional context to provide to Claude */
additionalContext?: string
}
}
export interface HookResult {
exitCode: number
stdout?: string
stderr?: string
}
export interface TranscriptEntry {
type: "tool_use" | "tool_result" | "user" | "assistant"
timestamp: string
tool_name?: string
tool_input?: Record<string, unknown>
tool_output?: Record<string, unknown>
content?: string
}
export interface TodoItem {
id: string
content: string
status: "pending" | "in_progress" | "completed" | "cancelled"
priority?: "low" | "medium" | "high"
created_at: string
updated_at?: string
}
export interface ClaudeCodeTodoItem {
content: string
status: string // "pending" | "in_progress" | "completed"
activeForm: string
}
export interface TodoFile {
session_id: string
items: TodoItem[]
created_at: string
updated_at: string
}
export interface StopOutput {
decision?: "block" | "continue"
reason?: string
stop_hook_active?: boolean
permission_mode?: PermissionMode
inject_prompt?: string
}
export type ClaudeCodeContent =
| { type: "text"; text: string }
| { type: "tool_use"; id: string; name: string; input: Record<string, unknown> }
| { type: "tool_result"; tool_use_id: string; content: string }
export interface ClaudeCodeMessage {
type: "user" | "assistant"
message: {
role: "user" | "assistant"
content: ClaudeCodeContent[]
}
}
export interface PluginConfig {
disabledHooks?: boolean | ClaudeHookEvent[]