aboutsummaryrefslogtreecommitdiff
path: root/tests/cli_wrapper.rs
diff options
context:
space:
mode:
authorLane <150401101+LaneBirmingham@users.noreply.github.com>2026-06-02 08:32:05 +1000
committerGitHub <noreply@github.com>2026-06-02 01:32:05 +0300
commitf7d315d494b6a3d583574012526d15c1ddc82bfe (patch)
tree327585c6cb27d478bbb1e4b0da782d9bbfd00901 /tests/cli_wrapper.rs
parent99e097c7d3cf76ae2d53bac5e7e2b3fd88b83591 (diff)
feat: add github copilot cli integration (#386)
* feat: add github copilot cli integration refs #232 * docs: restore 0.6.5 changelog and document copilot hook flow * test: cover copilot camelcase hook payloads --------- Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
Diffstat (limited to 'tests/cli_wrapper.rs')
-rw-r--r--tests/cli_wrapper.rs171
1 files changed, 171 insertions, 0 deletions
diff --git a/tests/cli_wrapper.rs b/tests/cli_wrapper.rs
index 0c81e7e4..511674ab 100644
--- a/tests/cli_wrapper.rs
+++ b/tests/cli_wrapper.rs
@@ -500,6 +500,14 @@ fn run_codex_hook(action: &str, hook_input: &str) -> Option<serde_json::Value> {
)
}
+fn run_copilot_hook(hook_input: &str) -> Option<serde_json::Value> {
+ run_shell_hook(
+ "src/integration/assets/copilot/herdr-agent-state.sh",
+ &[],
+ hook_input,
+ )
+}
+
fn run_shell_hook(asset_path: &str, args: &[&str], hook_input: &str) -> Option<serde_json::Value> {
let base = unique_test_dir();
fs::create_dir_all(&base).unwrap();
@@ -623,6 +631,169 @@ fn codex_hook_reports_session_id_from_stdin() {
}
#[test]
+fn copilot_hook_maps_turn_lifecycle() {
+ let session_start_idle = run_copilot_hook(
+ r#"{"hook_event_name":"SessionStart","session_id":"copilot-session","source":"resume"}"#,
+ )
+ .expect("copilot session start without prompt should report idle");
+ assert_eq!(session_start_idle["method"], "pane.report_agent");
+ assert_eq!(session_start_idle["params"]["state"], "idle");
+ assert_eq!(
+ session_start_idle["params"]["agent_session_id"],
+ "copilot-session"
+ );
+
+ let session_start_working = run_copilot_hook(
+ r#"{"hook_event_name":"SessionStart","sessionId":"copilot-session","initialPrompt":"run tests"}"#,
+ )
+ .expect("copilot session start with prompt should report working");
+ assert_eq!(session_start_working["method"], "pane.report_agent");
+ assert_eq!(session_start_working["params"]["state"], "working");
+ assert_eq!(
+ session_start_working["params"]["agent_session_id"],
+ "copilot-session"
+ );
+
+ let working = run_copilot_hook(
+ r#"{"hook_event_name":"UserPromptSubmit","session_id":"copilot-session","prompt":"run tests"}"#,
+ )
+ .expect("copilot prompt should report working");
+ assert_eq!(working["method"], "pane.report_agent");
+ assert_eq!(working["params"]["agent"], "copilot");
+ assert_eq!(working["params"]["state"], "working");
+ assert_eq!(working["params"]["agent_session_id"], "copilot-session");
+
+ let idle = run_copilot_hook(
+ r#"{"hook_event_name":"agentStop","session_id":"copilot-session","stop_reason":"end_turn"}"#,
+ )
+ .expect("copilot stop should report idle");
+ assert_eq!(idle["method"], "pane.report_agent");
+ assert_eq!(idle["params"]["state"], "idle");
+}
+
+#[test]
+fn copilot_hook_maps_camel_case_payloads() {
+ let session_start = run_copilot_hook(
+ r#"{"sessionId":"copilot-camel-session","source":"new","initialPrompt":"run tests"}"#,
+ )
+ .expect("copilot camelCase session start should report working");
+ assert_eq!(session_start["method"], "pane.report_agent");
+ assert_eq!(session_start["params"]["state"], "working");
+ assert_eq!(
+ session_start["params"]["agent_session_id"],
+ "copilot-camel-session"
+ );
+
+ let prompt =
+ run_copilot_hook(r#"{"sessionId":"copilot-camel-session","prompt":"continue the task"}"#)
+ .expect("copilot camelCase prompt should report working");
+ assert_eq!(prompt["method"], "pane.report_agent");
+ assert_eq!(prompt["params"]["state"], "working");
+
+ let blocker = run_copilot_hook(
+ r#"{"sessionId":"copilot-camel-session","toolName":"ask_user","toolArgs":{}}"#,
+ )
+ .expect("copilot camelCase ask_user should report blocked");
+ assert_eq!(blocker["method"], "pane.report_agent");
+ assert_eq!(blocker["params"]["state"], "blocked");
+
+ let answered = run_copilot_hook(
+ r#"{"sessionId":"copilot-camel-session","toolName":"ask_user","toolArgs":{},"toolResult":{"resultType":"success","textResultForLlm":"ok"}}"#,
+ )
+ .expect("copilot camelCase postToolUse should report working");
+ assert_eq!(answered["method"], "pane.report_agent");
+ assert_eq!(answered["params"]["state"], "working");
+
+ let idle = run_copilot_hook(
+ r#"{"sessionId":"copilot-camel-session","stopReason":"end_turn","transcriptPath":"/tmp/transcript.jsonl"}"#,
+ )
+ .expect("copilot camelCase agentStop should report idle");
+ assert_eq!(idle["method"], "pane.report_agent");
+ assert_eq!(idle["params"]["state"], "idle");
+
+ let user_exit =
+ run_copilot_hook(r#"{"sessionId":"copilot-camel-session","reason":"user_exit"}"#)
+ .expect("copilot camelCase user exit should release");
+ assert_eq!(user_exit["method"], "pane.release_agent");
+ assert_eq!(user_exit["params"]["agent"], "copilot");
+}
+
+#[test]
+fn copilot_hook_maps_user_prompts_and_notifications() {
+ let ask_user = run_copilot_hook(
+ r#"{"hook_event_name":"PreToolUse","session_id":"copilot-session","tool_name":"ask_user"}"#,
+ )
+ .expect("copilot ask_user should report blocked");
+ assert_eq!(ask_user["method"], "pane.report_agent");
+ assert_eq!(ask_user["params"]["state"], "blocked");
+
+ let stale_report_intent = run_copilot_hook(
+ r#"{"hook_event_name":"PostToolUse","session_id":"copilot-session","tool_name":"report_intent","tool_result":{"text_result_for_llm":"ok"}}"#,
+ );
+ assert!(
+ stale_report_intent.is_none(),
+ "postToolUse report_intent must not clear a pending ask_user prompt"
+ );
+
+ let ask_user_answered = run_copilot_hook(
+ r#"{"hook_event_name":"PostToolUse","session_id":"copilot-session","tool_name":"ask_user","tool_result":{"text_result_for_llm":"Blue"}}"#,
+ )
+ .expect("copilot answered ask_user should report working");
+ assert_eq!(ask_user_answered["method"], "pane.report_agent");
+ assert_eq!(ask_user_answered["params"]["state"], "working");
+
+ let exit_plan_mode = run_copilot_hook(
+ r#"{"hook_event_name":"PreToolUse","session_id":"copilot-session","tool_name":"exit_plan_mode"}"#,
+ )
+ .expect("copilot exit_plan_mode should report blocked");
+ assert_eq!(exit_plan_mode["method"], "pane.report_agent");
+ assert_eq!(exit_plan_mode["params"]["state"], "blocked");
+
+ let exit_plan_answered = run_copilot_hook(
+ r#"{"hook_event_name":"PostToolUse","session_id":"copilot-session","tool_name":"exit_plan_mode","tool_result":{"text_result_for_llm":"Approved"}}"#,
+ )
+ .expect("copilot answered exit_plan_mode should report working");
+ assert_eq!(exit_plan_answered["method"], "pane.report_agent");
+ assert_eq!(exit_plan_answered["params"]["state"], "working");
+
+ let notification = run_copilot_hook(
+ r#"{"hook_event_name":"notification","session_id":"copilot-session","notification_type":"permission_prompt"}"#,
+ )
+ .expect("copilot permission notification should report blocked");
+ assert_eq!(notification["method"], "pane.report_agent");
+ assert_eq!(notification["params"]["state"], "blocked");
+
+ let permission_approved_tool = run_copilot_hook(
+ r#"{"hook_event_name":"PostToolUse","session_id":"copilot-session","tool_name":"bash","tool_result":{"text_result_for_llm":"ok"}}"#,
+ )
+ .expect("copilot completed tool should report working after permission prompt");
+ assert_eq!(permission_approved_tool["method"], "pane.report_agent");
+ assert_eq!(permission_approved_tool["params"]["state"], "working");
+
+ let agent_idle = run_copilot_hook(
+ r#"{"hook_event_name":"notification","session_id":"copilot-session","notification_type":"agent_idle"}"#,
+ )
+ .expect("copilot agent_idle notification should report idle");
+ assert_eq!(agent_idle["method"], "pane.report_agent");
+ assert_eq!(agent_idle["params"]["state"], "idle");
+}
+
+#[test]
+fn copilot_hook_releases_on_user_exit_only() {
+ let complete = run_copilot_hook(
+ r#"{"hook_event_name":"SessionEnd","session_id":"copilot-session","reason":"complete"}"#,
+ );
+ assert!(complete.is_none());
+
+ let user_exit = run_copilot_hook(
+ r#"{"hook_event_name":"SessionEnd","session_id":"copilot-session","reason":"user_exit"}"#,
+ )
+ .expect("copilot user exit should release");
+ assert_eq!(user_exit["method"], "pane.release_agent");
+ assert_eq!(user_exit["params"]["agent"], "copilot");
+}
+
+#[test]
fn pane_run_sends_one_send_input_request_with_enter_key() {
let base = unique_test_dir();
fs::create_dir_all(&base).unwrap();