diff options
Diffstat (limited to 'src/integration/assets')
| -rw-r--r-- | src/integration/assets/claude/herdr-agent-state.ps1 | 3 | ||||
| -rw-r--r-- | src/integration/assets/claude/herdr-agent-state.sh | 4 | ||||
| -rw-r--r-- | src/integration/assets/codex/herdr-agent-state.ps1 | 22 | ||||
| -rw-r--r-- | src/integration/assets/codex/herdr-agent-state.sh | 26 | ||||
| -rw-r--r-- | src/integration/assets/hermes/__init__.py | 12 | ||||
| -rw-r--r-- | src/integration/assets/kilo/herdr-agent-state.js | 7 | ||||
| -rw-r--r-- | src/integration/assets/kimi/herdr-agent-state.ps1 | 8 | ||||
| -rw-r--r-- | src/integration/assets/kimi/herdr-agent-state.sh | 17 | ||||
| -rw-r--r-- | src/integration/assets/omp/herdr-agent-state.ts | 55 | ||||
| -rw-r--r-- | src/integration/assets/opencode/herdr-agent-state.js | 7 | ||||
| -rw-r--r-- | src/integration/assets/pi/herdr-agent-state.ts | 74 |
11 files changed, 134 insertions, 101 deletions
diff --git a/src/integration/assets/claude/herdr-agent-state.ps1 b/src/integration/assets/claude/herdr-agent-state.ps1 index dc78efd2..dcc9d4df 100644 --- a/src/integration/assets/claude/herdr-agent-state.ps1 +++ b/src/integration/assets/claude/herdr-agent-state.ps1 @@ -2,7 +2,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=6 +# HERDR_INTEGRATION_VERSION=7 param([string]$Action = "") @@ -17,6 +17,7 @@ try { exit 0 } +if (-not [string]::IsNullOrWhiteSpace($payload.agent_id)) { exit 0 } if ($payload.hook_event_name -eq "SubagentStop") { exit 0 } $sessionId = $payload.session_id diff --git a/src/integration/assets/claude/herdr-agent-state.sh b/src/integration/assets/claude/herdr-agent-state.sh index ce072189..cb5e840d 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=6 +# HERDR_INTEGRATION_VERSION=7 set -eu @@ -50,6 +50,8 @@ if hook_input_file: hook_event_name = str(hook_input.get("hook_event_name") or "") is_subagent = bool(hook_input.get("agent_id")) +if is_subagent: + raise SystemExit(0) if hook_event_name == "SubagentStop": # SubagentStop is a completion event. Older Herdr integrations mapped it # to durable working, but Claude recap/away-summary can emit it after the diff --git a/src/integration/assets/codex/herdr-agent-state.ps1 b/src/integration/assets/codex/herdr-agent-state.ps1 index e56948f5..d837b78a 100644 --- a/src/integration/assets/codex/herdr-agent-state.ps1 +++ b/src/integration/assets/codex/herdr-agent-state.ps1 @@ -2,7 +2,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=5 +# HERDR_INTEGRATION_VERSION=6 param([string]$Action = "") @@ -17,11 +17,29 @@ try { exit 0 } +if ($payload.hook_event_name -and $payload.hook_event_name -ne "SessionStart") { exit 0 } + $sessionId = $payload.session_id if ([string]::IsNullOrWhiteSpace($sessionId)) { exit 0 } $seq = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() try { - & herdr pane report-agent-session $env:HERDR_PANE_ID --source herdr:codex --agent codex --seq $seq --agent-session-id $sessionId 2>$null | Out-Null + $args = @( + "pane", + "report-agent-session", + $env:HERDR_PANE_ID, + "--source", + "herdr:codex", + "--agent", + "codex", + "--seq", + "$seq", + "--agent-session-id", + "$sessionId" + ) + if ($payload.hook_event_name -eq "SessionStart" -and $payload.source -is [string] -and -not [string]::IsNullOrWhiteSpace($payload.source)) { + $args += @("--session-start-source", "$($payload.source)") + } + & herdr @args 2>$null | Out-Null } catch { } diff --git a/src/integration/assets/codex/herdr-agent-state.sh b/src/integration/assets/codex/herdr-agent-state.sh index 385c9a98..b3b08a78 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=5 +# HERDR_INTEGRATION_VERSION=6 set -eu @@ -48,21 +48,31 @@ if hook_input_file: except Exception: hook_input = {} +hook_event_name = str(hook_input.get("hook_event_name") or "") +if hook_event_name and hook_event_name != "SessionStart": + 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 +session_start_source = hook_input.get("source") if hook_event_name == "SessionStart" else None +if not isinstance(session_start_source, str) or not session_start_source: + session_start_source = None if agent_session_id: + params = { + "pane_id": pane_id, + "source": source, + "agent": "codex", + "seq": report_seq, + "agent_session_id": agent_session_id, + } + if session_start_source: + params["session_start_source"] = session_start_source request = { "id": request_id, "method": "pane.report_agent_session", - "params": { - "pane_id": pane_id, - "source": source, - "agent": "codex", - "seq": report_seq, - "agent_session_id": agent_session_id, - }, + "params": params, } else: raise SystemExit(0) diff --git a/src/integration/assets/hermes/__init__.py b/src/integration/assets/hermes/__init__.py index 6bb0fe8a..e6f6971d 100644 --- a/src/integration/assets/hermes/__init__.py +++ b/src/integration/assets/hermes/__init__.py @@ -1,7 +1,7 @@ """Hermes plugin installed by Herdr to report agent lifecycle state.""" # HERDR_INTEGRATION_ID=hermes -# HERDR_INTEGRATION_VERSION=2 +# HERDR_INTEGRATION_VERSION=3 from __future__ import annotations @@ -71,10 +71,6 @@ def _report(state: str, **kwargs) -> None: _send("pane.report_agent", params) -def _release() -> None: - _send("pane.release_agent", {}) - - def _working(**kwargs) -> None: _report("working", **kwargs) @@ -87,11 +83,6 @@ def _idle(**kwargs) -> None: _report("idle", **kwargs) -def _finalize(**kwargs) -> None: - del kwargs - _release() - - def register(ctx): ctx.register_hook("on_session_start", _idle) ctx.register_hook("pre_llm_call", _working) @@ -102,4 +93,3 @@ def register(ctx): ctx.register_hook("post_approval_response", _working) ctx.register_hook("post_llm_call", _idle) ctx.register_hook("on_session_end", _idle) - ctx.register_hook("on_session_finalize", _finalize) diff --git a/src/integration/assets/kilo/herdr-agent-state.js b/src/integration/assets/kilo/herdr-agent-state.js index aa1a0c1b..fc12919c 100644 --- a/src/integration/assets/kilo/herdr-agent-state.js +++ b/src/integration/assets/kilo/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=kilo -// HERDR_INTEGRATION_VERSION=1 +// HERDR_INTEGRATION_VERSION=2 import net from "node:net"; @@ -96,10 +96,6 @@ function reportState(state, sessionID) { return request("pane.report_agent", params); } -function releaseAgent() { - return request("pane.release_agent", {}); -} - export const HerdrAgentStatePlugin = async () => { if ( process.env.HERDR_ENV !== "1" || @@ -149,7 +145,6 @@ export const HerdrAgentStatePlugin = async () => { await reportState("idle", sessionID); break; case "session.deleted": - await releaseAgent(); break; default: break; diff --git a/src/integration/assets/kimi/herdr-agent-state.ps1 b/src/integration/assets/kimi/herdr-agent-state.ps1 index d9924acc..ff6bcefe 100644 --- a/src/integration/assets/kimi/herdr-agent-state.ps1 +++ b/src/integration/assets/kimi/herdr-agent-state.ps1 @@ -2,11 +2,11 @@ # managed by herdr; reinstalling or updating the integration overwrites this file. # add custom hooks beside this file instead of editing it. # HERDR_INTEGRATION_ID=kimi -# HERDR_INTEGRATION_VERSION=3 +# HERDR_INTEGRATION_VERSION=4 param([string]$Action = "") -if (@("session", "working", "blocked", "idle", "release") -notcontains $Action) { exit 0 } +if (@("session", "working", "blocked", "idle") -notcontains $Action) { exit 0 } if ($env:HERDR_ENV -ne "1") { exit 0 } if ([string]::IsNullOrWhiteSpace($env:HERDR_PANE_ID)) { exit 0 } @@ -21,9 +21,7 @@ $seq = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() $sessionId = if ($null -ne $payload -and -not [string]::IsNullOrWhiteSpace($payload.session_id)) { $payload.session_id } else { $null } try { - if ($Action -eq "release") { - & herdr pane release-agent $env:HERDR_PANE_ID --source herdr:kimi --agent kimi --seq $seq 2>$null | Out-Null - } elseif ($Action -eq "session") { + if ($Action -eq "session") { if ([string]::IsNullOrWhiteSpace($sessionId)) { exit 0 } & herdr pane report-agent-session $env:HERDR_PANE_ID --source herdr:kimi --agent kimi --agent-session-id $sessionId --seq $seq 2>$null | Out-Null } else { diff --git a/src/integration/assets/kimi/herdr-agent-state.sh b/src/integration/assets/kimi/herdr-agent-state.sh index 2c8d8567..b5b6cc4b 100644 --- a/src/integration/assets/kimi/herdr-agent-state.sh +++ b/src/integration/assets/kimi/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=kimi -# HERDR_INTEGRATION_VERSION=3 +# HERDR_INTEGRATION_VERSION=4 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 - session|working|blocked|idle|release) ;; + session|working|blocked|idle) ;; *) exit 0 ;; esac @@ -54,18 +54,7 @@ agent_session_id = session_id if isinstance(session_id, str) and session_id else request_id = f"{source}:{int(time.time() * 1000)}:{random.randrange(1_000_000):06d}" report_seq = time.time_ns() -if action == "release": - request = { - "id": request_id, - "method": "pane.release_agent", - "params": { - "pane_id": pane_id, - "source": source, - "agent": agent, - "seq": report_seq, - }, - } -elif action == "session": +if action == "session": if not agent_session_id: raise SystemExit(0) request = { diff --git a/src/integration/assets/omp/herdr-agent-state.ts b/src/integration/assets/omp/herdr-agent-state.ts index a6428cdd..a933e867 100644 --- a/src/integration/assets/omp/herdr-agent-state.ts +++ b/src/integration/assets/omp/herdr-agent-state.ts @@ -100,6 +100,35 @@ function parseDurationEnv(name: string, fallback: number): number { return parsed; } +function currentSessionRef(): Record<string, unknown> | undefined { + if (currentAgentSessionPath) { + return { agent_session_path: currentAgentSessionPath }; + } + if (currentAgentSessionId) { + return { agent_session_id: currentAgentSessionId }; + } + return undefined; +} + +function reportSession(): Promise<void> { + const sessionRef = currentSessionRef(); + if (!sessionRef) { + return Promise.resolve(); + } + + return sendRequest({ + id: `${source}:session:${Date.now()}:${Math.random().toString(36).slice(2)}`, + method: "pane.report_agent_session", + params: { + pane_id: paneId, + source, + agent: "omp", + seq: nextReportSeq(), + ...sessionRef, + }, + }); +} + function sendState(state: AgentState, message?: string, seq = nextReportSeq()): Promise<void> { return sendRequest({ id: `${source}:${Date.now()}:${Math.random().toString(36).slice(2)}`, @@ -169,19 +198,6 @@ function retryableErrorMessage(event: any): string | undefined { return errorMessage || "retryable provider error"; } -function releaseAgent(): Promise<void> { - return sendRequest({ - id: `${source}:release:${Date.now()}:${Math.random().toString(36).slice(2)}`, - method: "pane.release_agent", - params: { - pane_id: paneId, - source, - agent: "omp", - seq: nextReportSeq(), - }, - }); -} - export default function (pi) { if (!enabled()) { return; @@ -287,11 +303,12 @@ export default function (pi) { }); pi.on("session_start", (_event, ctx) => { - rootSession = ctx?.hasUI === true; - if (!rootSession) { + if (ctx?.hasUI !== true) { return; } + rootSession = true; updateSessionRef(ctx); + void reportSession(); publishState(true); }); @@ -326,12 +343,4 @@ export default function (pi) { scheduleIdle(); }); - - pi.on("session_shutdown", async () => { - if (!rootSession) { - return; - } - clearPendingTimers(); - await releaseAgent(); - }); } diff --git a/src/integration/assets/opencode/herdr-agent-state.js b/src/integration/assets/opencode/herdr-agent-state.js index 1e9fff51..6836227b 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=5 +// HERDR_INTEGRATION_VERSION=6 import net from "node:net"; @@ -96,10 +96,6 @@ function reportState(state, sessionID) { return request("pane.report_agent", params); } -function releaseAgent() { - return request("pane.release_agent", {}); -} - export const HerdrAgentStatePlugin = async () => { if ( process.env.HERDR_ENV !== "1" || @@ -149,7 +145,6 @@ export const HerdrAgentStatePlugin = async () => { await reportState("idle", sessionID); break; case "session.deleted": - await releaseAgent(); break; default: break; diff --git a/src/integration/assets/pi/herdr-agent-state.ts b/src/integration/assets/pi/herdr-agent-state.ts index 0e620f1f..9af12cfd 100644 --- a/src/integration/assets/pi/herdr-agent-state.ts +++ b/src/integration/assets/pi/herdr-agent-state.ts @@ -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=pi -// HERDR_INTEGRATION_VERSION=2 +// HERDR_INTEGRATION_VERSION=3 // @ts-nocheck import { createConnection } from "node:net"; @@ -100,6 +100,35 @@ function withSessionRef(params: Record<string, unknown>): Record<string, unknown return params; } +function currentSessionRef(): Record<string, unknown> | undefined { + if (currentAgentSessionPath) { + return { agent_session_path: currentAgentSessionPath }; + } + if (currentAgentSessionId) { + return { agent_session_id: currentAgentSessionId }; + } + return undefined; +} + +function reportSession(): Promise<void> { + const sessionRef = currentSessionRef(); + if (!sessionRef) { + return Promise.resolve(); + } + + return sendRequest({ + id: `${source}:session:${Date.now()}:${Math.random().toString(36).slice(2)}`, + method: "pane.report_agent_session", + params: { + pane_id: paneId, + source, + agent: "pi", + seq: nextReportSeq(), + ...sessionRef, + }, + }); +} + function sendState(state: AgentState, message?: string, seq = nextReportSeq()): Promise<void> { return sendRequest({ id: `${source}:${Date.now()}:${Math.random().toString(36).slice(2)}`, @@ -169,19 +198,6 @@ function retryableErrorMessage(event: any): string | undefined { return errorMessage || "retryable provider error"; } -function releaseAgent(): Promise<void> { - return sendRequest({ - id: `${source}:release:${Date.now()}:${Math.random().toString(36).slice(2)}`, - method: "pane.release_agent", - params: { - pane_id: paneId, - source, - agent: "pi", - seq: nextReportSeq(), - }, - }); -} - export default function (pi) { if (!enabled()) { return; @@ -197,6 +213,7 @@ export default function (pi) { let lastMessage: string | undefined; let idleTimer: ReturnType<typeof setTimeout> | undefined; let retryTimer: ReturnType<typeof setTimeout> | undefined; + let rootSession = false; function clearTimer(timer: ReturnType<typeof setTimeout> | undefined) { if (timer) { @@ -250,11 +267,6 @@ export default function (pi) { idleTimer.unref?.(); } - pi.on("session_start", (_event, ctx) => { - updateSessionRef(ctx); - publishState(true); - }); - function holdForRetry(message: string) { clearPendingTimers(); retryHoldActive = true; @@ -272,6 +284,9 @@ export default function (pi) { } pi.events.on("herdr:blocked", (data) => { + if (!rootSession) { + return; + } if (!data?.active) { blockedCount = Math.max(0, blockedCount - 1); if (blockedCount === 0) { @@ -287,7 +302,20 @@ export default function (pi) { publishState(); }); + pi.on("session_start", (_event, ctx) => { + if (ctx?.hasUI !== true) { + return; + } + rootSession = true; + updateSessionRef(ctx); + void reportSession(); + publishState(true); + }); + pi.on("agent_start", () => { + if (!rootSession) { + return; + } clearPendingTimers(); clearFailureState(); agentActive = true; @@ -295,6 +323,9 @@ export default function (pi) { }); pi.on("agent_end", (event) => { + if (!rootSession) { + return; + } if (!agentActive) { // Pi can emit duplicate/late end events while auto-retry is already // holding the pane in Working. Do not let an unqualified duplicate end @@ -312,9 +343,4 @@ export default function (pi) { scheduleIdle(); }); - - pi.on("session_shutdown", async () => { - clearPendingTimers(); - await releaseAgent(); - }); } |
