# Метрики использования и выставления счетов

В этом руководстве показано, как считывать счетчики маркеров, использование контекстного окна, стоимость кредита ИИ и квоту учетной записи из приложения пакета SDK для Copilot. Примеры показаны для TypeScript, Python, Go, .NET, Java и Rust.

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

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

> \[!TIP]
> Каждый пример функционально эквивалентен для разных языков. Фрагмент кода TypeScript по умолчанию развернут; Выберите язык из свертых блоков, чтобы увидеть ту же логику в этом пакете SDK.

## Overview

Пакет SDK предоставляет данные об использовании с помощью двух дополнительных механизмов:

* **События сеанса**: временные события, которые среда выполнения выдает в качестве выполнения поворота. Подпишитесь на эти данные в режиме реального времени для каждого вызова API.
* **Методы RPC: вызовы** запроса и ответа, которые вы выполняете по запросу. Используйте их для моментального снимка накопленных итогов или поиска квоты на уровне учетной записи.

В приведенной ниже таблице сопоставляется каждый сигнал с API, предоставляющим его.

| Сигнал                                            | API                            | Объем   | Type  |
| ------------------------------------------------- | ------------------------------ | ------- | ----- |
| Количество маркеров для каждого вызова            | событие `assistant.usage`      | Session | Event |
| Использование контекстного окна                   | событие `session.usage_info`   | Session | Event |
| Разбивка контекстного окна (по запросу)           | `session.metadata.contextInfo` | Session | RPC   |
| Совокупные суммы кредитов и маркеров ИИ           | `session.usage.getMetrics`     | Session | RPC   |
| Цены на кредиты на ИИ для модели                  | `models.list`                  | Сервер  | RPC   |
| Квота учетной записи и взаимодействие с премиумом | `account.getQuota`             | Сервер  | RPC   |

> \[!NOTE]
> `session.usage.getMetrics`, `session.metadata.contextInfo`и `session.metadata.recomputeContextTokens` помечены экспериментальными в созданной поверхности RPC. В .NET они вызывают экспериментальную `GHCP001` диагностику, которая подавляется с помощью `#pragma warning disable GHCP001` или уровня `<NoWarn>GHCP001</NoWarn>`проекта. Закрепление пакета SDK и среды выполнения cli Copilot, если приложение зависит от них.

В приведенных ниже таблицах полей перечислены только поля, используемые в примерах на этой странице. Полный, всегда текущий справочник по полю — это созданные типы ПАКЕТА SDK, а также [События потоковых сессий](/ru/copilot/how-tos/copilot-sdk/features/streaming-events), который повторно создается из схемы CLI на каждом ударе зависимостей. Относиться к ним как к источнику истины и этой странице в качестве ориентированного на задачи руководства.

## Количество маркеров для каждого вызова

Событие `assistant.usage` создается один раз для каждого вызова API модели в свою очередь (включая вызовы, сделанные вложенными агентами). Он содержит количество маркеров и умножение выставления счетов для этого одного вызова.

В приведенном ниже примере используются эти поля. Полный список см. в разделе [События потоковых сессий](/ru/copilot/how-tos/copilot-sdk/features/streaming-events#assistantusage) , включая кэш, причины, задержку и поля трассировки.

| Поле           | Type     | Description                                                     |
| -------------- | -------- | --------------------------------------------------------------- |
| `model`        | `string` | Идентификатор модели для этого вызова                           |
| `inputTokens`  | `number` | Расходуемые входные токены                                      |
| `outputTokens` | `number` | Выпускные токены                                                |
| `cost`         | `number` | Умножение запросов уровня "Премиум", примененное к этому вызову |

> \[!TIP]
> `assistant.usage` является эфемерным, поэтому он поставляется в реальном времени, но не воспроизводился при возобновлении сеанса. Чтобы прочитать накопленные итоговые итоги после факта, вызов `session.usage.getMetrics` (см. [сведения о накопленных кредитах и токенах ИИ](#accumulated-ai-credit-and-token-totals)).

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
session.on("assistant.usage", (event) => {
    const { model, inputTokens, outputTokens, cost } = event.data;
    console.log(
        `${model}: in=${inputTokens ?? 0} out=${outputTokens ?? 0} cost=${cost ?? 0}`,
    );
});
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
def on_usage(event):
    if event.type == SessionEventType.ASSISTANT_USAGE:
        data = event.data
        print(f"{data.model}: in={data.input_tokens or 0} out={data.output_tokens or 0} cost={data.cost or 0}")

session.on(on_usage)
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
session.On(func(event copilot.SessionEvent) {
    d, ok := event.Data.(*copilot.AssistantUsageData)
    if !ok {
        return
    }
    in, out, cost := int64(0), int64(0), float64(0)
    if d.InputTokens != nil {
        in = *d.InputTokens
    }
    if d.OutputTokens != nil {
        out = *d.OutputTokens
    }
    if d.Cost != nil {
        cost = *d.Cost
    }
    fmt.Printf("%s: in=%d out=%d cost=%g\n", d.Model, in, out, cost)
})
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
session.On<AssistantUsageEvent>(evt =>
{
    var data = evt.Data;
    Console.WriteLine(
        $"{data.Model}: in={data.InputTokens ?? 0} out={data.OutputTokens ?? 0} cost={data.Cost ?? 0}");
});
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
session.on(AssistantUsageEvent.class, event -> {
    var data = event.getData();
    long in = data.inputTokens() != null ? data.inputTokens() : 0;
    long out = data.outputTokens() != null ? data.outputTokens() : 0;
    double cost = data.cost() != null ? data.cost() : 0.0;
    System.out.printf("%s: in=%d out=%d cost=%s%n", data.model(), in, out, cost);
});
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::session_events::AssistantUsageData;

let mut events = session.subscribe();
while let Ok(event) = events.recv().await {
    if event.event_type == "assistant.usage" {
        if let Some(data) = event.typed_data::<AssistantUsageData>() {
            println!(
                "{}: in={} out={} cost={}",
                data.model,
                data.input_tokens.unwrap_or(0),
                data.output_tokens.unwrap_or(0),
                data.cost.unwrap_or(0.0),
            );
        }
    }
}
```

</div>

</div>

## Использование контекстного окна

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

### Динамические обновления с помощью `session.usage_info`

Среда выполнения выдает `session.usage_info` событие при изменении размера контекстного окна. Пример использования `currentTokens` и `tokenLimit`; см. в разделе [События потоковых сессий](/ru/copilot/how-tos/copilot-sdk/features/streaming-events#sessionusage_info) для полной полезных данных.

| Поле            | Type     | Description                                                  |
| --------------- | -------- | ------------------------------------------------------------ |
| `currentTokens` | `number` | Маркеры в настоящее время в окне контекста                   |
| `tokenLimit`    | `number` | Максимальное количество токенов для контекстного окна модели |

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
session.on("session.usage_info", (event) => {
    const { currentTokens, tokenLimit } = event.data;
    const pct = Math.round((currentTokens / tokenLimit) * 100);
    console.log(`Context: ${currentTokens}/${tokenLimit} (${pct}%)`);
});
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
def on_usage_info(event):
    if event.type == SessionEventType.SESSION_USAGE_INFO:
        data = event.data
        pct = round(data.current_tokens / data.token_limit * 100)
        print(f"Context: {data.current_tokens}/{data.token_limit} ({pct}%)")

session.on(on_usage_info)
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
session.On(func(event copilot.SessionEvent) {
    d, ok := event.Data.(*copilot.SessionUsageInfoData)
    if !ok {
        return
    }
    pct := int(float64(d.CurrentTokens) / float64(d.TokenLimit) * 100)
    fmt.Printf("Context: %d/%d (%d%%)\n", d.CurrentTokens, d.TokenLimit, pct)
})
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
session.On<SessionUsageInfoEvent>(evt =>
{
    var pct = (int)Math.Round((double)evt.Data.CurrentTokens / evt.Data.TokenLimit * 100);
    Console.WriteLine($"Context: {evt.Data.CurrentTokens}/{evt.Data.TokenLimit} ({pct}%)");
});
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
session.on(SessionUsageInfoEvent.class, event -> {
    var data = event.getData();
    long pct = Math.round((double) data.currentTokens() / data.tokenLimit() * 100);
    System.out.printf("Context: %d/%d (%d%%)%n", data.currentTokens(), data.tokenLimit(), pct);
});
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::session_events::SessionUsageInfoData;

let mut events = session.subscribe();
while let Ok(event) = events.recv().await {
    if event.event_type == "session.usage_info" {
        if let Some(data) = event.typed_data::<SessionUsageInfoData>() {
            let pct = (data.current_tokens as f64 / data.token_limit as f64 * 100.0) as i64;
            println!("Context: {}/{} ({}%)", data.current_tokens, data.token_limit, pct);
        }
    }
}
```

</div>

</div>

### Разбивка по запросу с `session.metadata.contextInfo`

События срабатывает только при изменении контекста. Чтобы прочитать текущую разбивку в любой момент( например, сразу после возобновления сеанса— вызов `session.metadata.contextInfo`. Передайте для `0` использования среды выполнения по умолчанию; передайте `promptTokenLimit``0` значение`outputTokenLimit`, если значение неизвестно.

`contextInfo` Результат не `null` будет инициализирован до инициализации сеанса (системный запрос и метаданные инструмента были кэшированы). Он разбивает итог вниз `systemTokens`на , `conversationTokens`и `toolDefinitionsTokens`, наряду с `promptTokenLimit`.

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
const { contextInfo } = await session.rpc.metadata.contextInfo({
    promptTokenLimit: 0,
    outputTokenLimit: 0,
});

if (contextInfo) {
    console.log(
        `Total ${contextInfo.totalTokens}/${contextInfo.promptTokenLimit} ` +
            `(system=${contextInfo.systemTokens}, conversation=${contextInfo.conversationTokens})`,
    );
}
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
result = await session.rpc.metadata.context_info(
    MetadataContextInfoRequest(prompt_token_limit=0, output_token_limit=0)
)
info = result.context_info

if info is not None:
    print(
        f"Total {info.total_tokens}/{info.prompt_token_limit} "
        f"(system={info.system_tokens}, conversation={info.conversation_tokens})"
    )
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
result, _ := session.RPC.Metadata.ContextInfo(ctx, &rpc.MetadataContextInfoRequest{
    PromptTokenLimit: 0,
    OutputTokenLimit: 0,
})

if info := result.ContextInfo; info != nil {
    fmt.Printf("Total %d/%d (system=%d, conversation=%d)\n",
        info.TotalTokens, info.PromptTokenLimit, info.SystemTokens, info.ConversationTokens)
}
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
var result = await session.Rpc.Metadata.ContextInfoAsync(promptTokenLimit: 0, outputTokenLimit: 0);
var info = result.ContextInfo;

if (info is not null)
{
    Console.WriteLine(
        $"Total {info.TotalTokens}/{info.PromptTokenLimit} " +
        $"(system={info.SystemTokens}, conversation={info.ConversationTokens})");
}
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
var result = session.getRpc().metadata
    .contextInfo(new SessionMetadataContextInfoParams(null, 0L, 0L, null))
    .join();
var info = result.contextInfo();

if (info != null) {
    System.out.printf("Total %d/%d (system=%d, conversation=%d)%n",
        info.totalTokens(), info.promptTokenLimit(), info.systemTokens(), info.conversationTokens());
}
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::rpc::MetadataContextInfoRequest;

let result = session
    .rpc()
    .metadata()
    .context_info(MetadataContextInfoRequest {
        prompt_token_limit: 0,
        output_token_limit: 0,
        selected_model: None,
    })
    .await?;

if let Some(info) = result.context_info {
    println!(
        "Total {}/{} (system={}, conversation={})",
        info.total_tokens, info.prompt_token_limit, info.system_tokens, info.conversation_tokens,
    );
}
```

</div>

</div>

## Совокупные суммы кредитов и маркеров ИИ

`session.usage.getMetrics` возвращает итоги выполнения для всего сеанса в одном вызове. Это самый чистый способ чтения стоимости кредита ИИ, так как он агрегирует каждый вызов API (основной агент и вложенные агенты) для вас.

В примере используются приведенные ниже поля. Созданный `UsageGetMetricsResult` тип является полной ссылкой.

| Поле                      | Type                          | Description                                                                                       |
| ------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------- |
| `totalNanoAiu`            | `number`                      | Стоимость кредита на уровне сеанса ИИ в единицах nano-AI                                          |
| `totalPremiumRequestCost` | `number`                      | Стоимость запроса уровня "Премиум" во всех моделях после умножения                                |
| `modelMetrics`            | `Record<string, ModelMetric>` | Разбивка на модель; каждая запись имеет `usage.inputTokens`, `usage.outputTokens`и `totalNanoAiu` |

> \[!NOTE]
> Стоимость сообщается в **единицах nano-AI** (это поле называется `totalNanoAiu`). Точное преобразование в кредиты ИИ и точное значение учета запросов уровня "Премиум" определяются GitHub Copilot выставлением счетов, а не пакетом SDK, рассматривать Copilot [документации](/ru/copilot/concepts/billing) по выставлению счетов GitHub как источник истины и проверить перед отображением валюты, например значений для пользователей. Примеры делятся на `1e9` удобство, следуя префиксу SI `nano` ; убедитесь, что это соответствует текущему выставлению счетов, прежде чем полагаться на него.
> `modelMetrics` Карты `tokenDetails` ключом являются строки среды выполнения (идентификаторы модели и имена типов маркеров), которые система типов SDK не проверяет.

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
const metrics = await session.rpc.usage.getMetrics();

const aiCredits = (metrics.totalNanoAiu ?? 0) / 1e9;
console.log(`AI credits used: ${aiCredits.toFixed(6)}`);
console.log(`Premium requests: ${metrics.totalPremiumRequestCost}`);

for (const [model, m] of Object.entries(metrics.modelMetrics)) {
    if (!m) continue;
    console.log(
        `${model}: in=${m.usage.inputTokens} out=${m.usage.outputTokens} ` +
            `nanoAiu=${m.totalNanoAiu ?? 0}`,
    );
}
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
metrics = await session.rpc.usage.get_metrics()

ai_credits = (metrics.total_nano_aiu or 0) / 1e9
print(f"AI credits used: {ai_credits:.6f}")
print(f"Premium requests: {metrics.total_premium_request_cost}")

for model, m in metrics.model_metrics.items():
    print(f"{model}: in={m.usage.input_tokens} out={m.usage.output_tokens} nanoAiu={m.total_nano_aiu or 0}")
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
metrics, _ := session.RPC.Usage.GetMetrics(ctx)

aiCredits := float64(0)
if metrics.TotalNanoAiu != nil {
    aiCredits = *metrics.TotalNanoAiu / 1e9
}
fmt.Printf("AI credits used: %.6f\n", aiCredits)
fmt.Printf("Premium requests: %v\n", metrics.TotalPremiumRequestCost)

for model, m := range metrics.ModelMetrics {
    nanoAiu := float64(0)
    if m.TotalNanoAiu != nil {
        nanoAiu = *m.TotalNanoAiu
    }
    fmt.Printf("%s: in=%d out=%d nanoAiu=%v\n", model, m.Usage.InputTokens, m.Usage.OutputTokens, nanoAiu)
}
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
var metrics = await session.Rpc.Usage.GetMetricsAsync();

var aiCredits = (metrics.TotalNanoAiu ?? 0) / 1e9;
Console.WriteLine($"AI credits used: {aiCredits:F6}");
Console.WriteLine($"Premium requests: {metrics.TotalPremiumRequestCost}");

foreach (var (model, m) in metrics.ModelMetrics)
{
    Console.WriteLine(
        $"{model}: in={m.Usage.InputTokens} out={m.Usage.OutputTokens} nanoAiu={m.TotalNanoAiu ?? 0}");
}
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
var metrics = session.getRpc().usage.getMetrics().join();

double aiCredits = metrics.totalNanoAiu() != null ? metrics.totalNanoAiu() / 1e9 : 0;
System.out.printf("AI credits used: %.6f%n", aiCredits);
System.out.printf("Premium requests: %s%n", metrics.totalPremiumRequestCost());

metrics.modelMetrics().forEach((model, m) -> {
    double nanoAiu = m.totalNanoAiu() != null ? m.totalNanoAiu() : 0;
    System.out.printf("%s: in=%d out=%d nanoAiu=%s%n",
        model, m.usage().inputTokens(), m.usage().outputTokens(), nanoAiu);
});
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
let metrics = session.rpc().usage().get_metrics().await?;

let ai_credits = metrics.total_nano_aiu.unwrap_or(0.0) / 1e9;
println!("AI credits used: {ai_credits:.6}");
println!("Premium requests: {}", metrics.total_premium_request_cost);

for (model, m) in &metrics.model_metrics {
    let nano_aiu = m.total_nano_aiu.unwrap_or(0.0);
    println!(
        "{model}: in={} out={} nanoAiu={nano_aiu}",
        m.usage.input_tokens, m.usage.output_tokens,
    );
}
```

</div>

</div>

## Цены на кредиты на ИИ для модели

Чтобы оценить стоимость перед выполнением поворота, ознакомьтесь с ценами на маркеры каждой модели.`models.list` Это вызов на уровне сервера на клиенте, поэтому он не нуждается в сеансе. Цены выражаются в кредитах ИИ на пакет токенов выставления счетов. Созданный тип перечисляет каждое `ModelBillingTokenPrices` поле, в том числе `cachePrice`.

| Поле                              | Type     | Description                                               |
| --------------------------------- | -------- | --------------------------------------------------------- |
| `billing.multiplier`              | `number` | Умножение затрат на премиум по отношению к базовой ставке |
| `billing.tokenPrices.inputPrice`  | `number` | Затраты на кредит ИИ на пакет входных маркеров            |
| `billing.tokenPrices.outputPrice` | `number` | Затраты на кредит ИИ на пакет выходных маркеров           |
| `billing.tokenPrices.batchSize`   | `number` | Количество маркеров на пакет выставления счетов           |

> \[!NOTE]
> Ценовые значения изменяются по мере развития планов и моделей. Прочитайте их во время выполнения, как показано ниже; никогда не жестко кодируйте числа в приложении.

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
const { models } = await client.rpc.models.list({});

for (const model of models) {
    const prices = model.billing?.tokenPrices;
    if (!prices) continue;
    console.log(
        `${model.id}: input=${prices.inputPrice} output=${prices.outputPrice} ` +
            `per ${prices.batchSize} tokens (x${model.billing?.multiplier ?? 1})`,
    );
}
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
result = await client.rpc.models.list(ModelsListRequest())

for model in result.models:
    prices = model.billing.token_prices if model.billing else None
    if prices is None:
        continue
    multiplier = model.billing.multiplier if model.billing else 1
    print(
        f"{model.id}: input={prices.input_price} output={prices.output_price} "
        f"per {prices.batch_size} tokens (x{multiplier})"
    )
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
list, _ := client.RPC.Models.List(ctx, &rpc.ModelsListRequest{})

for _, model := range list.Models {
    if model.Billing == nil || model.Billing.TokenPrices == nil {
        continue
    }
    prices := model.Billing.TokenPrices
    multiplier := 1.0
    if model.Billing.Multiplier != nil {
        multiplier = *model.Billing.Multiplier
    }
    in, out := 0.0, 0.0
    if prices.InputPrice != nil {
        in = *prices.InputPrice
    }
    if prices.OutputPrice != nil {
        out = *prices.OutputPrice
    }
    batch := int64(0)
    if prices.BatchSize != nil {
        batch = *prices.BatchSize
    }
    fmt.Printf("%s: input=%v output=%v per %d tokens (x%v)\n", model.ID, in, out, batch, multiplier)
}
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
var list = await client.Rpc.Models.ListAsync();

foreach (var model in list.Models)
{
    var prices = model.Billing?.TokenPrices;
    if (prices is null) continue;
    Console.WriteLine(
        $"{model.Id}: input={prices.InputPrice} output={prices.OutputPrice} " +
        $"per {prices.BatchSize} tokens (x{model.Billing?.Multiplier ?? 1})");
}
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
var list = client.getRpc().models.list().join();

for (var model : list.models()) {
    var billing = model.billing();
    if (billing == null || billing.tokenPrices() == null) {
        continue;
    }
    var prices = billing.tokenPrices();
    double multiplier = billing.multiplier() != null ? billing.multiplier() : 1;
    System.out.printf("%s: input=%s output=%s per %d tokens (x%s)%n",
        model.id(), prices.inputPrice(), prices.outputPrice(), prices.batchSize(), multiplier);
}
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
let list = client.rpc().models().list().await?;

for model in &list.models {
    let Some(billing) = &model.billing else { continue };
    let Some(prices) = &billing.token_prices else { continue };
    let multiplier = billing.multiplier.unwrap_or(1.0);
    println!(
        "{}: input={} output={} per {} tokens (x{multiplier})",
        model.id,
        prices.input_price.unwrap_or(0.0),
        prices.output_price.unwrap_or(0.0),
        prices.batch_size.unwrap_or(0),
    );
}
```

</div>

</div>

## Квота учетной записи и взаимодействие с премиумом

`account.getQuota`сообщает о оставшейся Copilot права пользователя, прошедшего проверку подлинности. Карта результата `quotaSnapshots` определяется типом квоты, как правило `premium_interactions`, `chat`и `completions`. Используйте его, чтобы показать пользователям, сколько их ежемесячных пособий осталось, или ворот работы, прежде чем они достигли предела.

В примере используются приведенные ниже поля; Созданный `AccountQuotaSnapshot` тип является полной ссылкой. Ключи `quotaSnapshots` — это строки среды выполнения, которые система типов ПАКЕТА SDK не проверяет, поэтому защита подстановок.

| Поле                  | Type     | Description                                              |
| --------------------- | -------- | -------------------------------------------------------- |
| `entitlementRequests` | `number` | Запросы, включенные в право, или `-1` для неограниченных |
| `usedRequests`        | `number` | Запросы, используемые до сих пор в этот период           |
| `remainingPercentage` | `number` | Процент оставшихся прав                                  |
| `resetDate`           | `string` | Дата ISO 8601 при сбросе квоты                           |

> \[!TIP]
> Чтобы считывать квоту для конкретного пользователя, а не глобального контекста проверки подлинности подключения (например, в серверной части с несколькими клиентами), передайте этот пользователь GitHub маркер`getQuota`. См [. раздел AUTOTITLE](/ru/copilot/how-tos/copilot-sdk/setup/multi-tenancy).

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
const { quotaSnapshots } = await client.rpc.account.getQuota({});
const premium = quotaSnapshots["premium_interactions"];

if (premium) {
    console.log(
        `Premium interactions: ${premium.usedRequests}/${premium.entitlementRequests} ` +
            `(${premium.remainingPercentage.toFixed(1)}% left, resets ${premium.resetDate ?? "n/a"})`,
    );
}
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
result = await client.rpc.account.get_quota(AccountGetQuotaRequest())
premium = result.quota_snapshots.get("premium_interactions")

if premium is not None:
    print(
        f"Premium interactions: {premium.used_requests}/{premium.entitlement_requests} "
        f"({premium.remaining_percentage:.1f}% left, resets {premium.reset_date or 'n/a'})"
    )
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
result, _ := client.RPC.Account.GetQuota(ctx, &rpc.AccountGetQuotaRequest{})

if premium, ok := result.QuotaSnapshots["premium_interactions"]; ok {
    resets := "n/a"
    if premium.ResetDate != nil {
        resets = premium.ResetDate.Format(time.RFC3339)
    }
    fmt.Printf("Premium interactions: %d/%d (%.1f%% left, resets %s)\n",
        premium.UsedRequests, premium.EntitlementRequests, premium.RemainingPercentage, resets)
}
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
var result = await client.Rpc.Account.GetQuotaAsync();

if (result.QuotaSnapshots.TryGetValue("premium_interactions", out var premium))
{
    Console.WriteLine(
        $"Premium interactions: {premium.UsedRequests}/{premium.EntitlementRequests} " +
        $"({premium.RemainingPercentage:F1}% left, resets {premium.ResetDate?.ToString("o") ?? "n/a"})");
}
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
var result = client.getRpc().account.getQuota().join();
var premium = result.quotaSnapshots().get("premium_interactions");

if (premium != null) {
    System.out.printf("Premium interactions: %d/%d (%.1f%% left, resets %s)%n",
        premium.usedRequests(), premium.entitlementRequests(),
        premium.remainingPercentage(), premium.resetDate());
}
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
let result = client.rpc().account().get_quota().await?;

if let Some(premium) = result.quota_snapshots.get("premium_interactions") {
    let resets = premium.reset_date.as_deref().unwrap_or("n/a");
    println!(
        "Premium interactions: {}/{} ({:.1}% left, resets {resets})",
        premium.used_requests, premium.entitlement_requests, premium.remaining_percentage,
    );
}
```

</div>

</div>

## Выбор правильного API

Используйте эту сводку, чтобы решить, какой API соответствует вашему варианту использования:

* **Отрисовка динамической стоимости или счетчика токенов в виде выполнения:** подписка на `assistant.usage` и `session.usage_info`.
* **Отображение итоговой суммы затрат после поворота или сеанса**: вызов `session.usage.getMetrics`.
* **Отображение использования контекстного окна при возобновлении перед любым новым поворотом**: вызов `session.metadata.contextInfo`.
* **Оценка стоимости перед выполнением работы**: чтение `models.list` цен токенов.
* **Предупреждайте пользователей, прежде чем они исчерпают свой план**: вызов `account.getQuota`.

## Дополнительные материалы

* [События потоковых сессий](/ru/copilot/how-tos/copilot-sdk/features/streaming-events): полный справочник по уровню поля для `assistant.usage`, `session.usage_info`и каждое другое событие сеанса
* [Observability](/ru/copilot/how-tos/copilot-sdk/observability): экспорт данных об использовании в OpenTelemetry для присвоения затрат
* [Мультиарендные и серверные развертывания](/ru/copilot/how-tos/copilot-sdk/setup/multi-tenancy): разрешение квоты и моделей на пользователя с помощью маркера GitHub