Skip to content

Commit 4c29b59

Browse files
committed
πŸ› fix(notification): migrate to Bus events for tool and message hooks
OpenCode's tool.execute.before/after and chat.message hooks are not triggered by the core β€” they are defined in the SDK but never called by processor.ts or llm.ts. Replace with event handler using Bus events that ARE triggered: - message.part.updated: detect question tool (status=running) for question_asked, and tool completion (status=completed) for tool_complete - message.updated: detect user messages for prompt_submit
1 parent 1f116ad commit 4c29b59

1 file changed

Lines changed: 47 additions & 42 deletions

File tree

β€Žsrc/index.tsβ€Ž

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ export const WarpPlugin: Plugin = async ({ client, directory }) => {
7777
case "session.idle": {
7878
const sessionId = event.properties.sessionID
7979

80-
// Fetch the conversation to extract last query and response
81-
// (port of on-stop.sh transcript parsing)
8280
let query = ""
8381
let response = ""
8482

@@ -133,6 +131,52 @@ export const WarpPlugin: Plugin = async ({ client, directory }) => {
133131
return
134132
}
135133

134+
case "message.part.updated": {
135+
const part = (event.properties as { part: unknown }).part as {
136+
type: string
137+
tool?: string
138+
state?: { status: string }
139+
callID?: string
140+
}
141+
if (part?.type !== "tool" || !part?.state) return
142+
143+
const sessionId = (event.properties as { sessionID?: string }).sessionID || ""
144+
145+
if (part.tool === "question" && part.state.status === "running") {
146+
const body = buildPayload("question_asked", sessionId, cwd, {
147+
tool_name: part.tool,
148+
})
149+
warpNotify(NOTIFICATION_TITLE, body)
150+
return
151+
}
152+
153+
if (part.state.status === "completed") {
154+
const body = buildPayload("tool_complete", sessionId, cwd, {
155+
tool_name: part.tool || "unknown",
156+
})
157+
warpNotify(NOTIFICATION_TITLE, body)
158+
return
159+
}
160+
return
161+
}
162+
163+
case "message.updated": {
164+
const info = (event.properties as { info: { role?: string; parts?: unknown[]; id?: string } }).info
165+
if (info?.role !== "user") return
166+
167+
const sessionId = (event.properties as { sessionID?: string }).sessionID || ""
168+
const queryText = extractTextFromParts(
169+
info.parts as unknown as Parameters<typeof extractTextFromParts>[0],
170+
)
171+
if (!queryText) return
172+
173+
const body = buildPayload("prompt_submit", sessionId, cwd, {
174+
query: truncate(queryText, 200),
175+
})
176+
warpNotify(NOTIFICATION_TITLE, body)
177+
return
178+
}
179+
136180
default: {
137181
// permission.asked is listed in the opencode docs but has no SDK type.
138182
// Handle it with the same logic as permission.updated.
@@ -142,44 +186,5 @@ export const WarpPlugin: Plugin = async ({ client, directory }) => {
142186
}
143187
}
144188
},
145-
146-
// Fires once per new user message β€” used to send the prompt_submit hook.
147-
// (We avoid the generic message.updated event because OpenCode fires it
148-
// multiple times per message, and a late duplicate can clobber the
149-
// completion notification.)
150-
"chat.message": async (input, output) => {
151-
const cwd = directory || ""
152-
const queryText = extractTextFromParts(output.parts)
153-
if (!queryText) return
154-
155-
const body = buildPayload("prompt_submit", input.sessionID, cwd, {
156-
query: truncate(queryText, 200),
157-
})
158-
warpNotify(NOTIFICATION_TITLE, body)
159-
},
160-
161-
// Fires before a tool executes β€” used to detect the built-in
162-
// "question" tool so Warp can notify the user that input is needed.
163-
"tool.execute.before": async (input) => {
164-
if (input.tool !== "question") return
165-
166-
const cwd = directory || ""
167-
const body = buildPayload("question_asked", input.sessionID, cwd, {
168-
tool_name: input.tool,
169-
})
170-
warpNotify(NOTIFICATION_TITLE, body)
171-
},
172-
173-
// Tool completion β€” fires after every tool call
174-
"tool.execute.after": async (input) => {
175-
const toolName = input.tool
176-
const sessionId = input.sessionID
177-
const cwd = directory || ""
178-
179-
const body = buildPayload("tool_complete", sessionId, cwd, {
180-
tool_name: toolName,
181-
})
182-
warpNotify(NOTIFICATION_TITLE, body)
183-
},
184189
}
185-
}
190+
}

0 commit comments

Comments
Β (0)