---
metadata:
  - name: generator
    content: Diplodoc Platform v5.54.5
  - property: og:type
    content: article
  - property: article:section
    content: Платформа плагинов
  - property: og:title
    content: API Reference - plugin-sdk-core
  - property: article:tag
    content: Техническая инструкция
alternate:
  - https://yandex.ru/support/tracker/en/plugins/tools/sdk/core.md
  - https://yandex.ru/support/tracker/ru/plugins/tools/sdk/core.md
  - href: ru/plugins/tools/sdk/core.md
    type: text/markdown
    title: Markdown version
  - href: ../../../llms.txt
    type: text/markdown
    title: llms.txt
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.ru/support/tracker/ru/llms.txt


# API Reference - @weavix/tracker-plugin-sdk-core

## hostApi (HostApi) {#host-api}

API для взаимодействия с приложением Трекера: инициализация плагина, тема, язык, контекст слота, размер окна, уведомление о готовности.

Экспортируется singleton **`hostApi`**. Обычно используется внутри `TrackerPluginProvider` из пакета react. При необходимости можно вызывать напрямую.

### init() {#init}

Инициализирует плагин: читает параметры из URL, устанавливает связь с Трекером, при необходимости выполняет авто-ресайз. Вызывать один раз перед использованием остальных методов.

**Parameters:** `options?: HostInitOptions` — опции (например `autoResize`, по умолчанию `true`).

**Throws:** `Error` — если в URL нет обязательных параметров (slot, parentOrigin, id, elementId).

```typescript
import { hostApi } from "@weavix/tracker-plugin-sdk-core";

hostApi.init({ autoResize: true });
```

### getTheme() {#get-theme}

Возвращает текущую тему Трекера.

**Returns:** `Promise<Theme>`

```typescript
const theme = await hostApi.getTheme(); // 'light' | 'light-hc' | 'dark' | 'dark-hc' | 'system'
```

### getLanguage() {#get-language}

Возвращает текущий язык Трекера.

**Returns:** `Promise<string>` (например `'ru'`, `'en'`).

```typescript
const language = await hostApi.getLanguage();
```

### getContext() {#get-context}

Возвращает контекст слота, в котором запущен плагин. Уровень возвращаемых данных определяется параметром `contextLevel`, указанным для слота в `manifest.json`. Подробнее — в разделе [Уровни контекста слота](https://yandex.ru/support/tracker/ru/plugins/common.md#context-levels).

**Parameters:** `level: 'basic' | 'full'` (обязательный)

**Returns:**

- При `level: 'basic'` — `Promise<BasicContext>`, где `BasicContext = { entityId: string; entityMeta?: Record<string, string> }`
- При `level: 'full'` — `Promise<SlotContextMap[TSlot]>`

```typescript
// Базовый контекст (только идентификатор сущности)
// Требует contextLevel: 'basic' в manifest.json для данного слота
const basicContext = await hostApi.getContext("basic");
// basicContext.entityId — идентификатор текущей сущности
// basicContext.entityMeta — дополнительные метаданные (опционально)

// Полный контекст (все данные сущности)
// Требует contextLevel: 'full' в manifest.json для данного слота
const fullContext = await hostApi.getContext("full");
```

### updateContentSize() {#update-content-size}

Отправляет Трекеру запрос на изменение размеров окна плагина.

**Parameters:** `payload: ContentSizeUpdateRequest` (поля `height` и `width` - хотя бы одно должно присутствовать).

**Returns:** `Promise<…>`

```typescript
await hostApi.updateContentSize({ height: 500 }); // задает высоту окна плагина
await hostApi.updateContentSize({ width: 800 }); // задает ширину окна плагина
await hostApi.updateContentSize({ height: 500, width: 800 }); // задает высоту и ширину окна плагина
```

Ширина окна плагина применяется с учетом ограничений места встраивания.

### notifyReady() {#notifyReady}

Сообщает Трекеру, что плагин готов к работе.

**Returns:** `Promise<…>`

```typescript
await hostApi.notifyReady();
```

### getSlot() {#get-slot}

Возвращает текущий слот. Вызывать только после `init()`.

**Returns:** `TSlot` (ключ из SlotContextMap).

```typescript
const slot = hostApi.getSlot(); // например 'issue.action'
```

### disableAutoResize() {#disable-auto-resize}

Отключает автоматическое изменение размера контейнера по контенту.

```typescript
hostApi.disableAutoResize();
```

### close() {#close}

Закрытие плагина, если он показан во всплывающем окне

```typescript
hostApi.close();
```

{% note info "Передача данных" %}

Некоторые слоты поддерживают обработку данных, которые будут переданы в качестве аргумента метода `close`.
Точные типы и функциональность смотрите в документации по [конкретным точкам интеграции](https://yandex.ru/support/tracker/ru/plugins/slots/attachment-viewer-action.md).

{% endnote %}

### preventClose() {#preventClose}

Защищает плагин от случайного закрытия пользователем, например, по Esc или клику по крестику. Если установлен флаг `preventClose: true`, Трекер заблокирует закрытие до тех пор, пока флаг не будет сброшен. Работает только с плагинами, которые отображаются в модальном окне.

Используйте этот метод, чтобы предотвратить потерю несохраненных изменений.

```typescript
import { hostApi } from "@weavix/tracker-plugin-sdk-core";

// Блокируем закрытие, если есть несохраненные изменения
hostApi.preventClose({ preventClose: true });
```

**Parameters:** `{ preventClose: boolean }`

- `preventClose: true` — блокирует закрытие плагина пользователем
- `preventClose: false` — снимает блокировку

**Пример использования с React:**

```tsx
import { hostApi } from "@weavix/tracker-plugin-sdk-react";
import { useEffect, useState } from "react";

function MyEditor() {
    const [content, setContent] = useState("");
    const [saved, setSaved] = useState(true);

    const hasChanges = !saved;

    // Автоматически устанавливаем/снимаем блокировку при изменении состояния
    useEffect(() => {
        hostApi.preventClose({ preventClose: hasChanges });
    }, [hasChanges]);

    const handleSave = async () => {
        await saveContent(content);
        setSaved(true);
    };

    return (
        <div>
            <textarea
                value={content}
                onChange={(e) => {
                    setContent(e.target.value);
                    setSaved(false);
                }}
            />
            <button onClick={handleSave}>Сохранить</button>
        </div>
    );
}
```

{% note info "Важно" %}

- Не забывайте снимать блокировку (`preventClose: false`) после сохранения данных, иначе пользователь не сможет закрыть плагин.
- При принудительном закрытии, например при переходе на другой экран, Трекер может игнорировать блокировку.

{% endnote %}

## uiApi {#ui-api}

API для взаимодействия с пользовательским интерфейсом Трекера: показ уведомления, открытие попапов и т. п.

### Тосты (Toast notifications) {#toasts}

Плагины могут показывать toast-уведомления в интерфейсе Трекера через `uiApi.toaster`. API максимально приближен к `useToaster` из `@gravity-ui/uikit`.

{% note info "Permission" %}

В `manifest.json` нужно запросить `tracker:ui:toaster`:

```json
{
    "permissions": {
        "ui": ["toaster"]
    }
}
```

{% endnote %}

```typescript
import { uiApi } from "@weavix/tracker-plugin-sdk-core";

// Простой тост
uiApi.toaster.add({
    title: "Сохранено",
    theme: "success",
});

// Тост с текстовым содержимым и кастомным временем показа
uiApi.toaster.add({
    title: "Ошибка",
    theme: "danger",
    content: "Не удалось загрузить данные",
    autoHiding: 10000,
});

// Тост с кнопкой действия
uiApi.toaster.add({
    title: "Элемент удален",
    theme: "info",
    content: "QUEUE-123",
    actions: [
        {
            label: "Отменить",
            onClick: () => {
                // обработка нажатия
            },
        },
    ],
});
```

#### Параметры {#toasts-params}

| Параметр     | Тип                                            | По умолчанию | Описание                                                                      |
| ------------ | ---------------------------------------------- | ------------ | ----------------------------------------------------------------------------- |
| `title`      | `string`                                       | —            | Заголовок тоста (обязательный)                                                |
| `name`       | `string`                                       | auto         | Уникальный ключ для дедупликации. Генерируется автоматически, если не передан |
| `theme`      | `'success'` \| `'danger'` \| `'warning'` \| `'info'` | `'info'`     | Тема (цвет и иконка)                                                          |
| `content`    | `string`                                       | —            | Текстовое содержимое под заголовком                                           |
| `autoHiding` | `number`                                       | `5000`       | Время показа в мс (от 1000 до 30000)                                          |
| `isClosable` | `boolean`                                      | `true`       | Показывать кнопку закрытия                                                    |
| `actions`    | `ToastAction[]`                                | —            | Кнопки действий (макс. 2)                                                     |

**`ToastAction`:**

| Параметр  | Тип          | Описание                         |
| --------- | ------------ | -------------------------------- |
| `label`   | `string`     | Текст кнопки (макс. 50 символов) |
| `onClick` | `() => void` | Callback при нажатии             |

**Возвращает:** `Promise<{ name: string }>` — имя тоста (для идентификации).

**Ограничения:**

- `title` — макс. 200 символов
- `content` — макс. 500 символов
- `actions` — макс. 2 кнопки
- Rate limit — 5 тостов за 10 секунд на плагин

### Обработка ошибок {#error-handling}

```typescript
import {
    trackerApi,
    PluginActionError,
} from "@weavix/tracker-plugin-sdk-core";

try {
    await trackerApi.v3.get["/issues/{id}"]({ pathParams: { id: "BAD" } });
} catch (e) {
    if (e instanceof PluginActionError) {
        console.log(e.code, e.message, e.errorData);
    }
}
```

### Confirm Dialog {#confirm}

Плагин может показать модальный диалог подтверждения. Диалог рендерится **на стороне трекера**, а не внутри iframe, поэтому перекрывает всё приложение и фокусирует пользователя на принятии решения.

{% note info "Permission" %}

В `manifest.json` нужно запросить `tracker:ui:confirm`:

```json
{
    "permissions": {
        "ui": ["confirm"]
    }
}
```

{% endnote %}

```ts
import { uiApi } from "@weavix/tracker-plugin-sdk-core";

const { confirmed } = await uiApi.confirm.show({ message: "Уверены?" });
```

#### Параметры {#confirm-params}

| Параметр           | Тип                    | Лимит | По умолчанию    | Описание                   |
| ------------------ | ---------------------- | ----- | --------------- | -------------------------- |
| `title`            | `string`               | ≤ 200 | —               | Заголовок диалога          |
| `message`          | `string`               | ≤ 500 | — (обязательно) | Текст подтверждения        |
| `textButtonApply`  | `string`               | ≤ 50  | `"OK"`          | Текст кнопки подтверждения |
| `textButtonCancel` | `string`               | ≤ 50  | `"Отмена"`      | Текст кнопки отмены        |
| `theme`            | `'normal'` \| `'danger'` | —     | `'normal'`      | Тема кнопки apply          |

#### Лимиты и ошибки {#confirm-limits}

- **1 активный confirm на плагин.** Попытка открыть второй, пока висит первый — промис реджектится с `CONFIRM_ALREADY_OPEN`.
- **Максимум 5 одновременных диалогов в общей очереди** (от всех плагинов). При переполнении — `QUEUE_OVERFLOW`.
- **Таймаут 5 минут.** Если пользователь не отвечает, промис реджектится с `Request timeout`.
- **Закрытие iframe плагина**, то есть снятие с экрана, автоматически резолвит все повисшие confirm'ы этого плагина как `{ confirmed: false }`.
- **Esc / клик по крестику** — `{ confirmed: false }`.

### Навигация {#navigate}

Программное открытие ссылок

```typescript
uiApi.navigate({
    path: `/path`,
    params: { a: "testParam" },
    options: { newTab: true },
});
```

```typescript
type NavigateRequest = {
    path: string;
    params?: QueryParams;
    options?: {
        newTab?: boolean;
    };
};
```

{% note info "Обработка клика на ссылке" %}

1. Относительные ссылки и ссылки домена плагина =\> открываются в плагине

2. Внешние =\> прокидываются в трекер через uiApi.navigate =\>

    ссылки на трекер =\> открываются в текущей вкладке или в новом табе в зависимости от target="\_blank"
    внешние =\> всегда в новом табе

{% endnote %}

## trackerApi (TrackerApi) {#tracker-api}

Класс для вызова Tracker Public API через платформу по контракту `api.tracker.call`. Доступ к эндпоинтам — через типизированное API **v3**.

Описание методов и форматов ответов: [Common format](https://yandex.ru/support/tracker/ru/api-ref/common-format.md).

Экспортируется singleton **`trackerApi`**.

### v3 {#v3}

Объект с методами по HTTP: `get`, `post`, `put`, `patch`, `delete`. Ключи — пути эндпоинтов из OpenAPI (`@weavix/tracker-api-types`). При обращении по пути IDE показывает подсказки и JSDoc.

**Примеры:**

```typescript
import { trackerApi } from "@weavix/tracker-plugin-sdk-core";

// GET
const data = await trackerApi.v3.get["/issues/{id}"]({
    pathParams: { id: "QUEUE-123" },
    queryParams: { expand: ["COMMENTS"] },
});

// POST
await trackerApi.v3.post["/v2/issues"]({
    bodyParams: { queue: { key: "TASK" }, summary: "Новая задача" },
});

//POST with file
await trackerApi.v3.post["/attachments"]({
    bodyParams: { filename },
    file,
});
```

- **`v3.get[path](payload)`** — GET; `payload`: `pathParams`, опционально `queryParams`.
- **`v3.post[path](payload)`** / **put** / **patch** — в `payload` передается `bodyParams` (и при необходимости `pathParams`, `queryParams`).
- **`v3.delete[path](payload)`** — DELETE; `payload`: `pathParams`, опционально `queryParams`.

Во все запросы через `trackerApi.v3` в контракт уходит **version: 'v3'**.

## storageApi {#storageApi}

JSON-хранилище платформы уровня организации — `storageApi.orgShared.get` / `storageApi.orgShared.patch`. Полное описание методов, merge-семантики `patch`, версионирования и кодов ошибок — в разделе [Хранилище данных](https://yandex.ru/support/tracker/ru/plugins/storage.md).

```typescript
import { storageApi } from "@weavix/tracker-plugin-sdk-core";

const record = await storageApi.orgShared.get("settings");
await storageApi.orgShared.patch({
    bucket: "settings",
    data: { theme: "dark" },
});
```

## hostApi.externalApi\* {#externalApi}

Методы для обращения к внешним (не Tracker) HTTP API через прокси платформы с поддержкой OAuth-авторизации.

{% note warning "Политика безопасности" %}

Прямые HTTP-запросы из плагина (`fetch`, `XMLHttpRequest` и т.п.) **запрещены** — браузер заблокирует их из-за CSP и политики iframe. Все обращения к внешним API **обязаны** идти через `hostApi.externalApiCall()`.

{% endnote %}

Добавьте в `manifest.json` секцию `permissions.external` с перечнем разрешенных доменов:

```json
{
    "permissions": {
        "external": [
            {
                "domain": "api.example.com",
                "authorization": {
                    "type": "oauth",
                    "scopes": ["read", "write"],
                    "contextTypes": ["user"]
                }
            },
            {
                "domain": "cdn.example.com"
            }
        ]
    }
}
```

Поле `authorization` опционально — его можно опустить для доменов, не требующих авторизации, например для публичных CDN. Тип `"token"` используется для API-ключей и других не-OAuth токенов.


### externalApiCall() {#external-api-call}

Выполняет HTTP-запрос к внешнему API через прокси платформы. URL должен относиться к домену, разрешенному в `permissions.external`. Заголовки авторизации подставляет платформа.

**Parameters:**

| Параметр      | Тип                                               | По умолчанию | Описание                           |
| ------------- | ------------------------------------------------- | ------------ | ---------------------------------- |
| `url`         | `string`                                          | —            | Полный URL запроса (обязательный)  |
| `method`      | `'GET'` \| `'POST'` \| `'PUT'` \| `'PATCH'` \| `'DELETE'` | —            | HTTP-метод (обязательный)          |
| `headers`     | `Record<string, string>`                          | —            | Дополнительные заголовки           |
| `body`        | `Record<string, unknown>`                         | —            | Тело запроса                       |
| `timeoutMs`   | `number`                                          | —            | Таймаут запроса в миллисекундах    |
| `contextType` | `'user'` \| `'organization'`                        | —            | Контекст учетных данных для прокси |

**Returns:** `Promise<{ status: number; headers?: Record<string, string>; body?: Record<string, unknown> }>`

При ошибке прокси-запроса бросает `PluginActionError` с кодом `EXTERNAL_API_CALL_ERROR` (`1013`). Детали — в `e.errorData`.

```typescript
import {
    hostApi,
    PluginActionError,
    EXTERNAL_API_CALL_ERROR,
} from "@weavix/tracker-plugin-sdk-core";

// GET
const { status, body } = await hostApi.externalApiCall({
    url: "https://api.example.com/v1/items",
    method: "GET",
    contextType: "user",
});

// POST с телом и таймаутом
const result = await hostApi.externalApiCall({
    url: "https://api.example.com/v1/items",
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: { name: "New item", value: 42 },
    contextType: "organization",
    timeoutMs: 10000,
});

// Обработка ошибок
try {
    await hostApi.externalApiCall({
        url: "https://api.example.com/data",
        method: "GET",
    });
} catch (e) {
    if (e instanceof PluginActionError && e.code === EXTERNAL_API_CALL_ERROR) {
        console.error("Proxy error:", e.errorData);
    }
}
```

### externalApiAuthCheckAndRequest() {#external-api-auth-check-and-request}

Комбинирует проверку статуса авторизации и запрос credentials только для неаутентифицированных доменов. Если все домены уже аутентифицированы — сразу возвращает `{ success: true }` без диалога.

**Parameters:**

| Параметр      | Тип                        | По умолчанию       | Описание                     |
| ------------- | -------------------------- | ------------------ | ---------------------------- |
| `domains`     | `string[]`                 | все домены плагина | Домены для проверки          |
| `contextType` | `'user'` \| `'organization'` | —                  | Тип контекста учетных данных |

**Returns:** `Promise<{ success: boolean }>` — `false`, если пользователь закрыл диалог или истек таймаут (~5 минут).

```typescript
const { success } = await hostApi.externalApiAuthCheckAndRequest({
    domains: ["api.example.com"],
    contextType: "user",
});
if (!success) return;
```

### externalApiAuthGetStatus() {#external-api-auth-get-status}

Возвращает статус авторизации по доменам.

**Parameters:**

| Параметр      | Тип                        | По умолчанию       | Описание                     |
| ------------- | -------------------------- | ------------------ | ---------------------------- |
| `domains`     | `string[]`                 | все домены плагина | Домены для проверки          |
| `contextType` | `'user'` \| `'organization'` | —                  | Тип контекста учетных данных |

**Returns:** `Promise<{ domains: Array<{ domain: string; contextType: AuthContextType; authenticated: boolean }> }>`

```typescript
const { domains } = await hostApi.externalApiAuthGetStatus({
    domains: ["api.example.com"],
    contextType: "user",
});
const isAuthed = domains.every((d) => d.authenticated);
```

### externalApiAuthRequest() {#external-api-auth-request}

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

**Parameters:**

| Параметр  | Тип                       | По умолчанию | Описание                           |
| --------- | ------------------------- | ------------ | ---------------------------------- |
| `domains` | `ExternalApiDomainInfo[]` | —            | Домены (обязательно, минимум один) |

`ExternalApiDomainInfo`:

| Поле           | Тип                                      | Описание                          |
| -------------- | ---------------------------------------- | --------------------------------- |
| `domain`       | `string`                                 | Домен из манифеста                |
| `instructions` | `string | { en?: string; ru?: string }` | Подсказка в диалоге (опционально) |

**Returns:** `Promise<{ success: boolean }>` — `false`, если пользователь закрыл диалог.

```typescript
await hostApi.externalApiAuthRequest({
    domains: [
        {
            domain: "api.example.com",
            instructions: { ru: "Войдите в Example", en: "Sign in to Example" },
        },
    ],
});
```

### externalApiAuthRevoke() {#external-api-auth-revoke}

Отзывает сохраненную авторизацию для указанных доменов.

**Parameters:**

| Параметр      | Тип                        | По умолчанию | Описание                                      |
| ------------- | -------------------------- | ------------ | --------------------------------------------- |
| `domains`     | `string[]`                 | —            | Домены для отзыва (обязательно, минимум один) |
| `contextType` | `'user'` \| `'organization'` | —            | Тип контекста учетных данных                  |

**Returns:** `Promise<{ success: boolean }>`

```typescript
await hostApi.externalApiAuthRevoke({
    domains: ["api.example.com"],
    contextType: "user",
});
```

## Types {#types}

### TrackerApiInitOptions {#tracker-api-init-options}

Опции при создании экземпляра TrackerApi, если используется не singleton. Сейчас из core экспортируется только `trackerApi`, опции не передаются.

```typescript
interface TrackerApiInitOptions {
    apiVersion?: string;
}
```

### TrackerApiCallOptions {#tracker-api-call-options}

Параметры вызова эндпоинта в v3: `pathParams`, `queryParams`, `bodyParams`.

```typescript
interface TrackerApiCallOptions {
    pathParams?: Record<string, string>;
    queryParams?: Record<string, unknown>;
    bodyParams?: Record<string, unknown>;
}
```

### TrackerApiV3 {#tracker-api-v3}

Тип объекта `trackerApi.v3`: методы get/post/put/patch/delete с типизированными путями из `@weavix/tracker-api-types`.

### Theme {#theme}

Тип темы оформления Трекера.

```typescript
type Theme = "light" | "light-hc" | "dark" | "dark-hc" | "system";
```

### SlotContextMap {#slot-context-map}

Маппинг имен слотов на типы **полного** контекста (`level: 'full'`). Например, слот `issue.action` дает контекст типа `Issue`. Типы контекста — Issue и другие — задаются пакетом `@weavix/tracker-api-types`.

При `level: 'basic'` вместо полного объекта сущности возвращается `BasicContext`:

```typescript
type BasicContext = {
    /** Идентификатор текущей сущности */
    entityId: string;
    /** Дополнительная базовая информация.
     *  Например, для комментария содержит идентификатор родительского тикета. */
    entityMeta?: Record<string, string>;
};

// Базовый контекст: только entityId и entityMeta
const basicContext = await hostApi.getContext("basic");
// basicContext.entityId — идентификатор сущности

// Полный контекст: для слота 'issue.action' вернет Issue
// Требует contextLevel: 'full' в manifest.json
const fullContext = await hostApi.getContext("full");
```

### ContentSizeUpdateRequest {#content-size-update-request}

Запрос на изменение размера контента плагина.

```typescript
type ContentSizeUpdateRequest = { height?: number };
```

### HostInitOptions {#host-init-options}

Опции инициализации взаимодействия с Трекером, передаются в `hostApi.init()`.

```typescript
interface HostInitOptions {
    /** Авто-ресайз по контенту, по умолчанию true */
    autoResize?: boolean;
}
```

## Коды ошибок API {#codeErrors}

При вызовах методов платформа может вернуть ошибку с кодом. Константы экспортируются из пакета:

```typescript
import {
    EXTERNAL_API_CALL_ERROR,
    METHOD_NOT_SUPPORTED,
    MISSING_REQUIRED_SCOPE,
    PLUGIN_ID_IS_NOT_CORRECT,
    PLUGIN_ID_OR_SLOT_NOT_PROVIDED,
    UNKNOWN_ERROR,
    VALIDATION_ERROR,
} from "@weavix/tracker-plugin-sdk-core";
```

| Константа                        | Код  | Описание                                                              |
| -------------------------------- | ---- | --------------------------------------------------------------------- |
| `PLUGIN_ID_OR_SLOT_NOT_PROVIDED` | 1000 | Не переданы обязательные параметры инициализации плагина.             |
| `PLUGIN_ID_IS_NOT_CORRECT`       | 1001 | Неверный или несовпадающий pluginId.                                  |
| `VALIDATION_ERROR`               | 1002 | Ошибка валидации запроса.                                             |
| `METHOD_NOT_SUPPORTED`           | 1003 | Метод не поддерживается.                                              |
| `MISSING_REQUIRED_SCOPE`         | 1004 | Недостаточно прав (scope).                                            |
| `EXTERNAL_API_CALL_ERROR`        | 1013 | Ошибка при выполнении HTTP-запроса через `hostApi.externalApiCall()`. |
| `UNKNOWN_ERROR`                  | 6666 | Неизвестная ошибка.                                                   |

## Utils {#utils}

### getLocalizedString() {#get-localized-string}

Возвращает локализованную строку по коду языка. Тип `LocalizedString` экспортируется из `@weavix/tracker-api-types`, реэкспортируется из core.

```typescript
function getLocalizedString(
    value: LocalizedString,
    language: string,
    fallbackLanguage?: string,
): string;
```

### getField() {#get-field}

Извлекает значение из объекта по точечному пути (dot notation).

```typescript
function getField<T = unknown>(
    obj: Record<string, unknown>,
    path: string,
    defaultValue?: T,
): T | undefined;
```

## Handlers {#handlers}

Экспортируются **getHandler**, **setHandler**, типы **HandlerFunction**, **Handlers**, **HttpMethod** — для регистрации обработчиков запросов со стороны Трекера. См. контракт и слоты.

## Complete Example {#complete-example}

```typescript
import {
    hostApi,
    trackerApi,
    getField,
    type Theme,
} from "@weavix/tracker-plugin-sdk-core";

// Инициализация обычно выполняется в TrackerPluginProvider (react)
hostApi.init({ autoResize: true });

const theme: Theme = await hostApi.getTheme();
const language = await hostApi.getLanguage();
const context = await hostApi.getContext();

// Вызов Tracker API v3 (в payload уходит version: 'v3')
const issue = await trackerApi.v3.get["/issues/{id}"]({
    pathParams: { id: "KEY-1" },
    queryParams: { expand: ["COMMENTS"] },
});

const summary = getField<string>(issue, "summary", "Без названия");

await hostApi.notifyReady();
```

Типы запросов/ответов эндпоинтов (Issue, типы для создания задач, очередей и т.д.) задаются пакетом **@weavix/tracker-api-types**.
