From 4377e73f5db849e380a803d975632d7cb44ec85f Mon Sep 17 00:00:00 2001 From: Patrick Nikoletich Date: Thu, 26 Feb 2026 21:15:40 -0800 Subject: [PATCH] docs: clarify session destroy vs delete semantics across all SDKs Clarify the distinction between destroy() (closes session, releases in-memory resources, preserves disk state for resumption) and deleteSession() (permanently removes all data from disk). Update doc comments across all four SDK languages (Go, Node.js, Python, .NET) and the session persistence guide to make the behavioral difference explicit and help users choose the right method. Fixes #526 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/guides/session-persistence.md | 21 ++++++++++++++++----- dotnet/src/Client.cs | 17 ++++++++++++----- dotnet/src/Session.cs | 15 +++++++++------ go/client.go | 11 +++++++++-- go/session.go | 14 +++++++++----- nodejs/src/client.ts | 14 ++++++++++---- nodejs/src/session.ts | 17 +++++++++++------ python/copilot/client.py | 14 ++++++++++---- python/copilot/session.py | 15 ++++++++++----- 9 files changed, 96 insertions(+), 42 deletions(-) diff --git a/docs/guides/session-persistence.md b/docs/guides/session-persistence.md index 527f5ecc7..dec91d5fb 100644 --- a/docs/guides/session-persistence.md +++ b/docs/guides/session-persistence.md @@ -325,16 +325,16 @@ async function cleanupExpiredSessions(maxAgeMs: number) { await cleanupExpiredSessions(24 * 60 * 60 * 1000); ``` -### Explicit Session Destruction +### Closing a Session (`destroy`) -When a task completes, destroy the session explicitly rather than waiting for timeouts: +When a task completes, close the session explicitly rather than waiting for timeouts. This releases in-memory resources but **preserves session data on disk**, so the session can still be resumed later: ```typescript try { // Do work... await session.sendAndWait({ prompt: "Complete the task" }); - // Task complete - clean up + // Task complete — release in-memory resources (session can be resumed later) await session.destroy(); } catch (error) { // Clean up even on error @@ -343,6 +343,17 @@ try { } ``` +### Permanently Deleting a Session (`deleteSession`) + +To permanently remove a session and all its data from disk (conversation history, planning state, artifacts), use `deleteSession`. This is irreversible — the session **cannot** be resumed after deletion: + +```typescript +// Permanently remove session data +await client.deleteSession("user-123-task-456"); +``` + +> **`destroy()` vs `deleteSession()`:** `destroy()` releases in-memory resources but keeps session data on disk for later resumption. `deleteSession()` permanently removes everything, including files on disk. + ## Automatic Cleanup: Idle Timeout The CLI has a built-in 30-minute idle timeout. Sessions without activity are automatically cleaned up: @@ -526,8 +537,8 @@ await withSessionLock("user-123-task-456", async () => { | **Resume session** | `client.resumeSession(sessionId)` | | **BYOK resume** | Re-provide `provider` config | | **List sessions** | `client.listSessions(filter?)` | -| **Delete session** | `client.deleteSession(sessionId)` | -| **Destroy active session** | `session.destroy()` | +| **Close active session** | `session.destroy()` — releases in-memory resources; session data on disk is preserved for resumption | +| **Delete session permanently** | `client.deleteSession(sessionId)` — permanently removes all session data from disk; cannot be resumed | | **Containerized deployment** | Mount `~/.copilot/session-state/` to persistent storage | ## Next Steps diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 1f3a7fb43..40e153260 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -210,18 +210,23 @@ async Task StartCoreAsync(CancellationToken ct) } /// - /// Disconnects from the Copilot server and stops all active sessions. + /// Disconnects from the Copilot server and closes all active sessions. /// /// A representing the asynchronous operation. /// /// /// This method performs graceful cleanup: /// - /// Destroys all active sessions + /// Closes all active sessions (releases in-memory resources) /// Closes the JSON-RPC connection /// Terminates the CLI server process (if spawned by this client) /// /// + /// + /// Note: session data on disk is preserved, so sessions can be resumed later. + /// To permanently remove session data before stopping, call + /// for each session first. + /// /// /// Thrown when multiple errors occur during cleanup. /// @@ -655,15 +660,17 @@ public async Task> ListModelsAsync(CancellationToken cancellatio } /// - /// Deletes a Copilot session by its ID. + /// Permanently deletes a session and all its data from disk, including + /// conversation history, planning state, and artifacts. /// /// The ID of the session to delete. /// A that can be used to cancel the operation. /// A task that represents the asynchronous delete operation. /// Thrown when the session does not exist or deletion fails. /// - /// This permanently removes the session and all its conversation history. - /// The session cannot be resumed after deletion. + /// Unlike , which only releases in-memory + /// resources and preserves session data for later resumption, this method is + /// irreversible. The session cannot be resumed after deletion. /// /// /// diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 923b193cc..02bb276dc 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -541,22 +541,25 @@ await InvokeRpcAsync( } /// - /// Disposes the and releases all associated resources. + /// Closes this session and releases all in-memory resources (event handlers, + /// tool handlers, permission handlers). /// /// A task representing the dispose operation. /// /// - /// After calling this method, the session can no longer be used. All event handlers - /// and tool handlers are cleared. + /// Session state on disk (conversation history, planning state, artifacts) is + /// preserved, so the conversation can be resumed later by calling + /// with the session ID. To + /// permanently remove all session data including files on disk, use + /// instead. /// /// - /// To continue the conversation, use - /// with the session ID. + /// After calling this method, the session object can no longer be used. /// /// /// /// - /// // Using 'await using' for automatic disposal + /// // Using 'await using' for automatic disposal — session can still be resumed later /// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll }); /// /// // Or manually dispose diff --git a/go/client.go b/go/client.go index c88a68ac3..f140127b6 100644 --- a/go/client.go +++ b/go/client.go @@ -293,10 +293,14 @@ func (c *Client) Start(ctx context.Context) error { // Stop stops the CLI server and closes all active sessions. // // This method performs graceful cleanup: -// 1. Destroys all active sessions +// 1. Closes all active sessions (releases in-memory resources) // 2. Closes the JSON-RPC connection // 3. Terminates the CLI server process (if spawned by this client) // +// Note: session data on disk is preserved, so sessions can be resumed later. +// To permanently remove session data before stopping, call [Client.DeleteSession] +// for each session first. +// // Returns an error that aggregates all errors encountered during cleanup. // // Example: @@ -685,8 +689,11 @@ func (c *Client) ListSessions(ctx context.Context, filter *SessionListFilter) ([ return response.Sessions, nil } -// DeleteSession permanently deletes a session and all its conversation history. +// DeleteSession permanently deletes a session and all its data from disk, +// including conversation history, planning state, and artifacts. // +// Unlike [Session.Destroy], which only releases in-memory resources and +// preserves session data for later resumption, DeleteSession is irreversible. // The session cannot be resumed after deletion. If the session is in the local // sessions map, it will be removed. // diff --git a/go/session.go b/go/session.go index 12d1b1afa..561e566d1 100644 --- a/go/session.go +++ b/go/session.go @@ -511,17 +511,21 @@ func (s *Session) GetMessages(ctx context.Context) ([]SessionEvent, error) { return response.Events, nil } -// Destroy destroys this session and releases all associated resources. +// Destroy closes this session and releases all in-memory resources (event +// handlers, tool handlers, permission handlers). // -// After calling this method, the session can no longer be used. All event -// handlers and tool handlers are cleared. To continue the conversation, -// use [Client.ResumeSession] with the session ID. +// Session state on disk (conversation history, planning state, artifacts) is +// preserved, so the conversation can be resumed later by calling +// [Client.ResumeSession] with the session ID. To permanently remove all +// session data including files on disk, use [Client.DeleteSession] instead. +// +// After calling this method, the session object can no longer be used. // // Returns an error if the connection fails. // // Example: // -// // Clean up when done +// // Clean up when done — session can still be resumed later // if err := session.Destroy(); err != nil { // log.Printf("Failed to destroy session: %v", err) // } diff --git a/nodejs/src/client.ts b/nodejs/src/client.ts index 6d841c7cc..c8c81dc74 100644 --- a/nodejs/src/client.ts +++ b/nodejs/src/client.ts @@ -307,10 +307,14 @@ export class CopilotClient { * Stops the CLI server and closes all active sessions. * * This method performs graceful cleanup: - * 1. Destroys all active sessions with retry logic + * 1. Closes all active sessions (releases in-memory resources) * 2. Closes the JSON-RPC connection * 3. Terminates the CLI server process (if spawned by this client) * + * Note: session data on disk is preserved, so sessions can be resumed later. + * To permanently remove session data before stopping, call + * {@link deleteSession} for each session first. + * * @returns A promise that resolves with an array of errors encountered during cleanup. * An empty array indicates all cleanup succeeded. * @@ -823,10 +827,12 @@ export class CopilotClient { } /** - * Deletes a session and its data from disk. + * Permanently deletes a session and all its data from disk, including + * conversation history, planning state, and artifacts. * - * This permanently removes the session and all its conversation history. - * The session cannot be resumed after deletion. + * Unlike {@link CopilotSession.destroy}, which only releases in-memory + * resources and preserves session data for later resumption, this method + * is irreversible. The session cannot be resumed after deletion. * * @param sessionId - The ID of the session to delete * @returns A promise that resolves when the session is deleted diff --git a/nodejs/src/session.ts b/nodejs/src/session.ts index 04525d2bb..6e32ee5f9 100644 --- a/nodejs/src/session.ts +++ b/nodejs/src/session.ts @@ -499,18 +499,23 @@ export class CopilotSession { } /** - * Destroys this session and releases all associated resources. + * Closes this session and releases all in-memory resources (event handlers, + * tool handlers, permission handlers). * - * After calling this method, the session can no longer be used. All event - * handlers and tool handlers are cleared. To continue the conversation, - * use {@link CopilotClient.resumeSession} with the session ID. + * Session state on disk (conversation history, planning state, artifacts) is + * preserved, so the conversation can be resumed later by calling + * {@link CopilotClient.resumeSession} with the session ID. To permanently + * remove all session data including files on disk, use + * {@link CopilotClient.deleteSession} instead. * - * @returns A promise that resolves when the session is destroyed + * After calling this method, the session object can no longer be used. + * + * @returns A promise that resolves when the session is closed * @throws Error if the connection fails * * @example * ```typescript - * // Clean up when done + * // Clean up when done — session can still be resumed later * await session.destroy(); * ``` */ diff --git a/python/copilot/client.py b/python/copilot/client.py index c25e68096..2d50c73e5 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -320,10 +320,14 @@ async def stop(self) -> list["StopError"]: Stop the CLI server and close all active sessions. This method performs graceful cleanup: - 1. Destroys all active sessions + 1. Closes all active sessions (releases in-memory resources) 2. Closes the JSON-RPC connection 3. Terminates the CLI server process (if spawned by this client) + Note: session data on disk is preserved, so sessions can be resumed + later. To permanently remove session data before stopping, call + :meth:`delete_session` for each session first. + Returns: A list of StopError objects containing error messages that occurred during cleanup. An empty list indicates all cleanup succeeded. @@ -928,10 +932,12 @@ async def list_sessions( async def delete_session(self, session_id: str) -> None: """ - Delete a session permanently. + Permanently delete a session and all its data from disk, including + conversation history, planning state, and artifacts. - This permanently removes the session and all its conversation history. - The session cannot be resumed after deletion. + Unlike :meth:`CopilotSession.destroy`, which only releases in-memory + resources and preserves session data for later resumption, this method + is irreversible. The session cannot be resumed after deletion. Args: session_id: The ID of the session to delete. diff --git a/python/copilot/session.py b/python/copilot/session.py index a02dcf1e9..72c085304 100644 --- a/python/copilot/session.py +++ b/python/copilot/session.py @@ -476,17 +476,22 @@ async def get_messages(self) -> list[SessionEvent]: async def destroy(self) -> None: """ - Destroy this session and release all associated resources. + Close this session and release all in-memory resources (event handlers, + tool handlers, permission handlers). - After calling this method, the session can no longer be used. All event - handlers and tool handlers are cleared. To continue the conversation, - use :meth:`CopilotClient.resume_session` with the session ID. + Session state on disk (conversation history, planning state, artifacts) + is preserved, so the conversation can be resumed later by calling + :meth:`CopilotClient.resume_session` with the session ID. To + permanently remove all session data including files on disk, use + :meth:`CopilotClient.delete_session` instead. + + After calling this method, the session object can no longer be used. Raises: Exception: If the connection fails. Example: - >>> # Clean up when done + >>> # Clean up when done — session can still be resumed later >>> await session.destroy() """ await self._client.request("session.destroy", {"sessionId": self.session_id})