aboutsummaryrefslogtreecommitdiff
path: root/src/integration
diff options
context:
space:
mode:
Diffstat (limited to 'src/integration')
-rw-r--r--src/integration/assets/claude/herdr-agent-state.sh27
-rw-r--r--src/integration/assets/codex/herdr-agent-state.sh23
-rw-r--r--src/integration/assets/opencode/herdr-agent-state.js74
-rw-r--r--src/integration/mod.rs223
4 files changed, 112 insertions, 235 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;
diff --git a/src/integration/mod.rs b/src/integration/mod.rs
index 82afb195..31197318 100644
--- a/src/integration/mod.rs
+++ b/src/integration/mod.rs
@@ -19,11 +19,11 @@ const OMP_INTEGRATION_VERSION: u32 = 2;
const PI_CODING_AGENT_DIR_ENV_VAR: &str = "PI_CODING_AGENT_DIR";
const CLAUDE_HOOK_INSTALL_NAME: &str = "herdr-agent-state.sh";
const CLAUDE_HOOK_ASSET: &str = include_str!("assets/claude/herdr-agent-state.sh");
-const CLAUDE_INTEGRATION_VERSION: u32 = 4;
+const CLAUDE_INTEGRATION_VERSION: u32 = 5;
const CLAUDE_CONFIG_DIR_ENV_VAR: &str = "CLAUDE_CONFIG_DIR";
const CODEX_HOOK_INSTALL_NAME: &str = "herdr-agent-state.sh";
const CODEX_HOOK_ASSET: &str = include_str!("assets/codex/herdr-agent-state.sh");
-const CODEX_INTEGRATION_VERSION: u32 = 4;
+const CODEX_INTEGRATION_VERSION: u32 = 5;
const CODEX_HOME_ENV_VAR: &str = "CODEX_HOME";
const COPILOT_HOOK_INSTALL_NAME: &str = "herdr-agent-state.sh";
const COPILOT_HOOK_ASSET: &str = include_str!("assets/copilot/herdr-agent-state.sh");
@@ -31,7 +31,7 @@ const COPILOT_INTEGRATION_VERSION: u32 = 1;
const COPILOT_HOME_ENV_VAR: &str = "COPILOT_HOME";
const OPENCODE_PLUGIN_INSTALL_NAME: &str = "herdr-agent-state.js";
const OPENCODE_PLUGIN_ASSET: &str = include_str!("assets/opencode/herdr-agent-state.js");
-const OPENCODE_INTEGRATION_VERSION: u32 = 3;
+const OPENCODE_INTEGRATION_VERSION: u32 = 4;
const HERMES_PLUGIN_INSTALL_NAME: &str = "herdr-agent-state";
const HERMES_PLUGIN_MANIFEST_INSTALL_NAME: &str = "plugin.yaml";
const HERMES_PLUGIN_INIT_INSTALL_NAME: &str = "__init__.py";
@@ -813,45 +813,36 @@ pub(crate) fn install_claude() -> io::Result<ClaudeInstallPaths> {
"SubagentStop",
&format!("bash {quoted_hook_path} working"),
)?;
- ensure_command_hook(
+ remove_command_hook(
+ hooks,
+ "PermissionRequest",
+ &format!("bash {quoted_hook_path} blocked"),
+ )?;
+ remove_command_hook(
hooks,
"SessionStart",
- format!("bash {quoted_hook_path} idle"),
- 10,
- Some("*"),
+ &format!("bash {quoted_hook_path} idle"),
)?;
- ensure_command_hook(
+ remove_command_hook(
hooks,
"UserPromptSubmit",
- format!("bash {quoted_hook_path} working"),
- 10,
- Some("*"),
+ &format!("bash {quoted_hook_path} working"),
)?;
- ensure_command_hook(
+ remove_command_hook(
hooks,
"PreToolUse",
- format!("bash {quoted_hook_path} working"),
- 10,
- Some("*"),
- )?;
- ensure_command_hook(
- hooks,
- "PermissionRequest",
- format!("bash {quoted_hook_path} blocked"),
- 10,
- Some("*"),
+ &format!("bash {quoted_hook_path} working"),
)?;
- ensure_command_hook(
+ remove_command_hook(hooks, "Stop", &format!("bash {quoted_hook_path} idle"))?;
+ remove_command_hook(
hooks,
- "Stop",
- format!("bash {quoted_hook_path} idle"),
- 10,
- Some("*"),
+ "SessionEnd",
+ &format!("bash {quoted_hook_path} release"),
)?;
ensure_command_hook(
hooks,
- "SessionEnd",
- format!("bash {quoted_hook_path} release"),
+ "SessionStart",
+ format!("bash {quoted_hook_path} session"),
10,
Some("*"),
)?;
@@ -893,38 +884,31 @@ pub(crate) fn install_codex() -> io::Result<CodexInstallPaths> {
"codex hooks file hooks",
)?;
let quoted_hook_path = shell_single_quote(&hook_path.display().to_string());
- ensure_command_hook(
+ remove_command_hook(
+ hooks,
+ "PermissionRequest",
+ &format!("bash {quoted_hook_path} blocked"),
+ )?;
+ remove_command_hook(
hooks,
"SessionStart",
- format!("bash {quoted_hook_path} idle"),
- 10,
- None,
+ &format!("bash {quoted_hook_path} idle"),
)?;
- ensure_command_hook(
+ remove_command_hook(
hooks,
"UserPromptSubmit",
- format!("bash {quoted_hook_path} working"),
- 10,
- None,
+ &format!("bash {quoted_hook_path} working"),
)?;
- ensure_command_hook(
+ remove_command_hook(
hooks,
"PreToolUse",
- format!("bash {quoted_hook_path} working"),
- 10,
- None,
- )?;
- ensure_command_hook(
- hooks,
- "PermissionRequest",
- format!("bash {quoted_hook_path} blocked"),
- 10,
- None,
+ &format!("bash {quoted_hook_path} working"),
)?;
+ remove_command_hook(hooks, "Stop", &format!("bash {quoted_hook_path} idle"))?;
ensure_command_hook(
hooks,
- "Stop",
- format!("bash {quoted_hook_path} idle"),
+ "SessionStart",
+ format!("bash {quoted_hook_path} session"),
10,
None,
)?;
@@ -1114,6 +1098,11 @@ pub(crate) fn uninstall_claude() -> io::Result<ClaudeUninstallResult> {
)?;
updated_settings |= remove_command_hook(
hooks,
+ "SessionStart",
+ &format!("bash {quoted_hook_path} session"),
+ )?;
+ updated_settings |= remove_command_hook(
+ hooks,
"UserPromptSubmit",
&format!("bash {quoted_hook_path} working"),
)?;
@@ -1193,6 +1182,11 @@ pub(crate) fn uninstall_codex() -> io::Result<CodexUninstallResult> {
)?;
updated_hooks |= remove_command_hook(
hooks,
+ "SessionStart",
+ &format!("bash {quoted_hook_path} session"),
+ )?;
+ updated_hooks |= remove_command_hook(
+ hooks,
"UserPromptSubmit",
&format!("bash {quoted_hook_path} working"),
)?;
@@ -2408,35 +2402,15 @@ mod tests {
assert!(settings["hooks"]["SessionStart"][0]["hooks"][0]["command"]
.as_str()
.unwrap()
- .contains(" idle"));
- assert_eq!(settings["hooks"]["UserPromptSubmit"][0]["matcher"], "*");
- assert!(
- settings["hooks"]["UserPromptSubmit"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" working")
- );
- assert!(settings["hooks"]["PreToolUse"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" working"));
- assert!(
- settings["hooks"]["PermissionRequest"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" blocked")
- );
+ .contains(" session"));
+ assert!(settings["hooks"].get("UserPromptSubmit").is_none());
+ assert!(settings["hooks"].get("PreToolUse").is_none());
+ assert!(settings["hooks"].get("PermissionRequest").is_none());
assert!(settings["hooks"].get("PostToolUse").is_none());
assert!(settings["hooks"].get("PostToolUseFailure").is_none());
assert!(settings["hooks"].get("SubagentStop").is_none());
- assert!(settings["hooks"]["Stop"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" idle"));
- assert!(settings["hooks"]["SessionEnd"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" release"));
+ assert!(settings["hooks"].get("Stop").is_none());
+ assert!(settings["hooks"].get("SessionEnd").is_none());
std::env::remove_var("HOME");
let _ = fs::remove_dir_all(base);
@@ -2478,29 +2452,17 @@ mod tests {
serde_json::from_str(&fs::read_to_string(claude_dir.join("settings.json")).unwrap())
.unwrap();
assert_eq!(
- settings["hooks"]["UserPromptSubmit"]
- .as_array()
- .unwrap()
- .len(),
- 1
- );
- assert_eq!(settings["hooks"]["PreToolUse"].as_array().unwrap().len(), 1);
- assert_eq!(
- settings["hooks"]["PermissionRequest"]
- .as_array()
- .unwrap()
- .len(),
- 1
- );
- assert_eq!(
settings["hooks"]["SessionStart"].as_array().unwrap().len(),
1
);
+ assert!(settings["hooks"].get("UserPromptSubmit").is_none());
+ assert!(settings["hooks"].get("PreToolUse").is_none());
+ assert!(settings["hooks"].get("PermissionRequest").is_none());
assert!(settings["hooks"].get("PostToolUse").is_none());
assert!(settings["hooks"].get("PostToolUseFailure").is_none());
assert!(settings["hooks"].get("SubagentStop").is_none());
- assert_eq!(settings["hooks"]["Stop"].as_array().unwrap().len(), 1);
- assert_eq!(settings["hooks"]["SessionEnd"].as_array().unwrap().len(), 1);
+ assert!(settings["hooks"].get("Stop").is_none());
+ assert!(settings["hooks"].get("SessionEnd").is_none());
std::env::remove_var("HOME");
let _ = fs::remove_dir_all(base);
@@ -2518,7 +2480,8 @@ mod tests {
fs::write(
claude_dir.join("settings.json"),
format!(
- r#"{{"hooks":{{"PostToolUse":[{{"matcher":"*","hooks":[{{"type":"command","command":"bash '{}' working","timeout":10}},{{"type":"command","command":"echo keep-post","timeout":10}}]}}],"PostToolUseFailure":[{{"matcher":"*","hooks":[{{"type":"command","command":"bash '{}' working","timeout":10}},{{"type":"command","command":"echo keep-failure","timeout":10}}]}}],"SubagentStop":[{{"matcher":"*","hooks":[{{"type":"command","command":"bash '{}' working","timeout":10}},{{"type":"command","command":"echo keep-subagent","timeout":10}}]}}]}}}}"#,
+ r#"{{"hooks":{{"PostToolUse":[{{"matcher":"*","hooks":[{{"type":"command","command":"bash '{}' working","timeout":10}},{{"type":"command","command":"echo keep-post","timeout":10}}]}}],"PostToolUseFailure":[{{"matcher":"*","hooks":[{{"type":"command","command":"bash '{}' working","timeout":10}},{{"type":"command","command":"echo keep-failure","timeout":10}}]}}],"SubagentStop":[{{"matcher":"*","hooks":[{{"type":"command","command":"bash '{}' working","timeout":10}},{{"type":"command","command":"echo keep-subagent","timeout":10}}]}}],"SessionEnd":[{{"matcher":"*","hooks":[{{"type":"command","command":"bash '{}' release","timeout":10}},{{"type":"command","command":"echo keep-session-end","timeout":10}}]}}]}}}}"#,
+ hook_path.display(),
hook_path.display(),
hook_path.display(),
hook_path.display(),
@@ -2545,14 +2508,12 @@ mod tests {
"echo keep-subagent"
);
assert_eq!(
- settings["hooks"]["UserPromptSubmit"]
- .as_array()
- .unwrap()
- .len(),
- 1
+ settings["hooks"]["SessionEnd"][0]["hooks"][0]["command"],
+ "echo keep-session-end"
);
- assert_eq!(settings["hooks"]["PreToolUse"].as_array().unwrap().len(), 1);
- assert_eq!(settings["hooks"]["Stop"].as_array().unwrap().len(), 1);
+ assert!(settings["hooks"].get("UserPromptSubmit").is_none());
+ assert!(settings["hooks"].get("PreToolUse").is_none());
+ assert!(settings["hooks"].get("Stop").is_none());
std::env::remove_var("HOME");
let _ = fs::remove_dir_all(base);
@@ -2581,7 +2542,7 @@ mod tests {
assert_eq!(claude.path, hook_path);
assert_eq!(claude.installed_version, Some(1));
- assert_eq!(claude.expected_version, 4);
+ assert_eq!(claude.expected_version, 5);
assert_eq!(claude.state, IntegrationStatusKind::Outdated);
std::env::remove_var("HOME");
@@ -2611,7 +2572,7 @@ mod tests {
assert_eq!(claude.path, hook_path);
assert_eq!(claude.installed_version, Some(2));
- assert_eq!(claude.expected_version, 4);
+ assert_eq!(claude.expected_version, 5);
assert_eq!(claude.state, IntegrationStatusKind::Outdated);
std::env::remove_var("HOME");
@@ -2715,7 +2676,7 @@ mod tests {
assert_eq!(codex.path, hook_path);
assert_eq!(codex.installed_version, Some(2));
- assert_eq!(codex.expected_version, 4);
+ assert_eq!(codex.expected_version, 5);
assert_eq!(codex.state, IntegrationStatusKind::Outdated);
std::env::remove_var("HOME");
@@ -2745,25 +2706,11 @@ mod tests {
assert!(hooks["hooks"]["SessionStart"][0]["hooks"][0]["command"]
.as_str()
.unwrap()
- .contains(" idle"));
- assert!(hooks["hooks"]["UserPromptSubmit"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" working"));
- assert!(hooks["hooks"]["PreToolUse"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" working"));
- assert!(
- hooks["hooks"]["PermissionRequest"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" blocked")
- );
- assert!(hooks["hooks"]["Stop"][0]["hooks"][0]["command"]
- .as_str()
- .unwrap()
- .contains(" idle"));
+ .contains(" session"));
+ assert!(hooks["hooks"].get("UserPromptSubmit").is_none());
+ assert!(hooks["hooks"].get("PreToolUse").is_none());
+ assert!(hooks["hooks"].get("PermissionRequest").is_none());
+ assert!(hooks["hooks"].get("Stop").is_none());
assert!(config.contains("model = \"gpt-5.4\""));
assert!(config.contains("[features]"));
assert!(config.contains("hooks = true"));
@@ -2815,19 +2762,10 @@ mod tests {
let config = fs::read_to_string(codex_dir.join("config.toml")).unwrap();
assert_eq!(hooks["hooks"]["SessionStart"].as_array().unwrap().len(), 1);
- assert_eq!(
- hooks["hooks"]["UserPromptSubmit"].as_array().unwrap().len(),
- 1
- );
- assert_eq!(hooks["hooks"]["PreToolUse"].as_array().unwrap().len(), 1);
- assert_eq!(
- hooks["hooks"]["PermissionRequest"]
- .as_array()
- .unwrap()
- .len(),
- 1
- );
- assert_eq!(hooks["hooks"]["Stop"].as_array().unwrap().len(), 1);
+ assert!(hooks["hooks"].get("UserPromptSubmit").is_none());
+ assert!(hooks["hooks"].get("PreToolUse").is_none());
+ assert!(hooks["hooks"].get("PermissionRequest").is_none());
+ assert!(hooks["hooks"].get("Stop").is_none());
assert_eq!(config.matches("hooks = true").count(), 1);
assert!(!config.contains("codex_hooks"));
assert!(config.contains("other = true"));
@@ -3297,18 +3235,27 @@ mod tests {
assert!(PI_EXTENSION_ASSET.contains("agent_session_id: currentAgentSessionId"));
assert!(PI_EXTENSION_ASSET.contains("publishState(true)"));
assert!(CLAUDE_HOOK_ASSET.contains("agent_session_id"));
+ assert!(CLAUDE_HOOK_ASSET.contains("pane.report_agent_session"));
+ assert!(!CLAUDE_HOOK_ASSET.contains("\"state\": action"));
+ assert!(!CLAUDE_HOOK_ASSET.contains("pane.release_agent"));
assert!(CODEX_HOOK_ASSET.contains("HERDR_HOOK_INPUT_FILE"));
assert!(CODEX_HOOK_ASSET.contains("agent_session_id"));
+ assert!(CODEX_HOOK_ASSET.contains("pane.report_agent_session"));
+ assert!(!CODEX_HOOK_ASSET.contains("\"state\": action"));
+ assert!(!CODEX_HOOK_ASSET.contains("pane.release_agent"));
assert!(COPILOT_HOOK_ASSET.contains("agent_session_id"));
assert!(COPILOT_HOOK_ASSET.contains("notification_type"));
assert!(COPILOT_HOOK_ASSET.contains("ask_user"));
assert!(COPILOT_HOOK_ASSET.contains("exit_plan_mode"));
assert!(OPENCODE_PLUGIN_ASSET.contains("properties?.sessionID"));
- assert!(OPENCODE_PLUGIN_ASSET.contains("dispose: async"));
assert!(OPENCODE_PLUGIN_ASSET.contains("agent_session_id: sessionID"));
- assert!(!OPENCODE_PLUGIN_ASSET.contains("await reportState(\"idle\", sessionID);\n }\n break;\n case \"session.status\""));
+ assert!(OPENCODE_PLUGIN_ASSET.contains("pane.report_agent_session"));
+ assert!(!OPENCODE_PLUGIN_ASSET.contains("reportState"));
+ assert!(!OPENCODE_PLUGIN_ASSET.contains("pane.release_agent"));
assert!(HERMES_PLUGIN_INIT_ASSET.contains("session_id = _session_id(kwargs)"));
assert!(HERMES_PLUGIN_INIT_ASSET.contains("agent_session_id"));
+ assert!(HERMES_PLUGIN_INIT_ASSET.contains("pane.report_agent\","));
+ assert!(HERMES_PLUGIN_INIT_ASSET.contains("pane.release_agent"));
// Qoder hook reads the event from the stdin JSON payload (per
// https://docs.qoder.com/zh/cli/hooks). Make sure the bundled script
// never reaches for a QODER_HOOK_EVENT environment variable.