Skip to content

Commit 4377e73

Browse files
patnikoCopilot
andcommitted
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>
1 parent fc63890 commit 4377e73

9 files changed

Lines changed: 96 additions & 42 deletions

File tree

docs/guides/session-persistence.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,16 +325,16 @@ async function cleanupExpiredSessions(maxAgeMs: number) {
325325
await cleanupExpiredSessions(24 * 60 * 60 * 1000);
326326
```
327327

328-
### Explicit Session Destruction
328+
### Closing a Session (`destroy`)
329329

330-
When a task completes, destroy the session explicitly rather than waiting for timeouts:
330+
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:
331331

332332
```typescript
333333
try {
334334
// Do work...
335335
await session.sendAndWait({ prompt: "Complete the task" });
336336

337-
// Task complete - clean up
337+
// Task complete — release in-memory resources (session can be resumed later)
338338
await session.destroy();
339339
} catch (error) {
340340
// Clean up even on error
@@ -343,6 +343,17 @@ try {
343343
}
344344
```
345345

346+
### Permanently Deleting a Session (`deleteSession`)
347+
348+
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:
349+
350+
```typescript
351+
// Permanently remove session data
352+
await client.deleteSession("user-123-task-456");
353+
```
354+
355+
> **`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.
356+
346357
## Automatic Cleanup: Idle Timeout
347358

348359
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 () => {
526537
| **Resume session** | `client.resumeSession(sessionId)` |
527538
| **BYOK resume** | Re-provide `provider` config |
528539
| **List sessions** | `client.listSessions(filter?)` |
529-
| **Delete session** | `client.deleteSession(sessionId)` |
530-
| **Destroy active session** | `session.destroy()` |
540+
| **Close active session** | `session.destroy()` — releases in-memory resources; session data on disk is preserved for resumption |
541+
| **Delete session permanently** | `client.deleteSession(sessionId)` — permanently removes all session data from disk; cannot be resumed |
531542
| **Containerized deployment** | Mount `~/.copilot/session-state/` to persistent storage |
532543

533544
## Next Steps

dotnet/src/Client.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,23 @@ async Task<Connection> StartCoreAsync(CancellationToken ct)
210210
}
211211

212212
/// <summary>
213-
/// Disconnects from the Copilot server and stops all active sessions.
213+
/// Disconnects from the Copilot server and closes all active sessions.
214214
/// </summary>
215215
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
216216
/// <remarks>
217217
/// <para>
218218
/// This method performs graceful cleanup:
219219
/// <list type="number">
220-
/// <item>Destroys all active sessions</item>
220+
/// <item>Closes all active sessions (releases in-memory resources)</item>
221221
/// <item>Closes the JSON-RPC connection</item>
222222
/// <item>Terminates the CLI server process (if spawned by this client)</item>
223223
/// </list>
224224
/// </para>
225+
/// <para>
226+
/// Note: session data on disk is preserved, so sessions can be resumed later.
227+
/// To permanently remove session data before stopping, call
228+
/// <see cref="DeleteSessionAsync"/> for each session first.
229+
/// </para>
225230
/// </remarks>
226231
/// <exception cref="AggregateException">Thrown when multiple errors occur during cleanup.</exception>
227232
/// <example>
@@ -655,15 +660,17 @@ public async Task<List<ModelInfo>> ListModelsAsync(CancellationToken cancellatio
655660
}
656661

657662
/// <summary>
658-
/// Deletes a Copilot session by its ID.
663+
/// Permanently deletes a session and all its data from disk, including
664+
/// conversation history, planning state, and artifacts.
659665
/// </summary>
660666
/// <param name="sessionId">The ID of the session to delete.</param>
661667
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
662668
/// <returns>A task that represents the asynchronous delete operation.</returns>
663669
/// <exception cref="InvalidOperationException">Thrown when the session does not exist or deletion fails.</exception>
664670
/// <remarks>
665-
/// This permanently removes the session and all its conversation history.
666-
/// The session cannot be resumed after deletion.
671+
/// Unlike <see cref="CopilotSession.DisposeAsync"/>, which only releases in-memory
672+
/// resources and preserves session data for later resumption, this method is
673+
/// irreversible. The session cannot be resumed after deletion.
667674
/// </remarks>
668675
/// <example>
669676
/// <code>

dotnet/src/Session.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -541,22 +541,25 @@ await InvokeRpcAsync<object>(
541541
}
542542

543543
/// <summary>
544-
/// Disposes the <see cref="CopilotSession"/> and releases all associated resources.
544+
/// Closes this session and releases all in-memory resources (event handlers,
545+
/// tool handlers, permission handlers).
545546
/// </summary>
546547
/// <returns>A task representing the dispose operation.</returns>
547548
/// <remarks>
548549
/// <para>
549-
/// After calling this method, the session can no longer be used. All event handlers
550-
/// and tool handlers are cleared.
550+
/// Session state on disk (conversation history, planning state, artifacts) is
551+
/// preserved, so the conversation can be resumed later by calling
552+
/// <see cref="CopilotClient.ResumeSessionAsync"/> with the session ID. To
553+
/// permanently remove all session data including files on disk, use
554+
/// <see cref="CopilotClient.DeleteSessionAsync"/> instead.
551555
/// </para>
552556
/// <para>
553-
/// To continue the conversation, use <see cref="CopilotClient.ResumeSessionAsync"/>
554-
/// with the session ID.
557+
/// After calling this method, the session object can no longer be used.
555558
/// </para>
556559
/// </remarks>
557560
/// <example>
558561
/// <code>
559-
/// // Using 'await using' for automatic disposal
562+
/// // Using 'await using' for automatic disposal — session can still be resumed later
560563
/// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll });
561564
///
562565
/// // Or manually dispose

go/client.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,14 @@ func (c *Client) Start(ctx context.Context) error {
293293
// Stop stops the CLI server and closes all active sessions.
294294
//
295295
// This method performs graceful cleanup:
296-
// 1. Destroys all active sessions
296+
// 1. Closes all active sessions (releases in-memory resources)
297297
// 2. Closes the JSON-RPC connection
298298
// 3. Terminates the CLI server process (if spawned by this client)
299299
//
300+
// Note: session data on disk is preserved, so sessions can be resumed later.
301+
// To permanently remove session data before stopping, call [Client.DeleteSession]
302+
// for each session first.
303+
//
300304
// Returns an error that aggregates all errors encountered during cleanup.
301305
//
302306
// Example:
@@ -685,8 +689,11 @@ func (c *Client) ListSessions(ctx context.Context, filter *SessionListFilter) ([
685689
return response.Sessions, nil
686690
}
687691

688-
// DeleteSession permanently deletes a session and all its conversation history.
692+
// DeleteSession permanently deletes a session and all its data from disk,
693+
// including conversation history, planning state, and artifacts.
689694
//
695+
// Unlike [Session.Destroy], which only releases in-memory resources and
696+
// preserves session data for later resumption, DeleteSession is irreversible.
690697
// The session cannot be resumed after deletion. If the session is in the local
691698
// sessions map, it will be removed.
692699
//

go/session.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -511,17 +511,21 @@ func (s *Session) GetMessages(ctx context.Context) ([]SessionEvent, error) {
511511
return response.Events, nil
512512
}
513513

514-
// Destroy destroys this session and releases all associated resources.
514+
// Destroy closes this session and releases all in-memory resources (event
515+
// handlers, tool handlers, permission handlers).
515516
//
516-
// After calling this method, the session can no longer be used. All event
517-
// handlers and tool handlers are cleared. To continue the conversation,
518-
// use [Client.ResumeSession] with the session ID.
517+
// Session state on disk (conversation history, planning state, artifacts) is
518+
// preserved, so the conversation can be resumed later by calling
519+
// [Client.ResumeSession] with the session ID. To permanently remove all
520+
// session data including files on disk, use [Client.DeleteSession] instead.
521+
//
522+
// After calling this method, the session object can no longer be used.
519523
//
520524
// Returns an error if the connection fails.
521525
//
522526
// Example:
523527
//
524-
// // Clean up when done
528+
// // Clean up when done — session can still be resumed later
525529
// if err := session.Destroy(); err != nil {
526530
// log.Printf("Failed to destroy session: %v", err)
527531
// }

nodejs/src/client.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,14 @@ export class CopilotClient {
307307
* Stops the CLI server and closes all active sessions.
308308
*
309309
* This method performs graceful cleanup:
310-
* 1. Destroys all active sessions with retry logic
310+
* 1. Closes all active sessions (releases in-memory resources)
311311
* 2. Closes the JSON-RPC connection
312312
* 3. Terminates the CLI server process (if spawned by this client)
313313
*
314+
* Note: session data on disk is preserved, so sessions can be resumed later.
315+
* To permanently remove session data before stopping, call
316+
* {@link deleteSession} for each session first.
317+
*
314318
* @returns A promise that resolves with an array of errors encountered during cleanup.
315319
* An empty array indicates all cleanup succeeded.
316320
*
@@ -823,10 +827,12 @@ export class CopilotClient {
823827
}
824828

825829
/**
826-
* Deletes a session and its data from disk.
830+
* Permanently deletes a session and all its data from disk, including
831+
* conversation history, planning state, and artifacts.
827832
*
828-
* This permanently removes the session and all its conversation history.
829-
* The session cannot be resumed after deletion.
833+
* Unlike {@link CopilotSession.destroy}, which only releases in-memory
834+
* resources and preserves session data for later resumption, this method
835+
* is irreversible. The session cannot be resumed after deletion.
830836
*
831837
* @param sessionId - The ID of the session to delete
832838
* @returns A promise that resolves when the session is deleted

nodejs/src/session.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -499,18 +499,23 @@ export class CopilotSession {
499499
}
500500

501501
/**
502-
* Destroys this session and releases all associated resources.
502+
* Closes this session and releases all in-memory resources (event handlers,
503+
* tool handlers, permission handlers).
503504
*
504-
* After calling this method, the session can no longer be used. All event
505-
* handlers and tool handlers are cleared. To continue the conversation,
506-
* use {@link CopilotClient.resumeSession} with the session ID.
505+
* Session state on disk (conversation history, planning state, artifacts) is
506+
* preserved, so the conversation can be resumed later by calling
507+
* {@link CopilotClient.resumeSession} with the session ID. To permanently
508+
* remove all session data including files on disk, use
509+
* {@link CopilotClient.deleteSession} instead.
507510
*
508-
* @returns A promise that resolves when the session is destroyed
511+
* After calling this method, the session object can no longer be used.
512+
*
513+
* @returns A promise that resolves when the session is closed
509514
* @throws Error if the connection fails
510515
*
511516
* @example
512517
* ```typescript
513-
* // Clean up when done
518+
* // Clean up when done — session can still be resumed later
514519
* await session.destroy();
515520
* ```
516521
*/

python/copilot/client.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,14 @@ async def stop(self) -> list["StopError"]:
320320
Stop the CLI server and close all active sessions.
321321
322322
This method performs graceful cleanup:
323-
1. Destroys all active sessions
323+
1. Closes all active sessions (releases in-memory resources)
324324
2. Closes the JSON-RPC connection
325325
3. Terminates the CLI server process (if spawned by this client)
326326
327+
Note: session data on disk is preserved, so sessions can be resumed
328+
later. To permanently remove session data before stopping, call
329+
:meth:`delete_session` for each session first.
330+
327331
Returns:
328332
A list of StopError objects containing error messages that occurred
329333
during cleanup. An empty list indicates all cleanup succeeded.
@@ -928,10 +932,12 @@ async def list_sessions(
928932

929933
async def delete_session(self, session_id: str) -> None:
930934
"""
931-
Delete a session permanently.
935+
Permanently delete a session and all its data from disk, including
936+
conversation history, planning state, and artifacts.
932937
933-
This permanently removes the session and all its conversation history.
934-
The session cannot be resumed after deletion.
938+
Unlike :meth:`CopilotSession.destroy`, which only releases in-memory
939+
resources and preserves session data for later resumption, this method
940+
is irreversible. The session cannot be resumed after deletion.
935941
936942
Args:
937943
session_id: The ID of the session to delete.

python/copilot/session.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -476,17 +476,22 @@ async def get_messages(self) -> list[SessionEvent]:
476476

477477
async def destroy(self) -> None:
478478
"""
479-
Destroy this session and release all associated resources.
479+
Close this session and release all in-memory resources (event handlers,
480+
tool handlers, permission handlers).
480481
481-
After calling this method, the session can no longer be used. All event
482-
handlers and tool handlers are cleared. To continue the conversation,
483-
use :meth:`CopilotClient.resume_session` with the session ID.
482+
Session state on disk (conversation history, planning state, artifacts)
483+
is preserved, so the conversation can be resumed later by calling
484+
:meth:`CopilotClient.resume_session` with the session ID. To
485+
permanently remove all session data including files on disk, use
486+
:meth:`CopilotClient.delete_session` instead.
487+
488+
After calling this method, the session object can no longer be used.
484489
485490
Raises:
486491
Exception: If the connection fails.
487492
488493
Example:
489-
>>> # Clean up when done
494+
>>> # Clean up when done — session can still be resumed later
490495
>>> await session.destroy()
491496
"""
492497
await self._client.request("session.destroy", {"sessionId": self.session_id})

0 commit comments

Comments
 (0)