Skip to main content

Сохранение сессий в SDK Copilot

Пауза, возобновление и управление Второй пилот SDK сессиями при перезапусках и развертываниях.

Кто может использовать эту функцию?

GitHub Copilot SDK Доступна со всеми Copilot тарифными планами.

Примечание.

          Второй пилот SDK в настоящее время находится в Technical Preview. Функциональность и доступность могут меняться.

Когда вы создаёте сессию, Второй пилот SDK сохраняется история разговоров, состояние инструмента и контекст планирования. По умолчанию это состояние остаётся в памяти и исчезает после окончания сессии. С включенной устойчивостью вы можете возобновлять сессии при перезапусках, миграциях контейнеров или даже в разных клиентских инстансах. Для визуального обзора жизненного цикла состояния сессии см. репозиторийgithub/copilot-sdk.

ГосударствоЧто происходит
          **Создать** | 
          `sessionId` Назначено |

| Активный | Отправляйте подсказки, призывы к инструментам, ответы | | Приостановлено | Состояние сохранено на диск | | Резюме | Состояние, загруженное с диска |

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

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

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, Go и C# см. репозиторийgithub/copilot-sdk.

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

Вы можете продолжить сессию с того места, где она закончилась (через минуты, часы или даже дни). Для визуального обзора возобновления сессий между клиентами см. репозиторийgithub/copilot-sdk.

// 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, Go и C# см. репозиторийgithub/copilot-sdk.

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

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

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

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

// 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-ключи никогда не сохраняются на диске по соображениям безопасности.

// 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}/виде:

~/.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
ДанныеПродолжался?Примечания
История беседы
          ✅ Да | Полный поток сообщений |

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

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

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

РисунокПримерСценарий использования
          ❌
          `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

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

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 см. github/copilot-sdk репозиторий.

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

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

// 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" });

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

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);

Отключение от сессии

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

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 предоставляет идиоматические автоматические шаблоны очистки:

ЯзыкРисунокПример
          **TypeScript** | `Symbol.asyncDispose` | `await using session = await client.createSession(config);` |

| Python | async with диспетчер контекстов | async with await client.create_session(config) as session: | | C# | IAsyncDisposable | await using var session = await client.CreateSessionAsync(config); | | Вперед | defer | defer session.Disconnect() |

Примечание.

          `destroy()` была заменена и `disconnect()` будет удалена в одном из будущих релизов. Существующий код, использующий `destroy()` его, продолжит работать, но его следует перевести.

Постоянное удаление сессии

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

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

Совет

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

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

SDK имеет встроенный тайм-аут на 30 минут. Сессии без активности автоматически очищаются. Для визуального обзора потока тайм-аута в режиме простоя смотрите github/copilot-sdk репозиторий.

Слушайте случайные события, чтобы знать, когда работа заканчивается:

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

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

Лучше всего для: сильной изоляции, мульти-арендных сред, динамических сессий Azure. Для визуальной схемы см. репозиторийgithub/copilot-sdk.

Преимущества:

  • Полная изоляция
  • Простая безопасность
  • Простое масштабирование

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

Лучшие для: внутренних инструментов, доверенных сред, ограниченных ресурсами конфигураций. Для визуальной схемы см. репозиторийgithub/copilot-sdk.

Требования:

  • Уникальные идентификаторы сессий для каждого пользователя
  • Управление доступом на уровне приложений
  • Проверка идентификатора сессии перед операциями
// 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 Dynamic Sessions

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

# 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

Для визуальной схемы сохранения перезапуска контейнера см. репозиторийgithub/copilot-sdk.

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

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

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
  },
});

Примечание.

Пороги — это коэффициенты использования контекста (0,0–1,0), а не абсолютное количество токенов.

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

ОграничениеОписаниеСмягчение последствий
          **Повторная аутентификация BYOK** | Ключи API не сохраняются | Ключи от хранилища в вашем секретном менеджере; Указывайте в резюме |

| Регистрируемое хранилище | ~/.copilot/session-state/ должно быть записано | Монтировать постоянный объём в контейнеры | | Нет блокировки сессии | Параллельный доступ к одной и той же сессии не определен | Реализовать блокировку или очередь на уровне приложения | | Состояние инструмента не сохраняется | Состояние инструмента в памяти теряется | Проектируйте инструменты так, чтобы они были безсостоятельными или сохраняли своё собственное состояние |

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

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

// 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/ на постоянное хранилище |