> Усі статті WIKI Helomi: /wiki/llms.txt

# Розширення: свій розділ і свій агент кодом

Розширення — це ваш код усередині Helomi: **сторінка** (HTML + CSS + JavaScript) з'являється плиткою в «Власних розділах» (а перемикачем — пунктом лівого меню) і відкривається всередині програми, а **агент** (JavaScript, `function run(input)`) працює на сервері вручну, зі сторінки або за розкладом. Ядро Helomi ви не змінюєте: сторінка живе в ізольованому iframe, агент — в ізольованому рушії, і з даними обидва працюють лише через міст `sg`, тими самими маршрутами й правами, що й люди, тож сторінку не можна відрізнити від рідного розділу — **лише стиль NeoHelomi**.

## Можливості
- Найпростіше — файлом розділу: дані + сторінка + агент одним файлом, який ШІ пише за статтею [Розділ від ШІ](section-package.md), а людина перетягує в «+ Додати розділ» у «Власних розділах». Розширення — та сама сторінка й агент, що там встановлюються.
- Сторінка (адреса `/crm/x/ext/<slug>`) в ізольованому iframe, з мостом `sg.*`; плитка — у галереї «Власні розділи», у меню зліва — перемикачем «У меню зліва» на плитці.
- Якщо в розділу є свої дані (файл розділу з `data`), `sg.records.list/get/create/update` працює з ними без окремого дозволу.
- Читання будь-якого розділу CRM у межах прав людини, яка відкрила сторінку; запис — лише інструментами з дозволів розширення.
- Власне сховище розширення (JSON).
- Агент на сервері: вручну, зі сторінки або за розкладом (не частіше ніж раз на 5 хвилин), без мережі й файлів.
- Кожна зміна — нова версія з описом; повернення будь-якої версії.
- Розширення пише людина в налаштуваннях або ШІ з правом творця.

## 1. Налаштування
- **Людина** — «Налаштування → Типи даних → Розширення» (потрібен доступ до «Налаштувань CRM»): список розширень з автором («написав ШІ» для створених ШІ), «Нове розширення», редактор «Код сторінки» і «Код агента», «Плитка на сторінці /crm/x» (назва, іконка, опис), «Агент за розкладом, хвилин», «Що змінено», «Версії», «Запуски агента», «Інструкція для авторів (і для ШІ)» — ця стаття.
- **ШІ-співробітник** пише розширення лише з правом творця «Свої розширення (код)» у «Доступах» його пульта (видає адміністратор) і змінює лише свої розширення.
- Агент розширення працює від імені свого ШІ-співробітника («<назва> · агент»): його розділи, ліміти й «спочатку запитати» налаштовуються в пульті ШІ-співробітників.

## 2. Створити розширення
1. `extensions_guide` — ця інструкція і перелік інструментів.
2. `extensions_create` з `title`, `icon` (folder, clipboard, briefcase, calendar, tasks, documents, products, warehouse,
   deliveries, clients, structure, star, flag, bulb, gift, card, receipt, map, phone, mail, camera, scale, flask, spark, book), `page_html` і/або `agent_js`, `permissions` (інструменти ЗАПИСУ, які
   сторінці дозволено: напр. `["deals_create", "tasks_create"]`; читати сторінка може й так), `schedule_minutes`
   (агент за розкладом, не частіше ніж раз на 5 хв), `note` — що зроблено.
3. Відкрийте результат: `/crm/x/ext/<slug>`. Виправлення — `extensions_update` (кожна зміна — нова версія,
   `extensions_rollback` повертає попередню). Агента перевіряйте `extensions_run` — у відповіді результат, `logs` і помилка.

Людина робить те саме в «Налаштування → Типи даних → Розширення» → «Нове розширення» → «Створити»; відкрити сторінку — «Відкрити», плитка в «Власних розділах» або пункт меню зліва.

## 3. Стиль NeoHelomi — обов'язково

У сторінку вже підключено шрифт Onest, токени `--sg-*` і базові класи `sg-*`. **Не пишіть своїх кольорів, тіней, радіусів і рамок** — лише `var(--sg-…)` і класи нижче. Без смайликів (іконки — `sg.icon()`), без градієнтів, без темних панелей, без браузерних `alert/confirm` (є `sg.confirm`, `sg.toast`).

- **Шари.** Тло дає програма. Ваш вміст — у листі `.sg-sheet` (padding 20–24) → групи `.sg-group` (padding 14–16) →
  картки `.sg-card` / рядки `.sg-row`. Не більше трьох рівнів.
- **Шапка сторінки.** `<h1 class="sg-title">Назва</h1>` + `<span class="sg-muted">` підзаголовок; справа — одна головна
  дія `<button class="sg-btn sg-btn--black">`. **Чорне на екрані одне** (головна дія або активна вкладка).
- **Кнопки:** головна `.sg-btn.sg-btn--black`; другорядні `.sg-btn.sg-btn--white` або `.sg-btn.sg-btn--line`; дрібні —
  `.sg-btn--sm`. Кругла іконка-кнопка — `.sg-circ` (44 px) / `.sg-circ.sg-circ--sm` (34 px), всередині `sg.icon(...)`.
- **Вкладки й перемикачі:** `.sg-tabs` з `.sg-tab` (активна — `.is-active`, чорна пігулка); дрібний перемикач —
  `.sg-seg` з кнопками (`.is-active` біла).
- **Форми:** `.sg-field` → `<label>` + `.sg-input` / `select.sg-select` / `textarea.sg-input.sg-textarea`; прапорець —
  `input.sg-check`. Поля 40 px заввишки, пігулки.
- **Таблиці:** `.sg-table-wrap` → `table.sg-table` (щільні рядки, липка шапка). Числа — клас `.sg-num`.
- **Статуси:** `.sg-pill` + колір `--blue | --violet | --green | --yellow | --red | --gray`, дрібні — `.sg-pill--sm`.
- **Текст:** заголовки `.sg-title` / `.sg-h2` / `.sg-h3`; підпис групи `.sg-cap` (великі літери); другорядне `.sg-muted`,
  `.sg-faint`. Показники — `.sg-kpi` з `<small>` (підпис) і `<b>` (число).
- **Порожньо / завантаження:** `.sg-empty` з одним реченням, що робити; скелет — `.sg-skeleton`.
- **Телефон:** сторінка має працювати від 390 px: сітки — `grid-template-columns: repeat(auto-fill, minmax(240px, 1fr))`,
  на `@media (max-width: 768px)` рядки таблиць → картки, кнопки й поля на всю ширину, зони торкання ≥ 44 px.

Свій CSS — у `<style>` вашої сторінки, з префіксом класів (`.my-…`) і лише значеннями `var(--sg-…)`.

## 4. Міст `sg` (сторінка)

Усе асинхронне (`await`). Помилка → `throw Error` з реченням українською.

| виклик | що робить |
| --- | --- |
| `sg.user` | `{id, name, admin}` — хто відкрив сторінку |
| `sg.section` | `{slug, title, data_slug}` — цей розділ і його дані |
| `await sg.records.list({q, stage, per_page})` / `get(id)` / `meta()` / `kanban()` / `create({title, custom})` / `update(id, {stage_key, custom})` | записи даних свого розділу (файл розділу з `data`); запис — без окремого дозволу |
| `await sg.read("/api/crm/deals", {q: "Петро", per_page: 20})` | **читання будь-якого розділу CRM** у межах прав цієї людини: угоди, клієнти, задачі, склад, фінанси, документи, доставки, власні розділи (`/api/crm/x/<slug>`) |
| `await sg.call("deals_create", {values: {...}})` | інструмент (ті самі, що в ШІ): читання — завжди, запис — лише з `permissions` розширення |
| `await sg.data.get(col, key)` / `set(col, key, value)` / `list(col)` / `del(col, key)` | власне сховище розширення (JSON, до 64 КБ на запис) |
| `await sg.runAgent(input)` | запустити агента цього розширення → `{ok, result, error, logs}` |
| `sg.navigate("/crm/deals/123")` | перейти в розділ Helomi |
| `sg.toast("Збережено")` | коротке повідомлення внизу |
| `await sg.confirm("Видалити?")` | підтвердження в стилі програми → `true/false` |
| `sg.icon("plus", 18)` | SVG-рядок фірмової іконки (вставляйте в `innerHTML`) |

Інструменти й їхні аргументи — `extensions_guide.tools` або `describe_section`. Основні: `deals_list/get/create/update/ change_stage/close/add_item/add_note/add_task`, `clients_list/get/create/update/add_note`, `tasks_list/get/create/update`, `products_list/get`, `records_meta/list/get/create/update` (власні розділи). Обов'язкові поля, воронки, доступи й журнал діють так само, як для людини.

## 5. Агент (`agent_js`)

```js
function run(input) {               // input: {trigger: "schedule"} або те, що передала сторінка
  var deals = sg.call("deals_list", { overdue: true, per_page: 50 });
  deals.items.forEach(function (d) {
    sg.call("deals_add_task", { deal_id: d.id, values: { title: "Нагадати клієнту" } });
  });
  sg.data.set("stats", "last", { count: deals.items.length });
  sg.log("оброблено", deals.items.length);
  return { processed: deals.items.length };
}
```

У агента виклики **синхронні** (без `await`): `sg.call`, `sg.data.get/set/list/delete`, `sg.log`. Мережі, файлів, таймерів нема; 30 секунд і 300 викликів на прогін. Агент працює від імені свого ШІ-співробітника («<назва> · агент»): його розділи, ліміти й «спочатку запитати» (видалення, гроші, масові, відправки) — у пульті ШІ-співробітників. Розширень, агентів і розділів агент не створює.

## 6. Приклад сторінки

```html
<div class="sg-sheet my-page">
  <header class="my-head">
    <div><h1 class="sg-title">Прострочені угоди</h1><span class="sg-muted">де минув термін етапу</span></div>
    <button class="sg-btn sg-btn--black" id="run">Нагадати всім</button>
  </header>
  <div class="sg-group"><div class="sg-table-wrap"><table class="sg-table"><thead><tr><th>Угода</th><th>Клієнт</th><th class="sg-num">Сума</th></tr></thead>
    <tbody id="rows"><tr><td colspan="3" class="sg-empty">Завантаження…</td></tr></tbody></table></div></div>
</div>
<style>
  .my-page { padding: 24px; display: grid; gap: 14px; }
  .my-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
  @media (max-width: 768px) { .my-page { padding: 16px; } .my-head .sg-btn { width: 100%; } }
</style>
<script>
  async function load() {
    const res = await sg.read("/api/crm/deals", { overdue: true, per_page: 50 });
    document.getElementById("rows").innerHTML = res.items.length ? res.items.map((d) =>
      `<tr><td><a href="#" data-id="${d.id}">${d.title || "#" + d.id}</a></td><td>${d.client?.company || ""}</td>` +
      `<td class="sg-num">${d.total_amount ?? ""}</td></tr>`).join("") : `<tr><td colspan="3" class="sg-empty">Прострочених нема</td></tr>`;
  }
  document.addEventListener("click", (e) => { const a = e.target.closest("[data-id]"); if (a) { e.preventDefault(); sg.navigate("/crm/deals/" + a.dataset.id); } });
  document.getElementById("run").onclick = async () => { const r = await sg.runAgent({}); sg.toast(r.ok ? "Готово" : r.error); load(); };
  load();
</script>
```

## 7. Версії, відкат, запуск агента
- Кожне збереження — нова версія з приміткою «Що змінено»; «Версії» в налаштуваннях або `extensions_versions` показують історію, «повернути» — `extensions_rollback`.
- «Запустити агента» на сторінці розширення («Дії з розширенням») або в налаштуваннях; результат, журнал `sg.log` і помилка — у «Запуски агента» або у відповіді `extensions_run`.
- «Код і версії» в «⋮» сторінки веде до налаштувань розширення.

## Можливі помилки
| Що ви бачите | Чому | Що зробити |
| --- | --- | --- |
| «Розширенню потрібен код сторінки або агента» | Порожнє розширення | Додайте `page_html` або `agent_js` |
| «Код агента має оголосити function run(input) { … }» | Нема функції `run` | Оголосіть `function run(input)` |
| «Код сторінки довший за … символів» / «Код агента довший за … символів» | Ліміт 400 000 / 120 000 символів | Скоротіть код |
| «Розклад — не частіше ніж раз на 5 хвилин» | Замалий інтервал | Вкажіть 5 хвилин або більше |
| «Невідомий інструмент у дозволах: …» | Такого інструмента нема | Візьміть назву з `extensions_guide.tools` |
| «Іконку обирають з набору: …» | Іконка не з переліку | Виберіть іконку з переліку в розділі 2 |
| «Міст читає лише розділи CRM (/api/crm/…), довідку й каталог» | `sg.read` на інший шлях | Читайте лише `/api/crm/…` |
| «Запис сховища більший за 64000 символів» / «У сховищі розширення вже 20000 записів» | Ліміти сховища | Розбийте дані або приберіть старі записи |
| «Розширення пише ШІ з правом творця «Свої розширення» …» | ШІ без права творця | Попросіть адміністратора видати право |
| «Розширення налаштовує людина з доступом до «Налаштувань CRM»» | Людина без доступу | Попросіть адміністратора |

## Для ШІ-співробітників
Інструменти творця (потрібне право «Свої розширення (код)»):

| Інструмент | Що робить |
| --- | --- |
| `extensions_guide` | СПОЧАТКУ ПРОЧИТАЙТЕ: ця інструкція і перелік інструментів для `permissions` |
| `extensions_list` | Розширення організації (`made_by` — автор; змінювати можна лише свої) |
| `extensions_get` | Моє розширення з кодом сторінки й агента |
| `extensions_create` | Нове розширення: `title`, `icon`, `page_html`, `agent_js`, `schedule_minutes`, `permissions`, `note` |
| `extensions_update` | Змінити моє розширення (нова версія; `note` — що змінилося) |
| `extensions_versions` | Версії мого розширення |
| `extensions_rollback` | Повернути версію |
| `extensions_run` | Запустити агента: результат, `logs`, помилка |
| `extensions_delete` | Видалити моє розширення. **Спочатку запитати** (вид `delete`) |

Сторінки розширень відкривають люди; ШІ працює з даними через інструменти.

Чого не можна: ходити в інтернет зі сторінки (заборонено політикою безпеки), читати токени й паролі, змінювати ядро Helomi, налаштування організації, чужі розширення й агентів людей. Порушення стилю (свої кольори, смайлики, друге чорне) вважається помилкою — виправляйте наступною версією.

## Додаткова інформація
- Пов'язані статті: [Розділ від ШІ: файл розділу](section-package.md), [Власні розділи](custom-sections.md), ШІ-творець (`ai-creator.md`), ШІ-співробітники (`ai-employees.md`).
