Skip to content

Commit 19a7a44

Browse files
gimeneteCopilot
andcommitted
Add explicit legacy session claim
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 0acaa6f commit 19a7a44

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

‎rust/src/lib.rs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,6 +2590,23 @@ impl Client {
25902590
Ok(())
25912591
}
25922592

2593+
/// Claim one quarantined legacy local session for the active store identity.
2594+
///
2595+
/// The runtime atomically binds the claim to the identity most recently set
2596+
/// on this client connection through
2597+
/// [`set_session_store_identity`](Self::set_session_store_identity). Call
2598+
/// this only after explicit trusted-host user confirmation for the selected
2599+
/// session. The runtime rejects missing identities, conflicting ownership,
2600+
/// and sessions that are not eligible legacy local sessions.
2601+
pub async fn claim_legacy_session(&self, session_id: &SessionId) -> Result<()> {
2602+
self.call(
2603+
"sessionStore.claimLegacySession",
2604+
Some(serde_json::json!({ "sessionId": session_id })),
2605+
)
2606+
.await?;
2607+
Ok(())
2608+
}
2609+
25932610
/// List persisted sessions, optionally filtered by working directory,
25942611
/// repository, or git context.
25952612
pub async fn list_sessions(

‎rust/tests/session_test.rs‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,68 @@ async fn set_session_store_identity_sends_null_to_clear() {
25772577
handle.await.unwrap().unwrap();
25782578
}
25792579

2580+
#[tokio::test]
2581+
async fn claim_legacy_session_sends_exact_wire_shape() {
2582+
let (client, mut server_read, mut server_write) = make_client();
2583+
2584+
let handle = tokio::spawn({
2585+
let client = client.clone();
2586+
async move {
2587+
client
2588+
.claim_legacy_session(&SessionId::new("legacy-session"))
2589+
.await
2590+
}
2591+
});
2592+
2593+
let request = read_framed(&mut server_read).await;
2594+
assert_eq!(request["method"], "sessionStore.claimLegacySession");
2595+
assert_eq!(
2596+
request["params"],
2597+
serde_json::json!({ "sessionId": "legacy-session" })
2598+
);
2599+
let response = serde_json::json!({
2600+
"jsonrpc": "2.0",
2601+
"id": request["id"],
2602+
"result": {}
2603+
});
2604+
write_framed(&mut server_write, &serde_json::to_vec(&response).unwrap()).await;
2605+
handle.await.unwrap().unwrap();
2606+
}
2607+
2608+
#[tokio::test]
2609+
async fn claim_legacy_session_propagates_rpc_errors() {
2610+
let (client, mut server_read, mut server_write) = make_client();
2611+
2612+
let handle = tokio::spawn({
2613+
let client = client.clone();
2614+
async move {
2615+
client
2616+
.claim_legacy_session(&SessionId::new("owned-session"))
2617+
.await
2618+
}
2619+
});
2620+
2621+
let request = read_framed(&mut server_read).await;
2622+
assert_eq!(request["method"], "sessionStore.claimLegacySession");
2623+
let response = serde_json::json!({
2624+
"jsonrpc": "2.0",
2625+
"id": request["id"],
2626+
"error": {
2627+
"code": -32000,
2628+
"message": "legacy session is not eligible for claim"
2629+
}
2630+
});
2631+
write_framed(&mut server_write, &serde_json::to_vec(&response).unwrap()).await;
2632+
2633+
let error = handle.await.unwrap().unwrap_err();
2634+
assert!(matches!(error.kind(), ErrorKind::Rpc { code: -32000 }));
2635+
assert!(
2636+
error
2637+
.to_string()
2638+
.contains("legacy session is not eligible for claim")
2639+
);
2640+
}
2641+
25802642
#[tokio::test]
25812643
async fn list_sessions_serializes_typed_filter() {
25822644
use github_copilot_sdk::SessionListFilter;

0 commit comments

Comments
 (0)