# Возобновление сессии и сохранение

Это руководство проведёт вас через возможности сохранения сессий SDK — как поставить работу на паузу, возобновить её позже и управлять сессиями в производственных средах.

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

## Как работают сеансы

Когда вы создаёте сессию, CLI Copilot сохраняет историю разговоров, состояние инструмента и контекст планирования. По умолчанию это состояние остаётся в памяти и исчезает после окончания сессии. С включенной устойчивостью вы можете возобновлять сессии при перезапусках, миграциях контейнеров или даже в разных клиентских инстансах.

![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-0.png)

| Государство            | Что происходит                                        |
| ---------------------- | ----------------------------------------------------- |
| **Создать**            |                                                       |
| `session_id` Назначено |                                                       |
| **Активный**           | Отправляйте подсказки, призывы к инструментам, ответы |
| **Приостановлено**     | Состояние сохранено на диск                           |
| **Резюме**             | Состояние, загруженное с диска                        |

## Быстрый старт: создание возобновляемой сессии

Ключ к возобновляемым сессиям — это предоставление собственных `session_id`. Без этого SDK генерирует случайный идентификатор, и сессию нельзя возобновить позже.

### TypeScript

```typescript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();

// Create a session with a meaningful ID
const session = await client.createSession({
  sessionId: "user-123-task-456",
  model: "gpt-5.2-codex",
});

// Do some work...
await session.sendAndWait({ prompt: "Analyze my codebase" });

// Session state is automatically persisted
// You can safely close the client
```

### Python

```python
from copilot import CopilotClient
from copilot.session import PermissionHandler

client = CopilotClient()
await client.start()

# Create a session with a meaningful ID
session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-5.2-codex", session_id="user-123-task-456")

# Do some work...
await session.send_and_wait("Analyze my codebase")

# Session state is automatically persisted
```

### Go

```golang
ctx := context.Background()
client := copilot.NewClient(nil)

// Create a session with a meaningful ID
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
    SessionID: "user-123-task-456",
    Model:     "gpt-5.2-codex",
})

// Do some work...
session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Analyze my codebase"})

// Session state is automatically persisted
```

### C# (.NET)

```csharp
using GitHub.Copilot;

var client = new CopilotClient();

// Create a session with a meaningful ID
var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = "user-123-task-456",
    Model = "gpt-5.2-codex",
});

// Do some work...
await session.SendAndWaitAsync(new MessageOptions { Prompt = "Analyze my codebase" });

// Session state is automatically persisted
```

## Возобновление сессии

Позже — через минуты, часы или даже дни — вы сможете продолжить сессию с того места, где остановились.

![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-1.png)

### TypeScript

```typescript
// Resume from a different client instance (or after restart)
const session = await client.resumeSession("user-123-task-456");

// Continue where you left off
await session.sendAndWait({ prompt: "What did we discuss earlier?" });
```

### Python

```python
# Resume from a different client instance (or after restart)
session = await client.resume_session("user-123-task-456", on_permission_request=PermissionHandler.approve_all)

# Continue where you left off
await session.send_and_wait("What did we discuss earlier?")
```

### Go

```golang
ctx := context.Background()

// Resume from a different client instance (or after restart)
session, _ := client.ResumeSession(ctx, "user-123-task-456", nil)

// Continue where you left off
session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "What did we discuss earlier?"})
```

### C# (.NET)

```csharp
// Resume from a different client instance (or after restart)
var session = await client.ResumeSessionAsync("user-123-task-456");

// Continue where you left off
await session.SendAndWaitAsync(new MessageOptions { Prompt = "What did we discuss earlier?" });
```

## Варианты резюме

При возобновлении сессии вы можете опционально перенастроить несколько настроек. Это полезно, когда нужно изменить модель, обновить конфигурацию инструментов или изменить поведение.

| Опция              | Description                                                              |
| ------------------ | ------------------------------------------------------------------------ |
| `model`            | Измените модель для возобновлённой сессии                                |
| `systemMessage`    | Отменить или расширить системный запрос                                  |
| `availableTools`   | Ограничьте доступные инструменты                                         |
| `excludedTools`    | Отключите определённые инструменты                                       |
| `provider`         | Повторное предоставление учетных данных BYOK (требуется для сессий BYOK) |
| `reasoningEffort`  | Корректируйте уровень усилий по рассуждению                              |
| `streaming`        | Включить/отключить потоковые ответы                                      |
| `workingDirectory` | Изменить рабочий каталог                                                 |
| `configDir`        | Каталог конфигурации Override                                            |
| `mcpServers`       | Настройка MCP-серверов                                                   |
| `customAgents`     | Настройка пользовательских агентов                                       |
| `agent`            | Предварительный выбор пользовательского агента по имени                  |
| `skillDirectories` | Каталоги для загрузки навыков                                            |
| `disabledSkills`   | Навыки для отключения                                                    |
| `infiniteSessions` | Настройка поведения бесконечных сессий                                   |

### Пример: изменение модели в резюме

```typescript
// Resume with a different model
const session = await client.resumeSession("user-123-task-456", {
  model: "claude-sonnet-4",  // Switch to a different model
  reasoningEffort: "high",   // Increase reasoning effort
});
```

## Использование BYOK (принеси свой ключ) с возобновленными сессиями

При использовании собственных API-ключей при возобновлении работы необходимо повторно указать конфигурацию провайдера. API-ключи никогда не сохраняются на диске по соображениям безопасности.

```typescript
// Original session with BYOK
const session = await client.createSession({
  sessionId: "user-123-task-456",
  model: "gpt-5.2-codex",
  provider: {
    type: "azure",
    endpoint: "https://my-resource.openai.azure.com",
    apiKey: process.env.AZURE_OPENAI_KEY,
    deploymentId: "my-gpt-deployment",
  },
});

// When resuming, you MUST re-provide the provider config
const resumed = await client.resumeSession("user-123-task-456", {
  provider: {
    type: "azure",
    endpoint: "https://my-resource.openai.azure.com",
    apiKey: process.env.AZURE_OPENAI_KEY,  // Required again
    deploymentId: "my-gpt-deployment",
  },
});
```

## Что настаивает?

Состояние сессии сохраняется в `~/.copilot/session-state/{sessionId}/`виде:

```text
~/.copilot/session-state/
└── user-123-task-456/
    ├── checkpoints/           # Conversation history snapshots
    │   ├── 001.json          # Initial state
    │   ├── 002.json          # After first interaction
    │   └── ...               # Incremental checkpoints
    ├── plan.md               # Agent's planning state (if any)
    └── files/                # Session artifacts
        ├── analysis.md       # Files the agent created
        └── notes.txt         # Working documents
```

| Данные                         | Продолжался?                                   | Notes |
| ------------------------------ | ---------------------------------------------- | ----- |
| История беседы                 |                                                |       |
| ✅ Да                           | Полный поток сообщений                         |       |
| Результаты вызова инструментов |                                                |       |
| ✅ Да                           | Кэшировано для контекста                       |       |
| Состояние планирования агента  |                                                |       |
| ✅ Да                           | Файл `plan.md`                                 |       |
| Артефакты сессии               |                                                |       |
| ✅ Да                           | В `files/` справочнике                         |       |
| Ключи провайдера/API           |                                                |       |
| ❌ Нет                          | Безопасность: необходимо повторно предоставить |       |
| Состояние инструмента в памяти |                                                |       |
| ❌ Нет                          | Инструменты должны быть безсостоятельными      |       |

## Лучшие практики идентификатора сессии

Выбирайте идентификаторы сессий, которые кодируют принадлежность и назначение. Это значительно облегчает аудит и уборку.

| Pattern                         | Пример                                          | Вариант использования |
| ------------------------------- | ----------------------------------------------- | --------------------- |
| ❌                               |                                                 |                       |
| `abc123`                        |                                                 |                       |
| Случайные идентификаторы        | Сложно аудитировать, нет информации о владельце |                       |
| ✅                               |                                                 |                       |
| `user-{userId}-{taskId}`        |                                                 |                       |
| `user-alice-pr-review-42`       | Многопользовательские приложения                |                       |
| ✅                               |                                                 |                       |
| `tenant-{tenantId}-{workflow}`  |                                                 |                       |
| `tenant-acme-onboarding`        | Многопользовательский SaaS                      |                       |
| ✅                               |                                                 |                       |
| `{userId}-{taskId}-{timestamp}` |                                                 |                       |
| `alice-deploy-1706932800`       | Очистка по времени                              |                       |

**Преимущества структурированных ID:**

* Легко аудитировать: «Показать все сессии для пользователя Alice»
* Простое исправление: «Удалить все сессии старше X»
* Естественный контроль доступа: разбор user ID из session ID

### Пример: генерация идентификаторов сессий

```typescript
function createSessionId(userId: string, taskType: string): string {
  const timestamp = Date.now();
  return `${userId}-${taskType}-${timestamp}`;
}

const sessionId = createSessionId("alice", "code-review");
// → "alice-code-review-1706932800000"
```

```python
import time

def create_session_id(user_id: str, task_type: str) -> str:
    timestamp = int(time.time())
    return f"{user_id}-{task_type}-{timestamp}"

session_id = create_session_id("alice", "code-review")
# → "alice-code-review-1706932800"
```

## Управление жизненным циклом сессии

### Список активных сессий

```typescript
// List all sessions
const sessions = await client.listSessions();
console.log(`Found ${sessions.length} sessions`);

for (const session of sessions) {
  console.log(`- ${session.sessionId} (created: ${session.createdAt})`);
}

// Filter sessions by repository
const repoSessions = await client.listSessions({ repository: "owner/repo" });
```

### Уборка старых сессий

```typescript
async function cleanupExpiredSessions(maxAgeMs: number) {
  const sessions = await client.listSessions();
  const now = Date.now();
  
  for (const session of sessions) {
    const age = now - new Date(session.createdAt).getTime();
    if (age > maxAgeMs) {
      await client.deleteSession(session.sessionId);
      console.log(`Deleted expired session: ${session.sessionId}`);
    }
  }
}

// Clean up sessions older than 24 hours
await cleanupExpiredSessions(24 * 60 * 60 * 1000);
```

### Отключение от сессии (`disconnect`)

Когда задача завершена, явно отключайтесь от сессии, а не ждите тайм-аутов. Это освобождает ресурсы в памяти, но **сохраняет данные сессии на диске**, так что сессию можно возобновить позже:

```typescript
try {
  // Do work...
  await session.sendAndWait({ prompt: "Complete the task" });
  
  // Task complete — release in-memory resources (session can be resumed later)
  await session.disconnect();
} catch (error) {
  // Clean up even on error
  await session.disconnect();
  throw error;
}
```

Каждый SDK также предоставляет идиоматические автоматические шаблоны очистки:

| Язык                              | Pattern                                                                             | Пример                                                               |
| --------------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| **TypeScript**                    | `Symbol.asyncDispose`                                                               | `await using session = await client.createSession(config);`          |
| **Python**                        |                                                                                     |                                                                      |
| `async with` диспетчер контекстов | `async with await client.create_session(on_permission_request=handler) as session:` |                                                                      |
| **C#**                            | `IAsyncDisposable`                                                                  | `await using var session = await client.CreateSessionAsync(config);` |
| **Go**                            | `defer`                                                                             | `defer session.Disconnect()`                                         |

> \[!NOTE]
> Вместо <code>PackageIconUrl</code> теперь используется <code>PackageIcon</code>. Существующий код, использующий `destroy()` его, продолжит работать, но его следует перевести.

### Постоянное удаление сессии (`deleteSession`)

Чтобы навсегда удалить сессию и все её данные с диска (история разговоров, состояние планирования, артефакты), используйте `deleteSession`. Это необратимо — сессия **не** может быть возобновлена после удаления:

```typescript
// Permanently remove session data
await client.deleteSession("user-123-task-456");
```

> **`disconnect()` VS `deleteSession()`:**`disconnect()` освобождает ресурсы в памяти, но сохраняет данные сессии на диске для последующего возобновления. `deleteSession()` Навсегда удаляет всё, включая файлы с диска.

## Автоматическая очистка: тайм-аут на холостом ходу

По умолчанию сессии **не имеют тайм-аута в простое** и живут бесконечно, пока не будут явно отключены или удалены. По желанию вы можете настроить серверный тайм-аут простоя с помощью `CopilotClientOptions.sessionIdleTimeoutSeconds`следующих методов:

```typescript
const client = new CopilotClient({
  sessionIdleTimeoutSeconds: 30 * 60, // 30 minutes
});
```

Когда тайм-аут настроен, сессии без активности в течение этого времени автоматически очищаются. Настройте или `0` пропустите, чтобы отключить.

> \[!NOTE]
> Эта опция действует только тогда, когда SDK запускает процесс выполнения. При подключении к существующему серверу через `cliUrl`, применяется собственная тайм-аут сервера.

![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-2.png)

Сессии с активной работой (выполняющие команды, фоновые агенты) всегда защищены от очистки в режиме простоя, независимо от настройки тайм-аута.

Прислушивайтесь к событиям простоя, которые могут реагировать на неактивность сессии:

```typescript
session.on("session.idle", (event) => {
  console.log(`Session idle for ${event.idleDurationMs}ms`);
});
```

## Шаблоны развертывания

### Шаблон 1: один CLI-сервер на пользователя (рекомендуется)

Лучше всего для: сильной изоляции, многоарендных сред, динамических сессий Azure.

![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-3.png)

\*\*Преимущества:\*\*✅ Полная изоляция | ✅ Простая безопасность | ✅ Простое масштабирование

### Шаблон 2: общий CLI-сервер (ресурсоэффективный)

Лучше всего для: внутренних инструментов, доверенных сред, ограниченных ресурсами конфигураций.

![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-4.png)

**Требования:**

* ⚠️ Уникальные идентификаторы сессий для каждого пользователя
* ⚠️ Управление доступом на уровне приложений
* ⚠️ Проверка идентификатора сессии перед операциями

```typescript
// Application-level access control for shared CLI
async function resumeSessionWithAuth(
  client: CopilotClient,
  sessionId: string,
  currentUserId: string
): Promise<Session> {
  // Parse user from session ID
  const [sessionUserId] = sessionId.split("-");
  
  if (sessionUserId !== currentUserId) {
    throw new Error("Access denied: session belongs to another user");
  }
  
  return client.resumeSession(sessionId);
}
```

## динамические сеансы Azure

Для серверных/контейнерных развертываний, где контейнеры могут перезапускаться или мигрировать:

### Монтирование постоянного хранения

Каталог состояния сессии должен быть смонтирован в постоянное хранилище:

```yaml
# Azure Container Instance example
containers:
  - name: copilot-agent
    image: my-agent:latest
    volumeMounts:
      - name: session-storage
        mountPath: /home/app/.copilot/session-state

volumes:
  - name: session-storage
    azureFile:
      shareName: copilot-sessions
      storageAccountName: myaccount
```

![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-5.png)

**Сессия переживает запуск в контейнере!**

## Бесконечные сессии для долгосрочных рабочих процессов

Для рабочих процессов, которые могут превышать ограничения контекста, включайте бесконечные сессии с автоматической компрессией:

```typescript
const session = await client.createSession({
  sessionId: "long-workflow-123",
  infiniteSessions: {
    enabled: true,
    backgroundCompactionThreshold: 0.80,  // Start compaction at 80% context
    bufferExhaustionThreshold: 0.95,      // Block at 95% if needed
  },
});
```

> \[!NOTE]
> Пороги — это коэффициенты использования контекста (0,0-1,0), а не абсолютное количество токенов. Подробности смотрите [в АВТОЗАГОЛОВКЕ](/ru/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/troubleshooting/compatibility) .

## Ограничения и рекомендации

| Limitation                                       | Description                                              | Смягчение последствий                                                                                   |
| ------------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| **Повторная аутентификация BYOK**                | Ключи API не сохраняются                                 | Ключи от хранилища в вашем секретном менеджере; Указывайте в резюме                                     |
| **Регистрируемое хранилище**                     |                                                          |                                                                                                         |
| `~/.copilot/session-state/` должно быть записано | Монтировать постоянный объём в контейнеры                |                                                                                                         |
| **Нет блокировки сессии**                        | Параллельный доступ к одной и той же сессии не определен | Реализовать блокировку или очередь на уровне приложения                                                 |
| **Состояние инструмента не сохраняется**         | Состояние инструмента в памяти теряется                  | Проектируйте инструменты так, чтобы они были безсостоятельными или сохраняли своё собственное состояние |

### Обработка параллельного доступа

SDK не обеспечивает встроенную блокировку сессий. Если несколько клиентов могут получить доступ к одной и той же сессии:

```typescript
// Option 1: Application-level locking with Redis
import Redis from "ioredis";

const redis = new Redis();

async function withSessionLock<T>(
  sessionId: string,
  fn: () => Promise<T>
): Promise<T> {
  const lockKey = `session-lock:${sessionId}`;
  const acquired = await redis.set(lockKey, "locked", "NX", "EX", 300);
  
  if (!acquired) {
    throw new Error("Session is in use by another client");
  }
  
  try {
    return await fn();
  } finally {
    await redis.del(lockKey);
  }
}

// Usage
await withSessionLock("user-123-task-456", async () => {
  const session = await client.resumeSession("user-123-task-456");
  await session.sendAndWait({ prompt: "Continue the task" });
});
```

## Сводка

| Функция                                                                                                  | Использование                                                    |
| -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| **Создать вособновляемую сессию**                                                                        | Предоставляйте свои собственные `sessionId`                      |
| **Сессия резюме**                                                                                        | `client.resumeSession(sessionId)`                                |
| **Резюме BYOK**                                                                                          | Повторное предоставление `provider` конфигурации                 |
| **Перечисление сеансов**                                                                                 | `client.listSessions(filter?)`                                   |
| **Отключение от активной сессии**                                                                        |                                                                  |
| `session.disconnect()`— выпускает ресурсы в памяти; Данные сессии на диске сохраняются для возобновления |                                                                  |
| **Навсегда удалить сессию**                                                                              |                                                                  |
| `client.deleteSession(sessionId)`—навсегда удаляет все данные сессии с диска; возобновить не может       |                                                                  |
| **Контейнерное развертывание**                                                                           | Монтирование `~/.copilot/session-state/` на постоянное хранилище |

## Дальнейшие действия

* [Сессионные хуки](/ru/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/hooks-overview) — Настройка поведения сессии с помощью хуков
* [Совместимость SDK и CLI](/ru/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/troubleshooting/compatibility) — сравнение функций SDK и CLI
* [Руководство по отладке](/ru/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/troubleshooting/debugging) - Проблемы с диагностикой сессии