# Референца SDK-а

Комплетан API пакета @beeuni/sdk — методе клијента, модули, потези и дистрибуција.

Canonical page: https://beeuni.ai/docs/sr/sdk/reference

Ова страница представља комплетан API интерфејс `@beeuni/sdk`: све методе клијента,
модуле независне од радног оквира, помоћне функције за потезе и начин дистрибуције пакета. Користите
[SDK](/docs/sr/sdk) за почетак и [Сесије](/docs/sr/sdk/sessions) за детаљан опис
животног циклуса сесије.

<a id="the-client"></a>

## Клијент

`createBeeuni(config)` враћа једног клијента. Свака метода је типизован позив
платформског API-ја. Референце `project(id)` и `session(pid, sid)` везују идентификаторе
тако да их никада не понављате.

```ts
const beeuni = createBeeuni({ backendUrl, getToken });

beeuni.accounts; // account / team operations
beeuni.accountInvites; // invite accept/decline by token alone
beeuni.projects; // top-level project operations
beeuni.connectors; // Connector calls scoped by an agent-minted token
beeuni.connector(slug); // one connector in the token's scope → see p.connector(slug)
beeuni.project(id); // id-bound project handle
beeuni.session(pid, sid); // id-bound session handle → see Sessions
beeuni.github; // GitHub App install + repo linking (account-scoped)
beeuni.gitBackend; // the instance git backend ("Beeuni managed")
beeuni.billing; // credits, subscription, tier, transactions
beeuni.sandboxShares; // public share links for a sandbox port
beeuni.connectStatus; // easy-connect status
beeuni.marketplace; // public marketplace catalog
beeuni.validateToken; // pasted-API-key check
beeuni.config; // platform config in effect
beeuni.runtime(); // runtime REST compatibility client
```

<a id="accounts--beeuniaccounts"></a>

### Налози — `beeuni.accounts`

| метода | намена |
| --- | --- |
| `list()` · `get(accountId)` | налози којима припадате · један налог |
| `create({ name })` · `updateName(accountId, name)` | креирање · преименовање налога |
| `branding.get(accountId)` · `branding.update(accountId, { app_name })` · `branding.uploadAsset(accountId, kind, file)` · `branding.removeAsset(accountId, kind)` · `branding.reset(accountId)` | брендирање организације (Enterprise): сопствени логотип / икона / фавикон и назив производа; `kind` је `logo` · `icon` · `favicon`, или `logo_dark` · `icon_dark` · `favicon_dark` за варијанту са тамном шемом |
| `members(accountId)` · `invite(accountId, input)` | листа чланова · позивање једног члана |
| `updateMemberRole(accountId, userId, role)` · `removeMember(accountId, userId)` | додела улоге на налогу · уклањање члана |
| `invites(accountId)` | позиви на чекању |
| `cancelInvite(accountId, inviteId)` · `resendInvite(accountId, inviteId)` | отказивање · поновно слање позива на чекању |
| `leave(accountId)` | напуштање налога |

`accounts.tokens` издаје API кључеве ограничене на налог (`beeuni_pat_...`). Погледајте
[SDK аутентификација](/docs/sr/accounts#tokens) за комплетан модел токена.

| метода | намена |
| --- | --- |
| `tokens.list(accountId?, options?)` | листа API кључева — целог налога или само ваших уз `{ mine: true }` |
| `tokens.create(input)` | издавање једног — `{ accountId?, name, expiresAt?, projectId? }` |
| `tokens.revoke(tokenId, accountId?)` | опозив једног |

`accounts.audit` је евиденција за реконструкцију у предузећу. Она обједињује аутентификоване
API захтеве са семантичким догађајима сесија, конектора, одобрења и рачунара.

| метода | намена |
| --- | --- |
| `audit.log(accountId, filters?)` | листа догађаја по пројекту, сесији, актеру, извору, исходу, захтеву, корелацији, ресурсу, радњи или времену |
| `audit.export(accountId, filters?)` | извоз истог филтрираног тока догађаја као CSV или JSONL |
| `audit.webhooks.list/create/update/remove(...)` | управљање потписаним SIEM веб-хуковима за централизовани ток |

Сваки догађај садржи `project_id`, `session_id`, `actor_type`, `source`, `outcome`,
`request_id`, `trace_id` и `correlation_id` када их радња достави.
API не чува тела захтева, промптове, тајне, акредитиве нити необрађене
аргументе конектора у централизованом догађају. Догађаји конектора могу да садрже
ограничен преглед аргумената који прикрива поља налик акредитивима и непрозирне податке.

<a id="access-assignments"></a>

### Доделе приступа

Beeuni има једну врсту записа о додели права: **доделу**. Она повезује једног субјекта (`user`,
`group`, `service_account` или `pending`) са једном улогом, у једном опсегу (`account`
или једном `project`), уз могуће сужавање на један објекат (`agent`, `skill`, `secret`,
`app` или `trigger`) и могуће укључивање `expires_at`. Групни приступ,
приступ по ресурсу и везивања прилагођених улога — све су то доделе. Погледајте
[Налози и приступ](/docs/sr/accounts#one-access-model) за опис модела.

Канонски REST интерфејс је:

| Метод + путања | Радња |
| --- | --- |
| `GET /v1/accounts/{accountId}/iam/assignments` | приказ додела, филтрираних по субјекту, опсегу, објекту или улози |
| `POST /v1/accounts/{accountId}/iam/assignments` | креирање једне доделе |
| `DELETE /v1/accounts/{accountId}/iam/assignments/{assignmentId}` | опозив једне доделе |
| `GET /v1/accounts/{accountId}/iam/permissions` | каталог дозвола, као подаци |
| `GET /v1/accounts/{accountId}/iam/roles` · `…/roles/{roleId}/permissions` | улоге · дозволе једне улоге |

SDK их излаже као `listAssignments`, `createAssignment`,
`revokeAssignment` и `listPermissions`. Ред каталога садржи `action`,
`scope_type`, `resource_type`, `delegable`, `description`, `area`, `level` и
`implies` — читајте га уместо да стрингове радњи уграђујете у код.

За доделу прилагођене улоге потребно је право `rbac` на налогу; без њега рута враћа
`402` са `code: "entitlement_required"`.

<a id="account-invites--beeuniaccountinvites"></a>

### Позивнице за налог — `beeuni.accountInvites`

Приступа им се само помоћу токена позивнице — позвана особа можда још није члан.

| метод | опис |
| --- | --- |
| `listMine()` | све позивнице на чекању које нису истекле и упућене су на вашу имејл адресу, са радним простором и свим пројектима којима дају приступ |
| `describe(inviteId)` · `accept(inviteId)` · `decline(inviteId)` | преглед · прихватање · одбијање позивнице |

<a id="projects--beeuniprojects"></a>

### Пројекти — `beeuni.projects`

| метод | опис |
| --- | --- |
| `list()` · `listForAccount(accountId)` | ваши пројекти · пројекти на налогу |
| `get(id)` · `detail(id)` | сажетак · сви детаљи |
| `create(input)` · `createRepo(input)` | из постојећег `repo_url` · ново празно GitHub спремиште |
| `provision(input)` | нови пројекат у новом спремишту којим управља Beeuni, попуњен почетним шаблоном — `{ name, account_id?, seed_starter?, starter_template?, marketplace_items?, source_item_id?, idempotency_key? }` |
| `update(id, input)` · `archive(id)` | ажурирање подешавања · архивирање |
| `llmCatalog(id)` · `modelPicker(id)` | потпун · сажет каталог модела за бирач |
| `sandboxTemplates(id)` · `sandboxHealth(id)` | шаблони за изградњу изолованог окружења · стање изградње |
| `sessions(id)` · `createSession(id, input?)` | приказ видљивих сесија · креирање сесије |

`provision` креира нови пројекат; не покреће изоловано окружење
постојећег пројекта. Уместо тога покрените сесију — погледајте [Сесије](/docs/sr/sdk/sessions).

Пошаљите `idempotency_key` када је могућ поновни покушај — поновно учитавање, друга картица,
истек времена након којег сте поновили захтев. `provision` при сваком позиву креира потпуно ново спремиште којим се управља, па
без кључа сви ти позиви креирају стварне дупликате пројеката. Користите исти кључ за сваки
покушај једног логичког креирања и поновљени позиви ће вратити пројекат који је први
покушај креирао (201, исти `project_id`, `push_token: null`). Кључ идентификује
покушај, а не тело захтева — поновна употреба кључа са другачијим `name` враћа први
пројекат и игнорише нову вредност, па генеришите нов кључ за свако засебно креирање.
Креирање другог пројекта са истим **називом** и без кључа и даље ради.

Поновљени позив који стигне док први још обезбеђује ресурсе добија `409` са
`code: 'provision_in_flight'` уместо `project_id` који тај позив још може да
поништи. Покушајте поново са истим кључем.

`project(id).sessions.list({ scope: 'project' })` је преглед животног циклуса за
позиваоца са дозволама управника пројекта. Додаје доступне сесије које су недоступне, загрејане или логички обрисане, са
метаподацима о власништву и стању извршавања. Оба опсега приказа изостављају све сесије које
позивалац не може да отвори.

`sessions.list` и `sessions.listPage` такође прихватају филтере хијерархије и
атрибуције. Без њих листа остаје равна и непромењена.

| опција | опис |
| --- | --- |
| `parent: 'root'` | Само сесије највишег нивоа. Сваки ред садржи `child_count`. |
| `parent: '<sessionId>'` | Подређене сесије те сесије, од најновије. |
| `startedBy: 'me' \| 'others' \| 'automated'` | Филтрирање по `initiator`, у односу на позиваоца. |
| `q` | Претрага без разликовања великих и малих слова по наслову, ознаци покретача, slug-у окидача и префиксу ID-а сесије, у свим сесијама које позивалац може да отвори. Уз `parent: 'root'`, коренска сесија која се подудара преко подређене има `search_match: 'child'`. |

Сваки ред сесије има `parent_session_id` и `initiator`
(`{ type: 'member' | 'trigger' | 'channel' | 'api' | 'system', id, label }`).
`initiator` наводи ко је покренуо цело извршавање; подређена сесија копира ту вредност од надређене.
`sessionParentId(session)` чита `parent_session_id`, а затим застарели
`metadata.spawned_by_session`. Курсор важи само за скуп филтера за који је
издат.

### GitHub — `beeuni.github`

Инсталација GitHub App-а и повезивање репозиторијума на нивоу налога, не пројекта.

| метод | опис |
| --- | --- |
| `getInstallation(accountId)` · `listInstallations(accountId)` | инсталација овог налога · инсталације којима корисник може да приступи |
| `saveInstallation(input)` · `deleteInstallation(accountId, installationId?)` | забележи · прекини везу са инсталацијом |
| `listLinkableInstallations(input)` | инсталације које овлашћени GitHub корисник може да повеже; свака ставка садржи `linked_to_other_accounts`, број других Beeuni налога који је имају — никада њихова имена |
| `listRepositories(accountId, installationId?)` · `listRepositoryBranches(...)` | репозиторијуми које инсталација може да види · гране и подразумевана грана на GitHub-у |
| `linkRepository(input)` | Увези репозиторијум као пројекат користећи овлашћену GitHub инсталацију. |
| `replaceProjectRepository({ project_id, repo_url, expected_repo_url, github_token })` | замени GitHub репозиторијум постојећег пројекта. Користи или `github_token` са приступом Contents за читање/писање, или `installation_id` уз привремени `github_user_token` да провериш администраторски приступ организацији и одобриш приступ само овом репозиторијуму преко GitHub App-а. `copy_shared_secrets_from_project_id` уз `copy_shared_secret_identifiers` копира изабране дељене тајне извршног окружења у истој трансакцији. Застарели `expected_repo_url` враћа 409. Стари репозиторијум остаје на GitHub-у. Нове сесије користе заменски репозиторијум; постојеће сесије задржавају своју преузету радну копију. |

Ова листа садржи само стварне везе налога. „Beeuni managed“ није једна од
њих — то је позадински систем инстанце описан испод.

<a id="instance-git-backend--beeunigitbackend"></a>

### Git позадински систем инстанце — `beeuni.gitBackend`

Један власник и акредитив за цело окружење, који се користе за репозиторијуме
којима управља Beeuni. То никада није веза налога и никада се не појављује у
`beeuni.github.listInstallations`.

| метод | опис |
| --- | --- |
| `get()` | `{ configured, kind: 'app' \| 'pat' \| null, owner }` — може да га чита сваки аутентификовани корисник; открива само корисничко име власника које сваки управљани `repo_url` већ садржи |

<a id="billing--beeunibilling"></a>

### Наплата — `beeuni.billing`

Чита кредите, претплату, план и историју трансакција. Користите Beeuni плаћање и управљање наплатом за плаћања и куповину кредита.

| метод | намена |
| --- | --- |
| `accountState(accountId?)` · `accountStateMinimal(accountId?)` | потпуно · минимално стање обрачуна |
| `transactions(params?)` · `transactionsSummary(params?)` | историја · збирни износи |
| `creditBreakdown(accountId?)` · `usageHistory(params?)` | стање кредита по извору · потрошња током времена |
| `sessionCosts.list(options?)` · `sessionCosts.get(sessionId, options?)` | записи о трошковима сесија са пагинацијом · једна детаљна евиденција сесије |
| `tierConfigurations()` | доступни нивои планова |
| `checkout.createSession(input)` · `checkout.confirmSession(sessionId, accountId?)` | **Застарело.** Одбијају са `ENDPOINT_RETIRED`. Биће уклоњени у следећој главној верзији. |
| `subscription.createPortalSession(...)` · `subscription.cancel(...)` · `subscription.reactivate(...)` | отварање корисничког портала · отказивање · поновна активација |
| `subscription.cancelScheduledChange(...)` · `prorationPreview(...)` | отказивање · преглед промене плана |
| `subscription.scheduleDowngrade(...)` | **Застарело.** Одбија са `ENDPOINT_RETIRED`. Промените план у корисничком порталу. Биће уклоњен у следећој главној верзији. |
| `credits.purchase(input)` · `credits.autoTopupSettings(...)` · `credits.configureAutoTopup(...)` | једнократна куповина · читање · подешавање аутоматске допуне |

`sessionCosts.list()` прихвата `accountId`, `projectId`, `limit` и `offset`.
Сваки ред обједињује коначни LLM трошак и обрачунати трошак рачунарских ресурса sandbox-а.
`sessionCosts.get()` додаје коришћење модела и евиденцију која разликује LLM и рачунарске ресурсе.
Листа укључује укупан износ за усаглашавање трошкова без сесије.

<a id="sandbox-shares--beeunisandboxshares"></a>

### Дељење sandbox-а — `beeuni.sandboxShares`

Јавни линкови за дељење једног изложеног порта sandbox-а. Важе за sandbox, не за
пројекат.

| метод | намена |
| --- | --- |
| `list(sandboxId)` | активни линкови за дељење |
| `create(input)` | креирање једног — `{ sandboxId, port, ttl?, label? }` |
| `revoke(sandboxId, token)` | опозив једног |

<a id="marketplace-catalog--beeunimarketplace"></a>

### Каталог тржишта — `beeuni.marketplace`

Прегледање јавног каталога, само за читање — разликује се од `project(id).marketplace`,
који инсталира ставку у пројекат.

| метод | намена |
| --- | --- |
| `items(options?)` · `item(id)` · `itemFile(id, path)` | прегледање · једна ставка · датотека унутар ставке |
| `marketplaces()` · `featured()` | сва · истакнута тржишта |
| `sources.list()` · `sources.add(input)` · `sources.remove(id)` | листа · додавање · уклањање извора |

<a id="notifications--beeuninotifications"></a>

### Обавештења — `beeuni.notifications`

Обавештења позиваоца, на свим налозима и пројектима. Свака пријављена
особа има једно пријемно сандуче, један запис о подешавањима и Web Push претплате за
своје прегледаче. Сваки метод захтева акредитиве особе: сервисни налог
добија `403`.

> **Обавештења су заставица функције**
>
> Beeuni уписује редове у пријемно сандуче и шаље Web Push обавештења и имејлове само за пројекте са
> укљученом заставицом `notification_center`. Подразумевано је искључена. `list()` изоставља редове
> из пројеката са искљученом заставицом. `session(pid, sid).watch()` и `.setWatch()`
> враћају `403` са `{ error, code: "feature_disabled", feature: "notification_center" }`
> док је искључена; користите `isFeatureDisabledError(error)` за гранање на основу њеног стања.
> Подешавања, Web Push претплате и токени уређаја везани су за особу и раде
> у оба случаја. Када је заставица искључена, телефон особе која је креирала сесију и даље добија push обавештење
> када се потез заврши, не успе, постави питање или затражи дозволу. Погледајте
> [Заставице функција](/docs/sr/feature-flags) и [Обавештења](/docs/sr/work/notifications).

```ts
const page = await beeuni.notifications.list({ limit: 20 });
await beeuni.notifications.markRead({ ids: [page.notifications[0].id] });
await beeuni.notifications.updatePreferences({ kinds: { turn_done: { push: false } } });
```

| метода | опис |
| --- | --- |
| `list({ limit?, before? }, { signal? })` | најновија страница: `{ notifications, unread_count, next_before }`. `limit` је од 1 до 50 (подразумевано 20). Проследите `next_before` као `before` за следећу страницу. Редови које позивалац више не може да види се изостављају. Неуспех не позива обрађивач грешака хоста. |
| `markRead({ ids })` · `markRead({ all: true })` · `markRead({ sessionId })` | означава од 1 до 100 редова, све редове или све редове једне сесије као прочитане. Мења само редове позиваоца. Враћа `{ updated, unread_count }`. |
| `preferences()` · `updatePreferences({ kinds })` | чита · мења избор push обавештења и е-поште по врсти. Враћа `{ kinds, email_available }`. Закрпа мења само врсте и канале које наводи. |
| `webPushPublicKey()` | `{ public_key }`: `applicationServerKey` за `pushManager.subscribe` |
| `registerWebPushSubscription({ endpoint, keys })` | испоручује push обавештења овом прегледачу. Захтева пријаву у прегледачу: лични токен добија `403`. Крајња тачка на непознатом push сервису добија `400`. |
| `unregisterWebPushSubscription(endpoint, { signal? })` | зауставља push обавештења овом прегледачу. Враћа `{ deleted }`. |
| `registerDeviceToken(input)` · `unregisterDeviceToken(token, { signal? })` | региструје · уклања Expo push токен нативне апликације |

Врсте (`InboxNotificationKind`, наведене у `INBOX_NOTIFICATION_KINDS`):

| врста | шаље се када | push | е-пошта (подразумевано) |
| --- | --- | --- | --- |
| `turn_done` | заврши се потез који сте покренули упитом или пратите | укључено | искључено |
| `turn_error` | тај потез се заврши грешком | укључено | укључено, у сажетку |
| `question` | агент постави питање | укључено | укључено, у сажетку |
| `permission` | агент затражи дозволу | укључено | искључено |
| `shared` | неко подели сесију са вама | укључено | укључено, у сажетку |
| `automation_failed` | аутоматизација коју пратите почне да отказује | укључено | укључено, одмах |
| `automation_recovered` | та аутоматизација поново ради | укључено | искључено |

`DEFAULT_NOTIFICATION_PREFERENCES` садржи ове подразумеване вредности. Ред у пријемном сандучету се
увек уписује; подешавања одређују само push обавештења и е-пошту. Е-порука са сажетком
наводи редове који су и даље непрочитани 15 минута након пристизања, уз највише један сажетак
на сат. Сакријте колону е-поште када је `email_available` `false`.

`url` сваког реда отвара његову тему. Његов упит `?notification=<id>` омогућава
страници да означи ред као прочитан.

Објекат сесије садржи праћење једне сесије за позиваоца:

| метода | опис |
| --- | --- |
| `session(pid, sid).watch()` | `{ watching }`: да ли позивалац добија обавештења о овој сесији |
| `session(pid, sid).setWatch(watching)` | `false` утишава сесију за позиваоца, `true` је поново прати. Слање упита сесији укључује њено праћење, али никада не поништава утишавање. |
| `session(pid, sid).presence({ tab_id, active, alerts? }, { keepalive? })` | закуп присуства ове картице. `alerts: true` означава да картица приказује сопствена обавештења: када је `notification_center` укључено, сервер прескаче телефон и Web Push само док се користи картица која приказује упозорења. Када је искључено, `alerts` се игнорише и свака присутна картица задржава push обавештења за телефон. `keepalive` омогућава да захтев траје и након затварања странице. Подразумевано: укључено за пријаву одсуства, искључено за пријаву присуства. `useSession` шаље `keepalive` само уз `presencePageExit`. |

<a id="the-project-handle--beeuniprojectid"></a>

### Објекат пројекта — `beeuni.project(id)`

Везује идентификатор пројекта; сваки подресурс је везан за њега.

```ts
const p = beeuni.project(projectId);
await p.detail();
await p.update({ name });
await p.llmCatalog();
```

| метод | намена |
| --- | --- |
| `get` · `detail` · `update` · `archive` | читање · сви детаљи · ажурирање · архивирање |
| `llmCatalog` · `modelPicker` · `sandboxHealth` | читање модела и изградњи sandbox окружења |
| `onboardingComplete` | означавање почетног подешавања пројекта као завршеног |
| `validateManifest(raw)` | провера манифеста `beeuni.yaml` (или старијег `beeuni.toml`) на серверу |
| `gitToken()` | издавање новог токена ограниченог опсега за git push (`409` за сопствени репозиторијум) |
| `setAgentScope(agentName, scope)` | постављање дозвољених тајни и конектора агента у манифесту — друго повезивање, не улога |

<a id="ptokens--project-scoped-api-keys"></a>

#### `p.tokens` — API кључеви ограничени на пројекат

Аутоматски се издају при креирању сесије као `BEEUNI_TOKEN`; могу се издати и ручно.

| метод | намена |
| --- | --- |
| `list()` | API кључеви пројекта |
| `create(input?)` | издавање новог кључа |
| `revoke(tokenId)` | опозив кључа |

<a id="psetuplinks--agent-minted-setup-links"></a>

#### `p.setupLinks` — везе за подешавање које издаје агент

Веза коју особа отвара да унесе тајну или повеже апликацију, без пуног
приступа пројекту.

| метод | намена |
| --- | --- |
| `requestSecret(input)` · `requestConnector(input)` | веза за прикупљање тајне · повезивање апликације |

<a id="papps--apps-releases-machines-volumes"></a>

#### `p.apps` — апликације (издања, машине, волумени)

Доступно преко функције пројекта `apps`. Водич: [SDK → Апликације](/docs/sr/sdk/apps).

| метод | намена |
| --- | --- |
| `list()` · `get(appId)` · `create(input)` · `update(appId, input)` · `remove(appId)` | инвентар и животни циклус; `create` прихвата `uses`, `update` прихвата и `labels` |
| `deployments.*` · `artifacts.*` · `access.*` · `rollback` · `start` · `stop` | постављања, артефакти, политика приступа, саобраћај и извршно окружење |
| `machines.list/start/stop/restart/destroy` · `scale(appId, count)` · `exec(appId, input)` | машине по групи процеса; `exec` захтева `project.app.admin` |
| `volumes.list/create/update/destroy/snapshots/snapshot/restore/fork` | трајни волумени, дневни снимци стања, враћање, прављење засебне копије |
| `token(appId)` | токен за пријаву који важи 15 минута; `409 app_capability_unsupported` без `member_tokens` |

<a id="psecrets--project-secrets"></a>

#### `p.secrets` — тајне пројекта

| метод | намена |
| --- | --- |
| `list()` · `upsert(input)` | приказ метаподатака · креирање или ажурирање вредности доступне само за упис и политике испоруке |
| `setStrategy(identifier, strategy, options?)` | промена начина излагања и његове листе хостова |
| `broker(identifier, request)` | извршавање HTTPS захтева одобреног сесијом и ограниченог политиком |
| `remove(identifier)` | брисање тајне |
| `setPersonal(name, value)` · `removePersonal(name)` | постављање · уклањање замене за појединачног корисника |
| `setGitCredential(input)` | постављање git акредитива за аутентификацију |

`runtime` са потрошачем `sandbox` представља излагање **кроз окружење** — подразумевано,
и једину политику која ставља вредност у отвореном тексту у сесију. `egress` са
потрошачем `network` представља излагање **контролисано на излазу**: сесија чува референцу,
а Beeuni умеће стварну вредност изван sandbox окружења, за тачно оне HTTPS
хостове које политика наводи. Излагање контролисано на излазу је експериментално; захтева
заставицу функције `secrets_egress` (Settings → Feature flags). Када је заставица искључена,
`setStrategy(identifier, 'egress', …)` и `upsert(...)` са излазном политиком
враћају `403` `feature_disabled`. Ниједан потрошач `broker` уопште није присутан
у сесији. Погледајте
[Тајне](/docs/sr/project/secrets). Метод `broker(...)` захтева
токен ограничен на сесију и активну референцу сесије.

<a id="paccess--project-assignments-invites-requests"></a>

#### `p.access` — доделе пројекта, позиви, захтеви

Сваки метод овде чита или уписује доделу која важи за овај пројекат. Пројектне
улоге су `manager` и `member`.

| метод | опис |
| --- | --- |
| `list()` · `invite(email, role)` | субјекти са приступом · позивање корисника |
| `update(userId, role)` · `revoke(userId)` | додела пројектне улоге · опозив доделе |
| `pendingInvites()` · `requests()` | позиви на чекању · захтеви за приступ на чекању |
| `resendInvite(inviteId)` · `revokeInvite(inviteId)` · `approveRequest(id)` · `rejectRequest(id)` | поновно слање/опозив позива · одобравање/одбијање захтева |
| `groupGrants()` · `attachGroupGrant(...)` · `updateGroupGrant(...)` · `detachGroupGrant(...)` | исте доделе, са субјектом `group` |

`p.access.resourceGrants` је приказ **доделе објекта**: ограничава
субјекта на један објекат у пројекту уместо на цео пројекат. Beeuni
тренутно примењује доделе објеката на агенте и вештине. Агент је подразумевано
затворен — члан му приступа само када додела наводи њега или неку од његових
група. Додела објекта сама по себи не носи дозволе и ограничава
менаџера пројекта исто колико и члана.

| метод | опис |
| --- | --- |
| `resourceGrants.list()` | доделе објеката у овом пројекту |
| `resourceGrants.create(input)` | додела једног објекта кориснику или групи |
| `resourceGrants.remove(grantId)` | опозив једне доделе објекта |

<a id="pconnectorslug--one-connector"></a>

#### `p.connector(slug)` — један конектор

| метод | опис |
| --- | --- |
| `run(action, args, options?)` | излаз акције; баца `ConnectorCallError` или `ConnectorApprovalPendingError` — погледајте [Грешке](/docs/sr/sdk/reference#pconnectorslug--one-connector) |
| `call(action, args, options?)` | необрађени резултат позива; `202` се разрешава са `ok: false` |
| `describe()` · `describe(action)` | конектор са улазним и излазним шемама · једна акција |
| `accounts()` | налози под којима овај позивалац сме да га покрене, подразумевани први |
| `paginate(action, args, { next, maxPages? })` | асинхрони итератор кроз излаз сваке странице; баца `ConnectorPageLimitError` са `nextArgs` када постоји више од `maxPages` (подразумевано 100) страница — погледајте [Странице](/docs/sr/sdk/reference#pconnectorslug--one-connector) |
| `uploadAttachment(content, input)` | `p.connectors.uploadAttachment` са `connector` постављеним на овај slug |

`options`: `account`, `approvalContext`, `timeoutMs` (подразумевано 90 000), `signal`. Уз датотеку из `beeuni connectors types`, аргументи и излаз су типизирани.

<a id="pconnectors--tool-connectors"></a>

#### `p.connectors` — конектори алата

| метод | намена |
| --- | --- |
| `catalog()` · `tools()` | каталог Connector алата који се могу позивати · спљоштени `<connector>.<action>` алати |
| `search(query, options?)` · `describe(tool)` | пронађи · прегледај један алат који се може позивати |
| `call(tool, args?, options?)` | позови један `<connector>.<action>` алат преко мрежног пролаза на страни сервера. `options.account` одређује налог у чије име се извршава — види испод. |
| `accounts(slug)` | налози у чије име овај позивалац сме да позива `slug`, подразумевани први — са њима се упоређује `options.account` |
| `uploadAttachment(content, input)` | припреми бајтове за `input.connector`; враћа `ref` (`{ $beeuni_attachment }`) за уметање у аргументе каснијег позива — види [Приложи датотеке](/docs/sr/connect/connectors#attach-files) |
| `list()` · `config(connectorId)` | конфигурисани конектори · конфигурација једног конектора |
| `create(input)` | додај конектор |
| `auth.discover(input)` | прегледај аутентификацију из OpenAPI спецификације, Postman колекције или крајње тачке |
| `remove(connectorId)` · `sync()` | избриши конектор · поново синхронизуј конекторе |
| `setName(connectorId, name)` · `setSensitive(connectorId, sensitive)` | преименуј · означи као осетљив (додатна провера одобрења) |
| `setAuthorizationStrategy(slug, strategy)` | @deprecated. И даље позива руту; рута не обавља никакву операцију, одговара са `{ok:true, deprecated:true}` и ништа не мења. `owner_type` на свакој вези сада представља целокупно правило приступа. |
| `setCredentialMode(connectorId, mode)` · `setCredential(connectorId, input)` | промени извор · подеси вредност акредитива |
| `policies.get(connectorId)` · `policies.set(connectorId, policies)` | прочитај · замени његове смернице за алате |
| `connections.list()` · `connections.reconcile(input)` | излистај · креирај/ажурирај повезане налоге |
| `connections.updateCredential(connectionId, input)` | ротирај акредитив везе |
| `connections.revoke(connectionId)` · `connections.activate(connectionId)` | забрани · обнови везу |
| `connections.setDefault(connectionId)` | постави као подразумевану у опсегу њеног власника |
| `connections.rename(connectionId, label)` | промени само ознаку; налог остаје овлашћен. Свака веза садржи `connected_as`, идентитет у чије име је овлашћена. |

`p.connectors.discover` служи за преглед каталога директних конектора. Функција је **експериментална** и подразумевано искључена — омогућите је за сваки пројекат у [Settings → Feature flags](/docs/sr/feature-flags) → "Connectors API Discover". Easy Connect остаје подразумевано тржиште конектора.

| метод | намена |
| --- | --- |
| `discover.list(query?, cursor?)` · `discover.detail(id)` | претражи OpenAPI/MCP/GraphQL/CLI ставке · детаљи једне ставке |

`p.connectors.pipedream` је путања компатибилности за ранији управљани OAuth; `listApps`
враћа само OAuth апликације. За нове управљане интеграције користите Easy Connect. Апликације са API кључем повежите директно.

| метод | намена |
| --- | --- |
| `pipedream.listApps(params?)` · `pipedream.connect(input)` · `pipedream.finalize(input)` | прегледај каталог апликација · покрени поступак повезивања · доврши га |

Конектор дефинише алат, апликацију добављача и смернице. `connections`
чува његове повезане **налоге** — конектор може да садржи више њих истовремено.
Сесија може да фиксира један за сваки позив помоћу
`connector_bindings: { alias: { connection_id } }`, или појединачни позив може да наведе
један помоћу `call(tool, args, { account })`. Акредитиви остају шифровани и
одређују се за сваки захтев.

`connections` је једина активна фасада за ауторизацију. Повучени
називи `authorizations` и `profiles` нису део тренутног SDK интерфејса.

<a id="accounts-and-the-call-time-gate"></a>

#### Налози и провера у тренутку позива

Свака веза има `owner_type`: `project` (дељена — доступна свакоме
коме је одобрен приступ конектору, било особи или сервисном налогу) или `member` (приватна —
доступна само свом власнику, и то само у приватној сесији; никада
сервисном налогу). Дељени налог може да се ограничи на групе и особе:
`connections.list()` враћа његове дозволе у `shared_with`, а
`connectionSharedWithEveryone(connection)` показује да ли сви у
пројекту могу да га користе. Ограничени налог прати правила приватног налога за
наведене особе, а `usable: false` означава налог који позивалац види само да би њиме управљао.
Доделите или опозовите приступ помоћу `createAssignment` / `revokeAssignment`
(`object: { type: 'connection', id }`) — погледајте
[Изаберите ко може да користи дељени налог](/docs/sr/connect/connectors#choose-who-can-use-a-shared-account).
`p.connectors.accounts(slug)` наводи све налоге којима овај позивалац може да приступи,
са подразумеваним на првом месту:

```ts
const accounts = await beeuni.project(projectId).connectors.accounts('stripe-read');
// [{ connection_id, label, owner_type, is_default }, ...]

await beeuni.project(projectId).connectors.call(
  'stripe-read.get_balance',
  {},
  { account: 'My Stripe' }, // a connection id, a label, or the words `me` / `project`
);
```

Позив који не наводи налог прво се разрешава на подразумевани приватни
налог позиваоца, а затим на подразумевани дељени налог пројекта. Именовани налог
који не може да се разреши бива **одбијен** са `connector_not_connected` — никада
се не замењује прећутно — а одбијање наводи `requested_account` и
`available_accounts`. Сваки успешан позив враћа податак о налогу под којим је извршен:
`result.account = { connection_id, label, owner_type }`.

Више нема провере конектора при креирању сесије. Раније је сесија била
одбијана са `409 CONNECTOR_CONNECTION_REQUIRED` када обавезни конектор није имао
употребљиву везу; тог одбијања више нема (`require_connectors` нема дејство — погледајте
[`p.sessions`](#psessions--and-the-session-handle)). Провера је премештена на
позив: одбијени `connector_not_connected` садржи `connect_url`, хостовани
линк за ауторизацију, кад год може да се генерише за позиваоца — цео
проблем решава се једним кликом, преко дугмета за повезивање у транскрипту.

<a id="ppolicies--project-policies"></a>

#### `p.policies` — смернице пројекта

| метода | шта ради |
| --- | --- |
| `list()` · `set(policies)` | смернице пројекта · замена скупа |

<a id="ptriggers--cron-webhook-monitor-and-event-automations"></a>

#### `p.triggers` — cron, webhook, мониторске и догађајне аутоматизације

Окидач покреће радњу агента према распореду, долазном webhook-у, надгледаној команди или догађају апликације на конектору. Погледајте
[Окидачи](/docs/sr/connect/triggers) за стратегију сесије и шаблонизацију
корисног садржаја.

| метода | шта ради |
| --- | --- |
| `list()` | сви окидачи |
| `eventTypes({ connector })` | догађаји апликације на које конектор може да реагује (`{ provider, app, event_types }`); 404 за непознат конектор, 409 `event_source_unavailable` када његов провајдер нема извор догађаја |
| `create(input)` | креирање окидача |
| `update(triggerId, input)` | измена окидача |
| `remove(triggerId)` | брисање окидача |
| `fire(triggerId)` | покретање одмах |
| `setActivation(paused)` | паузирање или настављање свих окидача на пројекту |

`create(input)` прихвата `{ name, type: 'cron' | 'webhook' | 'monitor' | 'event', prompt_template,
slug?, agent?, model?, enabled?, session_mode?, session_id?, cron?, run_at?,
timezone?, secret_env?, connector?, event?, event_source?, event_account?, event_config?, session_access? }`. `name` and `prompt_template` су обавезни.
`cron`/`run_at` се међусобно искључују (`type: 'cron'`); `secret_env` (
HMAC тајна за webhook) примењује се на `type: 'webhook'`.

Окидач `event` захтева `connector` (slug конектора) и `event` (идентификатор типа
из `eventTypes`). `event_account` је опционо: ознака једног дељеног налога
тог конектора; `null` или изостављена вредност користи подразумевани дељени налог конектора.
`event_source` је опционо: идентификатор адаптера извора догађаја, као што је `composio`. `null` или изостављена вредност користи
провајдера конектора. Идентификатор типа припада том адаптеру. `event_config` се обликује према `config_schema` тог типа.
`eventTypes` и `eventApps` приказују адаптер као `source`; `provider` је застарели алијас.
Сваки наведени окидач садржи `event: { connector, account, connected_as, type, config, source, provider, app,
status: 'active' | 'needs_connection' | 'error' | 'pending', error,
last_event_at } | null`. Шаблони упита читају догађај као
`{{ event.data.<field> }}` уз `event.id`, `event.type`, `event.app`,
`event.connector` и `event.occurred_at`.

`session_access` одређује ко може да отвори сесије које окидач креира. Његов облик је
`{ mode: 'private' | 'members' | 'project', memberIds: string[], groupIds:
string[] }` and defaults to `private`. Ова политика је стање извршавања
локално за налог. Не улази у преносиви манифест `beeuni.yaml`. Ажурирање само
`session_access` не креира Git комит. Закачена сесија задржава сопствена подешавања
дељења. Менаџер пројекта увек може да отвори сесије које је креирао окидач, укључујући
сесије које користе `private` или приступ за изабране чланове.

`session_access` је подешавање видљивости по ресурсу, додато моделу улога,
а не улога. Одређује ко може да отвори сесије једног окидача. Не даје ниједну
дозволу коју одлука на основу улоге одбија. Погледајте
[Налози и приступ](/docs/sr/accounts#per-feature-access-settings).

<a id="pmarketplace--pregistry--installed-items"></a>

#### `p.marketplace` / `p.registry` — инсталиране ставке

Инсталира датотеке ставке из каталога на подразумевану грану пројекта.
`registry.*` је идентичан алијас за `marketplace.*`.

| метода | намена |
| --- | --- |
| `marketplace.list()` · `marketplace.install(id)` | инсталиране ставке · инсталирање ставке из каталога |
| `marketplace.updates()` · `marketplace.update(name)` · `marketplace.updateAll()` | доступна ажурирања · ажурирање једне · ажурирање свих |
| `marketplace.remove(name)` | деинсталирање ставке |

<a id="pfiles--repo-files-read"></a>

#### `p.files` — датотеке репозиторијума (читање)

Приступ git стаблу пројекта само за читање. За читање и писање датотека унутар
активне сесије користите операције над датотекама те сесије — погледајте
[Датотеке](#files) у одељку Модули испод.

| метода | намена |
| --- | --- |
| `listDirectory({ ref?, path? })` | један ниво фасцикле: `{ entries: [{ path, type, size? }], truncated }`. Користите за изградњу стабла; свака фасцикла је потпуна до 5.000 ставки. |
| `list(options?)` · `read(path, ref?)` | све датотеке испод путање, рекурзивно, ограничено на 1.000 (одговор садржи `X-Beeuni-Truncated: 1` када је скраћен) · садржај датотеке на git референци |
| `search(query, { content?, ref?, limit? })` | претрага назива датотека у целом репозиторијуму или садржаја помоћу `content: true` |
| `archive(options?)` · `history(path)` | преузимање tar архиве · git историја датотеке |

<a id="pgit--history"></a>

#### `p.git` — историја

| метода | намена |
| --- | --- |
| `commits()` | дневник комита |
| `commit(sha)` · `commitDiff(sha)` | један комит · његове разлике |
| `branches()` · `versionDiff(from, to)` | гране · разлике између две референце |

<a id="pchangerequests--lifecycle-and-merge"></a>

#### `p.changeRequests` — животни циклус и спајање

Захтев за измену (CR) је начин на који се рад сесије спаја у подразумевану грану.

| метод | намена |
| --- | --- |
| `list()` · `get(crId)` | отворени CR-ови · један CR |
| `diff(crId)` · `mergePreview(crId)` | његов diff · преглед резултата спајања |
| `open(input)` · `merge(crId, input?)` | отварање · спајање CR-а |
| `close(crId, input?)` · `reopen(crId, input?)` | затварање без спајања · поновно отварање затвореног CR-а |
| `requestChanges(crId, input)` | бележење повратних информација, уз опционално слање назад у изворну сесију |

<a id="psessions--and-the-session-handle"></a>

#### `p.sessions` — и објекат за приступ сесији

| метод | намена |
| --- | --- |
| `list()` | сесије пројекта |
| `create(input?)` | креирање сесије |
| `session(sid)` | објекат за приступ сесији (исто као `beeuni.session(id, sid)`) |

Објекат за приступ сесији је срж извршног окружења — погледајте
[Сесије](/docs/sr/sdk/sessions).

`create(input)` прихвата `connector_bindings` са slug-ом везе конектора као кључем.
Свака вредност именује `connection_id`. Такође прихвата `secrets` за
сужавање скупа тајни које потичу из бекенда. `require_connectors` је застарео и
неактиван: поље се и даље прихвата (стари клијент се никада не одбија зато што
га шаље), али га ништа не чита — сесија се никада не одбија при креирању
због конектора без употребљивог налога. Погледајте [Налози и провера у тренутку
позива](#accounts-and-the-call-time-gate).

<a id="papprovals--the-connector-approval-inbox"></a>

#### `p.approvals` — пријемно сандуче за одобрења конектора

Радње условљене одобрењем конектора које чекају одлуку — основа за
корисничко искуство одобравања дозвола (`APPROVE` / `ASK` / `BLOCK`).

| метод | намена |
| --- | --- |
| `list(options?)` · `sessionsNeedingInput(options?)` | одобрења на чекању · сесије блокиране до доношења одлуке |
| `resolve(executionId, decision, scope?)` | одобравање или одбијање једне ставке — `decision: 'approve' \| 'deny'`, `scope: 'once' \| 'session' \| 'session_all'` |

<a id="pgateway--llm-observability"></a>

#### `p.gateway` — надзор LLM-а

Евиденције захтева, збирни подаци о трошковима и кашњењу, буџети и API кључеви мрежног пролаза за
саобраћај овог пројекта ка моделима.

| метод | намена |
| --- | --- |
| `logs(opts?)` · `log(logId)` | записи у евиденцији захтева · један запис |
| `overview(days?)` · `series(days?)` · `breakdown(days?)` · `sessions(days?)` · `errors(days?)` | збирни подаци, трошак по сесији и грешке током временског интервала |
| `budgets()` · `setBudget(input)` · `deleteBudget(budgetId)` | читање · креирање/измена · уклањање буџета |
| `keys()` · `createKey(name)` · `revokeKey(keyId)` | листа · издавање · опозив API кључа мрежног пролаза |
| `playground(prompt, models)` | извршавање једног упита на највише 6 модела |
| `routing.get()` · `routing.set(policy)` · `routing.reset()` | читање · замена · наслеђивање политике усмеравања |
| `routing.preview(input)` | одређивање руте без позивања модела |

Политика усмеравања садржи подразумевани модел, модел за вид и уређени
ланац резервних модела, при чему се сваки модел испробава највише једном; `fallbackOn` је
`transient` или `any-error`.

Мрежни пролаз прелази на следећи резервни модел само када тренутни модел
откаже пре него што врати било какав излаз:

- `transient`: мрежна грешка, истек времена, било који `5xx` или `402`, `403`, `429`.
- `any-error`: сваки отказ, укључујући `400`.

Отказ након што је излаз започео остаје везан за тај модел. Захтев са вашим
сопственим кључем провајдера (BYOK) никада не прелази на модел који наплаћује Beeuni. Сваки резервни
модел добија сопствене подразумеване поставке генерисања.

<a id="pchannels--slack--email--voice"></a>

#### `p.channels` — Slack / имејл / глас

Интерфејси конектора који омогућавају агенту да делује као Slack апликација, имејл адреса
или да се придружи гласовном позиву у реалном времену.

| метода | намена |
| --- | --- |
| `slack.installation()` · `slack.mode()` · `slack.manifest()` | тренутна инсталација · режим · манифест апликације |
| `slack.connect(input)` · `slack.disconnect()` | повезивање · прекид везе |
| `slack.getFile(url)` · `slack.uploadFile(input)` | преузимање · отпремање датотеке преко серверског проксија |
| `email.installation(connectorSlug?)` · `email.mode()` | тренутна инсталација · режим |
| `email.connect(input)` · `email.disconnect(...)` · `email.updatePolicy(input)` | повезивање · прекид везе · ажурирање политике слања/одговарања |
| `voice.setBotName(name)` | преименовање бота током позива |

<a id="pmodeldefaults--default-model-preferences"></a>

#### `p.modelDefaults` — подразумеване поставке модела

Подразумеване поставке модела на нивоу налога, агента и пројекта, које разрешава мрежни пролаз.

| метода | намена |
| --- | --- |
| `get()` · `set(input)` · `clear(params)` | читање · постављање подразумеване вредности · уклањање замене |

<a id="psetdefaultagent--project-default-agent"></a>

#### `p.setDefaultAgent` — подразумевани агент пројекта

`p.setDefaultAgent(agentName)` проверава да ли је агент декларисан и омогућен,
а затим га поставља као `default_agent` у `beeuni.yaml` пројекта. Нове сесије
дају предност овом агенту, осим ако корисник не изабере другог.

<a id="pupdatefeatureflag--feature-flags"></a>

#### `p.updateFeatureFlag` — заставице функционалности

`p.updateFeatureFlag(feature, enabled)` укључује или искључује једну заставицу функционалности за
пројекат. Проследите `enabled: null` да бисте уклонили замену и вратили се на
подразумевану вредност платформе. Позива канонски `PATCH /v1/projects/:id/features`.

`feature` је један од `FEATURE_FLAG_KEYS` (извезен из `@beeuni/sdk`, типа
`FeatureFlagKey`). Позиваоцу је потребна дозвола `project.settings.write` за пројекат;
у супротном рута одговара са `403`.

Свака рута условљена заставицом одбија захтев на исти начин док је заставица искључена: HTTP `403`
са `{ error, code: "feature_disabled", feature }`. Користите `isFeatureDisabledError(error)`
за гранање на основу тога и `featureDisabledKey(error)` за читање кључа заставице — никада
не проверавајте подударање текста поруке.

`p.updateExperimentalFeature(feature, enabled)` је **застарели** алијас. Он
и даље позива застарели алијас руте `PATCH /v1/projects/:id/experimental`
како би корисници везани за старији API у употреби наставили да раде. Користите
`p.updateFeatureFlag` у новом коду.

<a id="psandbox--templates-and-snapshot-builds"></a>

#### `p.sandbox` — шаблони и израде снимака стања

Конфигурација израде изолованог окружења поред `sandboxHealth`/`sandboxTemplates` на објекту
пројекта: шаблони за Dockerfile/слику/пул спремних окружења и њихове израде снимака стања.

| метода | намена |
| --- | --- |
| `list()` · `snapshots()` | изолована окружења за овај пројекат · израђени снимци стања |
| `rebuildSnapshot(slug?)` · `fixWithAgent()` | поновна израда снимка стања · захтев агенту да поправи неуспелу израду |
| `createTemplate(input)` · `updateTemplate(...)` · `removeTemplate(...)` · `buildTemplate(...)` | додавање · измена · брисање · израда шаблона |
| `setProvider(provider)` | захтев за промену добављача. `null` (или подразумевани добављач платформе / већ активни добављач) примењује се одмах; прелазак на другог омогућеног добављача покреће трајни прелаз припрема→провера→активација — тренутни добављач наставља да опслужује док се циљна спремна слика израђује и проверава, а затим активира. Повратна вредност је означена унија: `kind:'project'` (одмах) или `kind:'preparation'` (периодично проверавајте `getProjectSandboxProviderTransition()` до `activated`/`failed`) |

<a id="platform-admin-hooks-beeunisdkreact"></a>

### Администраторски кукови платформе (`@beeuni/sdk/react`)

Ови кукови служе администраторској конзоли. API на њих одговара само администратору
платформе. Свака мутација поништава упите `['admin', 'accounts']`.

| Хук | Шта ради |
| --- | --- |
| `useAdminRole(userId, options?)` | чита улогу позиваоца из `GET /user-roles` → `{ isAdmin, role }`. `userId` служи као кључ кеша. Ако недостаје `userId`, упит је онемогућен. Поново преузима податке при монтирању и фокусирању, па опозвана улога престаје да условљава приступ у оквиру једне навигације. |
| `useAdminGrantCredits()` | мутација `{ accountId, amount, description, isExpiring }`: додаје средства у новчаник. `POST /admin/api/accounts/:id/credits`. Преноси новац: прво потврдите у корисничком интерфејсу. |
| `useAdminDebitCredits()` | мутација `{ accountId, amount, description }`: уклања средства из новчаника. `POST /admin/api/accounts/:id/credits/debit`. Преноси новац: прво потврдите у корисничком интерфејсу. |
| `useAdminSetTier()` | мутација `{ accountId, tier }`: поставља ниво плана. |
| `useAdminGrantTrial()` | мутација `{ accountId, tierKey, seats, durationDays, creditGrant?, note? }`: додељује или замењује пробни период. Налог се понаша као `tierKey` док период не истекне. `creditGrant` такође додаје средства у новчаник. |
| `useAdminRevokeTrial()` | мутација `{ accountId }`: одмах завршава активни пробни период. Враћа `400` када ниједан није активан. |

<a id="escape-hatch"></a>

### Излаз за посебне случајеве

`beeuni.runtime()` враћа типизовани runtime REST клијент за активни
sandbox.
На клијенту који је направио `createScopedBeeuni` (`@beeuni/sdk/server`), **баца изузетак**
— „активно“ извршно окружење на нивоу целог процеса је sandbox другог захтева на
серверу са више закупаца, што доводи до цурења података између закупаца. Уместо тога користите
`beeuni.session(pid, sid).runtime` у опсегу сесије (прво позовите `ensureReady()`), који
проналази sandbox те сесије.

<a id="modules"></a>

## Модули

Модули независни од радног оквира иза фасаде [клијента](#the-client) и
React хукова. Користите их када вам треба једна операција без фасаде,
чиста помоћна функција или слој изолације само за Node. Сваки модул има
ниво стабилности да бисте знали на чему можете да градите.

| Ниво | Значење |
| --- | --- |
| Канонски | Увозите из корена `@beeuni/sdk`. Користите ово за сав нови код. |
| Подржан | Наменска подпутања (`@beeuni/sdk/react`, `@beeuni/sdk/server`). Пуноправно подржана, није застарела. |
| Застарели алијас | Стара подпутања која и даље ради. Поново извози код који корен већ извози. Уместо тога увозите из корена. |
| Интерни | Изван semver правила. Не увозите ово у код домаћина. |

Коренска улазна тачка је канонска. Сваки назив испод који је независан од радног оквира може се увести
директно из `@beeuni/sdk`:

```ts
import { files, getSessionHealth, getClient, authenticatedFetch, backendApi } from '@beeuni/sdk';
```

<a id="canonical-modules"></a>

### Канонски модули

| Модул | Шта ради |
| --- | --- |
| Датотеке | Операције над датотекама радног простора: листање, читање, претрага, писање |
| Извршно окружење сесије | Провера исправности и функције за прављење URL-ова за преглед/прокси |
| runtime клијент | Типизовани runtime REST клијент и његов комплетан скуп типова |
| Аутентификација | `authenticatedFetch` и приступне функције за токене |
| REST за пројекте | Сирове REST функције које фасада обавија |
| API клијент | `backendApi`, типизовани HTTP клијент ниског нивоа |
| Потези | Груписање порука у потезе, израчунавање трошкова и статуса — погледајте [Потезе](#turns) |
| Транскрипти | `formatTranscript`, извоз у Markdown на страни клијента |
| Листе у састављачу | Листе агената и модела у састављачу сесије: који се нуде, који се покреће |

<a id="files"></a>

#### Датотеке

```ts
import { files } from '@beeuni/sdk';

const tree = await files.list('/workspace/src');
const { content } = await files.read('/workspace/README.md');
const hits = await files.findText('TODO');
await files.upload(file, '/workspace/uploads', file.name, {
  onProgress: ({ loadedBytes, totalBytes }) => {
    console.log(`${loadedBytes}/${totalBytes}`);
  },
});
```

Отпремања већа од 64 KiB прелазе границу sandbox-а у провереним деловима.
Повратни позив за напредак извршава се након што сваки део стигне у систем датотека сесије.

`uploadNativeFile({ uri, name, type? }, targetPath, baseUrl)` отпрема датотеку са
уређаја из React Native-а у једном захтеву. Извршно окружење стримује бајтове из
`uri`, тако да они никада не улазе у JS хип. Користи исту аутентификацију, крајњи рок и
поновно извршавање `401` као `files.upload`. Не дели податке на сегменте.

`fetchProjectArchive`, `fetchCostExportCsv` и позиви верзије за sandbox шаљу податке
преко истог транспорта. При неуспеху се баца `ApiError` са `status`.

`files.write(path, blob)` замењује датотеку на `path` и не успева ако је `path`
фасцикла. `files.create(path)` прави празну датотеку и никада не преписује постојећу: када
датотека или фасцикла већ постоји на `path`, баца `FileExistsError`
(`status` `409`, `code` `'FILE_EXISTS'`).

```ts
import { FileExistsError, files } from '@beeuni/sdk';

try {
  await files.create('/workspace/notes.md');
} catch (error) {
  if (error instanceof FileExistsError) console.log(`${error.path} already exists`);
  else throw error;
}
```

`files` циља глобално активан sandbox. Ако ваш хост истовремено покреће више од једне
сесије, уместо тога позовите `s.files` на референци сесије. Он увек
циља sandbox те сесије. Погледајте [Сесије](/docs/sr/sdk/sessions).

<a id="session-runtime-helpers"></a>

#### Помоћне функције извршног окружења сесије

```ts
import { getSessionHealth, isRuntimeReady } from '@beeuni/sdk';

const result = await getSessionHealth();
if (result.ok && isRuntimeReady(result.health)) {
  // the sandbox daemon is ready
}
```

`getSessionHealth` никада не баца изузетак за статус ван опсега 2xx. Враћа
`{ status, ok, health, body }` и препушта вам да одлучите шта статус значи.
Исти модул извози URL помоћне функције које претварају излаз агента `localhost`
у доступан прокси URL: `detectLocalhostUrls`, `rewriteLocalhostUrl`,
`proxyLocalhostUrl`, `parseLocalhostUrl` и `buildWebProxyUrl`.

<a id="opencode-client"></a>

#### runtime клијент

```ts
import { getClient } from '@beeuni/sdk';

const client = getClient();
const { data } = await client.session.list({ limit: 100 });
```

`getClient()` враћа типизовани клијент за компатибилност са runtime за активан sandbox,
са већ укљученом аутентификацијом. Дајте предност `beeuni.session(pid, sid).runtime`, истом
клијенту ограниченом на једну сесију, уместо глобалног `getClient()` када ваш
хост покреће више од једне сесије.

<a id="auth-helpers"></a>

#### Помоћне функције за аутентификацију

```ts
import { authenticatedFetch, getAuthToken } from '@beeuni/sdk';

const res = await authenticatedFetch(`${runtimeUrl}/beeuni/health`);
const token = await getAuthToken();
```

Токен долази из функције `getToken` коју сте проследили у `createBeeuni`.
Већини кода апликације овај модул није потребан — слојеви за датотеке, сесије и фасаду
већ обављају аутентификацију за вас.

<a id="api-client"></a>

#### API клијент

```ts
import { backendApi } from '@beeuni/sdk';

const data = await backendApi.get('/some/endpoint');
await backendApi.post('/some/endpoint', { name: 'x' });
```

`backendApi` је типизовани HTTP клијент на коме се заснива свака REST функција. Користите га
само за крајњу тачку која још нема типизовани омотач.

<a id="composer-agent-and-model-lists"></a>

#### Листе агената и модела за састављач

Направите бирач агената и бирач модела у састављачу сесије по истим правилима
која користи веб апликација Beeuni. Свака функција је чиста: преузмите улазне податке
клијентом, па их проследите.

```ts
import {
  composerSelectableAgents,
  createModelVisibility,
  flattenModels,
  modelInDefaultView,
  pickerProviderList,
  projectConfigAgentsToRuntimeAgents,
  resolveComposerAgent,
  resolveComposerModel,
  resolveModelDefault,
} from '@beeuni/sdk';

// Agents: the roster, the picker list, and the agent the send carries.
const roster = projectConfigAgentsToRuntimeAgents(detail.config);
const pickerAgents = composerSelectableAgents(roster, { enableProjects: false });
const agent = resolveComposerAgent({
  agents: roster,
  boundAgent: session?.agent,
  defaultAgent: detail.config.default_agent,
  selectedAgent: pick,
});
if (agent.disabled) {
  // no accessible agent: refuse the send
}

// Models: gateway projects read /model-picker, native projects merge the
// catalog synthesis with the running sandbox's provider list.
const gatewayEnabled = detail.project.experimental?.llm_gateway === true;
const providers = pickerProviderList({
  gatewayEnabled,
  modelPicker,
  runtimeProviders,
  llmCatalogProviders,
  secretNames,
});
const models = flattenModels(providers, { providerMode: gatewayEnabled ? 'gateway' : 'native' });
const isVisible = createModelVisibility({ catalogModels: models });
const defaultView = models.filter(
  (m) => m.enabled !== false && modelInDefaultView(m, { search: '', isStoreVisible: isVisible, selected }),
);
const { model, explicit } = resolveComposerModel({
  models,
  picks: [sessionPick],
  serverDefault: resolveModelDefault(modelDefaults, agent.selected ?? undefined),
  providers,
});
```

`resolveComposerModel` враћа `explicit: undefined` када је састављач на
подразумеваној поставци. `model` је кључ за приказ и слање. `id` сваког модела
у изравнатој листи је референца коју избор чува; `modelRefToKey(ref, gatewayEnabled)` чита
сачувану референцу (фиксирање сесије, везу канала, `model` окидача) и претвара је назад у
кључ.

<a id="supported-subpaths"></a>

### Подржане подпутање

| Подпутања | Шта ради |
| --- | --- |
| `@beeuni/sdk/react` | React куке — погледајте [React куке](/docs/sr/sdk/react) |
| `@beeuni/sdk/server` | Конфигурација у опсегу захтева за позадинске системе са више закупаца |
| `@beeuni/sdk/wire-message-id` | Само сат идентификатора порука runtime протокола (један модул, без увоза). Корен извози иста имена |

<a id="wire-message-ids"></a>

#### Идентификатори порука протокола

`messageId` упита је његов положај у транскрипту. runtime поређа
поруке по `msg_` + 48-битном сату (`Date.now() * 0x1000`, доњих 48 битова) +
14 base62 знакова, а сат се враћа на почетак сваких 2^36 ms (око 2,2 године).
Никада га не кодирајте ручно.

```ts
import { mintWireMessageId } from '@beeuni/sdk';

// `after`: the ids already in this session's transcript.
const messageId = mintWireMessageId({ after: transcriptIds });
```

Време генерисања се поставља два минута уназад, а затим помера за један корак изнад најновијег ID-а
у `after` који је највише један сат у будућности. Позивалац који чува најновију
позицију као време уместо као ID користи `mintWireMessageIdAbove({ nowMs,
newestKnownTime })`, which returns `{ id, time }`. `newestWireIdClock(ids)`
проналази то време. Свако поређење се обавља на прстену, па ID-ови са обе стране
преливања задржавају свој стварни редослед.

48-битни сат се прелива отприлике сваке 2,2 године, па никада не поредите два времена помоћу `>`
или `<=`: ID генерисан непосредно после преливања бројчано је мањи од оног генерисаног
непосредно пре њега. Користите `wireIdClockDelta(clock, reference)`, растојање са предзнаком
на прстену (позитивно када је `clock` испред), и `maxWireIdClock(clocks)` за
најновији међу више њих:

```ts
import { maxWireIdClock, wireIdClockDelta } from '@beeuni/sdk/wire-message-id';

const floor = maxWireIdClock([transcriptNewest, deliveredNewest]);
const stale = floor !== null && wireIdClockDelta(clientClock, floor) <= 0n;
```

<a id="server-side-isolation"></a>

#### Изолација на страни сервера

`createBeeuni` чува своју конфигурацију, укључујући функцију за токен, у једној
променљивој за цео процес. То је у реду за картицу прегледача, CLI или
сервер за једног корисника. Није безбедно за Node сервер који обрађује истовремене
захтеве различитих корисника, јер последњи позив `createBeeuni` важи за
све захтеве који су у току. `@beeuni/sdk/server` то решава изолацијом
по захтеву:

```ts
import { createScopedBeeuni } from '@beeuni/sdk/server';

export async function handler(req: Request) {
  const beeuni = createScopedBeeuni({ backendUrl, getToken: () => tokenFor(req) });
  return beeuni.projects.list();
}
```

`createScopedBeeuni` и `runWithBeeuni` изолују конфигурацију по захтеву помоћу
Node механизма `AsyncLocalStorage`. Никада не увозите `@beeuni/sdk/server` из пакета
за прегледач — он статички укључује `node:async_hooks`.

`runtime()` на највишем нивоу клијента са ограниченим опсегом баца изузетак (разрешио би
изоловано окружење другог корисника). Приступите извршном окружењу одређене сесије преко
`beeuni.session(pid, sid).runtime` после `await s.ensureReady()`.

<a id="deprecated-aliases"></a>

### Застарели алијаси

Око двадесет старих потпутања и даље ради: `/files`, `/turns`, `/session`, `/auth`,
`/projects-client`, `/api-client`, `/config`, `/event-stream`,
`/opencode-client`, `/platform-client` и друге. Свака поново извози код који
коренска улазна тачка `@beeuni/sdk` већ извози. Настављају да раде како ниједан постојећи
```ts
import { classifyPart, classifyTurn, toolInfo, toolViewModel } from '@beeuni/sdk';
```
```ts
import { classifyPart, type ClassifiedPart } from '@beeuni/sdk';

for (const part of message.parts) {
  const classified: ClassifiedPart = classifyPart(part);
  switch (classified.kind) {
    case 'text':
      render(classified.text);
      break;
    case 'tool':
      render(classified.tool.title, classified.tool.status);
      break;
  }
}
```
```ts
interface ToolView {
  name: string;
  title: string;
  status: 'pending' | 'running' | 'done' | 'error';
  input?: Record<string, unknown>;
  output?: string;
  error?: string;
  outputParsed?: unknown; // JSON.parse(output) when it parses, capped at 256KB
  outputText?: string;    // the raw output text, always present
  kind?: ToolKind;        // toolKind(name): the action, whatever the harness calls the tool
  files?: ToolFile[];     // the files a file tool read, wrote or changed: path, patch, additions/deletions
  diff?: string;          // a unified diff of the change
  diagnostics?: Record<string, unknown[]>; // language-server diagnostics, keyed by file path
  answers?: string[][];   // the answers to a `question`, one list per question
  childSessionId?: string; // the child session a delegating call (`task`) runs
}
```
```ts
toolKind('oc-apply_patch'); // 'apply_patch'
toolKind('pty_spawn');      // 'pty'
inputPath({ path: 'app.py' }); // 'app.py'
```
```ts
toolInfo('bash'); // { label: 'Shell', category: 'shell' }
getToolInfo('write', { filePath: '/workspace/main.go' });
// { icon: 'file-pen', title: 'Write', subtitle: 'main.go /workspace' }
```
```ts
const vm = toolViewModel(classifiedTool);
if (vm.kind === 'shell') {
  render(vm.command, vm.stdout, vm.exitCode);
}
```
```ts
import { groupMessagesIntoTurns, collectTurnParts, type TurnLike } from '@beeuni/sdk';

const turns: TurnLike[] = groupMessagesIntoTurns(messages);
for (const turn of turns) {
  const parts = collectTurnParts(turn);
}
```
```ts
import { isTextPart, isToolPart, getPartText } from '@beeuni/sdk';

if (isTextPart(part)) {
  // part.type narrowed to 'text'
}
const text = getPartText(part); // works for 'text' and 'reasoning' parts
```
```ts
import { getWorkingState, getTurnStatus, formatDuration } from '@beeuni/sdk';

const status = getTurnStatus(parts, childMessages); // "Running commands..."
formatDuration(4300); // "4s" — durations under 1s return ''
```
```ts
import { getTurnError, getChildSessionError, unwrapError } from '@beeuni/sdk';

getTurnError(turn);                    // the first assistant error, unwrapped
getChildSessionError(childMessages);   // newest error in a sub-agent's messages
unwrapError(rawError);                 // normalizes double-JSON and mixed error shapes
```
```ts
import { getTurnCost, getSessionCost, formatCost, formatTokens } from '@beeuni/sdk';

const info = getTurnCost(partsWithMessage, modelPricingLookup);
const sessionCost = getSessionCost(messages, modelPricingLookup);

formatCost(0.0032);  // "$0.003"
formatTokens(12345); // "12k"
```
```ts
import { directSubsessions, projectSessionForRuntimeId, rootRuntimeSession, runtimeSessionsOf } from '@beeuni/sdk';

const root = rootRuntimeSession(projectSession);            // the root conversation id
const children = directSubsessions(projectSession);         // its subagent conversations
const owner = projectSessionForRuntimeId(projectSessions, childId); // the session a conversation belongs to
```
```ts
import { getChildSessionId, getChildSessionToolParts } from '@beeuni/sdk';

const childId = getChildSessionId(taskToolPart);
const steps = getChildSessionToolParts(childMessages);
```
```ts
import { getPermissionForTool, getHiddenToolParts, isToolPartHidden } from '@beeuni/sdk';

const permission = getPermissionForTool(permissions, callID);
const hidden = getHiddenToolParts(activePermission, activeQuestion);
```
```ts
import { getFilename, getDirectory, relativizePath, stripAnsi } from '@beeuni/sdk';

getFilename('/workspace/src/main.go');               // "main.go"
getDirectory('/workspace/src/main.go');               // "/workspace/src"
relativizePath('/workspace/src/main.go', '/workspace'); // "src/main.go"
```
```ts
import { sortSessions, childMapByParent, allDescendantIds } from '@beeuni/sdk';

sessions.sort(sortSessions(Date.now())); // pins sessions updated in the last 60s
const childMap = childMapByParent(sessions);
const descendants = allDescendantIds(childMap, sessionId);
```
```sh
npm install @beeuni/sdk
```
```ts
import { createBeeuni } from '@beeuni/sdk'; // framework-free core
import { useSession } from '@beeuni/sdk/react'; // optional React layer
import { createScopedBeeuni } from '@beeuni/sdk/server'; // Node and Bun servers
```
```html
<script src="https://unpkg.com/@beeuni/sdk/dist/beeuni.global.js"></script>
<script>
  const beeuni = Beeuni.createBeeuni({
    backendUrl: 'https://api.beeuni.ai/v1',
    getToken: async () => KEY,
  });
</script>
```
