diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-02 21:20:28 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-02 21:25:32 +0300 |
| commit | 295b09ca25edbccac65401ee84fa420dd3888aad (patch) | |
| tree | d54ed875518e042869ed3f43e95f0b9ee59f5d34 /src/integration/assets | |
| parent | 48641e253f1aa3886b470cbebec60103247a7622 (diff) | |
feat: make claude codex opencode hooks session-only
Diffstat (limited to 'src/integration/assets')
| -rw-r--r-- | src/integration/assets/claude/herdr-agent-state.sh | 27 | ||||
| -rw-r--r-- | src/integration/assets/codex/herdr-agent-state.sh | 23 | ||||
| -rw-r--r-- | src/integration/assets/opencode/herdr-agent-state.js | 74 |
3 files changed, 27 insertions, 97 deletions
diff --git a/src/integration/assets/claude/herdr-agent-state.sh b/src/integration/assets/claude/herdr-agent-state.sh index e2a970d3..12068a69 100644 --- a/src/integration/assets/claude/herdr-agent-state.sh +++ b/src/integration/assets/claude/herdr-agent-state.sh @@ -3,7 +3,7 @@ # managed by herdr; reinstalling or updating the integration overwrites this file. # add custom hooks beside this file instead of editing it. # HERDR_INTEGRATION_ID=claude -# HERDR_INTEGRATION_VERSION=4 +# HERDR_INTEGRATION_VERSION=5 set -eu @@ -13,7 +13,7 @@ trap 'rm -f "$hook_input_file"' EXIT HUP INT TERM cat >"$hook_input_file" 2>/dev/null || true case "$action" in - working|idle|blocked|release) ;; + session) ;; *) exit 0 ;; esac @@ -55,39 +55,24 @@ if hook_event_name == "SubagentStop": # to durable working, but Claude recap/away-summary can emit it after the # main turn has already stopped. Never let it revive an idle pane. raise SystemExit(0) -if is_subagent and action in ("idle", "release"): - # Subagent completion must not make the parent pane look done early. - raise SystemExit(0) - request_id = f"{source}:{int(time.time() * 1000)}:{random.randrange(1_000_000):06d}" report_seq = time.time_ns() session_id = hook_input.get("session_id") agent_session_id = session_id if isinstance(session_id, str) and session_id else None -if action == "release": +if agent_session_id: request = { "id": request_id, - "method": "pane.release_agent", + "method": "pane.report_agent_session", "params": { "pane_id": pane_id, "source": source, "agent": "claude", "seq": report_seq, + "agent_session_id": agent_session_id, }, } else: - request = { - "id": request_id, - "method": "pane.report_agent", - "params": { - "pane_id": pane_id, - "source": source, - "agent": "claude", - "state": action, - "seq": report_seq, - }, - } - if agent_session_id: - request["params"]["agent_session_id"] = agent_session_id + raise SystemExit(0) try: client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) diff --git a/src/integration/assets/codex/herdr-agent-state.sh b/src/integration/assets/codex/herdr-agent-state.sh index 5341d71c..385c9a98 100644 --- a/src/integration/assets/codex/herdr-agent-state.sh +++ b/src/integration/assets/codex/herdr-agent-state.sh @@ -3,7 +3,7 @@ # managed by herdr; reinstalling or updating the integration overwrites this file. # add custom hooks beside this file instead of editing it. # HERDR_INTEGRATION_ID=codex -# HERDR_INTEGRATION_VERSION=4 +# HERDR_INTEGRATION_VERSION=5 set -eu @@ -13,7 +13,7 @@ trap 'rm -f "$hook_input_file"' EXIT HUP INT TERM cat >"$hook_input_file" 2>/dev/null || true case "$action" in - working|idle|blocked|release) ;; + session) ;; *) exit 0 ;; esac @@ -52,31 +52,20 @@ request_id = f"{source}:{int(time.time() * 1000)}:{random.randrange(1_000_000):0 report_seq = time.time_ns() session_id = hook_input.get("session_id") agent_session_id = session_id if isinstance(session_id, str) and session_id else None -if action == "release": +if agent_session_id: request = { "id": request_id, - "method": "pane.release_agent", + "method": "pane.report_agent_session", "params": { "pane_id": pane_id, "source": source, "agent": "codex", "seq": report_seq, + "agent_session_id": agent_session_id, }, } else: - request = { - "id": request_id, - "method": "pane.report_agent", - "params": { - "pane_id": pane_id, - "source": source, - "agent": "codex", - "state": action, - "seq": report_seq, - }, - } - if agent_session_id: - request["params"]["agent_session_id"] = agent_session_id + raise SystemExit(0) try: client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) diff --git a/src/integration/assets/opencode/herdr-agent-state.js b/src/integration/assets/opencode/herdr-agent-state.js index ed0958fd..c2fd79a6 100644 --- a/src/integration/assets/opencode/herdr-agent-state.js +++ b/src/integration/assets/opencode/herdr-agent-state.js @@ -2,7 +2,7 @@ // managed by herdr; reinstalling or updating the integration overwrites this file. // add custom hooks/plugins beside this file instead of editing it. // HERDR_INTEGRATION_ID=opencode -// HERDR_INTEGRATION_VERSION=3 +// HERDR_INTEGRATION_VERSION=4 import net from "node:net"; @@ -20,7 +20,10 @@ function sessionIDFromProperties(properties) { : undefined; } -function reportState(action, sessionID) { +function reportSession(sessionID) { + if (!sessionID) { + return Promise.resolve(); + } const paneId = process.env.HERDR_PANE_ID; const socketPath = process.env.HERDR_SOCKET_PATH; @@ -31,26 +34,16 @@ function reportState(action, sessionID) { const requestId = `${SOURCE}:${Date.now()}:${Math.floor(Math.random() * 1_000_000) .toString() .padStart(6, "0")}`; - const params = - action === "release" - ? { - pane_id: paneId, - source: SOURCE, - agent: "opencode", - seq: nextReportSeq(), - } - : { - pane_id: paneId, - source: SOURCE, - agent: "opencode", - state: action, - seq: nextReportSeq(), - ...(sessionID ? { agent_session_id: sessionID } : {}), - }; const request = { id: requestId, - method: action === "release" ? "pane.release_agent" : "pane.report_agent", - params, + method: "pane.report_agent_session", + params: { + pane_id: paneId, + source: SOURCE, + agent: "opencode", + seq: nextReportSeq(), + agent_session_id: sessionID, + }, }; return new Promise((resolve) => { @@ -81,53 +74,16 @@ export const HerdrAgentStatePlugin = async () => { } return { - dispose: async () => { - await reportState("release"); - }, event: async ({ event }) => { const type = event?.type; const properties = event?.properties ?? {}; const sessionID = sessionIDFromProperties(properties); switch (type) { - case "permission.asked": - case "question.asked": - await reportState("blocked", sessionID); - break; - case "permission.replied": { - const reply = properties.reply ?? properties.response; - if (reply === "reject") { - await reportState("idle", sessionID); - } else if (reply === "once" || reply === "always") { - await reportState("working", sessionID); - } - break; - } - case "question.replied": - await reportState("working", sessionID); - break; - case "question.rejected": - await reportState("idle", sessionID); - break; case "session.created": case "session.updated": - // session.created and session.updated are metadata events; lifecycle - // state comes from session.status and the deprecated session.idle. - break; - case "session.status": { - const status = - typeof properties.status === "string" - ? properties.status - : properties.status?.type; - if (status === "busy" || status === "retry") { - await reportState("working", sessionID); - } else if (status === "idle") { - await reportState("idle", sessionID); - } - break; - } - case "session.idle": - await reportState("idle", sessionID); + case "session.status": + await reportSession(sessionID); break; default: break; |
