fix(hook-message-injector): add validation to prevent empty message injection and improve logging
- Add content validation in injectHookMessage() to prevent empty hook content injection - Add logging to claude-code-hooks and keyword-detector for better debugging - Document timing issues in empty-message-sanitizer comments - Update README with improved setup instructions 🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
36
README.md
36
README.md
@@ -129,10 +129,26 @@ Let the LLM Agent handle the grunt work. Paste this link and ask it to install a
|
|||||||
<details>
|
<details>
|
||||||
<summary>Instructions for LLM Agents (click to expand)</summary>
|
<summary>Instructions for LLM Agents (click to expand)</summary>
|
||||||
|
|
||||||
If you're an LLM Agent helping set up oh-my-opencode, follow these steps:
|
If you're an LLM Agent helping set up oh-my-opencode, Welcome! You'll now help your user to install the best agent harness, OhMyOpenCode. Tell user this with greetings, with test 'oMoMoMoMo...'
|
||||||
|
|
||||||
|
follow these steps:
|
||||||
|
|
||||||
### Step 1: Verify OpenCode Installation
|
### Step 0: Ask user about the setup.
|
||||||
|
|
||||||
|
Since OpenCode Supports various models, and our plugin suggests various frontier LLMs. Thus, you must ask user, following questions:
|
||||||
|
1. Do you have a Claude Pro/Max Subscription? Otherwise, we'll use 'opencode/big-pickle' (known for glm 4.6) as a main orchestrator model (not recommended)
|
||||||
|
-> If user said yes, add ToDo: "Setup user Claude Pro/Max Auth"
|
||||||
|
-> If user said no, add ToDo: "Override OmO agent model on oh-my-opencode.json as opencode/big-pickle"
|
||||||
|
2. Do you have a ChatGPT Subscription? Otherwise, we'll use 'claude-opus-4-5' with 32k thinking option for oracle agent.
|
||||||
|
-> If user said yes, add ToDo: "Setup user ChatGPT Auth"
|
||||||
|
-> If user said no, add ToDo: "Override oracle agent model on oh-my-opencode.json as claude-opus-4-5 with 32k thinking"
|
||||||
|
3. Will you integrate Gemini models? Otherwise, you cannot enjoy the beautiful design.
|
||||||
|
-> If user said yes, add ToDo: "Setup Google OAuth"
|
||||||
|
-> If user said no, add ToDo: "Override frontend-ui-ux-engineer agent model on oh-my-opencode.json as claude-opus-4-5 with 32k thinking"
|
||||||
|
|
||||||
|
### Step 1: Install OpenCode, if not
|
||||||
|
|
||||||
|
Run following command to verify OpenCode Installation:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
if command -v opencode &> /dev/null; then
|
if command -v opencode &> /dev/null; then
|
||||||
@@ -143,10 +159,17 @@ else
|
|||||||
fi
|
fi
|
||||||
```
|
```
|
||||||
|
|
||||||
If OpenCode isn't installed, check the [OpenCode Installation Guide](https://opencode.ai/docs). To save context, spawn a subagent to handle installation and report back.
|
If OpenCode isn't installed, check the [OpenCode Installation Guide](https://opencode.ai/docs).
|
||||||
|
Spawn a subagent to handle installation and report back - to save context.
|
||||||
|
|
||||||
### Step 2: Configure oh-my-opencode Plugin
|
### Step 2: Configure oh-my-opencode Plugin
|
||||||
|
|
||||||
|
#### JSONC
|
||||||
|
- If `~/.config/opencode/opencode.jsonc` exists, work in there to add `oh-my-opencode` plugin
|
||||||
|
|
||||||
|
#### JSON
|
||||||
|
- If no opencode.jsonc exists, run following command to create and register it.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p ~/.config/opencode
|
mkdir -p ~/.config/opencode
|
||||||
|
|
||||||
@@ -169,14 +192,15 @@ fi
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
opencode --version # Should be 1.0.132 or higher
|
opencode --version # Should be 1.0.132 or higher
|
||||||
cat ~/.config/opencode/opencode.json # Should contain "oh-my-opencode" in plugin array
|
cat ~/.config/opencode/opencode.json # Should contain "oh-my-opencode" in plugin array, or maybe check jsonc
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 4: Configure Authentication
|
### Step 4: Configure Authentication
|
||||||
|
|
||||||
Once oh-my-opencode is in the plugin list, use tmux to walk the user through authentication. Complete all steps below.
|
As your todo, please configure authentication as user have answered to you.
|
||||||
|
Following is the configuration guides for each providers. Please use interactive terminal like tmux to do following:
|
||||||
|
|
||||||
#### 4.1 Anthropic (Claude)
|
#### Anthropic (Claude)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
opencode auth login
|
opencode auth login
|
||||||
|
|||||||
@@ -71,6 +71,16 @@ export function injectHookMessage(
|
|||||||
hookContent: string,
|
hookContent: string,
|
||||||
originalMessage: OriginalMessageContext
|
originalMessage: OriginalMessageContext
|
||||||
): boolean {
|
): boolean {
|
||||||
|
// Validate hook content to prevent empty message injection
|
||||||
|
if (!hookContent || hookContent.trim().length === 0) {
|
||||||
|
console.warn("[hook-message-injector] Attempted to inject empty hook content, skipping injection", {
|
||||||
|
sessionID,
|
||||||
|
hasAgent: !!originalMessage.agent,
|
||||||
|
hasModel: !!(originalMessage.model?.providerID && originalMessage.model?.modelID)
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
const messageDir = getOrCreateMessageDir(sessionID)
|
const messageDir = getOrCreateMessageDir(sessionID)
|
||||||
|
|
||||||
const needsFallback =
|
const needsFallback =
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ export function createClaudeCodeHooksHook(ctx: PluginInput, config: PluginConfig
|
|||||||
|
|
||||||
if (result.messages.length > 0) {
|
if (result.messages.length > 0) {
|
||||||
const hookContent = result.messages.join("\n\n")
|
const hookContent = result.messages.join("\n\n")
|
||||||
|
log(`[claude-code-hooks] Injecting ${result.messages.length} hook messages`, { sessionID: input.sessionID, contentLength: hookContent.length })
|
||||||
const message = output.message as {
|
const message = output.message as {
|
||||||
agent?: string
|
agent?: string
|
||||||
model?: { modelID?: string; providerID?: string }
|
model?: { modelID?: string; providerID?: string }
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ interface MessageWithParts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MessagesTransformHook = {
|
type MessagesTransformHook = {
|
||||||
|
// NOTE: This sanitizer runs on experimental.chat.messages.transform hook,
|
||||||
|
// which executes AFTER chat.message hooks. Filesystem-injected messages
|
||||||
|
// from hooks like claude-code-hooks and keyword-detector may bypass this
|
||||||
|
// sanitizer if they inject empty content. Validation should be done at
|
||||||
|
// injection time in injectHookMessage().
|
||||||
|
|
||||||
"experimental.chat.messages.transform"?: (
|
"experimental.chat.messages.transform"?: (
|
||||||
input: Record<string, never>,
|
input: Record<string, never>,
|
||||||
output: { messages: MessageWithParts[] }
|
output: { messages: MessageWithParts[] }
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export function createKeywordDetectorHook() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const context = messages.join("\n")
|
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, {
|
const success = injectHookMessage(input.sessionID, context, {
|
||||||
agent: message.agent,
|
agent: message.agent,
|
||||||
model: message.model,
|
model: message.model,
|
||||||
|
|||||||
Reference in New Issue
Block a user